PostgreSQL Source Code git master
Loading...
Searching...
No Matches
nbtcompare.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * nbtcompare.c
4 * Comparison functions for btree access method.
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/access/nbtree/nbtcompare.c
12 *
13 * NOTES
14 *
15 * These functions are stored in pg_amproc. For each operator class
16 * defined on btrees, they compute
17 *
18 * compare(a, b):
19 * < 0 if a < b,
20 * = 0 if a == b,
21 * > 0 if a > b.
22 *
23 * The result is always an int32 regardless of the input datatype.
24 *
25 * Although any negative int32 is acceptable for reporting "<",
26 * and any positive int32 is acceptable for reporting ">", routines
27 * that work on 32-bit or wider datatypes can't just return "a - b".
28 * That could overflow and give the wrong answer.
29 *
30 * NOTE: it is critical that the comparison function impose a total order
31 * on all non-NULL values of the data type, and that the datatype's
32 * boolean comparison operators (= < >= etc) yield results consistent
33 * with the comparison routine. Otherwise bad behavior may ensue.
34 * (For example, the comparison operators must NOT punt when faced with
35 * NAN or other funny values; you must devise some collation sequence for
36 * all such values.) If the datatype is not trivial, this is most
37 * reliably done by having the boolean operators invoke the same
38 * three-way comparison code that the btree function does. Therefore,
39 * this file contains only btree support for "trivial" datatypes ---
40 * all others are in the /utils/adt/ files that implement their datatypes.
41 *
42 * NOTE: these routines must not leak memory, since memory allocated
43 * during an index access won't be recovered till end of query. This
44 * primarily affects comparison routines for toastable datatypes;
45 * they have to be careful to free any detoasted copy of an input datum.
46 *
47 * NOTE: we used to forbid comparison functions from returning INT_MIN,
48 * but that proves to be too error-prone because some platforms' versions
49 * of memcmp() etc can return INT_MIN. As a means of stress-testing
50 * callers, this file can be compiled with STRESS_SORT_INT_MIN defined
51 * to cause many of these functions to return INT_MIN or INT_MAX instead of
52 * their customary -1/+1. For production, though, that's not a good idea
53 * since users or third-party code might expect the traditional results.
54 *-------------------------------------------------------------------------
55 */
56#include "postgres.h"
57
58#include <limits.h>
59
60#include "utils/builtins.h"
61#include "utils/fmgrprotos.h"
62#include "utils/skipsupport.h"
63#include "utils/sortsupport.h"
64
65#ifdef STRESS_SORT_INT_MIN
66#define A_LESS_THAN_B INT_MIN
67#define A_GREATER_THAN_B INT_MAX
68#else
69#define A_LESS_THAN_B (-1)
70#define A_GREATER_THAN_B 1
71#endif
72
73
76{
77 bool a = PG_GETARG_BOOL(0);
78 bool b = PG_GETARG_BOOL(1);
79
81}
82
83static Datum
85{
87
88 if (bexisting == false)
89 {
90 /* return value is undefined */
91 *underflow = true;
92 return (Datum) 0;
93 }
94
95 *underflow = false;
96 return BoolGetDatum(bexisting - 1);
97}
98
99static Datum
101{
103
104 if (bexisting == true)
105 {
106 /* return value is undefined */
107 *overflow = true;
108 return (Datum) 0;
109 }
110
111 *overflow = false;
112 return BoolGetDatum(bexisting + 1);
113}
114
115Datum
117{
119
120 sksup->decrement = bool_decrement;
121 sksup->increment = bool_increment;
122 sksup->low_elem = BoolGetDatum(false);
123 sksup->high_elem = BoolGetDatum(true);
124
126}
127
128Datum
136
137static int
139{
142
143 return (int) a - (int) b;
144}
145
146Datum
154
155static Datum
157{
159
160 if (iexisting == PG_INT16_MIN)
161 {
162 /* return value is undefined */
163 *underflow = true;
164 return (Datum) 0;
165 }
166
167 *underflow = false;
168 return Int16GetDatum(iexisting - 1);
169}
170
171static Datum
173{
175
176 if (iexisting == PG_INT16_MAX)
177 {
178 /* return value is undefined */
179 *overflow = true;
180 return (Datum) 0;
181 }
182
183 *overflow = false;
184 return Int16GetDatum(iexisting + 1);
185}
186
187Datum
199
200Datum
202{
205
206 if (a > b)
208 else if (a == b)
210 else
212}
213
214Datum
222
223static Datum
225{
227
228 if (iexisting == PG_INT32_MIN)
229 {
230 /* return value is undefined */
231 *underflow = true;
232 return (Datum) 0;
233 }
234
235 *underflow = false;
236 return Int32GetDatum(iexisting - 1);
237}
238
239static Datum
241{
243
244 if (iexisting == PG_INT32_MAX)
245 {
246 /* return value is undefined */
247 *overflow = true;
248 return (Datum) 0;
249 }
250
251 *overflow = false;
252 return Int32GetDatum(iexisting + 1);
253}
254
255Datum
267
268Datum
270{
273
274 if (a > b)
276 else if (a == b)
278 else
280}
281
282Datum
290
291static Datum
293{
295
296 if (iexisting == PG_INT64_MIN)
297 {
298 /* return value is undefined */
299 *underflow = true;
300 return (Datum) 0;
301 }
302
303 *underflow = false;
304 return Int64GetDatum(iexisting - 1);
305}
306
307static Datum
309{
311
312 if (iexisting == PG_INT64_MAX)
313 {
314 /* return value is undefined */
315 *overflow = true;
316 return (Datum) 0;
317 }
318
319 *overflow = false;
320 return Int64GetDatum(iexisting + 1);
321}
322
323Datum
335
336Datum
338{
341
342 if (a > b)
344 else if (a == b)
346 else
348}
349
350Datum
352{
355
356 if (a > b)
358 else if (a == b)
360 else
362}
363
364Datum
366{
369
370 if (a > b)
372 else if (a == b)
374 else
376}
377
378Datum
380{
383
384 if (a > b)
386 else if (a == b)
388 else
390}
391
392Datum
394{
397
398 if (a > b)
400 else if (a == b)
402 else
404}
405
406Datum
408{
411
412 if (a > b)
414 else if (a == b)
416 else
418}
419
420Datum
422{
423 Oid a = PG_GETARG_OID(0);
424 Oid b = PG_GETARG_OID(1);
425
426 if (a > b)
428 else if (a == b)
430 else
432}
433
434static int
436{
439
440 if (a > b)
441 return A_GREATER_THAN_B;
442 else if (a == b)
443 return 0;
444 else
445 return A_LESS_THAN_B;
446}
447
448Datum
456
457static Datum
459{
461
462 if (oexisting == InvalidOid)
463 {
464 /* return value is undefined */
465 *underflow = true;
466 return (Datum) 0;
467 }
468
469 *underflow = false;
470 return ObjectIdGetDatum(oexisting - 1);
471}
472
473static Datum
475{
477
478 if (oexisting == OID_MAX)
479 {
480 /* return value is undefined */
481 *overflow = true;
482 return (Datum) 0;
483 }
484
485 *overflow = false;
486 return ObjectIdGetDatum(oexisting + 1);
487}
488
489Datum
501
502Datum
504{
505 Oid8 a = PG_GETARG_OID8(0);
506 Oid8 b = PG_GETARG_OID8(1);
507
508 if (a > b)
510 else if (a == b)
512 else
514}
515
516static int
518{
521
522 if (a > b)
523 return A_GREATER_THAN_B;
524 else if (a == b)
525 return 0;
526 else
527 return A_LESS_THAN_B;
528}
529
530Datum
538
539static Datum
541{
543
544 if (oexisting == InvalidOid8)
545 {
546 /* return value is undefined */
547 *underflow = true;
548 return (Datum) 0;
549 }
550
551 *underflow = false;
552 return ObjectId8GetDatum(oexisting - 1);
553}
554
555static Datum
557{
559
560 if (oexisting == OID8_MAX)
561 {
562 /* return value is undefined */
563 *overflow = true;
564 return (Datum) 0;
565 }
566
567 *overflow = false;
568 return ObjectId8GetDatum(oexisting + 1);
569}
570
571Datum
583
584Datum
586{
589 int i;
590
593
594 /* We arbitrarily choose to sort first by vector length */
595 if (a->dim1 != b->dim1)
596 PG_RETURN_INT32(a->dim1 - b->dim1);
597
598 for (i = 0; i < a->dim1; i++)
599 {
600 if (a->values[i] != b->values[i])
601 {
602 if (a->values[i] > b->values[i])
604 else
606 }
607 }
609}
610
611Datum
613{
614 char a = PG_GETARG_CHAR(0);
615 char b = PG_GETARG_CHAR(1);
616
617 /* Be careful to compare chars as unsigned */
618 PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
619}
620
621static Datum
623{
625
626 if (cexisting == 0)
627 {
628 /* return value is undefined */
629 *underflow = true;
630 return (Datum) 0;
631 }
632
633 *underflow = false;
634 return CharGetDatum((uint8) cexisting - 1);
635}
636
637static Datum
639{
641
642 if (cexisting == UCHAR_MAX)
643 {
644 /* return value is undefined */
645 *overflow = true;
646 return (Datum) 0;
647 }
648
649 *overflow = false;
650 return CharGetDatum((uint8) cexisting + 1);
651}
652
653Datum
655{
657
658 sksup->decrement = char_decrement;
659 sksup->increment = char_increment;
660
661 /* btcharcmp compares chars as unsigned */
662 sksup->low_elem = UInt8GetDatum(0);
664
666}
uint64 Oid8
Definition c.h:686
#define PG_INT32_MAX
Definition c.h:603
uint8_t uint8
Definition c.h:544
#define InvalidOid8
Definition c.h:688
int64_t int64
Definition c.h:543
int16_t int16
Definition c.h:541
#define PG_INT16_MIN
Definition c.h:599
int32_t int32
Definition c.h:542
#define PG_INT64_MAX
Definition c.h:606
#define PG_INT64_MIN
Definition c.h:605
#define OID8_MAX
Definition c.h:689
#define PG_INT32_MIN
Definition c.h:602
#define PG_INT16_MAX
Definition c.h:600
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_GETARG_OID(n)
Definition fmgr.h:275
#define PG_GETARG_CHAR(n)
Definition fmgr.h:273
#define PG_GETARG_OID8(n)
Definition fmgr.h:276
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_GETARG_INT64(n)
Definition fmgr.h:284
#define PG_RETURN_INT32(x)
Definition fmgr.h:355
#define PG_GETARG_INT32(n)
Definition fmgr.h:269
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
#define PG_GETARG_INT16(n)
Definition fmgr.h:271
int y
Definition isn.c:76
int b
Definition isn.c:74
int x
Definition isn.c:75
int a
Definition isn.c:73
int i
Definition isn.c:77
Datum btoidvectorcmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:585
Datum btint4cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:201
static Datum char_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:622
Datum btint4skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:256
static Datum int8_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:292
Datum btboolcmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:75
static Datum bool_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:100
static Datum int2_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:156
#define A_GREATER_THAN_B
Definition nbtcompare.c:70
Datum btint2cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:129
Datum btoid8sortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:531
Datum btint24cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:365
static Datum int4_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:240
static Datum int4_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:224
Datum btoid8cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:503
static Datum oid_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:474
Datum btoidcmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:421
Datum btoidskipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:490
static Datum bool_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:84
Datum btint2skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:188
Datum btoid8skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:572
static Datum oid_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:458
static Datum oid8_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:556
static int btint2fastcmp(Datum x, Datum y, SortSupport ssup)
Definition nbtcompare.c:138
Datum btint84cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:351
Datum btoidsortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:449
static int btoid8fastcmp(Datum x, Datum y, SortSupport ssup)
Definition nbtcompare.c:517
Datum btcharcmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:612
#define A_LESS_THAN_B
Definition nbtcompare.c:69
Datum btboolskipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:116
static int btoidfastcmp(Datum x, Datum y, SortSupport ssup)
Definition nbtcompare.c:435
Datum btint8sortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:283
Datum btint82cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:407
static Datum int8_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:308
Datum btint8skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:324
Datum btint48cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:337
static Datum int2_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:172
static Datum char_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:638
Datum btcharskipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:654
Datum btint8cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:269
Datum btint4sortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:215
Datum btint42cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:379
Datum btint28cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:393
Datum btint2sortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:147
static Datum oid8_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:540
void check_valid_oidvector(const oidvector *oidArray)
Definition oid.c:118
static Datum Int64GetDatum(int64 X)
Definition postgres.h:423
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static int64 DatumGetInt64(Datum X)
Definition postgres.h:413
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:252
static Datum Int16GetDatum(int16 X)
Definition postgres.h:182
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:262
static Datum ObjectId8GetDatum(Oid8 X)
Definition postgres.h:282
uint64_t Datum
Definition postgres.h:70
static uint8 DatumGetUInt8(Datum X)
Definition postgres.h:152
static Datum UInt8GetDatum(uint8 X)
Definition postgres.h:162
static Datum Int32GetDatum(int32 X)
Definition postgres.h:222
static int16 DatumGetInt16(Datum X)
Definition postgres.h:172
static int32 DatumGetInt32(Datum X)
Definition postgres.h:212
static Datum CharGetDatum(char X)
Definition postgres.h:132
static Oid8 DatumGetObjectId8(Datum X)
Definition postgres.h:272
#define InvalidOid
unsigned int Oid
#define OID_MAX
static int fb(int x)
struct SkipSupportData * SkipSupport
Definition skipsupport.h:50
struct SortSupportData * SortSupport
Definition sortsupport.h:58
SkipSupportIncDec decrement
Definition skipsupport.h:91
SkipSupportIncDec increment
Definition skipsupport.h:92
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition c.h:745
int ssup_datum_signed_cmp(Datum x, Datum y, SortSupport ssup)
Definition tuplesort.c:3133
int ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup)
Definition tuplesort.c:3147