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_shdependdependencies on shared objects
@@ -2132,13 +2137,6 @@
- datconfig
- text[]
-
- Session defaults for run-time configuration variables
-
-
- dataclaclitem[]
@@ -3996,6 +3994,65 @@
+
+ pg_setting
+
+
+ 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.
+
+
+
+ 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
+
+
+
+
+
+
pg_shdepend
@@ -6448,13 +6505,6 @@
- rolconfig
- text[]
-
- Session defaults for run-time configuration variables
-
-
- oidoidpg_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