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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy