Index: doc/src/sgml/catalogs.sgml =================================================================== RCS file: /home/alvherre/cvs/pgsql/doc/src/sgml/catalogs.sgml,v retrieving revision 2.207 diff -c -p -r2.207 catalogs.sgml *** doc/src/sgml/catalogs.sgml 22 Sep 2009 23:43:37 -0000 2.207 --- doc/src/sgml/catalogs.sgml 25 Sep 2009 23:46:31 -0000 *************** *** 199,204 **** --- 199,209 ---- + pg_db_role_setting + per-role and per-database settings + + + pg_shdepend dependencies on shared objects *************** *** 2132,2144 **** - datconfig - text[] - - Session defaults for run-time configuration variables - - - datacl aclitem[] --- 2137,2142 ---- *************** *** 4014,4019 **** --- 4012,4076 ---- + + <structname>pg_db_role_setting</structname> + + + pg_db_role_setting + + + + The catalog pg_db_role_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_db_role_setting + is shared across all databases of a cluster: there is only one + copy of pg_db_role_setting per cluster, not + one per database. + + + + <structname>pg_db_role_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> *************** *** 6466,6478 ****
- rolconfig - text[] - - Session defaults for run-time configuration variables - - - oid oid pg_authid.oid --- 6523,6528 ---- Index: src/backend/catalog/Makefile =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/catalog/Makefile,v retrieving revision 1.71 diff -c -p -r1.71 Makefile *** src/backend/catalog/Makefile 26 Aug 2009 22:24:43 -0000 1.71 --- src/backend/catalog/Makefile 25 Sep 2009 19:20:23 -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_db_role_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_db_role_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/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 25 Sep 2009 19:54:45 -0000 *************** *** 31,36 **** --- 31,37 ---- #include "catalog/pg_database.h" #include "catalog/pg_namespace.h" #include "catalog/pg_pltemplate.h" + #include "catalog/pg_db_role_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 == DbRoleSettingRelationId) 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 == DbRoleSettingDatidRolidIndexId) 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 == PgDbRoleSettingToastTable || ! relationId == PgDbRoleSettingToastIndex) return true; return false; } Index: src/backend/catalog/system_views.sql =================================================================== RCS file: /home/alvherre/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 25 Sep 2009 23:13:18 -0000 *************** CREATE VIEW pg_roles AS *** 18,38 **** rolconnlimit, '********'::text as rolpassword, rolvaliduntil, ! rolconfig, ! oid ! FROM pg_authid; CREATE VIEW pg_shadow AS SELECT rolname AS usename, ! oid AS usesysid, rolcreatedb AS usecreatedb, rolsuper AS usesuper, rolcatupdate AS usecatupd, rolpassword AS passwd, rolvaliduntil::abstime AS valuntil, ! rolconfig AS useconfig ! FROM pg_authid WHERE rolcanlogin; REVOKE ALL on pg_shadow FROM public; --- 18,40 ---- rolconnlimit, '********'::text as rolpassword, rolvaliduntil, ! setconfig as rolconfig, ! pg_authid.oid ! FROM pg_authid LEFT JOIN pg_db_role_setting s ! ON (pg_authid.oid = setrole AND setdatabase = 0); CREATE VIEW pg_shadow AS SELECT rolname AS usename, ! pg_authid.oid AS usesysid, rolcreatedb AS usecreatedb, rolsuper AS usesuper, rolcatupdate AS usecatupd, rolpassword AS passwd, rolvaliduntil::abstime AS valuntil, ! setconfig AS useconfig ! FROM pg_authid LEFT JOIN pg_db_role_setting s ! ON (pg_authid.oid = setrole AND setdatabase = 0) WHERE rolcanlogin; REVOKE ALL on pg_shadow FROM public; *************** CREATE RULE pg_settings_n AS *** 171,176 **** --- 173,187 ---- GRANT SELECT, UPDATE ON pg_settings TO PUBLIC; + CREATE VIEW pg_db_role_settings AS + SELECT + datname AS database, + rolname AS role, + setconfig AS settings + FROM pg_db_role_setting AS s + LEFT JOIN pg_database ON pg_database.oid = setdatabase + LEFT JOIN pg_roles ON pg_roles.oid = setrole; + CREATE VIEW pg_timezone_abbrevs AS SELECT * FROM pg_timezone_abbrevs(); Index: src/backend/commands/dbcommands.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/dbcommands.c,v retrieving revision 1.226 diff -c -p -r1.226 dbcommands.c *** src/backend/commands/dbcommands.c 1 Sep 2009 02:54:51 -0000 1.226 --- src/backend/commands/dbcommands.c 25 Sep 2009 19:21:19 -0000 *************** *** 33,38 **** --- 33,39 ---- #include "catalog/indexing.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" + #include "catalog/pg_db_role_setting.h" #include "catalog/pg_tablespace.h" #include "commands/comment.h" #include "commands/dbcommands.h" *************** *** 50,56 **** #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" --- 51,56 ---- *************** createdb(const CreatedbStmt *stmt) *** 544,555 **** 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), --- 544,553 ---- 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_ *** 821,826 **** --- 819,829 ---- 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 *** 1397,1481 **** 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); } --- 1400,1421 ---- 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); } Index: src/backend/commands/user.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/commands/user.c,v retrieving revision 1.188 diff -c -p -r1.188 user.c *** src/backend/commands/user.c 1 Sep 2009 02:54:51 -0000 1.188 --- src/backend/commands/user.c 25 Sep 2009 19:22:11 -0000 *************** *** 19,25 **** --- 19,27 ---- #include "catalog/indexing.h" #include "catalog/pg_auth_members.h" #include "catalog/pg_authid.h" + #include "catalog/pg_db_role_setting.h" #include "commands/comment.h" + #include "commands/dbcommands.h" #include "commands/user.h" #include "libpq/md5.h" #include "miscadmin.h" *************** *** 27,33 **** #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" --- 29,34 ---- *************** CreateRole(CreateRoleStmt *stmt) *** 341,348 **** 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) *** 715,744 **** 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, --- 714,738 ---- void AlterRoleSet(AlterRoleSetStmt *stmt) { ! HeapTuple roletuple; ! Oid databaseid = InvalidOid; ! 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) *** 748,801 **** 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); ! heap_close(rel, RowExclusiveLock); } --- 742,765 ---- else { if (!have_createrole_privilege() && ! HeapTupleGetOid(roletuple) != GetUserId()) ereport(ERROR, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("permission denied"))); } ! /* look up the database, if specified */ ! if (stmt->database != NULL) { ! databaseid = get_database_oid(stmt->database); ! if (!OidIsValid(databaseid)) ! ereport(ERROR, ! (errcode(ERRCODE_UNDEFINED_OBJECT), ! errmsg("database \"%s\" not found", stmt->database))); } ! AlterSetting(databaseid, HeapTupleGetOid(roletuple), stmt->setstmt); ! ReleaseSysCache(roletuple); } *************** DropRole(DropRoleStmt *stmt) *** 944,949 **** --- 908,918 ---- 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/nodes/copyfuncs.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/nodes/copyfuncs.c,v retrieving revision 1.438 diff -c -p -r1.438 copyfuncs.c *** src/backend/nodes/copyfuncs.c 22 Sep 2009 23:43:37 -0000 1.438 --- src/backend/nodes/copyfuncs.c 25 Sep 2009 04:02:21 -0000 *************** _copyAlterRoleSetStmt(AlterRoleSetStmt * *** 3163,3168 **** --- 3163,3169 ---- AlterRoleSetStmt *newnode = makeNode(AlterRoleSetStmt); COPY_STRING_FIELD(role); + COPY_STRING_FIELD(database); COPY_NODE_FIELD(setstmt); return newnode; Index: src/backend/nodes/equalfuncs.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/nodes/equalfuncs.c,v retrieving revision 1.361 diff -c -p -r1.361 equalfuncs.c *** src/backend/nodes/equalfuncs.c 22 Sep 2009 23:43:38 -0000 1.361 --- src/backend/nodes/equalfuncs.c 25 Sep 2009 04:02:21 -0000 *************** static bool *** 1716,1721 **** --- 1716,1722 ---- _equalAlterRoleSetStmt(AlterRoleSetStmt *a, AlterRoleSetStmt *b) { COMPARE_STRING_FIELD(role); + COMPARE_STRING_FIELD(database); COMPARE_NODE_FIELD(setstmt); return true; Index: src/backend/parser/gram.y =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/parser/gram.y,v retrieving revision 2.679 diff -c -p -r2.679 gram.y *** src/backend/parser/gram.y 22 Sep 2009 23:43:38 -0000 2.679 --- src/backend/parser/gram.y 25 Sep 2009 14:09:49 -0000 *************** static TypeName *TableFuncTypeName(List *** 235,242 **** opt_grant_grant_option opt_grant_admin_option opt_nowait opt_if_exists opt_with_data ! %type OptRoleList ! %type OptRoleElem %type opt_type %type foreign_server_version opt_foreign_server_version --- 235,242 ---- opt_grant_grant_option opt_grant_admin_option opt_nowait opt_if_exists opt_with_data ! %type OptRoleList AlterOptRoleList ! %type CreateOptRoleElem AlterOptRoleElem %type opt_type %type foreign_server_version opt_foreign_server_version *************** opt_with: WITH {} *** 756,766 **** * is "WITH ADMIN name". */ OptRoleList: ! OptRoleList OptRoleElem { $$ = lappend($1, $2); } | /* EMPTY */ { $$ = NIL; } ; ! OptRoleElem: PASSWORD Sconst { $$ = makeDefElem("password", --- 756,771 ---- * is "WITH ADMIN name". */ OptRoleList: ! OptRoleList CreateOptRoleElem { $$ = lappend($1, $2); } | /* EMPTY */ { $$ = NIL; } ; ! AlterOptRoleList: ! AlterOptRoleList AlterOptRoleElem { $$ = lappend($1, $2); } ! | /* EMPTY */ { $$ = NIL; } ! ; ! ! AlterOptRoleElem: PASSWORD Sconst { $$ = makeDefElem("password", *************** OptRoleElem: *** 842,848 **** { $$ = makeDefElem("rolemembers", (Node *)$2); } ! /* The following are not supported by ALTER ROLE/USER/GROUP */ | SYSID Iconst { $$ = makeDefElem("sysid", (Node *)makeInteger($2)); --- 847,857 ---- { $$ = makeDefElem("rolemembers", (Node *)$2); } ! ; ! ! CreateOptRoleElem: ! AlterOptRoleElem { $$ = $1; } ! /* The following are not supported by ALTER ROLE/USER/GROUP */ | SYSID Iconst { $$ = makeDefElem("sysid", (Node *)makeInteger($2)); *************** CreateUserStmt: *** 891,897 **** *****************************************************************************/ AlterRoleStmt: ! ALTER ROLE RoleId opt_with OptRoleList { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; --- 900,906 ---- *****************************************************************************/ AlterRoleStmt: ! ALTER ROLE RoleId opt_with AlterOptRoleList { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; *************** AlterRoleStmt: *** 902,911 **** ; AlterRoleSetStmt: ! ALTER ROLE RoleId SetResetClause { AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); n->role = $3; n->setstmt = $4; $$ = (Node *)n; } --- 911,929 ---- ; AlterRoleSetStmt: ! ALTER ROLE RoleId IN_P DATABASE database_name SetResetClause ! { ! AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); ! n->role = $3; ! n->database = $6; ! n->setstmt = $7; ! $$ = (Node *)n; ! } ! | ALTER ROLE RoleId SetResetClause { AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); n->role = $3; + n->database = NULL; n->setstmt = $4; $$ = (Node *)n; } *************** AlterRoleSetStmt: *** 919,925 **** *****************************************************************************/ AlterUserStmt: ! ALTER USER RoleId opt_with OptRoleList { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; --- 937,943 ---- *****************************************************************************/ AlterUserStmt: ! ALTER USER RoleId opt_with AlterOptRoleList { AlterRoleStmt *n = makeNode(AlterRoleStmt); n->role = $3; *************** AlterUserSetStmt: *** 935,940 **** --- 953,959 ---- { AlterRoleSetStmt *n = makeNode(AlterRoleSetStmt); n->role = $3; + n->database = NULL; n->setstmt = $4; $$ = (Node *)n; } Index: src/backend/utils/init/miscinit.c =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/backend/utils/init/miscinit.c,v retrieving revision 1.177 diff -c -p -r1.177 miscinit.c *** src/backend/utils/init/miscinit.c 27 Aug 2009 16:59:38 -0000 1.177 --- src/backend/utils/init/miscinit.c 25 Sep 2009 04:02:21 -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/cvs/pgsql/src/backend/utils/init/postinit.c,v retrieving revision 1.197 diff -c -p -r1.197 postinit.c *** src/backend/utils/init/postinit.c 1 Sep 2009 00:09:42 -0000 1.197 --- src/backend/utils/init/postinit.c 25 Sep 2009 23:49:11 -0000 *************** *** 27,32 **** --- 27,33 ---- #include "catalog/namespace.h" #include "catalog/pg_authid.h" #include "catalog/pg_database.h" + #include "catalog/pg_db_role_setting.h" #include "catalog/pg_tablespace.h" #include "libpq/auth.h" #include "libpq/libpq-be.h" *************** static void CheckMyDatabase(const char * *** 63,68 **** --- 64,70 ---- 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 *** 344,372 **** 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); } --- 346,351 ---- *************** InitPostgres(const char *in_dbname, Oid *** 739,744 **** --- 718,726 ---- /* set up ACL framework (so CheckMyDatabase can check permissions) */ initialize_acl(); + /* Process pg_db_role_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 *************** InitPostgres(const char *in_dbname, Oid *** 851,856 **** --- 833,860 ---- CommitTransactionCommand(); } + /* + * Load GUC settings from pg_db_role_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 relsetting; + + if (!IsUnderPostmaster) + return; + + relsetting = heap_open(DbRoleSettingRelationId, AccessShareLock); + + ApplySetting(databaseid, roleid, relsetting, PGC_S_DATABASE_USER); + ApplySetting(InvalidOid, roleid, relsetting, PGC_S_USER); + ApplySetting(databaseid, InvalidOid, relsetting, PGC_S_DATABASE); + + heap_close(relsetting, AccessShareLock); + } /* * Backend-shutdown callback. Do cleanup that we want to be sure happens Index: src/include/catalog/indexing.h =================================================================== RCS file: /home/alvherre/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 25 Sep 2009 19:54:01 -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_db_role_setting_databaseid_rol_index, 2965, on pg_db_role_setting using btree(setdatabase oid_ops, setrole oid_ops)); + #define DbRoleSettingDatidRolidIndexId 2965 + /* last step of initialization script: build the indexes declared above */ BUILD_INDICES Index: src/include/catalog/pg_attribute.h =================================================================== RCS file: /home/alvherre/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 25 Sep 2009 04:02:21 -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/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 25 Sep 2009 23:54:26 -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/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 25 Sep 2009 23:54:32 -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/toasting.h =================================================================== RCS file: /home/alvherre/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 25 Sep 2009 19:56:03 -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_db_role_setting, 2966, 2967); + #define PgDbRoleSettingToastTable 2966 + #define PgDbRoleSettingToastIndex 2967 #endif /* TOASTING_H */ Index: src/include/nodes/parsenodes.h =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/include/nodes/parsenodes.h,v retrieving revision 1.402 diff -c -p -r1.402 parsenodes.h *** src/include/nodes/parsenodes.h 22 Sep 2009 23:43:41 -0000 1.402 --- src/include/nodes/parsenodes.h 25 Sep 2009 04:02:21 -0000 *************** typedef struct AlterRoleSetStmt *** 1619,1624 **** --- 1619,1625 ---- { NodeTag type; char *role; /* role name */ + char *database; /* database name, or NULL */ VariableSetStmt *setstmt; /* SET or RESET subcommand */ } AlterRoleSetStmt; Index: src/include/utils/guc.h =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/include/utils/guc.h,v retrieving revision 1.105 diff -c -p -r1.105 guc.h *** src/include/utils/guc.h 22 Sep 2009 23:43:41 -0000 1.105 --- src/include/utils/guc.h 25 Sep 2009 04:02:21 -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 */ Index: src/test/regress/expected/rules.out =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/rules.out,v retrieving revision 1.150 diff -c -p -r1.150 rules.out *** src/test/regress/expected/rules.out 22 Sep 2009 15:46:34 -0000 1.150 --- src/test/regress/expected/rules.out 25 Sep 2009 23:51:31 -0000 *************** SELECT viewname, definition FROM pg_view *** 1280,1294 **** --------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath); pg_cursors | SELECT c.name, c.statement, c.is_holdable, c.is_binary, c.is_scrollable, c.creation_time FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time); pg_group | SELECT pg_authid.rolname AS groname, pg_authid.oid AS grosysid, ARRAY(SELECT pg_auth_members.member FROM pg_auth_members WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin); pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS tablespace, pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")); 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_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_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; --- 1280,1295 ---- --------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath); pg_cursors | SELECT c.name, c.statement, c.is_holdable, c.is_binary, c.is_scrollable, c.creation_time FROM pg_cursor() c(name, statement, is_holdable, is_binary, is_scrollable, creation_time); + pg_db_role_settings | SELECT pg_database.datname AS database, pg_roles.rolname AS role, s.setconfig AS settings FROM ((pg_db_role_setting s LEFT JOIN pg_database ON ((pg_database.oid = s.setdatabase))) LEFT JOIN pg_roles ON ((pg_roles.oid = s.setrole))); pg_group | SELECT pg_authid.rolname AS groname, pg_authid.oid AS grosysid, ARRAY(SELECT pg_auth_members.member FROM pg_auth_members WHERE (pg_auth_members.roleid = pg_authid.oid)) AS grolist FROM pg_authid WHERE (NOT pg_authid.rolcanlogin); pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS tablespace, pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")); 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, s.setconfig AS rolconfig, pg_authid.oid FROM (pg_authid LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid)))); 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, s.setconfig AS useconfig FROM (pg_authid LEFT JOIN pg_db_role_setting s ON (((pg_authid.oid = s.setrole) AND (s.setdatabase = (0)::oid)))) 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; *************** SELECT viewname, definition FROM pg_view *** 1329,1335 **** shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color)))); street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath); toyemp | SELECT emp.name, emp.age, emp.location, (12 * emp.salary) AS annualsal FROM emp; ! (51 rows) SELECT tablename, rulename, definition FROM pg_rules ORDER BY tablename, rulename; --- 1330,1336 ---- shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color)))); street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath); toyemp | SELECT emp.name, emp.age, emp.location, (12 * emp.salary) AS annualsal FROM emp; ! (52 rows) SELECT tablename, rulename, definition FROM pg_rules ORDER BY tablename, rulename; Index: src/test/regress/expected/sanity_check.out =================================================================== RCS file: /home/alvherre/cvs/pgsql/src/test/regress/expected/sanity_check.out,v retrieving revision 1.40 diff -c -p -r1.40 sanity_check.out *** src/test/regress/expected/sanity_check.out 29 Jul 2009 20:56:21 -0000 1.40 --- src/test/regress/expected/sanity_check.out 25 Sep 2009 23:51:26 -0000 *************** SELECT relname, relhasindex *** 95,100 **** --- 95,101 ---- pg_constraint | t pg_conversion | t pg_database | t + pg_db_role_setting | t pg_depend | t pg_description | t pg_enum | t *************** SELECT relname, relhasindex *** 151,157 **** timetz_tbl | f tinterval_tbl | f varchar_tbl | f ! (140 rows) -- -- another sanity check: every system catalog that has OIDs should have --- 152,158 ---- timetz_tbl | f tinterval_tbl | f varchar_tbl | f ! (141 rows) -- -- another sanity check: every system catalog that has OIDs should have