*
*
* 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
*
* 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
* 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)
{
PG_RETURN_INT32(-1);
}
-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)
{
PG_RETURN_INT32(0);
}
-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)
{
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);
-}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.56 2001/03/22 03:59:49 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/date.c,v 1.57 2001/05/03 19:00:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
+static int
+timetz_cmp_internal(TimeTzADT *time1, TimeTzADT *time2)
+{
+ double t1,
+ t2;
+
+ /* Primary sort is by true (GMT-equivalent) time */
+ t1 = time1->time + time1->zone;
+ t2 = time2->time + time2->zone;
+
+ if (t1 > t2)
+ return 1;
+ if (t1 < t2)
+ return -1;
+
+ /*
+ * If same GMT time, sort by timezone; we only want to say that two
+ * timetz's are equal if both the time and zone parts are equal.
+ */
+ return time1->zone - time2->zone;
+}
+
Datum
timetz_eq(PG_FUNCTION_ARGS)
{
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
- PG_RETURN_BOOL(((time1->time + time1->zone) == (time2->time + time2->zone)));
+ PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) == 0);
}
Datum
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
- PG_RETURN_BOOL(((time1->time + time1->zone) != (time2->time + time2->zone)));
+ PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) != 0);
}
Datum
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
- PG_RETURN_BOOL(((time1->time + time1->zone) < (time2->time + time2->zone)));
+ PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) < 0);
}
Datum
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
- PG_RETURN_BOOL(((time1->time + time1->zone) <= (time2->time + time2->zone)));
+ PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) <= 0);
}
Datum
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
- PG_RETURN_BOOL(((time1->time + time1->zone) > (time2->time + time2->zone)));
+ PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) > 0);
}
Datum
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
- PG_RETURN_BOOL(((time1->time + time1->zone) >= (time2->time + time2->zone)));
+ PG_RETURN_BOOL(timetz_cmp_internal(time1, time2) >= 0);
}
Datum
TimeTzADT *time1 = PG_GETARG_TIMETZADT_P(0);
TimeTzADT *time2 = PG_GETARG_TIMETZADT_P(1);
- if (DatumGetBool(DirectFunctionCall2(timetz_lt,
- TimeTzADTPGetDatum(time1),
- TimeTzADTPGetDatum(time2))))
- PG_RETURN_INT32(-1);
- if (DatumGetBool(DirectFunctionCall2(timetz_gt,
- TimeTzADTPGetDatum(time1),
- TimeTzADTPGetDatum(time2))))
- PG_RETURN_INT32(1);
- PG_RETURN_INT32(0);
+ PG_RETURN_INT32(timetz_cmp_internal(time1, time2));
}
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.70 2001/03/22 03:59:50 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.71 2001/05/03 19:00:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-/*
+/*----------
* OLD COMMENTS
* Basic float4 ops:
* float4in, float4out, float4abs, float4um
* float4pl, float4mi, float4mul, float4div
* float8pl, float8mi, float8mul, float8div
* Comparison operators:
- * float4eq, float4ne, float4lt, float4le, float4gt, float4ge
- * float8eq, float8ne, float8lt, float8le, float8gt, float8ge
+ * float4eq, float4ne, float4lt, float4le, float4gt, float4ge, float4cmp
+ * float8eq, float8ne, float8lt, float8le, float8gt, float8ge, float8cmp
* Conversion routines:
* ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2
*
* float84eq, float84ne, float84lt, float84le, float84gt, float84ge
*
* (You can do the arithmetic and comparison stuff using conversion
- * routines, but then you pay the overhead of converting...)
+ * routines, but then you pay the overhead of invoking a separate
+ * conversion function...)
*
* XXX GLUESOME STUFF. FIX IT! -AY '94
*
* a bit of the existing code. Need to change the error checking
* for calls to pow(), exp() since on some machines (my Linux box
* included) these routines do not set errno. - tgl 97/05/10
+ *----------
*/
+#include "postgres.h"
+
#include <ctype.h>
#include <errno.h>
#include <float.h> /* faked on sunos4 */
#include <math.h>
-#include "postgres.h"
-
#include <limits.h>
/* for finite() on Solaris */
#ifdef HAVE_IEEEFP_H
val = strtod(num, &endptr);
if (*endptr != '\0')
{
- /* Should we accept "NaN" or "Infinity" for float4? */
+ /* Shouldn't we accept "NaN" or "Infinity" for float4? */
elog(ERROR, "Bad float4 input format '%s'", num);
}
else
float4 num = PG_GETARG_FLOAT4(0);
char *ascii = (char *) palloc(MAXFLOATWIDTH + 1);
+ if (isnan(num))
+ PG_RETURN_CSTRING(strcpy(ascii, "NaN"));
+ if (isinf(num))
+ PG_RETURN_CSTRING(strcpy(ascii, "Infinity"));
+
sprintf(ascii, "%.*g", FLT_DIG, num);
PG_RETURN_CSTRING(ascii);
}
/*
* float4{eq,ne,lt,le,gt,ge} - float4/float4 comparison operations
*/
+static int
+float4_cmp_internal(float4 a, float4 b)
+{
+ /*
+ * We consider all NANs to be equal and larger than any non-NAN.
+ * This is somewhat arbitrary; the important thing is to have a
+ * consistent sort order.
+ */
+ if (isnan(a))
+ {
+ if (isnan(b))
+ return 0; /* NAN = NAN */
+ else
+ return 1; /* NAN > non-NAN */
+ }
+ else if (isnan(b))
+ {
+ return -1; /* non-NAN < NAN */
+ }
+ else
+ {
+ if (a > b)
+ return 1;
+ else if (a == b)
+ return 0;
+ else
+ return -1;
+ }
+}
+
Datum
float4eq(PG_FUNCTION_ARGS)
{
float4 arg1 = PG_GETARG_FLOAT4(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 == arg2);
+ PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) == 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 != arg2);
+ PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) != 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 < arg2);
+ PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) < 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 <= arg2);
+ PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) <= 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 > arg2);
+ PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) > 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 >= arg2);
+ PG_RETURN_BOOL(float4_cmp_internal(arg1, arg2) >= 0);
+}
+
+Datum
+btfloat4cmp(PG_FUNCTION_ARGS)
+{
+ float4 arg1 = PG_GETARG_FLOAT4(0);
+ float4 arg2 = PG_GETARG_FLOAT4(1);
+
+ PG_RETURN_INT32(float4_cmp_internal(arg1, arg2));
}
/*
* float8{eq,ne,lt,le,gt,ge} - float8/float8 comparison operations
*/
+static int
+float8_cmp_internal(float8 a, float8 b)
+{
+ /*
+ * We consider all NANs to be equal and larger than any non-NAN.
+ * This is somewhat arbitrary; the important thing is to have a
+ * consistent sort order.
+ */
+ if (isnan(a))
+ {
+ if (isnan(b))
+ return 0; /* NAN = NAN */
+ else
+ return 1; /* NAN > non-NAN */
+ }
+ else if (isnan(b))
+ {
+ return -1; /* non-NAN < NAN */
+ }
+ else
+ {
+ if (a > b)
+ return 1;
+ else if (a == b)
+ return 0;
+ else
+ return -1;
+ }
+}
+
Datum
float8eq(PG_FUNCTION_ARGS)
{
float8 arg1 = PG_GETARG_FLOAT8(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 == arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 != arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 < arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 <= arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 > arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 >= arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
+}
+
+Datum
+btfloat8cmp(PG_FUNCTION_ARGS)
+{
+ float8 arg1 = PG_GETARG_FLOAT8(0);
+ float8 arg2 = PG_GETARG_FLOAT8(1);
+
+ PG_RETURN_INT32(float8_cmp_internal(arg1, arg2));
}
float4 arg1 = PG_GETARG_FLOAT4(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 == arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 != arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 < arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 <= arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 > arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
}
Datum
float4 arg1 = PG_GETARG_FLOAT4(0);
float8 arg2 = PG_GETARG_FLOAT8(1);
- PG_RETURN_BOOL(arg1 >= arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
}
/*
float8 arg1 = PG_GETARG_FLOAT8(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 == arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) == 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 != arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) != 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 < arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) < 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 <= arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) <= 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 > arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) > 0);
}
Datum
float8 arg1 = PG_GETARG_FLOAT8(0);
float4 arg2 = PG_GETARG_FLOAT4(1);
- PG_RETURN_BOOL(arg1 >= arg2);
+ PG_RETURN_BOOL(float8_cmp_internal(arg1, arg2) >= 0);
}
/* ========== PRIVATE ROUTINES ========== */
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.84 2001/04/26 21:52:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.85 2001/05/03 19:00:36 tgl Exp $
*
* NOTES
*
}
-/*
- * AbsoluteTimeIsBefore -- true iff time1 is before time2.
- * AbsoluteTimeIsAfter -- true iff time1 is after time2.
- */
-bool
-AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2)
-{
- if (time1 == CURRENT_ABSTIME)
- time1 = GetCurrentTransactionStartTime();
-
- if (time2 == CURRENT_ABSTIME)
- time2 = GetCurrentTransactionStartTime();
-
- return time1 < time2;
-}
-
-#ifdef NOT_USED
-bool
-AbsoluteTimeIsAfter(AbsoluteTime time1, AbsoluteTime time2)
-{
- if (time1 == CURRENT_ABSTIME)
- time1 = GetCurrentTransactionStartTime();
-
- if (time2 == CURRENT_ABSTIME)
- time2 = GetCurrentTransactionStartTime();
-
- return time1 > time2;
-}
-
-#endif
-
/* abstime_finite()
*/
Datum
/*
- * abstimeeq - returns true iff arguments are equal
- * abstimene - returns true iff arguments are not equal
- * abstimelt - returns true iff t1 less than t2
- * abstimegt - returns true iff t1 greater than t2
- * abstimele - returns true iff t1 less than or equal to t2
- * abstimege - returns true iff t1 greater than or equal to t2
+ * abstime comparison routines
*/
+static int
+abstime_cmp_internal(AbsoluteTime a, AbsoluteTime b)
+{
+ /*
+ * We consider all INVALIDs to be equal and larger than any non-INVALID.
+ * This is somewhat arbitrary; the important thing is to have a
+ * consistent sort order.
+ */
+ if (a == INVALID_ABSTIME)
+ {
+ if (b == INVALID_ABSTIME)
+ return 0; /* INVALID = INVALID */
+ else
+ return 1; /* INVALID > non-INVALID */
+ }
+ else if (b == INVALID_ABSTIME)
+ {
+ return -1; /* non-INVALID < INVALID */
+ }
+ else
+ {
+ /* XXX this is broken, should go away: */
+ if (a == CURRENT_ABSTIME)
+ a = GetCurrentTransactionStartTime();
+ if (b == CURRENT_ABSTIME)
+ b = GetCurrentTransactionStartTime();
+
+ if (a > b)
+ return 1;
+ else if (a == b)
+ return 0;
+ else
+ return -1;
+ }
+}
+
Datum
abstimeeq(PG_FUNCTION_ARGS)
{
AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- PG_RETURN_BOOL(false);
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
-
- PG_RETURN_BOOL(t1 == t2);
+ PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) == 0);
}
Datum
AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- PG_RETURN_BOOL(false);
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
-
- PG_RETURN_BOOL(t1 != t2);
+ PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) != 0);
}
Datum
AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- PG_RETURN_BOOL(false);
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
-
- PG_RETURN_BOOL(t1 < t2);
+ PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) < 0);
}
Datum
AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- PG_RETURN_BOOL(false);
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
-
- PG_RETURN_BOOL(t1 > t2);
+ PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) > 0);
}
Datum
AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- PG_RETURN_BOOL(false);
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
-
- PG_RETURN_BOOL(t1 <= t2);
+ PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) <= 0);
}
Datum
AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);
- if (t1 == INVALID_ABSTIME || t2 == INVALID_ABSTIME)
- PG_RETURN_BOOL(false);
- if (t1 == CURRENT_ABSTIME)
- t1 = GetCurrentTransactionStartTime();
- if (t2 == CURRENT_ABSTIME)
- t2 = GetCurrentTransactionStartTime();
+ PG_RETURN_BOOL(abstime_cmp_internal(t1, t2) >= 0);
+}
- PG_RETURN_BOOL(t1 >= t2);
+Datum
+btabstimecmp(PG_FUNCTION_ARGS)
+{
+ AbsoluteTime t1 = PG_GETARG_ABSOLUTETIME(0);
+ AbsoluteTime t2 = PG_GETARG_ABSOLUTETIME(1);
+
+ PG_RETURN_INT32(abstime_cmp_internal(t1, t2));
}
*
* 1998 Jan Wieck
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.40 2001/04/14 02:10:57 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/numeric.c,v 1.41 2001/05/03 19:00:36 tgl Exp $
*
* ----------
*/
static void apply_typmod(NumericVar *var, int32 typmod);
+static int cmp_numerics(Numeric num1, Numeric num2);
static int cmp_var(NumericVar *var1, NumericVar *var2);
static void add_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
static void sub_var(NumericVar *var1, NumericVar *var2, NumericVar *result);
Numeric num2 = PG_GETARG_NUMERIC(1);
int result;
- if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
- result = 0;
- else
- {
- NumericVar arg1;
- NumericVar arg2;
-
- init_var(&arg1);
- init_var(&arg2);
-
- set_var_from_num(num1, &arg1);
- set_var_from_num(num2, &arg2);
-
- result = cmp_var(&arg1, &arg2);
-
- free_var(&arg1);
- free_var(&arg2);
- }
+ result = cmp_numerics(num1, num2);
PG_FREE_IF_COPY(num1, 0);
PG_FREE_IF_COPY(num2, 1);
Numeric num2 = PG_GETARG_NUMERIC(1);
bool result;
- if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
- result = false;
- else
- {
- NumericVar arg1;
- NumericVar arg2;
-
- init_var(&arg1);
- init_var(&arg2);
-
- set_var_from_num(num1, &arg1);
- set_var_from_num(num2, &arg2);
-
- result = cmp_var(&arg1, &arg2) == 0;
-
- free_var(&arg1);
- free_var(&arg2);
- }
+ result = cmp_numerics(num1, num2) == 0;
PG_FREE_IF_COPY(num1, 0);
PG_FREE_IF_COPY(num2, 1);
Numeric num2 = PG_GETARG_NUMERIC(1);
bool result;
- if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
- result = false;
- else
- {
- NumericVar arg1;
- NumericVar arg2;
-
- init_var(&arg1);
- init_var(&arg2);
-
- set_var_from_num(num1, &arg1);
- set_var_from_num(num2, &arg2);
-
- result = cmp_var(&arg1, &arg2) != 0;
-
- free_var(&arg1);
- free_var(&arg2);
- }
+ result = cmp_numerics(num1, num2) != 0;
PG_FREE_IF_COPY(num1, 0);
PG_FREE_IF_COPY(num2, 1);
Numeric num2 = PG_GETARG_NUMERIC(1);
bool result;
- if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
- result = false;
- else
- {
- NumericVar arg1;
- NumericVar arg2;
-
- init_var(&arg1);
- init_var(&arg2);
-
- set_var_from_num(num1, &arg1);
- set_var_from_num(num2, &arg2);
-
- result = cmp_var(&arg1, &arg2) > 0;
-
- free_var(&arg1);
- free_var(&arg2);
- }
+ result = cmp_numerics(num1, num2) > 0;
PG_FREE_IF_COPY(num1, 0);
PG_FREE_IF_COPY(num2, 1);
Numeric num2 = PG_GETARG_NUMERIC(1);
bool result;
- if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
- result = false;
- else
- {
- NumericVar arg1;
- NumericVar arg2;
-
- init_var(&arg1);
- init_var(&arg2);
-
- set_var_from_num(num1, &arg1);
- set_var_from_num(num2, &arg2);
-
- result = cmp_var(&arg1, &arg2) >= 0;
-
- free_var(&arg1);
- free_var(&arg2);
- }
+ result = cmp_numerics(num1, num2) >= 0;
PG_FREE_IF_COPY(num1, 0);
PG_FREE_IF_COPY(num2, 1);
Numeric num2 = PG_GETARG_NUMERIC(1);
bool result;
- if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
- result = false;
- else
- {
- NumericVar arg1;
- NumericVar arg2;
-
- init_var(&arg1);
- init_var(&arg2);
-
- set_var_from_num(num1, &arg1);
- set_var_from_num(num2, &arg2);
-
- result = cmp_var(&arg1, &arg2) < 0;
-
- free_var(&arg1);
- free_var(&arg2);
- }
+ result = cmp_numerics(num1, num2) < 0;
PG_FREE_IF_COPY(num1, 0);
PG_FREE_IF_COPY(num2, 1);
Numeric num2 = PG_GETARG_NUMERIC(1);
bool result;
- if (NUMERIC_IS_NAN(num1) || NUMERIC_IS_NAN(num2))
- result = false;
+ result = cmp_numerics(num1, num2) <= 0;
+
+ PG_FREE_IF_COPY(num1, 0);
+ PG_FREE_IF_COPY(num2, 1);
+
+ PG_RETURN_BOOL(result);
+}
+
+static int
+cmp_numerics(Numeric num1, Numeric num2)
+{
+ int result;
+
+ /*
+ * We consider all NANs to be equal and larger than any non-NAN.
+ * This is somewhat arbitrary; the important thing is to have a
+ * consistent sort order.
+ */
+ if (NUMERIC_IS_NAN(num1))
+ {
+ if (NUMERIC_IS_NAN(num2))
+ result = 0; /* NAN = NAN */
+ else
+ result = 1; /* NAN > non-NAN */
+ }
+ else if (NUMERIC_IS_NAN(num2))
+ {
+ result = -1; /* non-NAN < NAN */
+ }
else
{
NumericVar arg1;
set_var_from_num(num1, &arg1);
set_var_from_num(num2, &arg2);
- result = cmp_var(&arg1, &arg2) <= 0;
+ result = cmp_var(&arg1, &arg2);
free_var(&arg1);
free_var(&arg2);
}
- PG_FREE_IF_COPY(num1, 0);
- PG_FREE_IF_COPY(num2, 1);
-
- PG_RETURN_BOOL(result);
+ return result;
}
char *str;
Datum result;
+ /* XXX would it be better to return NULL? */
if (NUMERIC_IS_NAN(num))
elog(ERROR, "Cannot convert NaN to int2");
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.47 2001/04/03 18:05:53 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/timestamp.c,v 1.48 2001/05/03 19:00:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/*
* timestamp_relop - is timestamp1 relop timestamp2
+ *
+ * collate invalid timestamp at the end
*/
+static int
+timestamp_cmp_internal(Timestamp dt1, Timestamp dt2)
+{
+ if (TIMESTAMP_IS_INVALID(dt1))
+ return (TIMESTAMP_IS_INVALID(dt2) ? 0 : 1);
+ else if (TIMESTAMP_IS_INVALID(dt2))
+ return -1;
+ else
+ {
+ if (TIMESTAMP_IS_RELATIVE(dt1))
+ dt1 = SetTimestamp(dt1);
+ if (TIMESTAMP_IS_RELATIVE(dt2))
+ dt2 = SetTimestamp(dt2);
+
+ return ((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));
+ }
+}
+
Datum
timestamp_eq(PG_FUNCTION_ARGS)
{
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
- if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
- PG_RETURN_BOOL(false);
-
- if (TIMESTAMP_IS_RELATIVE(dt1))
- dt1 = SetTimestamp(dt1);
- if (TIMESTAMP_IS_RELATIVE(dt2))
- dt2 = SetTimestamp(dt2);
-
- PG_RETURN_BOOL(dt1 == dt2);
+ PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) == 0);
}
Datum
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
- if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
- PG_RETURN_BOOL(false);
-
- if (TIMESTAMP_IS_RELATIVE(dt1))
- dt1 = SetTimestamp(dt1);
- if (TIMESTAMP_IS_RELATIVE(dt2))
- dt2 = SetTimestamp(dt2);
-
- PG_RETURN_BOOL(dt1 != dt2);
+ PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) != 0);
}
Datum
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
- if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
- PG_RETURN_BOOL(false);
-
- if (TIMESTAMP_IS_RELATIVE(dt1))
- dt1 = SetTimestamp(dt1);
- if (TIMESTAMP_IS_RELATIVE(dt2))
- dt2 = SetTimestamp(dt2);
-
- PG_RETURN_BOOL(dt1 < dt2);
+ PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) < 0);
}
Datum
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
- if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
- PG_RETURN_BOOL(false);
-
- if (TIMESTAMP_IS_RELATIVE(dt1))
- dt1 = SetTimestamp(dt1);
- if (TIMESTAMP_IS_RELATIVE(dt2))
- dt2 = SetTimestamp(dt2);
-
- PG_RETURN_BOOL(dt1 > dt2);
+ PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) > 0);
}
Datum
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
- if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
- PG_RETURN_BOOL(false);
-
- if (TIMESTAMP_IS_RELATIVE(dt1))
- dt1 = SetTimestamp(dt1);
- if (TIMESTAMP_IS_RELATIVE(dt2))
- dt2 = SetTimestamp(dt2);
-
- PG_RETURN_BOOL(dt1 <= dt2);
+ PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) <= 0);
}
Datum
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
- if (TIMESTAMP_IS_INVALID(dt1) || TIMESTAMP_IS_INVALID(dt2))
- PG_RETURN_BOOL(false);
-
- if (TIMESTAMP_IS_RELATIVE(dt1))
- dt1 = SetTimestamp(dt1);
- if (TIMESTAMP_IS_RELATIVE(dt2))
- dt2 = SetTimestamp(dt2);
-
- PG_RETURN_BOOL(dt1 >= dt2);
+ PG_RETURN_BOOL(timestamp_cmp_internal(dt1, dt2) >= 0);
}
-
-/* timestamp_cmp - 3-state comparison for timestamp
- * collate invalid timestamp at the end
- */
Datum
timestamp_cmp(PG_FUNCTION_ARGS)
{
Timestamp dt1 = PG_GETARG_TIMESTAMP(0);
Timestamp dt2 = PG_GETARG_TIMESTAMP(1);
- if (TIMESTAMP_IS_INVALID(dt1))
- PG_RETURN_INT32(TIMESTAMP_IS_INVALID(dt2) ? 0 : 1);
- else if (TIMESTAMP_IS_INVALID(dt2))
- PG_RETURN_INT32(-1);
- else
- {
- if (TIMESTAMP_IS_RELATIVE(dt1))
- dt1 = SetTimestamp(dt1);
- if (TIMESTAMP_IS_RELATIVE(dt2))
- dt2 = SetTimestamp(dt2);
- }
-
- PG_RETURN_INT32((dt1 < dt2) ? -1 : ((dt1 > dt2) ? 1 : 0));
+ PG_RETURN_INT32(timestamp_cmp_internal(dt1, dt2));
}
/*
* interval_relop - is interval1 relop interval2
+ *
+ * collate invalid interval at the end
*/
+static int
+interval_cmp_internal(Interval *interval1, Interval *interval2)
+{
+ if (INTERVAL_IS_INVALID(*interval1))
+ return (INTERVAL_IS_INVALID(*interval2) ? 0 : 1);
+ else if (INTERVAL_IS_INVALID(*interval2))
+ return -1;
+ else
+ {
+ double span1,
+ span2;
+
+ span1 = interval1->time;
+ if (interval1->month != 0)
+ span1 += (interval1->month * (30.0 * 86400));
+ span2 = interval2->time;
+ if (interval2->month != 0)
+ span2 += (interval2->month * (30.0 * 86400));
+
+ return ((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0);
+ }
+}
+
Datum
interval_eq(PG_FUNCTION_ARGS)
{
Interval *interval1 = PG_GETARG_INTERVAL_P(0);
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
- if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
- PG_RETURN_BOOL(false);
-
- PG_RETURN_BOOL((interval1->time == interval2->time) &&
- (interval1->month == interval2->month));
+ PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) == 0);
}
Datum
Interval *interval1 = PG_GETARG_INTERVAL_P(0);
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
- if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
- PG_RETURN_BOOL(false);
-
- PG_RETURN_BOOL((interval1->time != interval2->time) ||
- (interval1->month != interval2->month));
+ PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) != 0);
}
Datum
{
Interval *interval1 = PG_GETARG_INTERVAL_P(0);
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
- double span1,
- span2;
- if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
- PG_RETURN_BOOL(false);
-
- span1 = interval1->time;
- if (interval1->month != 0)
- span1 += (interval1->month * (30.0 * 86400));
- span2 = interval2->time;
- if (interval2->month != 0)
- span2 += (interval2->month * (30.0 * 86400));
-
- PG_RETURN_BOOL(span1 < span2);
+ PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) < 0);
}
Datum
{
Interval *interval1 = PG_GETARG_INTERVAL_P(0);
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
- double span1,
- span2;
-
- if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
- PG_RETURN_BOOL(false);
-
- span1 = interval1->time;
- if (interval1->month != 0)
- span1 += (interval1->month * (30.0 * 86400));
- span2 = interval2->time;
- if (interval2->month != 0)
- span2 += (interval2->month * (30.0 * 86400));
- PG_RETURN_BOOL(span1 > span2);
+ PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) > 0);
}
Datum
{
Interval *interval1 = PG_GETARG_INTERVAL_P(0);
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
- double span1,
- span2;
-
- if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
- PG_RETURN_BOOL(false);
-
- span1 = interval1->time;
- if (interval1->month != 0)
- span1 += (interval1->month * (30.0 * 86400));
- span2 = interval2->time;
- if (interval2->month != 0)
- span2 += (interval2->month * (30.0 * 86400));
- PG_RETURN_BOOL(span1 <= span2);
+ PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) <= 0);
}
Datum
{
Interval *interval1 = PG_GETARG_INTERVAL_P(0);
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
- double span1,
- span2;
- if (INTERVAL_IS_INVALID(*interval1) || INTERVAL_IS_INVALID(*interval2))
- PG_RETURN_BOOL(false);
-
- span1 = interval1->time;
- if (interval1->month != 0)
- span1 += (interval1->month * (30.0 * 86400));
- span2 = interval2->time;
- if (interval2->month != 0)
- span2 += (interval2->month * (30.0 * 86400));
-
- PG_RETURN_BOOL(span1 >= span2);
+ PG_RETURN_BOOL(interval_cmp_internal(interval1, interval2) >= 0);
}
-
-/* interval_cmp - 3-state comparison for interval
- */
Datum
interval_cmp(PG_FUNCTION_ARGS)
{
Interval *interval1 = PG_GETARG_INTERVAL_P(0);
Interval *interval2 = PG_GETARG_INTERVAL_P(1);
- double span1,
- span2;
-
- if (INTERVAL_IS_INVALID(*interval1))
- PG_RETURN_INT32(INTERVAL_IS_INVALID(*interval2) ? 0 : 1);
- else if (INTERVAL_IS_INVALID(*interval2))
- PG_RETURN_INT32(-1);
-
- span1 = interval1->time;
- if (interval1->month != 0)
- span1 += (interval1->month * (30.0 * 86400));
- span2 = interval2->time;
- if (interval2->month != 0)
- span2 += (interval2->month * (30.0 * 86400));
- PG_RETURN_INT32((span1 < span2) ? -1 : (span1 > span2) ? 1 : 0);
+ PG_RETURN_INT32(interval_cmp_internal(interval1, interval2));
}
/*
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.16 2001/03/22 03:59:54 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.17 2001/05/03 19:00:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* need to be so careful.
*/
+/* bit_cmp
+ *
+ * Compares two bitstrings and returns <0, 0, >0 depending on whether the first
+ * string is smaller, equal, or bigger than the second. All bits are considered
+ * and additional zero bits may make one string smaller/larger than the other,
+ * even if their zero-padded values would be the same.
+ */
+static int32
+bit_cmp(VarBit *arg1, VarBit *arg2)
+{
+ int bitlen1,
+ bytelen1,
+ bitlen2,
+ bytelen2;
+ int32 cmp;
+
+ bytelen1 = VARBITBYTES(arg1);
+ bytelen2 = VARBITBYTES(arg2);
+
+ cmp = memcmp(VARBITS(arg1), VARBITS(arg2), Min(bytelen1, bytelen2));
+ if (cmp == 0)
+ {
+ bitlen1 = VARBITLEN(arg1);
+ bitlen2 = VARBITLEN(arg2);
+ if (bitlen1 != bitlen2)
+ cmp = (bitlen1 < bitlen2) ? -1 : 1;
+ }
+ return cmp;
+}
+
Datum
biteq(PG_FUNCTION_ARGS)
{
bitlen1 = VARBITLEN(arg1);
bitlen2 = VARBITLEN(arg2);
+
+ /* fast path for different-length inputs */
if (bitlen1 != bitlen2)
result = false;
else
- {
- /* bit strings are always stored in a full number of bytes */
- result = memcmp(VARBITS(arg1), VARBITS(arg2), VARBITBYTES(arg1)) == 0;
- }
+ result = (bit_cmp(arg1, arg2) == 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
bitlen1 = VARBITLEN(arg1);
bitlen2 = VARBITLEN(arg2);
+
+ /* fast path for different-length inputs */
if (bitlen1 != bitlen2)
result = true;
else
- {
- /* bit strings are always stored in a full number of bytes */
- result = memcmp(VARBITS(arg1), VARBITS(arg2), VARBITBYTES(arg1)) != 0;
- }
+ result = (bit_cmp(arg1, arg2) != 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
PG_RETURN_BOOL(result);
}
-/* bit_cmp
- *
- * Compares two bitstrings and returns <0, 0, >0 depending on whether the first
- * string is smaller, equal, or bigger than the second. All bits are considered
- * and additional zero bits may make one string smaller/larger than the other,
- * even if their zero-padded values would be the same.
- */
-static int32
-bit_cmp(VarBit *arg1, VarBit *arg2)
-{
- int bitlen1,
- bytelen1,
- bitlen2,
- bytelen2;
- int32 cmp;
-
- bytelen1 = VARBITBYTES(arg1);
- bytelen2 = VARBITBYTES(arg2);
-
- cmp = memcmp(VARBITS(arg1), VARBITS(arg2), Min(bytelen1, bytelen2));
- if (cmp == 0)
- {
- bitlen1 = VARBITLEN(arg1);
- bitlen2 = VARBITLEN(arg2);
- if (bitlen1 != bitlen2)
- cmp = (bitlen1 < bitlen2) ? -1 : 1;
- }
- return cmp;
-}
-
Datum
bitlt(PG_FUNCTION_ARGS)
{
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.76 2001/04/19 19:01:23 petere Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.77 2001/05/03 19:00:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
-
#include "postgres.h"
#include "access/hash.h"
len1 = bcTruelen(arg1);
len2 = bcTruelen(arg2);
+ /* fast path for different-length inputs */
if (len1 != len2)
result = false;
else
- result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
+ result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) == 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
len1 = bcTruelen(arg1);
len2 = bcTruelen(arg2);
+ /* fast path for different-length inputs */
if (len1 != len2)
result = true;
else
- result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
+ result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) != 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
+ /* fast path for different-length inputs */
if (len1 != len2)
result = false;
else
- result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) == 0);
+ result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) == 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
len1 = VARSIZE(arg1) - VARHDRSZ;
len2 = VARSIZE(arg2) - VARHDRSZ;
+ /* fast path for different-length inputs */
if (len1 != len2)
result = true;
else
- result = (strncmp(VARDATA(arg1), VARDATA(arg2), len1) != 0);
+ result = (varstr_cmp(VARDATA(arg1), len1, VARDATA(arg2), len2) != 0);
PG_FREE_IF_COPY(arg1, 0);
PG_FREE_IF_COPY(arg2, 1);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.69 2001/03/22 03:59:55 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.70 2001/05/03 19:00:36 tgl Exp $
*
*-------------------------------------------------------------------------
*/
PG_RETURN_INT32(pos);
}
-/*
- * texteq - returns true iff arguments are equal
- * textne - returns true iff arguments are not equal
- *
- * Note: btree indexes need these routines not to leak memory; therefore,
- * be careful to free working copies of toasted datums. Most places don't
- * need to be so careful.
- */
-Datum
-texteq(PG_FUNCTION_ARGS)
-{
- text *arg1 = PG_GETARG_TEXT_P(0);
- text *arg2 = PG_GETARG_TEXT_P(1);
- bool result;
-
- if (VARSIZE(arg1) != VARSIZE(arg2))
- result = false;
- else
- {
- int len;
- char *a1p,
- *a2p;
-
- len = VARSIZE(arg1) - VARHDRSZ;
-
- a1p = VARDATA(arg1);
- a2p = VARDATA(arg2);
-
- result = (memcmp(a1p, a2p, len) == 0);
- }
-
- PG_FREE_IF_COPY(arg1, 0);
- PG_FREE_IF_COPY(arg2, 1);
-
- PG_RETURN_BOOL(result);
-}
-
-Datum
-textne(PG_FUNCTION_ARGS)
-{
- text *arg1 = PG_GETARG_TEXT_P(0);
- text *arg2 = PG_GETARG_TEXT_P(1);
- bool result;
-
- if (VARSIZE(arg1) != VARSIZE(arg2))
- result = true;
- else
- {
- int len;
- char *a1p,
- *a2p;
-
- len = VARSIZE(arg1) - VARHDRSZ;
-
- a1p = VARDATA(arg1);
- a2p = VARDATA(arg2);
-
- result = (memcmp(a1p, a2p, len) != 0);
- }
-
- PG_FREE_IF_COPY(arg1, 0);
- PG_FREE_IF_COPY(arg2, 1);
-
- PG_RETURN_BOOL(result);
-}
-
/* varstr_cmp()
* Comparison function for text strings with given lengths.
* Includes locale support, but must copy strings to temporary memory
*a2p;
#ifdef USE_LOCALE
- a1p = (unsigned char *) palloc(len1 + 1);
- a2p = (unsigned char *) palloc(len2 + 1);
+ a1p = (char *) palloc(len1 + 1);
+ a2p = (char *) palloc(len2 + 1);
memcpy(a1p, arg1, len1);
*(a1p + len1) = '\0';
/* text_cmp()
- * Comparison function for text strings.
- * Includes locale support, but must copy strings to temporary memory
- * to allow null-termination for inputs to strcoll().
- * XXX HACK code for textlen() indicates that there can be embedded nulls
- * but it appears that most routines (incl. this one) assume not! - tgl 97/04/07
+ * Internal comparison function for text strings.
* Returns -1, 0 or 1
*/
static int
* need to be so careful.
*/
+Datum
+texteq(PG_FUNCTION_ARGS)
+{
+ text *arg1 = PG_GETARG_TEXT_P(0);
+ text *arg2 = PG_GETARG_TEXT_P(1);
+ bool result;
+
+ /* fast path for different-length inputs */
+ if (VARSIZE(arg1) != VARSIZE(arg2))
+ result = false;
+ else
+ result = (text_cmp(arg1, arg2) == 0);
+
+ PG_FREE_IF_COPY(arg1, 0);
+ PG_FREE_IF_COPY(arg2, 1);
+
+ PG_RETURN_BOOL(result);
+}
+
+Datum
+textne(PG_FUNCTION_ARGS)
+{
+ text *arg1 = PG_GETARG_TEXT_P(0);
+ text *arg2 = PG_GETARG_TEXT_P(1);
+ bool result;
+
+ /* fast path for different-length inputs */
+ if (VARSIZE(arg1) != VARSIZE(arg2))
+ result = true;
+ else
+ result = (text_cmp(arg1, arg2) != 0);
+
+ PG_FREE_IF_COPY(arg1, 0);
+ PG_FREE_IF_COPY(arg2, 1);
+
+ PG_RETURN_BOOL(result);
+}
+
Datum
text_lt(PG_FUNCTION_ARGS)
{
PG_RETURN_BOOL(result);
}
+Datum
+bttextcmp(PG_FUNCTION_ARGS)
+{
+ text *arg1 = PG_GETARG_TEXT_P(0);
+ text *arg2 = PG_GETARG_TEXT_P(1);
+ int32 result;
+
+ result = text_cmp(arg1, arg2);
+
+ PG_FREE_IF_COPY(arg1, 0);
+ PG_FREE_IF_COPY(arg2, 1);
+
+ PG_RETURN_INT32(result);
+}
+
+
Datum
text_larger(PG_FUNCTION_ARGS)
{
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: nabstime.h,v 1.29 2001/03/22 04:01:13 momjian Exp $
+ * $Id: nabstime.h,v 1.30 2001/05/03 19:00:37 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* non-fmgr-callable support routines */
extern AbsoluteTime GetCurrentAbsoluteTime(void);
-extern bool AbsoluteTimeIsBefore(AbsoluteTime time1, AbsoluteTime time2);
extern void abstime2tm(AbsoluteTime time, int *tzp, struct tm * tm, char *tzn);
#endif /* NABSTIME_H */
| current
| infinity
| Sat May 10 23:59:12 1947 PDT
-(6 rows)
+ | invalid
+(7 rows)
SELECT '' AS six, ABSTIME_TBL.*
WHERE abstime 'May 10, 1947 23:59:12' <> ABSTIME_TBL.f1;
| current
| infinity
| -infinity
-(6 rows)
+ | invalid
+(7 rows)
SELECT '' AS one, ABSTIME_TBL.*
WHERE abstime 'current' = ABSTIME_TBL.f1;
| current
| infinity
| Sat May 10 23:59:12 1947 PST
-(6 rows)
+ | invalid
+(7 rows)
SELECT '' AS six, ABSTIME_TBL.*
WHERE abstime 'May 10, 1947 23:59:12' <> ABSTIME_TBL.f1;
| current
| infinity
| -infinity
-(6 rows)
+ | invalid
+(7 rows)
SELECT '' AS one, ABSTIME_TBL.*
WHERE abstime 'current' = ABSTIME_TBL.f1;
WHERE d1 > timestamp '1997-01-02' and d1 != timestamp 'current';
47 | d1
----+---------------------------------
+ | invalid
| infinity
| Mon Feb 10 17:32:01 1997 PST
+ | invalid
+ | invalid
| Mon Feb 10 17:32:01.00 1997 PST
| Mon Feb 10 17:32:02.00 1997 PST
| Mon Feb 10 17:32:01.40 1997 PST
| Sat Jan 01 17:32:01 2000 PST
| Sun Dec 31 17:32:01 2000 PST
| Mon Jan 01 17:32:01 2001 PST
-(47 rows)
+(50 rows)
SELECT '' AS "15", d1 FROM TIMESTAMP_TBL
WHERE d1 < timestamp '1997-01-02' and d1 != timestamp 'current';
WHERE d1 != timestamp '1997-01-02' and d1 != timestamp 'current';
62 | d1
----+---------------------------------
+ | invalid
| -infinity
| infinity
| epoch
| Mon Feb 10 17:32:01 1997 PST
+ | invalid
+ | invalid
| Mon Feb 10 17:32:01.00 1997 PST
| Mon Feb 10 17:32:02.00 1997 PST
| Mon Feb 10 17:32:01.40 1997 PST
| Sat Jan 01 17:32:01 2000 PST
| Sun Dec 31 17:32:01 2000 PST
| Mon Jan 01 17:32:01 2001 PST
-(62 rows)
+(65 rows)
SELECT '' AS "16", d1 FROM TIMESTAMP_TBL
WHERE d1 <= timestamp '1997-01-02' and d1 != timestamp 'current';
WHERE d1 >= timestamp '1997-01-02' and d1 != timestamp 'current';
48 | d1
----+---------------------------------
+ | invalid
| infinity
| Mon Feb 10 17:32:01 1997 PST
+ | invalid
+ | invalid
| Mon Feb 10 17:32:01.00 1997 PST
| Mon Feb 10 17:32:02.00 1997 PST
| Mon Feb 10 17:32:01.40 1997 PST
| Sat Jan 01 17:32:01 2000 PST
| Sun Dec 31 17:32:01 2000 PST
| Mon Jan 01 17:32:01 2001 PST
-(48 rows)
+(51 rows)
SELECT '' AS "66", d1 + interval '1 year' AS one_year FROM TIMESTAMP_TBL;
66 | one_year