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