sepgsql-v9.3-post-alter-support.v4.part-2.patch
application/octet-stream
Filename: sepgsql-v9.3-post-alter-support.v4.part-2.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v9
| File | + | − |
|---|---|---|
| contrib/sepgsql/database.c | 27 | 0 |
| contrib/sepgsql/expected/alter.out | 192 | 0 |
| contrib/sepgsql/expected/ddl.out | 9 | 0 |
| contrib/sepgsql/hooks.c | 66 | 0 |
| contrib/sepgsql/proc.c | 88 | 2 |
| contrib/sepgsql/relation.c | 96 | 7 |
| contrib/sepgsql/schema.c | 51 | 0 |
| contrib/sepgsql/sepgsql.h | 8 | 0 |
| contrib/sepgsql/sql/alter.sql | 136 | 0 |
| contrib/sepgsql/sql/ddl.sql | 6 | 0 |
| contrib/sepgsql/test_sepgsql | 1 | 1 |
| doc/src/sgml/sepgsql.sgml | 18 | 3 |
| src/backend/catalog/aclchk.c | 9 | 0 |
| src/backend/catalog/heap.c | 29 | 12 |
| src/backend/catalog/index.c | 9 | 3 |
| src/backend/catalog/objectaccess.c | 45 | 0 |
| src/backend/catalog/pg_constraint.c | 9 | 2 |
| src/backend/catalog/pg_db_role_setting.c | 4 | 1 |
| src/backend/catalog/pg_type.c | 3 | 0 |
| src/backend/commands/alter.c | 9 | 0 |
| src/backend/commands/cluster.c | 16 | 4 |
| src/backend/commands/collationcmds.c | 1 | 0 |
| src/backend/commands/dbcommands.c | 13 | 0 |
| src/backend/commands/event_trigger.c | 3 | 0 |
| src/backend/commands/extension.c | 8 | 0 |
| src/backend/commands/foreigncmds.c | 11 | 0 |
| src/backend/commands/functioncmds.c | 1 | 1 |
| src/backend/commands/opclasscmds.c | 6 | 0 |
| src/backend/commands/schemacmds.c | 6 | 1 |
| src/backend/commands/sequence.c | 4 | 0 |
| src/backend/commands/tablecmds.c | 82 | 17 |
| src/backend/commands/tablespace.c | 3 | 0 |
| src/backend/commands/trigger.c | 11 | 2 |
| src/backend/commands/tsearchcmds.c | 5 | 0 |
| src/backend/commands/typecmds.c | 25 | 3 |
| src/backend/commands/user.c | 5 | 0 |
| src/backend/rewrite/rewriteDefine.c | 2 | 0 |
| src/include/catalog/heap.h | 4 | 2 |
| src/include/catalog/index.h | 2 | 1 |
| src/include/catalog/objectaccess.h | 74 | 0 |
| src/include/catalog/pg_constraint.h | 2 | 1 |
| src/include/commands/cluster.h | 1 | 1 |
| src/include/commands/tablecmds.h | 1 | 1 |
contrib/sepgsql/database.c | 27 +++++
contrib/sepgsql/expected/alter.out | 192 ++++++++++++++++++++++++++++++
contrib/sepgsql/expected/ddl.out | 9 ++
contrib/sepgsql/hooks.c | 66 ++++++++++
contrib/sepgsql/proc.c | 90 +++++++++++++-
contrib/sepgsql/relation.c | 103 ++++++++++++++--
contrib/sepgsql/schema.c | 51 ++++++++
contrib/sepgsql/sepgsql.h | 8 ++
contrib/sepgsql/sql/alter.sql | 136 +++++++++++++++++++++
contrib/sepgsql/sql/ddl.sql | 6 +
contrib/sepgsql/test_sepgsql | 2 +-
doc/src/sgml/sepgsql.sgml | 21 +++-
src/backend/catalog/aclchk.c | 9 ++
src/backend/catalog/heap.c | 41 +++++--
src/backend/catalog/index.c | 12 +-
src/backend/catalog/objectaccess.c | 45 +++++++
src/backend/catalog/pg_constraint.c | 11 +-
src/backend/catalog/pg_db_role_setting.c | 5 +-
src/backend/catalog/pg_type.c | 3 +
src/backend/commands/alter.c | 9 ++
src/backend/commands/cluster.c | 20 +++-
src/backend/commands/collationcmds.c | 1 +
src/backend/commands/dbcommands.c | 13 ++
src/backend/commands/event_trigger.c | 3 +
src/backend/commands/extension.c | 8 ++
src/backend/commands/foreigncmds.c | 11 ++
src/backend/commands/functioncmds.c | 2 +-
src/backend/commands/opclasscmds.c | 6 +
src/backend/commands/schemacmds.c | 7 +-
src/backend/commands/sequence.c | 4 +
src/backend/commands/tablecmds.c | 99 ++++++++++++---
src/backend/commands/tablespace.c | 3 +
src/backend/commands/trigger.c | 13 +-
src/backend/commands/tsearchcmds.c | 5 +
src/backend/commands/typecmds.c | 28 ++++-
src/backend/commands/user.c | 5 +
src/backend/rewrite/rewriteDefine.c | 2 +
src/include/catalog/heap.h | 6 +-
src/include/catalog/index.h | 3 +-
src/include/catalog/objectaccess.h | 74 ++++++++++++
src/include/catalog/pg_constraint.h | 3 +-
src/include/commands/cluster.h | 2 +-
src/include/commands/tablecmds.h | 2 +-
43 files changed, 1101 insertions(+), 65 deletions(-)
diff --git a/contrib/sepgsql/database.c b/contrib/sepgsql/database.c
index c15f2d0..942d179 100644
--- a/contrib/sepgsql/database.c
+++ b/contrib/sepgsql/database.c
@@ -149,6 +149,33 @@ sepgsql_database_drop(Oid databaseId)
}
/*
+ * sepgsql_database_post_alter
+ *
+ * It checks privileges to alter the supplied database
+ */
+void
+sepgsql_database_setattr(Oid databaseId)
+{
+ ObjectAddress object;
+ char *audit_name;
+
+ /*
+ * check db_database:{setattr} permission
+ */
+ object.classId = DatabaseRelationId;
+ object.objectId = databaseId;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_DATABASE,
+ SEPG_DB_DATABASE__SETATTR,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
* sepgsql_database_relabel
*
* It checks privileges to relabel the supplied database with the `seclabel'
diff --git a/contrib/sepgsql/expected/alter.out b/contrib/sepgsql/expected/alter.out
new file mode 100644
index 0000000..ef9abb3
--- /dev/null
+++ b/contrib/sepgsql/expected/alter.out
@@ -0,0 +1,192 @@
+--
+-- Test for various ALTER statements
+--
+-- clean-up in case a prior regression run failed
+SET client_min_messages TO 'warning';
+DROP DATABASE IF EXISTS regtest_sepgsql_test_database_1;
+DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
+DROP USER IF EXISTS regtest_sepgsql_test_user;
+RESET client_min_messages;
+SELECT sepgsql_getcon(); -- confirm client privilege
+ sepgsql_getcon
+-------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0
+(1 row)
+
+--
+-- CREATE Objects to be altered (with debug_audit being silent)
+--
+CREATE DATABASE regtest_sepgsql_test_database_1;
+CREATE USER regtest_sepgsql_test_user;
+CREATE SCHEMA regtest_schema_1;
+CREATE SCHEMA regtest_schema_2;
+GRANT ALL ON SCHEMA regtest_schema_1 TO public;
+GRANT ALL ON SCHEMA regtest_schema_2 TO public;
+SET search_path = regtest_schema_1, regtest_schema_2, public;
+CREATE TABLE regtest_table_1 (a int, b text);
+CREATE TABLE regtest_table_2 (c text) inherits (regtest_table_1);
+CREATE TABLE regtest_table_3 (x int primary key, y text);
+CREATE SEQUENCE regtest_seq_1;
+CREATE VIEW regtest_view_1 AS SELECT * FROM regtest_table_1 WHERE a > 0;
+CREATE FUNCTION regtest_func_1 (text) RETURNS bool
+ AS 'BEGIN RETURN true; END' LANGUAGE 'plpgsql';
+-- switch on debug_audit
+SET sepgsql.debug_audit = true;
+SET client_min_messages = LOG;
+--
+-- ALTER xxx OWNER TO
+--
+-- XXX: It should take db_xxx:{setattr} permission checks even if
+-- owner is not actually changed.
+--
+ALTER DATABASE regtest_sepgsql_test_database_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database_1"
+ALTER DATABASE regtest_sepgsql_test_database_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database_1"
+ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_1"
+ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_1"
+ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq_1"
+ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq_1"
+ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+--
+-- ALTER xxx SET SCHEMA
+--
+ALTER TABLE regtest_table_1 SET SCHEMA regtest_schema_2;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_2"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_1"
+ALTER SEQUENCE regtest_seq_1 SET SCHEMA regtest_schema_2;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_2"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq_1"
+ALTER VIEW regtest_view_1 SET SCHEMA regtest_schema_2;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_2"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2;
+LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+--
+-- ALTER xxx RENAME TO
+--
+ALTER DATABASE regtest_sepgsql_test_database_1 RENAME TO regtest_sepgsql_test_database;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database_1"
+ALTER SCHEMA regtest_schema_1 RENAME TO regtest_schema;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_1"
+ALTER TABLE regtest_table_1 RENAME TO regtest_table;
+LOG: SELinux: allowed { add_name remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_2"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_1"
+ALTER SEQUENCE regtest_seq_1 RENAME TO regtest_seq;
+LOG: SELinux: allowed { add_name remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_2"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq_1"
+ALTER VIEW regtest_view_1 RENAME TO regtest_view;
+LOG: SELinux: allowed { add_name remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_2"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_1"
+ALTER FUNCTION regtest_func_1(text) RENAME TO regtest_func;
+LOG: SELinux: allowed { add_name remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema_2"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_proc_exec_t:s0 tclass=db_procedure name="function regtest_func_1(text)"
+SET search_path = regtest_schema, regtest_schema_2, public;
+--
+-- misc ALTER commands
+--
+ALTER DATABASE regtest_sepgsql_test_database CONNECTION LIMIT 999;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_db_t:s0 tclass=db_database name="database regtest_sepgsql_test_database"
+ALTER DATABASE regtest_sepgsql_test_database SET search_path TO regtest_schema, public; -- not supported yet
+ALTER TABLE regtest_table ADD COLUMN d float;
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column d"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column d"
+ALTER TABLE regtest_table DROP COLUMN d;
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column d"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column d"
+ALTER TABLE regtest_table ALTER b SET DEFAULT 'abcd'; -- not supported yet
+ALTER TABLE regtest_table ALTER b SET DEFAULT 'XYZ'; -- not supported yet
+ALTER TABLE regtest_table ALTER b DROP DEFAULT; -- not supported yet
+ALTER TABLE regtest_table ALTER b SET NOT NULL;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column b"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column b"
+ALTER TABLE regtest_table ALTER b DROP NOT NULL;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column b"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column b"
+ALTER TABLE regtest_table ALTER b SET STATISTICS -1;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column b"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column b"
+ALTER TABLE regtest_table ALTER b SET (n_distinct = 999);
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column b"
+ALTER TABLE regtest_table ALTER b SET STORAGE PLAIN;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column b"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column b"
+ALTER TABLE regtest_table ADD CONSTRAINT test_fk FOREIGN KEY (a) REFERENCES regtest_table_3(x); -- not supported
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column a"
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_3"
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column x"
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+CONTEXT: SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column a"
+CONTEXT: SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_3"
+CONTEXT: SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+LOG: SELinux: allowed { select } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column x"
+CONTEXT: SQL statement "SELECT fk."a" FROM ONLY "regtest_schema_2"."regtest_table" fk LEFT OUTER JOIN ONLY "regtest_schema"."regtest_table_3" pk ON ( pk."x" OPERATOR(pg_catalog.=) fk."a") WHERE pk."x" IS NULL AND (fk."a" IS NOT NULL)"
+ALTER TABLE regtest_table ADD CONSTRAINT test_ck CHECK (b like '%abc%') NOT VALID; -- not supported
+ALTER TABLE regtest_table VALIDATE CONSTRAINT test_ck; -- not supported
+ALTER TABLE regtest_table DROP CONSTRAINT test_ck; -- not supported
+CREATE TRIGGER regtest_test_trig BEFORE UPDATE ON regtest_table
+ FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+ALTER TABLE regtest_table DISABLE TRIGGER regtest_test_trig; -- not supported
+ALTER TABLE regtest_table ENABLE TRIGGER regtest_test_trig; -- not supported
+CREATE RULE regtest_test_rule AS ON INSERT TO regtest_table_3 DO ALSO NOTHING;
+ALTER TABLE regtest_table_3 DISABLE RULE regtest_test_rule; -- not supported
+ALTER TABLE regtest_table_3 ENABLE RULE regtest_test_rule; -- not supported
+ALTER TABLE regtest_table SET WITH OIDS;
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column oid"
+LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column oid"
+ALTER TABLE regtest_table SET WITHOUT OIDS;
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_2 column oid"
+LOG: SELinux: allowed { drop } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column oid"
+ALTER TABLE regtest_table SET (fillfactor = 75);
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+ALTER TABLE regtest_table RESET (fillfactor);
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+ALTER TABLE regtest_table_2 NO INHERIT regtest_table; -- not supported
+ALTER TABLE regtest_table_2 INHERIT regtest_table; -- not supported
+ALTER TABLE regtest_table SET TABLESPACE pg_default;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+ALTER VIEW regtest_view SET (security_barrier);
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view"
+ALTER SEQUENCE regtest_seq INCREMENT BY 10 START WITH 1000;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq"
+--
+-- clean-up objects
+--
+RESET sepgsql.debug_audit;
+RESET client_min_messages;
+DROP DATABASE regtest_sepgsql_test_database;
+DROP SCHEMA regtest_schema CASCADE;
+NOTICE: drop cascades to 3 other objects
+DETAIL: drop cascades to table regtest_table_2
+drop cascades to table regtest_table_3
+drop cascades to constraint test_fk on table regtest_table
+DROP SCHEMA regtest_schema_2 CASCADE;
+NOTICE: drop cascades to 4 other objects
+DETAIL: drop cascades to table regtest_table
+drop cascades to sequence regtest_seq
+drop cascades to view regtest_view
+drop cascades to function regtest_func(text)
+DROP USER regtest_sepgsql_test_user;
diff --git a/contrib/sepgsql/expected/ddl.out b/contrib/sepgsql/expected/ddl.out
index 1f7ea88..d60c65b 100644
--- a/contrib/sepgsql/expected/ddl.out
+++ b/contrib/sepgsql/expected/ddl.out
@@ -1,6 +1,11 @@
--
-- Regression Test for DDL of Object Permission Checks
--
+-- clean-up in case a prior regression run failed
+SET client_min_messages TO 'warning';
+DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
+DROP USER IF EXISTS regtest_sepgsql_test_user;
+RESET client_min_messages;
-- confirm required permissions using audit messages
SELECT sepgsql_getcon(); -- confirm client privilege
sepgsql_getcon
@@ -36,6 +41,7 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column y"
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_x_seq"
ALTER TABLE regtest_table ADD COLUMN z int;
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table column z"
CREATE TABLE regtest_table_2 (a int) WITH OIDS;
@@ -61,6 +67,7 @@ CREATE SEQUENCE regtest_seq;
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_seq"
CREATE TYPE regtest_comptype AS (a int, b text);
+LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
CREATE FUNCTION regtest_func(text,int[]) RETURNS bool LANGUAGE plpgsql
AS 'BEGIN RAISE NOTICE ''regtest_func => %'', $1; RETURN true; END';
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
@@ -86,6 +93,7 @@ LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column ctid"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column x"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_3 column y"
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_seq_t:s0 tclass=db_sequence name="sequence regtest_table_3_y_seq"
CREATE VIEW regtest_view_2 AS SELECT * FROM regtest_table_3 WHERE x < y;
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_view_t:s0 tclass=db_view name="view regtest_view_2"
@@ -118,6 +126,7 @@ CREATE INDEX regtest_index_tbl4_z ON regtest_table_4(z);
LOG: SELinux: allowed { add_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
ALTER TABLE regtest_table_4 ALTER COLUMN y TYPE float;
+LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_column name="table regtest_table_4 column y"
DROP INDEX regtest_index_tbl4_y;
LOG: SELinux: allowed { remove_name } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_schema_t:s0 tclass=db_schema name="schema regtest_schema"
LOG: SELinux: allowed { setattr } scontext=unconfined_u:unconfined_r:unconfined_t:s0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0 tclass=db_table name="table regtest_table_4"
diff --git a/contrib/sepgsql/hooks.c b/contrib/sepgsql/hooks.c
index ab55d6e..5ba3dd9 100644
--- a/contrib/sepgsql/hooks.c
+++ b/contrib/sepgsql/hooks.c
@@ -188,6 +188,72 @@ sepgsql_object_access(ObjectAccessType access,
}
break;
+ case OAT_PREP_ALTER:
+ {
+ ObjectAccessPrepAlter *pa_arg = arg;
+
+ switch (classId)
+ {
+ case RelationRelationId:
+ Assert(subId == 0);
+ sepgsql_relation_set_tablespace(objectId,
+ pa_arg->tablespaceId);
+ break;
+ default:
+ /* Ignore unsupported object classes */
+ break;
+ }
+ }
+ break;
+
+ case OAT_POST_ALTER:
+ {
+ ObjectAccessPostAlter *pa_arg = arg;
+ bool is_internal = (!pa_arg ? false : pa_arg->is_internal);
+
+ switch (classId)
+ {
+ case DatabaseRelationId:
+ Assert(!is_internal);
+ sepgsql_database_setattr(objectId);
+ break;
+
+ case NamespaceRelationId:
+ Assert(!is_internal);
+ sepgsql_schema_setattr(objectId);
+ break;
+
+ case RelationRelationId:
+ if (subId == 0)
+ {
+ /*
+ * A case when we don't want to apply permission
+ * check is that relation is internally altered
+ * without user's intention. E.g, no need to
+ * check on toast table/index to be renamed at
+ * end of the table rewrites.
+ */
+ if (is_internal)
+ break;
+
+ sepgsql_relation_setattr(objectId);
+ }
+ else
+ sepgsql_attribute_setattr(objectId, subId);
+ break;
+
+ case ProcedureRelationId:
+ Assert(!is_internal);
+ sepgsql_proc_setattr(objectId);
+ break;
+
+ default:
+ /* Ignore unsupported object classes */
+ break;
+ }
+ }
+ break;
+
default:
elog(ERROR, "unexpected object access type: %d", (int) access);
break;
diff --git a/contrib/sepgsql/proc.c b/contrib/sepgsql/proc.c
index fbd358a..6124f00 100644
--- a/contrib/sepgsql/proc.c
+++ b/contrib/sepgsql/proc.c
@@ -23,6 +23,7 @@
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/syscache.h"
#include "utils/tqual.h"
#include "sepgsql.h"
@@ -43,6 +44,7 @@ sepgsql_proc_post_create(Oid functionId)
char *scontext;
char *tcontext;
char *ncontext;
+ uint32 required;
int i;
StringInfoData audit_name;
ObjectAddress object;
@@ -96,7 +98,7 @@ sepgsql_proc_post_create(Oid functionId)
SEPG_CLASS_DB_PROCEDURE);
/*
- * check db_procedure:{create} permission
+ * check db_procedure:{create (install)} permission
*/
initStringInfo(&audit_name);
appendStringInfo(&audit_name, "function %s(", NameStr(proForm->proname));
@@ -110,9 +112,13 @@ sepgsql_proc_post_create(Oid functionId)
}
appendStringInfoChar(&audit_name, ')');
+ required = SEPG_DB_PROCEDURE__CREATE;
+ if (proForm->proleakproof)
+ required |= SEPG_DB_PROCEDURE__INSTALL;
+
sepgsql_avc_check_perms_label(ncontext,
SEPG_CLASS_DB_PROCEDURE,
- SEPG_DB_PROCEDURE__CREATE,
+ required,
audit_name.data,
true);
@@ -214,3 +220,83 @@ sepgsql_proc_relabel(Oid functionId, const char *seclabel)
true);
pfree(audit_name);
}
+
+/*
+ * sepgsql_proc_setattr
+ *
+ * It checks privileges to alter the supplied function.
+ */
+void
+sepgsql_proc_setattr(Oid functionId)
+{
+ Relation rel;
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple oldtup;
+ HeapTuple newtup;
+ Form_pg_proc oldform;
+ Form_pg_proc newform;
+ uint32 required;
+ ObjectAddress object;
+ char *audit_name;
+
+ /*
+ * Fetch newer catalog
+ */
+ rel = heap_open(ProcedureRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey,
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(functionId));
+
+ sscan = systable_beginscan(rel, ProcedureOidIndexId, true,
+ SnapshotSelf, 1, &skey);
+ newtup = systable_getnext(sscan);
+ if (!HeapTupleIsValid(newtup))
+ elog(ERROR, "catalog lookup failed for function %u", functionId);
+ newform = (Form_pg_proc) GETSTRUCT(newtup);
+
+ /*
+ * Fetch older catalog
+ */
+ oldtup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId));
+ if (!HeapTupleIsValid(oldtup))
+ elog(ERROR, "cache lookup failed for function %u", functionId);
+ oldform = (Form_pg_proc) GETSTRUCT(oldtup);
+
+ /*
+ * Does this ALTER command takes operation to namespace?
+ */
+ if (newform->pronamespace != oldform->pronamespace)
+ {
+ sepgsql_schema_remove_name(oldform->pronamespace);
+ sepgsql_schema_add_name(oldform->pronamespace);
+ }
+ if (strcmp(NameStr(newform->proname), NameStr(oldform->proname)) != 0)
+ sepgsql_schema_rename(oldform->pronamespace);
+
+ /*
+ * check db_procedure:{setattr (install)} permission
+ */
+ required = SEPG_DB_PROCEDURE__SETATTR;
+ if (!oldform->proleakproof && newform->proleakproof)
+ required |= SEPG_DB_PROCEDURE__INSTALL;
+
+ object.classId = ProcedureRelationId;
+ object.objectId = functionId;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_PROCEDURE,
+ required,
+ audit_name,
+ true);
+ /* cleanups */
+ pfree(audit_name);
+
+ ReleaseSysCache(oldtup);
+ systable_endscan(sscan);
+ heap_close(rel, AccessShareLock);
+}
diff --git a/contrib/sepgsql/relation.c b/contrib/sepgsql/relation.c
index 783f330..7ed4da9 100644
--- a/contrib/sepgsql/relation.c
+++ b/contrib/sepgsql/relation.c
@@ -191,6 +191,36 @@ sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
}
/*
+ * sepgsql_attribute_setattr
+ *
+ * It checks privileges to alter the supplied column.
+ */
+void
+sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum)
+{
+ ObjectAddress object;
+ char *audit_name;
+
+ if (get_rel_relkind(relOid) != RELKIND_RELATION)
+ return;
+
+ /*
+ * check db_column:{setattr} permission
+ */
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = attnum;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_COLUMN,
+ SEPG_DB_COLUMN__SETATTR,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/*
* sepgsql_relation_post_create
*
* The post creation hook of relation/attribute
@@ -529,6 +559,13 @@ sepgsql_relation_relabel(Oid relOid, const char *seclabel)
void
sepgsql_relation_setattr(Oid relOid)
{
+ Relation rel;
+ ScanKeyData skey;
+ SysScanDesc sscan;
+ HeapTuple oldtup;
+ HeapTuple newtup;
+ Form_pg_class oldform;
+ Form_pg_class newform;
ObjectAddress object;
char *audit_name;
uint16_t tclass;
@@ -553,26 +590,78 @@ sepgsql_relation_setattr(Oid relOid)
return;
}
- object.classId = RelationRelationId;
- object.objectId = relOid;
- object.objectSubId = 0;
- audit_name = getObjectDescription(&object);
+ /*
+ * Fetch newer catalog
+ */
+ rel = heap_open(RelationRelationId, AccessShareLock);
+
+ ScanKeyInit(&skey,
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(relOid));
+
+ sscan = systable_beginscan(rel, ClassOidIndexId, true,
+ SnapshotSelf, 1, &skey);
+
+ newtup = systable_getnext(sscan);
+ if (!HeapTupleIsValid(newtup))
+ elog(ERROR, "catalog lookup failed for relation %u", relOid);
+ newform = (Form_pg_class) GETSTRUCT(newtup);
+
+ /*
+ * Fetch older catalog
+ */
+ oldtup = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid));
+ if (!HeapTupleIsValid(oldtup))
+ elog(ERROR, "cache lookup failed for relation %u", relOid);
+ oldform = (Form_pg_class) GETSTRUCT(oldtup);
/*
- * XXX - we should add checks related to namespace stuff, when
- * object_access_hook get support for ALTER statement. Right now, there is
- * no invocation path on ALTER ... RENAME TO / SET SCHEMA.
+ * Does this ALTER command takes operation to namespace?
*/
+ if (newform->relnamespace != oldform->relnamespace)
+ {
+ sepgsql_schema_remove_name(oldform->relnamespace);
+ sepgsql_schema_add_name(newform->relnamespace);
+ }
+ if (strcmp(NameStr(newform->relname), NameStr(oldform->relname)) != 0)
+ sepgsql_schema_rename(oldform->relnamespace);
/*
* check db_xxx:{setattr} permission
*/
+ object.classId = RelationRelationId;
+ object.objectId = relOid;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
sepgsql_avc_check_perms(&object,
tclass,
SEPG_DB_TABLE__SETATTR,
audit_name,
true);
pfree(audit_name);
+
+ ReleaseSysCache(oldtup);
+ systable_endscan(sscan);
+ heap_close(rel, AccessShareLock);
+}
+
+/*
+ * sepgsql_relation_set_tablespace
+ *
+ * It checks privileges to set tablespace of the supplied relation
+ */
+void
+sepgsql_relation_set_tablespace(Oid relOid, Oid tablespaceId)
+{
+ /* check db_xxx:{setattr} permission */
+ sepgsql_relation_setattr(relOid);
+
+ /*
+ * XXX - In the future version, we also check db_tuple:{use}
+ * permission onto relevant tuple in the pg_tablespace catalog.
+ */
}
/*
diff --git a/contrib/sepgsql/schema.c b/contrib/sepgsql/schema.c
index e063e39..240a6d9 100644
--- a/contrib/sepgsql/schema.c
+++ b/contrib/sepgsql/schema.c
@@ -162,3 +162,54 @@ sepgsql_schema_relabel(Oid namespaceId, const char *seclabel)
true);
pfree(audit_name);
}
+
+/*
+ * sepgsql_schema_check_perms
+ *
+ * utility routine to check db_schema:{xxx} permissions
+ */
+static void
+check_schema_perms(Oid namespaceId, uint32 required)
+{
+ ObjectAddress object;
+ char *audit_name;
+
+ object.classId = NamespaceRelationId;
+ object.objectId = namespaceId;
+ object.objectSubId = 0;
+ audit_name = getObjectDescription(&object);
+
+ sepgsql_avc_check_perms(&object,
+ SEPG_CLASS_DB_SCHEMA,
+ required,
+ audit_name,
+ true);
+ pfree(audit_name);
+}
+
+/* db_schema:{setattr} permission */
+void
+sepgsql_schema_setattr(Oid namespaceId)
+{
+ check_schema_perms(namespaceId, SEPG_DB_SCHEMA__SETATTR);
+}
+
+void
+sepgsql_schema_add_name(Oid namespaceId)
+{
+ check_schema_perms(namespaceId, SEPG_DB_SCHEMA__ADD_NAME);
+}
+
+void
+sepgsql_schema_remove_name(Oid namespaceId)
+{
+ check_schema_perms(namespaceId, SEPG_DB_SCHEMA__REMOVE_NAME);
+}
+
+void
+sepgsql_schema_rename(Oid namespaceId)
+{
+ check_schema_perms(namespaceId,
+ SEPG_DB_SCHEMA__ADD_NAME |
+ SEPG_DB_SCHEMA__REMOVE_NAME);
+}
diff --git a/contrib/sepgsql/sepgsql.h b/contrib/sepgsql/sepgsql.h
index b6dcb86..94ecbb0 100644
--- a/contrib/sepgsql/sepgsql.h
+++ b/contrib/sepgsql/sepgsql.h
@@ -293,6 +293,7 @@ extern void sepgsql_database_post_create(Oid databaseId,
const char *dtemplate);
extern void sepgsql_database_drop(Oid databaseId);
extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
+extern void sepgsql_database_setattr(Oid databaseId);
/*
* schema.c
@@ -300,6 +301,10 @@ extern void sepgsql_database_relabel(Oid databaseId, const char *seclabel);
extern void sepgsql_schema_post_create(Oid namespaceId);
extern void sepgsql_schema_drop(Oid namespaceId);
extern void sepgsql_schema_relabel(Oid namespaceId, const char *seclabel);
+extern void sepgsql_schema_setattr(Oid namespaceId);
+extern void sepgsql_schema_add_name(Oid namespaceId);
+extern void sepgsql_schema_remove_name(Oid namespaceId);
+extern void sepgsql_schema_rename(Oid namespaceId);
/*
* relation.c
@@ -308,10 +313,12 @@ extern void sepgsql_attribute_post_create(Oid relOid, AttrNumber attnum);
extern void sepgsql_attribute_drop(Oid relOid, AttrNumber attnum);
extern void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
const char *seclabel);
+extern void sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum);
extern void sepgsql_relation_post_create(Oid relOid);
extern void sepgsql_relation_drop(Oid relOid);
extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel);
extern void sepgsql_relation_setattr(Oid relOid);
+extern void sepgsql_relation_set_tablespace(Oid relOid, Oid tablespaceId);
/*
* proc.c
@@ -319,5 +326,6 @@ extern void sepgsql_relation_setattr(Oid relOid);
extern void sepgsql_proc_post_create(Oid functionId);
extern void sepgsql_proc_drop(Oid functionId);
extern void sepgsql_proc_relabel(Oid functionId, const char *seclabel);
+extern void sepgsql_proc_setattr(Oid functionId);
#endif /* SEPGSQL_H */
diff --git a/contrib/sepgsql/sql/alter.sql b/contrib/sepgsql/sql/alter.sql
new file mode 100644
index 0000000..4bded7e
--- /dev/null
+++ b/contrib/sepgsql/sql/alter.sql
@@ -0,0 +1,136 @@
+--
+-- Test for various ALTER statements
+--
+
+-- clean-up in case a prior regression run failed
+SET client_min_messages TO 'warning';
+DROP DATABASE IF EXISTS regtest_sepgsql_test_database_1;
+DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
+DROP USER IF EXISTS regtest_sepgsql_test_user;
+RESET client_min_messages;
+
+-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0
+
+--
+-- CREATE Objects to be altered (with debug_audit being silent)
+--
+CREATE DATABASE regtest_sepgsql_test_database_1;
+
+CREATE USER regtest_sepgsql_test_user;
+
+CREATE SCHEMA regtest_schema_1;
+CREATE SCHEMA regtest_schema_2;
+
+GRANT ALL ON SCHEMA regtest_schema_1 TO public;
+GRANT ALL ON SCHEMA regtest_schema_2 TO public;
+
+SET search_path = regtest_schema_1, regtest_schema_2, public;
+
+CREATE TABLE regtest_table_1 (a int, b text);
+
+CREATE TABLE regtest_table_2 (c text) inherits (regtest_table_1);
+
+CREATE TABLE regtest_table_3 (x int primary key, y text);
+
+CREATE SEQUENCE regtest_seq_1;
+
+CREATE VIEW regtest_view_1 AS SELECT * FROM regtest_table_1 WHERE a > 0;
+
+CREATE FUNCTION regtest_func_1 (text) RETURNS bool
+ AS 'BEGIN RETURN true; END' LANGUAGE 'plpgsql';
+
+-- switch on debug_audit
+SET sepgsql.debug_audit = true;
+SET client_min_messages = LOG;
+
+--
+-- ALTER xxx OWNER TO
+--
+-- XXX: It should take db_xxx:{setattr} permission checks even if
+-- owner is not actually changed.
+--
+ALTER DATABASE regtest_sepgsql_test_database_1 OWNER TO regtest_sepgsql_test_user;
+ALTER DATABASE regtest_sepgsql_test_database_1 OWNER TO regtest_sepgsql_test_user;
+ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
+ALTER SCHEMA regtest_schema_1 OWNER TO regtest_sepgsql_test_user;
+ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
+ALTER TABLE regtest_table_1 OWNER TO regtest_sepgsql_test_user;
+ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
+ALTER SEQUENCE regtest_seq_1 OWNER TO regtest_sepgsql_test_user;
+ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
+ALTER VIEW regtest_view_1 OWNER TO regtest_sepgsql_test_user;
+ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
+ALTER FUNCTION regtest_func_1(text) OWNER TO regtest_sepgsql_test_user;
+
+--
+-- ALTER xxx SET SCHEMA
+--
+ALTER TABLE regtest_table_1 SET SCHEMA regtest_schema_2;
+ALTER SEQUENCE regtest_seq_1 SET SCHEMA regtest_schema_2;
+ALTER VIEW regtest_view_1 SET SCHEMA regtest_schema_2;
+ALTER FUNCTION regtest_func_1(text) SET SCHEMA regtest_schema_2;
+
+--
+-- ALTER xxx RENAME TO
+--
+ALTER DATABASE regtest_sepgsql_test_database_1 RENAME TO regtest_sepgsql_test_database;
+ALTER SCHEMA regtest_schema_1 RENAME TO regtest_schema;
+ALTER TABLE regtest_table_1 RENAME TO regtest_table;
+ALTER SEQUENCE regtest_seq_1 RENAME TO regtest_seq;
+ALTER VIEW regtest_view_1 RENAME TO regtest_view;
+ALTER FUNCTION regtest_func_1(text) RENAME TO regtest_func;
+
+SET search_path = regtest_schema, regtest_schema_2, public;
+
+--
+-- misc ALTER commands
+--
+ALTER DATABASE regtest_sepgsql_test_database CONNECTION LIMIT 999;
+ALTER DATABASE regtest_sepgsql_test_database SET search_path TO regtest_schema, public; -- not supported yet
+
+ALTER TABLE regtest_table ADD COLUMN d float;
+ALTER TABLE regtest_table DROP COLUMN d;
+ALTER TABLE regtest_table ALTER b SET DEFAULT 'abcd'; -- not supported yet
+ALTER TABLE regtest_table ALTER b SET DEFAULT 'XYZ'; -- not supported yet
+ALTER TABLE regtest_table ALTER b DROP DEFAULT; -- not supported yet
+ALTER TABLE regtest_table ALTER b SET NOT NULL;
+ALTER TABLE regtest_table ALTER b DROP NOT NULL;
+ALTER TABLE regtest_table ALTER b SET STATISTICS -1;
+ALTER TABLE regtest_table ALTER b SET (n_distinct = 999);
+ALTER TABLE regtest_table ALTER b SET STORAGE PLAIN;
+ALTER TABLE regtest_table ADD CONSTRAINT test_fk FOREIGN KEY (a) REFERENCES regtest_table_3(x); -- not supported
+ALTER TABLE regtest_table ADD CONSTRAINT test_ck CHECK (b like '%abc%') NOT VALID; -- not supported
+ALTER TABLE regtest_table VALIDATE CONSTRAINT test_ck; -- not supported
+ALTER TABLE regtest_table DROP CONSTRAINT test_ck; -- not supported
+
+CREATE TRIGGER regtest_test_trig BEFORE UPDATE ON regtest_table
+ FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+
+ALTER TABLE regtest_table DISABLE TRIGGER regtest_test_trig; -- not supported
+ALTER TABLE regtest_table ENABLE TRIGGER regtest_test_trig; -- not supported
+
+CREATE RULE regtest_test_rule AS ON INSERT TO regtest_table_3 DO ALSO NOTHING;
+ALTER TABLE regtest_table_3 DISABLE RULE regtest_test_rule; -- not supported
+ALTER TABLE regtest_table_3 ENABLE RULE regtest_test_rule; -- not supported
+
+ALTER TABLE regtest_table SET WITH OIDS;
+ALTER TABLE regtest_table SET WITHOUT OIDS;
+ALTER TABLE regtest_table SET (fillfactor = 75);
+ALTER TABLE regtest_table RESET (fillfactor);
+ALTER TABLE regtest_table_2 NO INHERIT regtest_table; -- not supported
+ALTER TABLE regtest_table_2 INHERIT regtest_table; -- not supported
+ALTER TABLE regtest_table SET TABLESPACE pg_default;
+
+ALTER VIEW regtest_view SET (security_barrier);
+
+ALTER SEQUENCE regtest_seq INCREMENT BY 10 START WITH 1000;
+
+--
+-- clean-up objects
+--
+RESET sepgsql.debug_audit;
+RESET client_min_messages;
+DROP DATABASE regtest_sepgsql_test_database;
+DROP SCHEMA regtest_schema CASCADE;
+DROP SCHEMA regtest_schema_2 CASCADE;
+DROP USER regtest_sepgsql_test_user;
diff --git a/contrib/sepgsql/sql/ddl.sql b/contrib/sepgsql/sql/ddl.sql
index 5afe1ba..c91c4cf 100644
--- a/contrib/sepgsql/sql/ddl.sql
+++ b/contrib/sepgsql/sql/ddl.sql
@@ -2,6 +2,12 @@
-- Regression Test for DDL of Object Permission Checks
--
+-- clean-up in case a prior regression run failed
+SET client_min_messages TO 'warning';
+DROP DATABASE IF EXISTS regtest_sepgsql_test_database;
+DROP USER IF EXISTS regtest_sepgsql_test_user;
+RESET client_min_messages;
+
-- confirm required permissions using audit messages
-- @SECURITY-CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0
SET sepgsql.debug_audit = true;
diff --git a/contrib/sepgsql/test_sepgsql b/contrib/sepgsql/test_sepgsql
index 473004f..eac14ff 100755
--- a/contrib/sepgsql/test_sepgsql
+++ b/contrib/sepgsql/test_sepgsql
@@ -259,6 +259,6 @@ echo "found ${NUM}"
echo
echo "============== running sepgsql regression tests =============="
-make REGRESS="label dml ddl misc" REGRESS_OPTS="--launcher ./launcher" installcheck
+make REGRESS="label dml ddl alter misc" REGRESS_OPTS="--launcher ./launcher" installcheck
# exit with the exit code provided by "make"
diff --git a/doc/src/sgml/sepgsql.sgml b/doc/src/sgml/sepgsql.sgml
index 522aa8b..a9141ff 100644
--- a/doc/src/sgml/sepgsql.sgml
+++ b/doc/src/sgml/sepgsql.sgml
@@ -438,21 +438,36 @@ UPDATE t1 SET x = 2, y = md5sum(y) WHERE z = 100;
On creation of objects within a particular schema (tables, views,
sequences and procedures), <literal>add_name</> will be also checked
on the schema, not only <literal>create</> on the new object itself.
+ On <xref linkend="sql-createfunction">, <literal>install</> permission
+ will be checked if <literal>leakproof</> attribute was given, not only
+ <literal>create</> on the new function.
</para>
<para>
When <literal>DROP</> command is executed, <literal>drop</> will be
checked on the object being removed for each object types. Permissions
- will not be checked for objects dropped indirectly via <literal>CASCADE</>.
+ will also be checked for objects dropped indirectly via <literal>CASCADE</>.
Deletion of objects contained within a particular schema (tables, views,
sequences and procedures) additionally requires
<literal>remove_name</> on the schema.
</para>
<para>
+ When <literal>ALTER</> command is executed, <literal>setattr</> will be
+ checked on the object being modified for each object types.
+ In addition, <literal>add_name</> and <literal>remove_name</> permission
+ will be checked towards relevant schema when we try to rename or set
+ new schema on the altered object.
+ A few additional checks are applied depending on object types.
+ On <xref linkend="sql-alterfunction">, <literal>install</> permission
+ will be checked if <literal>leakproof</> attribute was turned on, not
+ only <literal>setattr</> on the new function.
+ </para>
+
+ <para>
When objects that are subsidiary of other objects (such as a table's indexes
- or triggers) are created or dropped, <literal>setattr</> permission will be
- checked on the main object, instead of the subsidiary object itself.
+ or triggers) are created, dropped or altered, <literal>setattr</> permission
+ will be checked on the main object, instead of the subsidiary object itself.
</para>
<para>
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 4e4c7af..07788d9 100644
--- a/src/backend/catalog/aclchk.c
+++ b/src/backend/catalog/aclchk.c
@@ -25,6 +25,7 @@
#include "catalog/catalog.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_conversion.h"
@@ -1288,6 +1289,14 @@ SetDefaultACL(InternalDefaultACL *iacls)
iacls->roleid,
noldmembers, oldmembers,
nnewmembers, newmembers);
+
+ /* Post create or alter hook of this default ACL */
+ if (isNew)
+ InvokeObjectPostCreateHook(DefaultAclRelationId,
+ HeapTupleGetOid(newtuple), 0);
+ else
+ InvokeObjectPostAlterHook(DefaultAclRelationId,
+ HeapTupleGetOid(newtuple), 0);
}
if (HeapTupleIsValid(tuple))
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 54de9a7..f482656 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -95,8 +95,9 @@ static Oid AddNewRelationType(const char *typeName,
static void RelationRemoveInheritance(Oid relid);
static void StoreRelCheck(Relation rel, char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount,
- bool is_no_inherit);
-static void StoreConstraints(Relation rel, List *cooked_constraints);
+ bool is_no_inherit, bool is_internal);
+static void StoreConstraints(Relation rel, List *cooked_constraints,
+ bool is_internal);
static bool MergeWithExistingConstraint(Relation rel, char *ccname, Node *expr,
bool allow_merge, bool is_local,
bool is_no_inherit);
@@ -1286,7 +1287,7 @@ heap_create_with_catalog(const char *relname,
* entry, so the relation must be valid and self-consistent at this point.
* In particular, there are not yet constraints and defaults anywhere.
*/
- StoreConstraints(new_rel_desc, cooked_constraints);
+ StoreConstraints(new_rel_desc, cooked_constraints, is_internal);
/*
* If there's a special on-commit action, remember it
@@ -1799,7 +1800,8 @@ heap_drop_with_catalog(Oid relid)
* Store a default expression for column attnum of relation rel.
*/
void
-StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr)
+StoreAttrDefault(Relation rel, AttrNumber attnum,
+ Node *expr, bool is_internal)
{
char *adbin;
char *adsrc;
@@ -1891,6 +1893,17 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr)
* Record dependencies on objects used in the expression, too.
*/
recordDependencyOnExpr(&defobject, expr, NIL, DEPENDENCY_NORMAL);
+
+ /*
+ * Post creation hook of this attribute defaults
+ *
+ * XXX - Note that ALTER TABLE ALTER COLUMN SET/DROP DEFAULT is
+ * implemented with a couple of deletion/creation of the attribute's
+ * default entry, so the callee should check existence of an older
+ * version of this entry if needed to distinguish.
+ */
+ InvokeObjectPostCreateHookArg(AttrDefaultRelationId,
+ RelationGetRelid(rel), attnum, is_internal);
}
/*
@@ -1902,7 +1915,7 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr)
static void
StoreRelCheck(Relation rel, char *ccname, Node *expr,
bool is_validated, bool is_local, int inhcount,
- bool is_no_inherit)
+ bool is_no_inherit, bool is_internal)
{
char *ccbin;
char *ccsrc;
@@ -1986,7 +1999,8 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
ccsrc, /* Source form of check constraint */
is_local, /* conislocal */
inhcount, /* coninhcount */
- is_no_inherit); /* connoinherit */
+ is_no_inherit, /* connoinherit */
+ is_internal); /* internally constructed? */
pfree(ccbin);
pfree(ccsrc);
@@ -2001,7 +2015,7 @@ StoreRelCheck(Relation rel, char *ccname, Node *expr,
* and StoreRelCheck (see AddRelationNewConstraints()).
*/
static void
-StoreConstraints(Relation rel, List *cooked_constraints)
+StoreConstraints(Relation rel, List *cooked_constraints, bool is_internal)
{
int numchecks = 0;
ListCell *lc;
@@ -2023,11 +2037,12 @@ StoreConstraints(Relation rel, List *cooked_constraints)
switch (con->contype)
{
case CONSTR_DEFAULT:
- StoreAttrDefault(rel, con->attnum, con->expr);
+ StoreAttrDefault(rel, con->attnum, con->expr, is_internal);
break;
case CONSTR_CHECK:
StoreRelCheck(rel, con->name, con->expr, !con->skip_validation,
- con->is_local, con->inhcount, con->is_no_inherit);
+ con->is_local, con->inhcount,
+ con->is_no_inherit, is_internal);
numchecks++;
break;
default:
@@ -2053,6 +2068,7 @@ StoreConstraints(Relation rel, List *cooked_constraints)
* newConstraints: list of Constraint nodes
* allow_merge: TRUE if check constraints may be merged with existing ones
* is_local: TRUE if definition is local, FALSE if it's inherited
+ * is_internal: TRUE if constraint is constructed unless user's intention
*
* All entries in newColDefaults will be processed. Entries in newConstraints
* will be processed only if they are CONSTR_CHECK type.
@@ -2070,7 +2086,8 @@ AddRelationNewConstraints(Relation rel,
List *newColDefaults,
List *newConstraints,
bool allow_merge,
- bool is_local)
+ bool is_local,
+ bool is_internal)
{
List *cookedConstraints = NIL;
TupleDesc tupleDesc;
@@ -2133,7 +2150,7 @@ AddRelationNewConstraints(Relation rel,
(IsA(expr, Const) &&((Const *) expr)->constisnull))
continue;
- StoreAttrDefault(rel, colDef->attnum, expr);
+ StoreAttrDefault(rel, colDef->attnum, expr, is_internal);
cooked = (CookedConstraint *) palloc(sizeof(CookedConstraint));
cooked->contype = CONSTR_DEFAULT;
@@ -2259,7 +2276,7 @@ AddRelationNewConstraints(Relation rel,
* OK, store it.
*/
StoreRelCheck(rel, ccname, expr, !cdef->skip_validation, is_local,
- is_local ? 0 : 1, cdef->is_no_inherit);
+ is_local ? 0 : 1, cdef->is_no_inherit, is_internal);
numchecks++;
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index b1091ac..bc20725 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -932,7 +932,8 @@ index_create(Relation heapRelation,
false, /* already marked primary */
false, /* pg_index entry is OK */
false, /* no old dependencies */
- allow_system_table_mods);
+ allow_system_table_mods,
+ is_internal);
}
else
{
@@ -1106,6 +1107,7 @@ index_create(Relation heapRelation,
* remove_old_dependencies: if true, remove existing dependencies of index
* on table's columns
* allow_system_table_mods: allow table to be a system catalog
+ * is_internal: index is constructed due to internal process
*/
void
index_constraint_create(Relation heapRelation,
@@ -1118,7 +1120,8 @@ index_constraint_create(Relation heapRelation,
bool mark_as_primary,
bool update_pgindex,
bool remove_old_dependencies,
- bool allow_system_table_mods)
+ bool allow_system_table_mods,
+ bool is_internal)
{
Oid namespaceId = RelationGetNamespace(heapRelation);
ObjectAddress myself,
@@ -1183,7 +1186,8 @@ index_constraint_create(Relation heapRelation,
NULL,
true, /* islocal */
0, /* inhcount */
- true); /* noinherit */
+ true, /* noinherit */
+ is_internal);
/*
* Register the index as internally dependent on the constraint.
@@ -1292,6 +1296,8 @@ index_constraint_create(Relation heapRelation,
{
simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
CatalogUpdateIndexes(pg_index, indexTuple);
+ InvokeObjectPostAlterHookArg(IndexRelationId, indexRelationId, 0,
+ InvalidOid, is_internal);
}
heap_freetuple(indexTuple);
diff --git a/src/backend/catalog/objectaccess.c b/src/backend/catalog/objectaccess.c
index 79c1136..cf48bef 100644
--- a/src/backend/catalog/objectaccess.c
+++ b/src/backend/catalog/objectaccess.c
@@ -61,3 +61,48 @@ RunObjectDropHook(Oid classId, Oid objectId, int subId,
classId, objectId, subId,
(void *) &drop_arg);
}
+
+/*
+ * RunObjectPrepAlterHook
+ *
+ * It is entrypoint of OAT_PREP_ALTER event
+ */
+void
+RunObjectPrepAlterHook(Oid classId, Oid objectId, int subId,
+ Oid tablespaceId)
+{
+ ObjectAccessPrepAlter pa_arg;
+
+ /* XXX - should be checked at caller side */
+ Assert(object_access_hook != NULL);
+
+ memset(&pa_arg, 0, sizeof(ObjectAccessPrepAlter));
+ pa_arg.tablespaceId = tablespaceId;
+
+ (*object_access_hook)(OAT_PREP_ALTER,
+ classId, objectId, subId,
+ (void *) &pa_arg);
+}
+
+/*
+ * RunObjectPostAlterHook
+ *
+ * It is entrypoint of OAT_POST_ALTER event
+ */
+void
+RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
+ Oid auxiliaryId, bool is_internal)
+{
+ ObjectAccessPostAlter pa_arg;
+
+ /* XXX - should be checked at caller side */
+ Assert(object_access_hook != NULL);
+
+ memset(&pa_arg, 0, sizeof(ObjectAccessPostAlter));
+ pa_arg.auxiliary_id = auxiliaryId;
+ pa_arg.is_internal = is_internal;
+
+ (*object_access_hook)(OAT_POST_ALTER,
+ classId, objectId, subId,
+ (void *) &pa_arg);
+}
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 1e6d947..de5bc81 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -68,7 +68,8 @@ CreateConstraintEntry(const char *constraintName,
const char *conSrc,
bool conIsLocal,
int conInhCount,
- bool conNoInherit)
+ bool conNoInherit,
+ bool is_internal)
{
Relation conDesc;
Oid conOid;
@@ -367,7 +368,8 @@ CreateConstraintEntry(const char *constraintName,
}
/* Post creation hook for new constraint */
- InvokeObjectPostCreateHook(ConstraintRelationId, conOid, 0);
+ InvokeObjectPostCreateHookArg(ConstraintRelationId, conOid, 0,
+ is_internal);
return conOid;
}
@@ -665,6 +667,9 @@ RenameConstraintById(Oid conId, const char *newname)
/* update the system catalog indexes */
CatalogUpdateIndexes(conDesc, tuple);
+ /* Post alter hook for this constraint */
+ InvokeObjectPostAlterHook(ConstraintRelationId, conId, 0);
+
heap_freetuple(tuple);
heap_close(conDesc, RowExclusiveLock);
}
@@ -736,6 +741,8 @@ AlterConstraintNamespaces(Oid ownerId, Oid oldNspId,
* changeDependencyFor().
*/
}
+ /* Post alter hook for the constraint */
+ InvokeObjectPostAlterHook(ConstraintRelationId, thisobj.objectId, 0);
add_exact_object_address(&thisobj, objsMoved);
}
diff --git a/src/backend/catalog/pg_db_role_setting.c b/src/backend/catalog/pg_db_role_setting.c
index 616980c..9a0ead7 100644
--- a/src/backend/catalog/pg_db_role_setting.c
+++ b/src/backend/catalog/pg_db_role_setting.c
@@ -14,6 +14,7 @@
#include "access/heapam.h"
#include "access/htup_details.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_db_role_setting.h"
#include "utils/fmgroids.h"
#include "utils/rel.h"
@@ -159,7 +160,9 @@ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
/* Update indexes */
CatalogUpdateIndexes(rel, newtuple);
}
-
+ /* Post alter hook for this database-role-settings */
+ InvokeObjectPostAlterHookArg(DbRoleSettingRelationId,
+ databaseid, 0, roleid, false);
systable_endscan(scan);
/* Close pg_db_role_setting, but keep lock till commit */
diff --git a/src/backend/catalog/pg_type.c b/src/backend/catalog/pg_type.c
index cf0ebcc..8c756eb 100644
--- a/src/backend/catalog/pg_type.c
+++ b/src/backend/catalog/pg_type.c
@@ -712,6 +712,9 @@ RenameTypeInternal(Oid typeOid, const char *newTypeName, Oid typeNamespace)
/* update the system catalog indexes */
CatalogUpdateIndexes(pg_type_desc, tuple);
+ /* Post alter hook for this type */
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
heap_freetuple(tuple);
heap_close(pg_type_desc, RowExclusiveLock);
diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index 6f08210..5b257ff 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -19,6 +19,7 @@
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_largeobject.h"
#include "catalog/pg_largeobject_metadata.h"
#include "catalog/pg_namespace.h"
@@ -177,6 +178,9 @@ AlterObjectRename_internal(Relation rel, Oid objectId, const char *new_name)
simple_heap_update(rel, &oldtup->t_self, newtup);
CatalogUpdateIndexes(rel, newtup);
+ /* Post alter hook of the object */
+ InvokeObjectPostAlterHook(classId, objectId, 0);
+
/* Release memory */
pfree(values);
pfree(nulls);
@@ -560,6 +564,9 @@ AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid)
changeDependencyFor(classId, objid,
NamespaceRelationId, oldNspOid, nspOid);
+ /* Post alter hook for the object */
+ InvokeObjectPostAlterHook(classId, objid, 0);
+
return oldNspOid;
}
@@ -837,4 +844,6 @@ AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
pfree(nulls);
pfree(replaces);
}
+ /* Post alter hook for the object */
+ InvokeObjectPostAlterHook(classId, objectId, 0);
}
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index c3deb56..65abd20 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -26,6 +26,7 @@
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/toasting.h"
#include "commands/cluster.h"
#include "commands/tablecmds.h"
@@ -465,7 +466,7 @@ check_index_is_clusterable(Relation OldHeap, Oid indexOid, bool recheck, LOCKMOD
* otherwise concurrent executions of RelationGetIndexList could miss indexes.
*/
void
-mark_index_clustered(Relation rel, Oid indexOid)
+mark_index_clustered(Relation rel, Oid indexOid, bool is_internal)
{
HeapTuple indexTuple;
Form_pg_index indexForm;
@@ -525,6 +526,9 @@ mark_index_clustered(Relation rel, Oid indexOid)
simple_heap_update(pg_index, &indexTuple->t_self, indexTuple);
CatalogUpdateIndexes(pg_index, indexTuple);
}
+ /* Post object alter hook of this index */
+ InvokeObjectPostAlterHookArg(IndexRelationId, thisIndexOid, 0,
+ InvalidOid, is_internal);
heap_freetuple(indexTuple);
}
@@ -552,7 +556,7 @@ rebuild_relation(Relation OldHeap, Oid indexOid,
/* Mark the correct index as clustered */
if (OidIsValid(indexOid))
- mark_index_clustered(OldHeap, indexOid);
+ mark_index_clustered(OldHeap, indexOid, true);
/* Remember if it's a system catalog */
is_system_catalog = IsSystemRelation(OldHeap);
@@ -1257,6 +1261,14 @@ swap_relation_files(Oid r1, Oid r2, bool target_is_pg_class,
}
/*
+ * Post alter hook of these relations, but with is_internal=true
+ */
+ InvokeObjectPostAlterHookArg(RelationRelationId, r1, 0,
+ InvalidOid, true);
+ InvokeObjectPostAlterHookArg(RelationRelationId, r2, 0,
+ InvalidOid, true);
+
+ /*
* If we have toast tables associated with the relations being swapped,
* deal with them too.
*/
@@ -1495,13 +1507,13 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u",
OIDOldHeap);
RenameRelationInternal(newrel->rd_rel->reltoastrelid,
- NewToastName);
+ NewToastName, true);
/* ... and its index too */
snprintf(NewToastName, NAMEDATALEN, "pg_toast_%u_index",
OIDOldHeap);
RenameRelationInternal(toastidx,
- NewToastName);
+ NewToastName, true);
}
relation_close(newrel, NoLock);
}
diff --git a/src/backend/commands/collationcmds.c b/src/backend/commands/collationcmds.c
index 458b573..9eecd2b 100644
--- a/src/backend/commands/collationcmds.c
+++ b/src/backend/commands/collationcmds.c
@@ -20,6 +20,7 @@
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_collation_fn.h"
#include "commands/alter.h"
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 09c06ed..8695a52 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -965,6 +965,9 @@ RenameDatabase(const char *oldname, const char *newname)
simple_heap_update(rel, &newtup->t_self, newtup);
CatalogUpdateIndexes(rel, newtup);
+ /* Post alter hook for this database */
+ InvokeObjectPostAlterHook(DatabaseRelationId, db_id, 0);
+
/*
* Close pg_database, but keep lock till commit.
*/
@@ -1200,6 +1203,10 @@ movedb(const char *dbname, const char *tblspcname)
/* Update indexes */
CatalogUpdateIndexes(pgdbrel, newtuple);
+ /* Post alter hook for this database */
+ InvokeObjectPostAlterHook(DatabaseRelationId,
+ HeapTupleGetOid(newtuple), 0);
+
systable_endscan(sysscan);
/*
@@ -1394,6 +1401,10 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel)
/* Update indexes */
CatalogUpdateIndexes(rel, newtuple);
+ /* Post alter hook for this database */
+ InvokeObjectPostAlterHook(DatabaseRelationId,
+ HeapTupleGetOid(newtuple), 0);
+
systable_endscan(scan);
/* Close pg_database, but keep lock till commit */
@@ -1526,6 +1537,8 @@ AlterDatabaseOwner(const char *dbname, Oid newOwnerId)
changeDependencyOnOwner(DatabaseRelationId, HeapTupleGetOid(tuple),
newOwnerId);
}
+ /* Post alter hook for the database */
+ InvokeObjectPostAlterHook(DatabaseRelationId, HeapTupleGetOid(tuple), 0);
systable_endscan(scan);
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index 97dde84..ad32c9b 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -491,6 +491,9 @@ AlterEventTriggerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
changeDependencyOnOwner(EventTriggerRelationId,
HeapTupleGetOid(tup),
newOwnerId);
+ /* Post alter hook for the event trigger */
+ InvokeObjectPostAlterHook(EventTriggerRelationId,
+ HeapTupleGetOid(tup), 0);
}
/*
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index e45de83..d067fec 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2360,6 +2360,9 @@ AlterExtensionNamespace(List *names, const char *newschema)
/* update dependencies to point to the new schema */
changeDependencyFor(ExtensionRelationId, extensionOid,
NamespaceRelationId, oldNspOid, nspOid);
+
+ /* Post alter hook for the extension */
+ InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
}
/*
@@ -2640,6 +2643,9 @@ ApplyExtensionUpdates(Oid extensionOid,
recordDependencyOn(&myself, &otherext, DEPENDENCY_NORMAL);
}
+ /* Post alter hook for this extension */
+ InvokeObjectPostAlterHook(ExtensionRelationId, extensionOid, 0);
+
/*
* Finally, execute the update script file
*/
@@ -2745,6 +2751,8 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
DEPENDENCY_EXTENSION) != 1)
elog(ERROR, "unexpected number of extension dependency records");
}
+ /* Post alter hook of this extension */
+ InvokeObjectPostAlterHook(ExtensionRelationId, extension.objectId, 0);
/*
* If get_object_address() opened the relation for us, we close it to keep
diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c
index e2f86d2..5cb6c2f 100644
--- a/src/backend/commands/foreigncmds.c
+++ b/src/backend/commands/foreigncmds.c
@@ -241,6 +241,9 @@ AlterForeignDataWrapperOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerI
HeapTupleGetOid(tup),
newOwnerId);
}
+ /* Post alter hook for the FDW */
+ InvokeObjectPostAlterHook(ForeignDataWrapperRelationId,
+ HeapTupleGetOid(tup), 0);
}
/*
@@ -344,6 +347,9 @@ AlterForeignServerOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
changeDependencyOnOwner(ForeignServerRelationId, HeapTupleGetOid(tup),
newOwnerId);
}
+ /* Post alter hook for the foreign server */
+ InvokeObjectPostAlterHook(ForeignServerRelationId,
+ HeapTupleGetOid(tup), 0);
}
/*
@@ -751,6 +757,8 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
}
+ /* Post alter hook of this FDW */
+ InvokeObjectPostAlterHook(ForeignDataWrapperRelationId, fdwId, 0);
heap_close(rel, RowExclusiveLock);
}
@@ -978,6 +986,9 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
simple_heap_update(rel, &tp->t_self, tp);
CatalogUpdateIndexes(rel, tp);
+ /* Post alter hook of this foreign server */
+ InvokeObjectPostAlterHook(ForeignServerRelationId, srvId, 0);
+
heap_freetuple(tp);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 26a806b..91f9fdc 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -1222,7 +1222,7 @@ AlterFunction(AlterFunctionStmt *stmt)
/* Do the update */
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
-
+ InvokeObjectPostAlterHook(ProcedureRelationId, funcOid, 0);
heap_close(rel, NoLock);
heap_freetuple(tup);
}
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
index c8e0e75..35f10b5 100644
--- a/src/backend/commands/opclasscmds.c
+++ b/src/backend/commands/opclasscmds.c
@@ -1370,6 +1370,9 @@ storeOperators(List *opfamilyname, Oid amoid,
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
}
+ /* Post create hook of this access method operator */
+ InvokeObjectPostCreateHook(AccessMethodOperatorRelationId,
+ entryoid, 0);
}
heap_close(rel, RowExclusiveLock);
@@ -1469,6 +1472,9 @@ storeProcedures(List *opfamilyname, Oid amoid,
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_AUTO);
}
+ /* Post create hook of access method procedure */
+ InvokeObjectPostCreateHook(AccessMethodProcedureRelationId,
+ entryoid, 0);
}
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/commands/schemacmds.c b/src/backend/commands/schemacmds.c
index e69c86b..9d4d75e 100644
--- a/src/backend/commands/schemacmds.c
+++ b/src/backend/commands/schemacmds.c
@@ -21,6 +21,7 @@
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_namespace.h"
#include "commands/dbcommands.h"
#include "commands/schemacmds.h"
@@ -235,6 +236,8 @@ RenameSchema(const char *oldname, const char *newname)
simple_heap_update(rel, &tup->t_self, tup);
CatalogUpdateIndexes(rel, tup);
+ InvokeObjectPostAlterHook(NamespaceRelationId, HeapTupleGetOid(tup), 0);
+
heap_close(rel, NoLock);
heap_freetuple(tup);
}
@@ -363,5 +366,7 @@ AlterSchemaOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
changeDependencyOnOwner(NamespaceRelationId, HeapTupleGetOid(tup),
newOwnerId);
}
-
+ /* Post alter hook for the namespace */
+ InvokeObjectPostAlterHook(NamespaceRelationId,
+ HeapTupleGetOid(tup), 0);
}
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 634ce3f..3829003 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -19,6 +19,7 @@
#include "access/xlogutils.h"
#include "catalog/dependency.h"
#include "catalog/namespace.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "commands/sequence.h"
@@ -482,6 +483,9 @@ AlterSequence(AlterSeqStmt *stmt)
if (owned_by)
process_owned_by(seqrel, owned_by);
+ /* Post alter hook of this sequence */
+ InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
+
relation_close(seqrel, NoLock);
}
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index d516e2a..90b00fe 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -663,7 +663,7 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId)
*/
if (rawDefaults || stmt->constraints)
AddRelationNewConstraints(rel, rawDefaults, stmt->constraints,
- true, true);
+ true, true, false);
/*
* Clean up. We keep lock on new relation (although it shouldn't be
@@ -1955,6 +1955,11 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid,
recordDependencyOn(&childobject, &parentobject, DEPENDENCY_NORMAL);
+ /* Post creation hook of this inheritance */
+ InvokeObjectPostAlterHookArg(InheritsRelationId,
+ relationId, 0,
+ parentOid, false);
+
/*
* Mark the parent as having subclasses.
*/
@@ -2213,6 +2218,9 @@ renameatt_internal(Oid myrelid,
/* keep system catalog indexes current */
CatalogUpdateIndexes(attrelation, atttup);
+ /* Post alter hook for this attribute */
+ InvokeObjectPostAlterHook(RelationRelationId, myrelid, attnum);
+
heap_freetuple(atttup);
heap_close(attrelation, RowExclusiveLock);
@@ -2357,7 +2365,7 @@ rename_constraint_internal(Oid myrelid,
|| con->contype == CONSTRAINT_UNIQUE
|| con->contype == CONSTRAINT_EXCLUSION))
/* rename the index; this renames the constraint as well */
- RenameRelationInternal(con->conindid, newconname);
+ RenameRelationInternal(con->conindid, newconname, false);
else
RenameConstraintById(constraintOid, newconname);
@@ -2433,7 +2441,7 @@ RenameRelation(RenameStmt *stmt)
}
/* Do the work */
- RenameRelationInternal(relid, stmt->newname);
+ RenameRelationInternal(relid, stmt->newname, false);
}
/*
@@ -2446,7 +2454,7 @@ RenameRelation(RenameStmt *stmt)
* sequence, AFAIK there's no need for it to be there.
*/
void
-RenameRelationInternal(Oid myrelid, const char *newrelname)
+RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal)
{
Relation targetrelation;
Relation relrelation; /* for RELATION relation */
@@ -2488,6 +2496,10 @@ RenameRelationInternal(Oid myrelid, const char *newrelname)
/* keep the system catalog indexes current */
CatalogUpdateIndexes(relrelation, reltup);
+ /* Post alter hook for this relation */
+ InvokeObjectPostAlterHookArg(RelationRelationId, myrelid, 0,
+ InvalidOid, is_internal);
+
heap_freetuple(reltup);
heap_close(relrelation, RowExclusiveLock);
@@ -3309,7 +3321,9 @@ ATExecCmd(List **wqueue, AlteredTableInfo *tab, Relation rel,
*/
break;
case AT_SetTableSpace: /* SET TABLESPACE */
-
+ InvokeObjectPrepAlterHookArg(RelationRelationId,
+ RelationGetRelid(rel), 0,
+ tab->newTableSpace);
/*
* Nothing to do here; Phase 3 does the work
*/
@@ -4489,7 +4503,8 @@ ATExecAddColumn(List **wqueue, AlteredTableInfo *tab, Relation rel,
* This function is intended for CREATE TABLE, so it processes a
* _list_ of defaults, but we just do one.
*/
- AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
+ AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
+ false, true, false);
/* Make the additional catalog changes visible */
CommandCounterIncrement();
@@ -4826,6 +4841,8 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
/* keep the system catalog indexes current */
CatalogUpdateIndexes(attr_rel, tuple);
}
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel), attnum);
heap_close(attr_rel, RowExclusiveLock);
}
@@ -4878,6 +4895,8 @@ ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
/* Tell Phase 3 it needs to test the constraint */
tab->new_notnull = true;
}
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel), attnum);
heap_close(attr_rel, RowExclusiveLock);
}
@@ -4933,7 +4952,8 @@ ATExecColumnDefault(Relation rel, const char *colName,
* This function is intended for CREATE TABLE, so it processes a
* _list_ of defaults, but we just do one.
*/
- AddRelationNewConstraints(rel, list_make1(rawEnt), NIL, false, true);
+ AddRelationNewConstraints(rel, list_make1(rawEnt), NIL,
+ false, true, false);
}
}
@@ -5017,6 +5037,9 @@ ATExecSetStatistics(Relation rel, const char *colName, Node *newValue, LOCKMODE
/* keep system catalog indexes current */
CatalogUpdateIndexes(attrelation, tuple);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attrtuple->attnum);
heap_freetuple(tuple);
heap_close(attrelation, RowExclusiveLock);
@@ -5074,13 +5097,17 @@ ATExecSetOptions(Relation rel, const char *colName, Node *options,
repl_repl[Anum_pg_attribute_attoptions - 1] = true;
newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrelation),
repl_val, repl_null, repl_repl);
- ReleaseSysCache(tuple);
/* Update system catalog. */
simple_heap_update(attrelation, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(attrelation, newtuple);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attrtuple->attnum);
heap_freetuple(newtuple);
+ ReleaseSysCache(tuple);
+
heap_close(attrelation, RowExclusiveLock);
}
@@ -5150,6 +5177,9 @@ ATExecSetStorage(Relation rel, const char *colName, Node *newValue, LOCKMODE loc
/* keep system catalog indexes current */
CatalogUpdateIndexes(attrelation, tuple);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ attrtuple->attnum);
heap_freetuple(tuple);
heap_close(attrelation, RowExclusiveLock);
@@ -5464,7 +5494,7 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
ereport(NOTICE,
(errmsg("ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index \"%s\" to \"%s\"",
indexName, constraintName)));
- RenameRelationInternal(index_oid, constraintName);
+ RenameRelationInternal(index_oid, constraintName, false);
}
/* Extra checks needed if making primary key */
@@ -5488,7 +5518,8 @@ ATExecAddIndexConstraint(AlteredTableInfo *tab, Relation rel,
stmt->primary,
true, /* update pg_index */
true, /* remove old dependencies */
- allowSystemTableMods);
+ allowSystemTableMods,
+ false); /* is_internal */
index_close(indexRel, NoLock);
}
@@ -5600,7 +5631,8 @@ ATAddCheckConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
newcons = AddRelationNewConstraints(rel, NIL,
list_make1(copyObject(constr)),
recursing, /* allow_merge */
- !recursing); /* is_local */
+ !recursing, /* is_local */
+ is_readd); /* is_internal */
/* Add each to-be-validated constraint to Phase 3's queue */
foreach(lcon, newcons)
@@ -6050,7 +6082,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
NULL,
true, /* islocal */
0, /* inhcount */
- true); /* isnoinherit */
+ true, /* isnoinherit */
+ false); /* is_internal */
/*
* Create the triggers that will enforce the constraint.
@@ -6232,6 +6265,8 @@ ATExecValidateConstraint(Relation rel, char *constrName, bool recurse,
copy_con->convalidated = true;
simple_heap_update(conrel, ©Tuple->t_self, copyTuple);
CatalogUpdateIndexes(conrel, copyTuple);
+ InvokeObjectPostAlterHook(ConstraintRelationId,
+ HeapTupleGetOid(tuple), 0);
heap_freetuple(copyTuple);
}
@@ -7659,6 +7694,10 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
*/
RemoveStatistics(RelationGetRelid(rel), attnum);
+ /* Post alter hook of this column */
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel), attnum);
+
/*
* Update the default, if present, by brute force --- remove and re-add
* the default. Probably unsafe to take shortcuts, since the new version
@@ -7678,7 +7717,7 @@ ATExecAlterColumnType(AlteredTableInfo *tab, Relation rel,
RemoveAttrDefault(RelationGetRelid(rel), attnum, DROP_RESTRICT, true,
true);
- StoreAttrDefault(rel, attnum, defaultexpr);
+ StoreAttrDefault(rel, attnum, defaultexpr, true);
}
/* Cleanup */
@@ -7769,10 +7808,13 @@ ATExecAlterColumnGenericOptions(Relation rel,
newtuple = heap_modify_tuple(tuple, RelationGetDescr(attrel),
repl_val, repl_null, repl_repl);
- ReleaseSysCache(tuple);
simple_heap_update(attrel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(attrel, newtuple);
+ InvokeObjectPostAlterHook(RelationRelationId,
+ RelationGetRelid(rel),
+ atttableform->attnum);
+ ReleaseSysCache(tuple);
heap_close(attrel, RowExclusiveLock);
@@ -8244,6 +8286,8 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing, LOCKMODE lock
change_owner_recurse_to_sequences(relationOid, newOwnerId, lockmode);
}
}
+ /* Post alter hook of this relation */
+ InvokeObjectPostAlterHook(RelationRelationId, relationOid, 0);
ReleaseSysCache(tuple);
heap_close(class_rel, RowExclusiveLock);
@@ -8406,7 +8450,7 @@ ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
check_index_is_clusterable(rel, indexOid, false, lockmode);
/* And do the work */
- mark_index_clustered(rel, indexOid);
+ mark_index_clustered(rel, indexOid, false);
}
/*
@@ -8418,7 +8462,7 @@ ATExecClusterOn(Relation rel, const char *indexName, LOCKMODE lockmode)
static void
ATExecDropCluster(Relation rel, LOCKMODE lockmode)
{
- mark_index_clustered(rel, InvalidOid);
+ mark_index_clustered(rel, InvalidOid, false);
}
/*
@@ -8538,6 +8582,8 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
CatalogUpdateIndexes(pgclass, newtuple);
+ InvokeObjectPostAlterHook(RelationRelationId, RelationGetRelid(rel), 0);
+
heap_freetuple(newtuple);
ReleaseSysCache(tuple);
@@ -8595,6 +8641,10 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
CatalogUpdateIndexes(pgclass, newtuple);
+ InvokeObjectPostAlterHookArg(RelationRelationId,
+ RelationGetRelid(toastrel), 0,
+ InvalidOid, true);
+
heap_freetuple(newtuple);
ReleaseSysCache(tuple);
@@ -8732,7 +8782,9 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode)
rd_rel->relfilenode = newrelfilenode;
simple_heap_update(pg_class, &tuple->t_self, tuple);
CatalogUpdateIndexes(pg_class, tuple);
-
+ InvokeObjectPostAlterHookArg(RelationRelationId,
+ RelationGetRelid(rel), 0,
+ InvalidOid, true);
heap_freetuple(tuple);
heap_close(pg_class, RowExclusiveLock);
@@ -9421,6 +9473,11 @@ ATExecDropInherit(Relation rel, RangeVar *parent, LOCKMODE lockmode)
RelationRelationId,
RelationGetRelid(parent_rel));
+ /* Post alter hook of this inherits */
+ InvokeObjectPostAlterHookArg(InheritsRelationId,
+ RelationGetRelid(rel), 0,
+ RelationGetRelid(parent_rel), false);
+
/* keep our lock on the parent relation until commit */
heap_close(parent_rel, NoLock);
}
@@ -9603,6 +9660,7 @@ ATExecAddOf(Relation rel, const TypeName *ofTypename, LOCKMODE lockmode)
((Form_pg_class) GETSTRUCT(classtuple))->reloftype = typeid;
simple_heap_update(relationRelation, &classtuple->t_self, classtuple);
CatalogUpdateIndexes(relationRelation, classtuple);
+ InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
heap_freetuple(classtuple);
heap_close(relationRelation, RowExclusiveLock);
@@ -9643,6 +9701,7 @@ ATExecDropOf(Relation rel, LOCKMODE lockmode)
((Form_pg_class) GETSTRUCT(tuple))->reloftype = InvalidOid;
simple_heap_update(relationRelation, &tuple->t_self, tuple);
CatalogUpdateIndexes(relationRelation, tuple);
+ InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
heap_freetuple(tuple);
heap_close(relationRelation, RowExclusiveLock);
}
@@ -9712,6 +9771,9 @@ ATExecGenericOptions(Relation rel, List *options)
simple_heap_update(ftrel, &tuple->t_self, tuple);
CatalogUpdateIndexes(ftrel, tuple);
+ InvokeObjectPostAlterHook(ForeignTableRelationId,
+ RelationGetRelid(rel), 0);
+
heap_close(ftrel, RowExclusiveLock);
heap_freetuple(tuple);
@@ -9865,6 +9927,9 @@ AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
NameStr(classForm->relname));
add_exact_object_address(&thisobj, objsMoved);
+
+ /* Post alter hook for this relation */
+ InvokeObjectPostAlterHook(RelationRelationId, relOid, 0);
}
heap_freetuple(classTup);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index e794ecf..ade5d75 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -862,6 +862,8 @@ RenameTableSpace(const char *oldname, const char *newname)
/* OK, update the entry */
AlterObjectRename_internal(rel, tableSpaceId, newname);
+ InvokeObjectPostAlterHook(TableSpaceRelationId, tableSpaceId, 0);
+
heap_close(rel, NoLock);
}
@@ -925,6 +927,7 @@ AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
/* Update system catalog. */
simple_heap_update(rel, &newtuple->t_self, newtuple);
CatalogUpdateIndexes(rel, newtuple);
+ InvokeObjectPostAlterHook(TableSpaceRelationId, HeapTupleGetOid(tup), 0);
heap_freetuple(newtuple);
/* Conclude heap scan. */
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 4a369a4..311edef 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -445,7 +445,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
NULL,
true, /* islocal */
0, /* inhcount */
- true); /* isnoinherit */
+ true, /* isnoinherit */
+ isInternal); /* is_internal */
}
/*
@@ -741,7 +742,8 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
DEPENDENCY_NORMAL);
/* Post creation hook for new trigger */
- InvokeObjectPostCreateHook(TriggerRelationId, trigoid, 0);
+ InvokeObjectPostCreateHookArg(TriggerRelationId, trigoid, 0,
+ isInternal);
/* Keep lock on target rel until end of xact */
heap_close(rel, NoLock);
@@ -1273,6 +1275,10 @@ renametrig(RenameStmt *stmt)
/* keep system catalog indexes current */
CatalogUpdateIndexes(tgrel, tuple);
+ /* Post alter hook for this trigger */
+ InvokeObjectPostAlterHook(TriggerRelationId,
+ HeapTupleGetOid(tuple), 0);
+
/*
* Invalidate relation's relcache entry so that other backends (and
* this one too!) are sent SI message to make them rebuild relcache
@@ -1386,6 +1392,9 @@ EnableDisableTrigger(Relation rel, const char *tgname,
changed = true;
}
+ /* Post alter hook for this trigger */
+ InvokeObjectPostAlterHook(TriggerRelationId,
+ HeapTupleGetOid(tuple), 0);
}
systable_endscan(tgscan);
diff --git a/src/backend/commands/tsearchcmds.c b/src/backend/commands/tsearchcmds.c
index 64e9885..61342d2 100644
--- a/src/backend/commands/tsearchcmds.c
+++ b/src/backend/commands/tsearchcmds.c
@@ -608,6 +608,8 @@ AlterTSDictionary(AlterTSDictionaryStmt *stmt)
CatalogUpdateIndexes(rel, newtup);
+ InvokeObjectPostAlterHook(TSDictionaryRelationId, dictId, 0);
+
/*
* NOTE: because we only support altering the options, not the template,
* there is no need to update dependencies. This might have to change if
@@ -1171,6 +1173,9 @@ AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
/* Update dependencies */
makeConfigurationDependencies(tup, true, relMap);
+ InvokeObjectPostAlterHook(TSConfigMapRelationId,
+ HeapTupleGetOid(tup), 0);
+
heap_close(relMap, RowExclusiveLock);
ReleaseSysCache(tup);
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 36de6d7..b9fff13 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -39,6 +39,7 @@
#include "catalog/dependency.h"
#include "catalog/heap.h"
#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
#include "catalog/pg_authid.h"
#include "catalog/pg_collation.h"
#include "catalog/pg_constraint.h"
@@ -1210,6 +1211,9 @@ AlterEnum(AlterEnumStmt *stmt, bool isTopLevel)
stmt->newValNeighbor, stmt->newValIsAfter,
stmt->skipIfExists);
+ /* Post alter hook of this enum type */
+ InvokeObjectPostAlterHook(TypeRelationId, enum_type_oid, 0);
+
ReleaseSysCache(tup);
}
@@ -2183,7 +2187,8 @@ AlterDomainDefault(List *names, Node *defaultRaw)
typTup->typcollation,
defaultExpr,
true); /* Rebuild is true */
-
+ /* Post alter hook of this domain */
+ InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
/* Clean up */
heap_close(rel, NoLock);
heap_freetuple(newtuple);
@@ -2280,6 +2285,9 @@ AlterDomainNotNull(List *names, bool notNull)
CatalogUpdateIndexes(typrel, tup);
+ /* Post alter hook of this domain */
+ InvokeObjectPostAlterHook(TypeRelationId, domainoid, 0);
+
/* Clean up */
heap_freetuple(tup);
heap_close(typrel, RowExclusiveLock);
@@ -2561,6 +2569,8 @@ AlterDomainValidateConstraint(List *names, char *constrName)
copy_con->convalidated = true;
simple_heap_update(conrel, ©Tuple->t_self, copyTuple);
CatalogUpdateIndexes(conrel, copyTuple);
+ InvokeObjectPostAlterHook(ConstraintRelationId,
+ HeapTupleGetOid(copyTuple), 0);
heap_freetuple(copyTuple);
systable_endscan(scan);
@@ -2959,7 +2969,8 @@ domainAddConstraint(Oid domainOid, Oid domainNamespace, Oid baseTypeOid,
ccsrc, /* Source form of check constraint */
true, /* is local */
0, /* inhcount */
- false); /* connoinherit */
+ false, /* connoinherit */
+ false); /* is_internal */
/*
* Return the compiled constraint expression so the calling routine can
@@ -3154,7 +3165,7 @@ RenameType(RenameStmt *stmt)
* RenameRelationInternal will call RenameTypeInternal automatically.
*/
if (typTup->typtype == TYPTYPE_COMPOSITE)
- RenameRelationInternal(typTup->typrelid, newTypeName);
+ RenameRelationInternal(typTup->typrelid, newTypeName, false);
else
RenameTypeInternal(typeOid, newTypeName,
typTup->typnamespace);
@@ -3275,6 +3286,9 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
/* Update owner dependency reference */
changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
+ /* Post alter hook of this type */
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
/* If it has an array type, update that too */
if (OidIsValid(typTup->typarray))
AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
@@ -3295,6 +3309,8 @@ AlterTypeOwner(List *names, Oid newOwnerId, ObjectType objecttype)
*
* hasDependEntry should be TRUE if type is expected to have a pg_shdepend
* entry (ie, it's not a table rowtype nor an array type).
+ * is_primary_ops should be TRUE if this function is invoked with user's
+ * direct operation (e.g, shdepReassignOwned). Elsewhere,
*/
void
AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
@@ -3328,6 +3344,9 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
if (OidIsValid(typTup->typarray))
AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
+ /* Post alter hook for the type */
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
/* Clean up */
heap_close(rel, RowExclusiveLock);
}
@@ -3513,6 +3532,9 @@ AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
elog(ERROR, "failed to change schema dependency for type %s",
format_type_be(typeOid));
+ /* Post alter hook for this type */
+ InvokeObjectPostAlterHook(TypeRelationId, typeOid, 0);
+
heap_freetuple(tup);
heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index c1b7b93..2b17675 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -775,6 +775,9 @@ AlterRole(AlterRoleStmt *stmt)
/* Update indexes */
CatalogUpdateIndexes(pg_authid_rel, new_tuple);
+ /* Post alter hook of this role */
+ InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
+
ReleaseSysCache(tuple);
heap_freetuple(new_tuple);
@@ -1128,6 +1131,8 @@ RenameRole(const char *oldname, const char *newname)
CatalogUpdateIndexes(rel, newtuple);
+ InvokeObjectPostAlterHook(AuthIdRelationId, roleid, 0);
+
ReleaseSysCache(oldtuple);
/*
diff --git a/src/backend/rewrite/rewriteDefine.c b/src/backend/rewrite/rewriteDefine.c
index 17e3513..6f7e87d 100644
--- a/src/backend/rewrite/rewriteDefine.c
+++ b/src/backend/rewrite/rewriteDefine.c
@@ -733,6 +733,8 @@ EnableDisableRule(Relation rel, const char *rulename,
changed = true;
}
+ InvokeObjectPostAlterHook(RewriteRelationId,
+ HeapTupleGetOid(ruletup), 0);
heap_freetuple(ruletup);
heap_close(pg_rewrite_desc, RowExclusiveLock);
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index a35829b..5d335e0 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.h
@@ -95,9 +95,11 @@ extern List *AddRelationNewConstraints(Relation rel,
List *newColDefaults,
List *newConstraints,
bool allow_merge,
- bool is_local);
+ bool is_local,
+ bool is_internal);
-extern void StoreAttrDefault(Relation rel, AttrNumber attnum, Node *expr);
+extern void StoreAttrDefault(Relation rel, AttrNumber attnum,
+ Node *expr, bool is_internal);
extern Node *cookDefault(ParseState *pstate,
Node *raw_default,
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index b96099f..225ee73 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -72,7 +72,8 @@ extern void index_constraint_create(Relation heapRelation,
bool mark_as_primary,
bool update_pgindex,
bool remove_old_dependencies,
- bool allow_system_table_mods);
+ bool allow_system_table_mods,
+ bool is_internal);
extern void index_drop(Oid indexId, bool concurrent);
diff --git a/src/include/catalog/objectaccess.h b/src/include/catalog/objectaccess.h
index 3e080ba..aac090a 100644
--- a/src/include/catalog/objectaccess.h
+++ b/src/include/catalog/objectaccess.h
@@ -22,12 +22,23 @@
* OAT_DROP should be invoked just before deletion of objects; typically
* deleteOneObject(). Its arguments are packed within ObjectAccessDrop.
*
+ * OAT_PREP_ALTER should be invoked prior to actual works of alter commends,
+ * but limited on some cases when OAT_POST_ALTER does not work well. Right
+ * now, all the cases of this events are ALTER TABLE ... SET TABLESPACE.
+ *
+ * OAT_POST_ALTER should be invoked just after the object is altered.
+ * The command-counter is not incremented prior to invocation of this hook,
+ * extension can reference two different version of system catalog using
+ * SnapshotNow and SnapshotSelf, to identify which field was altered.
+ *
* Other types may be added in the future.
*/
typedef enum ObjectAccessType
{
OAT_POST_CREATE,
OAT_DROP,
+ OAT_PREP_ALTER,
+ OAT_POST_ALTER,
} ObjectAccessType;
/*
@@ -56,6 +67,43 @@ typedef struct
} ObjectAccessDrop;
/*
+ * Arguments of OAT_PREP_ALTER event
+ */
+typedef struct
+{
+ /*
+ * It is used to inform Oid of new tablespace on ALTER TABLE ... SET
+ * TABLESPACE command. Its system catalog is updated after whole the
+ * table rewrite even if it is very large, so we put prep-alter hook
+ * prior to actual works.
+ */
+ Oid tablespaceId;
+} ObjectAccessPrepAlter;
+
+
+/*
+ * Arguments of OAT_POST_ALTER event
+ */
+typedef struct
+{
+ /*
+ * This identifier is used when system catalog takes two IDs
+ * to identify a particular tuple of the catalog.
+ * It is only used when the caller want to identify an entry
+ * of pg_inherits, pg_db_role_setting or pg_user_mapping.
+ * Elsewhere, InvalidOid should be set.
+ */
+ Oid auxiliary_id;
+
+ /*
+ * This flag informs extensions whether the context of this alter
+ * is invoked by user's operations, or not. E.g, it shall be dealt
+ * as internal stuff on indexing due to type changes.
+ */
+ bool is_internal;
+} ObjectAccessPostAlter;
+
+/*
* Hook, and a macro to invoke it.
*/
typedef void (*object_access_hook_type) (ObjectAccessType access,
@@ -70,6 +118,10 @@ extern void RunObjectPostCreateHook(Oid classId, Oid objectId, int subId,
bool is_internal);
extern void RunObjectDropHook(Oid classId, Oid objectId, int subId,
int dropflags);
+extern void RunObjectPrepAlterHook(Oid classId, Oid objectId, int subId,
+ Oid tablespaceId);
+extern void RunObjectPostAlterHook(Oid classId, Oid objectId, int subId,
+ Oid auxiliaryId, bool is_internal);
#define InvokeObjectPostCreateHook(classId,objectId,subId) \
InvokeObjectPostCreateHookArg((classId),(objectId),(subId),false)
@@ -89,4 +141,26 @@ extern void RunObjectDropHook(Oid classId, Oid objectId, int subId,
(dropflags)); \
} while(0)
+#define InvokeObjectPrepAlterHook(classId,objectId,subId) \
+ InvokeObjectPrepAlterHookArg((classId),(objectId),(subId), \
+ InvalidOid)
+#define InvokeObjectPrepAlterHookArg(classId,objectId,subId, \
+ tablespaceId) \
+ do { \
+ if (object_access_hook) \
+ RunObjectPrepAlterHook((classId),(objectId),(subId), \
+ (tablespaceId)); \
+ } while(0)
+
+#define InvokeObjectPostAlterHook(classId,objectId,subId) \
+ InvokeObjectPostAlterHookArg((classId),(objectId),(subId), \
+ InvalidOid,false)
+#define InvokeObjectPostAlterHookArg(classId,objectId,subId, \
+ auxiliaryId,is_internal) \
+ do { \
+ if (object_access_hook) \
+ RunObjectPostAlterHook((classId),(objectId),(subId), \
+ (auxiliaryId),(is_internal)); \
+ } while(0)
+
#endif /* OBJECTACCESS_H */
diff --git a/src/include/catalog/pg_constraint.h b/src/include/catalog/pg_constraint.h
index e4e9c40..9c88e51 100644
--- a/src/include/catalog/pg_constraint.h
+++ b/src/include/catalog/pg_constraint.h
@@ -232,7 +232,8 @@ extern Oid CreateConstraintEntry(const char *constraintName,
const char *conSrc,
bool conIsLocal,
int conInhCount,
- bool conNoInherit);
+ bool conNoInherit,
+ bool is_internal);
extern void RemoveConstraintById(Oid conId);
extern void RenameConstraintById(Oid conId, const char *newname);
diff --git a/src/include/commands/cluster.h b/src/include/commands/cluster.h
index 21b2a58..490b3ba 100644
--- a/src/include/commands/cluster.h
+++ b/src/include/commands/cluster.h
@@ -23,7 +23,7 @@ extern void cluster_rel(Oid tableOid, Oid indexOid, bool recheck,
bool verbose, int freeze_min_age, int freeze_table_age);
extern void check_index_is_clusterable(Relation OldHeap, Oid indexOid,
bool recheck, LOCKMODE lockmode);
-extern void mark_index_clustered(Relation rel, Oid indexOid);
+extern void mark_index_clustered(Relation rel, Oid indexOid, bool is_internal);
extern Oid make_new_heap(Oid OIDOldHeap, Oid NewTableSpace);
extern void finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 4f32062..2ddcbc6 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -58,7 +58,7 @@ extern void RenameConstraint(RenameStmt *stmt);
extern void RenameRelation(RenameStmt *stmt);
extern void RenameRelationInternal(Oid myrelid,
- const char *newrelname);
+ const char *newrelname, bool is_internal);
extern void find_composite_type_dependencies(Oid typeOid,
Relation origRelation,