]> granicus.if.org Git - postgresql/blob - contrib/intarray/_int_op.c
Eliminate unnecessary NULL checks in picksplit method of intarray.
[postgresql] / contrib / intarray / _int_op.c
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
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
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
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
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
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
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
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
184 intset(PG_FUNCTION_ARGS)
185 {
186         PG_RETURN_POINTER(int_to_intset(PG_GETARG_INT32(0)));
187 }
188
189 Datum
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
200 sort(PG_FUNCTION_ARGS)
201 {
202         ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
203         text       *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_P(1) : NULL;
204         int32           dc = (dirstr) ? VARSIZE(dirstr) - VARHDRSZ : 0;
205         char       *d = (dirstr) ? VARDATA(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
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
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
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
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
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
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
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
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
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
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 }