diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index a69cef4..7c17ba2 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -199,6 +199,11 @@ + pg_setting + per-user and per-database settings + + + pg_shdepend dependencies on shared objects @@ -2132,13 +2137,6 @@ - datconfig - text[] - - Session defaults for run-time configuration variables - - - datacl aclitem[] @@ -3996,6 +3994,65 @@ + + <structname>pg_setting</structname> + + + pg_setting + + + + The catalog pg_setting records the default + values that have been set for run-time configuration variables, + for each role and database combination. + + + + Unlike most system catalogs, pg_setting + is shared across all databases of a cluster: there is only one + copy of pg_setting per cluster, not + one per database. + + + + <structname>pg_setting</> Columns + + + + + Name + Type + References + Description + + + + + + setdatabase + oid + pg_database.oid + The OID of the database the setting is applicable to, or zero if not database-specific + + + + setrole + oid + pg_authid.oid + The OID of the role the setting is applicable to, or zero if not role-specific + + + + setconfig + text[] + + Defaults for run-time configuration variables + + + +
+
+ <structname>pg_shdepend</structname> @@ -6448,13 +6505,6 @@
- rolconfig - text[] - - Session defaults for run-time configuration variables - - - oid oid pg_authid.oid diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile index 861cb1d..941f7db 100644 --- a/src/backend/catalog/Makefile +++ b/src/backend/catalog/Makefile @@ -13,7 +13,7 @@ include $(top_builddir)/src/Makefile.global OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \ pg_aggregate.o pg_constraint.o pg_conversion.o pg_depend.o pg_enum.o \ pg_inherits.o pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o \ - pg_shdepend.o pg_type.o storage.o toasting.o + pg_setting.o pg_shdepend.o pg_type.o storage.o toasting.o BKIFILES = postgres.bki postgres.description postgres.shdescription @@ -32,7 +32,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\ pg_language.h pg_largeobject.h pg_aggregate.h pg_statistic.h \ pg_rewrite.h pg_trigger.h pg_listener.h pg_description.h pg_cast.h \ pg_enum.h pg_namespace.h pg_conversion.h pg_depend.h \ - pg_database.h pg_tablespace.h pg_pltemplate.h \ + pg_database.h pg_setting.h pg_tablespace.h pg_pltemplate.h \ pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \ pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \ pg_ts_parser.h pg_ts_template.h \ diff --git a/src/backend/catalog/catalog.c b/src/backend/catalog/catalog.c index d168694..d6f4ea7 100644 --- a/src/backend/catalog/catalog.c +++ b/src/backend/catalog/catalog.c @@ -31,6 +31,7 @@ #include "catalog/pg_database.h" #include "catalog/pg_namespace.h" #include "catalog/pg_pltemplate.h" +#include "catalog/pg_setting.h" #include "catalog/pg_shdepend.h" #include "catalog/pg_shdescription.h" #include "catalog/pg_tablespace.h" @@ -306,7 +307,8 @@ IsSharedRelation(Oid relationId) relationId == PLTemplateRelationId || relationId == SharedDescriptionRelationId || relationId == SharedDependRelationId || - relationId == TableSpaceRelationId) + relationId == TableSpaceRelationId || + relationId == SettingRelationId) return true; /* These are their indexes (see indexing.h) */ if (relationId == AuthIdRolnameIndexId || @@ -320,7 +322,8 @@ IsSharedRelation(Oid relationId) relationId == SharedDependDependerIndexId || relationId == SharedDependReferenceIndexId || relationId == TablespaceOidIndexId || - relationId == TablespaceNameIndexId) + relationId == TablespaceNameIndexId || + relationId == SettingDatidRolidIndexId) return true; /* These are their toast tables and toast indexes (see toasting.h) */ if (relationId == PgAuthidToastTable || @@ -328,7 +331,9 @@ IsSharedRelation(Oid relationId) relationId == PgDatabaseToastTable || relationId == PgDatabaseToastIndex || relationId == PgShdescriptionToastTable || - relationId == PgShdescriptionToastIndex) + relationId == PgShdescriptionToastIndex || + relationId == PgSettingToastTable || + relationId == PgSettingToastIndex) return true; return false; } diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 67188de..15e1a42 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -18,7 +18,7 @@ CREATE VIEW pg_roles AS rolconnlimit, '********'::text as rolpassword, rolvaliduntil, - rolconfig, + NULL as rolconfig, oid FROM pg_authid; @@ -31,7 +31,7 @@ CREATE VIEW pg_shadow AS rolcatupdate AS usecatupd, rolpassword AS passwd, rolvaliduntil::abstime AS valuntil, - rolconfig AS useconfig + NULL AS useconfig FROM pg_authid WHERE rolcanlogin; diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 7d4ca41..405c1b2 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -33,6 +33,7 @@ #include "catalog/indexing.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" +#include "catalog/pg_setting.h" #include "catalog/pg_tablespace.h" #include "commands/comment.h" #include "commands/dbcommands.h" @@ -50,7 +51,6 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" -#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/pg_locale.h" #include "utils/snapmgr.h" @@ -544,12 +544,10 @@ createdb(const CreatedbStmt *stmt) new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace); /* - * We deliberately set datconfig and datacl to defaults (NULL), rather - * than copying them from the template database. Copying datacl would be - * a bad idea when the owner is not the same as the template's owner. It's - * more debatable whether datconfig should be copied. + * We deliberately set datacl to default (NULL), rather + * than copying it from the template database. Copying it would be + * a bad idea when the owner is not the same as the template's owner. */ - new_record_nulls[Anum_pg_database_datconfig - 1] = true; new_record_nulls[Anum_pg_database_datacl - 1] = true; tuple = heap_form_tuple(RelationGetDescr(pg_database_rel), @@ -821,6 +819,11 @@ dropdb(const char *dbname, bool missing_ok) DeleteSharedComments(db_id, DatabaseRelationId); /* + * Remove settings associated with this database + */ + DropSetting(db_id, InvalidOid); + + /* * Remove shared dependency references for the database. */ dropDatabaseDependencies(db_id); @@ -1397,85 +1400,22 @@ AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel) void AlterDatabaseSet(AlterDatabaseSetStmt *stmt) { - char *valuestr; - HeapTuple tuple, - newtuple; - Relation rel; - ScanKeyData scankey; - SysScanDesc scan; - Datum repl_val[Natts_pg_database]; - bool repl_null[Natts_pg_database]; - bool repl_repl[Natts_pg_database]; - - valuestr = ExtractSetVariableArgs(stmt->setstmt); - - /* - * Get the old tuple. We don't need a lock on the database per se, - * because we're not going to do anything that would mess up incoming - * connections. - */ - rel = heap_open(DatabaseRelationId, RowExclusiveLock); - ScanKeyInit(&scankey, - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(stmt->dbname)); - scan = systable_beginscan(rel, DatabaseNameIndexId, true, - SnapshotNow, 1, &scankey); - tuple = systable_getnext(scan); - if (!HeapTupleIsValid(tuple)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%s\" does not exist", stmt->dbname))); - - if (!pg_database_ownercheck(HeapTupleGetOid(tuple), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - stmt->dbname); - - memset(repl_repl, false, sizeof(repl_repl)); - repl_repl[Anum_pg_database_datconfig - 1] = true; - - if (stmt->setstmt->kind == VAR_RESET_ALL) - { - /* RESET ALL, so just set datconfig to null */ - repl_null[Anum_pg_database_datconfig - 1] = true; - repl_val[Anum_pg_database_datconfig - 1] = (Datum) 0; - } - else - { - Datum datum; - bool isnull; - ArrayType *a; - - repl_null[Anum_pg_database_datconfig - 1] = false; - - /* Extract old value of datconfig */ - datum = heap_getattr(tuple, Anum_pg_database_datconfig, - RelationGetDescr(rel), &isnull); - a = isnull ? NULL : DatumGetArrayTypeP(datum); - - /* Update (valuestr is NULL in RESET cases) */ - if (valuestr) - a = GUCArrayAdd(a, stmt->setstmt->name, valuestr); - else - a = GUCArrayDelete(a, stmt->setstmt->name); - - if (a) - repl_val[Anum_pg_database_datconfig - 1] = PointerGetDatum(a); - else - repl_null[Anum_pg_database_datconfig - 1] = true; - } - - newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); - simple_heap_update(rel, &tuple->t_self, newtuple); - - /* Update indexes */ - CatalogUpdateIndexes(rel, newtuple); - - systable_endscan(scan); - - /* Close pg_database, but keep lock till commit */ - heap_close(rel, NoLock); + Oid datid = get_database_oid(stmt->dbname); + + if (!OidIsValid(datid)) + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_DATABASE), + errmsg("database \"%s\" does not exist", stmt->dbname))); + + LockSharedObject(DatabaseRelationId, datid, 0, AccessShareLock); + + if (!pg_database_ownercheck(datid, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, + stmt->dbname); + + AlterSetting(datid, InvalidOid, stmt->setstmt); + + UnlockSharedObject(DatabaseRelationId, datid, 0, AccessShareLock); } diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c index fa260c4..3f2b520 100644 --- a/src/backend/commands/user.c +++ b/src/backend/commands/user.c @@ -19,6 +19,7 @@ #include "catalog/indexing.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" +#include "catalog/pg_setting.h" #include "commands/comment.h" #include "commands/user.h" #include "libpq/md5.h" @@ -27,7 +28,6 @@ #include "utils/acl.h" #include "utils/builtins.h" #include "utils/fmgroids.h" -#include "utils/guc.h" #include "utils/lsyscache.h" #include "utils/syscache.h" #include "utils/tqual.h" @@ -341,8 +341,6 @@ CreateRole(CreateRoleStmt *stmt) else new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = true; - new_record_nulls[Anum_pg_authid_rolconfig - 1] = true; - tuple = heap_form_tuple(pg_authid_dsc, new_record, new_record_nulls); /* @@ -715,30 +713,24 @@ AlterRole(AlterRoleStmt *stmt) void AlterRoleSet(AlterRoleSetStmt *stmt) { - char *valuestr; - HeapTuple oldtuple, - newtuple; - Relation rel; - Datum repl_val[Natts_pg_authid]; - bool repl_null[Natts_pg_authid]; - bool repl_repl[Natts_pg_authid]; + HeapTuple roletuple; - valuestr = ExtractSetVariableArgs(stmt->setstmt); + roletuple = SearchSysCache(AUTHNAME, + PointerGetDatum(stmt->role), + 0, 0, 0); - rel = heap_open(AuthIdRelationId, RowExclusiveLock); - oldtuple = SearchSysCache(AUTHNAME, - PointerGetDatum(stmt->role), - 0, 0, 0); - if (!HeapTupleIsValid(oldtuple)) + if (!HeapTupleIsValid(roletuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("role \"%s\" does not exist", stmt->role))); + /* XXX need some kind of lock here */ + /* * To mess with a superuser you gotta be superuser; else you need * createrole, or just want to change your own settings */ - if (((Form_pg_authid) GETSTRUCT(oldtuple))->rolsuper) + if (((Form_pg_authid) GETSTRUCT(roletuple))->rolsuper) { if (!superuser()) ereport(ERROR, @@ -748,54 +740,14 @@ AlterRoleSet(AlterRoleSetStmt *stmt) else { if (!have_createrole_privilege() && - HeapTupleGetOid(oldtuple) != GetUserId()) + HeapTupleGetOid(roletuple) != GetUserId()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); } - memset(repl_repl, false, sizeof(repl_repl)); - repl_repl[Anum_pg_authid_rolconfig - 1] = true; - - if (stmt->setstmt->kind == VAR_RESET_ALL) - { - /* RESET ALL, so just set rolconfig to null */ - repl_null[Anum_pg_authid_rolconfig - 1] = true; - repl_val[Anum_pg_authid_rolconfig - 1] = (Datum) 0; - } - else - { - Datum datum; - bool isnull; - ArrayType *array; - - repl_null[Anum_pg_authid_rolconfig - 1] = false; - - /* Extract old value of rolconfig */ - datum = SysCacheGetAttr(AUTHNAME, oldtuple, - Anum_pg_authid_rolconfig, &isnull); - array = isnull ? NULL : DatumGetArrayTypeP(datum); - - /* Update (valuestr is NULL in RESET cases) */ - if (valuestr) - array = GUCArrayAdd(array, stmt->setstmt->name, valuestr); - else - array = GUCArrayDelete(array, stmt->setstmt->name); - - if (array) - repl_val[Anum_pg_authid_rolconfig - 1] = PointerGetDatum(array); - else - repl_null[Anum_pg_authid_rolconfig - 1] = true; - } - - newtuple = heap_modify_tuple(oldtuple, RelationGetDescr(rel), - repl_val, repl_null, repl_repl); - - simple_heap_update(rel, &oldtuple->t_self, newtuple); - CatalogUpdateIndexes(rel, newtuple); - - ReleaseSysCache(oldtuple); - heap_close(rel, RowExclusiveLock); + AlterSetting(InvalidOid, HeapTupleGetOid(roletuple), stmt->setstmt); + ReleaseSysCache(roletuple); } @@ -944,6 +896,11 @@ DropRole(DropRoleStmt *stmt) DeleteSharedComments(roleid, AuthIdRelationId); /* + * Remove settings for this role. + */ + DropSetting(InvalidOid, roleid); + + /* * Advance command counter so that later iterations of this loop will * see the changes already made. This is essential if, for example, * we are trying to drop both a role and one of its direct members --- diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index b76be53..e6795f4 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -392,8 +392,6 @@ InitializeSessionUserId(const char *rolename) { HeapTuple roleTup; Form_pg_authid rform; - Datum datum; - bool isnull; Oid roleid; /* @@ -470,24 +468,6 @@ InitializeSessionUserId(const char *rolename) AuthenticatedUserIsSuperuser ? "on" : "off", PGC_INTERNAL, PGC_S_OVERRIDE); - /* - * Set up user-specific configuration variables. This is a good place to - * do it so we don't have to read pg_authid twice during session startup. - */ - datum = SysCacheGetAttr(AUTHNAME, roleTup, - Anum_pg_authid_rolconfig, &isnull); - if (!isnull) - { - ArrayType *a = DatumGetArrayTypeP(datum); - - /* - * We process all the options at SUSET level. We assume that the - * right to insert an option into pg_authid was checked when it was - * inserted. - */ - ProcessGUCArray(a, PGC_SUSET, PGC_S_USER, GUC_ACTION_SET); - } - ReleaseSysCache(roleTup); } diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index ab7bd6d..8514db2 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -27,6 +27,7 @@ #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" +#include "catalog/pg_setting.h" #include "catalog/pg_tablespace.h" #include "libpq/auth.h" #include "libpq/libpq-be.h" @@ -63,7 +64,7 @@ static void CheckMyDatabase(const char *name, bool am_superuser); static void InitCommunication(void); static void ShutdownPostgres(int code, Datum arg); static bool ThereIsAtLeastOneRole(void); - +static void process_settings(Oid databaseid, Oid roleid); /*** InitPostgres support ***/ @@ -344,29 +345,6 @@ CheckMyDatabase(const char *name, bool am_superuser) pg_bind_textdomain_codeset(textdomain(NULL)); #endif - /* - * Lastly, set up any database-specific configuration variables. - */ - if (IsUnderPostmaster) - { - Datum datum; - bool isnull; - - datum = SysCacheGetAttr(DATABASEOID, tup, Anum_pg_database_datconfig, - &isnull); - if (!isnull) - { - ArrayType *a = DatumGetArrayTypeP(datum); - - /* - * We process all the options at SUSET level. We assume that the - * right to insert an option into pg_database was checked when it - * was inserted. - */ - ProcessGUCArray(a, PGC_SUSET, PGC_S_DATABASE, GUC_ACTION_SET); - } - } - ReleaseSysCache(tup); } @@ -739,6 +717,9 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* set up ACL framework (so CheckMyDatabase can check permissions) */ initialize_acl(); + /* Process pg_setting options */ + process_settings(MyDatabaseId, GetSessionUserId()); + /* * Re-read the pg_database row for our database, check permissions and * set up database-specific GUC settings. We can't do this until all the @@ -851,6 +832,28 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, CommitTransactionCommand(); } +/* + * Load GUC settings from pg_setting. + * + * We try specific settings for the database/role combination, as well as + * general for this database and for this user. + */ +static void +process_settings(Oid databaseid, Oid roleid) +{ + Relation pg_setting; + + if (!IsUnderPostmaster) + return; + + pg_setting = heap_open(SettingRelationId, AccessShareLock); + + ApplySetting(databaseid, roleid, pg_setting, PGC_S_DATABASE_USER); + ApplySetting(InvalidOid, roleid, pg_setting, PGC_S_USER); + ApplySetting(databaseid, InvalidOid, pg_setting, PGC_S_DATABASE); + + heap_close(pg_setting, AccessShareLock); +} /* * Backend-shutdown callback. Do cleanup that we want to be sure happens diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index 81e18a1..6d5fef2 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -267,6 +267,9 @@ DECLARE_UNIQUE_INDEX(pg_user_mapping_oid_index, 174, on pg_user_mapping using bt DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, on pg_user_mapping using btree(umuser oid_ops, umserver oid_ops)); #define UserMappingUserServerIndexId 175 +DECLARE_UNIQUE_INDEX(pg_setting_databaseid_rol_index, 2965, on pg_setting using btree(setdatabase oid_ops, setrole oid_ops)); +#define SettingDatidRolidIndexId 2965 + /* last step of initialization script: build the indexes declared above */ BUILD_INDICES diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h index 411f63f..e1e1ec6 100644 --- a/src/include/catalog/pg_attribute.h +++ b/src/include/catalog/pg_attribute.h @@ -485,8 +485,7 @@ DATA(insert ( 1259 tableoid 26 0 0 4 -7 0 -1 -1 t p i t f f t 0 _null_)); { 1262, {"datlastsysoid"}, 26, -1, 0, 4, 9, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \ { 1262, {"datfrozenxid"}, 28, -1, 0, 4, 10, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \ { 1262, {"dattablespace"}, 26, -1, 0, 4, 11, 0, -1, -1, true, 'p', 'i', true, false, false, true, 0, { 0 } }, \ -{ 1262, {"datconfig"}, 1009, -1, 0, -1, 12, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }, \ -{ 1262, {"datacl"}, 1034, -1, 0, -1, 13, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } } +{ 1262, {"datacl"}, 1034, -1, 0, -1, 12, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } } /* ---------------- * pg_index diff --git a/src/include/catalog/pg_authid.h b/src/include/catalog/pg_authid.h index 74c4e89..ad24bba 100644 --- a/src/include/catalog/pg_authid.h +++ b/src/include/catalog/pg_authid.h @@ -55,7 +55,6 @@ CATALOG(pg_authid,1260) BKI_SHARED_RELATION /* remaining fields may be null; use heap_getattr to read them! */ text rolpassword; /* password, if any */ timestamptz rolvaliduntil; /* password expiration time, if any */ - text rolconfig[1]; /* GUC settings to apply at login */ } FormData_pg_authid; #undef timestamptz @@ -83,7 +82,6 @@ typedef FormData_pg_authid *Form_pg_authid; #define Anum_pg_authid_rolconnlimit 8 #define Anum_pg_authid_rolpassword 9 #define Anum_pg_authid_rolvaliduntil 10 -#define Anum_pg_authid_rolconfig 11 /* ---------------- * initial contents of pg_authid @@ -92,7 +90,7 @@ typedef FormData_pg_authid *Form_pg_authid; * user choices. * ---------------- */ -DATA(insert OID = 10 ( "POSTGRES" t t t t t t -1 _null_ _null_ _null_ )); +DATA(insert OID = 10 ( "POSTGRES" t t t t t t -1 _null_ _null_ )); #define BOOTSTRAP_SUPERUSERID 10 diff --git a/src/include/catalog/pg_database.h b/src/include/catalog/pg_database.h index 3a0516f..2a614fa 100644 --- a/src/include/catalog/pg_database.h +++ b/src/include/catalog/pg_database.h @@ -41,7 +41,6 @@ CATALOG(pg_database,1262) BKI_SHARED_RELATION Oid datlastsysoid; /* highest OID to consider a system OID */ TransactionId datfrozenxid; /* all Xids < this are frozen in this DB */ Oid dattablespace; /* default table space for this DB */ - text datconfig[1]; /* database-specific GUC (VAR LENGTH) */ aclitem datacl[1]; /* access permissions (VAR LENGTH) */ } FormData_pg_database; @@ -56,7 +55,7 @@ typedef FormData_pg_database *Form_pg_database; * compiler constants for pg_database * ---------------- */ -#define Natts_pg_database 13 +#define Natts_pg_database 12 #define Anum_pg_database_datname 1 #define Anum_pg_database_datdba 2 #define Anum_pg_database_encoding 3 @@ -68,10 +67,9 @@ typedef FormData_pg_database *Form_pg_database; #define Anum_pg_database_datlastsysoid 9 #define Anum_pg_database_datfrozenxid 10 #define Anum_pg_database_dattablespace 11 -#define Anum_pg_database_datconfig 12 -#define Anum_pg_database_datacl 13 +#define Anum_pg_database_datacl 12 -DATA(insert OID = 1 ( template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_ _null_)); +DATA(insert OID = 1 ( template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_)); SHDESCR("default template database"); #define TemplateDbOid 1 diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h index bd6e0cf..7a67aa1 100644 --- a/src/include/catalog/toasting.h +++ b/src/include/catalog/toasting.h @@ -58,5 +58,8 @@ DECLARE_TOAST(pg_database, 2844, 2845); DECLARE_TOAST(pg_shdescription, 2846, 2847); #define PgShdescriptionToastTable 2846 #define PgShdescriptionToastIndex 2847 +DECLARE_TOAST(pg_setting, 2966, 2967); +#define PgSettingToastTable 2966 +#define PgSettingToastIndex 2967 #endif /* TOASTING_H */ diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 16055f5..f731df6 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -86,6 +86,7 @@ typedef enum PGC_S_ARGV, /* postmaster command line */ PGC_S_DATABASE, /* per-database setting */ PGC_S_USER, /* per-user setting */ + PGC_S_DATABASE_USER, /* per-user-and-database setting */ PGC_S_CLIENT, /* from client connection request */ PGC_S_OVERRIDE, /* special case to forcibly set default */ PGC_S_INTERACTIVE, /* dividing line for error reporting */ diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 2667a13..c773b81 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1285,10 +1285,10 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem pg_locks | SELECT l.locktype, l.database, l.relation, l.page, l.tuple, l.virtualxid, l.transactionid, l.classid, l.objid, l.objsubid, l.virtualtransaction, l.pid, l.mode, l.granted FROM pg_lock_status() l(locktype, database, relation, page, tuple, virtualxid, transactionid, classid, objid, objsubid, virtualtransaction, pid, mode, granted); pg_prepared_statements | SELECT p.name, p.statement, p.prepare_time, p.parameter_types, p.from_sql FROM pg_prepared_statement() p(name, statement, prepare_time, parameter_types, from_sql); pg_prepared_xacts | SELECT p.transaction, p.gid, p.prepared, u.rolname AS owner, d.datname AS database FROM ((pg_prepared_xact() p(transaction, gid, prepared, ownerid, dbid) LEFT JOIN pg_authid u ON ((p.ownerid = u.oid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid))); - pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, pg_authid.rolconfig, pg_authid.oid FROM pg_authid; + pg_roles | SELECT pg_authid.rolname, pg_authid.rolsuper, pg_authid.rolinherit, pg_authid.rolcreaterole, pg_authid.rolcreatedb, pg_authid.rolcatupdate, pg_authid.rolcanlogin, pg_authid.rolconnlimit, '********'::text AS rolpassword, pg_authid.rolvaliduntil, NULL::unknown AS rolconfig, pg_authid.oid FROM pg_authid; pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name); pg_settings | SELECT a.name, a.setting, a.unit, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val, a.enumvals, a.boot_val, a.reset_val, a.sourcefile, a.sourceline FROM pg_show_all_settings() a(name, setting, unit, category, short_desc, extra_desc, context, vartype, source, min_val, max_val, enumvals, boot_val, reset_val, sourcefile, sourceline); - pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, pg_authid.rolconfig AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin; + pg_shadow | SELECT pg_authid.rolname AS usename, pg_authid.oid AS usesysid, pg_authid.rolcreatedb AS usecreatedb, pg_authid.rolsuper AS usesuper, pg_authid.rolcatupdate AS usecatupd, pg_authid.rolpassword AS passwd, (pg_authid.rolvaliduntil)::abstime AS valuntil, NULL::unknown AS useconfig FROM pg_authid WHERE pg_authid.rolcanlogin; pg_stat_activity | SELECT s.datid, d.datname, s.procpid, s.usesysid, u.rolname AS usename, s.current_query, s.waiting, s.xact_start, s.query_start, s.backend_start, s.client_addr, s.client_port FROM pg_database d, pg_stat_get_activity(NULL::integer) s(datid, procpid, usesysid, current_query, waiting, xact_start, query_start, backend_start, client_addr, client_port), pg_authid u WHERE ((s.datid = d.oid) AND (s.usesysid = u.oid)); pg_stat_all_indexes | SELECT c.oid AS relid, i.oid AS indexrelid, n.nspname AS schemaname, c.relname, i.relname AS indexrelname, pg_stat_get_numscans(i.oid) AS idx_scan, pg_stat_get_tuples_returned(i.oid) AS idx_tup_read, pg_stat_get_tuples_fetched(i.oid) AS idx_tup_fetch FROM (((pg_class c JOIN pg_index x ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"])); pg_stat_all_tables | SELECT c.oid AS relid, n.nspname AS schemaname, c.relname, pg_stat_get_numscans(c.oid) AS seq_scan, pg_stat_get_tuples_returned(c.oid) AS seq_tup_read, (sum(pg_stat_get_numscans(i.indexrelid)))::bigint AS idx_scan, ((sum(pg_stat_get_tuples_fetched(i.indexrelid)))::bigint + pg_stat_get_tuples_fetched(c.oid)) AS idx_tup_fetch, pg_stat_get_tuples_inserted(c.oid) AS n_tup_ins, pg_stat_get_tuples_updated(c.oid) AS n_tup_upd, pg_stat_get_tuples_deleted(c.oid) AS n_tup_del, pg_stat_get_tuples_hot_updated(c.oid) AS n_tup_hot_upd, pg_stat_get_live_tuples(c.oid) AS n_live_tup, pg_stat_get_dead_tuples(c.oid) AS n_dead_tup, pg_stat_get_last_vacuum_time(c.oid) AS last_vacuum, pg_stat_get_last_autovacuum_time(c.oid) AS last_autovacuum, pg_stat_get_last_analyze_time(c.oid) AS last_analyze, pg_stat_get_last_autoanalyze_time(c.oid) AS last_autoanalyze FROM ((pg_class c LEFT JOIN pg_index i ON ((c.oid = i.indrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = ANY (ARRAY['r'::"char", 't'::"char"])) GROUP BY c.oid, n.nspname, c.relname; @@ -1424,10 +1424,10 @@ insert into rule_and_refint_t3 values (1, 12, 11, 'row3'); insert into rule_and_refint_t3 values (1, 12, 12, 'row4'); insert into rule_and_refint_t3 values (1, 11, 13, 'row5'); ERROR: insert or update on table "rule_and_refint_t3" violates foreign key constraint "rule_and_refint_t3_id3a_fkey1" -DETAIL: Key (id3a,id3c)=(1,13) is not present in table "rule_and_refint_t2". +DETAIL: Key (id3a, id3c)=(1, 13) is not present in table "rule_and_refint_t2". insert into rule_and_refint_t3 values (1, 13, 11, 'row6'); ERROR: insert or update on table "rule_and_refint_t3" violates foreign key constraint "rule_and_refint_t3_id3a_fkey" -DETAIL: Key (id3a,id3b)=(1,13) is not present in table "rule_and_refint_t1". +DETAIL: Key (id3a, id3b)=(1, 13) is not present in table "rule_and_refint_t1". create rule rule_and_refint_t3_ins as on insert to rule_and_refint_t3 where (exists (select 1 from rule_and_refint_t3 where (((rule_and_refint_t3.id3a = new.id3a) @@ -1439,10 +1439,10 @@ create rule rule_and_refint_t3_ins as on insert to rule_and_refint_t3 and (rule_and_refint_t3.id3c = new.id3c)); insert into rule_and_refint_t3 values (1, 11, 13, 'row7'); ERROR: insert or update on table "rule_and_refint_t3" violates foreign key constraint "rule_and_refint_t3_id3a_fkey1" -DETAIL: Key (id3a,id3c)=(1,13) is not present in table "rule_and_refint_t2". +DETAIL: Key (id3a, id3c)=(1, 13) is not present in table "rule_and_refint_t2". insert into rule_and_refint_t3 values (1, 13, 11, 'row8'); ERROR: insert or update on table "rule_and_refint_t3" violates foreign key constraint "rule_and_refint_t3_id3a_fkey" -DETAIL: Key (id3a,id3b)=(1,13) is not present in table "rule_and_refint_t1". +DETAIL: Key (id3a, id3b)=(1, 13) is not present in table "rule_and_refint_t1". -- -- check for planner problems with complex inherited UPDATES -- diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out index 7213192..3e6e134 100644 --- a/src/test/regress/expected/sanity_check.out +++ b/src/test/regress/expected/sanity_check.out @@ -112,6 +112,7 @@ SELECT relname, relhasindex pg_pltemplate | t pg_proc | t pg_rewrite | t + pg_setting | t pg_shdepend | t pg_shdescription | t pg_statistic | t @@ -151,7 +152,7 @@ SELECT relname, relhasindex timetz_tbl | f tinterval_tbl | f varchar_tbl | f -(140 rows) +(141 rows) -- -- another sanity check: every system catalog that has OIDs should have