mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-03 09:13:20 +03:00 
			
		
		
		
	For upcoming BRIN opclasses, it's convenient to have strategy numbers defined in a single place. Since there's nothing appropriate, create it. The StrategyNumber typedef now lives there, as well as existing strategy numbers for B-trees (from skey.h) and R-tree-and-friends (from gist.h). skey.h is forced to include stratnum.h because of the StrategyNumber typedef, but gist.h is not; extensions that currently rely on gist.h for rtree strategy numbers might need to add a new A few .c files can stop including skey.h and/or gist.h, which is a nice side benefit. Per discussion: https://www.postgresql.org/message-id/20150514232132.GZ2523@alvh.no-ip.org Authored by Emre Hasegeli and Álvaro. (It's not clear to me why bootscanner.l has any #include lines at all.)
		
			
				
	
	
		
			182 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * contrib/intarray/_int_gin.c
 | 
						|
 */
 | 
						|
#include "postgres.h"
 | 
						|
 | 
						|
#include "access/gin.h"
 | 
						|
#include "access/stratnum.h"
 | 
						|
 | 
						|
#include "_int.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 = (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)
 | 
						|
		{
 | 
						|
			int32	   *arr;
 | 
						|
			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);
 | 
						|
 | 
						|
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);
 | 
						|
}
 |