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