Line data Source code
1 : /*
2 : * contrib/intarray/_int_op.c
3 : */
4 : #include "postgres.h"
5 :
6 : #include "_int.h"
7 :
8 1 : PG_MODULE_MAGIC_EXT(
9 : .name = "intarray",
10 : .version = PG_VERSION
11 : );
12 :
13 1 : PG_FUNCTION_INFO_V1(_int_different);
14 1 : PG_FUNCTION_INFO_V1(_int_same);
15 2 : PG_FUNCTION_INFO_V1(_int_contains);
16 2 : PG_FUNCTION_INFO_V1(_int_contained);
17 2 : PG_FUNCTION_INFO_V1(_int_overlap);
18 2 : PG_FUNCTION_INFO_V1(_int_union);
19 2 : PG_FUNCTION_INFO_V1(_int_inter);
20 :
21 : Datum
22 41160 : _int_contained(PG_FUNCTION_ARGS)
23 : {
24 : /* just reverse the operands and call _int_contains */
25 41160 : return DirectFunctionCall2(_int_contains,
26 : PG_GETARG_DATUM(1),
27 : PG_GETARG_DATUM(0));
28 : }
29 :
30 : Datum
31 68284 : _int_contains(PG_FUNCTION_ARGS)
32 : {
33 : /* Force copy so we can modify the arrays in-place */
34 68284 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
35 68284 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
36 : bool res;
37 :
38 68284 : CHECKARRVALID(a);
39 68284 : CHECKARRVALID(b);
40 68284 : PREPAREARR(a);
41 68284 : PREPAREARR(b);
42 68284 : res = inner_int_contains(a, b);
43 68284 : pfree(a);
44 68284 : pfree(b);
45 68284 : PG_RETURN_BOOL(res);
46 : }
47 :
48 : Datum
49 0 : _int_different(PG_FUNCTION_ARGS)
50 : {
51 0 : PG_RETURN_BOOL(!DatumGetBool(DirectFunctionCall2(_int_same,
52 : PointerGetDatum(PG_GETARG_POINTER(0)),
53 : PointerGetDatum(PG_GETARG_POINTER(1)))));
54 : }
55 :
56 : Datum
57 0 : _int_same(PG_FUNCTION_ARGS)
58 : {
59 0 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
60 0 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
61 : int na,
62 : nb;
63 : int n;
64 : int *da,
65 : *db;
66 : bool result;
67 :
68 0 : CHECKARRVALID(a);
69 0 : CHECKARRVALID(b);
70 0 : na = ARRNELEMS(a);
71 0 : nb = ARRNELEMS(b);
72 0 : da = ARRPTR(a);
73 0 : db = ARRPTR(b);
74 :
75 0 : result = false;
76 :
77 0 : if (na == nb)
78 : {
79 0 : SORT(a);
80 0 : SORT(b);
81 0 : result = true;
82 :
83 0 : for (n = 0; n < na; n++)
84 : {
85 0 : if (da[n] != db[n])
86 : {
87 0 : result = false;
88 0 : break;
89 : }
90 : }
91 : }
92 :
93 0 : pfree(a);
94 0 : pfree(b);
95 :
96 0 : PG_RETURN_BOOL(result);
97 : }
98 :
99 : /* _int_overlap -- does a overlap b?
100 : */
101 : Datum
102 7563 : _int_overlap(PG_FUNCTION_ARGS)
103 : {
104 7563 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
105 7563 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
106 : bool result;
107 :
108 7563 : CHECKARRVALID(a);
109 7563 : CHECKARRVALID(b);
110 7563 : if (ARRISEMPTY(a) || ARRISEMPTY(b))
111 9 : PG_RETURN_BOOL(false);
112 :
113 7554 : SORT(a);
114 7554 : SORT(b);
115 :
116 7554 : result = inner_int_overlap(a, b);
117 :
118 7554 : pfree(a);
119 7554 : pfree(b);
120 :
121 7554 : PG_RETURN_BOOL(result);
122 : }
123 :
124 : Datum
125 1 : _int_union(PG_FUNCTION_ARGS)
126 : {
127 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
128 1 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
129 : ArrayType *result;
130 :
131 1 : CHECKARRVALID(a);
132 1 : CHECKARRVALID(b);
133 :
134 1 : SORT(a);
135 1 : SORT(b);
136 :
137 1 : result = inner_int_union(a, b);
138 :
139 1 : pfree(a);
140 1 : pfree(b);
141 :
142 1 : PG_RETURN_POINTER(result);
143 : }
144 :
145 : Datum
146 6 : _int_inter(PG_FUNCTION_ARGS)
147 : {
148 6 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
149 6 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
150 : ArrayType *result;
151 :
152 6 : CHECKARRVALID(a);
153 6 : CHECKARRVALID(b);
154 :
155 6 : SORT(a);
156 6 : SORT(b);
157 :
158 6 : result = inner_int_inter(a, b);
159 :
160 6 : pfree(a);
161 6 : pfree(b);
162 :
163 6 : PG_RETURN_POINTER(result);
164 : }
165 :
166 :
167 2 : PG_FUNCTION_INFO_V1(intset);
168 2 : PG_FUNCTION_INFO_V1(icount);
169 4 : PG_FUNCTION_INFO_V1(sort);
170 2 : PG_FUNCTION_INFO_V1(sort_asc);
171 2 : PG_FUNCTION_INFO_V1(sort_desc);
172 2 : PG_FUNCTION_INFO_V1(uniq);
173 2 : PG_FUNCTION_INFO_V1(idx);
174 3 : PG_FUNCTION_INFO_V1(subarray);
175 2 : PG_FUNCTION_INFO_V1(intarray_push_elem);
176 2 : PG_FUNCTION_INFO_V1(intarray_push_array);
177 2 : PG_FUNCTION_INFO_V1(intarray_del_elem);
178 2 : PG_FUNCTION_INFO_V1(intset_union_elem);
179 2 : PG_FUNCTION_INFO_V1(intset_subtract);
180 :
181 : Datum
182 1 : intset(PG_FUNCTION_ARGS)
183 : {
184 1 : PG_RETURN_POINTER(int_to_intset(PG_GETARG_INT32(0)));
185 : }
186 :
187 : Datum
188 2 : icount(PG_FUNCTION_ARGS)
189 : {
190 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
191 2 : int32 count = ARRNELEMS(a);
192 :
193 2 : PG_FREE_IF_COPY(a, 0);
194 2 : PG_RETURN_INT32(count);
195 : }
196 :
197 : Datum
198 3 : sort(PG_FUNCTION_ARGS)
199 : {
200 3 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
201 3 : text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_PP(1) : NULL;
202 3 : int32 dc = (dirstr) ? VARSIZE_ANY_EXHDR(dirstr) : 0;
203 3 : char *d = (dirstr) ? VARDATA_ANY(dirstr) : NULL;
204 3 : int dir = -1;
205 :
206 3 : CHECKARRVALID(a);
207 3 : if (ARRNELEMS(a) < 2)
208 0 : PG_RETURN_POINTER(a);
209 :
210 3 : if (dirstr == NULL || (dc == 3
211 1 : && (d[0] == 'A' || d[0] == 'a')
212 1 : && (d[1] == 'S' || d[1] == 's')
213 1 : && (d[2] == 'C' || d[2] == 'c')))
214 2 : dir = 1;
215 1 : else if (dc == 4
216 1 : && (d[0] == 'D' || d[0] == 'd')
217 1 : && (d[1] == 'E' || d[1] == 'e')
218 1 : && (d[2] == 'S' || d[2] == 's')
219 1 : && (d[3] == 'C' || d[3] == 'c'))
220 1 : dir = 0;
221 3 : if (dir == -1)
222 0 : ereport(ERROR,
223 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
224 : errmsg("second parameter must be \"ASC\" or \"DESC\"")));
225 3 : QSORT(a, dir);
226 3 : PG_RETURN_POINTER(a);
227 : }
228 :
229 : Datum
230 2 : sort_asc(PG_FUNCTION_ARGS)
231 : {
232 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
233 :
234 2 : CHECKARRVALID(a);
235 2 : QSORT(a, 1);
236 2 : PG_RETURN_POINTER(a);
237 : }
238 :
239 : Datum
240 1 : sort_desc(PG_FUNCTION_ARGS)
241 : {
242 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
243 :
244 1 : CHECKARRVALID(a);
245 1 : QSORT(a, 0);
246 1 : PG_RETURN_POINTER(a);
247 : }
248 :
249 : Datum
250 2 : uniq(PG_FUNCTION_ARGS)
251 : {
252 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
253 :
254 2 : CHECKARRVALID(a);
255 2 : if (ARRNELEMS(a) < 2)
256 0 : PG_RETURN_POINTER(a);
257 2 : a = _int_unique(a);
258 2 : PG_RETURN_POINTER(a);
259 : }
260 :
261 : Datum
262 1 : idx(PG_FUNCTION_ARGS)
263 : {
264 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
265 : int32 result;
266 :
267 1 : CHECKARRVALID(a);
268 1 : result = ARRNELEMS(a);
269 1 : if (result)
270 1 : result = intarray_match_first(a, PG_GETARG_INT32(1));
271 1 : PG_FREE_IF_COPY(a, 0);
272 1 : PG_RETURN_INT32(result);
273 : }
274 :
275 : Datum
276 3 : subarray(PG_FUNCTION_ARGS)
277 : {
278 3 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
279 3 : int32 start = PG_GETARG_INT32(1);
280 3 : int32 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
281 3 : int32 end = 0;
282 : int32 c;
283 : ArrayType *result;
284 :
285 3 : start = (start > 0) ? start - 1 : start;
286 :
287 3 : CHECKARRVALID(a);
288 3 : if (ARRISEMPTY(a))
289 : {
290 0 : PG_FREE_IF_COPY(a, 0);
291 0 : PG_RETURN_POINTER(new_intArrayType(0));
292 : }
293 :
294 3 : c = ARRNELEMS(a);
295 :
296 3 : if (start < 0)
297 1 : start = c + start;
298 :
299 3 : if (len < 0)
300 1 : end = c + len;
301 2 : else if (len == 0)
302 0 : end = c;
303 : else
304 2 : end = start + len;
305 :
306 3 : if (end > c)
307 0 : end = c;
308 :
309 3 : if (start < 0)
310 0 : start = 0;
311 :
312 3 : if (start >= end || end <= 0)
313 : {
314 0 : PG_FREE_IF_COPY(a, 0);
315 0 : PG_RETURN_POINTER(new_intArrayType(0));
316 : }
317 :
318 3 : result = new_intArrayType(end - start);
319 3 : if (end - start > 0)
320 3 : memcpy(ARRPTR(result), ARRPTR(a) + start, (end - start) * sizeof(int32));
321 3 : PG_FREE_IF_COPY(a, 0);
322 3 : PG_RETURN_POINTER(result);
323 : }
324 :
325 : Datum
326 2 : intarray_push_elem(PG_FUNCTION_ARGS)
327 : {
328 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
329 : ArrayType *result;
330 :
331 2 : result = intarray_add_elem(a, PG_GETARG_INT32(1));
332 2 : PG_FREE_IF_COPY(a, 0);
333 2 : PG_RETURN_POINTER(result);
334 : }
335 :
336 : Datum
337 1 : intarray_push_array(PG_FUNCTION_ARGS)
338 : {
339 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
340 1 : ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
341 : ArrayType *result;
342 :
343 1 : result = intarray_concat_arrays(a, b);
344 1 : PG_FREE_IF_COPY(a, 0);
345 1 : PG_FREE_IF_COPY(b, 1);
346 1 : PG_RETURN_POINTER(result);
347 : }
348 :
349 : Datum
350 1 : intarray_del_elem(PG_FUNCTION_ARGS)
351 : {
352 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
353 1 : int32 elem = PG_GETARG_INT32(1);
354 : int32 c;
355 : int32 *aa;
356 1 : int32 n = 0,
357 : i;
358 :
359 1 : CHECKARRVALID(a);
360 1 : if (!ARRISEMPTY(a))
361 : {
362 1 : c = ARRNELEMS(a);
363 1 : aa = ARRPTR(a);
364 4 : for (i = 0; i < c; i++)
365 : {
366 3 : if (aa[i] != elem)
367 : {
368 2 : if (i > n)
369 1 : aa[n++] = aa[i];
370 : else
371 1 : n++;
372 : }
373 : }
374 1 : a = resize_intArrayType(a, n);
375 : }
376 1 : PG_RETURN_POINTER(a);
377 : }
378 :
379 : Datum
380 2 : intset_union_elem(PG_FUNCTION_ARGS)
381 : {
382 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
383 : ArrayType *result;
384 :
385 2 : result = intarray_add_elem(a, PG_GETARG_INT32(1));
386 2 : PG_FREE_IF_COPY(a, 0);
387 2 : QSORT(result, 1);
388 2 : PG_RETURN_POINTER(_int_unique(result));
389 : }
390 :
391 : Datum
392 1 : intset_subtract(PG_FUNCTION_ARGS)
393 : {
394 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
395 1 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
396 : ArrayType *result;
397 : int32 ca;
398 : int32 cb;
399 : int32 *aa,
400 : *bb,
401 : *r;
402 1 : int32 n = 0,
403 1 : i = 0,
404 1 : k = 0;
405 :
406 1 : CHECKARRVALID(a);
407 1 : CHECKARRVALID(b);
408 :
409 1 : QSORT(a, 1);
410 1 : a = _int_unique(a);
411 1 : ca = ARRNELEMS(a);
412 1 : QSORT(b, 1);
413 1 : b = _int_unique(b);
414 1 : cb = ARRNELEMS(b);
415 1 : result = new_intArrayType(ca);
416 1 : aa = ARRPTR(a);
417 1 : bb = ARRPTR(b);
418 1 : r = ARRPTR(result);
419 4 : while (i < ca)
420 : {
421 3 : if (k == cb || aa[i] < bb[k])
422 2 : r[n++] = aa[i++];
423 1 : else if (aa[i] == bb[k])
424 : {
425 1 : i++;
426 1 : k++;
427 : }
428 : else
429 0 : k++;
430 : }
431 1 : result = resize_intArrayType(result, n);
432 1 : pfree(a);
433 1 : pfree(b);
434 1 : PG_RETURN_POINTER(result);
435 : }
|