Skip to content

Commit 1754dbb

Browse files
committed
Initial.
0 parents  commit 1754dbb

10 files changed

+1953
-0
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Generated subdirectories
2+
/log/
3+
/results/
4+
/tmp_check/
5+
*.o
6+
*.so

Makefile

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# contrib/hstore_ops/Makefile
2+
3+
MODULE_big = hstore_ops
4+
OBJS = hstore_compat.o hstore_ops.o
5+
6+
EXTENSION = hstore_ops
7+
DATA = hstore_ops--1.0.sql
8+
9+
REGRESS = hstore_ops
10+
11+
ifdef USE_PGXS
12+
PG_CONFIG = pg_config
13+
PGXS := $(shell $(PG_CONFIG) --pgxs)
14+
include $(PGXS)
15+
else
16+
subdir = contrib/hstore_ops
17+
top_builddir = ../..
18+
include $(top_builddir)/src/Makefile.global
19+
include $(top_srcdir)/contrib/contrib-global.mk
20+
endif

data/hstore.data

+1,001
Large diffs are not rendered by default.

expected/hstore_ops.out

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
CREATE EXTENSION hstore;
2+
CREATE EXTENSION hstore_ops;
3+
set escape_string_warning=off;
4+
CREATE TABLE testhstore (h hstore);
5+
\copy testhstore from 'data/hstore.data'
6+
create index hidx on testhstore using gin(h gin_hstore_hash_ops);
7+
set enable_seqscan=off;
8+
select count(*) from testhstore where h @> 'wait=>NULL';
9+
count
10+
-------
11+
1
12+
(1 row)
13+
14+
select count(*) from testhstore where h @> 'wait=>CC';
15+
count
16+
-------
17+
15
18+
(1 row)
19+
20+
select count(*) from testhstore where h @> 'wait=>CC, public=>t';
21+
count
22+
-------
23+
2
24+
(1 row)
25+
26+
select count(*) from testhstore where h ? 'public';
27+
count
28+
-------
29+
194
30+
(1 row)
31+
32+
select count(*) from testhstore where h ?| ARRAY['public','disabled'];
33+
count
34+
-------
35+
337
36+
(1 row)
37+
38+
select count(*) from testhstore where h ?& ARRAY['public','disabled'];
39+
count
40+
-------
41+
42
42+
(1 row)
43+

hstore.h

+206
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/*
2+
* contrib/hstore/hstore.h
3+
*/
4+
#ifndef __HSTORE_H__
5+
#define __HSTORE_H__
6+
7+
#include "fmgr.h"
8+
#include "utils/array.h"
9+
10+
11+
/*
12+
* HEntry: there is one of these for each key _and_ value in an hstore
13+
*
14+
* the position offset points to the _end_ so that we can get the length
15+
* by subtraction from the previous entry. the ISFIRST flag lets us tell
16+
* whether there is a previous entry.
17+
*/
18+
typedef struct
19+
{
20+
uint32 entry;
21+
} HEntry;
22+
23+
#define HENTRY_ISFIRST 0x80000000
24+
#define HENTRY_ISNULL 0x40000000
25+
#define HENTRY_POSMASK 0x3FFFFFFF
26+
27+
/* note possible multiple evaluations, also access to prior array element */
28+
#define HSE_ISFIRST(he_) (((he_).entry & HENTRY_ISFIRST) != 0)
29+
#define HSE_ISNULL(he_) (((he_).entry & HENTRY_ISNULL) != 0)
30+
#define HSE_ENDPOS(he_) ((he_).entry & HENTRY_POSMASK)
31+
#define HSE_OFF(he_) (HSE_ISFIRST(he_) ? 0 : HSE_ENDPOS((&(he_))[-1]))
32+
#define HSE_LEN(he_) (HSE_ISFIRST(he_) \
33+
? HSE_ENDPOS(he_) \
34+
: HSE_ENDPOS(he_) - HSE_ENDPOS((&(he_))[-1]))
35+
36+
/*
37+
* determined by the size of "endpos" (ie HENTRY_POSMASK), though this is a
38+
* bit academic since currently varlenas (and hence both the input and the
39+
* whole hstore) have the same limit
40+
*/
41+
#define HSTORE_MAX_KEY_LEN 0x3FFFFFFF
42+
#define HSTORE_MAX_VALUE_LEN 0x3FFFFFFF
43+
44+
typedef struct
45+
{
46+
int32 vl_len_; /* varlena header (do not touch directly!) */
47+
uint32 size_; /* flags and number of items in hstore */
48+
/* array of HEntry follows */
49+
} HStore;
50+
51+
/*
52+
* It's not possible to get more than 2^28 items into an hstore, so we reserve
53+
* the top few bits of the size field. See hstore_compat.c for one reason
54+
* why. Some bits are left for future use here. MaxAllocSize makes the
55+
* practical count limit slightly more than 2^28 / 3, or INT_MAX / 24, the
56+
* limit for an hstore full of 4-byte keys and null values. Therefore, we
57+
* don't explicitly check the format-imposed limit.
58+
*/
59+
#define HS_FLAG_NEWVERSION 0x80000000
60+
61+
#define HS_COUNT(hsp_) ((hsp_)->size_ & 0x0FFFFFFF)
62+
#define HS_SETCOUNT(hsp_,c_) ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)
63+
64+
65+
/*
66+
* "x" comes from an existing HS_COUNT() (as discussed, <= INT_MAX/24) or a
67+
* Pairs array length (due to MaxAllocSize, <= INT_MAX/40). "lenstr" is no
68+
* more than INT_MAX, that extreme case arising in hstore_from_arrays().
69+
* Therefore, this calculation is limited to about INT_MAX / 5 + INT_MAX.
70+
*/
71+
#define HSHRDSIZE (sizeof(HStore))
72+
#define CALCDATASIZE(x, lenstr) ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
73+
74+
/* note multiple evaluations of x */
75+
#define ARRPTR(x) ( (HEntry*) ( (HStore*)(x) + 1 ) )
76+
#define STRPTR(x) ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) )
77+
78+
/* note multiple/non evaluations */
79+
#define HS_KEY(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)]))
80+
#define HS_VAL(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)+1]))
81+
#define HS_KEYLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)]))
82+
#define HS_VALLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)+1]))
83+
#define HS_VALISNULL(arr_,i_) (HSE_ISNULL((arr_)[2*(i_)+1]))
84+
85+
/*
86+
* currently, these following macros are the _only_ places that rely
87+
* on internal knowledge of HEntry. Everything else should be using
88+
* the above macros. Exception: the in-place upgrade in hstore_compat.c
89+
* messes with entries directly.
90+
*/
91+
92+
/*
93+
* copy one key/value pair (which must be contiguous starting at
94+
* sptr_) into an under-construction hstore; dent_ is an HEntry*,
95+
* dbuf_ is the destination's string buffer, dptr_ is the current
96+
* position in the destination. lots of modification and multiple
97+
* evaluation here.
98+
*/
99+
#define HS_COPYITEM(dent_,dbuf_,dptr_,sptr_,klen_,vlen_,vnull_) \
100+
do { \
101+
memcpy((dptr_), (sptr_), (klen_)+(vlen_)); \
102+
(dptr_) += (klen_)+(vlen_); \
103+
(dent_)++->entry = ((dptr_) - (dbuf_) - (vlen_)) & HENTRY_POSMASK; \
104+
(dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \
105+
| ((vnull_) ? HENTRY_ISNULL : 0)); \
106+
} while(0)
107+
108+
/*
109+
* add one key/item pair, from a Pairs structure, into an
110+
* under-construction hstore
111+
*/
112+
#define HS_ADDITEM(dent_,dbuf_,dptr_,pair_) \
113+
do { \
114+
memcpy((dptr_), (pair_).key, (pair_).keylen); \
115+
(dptr_) += (pair_).keylen; \
116+
(dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \
117+
if ((pair_).isnull) \
118+
(dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \
119+
| HENTRY_ISNULL); \
120+
else \
121+
{ \
122+
memcpy((dptr_), (pair_).val, (pair_).vallen); \
123+
(dptr_) += (pair_).vallen; \
124+
(dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \
125+
} \
126+
} while (0)
127+
128+
/* finalize a newly-constructed hstore */
129+
#define HS_FINALIZE(hsp_,count_,buf_,ptr_) \
130+
do { \
131+
int buflen = (ptr_) - (buf_); \
132+
if ((count_)) \
133+
ARRPTR(hsp_)[0].entry |= HENTRY_ISFIRST; \
134+
if ((count_) != HS_COUNT((hsp_))) \
135+
{ \
136+
HS_SETCOUNT((hsp_),(count_)); \
137+
memmove(STRPTR(hsp_), (buf_), buflen); \
138+
} \
139+
SET_VARSIZE((hsp_), CALCDATASIZE((count_), buflen)); \
140+
} while (0)
141+
142+
/* ensure the varlena size of an existing hstore is correct */
143+
#define HS_FIXSIZE(hsp_,count_) \
144+
do { \
145+
int bl = (count_) ? HSE_ENDPOS(ARRPTR(hsp_)[2*(count_)-1]) : 0; \
146+
SET_VARSIZE((hsp_), CALCDATASIZE((count_),bl)); \
147+
} while (0)
148+
149+
/* DatumGetHStoreP includes support for reading old-format hstore values */
150+
extern HStore *hstoreUpgrade(Datum orig);
151+
152+
#define DatumGetHStoreP(d) hstoreUpgrade(d)
153+
154+
#define PG_GETARG_HS(x) DatumGetHStoreP(PG_GETARG_DATUM(x))
155+
156+
157+
/*
158+
* Pairs is a "decompressed" representation of one key/value pair.
159+
* The two strings are not necessarily null-terminated.
160+
*/
161+
typedef struct
162+
{
163+
char *key;
164+
char *val;
165+
size_t keylen;
166+
size_t vallen;
167+
bool isnull; /* value is null? */
168+
bool needfree; /* need to pfree the value? */
169+
} Pairs;
170+
171+
extern int hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen);
172+
extern HStore *hstorePairs(Pairs *pairs, int32 pcount, int32 buflen);
173+
174+
extern size_t hstoreCheckKeyLen(size_t len);
175+
extern size_t hstoreCheckValLen(size_t len);
176+
177+
extern int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);
178+
extern Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
179+
180+
#define HStoreContainsStrategyNumber 7
181+
#define HStoreExistsStrategyNumber 9
182+
#define HStoreExistsAnyStrategyNumber 10
183+
#define HStoreExistsAllStrategyNumber 11
184+
#define HStoreOldContainsStrategyNumber 13 /* backwards compatibility */
185+
186+
/*
187+
* defining HSTORE_POLLUTE_NAMESPACE=0 will prevent use of old function names;
188+
* for now, we default to on for the benefit of people restoring old dumps
189+
*/
190+
#ifndef HSTORE_POLLUTE_NAMESPACE
191+
#define HSTORE_POLLUTE_NAMESPACE 1
192+
#endif
193+
194+
#if HSTORE_POLLUTE_NAMESPACE
195+
#define HSTORE_POLLUTE(newname_,oldname_) \
196+
PG_FUNCTION_INFO_V1(oldname_); \
197+
Datum oldname_(PG_FUNCTION_ARGS); \
198+
Datum newname_(PG_FUNCTION_ARGS); \
199+
Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
200+
extern int no_such_variable
201+
#else
202+
#define HSTORE_POLLUTE(newname_,oldname_) \
203+
extern int no_such_variable
204+
#endif
205+
206+
#endif /* __HSTORE_H__ */

0 commit comments

Comments
 (0)