1 : /*-------------------------------------------------------------------------
2 : *
3 : * ginarrayproc.c
4 : * support functions for GIN's indexing of any array
5 : *
6 : *
7 : * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
8 : * Portions Copyright (c) 1994, Regents of the University of California
9 : *
10 : * IDENTIFICATION
11 : * $PostgreSQL: pgsql/src/backend/access/gin/ginarrayproc.c,v 1.11 2007/11/15 21:14:31 momjian Exp $
12 : *-------------------------------------------------------------------------
13 : */
14 : #include "postgres.h"
15 :
16 : #include "access/gin.h"
17 : #include "utils/array.h"
18 : #include "utils/lsyscache.h"
19 :
20 :
21 : #define GinOverlapStrategy 1
22 : #define GinContainsStrategy 2
23 : #define GinContainedStrategy 3
24 : #define GinEqualStrategy 4
25 :
26 : #define ARRAYCHECK(x) do { \
27 : if ( ARR_HASNULL(x) ) \
28 : ereport(ERROR, \
29 : (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), \
30 : errmsg("array must not contain null values"))); \
31 : } while(0)
32 :
33 :
34 : /*
35 : * Function used as extractValue and extractQuery both
36 : */
37 : Datum
38 : ginarrayextract(PG_FUNCTION_ARGS)
39 216 : {
40 : ArrayType *array;
41 216 : int32 *nentries = (int32 *) PG_GETARG_POINTER(1);
42 216 : Datum *entries = NULL;
43 : int16 elmlen;
44 : bool elmbyval;
45 : char elmalign;
46 :
47 : /*
48 : * we should guarantee that array will not be destroyed during all
49 : * operation
50 : */
51 216 : array = PG_GETARG_ARRAYTYPE_P_COPY(0);
52 :
53 216 : ARRAYCHECK(array);
54 :
55 216 : get_typlenbyvalalign(ARR_ELEMTYPE(array),
56 : &elmlen, &elmbyval, &elmalign);
57 :
58 216 : deconstruct_array(array,
59 : ARR_ELEMTYPE(array),
60 : elmlen, elmbyval, elmalign,
61 : &entries, NULL, (int *) nentries);
62 :
63 216 : if (*nentries == 0 && PG_NARGS() == 3)
64 : {
65 0 : switch (PG_GETARG_UINT16(2)) /* StrategyNumber */
66 : {
67 : case GinOverlapStrategy:
68 0 : *nentries = -1; /* nobody can be found */
69 : break;
70 : case GinContainsStrategy:
71 : case GinContainedStrategy:
72 : case GinEqualStrategy:
73 : default: /* require fullscan: GIN can't find void
74 : * arrays */
75 : break;
76 : }
77 : }
78 :
79 : /* we should not free array, entries[i] points into it */
80 216 : PG_RETURN_POINTER(entries);
81 : }
82 :
83 : Datum
84 : ginqueryarrayextract(PG_FUNCTION_ARGS)
85 16 : {
86 16 : PG_RETURN_DATUM(DirectFunctionCall3(ginarrayextract,
87 : PG_GETARG_DATUM(0),
88 : PG_GETARG_DATUM(1),
89 : PG_GETARG_DATUM(2)));
90 : }
91 :
92 : Datum
93 : ginarrayconsistent(PG_FUNCTION_ARGS)
94 90 : {
95 90 : bool *check = (bool *) PG_GETARG_POINTER(0);
96 90 : StrategyNumber strategy = PG_GETARG_UINT16(1);
97 90 : ArrayType *query = PG_GETARG_ARRAYTYPE_P(2);
98 : int res,
99 : i,
100 : nentries;
101 :
102 : /* ARRAYCHECK was already done by previous ginarrayextract call */
103 :
104 90 : switch (strategy)
105 : {
106 : case GinOverlapStrategy:
107 : case GinContainedStrategy:
108 : /* at least one element in check[] is true, so result = true */
109 59 : res = TRUE;
110 59 : break;
111 : case GinContainsStrategy:
112 : case GinEqualStrategy:
113 31 : nentries = ArrayGetNItems(ARR_NDIM(query), ARR_DIMS(query));
114 31 : res = TRUE;
115 56 : for (i = 0; i < nentries; i++)
116 50 : if (!check[i])
117 : {
118 25 : res = FALSE;
119 25 : break;
120 : }
121 : break;
122 : default:
123 0 : elog(ERROR, "ginarrayconsistent: unknown strategy number: %d",
124 : strategy);
125 0 : res = FALSE;
126 : }
127 :
128 90 : PG_RETURN_BOOL(res);
129 : }
|