From 441563a698a7af06dfb71d0eca1283a1ca7a7cf1 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sun, 14 Mar 2021 11:40:01 +1300
Subject: [PATCH 3/9] Use qsort_oid() and friends in obvious places.

Done mainly for notational advantage over traditional qsort()/bsearch().
There may be some speedup, from inlined branchless comparators.
---
 src/backend/access/nbtree/nbtinsert.c   | 30 +++++--------------------
 src/backend/catalog/pg_enum.c           |  3 ++-
 src/backend/catalog/pg_inherits.c       |  3 ++-
 src/backend/commands/subscriptioncmds.c | 15 ++++++-------
 src/backend/utils/adt/acl.c             |  5 +++--
 src/backend/utils/cache/syscache.c      | 30 +++++--------------------
 6 files changed, 24 insertions(+), 62 deletions(-)

diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c
index 0bc86943eb..09abf342de 100644
--- a/src/backend/access/nbtree/nbtinsert.c
+++ b/src/backend/access/nbtree/nbtinsert.c
@@ -19,11 +19,11 @@
 #include "access/nbtxlog.h"
 #include "access/transam.h"
 #include "access/xloginsert.h"
-#include "lib/qunique.h"
 #include "miscadmin.h"
 #include "storage/lmgr.h"
 #include "storage/predicate.h"
 #include "storage/smgr.h"
+#include "utils/sortscalar.h"
 
 /* Minimum tree height for application of fastpath optimization */
 #define BTREE_FASTPATH_MIN_LEVEL	2
@@ -70,7 +70,6 @@ static void _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel,
 static BlockNumber *_bt_deadblocks(Page page, OffsetNumber *deletable,
 								   int ndeletable, IndexTuple newitem,
 								   int *nblocks);
-static inline int _bt_blk_cmp(const void *arg1, const void *arg2);
 
 /*
  *	_bt_doinsert() -- Handle insertion of a single index tuple in the tree.
@@ -2814,8 +2813,7 @@ _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel,
 		if (!BTreeTupleIsPosting(itup))
 		{
 			tidblock = ItemPointerGetBlockNumber(&itup->t_tid);
-			match = bsearch(&tidblock, deadblocks, ndeadblocks,
-							sizeof(BlockNumber), _bt_blk_cmp);
+			match = bsearch_blocknum(&tidblock, deadblocks, ndeadblocks);
 
 			if (!match)
 			{
@@ -2845,8 +2843,7 @@ _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel,
 				ItemPointer tid = BTreeTupleGetPostingN(itup, p);
 
 				tidblock = ItemPointerGetBlockNumber(tid);
-				match = bsearch(&tidblock, deadblocks, ndeadblocks,
-								sizeof(BlockNumber), _bt_blk_cmp);
+				match = bsearch_blocknum(&tidblock, deadblocks, ndeadblocks);
 
 				if (!match)
 				{
@@ -2966,25 +2963,8 @@ _bt_deadblocks(Page page, OffsetNumber *deletable, int ndeletable,
 		}
 	}
 
-	qsort(tidblocks, ntids, sizeof(BlockNumber), _bt_blk_cmp);
-	*nblocks = qunique(tidblocks, ntids, sizeof(BlockNumber), _bt_blk_cmp);
+	qsort_blocknum(tidblocks, ntids);
+	*nblocks = unique_blocknum(tidblocks, ntids);
 
 	return tidblocks;
 }
-
-/*
- * _bt_blk_cmp() -- qsort comparison function for _bt_simpledel_pass
- */
-static inline int
-_bt_blk_cmp(const void *arg1, const void *arg2)
-{
-	BlockNumber b1 = *((BlockNumber *) arg1);
-	BlockNumber b2 = *((BlockNumber *) arg2);
-
-	if (b1 < b2)
-		return -1;
-	else if (b1 > b2)
-		return 1;
-
-	return 0;
-}
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index f958f1541d..1d9dacb516 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -30,6 +30,7 @@
 #include "utils/fmgroids.h"
 #include "utils/hsearch.h"
 #include "utils/memutils.h"
+#include "utils/sortscalar.h"
 #include "utils/syscache.h"
 
 /* Potentially set by pg_upgrade_support functions */
@@ -108,7 +109,7 @@ EnumValuesCreate(Oid enumTypeOid, List *vals)
 	}
 
 	/* sort them, just in case OID counter wrapped from high to low */
-	qsort(oids, num_elems, sizeof(Oid), oid_cmp);
+	qsort_oid(oids, num_elems);
 
 	/* and make the entries */
 	memset(nulls, false, sizeof(nulls));
diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c
index 5ab7902827..5cf76b2cad 100644
--- a/src/backend/catalog/pg_inherits.c
+++ b/src/backend/catalog/pg_inherits.c
@@ -29,6 +29,7 @@
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
 #include "utils/memutils.h"
+#include "utils/sortscalar.h"
 #include "utils/syscache.h"
 
 /*
@@ -111,7 +112,7 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
 	 * lock children in the same order to avoid needless deadlocks.
 	 */
 	if (numoids > 1)
-		qsort(oidarr, numoids, sizeof(Oid), oid_cmp);
+		qsort_oid(oidarr, numoids);
 
 	/*
 	 * Acquire locks and build the result list.
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index bfd3514546..a24db5dca8 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -44,6 +44,7 @@
 #include "utils/guc.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
+#include "utils/sortscalar.h"
 #include "utils/syscache.h"
 
 static List *fetch_table_list(WalReceiverConn *wrconn, List *publications);
@@ -608,8 +609,7 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
 
 			subrel_local_oids[off++] = relstate->relid;
 		}
-		qsort(subrel_local_oids, list_length(subrel_states),
-			  sizeof(Oid), oid_cmp);
+		qsort_oid(subrel_local_oids, list_length(subrel_states));
 
 		/*
 		 * Rels that we want to remove from subscription and drop any slots
@@ -640,8 +640,8 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
 
 			pubrel_local_oids[off++] = relid;
 
-			if (!bsearch(&relid, subrel_local_oids,
-						 list_length(subrel_states), sizeof(Oid), oid_cmp))
+			if (!bsearch_oid(&relid, subrel_local_oids,
+							 list_length(subrel_states)))
 			{
 				AddSubscriptionRelState(sub->oid, relid,
 										copy_data ? SUBREL_STATE_INIT : SUBREL_STATE_READY,
@@ -656,16 +656,15 @@ AlterSubscription_refresh(Subscription *sub, bool copy_data)
 		 * Next remove state for tables we should not care about anymore using
 		 * the data we collected above
 		 */
-		qsort(pubrel_local_oids, list_length(pubrel_names),
-			  sizeof(Oid), oid_cmp);
+		qsort_oid(pubrel_local_oids, list_length(pubrel_names));
 
 		remove_rel_len = 0;
 		for (off = 0; off < list_length(subrel_states); off++)
 		{
 			Oid			relid = subrel_local_oids[off];
 
-			if (!bsearch(&relid, pubrel_local_oids,
-						 list_length(pubrel_names), sizeof(Oid), oid_cmp))
+			if (!bsearch_oid(&relid, pubrel_local_oids,
+							 list_length(pubrel_names)))
 			{
 				char		state;
 				XLogRecPtr	statelsn;
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index c7f029e218..2b90ee4c88 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -38,6 +38,7 @@
 #include "utils/inval.h"
 #include "utils/lsyscache.h"
 #include "utils/memutils.h"
+#include "utils/sortscalar.h"
 #include "utils/syscache.h"
 #include "utils/varlena.h"
 
@@ -1496,7 +1497,7 @@ aclmembers(const Acl *acl, Oid **roleids)
 	}
 
 	/* Sort the array */
-	qsort(list, j, sizeof(Oid), oid_cmp);
+	qsort_oid(list, j);
 
 	/*
 	 * We could repalloc the array down to minimum size, but it's hardly worth
@@ -1505,7 +1506,7 @@ aclmembers(const Acl *acl, Oid **roleids)
 	*roleids = list;
 
 	/* Remove duplicates from the array */
-	return qunique(list, j, sizeof(Oid), oid_cmp);
+	return unique_oid(list, j);
 }
 
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index e4dc4ee34e..26ef27b50d 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -76,6 +76,7 @@
 #include "lib/qunique.h"
 #include "utils/catcache.h"
 #include "utils/rel.h"
+#include "utils/sortscalar.h"
 #include "utils/syscache.h"
 
 /*---------------------------------------------------------------------------
@@ -1006,8 +1007,6 @@ static int	SysCacheRelationOidSize;
 static Oid	SysCacheSupportingRelOid[SysCacheSize * 2];
 static int	SysCacheSupportingRelOidSize;
 
-static int	oid_compare(const void *a, const void *b);
-
 
 /*
  * InitCatalogCache - initialize the caches
@@ -1055,17 +1054,13 @@ InitCatalogCache(void)
 	Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
 
 	/* Sort and de-dup OID arrays, so we can use binary search. */
-	pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
-			 sizeof(Oid), oid_compare);
+	qsort_oid(SysCacheRelationOid, SysCacheRelationOidSize);
 	SysCacheRelationOidSize =
-		qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
-				oid_compare);
+		unique_oid(SysCacheRelationOid, SysCacheRelationOidSize);
 
-	pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
-			 sizeof(Oid), oid_compare);
+	qsort_oid(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize);
 	SysCacheSupportingRelOidSize =
-		qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
-				sizeof(Oid), oid_compare);
+		unique_oid(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize);
 
 	CacheInitialized = true;
 }
@@ -1548,18 +1543,3 @@ RelationSupportsSysCache(Oid relid)
 
 	return false;
 }
-
-
-/*
- * OID comparator for pg_qsort
- */
-static int
-oid_compare(const void *a, const void *b)
-{
-	Oid			oa = *((const Oid *) a);
-	Oid			ob = *((const Oid *) b);
-
-	if (oa == ob)
-		return 0;
-	return (oa > ob) ? 1 : -1;
-}
-- 
2.30.1

