diff --strip-trailing-cr -U3 C:/cirrus/src/test/regress/expected/brin.out C:/cirrus/build/testrun/regress/regress/results/brin.out --- C:/cirrus/src/test/regress/expected/brin.out 2024-12-13 13:18:31.344091800 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/brin.out 2024-12-13 13:21:25.283060600 +0000 @@ -539,53 +539,10 @@ -- vacuum actually removes the TOAST rows. Creating an index concurrently -- is a one way to achieve that, because it does exactly such wait. CREATE INDEX CONCURRENTLY brin_test_temp_idx ON brintest_3(a); -DROP INDEX brin_test_temp_idx; --- vacuum the table, to discard TOAST data -VACUUM brintest_3; --- retry insert with a different random-looking (but deterministic) value --- the value is different, and so should replace either min or max in the --- brin summary -WITH rand_value AS (SELECT string_agg(fipshash((-i)::text),'') AS val FROM generate_series(1,60) s(i)) -INSERT INTO brintest_3 -SELECT val, val, val, val FROM rand_value; --- now try some queries, accessing the brin index -SET enable_seqscan = off; -EXPLAIN (COSTS OFF) -SELECT * FROM brintest_3 WHERE b < '0'; - QUERY PLAN ------------------------------------------------- - Bitmap Heap Scan on brintest_3 - Recheck Cond: (b < '0'::text) - -> Bitmap Index Scan on brin_test_toast_idx - Index Cond: (b < '0'::text) -(4 rows) - -SELECT * FROM brintest_3 WHERE b < '0'; - a | b | c | d ----+---+---+--- -(0 rows) - -DROP TABLE brintest_3; -RESET enable_seqscan; --- test parallel build with immutable function. -CREATE TABLE brintest_expr (n int); -CREATE FUNCTION brintest_func() RETURNS int LANGUAGE sql IMMUTABLE RETURN 0; -BEGIN; -SET LOCAL min_parallel_table_scan_size = 0; -SET LOCAL max_parallel_maintenance_workers = 4; -CREATE INDEX brintest_expr_idx ON brintest_expr USING brin (brintest_func()); -COMMIT; -DROP TABLE brintest_expr; -DROP FUNCTION brintest_func(); --- test an unlogged table, mostly to get coverage of brinbuildempty -CREATE UNLOGGED TABLE brintest_unlogged (n numrange); -CREATE INDEX brinidx_unlogged ON brintest_unlogged USING brin (n); -INSERT INTO brintest_unlogged VALUES (numrange(0, 2^1000::numeric)); -DROP TABLE brintest_unlogged; --- test that the insert optimization works if no rows end up inserted -CREATE TABLE brin_insert_optimization (a int); -INSERT INTO brin_insert_optimization VALUES (1); -CREATE INDEX brin_insert_optimization_idx ON brin_insert_optimization USING brin (a); -UPDATE brin_insert_optimization SET a = a; -REINDEX INDEX CONCURRENTLY brin_insert_optimization_idx; -DROP TABLE brin_insert_optimization; +WARNING: terminating connection because of crash of another server process +DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory. +HINT: In a moment you should be able to reconnect to the database and repeat your command. +server closed the connection unexpectedly + This probably means the server terminated abnormally + before or while processing the request. +connection to server was lost diff --strip-trailing-cr -U3 C:/cirrus/src/test/regress/expected/privileges.out C:/cirrus/build/testrun/regress/regress/results/privileges.out --- C:/cirrus/src/test/regress/expected/privileges.out 2024-12-13 13:18:31.474932500 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/privileges.out 2024-12-13 13:21:25.283060600 +0000 @@ -1842,1417 +1842,10 @@ -- Do the same concurrently CREATE INDEX CONCURRENTLY sro_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0))) WHERE sro_ifun(a + 10) > sro_ifun(10); --- REINDEX -REINDEX TABLE sro_tab; -REINDEX INDEX sro_idx; -REINDEX TABLE CONCURRENTLY sro_tab; -DROP INDEX sro_idx; --- CLUSTER -CREATE INDEX sro_cluster_idx ON sro_tab ((sro_ifun(a) + sro_ifun(0))); -CLUSTER sro_tab USING sro_cluster_idx; -DROP INDEX sro_cluster_idx; --- BRIN index -CREATE INDEX sro_brin ON sro_tab USING brin ((sro_ifun(a) + sro_ifun(0))); -SELECT brin_desummarize_range('sro_brin', 0); - brin_desummarize_range ------------------------- - -(1 row) - -SELECT brin_summarize_range('sro_brin', 0); - brin_summarize_range ----------------------- - 1 -(1 row) - -DROP TABLE sro_tab; --- Check with a partitioned table -CREATE TABLE sro_ptab (a int) PARTITION BY RANGE (a); -ALTER TABLE sro_ptab OWNER TO regress_sro_user; -CREATE TABLE sro_part PARTITION OF sro_ptab FOR VALUES FROM (1) TO (10); -ALTER TABLE sro_part OWNER TO regress_sro_user; -INSERT INTO sro_ptab VALUES (1), (2), (3); -CREATE INDEX sro_pidx ON sro_ptab ((sro_ifun(a) + sro_ifun(0))) - WHERE sro_ifun(a + 10) > sro_ifun(10); -REINDEX TABLE sro_ptab; -REINDEX INDEX CONCURRENTLY sro_pidx; -SET SESSION AUTHORIZATION regress_sro_user; -CREATE FUNCTION unwanted_grant() RETURNS void LANGUAGE sql AS - 'GRANT regress_priv_group2 TO regress_sro_user'; -CREATE FUNCTION mv_action() RETURNS bool LANGUAGE sql AS - 'DECLARE c CURSOR WITH HOLD FOR SELECT public.unwanted_grant(); SELECT true'; --- REFRESH of this MV will queue a GRANT at end of transaction -CREATE MATERIALIZED VIEW sro_mv AS SELECT mv_action() WITH NO DATA; -REFRESH MATERIALIZED VIEW sro_mv; -ERROR: cannot create a cursor WITH HOLD within security-restricted operation -CONTEXT: SQL function "mv_action" statement 1 -\c - -REFRESH MATERIALIZED VIEW sro_mv; -ERROR: cannot create a cursor WITH HOLD within security-restricted operation -CONTEXT: SQL function "mv_action" statement 1 -SET SESSION AUTHORIZATION regress_sro_user; --- INSERT to this table will queue a GRANT at end of transaction -CREATE TABLE sro_trojan_table (); -CREATE FUNCTION sro_trojan() RETURNS trigger LANGUAGE plpgsql AS - 'BEGIN PERFORM public.unwanted_grant(); RETURN NULL; END'; -CREATE CONSTRAINT TRIGGER t AFTER INSERT ON sro_trojan_table - INITIALLY DEFERRED FOR EACH ROW EXECUTE PROCEDURE sro_trojan(); --- Now, REFRESH will issue such an INSERT, queueing the GRANT -CREATE OR REPLACE FUNCTION mv_action() RETURNS bool LANGUAGE sql AS - 'INSERT INTO public.sro_trojan_table DEFAULT VALUES; SELECT true'; -REFRESH MATERIALIZED VIEW sro_mv; -ERROR: cannot fire deferred trigger within security-restricted operation -CONTEXT: SQL function "mv_action" statement 1 -\c - -REFRESH MATERIALIZED VIEW sro_mv; -ERROR: cannot fire deferred trigger within security-restricted operation -CONTEXT: SQL function "mv_action" statement 1 -BEGIN; SET CONSTRAINTS ALL IMMEDIATE; REFRESH MATERIALIZED VIEW sro_mv; COMMIT; -ERROR: permission denied to grant role "regress_priv_group2" -DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role. -CONTEXT: SQL function "unwanted_grant" statement 1 -SQL statement "SELECT public.unwanted_grant()" -PL/pgSQL function public.sro_trojan() line 1 at PERFORM -SQL function "mv_action" statement 1 --- REFRESH MATERIALIZED VIEW CONCURRENTLY use of eval_const_expressions() -SET SESSION AUTHORIZATION regress_sro_user; -CREATE FUNCTION unwanted_grant_nofail(int) RETURNS int - IMMUTABLE LANGUAGE plpgsql AS $$ -BEGIN - PERFORM public.unwanted_grant(); - RAISE WARNING 'owned'; - RETURN 1; -EXCEPTION WHEN OTHERS THEN - RETURN 2; -END$$; -CREATE MATERIALIZED VIEW sro_index_mv AS SELECT 1 AS c; -CREATE UNIQUE INDEX ON sro_index_mv (c) WHERE unwanted_grant_nofail(1) > 0; -\c - -REFRESH MATERIALIZED VIEW CONCURRENTLY sro_index_mv; -REFRESH MATERIALIZED VIEW sro_index_mv; -DROP OWNED BY regress_sro_user; -DROP ROLE regress_sro_user; --- Admin options -SET SESSION AUTHORIZATION regress_priv_user4; -CREATE FUNCTION dogrant_ok() RETURNS void LANGUAGE sql SECURITY DEFINER AS - 'GRANT regress_priv_group2 TO regress_priv_user5'; -GRANT regress_priv_group2 TO regress_priv_user5; -- ok: had ADMIN OPTION -SET ROLE regress_priv_group2; -GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE suspended privilege -ERROR: permission denied to grant role "regress_priv_group2" -DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role. -SET SESSION AUTHORIZATION regress_priv_user1; -GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no ADMIN OPTION -ERROR: permission denied to grant role "regress_priv_group2" -DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role. -SELECT dogrant_ok(); -- ok: SECURITY DEFINER conveys ADMIN -NOTICE: role "regress_priv_user5" has already been granted membership in role "regress_priv_group2" by role "regress_priv_user4" - dogrant_ok ------------- - -(1 row) - -SET ROLE regress_priv_group2; -GRANT regress_priv_group2 TO regress_priv_user5; -- fails: SET ROLE did not help -ERROR: permission denied to grant role "regress_priv_group2" -DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role. -SET SESSION AUTHORIZATION regress_priv_group2; -GRANT regress_priv_group2 TO regress_priv_user5; -- fails: no self-admin -ERROR: permission denied to grant role "regress_priv_group2" -DETAIL: Only roles with the ADMIN option on role "regress_priv_group2" may grant this role. -SET SESSION AUTHORIZATION regress_priv_user4; -DROP FUNCTION dogrant_ok(); -REVOKE regress_priv_group2 FROM regress_priv_user5; --- has_sequence_privilege tests -\c - -CREATE SEQUENCE x_seq; -GRANT USAGE on x_seq to regress_priv_user2; -SELECT has_sequence_privilege('regress_priv_user1', 'atest1', 'SELECT'); -ERROR: "atest1" is not a sequence -SELECT has_sequence_privilege('regress_priv_user1', 'x_seq', 'INSERT'); -ERROR: unrecognized privilege type: "INSERT" -SELECT has_sequence_privilege('regress_priv_user1', 'x_seq', 'SELECT'); - has_sequence_privilege ------------------------- - f -(1 row) - -SET SESSION AUTHORIZATION regress_priv_user2; -SELECT has_sequence_privilege('x_seq', 'USAGE'); - has_sequence_privilege ------------------------- - t -(1 row) - --- largeobject privilege tests -\c - -SET SESSION AUTHORIZATION regress_priv_user1; -SELECT lo_create(1001); - lo_create ------------ - 1001 -(1 row) - -SELECT lo_create(1002); - lo_create ------------ - 1002 -(1 row) - -SELECT lo_create(1003); - lo_create ------------ - 1003 -(1 row) - -SELECT lo_create(1004); - lo_create ------------ - 1004 -(1 row) - -SELECT lo_create(1005); - lo_create ------------ - 1005 -(1 row) - -GRANT ALL ON LARGE OBJECT 1001 TO PUBLIC; -GRANT SELECT ON LARGE OBJECT 1003 TO regress_priv_user2; -GRANT SELECT,UPDATE ON LARGE OBJECT 1004 TO regress_priv_user2; -GRANT ALL ON LARGE OBJECT 1005 TO regress_priv_user2; -GRANT SELECT ON LARGE OBJECT 1005 TO regress_priv_user2 WITH GRANT OPTION; -GRANT SELECT, INSERT ON LARGE OBJECT 1001 TO PUBLIC; -- to be failed -ERROR: invalid privilege type INSERT for large object -GRANT SELECT, UPDATE ON LARGE OBJECT 1001 TO nosuchuser; -- to be failed -ERROR: role "nosuchuser" does not exist -GRANT SELECT, UPDATE ON LARGE OBJECT 999 TO PUBLIC; -- to be failed -ERROR: large object 999 does not exist -\c - -SET SESSION AUTHORIZATION regress_priv_user2; -SELECT lo_create(2001); - lo_create ------------ - 2001 -(1 row) - -SELECT lo_create(2002); - lo_create ------------ - 2002 -(1 row) - -SELECT loread(lo_open(1001, x'20000'::int), 32); -- allowed, for now - loread --------- - \x -(1 row) - -SELECT lowrite(lo_open(1001, x'40000'::int), 'abcd'); -- fail, wrong mode -ERROR: large object descriptor 0 was not opened for writing -SELECT loread(lo_open(1001, x'40000'::int), 32); - loread --------- - \x -(1 row) - -SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied -ERROR: permission denied for large object 1002 -SELECT loread(lo_open(1003, x'40000'::int), 32); - loread --------- - \x -(1 row) - -SELECT loread(lo_open(1004, x'40000'::int), 32); - loread --------- - \x -(1 row) - -SELECT lowrite(lo_open(1001, x'20000'::int), 'abcd'); - lowrite ---------- - 4 -(1 row) - -SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied -ERROR: permission denied for large object 1002 -SELECT lowrite(lo_open(1003, x'20000'::int), 'abcd'); -- to be denied -ERROR: permission denied for large object 1003 -SELECT lowrite(lo_open(1004, x'20000'::int), 'abcd'); - lowrite ---------- - 4 -(1 row) - -GRANT SELECT ON LARGE OBJECT 1005 TO regress_priv_user3; -GRANT UPDATE ON LARGE OBJECT 1006 TO regress_priv_user3; -- to be denied -ERROR: large object 1006 does not exist -REVOKE ALL ON LARGE OBJECT 2001, 2002 FROM PUBLIC; -GRANT ALL ON LARGE OBJECT 2001 TO regress_priv_user3; -SELECT lo_unlink(1001); -- to be denied -ERROR: must be owner of large object 1001 -SELECT lo_unlink(2002); - lo_unlink ------------ - 1 -(1 row) - -\c - --- confirm ACL setting -SELECT oid, pg_get_userbyid(lomowner) ownername, lomacl FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; - oid | ownername | lomacl -------+--------------------+------------------------------------------------------------------------------------------------------------------------------ - 1001 | regress_priv_user1 | {regress_priv_user1=rw/regress_priv_user1,=rw/regress_priv_user1} - 1002 | regress_priv_user1 | - 1003 | regress_priv_user1 | {regress_priv_user1=rw/regress_priv_user1,regress_priv_user2=r/regress_priv_user1} - 1004 | regress_priv_user1 | {regress_priv_user1=rw/regress_priv_user1,regress_priv_user2=rw/regress_priv_user1} - 1005 | regress_priv_user1 | {regress_priv_user1=rw/regress_priv_user1,regress_priv_user2=r*w/regress_priv_user1,regress_priv_user3=r/regress_priv_user2} - 2001 | regress_priv_user2 | {regress_priv_user2=rw/regress_priv_user2,regress_priv_user3=rw/regress_priv_user2} -(6 rows) - -SET SESSION AUTHORIZATION regress_priv_user3; -SELECT loread(lo_open(1001, x'40000'::int), 32); - loread ------------- - \x61626364 -(1 row) - -SELECT loread(lo_open(1003, x'40000'::int), 32); -- to be denied -ERROR: permission denied for large object 1003 -SELECT loread(lo_open(1005, x'40000'::int), 32); - loread --------- - \x -(1 row) - -SELECT lo_truncate(lo_open(1005, x'20000'::int), 10); -- to be denied -ERROR: permission denied for large object 1005 -SELECT lo_truncate(lo_open(2001, x'20000'::int), 10); - lo_truncate -------------- - 0 -(1 row) - --- has_largeobject_privilege function --- superuser -\c - -SELECT has_largeobject_privilege(1001, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1002, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1003, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1004, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1001, 'UPDATE'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1002, 'UPDATE'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1003, 'UPDATE'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1004, 'UPDATE'); - has_largeobject_privilege ---------------------------- - t -(1 row) - --- not-existing large object -SELECT has_largeobject_privilege(9999, 'SELECT'); -- NULL - has_largeobject_privilege ---------------------------- - -(1 row) - --- non-superuser -SET SESSION AUTHORIZATION regress_priv_user2; -SELECT has_largeobject_privilege(1001, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1002, 'SELECT'); -- false - has_largeobject_privilege ---------------------------- - f -(1 row) - -SELECT has_largeobject_privilege(1003, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1004, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1001, 'UPDATE'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1002, 'UPDATE'); -- false - has_largeobject_privilege ---------------------------- - f -(1 row) - -SELECT has_largeobject_privilege(1003, 'UPDATE'); -- false - has_largeobject_privilege ---------------------------- - f -(1 row) - -SELECT has_largeobject_privilege(1004, 'UPDATE'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege('regress_priv_user3', 1001, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege('regress_priv_user3', 1003, 'SELECT'); -- false - has_largeobject_privilege ---------------------------- - f -(1 row) - -SELECT has_largeobject_privilege('regress_priv_user3', 1005, 'SELECT'); - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege('regress_priv_user3', 1005, 'UPDATE'); -- false - has_largeobject_privilege ---------------------------- - f -(1 row) - -SELECT has_largeobject_privilege('regress_priv_user3', 2001, 'UPDATE'); - has_largeobject_privilege ---------------------------- - t -(1 row) - --- compatibility mode in largeobject permission -\c - -SET lo_compat_privileges = false; -- default setting -SET SESSION AUTHORIZATION regress_priv_user4; -SELECT has_largeobject_privilege(1002, 'SELECT'); -- false - has_largeobject_privilege ---------------------------- - f -(1 row) - -SELECT has_largeobject_privilege(1002, 'UPDATE'); -- false - has_largeobject_privilege ---------------------------- - f -(1 row) - -SELECT loread(lo_open(1002, x'40000'::int), 32); -- to be denied -ERROR: permission denied for large object 1002 -SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); -- to be denied -ERROR: permission denied for large object 1002 -SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); -- to be denied -ERROR: permission denied for large object 1002 -SELECT lo_put(1002, 1, 'abcd'); -- to be denied -ERROR: permission denied for large object 1002 -SELECT lo_unlink(1002); -- to be denied -ERROR: must be owner of large object 1002 -SELECT lo_export(1001, '/dev/null'); -- to be denied -ERROR: permission denied for function lo_export -SELECT lo_import('/dev/null'); -- to be denied -ERROR: permission denied for function lo_import -SELECT lo_import('/dev/null', 2003); -- to be denied -ERROR: permission denied for function lo_import -\c - -SET lo_compat_privileges = true; -- compatibility mode -SET SESSION AUTHORIZATION regress_priv_user4; -SELECT has_largeobject_privilege(1002, 'SELECT'); -- true - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT has_largeobject_privilege(1002, 'UPDATE'); -- true - has_largeobject_privilege ---------------------------- - t -(1 row) - -SELECT loread(lo_open(1002, x'40000'::int), 32); - loread --------- - \x -(1 row) - -SELECT lowrite(lo_open(1002, x'20000'::int), 'abcd'); - lowrite ---------- - 4 -(1 row) - -SELECT lo_truncate(lo_open(1002, x'20000'::int), 10); - lo_truncate -------------- - 0 -(1 row) - -SELECT lo_unlink(1002); - lo_unlink ------------ - 1 -(1 row) - -SELECT lo_export(1001, '/dev/null'); -- to be denied -ERROR: permission denied for function lo_export --- don't allow unpriv users to access pg_largeobject contents -\c - -SELECT * FROM pg_largeobject LIMIT 0; - loid | pageno | data -------+--------+------ -(0 rows) - -SET SESSION AUTHORIZATION regress_priv_user1; -SELECT * FROM pg_largeobject LIMIT 0; -- to be denied -ERROR: permission denied for table pg_largeobject --- pg_signal_backend can't signal superusers -RESET SESSION AUTHORIZATION; -BEGIN; -CREATE OR REPLACE FUNCTION terminate_nothrow(pid int) RETURNS bool - LANGUAGE plpgsql SECURITY DEFINER SET client_min_messages = error AS $$ -BEGIN - RETURN pg_terminate_backend($1); -EXCEPTION WHEN OTHERS THEN - RETURN false; -END$$; -ALTER FUNCTION terminate_nothrow OWNER TO pg_signal_backend; -SELECT backend_type FROM pg_stat_activity -WHERE CASE WHEN COALESCE(usesysid, 10) = 10 THEN terminate_nothrow(pid) END; - backend_type --------------- -(0 rows) - -ROLLBACK; --- test pg_database_owner -RESET SESSION AUTHORIZATION; -GRANT pg_database_owner TO regress_priv_user1; -ERROR: role "pg_database_owner" cannot have explicit members -GRANT regress_priv_user1 TO pg_database_owner; -ERROR: role "pg_database_owner" cannot be a member of any role -CREATE TABLE datdba_only (); -ALTER TABLE datdba_only OWNER TO pg_database_owner; -REVOKE DELETE ON datdba_only FROM pg_database_owner; -SELECT - pg_has_role('regress_priv_user1', 'pg_database_owner', 'USAGE') as priv, - pg_has_role('regress_priv_user1', 'pg_database_owner', 'MEMBER') as mem, - pg_has_role('regress_priv_user1', 'pg_database_owner', - 'MEMBER WITH ADMIN OPTION') as admin; - priv | mem | admin -------+-----+------- - f | f | f -(1 row) - -BEGIN; -DO $$BEGIN EXECUTE format( - 'ALTER DATABASE %I OWNER TO regress_priv_group2', current_catalog); END$$; -SELECT - pg_has_role('regress_priv_user1', 'pg_database_owner', 'USAGE') as priv, - pg_has_role('regress_priv_user1', 'pg_database_owner', 'MEMBER') as mem, - pg_has_role('regress_priv_user1', 'pg_database_owner', - 'MEMBER WITH ADMIN OPTION') as admin; - priv | mem | admin -------+-----+------- - t | t | f -(1 row) - -SET SESSION AUTHORIZATION regress_priv_user1; -TABLE information_schema.enabled_roles ORDER BY role_name COLLATE "C"; - role_name ---------------------- - pg_database_owner - regress_priv_group2 - regress_priv_user1 -(3 rows) - -TABLE information_schema.applicable_roles ORDER BY role_name COLLATE "C"; - grantee | role_name | is_grantable ----------------------+---------------------+-------------- - regress_priv_group2 | pg_database_owner | NO - regress_priv_user1 | regress_priv_group2 | NO -(2 rows) - -INSERT INTO datdba_only DEFAULT VALUES; -SAVEPOINT q; DELETE FROM datdba_only; ROLLBACK TO q; -ERROR: permission denied for table datdba_only -SET SESSION AUTHORIZATION regress_priv_user2; -TABLE information_schema.enabled_roles; - role_name --------------------- - regress_priv_user2 -(1 row) - -INSERT INTO datdba_only DEFAULT VALUES; -ERROR: permission denied for table datdba_only -ROLLBACK; --- test default ACLs -\c - -CREATE SCHEMA testns; -GRANT ALL ON SCHEMA testns TO regress_priv_user1; -CREATE TABLE testns.acltest1 (x int); -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'SELECT'); -- no - has_table_privilege ---------------------- - f -(1 row) - -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -- no - has_table_privilege ---------------------- - f -(1 row) - --- placeholder for test with duplicated schema and role names -ALTER DEFAULT PRIVILEGES IN SCHEMA testns,testns GRANT SELECT ON TABLES TO public,public; -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'SELECT'); -- no - has_table_privilege ---------------------- - f -(1 row) - -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -- no - has_table_privilege ---------------------- - f -(1 row) - -DROP TABLE testns.acltest1; -CREATE TABLE testns.acltest1 (x int); -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'SELECT'); -- yes - has_table_privilege ---------------------- - t -(1 row) - -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -- no - has_table_privilege ---------------------- - f -(1 row) - -ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT INSERT ON TABLES TO regress_priv_user1; -DROP TABLE testns.acltest1; -CREATE TABLE testns.acltest1 (x int); -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'SELECT'); -- yes - has_table_privilege ---------------------- - t -(1 row) - -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -- yes - has_table_privilege ---------------------- - t -(1 row) - -ALTER DEFAULT PRIVILEGES IN SCHEMA testns REVOKE INSERT ON TABLES FROM regress_priv_user1; -DROP TABLE testns.acltest1; -CREATE TABLE testns.acltest1 (x int); -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'SELECT'); -- yes - has_table_privilege ---------------------- - t -(1 row) - -SELECT has_table_privilege('regress_priv_user1', 'testns.acltest1', 'INSERT'); -- no - has_table_privilege ---------------------- - f -(1 row) - -ALTER DEFAULT PRIVILEGES FOR ROLE regress_priv_user1 REVOKE EXECUTE ON FUNCTIONS FROM public; -ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_priv_user2; -- error -ERROR: cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS --- Test makeaclitem() -SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole, - 'SELECT', TRUE); -- single privilege - makeaclitem ------------------------------------------- - regress_priv_user1=r*/regress_priv_user2 -(1 row) - -SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole, - 'SELECT, INSERT, UPDATE , DELETE ', FALSE); -- multiple privileges - makeaclitem --------------------------------------------- - regress_priv_user1=arwd/regress_priv_user2 -(1 row) - -SELECT makeaclitem('regress_priv_user1'::regrole, 'regress_priv_user2'::regrole, - 'SELECT, fake_privilege', FALSE); -- error -ERROR: unrecognized privilege type: "fake_privilege" --- Test non-throwing aclitem I/O -SELECT pg_input_is_valid('regress_priv_user1=r/regress_priv_user2', 'aclitem'); - pg_input_is_valid -------------------- - t -(1 row) - -SELECT pg_input_is_valid('regress_priv_user1=r/', 'aclitem'); - pg_input_is_valid -------------------- - f -(1 row) - -SELECT * FROM pg_input_error_info('regress_priv_user1=r/', 'aclitem'); - message | detail | hint | sql_error_code ----------------------------------+--------+------+---------------- - a name must follow the "/" sign | | | 22P02 -(1 row) - -SELECT pg_input_is_valid('regress_priv_user1=r/regress_no_such_user', 'aclitem'); - pg_input_is_valid -------------------- - f -(1 row) - -SELECT * FROM pg_input_error_info('regress_priv_user1=r/regress_no_such_user', 'aclitem'); - message | detail | hint | sql_error_code ---------------------------------------------+--------+------+---------------- - role "regress_no_such_user" does not exist | | | 42704 -(1 row) - -SELECT pg_input_is_valid('regress_priv_user1=rY', 'aclitem'); - pg_input_is_valid -------------------- - f -(1 row) - -SELECT * FROM pg_input_error_info('regress_priv_user1=rY', 'aclitem'); - message | detail | hint | sql_error_code -----------------------------------------------------------+--------+------+---------------- - invalid mode character: must be one of "arwdDxtXUCTcsAm" | | | 22P02 -(1 row) - --- --- Testing blanket default grants is very hazardous since it might change --- the privileges attached to objects created by concurrent regression tests. --- To avoid that, be sure to revoke the privileges again before committing. --- -BEGIN; -ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO regress_priv_user2; -CREATE SCHEMA testns2; -SELECT has_schema_privilege('regress_priv_user2', 'testns2', 'USAGE'); -- yes - has_schema_privilege ----------------------- - t -(1 row) - -SELECT has_schema_privilege('regress_priv_user6', 'testns2', 'USAGE'); -- yes - has_schema_privilege ----------------------- - t -(1 row) - -SELECT has_schema_privilege('regress_priv_user2', 'testns2', 'CREATE'); -- no - has_schema_privilege ----------------------- - f -(1 row) - -ALTER DEFAULT PRIVILEGES REVOKE USAGE ON SCHEMAS FROM regress_priv_user2; -CREATE SCHEMA testns3; -SELECT has_schema_privilege('regress_priv_user2', 'testns3', 'USAGE'); -- no - has_schema_privilege ----------------------- - f -(1 row) - -SELECT has_schema_privilege('regress_priv_user2', 'testns3', 'CREATE'); -- no - has_schema_privilege ----------------------- - f -(1 row) - -ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO regress_priv_user2; -CREATE SCHEMA testns4; -SELECT has_schema_privilege('regress_priv_user2', 'testns4', 'USAGE'); -- yes - has_schema_privilege ----------------------- - t -(1 row) - -SELECT has_schema_privilege('regress_priv_user2', 'testns4', 'CREATE'); -- yes - has_schema_privilege ----------------------- - t -(1 row) - -ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_priv_user2; -COMMIT; --- Test for DROP OWNED BY with shared dependencies. This is done in a --- separate, rollbacked, transaction to avoid any trouble with other --- regression sessions. -BEGIN; -ALTER DEFAULT PRIVILEGES GRANT ALL ON FUNCTIONS TO regress_priv_user2; -ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO regress_priv_user2; -ALTER DEFAULT PRIVILEGES GRANT ALL ON SEQUENCES TO regress_priv_user2; -ALTER DEFAULT PRIVILEGES GRANT ALL ON TABLES TO regress_priv_user2; -ALTER DEFAULT PRIVILEGES GRANT ALL ON TYPES TO regress_priv_user2; -SELECT count(*) FROM pg_shdepend - WHERE deptype = 'a' AND - refobjid = 'regress_priv_user2'::regrole AND - classid = 'pg_default_acl'::regclass; - count -------- - 5 -(1 row) - -DROP OWNED BY regress_priv_user2, regress_priv_user2; -SELECT count(*) FROM pg_shdepend - WHERE deptype = 'a' AND - refobjid = 'regress_priv_user2'::regrole AND - classid = 'pg_default_acl'::regclass; - count -------- - 0 -(1 row) - -ROLLBACK; -CREATE SCHEMA testns5; -SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'USAGE'); -- no - has_schema_privilege ----------------------- - f -(1 row) - -SELECT has_schema_privilege('regress_priv_user2', 'testns5', 'CREATE'); -- no - has_schema_privilege ----------------------- - f -(1 row) - -SET ROLE regress_priv_user1; -CREATE FUNCTION testns.foo() RETURNS int AS 'select 1' LANGUAGE sql; -CREATE AGGREGATE testns.agg1(int) (sfunc = int4pl, stype = int4); -CREATE PROCEDURE testns.bar() AS 'select 1' LANGUAGE sql; -SELECT has_function_privilege('regress_priv_user2', 'testns.foo()', 'EXECUTE'); -- no - has_function_privilege ------------------------- - f -(1 row) - -SELECT has_function_privilege('regress_priv_user2', 'testns.agg1(int)', 'EXECUTE'); -- no - has_function_privilege ------------------------- - f -(1 row) - -SELECT has_function_privilege('regress_priv_user2', 'testns.bar()', 'EXECUTE'); -- no - has_function_privilege ------------------------- - f -(1 row) - -ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT EXECUTE ON ROUTINES to public; -DROP FUNCTION testns.foo(); -CREATE FUNCTION testns.foo() RETURNS int AS 'select 1' LANGUAGE sql; -DROP AGGREGATE testns.agg1(int); -CREATE AGGREGATE testns.agg1(int) (sfunc = int4pl, stype = int4); -DROP PROCEDURE testns.bar(); -CREATE PROCEDURE testns.bar() AS 'select 1' LANGUAGE sql; -SELECT has_function_privilege('regress_priv_user2', 'testns.foo()', 'EXECUTE'); -- yes - has_function_privilege ------------------------- - t -(1 row) - -SELECT has_function_privilege('regress_priv_user2', 'testns.agg1(int)', 'EXECUTE'); -- yes - has_function_privilege ------------------------- - t -(1 row) - -SELECT has_function_privilege('regress_priv_user2', 'testns.bar()', 'EXECUTE'); -- yes (counts as function here) - has_function_privilege ------------------------- - t -(1 row) - -DROP FUNCTION testns.foo(); -DROP AGGREGATE testns.agg1(int); -DROP PROCEDURE testns.bar(); -ALTER DEFAULT PRIVILEGES FOR ROLE regress_priv_user1 REVOKE USAGE ON TYPES FROM public; -CREATE DOMAIN testns.priv_testdomain1 AS int; -SELECT has_type_privilege('regress_priv_user2', 'testns.priv_testdomain1', 'USAGE'); -- no - has_type_privilege --------------------- - f -(1 row) - -ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON TYPES to public; -DROP DOMAIN testns.priv_testdomain1; -CREATE DOMAIN testns.priv_testdomain1 AS int; -SELECT has_type_privilege('regress_priv_user2', 'testns.priv_testdomain1', 'USAGE'); -- yes - has_type_privilege --------------------- - t -(1 row) - -DROP DOMAIN testns.priv_testdomain1; -RESET ROLE; -SELECT count(*) - FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid - WHERE nspname = 'testns'; - count -------- - 3 -(1 row) - -DROP SCHEMA testns CASCADE; -NOTICE: drop cascades to table testns.acltest1 -DROP SCHEMA testns2 CASCADE; -DROP SCHEMA testns3 CASCADE; -DROP SCHEMA testns4 CASCADE; -DROP SCHEMA testns5 CASCADE; -SELECT d.* -- check that entries went away - FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid - WHERE nspname IS NULL AND defaclnamespace != 0; - oid | defaclrole | defaclnamespace | defaclobjtype | defaclacl ------+------------+-----------------+---------------+----------- -(0 rows) - --- Grant on all objects of given type in a schema -\c - -CREATE SCHEMA testns; -CREATE TABLE testns.t1 (f1 int); -CREATE TABLE testns.t2 (f1 int); -SELECT has_table_privilege('regress_priv_user1', 'testns.t1', 'SELECT'); -- false - has_table_privilege ---------------------- - f -(1 row) - -GRANT ALL ON ALL TABLES IN SCHEMA testns TO regress_priv_user1; -SELECT has_table_privilege('regress_priv_user1', 'testns.t1', 'SELECT'); -- true - has_table_privilege ---------------------- - t -(1 row) - -SELECT has_table_privilege('regress_priv_user1', 'testns.t2', 'SELECT'); -- true - has_table_privilege ---------------------- - t -(1 row) - -REVOKE ALL ON ALL TABLES IN SCHEMA testns FROM regress_priv_user1; -SELECT has_table_privilege('regress_priv_user1', 'testns.t1', 'SELECT'); -- false - has_table_privilege ---------------------- - f -(1 row) - -SELECT has_table_privilege('regress_priv_user1', 'testns.t2', 'SELECT'); -- false - has_table_privilege ---------------------- - f -(1 row) - -CREATE FUNCTION testns.priv_testfunc(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql; -CREATE AGGREGATE testns.priv_testagg(int) (sfunc = int4pl, stype = int4); -CREATE PROCEDURE testns.priv_testproc(int) AS 'select 3' LANGUAGE sql; -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testfunc(int)', 'EXECUTE'); -- true by default - has_function_privilege ------------------------- - t -(1 row) - -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testagg(int)', 'EXECUTE'); -- true by default - has_function_privilege ------------------------- - t -(1 row) - -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testproc(int)', 'EXECUTE'); -- true by default - has_function_privilege ------------------------- - t -(1 row) - -REVOKE ALL ON ALL FUNCTIONS IN SCHEMA testns FROM PUBLIC; -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testfunc(int)', 'EXECUTE'); -- false - has_function_privilege ------------------------- - f -(1 row) - -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testagg(int)', 'EXECUTE'); -- false - has_function_privilege ------------------------- - f -(1 row) - -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testproc(int)', 'EXECUTE'); -- still true, not a function - has_function_privilege ------------------------- - t -(1 row) - -REVOKE ALL ON ALL PROCEDURES IN SCHEMA testns FROM PUBLIC; -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testproc(int)', 'EXECUTE'); -- now false - has_function_privilege ------------------------- - f -(1 row) - -GRANT ALL ON ALL ROUTINES IN SCHEMA testns TO PUBLIC; -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testfunc(int)', 'EXECUTE'); -- true - has_function_privilege ------------------------- - t -(1 row) - -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testagg(int)', 'EXECUTE'); -- true - has_function_privilege ------------------------- - t -(1 row) - -SELECT has_function_privilege('regress_priv_user1', 'testns.priv_testproc(int)', 'EXECUTE'); -- true - has_function_privilege ------------------------- - t -(1 row) - -DROP SCHEMA testns CASCADE; -NOTICE: drop cascades to 5 other objects -DETAIL: drop cascades to table testns.t1 -drop cascades to table testns.t2 -drop cascades to function testns.priv_testfunc(integer) -drop cascades to function testns.priv_testagg(integer) -drop cascades to function testns.priv_testproc(integer) --- Change owner of the schema & and rename of new schema owner -\c - -CREATE ROLE regress_schemauser1 superuser login; -CREATE ROLE regress_schemauser2 superuser login; -SET SESSION ROLE regress_schemauser1; -CREATE SCHEMA testns; -SELECT nspname, rolname FROM pg_namespace, pg_roles WHERE pg_namespace.nspname = 'testns' AND pg_namespace.nspowner = pg_roles.oid; - nspname | rolname ----------+--------------------- - testns | regress_schemauser1 -(1 row) - -ALTER SCHEMA testns OWNER TO regress_schemauser2; -ALTER ROLE regress_schemauser2 RENAME TO regress_schemauser_renamed; -SELECT nspname, rolname FROM pg_namespace, pg_roles WHERE pg_namespace.nspname = 'testns' AND pg_namespace.nspowner = pg_roles.oid; - nspname | rolname ----------+---------------------------- - testns | regress_schemauser_renamed -(1 row) - -set session role regress_schemauser_renamed; -DROP SCHEMA testns CASCADE; --- clean up -\c - -DROP ROLE regress_schemauser1; -DROP ROLE regress_schemauser_renamed; --- test that dependent privileges are revoked (or not) properly -\c - -set session role regress_priv_user1; -create table dep_priv_test (a int); -grant select on dep_priv_test to regress_priv_user2 with grant option; -grant select on dep_priv_test to regress_priv_user3 with grant option; -set session role regress_priv_user2; -grant select on dep_priv_test to regress_priv_user4 with grant option; -set session role regress_priv_user3; -grant select on dep_priv_test to regress_priv_user4 with grant option; -set session role regress_priv_user4; -grant select on dep_priv_test to regress_priv_user5; -\dp dep_priv_test - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+---------------+-------+------------------------------------------------+-------------------+---------- - public | dep_priv_test | table | regress_priv_user1=arwdDxtm/regress_priv_user1+| | - | | | regress_priv_user2=r*/regress_priv_user1 +| | - | | | regress_priv_user3=r*/regress_priv_user1 +| | - | | | regress_priv_user4=r*/regress_priv_user2 +| | - | | | regress_priv_user4=r*/regress_priv_user3 +| | - | | | regress_priv_user5=r/regress_priv_user4 | | -(1 row) - -set session role regress_priv_user2; -revoke select on dep_priv_test from regress_priv_user4 cascade; -\dp dep_priv_test - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+---------------+-------+------------------------------------------------+-------------------+---------- - public | dep_priv_test | table | regress_priv_user1=arwdDxtm/regress_priv_user1+| | - | | | regress_priv_user2=r*/regress_priv_user1 +| | - | | | regress_priv_user3=r*/regress_priv_user1 +| | - | | | regress_priv_user4=r*/regress_priv_user3 +| | - | | | regress_priv_user5=r/regress_priv_user4 | | -(1 row) - -set session role regress_priv_user3; -revoke select on dep_priv_test from regress_priv_user4 cascade; -\dp dep_priv_test - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+---------------+-------+------------------------------------------------+-------------------+---------- - public | dep_priv_test | table | regress_priv_user1=arwdDxtm/regress_priv_user1+| | - | | | regress_priv_user2=r*/regress_priv_user1 +| | - | | | regress_priv_user3=r*/regress_priv_user1 | | -(1 row) - -set session role regress_priv_user1; -drop table dep_priv_test; --- clean up -\c -drop sequence x_seq; -DROP AGGREGATE priv_testagg1(int); -DROP FUNCTION priv_testfunc2(int); -DROP FUNCTION priv_testfunc4(boolean); -DROP PROCEDURE priv_testproc1(int); -DROP VIEW atestv0; -DROP VIEW atestv1; -DROP VIEW atestv2; --- this should cascade to drop atestv4 -DROP VIEW atestv3 CASCADE; -NOTICE: drop cascades to view atestv4 --- this should complain "does not exist" -DROP VIEW atestv4; -ERROR: view "atestv4" does not exist -DROP TABLE atest1; -DROP TABLE atest2; -DROP TABLE atest3; -DROP TABLE atest4; -DROP TABLE atest5; -DROP TABLE atest6; -DROP TABLE atestc; -DROP TABLE atestp1; -DROP TABLE atestp2; -SELECT lo_unlink(oid) FROM pg_largeobject_metadata WHERE oid >= 1000 AND oid < 3000 ORDER BY oid; - lo_unlink ------------ - 1 - 1 - 1 - 1 - 1 -(5 rows) - -DROP GROUP regress_priv_group1; -DROP GROUP regress_priv_group2; --- these are needed to clean up permissions -REVOKE USAGE ON LANGUAGE sql FROM regress_priv_user1; -DROP OWNED BY regress_priv_user1; -DROP USER regress_priv_user1; -DROP USER regress_priv_user2; -DROP USER regress_priv_user3; -DROP USER regress_priv_user4; -DROP USER regress_priv_user5; -DROP USER regress_priv_user6; -DROP USER regress_priv_user7; -DROP USER regress_priv_user8; -- does not exist -ERROR: role "regress_priv_user8" does not exist --- permissions with LOCK TABLE -CREATE USER regress_locktable_user; -CREATE TABLE lock_table (a int); --- LOCK TABLE and SELECT permission -GRANT SELECT ON lock_table TO regress_locktable_user; -SET SESSION AUTHORIZATION regress_locktable_user; -BEGIN; -LOCK TABLE lock_table IN ACCESS SHARE MODE; -- should pass -COMMIT; -BEGIN; -LOCK TABLE lock_table IN ROW EXCLUSIVE MODE; -- should fail -ERROR: permission denied for table lock_table -ROLLBACK; -BEGIN; -LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should fail -ERROR: permission denied for table lock_table -ROLLBACK; -\c -REVOKE SELECT ON lock_table FROM regress_locktable_user; --- LOCK TABLE and INSERT permission -GRANT INSERT ON lock_table TO regress_locktable_user; -SET SESSION AUTHORIZATION regress_locktable_user; -BEGIN; -LOCK TABLE lock_table IN ACCESS SHARE MODE; -- should pass -ROLLBACK; -BEGIN; -LOCK TABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass -COMMIT; -BEGIN; -LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should fail -ERROR: permission denied for table lock_table -ROLLBACK; -\c -REVOKE INSERT ON lock_table FROM regress_locktable_user; --- LOCK TABLE and UPDATE permission -GRANT UPDATE ON lock_table TO regress_locktable_user; -SET SESSION AUTHORIZATION regress_locktable_user; -BEGIN; -LOCK TABLE lock_table IN ACCESS SHARE MODE; -- should pass -ROLLBACK; -BEGIN; -LOCK TABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass -COMMIT; -BEGIN; -LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass -COMMIT; -\c -REVOKE UPDATE ON lock_table FROM regress_locktable_user; --- LOCK TABLE and DELETE permission -GRANT DELETE ON lock_table TO regress_locktable_user; -SET SESSION AUTHORIZATION regress_locktable_user; -BEGIN; -LOCK TABLE lock_table IN ACCESS SHARE MODE; -- should pass -ROLLBACK; -BEGIN; -LOCK TABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass -COMMIT; -BEGIN; -LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass -COMMIT; -\c -REVOKE DELETE ON lock_table FROM regress_locktable_user; --- LOCK TABLE and TRUNCATE permission -GRANT TRUNCATE ON lock_table TO regress_locktable_user; -SET SESSION AUTHORIZATION regress_locktable_user; -BEGIN; -LOCK TABLE lock_table IN ACCESS SHARE MODE; -- should pass -ROLLBACK; -BEGIN; -LOCK TABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass -COMMIT; -BEGIN; -LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass -COMMIT; -\c -REVOKE TRUNCATE ON lock_table FROM regress_locktable_user; --- LOCK TABLE and MAINTAIN permission -GRANT MAINTAIN ON lock_table TO regress_locktable_user; -SET SESSION AUTHORIZATION regress_locktable_user; -BEGIN; -LOCK TABLE lock_table IN ACCESS SHARE MODE; -- should pass -ROLLBACK; -BEGIN; -LOCK TABLE lock_table IN ROW EXCLUSIVE MODE; -- should pass -COMMIT; -BEGIN; -LOCK TABLE lock_table IN ACCESS EXCLUSIVE MODE; -- should pass -COMMIT; -\c -REVOKE MAINTAIN ON lock_table FROM regress_locktable_user; --- clean up -DROP TABLE lock_table; -DROP USER regress_locktable_user; --- test to check privileges of system views pg_shmem_allocations and --- pg_backend_memory_contexts. --- switch to superuser -\c - -CREATE ROLE regress_readallstats; -SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- no - has_table_privilege ---------------------- - f -(1 row) - -SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT'); -- no - has_table_privilege ---------------------- - f -(1 row) - -GRANT pg_read_all_stats TO regress_readallstats; -SELECT has_table_privilege('regress_readallstats','pg_backend_memory_contexts','SELECT'); -- yes - has_table_privilege ---------------------- - t -(1 row) - -SELECT has_table_privilege('regress_readallstats','pg_shmem_allocations','SELECT'); -- yes - has_table_privilege ---------------------- - t -(1 row) - --- run query to ensure that functions within views can be executed -SET ROLE regress_readallstats; -SELECT COUNT(*) >= 0 AS ok FROM pg_backend_memory_contexts; - ok ----- - t -(1 row) - -SELECT COUNT(*) >= 0 AS ok FROM pg_shmem_allocations; - ok ----- - t -(1 row) - -RESET ROLE; --- clean up -DROP ROLE regress_readallstats; --- test role grantor machinery -CREATE ROLE regress_group; -CREATE ROLE regress_group_direct_manager; -CREATE ROLE regress_group_indirect_manager; -CREATE ROLE regress_group_member; -GRANT regress_group TO regress_group_direct_manager WITH INHERIT FALSE, ADMIN TRUE; -GRANT regress_group_direct_manager TO regress_group_indirect_manager; -SET SESSION AUTHORIZATION regress_group_direct_manager; -GRANT regress_group TO regress_group_member; -SELECT member::regrole::text, CASE WHEN grantor = 10 THEN 'BOOTSTRAP SUPERUSER' ELSE grantor::regrole::text END FROM pg_auth_members WHERE roleid = 'regress_group'::regrole ORDER BY 1, 2; - member | grantor -------------------------------+------------------------------ - regress_group_direct_manager | BOOTSTRAP SUPERUSER - regress_group_member | regress_group_direct_manager -(2 rows) - -REVOKE regress_group FROM regress_group_member; -SET SESSION AUTHORIZATION regress_group_indirect_manager; -GRANT regress_group TO regress_group_member; -SELECT member::regrole::text, CASE WHEN grantor = 10 THEN 'BOOTSTRAP SUPERUSER' ELSE grantor::regrole::text END FROM pg_auth_members WHERE roleid = 'regress_group'::regrole ORDER BY 1, 2; - member | grantor -------------------------------+------------------------------ - regress_group_direct_manager | BOOTSTRAP SUPERUSER - regress_group_member | regress_group_direct_manager -(2 rows) - -REVOKE regress_group FROM regress_group_member; -RESET SESSION AUTHORIZATION; -DROP ROLE regress_group; -DROP ROLE regress_group_direct_manager; -DROP ROLE regress_group_indirect_manager; -DROP ROLE regress_group_member; --- test SET and INHERIT options with object ownership changes -CREATE ROLE regress_roleoption_protagonist; -CREATE ROLE regress_roleoption_donor; -CREATE ROLE regress_roleoption_recipient; -CREATE SCHEMA regress_roleoption; -GRANT CREATE, USAGE ON SCHEMA regress_roleoption TO PUBLIC; -GRANT regress_roleoption_donor TO regress_roleoption_protagonist WITH INHERIT TRUE, SET FALSE; -GRANT regress_roleoption_recipient TO regress_roleoption_protagonist WITH INHERIT FALSE, SET TRUE; -SET SESSION AUTHORIZATION regress_roleoption_protagonist; -CREATE TABLE regress_roleoption.t1 (a int); -CREATE TABLE regress_roleoption.t2 (a int); -SET SESSION AUTHORIZATION regress_roleoption_donor; -CREATE TABLE regress_roleoption.t3 (a int); -SET SESSION AUTHORIZATION regress_roleoption_recipient; -CREATE TABLE regress_roleoption.t4 (a int); -SET SESSION AUTHORIZATION regress_roleoption_protagonist; -ALTER TABLE regress_roleoption.t1 OWNER TO regress_roleoption_donor; -- fails, can't be come donor -ERROR: must be able to SET ROLE "regress_roleoption_donor" -ALTER TABLE regress_roleoption.t2 OWNER TO regress_roleoption_recipient; -- works -ALTER TABLE regress_roleoption.t3 OWNER TO regress_roleoption_protagonist; -- works -ALTER TABLE regress_roleoption.t4 OWNER TO regress_roleoption_protagonist; -- fails, we don't inherit from recipient -ERROR: must be owner of table t4 -RESET SESSION AUTHORIZATION; -DROP TABLE regress_roleoption.t1; -DROP TABLE regress_roleoption.t2; -DROP TABLE regress_roleoption.t3; -DROP TABLE regress_roleoption.t4; -DROP SCHEMA regress_roleoption; -DROP ROLE regress_roleoption_protagonist; -DROP ROLE regress_roleoption_donor; -DROP ROLE regress_roleoption_recipient; --- MAINTAIN -CREATE ROLE regress_no_maintain; -CREATE ROLE regress_maintain; -CREATE ROLE regress_maintain_all IN ROLE pg_maintain; -CREATE TABLE maintain_test (a INT); -CREATE INDEX ON maintain_test (a); -GRANT MAINTAIN ON maintain_test TO regress_maintain; -CREATE MATERIALIZED VIEW refresh_test AS SELECT 1; -GRANT MAINTAIN ON refresh_test TO regress_maintain; -CREATE SCHEMA reindex_test; --- negative tests; should fail -SET ROLE regress_no_maintain; -VACUUM maintain_test; -WARNING: permission denied to vacuum "maintain_test", skipping it -ANALYZE maintain_test; -WARNING: permission denied to analyze "maintain_test", skipping it -VACUUM (ANALYZE) maintain_test; -WARNING: permission denied to vacuum "maintain_test", skipping it -CLUSTER maintain_test USING maintain_test_a_idx; -ERROR: permission denied for table maintain_test -REFRESH MATERIALIZED VIEW refresh_test; -ERROR: permission denied for materialized view refresh_test -REINDEX TABLE maintain_test; -ERROR: permission denied for table maintain_test -REINDEX INDEX maintain_test_a_idx; -ERROR: permission denied for index maintain_test_a_idx -REINDEX SCHEMA reindex_test; -ERROR: must be owner of schema reindex_test -RESET ROLE; -SET ROLE regress_maintain; -VACUUM maintain_test; -ANALYZE maintain_test; -VACUUM (ANALYZE) maintain_test; -CLUSTER maintain_test USING maintain_test_a_idx; -REFRESH MATERIALIZED VIEW refresh_test; -REINDEX TABLE maintain_test; -REINDEX INDEX maintain_test_a_idx; -REINDEX SCHEMA reindex_test; -ERROR: must be owner of schema reindex_test -RESET ROLE; -SET ROLE regress_maintain_all; -VACUUM maintain_test; -ANALYZE maintain_test; -VACUUM (ANALYZE) maintain_test; -CLUSTER maintain_test USING maintain_test_a_idx; -REFRESH MATERIALIZED VIEW refresh_test; -REINDEX TABLE maintain_test; -REINDEX INDEX maintain_test_a_idx; -REINDEX SCHEMA reindex_test; -RESET ROLE; -DROP TABLE maintain_test; -DROP MATERIALIZED VIEW refresh_test; -DROP SCHEMA reindex_test; -DROP ROLE regress_no_maintain; -DROP ROLE regress_maintain; -DROP ROLE regress_maintain_all; +WARNING: terminating connection because of crash of another server process +DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory. +HINT: In a moment you should be able to reconnect to the database and repeat your command. +server closed the connection unexpectedly + This probably means the server terminated abnormally + before or while processing the request. +connection to server was lost diff --strip-trailing-cr -U3 C:/cirrus/src/test/regress/expected/matview.out C:/cirrus/build/testrun/regress/regress/results/matview.out --- C:/cirrus/src/test/regress/expected/matview.out 2024-12-13 13:18:31.438871700 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/matview.out 2024-12-13 13:21:25.251809800 +0000 @@ -731,205 +731,7 @@ -- replace query with data CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS SELECT 2 AS a; -SELECT * FROM mvtest_replace; - a ---- - 2 -(1 row) - --- replace query without data -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 3 AS a - WITH NO DATA; -SELECT * FROM mvtest_replace; -- error: not populated -ERROR: materialized view "mvtest_replace" has not been populated -HINT: Use the REFRESH MATERIALIZED VIEW command. -REFRESH MATERIALIZED VIEW mvtest_replace; -SELECT * FROM mvtest_replace; - a ---- - 3 -(1 row) - --- replace query but keep old data -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 5 AS a - WITH OLD DATA; -SELECT * FROM mvtest_replace; - a ---- - 3 -(1 row) - -REFRESH MATERIALIZED VIEW mvtest_replace; -SELECT * FROM mvtest_replace; - a ---- - 5 -(1 row) - --- add column -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 4 AS a, 1 b; -SELECT * FROM mvtest_replace; - a | b ----+--- - 4 | 1 -(1 row) - --- replace table options -SELECT m.*, c.relname, c.reloptions, s.spcname, a.amname - FROM mvtest_replace m - CROSS JOIN pg_class c - LEFT JOIN pg_tablespace s ON s.oid = c.reltablespace - LEFT JOIN pg_am a ON a.oid = c.relam - WHERE c.relname = 'mvtest_replace'; - a | b | relname | reloptions | spcname | amname ----+---+----------------+------------+---------+-------- - 4 | 1 | mvtest_replace | | | heap -(1 row) - -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace - USING heap2 - WITH (fillfactor = 50) - TABLESPACE regress_tblspace - AS SELECT 5 AS a, 1 AS b; -SELECT m.*, c.relname, c.reloptions, s.spcname, a.amname - FROM mvtest_replace m - CROSS JOIN pg_class c - LEFT JOIN pg_tablespace s ON s.oid = c.reltablespace - LEFT JOIN pg_am a ON a.oid = c.relam - WHERE c.relname = 'mvtest_replace'; - a | b | relname | reloptions | spcname | amname ----+---+----------------+-----------------+------------------+-------- - 5 | 1 | mvtest_replace | {fillfactor=50} | regress_tblspace | heap2 -(1 row) - --- can replace matview that has a dependent view -CREATE VIEW mvtest_replace_v AS - SELECT * FROM mvtest_replace; -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 6 AS a, 1 AS b; -SELECT * FROM mvtest_replace, mvtest_replace_v; - a | b | a | b ----+---+---+--- - 6 | 1 | 6 | 1 -(1 row) - -DROP VIEW mvtest_replace_v; --- index gets rebuilt when replacing with data -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 7 AS a, 1 AS b; -CREATE UNIQUE INDEX ON mvtest_replace (b); -SELECT * FROM mvtest_replace; - a | b ----+--- - 7 | 1 -(1 row) - -SET enable_seqscan = off; -- force index scan -EXPLAIN (COSTS OFF) SELECT * FROM mvtest_replace WHERE b = 1; - QUERY PLAN ---------------------------------------------------------- - Index Scan using mvtest_replace_b_idx on mvtest_replace - Index Cond: (b = 1) -(2 rows) - -SELECT * FROM mvtest_replace WHERE b = 1; - a | b ----+--- - 7 | 1 -(1 row) - -RESET enable_seqscan; -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 8 AS a, 1 AS b; -SET enable_seqscan = off; -- force index scan -EXPLAIN (COSTS OFF) SELECT * FROM mvtest_replace WHERE b = 1; - QUERY PLAN ---------------------------------------------------------- - Index Scan using mvtest_replace_b_idx on mvtest_replace - Index Cond: (b = 1) -(2 rows) - -SELECT * FROM mvtest_replace WHERE b = 1; - a | b ----+--- - 8 | 1 -(1 row) - -RESET enable_seqscan; --- cannot change column data type -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 9 AS a, 'x' AS b; -- error -ERROR: cannot change data type of materialized view column "b" from integer to text -SELECT * FROM mvtest_replace; - a | b ----+--- - 8 | 1 -(1 row) - --- cannot rename column -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 10 AS a, 1 AS b2; -- error -ERROR: cannot change name of materialized view column "b" to "b2" -HINT: Use ALTER MATERIALIZED VIEW ... RENAME COLUMN ... to change name of materialized view column instead. -SELECT * FROM mvtest_replace; - a | b ----+--- - 8 | 1 -(1 row) - -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 11 AS a, 1 AS b, 'y' COLLATE "C" AS c; -SELECT * FROM mvtest_replace; - a | b | c -----+---+--- - 11 | 1 | y -(1 row) - --- cannot change column collation -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 12 AS a, 1 AS b, 'x' COLLATE "POSIX" AS c; -- error -ERROR: cannot change collation of materialized view column "c" from "C" to "POSIX" -SELECT * FROM mvtest_replace; - a | b | c -----+---+--- - 11 | 1 | y -(1 row) - --- cannot drop column -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 13 AS a, 1 AS b; -- error -ERROR: cannot drop columns from materialized view -SELECT * FROM mvtest_replace; - a | b | c -----+---+--- - 11 | 1 | y -(1 row) - --- must target a matview -CREATE VIEW mvtest_not_mv AS - SELECT 1 AS a; -CREATE OR REPLACE MATERIALIZED VIEW mvtest_not_mv AS - SELECT 1 AS a; -- error -ERROR: "mvtest_not_mv" is not a materialized view -DROP VIEW mvtest_not_mv; --- cannot use OR REPLACE with IF NOT EXISTS -CREATE OR REPLACE MATERIALIZED VIEW IF NOT EXISTS mvtest_replace AS - SELECT 1 AS a; -ERROR: syntax error at or near "NOT" -LINE 1: CREATE OR REPLACE MATERIALIZED VIEW IF NOT EXISTS mvtest_rep... - ^ -DROP MATERIALIZED VIEW mvtest_replace; --- Create new matview WITH OLD DATA. This populates the new matview as if --- WITH DATA had been specified. -CREATE OR REPLACE MATERIALIZED VIEW mvtest_replace AS - SELECT 17 AS a - WITH OLD DATA; -SELECT * FROM mvtest_replace; - a ----- - 17 -(1 row) - +server closed the connection unexpectedly + This probably means the server terminated abnormally + before or while processing the request. +connection to server was lost diff --strip-trailing-cr -U3 C:/cirrus/src/test/regress/expected/join_hash.out C:/cirrus/build/testrun/regress/regress/results/join_hash.out --- C:/cirrus/src/test/regress/expected/join_hash.out 2024-12-13 13:18:31.424160400 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/join_hash.out 2024-12-13 13:21:25.283060600 +0000 @@ -709,457 +709,10 @@ left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; $$); - multibatch ------------- - t -(1 row) - -rollback to settings; --- single-batch with rescan, parallel-aware -savepoint settings; -set enable_parallel_hash = on; -set parallel_leader_participation = off; -set min_parallel_table_scan_size = 0; -set parallel_setup_cost = 0; -set parallel_tuple_cost = 0; -set max_parallel_workers_per_gather = 2; -set enable_material = off; -set enable_mergejoin = off; -set work_mem = '4MB'; -set hash_mem_multiplier = 1.0; -explain (costs off) - select count(*) from join_foo - left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss - on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; - QUERY PLAN ------------------------------------------------------------------------------------- - Aggregate - -> Nested Loop Left Join - Join Filter: ((join_foo.id < (b1.id + 1)) AND (join_foo.id > (b1.id - 1))) - -> Seq Scan on join_foo - -> Gather - Workers Planned: 2 - -> Parallel Hash Join - Hash Cond: (b1.id = b2.id) - -> Parallel Seq Scan on join_bar b1 - -> Parallel Hash - -> Parallel Seq Scan on join_bar b2 -(11 rows) - -select count(*) from join_foo - left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss - on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; - count -------- - 3 -(1 row) - -select final > 1 as multibatch - from hash_join_batches( -$$ - select count(*) from join_foo - left join (select b1.id, b1.t from join_bar b1 join join_bar b2 using (id)) ss - on join_foo.id < ss.id + 1 and join_foo.id > ss.id - 1; -$$); - multibatch ------------- - f -(1 row) - -rollback to settings; --- A full outer join where every record is matched. --- non-parallel -savepoint settings; -set local max_parallel_workers_per_gather = 0; -explain (costs off) - select count(*) from simple r full outer join simple s using (id); - QUERY PLAN ----------------------------------------- - Aggregate - -> Hash Full Join - Hash Cond: (r.id = s.id) - -> Seq Scan on simple r - -> Hash - -> Seq Scan on simple s -(6 rows) - -select count(*) from simple r full outer join simple s using (id); - count -------- - 20000 -(1 row) - -rollback to settings; --- parallelism not possible with parallel-oblivious full hash join -savepoint settings; -set enable_parallel_hash = off; -set local max_parallel_workers_per_gather = 2; -explain (costs off) - select count(*) from simple r full outer join simple s using (id); - QUERY PLAN ----------------------------------------- - Aggregate - -> Hash Full Join - Hash Cond: (r.id = s.id) - -> Seq Scan on simple r - -> Hash - -> Seq Scan on simple s -(6 rows) - -select count(*) from simple r full outer join simple s using (id); - count -------- - 20000 -(1 row) - -rollback to settings; --- parallelism is possible with parallel-aware full hash join -savepoint settings; -set local max_parallel_workers_per_gather = 2; -explain (costs off) - select count(*) from simple r full outer join simple s using (id); - QUERY PLAN -------------------------------------------------------------- - Finalize Aggregate - -> Gather - Workers Planned: 2 - -> Partial Aggregate - -> Parallel Hash Full Join - Hash Cond: (r.id = s.id) - -> Parallel Seq Scan on simple r - -> Parallel Hash - -> Parallel Seq Scan on simple s -(9 rows) - -select count(*) from simple r full outer join simple s using (id); - count -------- - 20000 -(1 row) - -rollback to settings; --- A full outer join where every record is not matched. --- non-parallel -savepoint settings; -set local max_parallel_workers_per_gather = 0; -explain (costs off) - select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - QUERY PLAN ----------------------------------------- - Aggregate - -> Hash Full Join - Hash Cond: ((0 - s.id) = r.id) - -> Seq Scan on simple s - -> Hash - -> Seq Scan on simple r -(6 rows) - -select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - count -------- - 40000 -(1 row) - -rollback to settings; --- parallelism not possible with parallel-oblivious full hash join -savepoint settings; -set enable_parallel_hash = off; -set local max_parallel_workers_per_gather = 2; -explain (costs off) - select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - QUERY PLAN ----------------------------------------- - Aggregate - -> Hash Full Join - Hash Cond: ((0 - s.id) = r.id) - -> Seq Scan on simple s - -> Hash - -> Seq Scan on simple r -(6 rows) - -select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - count -------- - 40000 -(1 row) - -rollback to settings; --- parallelism is possible with parallel-aware full hash join -savepoint settings; -set local max_parallel_workers_per_gather = 2; -explain (costs off) - select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - QUERY PLAN -------------------------------------------------------------- - Finalize Aggregate - -> Gather - Workers Planned: 2 - -> Partial Aggregate - -> Parallel Hash Full Join - Hash Cond: ((0 - s.id) = r.id) - -> Parallel Seq Scan on simple s - -> Parallel Hash - -> Parallel Seq Scan on simple r -(9 rows) - -select count(*) from simple r full outer join simple s on (r.id = 0 - s.id); - count -------- - 40000 -(1 row) - -rollback to settings; --- exercise special code paths for huge tuples (note use of non-strict --- expression and left join required to get the detoasted tuple into --- the hash table) --- parallel with parallel-aware hash join (hits ExecParallelHashLoadTuple and --- sts_puttuple oversized tuple cases because it's multi-batch) -savepoint settings; -set max_parallel_workers_per_gather = 2; -set enable_parallel_hash = on; -set work_mem = '128kB'; -set hash_mem_multiplier = 1.0; -explain (costs off) - select length(max(s.t)) - from wide left join (select id, coalesce(t, '') || '' as t from wide) s using (id); - QUERY PLAN ----------------------------------------------------------------- - Finalize Aggregate - -> Gather - Workers Planned: 2 - -> Partial Aggregate - -> Parallel Hash Left Join - Hash Cond: (wide.id = wide_1.id) - -> Parallel Seq Scan on wide - -> Parallel Hash - -> Parallel Seq Scan on wide wide_1 -(9 rows) - -select length(max(s.t)) -from wide left join (select id, coalesce(t, '') || '' as t from wide) s using (id); - length --------- - 320000 -(1 row) - -select final > 1 as multibatch - from hash_join_batches( -$$ - select length(max(s.t)) - from wide left join (select id, coalesce(t, '') || '' as t from wide) s using (id); -$$); - multibatch ------------- - t -(1 row) - -rollback to settings; --- Hash join reuses the HOT status bit to indicate match status. This can only --- be guaranteed to produce correct results if all the hash join tuple match --- bits are reset before reuse. This is done upon loading them into the --- hashtable. -SAVEPOINT settings; -SET enable_parallel_hash = on; -SET min_parallel_table_scan_size = 0; -SET parallel_setup_cost = 0; -SET parallel_tuple_cost = 0; -CREATE TABLE hjtest_matchbits_t1(id int); -CREATE TABLE hjtest_matchbits_t2(id int); -INSERT INTO hjtest_matchbits_t1 VALUES (1); -INSERT INTO hjtest_matchbits_t2 VALUES (2); --- Update should create a HOT tuple. If this status bit isn't cleared, we won't --- correctly emit the NULL-extended unmatching tuple in full hash join. -UPDATE hjtest_matchbits_t2 set id = 2; -SELECT * FROM hjtest_matchbits_t1 t1 FULL JOIN hjtest_matchbits_t2 t2 ON t1.id = t2.id - ORDER BY t1.id; - id | id -----+---- - 1 | - | 2 -(2 rows) - --- Test serial full hash join. --- Resetting parallel_setup_cost should force a serial plan. --- Just to be safe, however, set enable_parallel_hash to off, as parallel full --- hash joins are only supported with shared hashtables. -RESET parallel_setup_cost; -SET enable_parallel_hash = off; -SELECT * FROM hjtest_matchbits_t1 t1 FULL JOIN hjtest_matchbits_t2 t2 ON t1.id = t2.id; - id | id -----+---- - 1 | - | 2 -(2 rows) - -ROLLBACK TO settings; -rollback; --- Verify that hash key expressions reference the correct --- nodes. Hashjoin's hashkeys need to reference its outer plan, Hash's --- need to reference Hash's outer plan (which is below HashJoin's --- inner plan). It's not trivial to verify that the references are --- correct (we don't display the hashkeys themselves), but if the --- hashkeys contain subplan references, those will be displayed. Force --- subplans to appear just about everywhere. --- --- Bug report: --- https://www.postgresql.org/message-id/CAPpHfdvGVegF_TKKRiBrSmatJL2dR9uwFCuR%2BteQ_8tEXU8mxg%40mail.gmail.com --- -BEGIN; -SET LOCAL enable_sort = OFF; -- avoid mergejoins -SET LOCAL from_collapse_limit = 1; -- allows easy changing of join order -CREATE TABLE hjtest_1 (a text, b int, id int, c bool); -CREATE TABLE hjtest_2 (a bool, id int, b text, c int); -INSERT INTO hjtest_1(a, b, id, c) VALUES ('text', 2, 1, false); -- matches -INSERT INTO hjtest_1(a, b, id, c) VALUES ('text', 1, 2, false); -- fails id join condition -INSERT INTO hjtest_1(a, b, id, c) VALUES ('text', 20, 1, false); -- fails < 50 -INSERT INTO hjtest_1(a, b, id, c) VALUES ('text', 1, 1, false); -- fails (SELECT hjtest_1.b * 5) = (SELECT hjtest_2.c*5) -INSERT INTO hjtest_2(a, id, b, c) VALUES (true, 1, 'another', 2); -- matches -INSERT INTO hjtest_2(a, id, b, c) VALUES (true, 3, 'another', 7); -- fails id join condition -INSERT INTO hjtest_2(a, id, b, c) VALUES (true, 1, 'another', 90); -- fails < 55 -INSERT INTO hjtest_2(a, id, b, c) VALUES (true, 1, 'another', 3); -- fails (SELECT hjtest_1.b * 5) = (SELECT hjtest_2.c*5) -INSERT INTO hjtest_2(a, id, b, c) VALUES (true, 1, 'text', 1); -- fails hjtest_1.a <> hjtest_2.b; -EXPLAIN (COSTS OFF, VERBOSE) -SELECT hjtest_1.a a1, hjtest_2.a a2,hjtest_1.tableoid::regclass t1, hjtest_2.tableoid::regclass t2 -FROM hjtest_1, hjtest_2 -WHERE - hjtest_1.id = (SELECT 1 WHERE hjtest_2.id = 1) - AND (SELECT hjtest_1.b * 5) = (SELECT hjtest_2.c*5) - AND (SELECT hjtest_1.b * 5) < 50 - AND (SELECT hjtest_2.c * 5) < 55 - AND hjtest_1.a <> hjtest_2.b; - QUERY PLAN ------------------------------------------------------------------------------------------------- - Hash Join - Output: hjtest_1.a, hjtest_2.a, (hjtest_1.tableoid)::regclass, (hjtest_2.tableoid)::regclass - Hash Cond: ((hjtest_1.id = (SubPlan 1)) AND ((SubPlan 2) = (SubPlan 3))) - Join Filter: (hjtest_1.a <> hjtest_2.b) - -> Seq Scan on public.hjtest_1 - Output: hjtest_1.a, hjtest_1.tableoid, hjtest_1.id, hjtest_1.b - Filter: ((SubPlan 4) < 50) - SubPlan 4 - -> Result - Output: (hjtest_1.b * 5) - -> Hash - Output: hjtest_2.a, hjtest_2.tableoid, hjtest_2.id, hjtest_2.c, hjtest_2.b - -> Seq Scan on public.hjtest_2 - Output: hjtest_2.a, hjtest_2.tableoid, hjtest_2.id, hjtest_2.c, hjtest_2.b - Filter: ((SubPlan 5) < 55) - SubPlan 5 - -> Result - Output: (hjtest_2.c * 5) - SubPlan 1 - -> Result - Output: 1 - One-Time Filter: (hjtest_2.id = 1) - SubPlan 3 - -> Result - Output: (hjtest_2.c * 5) - SubPlan 2 - -> Result - Output: (hjtest_1.b * 5) -(28 rows) - -SELECT hjtest_1.a a1, hjtest_2.a a2,hjtest_1.tableoid::regclass t1, hjtest_2.tableoid::regclass t2 -FROM hjtest_1, hjtest_2 -WHERE - hjtest_1.id = (SELECT 1 WHERE hjtest_2.id = 1) - AND (SELECT hjtest_1.b * 5) = (SELECT hjtest_2.c*5) - AND (SELECT hjtest_1.b * 5) < 50 - AND (SELECT hjtest_2.c * 5) < 55 - AND hjtest_1.a <> hjtest_2.b; - a1 | a2 | t1 | t2 -------+----+----------+---------- - text | t | hjtest_1 | hjtest_2 -(1 row) - -EXPLAIN (COSTS OFF, VERBOSE) -SELECT hjtest_1.a a1, hjtest_2.a a2,hjtest_1.tableoid::regclass t1, hjtest_2.tableoid::regclass t2 -FROM hjtest_2, hjtest_1 -WHERE - hjtest_1.id = (SELECT 1 WHERE hjtest_2.id = 1) - AND (SELECT hjtest_1.b * 5) = (SELECT hjtest_2.c*5) - AND (SELECT hjtest_1.b * 5) < 50 - AND (SELECT hjtest_2.c * 5) < 55 - AND hjtest_1.a <> hjtest_2.b; - QUERY PLAN ------------------------------------------------------------------------------------------------- - Hash Join - Output: hjtest_1.a, hjtest_2.a, (hjtest_1.tableoid)::regclass, (hjtest_2.tableoid)::regclass - Hash Cond: (((SubPlan 1) = hjtest_1.id) AND ((SubPlan 3) = (SubPlan 2))) - Join Filter: (hjtest_1.a <> hjtest_2.b) - -> Seq Scan on public.hjtest_2 - Output: hjtest_2.a, hjtest_2.tableoid, hjtest_2.id, hjtest_2.c, hjtest_2.b - Filter: ((SubPlan 5) < 55) - SubPlan 5 - -> Result - Output: (hjtest_2.c * 5) - -> Hash - Output: hjtest_1.a, hjtest_1.tableoid, hjtest_1.id, hjtest_1.b - -> Seq Scan on public.hjtest_1 - Output: hjtest_1.a, hjtest_1.tableoid, hjtest_1.id, hjtest_1.b - Filter: ((SubPlan 4) < 50) - SubPlan 4 - -> Result - Output: (hjtest_1.b * 5) - SubPlan 2 - -> Result - Output: (hjtest_1.b * 5) - SubPlan 1 - -> Result - Output: 1 - One-Time Filter: (hjtest_2.id = 1) - SubPlan 3 - -> Result - Output: (hjtest_2.c * 5) -(28 rows) - -SELECT hjtest_1.a a1, hjtest_2.a a2,hjtest_1.tableoid::regclass t1, hjtest_2.tableoid::regclass t2 -FROM hjtest_2, hjtest_1 -WHERE - hjtest_1.id = (SELECT 1 WHERE hjtest_2.id = 1) - AND (SELECT hjtest_1.b * 5) = (SELECT hjtest_2.c*5) - AND (SELECT hjtest_1.b * 5) < 50 - AND (SELECT hjtest_2.c * 5) < 55 - AND hjtest_1.a <> hjtest_2.b; - a1 | a2 | t1 | t2 -------+----+----------+---------- - text | t | hjtest_1 | hjtest_2 -(1 row) - -ROLLBACK; --- Verify that we behave sanely when the inner hash keys contain parameters --- (that is, outer or lateral references). This situation has to defeat --- re-use of the inner hash table across rescans. -begin; -set local enable_hashjoin = on; -explain (costs off) -select i8.q2, ss.* from -int8_tbl i8, -lateral (select t1.fivethous, i4.f1 from tenk1 t1 join int4_tbl i4 - on t1.fivethous = i4.f1+i8.q2 order by 1,2) ss; - QUERY PLAN ------------------------------------------------------------ - Nested Loop - -> Seq Scan on int8_tbl i8 - -> Sort - Sort Key: t1.fivethous, i4.f1 - -> Hash Join - Hash Cond: (t1.fivethous = (i4.f1 + i8.q2)) - -> Seq Scan on tenk1 t1 - -> Hash - -> Seq Scan on int4_tbl i4 -(9 rows) - -select i8.q2, ss.* from -int8_tbl i8, -lateral (select t1.fivethous, i4.f1 from tenk1 t1 join int4_tbl i4 - on t1.fivethous = i4.f1+i8.q2 order by 1,2) ss; - q2 | fivethous | f1 ------+-----------+---- - 456 | 456 | 0 - 456 | 456 | 0 - 123 | 123 | 0 - 123 | 123 | 0 -(4 rows) - -rollback; +WARNING: terminating connection because of crash of another server process +DETAIL: The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory. +HINT: In a moment you should be able to reconnect to the database and repeat your command. +server closed the connection unexpectedly + This probably means the server terminated abnormally + before or while processing the request. +connection to server was lost diff --strip-trailing-cr -U3 C:/cirrus/src/test/regress/expected/stats_ext.out C:/cirrus/build/testrun/regress/regress/results/stats_ext.out --- C:/cirrus/src/test/regress/expected/stats_ext.out 2024-12-13 13:18:31.506195100 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/stats_ext.out 2024-12-13 13:21:48.570173900 +0000 @@ -3252,6 +3252,7 @@ LANGUAGE plpgsql; CREATE OPERATOR <<< (procedure = op_leak, leftarg = int, rightarg = int, restrict = scalarltsel); +ERROR: operator <<< already exists SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 AND b <<< 0; -- Permission denied ERROR: permission denied for table priv_test_tbl SELECT * FROM tststats.priv_test_tbl WHERE a <<< 0 OR b <<< 0; @@ -3337,6 +3338,7 @@ -- Tidy up DROP OPERATOR <<< (int, int); +ERROR: must be owner of operator <<< DROP FUNCTION op_leak(int, int); RESET SESSION AUTHORIZATION; DROP TABLE stats_ext_tbl;