mirror of
https://github.com/neondatabase/neon.git
synced 2025-12-22 21:59:59 +00:00
Improve specificity with which we apply compute specs (#12773)
This makes sure we don't confuse user-controlled functions with PG's builtin functions. ## Problem See https://github.com/neondatabase/cloud/issues/31628
This commit is contained in:
committed by
GitHub
parent
842a5091d5
commit
f3a0e4f255
@@ -1 +1 @@
|
|||||||
SELECT num_requested AS checkpoints_req FROM pg_stat_checkpointer;
|
SELECT num_requested AS checkpoints_req FROM pg_catalog.pg_stat_checkpointer;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT checkpoints_req FROM pg_stat_bgwriter;
|
SELECT checkpoints_req FROM pg_catalog.pg_stat_bgwriter;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT checkpoints_timed FROM pg_stat_bgwriter;
|
SELECT checkpoints_timed FROM pg_catalog.pg_stat_bgwriter;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT (neon.backpressure_throttling_time()::float8 / 1000000) AS throttled;
|
SELECT (neon.backpressure_throttling_time()::pg_catalog.float8 / 1000000) AS throttled;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT CASE
|
SELECT CASE
|
||||||
WHEN pg_catalog.pg_is_in_recovery() THEN (pg_last_wal_replay_lsn() - '0/0')::FLOAT8
|
WHEN pg_catalog.pg_is_in_recovery() THEN (pg_catalog.pg_last_wal_replay_lsn() - '0/0')::pg_catalog.FLOAT8
|
||||||
ELSE (pg_current_wal_lsn() - '0/0')::FLOAT8
|
ELSE (pg_catalog.pg_current_wal_lsn() - '0/0')::pg_catalog.FLOAT8
|
||||||
END AS lsn;
|
END AS lsn;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
SELECT
|
SELECT
|
||||||
(SELECT setting FROM pg_settings WHERE name = 'neon.timeline_id') AS timeline_id,
|
(SELECT setting FROM pg_catalog.pg_settings WHERE name = 'neon.timeline_id') AS timeline_id,
|
||||||
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
||||||
-- These temporary snapshot files are renamed to the actual snapshot files
|
-- These temporary snapshot files are renamed to the actual snapshot files
|
||||||
-- after they are completely built. We only WAL-log the completely built
|
-- after they are completely built. We only WAL-log the completely built
|
||||||
-- snapshot files
|
-- snapshot files
|
||||||
(SELECT COUNT(*) FROM pg_ls_dir('pg_logical/snapshots') AS name WHERE name LIKE '%.snap') AS num_logical_snapshot_files;
|
(SELECT COUNT(*) FROM pg_catalog.pg_ls_dir('pg_logical/snapshots') AS name WHERE name LIKE '%.snap') AS num_logical_snapshot_files;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
SELECT
|
SELECT
|
||||||
(SELECT current_setting('neon.timeline_id')) AS timeline_id,
|
(SELECT pg_catalog.current_setting('neon.timeline_id')) AS timeline_id,
|
||||||
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
||||||
-- These temporary snapshot files are renamed to the actual snapshot files
|
-- These temporary snapshot files are renamed to the actual snapshot files
|
||||||
-- after they are completely built. We only WAL-log the completely built
|
-- after they are completely built. We only WAL-log the completely built
|
||||||
-- snapshot files
|
-- snapshot files
|
||||||
(SELECT COALESCE(sum(size), 0) FROM pg_ls_logicalsnapdir() WHERE name LIKE '%.snap') AS logical_snapshots_bytes;
|
(SELECT COALESCE(pg_catalog.sum(size), 0) FROM pg_catalog.pg_ls_logicalsnapdir() WHERE name LIKE '%.snap') AS logical_snapshots_bytes;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
SELECT
|
SELECT
|
||||||
(SELECT setting FROM pg_settings WHERE name = 'neon.timeline_id') AS timeline_id,
|
(SELECT setting FROM pg_catalog.pg_settings WHERE name = 'neon.timeline_id') AS timeline_id,
|
||||||
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
-- Postgres creates temporary snapshot files of the form %X-%X.snap.%d.tmp.
|
||||||
-- These temporary snapshot files are renamed to the actual snapshot files
|
-- These temporary snapshot files are renamed to the actual snapshot files
|
||||||
-- after they are completely built. We only WAL-log the completely built
|
-- after they are completely built. We only WAL-log the completely built
|
||||||
-- snapshot files
|
-- snapshot files
|
||||||
(SELECT COALESCE(sum((pg_stat_file('pg_logical/snapshots/' || name, missing_ok => true)).size), 0)
|
(SELECT COALESCE(pg_catalog.sum((pg_catalog.pg_stat_file('pg_logical/snapshots/' || name, missing_ok => true)).size), 0)
|
||||||
FROM (SELECT * FROM pg_ls_dir('pg_logical/snapshots') WHERE pg_ls_dir LIKE '%.snap') AS name
|
FROM (SELECT * FROM pg_catalog.pg_ls_dir('pg_logical/snapshots') WHERE pg_ls_dir LIKE '%.snap') AS name
|
||||||
) AS logical_snapshots_bytes;
|
) AS logical_snapshots_bytes;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT current_setting('max_connections') as max_connections;
|
SELECT pg_catalog.current_setting('max_connections') AS max_connections;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT datname database_name,
|
SELECT datname database_name,
|
||||||
age(datfrozenxid) frozen_xid_age
|
pg_catalog.age(datfrozenxid) frozen_xid_age
|
||||||
FROM pg_database
|
FROM pg_catalog.pg_database
|
||||||
ORDER BY frozen_xid_age DESC LIMIT 10;
|
ORDER BY frozen_xid_age DESC LIMIT 10;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT datname database_name,
|
SELECT datname database_name,
|
||||||
mxid_age(datminmxid) min_mxid_age
|
pg_catalog.mxid_age(datminmxid) min_mxid_age
|
||||||
FROM pg_database
|
FROM pg_catalog.pg_database
|
||||||
ORDER BY min_mxid_age DESC LIMIT 10;
|
ORDER BY min_mxid_age DESC LIMIT 10;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
SELECT CASE
|
SELECT CASE
|
||||||
WHEN pg_catalog.pg_is_in_recovery() THEN (pg_last_wal_receive_lsn() - '0/0')::FLOAT8
|
WHEN pg_catalog.pg_is_in_recovery() THEN (pg_catalog.pg_last_wal_receive_lsn() - '0/0')::pg_catalog.FLOAT8
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END AS lsn;
|
END AS lsn;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT subenabled::text AS enabled, count(*) AS subscriptions_count FROM pg_subscription GROUP BY subenabled;
|
SELECT subenabled::pg_catalog.text AS enabled, pg_catalog.count(*) AS subscriptions_count FROM pg_catalog.pg_subscription GROUP BY subenabled;
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT datname, state, count(*) AS count FROM pg_stat_activity WHERE state <> '' GROUP BY datname, state;
|
SELECT datname, state, pg_catalog.count(*) AS count FROM pg_catalog.pg_stat_activity WHERE state <> '' GROUP BY datname, state;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
SELECT sum(pg_database_size(datname)) AS total
|
SELECT pg_catalog.sum(pg_catalog.pg_database_size(datname)) AS total
|
||||||
FROM pg_database
|
FROM pg_catalog.pg_database
|
||||||
-- Ignore invalid databases, as we will likely have problems with
|
-- Ignore invalid databases, as we will likely have problems with
|
||||||
-- getting their size from the Pageserver.
|
-- getting their size from the Pageserver.
|
||||||
WHERE datconnlimit != -2;
|
WHERE datconnlimit != -2;
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
-- minutes.
|
-- minutes.
|
||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
x::text as duration_seconds,
|
x::pg_catalog.text AS duration_seconds,
|
||||||
neon.approximate_working_set_size_seconds(x) AS size
|
neon.approximate_working_set_size_seconds(x) AS size
|
||||||
FROM (SELECT generate_series * 60 AS x FROM generate_series(1, 60)) AS t (x);
|
FROM (SELECT generate_series * 60 AS x FROM generate_series(1, 60)) AS t (x);
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
|
|
||||||
SELECT
|
SELECT
|
||||||
x AS duration,
|
x AS duration,
|
||||||
neon.approximate_working_set_size_seconds(extract('epoch' FROM x::interval)::int) AS size FROM (
|
neon.approximate_working_set_size_seconds(extract('epoch' FROM x::pg_catalog.interval)::pg_catalog.int4) AS size FROM (
|
||||||
VALUES ('5m'), ('15m'), ('1h')
|
VALUES ('5m'), ('15m'), ('1h')
|
||||||
) AS t (x);
|
) AS t (x);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT pg_size_bytes(current_setting('neon.file_cache_size_limit')) AS lfc_cache_size_limit;
|
SELECT pg_catalog.pg_size_bytes(pg_catalog.current_setting('neon.file_cache_size_limit')) AS lfc_cache_size_limit;
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
SELECT slot_name, (restart_lsn - '0/0')::FLOAT8 as restart_lsn
|
SELECT slot_name, (restart_lsn - '0/0')::pg_catalog.FLOAT8 AS restart_lsn
|
||||||
FROM pg_replication_slots
|
FROM pg_catalog.pg_replication_slots
|
||||||
WHERE slot_type = 'logical';
|
WHERE slot_type = 'logical';
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
SELECT setting::int AS max_cluster_size FROM pg_settings WHERE name = 'neon.max_cluster_size';
|
SELECT setting::pg_catalog.int4 AS max_cluster_size FROM pg_catalog.pg_settings WHERE name = 'neon.max_cluster_size';
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
-- We export stats for 10 non-system databases. Without this limit it is too
|
-- We export stats for 10 non-system databases. Without this limit it is too
|
||||||
-- easy to abuse the system by creating lots of databases.
|
-- easy to abuse the system by creating lots of databases.
|
||||||
|
|
||||||
SELECT pg_database_size(datname) AS db_size,
|
SELECT pg_catalog.pg_database_size(datname) AS db_size,
|
||||||
deadlocks,
|
deadlocks,
|
||||||
tup_inserted AS inserted,
|
tup_inserted AS inserted,
|
||||||
tup_updated AS updated,
|
tup_updated AS updated,
|
||||||
tup_deleted AS deleted,
|
tup_deleted AS deleted,
|
||||||
datname
|
datname
|
||||||
FROM pg_stat_database
|
FROM pg_catalog.pg_stat_database
|
||||||
WHERE datname IN (
|
WHERE datname IN (
|
||||||
SELECT datname FROM pg_database
|
SELECT datname FROM pg_database
|
||||||
-- Ignore invalid databases, as we will likely have problems with
|
-- Ignore invalid databases, as we will likely have problems with
|
||||||
|
|||||||
@@ -3,4 +3,4 @@
|
|||||||
-- replay LSN may have advanced past the receive LSN we are using for the
|
-- replay LSN may have advanced past the receive LSN we are using for the
|
||||||
-- calculation.
|
-- calculation.
|
||||||
|
|
||||||
SELECT GREATEST(0, pg_wal_lsn_diff(pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn())) AS replication_delay_bytes;
|
SELECT GREATEST(0, pg_catalog.pg_wal_lsn_diff(pg_catalog.pg_last_wal_receive_lsn(), pg_catalog.pg_last_wal_replay_lsn())) AS replication_delay_bytes;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
SELECT
|
SELECT
|
||||||
CASE
|
CASE
|
||||||
WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() THEN 0
|
WHEN pg_catalog.pg_last_wal_receive_lsn() = pg_catalog.pg_last_wal_replay_lsn() THEN 0
|
||||||
ELSE GREATEST(0, EXTRACT (EPOCH FROM now() - pg_last_xact_replay_timestamp()))
|
ELSE GREATEST(0, EXTRACT (EPOCH FROM pg_catalog.now() - pg_catalog.pg_last_xact_replay_timestamp()))
|
||||||
END AS replication_delay_seconds;
|
END AS replication_delay_seconds;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
SELECT
|
SELECT
|
||||||
slot_name,
|
slot_name,
|
||||||
pg_wal_lsn_diff(
|
pg_catalog.pg_wal_lsn_diff(
|
||||||
CASE
|
CASE
|
||||||
WHEN pg_is_in_recovery() THEN pg_last_wal_replay_lsn()
|
WHEN pg_catalog.pg_is_in_recovery() THEN pg_catalog.pg_last_wal_replay_lsn()
|
||||||
ELSE pg_current_wal_lsn()
|
ELSE pg_catalog.pg_current_wal_lsn()
|
||||||
END,
|
END,
|
||||||
restart_lsn)::FLOAT8 AS retained_wal
|
restart_lsn)::pg_catalog.FLOAT8 AS retained_wal
|
||||||
FROM pg_replication_slots
|
FROM pg_catalog.pg_replication_slots
|
||||||
WHERE active = false;
|
WHERE active = false;
|
||||||
|
|||||||
@@ -4,4 +4,4 @@ SELECT
|
|||||||
WHEN wal_status = 'lost' THEN 1
|
WHEN wal_status = 'lost' THEN 1
|
||||||
ELSE 0
|
ELSE 0
|
||||||
END AS wal_is_lost
|
END AS wal_is_lost
|
||||||
FROM pg_replication_slots;
|
FROM pg_catalog.pg_replication_slots;
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ fn main() -> Result<()> {
|
|||||||
config,
|
config,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let exit_code = compute_node.run()?;
|
let exit_code = compute_node.run().context("running compute node")?;
|
||||||
|
|
||||||
scenario.teardown();
|
scenario.teardown();
|
||||||
|
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ pub async fn check_writability(compute: &ComputeNode) -> Result<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let query = "
|
let query = "
|
||||||
INSERT INTO health_check VALUES (1, now())
|
INSERT INTO public.health_check VALUES (1, pg_catalog.now())
|
||||||
ON CONFLICT (id) DO UPDATE
|
ON CONFLICT (id) DO UPDATE
|
||||||
SET updated_at = now();";
|
SET updated_at = pg_catalog.now();";
|
||||||
|
|
||||||
match client.simple_query(query).await {
|
match client.simple_query(query).await {
|
||||||
Result::Ok(result) => {
|
Result::Ok(result) => {
|
||||||
|
|||||||
@@ -583,7 +583,7 @@ impl ComputeNode {
|
|||||||
// that can affect `compute_ctl` and prevent it from properly configuring the database schema.
|
// that can affect `compute_ctl` and prevent it from properly configuring the database schema.
|
||||||
// Unset them via connection string options before connecting to the database.
|
// Unset them via connection string options before connecting to the database.
|
||||||
// N.B. keep it in sync with `ZENITH_OPTIONS` in `get_maintenance_client()`.
|
// N.B. keep it in sync with `ZENITH_OPTIONS` in `get_maintenance_client()`.
|
||||||
const EXTRA_OPTIONS: &str = "-c role=cloud_admin -c default_transaction_read_only=off -c search_path=public -c statement_timeout=0 -c pgaudit.log=none";
|
const EXTRA_OPTIONS: &str = "-c role=cloud_admin -c default_transaction_read_only=off -c search_path='' -c statement_timeout=0 -c pgaudit.log=none";
|
||||||
let options = match conn_conf.get_options() {
|
let options = match conn_conf.get_options() {
|
||||||
// Allow the control plane to override any options set by the
|
// Allow the control plane to override any options set by the
|
||||||
// compute
|
// compute
|
||||||
@@ -1884,7 +1884,7 @@ impl ComputeNode {
|
|||||||
|
|
||||||
// It doesn't matter what were the options before, here we just want
|
// It doesn't matter what were the options before, here we just want
|
||||||
// to connect and create a new superuser role.
|
// to connect and create a new superuser role.
|
||||||
const ZENITH_OPTIONS: &str = "-c role=zenith_admin -c default_transaction_read_only=off -c search_path=public -c statement_timeout=0";
|
const ZENITH_OPTIONS: &str = "-c role=zenith_admin -c default_transaction_read_only=off -c search_path='' -c statement_timeout=0";
|
||||||
zenith_admin_conf.options(ZENITH_OPTIONS);
|
zenith_admin_conf.options(ZENITH_OPTIONS);
|
||||||
|
|
||||||
let mut client =
|
let mut client =
|
||||||
@@ -2339,13 +2339,13 @@ impl ComputeNode {
|
|||||||
let result = client
|
let result = client
|
||||||
.simple_query(
|
.simple_query(
|
||||||
"SELECT
|
"SELECT
|
||||||
row_to_json(pg_stat_statements)
|
pg_catalog.row_to_json(pss)
|
||||||
FROM
|
FROM
|
||||||
pg_stat_statements
|
public.pg_stat_statements pss
|
||||||
WHERE
|
WHERE
|
||||||
userid != 'cloud_admin'::regrole::oid
|
pss.userid != 'cloud_admin'::pg_catalog.regrole::pg_catalog.oid
|
||||||
ORDER BY
|
ORDER BY
|
||||||
(mean_exec_time + mean_plan_time) DESC
|
(pss.mean_exec_time + pss.mean_plan_time) DESC
|
||||||
LIMIT 100",
|
LIMIT 100",
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -2473,11 +2473,11 @@ LIMIT 100",
|
|||||||
|
|
||||||
// check the role grants first - to gracefully handle read-replicas.
|
// check the role grants first - to gracefully handle read-replicas.
|
||||||
let select = "SELECT privilege_type
|
let select = "SELECT privilege_type
|
||||||
FROM pg_namespace
|
FROM pg_catalog.pg_namespace
|
||||||
JOIN LATERAL (SELECT * FROM aclexplode(nspacl) AS x) acl ON true
|
JOIN LATERAL (SELECT * FROM aclexplode(nspacl) AS x) AS acl ON true
|
||||||
JOIN pg_user users ON acl.grantee = users.usesysid
|
JOIN pg_catalog.pg_user users ON acl.grantee = users.usesysid
|
||||||
WHERE users.usename = $1
|
WHERE users.usename OPERATOR(pg_catalog.=) $1::pg_catalog.name
|
||||||
AND nspname = $2";
|
AND nspname OPERATOR(pg_catalog.=) $2::pg_catalog.name";
|
||||||
let rows = db_client
|
let rows = db_client
|
||||||
.query(select, &[role_name, schema_name])
|
.query(select, &[role_name, schema_name])
|
||||||
.await
|
.await
|
||||||
@@ -2546,8 +2546,9 @@ LIMIT 100",
|
|||||||
.await
|
.await
|
||||||
.with_context(|| format!("Failed to execute query: {query}"))?;
|
.with_context(|| format!("Failed to execute query: {query}"))?;
|
||||||
} else {
|
} else {
|
||||||
let query =
|
let query = format!(
|
||||||
format!("CREATE EXTENSION IF NOT EXISTS {ext_name} WITH VERSION {quoted_version}");
|
"CREATE EXTENSION IF NOT EXISTS {ext_name} WITH SCHEMA public VERSION {quoted_version}"
|
||||||
|
);
|
||||||
db_client
|
db_client
|
||||||
.simple_query(&query)
|
.simple_query(&query)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ impl ComputeNode {
|
|||||||
const RETRIES: i32 = 20;
|
const RETRIES: i32 = 20;
|
||||||
for i in 0..=RETRIES {
|
for i in 0..=RETRIES {
|
||||||
let row = client
|
let row = client
|
||||||
.query_one("SELECT pg_last_wal_replay_lsn()", &[])
|
.query_one("SELECT pg_catalog.pg_last_wal_replay_lsn()", &[])
|
||||||
.await
|
.await
|
||||||
.context("getting last replay lsn")?;
|
.context("getting last replay lsn")?;
|
||||||
let lsn: u64 = row.get::<usize, postgres_types::PgLsn>(0).into();
|
let lsn: u64 = row.get::<usize, postgres_types::PgLsn>(0).into();
|
||||||
@@ -103,7 +103,7 @@ impl ComputeNode {
|
|||||||
.await
|
.await
|
||||||
.context("setting safekeepers")?;
|
.context("setting safekeepers")?;
|
||||||
client
|
client
|
||||||
.query("SELECT pg_reload_conf()", &[])
|
.query("SELECT pg_catalog.pg_reload_conf()", &[])
|
||||||
.await
|
.await
|
||||||
.context("reloading postgres config")?;
|
.context("reloading postgres config")?;
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ impl ComputeNode {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let row = client
|
let row = client
|
||||||
.query_one("SELECT * FROM pg_promote()", &[])
|
.query_one("SELECT * FROM pg_catalog.pg_promote()", &[])
|
||||||
.await
|
.await
|
||||||
.context("pg_promote")?;
|
.context("pg_promote")?;
|
||||||
if !row.get::<usize, bool>(0) {
|
if !row.get::<usize, bool>(0) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ async fn list_dbs(client: &mut Client) -> Result<Vec<String>, PostgresError> {
|
|||||||
.query(
|
.query(
|
||||||
"SELECT datname FROM pg_catalog.pg_database
|
"SELECT datname FROM pg_catalog.pg_database
|
||||||
WHERE datallowconn
|
WHERE datallowconn
|
||||||
AND datconnlimit <> - 2
|
AND datconnlimit OPERATOR(pg_catalog.<>) (OPERATOR(pg_catalog.-) 2::pg_catalog.int4)
|
||||||
LIMIT 500",
|
LIMIT 500",
|
||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
@@ -67,7 +67,7 @@ pub async fn get_installed_extensions(
|
|||||||
|
|
||||||
let extensions: Vec<(String, String, i32)> = client
|
let extensions: Vec<(String, String, i32)> = client
|
||||||
.query(
|
.query(
|
||||||
"SELECT extname, extversion, extowner::integer FROM pg_catalog.pg_extension",
|
"SELECT extname, extversion, extowner::pg_catalog.int4 FROM pg_catalog.pg_extension",
|
||||||
&[],
|
&[],
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ impl<'m> MigrationRunner<'m> {
|
|||||||
self.client
|
self.client
|
||||||
.simple_query("CREATE SCHEMA IF NOT EXISTS neon_migration")
|
.simple_query("CREATE SCHEMA IF NOT EXISTS neon_migration")
|
||||||
.await?;
|
.await?;
|
||||||
self.client.simple_query("CREATE TABLE IF NOT EXISTS neon_migration.migration_id (key INT NOT NULL PRIMARY KEY, id bigint NOT NULL DEFAULT 0)").await?;
|
self.client.simple_query("CREATE TABLE IF NOT EXISTS neon_migration.migration_id (key pg_catalog.int4 NOT NULL PRIMARY KEY, id pg_catalog.int8 NOT NULL DEFAULT 0)").await?;
|
||||||
self.client
|
self.client
|
||||||
.simple_query(
|
.simple_query(
|
||||||
"INSERT INTO neon_migration.migration_id VALUES (0, 0) ON CONFLICT DO NOTHING",
|
"INSERT INTO neon_migration.migration_id VALUES (0, 0) ON CONFLICT DO NOTHING",
|
||||||
|
|||||||
@@ -15,17 +15,17 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
role_name text;
|
role_name text;
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR role_name IN SELECT rolname FROM pg_roles WHERE pg_has_role(rolname, '{privileged_role_name}', 'member')
|
FOR role_name IN SELECT rolname FROM pg_catalog.pg_roles WHERE pg_catalog.pg_has_role(rolname, '{privileged_role_name}', 'member')
|
||||||
LOOP
|
LOOP
|
||||||
RAISE NOTICE 'EXECUTING ALTER ROLE % INHERIT', quote_ident(role_name);
|
RAISE NOTICE 'EXECUTING ALTER ROLE % INHERIT', pg_catalog.quote_ident(role_name);
|
||||||
EXECUTE 'ALTER ROLE ' || quote_ident(role_name) || ' INHERIT';
|
EXECUTE pg_catalog.format('ALTER ROLE %I INHERIT;', role_name);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
|
|
||||||
FOR role_name IN SELECT rolname FROM pg_roles
|
FOR role_name IN SELECT rolname FROM pg_catalog.pg_roles
|
||||||
WHERE
|
WHERE
|
||||||
NOT pg_has_role(rolname, '{privileged_role_name}', 'member') AND NOT starts_with(rolname, 'pg_')
|
NOT pg_catalog.pg_has_role(rolname, '{privileged_role_name}', 'member') AND NOT pg_catalog.starts_with(rolname, 'pg_')
|
||||||
LOOP
|
LOOP
|
||||||
RAISE NOTICE 'EXECUTING ALTER ROLE % NOBYPASSRLS', quote_ident(role_name);
|
RAISE NOTICE 'EXECUTING ALTER ROLE % NOBYPASSRLS', pg_catalog.quote_ident(role_name);
|
||||||
EXECUTE 'ALTER ROLE ' || quote_ident(role_name) || ' NOBYPASSRLS';
|
EXECUTE pg_catalog.format('ALTER ROLE %I NOBYPASSRLS;', role_name);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END $$;
|
END $$;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF (SELECT setting::numeric >= 160000 FROM pg_settings WHERE name = 'server_version_num') THEN
|
IF (SELECT setting::pg_catalog.numeric >= 160000 FROM pg_catalog.pg_settings WHERE name = 'server_version_num') THEN
|
||||||
EXECUTE 'GRANT pg_create_subscription TO {privileged_role_name}';
|
EXECUTE 'GRANT pg_create_subscription TO {privileged_role_name}';
|
||||||
END IF;
|
END IF;
|
||||||
END $$;
|
END $$;
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
role_name TEXT;
|
role_name TEXT;
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR role_name IN SELECT rolname FROM pg_roles WHERE rolreplication IS TRUE
|
FOR role_name IN SELECT rolname FROM pg_catalog.pg_roles WHERE rolreplication IS TRUE
|
||||||
LOOP
|
LOOP
|
||||||
RAISE NOTICE 'EXECUTING ALTER ROLE % NOREPLICATION', quote_ident(role_name);
|
RAISE NOTICE 'EXECUTING ALTER ROLE % NOREPLICATION', pg_catalog.quote_ident(role_name);
|
||||||
EXECUTE 'ALTER ROLE ' || quote_ident(role_name) || ' NOREPLICATION';
|
EXECUTE pg_catalog.format('ALTER ROLE %I NOREPLICATION;', role_name);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END $$;
|
END $$;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF (SELECT setting::numeric >= 160000 FROM pg_settings WHERE name = 'server_version_num') THEN
|
IF (SELECT setting::pg_catalog.numeric >= 160000 FROM pg_catalog.pg_settings WHERE name OPERATOR(pg_catalog.=) 'server_version_num'::pg_catalog.text) THEN
|
||||||
EXECUTE 'GRANT EXECUTE ON FUNCTION pg_export_snapshot TO {privileged_role_name}';
|
EXECUTE 'GRANT EXECUTE ON FUNCTION pg_export_snapshot TO {privileged_role_name}';
|
||||||
EXECUTE 'GRANT EXECUTE ON FUNCTION pg_log_standby_snapshot TO {privileged_role_name}';
|
EXECUTE 'GRANT EXECUTE ON FUNCTION pg_log_standby_snapshot TO {privileged_role_name}';
|
||||||
END IF;
|
END IF;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
bypassrls boolean;
|
bypassrls boolean;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT rolbypassrls INTO bypassrls FROM pg_roles WHERE rolname = 'neon_superuser';
|
SELECT rolbypassrls INTO bypassrls FROM pg_catalog.pg_roles WHERE rolname = 'neon_superuser';
|
||||||
IF NOT bypassrls THEN
|
IF NOT bypassrls THEN
|
||||||
RAISE EXCEPTION 'neon_superuser cannot bypass RLS';
|
RAISE EXCEPTION 'neon_superuser cannot bypass RLS';
|
||||||
END IF;
|
END IF;
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ DECLARE
|
|||||||
BEGIN
|
BEGIN
|
||||||
FOR role IN
|
FOR role IN
|
||||||
SELECT rolname AS name, rolinherit AS inherit
|
SELECT rolname AS name, rolinherit AS inherit
|
||||||
FROM pg_roles
|
FROM pg_catalog.pg_roles
|
||||||
WHERE pg_has_role(rolname, 'neon_superuser', 'member')
|
WHERE pg_catalog.pg_has_role(rolname, 'neon_superuser', 'member')
|
||||||
LOOP
|
LOOP
|
||||||
IF NOT role.inherit THEN
|
IF NOT role.inherit THEN
|
||||||
RAISE EXCEPTION '% cannot inherit', quote_ident(role.name);
|
RAISE EXCEPTION '% cannot inherit', quote_ident(role.name);
|
||||||
@@ -14,12 +14,12 @@ BEGIN
|
|||||||
|
|
||||||
FOR role IN
|
FOR role IN
|
||||||
SELECT rolname AS name, rolbypassrls AS bypassrls
|
SELECT rolname AS name, rolbypassrls AS bypassrls
|
||||||
FROM pg_roles
|
FROM pg_catalog.pg_roles
|
||||||
WHERE NOT pg_has_role(rolname, 'neon_superuser', 'member')
|
WHERE NOT pg_catalog.pg_has_role(rolname, 'neon_superuser', 'member')
|
||||||
AND NOT starts_with(rolname, 'pg_')
|
AND NOT pg_catalog.starts_with(rolname, 'pg_')
|
||||||
LOOP
|
LOOP
|
||||||
IF role.bypassrls THEN
|
IF role.bypassrls THEN
|
||||||
RAISE EXCEPTION '% can bypass RLS', quote_ident(role.name);
|
RAISE EXCEPTION '% can bypass RLS', pg_catalog.quote_ident(role.name);
|
||||||
END IF;
|
END IF;
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END $$;
|
END $$;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF (SELECT current_setting('server_version_num')::numeric < 160000) THEN
|
IF (SELECT pg_catalog.current_setting('server_version_num')::pg_catalog.numeric < 160000) THEN
|
||||||
RETURN;
|
RETURN;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
IF NOT (SELECT pg_has_role('neon_superuser', 'pg_create_subscription', 'member')) THEN
|
IF NOT (SELECT pg_catalog.pg_has_role('neon_superuser', 'pg_create_subscription', 'member')) THEN
|
||||||
RAISE EXCEPTION 'neon_superuser cannot execute pg_create_subscription';
|
RAISE EXCEPTION 'neon_superuser cannot execute pg_create_subscription';
|
||||||
END IF;
|
END IF;
|
||||||
END $$;
|
END $$;
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
monitor record;
|
monitor record;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT pg_has_role('neon_superuser', 'pg_monitor', 'member') AS member,
|
SELECT pg_catalog.pg_has_role('neon_superuser', 'pg_monitor', 'member') AS member,
|
||||||
admin_option AS admin
|
admin_option AS admin
|
||||||
INTO monitor
|
INTO monitor
|
||||||
FROM pg_auth_members
|
FROM pg_catalog.pg_auth_members
|
||||||
WHERE roleid = 'pg_monitor'::regrole
|
WHERE roleid = 'pg_monitor'::pg_catalog.regrole
|
||||||
AND member = 'neon_superuser'::regrole;
|
AND member = 'neon_superuser'::pg_catalog.regrole;
|
||||||
|
|
||||||
IF monitor IS NULL THEN
|
IF monitor IS NULL THEN
|
||||||
RAISE EXCEPTION 'no entry in pg_auth_members for neon_superuser and pg_monitor';
|
RAISE EXCEPTION 'no entry in pg_auth_members for neon_superuser and pg_monitor';
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
can_execute boolean;
|
can_execute boolean;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT bool_and(has_function_privilege('neon_superuser', oid, 'execute'))
|
SELECT pg_catalog.bool_and(pg_catalog.has_function_privilege('neon_superuser', oid, 'execute'))
|
||||||
INTO can_execute
|
INTO can_execute
|
||||||
FROM pg_proc
|
FROM pg_catalog.pg_proc
|
||||||
WHERE proname IN ('pg_export_snapshot', 'pg_log_standby_snapshot')
|
WHERE proname IN ('pg_export_snapshot', 'pg_log_standby_snapshot')
|
||||||
AND pronamespace = 'pg_catalog'::regnamespace;
|
AND pronamespace = 'pg_catalog'::pg_catalog.regnamespace;
|
||||||
IF NOT can_execute THEN
|
IF NOT can_execute THEN
|
||||||
RAISE EXCEPTION 'neon_superuser cannot execute both pg_export_snapshot and pg_log_standby_snapshot';
|
RAISE EXCEPTION 'neon_superuser cannot execute both pg_export_snapshot and pg_log_standby_snapshot';
|
||||||
END IF;
|
END IF;
|
||||||
|
|||||||
@@ -2,9 +2,9 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
can_execute boolean;
|
can_execute boolean;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT has_function_privilege('neon_superuser', oid, 'execute')
|
SELECT pg_catalog.has_function_privilege('neon_superuser', oid, 'execute')
|
||||||
INTO can_execute
|
INTO can_execute
|
||||||
FROM pg_proc
|
FROM pg_catalog.pg_proc
|
||||||
WHERE proname = 'pg_show_replication_origin_status'
|
WHERE proname = 'pg_show_replication_origin_status'
|
||||||
AND pronamespace = 'pg_catalog'::regnamespace;
|
AND pronamespace = 'pg_catalog'::regnamespace;
|
||||||
IF NOT can_execute THEN
|
IF NOT can_execute THEN
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
signal_backend record;
|
signal_backend record;
|
||||||
BEGIN
|
BEGIN
|
||||||
SELECT pg_has_role('neon_superuser', 'pg_signal_backend', 'member') AS member,
|
SELECT pg_catalog.pg_has_role('neon_superuser', 'pg_signal_backend', 'member') AS member,
|
||||||
admin_option AS admin
|
admin_option AS admin
|
||||||
INTO signal_backend
|
INTO signal_backend
|
||||||
FROM pg_auth_members
|
FROM pg_catalog.pg_auth_members
|
||||||
WHERE roleid = 'pg_signal_backend'::regrole
|
WHERE roleid = 'pg_signal_backend'::regrole
|
||||||
AND member = 'neon_superuser'::regrole;
|
AND member = 'neon_superuser'::regrole;
|
||||||
|
|
||||||
|
|||||||
@@ -407,9 +407,9 @@ fn get_database_stats(cli: &mut Client) -> anyhow::Result<(f64, i64)> {
|
|||||||
// like `postgres_exporter` use it to query Postgres statistics.
|
// like `postgres_exporter` use it to query Postgres statistics.
|
||||||
// Use explicit 8 bytes type casts to match Rust types.
|
// Use explicit 8 bytes type casts to match Rust types.
|
||||||
let stats = cli.query_one(
|
let stats = cli.query_one(
|
||||||
"SELECT coalesce(sum(active_time), 0.0)::float8 AS total_active_time,
|
"SELECT pg_catalog.coalesce(pg_catalog.sum(active_time), 0.0)::pg_catalog.float8 AS total_active_time,
|
||||||
coalesce(sum(sessions), 0)::bigint AS total_sessions
|
pg_catalog.coalesce(pg_catalog.sum(sessions), 0)::pg_catalog.bigint AS total_sessions
|
||||||
FROM pg_stat_database
|
FROM pg_catalog.pg_stat_database
|
||||||
WHERE datname NOT IN (
|
WHERE datname NOT IN (
|
||||||
'postgres',
|
'postgres',
|
||||||
'template0',
|
'template0',
|
||||||
@@ -445,11 +445,11 @@ fn get_backends_state_change(cli: &mut Client) -> anyhow::Result<Option<DateTime
|
|||||||
let mut last_active: Option<DateTime<Utc>> = None;
|
let mut last_active: Option<DateTime<Utc>> = None;
|
||||||
// Get all running client backends except ourself, use RFC3339 DateTime format.
|
// Get all running client backends except ourself, use RFC3339 DateTime format.
|
||||||
let backends = cli.query(
|
let backends = cli.query(
|
||||||
"SELECT state, to_char(state_change, 'YYYY-MM-DD\"T\"HH24:MI:SS.US\"Z\"') AS state_change
|
"SELECT state, pg_catalog.to_char(state_change, 'YYYY-MM-DD\"T\"HH24:MI:SS.US\"Z\"'::pg_catalog.text) AS state_change
|
||||||
FROM pg_stat_activity
|
FROM pg_stat_activity
|
||||||
WHERE backend_type = 'client backend'
|
WHERE backend_type OPERATOR(pg_catalog.=) 'client backend'::pg_catalog.text
|
||||||
AND pid != pg_backend_pid()
|
AND pid OPERATOR(pg_catalog.!=) pg_catalog.pg_backend_pid()
|
||||||
AND usename != 'cloud_admin';", // XXX: find a better way to filter other monitors?
|
AND usename OPERATOR(pg_catalog.!=) 'cloud_admin'::pg_catalog.name;", // XXX: find a better way to filter other monitors?
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -299,9 +299,9 @@ pub async fn get_existing_dbs_async(
|
|||||||
.query_raw::<str, &String, &[String; 0]>(
|
.query_raw::<str, &String, &[String; 0]>(
|
||||||
"SELECT
|
"SELECT
|
||||||
datname AS name,
|
datname AS name,
|
||||||
(SELECT rolname FROM pg_roles WHERE oid = datdba) AS owner,
|
(SELECT rolname FROM pg_catalog.pg_roles WHERE oid OPERATOR(pg_catalog.=) datdba) AS owner,
|
||||||
NOT datallowconn AS restrict_conn,
|
NOT datallowconn AS restrict_conn,
|
||||||
datconnlimit = - 2 AS invalid
|
datconnlimit OPERATOR(pg_catalog.=) (OPERATOR(pg_catalog.-) 2) AS invalid
|
||||||
FROM
|
FROM
|
||||||
pg_catalog.pg_database;",
|
pg_catalog.pg_database;",
|
||||||
&[],
|
&[],
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ impl ComputeNode {
|
|||||||
info!("Checking if drop subscription operation was already performed for timeline_id: {}", timeline_id);
|
info!("Checking if drop subscription operation was already performed for timeline_id: {}", timeline_id);
|
||||||
|
|
||||||
drop_subscriptions_done = match
|
drop_subscriptions_done = match
|
||||||
client.query("select 1 from neon.drop_subscriptions_done where timeline_id = $1", &[&timeline_id.to_string()]).await {
|
client.query("select 1 from neon.drop_subscriptions_done where timeline_id OPERATOR(pg_catalog.=) $1", &[&timeline_id.to_string()]).await {
|
||||||
Ok(result) => !result.is_empty(),
|
Ok(result) => !result.is_empty(),
|
||||||
Err(e) =>
|
Err(e) =>
|
||||||
{
|
{
|
||||||
@@ -1142,7 +1142,9 @@ async fn get_operations<'a>(
|
|||||||
if let Some(libs) = spec.cluster.settings.find("shared_preload_libraries") {
|
if let Some(libs) = spec.cluster.settings.find("shared_preload_libraries") {
|
||||||
if libs.contains("pg_stat_statements") {
|
if libs.contains("pg_stat_statements") {
|
||||||
return Ok(Box::new(once(Operation {
|
return Ok(Box::new(once(Operation {
|
||||||
query: String::from("CREATE EXTENSION IF NOT EXISTS pg_stat_statements"),
|
query: String::from(
|
||||||
|
"CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA public",
|
||||||
|
),
|
||||||
comment: Some(String::from("create system extensions")),
|
comment: Some(String::from("create system extensions")),
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
@@ -1150,11 +1152,13 @@ async fn get_operations<'a>(
|
|||||||
Ok(Box::new(empty()))
|
Ok(Box::new(empty()))
|
||||||
}
|
}
|
||||||
ApplySpecPhase::CreatePgauditExtension => Ok(Box::new(once(Operation {
|
ApplySpecPhase::CreatePgauditExtension => Ok(Box::new(once(Operation {
|
||||||
query: String::from("CREATE EXTENSION IF NOT EXISTS pgaudit"),
|
query: String::from("CREATE EXTENSION IF NOT EXISTS pgaudit WITH SCHEMA public"),
|
||||||
comment: Some(String::from("create pgaudit extensions")),
|
comment: Some(String::from("create pgaudit extensions")),
|
||||||
}))),
|
}))),
|
||||||
ApplySpecPhase::CreatePgauditlogtofileExtension => Ok(Box::new(once(Operation {
|
ApplySpecPhase::CreatePgauditlogtofileExtension => Ok(Box::new(once(Operation {
|
||||||
query: String::from("CREATE EXTENSION IF NOT EXISTS pgauditlogtofile"),
|
query: String::from(
|
||||||
|
"CREATE EXTENSION IF NOT EXISTS pgauditlogtofile WITH SCHEMA public",
|
||||||
|
),
|
||||||
comment: Some(String::from("create pgauditlogtofile extensions")),
|
comment: Some(String::from("create pgauditlogtofile extensions")),
|
||||||
}))),
|
}))),
|
||||||
// Disable pgaudit logging for postgres database.
|
// Disable pgaudit logging for postgres database.
|
||||||
@@ -1178,7 +1182,7 @@ async fn get_operations<'a>(
|
|||||||
},
|
},
|
||||||
Operation {
|
Operation {
|
||||||
query: String::from(
|
query: String::from(
|
||||||
"UPDATE pg_extension SET extrelocatable = true WHERE extname = 'neon'",
|
"UPDATE pg_catalog.pg_extension SET extrelocatable = true WHERE extname OPERATOR(pg_catalog.=) 'neon'::pg_catalog.name AND extrelocatable OPERATOR(pg_catalog.=) false",
|
||||||
),
|
),
|
||||||
comment: Some(String::from("compat/fix: make neon relocatable")),
|
comment: Some(String::from("compat/fix: make neon relocatable")),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,16 +3,17 @@ BEGIN
|
|||||||
IF NOT EXISTS(
|
IF NOT EXISTS(
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM pg_catalog.pg_tables
|
FROM pg_catalog.pg_tables
|
||||||
WHERE tablename = 'health_check'
|
WHERE tablename::pg_catalog.name OPERATOR(pg_catalog.=) 'health_check'::pg_catalog.name
|
||||||
|
AND schemaname::pg_catalog.name OPERATOR(pg_catalog.=) 'public'::pg_catalog.name
|
||||||
)
|
)
|
||||||
THEN
|
THEN
|
||||||
CREATE TABLE health_check (
|
CREATE TABLE public.health_check (
|
||||||
id serial primary key,
|
id pg_catalog.int4 primary key generated by default as identity,
|
||||||
updated_at timestamptz default now()
|
updated_at pg_catalog.timestamptz default pg_catalog.now()
|
||||||
);
|
);
|
||||||
INSERT INTO health_check VALUES (1, now())
|
INSERT INTO public.health_check VALUES (1, pg_catalog.now())
|
||||||
ON CONFLICT (id) DO UPDATE
|
ON CONFLICT (id) DO UPDATE
|
||||||
SET updated_at = now();
|
SET updated_at = pg_catalog.now();
|
||||||
END IF;
|
END IF;
|
||||||
END
|
END
|
||||||
$$
|
$$
|
||||||
@@ -2,10 +2,11 @@ DO $$
|
|||||||
DECLARE
|
DECLARE
|
||||||
query varchar;
|
query varchar;
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR query IN SELECT 'ALTER FUNCTION '||nsp.nspname||'.'||p.proname||'('||pg_get_function_identity_arguments(p.oid)||') OWNER TO {db_owner};'
|
FOR query IN
|
||||||
FROM pg_proc p
|
SELECT pg_catalog.format('ALTER FUNCTION %I(%s) OWNER TO {db_owner};', p.oid::regproc, pg_catalog.pg_get_function_identity_arguments(p.oid))
|
||||||
JOIN pg_namespace nsp ON p.pronamespace = nsp.oid
|
FROM pg_catalog.pg_proc p
|
||||||
WHERE nsp.nspname = 'anon' LOOP
|
WHERE p.pronamespace OPERATOR(pg_catalog.=) 'anon'::regnamespace::oid
|
||||||
|
LOOP
|
||||||
EXECUTE query;
|
EXECUTE query;
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
DO $$
|
DO $$
|
||||||
BEGIN
|
BEGIN
|
||||||
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname = '{privileged_role_name}')
|
IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname OPERATOR(pg_catalog.=) '{privileged_role_name}'::pg_catalog.name)
|
||||||
THEN
|
THEN
|
||||||
CREATE ROLE {privileged_role_name} {privileges} IN ROLE pg_read_all_data, pg_write_all_data;
|
CREATE ROLE {privileged_role_name} {privileges} IN ROLE pg_read_all_data, pg_write_all_data;
|
||||||
END IF;
|
END IF;
|
||||||
|
|||||||
@@ -4,14 +4,14 @@ $$
|
|||||||
IF EXISTS(
|
IF EXISTS(
|
||||||
SELECT nspname
|
SELECT nspname
|
||||||
FROM pg_catalog.pg_namespace
|
FROM pg_catalog.pg_namespace
|
||||||
WHERE nspname = 'public'
|
WHERE nspname OPERATOR(pg_catalog.=) 'public'
|
||||||
) AND
|
) AND
|
||||||
current_setting('server_version_num')::int / 10000 >= 15
|
pg_catalog.current_setting('server_version_num')::int OPERATOR(pg_catalog./) 10000 OPERATOR(pg_catalog.>=) 15
|
||||||
THEN
|
THEN
|
||||||
IF EXISTS(
|
IF EXISTS(
|
||||||
SELECT rolname
|
SELECT rolname
|
||||||
FROM pg_catalog.pg_roles
|
FROM pg_catalog.pg_roles
|
||||||
WHERE rolname = 'web_access'
|
WHERE rolname OPERATOR(pg_catalog.=) 'web_access'
|
||||||
)
|
)
|
||||||
THEN
|
THEN
|
||||||
GRANT CREATE ON SCHEMA public TO web_access;
|
GRANT CREATE ON SCHEMA public TO web_access;
|
||||||
@@ -20,7 +20,7 @@ $$
|
|||||||
IF EXISTS(
|
IF EXISTS(
|
||||||
SELECT nspname
|
SELECT nspname
|
||||||
FROM pg_catalog.pg_namespace
|
FROM pg_catalog.pg_namespace
|
||||||
WHERE nspname = 'public'
|
WHERE nspname OPERATOR(pg_catalog.=) 'public'
|
||||||
)
|
)
|
||||||
THEN
|
THEN
|
||||||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO neon_superuser WITH GRANT OPTION;
|
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO neon_superuser WITH GRANT OPTION;
|
||||||
|
|||||||
@@ -2,11 +2,17 @@ DO ${outer_tag}$
|
|||||||
DECLARE
|
DECLARE
|
||||||
subname TEXT;
|
subname TEXT;
|
||||||
BEGIN
|
BEGIN
|
||||||
LOCK TABLE pg_subscription IN ACCESS EXCLUSIVE MODE;
|
LOCK TABLE pg_catalog.pg_subscription IN ACCESS EXCLUSIVE MODE;
|
||||||
FOR subname IN SELECT pg_subscription.subname FROM pg_subscription WHERE subdbid = (SELECT oid FROM pg_database WHERE datname = {datname_str}) LOOP
|
FOR subname IN
|
||||||
EXECUTE format('ALTER SUBSCRIPTION %I DISABLE;', subname);
|
SELECT pg_subscription.subname
|
||||||
EXECUTE format('ALTER SUBSCRIPTION %I SET (slot_name = NONE);', subname);
|
FROM pg_catalog.pg_subscription
|
||||||
EXECUTE format('DROP SUBSCRIPTION %I;', subname);
|
WHERE subdbid OPERATOR(pg_catalog.=) (
|
||||||
|
SELECT oid FROM pg_database WHERE datname OPERATOR(pg_catalog.=) {datname_str}::pg_catalog.name
|
||||||
|
)
|
||||||
|
LOOP
|
||||||
|
EXECUTE pg_catalog.format('ALTER SUBSCRIPTION %I DISABLE;', subname);
|
||||||
|
EXECUTE pg_catalog.format('ALTER SUBSCRIPTION %I SET (slot_name = NONE);', subname);
|
||||||
|
EXECUTE pg_catalog.format('DROP SUBSCRIPTION %I;', subname);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END;
|
END;
|
||||||
${outer_tag}$;
|
${outer_tag}$;
|
||||||
|
|||||||
@@ -3,19 +3,19 @@ BEGIN
|
|||||||
IF NOT EXISTS(
|
IF NOT EXISTS(
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM pg_catalog.pg_tables
|
FROM pg_catalog.pg_tables
|
||||||
WHERE tablename = 'drop_subscriptions_done'
|
WHERE tablename OPERATOR(pg_catalog.=) 'drop_subscriptions_done'::pg_catalog.name
|
||||||
AND schemaname = 'neon'
|
AND schemaname OPERATOR(pg_catalog.=) 'neon'::pg_catalog.name
|
||||||
)
|
)
|
||||||
THEN
|
THEN
|
||||||
CREATE TABLE neon.drop_subscriptions_done
|
CREATE TABLE neon.drop_subscriptions_done
|
||||||
(id serial primary key, timeline_id text);
|
(id pg_catalog.int4 primary key generated by default as identity, timeline_id pg_catalog.text);
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- preserve the timeline_id of the last drop_subscriptions run
|
-- preserve the timeline_id of the last drop_subscriptions run
|
||||||
-- to ensure that the cleanup of a timeline is executed only once.
|
-- to ensure that the cleanup of a timeline is executed only once.
|
||||||
-- use upsert to avoid the table bloat in case of cascade branching (branch of a branch)
|
-- use upsert to avoid the table bloat in case of cascade branching (branch of a branch)
|
||||||
INSERT INTO neon.drop_subscriptions_done VALUES (1, current_setting('neon.timeline_id'))
|
INSERT INTO neon.drop_subscriptions_done VALUES (1, pg_catalog.current_setting('neon.timeline_id'))
|
||||||
ON CONFLICT (id) DO UPDATE
|
ON CONFLICT (id) DO UPDATE
|
||||||
SET timeline_id = current_setting('neon.timeline_id');
|
SET timeline_id = pg_catalog.current_setting('neon.timeline_id')::pg_catalog.text;
|
||||||
END
|
END
|
||||||
$$
|
$$
|
||||||
|
|||||||
@@ -15,15 +15,15 @@ BEGIN
|
|||||||
WHERE schema_name IN ('public')
|
WHERE schema_name IN ('public')
|
||||||
LOOP
|
LOOP
|
||||||
FOR grantor IN EXECUTE
|
FOR grantor IN EXECUTE
|
||||||
format(
|
pg_catalog.format(
|
||||||
'SELECT DISTINCT rtg.grantor FROM information_schema.role_table_grants AS rtg WHERE grantee = %s',
|
'SELECT DISTINCT rtg.grantor FROM information_schema.role_table_grants AS rtg WHERE grantee OPERATOR(pg_catalog.=) %s',
|
||||||
-- N.B. this has to be properly dollar-escaped with `pg_quote_dollar()`
|
-- N.B. this has to be properly dollar-escaped with `pg_quote_dollar()`
|
||||||
quote_literal({role_name})
|
quote_literal({role_name})
|
||||||
)
|
)
|
||||||
LOOP
|
LOOP
|
||||||
EXECUTE format('SET LOCAL ROLE %I', grantor);
|
EXECUTE pg_catalog.format('SET LOCAL ROLE %I', grantor);
|
||||||
|
|
||||||
revoke_query := format(
|
revoke_query := pg_catalog.format(
|
||||||
'REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA %I FROM %I GRANTED BY %I',
|
'REVOKE ALL PRIVILEGES ON ALL TABLES IN SCHEMA %I FROM %I GRANTED BY %I',
|
||||||
schema,
|
schema,
|
||||||
-- N.B. this has to be properly dollar-escaped with `pg_quote_dollar()`
|
-- N.B. this has to be properly dollar-escaped with `pg_quote_dollar()`
|
||||||
|
|||||||
@@ -5,17 +5,17 @@ DO ${outer_tag}$
|
|||||||
IF EXISTS(
|
IF EXISTS(
|
||||||
SELECT nspname
|
SELECT nspname
|
||||||
FROM pg_catalog.pg_namespace
|
FROM pg_catalog.pg_namespace
|
||||||
WHERE nspname = 'public'
|
WHERE nspname OPERATOR(pg_catalog.=) 'public'::pg_catalog.name
|
||||||
)
|
)
|
||||||
THEN
|
THEN
|
||||||
SELECT nspowner::regrole::text
|
SELECT nspowner::regrole::text
|
||||||
FROM pg_catalog.pg_namespace
|
FROM pg_catalog.pg_namespace
|
||||||
WHERE nspname = 'public'
|
WHERE nspname OPERATOR(pg_catalog.=) 'public'::pg_catalog.text
|
||||||
INTO schema_owner;
|
INTO schema_owner;
|
||||||
|
|
||||||
IF schema_owner = 'cloud_admin' OR schema_owner = 'zenith_admin'
|
IF schema_owner OPERATOR(pg_catalog.=) 'cloud_admin'::pg_catalog.text OR schema_owner OPERATOR(pg_catalog.=) 'zenith_admin'::pg_catalog.text
|
||||||
THEN
|
THEN
|
||||||
EXECUTE format('ALTER SCHEMA public OWNER TO %I', {db_owner});
|
EXECUTE pg_catalog.format('ALTER SCHEMA public OWNER TO %I', {db_owner});
|
||||||
END IF;
|
END IF;
|
||||||
END IF;
|
END IF;
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ DO ${outer_tag}$
|
|||||||
IF EXISTS(
|
IF EXISTS(
|
||||||
SELECT 1
|
SELECT 1
|
||||||
FROM pg_catalog.pg_database
|
FROM pg_catalog.pg_database
|
||||||
WHERE datname = {datname}
|
WHERE datname OPERATOR(pg_catalog.=) {datname}::pg_catalog.name
|
||||||
)
|
)
|
||||||
THEN
|
THEN
|
||||||
EXECUTE format('ALTER DATABASE %I is_template false', {datname});
|
EXECUTE pg_catalog.format('ALTER DATABASE %I is_template false', {datname});
|
||||||
END IF;
|
END IF;
|
||||||
END
|
END
|
||||||
${outer_tag}$;
|
${outer_tag}$;
|
||||||
|
|||||||
Reference in New Issue
Block a user