Skip to content

Commit 1754dbb

Browse files
committed
Initial.
0 parents  commit 1754dbb

File tree

10 files changed

+1953
-0
lines changed

10 files changed

+1953
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
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

Lines changed: 20 additions & 0 deletions
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

Lines changed: 1001 additions & 0 deletions
Large diffs are not rendered by default.

expected/hstore_ops.out

Lines changed: 43 additions & 0 deletions
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

Lines changed: 206 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy