Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitba39896

Browse files
committed
Update contrib/hstore for new GIN extractQuery API.
In particular, make hstore @> '' succeed for all hstores, likewisehstore ?& '{}'. Previously the results were inconsistent and coulddepend on whether you were using a GiST index, GIN index, or seqscan.
1 parent327b257 commitba39896

File tree

3 files changed

+75
-53
lines changed

3 files changed

+75
-53
lines changed

‎contrib/hstore/expected/hstore.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ select hstore 'a=>NULL, b=>qq' ?& ARRAY['c','d'];
435435
select hstore 'a=>NULL, b=>qq' ?& '{}'::text[];
436436
?column?
437437
----------
438-
f
438+
t
439439
(1 row)
440440

441441
-- delete

‎contrib/hstore/hstore_gin.c

Lines changed: 65 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,31 @@
1010
#include"hstore.h"
1111

1212

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+
*/
1320
#defineKEYFLAG'K'
1421
#defineVALFLAG'V'
1522
#defineNULLFLAG'N'
1623

1724
PG_FUNCTION_INFO_V1(gin_extract_hstore);
1825
Datumgin_extract_hstore(PG_FUNCTION_ARGS);
1926

27+
/* Build an indexable text value */
2028
statictext*
21-
makeitem(char*str,intlen)
29+
makeitem(char*str,intlen,charflag)
2230
{
2331
text*item;
2432

2533
item= (text*)palloc(VARHDRSZ+len+1);
2634
SET_VARSIZE(item,VARHDRSZ+len+1);
2735

36+
*VARDATA(item)=flag;
37+
2838
if (str&&len>0)
2939
memcpy(VARDATA(item)+1,str,len);
3040

@@ -50,20 +60,15 @@ gin_extract_hstore(PG_FUNCTION_ARGS)
5060
{
5161
text*item;
5262

53-
item=makeitem(HS_KEY(hsent,ptr,i),HS_KEYLEN(hsent,i));
54-
*VARDATA(item)=KEYFLAG;
63+
item=makeitem(HS_KEY(hsent,ptr,i),HS_KEYLEN(hsent,i),
64+
KEYFLAG);
5565
entries[2*i]=PointerGetDatum(item);
5666

5767
if (HS_VALISNULL(hsent,i))
58-
{
59-
item=makeitem(NULL,0);
60-
*VARDATA(item)=NULLFLAG;
61-
}
68+
item=makeitem(NULL,0,NULLFLAG);
6269
else
63-
{
64-
item=makeitem(HS_VAL(hsent,ptr,i),HS_VALLEN(hsent,i));
65-
*VARDATA(item)=VALFLAG;
66-
}
70+
item=makeitem(HS_VAL(hsent,ptr,i),HS_VALLEN(hsent,i),
71+
VALFLAG);
6772
entries[2*i+1]=PointerGetDatum(item);
6873
}
6974

@@ -76,30 +81,31 @@ Datumgin_extract_hstore_query(PG_FUNCTION_ARGS);
7681
Datum
7782
gin_extract_hstore_query(PG_FUNCTION_ARGS)
7883
{
84+
int32*nentries= (int32*)PG_GETARG_POINTER(1);
7985
StrategyNumberstrategy=PG_GETARG_UINT16(2);
86+
int32*searchMode= (int32*)PG_GETARG_POINTER(6);
87+
Datum*entries;
8088

8189
if (strategy==HStoreContainsStrategyNumber)
8290
{
83-
PG_RETURN_DATUM(DirectFunctionCall2(gin_extract_hstore,
84-
PG_GETARG_DATUM(0),
85-
PG_GETARG_DATUM(1)
86-
));
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;
8799
}
88100
elseif (strategy==HStoreExistsStrategyNumber)
89101
{
90-
text*item,
91-
*query=PG_GETARG_TEXT_PP(0);
92-
int32*nentries= (int32*)PG_GETARG_POINTER(1);
93-
Datum*entries=NULL;
102+
text*query=PG_GETARG_TEXT_PP(0);
103+
text*item;
94104

95105
*nentries=1;
96106
entries= (Datum*)palloc(sizeof(Datum));
97-
98-
item=makeitem(VARDATA_ANY(query),VARSIZE_ANY_EXHDR(query));
99-
*VARDATA(item)=KEYFLAG;
107+
item=makeitem(VARDATA_ANY(query),VARSIZE_ANY_EXHDR(query),KEYFLAG);
100108
entries[0]=PointerGetDatum(item);
101-
102-
PG_RETURN_POINTER(entries);
103109
}
104110
elseif (strategy==HStoreExistsAnyStrategyNumber||
105111
strategy==HStoreExistsAllStrategyNumber)
@@ -110,8 +116,6 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
110116
intkey_count;
111117
inti,
112118
j;
113-
int32*nentries= (int32*)PG_GETARG_POINTER(1);
114-
Datum*entries=NULL;
115119
text*item;
116120

117121
deconstruct_array(query,
@@ -122,21 +126,25 @@ gin_extract_hstore_query(PG_FUNCTION_ARGS)
122126

123127
for (i=0,j=0;i<key_count;++i)
124128
{
129+
/* Nulls in the array are ignored, cf hstoreArrayToPairs */
125130
if (key_nulls[i])
126131
continue;
127-
item=makeitem(VARDATA(key_datums[i]),VARSIZE(key_datums[i])-VARHDRSZ);
128-
*VARDATA(item)=KEYFLAG;
132+
item=makeitem(VARDATA(key_datums[i]),VARSIZE(key_datums[i])-VARHDRSZ,KEYFLAG);
129133
entries[j++]=PointerGetDatum(item);
130134
}
131135

132-
*nentries=j ?j :-1;
133-
134-
PG_RETURN_POINTER(entries);
136+
*nentries=j;
137+
/* ExistsAll with no keys should match everything */
138+
if (j==0&&strategy==HStoreExistsAllStrategyNumber)
139+
*searchMode=GIN_SEARCH_MODE_ALL;
135140
}
136141
else
137-
elog(ERROR,"Unsupported strategy number: %d",strategy);
142+
{
143+
elog(ERROR,"unrecognized strategy number: %d",strategy);
144+
entries=NULL;/* keep compiler quiet */
145+
}
138146

139-
PG_RETURN_POINTER(NULL);
147+
PG_RETURN_POINTER(entries);
140148
}
141149

142150
PG_FUNCTION_INFO_V1(gin_consistent_hstore);
@@ -154,42 +162,52 @@ gin_consistent_hstore(PG_FUNCTION_ARGS)
154162
/* Pointer *extra_data = (Pointer *) PG_GETARG_POINTER(4); */
155163
bool*recheck= (bool*)PG_GETARG_POINTER(5);
156164
boolres= true;
157-
158-
*recheck= false;
165+
int32i;
159166

160167
if (strategy==HStoreContainsStrategyNumber)
161168
{
162-
inti;
163-
164169
/*
165-
* Index lost information about correspondence of keys and values, so
166-
* we need recheck (pre-8.4 this is handled at SQL level)
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.
167173
*/
168174
*recheck= true;
169-
for (i=0;res&&i<nkeys;i++)
170-
if (check[i]== false)
175+
for (i=0;i<nkeys;i++)
176+
{
177+
if (!check[i])
178+
{
171179
res= false;
180+
break;
181+
}
182+
}
172183
}
173184
elseif (strategy==HStoreExistsStrategyNumber)
174185
{
175-
/* Existence of key is guaranteed */
186+
/* Existence of key is guaranteed in default search mode */
187+
*recheck= false;
176188
res= true;
177189
}
178190
elseif (strategy==HStoreExistsAnyStrategyNumber)
179191
{
180-
/* Existence of key is guaranteed */
192+
/* Existence of key is guaranteed in default search mode */
193+
*recheck= false;
181194
res= true;
182195
}
183196
elseif (strategy==HStoreExistsAllStrategyNumber)
184197
{
185-
inti;
186-
187-
for (i=0;res&&i<nkeys;++i)
198+
/* Testing for all the keys being present gives an exact result */
199+
*recheck= false;
200+
for (i=0;i<nkeys;i++)
201+
{
188202
if (!check[i])
203+
{
189204
res= false;
205+
break;
206+
}
207+
}
190208
}
191209
else
192-
elog(ERROR,"Unsupported strategy number: %d",strategy);
210+
elog(ERROR,"unrecognized strategy number: %d",strategy);
193211

194212
PG_RETURN_BOOL(res);
195213
}

‎contrib/hstore/hstore_op.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,16 @@ hstore_exists_any(PG_FUNCTION_ARGS)
168168
* start one entry past the previous "found" entry, or at the lower bound
169169
* of the last search.
170170
*/
171-
172-
for (i=0; !res&&i<nkeys;++i)
171+
for (i=0;i<nkeys;i++)
173172
{
174173
intidx=hstoreFindKey(hs,&lowbound,
175174
key_pairs[i].key,key_pairs[i].keylen);
176175

177176
if (idx >=0)
177+
{
178178
res= true;
179+
break;
180+
}
179181
}
180182

181183
PG_RETURN_BOOL(res);
@@ -193,22 +195,24 @@ hstore_exists_all(PG_FUNCTION_ARGS)
193195
Pairs*key_pairs=hstoreArrayToPairs(keys,&nkeys);
194196
inti;
195197
intlowbound=0;
196-
boolres=nkeys ?true : false;
198+
boolres= true;
197199

198200
/*
199201
* we exploit the fact that the pairs list is already sorted into strictly
200202
* increasing order to narrow the hstoreFindKey search; each search can
201203
* start one entry past the previous "found" entry, or at the lower bound
202204
* of the last search.
203205
*/
204-
205-
for (i=0;res&&i<nkeys;++i)
206+
for (i=0;i<nkeys;i++)
206207
{
207208
intidx=hstoreFindKey(hs,&lowbound,
208209
key_pairs[i].key,key_pairs[i].keylen);
209210

210211
if (idx<0)
212+
{
211213
res= false;
214+
break;
215+
}
212216
}
213217

214218
PG_RETURN_BOOL(res);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp