diff --git a/contrib/intarray/_int.h b/contrib/intarray/_int.h
index dd50b37d2ea..11c069890ea 100644
--- a/contrib/intarray/_int.h
+++ b/contrib/intarray/_int.h
@@ -9,41 +9,36 @@
/* number ranges for compression */
#define MAXNUMRANGE 100
-/* dimension of array */
-#define NDIM 1
-
/* useful macros for accessing int4 arrays */
#define ARRPTR(x) ( (int4 *) ARR_DATA_PTR(x) )
#define ARRNELEMS(x) ArrayGetNItems(ARR_NDIM(x), ARR_DIMS(x))
-/* reject arrays we can't handle; but allow a NULL or empty array */
+/* reject arrays we can't handle; to wit, those containing nulls */
#define CHECKARRVALID(x) \
do { \
- if (x) { \
- if (ARR_NDIM(x) != NDIM && ARR_NDIM(x) != 0) \
- ereport(ERROR, \
- (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
- errmsg("array must be one-dimensional"))); \
- if (ARR_HASNULL(x)) \
- ereport(ERROR, \
- (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
- errmsg("array must not contain nulls"))); \
- } \
+ if (ARR_HASNULL(x) && array_contains_nulls(x)) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
+ errmsg("array must not contain nulls"))); \
} while(0)
-#define ARRISVOID(x) ((x) == NULL || ARRNELEMS(x) == 0)
+#define ARRISEMPTY(x) (ARRNELEMS(x) == 0)
+/* sort the elements of the array */
#define SORT(x) \
do { \
- if ( ARRNELEMS( x ) > 1 ) \
- isort( ARRPTR( x ), ARRNELEMS( x ) ); \
+ int _nelems_ = ARRNELEMS(x); \
+ if (_nelems_ > 1) \
+ isort(ARRPTR(x), _nelems_); \
} while(0)
+/* sort the elements of the array and remove duplicates */
#define PREPAREARR(x) \
do { \
- if ( ARRNELEMS( x ) > 1 ) \
- if ( isort( ARRPTR( x ), ARRNELEMS( x ) ) ) \
- x = _int_unique( x ); \
+ int _nelems_ = ARRNELEMS(x); \
+ if (_nelems_ > 1) \
+ if (isort(ARRPTR(x), _nelems_)) \
+ (x) = _int_unique(x); \
} while(0)
/* "wish" function */
@@ -90,14 +85,14 @@ typedef struct
#define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) )
/*
-** types for functions
-*/
+ * types for functions
+ */
typedef ArrayType *(*formarray) (ArrayType *, ArrayType *);
typedef void (*formfloat) (ArrayType *, float *);
/*
-** useful function
-*/
+ * useful functions
+ */
bool isort(int4 *a, int len);
ArrayType *new_intArrayType(int num);
ArrayType *copy_intArrayType(ArrayType *a);
@@ -133,17 +128,18 @@ typedef struct ITEM
int4 val;
} ITEM;
-typedef struct
+typedef struct QUERYTYPE
{
int32 vl_len_; /* varlena header (do not touch directly!) */
- int4 size;
- char data[1];
+ int4 size; /* number of ITEMs */
+ ITEM items[1]; /* variable length array */
} QUERYTYPE;
-#define HDRSIZEQT (VARHDRSZ + sizeof(int4))
-#define COMPUTESIZE(size) ( HDRSIZEQT + size * sizeof(ITEM) )
-#define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
+#define HDRSIZEQT offsetof(QUERYTYPE, items)
+#define COMPUTESIZE(size) ( HDRSIZEQT + (size) * sizeof(ITEM) )
+#define GETQUERY(x) ( (x)->items )
+/* "type" codes for ITEM */
#define END 0
#define ERR 1
#define VAL 2
@@ -151,18 +147,28 @@ typedef struct
#define OPEN 4
#define CLOSE 5
+/* fmgr macros for QUERYTYPE objects */
+#define DatumGetQueryTypeP(X) ((QUERYTYPE *) PG_DETOAST_DATUM(X))
+#define DatumGetQueryTypePCopy(X) ((QUERYTYPE *) PG_DETOAST_DATUM_COPY(X))
+#define PG_GETARG_QUERYTYPE_P(n) DatumGetQueryTypeP(PG_GETARG_DATUM(n))
+#define PG_GETARG_QUERYTYPE_P_COPY(n) DatumGetQueryTypePCopy(PG_GETARG_DATUM(n))
+
bool signconsistent(QUERYTYPE *query, BITVEC sign, bool calcnot);
bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot);
-bool ginconsistent(QUERYTYPE *query, bool *check);
-int4 shorterquery(ITEM *q, int4 len);
+
+bool gin_bool_consistent(QUERYTYPE *query, bool *check);
+bool query_has_required_values(QUERYTYPE *query);
int compASC(const void *a, const void *b);
-
int compDESC(const void *a, const void *b);
-#define QSORT(a, direction) \
-if (ARRNELEMS(a) > 1) \
- qsort((void*)ARRPTR(a), ARRNELEMS(a),sizeof(int4), \
- (direction) ? compASC : compDESC )
+/* sort, either ascending or descending */
+#define QSORT(a, direction) \
+ do { \
+ int _nelems_ = ARRNELEMS(a); \
+ if (_nelems_ > 1) \
+ qsort((void*) ARRPTR(a), _nelems_, sizeof(int4), \
+ (direction) ? compASC : compDESC ); \
+ } while(0)
#endif /* ___INT_H__ */
diff --git a/contrib/intarray/_int_bool.c b/contrib/intarray/_int_bool.c
index 4cc447bab2d..3492100c0c2 100644
--- a/contrib/intarray/_int_bool.c
+++ b/contrib/intarray/_int_bool.c
@@ -3,6 +3,7 @@
*/
#include "postgres.h"
+#include "miscadmin.h"
#include "utils/builtins.h"
#include "_int.h"
@@ -22,13 +23,6 @@ PG_FUNCTION_INFO_V1(querytree);
Datum querytree(PG_FUNCTION_ARGS);
-#define END 0
-#define ERR 1
-#define VAL 2
-#define OPR 3
-#define OPEN 4
-#define CLOSE 5
-
/* parser's states */
#define WAITOPERAND 1
#define WAITENDOPERAND 2
@@ -167,6 +161,9 @@ makepol(WORKSTATE *state)
int4 stack[STACKDEPTH];
int4 lenstack = 0;
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
while ((type = gettoken(state, &val)) != END)
{
switch (type)
@@ -236,7 +233,7 @@ typedef struct
} CHKVAL;
/*
- * is there value 'val' in array or not ?
+ * is there value 'val' in (sorted) array or not ?
*/
static bool
checkcondition_arr(void *checkval, ITEM *item)
@@ -267,11 +264,14 @@ checkcondition_bit(void *checkval, ITEM *item)
}
/*
- * check for boolean condition
+ * evaluate boolean expression, using chkcond() to test the primitive cases
*/
static bool
-execute(ITEM *curitem, void *checkval, bool calcnot, bool (*chkcond) (void *checkval, ITEM *item))
+execute(ITEM *curitem, void *checkval, bool calcnot,
+ bool (*chkcond) (void *checkval, ITEM *item))
{
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
if (curitem->type == VAL)
return (*chkcond) (checkval, curitem);
@@ -304,13 +304,12 @@ execute(ITEM *curitem, void *checkval, bool calcnot, bool (*chkcond) (void *chec
bool
signconsistent(QUERYTYPE *query, BITVEC sign, bool calcnot)
{
- return execute(
- GETQUERY(query) + query->size - 1,
+ return execute(GETQUERY(query) + query->size - 1,
(void *) sign, calcnot,
- checkcondition_bit
- );
+ checkcondition_bit);
}
+/* Array must be sorted! */
bool
execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
{
@@ -319,11 +318,9 @@ execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot)
CHECKARRVALID(array);
chkval.arrb = ARRPTR(array);
chkval.arre = chkval.arrb + ARRNELEMS(array);
- return execute(
- GETQUERY(query) + query->size - 1,
+ return execute(GETQUERY(query) + query->size - 1,
(void *) &chkval, calcnot,
- checkcondition_arr
- );
+ checkcondition_arr);
}
typedef struct
@@ -341,27 +338,75 @@ checkcondition_gin(void *checkval, ITEM *item)
}
bool
-ginconsistent(QUERYTYPE *query, bool *check)
+gin_bool_consistent(QUERYTYPE *query, bool *check)
{
GinChkVal gcv;
ITEM *items = GETQUERY(query);
int i,
j = 0;
- if (query->size < 0)
+ if (query->size <= 0)
return FALSE;
+ /*
+ * Set up data for checkcondition_gin. This must agree with the
+ * query extraction code in ginint4_queryextract.
+ */
gcv.first = items;
gcv.mapped_check = (bool *) palloc(sizeof(bool) * query->size);
for (i = 0; i < query->size; i++)
+ {
if (items[i].type == VAL)
gcv.mapped_check[i] = check[j++];
+ }
- return execute(
- GETQUERY(query) + query->size - 1,
+ return execute(GETQUERY(query) + query->size - 1,
(void *) &gcv, true,
- checkcondition_gin
- );
+ checkcondition_gin);
+}
+
+static bool
+contains_required_value(ITEM *curitem)
+{
+ /* since this function recurses, it could be driven to stack overflow */
+ check_stack_depth();
+
+ if (curitem->type == VAL)
+ return true;
+ else if (curitem->val == (int4) '!')
+ {
+ /*
+ * Assume anything under a NOT is non-required. For some cases with
+ * nested NOTs, we could prove there's a required value, but it seems
+ * unlikely to be worth the trouble.
+ */
+ return false;
+ }
+ else if (curitem->val == (int4) '&')
+ {
+ /* If either side has a required value, we're good */
+ if (contains_required_value(curitem + curitem->left))
+ return true;
+ else
+ return contains_required_value(curitem - 1);
+ }
+ else
+ { /* |-operator */
+ /* Both sides must have required values */
+ if (contains_required_value(curitem + curitem->left))
+ return contains_required_value(curitem - 1);
+ else
+ return false;
+ }
+ return false;
+}
+
+bool
+query_has_required_values(QUERYTYPE *query)
+{
+ if (query->size <= 0)
+ return false;
+ return contains_required_value(GETQUERY(query) + query->size - 1);
}
/*
@@ -370,37 +415,27 @@ ginconsistent(QUERYTYPE *query, bool *check)
Datum
rboolop(PG_FUNCTION_ARGS)
{
- return DirectFunctionCall2(
- boolop,
+ /* just reverse the operands */
+ return DirectFunctionCall2(boolop,
PG_GETARG_DATUM(1),
- PG_GETARG_DATUM(0)
- );
+ PG_GETARG_DATUM(0));
}
Datum
boolop(PG_FUNCTION_ARGS)
{
- ArrayType *val = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
+ ArrayType *val = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(1);
CHKVAL chkval;
bool result;
CHECKARRVALID(val);
- if (ARRISVOID(val))
- {
- pfree(val);
- PG_FREE_IF_COPY(query, 1);
- PG_RETURN_BOOL(false);
- }
-
PREPAREARR(val);
chkval.arrb = ARRPTR(val);
chkval.arre = chkval.arrb + ARRNELEMS(val);
- result = execute(
- GETQUERY(query) + query->size - 1,
+ result = execute(GETQUERY(query) + query->size - 1,
&chkval, true,
- checkcondition_arr
- );
+ checkcondition_arr);
pfree(val);
PG_FREE_IF_COPY(query, 1);
@@ -599,7 +634,7 @@ infix(INFIX *in, bool first)
Datum
bqarr_out(PG_FUNCTION_ARGS)
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
INFIX nrm;
if (query->size == 0)
@@ -617,173 +652,11 @@ bqarr_out(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(nrm.buf);
}
-static int4
-countdroptree(ITEM *q, int4 pos)
-{
- if (q[pos].type == VAL)
- return 1;
- else if (q[pos].val == (int4) '!')
- return 1 + countdroptree(q, pos - 1);
- else
- return 1 + countdroptree(q, pos - 1) + countdroptree(q, pos + q[pos].left);
-}
-
-/*
- * common algorithm:
- * result of all '!' will be = 'true', so
- * we can modify query tree for clearing
- */
-int4
-shorterquery(ITEM *q, int4 len)
-{
- int4 index,
- posnot,
- poscor;
- bool notisleft = false;
- int4 drop,
- i;
-
- /* out all '!' */
- do
- {
- index = 0;
- drop = 0;
- /* find ! */
- for (posnot = 0; posnot < len; posnot++)
- if (q[posnot].type == OPR && q[posnot].val == (int4) '!')
- {
- index = 1;
- break;
- }
-
- if (posnot == len)
- return len;
-
- /* last operator is ! */
- if (posnot == len - 1)
- return 0;
-
- /* find operator for this operand */
- for (poscor = posnot + 1; poscor < len; poscor++)
- {
- if (q[poscor].type == OPR)
- {
- if (poscor == posnot + 1)
- {
- notisleft = false;
- break;
- }
- else if (q[poscor].left + poscor == posnot)
- {
- notisleft = true;
- break;
- }
- }
- }
- if (q[poscor].val == (int4) '!')
- {
- drop = countdroptree(q, poscor);
- q[poscor - 1].type = VAL;
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i <= poscor)
- q[i].left += drop - 2;
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[poscor - 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- len -= drop - 2;
- }
- else if (q[poscor].val == (int4) '|')
- {
- drop = countdroptree(q, poscor);
- q[poscor - 1].type = VAL;
- q[poscor].val = (int4) '!';
- q[poscor].left = -1;
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i < poscor)
- q[i].left += drop - 2;
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[poscor - 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- len -= drop - 2;
- }
- else
- { /* &-operator */
- if (
- (notisleft && q[poscor - 1].type == OPR &&
- q[poscor - 1].val == (int4) '!') ||
- (!notisleft && q[poscor + q[poscor].left].type == OPR &&
- q[poscor + q[poscor].left].val == (int4) '!')
- )
- { /* drop subtree */
- drop = countdroptree(q, poscor);
- q[poscor - 1].type = VAL;
- q[poscor].val = (int4) '!';
- q[poscor].left = -1;
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i < poscor)
- q[i].left += drop - 2;
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[poscor - 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- len -= drop - 2;
- }
- else
- { /* drop only operator */
- int4 subtreepos = (notisleft) ?
- poscor - 1 : poscor + q[poscor].left;
- int4 subtreelen = countdroptree(q, subtreepos);
-
- drop = countdroptree(q, poscor);
- for (i = poscor + 1; i < len; i++)
- if (q[i].type == OPR && q[i].left + i < poscor)
- q[i].left += drop - subtreelen;
- memcpy((void *) &q[subtreepos + 1],
- (void *) &q[poscor + 1],
- sizeof(ITEM) * (len - (poscor - 1)));
- memcpy((void *) &q[poscor - drop + 1],
- (void *) &q[subtreepos - subtreelen + 1],
- sizeof(ITEM) * (len - (drop - subtreelen)));
- len -= drop - subtreelen;
- }
- }
- } while (index);
- return len;
-}
-
+/* Useless old "debugging" function for a fundamentally wrong algorithm */
Datum
querytree(PG_FUNCTION_ARGS)
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
- INFIX nrm;
- text *res;
- ITEM *q;
- int4 len;
-
- if (query->size == 0)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("empty query")));
-
- q = (ITEM *) palloc(sizeof(ITEM) * query->size);
- memcpy((void *) q, GETQUERY(query), sizeof(ITEM) * query->size);
- len = shorterquery(q, query->size);
- PG_FREE_IF_COPY(query, 0);
-
- if (len == 0)
- {
- res = cstring_to_text("T");
- }
- else
- {
- nrm.curpol = q + len - 1;
- nrm.buflen = 32;
- nrm.cur = nrm.buf = (char *) palloc(sizeof(char) * nrm.buflen);
- *(nrm.cur) = '\0';
- infix(&nrm, true);
- res = cstring_to_text_with_len(nrm.buf, nrm.cur - nrm.buf);
- }
- pfree(q);
-
- PG_RETURN_TEXT_P(res);
+ elog(ERROR, "querytree is no longer implemented");
+ PG_RETURN_NULL();
}
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c
index b5ad69eba35..3ef5c4635a1 100644
--- a/contrib/intarray/_int_gin.c
+++ b/contrib/intarray/_int_gin.c
@@ -3,6 +3,7 @@
*/
#include "postgres.h"
+#include "access/gin.h"
#include "access/gist.h"
#include "access/skey.h"
@@ -16,66 +17,90 @@ ginint4_queryextract(PG_FUNCTION_ARGS)
{
int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
StrategyNumber strategy = PG_GETARG_UINT16(2);
+ int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
Datum *res = NULL;
*nentries = 0;
if (strategy == BooleanSearchStrategy)
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(0);
ITEM *items = GETQUERY(query);
int i;
- if (query->size == 0)
+ /* empty query must fail */
+ if (query->size <= 0)
PG_RETURN_POINTER(NULL);
- if (shorterquery(items, query->size) == 0)
- elog(ERROR, "Query requires full scan, GIN doesn't support it");
-
- pfree(query);
-
- query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(0));
- items = GETQUERY(query);
+ /*
+ * If the query doesn't have any required primitive values (for
+ * instance, it's something like '! 42'), we have to do a full
+ * index scan.
+ */
+ if (query_has_required_values(query))
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else
+ *searchMode = GIN_SEARCH_MODE_ALL;
+ /*
+ * Extract all the VAL items as things we want GIN to check for.
+ */
res = (Datum *) palloc(sizeof(Datum) * query->size);
*nentries = 0;
for (i = 0; i < query->size; i++)
+ {
if (items[i].type == VAL)
{
res[*nentries] = Int32GetDatum(items[i].val);
(*nentries)++;
}
+ }
}
else
{
ArrayType *query = PG_GETARG_ARRAYTYPE_P(0);
- int4 *arr;
- uint32 i;
CHECKARRVALID(query);
*nentries = ARRNELEMS(query);
if (*nentries > 0)
{
+ int4 *arr;
+ int32 i;
+
res = (Datum *) palloc(sizeof(Datum) * (*nentries));
arr = ARRPTR(query);
for (i = 0; i < *nentries; i++)
res[i] = Int32GetDatum(arr[i]);
}
- }
- if (*nentries == 0)
- {
switch (strategy)
{
- case BooleanSearchStrategy:
case RTOverlapStrategyNumber:
- *nentries = -1; /* nobody can be found */
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
break;
- default: /* require fullscan: GIN can't find void
- * arrays */
+ case RTContainedByStrategyNumber:
+ case RTOldContainedByStrategyNumber:
+ /* empty set is contained in everything */
+ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
break;
+ case RTSameStrategyNumber:
+ if (*nentries > 0)
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else
+ *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
+ break;
+ case RTContainsStrategyNumber:
+ case RTOldContainsStrategyNumber:
+ if (*nentries > 0)
+ *searchMode = GIN_SEARCH_MODE_DEFAULT;
+ else /* everything contains the empty set */
+ *searchMode = GIN_SEARCH_MODE_ALL;
+ break;
+ default:
+ elog(ERROR, "ginint4_queryextract: unknown strategy number: %d",
+ strategy);
}
}
@@ -90,16 +115,11 @@ ginint4_consistent(PG_FUNCTION_ARGS)
{
bool *check = (bool *) PG_GETARG_POINTER(0);
StrategyNumber strategy = PG_GETARG_UINT16(1);
-
- /* int32 nkeys = PG_GETARG_INT32(3); */
+ int32 nkeys = PG_GETARG_INT32(3);
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
bool *recheck = (bool *) PG_GETARG_POINTER(5);
bool res = FALSE;
-
- /*
- * we need not check array carefully, it's done by previous
- * ginarrayextract call
- */
+ int32 i;
switch (strategy)
{
@@ -117,47 +137,41 @@ ginint4_consistent(PG_FUNCTION_ARGS)
res = TRUE;
break;
case RTSameStrategyNumber:
+ /* we will need recheck */
+ *recheck = true;
+ /* Must have all elements in check[] true */
+ res = TRUE;
+ for (i = 0; i < nkeys; i++)
{
- ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
- int i,
- nentries = ARRNELEMS(query);
-
- /* we will need recheck */
- *recheck = true;
- res = TRUE;
- for (i = 0; i < nentries; i++)
- if (!check[i])
- {
- res = FALSE;
- break;
- }
+ if (!check[i])
+ {
+ res = FALSE;
+ break;
+ }
}
break;
case RTContainsStrategyNumber:
case RTOldContainsStrategyNumber:
+ /* result is not lossy */
+ *recheck = false;
+ /* Must have all elements in check[] true */
+ res = TRUE;
+ for (i = 0; i < nkeys; i++)
{
- ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
- int i,
- nentries = ARRNELEMS(query);
-
- /* result is not lossy */
- *recheck = false;
- res = TRUE;
- for (i = 0; i < nentries; i++)
- if (!check[i])
- {
- res = FALSE;
- break;
- }
+ if (!check[i])
+ {
+ res = FALSE;
+ break;
+ }
}
break;
case BooleanSearchStrategy:
{
- QUERYTYPE *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(2));
+ QUERYTYPE *query = PG_GETARG_QUERYTYPE_P(2);
/* result is not lossy */
*recheck = false;
- res = ginconsistent(query, check);
+ res = gin_bool_consistent(query, check);
}
break;
default:
diff --git a/contrib/intarray/_int_gist.c b/contrib/intarray/_int_gist.c
index 65c9bf2e74b..0a173bfcb66 100644
--- a/contrib/intarray/_int_gist.c
+++ b/contrib/intarray/_int_gist.c
@@ -40,7 +40,7 @@ Datum
g_int_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
- ArrayType *query = (ArrayType *) PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(1));
+ ArrayType *query = PG_GETARG_ARRAYTYPE_P_COPY(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
@@ -62,11 +62,6 @@ g_int_consistent(PG_FUNCTION_ARGS)
/* sort query for fast search, key is already sorted */
CHECKARRVALID(query);
- if (ARRISVOID(query))
- {
- pfree(query);
- PG_RETURN_BOOL(false);
- }
PREPAREARR(query);
switch (strategy)
@@ -77,12 +72,10 @@ g_int_consistent(PG_FUNCTION_ARGS)
break;
case RTSameStrategyNumber:
if (GIST_LEAF(entry))
- DirectFunctionCall3(
- g_int_same,
+ DirectFunctionCall3(g_int_same,
entry->key,
PointerGetDatum(query),
- PointerGetDatum(&retval)
- );
+ PointerGetDatum(&retval));
else
retval = inner_int_contains((ArrayType *) DatumGetPointer(entry->key),
query);
@@ -162,7 +155,7 @@ g_int_compress(PG_FUNCTION_ARGS)
if (entry->leafkey)
{
- r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key);
+ r = DatumGetArrayTypePCopy(entry->key);
CHECKARRVALID(r);
PREPAREARR(r);
@@ -182,9 +175,9 @@ g_int_compress(PG_FUNCTION_ARGS)
* ==true, so now we work only with internal keys
*/
- r = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ r = DatumGetArrayTypeP(entry->key);
CHECKARRVALID(r);
- if (ARRISVOID(r))
+ if (ARRISEMPTY(r))
{
if (r != (ArrayType *) DatumGetPointer(entry->key))
pfree(r);
@@ -194,7 +187,7 @@ g_int_compress(PG_FUNCTION_ARGS)
if ((len = ARRNELEMS(r)) >= 2 * MAXNUMRANGE)
{ /* compress */
if (r == (ArrayType *) DatumGetPointer(entry->key))
- r = (ArrayType *) PG_DETOAST_DATUM_COPY(entry->key);
+ r = DatumGetArrayTypePCopy(entry->key);
r = resize_intArrayType(r, 2 * (len));
dr = ARRPTR(r);
@@ -242,10 +235,10 @@ g_int_decompress(PG_FUNCTION_ARGS)
int i,
j;
- in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ in = DatumGetArrayTypeP(entry->key);
CHECKARRVALID(in);
- if (ARRISVOID(in))
+ if (ARRISEMPTY(in))
{
if (in != (ArrayType *) DatumGetPointer(entry->key))
{
@@ -321,8 +314,8 @@ g_int_penalty(PG_FUNCTION_ARGS)
Datum
g_int_same(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) PointerGetDatum(PG_GETARG_POINTER(0));
- ArrayType *b = (ArrayType *) PointerGetDatum(PG_GETARG_POINTER(1));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
int4 n = ARRNELEMS(a);
int4 *da,
@@ -340,11 +333,13 @@ g_int_same(PG_FUNCTION_ARGS)
da = ARRPTR(a);
db = ARRPTR(b);
while (n--)
+ {
if (*da++ != *db++)
{
*result = FALSE;
break;
}
+ }
PG_RETURN_POINTER(result);
}
diff --git a/contrib/intarray/_int_op.c b/contrib/intarray/_int_op.c
index 1d99c6905ef..392e227cff8 100644
--- a/contrib/intarray/_int_op.c
+++ b/contrib/intarray/_int_op.c
@@ -29,27 +29,22 @@ Datum _int_inter(PG_FUNCTION_ARGS);
Datum
_int_contained(PG_FUNCTION_ARGS)
{
- PG_RETURN_BOOL(DatumGetBool(
- DirectFunctionCall2(
- _int_contains,
- PointerGetDatum(PG_GETARG_POINTER(1)),
- PointerGetDatum(PG_GETARG_POINTER(0))
- )
- ));
+ /* just reverse the operands and call _int_contains */
+ return DirectFunctionCall2(_int_contains,
+ PG_GETARG_DATUM(1),
+ PG_GETARG_DATUM(0));
}
Datum
_int_contains(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ /* Force copy so we can modify the arrays in-place */
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
bool res;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) || ARRISVOID(b))
- return FALSE;
-
PREPAREARR(a);
PREPAREARR(b);
res = inner_int_contains(a, b);
@@ -73,24 +68,17 @@ _int_different(PG_FUNCTION_ARGS)
Datum
_int_same(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
int na,
nb;
int n;
int *da,
*db;
bool result;
- bool avoid;
- bool bvoid;
CHECKARRVALID(a);
CHECKARRVALID(b);
- avoid = ARRISVOID(a);
- bvoid = ARRISVOID(b);
- if (avoid || bvoid)
- return (avoid && bvoid) ? TRUE : FALSE;
-
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
@@ -105,11 +93,13 @@ _int_same(PG_FUNCTION_ARGS)
result = TRUE;
for (n = 0; n < na; n++)
+ {
if (da[n] != db[n])
{
result = FALSE;
break;
}
+ }
}
pfree(a);
@@ -123,13 +113,13 @@ _int_same(PG_FUNCTION_ARGS)
Datum
_int_overlap(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
bool result;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) || ARRISVOID(b))
+ if (ARRISEMPTY(a) || ARRISEMPTY(b))
return FALSE;
SORT(a);
@@ -146,24 +136,20 @@ _int_overlap(PG_FUNCTION_ARGS)
Datum
_int_union(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
ArrayType *result;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (!ARRISVOID(a))
- SORT(a);
- if (!ARRISVOID(b))
- SORT(b);
+ SORT(a);
+ SORT(b);
result = inner_int_union(a, b);
- if (a)
- pfree(a);
- if (b)
- pfree(b);
+ pfree(a);
+ pfree(b);
PG_RETURN_POINTER(result);
}
@@ -171,14 +157,12 @@ _int_union(PG_FUNCTION_ARGS)
Datum
_int_inter(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
ArrayType *result;
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) || ARRISVOID(b))
- PG_RETURN_POINTER(new_intArrayType(0));
SORT(a);
SORT(b);
@@ -228,7 +212,7 @@ intset(PG_FUNCTION_ARGS)
Datum
icount(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
int32 count = ARRNELEMS(a);
PG_FREE_IF_COPY(a, 0);
@@ -238,14 +222,14 @@ icount(PG_FUNCTION_ARGS)
Datum
sort(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_P(1) : NULL;
int32 dc = (dirstr) ? VARSIZE(dirstr) - VARHDRSZ : 0;
char *d = (dirstr) ? VARDATA(dirstr) : NULL;
int dir = -1;
CHECKARRVALID(a);
- if (ARRISVOID(a) || ARRNELEMS(a) < 2)
+ if (ARRNELEMS(a) < 2)
PG_RETURN_POINTER(a);
if (dirstr == NULL || (dc == 3
@@ -270,11 +254,9 @@ sort(PG_FUNCTION_ARGS)
Datum
sort_asc(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
CHECKARRVALID(a);
- if (ARRISVOID(a))
- PG_RETURN_POINTER(a);
QSORT(a, 1);
PG_RETURN_POINTER(a);
}
@@ -282,11 +264,9 @@ sort_asc(PG_FUNCTION_ARGS)
Datum
sort_desc(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
CHECKARRVALID(a);
- if (ARRISVOID(a))
- PG_RETURN_POINTER(a);
QSORT(a, 0);
PG_RETURN_POINTER(a);
}
@@ -294,10 +274,10 @@ sort_desc(PG_FUNCTION_ARGS)
Datum
uniq(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
CHECKARRVALID(a);
- if (ARRISVOID(a) || ARRNELEMS(a) < 2)
+ if (ARRNELEMS(a) < 2)
PG_RETURN_POINTER(a);
a = _int_unique(a);
PG_RETURN_POINTER(a);
@@ -306,11 +286,11 @@ uniq(PG_FUNCTION_ARGS)
Datum
idx(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
int32 result;
CHECKARRVALID(a);
- result = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ result = ARRNELEMS(a);
if (result)
result = intarray_match_first(a, PG_GETARG_INT32(1));
PG_FREE_IF_COPY(a, 0);
@@ -320,15 +300,17 @@ idx(PG_FUNCTION_ARGS)
Datum
subarray(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
- ArrayType *result;
- int32 start = (PG_GETARG_INT32(1) > 0) ? PG_GETARG_INT32(1) - 1 : PG_GETARG_INT32(1);
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ int32 start = PG_GETARG_INT32(1);
int32 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
int32 end = 0;
int32 c;
+ ArrayType *result;
+
+ start = (start > 0) ? start - 1 : start;
CHECKARRVALID(a);
- if (ARRISVOID(a))
+ if (ARRISEMPTY(a))
{
PG_FREE_IF_COPY(a, 0);
PG_RETURN_POINTER(new_intArrayType(0));
@@ -358,7 +340,6 @@ subarray(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(new_intArrayType(0));
}
-
result = new_intArrayType(end - start);
if (end - start > 0)
memcpy(ARRPTR(result), ARRPTR(a) + start, (end - start) * sizeof(int32));
@@ -369,7 +350,7 @@ subarray(PG_FUNCTION_ARGS)
Datum
intarray_push_elem(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
ArrayType *result;
result = intarray_add_elem(a, PG_GETARG_INT32(1));
@@ -380,8 +361,8 @@ intarray_push_elem(PG_FUNCTION_ARGS)
Datum
intarray_push_array(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
ArrayType *result;
result = intarray_concat_arrays(a, b);
@@ -393,7 +374,7 @@ intarray_push_array(PG_FUNCTION_ARGS)
Datum
intarray_del_elem(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
int32 elem = PG_GETARG_INT32(1);
int32 c;
int32 *aa;
@@ -401,7 +382,7 @@ intarray_del_elem(PG_FUNCTION_ARGS)
i;
CHECKARRVALID(a);
- if (!ARRISVOID(a))
+ if (!ARRISEMPTY(a))
{
c = ARRNELEMS(a);
aa = ARRPTR(a);
@@ -423,7 +404,7 @@ intarray_del_elem(PG_FUNCTION_ARGS)
Datum
intset_union_elem(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(0)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
ArrayType *result;
result = intarray_add_elem(a, PG_GETARG_INT32(1));
@@ -435,8 +416,8 @@ intset_union_elem(PG_FUNCTION_ARGS)
Datum
intset_subtract(PG_FUNCTION_ARGS)
{
- ArrayType *a = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0)));
- ArrayType *b = (ArrayType *) DatumGetPointer(PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(1)));
+ ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
+ ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
ArrayType *result;
int32 ca;
int32 cb;
diff --git a/contrib/intarray/_int_tool.c b/contrib/intarray/_int_tool.c
index 8093103ba46..ddf07f042b2 100644
--- a/contrib/intarray/_int_tool.c
+++ b/contrib/intarray/_int_tool.c
@@ -8,6 +8,7 @@
#include "_int.h"
+/* arguments are assumed sorted & unique-ified */
bool
inner_int_contains(ArrayType *a, ArrayType *b)
{
@@ -19,12 +20,6 @@ inner_int_contains(ArrayType *a, ArrayType *b)
int *da,
*db;
- CHECKARRVALID(a);
- CHECKARRVALID(b);
-
- if (ARRISVOID(a) || ARRISVOID(b))
- return FALSE;
-
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
@@ -32,6 +27,7 @@ inner_int_contains(ArrayType *a, ArrayType *b)
i = j = n = 0;
while (i < na && j < nb)
+ {
if (da[i] < db[j])
i++;
else if (da[i] == db[j])
@@ -41,11 +37,13 @@ inner_int_contains(ArrayType *a, ArrayType *b)
j++;
}
else
- break;
+ break; /* db[j] is not in da */
+ }
return (n == nb) ? TRUE : FALSE;
}
+/* arguments are assumed sorted */
bool
inner_int_overlap(ArrayType *a, ArrayType *b)
{
@@ -56,12 +54,6 @@ inner_int_overlap(ArrayType *a, ArrayType *b)
int *da,
*db;
- CHECKARRVALID(a);
- CHECKARRVALID(b);
-
- if (ARRISVOID(a) || ARRISVOID(b))
- return FALSE;
-
na = ARRNELEMS(a);
nb = ARRNELEMS(b);
da = ARRPTR(a);
@@ -69,12 +61,14 @@ inner_int_overlap(ArrayType *a, ArrayType *b)
i = j = 0;
while (i < na && j < nb)
+ {
if (da[i] < db[j])
i++;
else if (da[i] == db[j])
return TRUE;
else
j++;
+ }
return FALSE;
}
@@ -87,11 +81,11 @@ inner_int_union(ArrayType *a, ArrayType *b)
CHECKARRVALID(a);
CHECKARRVALID(b);
- if (ARRISVOID(a) && ARRISVOID(b))
+ if (ARRISEMPTY(a) && ARRISEMPTY(b))
return new_intArrayType(0);
- if (ARRISVOID(a))
+ if (ARRISEMPTY(a))
r = copy_intArrayType(b);
- if (ARRISVOID(b))
+ if (ARRISEMPTY(b))
r = copy_intArrayType(a);
if (!r)
@@ -148,10 +142,7 @@ inner_int_inter(ArrayType *a, ArrayType *b)
int i,
j;
- CHECKARRVALID(a);
- CHECKARRVALID(b);
-
- if (ARRISVOID(a) || ARRISVOID(b))
+ if (ARRISEMPTY(a) || ARRISEMPTY(b))
return new_intArrayType(0);
na = ARRNELEMS(a);
@@ -163,6 +154,7 @@ inner_int_inter(ArrayType *a, ArrayType *b)
i = j = 0;
while (i < na && j < nb)
+ {
if (da[i] < db[j])
i++;
else if (da[i] == db[j])
@@ -174,6 +166,7 @@ inner_int_inter(ArrayType *a, ArrayType *b)
}
else
j++;
+ }
if ((dr - ARRPTR(r)) == 0)
{
@@ -188,57 +181,60 @@ void
rt__int_size(ArrayType *a, float *size)
{
*size = (float) ARRNELEMS(a);
-
- return;
}
-
-/* len >= 2 */
+/* Sort the given data (len >= 2). Return true if any duplicates found */
bool
isort(int4 *a, int len)
{
- int4 tmp,
- index;
- int4 *cur,
+ int4 cur,
+ prev;
+ int4 *pcur,
+ *pprev,
*end;
bool r = FALSE;
+ /*
+ * We use a simple insertion sort. While this is O(N^2) in the worst
+ * case, it's quite fast if the input is already sorted or nearly so.
+ * Also, for not-too-large inputs it's faster than more complex methods
+ * anyhow.
+ */
end = a + len;
- do
+ for (pcur = a + 1; pcur < end; pcur++)
{
- index = 0;
- cur = a + 1;
- while (cur < end)
+ cur = *pcur;
+ for (pprev = pcur - 1; pprev >= a; pprev--)
{
- if (*(cur - 1) > *cur)
+ prev = *pprev;
+ if (prev <= cur)
{
- tmp = *(cur - 1);
- *(cur - 1) = *cur;
- *cur = tmp;
- index = 1;
+ if (prev == cur)
+ r = TRUE;
+ break;
}
- else if (!r && *(cur - 1) == *cur)
- r = TRUE;
- cur++;
+ pprev[1] = prev;
}
- } while (index);
+ pprev[1] = cur;
+ }
return r;
}
+/* Create a new int array with room for "num" elements */
ArrayType *
new_intArrayType(int num)
{
ArrayType *r;
- int nbytes = ARR_OVERHEAD_NONULLS(NDIM) + sizeof(int) * num;
+ int nbytes = ARR_OVERHEAD_NONULLS(1) + sizeof(int) * num;
r = (ArrayType *) palloc0(nbytes);
SET_VARSIZE(r, nbytes);
- ARR_NDIM(r) = NDIM;
+ ARR_NDIM(r) = 1;
r->dataoffset = 0; /* marker for no null bitmap */
ARR_ELEMTYPE(r) = INT4OID;
- *((int *) ARR_DIMS(r)) = num;
- *((int *) ARR_LBOUND(r)) = 1;
+ ARR_DIMS(r)[0] = num;
+ ARR_LBOUND(r)[0] = 1;
return r;
}
@@ -246,7 +242,8 @@ new_intArrayType(int num)
ArrayType *
resize_intArrayType(ArrayType *a, int num)
{
- int nbytes = ARR_OVERHEAD_NONULLS(NDIM) + sizeof(int) * num;
+ int nbytes = ARR_DATA_OFFSET(a) + sizeof(int) * num;
+ int i;
if (num == ARRNELEMS(a))
return a;
@@ -254,7 +251,12 @@ resize_intArrayType(ArrayType *a, int num)
a = (ArrayType *) repalloc(a, nbytes);
SET_VARSIZE(a, nbytes);
- *((int *) ARR_DIMS(a)) = num;
+ /* usually the array should be 1-D already, but just in case ... */
+ for (i = 0; i < ARR_NDIM(a); i++)
+ {
+ ARR_DIMS(a)[i] = num;
+ num = 1;
+ }
return a;
}
@@ -262,9 +264,10 @@ ArrayType *
copy_intArrayType(ArrayType *a)
{
ArrayType *r;
+ int n = ARRNELEMS(a);
- r = new_intArrayType(ARRNELEMS(a));
- memmove(r, a, VARSIZE(r));
+ r = new_intArrayType(n);
+ memcpy(ARRPTR(r), ARRPTR(a), n * sizeof(int4));
return r;
}
@@ -276,13 +279,15 @@ internal_size(int *a, int len)
size = 0;
for (i = 0; i < len; i += 2)
+ {
if (!i || a[i] != a[i - 1]) /* do not count repeated range */
size += a[i + 1] - a[i] + 1;
+ }
return size;
}
-/* r is sorted and size of r > 1 */
+/* unique-ify elements of r in-place ... r must be sorted already */
ArrayType *
_int_unique(ArrayType *r)
{
@@ -291,17 +296,17 @@ _int_unique(ArrayType *r)
*data;
int num = ARRNELEMS(r);
- CHECKARRVALID(r);
-
if (num < 2)
return r;
data = tmp = dr = ARRPTR(r);
while (tmp - data < num)
+ {
if (*tmp != *dr)
*(++dr) = *tmp++;
else
tmp++;
+ }
return resize_intArrayType(r, dr + 1 - ARRPTR(r));
}
@@ -326,8 +331,6 @@ intarray_match_first(ArrayType *a, int32 elem)
i;
CHECKARRVALID(a);
- if (ARRISVOID(a))
- return 0;
c = ARRNELEMS(a);
aa = ARRPTR(a);
for (i = 0; i < c; i++)
@@ -344,7 +347,7 @@ intarray_add_elem(ArrayType *a, int32 elem)
int32 c;
CHECKARRVALID(a);
- c = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
+ c = ARRNELEMS(a);
result = new_intArrayType(c + 1);
r = ARRPTR(result);
if (c > 0)
@@ -357,8 +360,8 @@ ArrayType *
intarray_concat_arrays(ArrayType *a, ArrayType *b)
{
ArrayType *result;
- int32 ac = (ARRISVOID(a)) ? 0 : ARRNELEMS(a);
- int32 bc = (ARRISVOID(b)) ? 0 : ARRNELEMS(b);
+ int32 ac = ARRNELEMS(a);
+ int32 bc = ARRNELEMS(b);
CHECKARRVALID(a);
CHECKARRVALID(b);
diff --git a/contrib/intarray/_intbig_gist.c b/contrib/intarray/_intbig_gist.c
index d9557a6b11a..eb8f2826349 100644
--- a/contrib/intarray/_intbig_gist.c
+++ b/contrib/intarray/_intbig_gist.c
@@ -153,13 +153,13 @@ g_intbig_compress(PG_FUNCTION_ARGS)
if (entry->leafkey)
{
GISTENTRY *retval;
- ArrayType *in = (ArrayType *) PG_DETOAST_DATUM(entry->key);
+ ArrayType *in = DatumGetArrayTypeP(entry->key);
int4 *ptr;
int num;
GISTTYPE *res = (GISTTYPE *) palloc0(CALCGTSIZE(0));
CHECKARRVALID(in);
- if (ARRISVOID(in))
+ if (ARRISEMPTY(in))
{
ptr = NULL;
num = 0;
@@ -182,7 +182,7 @@ g_intbig_compress(PG_FUNCTION_ARGS)
entry->rel, entry->page,
entry->offset, FALSE);
- if (in != (ArrayType *) PG_DETOAST_DATUM(entry->key))
+ if (in != DatumGetArrayTypeP(entry->key))
pfree(in);
PG_RETURN_POINTER(retval);
@@ -504,7 +504,7 @@ Datum
g_intbig_consistent(PG_FUNCTION_ARGS)
{
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
- ArrayType *query = (ArrayType *) PG_DETOAST_DATUM(PG_GETARG_POINTER(1));
+ ArrayType *query = PG_GETARG_ARRAYTYPE_P(1);
StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid subtype = PG_GETARG_OID(3); */
@@ -527,11 +527,6 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
}
CHECKARRVALID(query);
- if (ARRISVOID(query))
- {
- PG_FREE_IF_COPY(query, 1);
- PG_RETURN_BOOL(FALSE);
- }
switch (strategy)
{
@@ -548,8 +543,6 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
BITVECP dq,
de;
- CHECKARRVALID(query);
-
memset(qp, 0, sizeof(BITVEC));
while (num--)
@@ -589,8 +582,6 @@ g_intbig_consistent(PG_FUNCTION_ARGS)
BITVECP dq,
de;
- CHECKARRVALID(query);
-
memset(qp, 0, sizeof(BITVEC));
while (num--)
diff --git a/contrib/intarray/uninstall__int.sql b/contrib/intarray/uninstall__int.sql
index 5cda23fdad1..345ad4464bd 100644
--- a/contrib/intarray/uninstall__int.sql
+++ b/contrib/intarray/uninstall__int.sql
@@ -5,9 +5,9 @@ SET search_path = public;
DROP OPERATOR CLASS gin__int_ops USING gin;
-DROP FUNCTION ginint4_queryextract(internal, internal, int2, internal, internal);
+DROP FUNCTION ginint4_queryextract(internal, internal, int2, internal, internal, internal, internal);
-DROP FUNCTION ginint4_consistent(internal, int2, internal, int4, internal, internal);
+DROP FUNCTION ginint4_consistent(internal, int2, internal, int4, internal, internal, internal, internal);
DROP OPERATOR CLASS gist__intbig_ops USING gist;
diff --git a/doc/src/sgml/intarray.sgml b/doc/src/sgml/intarray.sgml
index 1cf72a12010..449878d6716 100644
--- a/doc/src/sgml/intarray.sgml
+++ b/doc/src/sgml/intarray.sgml
@@ -9,10 +9,21 @@
The intarray> module provides a number of useful functions
- and operators for manipulating one-dimensional arrays of integers.
+ and operators for manipulating null-free arrays of integers.
There is also support for indexed searches using some of the operators.
+
+ All of these operations will throw an error if a supplied array contains any
+ NULL elements.
+
+
+
+ Many of these operations are only sensible for one-dimensional arrays.
+ Although they will accept input arrays of more dimensions, the data is
+ treated as though it were a linear array in storage order.
+
+
intarray> Functions and Operators
@@ -211,14 +222,12 @@
- The containment operators @>> and <@> are
- approximately equivalent to PostgreSQL>'s built-in operators
- of the same names, except that they work only on integer arrays while the
- built-in operators work for any array type. An important difference is
- that intarray>'s operators do not consider an empty array to be
- contained in anything else. This is consistent with the behavior of
- GIN-indexed queries, but not with the usual mathematical definition of
- containment.
+ The operators &&>, @>> and
+ <@> are equivalent to PostgreSQL>'s built-in
+ operators of the same names, except that they work only on integer arrays
+ that do not contain nulls, while the built-in operators work for any array
+ type. This restriction makes them faster than the built-in operators
+ in many cases.