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
137Datum
145
146static Datum
148{
150
151 if (iexisting == PG_INT16_MIN)
152 {
153 /* return value is undefined */
154 *underflow = true;
155 return (Datum) 0;
156 }
157
158 *underflow = false;
159 return Int16GetDatum(iexisting - 1);
160}
161
162static Datum
164{
166
167 if (iexisting == PG_INT16_MAX)
168 {
169 /* return value is undefined */
170 *overflow = true;
171 return (Datum) 0;
172 }
173
174 *overflow = false;
175 return Int16GetDatum(iexisting + 1);
176}
177
178Datum
190
191Datum
193{
196
197 if (a > b)
199 else if (a == b)
201 else
203}
204
205Datum
213
214static Datum
216{
218
219 if (iexisting == PG_INT32_MIN)
220 {
221 /* return value is undefined */
222 *underflow = true;
223 return (Datum) 0;
224 }
225
226 *underflow = false;
227 return Int32GetDatum(iexisting - 1);
228}
229
230static Datum
232{
234
235 if (iexisting == PG_INT32_MAX)
236 {
237 /* return value is undefined */
238 *overflow = true;
239 return (Datum) 0;
240 }
241
242 *overflow = false;
243 return Int32GetDatum(iexisting + 1);
244}
245
246Datum
258
259Datum
261{
264
265 if (a > b)
267 else if (a == b)
269 else
271}
272
273Datum
281
282static Datum
284{
286
287 if (iexisting == PG_INT64_MIN)
288 {
289 /* return value is undefined */
290 *underflow = true;
291 return (Datum) 0;
292 }
293
294 *underflow = false;
295 return Int64GetDatum(iexisting - 1);
296}
297
298static Datum
300{
302
303 if (iexisting == PG_INT64_MAX)
304 {
305 /* return value is undefined */
306 *overflow = true;
307 return (Datum) 0;
308 }
309
310 *overflow = false;
311 return Int64GetDatum(iexisting + 1);
312}
313
314Datum
326
327Datum
329{
332
333 if (a > b)
335 else if (a == b)
337 else
339}
340
341Datum
343{
346
347 if (a > b)
349 else if (a == b)
351 else
353}
354
355Datum
357{
360
361 if (a > b)
363 else if (a == b)
365 else
367}
368
369Datum
371{
374
375 if (a > b)
377 else if (a == b)
379 else
381}
382
383Datum
385{
388
389 if (a > b)
391 else if (a == b)
393 else
395}
396
397Datum
399{
402
403 if (a > b)
405 else if (a == b)
407 else
409}
410
411Datum
413{
414 Oid a = PG_GETARG_OID(0);
415 Oid b = PG_GETARG_OID(1);
416
417 if (a > b)
419 else if (a == b)
421 else
423}
424
425Datum
433
434static Datum
436{
438
439 if (oexisting == InvalidOid)
440 {
441 /* return value is undefined */
442 *underflow = true;
443 return (Datum) 0;
444 }
445
446 *underflow = false;
447 return ObjectIdGetDatum(oexisting - 1);
448}
449
450static Datum
452{
454
455 if (oexisting == OID_MAX)
456 {
457 /* return value is undefined */
458 *overflow = true;
459 return (Datum) 0;
460 }
461
462 *overflow = false;
463 return ObjectIdGetDatum(oexisting + 1);
464}
465
466Datum
478
479Datum
481{
482 Oid8 a = PG_GETARG_OID8(0);
483 Oid8 b = PG_GETARG_OID8(1);
484
485 if (a > b)
487 else if (a == b)
489 else
491}
492
493Datum
501
502static Datum
504{
506
507 if (oexisting == InvalidOid8)
508 {
509 /* return value is undefined */
510 *underflow = true;
511 return (Datum) 0;
512 }
513
514 *underflow = false;
515 return ObjectId8GetDatum(oexisting - 1);
516}
517
518static Datum
520{
522
523 if (oexisting == OID8_MAX)
524 {
525 /* return value is undefined */
526 *overflow = true;
527 return (Datum) 0;
528 }
529
530 *overflow = false;
531 return ObjectId8GetDatum(oexisting + 1);
532}
533
534Datum
546
547Datum
549{
552 int i;
553
556
557 /* We arbitrarily choose to sort first by vector length */
558 if (a->dim1 != b->dim1)
559 PG_RETURN_INT32(a->dim1 - b->dim1);
560
561 for (i = 0; i < a->dim1; i++)
562 {
563 if (a->values[i] != b->values[i])
564 {
565 if (a->values[i] > b->values[i])
567 else
569 }
570 }
572}
573
574Datum
576{
577 char a = PG_GETARG_CHAR(0);
578 char b = PG_GETARG_CHAR(1);
579
580 /* Be careful to compare chars as unsigned */
581 PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
582}
583
584static Datum
586{
588
589 if (cexisting == 0)
590 {
591 /* return value is undefined */
592 *underflow = true;
593 return (Datum) 0;
594 }
595
596 *underflow = false;
597 return CharGetDatum((uint8) cexisting - 1);
598}
599
600static Datum
602{
604
605 if (cexisting == UCHAR_MAX)
606 {
607 /* return value is undefined */
608 *overflow = true;
609 return (Datum) 0;
610 }
611
612 *overflow = false;
613 return CharGetDatum((uint8) cexisting + 1);
614}
615
616Datum
618{
620
621 sksup->decrement = char_decrement;
622 sksup->increment = char_increment;
623
624 /* btcharcmp compares chars as unsigned */
625 sksup->low_elem = UInt8GetDatum(0);
627
629}
uint64 Oid8
Definition c.h:815
#define PG_INT32_MAX
Definition c.h:732
uint8_t uint8
Definition c.h:681
#define InvalidOid8
Definition c.h:817
int64_t int64
Definition c.h:680
int16_t int16
Definition c.h:678
#define PG_INT16_MIN
Definition c.h:728
int32_t int32
Definition c.h:679
#define PG_INT64_MAX
Definition c.h:735
#define PG_INT64_MIN
Definition c.h:734
#define OID8_MAX
Definition c.h:818
#define PG_INT32_MIN
Definition c.h:731
#define PG_INT16_MAX
Definition c.h:729
struct SortSupportData * SortSupport
Definition execnodes.h:61
#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 b
Definition isn.c:74
int a
Definition isn.c:73
int i
Definition isn.c:77
Datum btoidvectorcmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:548
Datum btint4cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:192
static Datum char_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:585
Datum btint4skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:247
static Datum int8_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:283
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:147
#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:494
Datum btint24cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:356
static Datum int4_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:231
static Datum int4_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:215
Datum btoid8cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:480
static Datum oid_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:451
Datum btoidcmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:412
Datum btoidskipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:467
static Datum bool_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:84
Datum btint2skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:179
Datum btoid8skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:535
static Datum oid_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:435
static Datum oid8_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:519
Datum btint84cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:342
Datum btoidsortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:426
Datum btcharcmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:575
#define A_LESS_THAN_B
Definition nbtcompare.c:69
Datum btboolskipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:116
Datum btint8sortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:274
Datum btint82cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:398
static Datum int8_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:299
Datum btint8skipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:315
Datum btint48cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:328
static Datum int2_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:163
static Datum char_increment(Relation rel, Datum existing, bool *overflow)
Definition nbtcompare.c:601
Datum btcharskipsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:617
Datum btint8cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:260
Datum btint4sortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:206
Datum btint42cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:370
Datum btint28cmp(PG_FUNCTION_ARGS)
Definition nbtcompare.c:384
Datum btint2sortsupport(PG_FUNCTION_ARGS)
Definition nbtcompare.c:138
static Datum oid8_decrement(Relation rel, Datum existing, bool *underflow)
Definition nbtcompare.c:503
void check_valid_oidvector(const oidvector *oidArray)
Definition oid.c:118
static Datum Int64GetDatum(int64 X)
Definition postgres.h:426
static bool DatumGetBool(Datum X)
Definition postgres.h:100
static int64 DatumGetInt64(Datum X)
Definition postgres.h:416
static Oid DatumGetObjectId(Datum X)
Definition postgres.h:242
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum BoolGetDatum(bool X)
Definition postgres.h:112
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
static Datum ObjectId8GetDatum(Oid8 X)
Definition postgres.h:272
uint64_t Datum
Definition postgres.h:70
static uint8 DatumGetUInt8(Datum X)
Definition postgres.h:142
static Datum UInt8GetDatum(uint8 X)
Definition postgres.h:152
static Datum Int32GetDatum(int32 X)
Definition postgres.h:212
static int16 DatumGetInt16(Datum X)
Definition postgres.h:162
static int32 DatumGetInt32(Datum X)
Definition postgres.h:202
static Datum CharGetDatum(char X)
Definition postgres.h:132
static Oid8 DatumGetObjectId8(Datum X)
Definition postgres.h:262
#define InvalidOid
unsigned int Oid
#define OID_MAX
static int fb(int x)
struct SkipSupportData * SkipSupport
Definition skipsupport.h:50
SkipSupportIncDec decrement
Definition skipsupport.h:91
SkipSupportIncDec increment
Definition skipsupport.h:92
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition c.h:874
int ssup_datum_signed_cmp(Datum x, Datum y, SortSupport ssup)
Definition tuplesort.c:3461
int ssup_datum_unsigned_cmp(Datum x, Datum y, SortSupport ssup)
Definition tuplesort.c:3450
int ssup_datum_int32_cmp(Datum x, Datum y, SortSupport ssup)
Definition tuplesort.c:3475