1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-07 12:02:30 +03:00
Files
postgres/contrib/intarray/_int_gin.c
Michael Paquier 31d3847a37 Use more palloc_object() and palloc_array() in contrib/
The idea is to encourage more the use of these new routines across the
tree, as these offer stronger type safety guarantees than palloc().  In
an ideal world, palloc() would then act as an internal routine of these
flavors, whose footprint in the tree is minimal.

The patch sent by the author is very large, and this chunk of changes
represents something like 10% of the overall patch submitted.

The code compiled is the same before and after this commit, using
objdump to do some validation with a difference taken in-between.  There
are some diffs, which are caused by changes in line numbers because some
of the new allocation formulas are shorter, for the following files:
trgm_regexp.c, xpath.c and pg_walinspect.c.

Author: David Geier <geidav.pg@gmail.com>
Discussion: https://postgr.es/m/ad0748d4-3080-436e-b0bc-ac8f86a3466a@gmail.com
2025-12-05 16:40:26 +09:00

181 lines
3.9 KiB
C

/*
* contrib/intarray/_int_gin.c
*/
#include "postgres.h"
#include "_int.h"
#include "access/gin.h"
#include "access/stratnum.h"
PG_FUNCTION_INFO_V1(ginint4_queryextract);
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 = palloc_array(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)
{
int32 *arr;
int32 i;
res = palloc_array(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);
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);
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
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);
}