~ubuntu-branches/ubuntu/oneiric/postgresql-9.1/oneiric-security

« back to all changes in this revision

Viewing changes to src/backend/access/gin/ginarrayproc.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*-------------------------------------------------------------------------
 
2
 *
 
3
 * ginarrayproc.c
 
4
 *        support functions for GIN's indexing of any array
 
5
 *
 
6
 *
 
7
 * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
 
8
 * Portions Copyright (c) 1994, Regents of the University of California
 
9
 *
 
10
 * IDENTIFICATION
 
11
 *        src/backend/access/gin/ginarrayproc.c
 
12
 *-------------------------------------------------------------------------
 
13
 */
 
14
#include "postgres.h"
 
15
 
 
16
#include "access/gin.h"
 
17
#include "access/skey.h"
 
18
#include "utils/array.h"
 
19
#include "utils/builtins.h"
 
20
#include "utils/lsyscache.h"
 
21
 
 
22
 
 
23
#define GinOverlapStrategy              1
 
24
#define GinContainsStrategy             2
 
25
#define GinContainedStrategy    3
 
26
#define GinEqualStrategy                4
 
27
 
 
28
 
 
29
/*
 
30
 * extractValue support function
 
31
 */
 
32
Datum
 
33
ginarrayextract(PG_FUNCTION_ARGS)
 
34
{
 
35
        /* Make copy of array input to ensure it doesn't disappear while in use */
 
36
        ArrayType  *array = PG_GETARG_ARRAYTYPE_P_COPY(0);
 
37
        int32      *nkeys = (int32 *) PG_GETARG_POINTER(1);
 
38
        bool      **nullFlags = (bool **) PG_GETARG_POINTER(2);
 
39
        int16           elmlen;
 
40
        bool            elmbyval;
 
41
        char            elmalign;
 
42
        Datum      *elems;
 
43
        bool       *nulls;
 
44
        int                     nelems;
 
45
 
 
46
        get_typlenbyvalalign(ARR_ELEMTYPE(array),
 
47
                                                 &elmlen, &elmbyval, &elmalign);
 
48
 
 
49
        deconstruct_array(array,
 
50
                                          ARR_ELEMTYPE(array),
 
51
                                          elmlen, elmbyval, elmalign,
 
52
                                          &elems, &nulls, &nelems);
 
53
 
 
54
        *nkeys = nelems;
 
55
        *nullFlags = nulls;
 
56
 
 
57
        /* we should not free array, elems[i] points into it */
 
58
        PG_RETURN_POINTER(elems);
 
59
}
 
60
 
 
61
/*
 
62
 * Formerly, ginarrayextract had only two arguments.  Now it has three,
 
63
 * but we still need a pg_proc entry with two args to support reloading
 
64
 * pre-9.1 contrib/intarray opclass declarations.  This compatibility
 
65
 * function should go away eventually.
 
66
 */
 
67
Datum
 
68
ginarrayextract_2args(PG_FUNCTION_ARGS)
 
69
{
 
70
        if (PG_NARGS() < 3)                     /* should not happen */
 
71
                elog(ERROR, "ginarrayextract requires three arguments");
 
72
        return ginarrayextract(fcinfo);
 
73
}
 
74
 
 
75
/*
 
76
 * extractQuery support function
 
77
 */
 
78
Datum
 
79
ginqueryarrayextract(PG_FUNCTION_ARGS)
 
80
{
 
81
        /* Make copy of array input to ensure it doesn't disappear while in use */
 
82
        ArrayType  *array = PG_GETARG_ARRAYTYPE_P_COPY(0);
 
83
        int32      *nkeys = (int32 *) PG_GETARG_POINTER(1);
 
84
        StrategyNumber strategy = PG_GETARG_UINT16(2);
 
85
 
 
86
        /* bool   **pmatch = (bool **) PG_GETARG_POINTER(3); */
 
87
        /* Pointer         *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
 
88
        bool      **nullFlags = (bool **) PG_GETARG_POINTER(5);
 
89
        int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
 
90
        int16           elmlen;
 
91
        bool            elmbyval;
 
92
        char            elmalign;
 
93
        Datum      *elems;
 
94
        bool       *nulls;
 
95
        int                     nelems;
 
96
 
 
97
        get_typlenbyvalalign(ARR_ELEMTYPE(array),
 
98
                                                 &elmlen, &elmbyval, &elmalign);
 
99
 
 
100
        deconstruct_array(array,
 
101
                                          ARR_ELEMTYPE(array),
 
102
                                          elmlen, elmbyval, elmalign,
 
103
                                          &elems, &nulls, &nelems);
 
104
 
 
105
        *nkeys = nelems;
 
106
        *nullFlags = nulls;
 
107
 
 
108
        switch (strategy)
 
109
        {
 
110
                case GinOverlapStrategy:
 
111
                        *searchMode = GIN_SEARCH_MODE_DEFAULT;
 
112
                        break;
 
113
                case GinContainsStrategy:
 
114
                        if (nelems > 0)
 
115
                                *searchMode = GIN_SEARCH_MODE_DEFAULT;
 
116
                        else    /* everything contains the empty set */
 
117
                                *searchMode = GIN_SEARCH_MODE_ALL;
 
118
                        break;
 
119
                case GinContainedStrategy:
 
120
                        /* empty set is contained in everything */
 
121
                        *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
 
122
                        break;
 
123
                case GinEqualStrategy:
 
124
                        if (nelems > 0)
 
125
                                *searchMode = GIN_SEARCH_MODE_DEFAULT;
 
126
                        else
 
127
                                *searchMode = GIN_SEARCH_MODE_INCLUDE_EMPTY;
 
128
                        break;
 
129
                default:
 
130
                        elog(ERROR, "ginqueryarrayextract: unknown strategy number: %d",
 
131
                                 strategy);
 
132
        }
 
133
 
 
134
        /* we should not free array, elems[i] points into it */
 
135
        PG_RETURN_POINTER(elems);
 
136
}
 
137
 
 
138
/*
 
139
 * consistent support function
 
140
 */
 
141
Datum
 
142
ginarrayconsistent(PG_FUNCTION_ARGS)
 
143
{
 
144
        bool       *check = (bool *) PG_GETARG_POINTER(0);
 
145
        StrategyNumber strategy = PG_GETARG_UINT16(1);
 
146
 
 
147
        /* ArrayType  *query = PG_GETARG_ARRAYTYPE_P(2); */
 
148
        int32           nkeys = PG_GETARG_INT32(3);
 
149
 
 
150
        /* Pointer         *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
 
151
        bool       *recheck = (bool *) PG_GETARG_POINTER(5);
 
152
 
 
153
        /* Datum           *queryKeys = (Datum *) PG_GETARG_POINTER(6); */
 
154
        bool       *nullFlags = (bool *) PG_GETARG_POINTER(7);
 
155
        bool            res;
 
156
        int32           i;
 
157
 
 
158
        switch (strategy)
 
159
        {
 
160
                case GinOverlapStrategy:
 
161
                        /* result is not lossy */
 
162
                        *recheck = false;
 
163
                        /* must have a match for at least one non-null element */
 
164
                        res = false;
 
165
                        for (i = 0; i < nkeys; i++)
 
166
                        {
 
167
                                if (check[i] && !nullFlags[i])
 
168
                                {
 
169
                                        res = true;
 
170
                                        break;
 
171
                                }
 
172
                        }
 
173
                        break;
 
174
                case GinContainsStrategy:
 
175
                        /* result is not lossy */
 
176
                        *recheck = false;
 
177
                        /* must have all elements in check[] true, and no nulls */
 
178
                        res = true;
 
179
                        for (i = 0; i < nkeys; i++)
 
180
                        {
 
181
                                if (!check[i] || nullFlags[i])
 
182
                                {
 
183
                                        res = false;
 
184
                                        break;
 
185
                                }
 
186
                        }
 
187
                        break;
 
188
                case GinContainedStrategy:
 
189
                        /* we will need recheck */
 
190
                        *recheck = true;
 
191
                        /* can't do anything else useful here */
 
192
                        res = true;
 
193
                        break;
 
194
                case GinEqualStrategy:
 
195
                        /* we will need recheck */
 
196
                        *recheck = true;
 
197
 
 
198
                        /*
 
199
                         * Must have all elements in check[] true; no discrimination
 
200
                         * against nulls here.  This is because array_contain_compare and
 
201
                         * array_eq handle nulls differently ...
 
202
                         */
 
203
                        res = true;
 
204
                        for (i = 0; i < nkeys; i++)
 
205
                        {
 
206
                                if (!check[i])
 
207
                                {
 
208
                                        res = false;
 
209
                                        break;
 
210
                                }
 
211
                        }
 
212
                        break;
 
213
                default:
 
214
                        elog(ERROR, "ginarrayconsistent: unknown strategy number: %d",
 
215
                                 strategy);
 
216
                        res = false;
 
217
        }
 
218
 
 
219
        PG_RETURN_BOOL(res);
 
220
}