openGauss-server/contrib/intarray/_int_gin.cpp

167 lines
5.0 KiB
C++

/*
* contrib/intarray/_int_gin.c
*/
#include "postgres.h"
#include "knl/knl_variable.h"
#include "access/gin.h"
#include "access/gist.h"
#include "access/skey.h"
#include "_int.h"
PG_FUNCTION_INFO_V1(ginint4_queryextract);
extern "C" Datum ginint4_queryextract(PG_FUNCTION_ARGS);
Datum 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 = PG_GETARG_QUERYTYPE_P(0);
ITEM* items = GETQUERY(query);
int i;
/* empty query must fail */
if (query->size <= 0)
PG_RETURN_POINTER(NULL);
/*
* 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);
CHECKARRVALID(query);
*nentries = ARRNELEMS(query);
if (*nentries > 0) {
int4* arr = NULL;
int32 i;
res = (Datum*)palloc(sizeof(Datum) * (*nentries));
arr = ARRPTR(query);
for (i = 0; i < *nentries; i++)
res[i] = Int32GetDatum(arr[i]);
}
switch (strategy) {
case RTOverlapStrategyNumber:
*searchMode = GIN_SEARCH_MODE_DEFAULT;
break;
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);
}
}
PG_RETURN_POINTER(res);
}
PG_FUNCTION_INFO_V1(ginint4_consistent);
extern "C" 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);
int32 nkeys = PG_GETARG_INT32(3);
bool* recheck = (bool*)PG_GETARG_POINTER(5);
bool res = FALSE;
int32 i;
switch (strategy) {
case RTOverlapStrategyNumber:
/* result is not lossy */
*recheck = false;
/* at least one element in check[] is true, so result = true */
res = TRUE;
break;
case RTContainedByStrategyNumber:
case RTOldContainedByStrategyNumber:
/* we will need recheck */
*recheck = true;
/* at least one element in check[] is true, so result = true */
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++) {
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++) {
if (!check[i]) {
res = FALSE;
break;
}
}
break;
case BooleanSearchStrategy: {
QUERYTYPE* query = PG_GETARG_QUERYTYPE_P(2);
/* result is not lossy */
*recheck = false;
res = gin_bool_consistent(query, check);
} break;
default:
elog(ERROR, "ginint4_consistent: unknown strategy number: %d", strategy);
}
PG_RETURN_BOOL(res);
}