aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-08-17 19:58:06 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-08-17 19:58:06 +0000
commitec646dbc65afc8c55118cb3fb75cb6fd18d78dd8 (patch)
treebd256cf157c4636382d59938162326fccc70b62c /src/backend/utils/adt
parentd89578ccbefb83aa9f9d1c00269cd866be2cc857 (diff)
downloadpostgresql-ec646dbc65afc8c55118cb3fb75cb6fd18d78dd8.tar.gz
postgresql-ec646dbc65afc8c55118cb3fb75cb6fd18d78dd8.zip
Create a 'type cache' that keeps track of the data needed for any particular
datatype by array_eq and array_cmp; use this to solve problems with memory leaks in array indexing support. The parser's equality_oper and ordering_oper routines also use the cache. Change the operator search algorithms to look for appropriate btree or hash index opclasses, instead of assuming operators named '<' or '=' have the right semantics. (ORDER BY ASC/DESC now also look at opclasses, instead of assuming '<' and '>' are the right things.) Add several more index opclasses so that there is no regression in functionality for base datatypes. initdb forced due to catalog additions.
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/acl.c19
-rw-r--r--src/backend/utils/adt/arrayfuncs.c132
-rw-r--r--src/backend/utils/adt/cash.c19
-rw-r--r--src/backend/utils/adt/nabstime.c254
-rw-r--r--src/backend/utils/adt/ri_triggers.c76
-rw-r--r--src/backend/utils/adt/ruleutils.c35
6 files changed, 247 insertions, 288 deletions
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c
index 504e8f55652..8d5a675006b 100644
--- a/src/backend/utils/adt/acl.c
+++ b/src/backend/utils/adt/acl.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.95 2003/08/14 14:19:07 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/acl.c,v 1.96 2003/08/17 19:58:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -481,6 +481,23 @@ aclitem_eq(PG_FUNCTION_ARGS)
}
/*
+ * aclitem hash function
+ *
+ * We make aclitems hashable not so much because anyone is likely to hash
+ * them, as because we want array equality to work on aclitem arrays, and
+ * with the typcache mechanism we must have a hash or btree opclass.
+ */
+Datum
+hash_aclitem(PG_FUNCTION_ARGS)
+{
+ AclItem *a = PG_GETARG_ACLITEM_P(0);
+
+ /* not very bright, but avoids any issue of padding in struct */
+ PG_RETURN_UINT32((uint32) (a->ai_privs + a->ai_grantee + a->ai_grantor));
+}
+
+
+/*
* acldefault() --- create an ACL describing default access permissions
*
* Change this routine if you want to alter the default access policy for
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 37504718ad5..46f7881d648 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.98 2003/08/15 00:22:26 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/arrayfuncs.c,v 1.99 2003/08/17 19:58:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -28,6 +28,7 @@
#include "utils/memutils.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+#include "utils/typcache.h"
/*----------
@@ -2341,6 +2342,9 @@ deconstruct_array(ArrayType *array,
* compares two arrays for equality
* result :
* returns true if the arrays are equal, false otherwise.
+ *
+ * Note: we do not use array_cmp here, since equality may be meaningful in
+ * datatypes that don't have a total ordering (and hence no btree support).
*-----------------------------------------------------------------------------
*/
Datum
@@ -2357,13 +2361,12 @@ array_eq(PG_FUNCTION_ARGS)
int nitems1 = ArrayGetNItems(ndims1, dims1);
int nitems2 = ArrayGetNItems(ndims2, dims2);
Oid element_type = ARR_ELEMTYPE(array1);
- FmgrInfo *ae_fmgr_info = fcinfo->flinfo;
bool result = true;
+ TypeCacheEntry *typentry;
int typlen;
bool typbyval;
char typalign;
int i;
- ArrayMetaState *my_extra;
FunctionCallInfoData locfcinfo;
if (element_type != ARR_ELEMTYPE(array2))
@@ -2379,38 +2382,31 @@ array_eq(PG_FUNCTION_ARGS)
/*
* We arrange to look up the equality function only once per
* series of calls, assuming the element type doesn't change
- * underneath us.
+ * underneath us. The typcache is used so that we have no
+ * memory leakage when being used as an index support function.
*/
- my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra;
- if (my_extra == NULL)
+ typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
+ if (typentry == NULL ||
+ typentry->type_id != element_type)
{
- ae_fmgr_info->fn_extra = MemoryContextAlloc(ae_fmgr_info->fn_mcxt,
- sizeof(ArrayMetaState));
- my_extra = (ArrayMetaState *) ae_fmgr_info->fn_extra;
- my_extra->element_type = InvalidOid;
- }
-
- if (my_extra->element_type != element_type)
- {
- Oid opfuncid = equality_oper_funcid(element_type);
-
- get_typlenbyvalalign(element_type,
- &my_extra->typlen,
- &my_extra->typbyval,
- &my_extra->typalign);
- fmgr_info_cxt(opfuncid, &my_extra->proc,
- ae_fmgr_info->fn_mcxt);
- my_extra->element_type = element_type;
+ typentry = lookup_type_cache(element_type,
+ TYPECACHE_EQ_OPR_FINFO);
+ if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not identify an equality operator for type %s",
+ format_type_be(element_type))));
+ fcinfo->flinfo->fn_extra = (void *) typentry;
}
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typalign = my_extra->typalign;
+ typlen = typentry->typlen;
+ typbyval = typentry->typbyval;
+ typalign = typentry->typalign;
/*
* apply the operator to each pair of array elements.
*/
MemSet(&locfcinfo, 0, sizeof(locfcinfo));
- locfcinfo.flinfo = &my_extra->proc;
+ locfcinfo.flinfo = &typentry->eq_opr_finfo;
locfcinfo.nargs = 2;
/* Loop over source data */
@@ -2519,23 +2515,14 @@ array_cmp(FunctionCallInfo fcinfo)
int nitems1 = ArrayGetNItems(ndims1, dims1);
int nitems2 = ArrayGetNItems(ndims2, dims2);
Oid element_type = ARR_ELEMTYPE(array1);
- FmgrInfo *ac_fmgr_info = fcinfo->flinfo;
int result = 0;
+ TypeCacheEntry *typentry;
int typlen;
bool typbyval;
char typalign;
int min_nitems;
int i;
- typedef struct
- {
- Oid element_type;
- int16 typlen;
- bool typbyval;
- char typalign;
- FmgrInfo eqproc;
- FmgrInfo ordproc;
- } ac_extra;
- ac_extra *my_extra;
+ FunctionCallInfoData locfcinfo;
if (element_type != ARR_ELEMTYPE(array2))
ereport(ERROR,
@@ -2543,37 +2530,34 @@ array_cmp(FunctionCallInfo fcinfo)
errmsg("cannot compare arrays of different element types")));
/*
- * We arrange to look up the element type info and related functions
- * only once per series of calls, assuming the element type doesn't
- * change underneath us.
+ * We arrange to look up the comparison function only once per series of
+ * calls, assuming the element type doesn't change underneath us.
+ * The typcache is used so that we have no memory leakage when being used
+ * as an index support function.
*/
- my_extra = (ac_extra *) ac_fmgr_info->fn_extra;
- if (my_extra == NULL)
+ typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
+ if (typentry == NULL ||
+ typentry->type_id != element_type)
{
- ac_fmgr_info->fn_extra = MemoryContextAlloc(ac_fmgr_info->fn_mcxt,
- sizeof(ac_extra));
- my_extra = (ac_extra *) ac_fmgr_info->fn_extra;
- my_extra->element_type = InvalidOid;
+ typentry = lookup_type_cache(element_type,
+ TYPECACHE_CMP_PROC_FINFO);
+ if (!OidIsValid(typentry->cmp_proc_finfo.fn_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not identify a comparison function for type %s",
+ format_type_be(element_type))));
+ fcinfo->flinfo->fn_extra = (void *) typentry;
}
+ typlen = typentry->typlen;
+ typbyval = typentry->typbyval;
+ typalign = typentry->typalign;
- if (my_extra->element_type != element_type)
- {
- Oid eqfuncid = equality_oper_funcid(element_type);
- Oid ordfuncid = ordering_oper_funcid(element_type);
-
- get_typlenbyvalalign(element_type,
- &my_extra->typlen,
- &my_extra->typbyval,
- &my_extra->typalign);
- fmgr_info_cxt(eqfuncid, &my_extra->eqproc,
- ac_fmgr_info->fn_mcxt);
- fmgr_info_cxt(ordfuncid, &my_extra->ordproc,
- ac_fmgr_info->fn_mcxt);
- my_extra->element_type = element_type;
- }
- typlen = my_extra->typlen;
- typbyval = my_extra->typbyval;
- typalign = my_extra->typalign;
+ /*
+ * apply the operator to each pair of array elements.
+ */
+ MemSet(&locfcinfo, 0, sizeof(locfcinfo));
+ locfcinfo.flinfo = &typentry->cmp_proc_finfo;
+ locfcinfo.nargs = 2;
/* Loop over source data */
min_nitems = Min(nitems1, nitems2);
@@ -2581,7 +2565,7 @@ array_cmp(FunctionCallInfo fcinfo)
{
Datum elt1;
Datum elt2;
- Datum opresult;
+ int32 cmpresult;
/* Get element pair */
elt1 = fetch_att(p1, typbyval, typlen);
@@ -2594,15 +2578,17 @@ array_cmp(FunctionCallInfo fcinfo)
p2 = (char *) att_align(p2, typalign);
/* Compare the pair of elements */
+ locfcinfo.arg[0] = elt1;
+ locfcinfo.arg[1] = elt2;
+ locfcinfo.argnull[0] = false;
+ locfcinfo.argnull[1] = false;
+ locfcinfo.isnull = false;
+ cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
- /* are they equal */
- opresult = FunctionCall2(&my_extra->eqproc, elt1, elt2);
- if (DatumGetBool(opresult))
- continue;
+ if (cmpresult == 0)
+ continue; /* equal */
- /* nope, see if arg1 is less than arg2 */
- opresult = FunctionCall2(&my_extra->ordproc, elt1, elt2);
- if (DatumGetBool(opresult))
+ if (cmpresult < 0)
{
/* arg1 is less than arg2 */
result = -1;
diff --git a/src/backend/utils/adt/cash.c b/src/backend/utils/adt/cash.c
index e33aad28d64..c4fc14134f0 100644
--- a/src/backend/utils/adt/cash.c
+++ b/src/backend/utils/adt/cash.c
@@ -9,7 +9,7 @@
* workings can be found in the book "Software Solutions in C" by
* Dale Schumacher, Academic Press, ISBN: 0-12-632360-7.
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.59 2003/07/27 04:53:03 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/cash.c,v 1.60 2003/08/17 19:58:05 tgl Exp $
*/
#include "postgres.h"
@@ -342,6 +342,9 @@ cash_send(PG_FUNCTION_ARGS)
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
+/*
+ * Comparison functions
+ */
Datum
cash_eq(PG_FUNCTION_ARGS)
@@ -397,6 +400,20 @@ cash_ge(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(c1 >= c2);
}
+Datum
+cash_cmp(PG_FUNCTION_ARGS)
+{
+ Cash c1 = PG_GETARG_CASH(0);
+ Cash c2 = PG_GETARG_CASH(1);
+
+ if (c1 > c2)
+ PG_RETURN_INT32(1);
+ else if (c1 == c2)
+ PG_RETURN_INT32(0);
+ else
+ PG_RETURN_INT32(-1);
+}
+
/* cash_pl()
* Add two cash values.
diff --git a/src/backend/utils/adt/nabstime.c b/src/backend/utils/adt/nabstime.c
index a4f3b061e6f..f694349db7a 100644
--- a/src/backend/utils/adt/nabstime.c
+++ b/src/backend/utils/adt/nabstime.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.113 2003/08/04 02:40:05 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/nabstime.c,v 1.114 2003/08/17 19:58:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -505,11 +505,11 @@ abstime_finite(PG_FUNCTION_ARGS)
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.
- */
+ /*
+ * 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)
@@ -904,7 +904,7 @@ tintervalout(PG_FUNCTION_ARGS)
char *i_str,
*p;
- i_str = (char *) palloc(T_INTERVAL_LEN); /* ['...' '...'] */
+ i_str = (char *) palloc(T_INTERVAL_LEN); /* ["..." "..."] */
strcpy(i_str, "[\"");
if (interval->status == T_INTERVAL_INVAL)
strcat(i_str, INVALID_INTERVAL_STR);
@@ -920,7 +920,7 @@ tintervalout(PG_FUNCTION_ARGS)
strcat(i_str, p);
pfree(p);
}
- strcat(i_str, "\"]\0");
+ strcat(i_str, "\"]");
PG_RETURN_CSTRING(i_str);
}
@@ -1190,22 +1190,42 @@ timenow(PG_FUNCTION_ARGS)
}
/*
- * reltimeeq - returns true iff arguments are equal
- * reltimene - returns true iff arguments are not equal
- * reltimelt - returns true iff t1 less than t2
- * reltimegt - returns true iff t1 greater than t2
- * reltimele - returns true iff t1 less than or equal to t2
- * reltimege - returns true iff t1 greater than or equal to t2
+ * reltime comparison routines
*/
+static int
+reltime_cmp_internal(RelativeTime a, RelativeTime 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_RELTIME)
+ {
+ if (b == INVALID_RELTIME)
+ return 0; /* INVALID = INVALID */
+ else
+ return 1; /* INVALID > non-INVALID */
+ }
+
+ if (b == INVALID_RELTIME)
+ return -1; /* non-INVALID < INVALID */
+
+ if (a > b)
+ return 1;
+ else if (a == b)
+ return 0;
+ else
+ return -1;
+}
+
Datum
reltimeeq(PG_FUNCTION_ARGS)
{
RelativeTime t1 = PG_GETARG_RELATIVETIME(0);
RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
- if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
- PG_RETURN_BOOL(false);
- PG_RETURN_BOOL(t1 == t2);
+ PG_RETURN_BOOL(reltime_cmp_internal(t1, t2) == 0);
}
Datum
@@ -1214,9 +1234,7 @@ reltimene(PG_FUNCTION_ARGS)
RelativeTime t1 = PG_GETARG_RELATIVETIME(0);
RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
- if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
- PG_RETURN_BOOL(false);
- PG_RETURN_BOOL(t1 != t2);
+ PG_RETURN_BOOL(reltime_cmp_internal(t1, t2) != 0);
}
Datum
@@ -1225,9 +1243,7 @@ reltimelt(PG_FUNCTION_ARGS)
RelativeTime t1 = PG_GETARG_RELATIVETIME(0);
RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
- if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
- PG_RETURN_BOOL(false);
- PG_RETURN_BOOL(t1 < t2);
+ PG_RETURN_BOOL(reltime_cmp_internal(t1, t2) < 0);
}
Datum
@@ -1236,9 +1252,7 @@ reltimegt(PG_FUNCTION_ARGS)
RelativeTime t1 = PG_GETARG_RELATIVETIME(0);
RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
- if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
- PG_RETURN_BOOL(false);
- PG_RETURN_BOOL(t1 > t2);
+ PG_RETURN_BOOL(reltime_cmp_internal(t1, t2) > 0);
}
Datum
@@ -1247,9 +1261,7 @@ reltimele(PG_FUNCTION_ARGS)
RelativeTime t1 = PG_GETARG_RELATIVETIME(0);
RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
- if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
- PG_RETURN_BOOL(false);
- PG_RETURN_BOOL(t1 <= t2);
+ PG_RETURN_BOOL(reltime_cmp_internal(t1, t2) <= 0);
}
Datum
@@ -1258,9 +1270,16 @@ reltimege(PG_FUNCTION_ARGS)
RelativeTime t1 = PG_GETARG_RELATIVETIME(0);
RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
- if (t1 == INVALID_RELTIME || t2 == INVALID_RELTIME)
- PG_RETURN_BOOL(false);
- PG_RETURN_BOOL(t1 >= t2);
+ PG_RETURN_BOOL(reltime_cmp_internal(t1, t2) >= 0);
+}
+
+Datum
+btreltimecmp(PG_FUNCTION_ARGS)
+{
+ RelativeTime t1 = PG_GETARG_RELATIVETIME(0);
+ RelativeTime t2 = PG_GETARG_RELATIVETIME(1);
+
+ PG_RETURN_INT32(reltime_cmp_internal(t1, t2));
}
@@ -1287,59 +1306,71 @@ tintervalsame(PG_FUNCTION_ARGS)
PG_RETURN_BOOL(false);
}
-
/*
- * tintervaleq - returns true iff interval i1 is equal to interval i2
- * Check length of intervals.
+ * tinterval comparison routines
+ *
+ * Note: comparison is based on the lengths of the intervals, not on
+ * endpoint value. This is pretty bogus, but since it's only a legacy
+ * datatype I'm not going to propose changing it.
*/
-Datum
-tintervaleq(PG_FUNCTION_ARGS)
+static int
+tinterval_cmp_internal(TimeInterval a, TimeInterval b)
{
- TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
- TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- AbsoluteTime t10,
- t11,
- t20,
- t21;
+ bool a_invalid;
+ bool b_invalid;
+ AbsoluteTime a_len;
+ AbsoluteTime b_len;
- if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
- PG_RETURN_BOOL(false);
+ /*
+ * 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.
+ */
+ a_invalid = ((a->status == T_INTERVAL_INVAL) ||
+ (a->data[0] == INVALID_ABSTIME) ||
+ (a->data[1] == INVALID_ABSTIME));
+ b_invalid = ((b->status == T_INTERVAL_INVAL) ||
+ (b->data[0] == INVALID_ABSTIME) ||
+ (b->data[1] == INVALID_ABSTIME));
+
+ if (a_invalid)
+ {
+ if (b_invalid)
+ return 0; /* INVALID = INVALID */
+ else
+ return 1; /* INVALID > non-INVALID */
+ }
- t10 = i1->data[0];
- t11 = i1->data[1];
- t20 = i2->data[0];
- t21 = i2->data[1];
+ if (b_invalid)
+ return -1; /* non-INVALID < INVALID */
- if ((t10 == INVALID_ABSTIME) || (t11 == INVALID_ABSTIME)
- || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
- PG_RETURN_BOOL(false);
+ a_len = a->data[1] - a->data[0];
+ b_len = b->data[1] - b->data[0];
- PG_RETURN_BOOL((t11 - t10) == (t21 - t20));
+ if (a_len > b_len)
+ return 1;
+ else if (a_len == b_len)
+ return 0;
+ else
+ return -1;
}
Datum
-tintervalne(PG_FUNCTION_ARGS)
+tintervaleq(PG_FUNCTION_ARGS)
{
TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- AbsoluteTime t10,
- t11,
- t20,
- t21;
- if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
- PG_RETURN_BOOL(false);
-
- t10 = i1->data[0];
- t11 = i1->data[1];
- t20 = i2->data[0];
- t21 = i2->data[1];
+ PG_RETURN_BOOL(tinterval_cmp_internal(i1, i2) == 0);
+}
- if ((t10 == INVALID_ABSTIME) || (t11 == INVALID_ABSTIME)
- || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
- PG_RETURN_BOOL(false);
+Datum
+tintervalne(PG_FUNCTION_ARGS)
+{
+ TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
+ TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- PG_RETURN_BOOL((t11 - t10) != (t21 - t20));
+ PG_RETURN_BOOL(tinterval_cmp_internal(i1, i2) != 0);
}
Datum
@@ -1347,24 +1378,8 @@ tintervallt(PG_FUNCTION_ARGS)
{
TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- AbsoluteTime t10,
- t11,
- t20,
- t21;
-
- if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
- PG_RETURN_BOOL(false);
- t10 = i1->data[0];
- t11 = i1->data[1];
- t20 = i2->data[0];
- t21 = i2->data[1];
-
- if ((t10 == INVALID_ABSTIME) || (t11 == INVALID_ABSTIME)
- || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
- PG_RETURN_BOOL(false);
-
- PG_RETURN_BOOL((t11 - t10) < (t21 - t20));
+ PG_RETURN_BOOL(tinterval_cmp_internal(i1, i2) < 0);
}
Datum
@@ -1372,24 +1387,8 @@ tintervalle(PG_FUNCTION_ARGS)
{
TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- AbsoluteTime t10,
- t11,
- t20,
- t21;
-
- if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
- PG_RETURN_BOOL(false);
- t10 = i1->data[0];
- t11 = i1->data[1];
- t20 = i2->data[0];
- t21 = i2->data[1];
-
- if ((t10 == INVALID_ABSTIME) || (t11 == INVALID_ABSTIME)
- || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
- PG_RETURN_BOOL(false);
-
- PG_RETURN_BOOL((t11 - t10) <= (t21 - t20));
+ PG_RETURN_BOOL(tinterval_cmp_internal(i1, i2) <= 0);
}
Datum
@@ -1397,24 +1396,8 @@ tintervalgt(PG_FUNCTION_ARGS)
{
TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- AbsoluteTime t10,
- t11,
- t20,
- t21;
-
- if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
- PG_RETURN_BOOL(false);
- t10 = i1->data[0];
- t11 = i1->data[1];
- t20 = i2->data[0];
- t21 = i2->data[1];
-
- if ((t10 == INVALID_ABSTIME) || (t11 == INVALID_ABSTIME)
- || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
- PG_RETURN_BOOL(false);
-
- PG_RETURN_BOOL((t11 - t10) > (t21 - t20));
+ PG_RETURN_BOOL(tinterval_cmp_internal(i1, i2) > 0);
}
Datum
@@ -1422,24 +1405,17 @@ tintervalge(PG_FUNCTION_ARGS)
{
TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- AbsoluteTime t10,
- t11,
- t20,
- t21;
-
- if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
- PG_RETURN_BOOL(false);
- t10 = i1->data[0];
- t11 = i1->data[1];
- t20 = i2->data[0];
- t21 = i2->data[1];
+ PG_RETURN_BOOL(tinterval_cmp_internal(i1, i2) >= 0);
+}
- if ((t10 == INVALID_ABSTIME) || (t11 == INVALID_ABSTIME)
- || (t20 == INVALID_ABSTIME) || (t21 == INVALID_ABSTIME))
- PG_RETURN_BOOL(false);
+Datum
+bttintervalcmp(PG_FUNCTION_ARGS)
+{
+ TimeInterval i1 = PG_GETARG_TIMEINTERVAL(0);
+ TimeInterval i2 = PG_GETARG_TIMEINTERVAL(1);
- PG_RETURN_BOOL((t11 - t10) >= (t21 - t20));
+ PG_RETURN_INT32(tinterval_cmp_internal(i1, i2));
}
@@ -1652,7 +1628,7 @@ istinterval(char *i_string,
break;
}
p++;
- /* skip leading blanks up to "'" */
+ /* skip leading blanks up to '"' */
while ((c = *p) != '\0')
{
if (IsSpace(c))
@@ -1680,10 +1656,10 @@ istinterval(char *i_string,
/* get the first date */
*i_start = DatumGetAbsoluteTime(DirectFunctionCall1(abstimein,
CStringGetDatum(p)));
- /* rechange NULL at the end of the first date to a "'" */
+ /* rechange NULL at the end of the first date to a '"' */
*p1 = '"';
p = ++p1;
- /* skip blanks up to "'", beginning of second date */
+ /* skip blanks up to '"', beginning of second date */
while ((c = *p) != '\0')
{
if (IsSpace(c))
@@ -1708,7 +1684,7 @@ istinterval(char *i_string,
/* get the second date */
*i_end = DatumGetAbsoluteTime(DirectFunctionCall1(abstimein,
CStringGetDatum(p)));
- /* rechange NULL at the end of the first date to a ''' */
+ /* rechange NULL at the end of the first date to a '"' */
*p1 = '"';
p = ++p1;
/* skip blanks up to ']' */
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index 7476204d89f..55a6944971e 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -17,7 +17,7 @@
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.54 2003/08/04 02:40:05 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.55 2003/08/17 19:58:05 tgl Exp $
*
* ----------
*/
@@ -39,6 +39,7 @@
#include "parser/parse_oper.h"
#include "rewrite/rewriteHandler.h"
#include "utils/lsyscache.h"
+#include "utils/typcache.h"
#include "miscadmin.h"
@@ -48,7 +49,6 @@
*/
#define RI_INIT_QUERYHASHSIZE 128
-#define RI_INIT_OPREQHASHSIZE 128
#define RI_MATCH_TYPE_UNSPECIFIED 0
#define RI_MATCH_TYPE_FULL 1
@@ -109,20 +109,11 @@ typedef struct RI_QueryHashEntry
} RI_QueryHashEntry;
-typedef struct RI_OpreqHashEntry
-{
- Oid typeid;
- FmgrInfo oprfmgrinfo;
-} RI_OpreqHashEntry;
-
-
-
/* ----------
* Local data
* ----------
*/
static HTAB *ri_query_cache = (HTAB *) NULL;
-static HTAB *ri_opreq_cache = (HTAB *) NULL;
/* ----------
@@ -3197,8 +3188,8 @@ ri_NullCheck(Relation rel, HeapTuple tup, RI_QueryKey *key, int pairidx)
/* ----------
* ri_InitHashTables -
*
- * Initialize our internal hash tables for prepared
- * query plans and equal operators.
+ * Initialize our internal hash table for prepared
+ * query plans.
* ----------
*/
static void
@@ -3212,12 +3203,6 @@ ri_InitHashTables(void)
ctl.hash = tag_hash;
ri_query_cache = hash_create("RI query cache", RI_INIT_QUERYHASHSIZE,
&ctl, HASH_ELEM | HASH_FUNCTION);
-
- ctl.keysize = sizeof(Oid);
- ctl.entrysize = sizeof(RI_OpreqHashEntry);
- ctl.hash = tag_hash;
- ri_opreq_cache = hash_create("RI OpReq cache", RI_INIT_OPREQHASHSIZE,
- &ctl, HASH_ELEM | HASH_FUNCTION);
}
@@ -3438,57 +3423,22 @@ ri_OneKeyEqual(Relation rel, int column, HeapTuple oldtup, HeapTuple newtup,
static bool
ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
{
- RI_OpreqHashEntry *entry;
- bool found;
+ TypeCacheEntry *typentry;
/*
- * On the first call initialize the hashtable
+ * Find the data type in the typcache, and ask for eq_opr info.
*/
- if (!ri_opreq_cache)
- ri_InitHashTables();
+ typentry = lookup_type_cache(typeid, TYPECACHE_EQ_OPR_FINFO);
- /*
- * Try to find the '=' operator for this type in our cache
- */
- entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
- (void *) &typeid,
- HASH_FIND, NULL);
-
- /*
- * If not found, lookup the operator, then do the function manager
- * lookup, and remember that info.
- */
- if (!entry)
- {
- Oid opr_proc;
- FmgrInfo finfo;
-
- opr_proc = equality_oper_funcid(typeid);
-
- /*
- * Since fmgr_info could fail, call it *before* creating the
- * hashtable entry --- otherwise we could ereport leaving an
- * incomplete entry in the hashtable. Also, because this will be
- * a permanent table entry, we must make sure any subsidiary
- * structures of the fmgr record are kept in TopMemoryContext.
- */
- fmgr_info_cxt(opr_proc, &finfo, TopMemoryContext);
-
- entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
- (void *) &typeid,
- HASH_ENTER, &found);
- if (entry == NULL)
- ereport(ERROR,
- (errcode(ERRCODE_OUT_OF_MEMORY),
- errmsg("out of memory")));
-
- entry->typeid = typeid;
- memcpy(&(entry->oprfmgrinfo), &finfo, sizeof(FmgrInfo));
- }
+ if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
+ ereport(ERROR,
+ (errcode(ERRCODE_UNDEFINED_FUNCTION),
+ errmsg("could not identify an equality operator for type %s",
+ format_type_be(typeid))));
/*
* Call the type specific '=' function
*/
- return DatumGetBool(FunctionCall2(&(entry->oprfmgrinfo),
+ return DatumGetBool(FunctionCall2(&(typentry->eq_opr_finfo),
oldvalue, newvalue));
}
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 83989292d6a..5504251bc47 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.151 2003/08/11 23:04:49 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.152 2003/08/17 19:58:05 tgl Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -69,6 +69,7 @@
#include "utils/array.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
+#include "utils/typcache.h"
/* ----------
@@ -1815,21 +1816,24 @@ get_select_query_def(Query *query, deparse_context *context,
SortClause *srt = (SortClause *) lfirst(l);
Node *sortexpr;
Oid sortcoltype;
- char *opname;
+ TypeCacheEntry *typentry;
appendStringInfo(buf, sep);
sortexpr = get_rule_sortgroupclause(srt, query->targetList,
force_colno, context);
sortcoltype = exprType(sortexpr);
- opname = generate_operator_name(srt->sortop,
- sortcoltype, sortcoltype);
- if (strcmp(opname, "<") != 0)
- {
- if (strcmp(opname, ">") == 0)
- appendStringInfo(buf, " DESC");
- else
- appendStringInfo(buf, " USING %s", opname);
- }
+ /* See whether operator is default < or > for datatype */
+ typentry = lookup_type_cache(sortcoltype,
+ TYPECACHE_LT_OPR | TYPECACHE_GT_OPR);
+ if (srt->sortop == typentry->lt_opr)
+ /* ASC is default, so emit nothing */ ;
+ else if (srt->sortop == typentry->gt_opr)
+ appendStringInfo(buf, " DESC");
+ else
+ appendStringInfo(buf, " USING %s",
+ generate_operator_name(srt->sortop,
+ sortcoltype,
+ sortcoltype));
sep = ", ";
}
}
@@ -4032,6 +4036,15 @@ get_opclass_name(Oid opclass, Oid actual_datatype,
if (!HeapTupleIsValid(ht_opc))
elog(ERROR, "cache lookup failed for opclass %u", opclass);
opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc);
+
+ /* Special case for ARRAY_OPS: pretend it is default for any array type */
+ if (OidIsValid(actual_datatype))
+ {
+ if (opcrec->opcintype == ANYARRAYOID &&
+ OidIsValid(get_element_type(actual_datatype)))
+ actual_datatype = opcrec->opcintype;
+ }
+
if (actual_datatype != opcrec->opcintype || !opcrec->opcdefault)
{
/* Okay, we need the opclass name. Do we need to qualify it? */