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

« back to all changes in this revision

Viewing changes to contrib/hstore/hstore_gin.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
 * contrib/hstore/hstore_gin.c
 
3
 */
 
4
#include "postgres.h"
 
5
 
 
6
#include "access/gin.h"
 
7
#include "access/skey.h"
 
8
#include "catalog/pg_type.h"
 
9
 
 
10
#include "hstore.h"
 
11
 
 
12
 
 
13
/*
 
14
 * When using a GIN index for hstore, we choose to index both keys and values.
 
15
 * The storage format is "text" values, with K, V, or N prepended to the string
 
16
 * to indicate key, value, or null values.      (As of 9.1 it might be better to
 
17
 * store null values as nulls, but we'll keep it this way for on-disk
 
18
 * compatibility.)
 
19
 */
 
20
#define KEYFLAG         'K'
 
21
#define VALFLAG         'V'
 
22
#define NULLFLAG        'N'
 
23
 
 
24
PG_FUNCTION_INFO_V1(gin_extract_hstore);
 
25
Datum           gin_extract_hstore(PG_FUNCTION_ARGS);
 
26
 
 
27
/* Build an indexable text value */
 
28
static text *
 
29
makeitem(char *str, int len, char flag)
 
30
{
 
31
        text       *item;
 
32
 
 
33
        item = (text *) palloc(VARHDRSZ + len + 1);
 
34
        SET_VARSIZE(item, VARHDRSZ + len + 1);
 
35
 
 
36
        *VARDATA(item) = flag;
 
37
 
 
38
        if (str && len > 0)
 
39
                memcpy(VARDATA(item) + 1, str, len);
 
40
 
 
41
        return item;
 
42
}
 
43
 
 
44
Datum
 
45
gin_extract_hstore(PG_FUNCTION_ARGS)
 
46
{
 
47
        HStore     *hs = PG_GETARG_HS(0);
 
48
        int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
 
49
        Datum      *entries = NULL;
 
50
        HEntry     *hsent = ARRPTR(hs);
 
51
        char       *ptr = STRPTR(hs);
 
52
        int                     count = HS_COUNT(hs);
 
53
        int                     i;
 
54
 
 
55
        *nentries = 2 * count;
 
56
        if (count)
 
57
                entries = (Datum *) palloc(sizeof(Datum) * 2 * count);
 
58
 
 
59
        for (i = 0; i < count; ++i)
 
60
        {
 
61
                text       *item;
 
62
 
 
63
                item = makeitem(HS_KEY(hsent, ptr, i), HS_KEYLEN(hsent, i),
 
64
                                                KEYFLAG);
 
65
                entries[2 * i] = PointerGetDatum(item);
 
66
 
 
67
                if (HS_VALISNULL(hsent, i))
 
68
                        item = makeitem(NULL, 0, NULLFLAG);
 
69
                else
 
70
                        item = makeitem(HS_VAL(hsent, ptr, i), HS_VALLEN(hsent, i),
 
71
                                                        VALFLAG);
 
72
                entries[2 * i + 1] = PointerGetDatum(item);
 
73
        }
 
74
 
 
75
        PG_RETURN_POINTER(entries);
 
76
}
 
77
 
 
78
PG_FUNCTION_INFO_V1(gin_extract_hstore_query);
 
79
Datum           gin_extract_hstore_query(PG_FUNCTION_ARGS);
 
80
 
 
81
Datum
 
82
gin_extract_hstore_query(PG_FUNCTION_ARGS)
 
83
{
 
84
        int32      *nentries = (int32 *) PG_GETARG_POINTER(1);
 
85
        StrategyNumber strategy = PG_GETARG_UINT16(2);
 
86
        int32      *searchMode = (int32 *) PG_GETARG_POINTER(6);
 
87
        Datum      *entries;
 
88
 
 
89
        if (strategy == HStoreContainsStrategyNumber)
 
90
        {
 
91
                /* Query is an hstore, so just apply gin_extract_hstore... */
 
92
                entries = (Datum *)
 
93
                        DatumGetPointer(DirectFunctionCall2(gin_extract_hstore,
 
94
                                                                                                PG_GETARG_DATUM(0),
 
95
                                                                                                PointerGetDatum(nentries)));
 
96
                /* ... except that "contains {}" requires a full index scan */
 
97
                if (entries == NULL)
 
98
                        *searchMode = GIN_SEARCH_MODE_ALL;
 
99
        }
 
100
        else if (strategy == HStoreExistsStrategyNumber)
 
101
        {
 
102
                text       *query = PG_GETARG_TEXT_PP(0);
 
103
                text       *item;
 
104
 
 
105
                *nentries = 1;
 
106
                entries = (Datum *) palloc(sizeof(Datum));
 
107
                item = makeitem(VARDATA_ANY(query), VARSIZE_ANY_EXHDR(query), KEYFLAG);
 
108
                entries[0] = PointerGetDatum(item);
 
109
        }
 
110
        else if (strategy == HStoreExistsAnyStrategyNumber ||
 
111
                         strategy == HStoreExistsAllStrategyNumber)
 
112
        {
 
113
                ArrayType  *query = PG_GETARG_ARRAYTYPE_P(0);
 
114
                Datum      *key_datums;
 
115
                bool       *key_nulls;
 
116
                int                     key_count;
 
117
                int                     i,
 
118
                                        j;
 
119
                text       *item;
 
120
 
 
121
                deconstruct_array(query,
 
122
                                                  TEXTOID, -1, false, 'i',
 
123
                                                  &key_datums, &key_nulls, &key_count);
 
124
 
 
125
                entries = (Datum *) palloc(sizeof(Datum) * key_count);
 
126
 
 
127
                for (i = 0, j = 0; i < key_count; ++i)
 
128
                {
 
129
                        /* Nulls in the array are ignored, cf hstoreArrayToPairs */
 
130
                        if (key_nulls[i])
 
131
                                continue;
 
132
                        item = makeitem(VARDATA(key_datums[i]), VARSIZE(key_datums[i]) - VARHDRSZ, KEYFLAG);
 
133
                        entries[j++] = PointerGetDatum(item);
 
134
                }
 
135
 
 
136
                *nentries = j;
 
137
                /* ExistsAll with no keys should match everything */
 
138
                if (j == 0 && strategy == HStoreExistsAllStrategyNumber)
 
139
                        *searchMode = GIN_SEARCH_MODE_ALL;
 
140
        }
 
141
        else
 
142
        {
 
143
                elog(ERROR, "unrecognized strategy number: %d", strategy);
 
144
                entries = NULL;                 /* keep compiler quiet */
 
145
        }
 
146
 
 
147
        PG_RETURN_POINTER(entries);
 
148
}
 
149
 
 
150
PG_FUNCTION_INFO_V1(gin_consistent_hstore);
 
151
Datum           gin_consistent_hstore(PG_FUNCTION_ARGS);
 
152
 
 
153
Datum
 
154
gin_consistent_hstore(PG_FUNCTION_ARGS)
 
155
{
 
156
        bool       *check = (bool *) PG_GETARG_POINTER(0);
 
157
        StrategyNumber strategy = PG_GETARG_UINT16(1);
 
158
 
 
159
        /* HStore          *query = PG_GETARG_HS(2); */
 
160
        int32           nkeys = PG_GETARG_INT32(3);
 
161
 
 
162
        /* Pointer         *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
 
163
        bool       *recheck = (bool *) PG_GETARG_POINTER(5);
 
164
        bool            res = true;
 
165
        int32           i;
 
166
 
 
167
        if (strategy == HStoreContainsStrategyNumber)
 
168
        {
 
169
                /*
 
170
                 * Index doesn't have information about correspondence of keys and
 
171
                 * values, so we need recheck.  However, if not all the keys are
 
172
                 * present, we can fail at once.
 
173
                 */
 
174
                *recheck = true;
 
175
                for (i = 0; i < nkeys; i++)
 
176
                {
 
177
                        if (!check[i])
 
178
                        {
 
179
                                res = false;
 
180
                                break;
 
181
                        }
 
182
                }
 
183
        }
 
184
        else if (strategy == HStoreExistsStrategyNumber)
 
185
        {
 
186
                /* Existence of key is guaranteed in default search mode */
 
187
                *recheck = false;
 
188
                res = true;
 
189
        }
 
190
        else if (strategy == HStoreExistsAnyStrategyNumber)
 
191
        {
 
192
                /* Existence of key is guaranteed in default search mode */
 
193
                *recheck = false;
 
194
                res = true;
 
195
        }
 
196
        else if (strategy == HStoreExistsAllStrategyNumber)
 
197
        {
 
198
                /* Testing for all the keys being present gives an exact result */
 
199
                *recheck = false;
 
200
                for (i = 0; i < nkeys; i++)
 
201
                {
 
202
                        if (!check[i])
 
203
                        {
 
204
                                res = false;
 
205
                                break;
 
206
                        }
 
207
                }
 
208
        }
 
209
        else
 
210
                elog(ERROR, "unrecognized strategy number: %d", strategy);
 
211
 
 
212
        PG_RETURN_BOOL(res);
 
213
}