Skip to content

Commit f5b4d9a

Browse files
committed
If we're going to advertise the array overlap/containment operators,
we probably should make them work reliably for all arrays. Fix code to handle NULLs and multidimensional arrays, move it into arrayfuncs.c. GIN is still restricted to indexing arrays with no null elements, however.
1 parent 69b7c99 commit f5b4d9a

File tree

4 files changed

+245
-183
lines changed

4 files changed

+245
-183
lines changed

src/backend/access/gin/ginarrayproc.c

Lines changed: 13 additions & 175 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
/*-------------------------------------------------------------------------
22
*
3-
* ginvacuum.c
4-
* support function for GIN's indexing of any array
3+
* ginarrayproc.c
4+
* support functions for GIN's indexing of any array
55
*
66
*
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gin/ginarrayproc.c,v 1.4 2006/07/14 14:52:16 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gin/ginarrayproc.c,v 1.5 2006/09/10 20:14:20 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
14-
1514
#include "postgres.h"
15+
16+
#include "access/gin.h"
1617
#include "utils/array.h"
17-
#include "utils/builtins.h"
1818
#include "utils/lsyscache.h"
19-
#include "utils/typcache.h"
20-
#include "access/gin.h"
19+
2120

2221
#define GinOverlapStrategy 1
2322
#define GinContainsStrategy 2
@@ -29,13 +28,9 @@
2928
ereport(ERROR, \
3029
(errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
3130
errmsg("array must not contain nulls"))); \
32-
\
33-
if ( ARR_NDIM(x) != 1 && ARR_NDIM(x) != 0 ) \
34-
ereport(ERROR, \
35-
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), \
36-
errmsg("array must be one-dimensional"))); \
3731
} while(0)
3832

33+
3934
/*
4035
* Function used as extractValue and extractQuery both
4136
*/
@@ -70,9 +65,9 @@ ginarrayconsistent(PG_FUNCTION_ARGS) {
7065
bool *check = (bool*)PG_GETARG_POINTER(0);
7166
StrategyNumber strategy = PG_GETARG_UINT16(1);
7267
ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
73-
int res=FALSE, i, nentries=ArrayGetNItems(ARR_NDIM(query), ARR_DIMS(query));
68+
int res, i, nentries;
7469

75-
/* we can do not check array carefully, it's done by previous ginarrayextract call */
70+
/* ARRAYCHECK was already done by previous ginarrayextract call */
7671

7772
switch( strategy ) {
7873
case GinOverlapStrategy:
@@ -82,6 +77,7 @@ ginarrayconsistent(PG_FUNCTION_ARGS) {
8277
break;
8378
case GinContainsStrategy:
8479
case GinEqualStrategy:
80+
nentries=ArrayGetNItems(ARR_NDIM(query), ARR_DIMS(query));
8581
res = TRUE;
8682
for(i=0;i<nentries;i++)
8783
if ( !check[i] ) {
@@ -90,168 +86,10 @@ ginarrayconsistent(PG_FUNCTION_ARGS) {
9086
}
9187
break;
9288
default:
93-
elog(ERROR, "ginarrayconsistent: unknown strategy number: %d", strategy);
89+
elog(ERROR, "ginarrayconsistent: unknown strategy number: %d",
90+
strategy);
91+
res = FALSE;
9492
}
9593

9694
PG_RETURN_BOOL(res);
9795
}
98-
99-
static TypeCacheEntry*
100-
fillTypeCacheEntry( TypeCacheEntry *typentry, Oid element_type ) {
101-
if ( typentry && typentry->type_id == element_type )
102-
return typentry;
103-
104-
typentry = lookup_type_cache(element_type, TYPECACHE_EQ_OPR_FINFO);
105-
if (!OidIsValid(typentry->eq_opr_finfo.fn_oid))
106-
ereport(ERROR,
107-
(errcode(ERRCODE_UNDEFINED_FUNCTION),
108-
errmsg("could not identify an equality operator for type %s", format_type_be(element_type))));
109-
110-
return typentry;
111-
}
112-
113-
static bool
114-
typeEQ(FunctionCallInfoData *locfcinfo, Datum a, Datum b) {
115-
locfcinfo->arg[0] = a;
116-
locfcinfo->arg[1] = b;
117-
locfcinfo->argnull[0] = false;
118-
locfcinfo->argnull[1] = false;
119-
locfcinfo->isnull = false;
120-
121-
return DatumGetBool(FunctionCallInvoke(locfcinfo));
122-
}
123-
124-
static bool
125-
ginArrayOverlap(TypeCacheEntry *typentry, ArrayType *a, ArrayType *b) {
126-
Datum *da, *db;
127-
int na, nb, j, i;
128-
FunctionCallInfoData locfcinfo;
129-
130-
if ( ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b) )
131-
ereport(ERROR,
132-
(errcode(ERRCODE_DATATYPE_MISMATCH),
133-
errmsg("cannot compare arrays of different element types")));
134-
135-
ARRAYCHECK(a);
136-
ARRAYCHECK(b);
137-
138-
deconstruct_array(a,
139-
ARR_ELEMTYPE(a),
140-
typentry->typlen, typentry->typbyval, typentry->typalign,
141-
&da, NULL, &na);
142-
deconstruct_array(b,
143-
ARR_ELEMTYPE(b),
144-
typentry->typlen, typentry->typbyval, typentry->typalign,
145-
&db, NULL, &nb);
146-
147-
InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
148-
NULL, NULL);
149-
150-
for(i=0;i<na;i++) {
151-
for(j=0;j<nb;j++) {
152-
if ( typeEQ(&locfcinfo, da[i], db[j]) ) {
153-
pfree( da );
154-
pfree( db );
155-
return TRUE;
156-
}
157-
}
158-
}
159-
160-
pfree( da );
161-
pfree( db );
162-
163-
return FALSE;
164-
}
165-
166-
static bool
167-
ginArrayContains(TypeCacheEntry *typentry, ArrayType *a, ArrayType *b) {
168-
Datum *da, *db;
169-
int na, nb, j, i, n = 0;
170-
FunctionCallInfoData locfcinfo;
171-
172-
if ( ARR_ELEMTYPE(a) != ARR_ELEMTYPE(b) )
173-
ereport(ERROR,
174-
(errcode(ERRCODE_DATATYPE_MISMATCH),
175-
errmsg("cannot compare arrays of different element types")));
176-
177-
ARRAYCHECK(a);
178-
ARRAYCHECK(b);
179-
180-
deconstruct_array(a,
181-
ARR_ELEMTYPE(a),
182-
typentry->typlen, typentry->typbyval, typentry->typalign,
183-
&da, NULL, &na);
184-
deconstruct_array(b,
185-
ARR_ELEMTYPE(b),
186-
typentry->typlen, typentry->typbyval, typentry->typalign,
187-
&db, NULL, &nb);
188-
189-
InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
190-
NULL, NULL);
191-
192-
for(i=0;i<nb;i++) {
193-
for(j=0;j<na;j++) {
194-
if ( typeEQ(&locfcinfo, db[i], da[j]) ) {
195-
n++;
196-
break;
197-
}
198-
}
199-
}
200-
201-
pfree( da );
202-
pfree( db );
203-
204-
return ( n==nb ) ? TRUE : FALSE;
205-
}
206-
207-
Datum
208-
arrayoverlap(PG_FUNCTION_ARGS) {
209-
ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
210-
ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
211-
TypeCacheEntry *typentry = fillTypeCacheEntry( fcinfo->flinfo->fn_extra, ARR_ELEMTYPE(a) );
212-
bool res;
213-
214-
fcinfo->flinfo->fn_extra = (void*)typentry;
215-
216-
res = ginArrayOverlap( typentry, a, b );
217-
218-
PG_FREE_IF_COPY(a,0);
219-
PG_FREE_IF_COPY(b,1);
220-
221-
PG_RETURN_BOOL(res);
222-
}
223-
224-
Datum
225-
arraycontains(PG_FUNCTION_ARGS) {
226-
ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
227-
ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
228-
TypeCacheEntry *typentry = fillTypeCacheEntry( fcinfo->flinfo->fn_extra, ARR_ELEMTYPE(a) );
229-
bool res;
230-
231-
fcinfo->flinfo->fn_extra = (void*)typentry;
232-
233-
res = ginArrayContains( typentry, a, b );
234-
235-
PG_FREE_IF_COPY(a,0);
236-
PG_FREE_IF_COPY(b,1);
237-
238-
PG_RETURN_BOOL(res);
239-
}
240-
241-
Datum
242-
arraycontained(PG_FUNCTION_ARGS) {
243-
ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
244-
ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
245-
TypeCacheEntry *typentry = fillTypeCacheEntry( fcinfo->flinfo->fn_extra, ARR_ELEMTYPE(a) );
246-
bool res;
247-
248-
fcinfo->flinfo->fn_extra = (void*)typentry;
249-
250-
res = ginArrayContains( typentry, b, a );
251-
252-
PG_FREE_IF_COPY(a,0);
253-
PG_FREE_IF_COPY(b,1);
254-
255-
PG_RETURN_BOOL(res);
256-
}
257-

0 commit comments

Comments
 (0)