diff --git a/src/common/backend/catalog/information_schema.sql b/src/common/backend/catalog/information_schema.sql index c8b24cbea..ef35c6a49 100644 --- a/src/common/backend/catalog/information_schema.sql +++ b/src/common/backend/catalog/information_schema.sql @@ -745,7 +745,29 @@ CREATE VIEW columns AS CAST(CASE WHEN c.relkind = 'r' OR (c.relkind in ('v', 'f') AND pg_column_is_updatable(c.oid, a.attnum, false)) - THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable, + CAST( + CASE WHEN t.typtype = 'd' THEN + CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY' + WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(t.typbasetype, null) + ELSE 'USER-DEFINED' END + ELSE + CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY' + WHEN nt.nspname = 'pg_catalog' THEN pg_catalog.format_type(a.atttypid, null) + ELSE 'USER-DEFINED' END + END + AS character_data) + AS COLUMN_TYPE, + CAST(d.description AS information_schema.character_data) AS COLUMN_COMMENT, + CAST( + CASE WHEN ad.adsrc = 'AUTO_INCREMENT' THEN 'AUTO_INCREMENT' + ELSE + CASE WHEN ad.adsrc_on_update is not null THEN CONCAT('DEFAULT_GENERATED on update ', ad.adsrc_on_update) + ELSE null + END + END + AS character_data) + AS EXTRA FROM (pg_attribute a LEFT JOIN pg_attrdef ad ON attrelid = adrelid AND attnum = adnum) JOIN (pg_class c JOIN pg_namespace nc ON (c.relnamespace = nc.oid)) ON a.attrelid = c.oid @@ -754,6 +776,7 @@ CREATE VIEW columns AS ON (t.typtype = 'd' AND t.typbasetype = bt.oid) LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + LEFT JOIN pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum WHERE (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) @@ -1889,10 +1912,12 @@ CREATE VIEW tables AS THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into, CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed, - CAST(null AS character_data) AS commit_action + CAST(null AS character_data) AS commit_action, + CAST(d.description AS information_schema.character_data) AS TABLE_COMMENT FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace) LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid) + LEFT JOIN pg_description d on d.objoid = c.oid and objsubid = 0 WHERE c.relkind IN ('r', 'm', 'v', 'f') AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') diff --git a/src/common/backend/utils/init/globals.cpp b/src/common/backend/utils/init/globals.cpp index b2b2b4a1d..ade668a27 100644 --- a/src/common/backend/utils/init/globals.cpp +++ b/src/common/backend/utils/init/globals.cpp @@ -77,7 +77,7 @@ bool will_shutdown = false; * ********************************************/ -const uint32 GRAND_VERSION_NUM = 92973; +const uint32 GRAND_VERSION_NUM = 92974; /******************************************** * 2.VERSION NUM FOR EACH FEATURE diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_974.sql b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_974.sql new file mode 100644 index 000000000..bc4edaf0c --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_maindb/rollback-post_catalog_maindb_92_974.sql @@ -0,0 +1,355 @@ +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0; + +SET search_path TO information_schema; + + +DO $$ +DECLARE + function_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_proc + WHERE proname = 'pg_relation_is_updatable' + ) INTO function_exists; + IF function_exists THEN + DROP VIEW IF EXISTS information_schema.tables CASCADE; + CREATE VIEW tables AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + + CAST( + CASE WHEN nc.oid = pg_catalog.pg_my_temp_schema() THEN 'LOCAL TEMPORARY' + WHEN c.relkind = 'r' THEN 'BASE TABLE' + WHEN c.relkind = 'm' THEN 'MATERIALIZED VIEW' + WHEN c.relkind = 'v' THEN 'VIEW' + WHEN c.relkind = 'f' THEN 'FOREIGN TABLE' + ELSE null END + AS character_data) AS table_type, + + CAST(null AS sql_identifier) AS self_referencing_column_name, + CAST(null AS character_data) AS reference_generation, + + CAST(CASE WHEN t.typname IS NOT NULL THEN pg_catalog.current_database() ELSE null END AS sql_identifier) AS user_defined_type_catalog, + CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema, + CAST(t.typname AS sql_identifier) AS user_defined_type_name, + + CAST(CASE WHEN c.relkind = 'r' OR + (c.relkind in ('v', 'f') AND + -- 1 << CMD_INSERT + pg_relation_is_updatable(c.oid, false) & 8 = 8) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into, + + CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed, + CAST(null AS character_data) AS commit_action + + FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace) + LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid) + + WHERE c.relkind IN ('r', 'm', 'v', 'f') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') + OR pg_catalog.has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') ); + END IF; +END $$; + + +DO $$ +DECLARE + function_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_proc + WHERE proname = 'pg_column_is_updatable' + ) INTO function_exists; + IF function_exists THEN + + DROP VIEW IF EXISTS information_schema.columns CASCADE; + CREATE VIEW columns AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + CAST(a.attname AS sql_identifier) AS column_name, + CAST(a.attnum AS cardinal_number) AS ordinal_position, + CAST(CASE WHEN ad.adgencol <> 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS column_default, + CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END + AS yes_or_no) + AS is_nullable, + + CAST( + CASE WHEN t.typtype = 'd' THEN + CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY' + WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(t.typbasetype, null) + ELSE 'USER-DEFINED' END + ELSE + CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY' + WHEN nt.nspname = 'pg_catalog' THEN pg_catalog.format_type(a.atttypid, null) + ELSE 'USER-DEFINED' END + END + AS character_data) + AS data_type, + + CAST( + _pg_char_max_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_maximum_length, + + CAST( + _pg_char_octet_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_octet_length, + + CAST( + _pg_numeric_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision, + + CAST( + _pg_numeric_precision_radix(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision_radix, + + CAST( + _pg_numeric_scale(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_scale, + + CAST( + _pg_datetime_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS datetime_precision, + + CAST( + _pg_interval_type(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS character_data) + AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + + CAST(CASE WHEN t.typtype = 'd' THEN pg_catalog.current_database() ELSE null END + AS sql_identifier) AS domain_catalog, + CAST(CASE WHEN t.typtype = 'd' THEN nt.nspname ELSE null END + AS sql_identifier) AS domain_schema, + CAST(CASE WHEN t.typtype = 'd' THEN t.typname ELSE null END + AS sql_identifier) AS domain_name, + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(coalesce(nbt.nspname, nt.nspname) AS sql_identifier) AS udt_schema, + CAST(coalesce(bt.typname, t.typname) AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST(a.attnum AS sql_identifier) AS dtd_identifier, + CAST('NO' AS yes_or_no) AS is_self_referencing, + + CAST('NO' AS yes_or_no) AS is_identity, + CAST(null AS character_data) AS identity_generation, + CAST(null AS character_data) AS identity_start, + CAST(null AS character_data) AS identity_increment, + CAST(null AS character_data) AS identity_maximum, + CAST(null AS character_data) AS identity_minimum, + CAST(null AS yes_or_no) AS identity_cycle, + + CAST(CASE WHEN ad.adgencol = 's' THEN 'ALWAYS' ELSE 'NEVER' END AS character_data) AS is_generated, + CAST(CASE WHEN ad.adgencol = 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS generation_expression, + + CAST(CASE WHEN c.relkind = 'r' + OR (c.relkind in ('v', 'f') AND pg_column_is_updatable(c.oid, a.attnum, false)) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable + + FROM (pg_attribute a LEFT JOIN pg_attrdef ad ON attrelid = adrelid AND attnum = adnum) + JOIN (pg_class c JOIN pg_namespace nc ON (c.relnamespace = nc.oid)) ON a.attrelid = c.oid + JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON a.atttypid = t.oid + LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON (bt.typnamespace = nbt.oid)) + ON (t.typtype = 'd' AND t.typbasetype = bt.oid) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + + WHERE (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + + AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind in ('r', 'm', 'v', 'f') + + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_column_privilege(c.oid, a.attnum, + 'SELECT, INSERT, UPDATE, REFERENCES')); + END IF; +END $$; + + +DO $$ +DECLARE + view_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_class c + JOIN pg_namespace n ON c.relnamespace = n.oid + WHERE c.relname = 'data_type_privileges' + AND n.nspname = 'information_schema' + AND c.relkind = 'v' + ) INTO view_exists; + IF NOT view_exists THEN + CREATE VIEW data_type_privileges AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(x.objschema AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS dtd_identifier + + FROM + ( + SELECT udt_schema, udt_name, 'USER-DEFINED TYPE'::text, dtd_identifier FROM attributes + UNION ALL + SELECT table_schema, table_name, 'TABLE'::text, dtd_identifier FROM columns + UNION ALL + SELECT domain_schema, domain_name, 'DOMAIN'::text, dtd_identifier FROM domains + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM parameters + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM routines + ) AS x (objschema, objname, objtype, objdtdid); + END IF; +END $$; + + +DO $$ +DECLARE + view_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_class c + JOIN pg_namespace n ON c.relnamespace = n.oid + WHERE c.relname = 'element_types' + AND n.nspname = 'information_schema' + AND c.relkind = 'v' + ) INTO view_exists; + IF NOT view_exists THEN + CREATE VIEW element_types AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(n.nspname AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS collection_type_identifier, + CAST( + CASE WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(bt.oid, null) + ELSE 'USER-DEFINED' END AS character_data) AS data_type, + + CAST(null AS cardinal_number) AS character_maximum_length, + CAST(null AS cardinal_number) AS character_octet_length, + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + CAST(null AS cardinal_number) AS numeric_precision, + CAST(null AS cardinal_number) AS numeric_precision_radix, + CAST(null AS cardinal_number) AS numeric_scale, + CAST(null AS cardinal_number) AS datetime_precision, + CAST(null AS character_data) AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS character_data) AS domain_default, -- XXX maybe a bug in the standard + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(nbt.nspname AS sql_identifier) AS udt_schema, + CAST(bt.typname AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST('a' || CAST(x.objdtdid AS text) AS sql_identifier) AS dtd_identifier + + FROM pg_namespace n, pg_type at, pg_namespace nbt, pg_type bt, + ( + /* columns, attributes */ + SELECT c.relnamespace, CAST(c.relname AS sql_identifier), + CASE WHEN c.relkind = 'c' THEN 'USER-DEFINED TYPE'::text ELSE 'TABLE'::text END, + a.attnum, a.atttypid, a.attcollation + FROM pg_class c, pg_attribute a + WHERE c.oid = a.attrelid + AND c.relkind IN ('r', 'm', 'v', 'f', 'c') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND attnum > 0 AND NOT attisdropped + + UNION ALL + + /* domains */ + SELECT t.typnamespace, CAST(t.typname AS sql_identifier), + 'DOMAIN'::text, 1, t.typbasetype, t.typcollation + FROM pg_type t + WHERE t.typtype = 'd' + + UNION ALL + + /* parameters */ + SELECT pronamespace, CAST(proname || '_' || CAST(oid AS text) AS sql_identifier), + 'ROUTINE'::text, (ss.x).n, (ss.x).x, 0 + FROM (SELECT p.pronamespace, p.proname, p.oid, + _pg_expandarray(coalesce(p.proallargtypes, p.proargtypes::oid[])) AS x + FROM pg_proc p) AS ss + + UNION ALL + + /* result types */ + SELECT p.pronamespace, CAST(p.proname || '_' || CAST(p.oid AS text) AS sql_identifier), + 'ROUTINE'::text, 0, p.prorettype, 0 + FROM pg_proc p + + ) AS x (objschema, objname, objtype, objdtdid, objtypeid, objcollation) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON x.objcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + + WHERE n.oid = x.objschema + AND at.oid = x.objtypeid + AND (at.typelem <> 0 AND at.typlen = -1) + AND at.typelem = bt.oid + AND nbt.oid = bt.typnamespace + + AND (n.nspname, x.objname, x.objtype, CAST(x.objdtdid AS sql_identifier)) IN + ( SELECT object_schema, object_name, object_type, dtd_identifier + FROM data_type_privileges ); + END IF; +END $$; + + +do $$DECLARE + user_name text; + query_str text; +BEGIN + SELECT SESSION_USER INTO user_name; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.element_types TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.data_type_privileges TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.tables TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.columns TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; +END$$; + +GRANT SELECT ON information_schema.element_types TO PUBLIC; +GRANT SELECT ON information_schema.data_type_privileges TO PUBLIC; +GRANT SELECT ON information_schema.tables TO PUBLIC; +GRANT SELECT ON information_schema.columns TO PUBLIC; + +RESET search_path; diff --git a/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_974.sql b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_974.sql new file mode 100644 index 000000000..9e61dbf6e --- /dev/null +++ b/src/include/catalog/upgrade_sql/rollback_catalog_otherdb/rollback-post_catalog_otherdb_92_974.sql @@ -0,0 +1,355 @@ +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0; + +SET search_path TO information_schema; + + +DO $$ +DECLARE + function_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_proc + WHERE proname = 'pg_relation_is_updatable' + ) INTO function_exists; + IF function_exists THEN + DROP VIEW IF EXISTS information_schema.tables CASCADE; + CREATE VIEW tables AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + + CAST( + CASE WHEN nc.oid = pg_catalog.pg_my_temp_schema() THEN 'LOCAL TEMPORARY' + WHEN c.relkind = 'r' THEN 'BASE TABLE' + WHEN c.relkind = 'm' THEN 'MATERIALIZED VIEW' + WHEN c.relkind = 'v' THEN 'VIEW' + WHEN c.relkind = 'f' THEN 'FOREIGN TABLE' + ELSE null END + AS character_data) AS table_type, + + CAST(null AS sql_identifier) AS self_referencing_column_name, + CAST(null AS character_data) AS reference_generation, + + CAST(CASE WHEN t.typname IS NOT NULL THEN pg_catalog.current_database() ELSE null END AS sql_identifier) AS user_defined_type_catalog, + CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema, + CAST(t.typname AS sql_identifier) AS user_defined_type_name, + + CAST(CASE WHEN c.relkind = 'r' OR + (c.relkind in ('v', 'f') AND + -- 1 << CMD_INSERT + pg_relation_is_updatable(c.oid, false) & 8 = 8) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into, + + CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed, + CAST(null AS character_data) AS commit_action + + FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace) + LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid) + + WHERE c.relkind IN ('r', 'm', 'v', 'f') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') + OR pg_catalog.has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') ); + END IF; +END $$; + + +DO $$ +DECLARE + function_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_proc + WHERE proname = 'pg_column_is_updatable' + ) INTO function_exists; + IF function_exists THEN + + DROP VIEW IF EXISTS information_schema.columns CASCADE; + CREATE VIEW columns AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + CAST(a.attname AS sql_identifier) AS column_name, + CAST(a.attnum AS cardinal_number) AS ordinal_position, + CAST(CASE WHEN ad.adgencol <> 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS column_default, + CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END + AS yes_or_no) + AS is_nullable, + + CAST( + CASE WHEN t.typtype = 'd' THEN + CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY' + WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(t.typbasetype, null) + ELSE 'USER-DEFINED' END + ELSE + CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY' + WHEN nt.nspname = 'pg_catalog' THEN pg_catalog.format_type(a.atttypid, null) + ELSE 'USER-DEFINED' END + END + AS character_data) + AS data_type, + + CAST( + _pg_char_max_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_maximum_length, + + CAST( + _pg_char_octet_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_octet_length, + + CAST( + _pg_numeric_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision, + + CAST( + _pg_numeric_precision_radix(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision_radix, + + CAST( + _pg_numeric_scale(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_scale, + + CAST( + _pg_datetime_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS datetime_precision, + + CAST( + _pg_interval_type(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS character_data) + AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + + CAST(CASE WHEN t.typtype = 'd' THEN pg_catalog.current_database() ELSE null END + AS sql_identifier) AS domain_catalog, + CAST(CASE WHEN t.typtype = 'd' THEN nt.nspname ELSE null END + AS sql_identifier) AS domain_schema, + CAST(CASE WHEN t.typtype = 'd' THEN t.typname ELSE null END + AS sql_identifier) AS domain_name, + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(coalesce(nbt.nspname, nt.nspname) AS sql_identifier) AS udt_schema, + CAST(coalesce(bt.typname, t.typname) AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST(a.attnum AS sql_identifier) AS dtd_identifier, + CAST('NO' AS yes_or_no) AS is_self_referencing, + + CAST('NO' AS yes_or_no) AS is_identity, + CAST(null AS character_data) AS identity_generation, + CAST(null AS character_data) AS identity_start, + CAST(null AS character_data) AS identity_increment, + CAST(null AS character_data) AS identity_maximum, + CAST(null AS character_data) AS identity_minimum, + CAST(null AS yes_or_no) AS identity_cycle, + + CAST(CASE WHEN ad.adgencol = 's' THEN 'ALWAYS' ELSE 'NEVER' END AS character_data) AS is_generated, + CAST(CASE WHEN ad.adgencol = 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS generation_expression, + + CAST(CASE WHEN c.relkind = 'r' + OR (c.relkind in ('v', 'f') AND pg_column_is_updatable(c.oid, a.attnum, false)) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable + + FROM (pg_attribute a LEFT JOIN pg_attrdef ad ON attrelid = adrelid AND attnum = adnum) + JOIN (pg_class c JOIN pg_namespace nc ON (c.relnamespace = nc.oid)) ON a.attrelid = c.oid + JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON a.atttypid = t.oid + LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON (bt.typnamespace = nbt.oid)) + ON (t.typtype = 'd' AND t.typbasetype = bt.oid) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + + WHERE (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + + AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind in ('r', 'm', 'v', 'f') + + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_column_privilege(c.oid, a.attnum, + 'SELECT, INSERT, UPDATE, REFERENCES')); + END IF; +END $$; + + +DO $$ +DECLARE + view_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_class c + JOIN pg_namespace n ON c.relnamespace = n.oid + WHERE c.relname = 'data_type_privileges' + AND n.nspname = 'information_schema' + AND c.relkind = 'v' + ) INTO view_exists; + IF NOT view_exists THEN + CREATE VIEW data_type_privileges AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(x.objschema AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS dtd_identifier + + FROM + ( + SELECT udt_schema, udt_name, 'USER-DEFINED TYPE'::text, dtd_identifier FROM attributes + UNION ALL + SELECT table_schema, table_name, 'TABLE'::text, dtd_identifier FROM columns + UNION ALL + SELECT domain_schema, domain_name, 'DOMAIN'::text, dtd_identifier FROM domains + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM parameters + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM routines + ) AS x (objschema, objname, objtype, objdtdid); + END IF; +END $$; + + +DO $$ +DECLARE + view_exists BOOLEAN; +BEGIN + SELECT EXISTS ( + SELECT 1 + FROM pg_class c + JOIN pg_namespace n ON c.relnamespace = n.oid + WHERE c.relname = 'element_types' + AND n.nspname = 'information_schema' + AND c.relkind = 'v' + ) INTO view_exists; + IF NOT view_exists THEN + CREATE VIEW element_types AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(n.nspname AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS collection_type_identifier, + CAST( + CASE WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(bt.oid, null) + ELSE 'USER-DEFINED' END AS character_data) AS data_type, + + CAST(null AS cardinal_number) AS character_maximum_length, + CAST(null AS cardinal_number) AS character_octet_length, + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + CAST(null AS cardinal_number) AS numeric_precision, + CAST(null AS cardinal_number) AS numeric_precision_radix, + CAST(null AS cardinal_number) AS numeric_scale, + CAST(null AS cardinal_number) AS datetime_precision, + CAST(null AS character_data) AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS character_data) AS domain_default, -- XXX maybe a bug in the standard + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(nbt.nspname AS sql_identifier) AS udt_schema, + CAST(bt.typname AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST('a' || CAST(x.objdtdid AS text) AS sql_identifier) AS dtd_identifier + + FROM pg_namespace n, pg_type at, pg_namespace nbt, pg_type bt, + ( + /* columns, attributes */ + SELECT c.relnamespace, CAST(c.relname AS sql_identifier), + CASE WHEN c.relkind = 'c' THEN 'USER-DEFINED TYPE'::text ELSE 'TABLE'::text END, + a.attnum, a.atttypid, a.attcollation + FROM pg_class c, pg_attribute a + WHERE c.oid = a.attrelid + AND c.relkind IN ('r', 'm', 'v', 'f', 'c') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND attnum > 0 AND NOT attisdropped + + UNION ALL + + /* domains */ + SELECT t.typnamespace, CAST(t.typname AS sql_identifier), + 'DOMAIN'::text, 1, t.typbasetype, t.typcollation + FROM pg_type t + WHERE t.typtype = 'd' + + UNION ALL + + /* parameters */ + SELECT pronamespace, CAST(proname || '_' || CAST(oid AS text) AS sql_identifier), + 'ROUTINE'::text, (ss.x).n, (ss.x).x, 0 + FROM (SELECT p.pronamespace, p.proname, p.oid, + _pg_expandarray(coalesce(p.proallargtypes, p.proargtypes::oid[])) AS x + FROM pg_proc p) AS ss + + UNION ALL + + /* result types */ + SELECT p.pronamespace, CAST(p.proname || '_' || CAST(p.oid AS text) AS sql_identifier), + 'ROUTINE'::text, 0, p.prorettype, 0 + FROM pg_proc p + + ) AS x (objschema, objname, objtype, objdtdid, objtypeid, objcollation) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON x.objcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + + WHERE n.oid = x.objschema + AND at.oid = x.objtypeid + AND (at.typelem <> 0 AND at.typlen = -1) + AND at.typelem = bt.oid + AND nbt.oid = bt.typnamespace + + AND (n.nspname, x.objname, x.objtype, CAST(x.objdtdid AS sql_identifier)) IN + ( SELECT object_schema, object_name, object_type, dtd_identifier + FROM data_type_privileges ); + END IF; +END $$; + + +do $$DECLARE + user_name text; + query_str text; +BEGIN + SELECT SESSION_USER INTO user_name; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.element_types TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.data_type_privileges TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.tables TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.columns TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; +END$$; + +GRANT SELECT ON information_schema.element_types TO PUBLIC; +GRANT SELECT ON information_schema.data_type_privileges TO PUBLIC; +GRANT SELECT ON information_schema.tables TO PUBLIC; +GRANT SELECT ON information_schema.columns TO PUBLIC; + +RESET search_path; diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_974.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_974.sql new file mode 100644 index 000000000..0290c2849 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_maindb/upgrade-post_catalog_maindb_92_974.sql @@ -0,0 +1,322 @@ +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0; + +SET search_path TO information_schema; + +DROP VIEW IF EXISTS information_schema.tables CASCADE; +DROP VIEW IF EXISTS information_schema.columns CASCADE; + +CREATE VIEW tables AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + + CAST( + CASE WHEN nc.oid = pg_catalog.pg_my_temp_schema() THEN 'LOCAL TEMPORARY' + WHEN c.relkind = 'r' THEN 'BASE TABLE' + WHEN c.relkind = 'm' THEN 'MATERIALIZED VIEW' + WHEN c.relkind = 'v' THEN 'VIEW' + WHEN c.relkind = 'f' THEN 'FOREIGN TABLE' + ELSE null END + AS character_data) AS table_type, + + CAST(null AS sql_identifier) AS self_referencing_column_name, + CAST(null AS character_data) AS reference_generation, + + CAST(CASE WHEN t.typname IS NOT NULL THEN pg_catalog.current_database() ELSE null END AS sql_identifier) AS user_defined_type_catalog, + CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema, + CAST(t.typname AS sql_identifier) AS user_defined_type_name, + + CAST(CASE WHEN c.relkind = 'r' OR + (c.relkind in ('v', 'f') AND + -- 1 << CMD_INSERT + pg_relation_is_updatable(c.oid, false) & 8 = 8) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into, + + CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed, + CAST(null AS character_data) AS commit_action, + CAST(d.description AS information_schema.character_data) AS TABLE_COMMENT + + FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace) + LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid) + LEFT JOIN pg_description d on d.objoid = c.oid and objsubid = 0 + + WHERE c.relkind IN ('r', 'm', 'v', 'f') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') + OR pg_catalog.has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') ); + +CREATE VIEW columns AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + CAST(a.attname AS sql_identifier) AS column_name, + CAST(a.attnum AS cardinal_number) AS ordinal_position, + CAST(CASE WHEN ad.adgencol <> 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS column_default, + CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END + AS yes_or_no) + AS is_nullable, + + CAST( + CASE WHEN t.typtype = 'd' THEN + CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY' + WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(t.typbasetype, null) + ELSE 'USER-DEFINED' END + ELSE + CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY' + WHEN nt.nspname = 'pg_catalog' THEN pg_catalog.format_type(a.atttypid, null) + ELSE 'USER-DEFINED' END + END + AS character_data) + AS data_type, + + CAST( + _pg_char_max_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_maximum_length, + + CAST( + _pg_char_octet_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_octet_length, + + CAST( + _pg_numeric_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision, + + CAST( + _pg_numeric_precision_radix(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision_radix, + + CAST( + _pg_numeric_scale(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_scale, + + CAST( + _pg_datetime_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS datetime_precision, + + CAST( + _pg_interval_type(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS character_data) + AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + + CAST(CASE WHEN t.typtype = 'd' THEN pg_catalog.current_database() ELSE null END + AS sql_identifier) AS domain_catalog, + CAST(CASE WHEN t.typtype = 'd' THEN nt.nspname ELSE null END + AS sql_identifier) AS domain_schema, + CAST(CASE WHEN t.typtype = 'd' THEN t.typname ELSE null END + AS sql_identifier) AS domain_name, + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(coalesce(nbt.nspname, nt.nspname) AS sql_identifier) AS udt_schema, + CAST(coalesce(bt.typname, t.typname) AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST(a.attnum AS sql_identifier) AS dtd_identifier, + CAST('NO' AS yes_or_no) AS is_self_referencing, + + CAST('NO' AS yes_or_no) AS is_identity, + CAST(null AS character_data) AS identity_generation, + CAST(null AS character_data) AS identity_start, + CAST(null AS character_data) AS identity_increment, + CAST(null AS character_data) AS identity_maximum, + CAST(null AS character_data) AS identity_minimum, + CAST(null AS yes_or_no) AS identity_cycle, + + CAST(CASE WHEN ad.adgencol = 's' THEN 'ALWAYS' ELSE 'NEVER' END AS character_data) AS is_generated, + CAST(CASE WHEN ad.adgencol = 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS generation_expression, + + CAST(CASE WHEN c.relkind = 'r' + OR (c.relkind in ('v', 'f') AND pg_column_is_updatable(c.oid, a.attnum, false)) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable, + CAST( + CASE WHEN t.typtype = 'd' THEN + CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY' + WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(t.typbasetype, null) + ELSE 'USER-DEFINED' END + ELSE + CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY' + WHEN nt.nspname = 'pg_catalog' THEN pg_catalog.format_type(a.atttypid, null) + ELSE 'USER-DEFINED' END + END + AS character_data) + AS COLUMN_TYPE, + CAST(d.description AS information_schema.character_data) AS COLUMN_COMMENT, + CAST( + CASE WHEN ad.adsrc = 'AUTO_INCREMENT' THEN 'AUTO_INCREMENT' + ELSE + CASE WHEN ad.adsrc_on_update is not null THEN CONCAT('DEFAULT_GENERATED on update ', ad.adsrc_on_update) + ELSE null + END + END + AS character_data) + AS EXTRA + + FROM (pg_attribute a LEFT JOIN pg_attrdef ad ON attrelid = adrelid AND attnum = adnum) + JOIN (pg_class c JOIN pg_namespace nc ON (c.relnamespace = nc.oid)) ON a.attrelid = c.oid + JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON a.atttypid = t.oid + LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON (bt.typnamespace = nbt.oid)) + ON (t.typtype = 'd' AND t.typbasetype = bt.oid) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + LEFT JOIN pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum + + WHERE (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + + AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind in ('r', 'm', 'v', 'f') + + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_column_privilege(c.oid, a.attnum, + 'SELECT, INSERT, UPDATE, REFERENCES')); + +CREATE VIEW data_type_privileges AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(x.objschema AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS dtd_identifier + + FROM + ( + SELECT udt_schema, udt_name, 'USER-DEFINED TYPE'::text, dtd_identifier FROM attributes + UNION ALL + SELECT table_schema, table_name, 'TABLE'::text, dtd_identifier FROM columns + UNION ALL + SELECT domain_schema, domain_name, 'DOMAIN'::text, dtd_identifier FROM domains + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM parameters + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM routines + ) AS x (objschema, objname, objtype, objdtdid); + + +CREATE VIEW element_types AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(n.nspname AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS collection_type_identifier, + CAST( + CASE WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(bt.oid, null) + ELSE 'USER-DEFINED' END AS character_data) AS data_type, + + CAST(null AS cardinal_number) AS character_maximum_length, + CAST(null AS cardinal_number) AS character_octet_length, + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + CAST(null AS cardinal_number) AS numeric_precision, + CAST(null AS cardinal_number) AS numeric_precision_radix, + CAST(null AS cardinal_number) AS numeric_scale, + CAST(null AS cardinal_number) AS datetime_precision, + CAST(null AS character_data) AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS character_data) AS domain_default, -- XXX maybe a bug in the standard + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(nbt.nspname AS sql_identifier) AS udt_schema, + CAST(bt.typname AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST('a' || CAST(x.objdtdid AS text) AS sql_identifier) AS dtd_identifier + + FROM pg_namespace n, pg_type at, pg_namespace nbt, pg_type bt, + ( + /* columns, attributes */ + SELECT c.relnamespace, CAST(c.relname AS sql_identifier), + CASE WHEN c.relkind = 'c' THEN 'USER-DEFINED TYPE'::text ELSE 'TABLE'::text END, + a.attnum, a.atttypid, a.attcollation + FROM pg_class c, pg_attribute a + WHERE c.oid = a.attrelid + AND c.relkind IN ('r', 'm', 'v', 'f', 'c') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND attnum > 0 AND NOT attisdropped + + UNION ALL + + /* domains */ + SELECT t.typnamespace, CAST(t.typname AS sql_identifier), + 'DOMAIN'::text, 1, t.typbasetype, t.typcollation + FROM pg_type t + WHERE t.typtype = 'd' + + UNION ALL + + /* parameters */ + SELECT pronamespace, CAST(proname || '_' || CAST(oid AS text) AS sql_identifier), + 'ROUTINE'::text, (ss.x).n, (ss.x).x, 0 + FROM (SELECT p.pronamespace, p.proname, p.oid, + _pg_expandarray(coalesce(p.proallargtypes, p.proargtypes::oid[])) AS x + FROM pg_proc p) AS ss + + UNION ALL + + /* result types */ + SELECT p.pronamespace, CAST(p.proname || '_' || CAST(p.oid AS text) AS sql_identifier), + 'ROUTINE'::text, 0, p.prorettype, 0 + FROM pg_proc p + + ) AS x (objschema, objname, objtype, objdtdid, objtypeid, objcollation) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON x.objcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + + WHERE n.oid = x.objschema + AND at.oid = x.objtypeid + AND (at.typelem <> 0 AND at.typlen = -1) + AND at.typelem = bt.oid + AND nbt.oid = bt.typnamespace + + AND (n.nspname, x.objname, x.objtype, CAST(x.objdtdid AS sql_identifier)) IN + ( SELECT object_schema, object_name, object_type, dtd_identifier + FROM data_type_privileges ); + +do $$DECLARE + user_name text; + query_str text; +BEGIN + SELECT SESSION_USER INTO user_name; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.element_types TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.data_type_privileges TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.tables TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.columns TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; +END$$; + +GRANT SELECT ON information_schema.element_types TO PUBLIC; +GRANT SELECT ON information_schema.data_type_privileges TO PUBLIC; +GRANT SELECT ON information_schema.tables TO PUBLIC; +GRANT SELECT ON information_schema.columns TO PUBLIC; + +RESET search_path; diff --git a/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_974.sql b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_974.sql new file mode 100644 index 000000000..0290c2849 --- /dev/null +++ b/src/include/catalog/upgrade_sql/upgrade_catalog_otherdb/upgrade-post_catalog_otherdb_92_974.sql @@ -0,0 +1,322 @@ +SET LOCAL inplace_upgrade_next_system_object_oids = IUO_CATALOG, false, true, 0, 0, 0, 0; + +SET search_path TO information_schema; + +DROP VIEW IF EXISTS information_schema.tables CASCADE; +DROP VIEW IF EXISTS information_schema.columns CASCADE; + +CREATE VIEW tables AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + + CAST( + CASE WHEN nc.oid = pg_catalog.pg_my_temp_schema() THEN 'LOCAL TEMPORARY' + WHEN c.relkind = 'r' THEN 'BASE TABLE' + WHEN c.relkind = 'm' THEN 'MATERIALIZED VIEW' + WHEN c.relkind = 'v' THEN 'VIEW' + WHEN c.relkind = 'f' THEN 'FOREIGN TABLE' + ELSE null END + AS character_data) AS table_type, + + CAST(null AS sql_identifier) AS self_referencing_column_name, + CAST(null AS character_data) AS reference_generation, + + CAST(CASE WHEN t.typname IS NOT NULL THEN pg_catalog.current_database() ELSE null END AS sql_identifier) AS user_defined_type_catalog, + CAST(nt.nspname AS sql_identifier) AS user_defined_type_schema, + CAST(t.typname AS sql_identifier) AS user_defined_type_name, + + CAST(CASE WHEN c.relkind = 'r' OR + (c.relkind in ('v', 'f') AND + -- 1 << CMD_INSERT + pg_relation_is_updatable(c.oid, false) & 8 = 8) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_insertable_into, + + CAST(CASE WHEN t.typname IS NOT NULL THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_typed, + CAST(null AS character_data) AS commit_action, + CAST(d.description AS information_schema.character_data) AS TABLE_COMMENT + + FROM pg_namespace nc JOIN pg_class c ON (nc.oid = c.relnamespace) + LEFT JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON (c.reloftype = t.oid) + LEFT JOIN pg_description d on d.objoid = c.oid and objsubid = 0 + + WHERE c.relkind IN ('r', 'm', 'v', 'f') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_table_privilege(c.oid, 'SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER') + OR pg_catalog.has_any_column_privilege(c.oid, 'SELECT, INSERT, UPDATE, REFERENCES') ); + +CREATE VIEW columns AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS table_catalog, + CAST(nc.nspname AS sql_identifier) AS table_schema, + CAST(c.relname AS sql_identifier) AS table_name, + CAST(a.attname AS sql_identifier) AS column_name, + CAST(a.attnum AS cardinal_number) AS ordinal_position, + CAST(CASE WHEN ad.adgencol <> 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS column_default, + CAST(CASE WHEN a.attnotnull OR (t.typtype = 'd' AND t.typnotnull) THEN 'NO' ELSE 'YES' END + AS yes_or_no) + AS is_nullable, + + CAST( + CASE WHEN t.typtype = 'd' THEN + CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY' + WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(t.typbasetype, null) + ELSE 'USER-DEFINED' END + ELSE + CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY' + WHEN nt.nspname = 'pg_catalog' THEN pg_catalog.format_type(a.atttypid, null) + ELSE 'USER-DEFINED' END + END + AS character_data) + AS data_type, + + CAST( + _pg_char_max_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_maximum_length, + + CAST( + _pg_char_octet_length(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS character_octet_length, + + CAST( + _pg_numeric_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision, + + CAST( + _pg_numeric_precision_radix(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_precision_radix, + + CAST( + _pg_numeric_scale(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS numeric_scale, + + CAST( + _pg_datetime_precision(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS cardinal_number) + AS datetime_precision, + + CAST( + _pg_interval_type(_pg_truetypid(a, t), _pg_truetypmod(a, t)) + AS character_data) + AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + + CAST(CASE WHEN t.typtype = 'd' THEN pg_catalog.current_database() ELSE null END + AS sql_identifier) AS domain_catalog, + CAST(CASE WHEN t.typtype = 'd' THEN nt.nspname ELSE null END + AS sql_identifier) AS domain_schema, + CAST(CASE WHEN t.typtype = 'd' THEN t.typname ELSE null END + AS sql_identifier) AS domain_name, + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(coalesce(nbt.nspname, nt.nspname) AS sql_identifier) AS udt_schema, + CAST(coalesce(bt.typname, t.typname) AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST(a.attnum AS sql_identifier) AS dtd_identifier, + CAST('NO' AS yes_or_no) AS is_self_referencing, + + CAST('NO' AS yes_or_no) AS is_identity, + CAST(null AS character_data) AS identity_generation, + CAST(null AS character_data) AS identity_start, + CAST(null AS character_data) AS identity_increment, + CAST(null AS character_data) AS identity_maximum, + CAST(null AS character_data) AS identity_minimum, + CAST(null AS yes_or_no) AS identity_cycle, + + CAST(CASE WHEN ad.adgencol = 's' THEN 'ALWAYS' ELSE 'NEVER' END AS character_data) AS is_generated, + CAST(CASE WHEN ad.adgencol = 's' THEN pg_catalog.pg_get_expr(ad.adbin, ad.adrelid) END AS character_data) AS generation_expression, + + CAST(CASE WHEN c.relkind = 'r' + OR (c.relkind in ('v', 'f') AND pg_column_is_updatable(c.oid, a.attnum, false)) + THEN 'YES' ELSE 'NO' END AS yes_or_no) AS is_updatable, + CAST( + CASE WHEN t.typtype = 'd' THEN + CASE WHEN bt.typelem <> 0 AND bt.typlen = -1 THEN 'ARRAY' + WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(t.typbasetype, null) + ELSE 'USER-DEFINED' END + ELSE + CASE WHEN t.typelem <> 0 AND t.typlen = -1 THEN 'ARRAY' + WHEN nt.nspname = 'pg_catalog' THEN pg_catalog.format_type(a.atttypid, null) + ELSE 'USER-DEFINED' END + END + AS character_data) + AS COLUMN_TYPE, + CAST(d.description AS information_schema.character_data) AS COLUMN_COMMENT, + CAST( + CASE WHEN ad.adsrc = 'AUTO_INCREMENT' THEN 'AUTO_INCREMENT' + ELSE + CASE WHEN ad.adsrc_on_update is not null THEN CONCAT('DEFAULT_GENERATED on update ', ad.adsrc_on_update) + ELSE null + END + END + AS character_data) + AS EXTRA + + FROM (pg_attribute a LEFT JOIN pg_attrdef ad ON attrelid = adrelid AND attnum = adnum) + JOIN (pg_class c JOIN pg_namespace nc ON (c.relnamespace = nc.oid)) ON a.attrelid = c.oid + JOIN (pg_type t JOIN pg_namespace nt ON (t.typnamespace = nt.oid)) ON a.atttypid = t.oid + LEFT JOIN (pg_type bt JOIN pg_namespace nbt ON (bt.typnamespace = nbt.oid)) + ON (t.typtype = 'd' AND t.typbasetype = bt.oid) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON a.attcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + LEFT JOIN pg_description d on d.objoid = a.attrelid and d.objsubid = a.attnum + + WHERE (NOT pg_catalog.pg_is_other_temp_schema(nc.oid)) + + AND a.attnum > 0 AND NOT a.attisdropped AND c.relkind in ('r', 'm', 'v', 'f') + + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + + AND (pg_catalog.pg_has_role(c.relowner, 'USAGE') + OR pg_catalog.has_column_privilege(c.oid, a.attnum, + 'SELECT, INSERT, UPDATE, REFERENCES')); + +CREATE VIEW data_type_privileges AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(x.objschema AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS dtd_identifier + + FROM + ( + SELECT udt_schema, udt_name, 'USER-DEFINED TYPE'::text, dtd_identifier FROM attributes + UNION ALL + SELECT table_schema, table_name, 'TABLE'::text, dtd_identifier FROM columns + UNION ALL + SELECT domain_schema, domain_name, 'DOMAIN'::text, dtd_identifier FROM domains + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM parameters + UNION ALL + SELECT specific_schema, specific_name, 'ROUTINE'::text, dtd_identifier FROM routines + ) AS x (objschema, objname, objtype, objdtdid); + + +CREATE VIEW element_types AS + SELECT CAST(pg_catalog.current_database() AS sql_identifier) AS object_catalog, + CAST(n.nspname AS sql_identifier) AS object_schema, + CAST(x.objname AS sql_identifier) AS object_name, + CAST(x.objtype AS character_data) AS object_type, + CAST(x.objdtdid AS sql_identifier) AS collection_type_identifier, + CAST( + CASE WHEN nbt.nspname = 'pg_catalog' THEN pg_catalog.format_type(bt.oid, null) + ELSE 'USER-DEFINED' END AS character_data) AS data_type, + + CAST(null AS cardinal_number) AS character_maximum_length, + CAST(null AS cardinal_number) AS character_octet_length, + CAST(null AS sql_identifier) AS character_set_catalog, + CAST(null AS sql_identifier) AS character_set_schema, + CAST(null AS sql_identifier) AS character_set_name, + CAST(CASE WHEN nco.nspname IS NOT NULL THEN pg_catalog.current_database() END AS sql_identifier) AS collation_catalog, + CAST(nco.nspname AS sql_identifier) AS collation_schema, + CAST(co.collname AS sql_identifier) AS collation_name, + CAST(null AS cardinal_number) AS numeric_precision, + CAST(null AS cardinal_number) AS numeric_precision_radix, + CAST(null AS cardinal_number) AS numeric_scale, + CAST(null AS cardinal_number) AS datetime_precision, + CAST(null AS character_data) AS interval_type, + CAST(null AS cardinal_number) AS interval_precision, + + CAST(null AS character_data) AS domain_default, -- XXX maybe a bug in the standard + + CAST(pg_catalog.current_database() AS sql_identifier) AS udt_catalog, + CAST(nbt.nspname AS sql_identifier) AS udt_schema, + CAST(bt.typname AS sql_identifier) AS udt_name, + + CAST(null AS sql_identifier) AS scope_catalog, + CAST(null AS sql_identifier) AS scope_schema, + CAST(null AS sql_identifier) AS scope_name, + + CAST(null AS cardinal_number) AS maximum_cardinality, + CAST('a' || CAST(x.objdtdid AS text) AS sql_identifier) AS dtd_identifier + + FROM pg_namespace n, pg_type at, pg_namespace nbt, pg_type bt, + ( + /* columns, attributes */ + SELECT c.relnamespace, CAST(c.relname AS sql_identifier), + CASE WHEN c.relkind = 'c' THEN 'USER-DEFINED TYPE'::text ELSE 'TABLE'::text END, + a.attnum, a.atttypid, a.attcollation + FROM pg_class c, pg_attribute a + WHERE c.oid = a.attrelid + AND c.relkind IN ('r', 'm', 'v', 'f', 'c') + AND (c.relname not like 'mlog\_%' AND c.relname not like 'matviewmap\_%') + AND attnum > 0 AND NOT attisdropped + + UNION ALL + + /* domains */ + SELECT t.typnamespace, CAST(t.typname AS sql_identifier), + 'DOMAIN'::text, 1, t.typbasetype, t.typcollation + FROM pg_type t + WHERE t.typtype = 'd' + + UNION ALL + + /* parameters */ + SELECT pronamespace, CAST(proname || '_' || CAST(oid AS text) AS sql_identifier), + 'ROUTINE'::text, (ss.x).n, (ss.x).x, 0 + FROM (SELECT p.pronamespace, p.proname, p.oid, + _pg_expandarray(coalesce(p.proallargtypes, p.proargtypes::oid[])) AS x + FROM pg_proc p) AS ss + + UNION ALL + + /* result types */ + SELECT p.pronamespace, CAST(p.proname || '_' || CAST(p.oid AS text) AS sql_identifier), + 'ROUTINE'::text, 0, p.prorettype, 0 + FROM pg_proc p + + ) AS x (objschema, objname, objtype, objdtdid, objtypeid, objcollation) + LEFT JOIN (pg_collation co JOIN pg_namespace nco ON (co.collnamespace = nco.oid)) + ON x.objcollation = co.oid AND (nco.nspname, co.collname) <> ('pg_catalog', 'default') + + WHERE n.oid = x.objschema + AND at.oid = x.objtypeid + AND (at.typelem <> 0 AND at.typlen = -1) + AND at.typelem = bt.oid + AND nbt.oid = bt.typnamespace + + AND (n.nspname, x.objname, x.objtype, CAST(x.objdtdid AS sql_identifier)) IN + ( SELECT object_schema, object_name, object_type, dtd_identifier + FROM data_type_privileges ); + +do $$DECLARE + user_name text; + query_str text; +BEGIN + SELECT SESSION_USER INTO user_name; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.element_types TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.data_type_privileges TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.tables TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; + query_str := 'GRANT INSERT, SELECT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER ON information_schema.columns TO ' || quote_ident(user_name) || ';'; + EXECUTE IMMEDIATE query_str; +END$$; + +GRANT SELECT ON information_schema.element_types TO PUBLIC; +GRANT SELECT ON information_schema.data_type_privileges TO PUBLIC; +GRANT SELECT ON information_schema.tables TO PUBLIC; +GRANT SELECT ON information_schema.columns TO PUBLIC; + +RESET search_path;