From 5aab83edcdf72214aed5bf61b736b3d41ac08bc2 Mon Sep 17 00:00:00 2001 From: Zhang Hao Date: Thu, 24 Aug 2023 13:59:03 +0800 Subject: [PATCH] Update to 2.3.0 (#362) Fix the following issues: diskquota cannot correctly print a warning when calling `create extension` in a non-empty database. The diskquota.state shows whether the current database is empty. Previously, we updated the status to diskquota.state during `create extension` and queried the status in UDF `diskquota.diskquota_start_worker`. When querying the database status, the relations whose `relkind in ('v', 'c', 'f')` are skipped, while all relations are filtered when updating the database status. This patch merges the two SQL statements to `INSERT RETURNING` to solve this problem. Benefit: we won't need to upgrade the minor version of diskquota when changing the statement. Remove useless test `test_update_db_cache`. The behavior of the bgworker scheduler is changed, so this test is no longer helpful. Update the upgrade test script `2.2_set_quota`. Since the above issue, there should be `select diskquota.init_table_size_table()` in `2.2_set_quota`. Add upgrade test for gp7. Fix upgrade test for gp6. --- VERSION | 2 +- concourse/scripts/test_diskquota.sh | 6 - control/ddl/diskquota--2.2--2.3.sql | 45 ++ control/ddl/diskquota--2.3--2.2.sql | 45 ++ control/ddl/diskquota--2.3.sql | 322 ++++++++ control/ddl/diskquota.control | 2 +- control/test/diskquota_test--1.0.sql | 2 +- src/diskquota_utility.c | 14 +- .../expected7/test_create_extension.out | 15 + .../expected7/test_drop_extension.out | 12 + .../expected7/test_ereport_from_seg.out | 62 ++ .../expected7/test_fast_quota_view.out | 182 +++++ .../expected7/test_per_segment_config.out | 34 +- .../expected7/test_postmaster_restart.out | 72 +- tests/isolation2/expected7/test_rejectmap.out | 738 ++++++++++++++++++ .../expected7/test_relation_cache.out | 70 ++ .../expected7/test_relation_size.out | 87 +++ tests/isolation2/expected7/test_truncate.out | 86 ++ tests/isolation2/expected7/test_vacuum.out | 99 +++ tests/regress/diskquota_schedule | 1 - .../regress/expected/test_update_db_cache.out | 64 -- tests/regress/sql/config.sql | 1 + tests/regress/sql/test_update_db_cache.sql | 43 - upgrade_test/CMakeLists.txt | 9 +- upgrade_test/expected/2.2_set_quota.out | 13 +- .../2.2_test_in_2.3_quota_create_in_2.2.out | 16 + upgrade_test/expected/2.3_catalog.out | 310 ++++++++ upgrade_test/expected/2.3_cleanup_quota.out | 1 + upgrade_test/expected/2.3_install.out | 13 + .../expected/2.3_migrate_to_version_2.3.out | 10 + upgrade_test/expected/2.3_set_quota.out | 68 ++ .../2.3_test_in_2.2_quota_create_in_2.3.out | 16 + upgrade_test/expected7/2.2_catalog.out | 308 ++++++++ upgrade_test/expected7/2.2_cleanup_quota.out | 1 + upgrade_test/expected7/2.2_install.out | 13 + .../expected7/2.2_migrate_to_version_2.2.out | 10 + upgrade_test/expected7/2.2_set_quota.out | 72 ++ .../2.2_test_in_2.3_quota_create_in_2.2.out | 16 + upgrade_test/expected7/2.3_catalog.out | 308 ++++++++ upgrade_test/expected7/2.3_cleanup_quota.out | 1 + upgrade_test/expected7/2.3_install.out | 13 + .../expected7/2.3_migrate_to_version_2.3.out | 10 + upgrade_test/expected7/2.3_set_quota.out | 66 ++ .../2.3_test_in_2.2_quota_create_in_2.3.out | 16 + upgrade_test/schedule_2.2--2.3 | 8 + upgrade_test/schedule_2.3--2.2 | 8 + upgrade_test/sql/2.2_set_quota.sql | 3 +- .../2.2_test_in_2.3_quota_create_in_2.2.sql | 16 + upgrade_test/sql/2.3_catalog.sql | 81 ++ upgrade_test/sql/2.3_cleanup_quota.sql | 1 + upgrade_test/sql/2.3_install.sql | 17 + .../sql/2.3_migrate_to_version_2.3.sql | 8 + upgrade_test/sql/2.3_set_quota.sql | 44 ++ .../2.3_test_in_2.2_quota_create_in_2.3.sql | 16 + 54 files changed, 3317 insertions(+), 179 deletions(-) create mode 100644 control/ddl/diskquota--2.2--2.3.sql create mode 100644 control/ddl/diskquota--2.3--2.2.sql create mode 100644 control/ddl/diskquota--2.3.sql create mode 100644 tests/isolation2/expected7/test_create_extension.out create mode 100644 tests/isolation2/expected7/test_drop_extension.out create mode 100644 tests/isolation2/expected7/test_ereport_from_seg.out create mode 100644 tests/isolation2/expected7/test_fast_quota_view.out create mode 100644 tests/isolation2/expected7/test_rejectmap.out create mode 100644 tests/isolation2/expected7/test_relation_cache.out create mode 100644 tests/isolation2/expected7/test_relation_size.out create mode 100644 tests/isolation2/expected7/test_truncate.out create mode 100644 tests/isolation2/expected7/test_vacuum.out delete mode 100644 tests/regress/expected/test_update_db_cache.out delete mode 100644 tests/regress/sql/test_update_db_cache.sql create mode 100644 upgrade_test/expected/2.2_test_in_2.3_quota_create_in_2.2.out create mode 100644 upgrade_test/expected/2.3_catalog.out create mode 100644 upgrade_test/expected/2.3_cleanup_quota.out create mode 100644 upgrade_test/expected/2.3_install.out create mode 100644 upgrade_test/expected/2.3_migrate_to_version_2.3.out create mode 100644 upgrade_test/expected/2.3_set_quota.out create mode 100644 upgrade_test/expected/2.3_test_in_2.2_quota_create_in_2.3.out create mode 100644 upgrade_test/expected7/2.2_catalog.out create mode 100644 upgrade_test/expected7/2.2_cleanup_quota.out create mode 100644 upgrade_test/expected7/2.2_install.out create mode 100644 upgrade_test/expected7/2.2_migrate_to_version_2.2.out create mode 100644 upgrade_test/expected7/2.2_set_quota.out create mode 100644 upgrade_test/expected7/2.2_test_in_2.3_quota_create_in_2.2.out create mode 100644 upgrade_test/expected7/2.3_catalog.out create mode 100644 upgrade_test/expected7/2.3_cleanup_quota.out create mode 100644 upgrade_test/expected7/2.3_install.out create mode 100644 upgrade_test/expected7/2.3_migrate_to_version_2.3.out create mode 100644 upgrade_test/expected7/2.3_set_quota.out create mode 100644 upgrade_test/expected7/2.3_test_in_2.2_quota_create_in_2.3.out create mode 100644 upgrade_test/schedule_2.2--2.3 create mode 100644 upgrade_test/schedule_2.3--2.2 create mode 100644 upgrade_test/sql/2.2_test_in_2.3_quota_create_in_2.2.sql create mode 100644 upgrade_test/sql/2.3_catalog.sql create mode 100644 upgrade_test/sql/2.3_cleanup_quota.sql create mode 100644 upgrade_test/sql/2.3_install.sql create mode 100644 upgrade_test/sql/2.3_migrate_to_version_2.3.sql create mode 100644 upgrade_test/sql/2.3_set_quota.sql create mode 100644 upgrade_test/sql/2.3_test_in_2.2_quota_create_in_2.3.sql diff --git a/VERSION b/VERSION index b1b25a5f..276cbf9e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.2.2 +2.3.0 diff --git a/concourse/scripts/test_diskquota.sh b/concourse/scripts/test_diskquota.sh index f24180cc..6abe35d0 100755 --- a/concourse/scripts/test_diskquota.sh +++ b/concourse/scripts/test_diskquota.sh @@ -23,12 +23,6 @@ function _main() { source /home/gpadmin/gpdb_src/gpAux/gpdemo/gpdemo-env.sh - # FIXME: remove this line after 2.2.2 released. - if [[ $PGPORT -eq 7000 ]] - then - exit - fi - pushd /home/gpadmin/gpdb_src make -C src/test/isolation2 install popd diff --git a/control/ddl/diskquota--2.2--2.3.sql b/control/ddl/diskquota--2.2--2.3.sql new file mode 100644 index 00000000..4669f79a --- /dev/null +++ b/control/ddl/diskquota--2.2--2.3.sql @@ -0,0 +1,45 @@ +-- TODO check if worker should not refresh, current lib should be diskquota-2.3.so + +-- UDF +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_schema_quota(text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_role_quota(text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.init_table_size_table() RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.diskquota_fetch_table_stat(int4, oid[]) RETURNS setof diskquota.diskquota_active_table_type AS '$libdir/diskquota-2.3.so', 'diskquota_fetch_table_stat' LANGUAGE C VOLATILE; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_schema_tablespace_quota(text, text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_role_tablespace_quota(text, text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_per_segment_quota(text, float4) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.refresh_rejectmap(diskquota.rejectmap_entry[], oid[]) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_rejectmap() RETURNS setof diskquota.rejectmap_entry_detail AS '$libdir/diskquota-2.3.so', 'show_rejectmap' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.pause() RETURNS void STRICT AS '$libdir/diskquota-2.3.so', 'diskquota_pause' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.resume() RETURNS void STRICT AS '$libdir/diskquota-2.3.so', 'diskquota_resume' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_worker_epoch() RETURNS bigint STRICT AS '$libdir/diskquota-2.3.so', 'show_worker_epoch' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.wait_for_worker_new_epoch() RETURNS boolean STRICT AS '$libdir/diskquota-2.3.so', 'wait_for_worker_new_epoch' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.status() RETURNS TABLE ("name" text, "status" text) STRICT AS '$libdir/diskquota-2.3.so', 'diskquota_status' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_relation_cache() RETURNS setof diskquota.relation_cache_detail AS '$libdir/diskquota-2.3.so', 'show_relation_cache' LANGUAGE C; + +DROP FUNCTION IF EXISTS diskquota.relation_size(relation regclass); +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.relation_size_local(reltablespace oid, relfilenode oid, relpersistence "char", relstorage "char", relam oid) RETURNS bigint STRICT AS '$libdir/diskquota-2.3.so', 'relation_size_local' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.pull_all_table_size(OUT tableid oid, OUT size bigint, OUT segid smallint) RETURNS SETOF RECORD AS '$libdir/diskquota-2.3.so', 'pull_all_table_size' LANGUAGE C; + +CREATE FUNCTION diskquota.relation_size(relation regclass) RETURNS bigint STRICT AS $$ + SELECT SUM(size)::bigint FROM ( + SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, + CASE WHEN EXISTS + (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END, + relam) AS size + FROM gp_dist_random('pg_class') as relstorage WHERE oid = relation + UNION ALL + SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, + CASE WHEN EXISTS + (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END, + relam) AS size + FROM pg_class as relstorage WHERE oid = relation + ) AS t $$ LANGUAGE SQL; + +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_relation_cache_all_seg() RETURNS setof diskquota.relation_cache_detail AS $$ + WITH relation_cache AS ( + SELECT diskquota.show_relation_cache() AS a + FROM gp_dist_random('gp_id') + ) + SELECT (a).* FROM relation_cache; $$ LANGUAGE SQL; +-- UDF end diff --git a/control/ddl/diskquota--2.3--2.2.sql b/control/ddl/diskquota--2.3--2.2.sql new file mode 100644 index 00000000..35dd1b29 --- /dev/null +++ b/control/ddl/diskquota--2.3--2.2.sql @@ -0,0 +1,45 @@ +-- TODO check if worker should not refresh, current lib should be diskquota-2.2.so + +-- UDF +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_schema_quota(text, text) RETURNS void STRICT AS '$libdir/diskquota-2.2.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_role_quota(text, text) RETURNS void STRICT AS '$libdir/diskquota-2.2.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.init_table_size_table() RETURNS void STRICT AS '$libdir/diskquota-2.2.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.diskquota_fetch_table_stat(int4, oid[]) RETURNS setof diskquota.diskquota_active_table_type AS '$libdir/diskquota-2.2.so', 'diskquota_fetch_table_stat' LANGUAGE C VOLATILE; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_schema_tablespace_quota(text, text, text) RETURNS void STRICT AS '$libdir/diskquota-2.2.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_role_tablespace_quota(text, text, text) RETURNS void STRICT AS '$libdir/diskquota-2.2.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.set_per_segment_quota(text, float4) RETURNS void STRICT AS '$libdir/diskquota-2.2.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.refresh_rejectmap(diskquota.rejectmap_entry[], oid[]) RETURNS void STRICT AS '$libdir/diskquota-2.2.so' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_rejectmap() RETURNS setof diskquota.rejectmap_entry_detail AS '$libdir/diskquota-2.2.so', 'show_rejectmap' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.pause() RETURNS void STRICT AS '$libdir/diskquota-2.2.so', 'diskquota_pause' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.resume() RETURNS void STRICT AS '$libdir/diskquota-2.2.so', 'diskquota_resume' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_worker_epoch() RETURNS bigint STRICT AS '$libdir/diskquota-2.2.so', 'show_worker_epoch' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.wait_for_worker_new_epoch() RETURNS boolean STRICT AS '$libdir/diskquota-2.2.so', 'wait_for_worker_new_epoch' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.status() RETURNS TABLE ("name" text, "status" text) STRICT AS '$libdir/diskquota-2.2.so', 'diskquota_status' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_relation_cache() RETURNS setof diskquota.relation_cache_detail AS '$libdir/diskquota-2.2.so', 'show_relation_cache' LANGUAGE C; + +DROP FUNCTION IF EXISTS diskquota.relation_size(relation regclass); +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.relation_size_local(reltablespace oid, relfilenode oid, relpersistence "char", relstorage "char", relam oid) RETURNS bigint STRICT AS '$libdir/diskquota-2.2.so', 'relation_size_local' LANGUAGE C; +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.pull_all_table_size(OUT tableid oid, OUT size bigint, OUT segid smallint) RETURNS SETOF RECORD AS '$libdir/diskquota-2.2.so', 'pull_all_table_size' LANGUAGE C; + +CREATE FUNCTION diskquota.relation_size(relation regclass) RETURNS bigint STRICT AS $$ + SELECT SUM(size)::bigint FROM ( + SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, + CASE WHEN EXISTS + (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END, + relam) AS size + FROM gp_dist_random('pg_class') as relstorage WHERE oid = relation + UNION ALL + SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, + CASE WHEN EXISTS + (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END, + relam) AS size + FROM pg_class as relstorage WHERE oid = relation + ) AS t $$ LANGUAGE SQL; + +/* ALTER */ CREATE OR REPLACE FUNCTION diskquota.show_relation_cache_all_seg() RETURNS setof diskquota.relation_cache_detail AS $$ + WITH relation_cache AS ( + SELECT diskquota.show_relation_cache() AS a + FROM gp_dist_random('gp_id') + ) + SELECT (a).* FROM relation_cache; $$ LANGUAGE SQL; +-- UDF end diff --git a/control/ddl/diskquota--2.3.sql b/control/ddl/diskquota--2.3.sql new file mode 100644 index 00000000..8be7749f --- /dev/null +++ b/control/ddl/diskquota--2.3.sql @@ -0,0 +1,322 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION diskquota" to load this file. \quit + +CREATE SCHEMA diskquota; + +-- when (quotatype == NAMESPACE_QUOTA/ROLE_QUOTA) then targetOid = role_oid/schema_oid; +-- when (quotatype == NAMESPACE_TABLESPACE_QUOTA/ROLE_TABLESPACE_QUOTA) then targetOid = diskquota.target.rowId; +CREATE TABLE diskquota.quota_config( + targetOid oid, + quotatype int, + quotalimitMB int8, + segratio float4 DEFAULT 0, + PRIMARY KEY(targetOid, quotatype) +) DISTRIBUTED BY (targetOid, quotatype); + +CREATE TABLE diskquota.target ( + rowId serial, + quotatype int, --REFERENCES disquota.quota_config.quotatype, + primaryOid oid, + tablespaceOid oid, --REFERENCES pg_tablespace.oid, + PRIMARY KEY (primaryOid, tablespaceOid, quotatype) +); + +CREATE TABLE diskquota.table_size( + tableid oid, + size bigint, + segid smallint, + PRIMARY KEY(tableid, segid) +) DISTRIBUTED BY (tableid, segid); + +CREATE TABLE diskquota.state( + state int, + PRIMARY KEY(state) +) DISTRIBUTED BY (state); + +-- diskquota.quota_config AND diskquota.target is dump-able, other table can be generate on fly +SELECT pg_catalog.pg_extension_config_dump('diskquota.quota_config', ''); +SELECT gp_segment_id, pg_catalog.pg_extension_config_dump('diskquota.quota_config', '') FROM gp_dist_random('gp_id'); +SELECT pg_catalog.pg_extension_config_dump('diskquota.target', ''); +SELECT gp_segment_id, pg_catalog.pg_extension_config_dump('diskquota.target', '') FROM gp_dist_random('gp_id'); + +CREATE TYPE diskquota.diskquota_active_table_type AS ( + "TABLE_OID" oid, + "TABLE_SIZE" int8, + "GP_SEGMENT_ID" smallint +); + +CREATE TYPE diskquota.rejectmap_entry AS ( + target_oid oid, + database_oid oid, + tablespace_oid oid, + target_type integer, + seg_exceeded boolean +); + +CREATE TYPE diskquota.rejectmap_entry_detail AS ( + target_type text, + target_oid oid, + database_oid oid, + tablespace_oid oid, + seg_exceeded boolean, + dbnode oid, + spcnode oid, + relnode oid, + segid int +); + +CREATE TYPE diskquota.relation_cache_detail AS ( + RELID oid, + PRIMARY_TABLE_OID oid, + AUXREL_NUM int, + OWNEROID oid, + NAMESPACEOID oid, + BACKENDID int, + SPCNODE oid, + DBNODE oid, + RELNODE oid, + RELSTORAGE "char", + AUXREL_OID oid[], + RELAM oid +); + +CREATE FUNCTION diskquota.set_schema_quota(text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +CREATE FUNCTION diskquota.set_role_quota(text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +CREATE FUNCTION diskquota.init_table_size_table() RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +CREATE FUNCTION diskquota.diskquota_fetch_table_stat(int4, oid[]) RETURNS setof diskquota.diskquota_active_table_type AS '$libdir/diskquota-2.3.so', 'diskquota_fetch_table_stat' LANGUAGE C VOLATILE; +CREATE FUNCTION diskquota.set_schema_tablespace_quota(text, text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +CREATE FUNCTION diskquota.set_role_tablespace_quota(text, text, text) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +CREATE FUNCTION diskquota.set_per_segment_quota(text, float4) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +CREATE FUNCTION diskquota.refresh_rejectmap(diskquota.rejectmap_entry[], oid[]) RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +CREATE FUNCTION diskquota.show_rejectmap() RETURNS setof diskquota.rejectmap_entry_detail AS '$libdir/diskquota-2.3.so', 'show_rejectmap' LANGUAGE C; +CREATE FUNCTION diskquota.pause() RETURNS void STRICT AS '$libdir/diskquota-2.3.so', 'diskquota_pause' LANGUAGE C; +CREATE FUNCTION diskquota.resume() RETURNS void STRICT AS '$libdir/diskquota-2.3.so', 'diskquota_resume' LANGUAGE C; +CREATE FUNCTION diskquota.show_worker_epoch() RETURNS bigint STRICT AS '$libdir/diskquota-2.3.so', 'show_worker_epoch' LANGUAGE C; +CREATE FUNCTION diskquota.wait_for_worker_new_epoch() RETURNS boolean STRICT AS '$libdir/diskquota-2.3.so', 'wait_for_worker_new_epoch' LANGUAGE C; +CREATE FUNCTION diskquota.status() RETURNS TABLE ("name" text, "status" text) STRICT AS '$libdir/diskquota-2.3.so', 'diskquota_status' LANGUAGE C; +CREATE FUNCTION diskquota.show_relation_cache() RETURNS setof diskquota.relation_cache_detail AS '$libdir/diskquota-2.3.so', 'show_relation_cache' LANGUAGE C; +CREATE FUNCTION diskquota.relation_size_local(reltablespace oid, relfilenode oid, relpersistence "char", relstorage "char", relam oid) RETURNS bigint STRICT AS '$libdir/diskquota-2.3.so', 'relation_size_local' LANGUAGE C; +CREATE FUNCTION diskquota.pull_all_table_size(OUT tableid oid, OUT size bigint, OUT segid smallint) RETURNS SETOF RECORD AS '$libdir/diskquota-2.3.so', 'pull_all_table_size' LANGUAGE C; + +CREATE FUNCTION diskquota.relation_size(relation regclass) RETURNS bigint STRICT AS $$ + SELECT SUM(size)::bigint FROM ( + SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, + CASE WHEN EXISTS + (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END, + relam) AS size + FROM gp_dist_random('pg_class') as relstorage WHERE oid = relation + UNION ALL + SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, + CASE WHEN EXISTS + (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END, + relam) AS size + FROM pg_class as relstorage WHERE oid = relation + ) AS t $$ LANGUAGE SQL; + +CREATE FUNCTION diskquota.show_relation_cache_all_seg() RETURNS setof diskquota.relation_cache_detail AS $$ + WITH relation_cache AS ( + SELECT diskquota.show_relation_cache() AS a + FROM gp_dist_random('gp_id') + ) + SELECT (a).* FROM relation_cache; $$ LANGUAGE SQL; + +-- view part +CREATE VIEW diskquota.show_all_relation_view AS +WITH + relation_cache AS ( + SELECT (f).* FROM diskquota.show_relation_cache() as f + ) +SELECT DISTINCT(oid), relowner, relnamespace, reltablespace from ( + SELECT relid as oid, owneroid as relowner, namespaceoid as relnamespace, spcnode as reltablespace FROM relation_cache + UNION + SELECT oid, relowner, relnamespace, reltablespace from pg_class +) as union_relation; + +CREATE VIEW diskquota.show_fast_schema_quota_view AS +WITH + quota_usage AS ( + SELECT + relnamespace, + SUM(size) AS total_size + FROM + diskquota.table_size, + diskquota.show_all_relation_view + WHERE + tableid = diskquota.show_all_relation_view.oid AND + segid = -1 + GROUP BY + relnamespace + ) +SELECT + nspname AS schema_name, + targetoid AS schema_oid, + quotalimitMB AS quota_in_mb, + COALESCE(total_size, 0) AS nspsize_in_bytes +FROM + diskquota.quota_config JOIN + pg_namespace ON targetoid = pg_namespace.oid LEFT OUTER JOIN + quota_usage ON pg_namespace.oid = relnamespace +WHERE + quotaType = 0; -- NAMESPACE_QUOTA + +CREATE VIEW diskquota.show_fast_role_quota_view AS +WITH + quota_usage AS ( + SELECT + relowner, + SUM(size) AS total_size + FROM + diskquota.table_size, + diskquota.show_all_relation_view + WHERE + tableid = diskquota.show_all_relation_view.oid AND + segid = -1 + GROUP BY + relowner + ) +SELECT + rolname AS role_name, + targetoid AS role_oid, + quotalimitMB AS quota_in_mb, + COALESCE(total_size, 0) AS rolsize_in_bytes +FROM + diskquota.quota_config JOIN + pg_roles ON targetoid = pg_roles.oid LEFT OUTER JOIN + quota_usage ON pg_roles.oid = relowner +WHERE + quotaType = 1; -- ROLE_QUOTA + +CREATE VIEW diskquota.show_fast_database_size_view AS +SELECT ( + (SELECT SUM(pg_relation_size(oid)) FROM pg_class WHERE oid <= 16384) + + + (SELECT SUM(size) FROM diskquota.table_size WHERE segid = -1) +) AS dbsize; + +CREATE VIEW diskquota.rejectmap AS SELECT * FROM diskquota.show_rejectmap() AS BM; + +CREATE VIEW diskquota.show_fast_schema_tablespace_quota_view AS +WITH + default_tablespace AS ( + SELECT dattablespace FROM pg_database + WHERE datname = current_database() + ), + quota_usage AS ( + SELECT + relnamespace, + CASE + WHEN reltablespace = 0 THEN dattablespace + ELSE reltablespace + END AS reltablespace, + SUM(size) AS total_size + FROM + diskquota.table_size, + diskquota.show_all_relation_view, + default_tablespace + WHERE + tableid = diskquota.show_all_relation_view.oid AND + segid = -1 + GROUP BY + relnamespace, + reltablespace, + dattablespace + ), + full_quota_config AS ( + SELECT + primaryOid, + tablespaceoid, + quotalimitMB + FROM + diskquota.quota_config AS config, + diskquota.target AS target + WHERE + config.targetOid = target.rowId AND + config.quotaType = target.quotaType AND + config.quotaType = 2 -- NAMESPACE_TABLESPACE_QUOTA + ) +SELECT + nspname AS schema_name, + primaryoid AS schema_oid, + spcname AS tablespace_name, + tablespaceoid AS tablespace_oid, + quotalimitMB AS quota_in_mb, + COALESCE(total_size, 0) AS nspsize_tablespace_in_bytes +FROM + full_quota_config JOIN + pg_namespace ON primaryOid = pg_namespace.oid JOIN + pg_tablespace ON tablespaceoid = pg_tablespace.oid LEFT OUTER JOIN + quota_usage ON pg_namespace.oid = relnamespace AND pg_tablespace.oid = reltablespace; + +CREATE VIEW diskquota.show_fast_role_tablespace_quota_view AS +WITH + default_tablespace AS ( + SELECT dattablespace FROM pg_database + WHERE datname = current_database() + ), + quota_usage AS ( + SELECT + relowner, + CASE + WHEN reltablespace = 0 THEN dattablespace + ELSE reltablespace + END AS reltablespace, + SUM(size) AS total_size + FROM + diskquota.table_size, + diskquota.show_all_relation_view, + default_tablespace + WHERE + tableid = diskquota.show_all_relation_view.oid AND + segid = -1 + GROUP BY + relowner, + reltablespace, + dattablespace + ), + full_quota_config AS ( + SELECT + primaryOid, + tablespaceoid, + quotalimitMB + FROM + diskquota.quota_config AS config, + diskquota.target AS target + WHERE + config.targetOid = target.rowId AND + config.quotaType = target.quotaType AND + config.quotaType = 3 -- ROLE_TABLESPACE_QUOTA + ) +SELECT + rolname AS role_name, + primaryoid AS role_oid, + spcname AS tablespace_name, + tablespaceoid AS tablespace_oid, + quotalimitMB AS quota_in_mb, + COALESCE(total_size, 0) AS rolsize_tablespace_in_bytes +FROM + full_quota_config JOIN + pg_roles ON primaryoid = pg_roles.oid JOIN + pg_tablespace ON tablespaceoid = pg_tablespace.oid LEFT OUTER JOIN + quota_usage ON pg_roles.oid = relowner AND pg_tablespace.oid = reltablespace; + +CREATE VIEW diskquota.show_segment_ratio_quota_view AS +SELECT + spcname as tablespace_name, + pg_tablespace.oid as tablespace_oid, + segratio as per_seg_quota_ratio +FROM + diskquota.quota_config JOIN + pg_tablespace ON targetOid = pg_tablespace.oid + AND quotatype = 4; + +-- view end + +-- re-dispatch pause status to false. in case user pause-drop-recreate. +-- refer to see test case 'test_drop_after_pause' +SELECT FROM diskquota.resume(); + + +--- Starting the worker has to be the last step. +CREATE FUNCTION diskquota.diskquota_start_worker() RETURNS void STRICT AS '$libdir/diskquota-2.3.so' LANGUAGE C; +SELECT diskquota.diskquota_start_worker(); +DROP FUNCTION diskquota.diskquota_start_worker(); diff --git a/control/ddl/diskquota.control b/control/ddl/diskquota.control index 32b4809f..4e5f6e5e 100644 --- a/control/ddl/diskquota.control +++ b/control/ddl/diskquota.control @@ -1,5 +1,5 @@ # diskquota extension comment = 'Disk Quota Main Program' -default_version = '2.2' +default_version = '2.3' module_pathname = 'do-not-use-this' relocatable = true diff --git a/control/test/diskquota_test--1.0.sql b/control/test/diskquota_test--1.0.sql index f5e39444..2a86e965 100644 --- a/control/test/diskquota_test--1.0.sql +++ b/control/test/diskquota_test--1.0.sql @@ -27,7 +27,7 @@ CREATE TYPE diskquota_test.db_status AS ( "epoch" int8, "paused" bool ); -CREATE FUNCTION diskquota_test.db_status() RETURNS setof diskquota_test.db_status AS '$libdir/diskquota-2.2.so', 'db_status' LANGUAGE C VOLATILE; +CREATE FUNCTION diskquota_test.db_status() RETURNS setof diskquota_test.db_status AS '$libdir/diskquota-2.3.so', 'db_status' LANGUAGE C VOLATILE; CREATE FUNCTION diskquota_test.cur_db_status() RETURNS diskquota_test.db_status AS $$ SELECT * from diskquota_test.db_status() where datname = current_database(); $$ LANGUAGE SQL; diff --git a/src/diskquota_utility.c b/src/diskquota_utility.c index f406809c..00dab97b 100644 --- a/src/diskquota_utility.c +++ b/src/diskquota_utility.c @@ -499,17 +499,19 @@ is_database_empty(void) SPI_connect(); ret = SPI_execute( - "SELECT (count(relname) = 0) " + "INSERT INTO diskquota.state SELECT (count(relname) = 0)::int " "FROM " " pg_class AS c, " " pg_namespace AS n " - "WHERE c.oid > 16384 and relnamespace = n.oid and nspname != 'diskquota'" - " and relkind not in ('v', 'c', 'f')", - true, 0); - if (ret != SPI_OK_SELECT) + "WHERE c.oid > 16384 and relnamespace = n.oid and nspname != 'diskquota' " + "and relkind not in ('v', 'c', 'f') " + "returning state", + false, 0); + if (ret != SPI_OK_INSERT_RETURNING) { int saved_errno = errno; - elog(ERROR, "cannot select pg_class and pg_namespace table, reason: %s.", strerror(saved_errno)); + elog(ERROR, "cannot select pg_class and pg_namespace table and update diskquota.state, reason: %s.", + strerror(saved_errno)); } tupdesc = SPI_tuptable->tupdesc; diff --git a/tests/isolation2/expected7/test_create_extension.out b/tests/isolation2/expected7/test_create_extension.out new file mode 100644 index 00000000..f34d591a --- /dev/null +++ b/tests/isolation2/expected7/test_create_extension.out @@ -0,0 +1,15 @@ +CREATE EXTENSION diskquota; +CREATE EXTENSION + +SELECT diskquota.init_table_size_table(); + init_table_size_table +----------------------- + +(1 row) + +-- Wait after init so that diskquota.state is clean +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) diff --git a/tests/isolation2/expected7/test_drop_extension.out b/tests/isolation2/expected7/test_drop_extension.out new file mode 100644 index 00000000..7e299700 --- /dev/null +++ b/tests/isolation2/expected7/test_drop_extension.out @@ -0,0 +1,12 @@ +SELECT diskquota.pause(); + pause +------- + +(1 row) +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +DROP EXTENSION diskquota; +DROP EXTENSION diff --git a/tests/isolation2/expected7/test_ereport_from_seg.out b/tests/isolation2/expected7/test_ereport_from_seg.out new file mode 100644 index 00000000..67ae6925 --- /dev/null +++ b/tests/isolation2/expected7/test_ereport_from_seg.out @@ -0,0 +1,62 @@ +CREATE SCHEMA efs1; +CREATE SCHEMA +SELECT diskquota.set_schema_quota('efs1', '1MB'); + set_schema_quota +------------------ + +(1 row) +CREATE TABLE efs1.t(i int); +CREATE TABLE + +INSERT INTO efs1.t SELECT generate_series(1, 10000); +INSERT 0 10000 +-- wait for refresh of diskquota and check the quota size +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +SELECT schema_name, quota_in_mb, nspsize_in_bytes FROM diskquota.show_fast_schema_quota_view WHERE schema_name = 'efs1'; + schema_name | quota_in_mb | nspsize_in_bytes +-------------+-------------+------------------ + efs1 | 1 | 688128 +(1 row) + +-- Enable check quota by relfilenode on seg0. +SELECT gp_inject_fault_infinite('ereport_warning_from_segment', 'skip', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +INSERT INTO efs1.t SELECT generate_series(1, 10000); +INSERT 0 10000 + +-- wait for refresh of diskquota and check whether the quota size changes +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +SELECT schema_name, quota_in_mb, nspsize_in_bytes FROM diskquota.show_fast_schema_quota_view WHERE schema_name = 'efs1'; + schema_name | quota_in_mb | nspsize_in_bytes +-------------+-------------+------------------ + efs1 | 1 | 1081344 +(1 row) + +DROP TABLE efs1.t; +DROP TABLE +DROP SCHEMA efs1; +DROP SCHEMA + +-- Reset fault injection points set by us at the top of this test. +SELECT gp_inject_fault_infinite('ereport_warning_from_segment', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) diff --git a/tests/isolation2/expected7/test_fast_quota_view.out b/tests/isolation2/expected7/test_fast_quota_view.out new file mode 100644 index 00000000..75ee06e7 --- /dev/null +++ b/tests/isolation2/expected7/test_fast_quota_view.out @@ -0,0 +1,182 @@ +CREATE SCHEMA s1; +CREATE SCHEMA +CREATE SCHEMA s2; +CREATE SCHEMA + +CREATE ROLE r LOGIN SUPERUSER; +CREATE ROLE + +!\retcode mkdir -p /tmp/spc1; +-- start_ignore + +-- end_ignore +(exited with code 0) +!\retcode mkdir -p /tmp/spc2; +-- start_ignore + +-- end_ignore +(exited with code 0) + +DROP TABLESPACE IF EXISTS spc1; +DROP TABLESPACE +CREATE TABLESPACE spc1 LOCATION '/tmp/spc1'; +CREATE TABLESPACE +DROP TABLESPACE IF EXISTS spc2; +DROP TABLESPACE +CREATE TABLESPACE spc2 LOCATION '/tmp/spc2'; +CREATE TABLESPACE + +SELECT diskquota.set_schema_quota('s1', '100 MB'); + set_schema_quota +------------------ + +(1 row) +SELECT diskquota.set_schema_tablespace_quota('s2', 'spc1','100 MB'); + set_schema_tablespace_quota +----------------------------- + +(1 row) +SELECT diskquota.set_role_quota('r', '100 MB'); + set_role_quota +---------------- + +(1 row) +SELECT diskquota.set_role_tablespace_quota('r', 'spc2', '100 MB'); + set_role_tablespace_quota +--------------------------- + +(1 row) + +-- test show_fast_schema_quota_view and show_fast_schema_tablespace_quota_view +1: BEGIN; +BEGIN +1: CREATE TABLE s1.t(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: INSERT INTO s1.t SELECT generate_series(1, 100000); +INSERT 0 100000 + +1: CREATE TABLE s2.t(i int) TABLESPACE spc1 DISTRIBUTED BY (i); +CREATE TABLE +1: INSERT INTO s2.t SELECT generate_series(1, 100000); +INSERT 0 100000 + +1: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) + +-- check schema quota view before transaction commits +2: SELECT schema_name, quota_in_mb, nspsize_in_bytes FROM diskquota.show_fast_schema_quota_view; + schema_name | quota_in_mb | nspsize_in_bytes +-------------+-------------+------------------ + s1 | 100 | 3932160 +(1 row) +2: SELECT schema_name, tablespace_name, quota_in_mb, nspsize_tablespace_in_bytes FROM diskquota.show_fast_schema_tablespace_quota_view; + schema_name | tablespace_name | quota_in_mb | nspsize_tablespace_in_bytes +-------------+-----------------+-------------+----------------------------- + s2 | spc1 | 100 | 3932160 +(1 row) + +1: COMMIT; +COMMIT +2: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +2: SELECT schema_name, quota_in_mb, nspsize_in_bytes FROM diskquota.show_fast_schema_quota_view; + schema_name | quota_in_mb | nspsize_in_bytes +-------------+-------------+------------------ + s1 | 100 | 3932160 +(1 row) +2: SELECT schema_name, tablespace_name, quota_in_mb, nspsize_tablespace_in_bytes FROM diskquota.show_fast_schema_tablespace_quota_view; + schema_name | tablespace_name | quota_in_mb | nspsize_tablespace_in_bytes +-------------+-----------------+-------------+----------------------------- + s2 | spc1 | 100 | 3932160 +(1 row) + +-- login r to test role quota view +1: SET ROLE r; +SET + +-- test show_fast_role_quota_view and show_fast_role_tablespace_quota_view +1: BEGIN; +BEGIN +1: CREATE TABLE t1(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: INSERT INTO t1 SELECT generate_series(1, 100000); +INSERT 0 100000 + +1: CREATE TABLE t2(i int) TABLESPACE spc2 DISTRIBUTED BY (i); +CREATE TABLE +1: INSERT INTO t2 SELECT generate_series(1, 100000); +INSERT 0 100000 + +1: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) + +-- check role quota view before transaction commits +2: SELECT role_name, quota_in_mb, rolsize_in_bytes FROM diskquota.show_fast_role_quota_view; + role_name | quota_in_mb | rolsize_in_bytes +-----------+-------------+------------------ + r | 100 | 7864320 +(1 row) +2: SELECT role_name, tablespace_name, quota_in_mb, rolsize_tablespace_in_bytes FROM diskquota.show_fast_role_tablespace_quota_view; + role_name | tablespace_name | quota_in_mb | rolsize_tablespace_in_bytes +-----------+-----------------+-------------+----------------------------- + r | spc2 | 100 | 3932160 +(1 row) + +1: COMMIT; +COMMIT +2: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +2: SELECT role_name, quota_in_mb, rolsize_in_bytes FROM diskquota.show_fast_role_quota_view; + role_name | quota_in_mb | rolsize_in_bytes +-----------+-------------+------------------ + r | 100 | 7864320 +(1 row) +2: SELECT role_name, tablespace_name, quota_in_mb, rolsize_tablespace_in_bytes FROM diskquota.show_fast_role_tablespace_quota_view; + role_name | tablespace_name | quota_in_mb | rolsize_tablespace_in_bytes +-----------+-----------------+-------------+----------------------------- + r | spc2 | 100 | 3932160 +(1 row) + +DROP TABLE IF EXISTS s1.t; +DROP TABLE +DROP TABLE IF EXISTS s2.t; +DROP TABLE +DROP TABLE IF EXISTS t1; +DROP TABLE +DROP TABLE IF EXISTS t2; +DROP TABLE + +DROP SCHEMA IF EXISTS s1; +DROP SCHEMA +DROP SCHEMA IF EXISTS s2; +DROP SCHEMA +DROP ROLE IF EXISTS r; +DROP ROLE + +DROP TABLESPACE IF EXISTS spc1; +DROP TABLESPACE +DROP TABLESPACE IF EXISTS spc2; +DROP TABLESPACE + +!\retcode rm -rf /tmp/spc1; +-- start_ignore + +-- end_ignore +(exited with code 0) +!\retcode rm -rf /tmp/spc2; +-- start_ignore + +-- end_ignore +(exited with code 0) diff --git a/tests/isolation2/expected7/test_per_segment_config.out b/tests/isolation2/expected7/test_per_segment_config.out index 79b4a8ff..1a6deb8b 100644 --- a/tests/isolation2/expected7/test_per_segment_config.out +++ b/tests/isolation2/expected7/test_per_segment_config.out @@ -10,11 +10,11 @@ (exited with code 0) -- end_ignore CREATE SCHEMA s101; -CREATE +CREATE SCHEMA DROP TABLESPACE IF EXISTS spc101; -DROP +DROP TABLESPACE CREATE TABLESPACE spc101 LOCATION '/tmp/spc101'; -CREATE +CREATE TABLESPACE -- -- There is no tablesapce per segment quota configed yet @@ -53,9 +53,9 @@ SELECT segratio from diskquota.quota_config, pg_tablespace where targetoid = oid (1 row) -- cleanup truncate table diskquota.quota_config; -TRUNCATE +TRUNCATE TABLE truncate table diskquota.target; -TRUNCATE +TRUNCATE TABLE -- Read commited, first set_schema_tablespace_quota, then set_per_segment_quota, 1: BEGIN; @@ -90,9 +90,9 @@ SELECT segratio from diskquota.quota_config, pg_tablespace where targetoid = oid (1 row) -- cleanup truncate table diskquota.quota_config; -TRUNCATE +TRUNCATE TABLE truncate table diskquota.target; -TRUNCATE +TRUNCATE TABLE -- -- There is already a tablesapce per segment quota configed @@ -136,9 +136,9 @@ SELECT segratio from diskquota.quota_config, pg_tablespace where targetoid = oid (1 row) -- cleanup truncate table diskquota.quota_config; -TRUNCATE +TRUNCATE TABLE truncate table diskquota.target; -TRUNCATE +TRUNCATE TABLE -- Read commited, first set_schema_tablespace_quota, then set_per_segment_quota, SELECT diskquota.set_per_segment_quota('spc101', 2); @@ -178,9 +178,9 @@ SELECT segratio from diskquota.quota_config, pg_tablespace where targetoid = oid (1 row) -- cleanup truncate table diskquota.quota_config; -TRUNCATE +TRUNCATE TABLE truncate table diskquota.target; -TRUNCATE +TRUNCATE TABLE -- Read commited, first delete per_segment_quota, then set_schema_tablespace_quota SELECT diskquota.set_per_segment_quota('spc101', 2); @@ -219,9 +219,9 @@ SELECT segratio from diskquota.quota_config, pg_tablespace where targetoid = oid (0 rows) -- cleanup truncate table diskquota.quota_config; -TRUNCATE +TRUNCATE TABLE truncate table diskquota.target; -TRUNCATE +TRUNCATE TABLE -- Read commited, first set_schema_tablespace_quota, then delete tablespace per segment ratio SELECT diskquota.set_per_segment_quota('spc101', 2); @@ -260,10 +260,10 @@ SELECT segratio from diskquota.quota_config, pg_tablespace where targetoid = oid (0 rows) -- cleanup truncate table diskquota.quota_config; -TRUNCATE +TRUNCATE TABLE truncate table diskquota.target; -TRUNCATE +TRUNCATE TABLE DROP SCHEMA s101; -DROP +DROP SCHEMA DROP TABLESPACE spc101; -DROP +DROP TABLESPACE diff --git a/tests/isolation2/expected7/test_postmaster_restart.out b/tests/isolation2/expected7/test_postmaster_restart.out index bf842f49..ccc9c53a 100644 --- a/tests/isolation2/expected7/test_postmaster_restart.out +++ b/tests/isolation2/expected7/test_postmaster_restart.out @@ -10,7 +10,7 @@ (exited with code 0) 1: CREATE SCHEMA postmaster_restart_s; -CREATE +CREATE SCHEMA 1: SET search_path TO postmaster_restart_s; SET @@ -27,29 +27,29 @@ SET -- expect fail 1: CREATE TABLE t1 AS SELECT generate_series(1,10000000); -ERROR: schema's disk space quota exceeded with name: 33502 (seg2 127.0.0.1:7004 pid=675047) +ERROR: schema's disk space quota exceeded with name: 17614 (seg0 127.0.0.1:7002 pid=854097) 1q: ... -- launcher should exist -- [p]ostgres is to filter out the pgrep itself !\retcode pgrep -f "[p]ostgres.*launcher"; -- start_ignore -673843 -673846 -673855 -673857 -673872 -673875 -673925 -673943 -673944 +839083 +839087 +839094 +839097 +839109 +839112 +839139 +839157 +839160 -- end_ignore (exited with code 0) -- bgworker should exist !\retcode pgrep -f "[p]ostgres.*diskquota.*isolation2test"; -- start_ignore -674189 +839377 -- end_ignore (exited with code 0) @@ -66,12 +66,12 @@ server stopped -- launcher should be terminated !\retcode pgrep -f "[p]ostgres.*launcher"; -- start_ignore -673843 -673846 -673855 -673857 -673872 -673875 +839083 +839087 +839094 +839097 +839109 +839112 -- end_ignore (exited with code 0) @@ -87,11 +87,11 @@ server stopped -- See https://github.com/greenplum-db/gpdb/pull/9396 !\retcode pg_ctl -D $MASTER_DATA_DIRECTORY -w -o "-c gp_role=dispatch" start; -- start_ignore -waiting for server to start....2023-03-06 16:13:41.483928 CST,,,p675192,th987391872,,,,0,,,seg-1,,,,,"LOG","00000","starting PostgreSQL 12.12 (Greenplum Database 7.0.0-beta.1+dev.215.gb9adc4ece5 build dev) on x86_64-pc-linux-gnu, compiled by clang version 15.0.7, 64-bit",,,,,,,,"PostmasterMain","postmaster.c",1237, -2023-03-06 16:13:41.484093 CST,,,p675192,th987391872,,,,0,,,seg-1,,,,,"LOG","00000","listening on IPv4 address ""0.0.0.0"", port 7000",,,,,,,,"StreamServerPort","pqcomm.c",631, -2023-03-06 16:13:41.484153 CST,,,p675192,th987391872,,,,0,,,seg-1,,,,,"LOG","00000","listening on IPv6 address ""::"", port 7000",,,,,,,,"StreamServerPort","pqcomm.c",631, -2023-03-06 16:13:41.484241 CST,,,p675192,th987391872,,,,0,,,seg-1,,,,,"LOG","00000","listening on Unix socket ""/tmp/.s.PGSQL.7000""",,,,,,,,"StreamServerPort","pqcomm.c",625, -2023-03-06 16:13:41.510380 CST,,,p675192,th987391872,,,,0,,,seg-1,,,,,"LOG","00000","redirecting log output to logging collector process",,"Future log output will appear in directory ""log"".",,,,,,"SysLogger_Start","syslogger.c",929, +waiting for server to start....2023-07-31 15:59:31.043830 CST,,,p854265,th579172224,,,,0,,,seg-1,,,,,"LOG","00000","starting PostgreSQL 12.12 (Greenplum Database 7.0.0-beta.4+dev.218.g9ec0a0a842 build dev) on x86_64-pc-linux-gnu, compiled by clang version 15.0.7, 64-bit",,,,,,,,"PostmasterMain","postmaster.c",1243, +2023-07-31 15:59:31.044012 CST,,,p854265,th579172224,,,,0,,,seg-1,,,,,"LOG","00000","listening on IPv4 address ""0.0.0.0"", port 7000",,,,,,,,"StreamServerPort","pqcomm.c",631, +2023-07-31 15:59:31.044060 CST,,,p854265,th579172224,,,,0,,,seg-1,,,,,"LOG","00000","listening on IPv6 address ""::"", port 7000",,,,,,,,"StreamServerPort","pqcomm.c",631, +2023-07-31 15:59:31.044140 CST,,,p854265,th579172224,,,,0,,,seg-1,,,,,"LOG","00000","listening on Unix socket ""/tmp/.s.PGSQL.7000""",,,,,,,,"StreamServerPort","pqcomm.c",625, +2023-07-31 15:59:31.076319 CST,,,p854265,th579172224,,,,0,,,seg-1,,,,,"LOG","00000","redirecting log output to logging collector process",,"Future log output will appear in directory ""log"".",,,,,,"SysLogger_Start","syslogger.c",929, done server started @@ -107,22 +107,22 @@ server started -- launcher should be restarted !\retcode pgrep -f "[p]ostgres.*launcher"; -- start_ignore -673843 -673846 -673855 -673857 -673872 -673875 -675198 -675213 -675217 +839083 +839087 +839094 +839097 +839109 +839112 +854271 +854289 +854293 -- end_ignore (exited with code 0) -- bgworker should be restarted !\retcode pgrep -f "[p]ostgres.*diskquota.*isolation2test"; -- start_ignore -675239 +854311 -- end_ignore (exited with code 0) @@ -136,7 +136,7 @@ SET (1 row) -- expect fail 1: CREATE TABLE t2 AS SELECT generate_series(1,10000000); -ERROR: schema's disk space quota exceeded with name: 33502 (seg2 127.0.0.1:7004 pid=679604) +ERROR: schema's disk space quota exceeded with name: 17614 (seg0 127.0.0.1:7002 pid=858309) -- enlarge the quota limits 1: SELECT diskquota.set_schema_quota('postmaster_restart_s', '100 MB'); set_schema_quota @@ -150,10 +150,10 @@ ERROR: schema's disk space quota exceeded with name: 33502 (seg2 127.0.0.1:700 (1 row) -- expect succeed 1: CREATE TABLE t3 AS SELECT generate_series(1,1000000); -CREATE 1000000 +SELECT 1000000 1: DROP SCHEMA postmaster_restart_s CASCADE; -DROP +DROP SCHEMA 1q: ... !\retcode gpconfig -c "diskquota.hard_limit" -v "off" > /dev/null; -- start_ignore diff --git a/tests/isolation2/expected7/test_rejectmap.out b/tests/isolation2/expected7/test_rejectmap.out new file mode 100644 index 00000000..385889fa --- /dev/null +++ b/tests/isolation2/expected7/test_rejectmap.out @@ -0,0 +1,738 @@ +-- +-- This file contains tests for dispatching rejectmap and canceling +-- queries in smgrextend hook by relation's relfilenode. +-- + +-- Enable check quota by relfilenode on seg0. +SELECT gp_inject_fault_infinite('enable_check_quota_by_relfilenode', 'skip', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- this function return valid tablespaceoid. +-- For role/namespace quota, return as it is. +-- For namespace_tablespace/role_tablespace quota, return non-zero tablespaceoid. +CREATE OR REPLACE FUNCTION get_real_tablespace_oid(block_type text, tablespaceoid oid) /*in func*/ RETURNS oid AS /*in func*/ $$ /*in func*/ BEGIN /*in func*/ /*in func*/ CASE /*in func*/ WHEN (block_type = 'NAMESPACE') OR (block_type = 'ROLE') THEN RETURN tablespaceoid; /*in func*/ ELSE RETURN ( /*in func*/ CASE tablespaceoid /*in func*/ WHEN 0 THEN (SELECT dattablespace FROM pg_database WHERE datname = CURRENT_DATABASE()) /*in func*/ ELSE /*in func*/ tablespaceoid /*in func*/ END /*in func*/ ); /*in func*/ END CASE; /*in func*/ END; /*in func*/ $$ LANGUAGE plpgsql; /*in func*/ +CREATE OR REPLACE FUNCTION block_relation_on_seg0(rel regclass, block_type text, segexceeded boolean) RETURNS void AS $$ /*in func*/ DECLARE /*in func*/ bt int; /*in func*/ targetoid oid; /*in func*/ BEGIN /*in func*/ CASE block_type /*in func*/ WHEN 'NAMESPACE' THEN /*in func*/ bt = 0; /*in func*/ SELECT relnamespace INTO targetoid /*in func*/ FROM pg_class WHERE relname=rel::text; /*in func*/ WHEN 'ROLE' THEN /*in func*/ bt = 1; /*in func*/ SELECT relowner INTO targetoid /*in func*/ FROM pg_class WHERE relname=rel::text; /*in func*/ WHEN 'NAMESPACE_TABLESPACE' THEN /*in func*/ bt = 2; /*in func*/ SELECT relnamespace INTO targetoid /*in func*/ FROM pg_class WHERE relname=rel::text; /*in func*/ WHEN 'ROLE_TABLESPACE' THEN /*in func*/ bt = 3; /*in func*/ SELECT relowner INTO targetoid /*in func*/ FROM pg_class WHERE relname=rel::text; /*in func*/ END CASE; /*in func*/ PERFORM diskquota.refresh_rejectmap( /*in func*/ ARRAY[ /*in func*/ ROW (targetoid, /*in func*/ (SELECT oid FROM pg_database WHERE datname = CURRENT_DATABASE()), /*in func*/ (SELECT get_real_tablespace_oid( /*in func*/ block_type, /*in func*/ (SELECT pg_class.reltablespace FROM pg_class WHERE relname = rel::TEXT) /*in func*/ )), /*in func*/ bt, /*in func*/ segexceeded) /*in func*/ ]::diskquota.rejectmap_entry[], /*in func*/ ARRAY[rel]::oid[]) /*in func*/ FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; /*in func*/ END; $$ /*in func*/ LANGUAGE 'plpgsql'; +CREATE FUNCTION + +-- 1. Test canceling the extending of an ordinary table. +CREATE TABLE blocked_t1(i int) DISTRIBUTED BY (i); +CREATE TABLE +INSERT INTO blocked_t1 SELECT generate_series(1, 100); +INSERT 0 100 +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Insert a small amount of data into blocked_t1. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t1 SELECT generate_series(1, 10000); + +SELECT gp_wait_until_triggered_fault('check_rejectmap_by_relfilenode', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +-- Dispatch rejectmap to seg0. +SELECT block_relation_on_seg0('blocked_t1'::regclass, 'NAMESPACE'::text, false); + block_relation_on_seg0 +------------------------ + +(1 row) + +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Session 1 will return and emit an error message saying that the quota limit is exceeded on seg0. +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) + +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 2. Test canceling the extending of a toast relation. +CREATE TABLE blocked_t2(i text) DISTRIBUTED BY (i); +CREATE TABLE +INSERT INTO blocked_t2 SELECT generate_series(1, 100); +INSERT 0 100 +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Insert a small amount of data into blocked_t2. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t2 SELECT generate_series(1, 10000); + +SELECT gp_wait_until_triggered_fault('check_rejectmap_by_relfilenode', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +-- Dispatch rejectmap to seg0. +SELECT block_relation_on_seg0('blocked_t2'::regclass, 'NAMESPACE'::text, false); + block_relation_on_seg0 +------------------------ + +(1 row) + +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Session 1 will return and emit an error message saying that the quota limit is exceeded on seg0. +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) + +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 3. Test canceling the extending of an appendonly relation. +CREATE TABLE blocked_t3(i int) WITH (appendonly=true) DISTRIBUTED BY (i); +CREATE TABLE +INSERT INTO blocked_t3 SELECT generate_series(1, 100); +INSERT 0 100 +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Insert a small amount of data into blocked_t3. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t3 SELECT generate_series(1, 10000); + +SELECT gp_wait_until_triggered_fault('check_rejectmap_by_relfilenode', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +-- Dispatch rejectmap to seg0. +SELECT block_relation_on_seg0('blocked_t3'::regclass, 'NAMESPACE'::text, false); + block_relation_on_seg0 +------------------------ + +(1 row) + +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Session 1 will return and emit an error message saying that the quota limit is exceeded on seg0. +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) + +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 4. Test canceling the extending of an index relation. +CREATE TABLE blocked_t4(i int) DISTRIBUTED BY (i); +CREATE TABLE +CREATE INDEX blocked_t4_index ON blocked_t4(i); +CREATE INDEX +INSERT INTO blocked_t4 SELECT generate_series(1, 100); +INSERT 0 100 +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Insert a small amount of data into blocked_t4. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t4 SELECT generate_series(1, 10000); + +SELECT gp_wait_until_triggered_fault('check_rejectmap_by_relfilenode', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +-- Dispatch rejectmap to seg0. +SELECT block_relation_on_seg0('blocked_t4_index'::regclass, 'NAMESPACE'::text, false); + block_relation_on_seg0 +------------------------ + +(1 row) + +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +-- Session 1 will return and emit an error message saying that the quota limit is exceeded on seg0. +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) + +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 5. Test error message for NAMESPACE_TABLESPACE_QUOTA when the quota limit is exceeded on segments. +CREATE TABLE blocked_t5(i int) DISTRIBUTED BY (i); +CREATE TABLE +INSERT INTO blocked_t5 SELECT generate_series(1, 100); +INSERT 0 100 +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1&: INSERT INTO blocked_t5 SELECT generate_series(1, 10000); + +SELECT gp_wait_until_triggered_fault('check_rejectmap_by_relfilenode', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +SELECT block_relation_on_seg0('blocked_t5'::regclass, 'NAMESPACE_TABLESPACE'::text, true); + block_relation_on_seg0 +------------------------ + +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: tablespace: 1663, schema: 2200 diskquota exceeded per segment quota (seg0 127.0.0.1:7002 pid=841032) +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 6. Test error message for ROLE_TABLESPACE_QUOTA when the quota limit is exceeded on segments. +CREATE TABLE blocked_t6(i int) DISTRIBUTED BY (i); +CREATE TABLE +INSERT INTO blocked_t6 SELECT generate_series(1, 100); +INSERT 0 100 +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +1&: INSERT INTO blocked_t6 SELECT generate_series(1, 10000); + +SELECT gp_wait_until_triggered_fault('check_rejectmap_by_relfilenode', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +SELECT block_relation_on_seg0('blocked_t6'::regclass, 'ROLE_TABLESPACE'::text, true); + block_relation_on_seg0 +------------------------ + +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: tablespace: 1663, role: 10 diskquota exceeded per segment quota (seg0 127.0.0.1:7002 pid=841032) +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- Do some clean-ups. +DROP TABLE blocked_t1; +DROP TABLE +DROP TABLE blocked_t2; +DROP TABLE +DROP TABLE blocked_t3; +DROP TABLE +DROP TABLE blocked_t4; +DROP TABLE +DROP TABLE blocked_t5; +DROP TABLE +DROP TABLE blocked_t6; +DROP TABLE + +-- +-- Below are helper functions for testing adding uncommitted relations to rejectmap. +-- +-- start_ignore +CREATE OR REPLACE LANGUAGE plpython3u; +CREATE LANGUAGE +-- end_ignore +CREATE TYPE cached_relation_entry AS ( reloid oid, relname text, relowner oid, relnamespace oid, reltablespace oid, relfilenode oid, segid int); +CREATE TYPE + +-- This function dumps given relation_cache entries to the given file. +CREATE OR REPLACE FUNCTION dump_relation_cache_to_file(filename text) RETURNS void AS $$ rv = plpy.execute(""" SELECT (oid, relname, relowner, relnamespace, reltablespace, relfilenode, gp_segment_id)::cached_relation_entry FROM gp_dist_random('pg_class') """) with open(filename, 'wt') as f: for v in rv: row = v['row'] # The composite type results are different between GP6 & GP7 if isinstance(row, dict): r = "{0},{1},{2},{3},{4},{5},{6}".format( row['reloid'], row['relname'], row['relowner'], row['relnamespace'], row['reltablespace'], row['relfilenode'], row['segid']) else: r = row[1:-1] f.write(r + '\n') $$ LANGUAGE plpython3u; +CREATE FUNCTION + +-- This function reads relation_cache entries from the given file. +CREATE OR REPLACE FUNCTION read_relation_cache_from_file(filename text) RETURNS SETOF cached_relation_entry AS $$ with open(filename) as f: for l in f: r = l.split(',') yield (r[0], r[1], r[2], r[3], r[4], r[5], r[6]) $$ LANGUAGE plpython3u; +CREATE FUNCTION + +-- This function replaces the oid appears in the auxiliary relation's name +-- with the corresponding relname of that oid. +CREATE OR REPLACE FUNCTION replace_oid_with_relname(given_name text, filename text) RETURNS text AS $$ /*in func*/ BEGIN /*in func*/ RETURN COALESCE( /*in func*/ REGEXP_REPLACE(given_name, /*in func*/ '^(pg_toast_|pg_aoseg_|pg_aovisimap_|pg_aoblkdir_|pg_aocsseg_)\d+', /*in func*/ '\1' || /*in func*/ (SELECT DISTINCT relname FROM read_relation_cache_from_file(filename) /*in func*/ WHERE REGEXP_REPLACE(given_name, '\D', '', 'g') <> '' /*in func*/ AND reloid=REGEXP_REPLACE(given_name, '\D', '', 'g')::oid), 'g'), given_name); /*in func*/ END; /*in func*/ $$ LANGUAGE plpgsql; +CREATE FUNCTION + +-- This function helps dispatch rejectmap for the given relation to seg0. +CREATE OR REPLACE FUNCTION block_uncommitted_relation_on_seg0(rel text, block_type text, segexceeded boolean, filename text) RETURNS void AS $$ /*in func*/ DECLARE /*in func*/ bt int; /*in func*/ targetoid oid; /*in func*/ BEGIN /*in func*/ CASE block_type /*in func*/ WHEN 'NAMESPACE' THEN /*in func*/ bt = 0; /*in func*/ SELECT relnamespace INTO targetoid /*in func*/ FROM read_relation_cache_from_file(filename) /*in func*/ WHERE relname=rel::text AND segid=0; /*in func*/ WHEN 'ROLE' THEN /*in func*/ bt = 1; /*in func*/ SELECT relowner INTO targetoid /*in func*/ FROM read_relation_cache_from_file(filename) /*in func*/ WHERE relname=rel::text AND segid=0; /*in func*/ WHEN 'NAMESPACE_TABLESPACE' THEN /*in func*/ bt = 2; /*in func*/ SELECT relnamespace INTO targetoid /*in func*/ FROM read_relation_cache_from_file(filename) /*in func*/ WHERE relname=rel::text AND segid=0; /*in func*/ WHEN 'ROLE_TABLESPACE' THEN /*in func*/ bt = 3; /*in func*/ SELECT relowner INTO targetoid /*in func*/ FROM read_relation_cache_from_file(filename) /*in func*/ WHERE relname=rel::text AND segid=0; /*in func*/ END CASE; /*in func*/ PERFORM diskquota.refresh_rejectmap( /*in func*/ ARRAY[ /*in func*/ ROW (targetoid, /*in func*/ (SELECT oid FROM pg_database WHERE datname = CURRENT_DATABASE()), /*in func*/ (SELECT get_real_tablespace_oid( /*in func*/ block_type, /*in func*/ (SELECT reltablespace /*in func*/ FROM read_relation_cache_from_file(filename) /*in func*/ WHERE relname = rel::text /*in func*/ AND segid = 0) /*in func*/ )), /*in func*/ bt, /*in func*/ segexceeded) /*in func*/ ]::diskquota.rejectmap_entry[], /*in func*/ ARRAY[(SELECT reloid FROM read_relation_cache_from_file(filename) /*in func*/ WHERE relname=rel::text AND segid=0)::regclass]::oid[]) /*in func*/ FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; /*in func*/ END; $$ /*in func*/ LANGUAGE 'plpgsql'; +CREATE FUNCTION + +-- 7. Test that we are able to block an ordinary relation on seg0 by its relnamespace. +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'NAMESPACE'::text, false, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text), be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0; + segid | relnamespace | reltablespace | relowner | replace_oid_with_relname | target_type | target_oid +-------+--------------+---------------+----------+--------------------------+-----------------+------------ + 0 | 2200 | 0 | 10 | blocked_t7 | NAMESPACE_QUOTA | 2200 +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 8. Test that we are able to block an ordinary relation on seg0 by its relowner. +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'ROLE'::text, false, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text), be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0; + segid | relnamespace | reltablespace | relowner | replace_oid_with_relname | target_type | target_oid +-------+--------------+---------------+----------+--------------------------+-------------+------------ + 0 | 2200 | 0 | 10 | blocked_t7 | ROLE_QUOTA | 10 +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: role's disk space quota exceeded with name: 10 (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 9. Test that we are able to block an ordinary relation on seg0 by its relnamespace and reltablespace. +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'NAMESPACE_TABLESPACE'::text, false, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text), be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0; + segid | relnamespace | reltablespace | relowner | replace_oid_with_relname | target_type | target_oid +-------+--------------+---------------+----------+--------------------------+----------------------------+------------ + 0 | 2200 | 0 | 10 | blocked_t7 | NAMESPACE_TABLESPACE_QUOTA | 2200 +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: tablespace: 1663, schema: 2200 diskquota exceeded (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 10. Test that we are able to block an ordinary relation on seg0 by its relowner and reltablespace. +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'ROLE_TABLESPACE'::text, false, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text), be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0; + segid | relnamespace | reltablespace | relowner | replace_oid_with_relname | target_type | target_oid +-------+--------------+---------------+----------+--------------------------+-----------------------+------------ + 0 | 2200 | 0 | 10 | blocked_t7 | ROLE_TABLESPACE_QUOTA | 10 +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: tablespace: 1663, role: 10 diskquota exceeded (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 11. Test that we are able to block an ordinary relation on seg0 by its relnamespace and reltablespace (segexceeded=true). +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'NAMESPACE_TABLESPACE'::text, true, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text), be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0; + segid | relnamespace | reltablespace | relowner | replace_oid_with_relname | target_type | target_oid +-------+--------------+---------------+----------+--------------------------+----------------------------+------------ + 0 | 2200 | 0 | 10 | blocked_t7 | NAMESPACE_TABLESPACE_QUOTA | 2200 +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: tablespace: 1663, schema: 2200 diskquota exceeded per segment quota (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 12. Test that we are able to block an ordinary relation on seg0 by its relowner and reltablespace (segexceeded=true). +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'ROLE_TABLESPACE'::text, true, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text), be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0; + segid | relnamespace | reltablespace | relowner | replace_oid_with_relname | target_type | target_oid +-------+--------------+---------------+----------+--------------------------+-----------------------+------------ + 0 | 2200 | 0 | 10 | blocked_t7 | ROLE_TABLESPACE_QUOTA | 10 +(1 row) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: tablespace: 1663, role: 10 diskquota exceeded per segment quota (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 13. Test that we are able to block a toast relation on seg0 by its namespace. +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i text) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'NAMESPACE'::text, true, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text) AS relname, be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0 ORDER BY relname DESC; + segid | relnamespace | reltablespace | relowner | relname | target_type | target_oid +-------+--------------+---------------+----------+---------------------------+-----------------+------------ + 0 | 99 | 0 | 10 | pg_toast_blocked_t7_index | NAMESPACE_QUOTA | 2200 + 0 | 99 | 0 | 10 | pg_toast_blocked_t7 | NAMESPACE_QUOTA | 2200 + 0 | 2200 | 0 | 10 | blocked_t7 | NAMESPACE_QUOTA | 2200 +(3 rows) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 14. Test that we are able to block an appendonly relation on seg0 by its namespace. +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) WITH (appendonly=true) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'NAMESPACE'::text, true, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text) AS relname, be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0 ORDER BY relname DESC; + segid | relnamespace | reltablespace | relowner | relname | target_type | target_oid +-------+--------------+---------------+----------+-------------------------------+-----------------+------------ + 0 | 6104 | 0 | 10 | pg_aovisimap_blocked_t7_index | NAMESPACE_QUOTA | 2200 + 0 | 6104 | 0 | 10 | pg_aovisimap_blocked_t7 | NAMESPACE_QUOTA | 2200 + 0 | 6104 | 0 | 10 | pg_aoseg_blocked_t7 | NAMESPACE_QUOTA | 2200 + 0 | 2200 | 0 | 10 | blocked_t7 | NAMESPACE_QUOTA | 2200 +(4 rows) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- 15. Test that we are able to block an appendonly (column oriented) relation on seg0 by its namespace. +1: BEGIN; +BEGIN +1: CREATE TABLE blocked_t7(i int) WITH (appendonly=true, orientation=column) DISTRIBUTED BY (i); +CREATE TABLE +1: SELECT dump_relation_cache_to_file('/tmp/test_rejectmap.csv'); + dump_relation_cache_to_file +----------------------------- + +(1 row) +-- Inject 'suspension' to check_rejectmap_by_relfilenode on seg0. +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +-- Insert a small amount of data into blocked_t7. It will hang up at check_rejectmap_by_relfilenode(). +1&: INSERT INTO blocked_t7 SELECT generate_series(1, 10000); +SELECT block_uncommitted_relation_on_seg0('blocked_t7'::text, 'NAMESPACE'::text, true, '/tmp/test_rejectmap.csv'::text); + block_uncommitted_relation_on_seg0 +------------------------------------ + +(1 row) +-- Show that blocked_t7 is blocked on seg0. +2: SELECT rel.segid, rel.relnamespace, rel.reltablespace, rel.relowner, replace_oid_with_relname(rel.relname, '/tmp/test_rejectmap.csv'::text) AS relname, be.target_type, be.target_oid FROM gp_dist_random('diskquota.rejectmap') AS be, read_relation_cache_from_file('/tmp/test_rejectmap.csv') AS rel WHERE be.segid=rel.segid AND be.relnode=rel.relfilenode AND rel.relfilenode<>0 ORDER BY relname DESC; + segid | relnamespace | reltablespace | relowner | relname | target_type | target_oid +-------+--------------+---------------+----------+-------------------------------+-----------------+------------ + 0 | 6104 | 0 | 10 | pg_aovisimap_blocked_t7_index | NAMESPACE_QUOTA | 2200 + 0 | 6104 | 0 | 10 | pg_aovisimap_blocked_t7 | NAMESPACE_QUOTA | 2200 + 0 | 6104 | 0 | 10 | pg_aocsseg_blocked_t7 | NAMESPACE_QUOTA | 2200 + 0 | 2200 | 0 | 10 | blocked_t7 | NAMESPACE_QUOTA | 2200 +(4 rows) +SELECT gp_inject_fault_infinite('check_rejectmap_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) +1<: <... completed> +ERROR: schema's disk space quota exceeded with name: 2200 (seg0 127.0.0.1:7002 pid=841032) +1: ABORT; +ROLLBACK +-- Clean up the rejectmap on seg0. +SELECT diskquota.refresh_rejectmap( ARRAY[]::diskquota.rejectmap_entry[], ARRAY[]::oid[]) FROM gp_dist_random('gp_id') WHERE gp_segment_id=0; + refresh_rejectmap +------------------- + +(1 row) + +-- Reset fault injection points set by us at the top of this test. +SELECT gp_inject_fault_infinite('enable_check_quota_by_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) diff --git a/tests/isolation2/expected7/test_relation_cache.out b/tests/isolation2/expected7/test_relation_cache.out new file mode 100644 index 00000000..14ad3966 --- /dev/null +++ b/tests/isolation2/expected7/test_relation_cache.out @@ -0,0 +1,70 @@ +CREATE DATABASE tempdb1; +CREATE DATABASE +CREATE DATABASE tempdb2; +CREATE DATABASE + +-- perpare extension +1:@db_name tempdb1: CREATE EXTENSION diskquota; +CREATE EXTENSION +1:@db_name tempdb1: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +2:@db_name tempdb2: CREATE EXTENSION diskquota; +CREATE EXTENSION +2:@db_name tempdb2: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) + +-- create a table in tempdb1 +1:@db_name tempdb1: BEGIN; +BEGIN +1:@db_name tempdb1: CREATE TABLE t(i int); +CREATE TABLE +1:@db_name tempdb1: INSERT INTO t select generate_series(1, 10000); +INSERT 0 10000 + +-- query relation_cache in tempdb2 +2:@db_name tempdb2: SELECT count(*) from diskquota.show_relation_cache(); + count +------- + 0 +(1 row) + +1:@db_name tempdb1: ABORT; +ROLLBACK + +1:@db_name tempdb1: SELECT diskquota.pause(); + pause +------- + +(1 row) +1:@db_name tempdb1: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +1:@db_name tempdb1: DROP EXTENSION diskquota; +DROP EXTENSION +2:@db_name tempdb2: SELECT diskquota.pause(); + pause +------- + +(1 row) +2:@db_name tempdb2: SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +2:@db_name tempdb2: DROP EXTENSION diskquota; +DROP EXTENSION +1q: ... +2q: ... + +DROP DATABASE tempdb1; +DROP DATABASE +DROP DATABASE tempdb2; +DROP DATABASE diff --git a/tests/isolation2/expected7/test_relation_size.out b/tests/isolation2/expected7/test_relation_size.out new file mode 100644 index 00000000..3ddafe8f --- /dev/null +++ b/tests/isolation2/expected7/test_relation_size.out @@ -0,0 +1,87 @@ +-- +-- 1. Test that when a relation is dropped before diskquota.relation_size() +-- applying stat(2) on the physical file, diskquota.relation_size() consumes +-- the error and returns 0. +-- + +CREATE TABLE t_dropped(i int) DISTRIBUTED BY (i); +CREATE TABLE +-- Insert a small amount of data to 't_dropped'. +INSERT INTO t_dropped SELECT generate_series(1, 100); +INSERT 0 100 +-- Shows that the size of relfilenode is not zero. +SELECT diskquota.relation_size('t_dropped'); + relation_size +--------------- + 98304 +(1 row) + +-- Inject 'suspension' to servers. +SELECT gp_inject_fault_infinite('diskquota_before_stat_relfilenode', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content>=0; + gp_inject_fault_infinite +-------------------------- + Success: + Success: + Success: +(3 rows) + +-- Session 1 will hang before applying stat(2) to the physical file. +1&: SELECT diskquota.relation_size('t_dropped'); +-- Wait until the fault is triggered to avoid the following race condition: +-- The 't_dropped' table is dropped before evaluating "SELECT diskquota.relation_size('t_dropped')" +-- and the query will fail with 'ERROR: relation "t_dropped" does not exist' +SELECT gp_wait_until_triggered_fault('diskquota_before_stat_relfilenode', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content>=0; + gp_wait_until_triggered_fault +------------------------------- + Success: + Success: + Success: +(3 rows) +-- Drop the table. +DROP TABLE t_dropped; +DROP TABLE +-- Remove the injected 'suspension'. +SELECT gp_inject_fault_infinite('diskquota_before_stat_relfilenode', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content>=0; + gp_inject_fault_infinite +-------------------------- + Success: + Success: + Success: +(3 rows) +-- Session 1 will continue and returns 0. +1<: <... completed> + relation_size +--------------- + 0 +(1 row) + +-- 2. Test whether relation size is correct under concurrent writes for AO tables. +-- Since no row is deleted, diskquota.relation_size() should be equal to +-- pg_relation_size(). + +CREATE TABLE t_ao(i int) WITH (appendonly=true) DISTRIBUTED BY (i); +CREATE TABLE +1: BEGIN; +BEGIN +1: INSERT INTO t_ao SELECT generate_series(1, 10000); +INSERT 0 10000 +2: BEGIN; +BEGIN +2: INSERT INTO t_ao SELECT generate_series(1, 10000); +INSERT 0 10000 +1: COMMIT; +COMMIT +2: COMMIT; +COMMIT +SELECT diskquota.relation_size('t_ao'); + relation_size +--------------- + 200400 +(1 row) +SELECT pg_relation_size('t_ao'); + pg_relation_size +------------------ + 200400 +(1 row) +DROP TABLE t_ao; +DROP TABLE diff --git a/tests/isolation2/expected7/test_truncate.out b/tests/isolation2/expected7/test_truncate.out new file mode 100644 index 00000000..64b0fef8 --- /dev/null +++ b/tests/isolation2/expected7/test_truncate.out @@ -0,0 +1,86 @@ +-- Test various race conditions for TRUNCATE. + +-- Case 1: Pulling active table before swapping relfilenode +CREATE TABLE dummy_t1(i int) DISTRIBUTED BY (i); +CREATE TABLE +INSERT INTO dummy_t1 SELECT generate_series(1, 1000); +INSERT 0 1000 +-- Wait for the diskquota bgworker refreshing the size of 'dummy_t1'. +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +-- Shows that the result of pg_table_size() and diskquota.table_size are identical. +SELECT pg_table_size('dummy_t1'); + pg_table_size +--------------- + 98304 +(1 row) +SELECT tableid::regclass, size, segid FROM diskquota.table_size WHERE tableid='dummy_t1'::regclass ORDER BY segid; + tableid | size | segid +----------+-------+------- + dummy_t1 | 98304 | -1 + dummy_t1 | 32768 | 0 + dummy_t1 | 32768 | 1 + dummy_t1 | 32768 | 2 +(4 rows) + +SELECT gp_inject_fault_infinite('diskquota_after_smgrcreate', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content<>-1; + gp_inject_fault_infinite +-------------------------- + Success: + Success: + Success: +(3 rows) +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +1&: TRUNCATE dummy_t1; +SELECT gp_wait_until_triggered_fault('diskquota_after_smgrcreate', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content<>-1; + gp_wait_until_triggered_fault +------------------------------- + Success: + Success: + Success: +(3 rows) +-- Wait for the diskquota bgworker 'consumes' the newly created relfilenode from shmem. +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +SELECT gp_inject_fault_infinite('diskquota_after_smgrcreate', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content<>-1; + gp_inject_fault_infinite +-------------------------- + Success: + Success: + Success: +(3 rows) +1<: <... completed> +TRUNCATE TABLE + +-- Wait for the diskquota bgworker refreshing the size of 'dummy_t1'. +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +-- Shows that the result of pg_table_size() and diskquota.table_size are identical. +SELECT pg_table_size('dummy_t1'); + pg_table_size +--------------- + 0 +(1 row) +SELECT tableid::regclass, size, segid FROM diskquota.table_size WHERE tableid='dummy_t1'::regclass ORDER BY segid; + tableid | size | segid +----------+------+------- + dummy_t1 | 0 | -1 + dummy_t1 | 0 | 0 + dummy_t1 | 0 | 1 + dummy_t1 | 0 | 2 +(4 rows) +DROP TABLE dummy_t1; +DROP TABLE diff --git a/tests/isolation2/expected7/test_vacuum.out b/tests/isolation2/expected7/test_vacuum.out new file mode 100644 index 00000000..f40397f3 --- /dev/null +++ b/tests/isolation2/expected7/test_vacuum.out @@ -0,0 +1,99 @@ +-- This file tests various race conditions when performing 'VACUUM FULL'. + +-- 1. When the gpdb is performing 'VACUUM FULL' on some relation, it can be summarized +-- as the following 3 steps: +-- s1) create a new temporary relation (smgrcreate hook will be triggered, newly +-- created relfilenode will be put into shmem). +-- s2) insert data into the newly created relation from the old relation (smgrextend +-- hook will be triggered, newly created relfilenode will be put into shmem). +-- s3) change the old relation's relfilenode to the newly created one. +-- Consider the following situation: +-- If the diskquota bgworker pulls active oids before the 'VACUUM FULL' operation finishing, +-- the newly created relfilenode is translated to the newly created temporary relation's oid, +-- the old relation's size cannot be updated. We resolve it by making altered relations' oids +-- constantly active so that the diskquota bgworker keeps updating the altered relation size +-- during 'VACUUM FULL'. +CREATE TABLE dummy_t1(i int) DISTRIBUTED BY (i); +CREATE TABLE +INSERT INTO dummy_t1 SELECT generate_series(1, 1000); +INSERT 0 1000 +DELETE FROM dummy_t1; +DELETE 1000 +-- Wait for the diskquota bgworker refreshing the size of 'dummy_t1'. +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +-- Shows that the result of pg_table_size() and diskquota.table_size are identical. +SELECT pg_table_size('dummy_t1'); + pg_table_size +--------------- + 98304 +(1 row) +SELECT tableid::regclass, size, segid FROM diskquota.table_size WHERE tableid='dummy_t1'::regclass ORDER BY segid; + tableid | size | segid +----------+-------+------- + dummy_t1 | 98304 | -1 + dummy_t1 | 32768 | 0 + dummy_t1 | 32768 | 1 + dummy_t1 | 32768 | 2 +(4 rows) +SELECT gp_inject_fault_infinite('object_access_post_alter', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content<>-1; + gp_inject_fault_infinite +-------------------------- + Success: + Success: + Success: +(3 rows) +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +1&: VACUUM FULL dummy_t1; +SELECT gp_wait_until_triggered_fault('object_access_post_alter', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content<>-1; + gp_wait_until_triggered_fault +------------------------------- + Success: + Success: + Success: +(3 rows) +-- Wait for the diskquota bgworker 'consumes' the newly created relfilenode from shmem. +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +SELECT gp_inject_fault_infinite('object_access_post_alter', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content<>-1; + gp_inject_fault_infinite +-------------------------- + Success: + Success: + Success: +(3 rows) +1<: <... completed> +VACUUM + +-- Wait for the diskquota bgworker refreshing the size of 'dummy_t1'. +SELECT diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) +-- Shows that the result of pg_table_size() and diskquota.table_size are identical. +SELECT pg_table_size('dummy_t1'); + pg_table_size +--------------- + 0 +(1 row) +SELECT tableid::regclass, size, segid FROM diskquota.table_size WHERE tableid='dummy_t1'::regclass ORDER BY segid; + tableid | size | segid +----------+------+------- + dummy_t1 | 0 | -1 + dummy_t1 | 0 | 0 + dummy_t1 | 0 | 1 + dummy_t1 | 0 | 2 +(4 rows) +DROP TABLE dummy_t1; +DROP TABLE diff --git a/tests/regress/diskquota_schedule b/tests/regress/diskquota_schedule index 9805a8e4..c3a25ff4 100644 --- a/tests/regress/diskquota_schedule +++ b/tests/regress/diskquota_schedule @@ -9,7 +9,6 @@ test: test_pause_and_resume test: test_pause_and_resume_multiple_db test: test_drop_after_pause test: test_show_status -test: test_update_db_cache test: test_quota_view_no_table # disable this test due to GPDB behavior change # test: test_table_size diff --git a/tests/regress/expected/test_update_db_cache.out b/tests/regress/expected/test_update_db_cache.out deleted file mode 100644 index 785c8bff..00000000 --- a/tests/regress/expected/test_update_db_cache.out +++ /dev/null @@ -1,64 +0,0 @@ ---start_ignore -CREATE DATABASE test_db_cache; ---end_ignore -\c test_db_cache -CREATE EXTENSION diskquota; -CREATE EXTENSION diskquota_test; --- Wait until the db cache gets updated -SELECT diskquota.wait_for_worker_new_epoch(); - wait_for_worker_new_epoch ---------------------------- - t -(1 row) - -CREATE TABLE t(i) AS SELECT generate_series(1, 100000) -DISTRIBUTED BY (i); -SELECT diskquota.wait_for_worker_new_epoch(); - wait_for_worker_new_epoch ---------------------------- - t -(1 row) - -SELECT tableid::regclass, size, segid -FROM diskquota.table_size -WHERE tableid = 't'::regclass -ORDER BY segid; - tableid | size | segid ----------+---------+------- - t | 3637248 | -1 - t | 1212416 | 0 - t | 1212416 | 1 - t | 1212416 | 2 -(4 rows) - -DROP EXTENSION diskquota; --- Create table without extension -CREATE TABLE t_no_extension(i) AS SELECT generate_series(1, 100000) -DISTRIBUTED BY (i); -CREATE EXTENSION diskquota; -WARNING: [diskquota] diskquota is not ready because current database is not empty -HINT: please run 'SELECT diskquota.init_table_size_table();' to initialize diskquota -SELECT diskquota_test.wait('SELECT diskquota_test.check_cur_db_status(''UNREADY'');'); - wait ------- - t -(1 row) - --- Should find nothing since t_no_extension is not recorded. -SELECT diskquota.diskquota_fetch_table_stat(0, ARRAY[]::oid[]) -FROM gp_dist_random('gp_id'); - diskquota_fetch_table_stat ----------------------------- -(0 rows) - -DROP TABLE t; -DROP TABLE t_no_extension; -SELECT diskquota.pause(); - pause -------- - -(1 row) - -DROP EXTENSION diskquota; -\c contrib_regression -DROP DATABASE test_db_cache; diff --git a/tests/regress/sql/config.sql b/tests/regress/sql/config.sql index f6755ab2..d8f54870 100644 --- a/tests/regress/sql/config.sql +++ b/tests/regress/sql/config.sql @@ -6,6 +6,7 @@ CREATE DATABASE diskquota; \! gpconfig -c max_worker_processes -v 20 --skipvalidation \! gpconfig -c diskquota.hard_limit -v "off" --skipvalidation \! gpconfig -c diskquota.max_workers -v 1 --skipvalidation +\! gpconfig -c plpython3.python_path -v "'$GPHOME/lib/python'" --skipvalidation; \! gpconfig -c log_min_messages -v debug1 \! gpstop -raf diff --git a/tests/regress/sql/test_update_db_cache.sql b/tests/regress/sql/test_update_db_cache.sql deleted file mode 100644 index c426d118..00000000 --- a/tests/regress/sql/test_update_db_cache.sql +++ /dev/null @@ -1,43 +0,0 @@ ---start_ignore -CREATE DATABASE test_db_cache; ---end_ignore - -\c test_db_cache -CREATE EXTENSION diskquota; -CREATE EXTENSION diskquota_test; - --- Wait until the db cache gets updated -SELECT diskquota.wait_for_worker_new_epoch(); - -CREATE TABLE t(i) AS SELECT generate_series(1, 100000) -DISTRIBUTED BY (i); - -SELECT diskquota.wait_for_worker_new_epoch(); - -SELECT tableid::regclass, size, segid -FROM diskquota.table_size -WHERE tableid = 't'::regclass -ORDER BY segid; - -DROP EXTENSION diskquota; - --- Create table without extension -CREATE TABLE t_no_extension(i) AS SELECT generate_series(1, 100000) -DISTRIBUTED BY (i); - -CREATE EXTENSION diskquota; - -SELECT diskquota_test.wait('SELECT diskquota_test.check_cur_db_status(''UNREADY'');'); - --- Should find nothing since t_no_extension is not recorded. -SELECT diskquota.diskquota_fetch_table_stat(0, ARRAY[]::oid[]) -FROM gp_dist_random('gp_id'); - -DROP TABLE t; -DROP TABLE t_no_extension; -SELECT diskquota.pause(); - -DROP EXTENSION diskquota; - -\c contrib_regression -DROP DATABASE test_db_cache; diff --git a/upgrade_test/CMakeLists.txt b/upgrade_test/CMakeLists.txt index f151bd66..bf96af5f 100644 --- a/upgrade_test/CMakeLists.txt +++ b/upgrade_test/CMakeLists.txt @@ -14,7 +14,14 @@ if (${GP_MAJOR_VERSION} EQUAL 6) ${CMAKE_CURRENT_SOURCE_DIR}/schedule_2.1--2.2 ${CMAKE_CURRENT_SOURCE_DIR}/schedule_2.2--2.1 ) + set(EXPECTED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/expected") +else() + set(EXPECTED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/expected7") endif() +list(APPEND schedule_files + ${CMAKE_CURRENT_SOURCE_DIR}/schedule_2.2--2.3 + ${CMAKE_CURRENT_SOURCE_DIR}/schedule_2.3--2.2 +) regresstarget_add( upgradecheck INIT_FILE @@ -22,7 +29,7 @@ regresstarget_add( SQL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/sql EXPECTED_DIR - ${CMAKE_CURRENT_SOURCE_DIR}/expected + ${EXPECTED_DIR} RESULTS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/results SCHEDULE_FILE diff --git a/upgrade_test/expected/2.2_set_quota.out b/upgrade_test/expected/2.2_set_quota.out index 400f3e54..2d2d5486 100644 --- a/upgrade_test/expected/2.2_set_quota.out +++ b/upgrade_test/expected/2.2_set_quota.out @@ -4,7 +4,18 @@ GUC : shared_preload_libraries Master value: diskquota-2.2.so Segment value: diskquota-2.2.so create extension diskquota with version '2.2'; -\!sleep 5 +select diskquota.init_table_size_table(); + init_table_size_table +----------------------- + +(1 row) + +select diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) + -- schema quota create schema s1; select diskquota.set_schema_quota('s1', '1 MB'); diff --git a/upgrade_test/expected/2.2_test_in_2.3_quota_create_in_2.2.out b/upgrade_test/expected/2.2_test_in_2.3_quota_create_in_2.2.out new file mode 100644 index 00000000..aab1cb10 --- /dev/null +++ b/upgrade_test/expected/2.2_test_in_2.3_quota_create_in_2.2.out @@ -0,0 +1,16 @@ +-- need run 2.3_set_quota before run this test +-- FIXME add version check here +\! sleep 5 +insert into s1.a select generate_series(1, 10000000); -- fail. +ERROR: schema's disk space quota exceeded with name: s1 +insert into srole.b select generate_series(1, 100000); -- fail. +ERROR: role's disk space quota exceeded with name: u1 +insert into rolespcrole.b select generate_series(1, 100000); -- fail. +ERROR: tablespace: rolespc, role: rolespcu1 diskquota exceeded +insert into spcs1.a select generate_series(1, 100000); -- fail. +ERROR: tablespace: schemaspc, schema: spcs1 diskquota exceeded +drop table s1.a, srole.b, spcs1.a, rolespcrole.b; +drop schema s1, srole, spcs1, rolespcrole; +drop tablespace rolespc; +drop tablespace schemaspc; +drop role u1, rolespcu1; diff --git a/upgrade_test/expected/2.3_catalog.out b/upgrade_test/expected/2.3_catalog.out new file mode 100644 index 00000000..0d74319b --- /dev/null +++ b/upgrade_test/expected/2.3_catalog.out @@ -0,0 +1,310 @@ +CREATE FUNCTION typeid_to_name(oid[]) RETURNS name[] AS ' + WITH io AS ( + SELECT x.i AS index, x.o AS type_id FROM ( + SELECT generate_series(1, array_length($1, 1)) AS i, unnest($1) AS o + ) AS x + ) SELECT array_agg(typname order by io.index) FROM io, pg_type t WHERE io.type_id = t.oid; +' LANGUAGE sql STABLE; +-- types +SELECT + t1.typname, + array_agg(t2.typname order by a.atttypid) typname +FROM + pg_namespace n, + pg_class c, + pg_type t1, + pg_type t2, + pg_attribute a +WHERE + n.nspname = 'diskquota' + AND c.oid = t1.typrelid + AND n.oid = t1.typnamespace + AND a.attrelid = c.oid + AND t2.oid = a.atttypid +GROUP BY + t1.typname +ORDER BY + t1.typname; + typname | typname +----------------------------------------+---------------------------------------------------------------------------------- + diskquota_active_table_type | {int8,int2,oid} + quota_config | {int8,int4,int4,oid,oid,tid,xid,xid,cid,cid,float4} + rejectmap | {bool,int4,text,oid,oid,oid,oid,oid,oid} + rejectmap_entry | {bool,int4,oid,oid,oid} + rejectmap_entry_detail | {bool,int4,text,oid,oid,oid,oid,oid,oid} + relation_cache_detail | {char,int4,int4,oid,oid,oid,oid,oid,oid,oid,oid,_oid} + show_all_relation_view | {oid,oid,oid,oid} + show_fast_database_size_view | {numeric} + show_fast_role_quota_view | {name,int8,oid,numeric} + show_fast_role_tablespace_quota_view | {name,name,int8,oid,oid,numeric} + show_fast_schema_quota_view | {name,int8,oid,numeric} + show_fast_schema_tablespace_quota_view | {name,name,int8,oid,oid,numeric} + show_segment_ratio_quota_view | {name,oid,float4} + state | {int4,int4,oid,tid,xid,xid,cid,cid} + table_size | {int8,int2,int4,oid,oid,tid,xid,xid,cid,cid} + target | {int4,int4,int4,oid,oid,oid,tid,xid,xid,cid,cid} + target_rowid_seq | {bool,bool,name,int8,int8,int8,int8,int8,int8,int8,int4,oid,tid,xid,xid,cid,cid} +(17 rows) + +-- types end +-- tables +SELECT + relname, + typeid_to_name(ARRAY[c.reltype]::oid[]) as reltype, + typeid_to_name(ARRAY[c.reloftype]::oid[]) as reloftype +FROM + pg_class c, + pg_namespace n +WHERE + c.relnamespace = n.oid + AND n.nspname = 'diskquota' + and c.relkind != 'v' +ORDER BY + relname; + relname | reltype | reloftype +-----------------------------+-------------------------------+----------- + diskquota_active_table_type | {diskquota_active_table_type} | + quota_config | {quota_config} | + quota_config_pkey | | + rejectmap_entry | {rejectmap_entry} | + rejectmap_entry_detail | {rejectmap_entry_detail} | + relation_cache_detail | {relation_cache_detail} | + state | {state} | + state_pkey | | + table_size | {table_size} | + table_size_pkey | | + target | {target} | + target_pkey | | + target_rowid_seq | {target_rowid_seq} | +(13 rows) + +-- tables end +-- UDF +SELECT + proname, + typeid_to_name(ARRAY[prorettype]::oid[]) as prorettype, + typeid_to_name(proargtypes) as proargtypes, + typeid_to_name(proallargtypes) as proallargtypes, + proargmodes, + prosrc, + probin, + proacl +FROM + pg_namespace n, + pg_proc p +WHERE + n.nspname = 'diskquota' + AND n.oid = p.pronamespace + AND p.proname != 'update_diskquota_db_list' -- update_diskquota_db_list in 1.0 can not be dropd, this is acceptable +ORDER BY + proname; + proname | prorettype | proargtypes | proallargtypes | proargmodes | prosrc | probin | proacl +-----------------------------+-------------------------------+-------------------------+-----------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------+-------- + diskquota_fetch_table_stat | {diskquota_active_table_type} | {int4,_oid} | | | diskquota_fetch_table_stat | $libdir/diskquota-2.3.so | + init_table_size_table | {void} | | | | init_table_size_table | $libdir/diskquota-2.3.so | + pause | {void} | | | | diskquota_pause | $libdir/diskquota-2.3.so | + pull_all_table_size | {record} | | {oid,int8,int2} | {o,o,o} | pull_all_table_size | $libdir/diskquota-2.3.so | + refresh_rejectmap | {void} | {_rejectmap_entry,_oid} | | | refresh_rejectmap | $libdir/diskquota-2.3.so | + relation_size | {int8} | {regclass} | | | +| | + | | | | | SELECT SUM(size)::bigint FROM ( +| | + | | | | | SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, +| | + | | | | | CASE WHEN EXISTS +| | + | | | | | (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END,+| | + | | | | | relam) AS size +| | + | | | | | FROM gp_dist_random('pg_class') as relstorage WHERE oid = relation +| | + | | | | | UNION ALL +| | + | | | | | SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, +| | + | | | | | CASE WHEN EXISTS +| | + | | | | | (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END,+| | + | | | | | relam) AS size +| | + | | | | | FROM pg_class as relstorage WHERE oid = relation +| | + | | | | | ) AS t | | + relation_size_local | {int8} | {oid,oid,char,char,oid} | | | relation_size_local | $libdir/diskquota-2.3.so | + resume | {void} | | | | diskquota_resume | $libdir/diskquota-2.3.so | + set_per_segment_quota | {void} | {text,float4} | | | set_per_segment_quota | $libdir/diskquota-2.3.so | + set_role_quota | {void} | {text,text} | | | set_role_quota | $libdir/diskquota-2.3.so | + set_role_tablespace_quota | {void} | {text,text,text} | | | set_role_tablespace_quota | $libdir/diskquota-2.3.so | + set_schema_quota | {void} | {text,text} | | | set_schema_quota | $libdir/diskquota-2.3.so | + set_schema_tablespace_quota | {void} | {text,text,text} | | | set_schema_tablespace_quota | $libdir/diskquota-2.3.so | + show_rejectmap | {rejectmap_entry_detail} | | | | show_rejectmap | $libdir/diskquota-2.3.so | + show_relation_cache | {relation_cache_detail} | | | | show_relation_cache | $libdir/diskquota-2.3.so | + show_relation_cache_all_seg | {relation_cache_detail} | | | | +| | + | | | | | WITH relation_cache AS ( +| | + | | | | | SELECT diskquota.show_relation_cache() AS a +| | + | | | | | FROM gp_dist_random('gp_id') +| | + | | | | | ) +| | + | | | | | SELECT (a).* FROM relation_cache; | | + show_worker_epoch | {int8} | | | | show_worker_epoch | $libdir/diskquota-2.3.so | + status | {record} | | {text,text} | {t,t} | diskquota_status | $libdir/diskquota-2.3.so | + wait_for_worker_new_epoch | {bool} | | | | wait_for_worker_new_epoch | $libdir/diskquota-2.3.so | +(19 rows) + +-- UDF end +-- views +SELECT + schemaname, + viewname, + definition +FROM + pg_views +WHERE + schemaname = 'diskquota' +ORDER by + schemaname, viewname; + schemaname | viewname | definition +------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + diskquota | rejectmap | SELECT bm.target_type, + + | | bm.target_oid, + + | | bm.database_oid, + + | | bm.tablespace_oid, + + | | bm.seg_exceeded, + + | | bm.dbnode, + + | | bm.spcnode, + + | | bm.relnode, + + | | bm.segid + + | | FROM diskquota.show_rejectmap() bm(target_type, target_oid, database_oid, tablespace_oid, seg_exceeded, dbnode, spcnode, relnode, segid); + diskquota | show_all_relation_view | WITH relation_cache AS ( + + | | SELECT f.relid, + + | | f.primary_table_oid, + + | | f.auxrel_num, + + | | f.owneroid, + + | | f.namespaceoid, + + | | f.backendid, + + | | f.spcnode, + + | | f.dbnode, + + | | f.relnode, + + | | f.relstorage, + + | | f.auxrel_oid, + + | | f.relam + + | | FROM diskquota.show_relation_cache() f(relid, primary_table_oid, auxrel_num, owneroid, namespaceoid, backendid, spcnode, dbnode, relnode, relstorage, auxrel_oid, relam)+ + | | ) + + | | SELECT union_relation.oid, + + | | union_relation.relowner, + + | | union_relation.relnamespace, + + | | union_relation.reltablespace + + | | FROM ( SELECT relation_cache.relid AS oid, + + | | relation_cache.owneroid AS relowner, + + | | relation_cache.namespaceoid AS relnamespace, + + | | relation_cache.spcnode AS reltablespace + + | | FROM relation_cache + + | | UNION + + | | SELECT pg_class.oid, + + | | pg_class.relowner, + + | | pg_class.relnamespace, + + | | pg_class.reltablespace + + | | FROM pg_class) union_relation + + | | GROUP BY union_relation.oid, union_relation.relowner, union_relation.relnamespace, union_relation.reltablespace; + diskquota | show_fast_database_size_view | SELECT (( SELECT sum(pg_relation_size((pg_class.oid)::regclass)) AS sum + + | | FROM pg_class + + | | WHERE (pg_class.oid <= (16384)::oid)) + ( SELECT sum(table_size.size) AS sum + + | | FROM diskquota.table_size + + | | WHERE (table_size.segid = '-1'::integer))) AS dbsize; + diskquota | show_fast_role_quota_view | WITH quota_usage AS ( + + | | SELECT show_all_relation_view.relowner, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relowner + + | | ) + + | | SELECT pg_roles.rolname AS role_name, + + | | quota_config.targetoid AS role_oid, + + | | quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS rolsize_in_bytes + + | | FROM ((diskquota.quota_config + + | | JOIN pg_roles ON ((quota_config.targetoid = pg_roles.oid))) + + | | LEFT JOIN quota_usage ON ((pg_roles.oid = quota_usage.relowner))) + + | | WHERE (quota_config.quotatype = 1); + diskquota | show_fast_role_tablespace_quota_view | WITH default_tablespace AS ( + + | | SELECT pg_database.dattablespace + + | | FROM pg_database + + | | WHERE (pg_database.datname = current_database()) + + | | ), quota_usage AS ( + + | | SELECT show_all_relation_view.relowner, + + | | CASE + + | | WHEN (show_all_relation_view.reltablespace = (0)::oid) THEN default_tablespace.dattablespace + + | | ELSE show_all_relation_view.reltablespace + + | | END AS reltablespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view, + + | | default_tablespace + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relowner, show_all_relation_view.reltablespace, default_tablespace.dattablespace + + | | ), full_quota_config AS ( + + | | SELECT target.primaryoid, + + | | target.tablespaceoid, + + | | config.quotalimitmb + + | | FROM diskquota.quota_config config, + + | | diskquota.target target + + | | WHERE (((config.targetoid = (target.rowid)::oid) AND (config.quotatype = target.quotatype)) AND (config.quotatype = 3)) + + | | ) + + | | SELECT pg_roles.rolname AS role_name, + + | | full_quota_config.primaryoid AS role_oid, + + | | pg_tablespace.spcname AS tablespace_name, + + | | full_quota_config.tablespaceoid AS tablespace_oid, + + | | full_quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS rolsize_tablespace_in_bytes + + | | FROM (((full_quota_config + + | | JOIN pg_roles ON ((full_quota_config.primaryoid = pg_roles.oid))) + + | | JOIN pg_tablespace ON ((full_quota_config.tablespaceoid = pg_tablespace.oid))) + + | | LEFT JOIN quota_usage ON (((pg_roles.oid = quota_usage.relowner) AND (pg_tablespace.oid = quota_usage.reltablespace)))); + diskquota | show_fast_schema_quota_view | WITH quota_usage AS ( + + | | SELECT show_all_relation_view.relnamespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relnamespace + + | | ) + + | | SELECT pg_namespace.nspname AS schema_name, + + | | quota_config.targetoid AS schema_oid, + + | | quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS nspsize_in_bytes + + | | FROM ((diskquota.quota_config + + | | JOIN pg_namespace ON ((quota_config.targetoid = pg_namespace.oid))) + + | | LEFT JOIN quota_usage ON ((pg_namespace.oid = quota_usage.relnamespace))) + + | | WHERE (quota_config.quotatype = 0); + diskquota | show_fast_schema_tablespace_quota_view | WITH default_tablespace AS ( + + | | SELECT pg_database.dattablespace + + | | FROM pg_database + + | | WHERE (pg_database.datname = current_database()) + + | | ), quota_usage AS ( + + | | SELECT show_all_relation_view.relnamespace, + + | | CASE + + | | WHEN (show_all_relation_view.reltablespace = (0)::oid) THEN default_tablespace.dattablespace + + | | ELSE show_all_relation_view.reltablespace + + | | END AS reltablespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view, + + | | default_tablespace + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relnamespace, show_all_relation_view.reltablespace, default_tablespace.dattablespace + + | | ), full_quota_config AS ( + + | | SELECT target.primaryoid, + + | | target.tablespaceoid, + + | | config.quotalimitmb + + | | FROM diskquota.quota_config config, + + | | diskquota.target target + + | | WHERE (((config.targetoid = (target.rowid)::oid) AND (config.quotatype = target.quotatype)) AND (config.quotatype = 2)) + + | | ) + + | | SELECT pg_namespace.nspname AS schema_name, + + | | full_quota_config.primaryoid AS schema_oid, + + | | pg_tablespace.spcname AS tablespace_name, + + | | full_quota_config.tablespaceoid AS tablespace_oid, + + | | full_quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS nspsize_tablespace_in_bytes + + | | FROM (((full_quota_config + + | | JOIN pg_namespace ON ((full_quota_config.primaryoid = pg_namespace.oid))) + + | | JOIN pg_tablespace ON ((full_quota_config.tablespaceoid = pg_tablespace.oid))) + + | | LEFT JOIN quota_usage ON (((pg_namespace.oid = quota_usage.relnamespace) AND (pg_tablespace.oid = quota_usage.reltablespace)))); + diskquota | show_segment_ratio_quota_view | SELECT pg_tablespace.spcname AS tablespace_name, + + | | pg_tablespace.oid AS tablespace_oid, + + | | quota_config.segratio AS per_seg_quota_ratio + + | | FROM (diskquota.quota_config + + | | JOIN pg_tablespace ON (((quota_config.targetoid = pg_tablespace.oid) AND (quota_config.quotatype = 4)))); +(8 rows) + +-- views end +DROP FUNCTION typeid_to_name (oid[]); diff --git a/upgrade_test/expected/2.3_cleanup_quota.out b/upgrade_test/expected/2.3_cleanup_quota.out new file mode 100644 index 00000000..3935d709 --- /dev/null +++ b/upgrade_test/expected/2.3_cleanup_quota.out @@ -0,0 +1 @@ +drop extension diskquota; diff --git a/upgrade_test/expected/2.3_install.out b/upgrade_test/expected/2.3_install.out new file mode 100644 index 00000000..4738c064 --- /dev/null +++ b/upgrade_test/expected/2.3_install.out @@ -0,0 +1,13 @@ +-- cleanup previous diskquota installation +\! gpconfig -c shared_preload_libraries -v '' > /dev/null +\! gpstop -raf > /dev/null +\! dropdb --if-exists diskquota +-- TODO reset all diskquota GUC +\! gpstop -raf > /dev/null +-- setup basic environment +\! createdb diskquota +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.3.so' > /dev/null +\! gpstop -raf > /dev/null +-- TODO setup GUC +\! gpconfig -c diskquota.naptime -v '1' > /dev/null +\! gpstop -raf > /dev/null diff --git a/upgrade_test/expected/2.3_migrate_to_version_2.3.out b/upgrade_test/expected/2.3_migrate_to_version_2.3.out new file mode 100644 index 00000000..bc14c46c --- /dev/null +++ b/upgrade_test/expected/2.3_migrate_to_version_2.3.out @@ -0,0 +1,10 @@ +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.3.so' > /dev/null +\! gpstop -raf > /dev/null +\! gpconfig -s 'shared_preload_libraries' +Values on all segments are consistent +GUC : shared_preload_libraries +Master value: diskquota-2.3.so +Segment value: diskquota-2.3.so +\c +alter extension diskquota update to '2.3'; +\! sleep 5 diff --git a/upgrade_test/expected/2.3_set_quota.out b/upgrade_test/expected/2.3_set_quota.out new file mode 100644 index 00000000..57dc9145 --- /dev/null +++ b/upgrade_test/expected/2.3_set_quota.out @@ -0,0 +1,68 @@ +\!gpconfig -s 'shared_preload_libraries' +Values on all segments are consistent +GUC : shared_preload_libraries +Master value: diskquota-2.3.so +Segment value: diskquota-2.3.so +create extension diskquota with version '2.3'; +select diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) + +-- schema quota +create schema s1; +select diskquota.set_schema_quota('s1', '1 MB'); + set_schema_quota +------------------ + +(1 row) + +create table s1.a(i int) distributed by (i); +insert into s1.a select generate_series(1, 10000000); -- ok. +-- role quota +create schema srole; +create role u1 nologin; +NOTICE: resource queue required -- using default resource queue "pg_default" +create table srole.b (t text) distributed by (t); +alter table srole.b owner to u1; +select diskquota.set_role_quota('u1', '1 MB'); + set_role_quota +---------------- + +(1 row) + +insert into srole.b select generate_series(1,100000); -- ok. +-- schema tablespace quota +\! mkdir -p /tmp/schemaspc +create schema spcs1; +create tablespace schemaspc location '/tmp/schemaspc'; +select diskquota.set_schema_tablespace_quota('spcs1', 'schemaspc','1 MB'); + set_schema_tablespace_quota +----------------------------- + +(1 row) + +create table spcs1.a(i int) tablespace schemaspc distributed by (i); +insert into spcs1.a select generate_series(1,100000); -- ok. +-- role tablespace quota +\! mkdir -p /tmp/rolespc +create tablespace rolespc location '/tmp/rolespc'; +create role rolespcu1 nologin; +NOTICE: resource queue required -- using default resource queue "pg_default" +create schema rolespcrole; +create table rolespcrole.b (t text) tablespace rolespc distributed by (t); +alter table rolespcrole.b owner to rolespcu1; +select diskquota.set_role_tablespace_quota('rolespcu1', 'rolespc', '1 MB'); + set_role_tablespace_quota +--------------------------- + +(1 row) + +insert into rolespcrole.b select generate_series(1,100000); -- ok. +\!sleep 5 +-- leaked resource: +-- role u1, rolespcu1 +-- table s1.a, srole.b spcs1.a, rolespcrole.b +-- schema s1, srole, spcs1, rolespcrole +-- tablespace schemaspc, rolespc diff --git a/upgrade_test/expected/2.3_test_in_2.2_quota_create_in_2.3.out b/upgrade_test/expected/2.3_test_in_2.2_quota_create_in_2.3.out new file mode 100644 index 00000000..71c24e58 --- /dev/null +++ b/upgrade_test/expected/2.3_test_in_2.2_quota_create_in_2.3.out @@ -0,0 +1,16 @@ +-- need run 2.2_set_quota before run this test +-- FIXME add version check here +\! sleep 5 +insert into s1.a select generate_series(1, 10000000); -- fail. +ERROR: schema's disk space quota exceeded with name: s1 +insert into srole.b select generate_series(1, 100000); -- fail. +ERROR: role's disk space quota exceeded with name: u1 +insert into rolespcrole.b select generate_series(1, 100000); -- fail. +ERROR: tablespace: rolespc, role: rolespcu1 diskquota exceeded +insert into spcs1.a select generate_series(1, 100000); -- fail. +ERROR: tablespace: schemaspc, schema: spcs1 diskquota exceeded +drop table s1.a, srole.b, spcs1.a, rolespcrole.b; +drop schema s1, srole, spcs1, rolespcrole; +drop tablespace rolespc; +drop tablespace schemaspc; +drop role u1, rolespcu1; diff --git a/upgrade_test/expected7/2.2_catalog.out b/upgrade_test/expected7/2.2_catalog.out new file mode 100644 index 00000000..48d2934a --- /dev/null +++ b/upgrade_test/expected7/2.2_catalog.out @@ -0,0 +1,308 @@ +CREATE FUNCTION typeid_to_name(oid[]) RETURNS name[] AS ' + WITH io AS ( + SELECT x.i AS index, x.o AS type_id FROM ( + SELECT generate_series(1, array_length($1, 1)) AS i, unnest($1) AS o + ) AS x + ) SELECT array_agg(typname order by io.index) FROM io, pg_type t WHERE io.type_id = t.oid; +' LANGUAGE sql STABLE; +-- types +SELECT + t1.typname, + array_agg(t2.typname order by a.atttypid) typname +FROM + pg_namespace n, + pg_class c, + pg_type t1, + pg_type t2, + pg_attribute a +WHERE + n.nspname = 'diskquota' + AND c.oid = t1.typrelid + AND n.oid = t1.typnamespace + AND a.attrelid = c.oid + AND t2.oid = a.atttypid +GROUP BY + t1.typname +ORDER BY + t1.typname; + typname | typname +----------------------------------------+------------------------------------------------------- + diskquota_active_table_type | {int8,int2,oid} + quota_config | {int8,int4,int4,oid,oid,tid,xid,xid,cid,cid,float4} + rejectmap | {bool,int4,text,oid,oid,oid,oid,oid,oid} + rejectmap_entry | {bool,int4,oid,oid,oid} + rejectmap_entry_detail | {bool,int4,text,oid,oid,oid,oid,oid,oid} + relation_cache_detail | {char,int4,int4,oid,oid,oid,oid,oid,oid,oid,oid,_oid} + show_all_relation_view | {oid,oid,oid,oid} + show_fast_database_size_view | {numeric} + show_fast_role_quota_view | {name,int8,oid,numeric} + show_fast_role_tablespace_quota_view | {name,name,int8,oid,oid,numeric} + show_fast_schema_quota_view | {name,int8,oid,numeric} + show_fast_schema_tablespace_quota_view | {name,name,int8,oid,oid,numeric} + show_segment_ratio_quota_view | {name,oid,float4} + state | {int4,int4,oid,tid,xid,xid,cid,cid} + table_size | {int8,int2,int4,oid,oid,tid,xid,xid,cid,cid} + target | {int4,int4,int4,oid,oid,oid,tid,xid,xid,cid,cid} +(16 rows) + +-- types end +-- tables +SELECT + relname, + typeid_to_name(ARRAY[c.reltype]::oid[]) as reltype, + typeid_to_name(ARRAY[c.reloftype]::oid[]) as reloftype +FROM + pg_class c, + pg_namespace n +WHERE + c.relnamespace = n.oid + AND n.nspname = 'diskquota' + and c.relkind != 'v' +ORDER BY + relname; + relname | reltype | reloftype +-----------------------------+-------------------------------+----------- + diskquota_active_table_type | {diskquota_active_table_type} | + quota_config | {quota_config} | + quota_config_pkey | | + rejectmap_entry | {rejectmap_entry} | + rejectmap_entry_detail | {rejectmap_entry_detail} | + relation_cache_detail | {relation_cache_detail} | + state | {state} | + state_pkey | | + table_size | {table_size} | + table_size_pkey | | + target | {target} | + target_pkey | | + target_rowid_seq | | +(13 rows) + +-- tables end +-- UDF +SELECT + proname, + typeid_to_name(ARRAY[prorettype]::oid[]) as prorettype, + typeid_to_name(proargtypes) as proargtypes, + typeid_to_name(proallargtypes) as proallargtypes, + proargmodes, + prosrc, + probin, + proacl +FROM + pg_namespace n, + pg_proc p +WHERE + n.nspname = 'diskquota' + AND n.oid = p.pronamespace + AND p.proname != 'update_diskquota_db_list' -- update_diskquota_db_list in 1.0 can not be dropd, this is acceptable +ORDER BY + proname; + proname | prorettype | proargtypes | proallargtypes | proargmodes | prosrc | probin | proacl +-----------------------------+-------------------------------+-------------------------+-----------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------+-------- + diskquota_fetch_table_stat | {diskquota_active_table_type} | {int4,_oid} | | | diskquota_fetch_table_stat | $libdir/diskquota-2.2.so | + init_table_size_table | {void} | | | | init_table_size_table | $libdir/diskquota-2.2.so | + pause | {void} | | | | diskquota_pause | $libdir/diskquota-2.2.so | + pull_all_table_size | {record} | | {oid,int8,int2} | {o,o,o} | pull_all_table_size | $libdir/diskquota-2.2.so | + refresh_rejectmap | {void} | {_rejectmap_entry,_oid} | | | refresh_rejectmap | $libdir/diskquota-2.2.so | + relation_size | {int8} | {regclass} | | | +| | + | | | | | SELECT SUM(size)::bigint FROM ( +| | + | | | | | SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, +| | + | | | | | CASE WHEN EXISTS +| | + | | | | | (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END,+| | + | | | | | relam) AS size +| | + | | | | | FROM gp_dist_random('pg_class') as relstorage WHERE oid = relation +| | + | | | | | UNION ALL +| | + | | | | | SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, +| | + | | | | | CASE WHEN EXISTS +| | + | | | | | (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END,+| | + | | | | | relam) AS size +| | + | | | | | FROM pg_class as relstorage WHERE oid = relation +| | + | | | | | ) AS t | | + relation_size_local | {int8} | {oid,oid,char,char,oid} | | | relation_size_local | $libdir/diskquota-2.2.so | + resume | {void} | | | | diskquota_resume | $libdir/diskquota-2.2.so | + set_per_segment_quota | {void} | {text,float4} | | | set_per_segment_quota | $libdir/diskquota-2.2.so | + set_role_quota | {void} | {text,text} | | | set_role_quota | $libdir/diskquota-2.2.so | + set_role_tablespace_quota | {void} | {text,text,text} | | | set_role_tablespace_quota | $libdir/diskquota-2.2.so | + set_schema_quota | {void} | {text,text} | | | set_schema_quota | $libdir/diskquota-2.2.so | + set_schema_tablespace_quota | {void} | {text,text,text} | | | set_schema_tablespace_quota | $libdir/diskquota-2.2.so | + show_rejectmap | {rejectmap_entry_detail} | | | | show_rejectmap | $libdir/diskquota-2.2.so | + show_relation_cache | {relation_cache_detail} | | | | show_relation_cache | $libdir/diskquota-2.2.so | + show_relation_cache_all_seg | {relation_cache_detail} | | | | +| | + | | | | | WITH relation_cache AS ( +| | + | | | | | SELECT diskquota.show_relation_cache() AS a +| | + | | | | | FROM gp_dist_random('gp_id') +| | + | | | | | ) +| | + | | | | | SELECT (a).* FROM relation_cache; | | + show_worker_epoch | {int8} | | | | show_worker_epoch | $libdir/diskquota-2.2.so | + status | {record} | | {text,text} | {t,t} | diskquota_status | $libdir/diskquota-2.2.so | + wait_for_worker_new_epoch | {bool} | | | | wait_for_worker_new_epoch | $libdir/diskquota-2.2.so | +(19 rows) + +-- UDF end +-- views +SELECT + schemaname, + viewname, + definition +FROM + pg_views +WHERE + schemaname = 'diskquota' +ORDER by + schemaname, viewname; + schemaname | viewname | definition +------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + diskquota | rejectmap | SELECT bm.target_type, + + | | bm.target_oid, + + | | bm.database_oid, + + | | bm.tablespace_oid, + + | | bm.seg_exceeded, + + | | bm.dbnode, + + | | bm.spcnode, + + | | bm.relnode, + + | | bm.segid + + | | FROM diskquota.show_rejectmap() bm(target_type, target_oid, database_oid, tablespace_oid, seg_exceeded, dbnode, spcnode, relnode, segid); + diskquota | show_all_relation_view | WITH relation_cache AS ( + + | | SELECT f.relid, + + | | f.primary_table_oid, + + | | f.auxrel_num, + + | | f.owneroid, + + | | f.namespaceoid, + + | | f.backendid, + + | | f.spcnode, + + | | f.dbnode, + + | | f.relnode, + + | | f.relstorage, + + | | f.auxrel_oid, + + | | f.relam + + | | FROM diskquota.show_relation_cache() f(relid, primary_table_oid, auxrel_num, owneroid, namespaceoid, backendid, spcnode, dbnode, relnode, relstorage, auxrel_oid, relam)+ + | | ) + + | | SELECT DISTINCT union_relation.oid, + + | | union_relation.relowner, + + | | union_relation.relnamespace, + + | | union_relation.reltablespace + + | | FROM ( SELECT relation_cache.relid AS oid, + + | | relation_cache.owneroid AS relowner, + + | | relation_cache.namespaceoid AS relnamespace, + + | | relation_cache.spcnode AS reltablespace + + | | FROM relation_cache + + | | UNION + + | | SELECT pg_class.oid, + + | | pg_class.relowner, + + | | pg_class.relnamespace, + + | | pg_class.reltablespace + + | | FROM pg_class) union_relation; + diskquota | show_fast_database_size_view | SELECT (( SELECT sum(pg_relation_size((pg_class.oid)::regclass)) AS sum + + | | FROM pg_class + + | | WHERE (pg_class.oid <= (16384)::oid)) + ( SELECT sum(table_size.size) AS sum + + | | FROM diskquota.table_size + + | | WHERE (table_size.segid = '-1'::integer))) AS dbsize; + diskquota | show_fast_role_quota_view | WITH quota_usage AS ( + + | | SELECT show_all_relation_view.relowner, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relowner + + | | ) + + | | SELECT pg_roles.rolname AS role_name, + + | | quota_config.targetoid AS role_oid, + + | | quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS rolsize_in_bytes + + | | FROM ((diskquota.quota_config + + | | JOIN pg_roles ON ((quota_config.targetoid = pg_roles.oid))) + + | | LEFT JOIN quota_usage ON ((pg_roles.oid = quota_usage.relowner))) + + | | WHERE (quota_config.quotatype = 1); + diskquota | show_fast_role_tablespace_quota_view | WITH default_tablespace AS ( + + | | SELECT pg_database.dattablespace + + | | FROM pg_database + + | | WHERE (pg_database.datname = current_database()) + + | | ), quota_usage AS ( + + | | SELECT show_all_relation_view.relowner, + + | | CASE + + | | WHEN (show_all_relation_view.reltablespace = (0)::oid) THEN default_tablespace.dattablespace + + | | ELSE show_all_relation_view.reltablespace + + | | END AS reltablespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view, + + | | default_tablespace + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relowner, show_all_relation_view.reltablespace, default_tablespace.dattablespace + + | | ), full_quota_config AS ( + + | | SELECT target.primaryoid, + + | | target.tablespaceoid, + + | | config.quotalimitmb + + | | FROM diskquota.quota_config config, + + | | diskquota.target target + + | | WHERE ((config.targetoid = (target.rowid)::oid) AND (config.quotatype = target.quotatype) AND (config.quotatype = 3)) + + | | ) + + | | SELECT pg_roles.rolname AS role_name, + + | | full_quota_config.primaryoid AS role_oid, + + | | pg_tablespace.spcname AS tablespace_name, + + | | full_quota_config.tablespaceoid AS tablespace_oid, + + | | full_quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS rolsize_tablespace_in_bytes + + | | FROM (((full_quota_config + + | | JOIN pg_roles ON ((full_quota_config.primaryoid = pg_roles.oid))) + + | | JOIN pg_tablespace ON ((full_quota_config.tablespaceoid = pg_tablespace.oid))) + + | | LEFT JOIN quota_usage ON (((pg_roles.oid = quota_usage.relowner) AND (pg_tablespace.oid = quota_usage.reltablespace)))); + diskquota | show_fast_schema_quota_view | WITH quota_usage AS ( + + | | SELECT show_all_relation_view.relnamespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relnamespace + + | | ) + + | | SELECT pg_namespace.nspname AS schema_name, + + | | quota_config.targetoid AS schema_oid, + + | | quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS nspsize_in_bytes + + | | FROM ((diskquota.quota_config + + | | JOIN pg_namespace ON ((quota_config.targetoid = pg_namespace.oid))) + + | | LEFT JOIN quota_usage ON ((pg_namespace.oid = quota_usage.relnamespace))) + + | | WHERE (quota_config.quotatype = 0); + diskquota | show_fast_schema_tablespace_quota_view | WITH default_tablespace AS ( + + | | SELECT pg_database.dattablespace + + | | FROM pg_database + + | | WHERE (pg_database.datname = current_database()) + + | | ), quota_usage AS ( + + | | SELECT show_all_relation_view.relnamespace, + + | | CASE + + | | WHEN (show_all_relation_view.reltablespace = (0)::oid) THEN default_tablespace.dattablespace + + | | ELSE show_all_relation_view.reltablespace + + | | END AS reltablespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view, + + | | default_tablespace + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relnamespace, show_all_relation_view.reltablespace, default_tablespace.dattablespace + + | | ), full_quota_config AS ( + + | | SELECT target.primaryoid, + + | | target.tablespaceoid, + + | | config.quotalimitmb + + | | FROM diskquota.quota_config config, + + | | diskquota.target target + + | | WHERE ((config.targetoid = (target.rowid)::oid) AND (config.quotatype = target.quotatype) AND (config.quotatype = 2)) + + | | ) + + | | SELECT pg_namespace.nspname AS schema_name, + + | | full_quota_config.primaryoid AS schema_oid, + + | | pg_tablespace.spcname AS tablespace_name, + + | | full_quota_config.tablespaceoid AS tablespace_oid, + + | | full_quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS nspsize_tablespace_in_bytes + + | | FROM (((full_quota_config + + | | JOIN pg_namespace ON ((full_quota_config.primaryoid = pg_namespace.oid))) + + | | JOIN pg_tablespace ON ((full_quota_config.tablespaceoid = pg_tablespace.oid))) + + | | LEFT JOIN quota_usage ON (((pg_namespace.oid = quota_usage.relnamespace) AND (pg_tablespace.oid = quota_usage.reltablespace)))); + diskquota | show_segment_ratio_quota_view | SELECT pg_tablespace.spcname AS tablespace_name, + + | | pg_tablespace.oid AS tablespace_oid, + + | | quota_config.segratio AS per_seg_quota_ratio + + | | FROM (diskquota.quota_config + + | | JOIN pg_tablespace ON (((quota_config.targetoid = pg_tablespace.oid) AND (quota_config.quotatype = 4)))); +(8 rows) + +-- views end +DROP FUNCTION typeid_to_name (oid[]); diff --git a/upgrade_test/expected7/2.2_cleanup_quota.out b/upgrade_test/expected7/2.2_cleanup_quota.out new file mode 100644 index 00000000..3935d709 --- /dev/null +++ b/upgrade_test/expected7/2.2_cleanup_quota.out @@ -0,0 +1 @@ +drop extension diskquota; diff --git a/upgrade_test/expected7/2.2_install.out b/upgrade_test/expected7/2.2_install.out new file mode 100644 index 00000000..c4b7f4c9 --- /dev/null +++ b/upgrade_test/expected7/2.2_install.out @@ -0,0 +1,13 @@ +-- cleanup previous diskquota installation +\! gpconfig -c shared_preload_libraries -v '' > /dev/null +\! gpstop -raf > /dev/null +\! dropdb --if-exists diskquota +-- TODO reset all diskquota GUC +\! gpstop -raf > /dev/null +-- setup basic environment +\! createdb diskquota +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.2.so' > /dev/null +\! gpstop -raf > /dev/null +-- TODO setup GUC +\! gpconfig -c diskquota.naptime -v '1' > /dev/null +\! gpstop -raf > /dev/null diff --git a/upgrade_test/expected7/2.2_migrate_to_version_2.2.out b/upgrade_test/expected7/2.2_migrate_to_version_2.2.out new file mode 100644 index 00000000..d6fbb962 --- /dev/null +++ b/upgrade_test/expected7/2.2_migrate_to_version_2.2.out @@ -0,0 +1,10 @@ +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.2.so' > /dev/null +\! gpstop -raf > /dev/null +\! gpconfig -s 'shared_preload_libraries' +Values on all segments are consistent +GUC : shared_preload_libraries +Coordinator value: diskquota-2.2.so +Segment value: diskquota-2.2.so +\c +alter extension diskquota update to '2.2'; +\! sleep 5 diff --git a/upgrade_test/expected7/2.2_set_quota.out b/upgrade_test/expected7/2.2_set_quota.out new file mode 100644 index 00000000..5083f574 --- /dev/null +++ b/upgrade_test/expected7/2.2_set_quota.out @@ -0,0 +1,72 @@ +\!gpconfig -s 'shared_preload_libraries' +Values on all segments are consistent +GUC : shared_preload_libraries +Coordinator value: diskquota-2.2.so +Segment value: diskquota-2.2.so +create extension diskquota with version '2.2'; +select diskquota.init_table_size_table(); + init_table_size_table +----------------------- + +(1 row) + +select diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) + +-- schema quota +create schema s1; +select diskquota.set_schema_quota('s1', '1 MB'); + set_schema_quota +------------------ + +(1 row) + +create table s1.a(i int) distributed by (i); +insert into s1.a select generate_series(1, 10000000); -- ok. +-- role quota +create schema srole; +create role u1 nologin; +create table srole.b (t text) distributed by (t); +alter table srole.b owner to u1; +select diskquota.set_role_quota('u1', '1 MB'); + set_role_quota +---------------- + +(1 row) + +insert into srole.b select generate_series(1,100000); -- ok. +-- schema tablespace quota +\! mkdir -p /tmp/schemaspc +create schema spcs1; +create tablespace schemaspc location '/tmp/schemaspc'; +select diskquota.set_schema_tablespace_quota('spcs1', 'schemaspc','1 MB'); + set_schema_tablespace_quota +----------------------------- + +(1 row) + +create table spcs1.a(i int) tablespace schemaspc distributed by (i); +insert into spcs1.a select generate_series(1,100000); -- ok. +-- role tablespace quota +\! mkdir -p /tmp/rolespc +create tablespace rolespc location '/tmp/rolespc'; +create role rolespcu1 nologin; +create schema rolespcrole; +create table rolespcrole.b (t text) tablespace rolespc distributed by (t); +alter table rolespcrole.b owner to rolespcu1; +select diskquota.set_role_tablespace_quota('rolespcu1', 'rolespc', '1 MB'); + set_role_tablespace_quota +--------------------------- + +(1 row) + +insert into rolespcrole.b select generate_series(1,100000); -- ok. +\!sleep 5 +-- leaked resource: +-- role u1, rolespcu1 +-- table s1.a, srole.b spcs1.a, rolespcrole.b +-- schema s1, srole, spcs1, rolespcrole +-- tablespace schemaspc, rolespc diff --git a/upgrade_test/expected7/2.2_test_in_2.3_quota_create_in_2.2.out b/upgrade_test/expected7/2.2_test_in_2.3_quota_create_in_2.2.out new file mode 100644 index 00000000..aab1cb10 --- /dev/null +++ b/upgrade_test/expected7/2.2_test_in_2.3_quota_create_in_2.2.out @@ -0,0 +1,16 @@ +-- need run 2.3_set_quota before run this test +-- FIXME add version check here +\! sleep 5 +insert into s1.a select generate_series(1, 10000000); -- fail. +ERROR: schema's disk space quota exceeded with name: s1 +insert into srole.b select generate_series(1, 100000); -- fail. +ERROR: role's disk space quota exceeded with name: u1 +insert into rolespcrole.b select generate_series(1, 100000); -- fail. +ERROR: tablespace: rolespc, role: rolespcu1 diskquota exceeded +insert into spcs1.a select generate_series(1, 100000); -- fail. +ERROR: tablespace: schemaspc, schema: spcs1 diskquota exceeded +drop table s1.a, srole.b, spcs1.a, rolespcrole.b; +drop schema s1, srole, spcs1, rolespcrole; +drop tablespace rolespc; +drop tablespace schemaspc; +drop role u1, rolespcu1; diff --git a/upgrade_test/expected7/2.3_catalog.out b/upgrade_test/expected7/2.3_catalog.out new file mode 100644 index 00000000..016aecd9 --- /dev/null +++ b/upgrade_test/expected7/2.3_catalog.out @@ -0,0 +1,308 @@ +CREATE FUNCTION typeid_to_name(oid[]) RETURNS name[] AS ' + WITH io AS ( + SELECT x.i AS index, x.o AS type_id FROM ( + SELECT generate_series(1, array_length($1, 1)) AS i, unnest($1) AS o + ) AS x + ) SELECT array_agg(typname order by io.index) FROM io, pg_type t WHERE io.type_id = t.oid; +' LANGUAGE sql STABLE; +-- types +SELECT + t1.typname, + array_agg(t2.typname order by a.atttypid) typname +FROM + pg_namespace n, + pg_class c, + pg_type t1, + pg_type t2, + pg_attribute a +WHERE + n.nspname = 'diskquota' + AND c.oid = t1.typrelid + AND n.oid = t1.typnamespace + AND a.attrelid = c.oid + AND t2.oid = a.atttypid +GROUP BY + t1.typname +ORDER BY + t1.typname; + typname | typname +----------------------------------------+------------------------------------------------------- + diskquota_active_table_type | {int8,int2,oid} + quota_config | {int8,int4,int4,oid,oid,tid,xid,xid,cid,cid,float4} + rejectmap | {bool,int4,text,oid,oid,oid,oid,oid,oid} + rejectmap_entry | {bool,int4,oid,oid,oid} + rejectmap_entry_detail | {bool,int4,text,oid,oid,oid,oid,oid,oid} + relation_cache_detail | {char,int4,int4,oid,oid,oid,oid,oid,oid,oid,oid,_oid} + show_all_relation_view | {oid,oid,oid,oid} + show_fast_database_size_view | {numeric} + show_fast_role_quota_view | {name,int8,oid,numeric} + show_fast_role_tablespace_quota_view | {name,name,int8,oid,oid,numeric} + show_fast_schema_quota_view | {name,int8,oid,numeric} + show_fast_schema_tablespace_quota_view | {name,name,int8,oid,oid,numeric} + show_segment_ratio_quota_view | {name,oid,float4} + state | {int4,int4,oid,tid,xid,xid,cid,cid} + table_size | {int8,int2,int4,oid,oid,tid,xid,xid,cid,cid} + target | {int4,int4,int4,oid,oid,oid,tid,xid,xid,cid,cid} +(16 rows) + +-- types end +-- tables +SELECT + relname, + typeid_to_name(ARRAY[c.reltype]::oid[]) as reltype, + typeid_to_name(ARRAY[c.reloftype]::oid[]) as reloftype +FROM + pg_class c, + pg_namespace n +WHERE + c.relnamespace = n.oid + AND n.nspname = 'diskquota' + and c.relkind != 'v' +ORDER BY + relname; + relname | reltype | reloftype +-----------------------------+-------------------------------+----------- + diskquota_active_table_type | {diskquota_active_table_type} | + quota_config | {quota_config} | + quota_config_pkey | | + rejectmap_entry | {rejectmap_entry} | + rejectmap_entry_detail | {rejectmap_entry_detail} | + relation_cache_detail | {relation_cache_detail} | + state | {state} | + state_pkey | | + table_size | {table_size} | + table_size_pkey | | + target | {target} | + target_pkey | | + target_rowid_seq | | +(13 rows) + +-- tables end +-- UDF +SELECT + proname, + typeid_to_name(ARRAY[prorettype]::oid[]) as prorettype, + typeid_to_name(proargtypes) as proargtypes, + typeid_to_name(proallargtypes) as proallargtypes, + proargmodes, + prosrc, + probin, + proacl +FROM + pg_namespace n, + pg_proc p +WHERE + n.nspname = 'diskquota' + AND n.oid = p.pronamespace + AND p.proname != 'update_diskquota_db_list' -- update_diskquota_db_list in 1.0 can not be dropd, this is acceptable +ORDER BY + proname; + proname | prorettype | proargtypes | proallargtypes | proargmodes | prosrc | probin | proacl +-----------------------------+-------------------------------+-------------------------+-----------------+-------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------+-------- + diskquota_fetch_table_stat | {diskquota_active_table_type} | {int4,_oid} | | | diskquota_fetch_table_stat | $libdir/diskquota-2.3.so | + init_table_size_table | {void} | | | | init_table_size_table | $libdir/diskquota-2.3.so | + pause | {void} | | | | diskquota_pause | $libdir/diskquota-2.3.so | + pull_all_table_size | {record} | | {oid,int8,int2} | {o,o,o} | pull_all_table_size | $libdir/diskquota-2.3.so | + refresh_rejectmap | {void} | {_rejectmap_entry,_oid} | | | refresh_rejectmap | $libdir/diskquota-2.3.so | + relation_size | {int8} | {regclass} | | | +| | + | | | | | SELECT SUM(size)::bigint FROM ( +| | + | | | | | SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, +| | + | | | | | CASE WHEN EXISTS +| | + | | | | | (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END,+| | + | | | | | relam) AS size +| | + | | | | | FROM gp_dist_random('pg_class') as relstorage WHERE oid = relation +| | + | | | | | UNION ALL +| | + | | | | | SELECT diskquota.relation_size_local(reltablespace, relfilenode, relpersistence, +| | + | | | | | CASE WHEN EXISTS +| | + | | | | | (SELECT FROM pg_catalog.pg_attribute WHERE attrelid = 'pg_class'::regclass AND attname = 'relstorage') THEN relstorage::"char" ELSE ''::"char" END,+| | + | | | | | relam) AS size +| | + | | | | | FROM pg_class as relstorage WHERE oid = relation +| | + | | | | | ) AS t | | + relation_size_local | {int8} | {oid,oid,char,char,oid} | | | relation_size_local | $libdir/diskquota-2.3.so | + resume | {void} | | | | diskquota_resume | $libdir/diskquota-2.3.so | + set_per_segment_quota | {void} | {text,float4} | | | set_per_segment_quota | $libdir/diskquota-2.3.so | + set_role_quota | {void} | {text,text} | | | set_role_quota | $libdir/diskquota-2.3.so | + set_role_tablespace_quota | {void} | {text,text,text} | | | set_role_tablespace_quota | $libdir/diskquota-2.3.so | + set_schema_quota | {void} | {text,text} | | | set_schema_quota | $libdir/diskquota-2.3.so | + set_schema_tablespace_quota | {void} | {text,text,text} | | | set_schema_tablespace_quota | $libdir/diskquota-2.3.so | + show_rejectmap | {rejectmap_entry_detail} | | | | show_rejectmap | $libdir/diskquota-2.3.so | + show_relation_cache | {relation_cache_detail} | | | | show_relation_cache | $libdir/diskquota-2.3.so | + show_relation_cache_all_seg | {relation_cache_detail} | | | | +| | + | | | | | WITH relation_cache AS ( +| | + | | | | | SELECT diskquota.show_relation_cache() AS a +| | + | | | | | FROM gp_dist_random('gp_id') +| | + | | | | | ) +| | + | | | | | SELECT (a).* FROM relation_cache; | | + show_worker_epoch | {int8} | | | | show_worker_epoch | $libdir/diskquota-2.3.so | + status | {record} | | {text,text} | {t,t} | diskquota_status | $libdir/diskquota-2.3.so | + wait_for_worker_new_epoch | {bool} | | | | wait_for_worker_new_epoch | $libdir/diskquota-2.3.so | +(19 rows) + +-- UDF end +-- views +SELECT + schemaname, + viewname, + definition +FROM + pg_views +WHERE + schemaname = 'diskquota' +ORDER by + schemaname, viewname; + schemaname | viewname | definition +------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + diskquota | rejectmap | SELECT bm.target_type, + + | | bm.target_oid, + + | | bm.database_oid, + + | | bm.tablespace_oid, + + | | bm.seg_exceeded, + + | | bm.dbnode, + + | | bm.spcnode, + + | | bm.relnode, + + | | bm.segid + + | | FROM diskquota.show_rejectmap() bm(target_type, target_oid, database_oid, tablespace_oid, seg_exceeded, dbnode, spcnode, relnode, segid); + diskquota | show_all_relation_view | WITH relation_cache AS ( + + | | SELECT f.relid, + + | | f.primary_table_oid, + + | | f.auxrel_num, + + | | f.owneroid, + + | | f.namespaceoid, + + | | f.backendid, + + | | f.spcnode, + + | | f.dbnode, + + | | f.relnode, + + | | f.relstorage, + + | | f.auxrel_oid, + + | | f.relam + + | | FROM diskquota.show_relation_cache() f(relid, primary_table_oid, auxrel_num, owneroid, namespaceoid, backendid, spcnode, dbnode, relnode, relstorage, auxrel_oid, relam)+ + | | ) + + | | SELECT DISTINCT union_relation.oid, + + | | union_relation.relowner, + + | | union_relation.relnamespace, + + | | union_relation.reltablespace + + | | FROM ( SELECT relation_cache.relid AS oid, + + | | relation_cache.owneroid AS relowner, + + | | relation_cache.namespaceoid AS relnamespace, + + | | relation_cache.spcnode AS reltablespace + + | | FROM relation_cache + + | | UNION + + | | SELECT pg_class.oid, + + | | pg_class.relowner, + + | | pg_class.relnamespace, + + | | pg_class.reltablespace + + | | FROM pg_class) union_relation; + diskquota | show_fast_database_size_view | SELECT (( SELECT sum(pg_relation_size((pg_class.oid)::regclass)) AS sum + + | | FROM pg_class + + | | WHERE (pg_class.oid <= (16384)::oid)) + ( SELECT sum(table_size.size) AS sum + + | | FROM diskquota.table_size + + | | WHERE (table_size.segid = '-1'::integer))) AS dbsize; + diskquota | show_fast_role_quota_view | WITH quota_usage AS ( + + | | SELECT show_all_relation_view.relowner, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relowner + + | | ) + + | | SELECT pg_roles.rolname AS role_name, + + | | quota_config.targetoid AS role_oid, + + | | quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS rolsize_in_bytes + + | | FROM ((diskquota.quota_config + + | | JOIN pg_roles ON ((quota_config.targetoid = pg_roles.oid))) + + | | LEFT JOIN quota_usage ON ((pg_roles.oid = quota_usage.relowner))) + + | | WHERE (quota_config.quotatype = 1); + diskquota | show_fast_role_tablespace_quota_view | WITH default_tablespace AS ( + + | | SELECT pg_database.dattablespace + + | | FROM pg_database + + | | WHERE (pg_database.datname = current_database()) + + | | ), quota_usage AS ( + + | | SELECT show_all_relation_view.relowner, + + | | CASE + + | | WHEN (show_all_relation_view.reltablespace = (0)::oid) THEN default_tablespace.dattablespace + + | | ELSE show_all_relation_view.reltablespace + + | | END AS reltablespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view, + + | | default_tablespace + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relowner, show_all_relation_view.reltablespace, default_tablespace.dattablespace + + | | ), full_quota_config AS ( + + | | SELECT target.primaryoid, + + | | target.tablespaceoid, + + | | config.quotalimitmb + + | | FROM diskquota.quota_config config, + + | | diskquota.target target + + | | WHERE ((config.targetoid = (target.rowid)::oid) AND (config.quotatype = target.quotatype) AND (config.quotatype = 3)) + + | | ) + + | | SELECT pg_roles.rolname AS role_name, + + | | full_quota_config.primaryoid AS role_oid, + + | | pg_tablespace.spcname AS tablespace_name, + + | | full_quota_config.tablespaceoid AS tablespace_oid, + + | | full_quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS rolsize_tablespace_in_bytes + + | | FROM (((full_quota_config + + | | JOIN pg_roles ON ((full_quota_config.primaryoid = pg_roles.oid))) + + | | JOIN pg_tablespace ON ((full_quota_config.tablespaceoid = pg_tablespace.oid))) + + | | LEFT JOIN quota_usage ON (((pg_roles.oid = quota_usage.relowner) AND (pg_tablespace.oid = quota_usage.reltablespace)))); + diskquota | show_fast_schema_quota_view | WITH quota_usage AS ( + + | | SELECT show_all_relation_view.relnamespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relnamespace + + | | ) + + | | SELECT pg_namespace.nspname AS schema_name, + + | | quota_config.targetoid AS schema_oid, + + | | quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS nspsize_in_bytes + + | | FROM ((diskquota.quota_config + + | | JOIN pg_namespace ON ((quota_config.targetoid = pg_namespace.oid))) + + | | LEFT JOIN quota_usage ON ((pg_namespace.oid = quota_usage.relnamespace))) + + | | WHERE (quota_config.quotatype = 0); + diskquota | show_fast_schema_tablespace_quota_view | WITH default_tablespace AS ( + + | | SELECT pg_database.dattablespace + + | | FROM pg_database + + | | WHERE (pg_database.datname = current_database()) + + | | ), quota_usage AS ( + + | | SELECT show_all_relation_view.relnamespace, + + | | CASE + + | | WHEN (show_all_relation_view.reltablespace = (0)::oid) THEN default_tablespace.dattablespace + + | | ELSE show_all_relation_view.reltablespace + + | | END AS reltablespace, + + | | sum(table_size.size) AS total_size + + | | FROM diskquota.table_size, + + | | diskquota.show_all_relation_view, + + | | default_tablespace + + | | WHERE ((table_size.tableid = show_all_relation_view.oid) AND (table_size.segid = '-1'::integer)) + + | | GROUP BY show_all_relation_view.relnamespace, show_all_relation_view.reltablespace, default_tablespace.dattablespace + + | | ), full_quota_config AS ( + + | | SELECT target.primaryoid, + + | | target.tablespaceoid, + + | | config.quotalimitmb + + | | FROM diskquota.quota_config config, + + | | diskquota.target target + + | | WHERE ((config.targetoid = (target.rowid)::oid) AND (config.quotatype = target.quotatype) AND (config.quotatype = 2)) + + | | ) + + | | SELECT pg_namespace.nspname AS schema_name, + + | | full_quota_config.primaryoid AS schema_oid, + + | | pg_tablespace.spcname AS tablespace_name, + + | | full_quota_config.tablespaceoid AS tablespace_oid, + + | | full_quota_config.quotalimitmb AS quota_in_mb, + + | | COALESCE(quota_usage.total_size, (0)::numeric) AS nspsize_tablespace_in_bytes + + | | FROM (((full_quota_config + + | | JOIN pg_namespace ON ((full_quota_config.primaryoid = pg_namespace.oid))) + + | | JOIN pg_tablespace ON ((full_quota_config.tablespaceoid = pg_tablespace.oid))) + + | | LEFT JOIN quota_usage ON (((pg_namespace.oid = quota_usage.relnamespace) AND (pg_tablespace.oid = quota_usage.reltablespace)))); + diskquota | show_segment_ratio_quota_view | SELECT pg_tablespace.spcname AS tablespace_name, + + | | pg_tablespace.oid AS tablespace_oid, + + | | quota_config.segratio AS per_seg_quota_ratio + + | | FROM (diskquota.quota_config + + | | JOIN pg_tablespace ON (((quota_config.targetoid = pg_tablespace.oid) AND (quota_config.quotatype = 4)))); +(8 rows) + +-- views end +DROP FUNCTION typeid_to_name (oid[]); diff --git a/upgrade_test/expected7/2.3_cleanup_quota.out b/upgrade_test/expected7/2.3_cleanup_quota.out new file mode 100644 index 00000000..3935d709 --- /dev/null +++ b/upgrade_test/expected7/2.3_cleanup_quota.out @@ -0,0 +1 @@ +drop extension diskquota; diff --git a/upgrade_test/expected7/2.3_install.out b/upgrade_test/expected7/2.3_install.out new file mode 100644 index 00000000..4738c064 --- /dev/null +++ b/upgrade_test/expected7/2.3_install.out @@ -0,0 +1,13 @@ +-- cleanup previous diskquota installation +\! gpconfig -c shared_preload_libraries -v '' > /dev/null +\! gpstop -raf > /dev/null +\! dropdb --if-exists diskquota +-- TODO reset all diskquota GUC +\! gpstop -raf > /dev/null +-- setup basic environment +\! createdb diskquota +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.3.so' > /dev/null +\! gpstop -raf > /dev/null +-- TODO setup GUC +\! gpconfig -c diskquota.naptime -v '1' > /dev/null +\! gpstop -raf > /dev/null diff --git a/upgrade_test/expected7/2.3_migrate_to_version_2.3.out b/upgrade_test/expected7/2.3_migrate_to_version_2.3.out new file mode 100644 index 00000000..db67a0e3 --- /dev/null +++ b/upgrade_test/expected7/2.3_migrate_to_version_2.3.out @@ -0,0 +1,10 @@ +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.3.so' > /dev/null +\! gpstop -raf > /dev/null +\! gpconfig -s 'shared_preload_libraries' +Values on all segments are consistent +GUC : shared_preload_libraries +Coordinator value: diskquota-2.3.so +Segment value: diskquota-2.3.so +\c +alter extension diskquota update to '2.3'; +\! sleep 5 diff --git a/upgrade_test/expected7/2.3_set_quota.out b/upgrade_test/expected7/2.3_set_quota.out new file mode 100644 index 00000000..114f346d --- /dev/null +++ b/upgrade_test/expected7/2.3_set_quota.out @@ -0,0 +1,66 @@ +\!gpconfig -s 'shared_preload_libraries' +Values on all segments are consistent +GUC : shared_preload_libraries +Coordinator value: diskquota-2.3.so +Segment value: diskquota-2.3.so +create extension diskquota with version '2.3'; +select diskquota.wait_for_worker_new_epoch(); + wait_for_worker_new_epoch +--------------------------- + t +(1 row) + +-- schema quota +create schema s1; +select diskquota.set_schema_quota('s1', '1 MB'); + set_schema_quota +------------------ + +(1 row) + +create table s1.a(i int) distributed by (i); +insert into s1.a select generate_series(1, 10000000); -- ok. +-- role quota +create schema srole; +create role u1 nologin; +create table srole.b (t text) distributed by (t); +alter table srole.b owner to u1; +select diskquota.set_role_quota('u1', '1 MB'); + set_role_quota +---------------- + +(1 row) + +insert into srole.b select generate_series(1,100000); -- ok. +-- schema tablespace quota +\! mkdir -p /tmp/schemaspc +create schema spcs1; +create tablespace schemaspc location '/tmp/schemaspc'; +select diskquota.set_schema_tablespace_quota('spcs1', 'schemaspc','1 MB'); + set_schema_tablespace_quota +----------------------------- + +(1 row) + +create table spcs1.a(i int) tablespace schemaspc distributed by (i); +insert into spcs1.a select generate_series(1,100000); -- ok. +-- role tablespace quota +\! mkdir -p /tmp/rolespc +create tablespace rolespc location '/tmp/rolespc'; +create role rolespcu1 nologin; +create schema rolespcrole; +create table rolespcrole.b (t text) tablespace rolespc distributed by (t); +alter table rolespcrole.b owner to rolespcu1; +select diskquota.set_role_tablespace_quota('rolespcu1', 'rolespc', '1 MB'); + set_role_tablespace_quota +--------------------------- + +(1 row) + +insert into rolespcrole.b select generate_series(1,100000); -- ok. +\!sleep 5 +-- leaked resource: +-- role u1, rolespcu1 +-- table s1.a, srole.b spcs1.a, rolespcrole.b +-- schema s1, srole, spcs1, rolespcrole +-- tablespace schemaspc, rolespc diff --git a/upgrade_test/expected7/2.3_test_in_2.2_quota_create_in_2.3.out b/upgrade_test/expected7/2.3_test_in_2.2_quota_create_in_2.3.out new file mode 100644 index 00000000..71c24e58 --- /dev/null +++ b/upgrade_test/expected7/2.3_test_in_2.2_quota_create_in_2.3.out @@ -0,0 +1,16 @@ +-- need run 2.2_set_quota before run this test +-- FIXME add version check here +\! sleep 5 +insert into s1.a select generate_series(1, 10000000); -- fail. +ERROR: schema's disk space quota exceeded with name: s1 +insert into srole.b select generate_series(1, 100000); -- fail. +ERROR: role's disk space quota exceeded with name: u1 +insert into rolespcrole.b select generate_series(1, 100000); -- fail. +ERROR: tablespace: rolespc, role: rolespcu1 diskquota exceeded +insert into spcs1.a select generate_series(1, 100000); -- fail. +ERROR: tablespace: schemaspc, schema: spcs1 diskquota exceeded +drop table s1.a, srole.b, spcs1.a, rolespcrole.b; +drop schema s1, srole, spcs1, rolespcrole; +drop tablespace rolespc; +drop tablespace schemaspc; +drop role u1, rolespcu1; diff --git a/upgrade_test/schedule_2.2--2.3 b/upgrade_test/schedule_2.2--2.3 new file mode 100644 index 00000000..48677583 --- /dev/null +++ b/upgrade_test/schedule_2.2--2.3 @@ -0,0 +1,8 @@ +test: 2.2_install +test: 2.2_set_quota +test: 2.2_catalog +test: 2.3_migrate_to_version_2.3 +test: 2.3_catalog +# run 2.2 behavior test using 2.3 DDL and binary +test: 2.2_test_in_2.3_quota_create_in_2.2 +test: 2.2_cleanup_quota diff --git a/upgrade_test/schedule_2.3--2.2 b/upgrade_test/schedule_2.3--2.2 new file mode 100644 index 00000000..0de828c9 --- /dev/null +++ b/upgrade_test/schedule_2.3--2.2 @@ -0,0 +1,8 @@ +test: 2.3_install +test: 2.3_set_quota +test: 2.3_catalog +test: 2.2_migrate_to_version_2.2 +test: 2.2_catalog +# run 2.3 behavior test using 2.2 DDL and binary +test: 2.3_test_in_2.2_quota_create_in_2.3 +test: 2.3_cleanup_quota diff --git a/upgrade_test/sql/2.2_set_quota.sql b/upgrade_test/sql/2.2_set_quota.sql index adaf8707..8ccb3a80 100644 --- a/upgrade_test/sql/2.2_set_quota.sql +++ b/upgrade_test/sql/2.2_set_quota.sql @@ -1,7 +1,8 @@ \!gpconfig -s 'shared_preload_libraries' create extension diskquota with version '2.2'; -\!sleep 5 +select diskquota.init_table_size_table(); +select diskquota.wait_for_worker_new_epoch(); -- schema quota create schema s1; diff --git a/upgrade_test/sql/2.2_test_in_2.3_quota_create_in_2.2.sql b/upgrade_test/sql/2.2_test_in_2.3_quota_create_in_2.2.sql new file mode 100644 index 00000000..e67027c7 --- /dev/null +++ b/upgrade_test/sql/2.2_test_in_2.3_quota_create_in_2.2.sql @@ -0,0 +1,16 @@ +-- need run 2.3_set_quota before run this test +-- FIXME add version check here + +\! sleep 5 + +insert into s1.a select generate_series(1, 10000000); -- fail. +insert into srole.b select generate_series(1, 100000); -- fail. + +insert into rolespcrole.b select generate_series(1, 100000); -- fail. +insert into spcs1.a select generate_series(1, 100000); -- fail. + +drop table s1.a, srole.b, spcs1.a, rolespcrole.b; +drop schema s1, srole, spcs1, rolespcrole; +drop tablespace rolespc; +drop tablespace schemaspc; +drop role u1, rolespcu1; diff --git a/upgrade_test/sql/2.3_catalog.sql b/upgrade_test/sql/2.3_catalog.sql new file mode 100644 index 00000000..ebf5f00a --- /dev/null +++ b/upgrade_test/sql/2.3_catalog.sql @@ -0,0 +1,81 @@ +CREATE FUNCTION typeid_to_name(oid[]) RETURNS name[] AS ' + WITH io AS ( + SELECT x.i AS index, x.o AS type_id FROM ( + SELECT generate_series(1, array_length($1, 1)) AS i, unnest($1) AS o + ) AS x + ) SELECT array_agg(typname order by io.index) FROM io, pg_type t WHERE io.type_id = t.oid; +' LANGUAGE sql STABLE; + +-- types +SELECT + t1.typname, + array_agg(t2.typname order by a.atttypid) typname +FROM + pg_namespace n, + pg_class c, + pg_type t1, + pg_type t2, + pg_attribute a +WHERE + n.nspname = 'diskquota' + AND c.oid = t1.typrelid + AND n.oid = t1.typnamespace + AND a.attrelid = c.oid + AND t2.oid = a.atttypid +GROUP BY + t1.typname +ORDER BY + t1.typname; +-- types end + +-- tables +SELECT + relname, + typeid_to_name(ARRAY[c.reltype]::oid[]) as reltype, + typeid_to_name(ARRAY[c.reloftype]::oid[]) as reloftype +FROM + pg_class c, + pg_namespace n +WHERE + c.relnamespace = n.oid + AND n.nspname = 'diskquota' + and c.relkind != 'v' +ORDER BY + relname; +-- tables end + +-- UDF +SELECT + proname, + typeid_to_name(ARRAY[prorettype]::oid[]) as prorettype, + typeid_to_name(proargtypes) as proargtypes, + typeid_to_name(proallargtypes) as proallargtypes, + proargmodes, + prosrc, + probin, + proacl +FROM + pg_namespace n, + pg_proc p +WHERE + n.nspname = 'diskquota' + AND n.oid = p.pronamespace + AND p.proname != 'update_diskquota_db_list' -- update_diskquota_db_list in 1.0 can not be dropd, this is acceptable +ORDER BY + proname; +-- UDF end + +-- views +SELECT + schemaname, + viewname, + definition +FROM + pg_views +WHERE + schemaname = 'diskquota' +ORDER by + schemaname, viewname; +-- views end + +DROP FUNCTION typeid_to_name (oid[]); diff --git a/upgrade_test/sql/2.3_cleanup_quota.sql b/upgrade_test/sql/2.3_cleanup_quota.sql new file mode 100644 index 00000000..3935d709 --- /dev/null +++ b/upgrade_test/sql/2.3_cleanup_quota.sql @@ -0,0 +1 @@ +drop extension diskquota; diff --git a/upgrade_test/sql/2.3_install.sql b/upgrade_test/sql/2.3_install.sql new file mode 100644 index 00000000..03020f08 --- /dev/null +++ b/upgrade_test/sql/2.3_install.sql @@ -0,0 +1,17 @@ +-- cleanup previous diskquota installation +\! gpconfig -c shared_preload_libraries -v '' > /dev/null +\! gpstop -raf > /dev/null +\! dropdb --if-exists diskquota + +-- TODO reset all diskquota GUC +\! gpstop -raf > /dev/null + +-- setup basic environment +\! createdb diskquota + +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.3.so' > /dev/null +\! gpstop -raf > /dev/null + +-- TODO setup GUC +\! gpconfig -c diskquota.naptime -v '1' > /dev/null +\! gpstop -raf > /dev/null diff --git a/upgrade_test/sql/2.3_migrate_to_version_2.3.sql b/upgrade_test/sql/2.3_migrate_to_version_2.3.sql new file mode 100644 index 00000000..f6ce2141 --- /dev/null +++ b/upgrade_test/sql/2.3_migrate_to_version_2.3.sql @@ -0,0 +1,8 @@ +\! gpconfig -c shared_preload_libraries -v 'diskquota-2.3.so' > /dev/null +\! gpstop -raf > /dev/null + +\! gpconfig -s 'shared_preload_libraries' + +\c +alter extension diskquota update to '2.3'; +\! sleep 5 diff --git a/upgrade_test/sql/2.3_set_quota.sql b/upgrade_test/sql/2.3_set_quota.sql new file mode 100644 index 00000000..48284155 --- /dev/null +++ b/upgrade_test/sql/2.3_set_quota.sql @@ -0,0 +1,44 @@ +\!gpconfig -s 'shared_preload_libraries' + +create extension diskquota with version '2.3'; +select diskquota.wait_for_worker_new_epoch(); + +-- schema quota +create schema s1; +select diskquota.set_schema_quota('s1', '1 MB'); +create table s1.a(i int) distributed by (i); +insert into s1.a select generate_series(1, 10000000); -- ok. + +-- role quota +create schema srole; +create role u1 nologin; +create table srole.b (t text) distributed by (t); +alter table srole.b owner to u1; +select diskquota.set_role_quota('u1', '1 MB'); +insert into srole.b select generate_series(1,100000); -- ok. + +-- schema tablespace quota +\! mkdir -p /tmp/schemaspc +create schema spcs1; +create tablespace schemaspc location '/tmp/schemaspc'; +select diskquota.set_schema_tablespace_quota('spcs1', 'schemaspc','1 MB'); +create table spcs1.a(i int) tablespace schemaspc distributed by (i); +insert into spcs1.a select generate_series(1,100000); -- ok. + +-- role tablespace quota +\! mkdir -p /tmp/rolespc +create tablespace rolespc location '/tmp/rolespc'; +create role rolespcu1 nologin; +create schema rolespcrole; +create table rolespcrole.b (t text) tablespace rolespc distributed by (t); +alter table rolespcrole.b owner to rolespcu1; +select diskquota.set_role_tablespace_quota('rolespcu1', 'rolespc', '1 MB'); +insert into rolespcrole.b select generate_series(1,100000); -- ok. + +\!sleep 5 + +-- leaked resource: +-- role u1, rolespcu1 +-- table s1.a, srole.b spcs1.a, rolespcrole.b +-- schema s1, srole, spcs1, rolespcrole +-- tablespace schemaspc, rolespc diff --git a/upgrade_test/sql/2.3_test_in_2.2_quota_create_in_2.3.sql b/upgrade_test/sql/2.3_test_in_2.2_quota_create_in_2.3.sql new file mode 100644 index 00000000..4a599cfb --- /dev/null +++ b/upgrade_test/sql/2.3_test_in_2.2_quota_create_in_2.3.sql @@ -0,0 +1,16 @@ +-- need run 2.2_set_quota before run this test +-- FIXME add version check here + +\! sleep 5 + +insert into s1.a select generate_series(1, 10000000); -- fail. +insert into srole.b select generate_series(1, 100000); -- fail. + +insert into rolespcrole.b select generate_series(1, 100000); -- fail. +insert into spcs1.a select generate_series(1, 100000); -- fail. + +drop table s1.a, srole.b, spcs1.a, rolespcrole.b; +drop schema s1, srole, spcs1, rolespcrole; +drop tablespace rolespc; +drop tablespace schemaspc; +drop role u1, rolespcu1;