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