in src/backend/utils/adt/agtype_gin.c [181:276]
Datum gin_extract_agtype_query(PG_FUNCTION_ARGS)
{
int32 *nentries;
StrategyNumber strategy;
int32 *searchMode;
Datum *entries;
if (PG_ARGISNULL(0) || PG_ARGISNULL(1) ||
PG_ARGISNULL(2) || PG_ARGISNULL(6))
{
PG_RETURN_NULL();
}
nentries = (int32 *) PG_GETARG_POINTER(1);
strategy = PG_GETARG_UINT16(2);
searchMode = (int32 *) PG_GETARG_POINTER(6);
if (strategy == AGTYPE_CONTAINS_STRATEGY_NUMBER ||
strategy == AGTYPE_CONTAINS_TOP_LEVEL_STRATEGY_NUMBER)
{
/* Query is a agtype, so just apply gin_extract_agtype... */
entries = (Datum *)
DatumGetPointer(DirectFunctionCall2(gin_extract_agtype,
PG_GETARG_DATUM(0),
PointerGetDatum(nentries)));
/* ...although "contains {}" requires a full index scan */
if (*nentries == 0)
{
*searchMode = GIN_SEARCH_MODE_ALL;
}
}
else if (strategy == AGTYPE_EXISTS_STRATEGY_NUMBER)
{
/* Query is a text string, which we treat as a key */
text *query = PG_GETARG_TEXT_PP(0);
*nentries = 1;
entries = (Datum *)palloc(sizeof(Datum));
entries[0] = make_text_key(AGT_GIN_FLAG_KEY, VARDATA_ANY(query),
VARSIZE_ANY_EXHDR(query));
}
else if (strategy == AGTYPE_EXISTS_ANY_STRATEGY_NUMBER ||
strategy == AGTYPE_EXISTS_ALL_STRATEGY_NUMBER)
{
/* Query is a text array; each element is treated as a key */
agtype *agt = AG_GET_ARG_AGTYPE_P(0);
agtype_iterator *it = NULL;
agtype_value elem;
agtype_iterator_token itok;
int key_count = AGTYPE_CONTAINER_SIZE(&agt->root);
int index = 0;
if (AGTYPE_CONTAINER_IS_SCALAR(&agt->root) ||
!AGTYPE_CONTAINER_IS_ARRAY(&agt->root))
{
elog(ERROR, "GIN query requires an agtype array");
}
entries = (Datum *) palloc(sizeof(Datum) * key_count);
it = agtype_iterator_init(&agt->root);
/* it should be WAGT_BEGIN_ARRAY */
itok = agtype_iterator_next(&it, &elem, true);
if (itok != WAGT_BEGIN_ARRAY)
{
elog(ERROR, "unexpected iterator token: %d", itok);
}
while (WAGT_END_ARRAY != agtype_iterator_next(&it, &elem, true))
{
if (elem.type != AGTV_STRING)
{
elog(ERROR, "unsupport agtype for GIN lookup: %d", elem.type);
}
entries[index++] = make_text_key(AGT_GIN_FLAG_KEY,
elem.val.string.val,
elem.val.string.len);
}
*nentries = index;
/* ExistsAll with no keys should match everything */
if (index == 0 && strategy == AGTYPE_EXISTS_ALL_STRATEGY_NUMBER)
{
*searchMode = GIN_SEARCH_MODE_ALL;
}
}
else
{
elog(ERROR, "unrecognized strategy number: %d", strategy);
entries = NULL; /* keep compiler quiet */
}
PG_RETURN_POINTER(entries);
}