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 : /*
100 : * _int_overlap -- does a overlap b?
101 : */
102 : Datum
103 7563 : _int_overlap(PG_FUNCTION_ARGS)
104 : {
105 7563 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
106 7563 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
107 : bool result;
108 :
109 7563 : CHECKARRVALID(a);
110 7563 : CHECKARRVALID(b);
111 7563 : if (ARRISEMPTY(a) || ARRISEMPTY(b))
112 9 : PG_RETURN_BOOL(false);
113 :
114 7554 : SORT(a);
115 7554 : SORT(b);
116 :
117 7554 : result = inner_int_overlap(a, b);
118 :
119 7554 : pfree(a);
120 7554 : pfree(b);
121 :
122 7554 : PG_RETURN_BOOL(result);
123 : }
124 :
125 : Datum
126 1 : _int_union(PG_FUNCTION_ARGS)
127 : {
128 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
129 1 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
130 : ArrayType *result;
131 :
132 1 : CHECKARRVALID(a);
133 1 : CHECKARRVALID(b);
134 :
135 1 : SORT(a);
136 1 : SORT(b);
137 :
138 1 : result = inner_int_union(a, b);
139 :
140 1 : pfree(a);
141 1 : pfree(b);
142 :
143 1 : PG_RETURN_POINTER(result);
144 : }
145 :
146 : Datum
147 6 : _int_inter(PG_FUNCTION_ARGS)
148 : {
149 6 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
150 6 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
151 : ArrayType *result;
152 :
153 6 : CHECKARRVALID(a);
154 6 : CHECKARRVALID(b);
155 :
156 6 : SORT(a);
157 6 : SORT(b);
158 :
159 6 : result = inner_int_inter(a, b);
160 :
161 6 : pfree(a);
162 6 : pfree(b);
163 :
164 6 : PG_RETURN_POINTER(result);
165 : }
166 :
167 :
168 2 : PG_FUNCTION_INFO_V1(intset);
169 2 : PG_FUNCTION_INFO_V1(icount);
170 4 : PG_FUNCTION_INFO_V1(sort);
171 2 : PG_FUNCTION_INFO_V1(sort_asc);
172 2 : PG_FUNCTION_INFO_V1(sort_desc);
173 2 : PG_FUNCTION_INFO_V1(uniq);
174 2 : PG_FUNCTION_INFO_V1(idx);
175 3 : PG_FUNCTION_INFO_V1(subarray);
176 2 : PG_FUNCTION_INFO_V1(intarray_push_elem);
177 2 : PG_FUNCTION_INFO_V1(intarray_push_array);
178 2 : PG_FUNCTION_INFO_V1(intarray_del_elem);
179 2 : PG_FUNCTION_INFO_V1(intset_union_elem);
180 2 : PG_FUNCTION_INFO_V1(intset_subtract);
181 :
182 : Datum
183 1 : intset(PG_FUNCTION_ARGS)
184 : {
185 1 : PG_RETURN_POINTER(int_to_intset(PG_GETARG_INT32(0)));
186 : }
187 :
188 : Datum
189 2 : icount(PG_FUNCTION_ARGS)
190 : {
191 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
192 2 : int32 count = ARRNELEMS(a);
193 :
194 2 : PG_FREE_IF_COPY(a, 0);
195 2 : PG_RETURN_INT32(count);
196 : }
197 :
198 : Datum
199 3 : sort(PG_FUNCTION_ARGS)
200 : {
201 3 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
202 3 : text *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_PP(1) : NULL;
203 3 : int32 dc = (dirstr) ? VARSIZE_ANY_EXHDR(dirstr) : 0;
204 3 : char *d = (dirstr) ? VARDATA_ANY(dirstr) : NULL;
205 3 : int dir = -1;
206 :
207 3 : CHECKARRVALID(a);
208 3 : if (ARRNELEMS(a) < 2)
209 0 : PG_RETURN_POINTER(a);
210 :
211 3 : if (dirstr == NULL || (dc == 3
212 1 : && (d[0] == 'A' || d[0] == 'a')
213 1 : && (d[1] == 'S' || d[1] == 's')
214 1 : && (d[2] == 'C' || d[2] == 'c')))
215 2 : dir = 1;
216 1 : else if (dc == 4
217 1 : && (d[0] == 'D' || d[0] == 'd')
218 1 : && (d[1] == 'E' || d[1] == 'e')
219 1 : && (d[2] == 'S' || d[2] == 's')
220 1 : && (d[3] == 'C' || d[3] == 'c'))
221 1 : dir = 0;
222 3 : if (dir == -1)
223 0 : ereport(ERROR,
224 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
225 : errmsg("second parameter must be \"ASC\" or \"DESC\"")));
226 3 : QSORT(a, dir);
227 3 : PG_RETURN_POINTER(a);
228 : }
229 :
230 : Datum
231 2 : sort_asc(PG_FUNCTION_ARGS)
232 : {
233 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
234 :
235 2 : CHECKARRVALID(a);
236 2 : QSORT(a, 1);
237 2 : PG_RETURN_POINTER(a);
238 : }
239 :
240 : Datum
241 1 : sort_desc(PG_FUNCTION_ARGS)
242 : {
243 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
244 :
245 1 : CHECKARRVALID(a);
246 1 : QSORT(a, 0);
247 1 : PG_RETURN_POINTER(a);
248 : }
249 :
250 : Datum
251 2 : uniq(PG_FUNCTION_ARGS)
252 : {
253 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
254 :
255 2 : CHECKARRVALID(a);
256 2 : if (ARRNELEMS(a) < 2)
257 0 : PG_RETURN_POINTER(a);
258 2 : a = _int_unique(a);
259 2 : PG_RETURN_POINTER(a);
260 : }
261 :
262 : Datum
263 1 : idx(PG_FUNCTION_ARGS)
264 : {
265 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
266 : int32 result;
267 :
268 1 : CHECKARRVALID(a);
269 1 : result = ARRNELEMS(a);
270 1 : if (result)
271 1 : result = intarray_match_first(a, PG_GETARG_INT32(1));
272 1 : PG_FREE_IF_COPY(a, 0);
273 1 : PG_RETURN_INT32(result);
274 : }
275 :
276 : Datum
277 3 : subarray(PG_FUNCTION_ARGS)
278 : {
279 3 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
280 3 : int32 start = PG_GETARG_INT32(1);
281 3 : int32 len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
282 3 : int32 end = 0;
283 : int32 c;
284 : ArrayType *result;
285 :
286 3 : start = (start > 0) ? start - 1 : start;
287 :
288 3 : CHECKARRVALID(a);
289 3 : if (ARRISEMPTY(a))
290 : {
291 0 : PG_FREE_IF_COPY(a, 0);
292 0 : PG_RETURN_POINTER(new_intArrayType(0));
293 : }
294 :
295 3 : c = ARRNELEMS(a);
296 :
297 3 : if (start < 0)
298 1 : start = c + start;
299 :
300 3 : if (len < 0)
301 1 : end = c + len;
302 2 : else if (len == 0)
303 0 : end = c;
304 : else
305 2 : end = start + len;
306 :
307 3 : if (end > c)
308 0 : end = c;
309 :
310 3 : if (start < 0)
311 0 : start = 0;
312 :
313 3 : if (start >= end || end <= 0)
314 : {
315 0 : PG_FREE_IF_COPY(a, 0);
316 0 : PG_RETURN_POINTER(new_intArrayType(0));
317 : }
318 :
319 3 : result = new_intArrayType(end - start);
320 3 : if (end - start > 0)
321 3 : memcpy(ARRPTR(result), ARRPTR(a) + start, (end - start) * sizeof(int32));
322 3 : PG_FREE_IF_COPY(a, 0);
323 3 : PG_RETURN_POINTER(result);
324 : }
325 :
326 : Datum
327 2 : intarray_push_elem(PG_FUNCTION_ARGS)
328 : {
329 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
330 : ArrayType *result;
331 :
332 2 : result = intarray_add_elem(a, PG_GETARG_INT32(1));
333 2 : PG_FREE_IF_COPY(a, 0);
334 2 : PG_RETURN_POINTER(result);
335 : }
336 :
337 : Datum
338 1 : intarray_push_array(PG_FUNCTION_ARGS)
339 : {
340 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
341 1 : ArrayType *b = PG_GETARG_ARRAYTYPE_P(1);
342 : ArrayType *result;
343 :
344 1 : result = intarray_concat_arrays(a, b);
345 1 : PG_FREE_IF_COPY(a, 0);
346 1 : PG_FREE_IF_COPY(b, 1);
347 1 : PG_RETURN_POINTER(result);
348 : }
349 :
350 : Datum
351 1 : intarray_del_elem(PG_FUNCTION_ARGS)
352 : {
353 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
354 1 : int32 elem = PG_GETARG_INT32(1);
355 : int32 c;
356 : int32 *aa;
357 1 : int32 n = 0,
358 : i;
359 :
360 1 : CHECKARRVALID(a);
361 1 : if (!ARRISEMPTY(a))
362 : {
363 1 : c = ARRNELEMS(a);
364 1 : aa = ARRPTR(a);
365 4 : for (i = 0; i < c; i++)
366 : {
367 3 : if (aa[i] != elem)
368 : {
369 2 : if (i > n)
370 1 : aa[n++] = aa[i];
371 : else
372 1 : n++;
373 : }
374 : }
375 1 : a = resize_intArrayType(a, n);
376 : }
377 1 : PG_RETURN_POINTER(a);
378 : }
379 :
380 : Datum
381 2 : intset_union_elem(PG_FUNCTION_ARGS)
382 : {
383 2 : ArrayType *a = PG_GETARG_ARRAYTYPE_P(0);
384 : ArrayType *result;
385 :
386 2 : result = intarray_add_elem(a, PG_GETARG_INT32(1));
387 2 : PG_FREE_IF_COPY(a, 0);
388 2 : QSORT(result, 1);
389 2 : PG_RETURN_POINTER(_int_unique(result));
390 : }
391 :
392 : Datum
393 1 : intset_subtract(PG_FUNCTION_ARGS)
394 : {
395 1 : ArrayType *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
396 1 : ArrayType *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
397 : ArrayType *result;
398 : int32 ca;
399 : int32 cb;
400 : int32 *aa,
401 : *bb,
402 : *r;
403 1 : int32 n = 0,
404 1 : i = 0,
405 1 : k = 0;
406 :
407 1 : CHECKARRVALID(a);
408 1 : CHECKARRVALID(b);
409 :
410 1 : QSORT(a, 1);
411 1 : a = _int_unique(a);
412 1 : ca = ARRNELEMS(a);
413 1 : QSORT(b, 1);
414 1 : b = _int_unique(b);
415 1 : cb = ARRNELEMS(b);
416 1 : result = new_intArrayType(ca);
417 1 : aa = ARRPTR(a);
418 1 : bb = ARRPTR(b);
419 1 : r = ARRPTR(result);
420 4 : while (i < ca)
421 : {
422 3 : if (k == cb || aa[i] < bb[k])
423 2 : r[n++] = aa[i++];
424 1 : else if (aa[i] == bb[k])
425 : {
426 1 : i++;
427 1 : k++;
428 : }
429 : else
430 0 : k++;
431 : }
432 1 : result = resize_intArrayType(result, n);
433 1 : pfree(a);
434 1 : pfree(b);
435 1 : PG_RETURN_POINTER(result);
436 : }
|