1 /*
2  * contrib/intarray/_int_gin.c
3  */
4 #include "postgres.h"
5 
6 #include "_int.h"
7 #include "access/gin.h"
8 #include "access/stratnum.h"
9 
10 PG_FUNCTION_INFO_V1(ginint4_queryextract);
11 
12 Datum
ginint4_queryextract(PG_FUNCTION_ARGS)13 ginint4_queryextract(PG_FUNCTION_ARGS)
14 {
15 	int32	   *nentries = (int32 *) PG_GETARG_POINTER(1);
16 	StrategyNumber strategy = PG_GETARG_UINT16(2);
17 	int32	   *searchMode = (int32 *) PG_GETARG_POINTER(6);
18 	Datum	   *res = NULL;
19 
20 	*nentries = 0;
21 
22 	if (strategy == BooleanSearchStrategy)
23 	{
24 		QUERYTYPE  *query = PG_GETARG_QUERYTYPE_P(0);
25 		ITEM	   *items = GETQUERY(query);
26 		int			i;
27 
28 		/* empty query must fail */
29 		if (query->size <= 0)
30 			PG_RETURN_POINTER(NULL);
31 
32 		/*
33 		 * If the query doesn't have any required primitive values (for
34 		 * instance, it's something like '! 42'), we have to do a full index
35 		 * scan.
36 		 */
37 		if (query_has_required_values(query))
38 			*searchMode = GIN_SEARCH_MODE_DEFAULT;
39 		else
40 			*searchMode = GIN_SEARCH_MODE_ALL;
41 
42 		/*
43 		 * Extract all the VAL items as things we want GIN to check for.
44 		 */
45 		res = (Datum *) palloc(sizeof(Datum) * query->size);
46 		*nentries = 0;
47 
48 		for (i = 0; i < query->size; i++)
49 		{
50 			if (items[i].type == VAL)
51 			{
52 				res[*nentries] = Int32GetDatum(items[i].val);
53 				(*nentries)++;
54 			}
55 		}
56 	}
57 	else
58 	{
59 		ArrayType  *query = PG_GETARG_ARRAYTYPE_P(0);
60 
61 		CHECKARRVALID(query);
62 		*nentries = ARRNELEMS(query);
63 		if (*nentries > 0)
64 		{
65 			int32	   *arr;
66 			int32		i;
67 
68 			res = (Datum *) palloc(sizeof(Datum) * (*nentries));
69 
70 			arr = ARRPTR(query);
71 			for (i = 0; i < *nentries; i++)
72 				res[i] = Int32GetDatum(arr[i]);
73 		}
74 
75 		switch (strategy)
76 		{
77 			case RTOverlapStrategyNumber:
78 				*searchMode = GIN_SEARCH_MODE_DEFAULT;
79 				break;
80 			case RTContainedByStrategyNumber:
81 			case RTOldContainedByStrategyNumber:
82 				/* empty set is contained in everything */
83 				*searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
84 				break;
85 			case RTSameStrategyNumber:
86 				if (*nentries > 0)
87 					*searchMode = GIN_SEARCH_MODE_DEFAULT;
88 				else
89 					*searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
90 				break;
91 			case RTContainsStrategyNumber:
92 			case RTOldContainsStrategyNumber:
93 				if (*nentries > 0)
94 					*searchMode = GIN_SEARCH_MODE_DEFAULT;
95 				else			/* everything contains the empty set */
96 					*searchMode = GIN_SEARCH_MODE_ALL;
97 				break;
98 			default:
99 				elog(ERROR, "ginint4_queryextract: unknown strategy number: %d",
100 					 strategy);
101 		}
102 	}
103 
104 	PG_RETURN_POINTER(res);
105 }
106 
107 PG_FUNCTION_INFO_V1(ginint4_consistent);
108 
109 Datum
ginint4_consistent(PG_FUNCTION_ARGS)110 ginint4_consistent(PG_FUNCTION_ARGS)
111 {
112 	bool	   *check = (bool *) PG_GETARG_POINTER(0);
113 	StrategyNumber strategy = PG_GETARG_UINT16(1);
114 	int32		nkeys = PG_GETARG_INT32(3);
115 
116 	/* Pointer	   *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
117 	bool	   *recheck = (bool *) PG_GETARG_POINTER(5);
118 	bool		res = false;
119 	int32		i;
120 
121 	switch (strategy)
122 	{
123 		case RTOverlapStrategyNumber:
124 			/* result is not lossy */
125 			*recheck = false;
126 			/* at least one element in check[] is true, so result = true */
127 			res = true;
128 			break;
129 		case RTContainedByStrategyNumber:
130 		case RTOldContainedByStrategyNumber:
131 			/* we will need recheck */
132 			*recheck = true;
133 			/* at least one element in check[] is true, so result = true */
134 			res = true;
135 			break;
136 		case RTSameStrategyNumber:
137 			/* we will need recheck */
138 			*recheck = true;
139 			/* Must have all elements in check[] true */
140 			res = true;
141 			for (i = 0; i < nkeys; i++)
142 			{
143 				if (!check[i])
144 				{
145 					res = false;
146 					break;
147 				}
148 			}
149 			break;
150 		case RTContainsStrategyNumber:
151 		case RTOldContainsStrategyNumber:
152 			/* result is not lossy */
153 			*recheck = false;
154 			/* Must have all elements in check[] true */
155 			res = true;
156 			for (i = 0; i < nkeys; i++)
157 			{
158 				if (!check[i])
159 				{
160 					res = false;
161 					break;
162 				}
163 			}
164 			break;
165 		case BooleanSearchStrategy:
166 			{
167 				QUERYTYPE  *query = PG_GETARG_QUERYTYPE_P(2);
168 
169 				/* result is not lossy */
170 				*recheck = false;
171 				res = gin_bool_consistent(query, check);
172 			}
173 			break;
174 		default:
175 			elog(ERROR, "ginint4_consistent: unknown strategy number: %d",
176 				 strategy);
177 	}
178 
179 	PG_RETURN_BOOL(res);
180 }
181