diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-03 19:00:37 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2001-05-03 19:00:37 +0000 |
commit | 2792374cff361a7a4ec0e750b5fa935d85afc9ac (patch) | |
tree | 98736405bf8af30af89bdf224802f868057b7d2a /src/backend/access | |
parent | 77fe28f33e49d752be4e4a1bbc6c112f825e7882 (diff) | |
download | postgresql-2792374cff361a7a4ec0e750b5fa935d85afc9ac.tar.gz postgresql-2792374cff361a7a4ec0e750b5fa935d85afc9ac.zip |
Ensure that btree sort ordering functions and boolean comparison operators
give consistent results for all datatypes. Types float4, float8, and
numeric were broken for NaN values; abstime, timestamp, and interval
were broken for INVALID values; timetz was just plain broken (some
possible pairs of values were neither < nor = nor >). Also clean up
text, bpchar, varchar, and bit/varbit to eliminate duplicate code and
thereby reduce the probability of similar inconsistencies arising in
the future.
Diffstat (limited to 'src/backend/access')
-rw-r--r-- | src/backend/access/nbtree/nbtcompare.c | 138 |
1 files changed, 16 insertions, 122 deletions
diff --git a/src/backend/access/nbtree/nbtcompare.c b/src/backend/access/nbtree/nbtcompare.c index fc85906d9b2..b1affe20188 100644 --- a/src/backend/access/nbtree/nbtcompare.c +++ b/src/backend/access/nbtree/nbtcompare.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.41 2001/03/22 03:59:14 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtcompare.c,v 1.42 2001/05/03 19:00:36 tgl Exp $ * * NOTES * @@ -25,7 +25,20 @@ * NOTE: although any negative int32 is acceptable for reporting "<", * and any positive int32 is acceptable for reporting ">", routines * that work on 32-bit or wider datatypes can't just return "a - b". - * That could overflow and give the wrong answer. + * That could overflow and give the wrong answer. Also, one should not + * return INT_MIN to report "<", since some callers will negate the result. + * + * NOTE: it is critical that the comparison function impose a total order + * on all non-NULL values of the data type, and that the datatype's + * boolean comparison operators (= < >= etc) yield results consistent + * with the comparison routine. Otherwise bad behavior may ensue. + * (For example, the comparison operators must NOT punt when faced with + * NAN or other funny values; you must devise some collation sequence for + * all such values.) If the datatype is not trivial, this is most + * reliably done by having the boolean operators invoke the same + * three-way comparison code that the btree function does. Therefore, + * this file contains only btree support for "trivial" datatypes --- + * all others are in the /utils/adt/ files that implement their datatypes. * * NOTE: these routines must not leak memory, since memory allocated * during an index access won't be recovered till end of query. This @@ -33,12 +46,11 @@ * they have to be careful to free any detoasted copy of an input datum. *------------------------------------------------------------------------- */ - #include "postgres.h" -#include "utils/nabstime.h" #include "utils/builtins.h" + Datum btboolcmp(PG_FUNCTION_ARGS) { @@ -86,34 +98,6 @@ btint8cmp(PG_FUNCTION_ARGS) } Datum -btfloat4cmp(PG_FUNCTION_ARGS) -{ - float4 a = PG_GETARG_FLOAT4(0); - float4 b = PG_GETARG_FLOAT4(1); - - if (a > b) - PG_RETURN_INT32(1); - else if (a == b) - PG_RETURN_INT32(0); - else - PG_RETURN_INT32(-1); -} - -Datum -btfloat8cmp(PG_FUNCTION_ARGS) -{ - float8 a = PG_GETARG_FLOAT8(0); - float8 b = PG_GETARG_FLOAT8(1); - - if (a > b) - PG_RETURN_INT32(1); - else if (a == b) - PG_RETURN_INT32(0); - else - PG_RETURN_INT32(-1); -} - -Datum btoidcmp(PG_FUNCTION_ARGS) { Oid a = PG_GETARG_OID(0); @@ -148,20 +132,6 @@ btoidvectorcmp(PG_FUNCTION_ARGS) } Datum -btabstimecmp(PG_FUNCTION_ARGS) -{ - AbsoluteTime a = PG_GETARG_ABSOLUTETIME(0); - AbsoluteTime b = PG_GETARG_ABSOLUTETIME(1); - - if (AbsoluteTimeIsBefore(a, b)) - PG_RETURN_INT32(-1); - else if (AbsoluteTimeIsBefore(b, a)) - PG_RETURN_INT32(1); - else - PG_RETURN_INT32(0); -} - -Datum btcharcmp(PG_FUNCTION_ARGS) { char a = PG_GETARG_CHAR(0); @@ -179,79 +149,3 @@ btnamecmp(PG_FUNCTION_ARGS) PG_RETURN_INT32(strncmp(NameStr(*a), NameStr(*b), NAMEDATALEN)); } - -Datum -bttextcmp(PG_FUNCTION_ARGS) -{ - text *a = PG_GETARG_TEXT_P(0); - text *b = PG_GETARG_TEXT_P(1); - int res; - unsigned char *ap, - *bp; - -#ifdef USE_LOCALE - int la = VARSIZE(a) - VARHDRSZ; - int lb = VARSIZE(b) - VARHDRSZ; - - ap = (unsigned char *) palloc(la + 1); - bp = (unsigned char *) palloc(lb + 1); - - memcpy(ap, VARDATA(a), la); - *(ap + la) = '\0'; - memcpy(bp, VARDATA(b), lb); - *(bp + lb) = '\0'; - - res = strcoll(ap, bp); - - pfree(ap); - pfree(bp); - -#else - int len = VARSIZE(a); - - /* len is the length of the shorter of the two strings */ - if (len > VARSIZE(b)) - len = VARSIZE(b); - - len -= VARHDRSZ; - - ap = (unsigned char *) VARDATA(a); - bp = (unsigned char *) VARDATA(b); - - /* - * If the two strings differ in the first len bytes, or if they're the - * same in the first len bytes and they're both len bytes long, we're - * done. - */ - - res = 0; - if (len > 0) - { - do - { - res = (int) *ap++ - (int) *bp++; - len--; - } while (res == 0 && len != 0); - } - - if (res == 0 && VARSIZE(a) != VARSIZE(b)) - { - - /* - * The two strings are the same in the first len bytes, and they - * are of different lengths. - */ - if (VARSIZE(a) < VARSIZE(b)) - res = -1; - else - res = 1; - } - -#endif - - /* Avoid leaking memory when handed toasted input. */ - PG_FREE_IF_COPY(a, 0); - PG_FREE_IF_COPY(b, 1); - - PG_RETURN_INT32(res); -} |