From cb98e6fb8fd4f1ca955a85d5c0088e42e77a04f0 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 3 May 2006 22:45:26 +0000 Subject: [PATCH] Create a syscache for pg_database-indexed-by-oid, and make use of it in various places that were previously doing ad hoc pg_database searches. This may speed up database-related privilege checks a little bit, but the main motivation is to eliminate the performance reason for having ReverifyMyDatabase do such a lot of stuff (viz, avoiding repeat scans of pg_database during backend startup). The locking reason for having that routine is about to go away, and it'd be good to have the option to break it up. --- src/backend/catalog/aclchk.c | 137 ++++++++++-------------------------- src/backend/commands/dbcommands.c | 59 +++++----------- src/backend/commands/vacuum.c | 25 ++++--- src/backend/postmaster/autovacuum.c | 29 +++----- src/backend/utils/cache/syscache.c | 13 +++- src/backend/utils/init/postinit.c | 17 ++--- src/include/utils/acl.h | 6 +- src/include/utils/syscache.h | 35 ++++----- 8 files changed, 116 insertions(+), 205 deletions(-) diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c index a74c28e5b3..19c34bc49c 100644 --- a/src/backend/catalog/aclchk.c +++ b/src/backend/catalog/aclchk.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.127 2006/04/30 21:15:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.128 2006/05/03 22:45:26 tgl Exp $ * * NOTES * See acl.h. @@ -34,6 +34,7 @@ #include "catalog/pg_proc.h" #include "catalog/pg_tablespace.h" #include "catalog/pg_type.h" +#include "commands/dbcommands.h" #include "miscadmin.h" #include "parser/parse_func.h" #include "utils/acl.h" @@ -412,8 +413,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames) case ACL_OBJECT_SEQUENCE: foreach(cell, objnames) { - Oid relOid; RangeVar *relvar = (RangeVar *) lfirst(cell); + Oid relOid; relOid = RangeVarGetRelid(relvar, false); objects = lappend_oid(objects, relOid); @@ -423,32 +424,15 @@ objectNamesToOids(GrantObjectType objtype, List *objnames) foreach(cell, objnames) { char *dbname = strVal(lfirst(cell)); - ScanKeyData entry[1]; - HeapScanDesc scan; - HeapTuple tuple; - Relation relation; - - relation = heap_open(DatabaseRelationId, AccessShareLock); + Oid dbid; - /* - * There's no syscache for pg_database, so we must look the - * hard way. - */ - ScanKeyInit(&entry[0], - Anum_pg_database_datname, - BTEqualStrategyNumber, F_NAMEEQ, - CStringGetDatum(dbname)); - scan = heap_beginscan(relation, SnapshotNow, 1, entry); - tuple = heap_getnext(scan, ForwardScanDirection); - if (!HeapTupleIsValid(tuple)) + dbid = get_database_oid(dbname); + if (!OidIsValid(dbid)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), - errmsg("database \"%s\" does not exist", dbname))); - objects = lappend_oid(objects, HeapTupleGetOid(tuple)); - - heap_close(relation, AccessShareLock); - - heap_endscan(scan); + errmsg("database \"%s\" does not exist", + dbname))); + objects = lappend_oid(objects, dbid); } break; case ACL_OBJECT_FUNCTION: @@ -474,7 +458,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames) if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("language \"%s\" does not exist", langname))); + errmsg("language \"%s\" does not exist", + langname))); objects = lappend_oid(objects, HeapTupleGetOid(tuple)); @@ -493,7 +478,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames) if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_SCHEMA), - errmsg("schema \"%s\" does not exist", nspname))); + errmsg("schema \"%s\" does not exist", + nspname))); objects = lappend_oid(objects, HeapTupleGetOid(tuple)); @@ -764,22 +750,13 @@ ExecGrant_Database(InternalGrant *istmt) int nnewmembers; Oid *oldmembers; Oid *newmembers; - ScanKeyData entry[1]; - SysScanDesc scan; HeapTuple tuple; - /* There's no syscache for pg_database, so must look the hard way */ - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(datId)); - scan = systable_beginscan(relation, DatabaseOidIndexId, true, - SnapshotNow, 1, entry); - - tuple = systable_getnext(scan); - + tuple = SearchSysCache(DATABASEOID, + ObjectIdGetDatum(datId), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) - elog(ERROR, "could not find tuple for database %u", datId); + elog(ERROR, "cache lookup failed for database %u", datId); pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple); @@ -847,7 +824,7 @@ ExecGrant_Database(InternalGrant *istmt) noldmembers, oldmembers, nnewmembers, newmembers); - systable_endscan(scan); + ReleaseSysCache(tuple); pfree(new_acl); @@ -1657,10 +1634,11 @@ pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how) { AclMode result; - Relation pg_database; - ScanKeyData entry[1]; - SysScanDesc scan; HeapTuple tuple; + Datum aclDatum; + bool isNull; + Acl *acl; + Oid ownerId; /* Superusers bypass all permission checking. */ if (superuser_arg(roleid)) @@ -1668,50 +1646,19 @@ pg_database_aclmask(Oid db_oid, Oid roleid, /* * Get the database's ACL from pg_database - * - * There's no syscache for pg_database, so must look the hard way */ - pg_database = heap_open(DatabaseRelationId, AccessShareLock); - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(db_oid)); - scan = systable_beginscan(pg_database, DatabaseOidIndexId, true, - SnapshotNow, 1, entry); - tuple = systable_getnext(scan); + tuple = SearchSysCache(DATABASEOID, + ObjectIdGetDatum(db_oid), + 0, 0, 0); if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database with OID %u does not exist", db_oid))); - result = pg_database_tuple_aclmask(tuple, RelationGetDescr(pg_database), - roleid, mask, how); - - systable_endscan(scan); - heap_close(pg_database, AccessShareLock); - - return result; -} - -/* - * This is split out so that ReverifyMyDatabase can perform an ACL check - * without a whole extra search of pg_database - */ -AclMode -pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc, - Oid roleid, AclMode mask, AclMaskHow how) -{ - AclMode result; - Datum aclDatum; - bool isNull; - Acl *acl; - Oid ownerId; - - ownerId = ((Form_pg_database) GETSTRUCT(db_tuple))->datdba; - - aclDatum = heap_getattr(db_tuple, Anum_pg_database_datacl, - tupdesc, &isNull); + ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba; + aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl, + &isNull); if (isNull) { /* No ACL, so build default ACL */ @@ -1730,6 +1677,8 @@ pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc, if (acl && (Pointer) acl != DatumGetPointer(aclDatum)) pfree(acl); + ReleaseSysCache(tuple); + return result; } @@ -2298,36 +2247,24 @@ pg_opclass_ownercheck(Oid opc_oid, Oid roleid) bool pg_database_ownercheck(Oid db_oid, Oid roleid) { - Relation pg_database; - ScanKeyData entry[1]; - SysScanDesc scan; - HeapTuple dbtuple; + HeapTuple tuple; Oid dba; /* Superusers bypass all permission checking. */ if (superuser_arg(roleid)) return true; - /* There's no syscache for pg_database, so must look the hard way */ - pg_database = heap_open(DatabaseRelationId, AccessShareLock); - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(db_oid)); - scan = systable_beginscan(pg_database, DatabaseOidIndexId, true, - SnapshotNow, 1, entry); - - dbtuple = systable_getnext(scan); - - if (!HeapTupleIsValid(dbtuple)) + tuple = SearchSysCache(DATABASEOID, + ObjectIdGetDatum(db_oid), + 0, 0, 0); + if (!HeapTupleIsValid(tuple)) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_DATABASE), errmsg("database with OID %u does not exist", db_oid))); - dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba; + dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba; - systable_endscan(scan); - heap_close(pg_database, AccessShareLock); + ReleaseSysCache(tuple); return has_privs_of_role(roleid, dba); } diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c index 209362782a..b21d750394 100644 --- a/src/backend/commands/dbcommands.c +++ b/src/backend/commands/dbcommands.c @@ -15,7 +15,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.179 2006/03/29 21:17:38 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.180 2006/05/03 22:45:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -556,8 +556,6 @@ dropdb(const char *dbname, bool missing_ok) Oid db_id; bool db_istemplate; Relation pgdbrel; - SysScanDesc pgdbscan; - ScanKeyData key; HeapTuple tup; PreventTransactionChain((void *) dbname, "DROP DATABASE"); @@ -629,31 +627,17 @@ dropdb(const char *dbname, bool missing_ok) dbname))); /* - * Find the database's tuple by OID (should be unique). + * Remove the database's tuple from pg_database. */ - ScanKeyInit(&key, - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(db_id)); - - pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndexId, true, - SnapshotNow, 1, &key); - - tup = systable_getnext(pgdbscan); + tup = SearchSysCache(DATABASEOID, + ObjectIdGetDatum(db_id), + 0, 0, 0); if (!HeapTupleIsValid(tup)) - { - /* - * This error should never come up since the existence of the database - * is checked earlier - */ - elog(ERROR, "database \"%s\" doesn't exist despite earlier reports to the contrary", - dbname); - } + elog(ERROR, "cache lookup failed for database %u", db_id); - /* Remove the database's tuple from pg_database */ simple_heap_delete(pgdbrel, &tup->t_self); - systable_endscan(pgdbscan); + ReleaseSysCache(tup); /* * Delete any comments associated with the database @@ -1262,7 +1246,10 @@ get_database_oid(const char *dbname) HeapTuple dbtuple; Oid oid; - /* There's no syscache for pg_database, so must look the hard way */ + /* + * There's no syscache for pg_database indexed by name, + * so we must look the hard way. + */ pg_database = heap_open(DatabaseRelationId, AccessShareLock); ScanKeyInit(&entry[0], Anum_pg_database_datname, @@ -1296,32 +1283,20 @@ get_database_oid(const char *dbname) char * get_database_name(Oid dbid) { - Relation pg_database; - ScanKeyData entry[1]; - SysScanDesc scan; HeapTuple dbtuple; char *result; - /* There's no syscache for pg_database, so must look the hard way */ - pg_database = heap_open(DatabaseRelationId, AccessShareLock); - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(dbid)); - scan = systable_beginscan(pg_database, DatabaseOidIndexId, true, - SnapshotNow, 1, entry); - - dbtuple = systable_getnext(scan); - - /* We assume that there can be at most one matching tuple */ + dbtuple = SearchSysCache(DATABASEOID, + ObjectIdGetDatum(dbid), + 0, 0, 0); if (HeapTupleIsValid(dbtuple)) + { result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname)); + ReleaseSysCache(dbtuple); + } else result = NULL; - systable_endscan(scan); - heap_close(pg_database, AccessShareLock); - return result; } diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index a5d704c1d8..7f13bae809 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -13,7 +13,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.328 2006/05/02 22:25:10 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/vacuum.c,v 1.329 2006/05/03 22:45:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "access/subtrans.h" #include "access/xlog.h" #include "catalog/catalog.h" +#include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_database.h" #include "catalog/pg_index.h" @@ -767,27 +768,33 @@ vac_update_dbstats(Oid dbid, { Relation relation; ScanKeyData entry[1]; - HeapScanDesc scan; + SysScanDesc scan; HeapTuple tuple; + Buffer buf; Form_pg_database dbform; relation = heap_open(DatabaseRelationId, RowExclusiveLock); - /* Must use a heap scan, since there's no syscache for pg_database */ ScanKeyInit(&entry[0], ObjectIdAttributeNumber, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(dbid)); - scan = heap_beginscan(relation, SnapshotNow, 1, entry); + scan = systable_beginscan(relation, DatabaseOidIndexId, true, + SnapshotNow, 1, entry); - tuple = heap_getnext(scan, ForwardScanDirection); + tuple = systable_getnext(scan); if (!HeapTupleIsValid(tuple)) elog(ERROR, "could not find tuple for database %u", dbid); + if (scan->irel) + buf = scan->iscan->xs_cbuf; + else + buf = scan->scan->rs_cbuf; + /* ensure no one else does this at the same time */ - LockBuffer(scan->rs_cbuf, BUFFER_LOCK_EXCLUSIVE); + LockBuffer(buf, BUFFER_LOCK_EXCLUSIVE); dbform = (Form_pg_database) GETSTRUCT(tuple); @@ -795,14 +802,14 @@ vac_update_dbstats(Oid dbid, dbform->datvacuumxid = vacuumXID; dbform->datfrozenxid = frozenXID; - MarkBufferDirty(scan->rs_cbuf); + MarkBufferDirty(buf); - LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK); + LockBuffer(buf, BUFFER_LOCK_UNLOCK); /* invalidate the tuple in the cache so we'll see the change in cache */ CacheInvalidateHeapTuple(relation, tuple); - heap_endscan(scan); + systable_endscan(scan); heap_close(relation, RowExclusiveLock); diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c index 4a5a05c1b2..a19e504b0e 100644 --- a/src/backend/postmaster/autovacuum.c +++ b/src/backend/postmaster/autovacuum.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.17 2006/04/27 15:57:10 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.18 2006/05/03 22:45:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,6 +46,7 @@ #include "utils/memutils.h" #include "utils/ps_status.h" #include "utils/relcache.h" +#include "utils/syscache.h" /* @@ -493,9 +494,6 @@ autovac_get_database_list(void) static void process_whole_db(void) { - Relation dbRel; - ScanKeyData entry[1]; - SysScanDesc scan; HeapTuple tup; Form_pg_database dbForm; bool freeze; @@ -511,21 +509,12 @@ process_whole_db(void) */ pgstat_vacuum_tabstat(); - dbRel = heap_open(DatabaseRelationId, AccessShareLock); - - /* Must use a table scan, since there's no syscache for pg_database */ - ScanKeyInit(&entry[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(MyDatabaseId)); - - scan = systable_beginscan(dbRel, DatabaseOidIndexId, true, - SnapshotNow, 1, entry); - - tup = systable_getnext(scan); - + /* Look up the pg_database entry and decide whether to FREEZE */ + tup = SearchSysCache(DATABASEOID, + ObjectIdGetDatum(MyDatabaseId), + 0, 0, 0); if (!HeapTupleIsValid(tup)) - elog(ERROR, "could not find tuple for database %u", MyDatabaseId); + elog(ERROR, "cache lookup failed for database %u", MyDatabaseId); dbForm = (Form_pg_database) GETSTRUCT(tup); @@ -534,9 +523,7 @@ process_whole_db(void) else freeze = false; - systable_endscan(scan); - - heap_close(dbRel, AccessShareLock); + ReleaseSysCache(tup); elog(DEBUG2, "autovacuum: VACUUM%s whole database", (freeze) ? " FREEZE" : ""); diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index 90b9c4cb05..ffcb26e3c5 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.102 2006/03/05 15:58:45 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.103 2006/05/03 22:45:26 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -31,6 +31,7 @@ #include "catalog/pg_auth_members.h" #include "catalog/pg_cast.h" #include "catalog/pg_conversion.h" +#include "catalog/pg_database.h" #include "catalog/pg_index.h" #include "catalog/pg_inherits.h" #include "catalog/pg_language.h" @@ -273,6 +274,16 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, + {DatabaseRelationId, /* DATABASEOID */ + DatabaseOidIndexId, + 0, + 1, + { + ObjectIdAttributeNumber, + 0, + 0, + 0 + }}, {IndexRelationId, /* INDEXRELID */ IndexRelidIndexId, Anum_pg_index_indrelid, diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index e89df5bb3a..4ddc7f712a 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.164 2006/04/30 21:15:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.165 2006/05/03 22:45:26 tgl Exp $ * * *------------------------------------------------------------------------- @@ -195,19 +195,16 @@ ReverifyMyDatabase(const char *name, bool am_superuser) name))); /* - * Check privilege to connect to the database. To avoid making - * a whole extra search of pg_database here, we don't go through - * pg_database_aclcheck, but instead use a lower-level routine - * that we can pass the pg_database tuple to. + * Check privilege to connect to the database. (The am_superuser + * test is redundant, but since we have the flag, might as well + * check it and save a few cycles.) */ if (!am_superuser && - pg_database_tuple_aclmask(tup, RelationGetDescr(pgdbrel), - GetUserId(), - ACL_CONNECT, ACLMASK_ANY) == 0) + pg_database_aclcheck(MyDatabaseId, GetUserId(), + ACL_CONNECT) != ACLCHECK_OK) ereport(FATAL, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied for database %s", - NameStr(dbform->datname)), + errmsg("permission denied for database \"%s\"", name), errdetail("User does not have CONNECT privilege."))); /* diff --git a/src/include/utils/acl.h b/src/include/utils/acl.h index 7651fba290..27aaf0dfbf 100644 --- a/src/include/utils/acl.h +++ b/src/include/utils/acl.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.95 2006/04/30 21:15:33 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.96 2006/05/03 22:45:26 tgl Exp $ * * NOTES * An ACL array is simply an array of AclItems, representing the union @@ -24,8 +24,6 @@ #ifndef ACL_H #define ACL_H -#include "access/htup.h" -#include "access/tupdesc.h" #include "nodes/parsenodes.h" #include "utils/array.h" @@ -252,8 +250,6 @@ extern AclMode pg_class_aclmask(Oid table_oid, Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_database_aclmask(Oid db_oid, Oid roleid, AclMode mask, AclMaskHow how); -extern AclMode pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc, - Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_proc_aclmask(Oid proc_oid, Oid roleid, AclMode mask, AclMaskHow how); extern AclMode pg_language_aclmask(Oid lang_oid, Oid roleid, diff --git a/src/include/utils/syscache.h b/src/include/utils/syscache.h index d3feea1f82..34ef6132b3 100644 --- a/src/include/utils/syscache.h +++ b/src/include/utils/syscache.h @@ -9,7 +9,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.62 2006/03/05 15:59:08 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.63 2006/05/03 22:45:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,22 +46,23 @@ #define CONDEFAULT 15 #define CONNAMENSP 16 #define CONOID 17 -#define INDEXRELID 18 -#define INHRELID 19 -#define LANGNAME 20 -#define LANGOID 21 -#define NAMESPACENAME 22 -#define NAMESPACEOID 23 -#define OPERNAMENSP 24 -#define OPEROID 25 -#define PROCNAMEARGSNSP 26 -#define PROCOID 27 -#define RELNAMENSP 28 -#define RELOID 29 -#define RULERELNAME 30 -#define STATRELATT 31 -#define TYPENAMENSP 32 -#define TYPEOID 33 +#define DATABASEOID 18 +#define INDEXRELID 19 +#define INHRELID 20 +#define LANGNAME 21 +#define LANGOID 22 +#define NAMESPACENAME 23 +#define NAMESPACEOID 24 +#define OPERNAMENSP 25 +#define OPEROID 26 +#define PROCNAMEARGSNSP 27 +#define PROCOID 28 +#define RELNAMENSP 29 +#define RELOID 30 +#define RULERELNAME 31 +#define STATRELATT 32 +#define TYPENAMENSP 33 +#define TYPEOID 34 extern void InitCatalogCache(void); extern void InitCatalogCachePhase2(void); -- 2.11.0