Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit fdf2dbd

Browse files
committed
Fix assorted corner-case bugs in contrib/intarray.
The array containment operators now behave per mathematical expectation for empty arrays (ie, an empty array is contained in anything). Both these operators and the query_int operators now work as expected in GiST and GIN index searches, rather than having corner cases where the index searches gave different answers. Also, fix unexpected failures where the operators would claim that an array contained nulls, when in fact there was no longer any null present (similar to bug #5784). The restriction to not have nulls is still there, as removing it would take a lot of added code complexity and probably slow things down significantly. Also, remove the arbitrary restriction to 1-D arrays; unlike the other restriction, this was buying us nothing performance-wise. Assorted cosmetic improvements and marginal performance improvements, too.
1 parent adf328c commit fdf2dbd

File tree

9 files changed

+332
-460
lines changed

9 files changed

+332
-460
lines changed

contrib/intarray/_int.h

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,41 +9,36 @@
99
/* number ranges for compression */
1010
#define MAXNUMRANGE 100
1111

12-
/* dimension of array */
13-
#define NDIM 1
14-
1512
/* useful macros for accessing int4 arrays */
1613
#define ARRPTR(x) ( (int4 *) ARR_DATA_PTR(x) )
1714
#define ARRNELEMS(x) ArrayGetNItems(ARR_NDIM(x), ARR_DIMS(x))
1815

19-
/* reject arrays we can't handle; but allow a NULL or empty array */
16+
/* reject arrays we can't handle; to wit, those containing nulls */
2017
#define CHECKARRVALID(x) \
2118
do { \
22-
if (x) { \
23-
if (ARR_NDIM(x) != NDIM && ARR_NDIM(x) != 0) \
24-
ereport(ERROR, \
25-
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
26-
errmsg("array must be one-dimensional"))); \
27-
if (ARR_HASNULL(x)) \
28-
ereport(ERROR, \
29-
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
30-
errmsg("array must not contain nulls"))); \
31-
} \
19+
if (ARR_HASNULL(x) && array_contains_nulls(x)) \
20+
ereport(ERROR, \
21+
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
22+
errmsg("array must not contain nulls"))); \
3223
} while(0)
3324

34-
#define ARRISVOID(x) ((x) == NULL || ARRNELEMS(x) == 0)
25+
#define ARRISEMPTY(x) (ARRNELEMS(x) == 0)
3526

27+
/* sort the elements of the array */
3628
#define SORT(x) \
3729
do { \
38-
if ( ARRNELEMS( x ) > 1 ) \
39-
isort( ARRPTR( x ), ARRNELEMS( x ) ); \
30+
int _nelems_ = ARRNELEMS(x); \
31+
if (_nelems_ > 1) \
32+
isort(ARRPTR(x), _nelems_); \
4033
} while(0)
4134

35+
/* sort the elements of the array and remove duplicates */
4236
#define PREPAREARR(x) \
4337
do { \
44-
if ( ARRNELEMS( x ) > 1 ) \
45-
if ( isort( ARRPTR( x ), ARRNELEMS( x ) ) ) \
46-
x = _int_unique( x ); \
38+
int _nelems_ = ARRNELEMS(x); \
39+
if (_nelems_ > 1) \
40+
if (isort(ARRPTR(x), _nelems_)) \
41+
(x) = _int_unique(x); \
4742
} while(0)
4843

4944
/* "wish" function */
@@ -90,14 +85,14 @@ typedef struct
9085
#define GETSIGN(x) ( (BITVECP)( (char*)x+GTHDRSIZE ) )
9186

9287
/*
93-
** types for functions
94-
*/
88+
* types for functions
89+
*/
9590
typedef ArrayType *(*formarray) (ArrayType *, ArrayType *);
9691
typedef void (*formfloat) (ArrayType *, float *);
9792

9893
/*
99-
** useful function
100-
*/
94+
* useful functions
95+
*/
10196
bool isort(int4 *a, int len);
10297
ArrayType *new_intArrayType(int num);
10398
ArrayType *copy_intArrayType(ArrayType *a);
@@ -133,36 +128,47 @@ typedef struct ITEM
133128
int4 val;
134129
} ITEM;
135130

136-
typedef struct
131+
typedef struct QUERYTYPE
137132
{
138133
int32 vl_len_; /* varlena header (do not touch directly!) */
139-
int4 size;
140-
char data[1];
134+
int4 size; /* number of ITEMs */
135+
ITEM items[1]; /* variable length array */
141136
} QUERYTYPE;
142137

143-
#define HDRSIZEQT (VARHDRSZ + sizeof(int4))
144-
#define COMPUTESIZE(size) ( HDRSIZEQT + size * sizeof(ITEM) )
145-
#define GETQUERY(x) (ITEM*)( (char*)(x)+HDRSIZEQT )
138+
#define HDRSIZEQT offsetof(QUERYTYPE, items)
139+
#define COMPUTESIZE(size) ( HDRSIZEQT + (size) * sizeof(ITEM) )
140+
#define GETQUERY(x) ( (x)->items )
146141

142+
/* "type" codes for ITEM */
147143
#define END 0
148144
#define ERR 1
149145
#define VAL 2
150146
#define OPR 3
151147
#define OPEN 4
152148
#define CLOSE 5
153149

150+
/* fmgr macros for QUERYTYPE objects */
151+
#define DatumGetQueryTypeP(X) ((QUERYTYPE *) PG_DETOAST_DATUM(X))
152+
#define DatumGetQueryTypePCopy(X) ((QUERYTYPE *) PG_DETOAST_DATUM_COPY(X))
153+
#define PG_GETARG_QUERYTYPE_P(n) DatumGetQueryTypeP(PG_GETARG_DATUM(n))
154+
#define PG_GETARG_QUERYTYPE_P_COPY(n) DatumGetQueryTypePCopy(PG_GETARG_DATUM(n))
155+
154156
bool signconsistent(QUERYTYPE *query, BITVEC sign, bool calcnot);
155157
bool execconsistent(QUERYTYPE *query, ArrayType *array, bool calcnot);
156-
bool ginconsistent(QUERYTYPE *query, bool *check);
157-
int4 shorterquery(ITEM *q, int4 len);
158158

159-
int compASC(const void *a, const void *b);
159+
bool gin_bool_consistent(QUERYTYPE *query, bool *check);
160+
bool query_has_required_values(QUERYTYPE *query);
160161

162+
int compASC(const void *a, const void *b);
161163
int compDESC(const void *a, const void *b);
162164

163-
#define QSORT(a, direction) \
164-
if (ARRNELEMS(a) > 1) \
165-
qsort((void*)ARRPTR(a), ARRNELEMS(a),sizeof(int4), \
166-
(direction) ? compASC : compDESC )
165+
/* sort, either ascending or descending */
166+
#define QSORT(a, direction) \
167+
do { \
168+
int _nelems_ = ARRNELEMS(a); \
169+
if (_nelems_ > 1) \
170+
qsort((void*) ARRPTR(a), _nelems_, sizeof(int4), \
171+
(direction) ? compASC : compDESC ); \
172+
} while(0)
167173

168174
#endif /* ___INT_H__ */

0 commit comments

Comments
 (0)