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