diff options
Diffstat (limited to 'contrib/intarray/_int_gin.c')
-rw-r--r-- | contrib/intarray/_int_gin.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/contrib/intarray/_int_gin.c b/contrib/intarray/_int_gin.c new file mode 100644 index 00000000000..dfbb6e2ff1d --- /dev/null +++ b/contrib/intarray/_int_gin.c @@ -0,0 +1,100 @@ +#include "_int.h" + +PG_FUNCTION_INFO_V1(ginint4_queryextract); +Datum ginint4_queryextract(PG_FUNCTION_ARGS); + +Datum +ginint4_queryextract(PG_FUNCTION_ARGS) { + uint32 *nentries = (uint32*)PG_GETARG_POINTER(1); + StrategyNumber strategy = PG_GETARG_UINT16(2); + Datum *res = NULL; + + *nentries = 0; + + if ( strategy == BooleanSearchStrategy ) { + QUERYTYPE *query = (QUERYTYPE*)PG_DETOAST_DATUM_COPY(PG_GETARG_POINTER(0)); + ITEM *items = GETQUERY(query); + int i; + + 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); + + 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 ) { + res = (Datum*)palloc(sizeof(Datum) * (*nentries)); + + arr=ARRPTR(query); + for(i=0;i<*nentries;i++) + res[i] = Int32GetDatum( arr[i] ); + } + } + + PG_RETURN_POINTER( res ); +} + +PG_FUNCTION_INFO_V1(ginint4_consistent); +Datum ginint4_consistent(PG_FUNCTION_ARGS); + +Datum +ginint4_consistent(PG_FUNCTION_ARGS) { + bool *check = (bool*)PG_GETARG_POINTER(0); + StrategyNumber strategy = PG_GETARG_UINT16(1); + int res=FALSE; + + /* we can do not check array carefully, it's done by previous ginarrayextract call */ + + switch( strategy ) { + case RTOverlapStrategyNumber: + case RTContainedByStrategyNumber: + /* at least one element in check[] is true, so result = true */ + + res = TRUE; + break; + case RTSameStrategyNumber: + case RTContainsStrategyNumber: + res = TRUE; + do { + ArrayType *query = PG_GETARG_ARRAYTYPE_P(2); + int i, nentries=ARRNELEMS(query); + + for(i=0;i<nentries;i++) + if ( !check[i] ) { + res = FALSE; + break; + } + } while(0); + break; + case BooleanSearchStrategy: + do { + QUERYTYPE *query = (QUERYTYPE*)PG_DETOAST_DATUM(PG_GETARG_POINTER(2)); + res = ginconsistent( query, check ); + } while(0); + break; + default: + elog(ERROR, "ginint4_consistent: unknown strategy number: %d", strategy); + } + + PG_RETURN_BOOL(res); +} |