Header And Logo

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

ginarrayproc.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * ginarrayproc.c
00004  *    support functions for GIN's indexing of any array
00005  *
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  * Portions Copyright (c) 1994, Regents of the University of California
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/access/gin/ginarrayproc.c
00012  *-------------------------------------------------------------------------
00013  */
00014 #include "postgres.h"
00015 
00016 #include "access/gin.h"
00017 #include "access/skey.h"
00018 #include "utils/array.h"
00019 #include "utils/builtins.h"
00020 #include "utils/lsyscache.h"
00021 
00022 
00023 #define GinOverlapStrategy      1
00024 #define GinContainsStrategy     2
00025 #define GinContainedStrategy    3
00026 #define GinEqualStrategy        4
00027 
00028 
00029 /*
00030  * extractValue support function
00031  */
00032 Datum
00033 ginarrayextract(PG_FUNCTION_ARGS)
00034 {
00035     /* Make copy of array input to ensure it doesn't disappear while in use */
00036     ArrayType  *array = PG_GETARG_ARRAYTYPE_P_COPY(0);
00037     int32      *nkeys = (int32 *) PG_GETARG_POINTER(1);
00038     bool      **nullFlags = (bool **) PG_GETARG_POINTER(2);
00039     int16       elmlen;
00040     bool        elmbyval;
00041     char        elmalign;
00042     Datum      *elems;
00043     bool       *nulls;
00044     int         nelems;
00045 
00046     get_typlenbyvalalign(ARR_ELEMTYPE(array),
00047                          &elmlen, &elmbyval, &elmalign);
00048 
00049     deconstruct_array(array,
00050                       ARR_ELEMTYPE(array),
00051                       elmlen, elmbyval, elmalign,
00052                       &elems, &nulls, &nelems);
00053 
00054     *nkeys = nelems;
00055     *nullFlags = nulls;
00056 
00057     /* we should not free array, elems[i] points into it */
00058     PG_RETURN_POINTER(elems);
00059 }
00060 
00061 /*
00062  * Formerly, ginarrayextract had only two arguments.  Now it has three,
00063  * but we still need a pg_proc entry with two args to support reloading
00064  * pre-9.1 contrib/intarray opclass declarations.  This compatibility
00065  * function should go away eventually.
00066  */
00067 Datum
00068 ginarrayextract_2args(PG_FUNCTION_ARGS)
00069 {
00070     if (PG_NARGS() < 3)         /* should not happen */
00071         elog(ERROR, "ginarrayextract requires three arguments");
00072     return ginarrayextract(fcinfo);
00073 }
00074 
00075 /*
00076  * extractQuery support function
00077  */
00078 Datum
00079 ginqueryarrayextract(PG_FUNCTION_ARGS)
00080 {
00081     /* Make copy of array input to ensure it doesn't disappear while in use */
00082     ArrayType  *array = PG_GETARG_ARRAYTYPE_P_COPY(0);
00083     int32      *nkeys = (int32 *) PG_GETARG_POINTER(1);
00084     StrategyNumber strategy = PG_GETARG_UINT16(2);
00085 
00086     /* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
00087     /* Pointer     *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
00088     bool      **nullFlags = (bool **) PG_GETARG_POINTER(5);
00089     int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
00090     int16       elmlen;
00091     bool        elmbyval;
00092     char        elmalign;
00093     Datum      *elems;
00094     bool       *nulls;
00095     int         nelems;
00096 
00097     get_typlenbyvalalign(ARR_ELEMTYPE(array),
00098                          &elmlen, &elmbyval, &elmalign);
00099 
00100     deconstruct_array(array,
00101                       ARR_ELEMTYPE(array),
00102                       elmlen, elmbyval, elmalign,
00103                       &elems, &nulls, &nelems);
00104 
00105     *nkeys = nelems;
00106     *nullFlags = nulls;
00107 
00108     switch (strategy)
00109     {
00110         case GinOverlapStrategy:
00111             *searchMode = GIN_SEARCH_MODE_DEFAULT;
00112             break;
00113         case GinContainsStrategy:
00114             if (nelems > 0)
00115                 *searchMode = GIN_SEARCH_MODE_DEFAULT;
00116             else    /* everything contains the empty set */
00117                 *searchMode = GIN_SEARCH_MODE_ALL;
00118             break;
00119         case GinContainedStrategy:
00120             /* empty set is contained in everything */
00121             *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
00122             break;
00123         case GinEqualStrategy:
00124             if (nelems > 0)
00125                 *searchMode = GIN_SEARCH_MODE_DEFAULT;
00126             else
00127                 *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
00128             break;
00129         default:
00130             elog(ERROR, "ginqueryarrayextract: unknown strategy number: %d",
00131                  strategy);
00132     }
00133 
00134     /* we should not free array, elems[i] points into it */
00135     PG_RETURN_POINTER(elems);
00136 }
00137 
00138 /*
00139  * consistent support function
00140  */
00141 Datum
00142 ginarrayconsistent(PG_FUNCTION_ARGS)
00143 {
00144     bool       *check = (bool *) PG_GETARG_POINTER(0);
00145     StrategyNumber strategy = PG_GETARG_UINT16(1);
00146 
00147     /* ArrayType  *query = PG_GETARG_ARRAYTYPE_P(2); */
00148     int32       nkeys = PG_GETARG_INT32(3);
00149 
00150     /* Pointer     *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
00151     bool       *recheck = (bool *) PG_GETARG_POINTER(5);
00152 
00153     /* Datum       *queryKeys = (Datum *) PG_GETARG_POINTER(6); */
00154     bool       *nullFlags = (bool *) PG_GETARG_POINTER(7);
00155     bool        res;
00156     int32       i;
00157 
00158     switch (strategy)
00159     {
00160         case GinOverlapStrategy:
00161             /* result is not lossy */
00162             *recheck = false;
00163             /* must have a match for at least one non-null element */
00164             res = false;
00165             for (i = 0; i < nkeys; i++)
00166             {
00167                 if (check[i] && !nullFlags[i])
00168                 {
00169                     res = true;
00170                     break;
00171                 }
00172             }
00173             break;
00174         case GinContainsStrategy:
00175             /* result is not lossy */
00176             *recheck = false;
00177             /* must have all elements in check[] true, and no nulls */
00178             res = true;
00179             for (i = 0; i < nkeys; i++)
00180             {
00181                 if (!check[i] || nullFlags[i])
00182                 {
00183                     res = false;
00184                     break;
00185                 }
00186             }
00187             break;
00188         case GinContainedStrategy:
00189             /* we will need recheck */
00190             *recheck = true;
00191             /* can't do anything else useful here */
00192             res = true;
00193             break;
00194         case GinEqualStrategy:
00195             /* we will need recheck */
00196             *recheck = true;
00197 
00198             /*
00199              * Must have all elements in check[] true; no discrimination
00200              * against nulls here.  This is because array_contain_compare and
00201              * array_eq handle nulls differently ...
00202              */
00203             res = true;
00204             for (i = 0; i < nkeys; i++)
00205             {
00206                 if (!check[i])
00207                 {
00208                     res = false;
00209                     break;
00210                 }
00211             }
00212             break;
00213         default:
00214             elog(ERROR, "ginarrayconsistent: unknown strategy number: %d",
00215                  strategy);
00216             res = false;
00217     }
00218 
00219     PG_RETURN_BOOL(res);
00220 }