aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2019-07-16 12:04:06 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2019-07-16 12:04:06 -0400
commit2f5b8eb5a28b4e6de9d20cc7d2c6028c6c7a8aa8 (patch)
tree5e6d2f0a67adc23d27ce7445aaad08c28d9fe22e /src/backend/utils/cache/relcache.c
parent569ed7f48312c70ed4a79daec1d7688fda4e74ac (diff)
downloadpostgresql-2f5b8eb5a28b4e6de9d20cc7d2c6028c6c7a8aa8.tar.gz
postgresql-2f5b8eb5a28b4e6de9d20cc7d2c6028c6c7a8aa8.zip
Clean up some ad-hoc code for sorting and de-duplicating Lists.
heap.c and relcache.c contained nearly identical copies of logic to insert OIDs into an OID list while preserving the list's OID ordering (and rejecting duplicates, in one case but not the other). The comments argue that this is faster than qsort for small numbers of OIDs, which is at best unproven, and seems even less likely to be true now that lappend_cell_oid has to move data around. In any case it's ugly and hard-to-follow code, and if we do have a lot of OIDs to consider, it's O(N^2). Hence, replace with simply lappend'ing OIDs to a List, then list_sort the completed List, then remove adjacent duplicates if necessary. This is demonstrably O(N log N) and it's much simpler for the callers. It's possible that this would be somewhat inefficient if there were a very large number of duplicates, but that seems unlikely in the existing usage. This adds list_deduplicate_oid and list_oid_cmp infrastructure to list.c. I didn't bother with equivalent functionality for integer or pointer Lists, but such could always be added later if we find a use for it. Discussion: https://postgr.es/m/26193.1563228600@sss.pgh.pa.us
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c46
1 files changed, 9 insertions, 37 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 3ca9a9f3586..7aa5d7c7fa8 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -285,7 +285,6 @@ static TupleDesc GetPgIndexDescriptor(void);
static void AttrDefaultFetch(Relation relation);
static void CheckConstraintFetch(Relation relation);
static int CheckConstraintCmp(const void *a, const void *b);
-static List *insert_ordered_oid(List *list, Oid datum);
static void InitIndexAmRoutine(Relation relation);
static void IndexSupportInitialize(oidvector *indclass,
RegProcedure *indexSupport,
@@ -4387,8 +4386,8 @@ RelationGetIndexList(Relation relation)
if (!index->indislive)
continue;
- /* Add index's OID to result list in the proper order */
- result = insert_ordered_oid(result, index->indexrelid);
+ /* add index's OID to result list */
+ result = lappend_oid(result, index->indexrelid);
/*
* Invalid, non-unique, non-immediate or predicate indexes aren't
@@ -4413,6 +4412,9 @@ RelationGetIndexList(Relation relation)
table_close(indrel, AccessShareLock);
+ /* Sort the result list into OID order, per API spec. */
+ list_sort(result, list_oid_cmp);
+
/* Now save a copy of the completed list in the relcache entry. */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
oldlist = relation->rd_indexlist;
@@ -4494,13 +4496,16 @@ RelationGetStatExtList(Relation relation)
{
Oid oid = ((Form_pg_statistic_ext) GETSTRUCT(htup))->oid;
- result = insert_ordered_oid(result, oid);
+ result = lappend_oid(result, oid);
}
systable_endscan(indscan);
table_close(indrel, AccessShareLock);
+ /* Sort the result list into OID order, per API spec. */
+ list_sort(result, list_oid_cmp);
+
/* Now save a copy of the completed list in the relcache entry. */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
oldlist = relation->rd_statlist;
@@ -4516,39 +4521,6 @@ RelationGetStatExtList(Relation relation)
}
/*
- * insert_ordered_oid
- * Insert a new Oid into a sorted list of Oids, preserving ordering
- *
- * Building the ordered list this way is O(N^2), but with a pretty small
- * constant, so for the number of entries we expect it will probably be
- * faster than trying to apply qsort(). Most tables don't have very many
- * indexes...
- */
-static List *
-insert_ordered_oid(List *list, Oid datum)
-{
- ListCell *prev;
-
- /* Does the datum belong at the front? */
- if (list == NIL || datum < linitial_oid(list))
- return lcons_oid(datum, list);
- /* No, so find the entry it belongs after */
- prev = list_head(list);
- for (;;)
- {
- ListCell *curr = lnext(list, prev);
-
- if (curr == NULL || datum < lfirst_oid(curr))
- break; /* it belongs after 'prev', before 'curr' */
-
- prev = curr;
- }
- /* Insert datum into list after 'prev' */
- lappend_cell_oid(list, prev, datum);
- return list;
-}
-
-/*
* RelationGetPrimaryKeyIndex -- get OID of the relation's primary key index
*
* Returns InvalidOid if there is no such index.