PostgreSQL Source Code git master
ginarrayproc.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * ginarrayproc.c
4 * support functions for GIN's indexing of any array
5 *
6 *
7 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
9 *
10 * IDENTIFICATION
11 * src/backend/access/gin/ginarrayproc.c
12 *-------------------------------------------------------------------------
13 */
14#include "postgres.h"
15
16#include "access/gin.h"
17#include "access/stratnum.h"
18#include "utils/array.h"
19#include "utils/fmgrprotos.h"
20#include "utils/lsyscache.h"
21
22
23#define GinOverlapStrategy 1
24#define GinContainsStrategy 2
25#define GinContainedStrategy 3
26#define GinEqualStrategy 4
27
28
29/*
30 * extractValue support function
31 */
34{
35 /* Make copy of array input to ensure it doesn't disappear while in use */
37 int32 *nkeys = (int32 *) PG_GETARG_POINTER(1);
38 bool **nullFlags = (bool **) PG_GETARG_POINTER(2);
39 int16 elmlen;
40 bool elmbyval;
41 char elmalign;
42 Datum *elems;
43 bool *nulls;
44 int nelems;
45
47 &elmlen, &elmbyval, &elmalign);
48
50 ARR_ELEMTYPE(array),
51 elmlen, elmbyval, elmalign,
52 &elems, &nulls, &nelems);
53
54 *nkeys = nelems;
55 *nullFlags = nulls;
56
57 /* we should not free array, elems[i] points into it */
58 PG_RETURN_POINTER(elems);
59}
60
61/*
62 * Formerly, ginarrayextract had only two arguments. Now it has three,
63 * but we still need a pg_proc entry with two args to support reloading
64 * pre-9.1 contrib/intarray opclass declarations. This compatibility
65 * function should go away eventually.
66 */
69{
70 if (PG_NARGS() < 3) /* should not happen */
71 elog(ERROR, "ginarrayextract requires three arguments");
72 return ginarrayextract(fcinfo);
73}
74
75/*
76 * extractQuery support function
77 */
80{
81 /* Make copy of array input to ensure it doesn't disappear while in use */
83 int32 *nkeys = (int32 *) PG_GETARG_POINTER(1);
84 StrategyNumber strategy = PG_GETARG_UINT16(2);
85
86 /* bool **pmatch = (bool **) PG_GETARG_POINTER(3); */
87 /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
88 bool **nullFlags = (bool **) PG_GETARG_POINTER(5);
89 int32 *searchMode = (int32 *) PG_GETARG_POINTER(6);
90 int16 elmlen;
91 bool elmbyval;
92 char elmalign;
93 Datum *elems;
94 bool *nulls;
95 int nelems;
96
98 &elmlen, &elmbyval, &elmalign);
99
100 deconstruct_array(array,
101 ARR_ELEMTYPE(array),
102 elmlen, elmbyval, elmalign,
103 &elems, &nulls, &nelems);
104
105 *nkeys = nelems;
106 *nullFlags = nulls;
107
108 switch (strategy)
109 {
111 *searchMode = GIN_SEARCH_MODE_DEFAULT;
112 break;
114 if (nelems > 0)
115 *searchMode = GIN_SEARCH_MODE_DEFAULT;
116 else /* everything contains the empty set */
117 *searchMode = GIN_SEARCH_MODE_ALL;
118 break;
120 /* empty set is contained in everything */
121 *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
122 break;
123 case GinEqualStrategy:
124 if (nelems > 0)
125 *searchMode = GIN_SEARCH_MODE_DEFAULT;
126 else
127 *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
128 break;
129 default:
130 elog(ERROR, "ginqueryarrayextract: unknown strategy number: %d",
131 strategy);
132 }
133
134 /* we should not free array, elems[i] points into it */
135 PG_RETURN_POINTER(elems);
136}
137
138/*
139 * consistent support function
140 */
141Datum
143{
144 bool *check = (bool *) PG_GETARG_POINTER(0);
145 StrategyNumber strategy = PG_GETARG_UINT16(1);
146
147 /* ArrayType *query = PG_GETARG_ARRAYTYPE_P(2); */
148 int32 nkeys = PG_GETARG_INT32(3);
149
150 /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
151 bool *recheck = (bool *) PG_GETARG_POINTER(5);
152
153 /* Datum *queryKeys = (Datum *) PG_GETARG_POINTER(6); */
154 bool *nullFlags = (bool *) PG_GETARG_POINTER(7);
155 bool res;
156 int32 i;
157
158 switch (strategy)
159 {
161 /* result is not lossy */
162 *recheck = false;
163 /* must have a match for at least one non-null element */
164 res = false;
165 for (i = 0; i < nkeys; i++)
166 {
167 if (check[i] && !nullFlags[i])
168 {
169 res = true;
170 break;
171 }
172 }
173 break;
175 /* result is not lossy */
176 *recheck = false;
177 /* must have all elements in check[] true, and no nulls */
178 res = true;
179 for (i = 0; i < nkeys; i++)
180 {
181 if (!check[i] || nullFlags[i])
182 {
183 res = false;
184 break;
185 }
186 }
187 break;
189 /* we will need recheck */
190 *recheck = true;
191 /* can't do anything else useful here */
192 res = true;
193 break;
194 case GinEqualStrategy:
195 /* we will need recheck */
196 *recheck = true;
197
198 /*
199 * Must have all elements in check[] true; no discrimination
200 * against nulls here. This is because array_contain_compare and
201 * array_eq handle nulls differently ...
202 */
203 res = true;
204 for (i = 0; i < nkeys; i++)
205 {
206 if (!check[i])
207 {
208 res = false;
209 break;
210 }
211 }
212 break;
213 default:
214 elog(ERROR, "ginarrayconsistent: unknown strategy number: %d",
215 strategy);
216 res = false;
217 }
218
220}
221
222/*
223 * triconsistent support function
224 */
225Datum
227{
229 StrategyNumber strategy = PG_GETARG_UINT16(1);
230
231 /* ArrayType *query = PG_GETARG_ARRAYTYPE_P(2); */
232 int32 nkeys = PG_GETARG_INT32(3);
233
234 /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
235 /* Datum *queryKeys = (Datum *) PG_GETARG_POINTER(5); */
236 bool *nullFlags = (bool *) PG_GETARG_POINTER(6);
238 int32 i;
239
240 switch (strategy)
241 {
243 /* must have a match for at least one non-null element */
244 res = GIN_FALSE;
245 for (i = 0; i < nkeys; i++)
246 {
247 if (!nullFlags[i])
248 {
249 if (check[i] == GIN_TRUE)
250 {
251 res = GIN_TRUE;
252 break;
253 }
254 else if (check[i] == GIN_MAYBE && res == GIN_FALSE)
255 {
256 res = GIN_MAYBE;
257 }
258 }
259 }
260 break;
262 /* must have all elements in check[] true, and no nulls */
263 res = GIN_TRUE;
264 for (i = 0; i < nkeys; i++)
265 {
266 if (check[i] == GIN_FALSE || nullFlags[i])
267 {
268 res = GIN_FALSE;
269 break;
270 }
271 if (check[i] == GIN_MAYBE)
272 {
273 res = GIN_MAYBE;
274 }
275 }
276 break;
278 /* can't do anything else useful here */
279 res = GIN_MAYBE;
280 break;
281 case GinEqualStrategy:
282
283 /*
284 * Must have all elements in check[] true; no discrimination
285 * against nulls here. This is because array_contain_compare and
286 * array_eq handle nulls differently ...
287 */
288 res = GIN_MAYBE;
289 for (i = 0; i < nkeys; i++)
290 {
291 if (check[i] == GIN_FALSE)
292 {
293 res = GIN_FALSE;
294 break;
295 }
296 }
297 break;
298 default:
299 elog(ERROR, "ginarrayconsistent: unknown strategy number: %d",
300 strategy);
301 res = false;
302 }
303
305}
#define PG_GETARG_ARRAYTYPE_P_COPY(n)
Definition: array.h:264
#define ARR_ELEMTYPE(a)
Definition: array.h:292
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3631
int16_t int16
Definition: c.h:483
int32_t int32
Definition: c.h:484
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_NARGS()
Definition: fmgr.h:203
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:272
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_RETURN_GIN_TERNARY_VALUE(x)
Definition: gin.h:79
#define GIN_SEARCH_MODE_ALL
Definition: gin.h:36
#define GIN_FALSE
Definition: gin.h:63
#define GIN_SEARCH_MODE_DEFAULT
Definition: gin.h:34
char GinTernaryValue
Definition: gin.h:58
#define GIN_SEARCH_MODE_INCLUDE_EMPTY
Definition: gin.h:35
#define GIN_MAYBE
Definition: gin.h:65
#define GIN_TRUE
Definition: gin.h:64
Datum ginarraytriconsistent(PG_FUNCTION_ARGS)
Definition: ginarrayproc.c:226
Datum ginarrayextract_2args(PG_FUNCTION_ARGS)
Definition: ginarrayproc.c:68
#define GinEqualStrategy
Definition: ginarrayproc.c:26
Datum ginarrayextract(PG_FUNCTION_ARGS)
Definition: ginarrayproc.c:33
Datum ginarrayconsistent(PG_FUNCTION_ARGS)
Definition: ginarrayproc.c:142
#define GinOverlapStrategy
Definition: ginarrayproc.c:23
#define GinContainedStrategy
Definition: ginarrayproc.c:25
#define GinContainsStrategy
Definition: ginarrayproc.c:24
Datum ginqueryarrayextract(PG_FUNCTION_ARGS)
Definition: ginarrayproc.c:79
int i
Definition: isn.c:72
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2298
uintptr_t Datum
Definition: postgres.h:69
uint16 StrategyNumber
Definition: stratnum.h:22