Age Owner TLA Line data Source code
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 : #define HSHRDSIZE (sizeof(HStore))
66 :
67 : /*
68 : * "x" is a pair count, coming from an existing HS_COUNT() (as discussed, <=
69 : * INT_MAX/24) or a Pairs array length (due to MaxAllocSize, <= INT_MAX/40).
70 : * "lenstr" is no more than INT_MAX, that extreme case arising in
71 : * hstore_from_arrays(). Therefore, this calculation should be limited to
72 : * about INT_MAX / 5 + INT_MAX.
73 : */
74 : static inline Size
9 michael@paquier.xyz 75 GNC 4432 : hstoreCalcDataSize(Size x, Size lenstr)
76 : {
77 4432 : Size entrysize = mul_size(x, 2 * sizeof(HEntry));
78 4432 : Size total = add_size(HSHRDSIZE, lenstr);
79 :
80 4432 : return add_size(entrysize, total);
81 : }
82 :
83 : /* note multiple evaluations of x */
84 : #define ARRPTR(x) ( (HEntry*) ( (HStore*)(x) + 1 ) )
85 : #define STRPTR(x) ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) )
86 :
87 : /* note multiple/non evaluations */
88 : #define HSTORE_KEY(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)]))
89 : #define HSTORE_VAL(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)+1]))
90 : #define HSTORE_KEYLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)]))
91 : #define HSTORE_VALLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)+1]))
92 : #define HSTORE_VALISNULL(arr_,i_) (HSE_ISNULL((arr_)[2*(i_)+1]))
93 :
94 : /*
95 : * currently, these following macros are the _only_ places that rely
96 : * on internal knowledge of HEntry. Everything else should be using
97 : * the above macros. Exception: the in-place upgrade in hstore_compat.c
98 : * messes with entries directly.
99 : */
100 :
101 : /*
102 : * copy one key/value pair (which must be contiguous starting at
103 : * sptr_) into an under-construction hstore; dent_ is an HEntry*,
104 : * dbuf_ is the destination's string buffer, dptr_ is the current
105 : * position in the destination. lots of modification and multiple
106 : * evaluation here.
107 : */
108 : #define HS_COPYITEM(dent_,dbuf_,dptr_,sptr_,klen_,vlen_,vnull_) \
109 : do { \
110 : memcpy((dptr_), (sptr_), (klen_)+(vlen_)); \
111 : (dptr_) += (klen_)+(vlen_); \
112 : (dent_)++->entry = ((dptr_) - (dbuf_) - (vlen_)) & HENTRY_POSMASK; \
113 : (dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \
114 : | ((vnull_) ? HENTRY_ISNULL : 0)); \
115 : } while(0)
116 :
117 : /*
118 : * add one key/item pair, from a Pairs structure, into an
119 : * under-construction hstore
120 : */
121 : #define HS_ADDITEM(dent_,dbuf_,dptr_,pair_) \
122 : do { \
123 : memcpy((dptr_), (pair_).key, (pair_).keylen); \
124 : (dptr_) += (pair_).keylen; \
125 : (dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \
126 : if ((pair_).isnull) \
127 : (dent_)++->entry = ((((dptr_) - (dbuf_)) & HENTRY_POSMASK) \
128 : | HENTRY_ISNULL); \
129 : else \
130 : { \
131 : memcpy((dptr_), (pair_).val, (pair_).vallen); \
132 : (dptr_) += (pair_).vallen; \
133 : (dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \
134 : } \
135 : } while (0)
136 :
137 : /* finalize a newly-constructed hstore */
138 : #define HS_FINALIZE(hsp_,count_,buf_,ptr_) \
139 : do { \
140 : Size _buflen = (ptr_) - (buf_); \
141 : if ((count_)) \
142 : ARRPTR(hsp_)[0].entry |= HENTRY_ISFIRST; \
143 : if ((count_) != HS_COUNT((hsp_))) \
144 : { \
145 : HS_SETCOUNT((hsp_),(count_)); \
146 : memmove(STRPTR(hsp_), (buf_), _buflen); \
147 : } \
148 : SET_VARSIZE((hsp_), hstoreCalcDataSize((count_), _buflen)); \
149 : } while (0)
150 :
151 : /* ensure the varlena size of an existing hstore is correct */
152 : #define HS_FIXSIZE(hsp_,count_) \
153 : do { \
154 : Size bl = (count_) ? HSE_ENDPOS(ARRPTR(hsp_)[2*(count_)-1]) : 0; \
155 : SET_VARSIZE((hsp_), hstoreCalcDataSize((count_),bl)); \
156 : } while (0)
157 :
158 : /* DatumGetHStoreP includes support for reading old-format hstore values */
159 : extern PGDLLEXPORT HStore *hstoreUpgrade(Datum orig);
160 :
161 : #define DatumGetHStoreP(d) hstoreUpgrade(d)
162 :
163 : #define PG_GETARG_HSTORE_P(x) DatumGetHStoreP(PG_GETARG_DATUM(x))
164 :
165 :
166 : /*
167 : * Pairs is a "decompressed" representation of one key/value pair.
168 : * The two strings are not necessarily null-terminated.
169 : */
170 : typedef struct
171 : {
172 : char *key;
173 : char *val;
174 : size_t keylen;
175 : size_t vallen;
176 : bool isnull; /* value is null? */
177 : bool needfree; /* need to pfree the value? */
178 : } Pairs;
179 :
180 : extern PGDLLEXPORT int hstoreUniquePairs(Pairs *a, int32 l, Size *buflen);
181 : extern PGDLLEXPORT HStore *hstorePairs(Pairs *pairs, int32 pcount, Size buflen);
182 :
183 : extern PGDLLEXPORT size_t hstoreCheckKeyLen(size_t len);
184 : extern PGDLLEXPORT size_t hstoreCheckValLen(size_t len);
185 :
186 : extern PGDLLEXPORT int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);
187 : extern PGDLLEXPORT Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);
188 :
189 : #define HStoreContainsStrategyNumber 7
190 : #define HStoreExistsStrategyNumber 9
191 : #define HStoreExistsAnyStrategyNumber 10
192 : #define HStoreExistsAllStrategyNumber 11
193 : #define HStoreOldContainsStrategyNumber 13 /* backwards compatibility */
194 :
195 : /*
196 : * defining HSTORE_POLLUTE_NAMESPACE=0 will prevent use of old function names;
197 : * for now, we default to on for the benefit of people restoring old dumps
198 : */
199 : #ifndef HSTORE_POLLUTE_NAMESPACE
200 : #define HSTORE_POLLUTE_NAMESPACE 1
201 : #endif
202 :
203 : #if HSTORE_POLLUTE_NAMESPACE
204 : #define HSTORE_POLLUTE(newname_,oldname_) \
205 : PG_FUNCTION_INFO_V1(oldname_); \
206 : extern PGDLLEXPORT Datum newname_(PG_FUNCTION_ARGS); \
207 : Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
208 : extern int no_such_variable
209 : #else
210 : #define HSTORE_POLLUTE(newname_,oldname_) \
211 : extern int no_such_variable
212 : #endif
213 :
214 : #endif /* __HSTORE_H__ */
|