Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit cb98e6f

Browse files
committed
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.
1 parent 5320c6c commit cb98e6f

File tree

8 files changed

+116
-205
lines changed

8 files changed

+116
-205
lines changed

src/backend/catalog/aclchk.c

Lines changed: 37 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.127 2006/04/30 21:15:33 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.128 2006/05/03 22:45:26 tgl Exp $
1212
*
1313
* NOTES
1414
* See acl.h.
@@ -34,6 +34,7 @@
3434
#include "catalog/pg_proc.h"
3535
#include "catalog/pg_tablespace.h"
3636
#include "catalog/pg_type.h"
37+
#include "commands/dbcommands.h"
3738
#include "miscadmin.h"
3839
#include "parser/parse_func.h"
3940
#include "utils/acl.h"
@@ -412,8 +413,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
412413
case ACL_OBJECT_SEQUENCE:
413414
foreach(cell, objnames)
414415
{
415-
Oid relOid;
416416
RangeVar *relvar = (RangeVar *) lfirst(cell);
417+
Oid relOid;
417418

418419
relOid = RangeVarGetRelid(relvar, false);
419420
objects = lappend_oid(objects, relOid);
@@ -423,32 +424,15 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
423424
foreach(cell, objnames)
424425
{
425426
char *dbname = strVal(lfirst(cell));
426-
ScanKeyData entry[1];
427-
HeapScanDesc scan;
428-
HeapTuple tuple;
429-
Relation relation;
430-
431-
relation = heap_open(DatabaseRelationId, AccessShareLock);
427+
Oid dbid;
432428

433-
/*
434-
* There's no syscache for pg_database, so we must look the
435-
* hard way.
436-
*/
437-
ScanKeyInit(&entry[0],
438-
Anum_pg_database_datname,
439-
BTEqualStrategyNumber, F_NAMEEQ,
440-
CStringGetDatum(dbname));
441-
scan = heap_beginscan(relation, SnapshotNow, 1, entry);
442-
tuple = heap_getnext(scan, ForwardScanDirection);
443-
if (!HeapTupleIsValid(tuple))
429+
dbid = get_database_oid(dbname);
430+
if (!OidIsValid(dbid))
444431
ereport(ERROR,
445432
(errcode(ERRCODE_UNDEFINED_DATABASE),
446-
errmsg("database \"%s\" does not exist", dbname)));
447-
objects = lappend_oid(objects, HeapTupleGetOid(tuple));
448-
449-
heap_close(relation, AccessShareLock);
450-
451-
heap_endscan(scan);
433+
errmsg("database \"%s\" does not exist",
434+
dbname)));
435+
objects = lappend_oid(objects, dbid);
452436
}
453437
break;
454438
case ACL_OBJECT_FUNCTION:
@@ -474,7 +458,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
474458
if (!HeapTupleIsValid(tuple))
475459
ereport(ERROR,
476460
(errcode(ERRCODE_UNDEFINED_OBJECT),
477-
errmsg("language \"%s\" does not exist", langname)));
461+
errmsg("language \"%s\" does not exist",
462+
langname)));
478463

479464
objects = lappend_oid(objects, HeapTupleGetOid(tuple));
480465

@@ -493,7 +478,8 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
493478
if (!HeapTupleIsValid(tuple))
494479
ereport(ERROR,
495480
(errcode(ERRCODE_UNDEFINED_SCHEMA),
496-
errmsg("schema \"%s\" does not exist", nspname)));
481+
errmsg("schema \"%s\" does not exist",
482+
nspname)));
497483

498484
objects = lappend_oid(objects, HeapTupleGetOid(tuple));
499485

@@ -764,22 +750,13 @@ ExecGrant_Database(InternalGrant *istmt)
764750
int nnewmembers;
765751
Oid *oldmembers;
766752
Oid *newmembers;
767-
ScanKeyData entry[1];
768-
SysScanDesc scan;
769753
HeapTuple tuple;
770754

771-
/* There's no syscache for pg_database, so must look the hard way */
772-
ScanKeyInit(&entry[0],
773-
ObjectIdAttributeNumber,
774-
BTEqualStrategyNumber, F_OIDEQ,
775-
ObjectIdGetDatum(datId));
776-
scan = systable_beginscan(relation, DatabaseOidIndexId, true,
777-
SnapshotNow, 1, entry);
778-
779-
tuple = systable_getnext(scan);
780-
755+
tuple = SearchSysCache(DATABASEOID,
756+
ObjectIdGetDatum(datId),
757+
0, 0, 0);
781758
if (!HeapTupleIsValid(tuple))
782-
elog(ERROR, "could not find tuple for database %u", datId);
759+
elog(ERROR, "cache lookup failed for database %u", datId);
783760

784761
pg_database_tuple = (Form_pg_database) GETSTRUCT(tuple);
785762

@@ -847,7 +824,7 @@ ExecGrant_Database(InternalGrant *istmt)
847824
noldmembers, oldmembers,
848825
nnewmembers, newmembers);
849826

850-
systable_endscan(scan);
827+
ReleaseSysCache(tuple);
851828

852829
pfree(new_acl);
853830

@@ -1657,61 +1634,31 @@ pg_database_aclmask(Oid db_oid, Oid roleid,
16571634
AclMode mask, AclMaskHow how)
16581635
{
16591636
AclMode result;
1660-
Relation pg_database;
1661-
ScanKeyData entry[1];
1662-
SysScanDesc scan;
16631637
HeapTuple tuple;
1638+
Datum aclDatum;
1639+
bool isNull;
1640+
Acl *acl;
1641+
Oid ownerId;
16641642

16651643
/* Superusers bypass all permission checking. */
16661644
if (superuser_arg(roleid))
16671645
return mask;
16681646

16691647
/*
16701648
* Get the database's ACL from pg_database
1671-
*
1672-
* There's no syscache for pg_database, so must look the hard way
16731649
*/
1674-
pg_database = heap_open(DatabaseRelationId, AccessShareLock);
1675-
ScanKeyInit(&entry[0],
1676-
ObjectIdAttributeNumber,
1677-
BTEqualStrategyNumber, F_OIDEQ,
1678-
ObjectIdGetDatum(db_oid));
1679-
scan = systable_beginscan(pg_database, DatabaseOidIndexId, true,
1680-
SnapshotNow, 1, entry);
1681-
tuple = systable_getnext(scan);
1650+
tuple = SearchSysCache(DATABASEOID,
1651+
ObjectIdGetDatum(db_oid),
1652+
0, 0, 0);
16821653
if (!HeapTupleIsValid(tuple))
16831654
ereport(ERROR,
16841655
(errcode(ERRCODE_UNDEFINED_DATABASE),
16851656
errmsg("database with OID %u does not exist", db_oid)));
16861657

1687-
result = pg_database_tuple_aclmask(tuple, RelationGetDescr(pg_database),
1688-
roleid, mask, how);
1689-
1690-
systable_endscan(scan);
1691-
heap_close(pg_database, AccessShareLock);
1692-
1693-
return result;
1694-
}
1695-
1696-
/*
1697-
* This is split out so that ReverifyMyDatabase can perform an ACL check
1698-
* without a whole extra search of pg_database
1699-
*/
1700-
AclMode
1701-
pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
1702-
Oid roleid, AclMode mask, AclMaskHow how)
1703-
{
1704-
AclMode result;
1705-
Datum aclDatum;
1706-
bool isNull;
1707-
Acl *acl;
1708-
Oid ownerId;
1709-
1710-
ownerId = ((Form_pg_database) GETSTRUCT(db_tuple))->datdba;
1711-
1712-
aclDatum = heap_getattr(db_tuple, Anum_pg_database_datacl,
1713-
tupdesc, &isNull);
1658+
ownerId = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
17141659

1660+
aclDatum = SysCacheGetAttr(DATABASEOID, tuple, Anum_pg_database_datacl,
1661+
&isNull);
17151662
if (isNull)
17161663
{
17171664
/* No ACL, so build default ACL */
@@ -1730,6 +1677,8 @@ pg_database_tuple_aclmask(HeapTuple db_tuple, TupleDesc tupdesc,
17301677
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
17311678
pfree(acl);
17321679

1680+
ReleaseSysCache(tuple);
1681+
17331682
return result;
17341683
}
17351684

@@ -2298,36 +2247,24 @@ pg_opclass_ownercheck(Oid opc_oid, Oid roleid)
22982247
bool
22992248
pg_database_ownercheck(Oid db_oid, Oid roleid)
23002249
{
2301-
Relation pg_database;
2302-
ScanKeyData entry[1];
2303-
SysScanDesc scan;
2304-
HeapTuple dbtuple;
2250+
HeapTuple tuple;
23052251
Oid dba;
23062252

23072253
/* Superusers bypass all permission checking. */
23082254
if (superuser_arg(roleid))
23092255
return true;
23102256

2311-
/* There's no syscache for pg_database, so must look the hard way */
2312-
pg_database = heap_open(DatabaseRelationId, AccessShareLock);
2313-
ScanKeyInit(&entry[0],
2314-
ObjectIdAttributeNumber,
2315-
BTEqualStrategyNumber, F_OIDEQ,
2316-
ObjectIdGetDatum(db_oid));
2317-
scan = systable_beginscan(pg_database, DatabaseOidIndexId, true,
2318-
SnapshotNow, 1, entry);
2319-
2320-
dbtuple = systable_getnext(scan);
2321-
2322-
if (!HeapTupleIsValid(dbtuple))
2257+
tuple = SearchSysCache(DATABASEOID,
2258+
ObjectIdGetDatum(db_oid),
2259+
0, 0, 0);
2260+
if (!HeapTupleIsValid(tuple))
23232261
ereport(ERROR,
23242262
(errcode(ERRCODE_UNDEFINED_DATABASE),
23252263
errmsg("database with OID %u does not exist", db_oid)));
23262264

2327-
dba = ((Form_pg_database) GETSTRUCT(dbtuple))->datdba;
2265+
dba = ((Form_pg_database) GETSTRUCT(tuple))->datdba;
23282266

2329-
systable_endscan(scan);
2330-
heap_close(pg_database, AccessShareLock);
2267+
ReleaseSysCache(tuple);
23312268

23322269
return has_privs_of_role(roleid, dba);
23332270
}

src/backend/commands/dbcommands.c

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.179 2006/03/29 21:17:38 tgl Exp $
18+
* $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.180 2006/05/03 22:45:26 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -556,8 +556,6 @@ dropdb(const char *dbname, bool missing_ok)
556556
Oid db_id;
557557
bool db_istemplate;
558558
Relation pgdbrel;
559-
SysScanDesc pgdbscan;
560-
ScanKeyData key;
561559
HeapTuple tup;
562560

563561
PreventTransactionChain((void *) dbname, "DROP DATABASE");
@@ -629,31 +627,17 @@ dropdb(const char *dbname, bool missing_ok)
629627
dbname)));
630628

631629
/*
632-
* Find the database's tuple by OID (should be unique).
630+
* Remove the database's tuple from pg_database.
633631
*/
634-
ScanKeyInit(&key,
635-
ObjectIdAttributeNumber,
636-
BTEqualStrategyNumber, F_OIDEQ,
637-
ObjectIdGetDatum(db_id));
638-
639-
pgdbscan = systable_beginscan(pgdbrel, DatabaseOidIndexId, true,
640-
SnapshotNow, 1, &key);
641-
642-
tup = systable_getnext(pgdbscan);
632+
tup = SearchSysCache(DATABASEOID,
633+
ObjectIdGetDatum(db_id),
634+
0, 0, 0);
643635
if (!HeapTupleIsValid(tup))
644-
{
645-
/*
646-
* This error should never come up since the existence of the database
647-
* is checked earlier
648-
*/
649-
elog(ERROR, "database \"%s\" doesn't exist despite earlier reports to the contrary",
650-
dbname);
651-
}
636+
elog(ERROR, "cache lookup failed for database %u", db_id);
652637

653-
/* Remove the database's tuple from pg_database */
654638
simple_heap_delete(pgdbrel, &tup->t_self);
655639

656-
systable_endscan(pgdbscan);
640+
ReleaseSysCache(tup);
657641

658642
/*
659643
* Delete any comments associated with the database
@@ -1262,7 +1246,10 @@ get_database_oid(const char *dbname)
12621246
HeapTuple dbtuple;
12631247
Oid oid;
12641248

1265-
/* There's no syscache for pg_database, so must look the hard way */
1249+
/*
1250+
* There's no syscache for pg_database indexed by name,
1251+
* so we must look the hard way.
1252+
*/
12661253
pg_database = heap_open(DatabaseRelationId, AccessShareLock);
12671254
ScanKeyInit(&entry[0],
12681255
Anum_pg_database_datname,
@@ -1296,32 +1283,20 @@ get_database_oid(const char *dbname)
12961283
char *
12971284
get_database_name(Oid dbid)
12981285
{
1299-
Relation pg_database;
1300-
ScanKeyData entry[1];
1301-
SysScanDesc scan;
13021286
HeapTuple dbtuple;
13031287
char *result;
13041288

1305-
/* There's no syscache for pg_database, so must look the hard way */
1306-
pg_database = heap_open(DatabaseRelationId, AccessShareLock);
1307-
ScanKeyInit(&entry[0],
1308-
ObjectIdAttributeNumber,
1309-
BTEqualStrategyNumber, F_OIDEQ,
1310-
ObjectIdGetDatum(dbid));
1311-
scan = systable_beginscan(pg_database, DatabaseOidIndexId, true,
1312-
SnapshotNow, 1, entry);
1313-
1314-
dbtuple = systable_getnext(scan);
1315-
1316-
/* We assume that there can be at most one matching tuple */
1289+
dbtuple = SearchSysCache(DATABASEOID,
1290+
ObjectIdGetDatum(dbid),
1291+
0, 0, 0);
13171292
if (HeapTupleIsValid(dbtuple))
1293+
{
13181294
result = pstrdup(NameStr(((Form_pg_database) GETSTRUCT(dbtuple))->datname));
1295+
ReleaseSysCache(dbtuple);
1296+
}
13191297
else
13201298
result = NULL;
13211299

1322-
systable_endscan(scan);
1323-
heap_close(pg_database, AccessShareLock);
1324-
13251300
return result;
13261301
}
13271302

0 commit comments

Comments
 (0)