diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c index 8ae368b741..4106417fb3 100644 --- a/src/backend/catalog/pg_inherits.c +++ b/src/backend/catalog/pg_inherits.c @@ -13,13 +13,15 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.3 2009/06/11 14:48:55 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/pg_inherits.c,v 1.4 2009/12/29 22:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" +#include "access/genam.h" #include "access/heapam.h" +#include "catalog/indexing.h" #include "catalog/pg_class.h" #include "catalog/pg_inherits.h" #include "catalog/pg_inherits_fn.h" @@ -29,6 +31,8 @@ #include "utils/syscache.h" #include "utils/tqual.h" +static int oid_cmp(const void *p1, const void *p2); + /* * find_inheritance_children @@ -46,10 +50,14 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) { List *list = NIL; Relation relation; - HeapScanDesc scan; + SysScanDesc scan; ScanKeyData key[1]; HeapTuple inheritsTuple; Oid inhrelid; + Oid *oidarr; + int maxoids, + numoids, + i; /* * Can skip the scan if pg_class shows the relation has never had a @@ -59,21 +67,52 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) return NIL; /* - * XXX might be a good idea to create an index on pg_inherits' inhparent - * field, so that we can use an indexscan instead of sequential scan here. - * However, in typical databases pg_inherits won't have enough entries to - * justify an indexscan... + * Scan pg_inherits and build a working array of subclass OIDs. */ + maxoids = 32; + oidarr = (Oid *) palloc(maxoids * sizeof(Oid)); + numoids = 0; + relation = heap_open(InheritsRelationId, AccessShareLock); + ScanKeyInit(&key[0], Anum_pg_inherits_inhparent, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(parentrelId)); - scan = heap_beginscan(relation, SnapshotNow, 1, key); - while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL) + scan = systable_beginscan(relation, InheritsParentIndexId, true, + SnapshotNow, 1, key); + + while ((inheritsTuple = systable_getnext(scan)) != NULL) { inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid; + if (numoids >= maxoids) + { + maxoids *= 2; + oidarr = (Oid *) repalloc(oidarr, maxoids * sizeof(Oid)); + } + oidarr[numoids++] = inhrelid; + } + + systable_endscan(scan); + + heap_close(relation, AccessShareLock); + + /* + * If we found more than one child, sort them by OID. This ensures + * reasonably consistent behavior regardless of the vagaries of an + * indexscan. This is important since we need to be sure all backends + * lock children in the same order to avoid needless deadlocks. + */ + if (numoids > 1) + qsort(oidarr, numoids, sizeof(Oid), oid_cmp); + + /* + * Acquire locks and build the result list. + */ + for (i = 0; i < numoids; i++) + { + inhrelid = oidarr[i]; if (lockmode != NoLock) { @@ -99,8 +138,7 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode) list = lappend_oid(list, inhrelid); } - heap_endscan(scan); - heap_close(relation, AccessShareLock); + pfree(oidarr); return list; } @@ -231,7 +269,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) { Oid this_relid = lfirst_oid(queue_item); ScanKeyData skey; - HeapScanDesc inhscan; + SysScanDesc inhscan; HeapTuple inhtup; /* @@ -255,9 +293,10 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(this_relid)); - inhscan = heap_beginscan(inhrel, SnapshotNow, 1, &skey); + inhscan = systable_beginscan(inhrel, InheritsRelidSeqnoIndexId, true, + SnapshotNow, 1, &skey); - while ((inhtup = heap_getnext(inhscan, ForwardScanDirection)) != NULL) + while ((inhtup = systable_getnext(inhscan)) != NULL) { Form_pg_inherits inh = (Form_pg_inherits) GETSTRUCT(inhtup); Oid inhparent = inh->inhparent; @@ -273,7 +312,7 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) queue = lappend_oid(queue, inhparent); } - heap_endscan(inhscan); + systable_endscan(inhscan); if (result) break; @@ -287,3 +326,18 @@ typeInheritsFrom(Oid subclassTypeId, Oid superclassTypeId) return result; } + + +/* qsort comparison function */ +static int +oid_cmp(const void *p1, const void *p2) +{ + Oid v1 = *((const Oid *) p1); + Oid v2 = *((const Oid *) p2); + + if (v1 < v2) + return -1; + if (v1 > v2) + return 1; + return 0; +} diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 5595473808..0412aaf73f 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.311 2009/12/23 16:43:43 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.312 2009/12/29 22:00:12 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1793,8 +1793,8 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid, int16 seqNumber, Relation inhRelation) { TupleDesc desc = RelationGetDescr(inhRelation); - Datum datum[Natts_pg_inherits]; - bool nullarr[Natts_pg_inherits]; + Datum values[Natts_pg_inherits]; + bool nulls[Natts_pg_inherits]; ObjectAddress childobject, parentobject; HeapTuple tuple; @@ -1802,15 +1802,13 @@ StoreCatalogInheritance1(Oid relationId, Oid parentOid, /* * Make the pg_inherits entry */ - datum[0] = ObjectIdGetDatum(relationId); /* inhrelid */ - datum[1] = ObjectIdGetDatum(parentOid); /* inhparent */ - datum[2] = Int16GetDatum(seqNumber); /* inhseqno */ + values[Anum_pg_inherits_inhrelid - 1] = ObjectIdGetDatum(relationId); + values[Anum_pg_inherits_inhparent - 1] = ObjectIdGetDatum(parentOid); + values[Anum_pg_inherits_inhseqno - 1] = Int16GetDatum(seqNumber); - nullarr[0] = false; - nullarr[1] = false; - nullarr[2] = false; + memset(nulls, 0, sizeof(nulls)); - tuple = heap_form_tuple(desc, datum, nullarr); + tuple = heap_form_tuple(desc, values, nulls); simple_heap_insert(inhRelation, tuple); diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 0c4ce00529..05ee959026 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.562 2009/12/29 20:11:45 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.563 2009/12/29 22:00:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200912281 +#define CATALOG_VERSION_NO 200912291 #endif diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index a5d93ed445..a7ab8721c7 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.112 2009/12/29 20:11:45 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.113 2009/12/29 22:00:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -156,6 +156,9 @@ DECLARE_UNIQUE_INDEX(pg_index_indexrelid_index, 2679, on pg_index using btree(in DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index, 2680, on pg_inherits using btree(inhrelid oid_ops, inhseqno int4_ops)); #define InheritsRelidSeqnoIndexId 2680 +/* This following index is not used for a cache and is not unique */ +DECLARE_INDEX(pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops)); +#define InheritsParentIndexId 2187 DECLARE_UNIQUE_INDEX(pg_language_name_index, 2681, on pg_language using btree(lanname name_ops)); #define LanguageNameIndexId 2681