Index: doc/src/sgml/catalogs.sgml
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/doc/src/sgml/catalogs.sgml,v
retrieving revision 2.206
diff -c -p -r2.206 catalogs.sgml
*** doc/src/sgml/catalogs.sgml	10 Aug 2009 22:13:50 -0000	2.206
--- doc/src/sgml/catalogs.sgml	26 Aug 2009 02:01:11 -0000
***************
*** 199,204 ****
--- 199,209 ----
       </row>
  
       <row>
+       <entry><link linkend="catalog-pg-setting"><structname>pg_setting</structname></link></entry>
+       <entry>per-user and per-database settings</entry>
+      </row>
+ 
+      <row>
        <entry><link linkend="catalog-pg-shdepend"><structname>pg_shdepend</structname></link></entry>
        <entry>dependencies on shared objects</entry>
       </row>
***************
*** 2132,2144 ****
       </row>
  
       <row>
-       <entry><structfield>datconfig</structfield></entry>
-       <entry><type>text[]</type></entry>
-       <entry></entry>
-       <entry>Session defaults for run-time configuration variables</entry>
-      </row>
- 
-      <row>
        <entry><structfield>datacl</structfield></entry>
        <entry><type>aclitem[]</type></entry>
        <entry></entry>
--- 2137,2142 ----
***************
*** 3996,4001 ****
--- 3994,4058 ----
  
   </sect1>
  
+  <sect1 id="catalog-pg-setting">
+   <title><structname>pg_setting</structname></title>
+ 
+   <indexterm zone="catalog-pg-setting">
+    <primary>pg_setting</primary>
+   </indexterm>
+ 
+   <para>
+    The catalog <structname>pg_setting</structname> records the default
+    values that have been set for run-time configuration variables,
+    for each role and database combination.
+   </para>
+ 
+   <para>
+    Unlike most system catalogs, <structname>pg_setting</structname>
+    is shared across all databases of a cluster: there is only one
+    copy of <structname>pg_setting</structname> per cluster, not
+    one per database.
+   </para>
+ 
+   <table>
+    <title><structname>pg_setting</> Columns</title>
+ 
+    <tgroup cols="4">
+     <thead>
+      <row>
+       <entry>Name</entry>
+       <entry>Type</entry>
+       <entry>References</entry>
+       <entry>Description</entry>
+      </row>
+     </thead>
+ 
+     <tbody>
+      <row>
+       <entry><structfield>setdatabase</structfield></entry>
+       <entry><type>oid</type></entry>
+       <entry><literal><link linkend="catalog-pg-database"><structname>pg_database</structname></link>.oid</literal></entry>
+       <entry>The OID of the database the setting is applicable to, or zero if not database-specific</entry>
+      </row>
+ 
+      <row>
+       <entry><structfield>setrole</structfield></entry>
+       <entry><type>oid</type></entry>
+       <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
+       <entry>The OID of the role the setting is applicable to, or zero if not role-specific</entry>
+      </row>
+ 
+      <row>
+       <entry><structfield>setconfig</structfield></entry>
+       <entry><type>text[]</type></entry>
+       <entry></entry>
+       <entry>Defaults for run-time configuration variables</entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
+  </sect1>
+ 
  
   <sect1 id="catalog-pg-shdepend">
    <title><structname>pg_shdepend</structname></title>
***************
*** 6448,6460 ****
       </row>
  
       <row>
-       <entry><structfield>rolconfig</structfield></entry>
-       <entry><type>text[]</type></entry>
-       <entry></entry>
-       <entry>Session defaults for run-time configuration variables</entry>
-      </row>
- 
-      <row>
        <entry><structfield>oid</structfield></entry>
        <entry><type>oid</type></entry>
        <entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
--- 6505,6510 ----
Index: src/backend/catalog/Makefile
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/catalog/Makefile,v
retrieving revision 1.70
diff -c -p -r1.70 Makefile
*** src/backend/catalog/Makefile	12 May 2009 00:56:05 -0000	1.70
--- src/backend/catalog/Makefile	25 Aug 2009 19:15:03 -0000
*************** include $(top_builddir)/src/Makefile.glo
*** 13,19 ****
  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
  
  BKIFILES = postgres.bki postgres.description postgres.shdescription
  
--- 13,19 ----
  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_setting.o pg_shdepend.o pg_type.o storage.o toasting.o
  
  BKIFILES = postgres.bki postgres.description postgres.shdescription
  
*************** POSTGRES_BKI_SRCS = $(addprefix $(top_sr
*** 32,38 ****
  	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_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 \
--- 32,38 ----
  	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_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 \
Index: src/backend/catalog/catalog.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/catalog/catalog.c,v
retrieving revision 1.83
diff -c -p -r1.83 catalog.c
*** src/backend/catalog/catalog.c	11 Jun 2009 14:48:54 -0000	1.83
--- src/backend/catalog/catalog.c	24 Aug 2009 22:41:36 -0000
***************
*** 31,36 ****
--- 31,37 ----
  #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"
*************** IsSharedRelation(Oid relationId)
*** 306,312 ****
  		relationId == PLTemplateRelationId ||
  		relationId == SharedDescriptionRelationId ||
  		relationId == SharedDependRelationId ||
! 		relationId == TableSpaceRelationId)
  		return true;
  	/* These are their indexes (see indexing.h) */
  	if (relationId == AuthIdRolnameIndexId ||
--- 307,314 ----
  		relationId == PLTemplateRelationId ||
  		relationId == SharedDescriptionRelationId ||
  		relationId == SharedDependRelationId ||
! 		relationId == TableSpaceRelationId ||
! 		relationId == SettingRelationId)
  		return true;
  	/* These are their indexes (see indexing.h) */
  	if (relationId == AuthIdRolnameIndexId ||
*************** IsSharedRelation(Oid relationId)
*** 320,326 ****
  		relationId == SharedDependDependerIndexId ||
  		relationId == SharedDependReferenceIndexId ||
  		relationId == TablespaceOidIndexId ||
! 		relationId == TablespaceNameIndexId)
  		return true;
  	/* These are their toast tables and toast indexes (see toasting.h) */
  	if (relationId == PgAuthidToastTable ||
--- 322,329 ----
  		relationId == SharedDependDependerIndexId ||
  		relationId == SharedDependReferenceIndexId ||
  		relationId == TablespaceOidIndexId ||
! 		relationId == TablespaceNameIndexId ||
! 		relationId == SettingDatidRolidIndexId)
  		return true;
  	/* These are their toast tables and toast indexes (see toasting.h) */
  	if (relationId == PgAuthidToastTable ||
*************** IsSharedRelation(Oid relationId)
*** 328,334 ****
  		relationId == PgDatabaseToastTable ||
  		relationId == PgDatabaseToastIndex ||
  		relationId == PgShdescriptionToastTable ||
! 		relationId == PgShdescriptionToastIndex)
  		return true;
  	return false;
  }
--- 331,339 ----
  		relationId == PgDatabaseToastTable ||
  		relationId == PgDatabaseToastIndex ||
  		relationId == PgShdescriptionToastTable ||
! 		relationId == PgShdescriptionToastIndex ||
! 		relationId == PgSettingToastTable ||
! 		relationId == PgSettingToastIndex)
  		return true;
  	return false;
  }
Index: src/backend/catalog/pg_setting.c
===================================================================
RCS file: src/backend/catalog/pg_setting.c
diff -N src/backend/catalog/pg_setting.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- src/backend/catalog/pg_setting.c	25 Aug 2009 21:15:57 -0000
***************
*** 0 ****
--- 1,231 ----
+ /*
+  * pg_setting.c
+  *		Routines to support manipulation of the pg_setting relation
+  *    
+  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * IDENTIFICATION
+  *		$PostgreSQL$
+  */
+ #include "postgres.h"
+ 
+ #include "access/genam.h"
+ #include "access/heapam.h"
+ #include "access/htup.h"
+ #include "access/skey.h"
+ #include "catalog/indexing.h"
+ #include "catalog/pg_setting.h"
+ #include "utils/fmgroids.h"
+ #include "utils/rel.h"
+ #include "utils/tqual.h"
+ 
+ void
+ AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt)
+ {
+ 	char	   *valuestr;
+ 	HeapTuple	tuple;
+ 	Relation	rel;
+ 	ScanKeyData scankey[2];
+ 	SysScanDesc scan;
+ 
+ 	valuestr = ExtractSetVariableArgs(setstmt);
+ 
+ 	/* Get the old tuple, if any. */
+ 
+ 	rel = heap_open(SettingRelationId, RowExclusiveLock);
+ 	ScanKeyInit(&scankey[0],
+ 				Anum_pg_setting_setdatabase,
+ 				BTEqualStrategyNumber, F_OIDEQ,
+ 				ObjectIdGetDatum(databaseid));
+ 	ScanKeyInit(&scankey[1],
+ 				Anum_pg_setting_setrole,
+ 				BTEqualStrategyNumber, F_OIDEQ,
+ 				ObjectIdGetDatum(roleid));
+ 	scan = systable_beginscan(rel, SettingDatidRolidIndexId, true,
+ 							  SnapshotNow, 2, scankey);
+ 	tuple = systable_getnext(scan);
+ 
+ 	/*
+ 	 * There are three cases:
+ 	 *
+ 	 * - in RESET ALL, simply delete the pg_setting tuple (if any)
+ 	 *
+ 	 * - in other commands, if there's a tuple in pg_setting, update it;
+ 	 *   if it ends up empty, delete it
+ 	 *
+ 	 * - otherwise, insert a new pg_setting tuple, but only if the command is
+ 	 *   not RESET
+ 	 */
+ 	if (setstmt->kind == VAR_RESET_ALL)
+ 	{
+ 		if (HeapTupleIsValid(tuple))
+ 			simple_heap_delete(rel, &tuple->t_self);
+ 	}
+ 	else if (HeapTupleIsValid(tuple))
+ 	{
+ 		Datum		repl_val[Natts_pg_setting];
+ 		bool		repl_null[Natts_pg_setting];
+ 		bool		repl_repl[Natts_pg_setting];
+ 		HeapTuple	newtuple;
+ 		Datum		datum;
+ 		bool		isnull;
+ 		ArrayType  *a;
+ 
+ 		memset(repl_repl, false, sizeof(repl_repl));
+ 		repl_repl[Anum_pg_setting_setconfig - 1] = true;
+ 		repl_null[Anum_pg_setting_setconfig - 1] = false;
+ 
+ 		/* Extract old value of setconfig */
+ 		datum = heap_getattr(tuple, Anum_pg_setting_setconfig,
+ 							 RelationGetDescr(rel), &isnull);
+ 		a = isnull ? NULL : DatumGetArrayTypeP(datum);
+ 
+ 		/* Update (valuestr is NULL in RESET cases) */
+ 		if (valuestr)
+ 			a = GUCArrayAdd(a, setstmt->name, valuestr);
+ 		else
+ 			a = GUCArrayDelete(a, setstmt->name);
+ 
+ 		if (a)
+ 		{
+ 			repl_val[Anum_pg_setting_setconfig - 1] = PointerGetDatum(a);
+ 
+ 			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);
+ 		}
+ 		else
+ 		{
+ 			simple_heap_delete(rel, &tuple->t_self);
+ 		}
+ 	}
+ 	else if (valuestr)
+ 	{
+ 		/* non-null valuestr means it's not RESET, so insert a new tuple */
+ 		HeapTuple	newtuple;
+ 		Datum		values[Natts_pg_setting];
+ 		bool		nulls[Natts_pg_setting];
+ 		ArrayType  *a;
+ 
+ 		memset(nulls, false, sizeof(nulls));
+ 		
+ 		a = GUCArrayAdd(NULL, setstmt->name, valuestr);
+ 
+ 		values[Anum_pg_setting_setdatabase - 1] = ObjectIdGetDatum(databaseid);
+ 		values[Anum_pg_setting_setrole - 1] = ObjectIdGetDatum(roleid);
+ 		values[Anum_pg_setting_setconfig - 1] = PointerGetDatum(a);
+ 		newtuple = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+ 
+ 		simple_heap_insert(rel, newtuple);
+ 
+ 		/* Update indexes */
+ 		CatalogUpdateIndexes(rel, newtuple);
+ 	}
+ 
+ 	systable_endscan(scan);
+ 
+ 	/* Close pg_setting, but keep lock till commit */
+ 	heap_close(rel, NoLock);
+ }
+ 
+ /*
+  * Drop some settings from the catalog.  These can be for a particular
+  * database, or for a particular role.  (It is of course possible to do both
+  * too, but it doesn't make sense for current uses.)
+  */
+ void
+ DropSetting(Oid databaseid, Oid roleid)
+ {
+ 	Relation		relsetting;
+ 	HeapScanDesc	scan;
+ 	ScanKeyData		keys[2];
+ 	HeapTuple		tup;
+ 	int				numkeys = 0;
+ 
+ 	relsetting = heap_open(SettingRelationId, RowExclusiveLock);
+ 
+ 	if (OidIsValid(databaseid))
+ 	{
+ 		ScanKeyInit(&keys[numkeys],
+ 					Anum_pg_setting_setdatabase,
+ 					BTEqualStrategyNumber,
+ 					F_OIDEQ,
+ 					ObjectIdGetDatum(databaseid));
+ 		numkeys++;
+ 	}
+ 	if (OidIsValid(roleid))
+ 	{
+ 		ScanKeyInit(&keys[numkeys],
+ 					Anum_pg_setting_setrole,
+ 					BTEqualStrategyNumber,
+ 					F_OIDEQ,
+ 					ObjectIdGetDatum(roleid));
+ 		numkeys++;
+ 	}
+ 
+ 	scan = heap_beginscan(relsetting, SnapshotNow, numkeys, keys);
+ 	while (HeapTupleIsValid(tup = heap_getnext(scan, ForwardScanDirection)))
+ 	{
+ 		simple_heap_delete(relsetting, &tup->t_self);
+ 	}
+ 	heap_endscan(scan);
+ 
+ 	heap_close(relsetting, RowExclusiveLock);
+ }
+ 
+ /*
+  * Scan pg_setting looking for applicable settings, and load them on the
+  * current process.
+  *
+  * relsetting is pg_setting, already opened and locked.
+  *
+  * Note: we only consider setting for the exact databaseid/roleid combination.
+  * This probably needs to be called more than once, with InvalidOid passed as
+  * databaseid/roleid.
+  */
+ void
+ ApplySetting(Oid databaseid, Oid roleid, Relation relsetting, GucSource source)
+ {
+ 	SysScanDesc		scan;
+ 	ScanKeyData		keys[2];
+ 	HeapTuple		tup;
+ 
+ 	ScanKeyInit(&keys[0],
+ 				Anum_pg_setting_setdatabase,
+ 				BTEqualStrategyNumber,
+ 				F_OIDEQ,
+ 				ObjectIdGetDatum(databaseid));
+ 	ScanKeyInit(&keys[1],
+ 				Anum_pg_setting_setrole,
+ 				BTEqualStrategyNumber,
+ 				F_OIDEQ,
+ 				ObjectIdGetDatum(roleid));
+ 
+ 	scan = systable_beginscan(relsetting, SettingDatidRolidIndexId, true,
+ 							  SnapshotNow, 2, keys);
+ 	while (HeapTupleIsValid(tup = systable_getnext(scan)))
+ 	{
+ 		bool	isnull;
+ 		Datum	datum;
+ 
+ 		datum = heap_getattr(tup, Anum_pg_setting_setconfig,
+ 							 RelationGetDescr(relsetting), &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_settings was checked when it
+ 			 * was inserted.
+ 			 */
+ 			ProcessGUCArray(a, PGC_SUSET, source, GUC_ACTION_SET);
+ 		}
+ 	}
+ 
+ 	systable_endscan(scan);
+ }
Index: src/backend/catalog/system_views.sql
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/catalog/system_views.sql,v
retrieving revision 1.60
diff -c -p -r1.60 system_views.sql
*** src/backend/catalog/system_views.sql	7 Apr 2009 00:31:26 -0000	1.60
--- src/backend/catalog/system_views.sql	24 Aug 2009 22:32:31 -0000
*************** CREATE VIEW pg_roles AS 
*** 18,24 ****
          rolconnlimit,
          '********'::text as rolpassword,
          rolvaliduntil,
!         rolconfig,
          oid
      FROM pg_authid;
  
--- 18,24 ----
          rolconnlimit,
          '********'::text as rolpassword,
          rolvaliduntil,
!         NULL as rolconfig,
          oid
      FROM pg_authid;
  
*************** CREATE VIEW pg_shadow AS
*** 31,37 ****
          rolcatupdate AS usecatupd,
          rolpassword AS passwd,
          rolvaliduntil::abstime AS valuntil,
!         rolconfig AS useconfig
      FROM pg_authid
      WHERE rolcanlogin;
  
--- 31,37 ----
          rolcatupdate AS usecatupd,
          rolpassword AS passwd,
          rolvaliduntil::abstime AS valuntil,
!         NULL AS useconfig
      FROM pg_authid
      WHERE rolcanlogin;
  
Index: src/backend/commands/dbcommands.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/dbcommands.c,v
retrieving revision 1.225
diff -c -p -r1.225 dbcommands.c
*** src/backend/commands/dbcommands.c	11 Jun 2009 14:48:55 -0000	1.225
--- src/backend/commands/dbcommands.c	25 Aug 2009 19:43:40 -0000
***************
*** 33,38 ****
--- 33,39 ----
  #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"
***************
*** 51,57 ****
  #include "utils/builtins.h"
  #include "utils/flatfiles.h"
  #include "utils/fmgroids.h"
- #include "utils/guc.h"
  #include "utils/lsyscache.h"
  #include "utils/pg_locale.h"
  #include "utils/snapmgr.h"
--- 52,57 ----
*************** createdb(const CreatedbStmt *stmt)
*** 545,556 ****
  	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.
  	 */
- 	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),
--- 545,554 ----
  	new_record[Anum_pg_database_dattablespace - 1] = ObjectIdGetDatum(dst_deftablespace);
  
  	/*
! 	 * 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_datacl - 1] = true;
  
  	tuple = heap_form_tuple(RelationGetDescr(pg_database_rel),
*************** dropdb(const char *dbname, bool missing_
*** 824,829 ****
--- 822,832 ----
  	DeleteSharedComments(db_id, DatabaseRelationId);
  
  	/*
+ 	 * Remove settings associated with this database
+ 	 */
+ 	DropSetting(db_id, InvalidOid);
+ 
+ 	/*
  	 * Remove shared dependency references for the database.
  	 */
  	dropDatabaseDependencies(db_id);
*************** AlterDatabase(AlterDatabaseStmt *stmt, b
*** 1415,1499 ****
  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);
  
  	/*
  	 * We don't bother updating the flat file since ALTER DATABASE SET doesn't
--- 1418,1439 ----
  void
  AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
  {
! 	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);
  
  	/*
  	 * We don't bother updating the flat file since ALTER DATABASE SET doesn't
Index: src/backend/commands/user.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/commands/user.c,v
retrieving revision 1.187
diff -c -p -r1.187 user.c
*** src/backend/commands/user.c	11 Jun 2009 14:48:56 -0000	1.187
--- src/backend/commands/user.c	25 Aug 2009 21:16:09 -0000
***************
*** 19,24 ****
--- 19,25 ----
  #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"
***************
*** 28,34 ****
  #include "utils/builtins.h"
  #include "utils/flatfiles.h"
  #include "utils/fmgroids.h"
- #include "utils/guc.h"
  #include "utils/lsyscache.h"
  #include "utils/syscache.h"
  #include "utils/tqual.h"
--- 29,34 ----
*************** CreateRole(CreateRoleStmt *stmt)
*** 342,349 ****
  	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);
  
  	/*
--- 342,347 ----
*************** AlterRole(AlterRoleStmt *stmt)
*** 728,757 ****
  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];
  
! 	valuestr = ExtractSetVariableArgs(stmt->setstmt);
  
! 	rel = heap_open(AuthIdRelationId, RowExclusiveLock);
! 	oldtuple = SearchSysCache(AUTHNAME,
! 							  PointerGetDatum(stmt->role),
! 							  0, 0, 0);
! 	if (!HeapTupleIsValid(oldtuple))
  		ereport(ERROR,
  				(errcode(ERRCODE_UNDEFINED_OBJECT),
  				 errmsg("role \"%s\" does not exist", stmt->role)));
  
  	/*
  	 * 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 (!superuser())
  			ereport(ERROR,
--- 726,749 ----
  void
  AlterRoleSet(AlterRoleSetStmt *stmt)
  {
! 	HeapTuple	roletuple;
  
! 	roletuple = SearchSysCache(AUTHNAME,
! 							   PointerGetDatum(stmt->role),
! 							   0, 0, 0);
  
! 	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(roletuple))->rolsuper)
  	{
  		if (!superuser())
  			ereport(ERROR,
*************** AlterRoleSet(AlterRoleSetStmt *stmt)
*** 761,815 ****
  	else
  	{
  		if (!have_createrole_privilege() &&
! 			HeapTupleGetOid(oldtuple) != 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);
! 	/* needn't keep lock since we won't be updating the flat file */
! 	heap_close(rel, RowExclusiveLock);
  }
  
  
--- 753,767 ----
  	else
  	{
  		if (!have_createrole_privilege() &&
! 			HeapTupleGetOid(roletuple) != GetUserId())
  			ereport(ERROR,
  					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
  					 errmsg("permission denied")));
  	}
  
! 	AlterSetting(InvalidOid, HeapTupleGetOid(roletuple), stmt->setstmt);
  
! 	ReleaseSysCache(roletuple);
  }
  
  
*************** DropRole(DropRoleStmt *stmt)
*** 958,963 ****
--- 910,920 ----
  		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 ---
Index: src/backend/utils/init/miscinit.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/init/miscinit.c,v
retrieving revision 1.176
diff -c -p -r1.176 miscinit.c
*** src/backend/utils/init/miscinit.c	12 Aug 2009 20:53:30 -0000	1.176
--- src/backend/utils/init/miscinit.c	26 Aug 2009 02:15:51 -0000
*************** InitializeSessionUserId(const char *role
*** 392,399 ****
  {
  	HeapTuple	roleTup;
  	Form_pg_authid rform;
- 	Datum		datum;
- 	bool		isnull;
  	Oid			roleid;
  
  	/*
--- 392,397 ----
*************** InitializeSessionUserId(const char *role
*** 470,493 ****
  					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);
  }
  
--- 468,473 ----
Index: src/backend/utils/init/postinit.c
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/backend/utils/init/postinit.c,v
retrieving revision 1.194
diff -c -p -r1.194 postinit.c
*** src/backend/utils/init/postinit.c	12 Aug 2009 20:53:30 -0000	1.194
--- src/backend/utils/init/postinit.c	25 Aug 2009 19:58:05 -0000
***************
*** 26,31 ****
--- 26,32 ----
  #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/libpq-be.h"
  #include "mb/pg_wchar.h"
*************** static void CheckMyDatabase(const char *
*** 58,64 ****
  static void InitCommunication(void);
  static void ShutdownPostgres(int code, Datum arg);
  static bool ThereIsAtLeastOneRole(void);
! 
  
  /*** InitPostgres support ***/
  
--- 59,65 ----
  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 ***/
  
*************** CheckMyDatabase(const char *name, bool a
*** 277,305 ****
  	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);
  }
  
--- 278,283 ----
*************** InitPostgres(const char *in_dbname, Oid 
*** 659,664 ****
--- 637,645 ----
  				(errcode(ERRCODE_TOO_MANY_CONNECTIONS),
  				 errmsg("connection limit exceeded for non-superusers")));
  
+ 	/* Process pg_setting options */
+ 	process_settings(MyDatabaseId, GetSessionUserId());
+ 
  	/*
  	 * Initialize various default states that can't be set up until we've
  	 * selected the active user and gotten the right GUC settings.
*************** InitPostgres(const char *in_dbname, Oid 
*** 681,686 ****
--- 662,689 ----
  	return am_superuser;
  }
  
+ /*
+  * 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
Index: src/include/catalog/indexing.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/indexing.h,v
retrieving revision 1.108
diff -c -p -r1.108 indexing.h
*** src/include/catalog/indexing.h	11 Jun 2009 14:49:09 -0000	1.108
--- src/include/catalog/indexing.h	24 Aug 2009 22:40:59 -0000
*************** DECLARE_UNIQUE_INDEX(pg_user_mapping_oid
*** 267,272 ****
--- 267,275 ----
  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
  
Index: src/include/catalog/pg_attribute.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/pg_attribute.h,v
retrieving revision 1.152
diff -c -p -r1.152 pg_attribute.h
*** src/include/catalog/pg_attribute.h	12 Aug 2009 20:53:30 -0000	1.152
--- src/include/catalog/pg_attribute.h	24 Aug 2009 21:47:31 -0000
*************** DATA(insert ( 1259 tableoid			26 0 0  4 
*** 485,492 ****
  { 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 } }
  
  /* ----------------
   *		pg_index
--- 485,491 ----
  { 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, {"datacl"},			1034, -1, 0,   -1, 12, 1, -1, -1, false, 'x', 'i', false, false, false, true, 0, { 0 } }
  
  /* ----------------
   *		pg_index
Index: src/include/catalog/pg_authid.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/pg_authid.h,v
retrieving revision 1.9
diff -c -p -r1.9 pg_authid.h
*** src/include/catalog/pg_authid.h	1 Jan 2009 17:23:56 -0000	1.9
--- src/include/catalog/pg_authid.h	24 Aug 2009 21:39:19 -0000
*************** CATALOG(pg_authid,1260) BKI_SHARED_RELAT
*** 55,61 ****
  	/* 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
--- 55,60 ----
*************** typedef FormData_pg_authid *Form_pg_auth
*** 83,89 ****
  #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
--- 82,87 ----
*************** typedef FormData_pg_authid *Form_pg_auth
*** 92,98 ****
   * user choices.
   * ----------------
   */
! DATA(insert OID = 10 ( "POSTGRES" t t t t t t -1 _null_ _null_ _null_ ));
  
  #define BOOTSTRAP_SUPERUSERID 10
  
--- 90,96 ----
   * user choices.
   * ----------------
   */
! DATA(insert OID = 10 ( "POSTGRES" t t t t t t -1 _null_ _null_ ));
  
  #define BOOTSTRAP_SUPERUSERID 10
  
Index: src/include/catalog/pg_database.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/pg_database.h,v
retrieving revision 1.49
diff -c -p -r1.49 pg_database.h
*** src/include/catalog/pg_database.h	1 Jan 2009 17:23:57 -0000	1.49
--- src/include/catalog/pg_database.h	24 Aug 2009 22:35:04 -0000
*************** CATALOG(pg_database,1262) BKI_SHARED_REL
*** 41,47 ****
  	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;
  
--- 41,46 ----
*************** typedef FormData_pg_database *Form_pg_da
*** 56,62 ****
   *		compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database				13
  #define Anum_pg_database_datname		1
  #define Anum_pg_database_datdba			2
  #define Anum_pg_database_encoding		3
--- 55,61 ----
   *		compiler constants for pg_database
   * ----------------
   */
! #define Natts_pg_database				12
  #define Anum_pg_database_datname		1
  #define Anum_pg_database_datdba			2
  #define Anum_pg_database_encoding		3
*************** typedef FormData_pg_database *Form_pg_da
*** 68,77 ****
  #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
  
! DATA(insert OID = 1 (  template1 PGUID ENCODING "LC_COLLATE" "LC_CTYPE" t t -1 0 0 1663 _null_ _null_));
  SHDESCR("default template database");
  #define TemplateDbOid			1
  
--- 67,75 ----
  #define Anum_pg_database_datlastsysoid	9
  #define Anum_pg_database_datfrozenxid	10
  #define Anum_pg_database_dattablespace	11
! #define Anum_pg_database_datacl			12
  
! 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
  
Index: src/include/catalog/pg_setting.h
===================================================================
RCS file: src/include/catalog/pg_setting.h
diff -N src/include/catalog/pg_setting.h
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- src/include/catalog/pg_setting.h	25 Aug 2009 19:59:31 -0000
***************
*** 0 ****
--- 1,67 ----
+ /*-------------------------------------------------------------------------
+  *
+  * pg_setting.h
+  *	definition of configuration settings
+  *
+  *
+  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  * $PostgreSQL: pgsql/src/include/catalog/pg_ts_config.h,v 1.5 2009-01-01 17:23:58 momjian Exp $
+  *
+  * NOTES
+  *		the genbki.sh script reads this file and generates .bki
+  *		information from the DATA() statements.
+  *
+  *		XXX do NOT break up DATA() statements into multiple lines!
+  *			the scripts are not as smart as you might think...
+  *
+  *-------------------------------------------------------------------------
+  */
+ #ifndef PG_SETTING_H
+ #define PG_SETTING_H
+ 
+ #include "catalog/genbki.h"
+ #include "nodes/parsenodes.h"
+ #include "utils/guc.h"
+ #include "utils/relcache.h"
+ 
+ /* ----------------
+  *		pg_setting definition.  cpp turns this into
+  *		typedef struct FormData_pg_setting
+  * ----------------
+  */
+ #define SettingRelationId	2964
+ 
+ CATALOG(pg_setting,2964) BKI_SHARED_RELATION BKI_WITHOUT_OIDS
+ {
+ 	Oid			setdatabase;	/* database */
+ 	Oid			setrole;		/* role */
+ 	text		setconfig[1];	/* GUC settings to apply at login */
+ } FormData_pg_setting;
+ 
+ typedef FormData_pg_setting *Form_pg_setting;
+ 
+ /* ----------------
+  *		compiler constants for pg_setting
+  * ----------------
+  */
+ #define Natts_pg_setting				3
+ #define Anum_pg_setting_setdatabase		1
+ #define Anum_pg_setting_setrole			2
+ #define Anum_pg_setting_setconfig		3
+ 
+ /* ----------------
+  *		initial contents of pg_setting are NOTHING
+  * ----------------
+  */
+ 
+ /*
+  * prototypes for functions in pg_setting.h
+  */
+ extern void AlterSetting(Oid databaseid, Oid roleid, VariableSetStmt *setstmt);
+ extern void DropSetting(Oid databaseid, Oid roleid);
+ extern void ApplySetting(Oid databaseid, Oid roleid, Relation pg_setting,
+ 			 GucSource source);
+ 
+ #endif   /* PG_SETTING_H */
Index: src/include/catalog/toasting.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/catalog/toasting.h,v
retrieving revision 1.8
diff -c -p -r1.8 toasting.h
*** src/include/catalog/toasting.h	11 Jun 2009 20:46:11 -0000	1.8
--- src/include/catalog/toasting.h	24 Aug 2009 22:40:36 -0000
*************** DECLARE_TOAST(pg_database, 2844, 2845);
*** 58,62 ****
--- 58,65 ----
  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 */
Index: src/include/utils/guc.h
===================================================================
RCS file: /home/alvherre/Code/cvs/pgsql/src/include/utils/guc.h,v
retrieving revision 1.102
diff -c -p -r1.102 guc.h
*** src/include/utils/guc.h	11 Jun 2009 14:49:13 -0000	1.102
--- src/include/utils/guc.h	24 Aug 2009 21:11:00 -0000
*************** typedef enum
*** 86,91 ****
--- 86,92 ----
  	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 */
