PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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

PGDLLEXPORT HStorehstoreUpgrade (Datum orig)
 
PGDLLEXPORT int hstoreUniquePairs (Pairs *a, int32 l, int32 *buflen)
 
PGDLLEXPORT HStorehstorePairs (Pairs *pairs, int32 pcount, int32 buflen)
 
PGDLLEXPORT size_t hstoreCheckKeyLen (size_t len)
 
PGDLLEXPORT size_t hstoreCheckValLen (size_t len)
 
PGDLLEXPORT int hstoreFindKey (HStore *hs, int *lowbound, char *key, int keylen)
 
PGDLLEXPORT 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

#define CALCDATASIZE (   x,
  lenstr 
)    ( (x) * 2 * sizeof(HEntry) + HSHRDSIZE + (lenstr) )

Definition at line 72 of file hstore.h.

◆ DatumGetHStoreP

#define DatumGetHStoreP (   d)    hstoreUpgrade(d)

Definition at line 152 of file hstore.h.

◆ HENTRY_ISFIRST

#define HENTRY_ISFIRST   0x80000000

Definition at line 23 of file hstore.h.

◆ HENTRY_ISNULL

#define HENTRY_ISNULL   0x40000000

Definition at line 24 of file hstore.h.

◆ HENTRY_POSMASK

#define HENTRY_POSMASK   0x3FFFFFFF

Definition at line 25 of file hstore.h.

◆ 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:689

Definition at line 112 of file hstore.h.

◆ 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)

Definition at line 99 of file hstore.h.

◆ HS_COUNT

#define HS_COUNT (   hsp_)    ((hsp_)->size_ & 0x0FFFFFFF)

Definition at line 61 of file hstore.h.

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

Definition at line 129 of file hstore.h.

◆ 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 ARRPTR(x)
Definition: hstore.h:75
#define HSE_ENDPOS(he_)
Definition: hstore.h:30

Definition at line 143 of file hstore.h.

◆ HS_FLAG_NEWVERSION

#define HS_FLAG_NEWVERSION   0x80000000

Definition at line 59 of file hstore.h.

◆ HS_SETCOUNT

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

Definition at line 62 of file hstore.h.

◆ HSE_ENDPOS

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

Definition at line 30 of file hstore.h.

◆ HSE_ISFIRST

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

Definition at line 28 of file hstore.h.

◆ HSE_ISNULL

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

Definition at line 29 of file hstore.h.

◆ HSE_LEN

#define HSE_LEN (   he_)
Value:
(HSE_ISFIRST(he_) \
? HSE_ENDPOS(he_) \
: HSE_ENDPOS(he_) - HSE_ENDPOS((&(he_))[-1]))
#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.

◆ HSTORE_KEY

#define HSTORE_KEY (   arr_,
  str_,
  i_ 
)    ((str_) + HSE_OFF((arr_)[2*(i_)]))

Definition at line 79 of file hstore.h.

◆ HSTORE_KEYLEN

#define HSTORE_KEYLEN (   arr_,
  i_ 
)    (HSE_LEN((arr_)[2*(i_)]))

Definition at line 81 of file hstore.h.

◆ HSTORE_MAX_KEY_LEN

#define HSTORE_MAX_KEY_LEN   0x3FFFFFFF

Definition at line 41 of file hstore.h.

◆ HSTORE_MAX_VALUE_LEN

#define HSTORE_MAX_VALUE_LEN   0x3FFFFFFF

Definition at line 42 of file hstore.h.

◆ HSTORE_POLLUTE

#define HSTORE_POLLUTE (   newname_,
  oldname_ 
)
Value:
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
#define PGDLLEXPORT
Definition: c.h:1310
#define PG_FUNCTION_INFO_V1(funcname)
Definition: fmgr.h:415
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
uintptr_t Datum
Definition: postgres.h:64

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

#define HSTORE_VAL (   arr_,
  str_,
  i_ 
)    ((str_) + HSE_OFF((arr_)[2*(i_)+1]))

Definition at line 80 of file hstore.h.

◆ HSTORE_VALISNULL

#define HSTORE_VALISNULL (   arr_,
  i_ 
)    (HSE_ISNULL((arr_)[2*(i_)+1]))

Definition at line 83 of file hstore.h.

◆ HSTORE_VALLEN

#define HSTORE_VALLEN (   arr_,
  i_ 
)    (HSE_LEN((arr_)[2*(i_)+1]))

Definition at line 82 of file hstore.h.

◆ HStoreContainsStrategyNumber

#define HStoreContainsStrategyNumber   7

Definition at line 180 of file hstore.h.

◆ HStoreExistsAllStrategyNumber

#define HStoreExistsAllStrategyNumber   11

Definition at line 183 of file hstore.h.

◆ HStoreExistsAnyStrategyNumber

#define HStoreExistsAnyStrategyNumber   10

Definition at line 182 of file hstore.h.

◆ HStoreExistsStrategyNumber

#define HStoreExistsStrategyNumber   9

Definition at line 181 of file hstore.h.

◆ HStoreOldContainsStrategyNumber

#define HStoreOldContainsStrategyNumber   13 /* backwards compatibility */

Definition at line 184 of file hstore.h.

◆ PG_GETARG_HSTORE_P

#define PG_GETARG_HSTORE_P (   x)    DatumGetHStoreP(PG_GETARG_DATUM(x))

Definition at line 154 of file hstore.h.

◆ STRPTR

#define STRPTR (   x)    ( (char*)(ARRPTR(x) + HS_COUNT((HStore*)(x)) * 2) )

Definition at line 76 of file hstore.h.

Function Documentation

◆ hstoreArrayToPairs()

PGDLLEXPORT Pairs* hstoreArrayToPairs ( ArrayType a,
int *  npairs 
)

Definition at line 73 of file hstore_op.c.

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 
83  deconstruct_array_builtin(a, TEXTOID, &key_datums, &key_nulls, &key_count);
84 
85  if (key_count == 0)
86  {
87  *npairs = 0;
88  return NULL;
89  }
90 
91  /*
92  * A text array uses at least eight bytes per element, so any overflow in
93  * "key_count * sizeof(Pairs)" is small enough for palloc() to catch.
94  * However, credible improvements to the array format could invalidate
95  * that assumption. Therefore, use an explicit check rather than relying
96  * on palloc() to complain.
97  */
98  if (key_count > MaxAllocSize / sizeof(Pairs))
99  ereport(ERROR,
100  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
101  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
102  key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
103 
104  key_pairs = palloc(sizeof(Pairs) * key_count);
105 
106  for (i = 0, j = 0; i < key_count; i++)
107  {
108  if (!key_nulls[i])
109  {
110  key_pairs[j].key = VARDATA(key_datums[i]);
111  key_pairs[j].keylen = VARSIZE(key_datums[i]) - VARHDRSZ;
112  key_pairs[j].val = NULL;
113  key_pairs[j].vallen = 0;
114  key_pairs[j].needfree = 0;
115  key_pairs[j].isnull = 1;
116  j++;
117  }
118  }
119 
120  *npairs = hstoreUniquePairs(key_pairs, j, &bufsiz);
121 
122  return key_pairs;
123 }
void deconstruct_array_builtin(ArrayType *array, Oid elmtype, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3697
#define VARHDRSZ
Definition: c.h:671
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define MaxAllocSize
Definition: fe_memutils.h:22
#define hstoreUniquePairs
Definition: hstore_plperl.c:54
int a
Definition: isn.c:68
int j
Definition: isn.c:73
int i
Definition: isn.c:72
void * palloc(Size size)
Definition: mcxt.c:1317
Definition: hstore.h:162
char * val
Definition: hstore.h:164
bool isnull
Definition: hstore.h:167
size_t keylen
Definition: hstore.h:165
char * key
Definition: hstore.h:163
bool needfree
Definition: hstore.h:168
size_t vallen
Definition: hstore.h:166
#define VARDATA(PTR)
Definition: varatt.h:278
#define VARSIZE(PTR)
Definition: varatt.h:279

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

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

◆ hstoreCheckKeyLen()

PGDLLEXPORT size_t hstoreCheckKeyLen ( size_t  len)

Definition at line 404 of file hstore_io.c.

405 {
406  if (len > HSTORE_MAX_KEY_LEN)
407  ereport(ERROR,
408  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
409  errmsg("string too long for hstore key")));
410  return len;
411 }
#define HSTORE_MAX_KEY_LEN
Definition: hstore.h:41
const void size_t len

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

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

◆ hstoreCheckValLen()

PGDLLEXPORT size_t hstoreCheckValLen ( size_t  len)

Definition at line 424 of file hstore_io.c.

425 {
427  ereport(ERROR,
428  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
429  errmsg("string too long for hstore value")));
430  return len;
431 }
#define HSTORE_MAX_VALUE_LEN
Definition: hstore.h:42

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

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

◆ hstoreFindKey()

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

Definition at line 36 of file hstore_op.c.

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 ARRPTR(x)
Definition: cube.c:25
Datum difference(PG_FUNCTION_ARGS)
#define HSTORE_KEY(arr_, str_, i_)
Definition: hstore.h:79
#define HSTORE_KEYLEN(arr_, i_)
Definition: hstore.h:81
Definition: hstore.h:19

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(), hstore_slice_to_hstore(), and hstore_subscript_fetch().

◆ hstorePairs()

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

Definition at line 445 of file hstore_io.c.

446 {
447  HStore *out;
448  HEntry *entry;
449  char *ptr;
450  char *buf;
451  int32 len;
452  int32 i;
453 
454  len = CALCDATASIZE(pcount, buflen);
455  out = palloc(len);
456  SET_VARSIZE(out, len);
457  HS_SETCOUNT(out, pcount);
458 
459  if (pcount == 0)
460  return out;
461 
462  entry = ARRPTR(out);
463  buf = ptr = STRPTR(out);
464 
465  for (i = 0; i < pcount; i++)
466  HS_ADDITEM(entry, buf, ptr, pairs[i]);
467 
468  HS_FINALIZE(out, pcount, buf, ptr);
469 
470  return out;
471 }
signed int int32
Definition: c.h:482
#define HS_FINALIZE(hsp_, count_, buf_, ptr_)
Definition: hstore.h:129
#define HS_ADDITEM(dent_, dbuf_, dptr_, pair_)
Definition: hstore.h:112
#define HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62
static char * buf
Definition: pg_test_fsync.c:72
Definition: hstore.h:45
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305

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

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

◆ hstoreUniquePairs()

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

Definition at line 356 of file hstore_io.c.

357 {
358  Pairs *ptr,
359  *res;
360 
361  *buflen = 0;
362  if (l < 2)
363  {
364  if (l == 1)
365  *buflen = a->keylen + ((a->isnull) ? 0 : a->vallen);
366  return l;
367  }
368 
369  qsort(a, l, sizeof(Pairs), comparePairs);
370 
371  /*
372  * We can't use qunique here because we have some clean-up code to run on
373  * removed elements.
374  */
375  ptr = a + 1;
376  res = a;
377  while (ptr - a < l)
378  {
379  if (ptr->keylen == res->keylen &&
380  memcmp(ptr->key, res->key, res->keylen) == 0)
381  {
382  if (ptr->needfree)
383  {
384  pfree(ptr->key);
385  pfree(ptr->val);
386  }
387  }
388  else
389  {
390  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
391  res++;
392  if (res != ptr)
393  memcpy(res, ptr, sizeof(Pairs));
394  }
395 
396  ptr++;
397  }
398 
399  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
400  return res + 1 - a;
401 }
static int comparePairs(const void *a, const void *b)
Definition: hstore_io.c:326
void pfree(void *pointer)
Definition: mcxt.c:1521
#define qsort(a, b, c, d)
Definition: port.h:447

References a, comparePairs(), Pairs::key, Pairs::keylen, Pairs::needfree, pfree(), qsort, res, and Pairs::val.

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

◆ hstoreUpgrade()

PGDLLEXPORT HStore* hstoreUpgrade ( Datum  orig)

Definition at line 236 of file hstore_compat.c.

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 }
unsigned int uint32
Definition: c.h:492
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:225
#define PG_DETOAST_DATUM_COPY(datum)
Definition: fmgr.h:242
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
#define HS_FIXSIZE(hsp_, count_)
Definition: hstore.h:143
#define HS_FLAG_NEWVERSION
Definition: hstore.h:59
static int hstoreValidOldFormat(HStore *hs)
static int hstoreValidNewFormat(HStore *hs)
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
uint32 entry
Definition: hstore.h:20
uint16 vallen
uint16 keylen
uint32 pos
uint32 valisnull
uint32 size_
Definition: hstore.h:47

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