PostgreSQL Source Code  git master
hstore.h File Reference
#include "fmgr.h"
#include "utils/array.h"
Include dependency graph for hstore.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  HEntry
 
struct  HStore
 
struct  Pairs
 

Macros

#define HENTRY_ISFIRST   0x80000000
 
#define HENTRY_ISNULL   0x40000000
 
#define HENTRY_POSMASK   0x3FFFFFFF
 
#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_)
 
#define HSTORE_MAX_KEY_LEN   0x3FFFFFFF
 
#define HSTORE_MAX_VALUE_LEN   0x3FFFFFFF
 
#define HS_FLAG_NEWVERSION   0x80000000
 
#define HS_COUNT(hsp_)   ((hsp_)->size_ & 0x0FFFFFFF)
 
#define HS_SETCOUNT(hsp_, c_)   ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)
 
#define HSHRDSIZE   (sizeof(HStore))
 
#define CALCDATASIZE(x, lenstr)   ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )
 
#define ARRPTR(x)   ( (HEntry*) ( (HStore*)(x) + 1 ) )
 
#define STRPTR(x)   ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) )
 
#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]))
 
#define HS_COPYITEM(dent_, dbuf_, dptr_, sptr_, klen_, vlen_, vnull_)
 
#define HS_ADDITEM(dent_, dbuf_, dptr_, pair_)
 
#define HS_FINALIZE(hsp_, count_, buf_, ptr_)
 
#define HS_FIXSIZE(hsp_, count_)
 
#define DatumGetHStoreP(d)   hstoreUpgrade(d)
 
#define PG_GETARG_HSTORE_P(x)   DatumGetHStoreP(PG_GETARG_DATUM(x))
 
#define HStoreContainsStrategyNumber   7
 
#define HStoreExistsStrategyNumber   9
 
#define HStoreExistsAnyStrategyNumber   10
 
#define HStoreExistsAllStrategyNumber   11
 
#define HStoreOldContainsStrategyNumber   13 /* backwards compatibility */
 
#define HSTORE_POLLUTE_NAMESPACE   1
 
#define HSTORE_POLLUTE(newname_, oldname_)
 

Functions

HStorehstoreUpgrade (Datum orig)
 
int hstoreUniquePairs (Pairs *a, int32 l, int32 *buflen)
 
HStorehstorePairs (Pairs *pairs, int32 pcount, int32 buflen)
 
size_t hstoreCheckKeyLen (size_t len)
 
size_t hstoreCheckValLen (size_t len)
 
int hstoreFindKey (HStore *hs, int *lowbound, char *key, int keylen)
 
PairshstoreArrayToPairs (ArrayType *a, int *npairs)
 

Macro Definition Documentation

◆ ARRPTR

#define ARRPTR (   x)    ( (HEntry*) ( (HStore*)(x) + 1 ) )

Definition at line 75 of file hstore.h.

◆ CALCDATASIZE

◆ DatumGetHStoreP

#define DatumGetHStoreP (   d)    hstoreUpgrade(d)

Definition at line 152 of file hstore.h.

Referenced by ghstore_compress().

◆ HENTRY_ISFIRST

#define HENTRY_ISFIRST   0x80000000

Definition at line 23 of file hstore.h.

Referenced by hstoreUpgrade().

◆ HENTRY_ISNULL

#define HENTRY_ISNULL   0x40000000

Definition at line 24 of file hstore.h.

Referenced by hstoreUpgrade().

◆ HENTRY_POSMASK

#define HENTRY_POSMASK   0x3FFFFFFF

Definition at line 25 of file hstore.h.

Referenced by hstoreUpgrade().

◆ HS_ADDITEM

#define HS_ADDITEM (   dent_,
  dbuf_,
  dptr_,
  pair_ 
)
Value:
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) \
else \
{ \
memcpy((dptr_), (pair_).val, (pair_).vallen); \
(dptr_) += (pair_).vallen; \
(dent_)++->entry = ((dptr_) - (dbuf_)) & HENTRY_POSMASK; \
} \
} while (0)
#define HENTRY_POSMASK
Definition: hstore.h:25
#define HENTRY_ISNULL
Definition: hstore.h:24
long val
Definition: informix.c:684

Definition at line 112 of file hstore.h.

Referenced by hstorePairs().

◆ HS_COPYITEM

#define HS_COPYITEM (   dent_,
  dbuf_,
  dptr_,
  sptr_,
  klen_,
  vlen_,
  vnull_ 
)
Value:
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)
#define HENTRY_POSMASK
Definition: hstore.h:25
#define HENTRY_ISNULL
Definition: hstore.h:24

Definition at line 99 of file hstore.h.

Referenced by hstore_concat(), hstore_delete(), hstore_delete_array(), and hstore_delete_hstore().

◆ HS_COUNT

◆ HS_FINALIZE

#define HS_FINALIZE (   hsp_,
  count_,
  buf_,
  ptr_ 
)
Value:
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)
#define HS_COUNT(hsp_)
Definition: hstore.h:61
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
#define HENTRY_ISFIRST
Definition: hstore.h:23
#define STRPTR(x)
Definition: hstore.h:76

Definition at line 129 of file hstore.h.

Referenced by hstore_concat(), hstore_delete(), hstore_delete_array(), hstore_delete_hstore(), and hstorePairs().

◆ HS_FIXSIZE

#define HS_FIXSIZE (   hsp_,
  count_ 
)
Value:
do { \
int bl = (count_) ? HSE_ENDPOS(ARRPTR(hsp_)[2*(count_)-1]) : 0; \
SET_VARSIZE((hsp_), CALCDATASIZE((count_),bl)); \
} while (0)
#define HSE_ENDPOS(he_)
Definition: hstore.h:30
#define ARRPTR(x)
Definition: hstore.h:75
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72

Definition at line 143 of file hstore.h.

Referenced by hstore_concat(), hstore_delete_array(), hstore_delete_hstore(), and hstoreUpgrade().

◆ HS_FLAG_NEWVERSION

#define HS_FLAG_NEWVERSION   0x80000000

Definition at line 59 of file hstore.h.

Referenced by hstoreUpgrade(), hstoreValidNewFormat(), and hstoreValidOldFormat().

◆ HS_SETCOUNT

#define HS_SETCOUNT (   hsp_,
  c_ 
)    ((hsp_)->size_ = (c_) | HS_FLAG_NEWVERSION)

◆ HSE_ENDPOS

#define HSE_ENDPOS (   he_)    ((he_).entry & HENTRY_POSMASK)

Definition at line 30 of file hstore.h.

Referenced by hstore_cmp(), hstore_hash(), hstore_hash_extended(), and hstoreValidNewFormat().

◆ HSE_ISFIRST

#define HSE_ISFIRST (   he_)    (((he_).entry & HENTRY_ISFIRST) != 0)

Definition at line 28 of file hstore.h.

Referenced by hstoreUpgrade(), and hstoreValidNewFormat().

◆ HSE_ISNULL

#define HSE_ISNULL (   he_)    (((he_).entry & HENTRY_ISNULL) != 0)

Definition at line 29 of file hstore.h.

Referenced by hstore_cmp(), and hstoreValidNewFormat().

◆ HSE_LEN

#define HSE_LEN (   he_)
Value:
(HSE_ISFIRST(he_) \
? HSE_ENDPOS(he_) \
: HSE_ENDPOS(he_) - HSE_ENDPOS((&(he_))[-1]))
#define HSE_ENDPOS(he_)
Definition: hstore.h:30
#define HSE_ISFIRST(he_)
Definition: hstore.h:28

Definition at line 32 of file hstore.h.

◆ HSE_OFF

#define HSE_OFF (   he_)    (HSE_ISFIRST(he_) ? 0 : HSE_ENDPOS((&(he_))[-1]))

Definition at line 31 of file hstore.h.

◆ HSHRDSIZE

#define HSHRDSIZE   (sizeof(HStore))

Definition at line 71 of file hstore.h.

Referenced by hstore_concat(), hstore_hash(), and hstore_hash_extended().

◆ HSTORE_KEY

◆ HSTORE_KEYLEN

◆ HSTORE_MAX_KEY_LEN

#define HSTORE_MAX_KEY_LEN   0x3FFFFFFF

Definition at line 41 of file hstore.h.

Referenced by hstoreCheckKeyLen().

◆ HSTORE_MAX_VALUE_LEN

#define HSTORE_MAX_VALUE_LEN   0x3FFFFFFF

Definition at line 42 of file hstore.h.

Referenced by hstoreCheckValLen().

◆ HSTORE_POLLUTE

#define HSTORE_POLLUTE (   newname_,
  oldname_ 
)
Value:
PG_FUNCTION_INFO_V1(oldname_); \
Datum newname_(PG_FUNCTION_ARGS); \
Datum oldname_(PG_FUNCTION_ARGS) { return newname_(fcinfo); } \
extern int no_such_variable
#define PG_FUNCTION_INFO_V1(funcname)
Definition: fmgr.h:404
#define PG_FUNCTION_ARGS
Definition: fmgr.h:188

Definition at line 195 of file hstore.h.

◆ HSTORE_POLLUTE_NAMESPACE

#define HSTORE_POLLUTE_NAMESPACE   1

Definition at line 191 of file hstore.h.

◆ HSTORE_VAL

◆ HSTORE_VALISNULL

◆ HSTORE_VALLEN

◆ HStoreContainsStrategyNumber

#define HStoreContainsStrategyNumber   7

Definition at line 180 of file hstore.h.

Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().

◆ HStoreExistsAllStrategyNumber

#define HStoreExistsAllStrategyNumber   11

Definition at line 183 of file hstore.h.

Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().

◆ HStoreExistsAnyStrategyNumber

#define HStoreExistsAnyStrategyNumber   10

Definition at line 182 of file hstore.h.

Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().

◆ HStoreExistsStrategyNumber

#define HStoreExistsStrategyNumber   9

Definition at line 181 of file hstore.h.

Referenced by ghstore_consistent(), gin_consistent_hstore(), and gin_extract_hstore_query().

◆ HStoreOldContainsStrategyNumber

#define HStoreOldContainsStrategyNumber   13 /* backwards compatibility */

Definition at line 184 of file hstore.h.

Referenced by ghstore_consistent().

◆ PG_GETARG_HSTORE_P

◆ STRPTR

Function Documentation

◆ hstoreArrayToPairs()

Pairs* hstoreArrayToPairs ( ArrayType a,
int *  npairs 
)

Definition at line 73 of file hstore_op.c.

References deconstruct_array(), ereport, errcode(), errmsg(), ERROR, hstore_fetchval(), hstoreUniquePairs, i, Pairs::isnull, Pairs::key, Pairs::keylen, MaxAllocSize, Pairs::needfree, palloc(), PG_FUNCTION_INFO_V1(), Pairs::val, Pairs::vallen, VARDATA, VARHDRSZ, and VARSIZE.

Referenced by hstore_delete_array(), hstore_exists_all(), hstore_exists_any(), and hstore_slice_to_hstore().

74 {
75  Datum *key_datums;
76  bool *key_nulls;
77  int key_count;
78  Pairs *key_pairs;
79  int bufsiz;
80  int i,
81  j;
82 
84  TEXTOID, -1, false, 'i',
85  &key_datums, &key_nulls, &key_count);
86 
87  if (key_count == 0)
88  {
89  *npairs = 0;
90  return NULL;
91  }
92 
93  /*
94  * A text array uses at least eight bytes per element, so any overflow in
95  * "key_count * sizeof(Pairs)" is small enough for palloc() to catch.
96  * However, credible improvements to the array format could invalidate
97  * that assumption. Therefore, use an explicit check rather than relying
98  * on palloc() to complain.
99  */
100  if (key_count > MaxAllocSize / sizeof(Pairs))
101  ereport(ERROR,
102  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
103  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
104  key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
105 
106  key_pairs = palloc(sizeof(Pairs) * key_count);
107 
108  for (i = 0, j = 0; i < key_count; i++)
109  {
110  if (!key_nulls[i])
111  {
112  key_pairs[j].key = VARDATA(key_datums[i]);
113  key_pairs[j].keylen = VARSIZE(key_datums[i]) - VARHDRSZ;
114  key_pairs[j].val = NULL;
115  key_pairs[j].vallen = 0;
116  key_pairs[j].needfree = 0;
117  key_pairs[j].isnull = 1;
118  j++;
119  }
120  }
121 
122  *npairs = hstoreUniquePairs(key_pairs, j, &bufsiz);
123 
124  return key_pairs;
125 }
#define VARDATA(PTR)
Definition: postgres.h:302
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:556
int errcode(int sqlerrcode)
Definition: elog.c:608
size_t vallen
Definition: hstore.h:166
bool needfree
Definition: hstore.h:168
char * val
Definition: hstore.h:164
char * key
Definition: hstore.h:163
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define MaxAllocSize
Definition: memutils.h:40
#define hstoreUniquePairs
Definition: hstore_plperl.c:57
uintptr_t Datum
Definition: postgres.h:367
size_t keylen
Definition: hstore.h:165
bool isnull
Definition: hstore.h:167
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
Definition: hstore.h:161

◆ hstoreCheckKeyLen()

size_t hstoreCheckKeyLen ( size_t  len)

Definition at line 359 of file hstore_io.c.

References ereport, errcode(), errmsg(), ERROR, and HSTORE_MAX_KEY_LEN.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_recv(), and parse_hstore().

360 {
361  if (len > HSTORE_MAX_KEY_LEN)
362  ereport(ERROR,
363  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
364  errmsg("string too long for hstore key")));
365  return len;
366 }
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
#define HSTORE_MAX_KEY_LEN
Definition: hstore.h:41
int errmsg(const char *fmt,...)
Definition: elog.c:822

◆ hstoreCheckValLen()

size_t hstoreCheckValLen ( size_t  len)

Definition at line 369 of file hstore_io.c.

References ereport, errcode(), errmsg(), ERROR, and HSTORE_MAX_VALUE_LEN.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_recv(), and parse_hstore().

370 {
371  if (len > HSTORE_MAX_VALUE_LEN)
372  ereport(ERROR,
373  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
374  errmsg("string too long for hstore value")));
375  return len;
376 }
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
int errmsg(const char *fmt,...)
Definition: elog.c:822
#define HSTORE_MAX_VALUE_LEN
Definition: hstore.h:42

◆ hstoreFindKey()

int hstoreFindKey ( HStore hs,
int *  lowbound,
char *  key,
int  keylen 
)

Definition at line 36 of file hstore_op.c.

References ARRPTR, difference(), HS_COUNT, HSTORE_KEY, HSTORE_KEYLEN, sort-test::key, and STRPTR.

Referenced by hstore_contains(), hstore_defined(), hstore_exists(), hstore_exists_all(), hstore_exists_any(), hstore_fetchval(), hstore_populate_record(), hstore_slice_to_array(), and hstore_slice_to_hstore().

37 {
38  HEntry *entries = ARRPTR(hs);
39  int stopLow = lowbound ? *lowbound : 0;
40  int stopHigh = HS_COUNT(hs);
41  int stopMiddle;
42  char *base = STRPTR(hs);
43 
44  while (stopLow < stopHigh)
45  {
46  int difference;
47 
48  stopMiddle = stopLow + (stopHigh - stopLow) / 2;
49 
50  if (HSTORE_KEYLEN(entries, stopMiddle) == keylen)
51  difference = memcmp(HSTORE_KEY(entries, base, stopMiddle), key, keylen);
52  else
53  difference = (HSTORE_KEYLEN(entries, stopMiddle) > keylen) ? 1 : -1;
54 
55  if (difference == 0)
56  {
57  if (lowbound)
58  *lowbound = stopMiddle + 1;
59  return stopMiddle;
60  }
61  else if (difference < 0)
62  stopLow = stopMiddle + 1;
63  else
64  stopHigh = stopMiddle;
65  }
66 
67  if (lowbound)
68  *lowbound = stopLow;
69  return -1;
70 }
#define HSTORE_KEYLEN(arr_, i_)
Definition: hstore.h:81
#define HS_COUNT(hsp_)
Definition: hstore.h:61
#define HSTORE_KEY(arr_, str_, i_)
Definition: hstore.h:79
Datum difference(PG_FUNCTION_ARGS)
Definition: hstore.h:18
#define STRPTR(x)
Definition: hstore.h:76
#define ARRPTR(x)
Definition: cube.c:24

◆ hstorePairs()

HStore* hstorePairs ( Pairs pairs,
int32  pcount,
int32  buflen 
)

Definition at line 380 of file hstore_io.c.

References ARRPTR, buf, CALCDATASIZE, HS_ADDITEM, HS_FINALIZE, HS_SETCOUNT, hstore_in(), i, palloc(), PG_FUNCTION_INFO_V1(), SET_VARSIZE, and STRPTR.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_from_text(), hstore_in(), and hstore_recv().

381 {
382  HStore *out;
383  HEntry *entry;
384  char *ptr;
385  char *buf;
386  int32 len;
387  int32 i;
388 
389  len = CALCDATASIZE(pcount, buflen);
390  out = palloc(len);
391  SET_VARSIZE(out, len);
392  HS_SETCOUNT(out, pcount);
393 
394  if (pcount == 0)
395  return out;
396 
397  entry = ARRPTR(out);
398  buf = ptr = STRPTR(out);
399 
400  for (i = 0; i < pcount; i++)
401  HS_ADDITEM(entry, buf, ptr, pairs[i]);
402 
403  HS_FINALIZE(out, pcount, buf, ptr);
404 
405  return out;
406 }
Definition: hstore.h:44
signed int int32
Definition: c.h:347
static char * buf
Definition: pg_test_fsync.c:67
#define HS_ADDITEM(dent_, dbuf_, dptr_, pair_)
Definition: hstore.h:112
#define HS_FINALIZE(hsp_, count_, buf_, ptr_)
Definition: hstore.h:129
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
Definition: hstore.h:18
void * palloc(Size size)
Definition: mcxt.c:949
#define STRPTR(x)
Definition: hstore.h:76
int i
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:329
#define ARRPTR(x)
Definition: cube.c:24
#define HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62

◆ hstoreUniquePairs()

int hstoreUniquePairs ( Pairs a,
int32  l,
int32 buflen 
)

Definition at line 311 of file hstore_io.c.

References comparePairs(), Pairs::isnull, Pairs::key, Pairs::keylen, Pairs::needfree, pfree(), qsort, Pairs::val, and Pairs::vallen.

Referenced by hstore_from_array(), hstore_from_arrays(), hstore_from_record(), hstore_in(), and hstore_recv().

312 {
313  Pairs *ptr,
314  *res;
315 
316  *buflen = 0;
317  if (l < 2)
318  {
319  if (l == 1)
320  *buflen = a->keylen + ((a->isnull) ? 0 : a->vallen);
321  return l;
322  }
323 
324  qsort((void *) a, l, sizeof(Pairs), comparePairs);
325 
326  /*
327  * We can't use qunique here because we have some clean-up code to run on
328  * removed elements.
329  */
330  ptr = a + 1;
331  res = a;
332  while (ptr - a < l)
333  {
334  if (ptr->keylen == res->keylen &&
335  memcmp(ptr->key, res->key, res->keylen) == 0)
336  {
337  if (ptr->needfree)
338  {
339  pfree(ptr->key);
340  pfree(ptr->val);
341  }
342  }
343  else
344  {
345  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
346  res++;
347  if (res != ptr)
348  memcpy(res, ptr, sizeof(Pairs));
349  }
350 
351  ptr++;
352  }
353 
354  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
355  return res + 1 - a;
356 }
size_t vallen
Definition: hstore.h:166
bool needfree
Definition: hstore.h:168
char * val
Definition: hstore.h:164
char * key
Definition: hstore.h:163
void pfree(void *pointer)
Definition: mcxt.c:1056
static int comparePairs(const void *a, const void *b)
Definition: hstore_io.c:281
size_t keylen
Definition: hstore.h:165
bool isnull
Definition: hstore.h:167
#define qsort(a, b, c, d)
Definition: port.h:492
Definition: hstore.h:161

◆ hstoreUpgrade()

HStore* hstoreUpgrade ( Datum  orig)

Definition at line 236 of file hstore_compat.c.

References ARRPTR, DatumGetPointer, elog, HEntry::entry, ERROR, HENTRY_ISFIRST, HENTRY_ISNULL, HENTRY_POSMASK, HS_COUNT, HS_FIXSIZE, HS_FLAG_NEWVERSION, HS_SETCOUNT, HSE_ISFIRST, hstore_version_diag(), hstoreValidNewFormat(), hstoreValidOldFormat(), i, HOldEntry::keylen, PG_DETOAST_DATUM, PG_DETOAST_DATUM_COPY, PG_FUNCTION_INFO_V1(), HOldEntry::pos, HStore::size_, HOldEntry::valisnull, HOldEntry::vallen, VARSIZE, and WARNING.

237 {
238  HStore *hs = (HStore *) PG_DETOAST_DATUM(orig);
239  int valid_new;
240  int valid_old;
241 
242  /* Return immediately if no conversion needed */
243  if (hs->size_ & HS_FLAG_NEWVERSION)
244  return hs;
245 
246  /* Do we have a writable copy? If not, make one. */
247  if ((void *) hs == (void *) DatumGetPointer(orig))
248  hs = (HStore *) PG_DETOAST_DATUM_COPY(orig);
249 
250  if (hs->size_ == 0 ||
251  (VARSIZE(hs) < 32768 && HSE_ISFIRST((ARRPTR(hs)[0]))))
252  {
253  HS_SETCOUNT(hs, HS_COUNT(hs));
254  HS_FIXSIZE(hs, HS_COUNT(hs));
255  return hs;
256  }
257 
258  valid_new = hstoreValidNewFormat(hs);
259  valid_old = hstoreValidOldFormat(hs);
260 
261  if (!valid_old || hs->size_ == 0)
262  {
263  if (valid_new)
264  {
265  /*
266  * force the "new version" flag and the correct varlena length.
267  */
268  HS_SETCOUNT(hs, HS_COUNT(hs));
269  HS_FIXSIZE(hs, HS_COUNT(hs));
270  return hs;
271  }
272  else
273  {
274  elog(ERROR, "invalid hstore value found");
275  }
276  }
277 
278  /*
279  * this is the tricky edge case. It is only possible in some quite extreme
280  * cases (the hstore must have had a lot of wasted padding space at the
281  * end). But the only way a "new" hstore value could get here is if we're
282  * upgrading in place from a pre-release version of hstore-new (NOT
283  * contrib/hstore), so we work off the following assumptions: 1. If you're
284  * moving from old contrib/hstore to hstore-new, you're required to fix up
285  * any potential conflicts first, e.g. by running ALTER TABLE ... USING
286  * col::text::hstore; on all hstore columns before upgrading. 2. If you're
287  * moving from old contrib/hstore to new contrib/hstore, then "new" values
288  * are impossible here 3. If you're moving from pre-release hstore-new to
289  * hstore-new, then "old" values are impossible here 4. If you're moving
290  * from pre-release hstore-new to new contrib/hstore, you're not doing so
291  * as an in-place upgrade, so there is no issue So the upshot of all this
292  * is that we can treat all the edge cases as "new" if we're being built
293  * as hstore-new, and "old" if we're being built as contrib/hstore.
294  *
295  * XXX the WARNING can probably be downgraded to DEBUG1 once this has been
296  * beta-tested. But for now, it would be very useful to know if anyone can
297  * actually reach this case in a non-contrived setting.
298  */
299 
300  if (valid_new)
301  {
302 #ifdef HSTORE_IS_HSTORE_NEW
303  elog(WARNING, "ambiguous hstore value resolved as hstore-new");
304 
305  /*
306  * force the "new version" flag and the correct varlena length.
307  */
308  HS_SETCOUNT(hs, HS_COUNT(hs));
309  HS_FIXSIZE(hs, HS_COUNT(hs));
310  return hs;
311 #else
312  elog(WARNING, "ambiguous hstore value resolved as hstore-old");
313 #endif
314  }
315 
316  /*
317  * must have an old-style value. Overwrite it in place as a new-style one.
318  */
319  {
320  int count = hs->size_;
321  HEntry *new_entries = ARRPTR(hs);
322  HOldEntry *old_entries = (HOldEntry *) ARRPTR(hs);
323  int i;
324 
325  for (i = 0; i < count; ++i)
326  {
327  uint32 pos = old_entries[i].pos;
328  uint32 keylen = old_entries[i].keylen;
329  uint32 vallen = old_entries[i].vallen;
330  bool isnull = old_entries[i].valisnull;
331 
332  if (isnull)
333  vallen = 0;
334 
335  new_entries[2 * i].entry = (pos + keylen) & HENTRY_POSMASK;
336  new_entries[2 * i + 1].entry = (((pos + keylen + vallen) & HENTRY_POSMASK)
337  | ((isnull) ? HENTRY_ISNULL : 0));
338  }
339 
340  if (count)
341  new_entries[0].entry |= HENTRY_ISFIRST;
342  HS_SETCOUNT(hs, count);
343  HS_FIXSIZE(hs, count);
344  }
345 
346  return hs;
347 }
Definition: hstore.h:44
#define HENTRY_POSMASK
Definition: hstore.h:25
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:237
#define VARSIZE(PTR)
Definition: postgres.h:303
#define HSE_ISFIRST(he_)
Definition: hstore.h:28
#define HENTRY_ISNULL
Definition: hstore.h:24
static int hstoreValidNewFormat(HStore *hs)
uint16 keylen
#define ERROR
Definition: elog.h:43
#define HS_FLAG_NEWVERSION
Definition: hstore.h:59
#define HS_COUNT(hsp_)
Definition: hstore.h:61
uint16 vallen
uint32 entry
Definition: hstore.h:20
unsigned int uint32
Definition: c.h:359
#define WARNING
Definition: elog.h:40
static int hstoreValidOldFormat(HStore *hs)
#define HENTRY_ISFIRST
Definition: hstore.h:23
uint32 valisnull
uint32 pos
Definition: hstore.h:18
#define DatumGetPointer(X)
Definition: postgres.h:549
uint32 size_
Definition: hstore.h:47
#define elog(elevel,...)
Definition: elog.h:228
int i
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:235
#define ARRPTR(x)
Definition: cube.c:24
#define HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62
#define HS_FIXSIZE(hsp_, count_)
Definition: hstore.h:143