11/*-------------------------------------------------------------------------
22 *
3- *ginvacuum .c
4- * supportfunction for GIN's indexing of any array
3+ *ginarrayproc .c
4+ * supportfunctions 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
2928ereport(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) {
7065bool * check = (bool * )PG_GETARG_POINTER (0 );
7166StrategyNumber strategy = PG_GETARG_UINT16 (1 );
7267ArrayType * 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
7772switch (strategy ) {
7873case GinOverlapStrategy :
@@ -82,6 +77,7 @@ ginarrayconsistent(PG_FUNCTION_ARGS) {
8277break ;
8378case GinContainsStrategy :
8479case GinEqualStrategy :
80+ nentries = ArrayGetNItems (ARR_NDIM (query ),ARR_DIMS (query ));
8581res = TRUE;
8682for (i = 0 ;i < nentries ;i ++ )
8783if ( !check [i ] ) {
@@ -90,168 +86,10 @@ ginarrayconsistent(PG_FUNCTION_ARGS) {
9086}
9187break ;
9288default :
93- elog (ERROR ,"ginarrayconsistent: unknown strategy number: %d" ,strategy );
89+ elog (ERROR ,"ginarrayconsistent: unknown strategy number: %d" ,
90+ strategy );
91+ res = FALSE;
9492}
9593
9694PG_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-