Header And Logo

PostgreSQL
| The world's most advanced open source database.

_int_op.c

Go to the documentation of this file.
00001 /*
00002  * contrib/intarray/_int_op.c
00003  */
00004 #include "postgres.h"
00005 
00006 
00007 #include "_int.h"
00008 
00009 
00010 PG_MODULE_MAGIC;
00011 
00012 PG_FUNCTION_INFO_V1(_int_different);
00013 PG_FUNCTION_INFO_V1(_int_same);
00014 PG_FUNCTION_INFO_V1(_int_contains);
00015 PG_FUNCTION_INFO_V1(_int_contained);
00016 PG_FUNCTION_INFO_V1(_int_overlap);
00017 PG_FUNCTION_INFO_V1(_int_union);
00018 PG_FUNCTION_INFO_V1(_int_inter);
00019 
00020 Datum       _int_different(PG_FUNCTION_ARGS);
00021 Datum       _int_same(PG_FUNCTION_ARGS);
00022 Datum       _int_contains(PG_FUNCTION_ARGS);
00023 Datum       _int_contained(PG_FUNCTION_ARGS);
00024 Datum       _int_overlap(PG_FUNCTION_ARGS);
00025 Datum       _int_union(PG_FUNCTION_ARGS);
00026 Datum       _int_inter(PG_FUNCTION_ARGS);
00027 
00028 Datum
00029 _int_contained(PG_FUNCTION_ARGS)
00030 {
00031     /* just reverse the operands and call _int_contains */
00032     return DirectFunctionCall2(_int_contains,
00033                                PG_GETARG_DATUM(1),
00034                                PG_GETARG_DATUM(0));
00035 }
00036 
00037 Datum
00038 _int_contains(PG_FUNCTION_ARGS)
00039 {
00040     /* Force copy so we can modify the arrays in-place */
00041     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00042     ArrayType  *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
00043     bool        res;
00044 
00045     CHECKARRVALID(a);
00046     CHECKARRVALID(b);
00047     PREPAREARR(a);
00048     PREPAREARR(b);
00049     res = inner_int_contains(a, b);
00050     pfree(a);
00051     pfree(b);
00052     PG_RETURN_BOOL(res);
00053 }
00054 
00055 Datum
00056 _int_different(PG_FUNCTION_ARGS)
00057 {
00058     PG_RETURN_BOOL(!DatumGetBool(
00059                                  DirectFunctionCall2(
00060                                                      _int_same,
00061                                        PointerGetDatum(PG_GETARG_POINTER(0)),
00062                                         PointerGetDatum(PG_GETARG_POINTER(1))
00063                                                      )
00064                                  ));
00065 }
00066 
00067 Datum
00068 _int_same(PG_FUNCTION_ARGS)
00069 {
00070     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00071     ArrayType  *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
00072     int         na,
00073                 nb;
00074     int         n;
00075     int        *da,
00076                *db;
00077     bool        result;
00078 
00079     CHECKARRVALID(a);
00080     CHECKARRVALID(b);
00081     na = ARRNELEMS(a);
00082     nb = ARRNELEMS(b);
00083     da = ARRPTR(a);
00084     db = ARRPTR(b);
00085 
00086     result = FALSE;
00087 
00088     if (na == nb)
00089     {
00090         SORT(a);
00091         SORT(b);
00092         result = TRUE;
00093 
00094         for (n = 0; n < na; n++)
00095         {
00096             if (da[n] != db[n])
00097             {
00098                 result = FALSE;
00099                 break;
00100             }
00101         }
00102     }
00103 
00104     pfree(a);
00105     pfree(b);
00106 
00107     PG_RETURN_BOOL(result);
00108 }
00109 
00110 /*  _int_overlap -- does a overlap b?
00111  */
00112 Datum
00113 _int_overlap(PG_FUNCTION_ARGS)
00114 {
00115     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00116     ArrayType  *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
00117     bool        result;
00118 
00119     CHECKARRVALID(a);
00120     CHECKARRVALID(b);
00121     if (ARRISEMPTY(a) || ARRISEMPTY(b))
00122         return FALSE;
00123 
00124     SORT(a);
00125     SORT(b);
00126 
00127     result = inner_int_overlap(a, b);
00128 
00129     pfree(a);
00130     pfree(b);
00131 
00132     PG_RETURN_BOOL(result);
00133 }
00134 
00135 Datum
00136 _int_union(PG_FUNCTION_ARGS)
00137 {
00138     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00139     ArrayType  *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
00140     ArrayType  *result;
00141 
00142     CHECKARRVALID(a);
00143     CHECKARRVALID(b);
00144 
00145     SORT(a);
00146     SORT(b);
00147 
00148     result = inner_int_union(a, b);
00149 
00150     pfree(a);
00151     pfree(b);
00152 
00153     PG_RETURN_POINTER(result);
00154 }
00155 
00156 Datum
00157 _int_inter(PG_FUNCTION_ARGS)
00158 {
00159     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00160     ArrayType  *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
00161     ArrayType  *result;
00162 
00163     CHECKARRVALID(a);
00164     CHECKARRVALID(b);
00165 
00166     SORT(a);
00167     SORT(b);
00168 
00169     result = inner_int_inter(a, b);
00170 
00171     pfree(a);
00172     pfree(b);
00173 
00174     PG_RETURN_POINTER(result);
00175 }
00176 
00177 
00178 PG_FUNCTION_INFO_V1(intset);
00179 PG_FUNCTION_INFO_V1(icount);
00180 PG_FUNCTION_INFO_V1(sort);
00181 PG_FUNCTION_INFO_V1(sort_asc);
00182 PG_FUNCTION_INFO_V1(sort_desc);
00183 PG_FUNCTION_INFO_V1(uniq);
00184 PG_FUNCTION_INFO_V1(idx);
00185 PG_FUNCTION_INFO_V1(subarray);
00186 PG_FUNCTION_INFO_V1(intarray_push_elem);
00187 PG_FUNCTION_INFO_V1(intarray_push_array);
00188 PG_FUNCTION_INFO_V1(intarray_del_elem);
00189 PG_FUNCTION_INFO_V1(intset_union_elem);
00190 PG_FUNCTION_INFO_V1(intset_subtract);
00191 Datum       intset(PG_FUNCTION_ARGS);
00192 Datum       icount(PG_FUNCTION_ARGS);
00193 Datum       sort(PG_FUNCTION_ARGS);
00194 Datum       sort_asc(PG_FUNCTION_ARGS);
00195 Datum       sort_desc(PG_FUNCTION_ARGS);
00196 Datum       uniq(PG_FUNCTION_ARGS);
00197 Datum       idx(PG_FUNCTION_ARGS);
00198 Datum       subarray(PG_FUNCTION_ARGS);
00199 Datum       intarray_push_elem(PG_FUNCTION_ARGS);
00200 Datum       intarray_push_array(PG_FUNCTION_ARGS);
00201 Datum       intarray_del_elem(PG_FUNCTION_ARGS);
00202 Datum       intset_union_elem(PG_FUNCTION_ARGS);
00203 Datum       intset_subtract(PG_FUNCTION_ARGS);
00204 
00205 Datum
00206 intset(PG_FUNCTION_ARGS)
00207 {
00208     PG_RETURN_POINTER(int_to_intset(PG_GETARG_INT32(0)));
00209 }
00210 
00211 Datum
00212 icount(PG_FUNCTION_ARGS)
00213 {
00214     ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
00215     int32       count = ARRNELEMS(a);
00216 
00217     PG_FREE_IF_COPY(a, 0);
00218     PG_RETURN_INT32(count);
00219 }
00220 
00221 Datum
00222 sort(PG_FUNCTION_ARGS)
00223 {
00224     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00225     text       *dirstr = (fcinfo->nargs == 2) ? PG_GETARG_TEXT_P(1) : NULL;
00226     int32       dc = (dirstr) ? VARSIZE(dirstr) - VARHDRSZ : 0;
00227     char       *d = (dirstr) ? VARDATA(dirstr) : NULL;
00228     int         dir = -1;
00229 
00230     CHECKARRVALID(a);
00231     if (ARRNELEMS(a) < 2)
00232         PG_RETURN_POINTER(a);
00233 
00234     if (dirstr == NULL || (dc == 3
00235                            && (d[0] == 'A' || d[0] == 'a')
00236                            && (d[1] == 'S' || d[1] == 's')
00237                            && (d[2] == 'C' || d[2] == 'c')))
00238         dir = 1;
00239     else if (dc == 4
00240              && (d[0] == 'D' || d[0] == 'd')
00241              && (d[1] == 'E' || d[1] == 'e')
00242              && (d[2] == 'S' || d[2] == 's')
00243              && (d[3] == 'C' || d[3] == 'c'))
00244         dir = 0;
00245     if (dir == -1)
00246         ereport(ERROR,
00247                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
00248                  errmsg("second parameter must be \"ASC\" or \"DESC\"")));
00249     QSORT(a, dir);
00250     PG_RETURN_POINTER(a);
00251 }
00252 
00253 Datum
00254 sort_asc(PG_FUNCTION_ARGS)
00255 {
00256     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00257 
00258     CHECKARRVALID(a);
00259     QSORT(a, 1);
00260     PG_RETURN_POINTER(a);
00261 }
00262 
00263 Datum
00264 sort_desc(PG_FUNCTION_ARGS)
00265 {
00266     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00267 
00268     CHECKARRVALID(a);
00269     QSORT(a, 0);
00270     PG_RETURN_POINTER(a);
00271 }
00272 
00273 Datum
00274 uniq(PG_FUNCTION_ARGS)
00275 {
00276     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00277 
00278     CHECKARRVALID(a);
00279     if (ARRNELEMS(a) < 2)
00280         PG_RETURN_POINTER(a);
00281     a = _int_unique(a);
00282     PG_RETURN_POINTER(a);
00283 }
00284 
00285 Datum
00286 idx(PG_FUNCTION_ARGS)
00287 {
00288     ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
00289     int32       result;
00290 
00291     CHECKARRVALID(a);
00292     result = ARRNELEMS(a);
00293     if (result)
00294         result = intarray_match_first(a, PG_GETARG_INT32(1));
00295     PG_FREE_IF_COPY(a, 0);
00296     PG_RETURN_INT32(result);
00297 }
00298 
00299 Datum
00300 subarray(PG_FUNCTION_ARGS)
00301 {
00302     ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
00303     int32       start = PG_GETARG_INT32(1);
00304     int32       len = (fcinfo->nargs == 3) ? PG_GETARG_INT32(2) : 0;
00305     int32       end = 0;
00306     int32       c;
00307     ArrayType  *result;
00308 
00309     start = (start > 0) ? start - 1 : start;
00310 
00311     CHECKARRVALID(a);
00312     if (ARRISEMPTY(a))
00313     {
00314         PG_FREE_IF_COPY(a, 0);
00315         PG_RETURN_POINTER(new_intArrayType(0));
00316     }
00317 
00318     c = ARRNELEMS(a);
00319 
00320     if (start < 0)
00321         start = c + start;
00322 
00323     if (len < 0)
00324         end = c + len;
00325     else if (len == 0)
00326         end = c;
00327     else
00328         end = start + len;
00329 
00330     if (end > c)
00331         end = c;
00332 
00333     if (start < 0)
00334         start = 0;
00335 
00336     if (start >= end || end <= 0)
00337     {
00338         PG_FREE_IF_COPY(a, 0);
00339         PG_RETURN_POINTER(new_intArrayType(0));
00340     }
00341 
00342     result = new_intArrayType(end - start);
00343     if (end - start > 0)
00344         memcpy(ARRPTR(result), ARRPTR(a) + start, (end - start) * sizeof(int32));
00345     PG_FREE_IF_COPY(a, 0);
00346     PG_RETURN_POINTER(result);
00347 }
00348 
00349 Datum
00350 intarray_push_elem(PG_FUNCTION_ARGS)
00351 {
00352     ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
00353     ArrayType  *result;
00354 
00355     result = intarray_add_elem(a, PG_GETARG_INT32(1));
00356     PG_FREE_IF_COPY(a, 0);
00357     PG_RETURN_POINTER(result);
00358 }
00359 
00360 Datum
00361 intarray_push_array(PG_FUNCTION_ARGS)
00362 {
00363     ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
00364     ArrayType  *b = PG_GETARG_ARRAYTYPE_P(1);
00365     ArrayType  *result;
00366 
00367     result = intarray_concat_arrays(a, b);
00368     PG_FREE_IF_COPY(a, 0);
00369     PG_FREE_IF_COPY(b, 1);
00370     PG_RETURN_POINTER(result);
00371 }
00372 
00373 Datum
00374 intarray_del_elem(PG_FUNCTION_ARGS)
00375 {
00376     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00377     int32       elem = PG_GETARG_INT32(1);
00378     int32       c;
00379     int32      *aa;
00380     int32       n = 0,
00381                 i;
00382 
00383     CHECKARRVALID(a);
00384     if (!ARRISEMPTY(a))
00385     {
00386         c = ARRNELEMS(a);
00387         aa = ARRPTR(a);
00388         for (i = 0; i < c; i++)
00389         {
00390             if (aa[i] != elem)
00391             {
00392                 if (i > n)
00393                     aa[n++] = aa[i];
00394                 else
00395                     n++;
00396             }
00397         }
00398         a = resize_intArrayType(a, n);
00399     }
00400     PG_RETURN_POINTER(a);
00401 }
00402 
00403 Datum
00404 intset_union_elem(PG_FUNCTION_ARGS)
00405 {
00406     ArrayType  *a = PG_GETARG_ARRAYTYPE_P(0);
00407     ArrayType  *result;
00408 
00409     result = intarray_add_elem(a, PG_GETARG_INT32(1));
00410     PG_FREE_IF_COPY(a, 0);
00411     QSORT(result, 1);
00412     PG_RETURN_POINTER(_int_unique(result));
00413 }
00414 
00415 Datum
00416 intset_subtract(PG_FUNCTION_ARGS)
00417 {
00418     ArrayType  *a = PG_GETARG_ARRAYTYPE_P_COPY(0);
00419     ArrayType  *b = PG_GETARG_ARRAYTYPE_P_COPY(1);
00420     ArrayType  *result;
00421     int32       ca;
00422     int32       cb;
00423     int32      *aa,
00424                *bb,
00425                *r;
00426     int32       n = 0,
00427                 i = 0,
00428                 k = 0;
00429 
00430     CHECKARRVALID(a);
00431     CHECKARRVALID(b);
00432 
00433     QSORT(a, 1);
00434     a = _int_unique(a);
00435     ca = ARRNELEMS(a);
00436     QSORT(b, 1);
00437     b = _int_unique(b);
00438     cb = ARRNELEMS(b);
00439     result = new_intArrayType(ca);
00440     aa = ARRPTR(a);
00441     bb = ARRPTR(b);
00442     r = ARRPTR(result);
00443     while (i < ca)
00444     {
00445         if (k == cb || aa[i] < bb[k])
00446             r[n++] = aa[i++];
00447         else if (aa[i] == bb[k])
00448         {
00449             i++;
00450             k++;
00451         }
00452         else
00453             k++;
00454     }
00455     result = resize_intArrayType(result, n);
00456     pfree(a);
00457     pfree(b);
00458     PG_RETURN_POINTER(result);
00459 }