1818#include "miscadmin.h"
1919#include "utils/array.h"
2020#include "utils/builtins.h"
21+ #include "utils/lsyscache.h"
2122#include "utils/typcache.h"
2223
2324#include "rum.h"
2425
2526#include <math.h>
2627
2728
29+ #define RumOverlapStrategy 1
30+ #define RumContainsStrategy 2
31+ #define RumContainedStrategy 3
32+ #define RumEqualStrategy 4
33+ #define RumSimilarStrategy 5
34+
35+
2836PG_FUNCTION_INFO_V1 (rum_anyarray_config );
2937
38+ PG_FUNCTION_INFO_V1 (rum_extract_anyarray );
39+ PG_FUNCTION_INFO_V1 (rum_extract_anyarray_query );
40+
41+ PG_FUNCTION_INFO_V1 (rum_anyarray_consistent );
42+
43+ PG_FUNCTION_INFO_V1 (rum_anyarray_similar );
44+ PG_FUNCTION_INFO_V1 (rum_anyarray_distance );
45+
3046
3147/*
3248 * Specifies additional information type for operator class.
@@ -41,3 +57,239 @@ rum_anyarray_config(PG_FUNCTION_ARGS)
4157
4258 PG_RETURN_VOID ();
4359}
60+
61+
62+ /* ginarrayextract() */
63+ Datum
64+ rum_extract_anyarray (PG_FUNCTION_ARGS )
65+ {
66+ /* Make copy of array input to ensure it doesn't disappear while in use */
67+ ArrayType * array = PG_GETARG_ARRAYTYPE_P_COPY (0 );
68+
69+ Datum * entries ;
70+ int32 * nentries = (int32 * ) PG_GETARG_POINTER (1 );
71+ bool * * entries_isnull = (bool * * ) PG_GETARG_POINTER (2 );
72+
73+ Datum * * addInfo = (Datum * * ) PG_GETARG_POINTER (3 );
74+ bool * * addInfoIsNull = (bool * * ) PG_GETARG_POINTER (4 );
75+
76+ int16 elmlen ;
77+ bool elmbyval ;
78+ char elmalign ;
79+ int i ;
80+
81+ get_typlenbyvalalign (ARR_ELEMTYPE (array ),
82+ & elmlen , & elmbyval , & elmalign );
83+
84+ deconstruct_array (array ,
85+ ARR_ELEMTYPE (array ),
86+ elmlen , elmbyval , elmalign ,
87+ & entries , entries_isnull , nentries );
88+
89+ * addInfo = (Datum * ) palloc (* nentries * sizeof (Datum ));
90+ * addInfoIsNull = (bool * ) palloc (* nentries * sizeof (bool ));
91+
92+ for (i = 0 ; i < * nentries ; i ++ )
93+ {
94+ /* Use array's size as additional info */
95+ (* addInfo )[i ] = Int32GetDatum (* nentries );
96+ (* addInfoIsNull )[i ] = BoolGetDatum (false);
97+ }
98+
99+ /* we should not free array, entries[i] points into it */
100+ PG_RETURN_POINTER (entries );
101+ }
102+
103+ /* ginqueryarrayextract() */
104+ Datum
105+ rum_extract_anyarray_query (PG_FUNCTION_ARGS )
106+ {
107+ /* Make copy of array input to ensure it doesn't disappear while in use */
108+ ArrayType * array = PG_GETARG_ARRAYTYPE_P_COPY (0 );
109+
110+ Datum * entries ;
111+ int32 * nentries = (int32 * ) PG_GETARG_POINTER (1 );
112+ bool * * entries_isnull = (bool * * ) PG_GETARG_POINTER (5 );
113+
114+ StrategyNumber strategy = PG_GETARG_UINT16 (2 );
115+
116+ /* bool **pmatch = (bool **) PG_GETARG_POINTER(3); */
117+ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
118+
119+ int32 * searchMode = (int32 * ) PG_GETARG_POINTER (6 );
120+
121+ int16 elmlen ;
122+ bool elmbyval ;
123+ char elmalign ;
124+
125+ get_typlenbyvalalign (ARR_ELEMTYPE (array ),
126+ & elmlen , & elmbyval , & elmalign );
127+
128+ deconstruct_array (array ,
129+ ARR_ELEMTYPE (array ),
130+ elmlen , elmbyval , elmalign ,
131+ & entries , entries_isnull , nentries );
132+
133+ switch (strategy )
134+ {
135+ case RumOverlapStrategy :
136+ * searchMode = GIN_SEARCH_MODE_DEFAULT ;
137+ break ;
138+ case RumContainsStrategy :
139+ if (* nentries > 0 )
140+ * searchMode = GIN_SEARCH_MODE_DEFAULT ;
141+ else /* everything contains the empty set */
142+ * searchMode = GIN_SEARCH_MODE_ALL ;
143+ break ;
144+ case RumContainedStrategy :
145+ /* empty set is contained in everything */
146+ * searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY ;
147+ break ;
148+ case RumEqualStrategy :
149+ if (* nentries > 0 )
150+ * searchMode = GIN_SEARCH_MODE_DEFAULT ;
151+ else
152+ * searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY ;
153+ break ;
154+ case RumSimilarStrategy :
155+ if (* nentries > 0 )
156+ * searchMode = GIN_SEARCH_MODE_DEFAULT ;
157+ else
158+ * searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY ;
159+ break ;
160+ default :
161+ elog (ERROR , "rum_extract_anyarray_query: unknown strategy number: %d" ,
162+ strategy );
163+ }
164+
165+ /* we should not free array, elems[i] points into it */
166+ PG_RETURN_POINTER (entries );
167+ }
168+
169+
170+
171+ /* ginarrayconsistent() */
172+ Datum
173+ rum_anyarray_consistent (PG_FUNCTION_ARGS )
174+ {
175+ bool * check = (bool * ) PG_GETARG_POINTER (0 );
176+
177+ StrategyNumber strategy = PG_GETARG_UINT16 (1 );
178+
179+ /* ArrayType *query = PG_GETARG_ARRAYTYPE_P(2); */
180+ int32 nkeys = PG_GETARG_INT32 (3 );
181+
182+ /* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
183+ bool * recheck = (bool * ) PG_GETARG_POINTER (5 );
184+
185+ /* Datum *queryKeys = (Datum *) PG_GETARG_POINTER(6); */
186+ bool * nullFlags = (bool * ) PG_GETARG_POINTER (7 );
187+
188+ Datum * addInfo = (Datum * ) PG_GETARG_POINTER (8 );
189+ bool * addInfoIsNull = (bool * ) PG_GETARG_POINTER (9 );
190+
191+ bool res ;
192+ int32 i ;
193+
194+ switch (strategy )
195+ {
196+ case RumOverlapStrategy :
197+ /* result is not lossy */
198+ * recheck = false;
199+ /* must have a match for at least one non-null element */
200+ res = false;
201+ for (i = 0 ; i < nkeys ; i ++ )
202+ {
203+ if (check [i ] && !nullFlags [i ])
204+ {
205+ res = true;
206+ break ;
207+ }
208+ }
209+ break ;
210+ case RumContainsStrategy :
211+ /* result is not lossy */
212+ * recheck = false;
213+
214+ /* must have all elements in check[] true, and no nulls */
215+ res = true;
216+ for (i = 0 ; i < nkeys ; i ++ )
217+ {
218+ if (!check [i ] || nullFlags [i ])
219+ {
220+ res = false;
221+ break ;
222+ }
223+ }
224+ break ;
225+ case RumContainedStrategy :
226+ /* we will need recheck */
227+ * recheck = true;
228+
229+ /* query must have <= amount of elements than array */
230+ res = true;
231+ for (i = 0 ; i < nkeys ; i ++ )
232+ {
233+ if (!addInfoIsNull [i ] && DatumGetInt32 (addInfo [i ]) > nkeys )
234+ {
235+ res = false;
236+ break ;
237+ }
238+ }
239+ break ;
240+ case RumEqualStrategy :
241+ /* we will need recheck */
242+ * recheck = true;
243+
244+ /*
245+ * Must have all elements in check[] true; no discrimination
246+ * against nulls here. This is because array_contain_compare and
247+ * array_eq handle nulls differently ...
248+ *
249+ * Also, query and array must have equal amount of elements.
250+ */
251+ res = true;
252+ for (i = 0 ; i < nkeys ; i ++ )
253+ {
254+ if (!check [i ])
255+ {
256+ res = false;
257+ break ;
258+ }
259+
260+ if (!addInfoIsNull [i ] && DatumGetInt32 (addInfo [i ]) != nkeys )
261+ {
262+ res = false;
263+ break ;
264+ }
265+ }
266+ break ;
267+ case RumSimilarStrategy :
268+ /* we will need recheck */
269+ * recheck = true;
270+
271+ /* can't do anything else useful here */
272+ res = true;
273+ break ;
274+ default :
275+ elog (ERROR , "rum_anyarray_consistent: unknown strategy number: %d" ,
276+ strategy );
277+ res = false;
278+ }
279+
280+ PG_RETURN_BOOL (res );
281+ }
282+
283+
284+
285+ Datum
286+ rum_anyarray_similar (PG_FUNCTION_ARGS )
287+ {
288+ PG_RETURN_BOOL (true);
289+ }
290+
291+ Datum
292+ rum_anyarray_distance (PG_FUNCTION_ARGS )
293+ {
294+ PG_RETURN_FLOAT8 (0.0 );
295+ }
0 commit comments