mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-29 22:49:41 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			170 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * $PostgreSQL: pgsql/contrib/intarray/_int_gin.c,v 1.10 2009/06/11 14:48:51 momjian Exp $
 | |
|  */
 | |
| #include "postgres.h"
 | |
| 
 | |
| #include "access/gist.h"
 | |
| #include "access/skey.h"
 | |
| 
 | |
| #include "_int.h"
 | |
| 
 | |
| PG_FUNCTION_INFO_V1(ginint4_queryextract);
 | |
| 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);
 | |
| 	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]);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (nentries == 0)
 | |
| 	{
 | |
| 		switch (strategy)
 | |
| 		{
 | |
| 			case BooleanSearchStrategy:
 | |
| 			case RTOverlapStrategyNumber:
 | |
| 				*nentries = -1; /* nobody can be found */
 | |
| 				break;
 | |
| 			default:			/* require fullscan: GIN can't find void
 | |
| 								 * arrays */
 | |
| 				break;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	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);
 | |
| 
 | |
| 	/* int32	nkeys = PG_GETARG_INT32(3); */
 | |
| 	/* Pointer	   *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
 | |
| 	bool	   *recheck = (bool *) PG_GETARG_POINTER(5);
 | |
| 	bool		res = FALSE;
 | |
| 
 | |
| 	/*
 | |
| 	 * we need not check array carefully, it's done by previous
 | |
| 	 * ginarrayextract call
 | |
| 	 */
 | |
| 
 | |
| 	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:
 | |
| 			{
 | |
| 				ArrayType  *query = PG_GETARG_ARRAYTYPE_P(2);
 | |
| 				int			i,
 | |
| 							nentries = ARRNELEMS(query);
 | |
| 
 | |
| 				/* we will need recheck */
 | |
| 				*recheck = true;
 | |
| 				res = TRUE;
 | |
| 				for (i = 0; i < nentries; i++)
 | |
| 					if (!check[i])
 | |
| 					{
 | |
| 						res = FALSE;
 | |
| 						break;
 | |
| 					}
 | |
| 			}
 | |
| 			break;
 | |
| 		case RTContainsStrategyNumber:
 | |
| 		case RTOldContainsStrategyNumber:
 | |
| 			{
 | |
| 				ArrayType  *query = PG_GETARG_ARRAYTYPE_P(2);
 | |
| 				int			i,
 | |
| 							nentries = ARRNELEMS(query);
 | |
| 
 | |
| 				/* result is not lossy */
 | |
| 				*recheck = false;
 | |
| 				res = TRUE;
 | |
| 				for (i = 0; i < nentries; i++)
 | |
| 					if (!check[i])
 | |
| 					{
 | |
| 						res = FALSE;
 | |
| 						break;
 | |
| 					}
 | |
| 			}
 | |
| 			break;
 | |
| 		case BooleanSearchStrategy:
 | |
| 			{
 | |
| 				QUERYTYPE  *query = (QUERYTYPE *) PG_DETOAST_DATUM(PG_GETARG_POINTER(2));
 | |
| 
 | |
| 				/* result is not lossy */
 | |
| 				*recheck = false;
 | |
| 				res = ginconsistent(query, check);
 | |
| 			}
 | |
| 			break;
 | |
| 		default:
 | |
| 			elog(ERROR, "ginint4_consistent: unknown strategy number: %d",
 | |
| 				 strategy);
 | |
| 	}
 | |
| 
 | |
| 	PG_RETURN_BOOL(res);
 | |
| }
 |