codekingpro/portable-devtools
114k
1/*2 * contrib/hstore/hstore.h3 */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 hstore13 *14 * the position offset points to the _end_ so that we can get the length15 * by subtraction from the previous entry. the ISFIRST flag lets us tell16 * whether there is a previous entry.17 */18typedef struct19{20 uint32 entry;21} HEntry;22 23#define HENTRY_ISFIRST 0x8000000024#define HENTRY_ISNULL 0x4000000025#define HENTRY_POSMASK 0x3FFFFFFF26 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 a38 * bit academic since currently varlenas (and hence both the input and the39 * whole hstore) have the same limit40 */41#define HSTORE_MAX_KEY_LEN 0x3FFFFFFF42#define HSTORE_MAX_VALUE_LEN 0x3FFFFFFF43 44typedef struct45{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 reserve53 * the top few bits of the size field. See hstore_compat.c for one reason54 * why. Some bits are left for future use here. MaxAllocSize makes the55 * practical count limit slightly more than 2^28 / 3, or INT_MAX / 24, the56 * limit for an hstore full of 4-byte keys and null values. Therefore, we57 * don't explicitly check the format-imposed limit.58 */59#define HS_FLAG_NEWVERSION 0x8000000060 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 a67 * Pairs array length (due to MaxAllocSize, <= INT_MAX/40). "lenstr" is no68 * 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 HSTORE_KEY(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)]))80#define HSTORE_VAL(arr_,str_,i_) ((str_) + HSE_OFF((arr_)[2*(i_)+1]))81#define HSTORE_KEYLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)]))82#define HSTORE_VALLEN(arr_,i_) (HSE_LEN((arr_)[2*(i_)+1]))83#define HSTORE_VALISNULL(arr_,i_) (HSE_ISNULL((arr_)[2*(i_)+1]))84 85/*86 * currently, these following macros are the _only_ places that rely87 * on internal knowledge of HEntry. Everything else should be using88 * the above macros. Exception: the in-place upgrade in hstore_compat.c89 * messes with entries directly.90 */91 92/*93 * copy one key/value pair (which must be contiguous starting at94 * sptr_) into an under-construction hstore; dent_ is an HEntry*,95 * dbuf_ is the destination's string buffer, dptr_ is the current96 * position in the destination. lots of modification and multiple97 * 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 an110 * under-construction hstore111 */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 */150extern PGDLLEXPORT HStore *hstoreUpgrade(Datum orig);151 152#define DatumGetHStoreP(d) hstoreUpgrade(d)153 154#define PG_GETARG_HSTORE_P(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 */161typedef struct162{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 171extern PGDLLEXPORT int hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen);172extern PGDLLEXPORT HStore *hstorePairs(Pairs *pairs, int32 pcount, int32 buflen);173 174extern PGDLLEXPORT size_t hstoreCheckKeyLen(size_t len);175extern PGDLLEXPORT size_t hstoreCheckValLen(size_t len);176 177extern PGDLLEXPORT int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen);178extern PGDLLEXPORT Pairs *hstoreArrayToPairs(ArrayType *a, int *npairs);179 180#define HStoreContainsStrategyNumber 7181#define HStoreExistsStrategyNumber 9182#define HStoreExistsAnyStrategyNumber 10183#define HStoreExistsAllStrategyNumber 11184#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 dumps189 */190#ifndef HSTORE_POLLUTE_NAMESPACE191#define HSTORE_POLLUTE_NAMESPACE 1192#endif193 194#if HSTORE_POLLUTE_NAMESPACE195#define HSTORE_POLLUTE(newname_,oldname_) \196 PG_FUNCTION_INFO_V1(oldname_); \197 extern PGDLLEXPORT Datum newname_(PG_FUNCTION_ARGS); \198 Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \199 extern int no_such_variable200#else201#define HSTORE_POLLUTE(newname_,oldname_) \202 extern int no_such_variable203#endif204 205#endif /* __HSTORE_H__ */206 