Use new overflow-safe integer comparison functions.

Commit 6b80394781 introduced integer comparison functions designed
to be as efficient as possible while avoiding overflow.  This
commit makes use of these functions in many of the in-tree qsort()
comparators to help ensure transitivity.  Many of these comparator
functions should also see a small performance boost.

Author: Mats Kindahl
Reviewed-by: Andres Freund, Fabrízio de Royes Mello
Discussion: https://postgr.es/m/CA%2B14426g2Wa9QuUpmakwPxXFWG_1FaY0AsApkvcTBy-YfS6uaw%40mail.gmail.com
This commit is contained in:
Nathan Bossart 2024-02-16 14:05:36 -06:00
parent 6b80394781
commit 3b42bdb471
34 changed files with 80 additions and 159 deletions

View File

@ -7,6 +7,7 @@
#include "access/reloptions.h"
#include "access/stratnum.h"
#include "catalog/pg_type.h"
#include "common/int.h"
#include "hstore.h"
#include "utils/pg_crc.h"
@ -356,7 +357,8 @@ typedef struct
static int
comparecost(const void *a, const void *b)
{
return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
return pg_cmp_s32(((const SPLITCOST *) a)->cost,
((const SPLITCOST *) b)->cost);
}

View File

@ -7,6 +7,7 @@
#include "_int.h"
#include "catalog/pg_type.h"
#include "common/int.h"
#include "lib/qunique.h"
/* arguments are assumed sorted & unique-ified */
@ -396,15 +397,11 @@ int_to_intset(int32 elem)
int
compASC(const void *a, const void *b)
{
if (*(const int32 *) a == *(const int32 *) b)
return 0;
return (*(const int32 *) a > *(const int32 *) b) ? 1 : -1;
return pg_cmp_s32(*(const int32 *) a, *(const int32 *) b);
}
int
compDESC(const void *a, const void *b)
{
if (*(const int32 *) a == *(const int32 *) b)
return 0;
return (*(const int32 *) a < *(const int32 *) b) ? 1 : -1;
return pg_cmp_s32(*(const int32 *) b, *(const int32 *) a);
}

View File

@ -9,6 +9,7 @@
#include "access/gist.h"
#include "access/reloptions.h"
#include "access/stratnum.h"
#include "common/int.h"
#include "port/pg_bitutils.h"
#define GETENTRY(vec,pos) ((GISTTYPE *) DatumGetPointer((vec)->vector[(pos)].key))
@ -312,7 +313,8 @@ typedef struct
static int
comparecost(const void *a, const void *b)
{
return ((const SPLITCOST *) a)->cost - ((const SPLITCOST *) b)->cost;
return pg_cmp_s32(((const SPLITCOST *) a)->cost,
((const SPLITCOST *) b)->cost);
}

View File

@ -50,6 +50,7 @@
#include "access/parallel.h"
#include "catalog/pg_authid.h"
#include "common/hashfn.h"
#include "common/int.h"
#include "executor/instrument.h"
#include "funcapi.h"
#include "jit/jit.h"
@ -3007,10 +3008,5 @@ comp_location(const void *a, const void *b)
int l = ((const LocationLen *) a)->location;
int r = ((const LocationLen *) b)->location;
if (l < r)
return -1;
else if (l > r)
return +1;
else
return 0;
return pg_cmp_s32(l, r);
}

View File

@ -6,6 +6,7 @@
#include <ctype.h>
#include "catalog/pg_type.h"
#include "common/int.h"
#include "lib/qunique.h"
#include "miscadmin.h"
#include "trgm.h"
@ -433,12 +434,7 @@ comp_ptrgm(const void *v1, const void *v2)
if (cmp != 0)
return cmp;
if (p1->index < p2->index)
return -1;
else if (p1->index == p2->index)
return 0;
else
return 1;
return pg_cmp_s32(p1->index, p2->index);
}
/*

View File

@ -19,6 +19,7 @@
#include "access/nbtxlog.h"
#include "access/transam.h"
#include "access/xloginsert.h"
#include "common/int.h"
#include "common/pg_prng.h"
#include "lib/qunique.h"
#include "miscadmin.h"
@ -3013,10 +3014,5 @@ _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;
return pg_cmp_u32(b1, b2);
}

View File

@ -28,6 +28,7 @@
#include "access/transam.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "common/int.h"
#include "miscadmin.h"
#include "storage/indexfsm.h"
#include "storage/lmgr.h"
@ -1466,14 +1467,9 @@ _bt_delitems_cmp(const void *a, const void *b)
TM_IndexDelete *indexdelete1 = (TM_IndexDelete *) a;
TM_IndexDelete *indexdelete2 = (TM_IndexDelete *) b;
if (indexdelete1->id > indexdelete2->id)
return 1;
if (indexdelete1->id < indexdelete2->id)
return -1;
Assert(indexdelete1->id != indexdelete2->id);
Assert(false);
return 0;
return pg_cmp_s16(indexdelete1->id, indexdelete2->id);
}
/*

View File

@ -15,6 +15,7 @@
#include "postgres.h"
#include "access/nbtree.h"
#include "common/int.h"
#include "storage/lmgr.h"
typedef enum
@ -596,12 +597,7 @@ _bt_splitcmp(const void *arg1, const void *arg2)
SplitPoint *split1 = (SplitPoint *) arg1;
SplitPoint *split2 = (SplitPoint *) arg2;
if (split1->curdelta > split2->curdelta)
return 1;
if (split1->curdelta < split2->curdelta)
return -1;
return 0;
return pg_cmp_s16(split1->curdelta, split2->curdelta);
}
/*

View File

@ -19,6 +19,7 @@
#include "access/spgist_private.h"
#include "access/spgxlog.h"
#include "access/xloginsert.h"
#include "common/int.h"
#include "common/pg_prng.h"
#include "miscadmin.h"
#include "storage/bufmgr.h"
@ -110,9 +111,7 @@ addNode(SpGistState *state, SpGistInnerTuple tuple, Datum label, int offset)
static int
cmpOffsetNumbers(const void *a, const void *b)
{
if (*(const OffsetNumber *) a == *(const OffsetNumber *) b)
return 0;
return (*(const OffsetNumber *) a > *(const OffsetNumber *) b) ? 1 : -1;
return pg_cmp_u16(*(const OffsetNumber *) a, *(const OffsetNumber *) b);
}
/*

View File

@ -40,6 +40,7 @@
#include "postgres.h"
#include "access/spgist.h"
#include "common/int.h"
#include "catalog/pg_type.h"
#include "mb/pg_wchar.h"
#include "utils/builtins.h"
@ -325,7 +326,7 @@ cmpNodePtr(const void *a, const void *b)
const spgNodePtr *aa = (const spgNodePtr *) a;
const spgNodePtr *bb = (const spgNodePtr *) b;
return aa->c - bb->c;
return pg_cmp_s16(aa->c, bb->c);
}
Datum

View File

@ -27,6 +27,7 @@
#include "common/blkreftable.h"
#include "common/parse_manifest.h"
#include "common/hashfn.h"
#include "common/int.h"
#include "postmaster/walsummarizer.h"
#define BLOCKS_PER_READ 512
@ -994,10 +995,5 @@ compare_block_numbers(const void *a, const void *b)
BlockNumber aa = *(BlockNumber *) a;
BlockNumber bb = *(BlockNumber *) b;
if (aa > bb)
return 1;
else if (aa == bb)
return 0;
else
return -1;
return pg_cmp_u32(aa, bb);
}

View File

@ -17,6 +17,7 @@
#include "access/xlog_internal.h"
#include "backup/walsummary.h"
#include "common/int.h"
#include "utils/wait_event.h"
static bool IsWalSummaryFilename(char *filename);
@ -355,9 +356,5 @@ ListComparatorForWalSummaryFiles(const ListCell *a, const ListCell *b)
WalSummaryFile *ws1 = lfirst(a);
WalSummaryFile *ws2 = lfirst(b);
if (ws1->start_lsn < ws2->start_lsn)
return -1;
if (ws1->start_lsn > ws2->start_lsn)
return 1;
return 0;
return pg_cmp_u64(ws1->start_lsn, ws2->start_lsn);
}

View File

@ -56,6 +56,7 @@
#include "catalog/storage.h"
#include "commands/tablecmds.h"
#include "commands/typecmds.h"
#include "common/int.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
@ -2762,11 +2763,7 @@ list_cookedconstr_attnum_cmp(const ListCell *p1, const ListCell *p2)
AttrNumber v1 = ((CookedConstraint *) lfirst(p1))->attnum;
AttrNumber v2 = ((CookedConstraint *) lfirst(p2))->attnum;
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
return pg_cmp_s16(v1, v2);
}
/*

View File

@ -17,6 +17,7 @@
*/
#include "postgres.h"
#include "common/int.h"
#include "nodes/pg_list.h"
#include "port/pg_bitutils.h"
#include "utils/memdebug.h"
@ -1692,11 +1693,7 @@ list_int_cmp(const ListCell *p1, const ListCell *p2)
int v1 = lfirst_int(p1);
int v2 = lfirst_int(p2);
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
return pg_cmp_s32(v1, v2);
}
/*
@ -1708,9 +1705,5 @@ list_oid_cmp(const ListCell *p1, const ListCell *p2)
Oid v1 = lfirst_oid(p1);
Oid v2 = lfirst_oid(p2);
if (v1 < v2)
return -1;
if (v1 > v2)
return 1;
return 0;
return pg_cmp_u32(v1, v2);
}

View File

@ -42,6 +42,7 @@
#include "access/htup_details.h"
#include "common/hashfn.h"
#include "common/int.h"
#include "nodes/bitmapset.h"
#include "nodes/tidbitmap.h"
#include "storage/lwlock.h"
@ -1425,11 +1426,7 @@ tbm_comparator(const void *left, const void *right)
BlockNumber l = (*((PagetableEntry *const *) left))->blockno;
BlockNumber r = (*((PagetableEntry *const *) right))->blockno;
if (l < r)
return -1;
else if (l > r)
return 1;
return 0;
return pg_cmp_u32(l, r);
}
/*

View File

@ -18,6 +18,7 @@
#include "catalog/pg_aggregate.h"
#include "catalog/pg_constraint.h"
#include "catalog/pg_type.h"
#include "common/int.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.h"
@ -1760,7 +1761,7 @@ cmp_list_len_asc(const ListCell *a, const ListCell *b)
int la = list_length((const List *) lfirst(a));
int lb = list_length((const List *) lfirst(b));
return (la > lb) ? 1 : (la == lb) ? 0 : -1;
return pg_cmp_s32(la, lb);
}
/* list_sort comparator to sort sub-lists by length and contents */

View File

@ -78,6 +78,7 @@
#include "catalog/pg_database.h"
#include "commands/dbcommands.h"
#include "commands/vacuum.h"
#include "common/int.h"
#include "lib/ilist.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
@ -1120,10 +1121,8 @@ rebuild_database_list(Oid newdb)
static int
db_comparator(const void *a, const void *b)
{
if (((const avl_dbase *) a)->adl_score == ((const avl_dbase *) b)->adl_score)
return 0;
else
return (((const avl_dbase *) a)->adl_score < ((const avl_dbase *) b)->adl_score) ? 1 : -1;
return pg_cmp_s32(((const avl_dbase *) a)->adl_score,
((const avl_dbase *) b)->adl_score);
}
/*

View File

@ -91,6 +91,7 @@
#include "access/xact.h"
#include "access/xlog_internal.h"
#include "catalog/catalog.h"
#include "common/int.h"
#include "lib/binaryheap.h"
#include "miscadmin.h"
#include "pgstat.h"
@ -5119,11 +5120,7 @@ file_sort_by_lsn(const ListCell *a_p, const ListCell *b_p)
RewriteMappingFile *a = (RewriteMappingFile *) lfirst(a_p);
RewriteMappingFile *b = (RewriteMappingFile *) lfirst(b_p);
if (a->lsn < b->lsn)
return -1;
else if (a->lsn > b->lsn)
return 1;
return 0;
return pg_cmp_u64(a->lsn, b->lsn);
}
/*

View File

@ -75,6 +75,7 @@
#include <unistd.h>
#include "access/xact.h"
#include "common/int.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "replication/syncrep.h"
@ -698,12 +699,7 @@ cmp_lsn(const void *a, const void *b)
XLogRecPtr lsn1 = *((const XLogRecPtr *) a);
XLogRecPtr lsn2 = *((const XLogRecPtr *) b);
if (lsn1 > lsn2)
return -1;
else if (lsn1 == lsn2)
return 0;
else
return 1;
return pg_cmp_u64(lsn2, lsn1);
}
/*

View File

@ -18,6 +18,7 @@
#include <limits.h>
#include "catalog/pg_type.h"
#include "common/int.h"
#include "libpq/pqformat.h"
#include "nodes/miscnodes.h"
#include "nodes/value.h"
@ -259,11 +260,7 @@ 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;
return pg_cmp_u32(v1, v2);
}

View File

@ -17,6 +17,7 @@
#include "access/gist.h"
#include "access/heaptoast.h"
#include "access/reloptions.h"
#include "common/int.h"
#include "lib/qunique.h"
#include "port/pg_bitutils.h"
#include "tsearch/ts_utils.h"
@ -136,9 +137,7 @@ compareint(const void *va, const void *vb)
int32 a = *((const int32 *) va);
int32 b = *((const int32 *) vb);
if (a == b)
return 0;
return (a > b) ? 1 : -1;
return pg_cmp_s32(a, b);
}
static void
@ -598,10 +597,7 @@ comparecost(const void *va, const void *vb)
const SPLITCOST *a = (const SPLITCOST *) va;
const SPLITCOST *b = (const SPLITCOST *) vb;
if (a->cost == b->cost)
return 0;
else
return (a->cost > b->cost) ? 1 : -1;
return pg_cmp_s32(a->cost, b->cost);
}

View File

@ -16,6 +16,7 @@
#include "access/gist.h"
#include "access/stratnum.h"
#include "common/int.h"
#include "tsearch/ts_utils.h"
#include "utils/builtins.h"
@ -156,10 +157,8 @@ typedef struct
static int
comparecost(const void *a, const void *b)
{
if (((const SPLITCOST *) a)->cost == ((const SPLITCOST *) b)->cost)
return 0;
else
return (((const SPLITCOST *) a)->cost > ((const SPLITCOST *) b)->cost) ? 1 : -1;
return pg_cmp_s32(((const SPLITCOST *) a)->cost,
((const SPLITCOST *) b)->cost);
}
#define WISH_F(a,b,c) (double)( -(double)(((a)-(b))*((a)-(b))*((a)-(b)))*(c) )

View File

@ -14,6 +14,7 @@
#include "postgres.h"
#include "common/int.h"
#include "libpq/pqformat.h"
#include "nodes/miscnodes.h"
#include "tsearch/ts_locale.h"
@ -37,9 +38,7 @@ compareWordEntryPos(const void *a, const void *b)
int apos = WEP_GETPOS(*(const WordEntryPos *) a);
int bpos = WEP_GETPOS(*(const WordEntryPos *) b);
if (apos == bpos)
return 0;
return (apos > bpos) ? 1 : -1;
return pg_cmp_s32(apos, bpos);
}
/*

View File

@ -19,6 +19,7 @@
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "commands/trigger.h"
#include "common/int.h"
#include "executor/spi.h"
#include "funcapi.h"
#include "lib/qunique.h"
@ -435,9 +436,7 @@ compare_int(const void *va, const void *vb)
int a = *((const int *) va);
int b = *((const int *) vb);
if (a == b)
return 0;
return (a > b) ? 1 : -1;
return pg_cmp_s32(a, b);
}
static int

View File

@ -19,6 +19,7 @@
#include "access/multixact.h"
#include "access/transam.h"
#include "access/xact.h"
#include "common/int.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#include "utils/xid8.h"
@ -140,11 +141,7 @@ xidComparator(const void *arg1, const void *arg2)
TransactionId xid1 = *(const TransactionId *) arg1;
TransactionId xid2 = *(const TransactionId *) arg2;
if (xid1 > xid2)
return 1;
if (xid1 < xid2)
return -1;
return 0;
return pg_cmp_u32(xid1, xid2);
}
/*

View File

@ -69,6 +69,7 @@
#include "commands/policy.h"
#include "commands/publicationcmds.h"
#include "commands/trigger.h"
#include "common/int.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
@ -4520,7 +4521,7 @@ AttrDefaultCmp(const void *a, const void *b)
const AttrDefault *ada = (const AttrDefault *) a;
const AttrDefault *adb = (const AttrDefault *) b;
return ada->adnum - adb->adnum;
return pg_cmp_s16(ada->adnum, adb->adnum);
}
/*

View File

@ -29,6 +29,7 @@
#include "catalog/pg_shdepend_d.h"
#include "catalog/pg_shdescription_d.h"
#include "catalog/pg_shseclabel_d.h"
#include "common/int.h"
#include "lib/qunique.h"
#include "utils/catcache.h"
#include "utils/lsyscache.h"
@ -676,7 +677,5 @@ 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;
return pg_cmp_u32(oa, ob);
}

View File

@ -57,6 +57,7 @@
#include "catalog/pg_range.h"
#include "catalog/pg_type.h"
#include "commands/defrem.h"
#include "common/int.h"
#include "executor/executor.h"
#include "lib/dshash.h"
#include "optimizer/optimizer.h"
@ -2722,12 +2723,7 @@ enum_oid_cmp(const void *left, const void *right)
const EnumItem *l = (const EnumItem *) left;
const EnumItem *r = (const EnumItem *) right;
if (l->enum_oid < r->enum_oid)
return -1;
else if (l->enum_oid > r->enum_oid)
return 1;
else
return 0;
return pg_cmp_u32(l->enum_oid, r->enum_oid);
}
/*

View File

@ -46,6 +46,7 @@
#include "postgres.h"
#include "common/hashfn.h"
#include "common/int.h"
#include "storage/ipc.h"
#include "storage/predicate.h"
#include "storage/proc.h"
@ -264,14 +265,7 @@ resource_priority_cmp(const void *a, const void *b)
/* Note: reverse order */
if (ra->kind->release_phase == rb->kind->release_phase)
{
if (ra->kind->release_priority == rb->kind->release_priority)
return 0;
else if (ra->kind->release_priority > rb->kind->release_priority)
return -1;
else
return 1;
}
return pg_cmp_u32(rb->kind->release_priority, ra->kind->release_priority);
else if (ra->kind->release_phase > rb->kind->release_phase)
return -1;
else

View File

@ -16,6 +16,7 @@
#include "postgres_fe.h"
#include "catalog/pg_class_d.h"
#include "common/int.h"
#include "lib/binaryheap.h"
#include "pg_backup_archiver.h"
#include "pg_backup_utils.h"
@ -1504,9 +1505,5 @@ int_cmp(void *a, void *b, void *arg)
int ai = (int) (intptr_t) a;
int bi = (int) (intptr_t) b;
if (ai < bi)
return -1;
if (ai > bi)
return 1;
return 0;
return pg_cmp_s32(ai, bi);
}

View File

@ -11,6 +11,7 @@
#include "access/transam.h"
#include "catalog/pg_language_d.h"
#include "common/int.h"
#include "pg_upgrade.h"
/*
@ -29,17 +30,16 @@ library_name_compare(const void *p1, const void *p2)
{
const char *str1 = ((const LibraryInfo *) p1)->name;
const char *str2 = ((const LibraryInfo *) p2)->name;
int slen1 = strlen(str1);
int slen2 = strlen(str2);
size_t slen1 = strlen(str1);
size_t slen2 = strlen(str2);
int cmp = strcmp(str1, str2);
if (slen1 != slen2)
return slen1 - slen2;
return pg_cmp_size(slen1, slen2);
if (cmp != 0)
return cmp;
else
return ((const LibraryInfo *) p1)->dbnum -
((const LibraryInfo *) p2)->dbnum;
return pg_cmp_s32(((const LibraryInfo *) p1)->dbnum,
((const LibraryInfo *) p2)->dbnum);
}

View File

@ -16,6 +16,7 @@
#include <limits.h>
#include "common/blkreftable.h"
#include "common/int.h"
#include "common/logging.h"
#include "fe_utils/option_utils.h"
#include "lib/stringinfo.h"
@ -219,12 +220,7 @@ compare_block_numbers(const void *a, const void *b)
BlockNumber aa = *(BlockNumber *) a;
BlockNumber bb = *(BlockNumber *) b;
if (aa > bb)
return 1;
else if (aa == bb)
return 0;
else
return -1;
return pg_cmp_u32(aa, bb);
}
/*

View File

@ -8,6 +8,7 @@
#include "postgres_fe.h"
#include "common.h"
#include "common/int.h"
#include "common/logging.h"
#include "crosstabview.h"
#include "pqexpbuffer.h"
@ -709,5 +710,5 @@ pivotFieldCompare(const void *a, const void *b)
static int
rankCompare(const void *a, const void *b)
{
return *((const int *) a) - *((const int *) b);
return pg_cmp_s32(*(const int *) a, *(const int *) b);
}

View File

@ -14,6 +14,7 @@
#include "access/gin.h"
#include "access/ginblock.h"
#include "access/itup.h"
#include "common/int.h"
#include "catalog/pg_am_d.h"
#include "fmgr.h"
#include "lib/rbtree.h"
@ -489,12 +490,7 @@ ginCompareItemPointers(ItemPointer a, ItemPointer b)
uint64 ia = (uint64) GinItemPointerGetBlockNumber(a) << 32 | GinItemPointerGetOffsetNumber(a);
uint64 ib = (uint64) GinItemPointerGetBlockNumber(b) << 32 | GinItemPointerGetOffsetNumber(b);
if (ia == ib)
return 0;
else if (ia > ib)
return 1;
else
return -1;
return pg_cmp_u64(ia, ib);
}
extern int ginTraverseLock(Buffer buffer, bool searchMode);