2 #include "utils/builtins.h"
6 /****************************************************************************
8 ****************************************************************************/
10 compareHStoreStringValue(const void *a, const void *b, void *arg)
12 const HStoreValue *va = a;
13 const HStoreValue *vb = b;
16 Assert(va->type == hsvString);
17 Assert(vb->type == hsvString);
19 if (va->string.len == vb->string.len)
21 res = memcmp(va->string.val, vb->string.val, va->string.len);
27 res = (va->string.len > vb->string.len) ? 1 : -1;
34 compareHStorePair(const void *a, const void *b, void *arg)
36 const HStorePair *pa = a;
37 const HStorePair *pb = b;
40 res = compareHStoreStringValue(&pa->key, &pb->key, arg);
43 * guarantee keeping order of equal pair. Unique algorithm will
44 * prefer first element as value
48 res = (pa->order > pb->order) ? -1 : 1;
54 compareHStoreValue(HStoreValue *a, HStoreValue *b)
56 if (a->type == b->type)
63 return compareHStoreStringValue(a, b, NULL);
65 if (a->boolean == b->boolean)
67 return (a->boolean > b->boolean) ? 1 : -1;
69 return DatumGetInt32(DirectFunctionCall2(numeric_cmp,
70 PointerGetDatum(a->numeric),
71 PointerGetDatum(b->numeric)));
73 if (a->array.nelems == b->array.nelems)
77 for(i=0; i<a->array.nelems; i++)
78 if ((r = compareHStoreValue(a->array.elems + i,
79 b->array.elems + i)) != 0)
85 return (a->array.nelems > b->array.nelems) ? 1 : -1;
87 if (a->hash.npairs == b->hash.npairs)
91 for(i=0; i<a->hash.npairs; i++)
93 if ((r = compareHStoreStringValue(&a->hash.pairs[i].key,
94 &b->hash.pairs[i].key,
97 if ((r = compareHStoreValue(&a->hash.pairs[i].value,
98 &b->hash.pairs[i].value)) != 0)
105 return (a->hash.npairs > b->hash.npairs) ? 1 : -1;
107 return compareHStoreBinaryValue(a->binary.data, b->binary.data);
109 elog(PANIC, "unknown HStoreValue->type: %d", a->type);
113 return (a->type > b->type) ? 1 : -1;
117 compareHStoreBinaryValue(char *a, char *b)
119 HStoreIterator *it1, *it2;
122 it1 = HStoreIteratorInit(a);
123 it2 = HStoreIteratorInit(b);
130 r1 = HStoreIteratorGet(&it1, &v1, false);
131 r2 = HStoreIteratorGet(&it2, &v2, false);
138 if (v1.type == v2.type)
143 res = compareHStoreStringValue(&v1, &v2, NULL);
146 if (v1.boolean == v2.boolean)
149 res = (v1.boolean > v2.boolean) ? 1 : -1;
152 res = DatumGetInt32(DirectFunctionCall2(numeric_cmp,
153 PointerGetDatum(v1.numeric),
154 PointerGetDatum(v2.numeric)));
157 if (v1.array.nelems != v2.array.nelems)
158 res = (v1.array.nelems > v2.array.nelems) ? 1 : -1;
161 if (v1.hash.npairs != v2.hash.npairs)
162 res = (v1.hash.npairs > v2.hash.npairs) ? 1 : -1;
170 res = (v1.type > v2.type) ? 1 : -1; /* dummy order */
175 res = (r1 > r2) ? 1 : -1; /* dummy order */
183 * Sort and unique pairs in hash-like HStoreValue
186 uniqueHStoreValue(HStoreValue *v)
188 bool hasNonUniq = false;
190 Assert(v->type == hsvHash);
192 if (v->hash.npairs > 1)
193 qsort_arg(v->hash.pairs, v->hash.npairs, sizeof(*v->hash.pairs),
194 compareHStorePair, &hasNonUniq);
198 HStorePair *ptr = v->hash.pairs + 1,
199 *res = v->hash.pairs;
201 while(ptr - v->hash.pairs < v->hash.npairs)
203 if (ptr->key.string.len == res->key.string.len &&
204 memcmp(ptr->key.string.val, res->key.string.val,
205 ptr->key.string.len) == 0)
207 v->size -= ptr->key.size + ptr->value.size;
213 memcpy(res, ptr, sizeof(*res));
218 v->hash.npairs = res + 1 - v->hash.pairs;
223 /****************************************************************************
224 * find string key in hash or array *
225 ****************************************************************************/
227 findUncompressedHStoreValueByValue(char *buffer, uint32 flags, uint32 *lowbound, HStoreValue *key)
229 uint32 header = *(uint32*)buffer;
230 static HStoreValue r;
232 Assert((header & (HS_FLAG_ARRAY | HS_FLAG_HSTORE)) !=
233 (HS_FLAG_ARRAY | HS_FLAG_HSTORE));
235 if (flags & HS_FLAG_ARRAY & header)
237 HEntry *array = (HEntry*)(buffer + sizeof(header));
238 char *data = (char*)(array + (header & HS_COUNT_MASK));
241 for(i=(lowbound) ? *lowbound : 0; i<(header & HS_COUNT_MASK); i++) {
242 HEntry *e = array + i;
244 if (HSE_ISNULL(*e) && key->type == hsvNull)
249 r.size = sizeof(HEntry);
253 else if (HSE_ISSTRING(*e) && key->type == hsvString )
255 if (key->string.len == HSE_LEN(*e) &&
256 memcmp(key->string.val, data + HSE_OFF(*e),
257 key->string.len) == 0)
260 r.string.val = data + HSE_OFF(*e);
261 r.string.len = key->string.len;
262 r.size = sizeof(HEntry) + r.string.len;
269 else if (HSE_ISBOOL(*e) && key->type == hsvBool)
271 if ((HSE_ISBOOL_TRUE(*e) && key->boolean == true) ||
272 (HSE_ISBOOL_FALSE(*e) && key->boolean == false))
275 r.size = sizeof(HEntry);
282 else if (HSE_ISNUMERIC(*e) && key->type == hsvNumeric)
284 if (DatumGetBool(DirectFunctionCall2(numeric_eq,
285 PointerGetDatum(data + INTALIGN(HSE_OFF(*e))),
286 PointerGetDatum(key->numeric))) == true)
289 r.numeric = (Numeric)(data + INTALIGN(HSE_OFF(*e)));
298 else if (flags & HS_FLAG_HSTORE & header)
300 HEntry *array = (HEntry*)(buffer + sizeof(header));
301 char *data = (char*)(array + (header & HS_COUNT_MASK) * 2);
302 uint32 stopLow = lowbound ? *lowbound : 0,
303 stopHigh = (header & HS_COUNT_MASK),
306 if (key->type != hsvString)
309 while (stopLow < stopHigh)
314 stopMiddle = stopLow + (stopHigh - stopLow) / 2;
316 e = array + stopMiddle * 2;
318 if (key->string.len == HSE_LEN(*e))
319 difference = memcmp(data + HSE_OFF(*e), key->string.val,
322 difference = (HSE_LEN(*e) > key->string.len) ? 1 : -1;
329 *lowbound = stopMiddle + 1;
331 if (HSE_ISSTRING(*v))
334 r.string.val = data + HSE_OFF(*v);
335 r.string.len = HSE_LEN(*v);
336 r.size = sizeof(HEntry) + r.string.len;
338 else if (HSE_ISBOOL(*v))
341 r.boolean = (HSE_ISBOOL_TRUE(*v)) ? true : false;
342 r.size = sizeof(HEntry);
344 else if (HSE_ISNUMERIC(*v))
347 r.numeric = (Numeric)(data + INTALIGN(HSE_OFF(*v)));
348 r.size = 2*sizeof(HEntry) + VARSIZE_ANY(r.numeric);
350 else if (HSE_ISNULL(*v))
353 r.size = sizeof(HEntry);
358 r.binary.data = data + INTALIGN(HSE_OFF(*v));
359 r.binary.len = HSE_LEN(*v) -
360 (INTALIGN(HSE_OFF(*v)) - HSE_OFF(*v));
361 r.size = 2*sizeof(HEntry) + r.binary.len;
366 else if (difference < 0)
368 stopLow = stopMiddle + 1;
372 stopHigh = stopMiddle;
384 findUncompressedHStoreValue(char *buffer, uint32 flags, uint32 *lowbound,
385 char *key, uint32 keylen)
397 v.string.len = keylen;
400 return findUncompressedHStoreValueByValue(buffer, flags, lowbound, &v);
404 getHStoreValue(char *buffer, uint32 flags, int32 i)
406 uint32 header = *(uint32*)buffer;
407 static HStoreValue r;
411 Assert((header & (HS_FLAG_ARRAY | HS_FLAG_HSTORE)) !=
412 (HS_FLAG_ARRAY | HS_FLAG_HSTORE));
416 if (i >= (header & HS_COUNT_MASK))
421 if (-i > (header & HS_COUNT_MASK))
424 i = (header & HS_COUNT_MASK) + i;
427 array = (HEntry*)(buffer + sizeof(header));
429 if (flags & HS_FLAG_ARRAY & header)
432 data = (char*)(array + (header & HS_COUNT_MASK));
434 else if (flags & HS_FLAG_HSTORE & header)
436 e = array + i * 2 + 1;
437 data = (char*)(array + (header & HS_COUNT_MASK) * 2);
444 if (HSE_ISSTRING(*e))
447 r.string.val = data + HSE_OFF(*e);
448 r.string.len = HSE_LEN(*e);
449 r.size = sizeof(HEntry) + r.string.len;
451 else if (HSE_ISBOOL(*e))
454 r.boolean = (HSE_ISBOOL_TRUE(*e)) ? true : false;
455 r.size = sizeof(HEntry);
457 else if (HSE_ISNUMERIC(*e))
460 r.numeric = (Numeric)(data + INTALIGN(HSE_OFF(*e)));
461 r.size = 2*sizeof(HEntry) + VARSIZE_ANY(r.numeric);
463 else if (HSE_ISNULL(*e))
466 r.size = sizeof(HEntry);
471 r.binary.data = data + INTALIGN(HSE_OFF(*e));
472 r.binary.len = HSE_LEN(*e) - (INTALIGN(HSE_OFF(*e)) - HSE_OFF(*e));
473 r.size = r.binary.len + 2*sizeof(HEntry);
479 /****************************************************************************
480 * Walk on tree representation of hstore *
481 ****************************************************************************/
483 walkUncompressedHStoreDo(HStoreValue *v, walk_hstore_cb cb, void *cb_arg,
491 cb(cb_arg, v, WHS_BEGIN_ARRAY, level);
492 for(i=0; i<v->array.nelems; i++)
494 if (v->array.elems[i].type == hsvNull ||
495 v->array.elems[i].type == hsvString ||
496 v->array.elems[i].type == hsvBool ||
497 v->array.elems[i].type == hsvNumeric ||
498 v->array.elems[i].type == hsvBinary)
499 cb(cb_arg, v->array.elems + i, WHS_ELEM, level);
501 walkUncompressedHStoreDo(v->array.elems + i, cb, cb_arg,
504 cb(cb_arg, v, WHS_END_ARRAY, level);
507 cb(cb_arg, v, WHS_BEGIN_HASH, level);
509 for(i=0; i<v->hash.npairs; i++)
511 cb(cb_arg, &v->hash.pairs[i].key, WHS_KEY, level);
513 if (v->hash.pairs[i].value.type == hsvNull ||
514 v->hash.pairs[i].value.type == hsvString ||
515 v->hash.pairs[i].value.type == hsvBool ||
516 v->hash.pairs[i].value.type == hsvNumeric ||
517 v->hash.pairs[i].value.type == hsvBinary)
518 cb(cb_arg, &v->hash.pairs[i].value, WHS_VALUE, level);
520 walkUncompressedHStoreDo(&v->hash.pairs[i].value, cb, cb_arg, level + 1);
523 cb(cb_arg, v, WHS_END_HASH, level);
526 elog(PANIC, "impossible HStoreValue->type: %d", v->type);
531 walkUncompressedHStore(HStoreValue *v, walk_hstore_cb cb, void *cb_arg)
534 walkUncompressedHStoreDo(v, cb, cb_arg, 0);
537 /****************************************************************************
538 * Iteration over binary hstore *
539 ****************************************************************************/
541 parseBuffer(HStoreIterator *it, char *buffer)
543 uint32 header = *(uint32*)buffer;
545 it->type = header & (HS_FLAG_ARRAY | HS_FLAG_HSTORE);
546 it->nelems = header & HS_COUNT_MASK;
550 buffer += sizeof(uint32);
551 it->array = (HEntry*)buffer;
553 it->state = hsi_start;
558 it->data = buffer + it->nelems * sizeof(HEntry);
559 it->isScalar = (header & HS_FLAG_SCALAR) ? true : false;
560 Assert(it->isScalar == false || it->nelems == 1);
563 it->data = buffer + it->nelems * sizeof(HEntry) * 2;
566 elog(PANIC, "impossible type: %08x", it->type);
571 HStoreIteratorInit(char *buffer)
573 HStoreIterator *it = palloc(sizeof(*it));
575 parseBuffer(it, buffer);
582 formAnswer(HStoreIterator **it, HStoreValue *v, HEntry *e, bool skipNested)
584 if (HSE_ISSTRING(*e))
587 v->string.val = (*it)->data + HSE_OFF(*e);
588 v->string.len = HSE_LEN(*e);
589 v->size = sizeof(HEntry) + v->string.len;
593 else if (HSE_ISBOOL(*e))
596 v->boolean = (HSE_ISBOOL_TRUE(*e)) ? true : false;
597 v->size = sizeof(HEntry);
601 else if (HSE_ISNUMERIC(*e))
603 v->type = hsvNumeric;
604 v->numeric = (Numeric)((*it)->data + INTALIGN(HSE_OFF(*e)));
605 v->size = 2*sizeof(HEntry) + VARSIZE_ANY(v->numeric);
609 else if (HSE_ISNULL(*e))
612 v->size = sizeof(HEntry);
619 v->binary.data = (*it)->data + INTALIGN(HSE_OFF(*e));
620 v->binary.len = HSE_LEN(*e) - (INTALIGN(HSE_OFF(*e)) - HSE_OFF(*e));
621 v->size = v->binary.len + 2*sizeof(HEntry);
627 HStoreIterator *nit = palloc(sizeof(*nit));
629 parseBuffer(nit, (*it)->data + INTALIGN(HSE_OFF(*e)));
637 static HStoreIterator*
638 up(HStoreIterator *it)
640 HStoreIterator *v = it->next;
648 HStoreIteratorGet(HStoreIterator **it, HStoreValue *v, bool skipNested)
656 * Encode all possible states by one integer. That's possible
657 * because enum members of HStoreIterator->state uses different bits
658 * than HS_FLAG_ARRAY/HS_FLAG_HSTORE. See definition of HStoreIterator
661 switch((*it)->type | (*it)->state)
663 case HS_FLAG_ARRAY | hsi_start:
664 (*it)->state = hsi_elem;
667 v->array.nelems = (*it)->nelems;
668 res = WHS_BEGIN_ARRAY;
669 v->array.scalar = (*it)->isScalar;
671 case HS_FLAG_ARRAY | hsi_elem:
672 if ((*it)->i >= (*it)->nelems)
677 else if (formAnswer(it, v, &(*it)->array[ (*it)->i++ ], skipNested))
679 res = HStoreIteratorGet(it, v, skipNested);
686 case HS_FLAG_HSTORE | hsi_start:
687 (*it)->state = hsi_key;
690 v->hash.npairs = (*it)->nelems;
691 res = WHS_BEGIN_HASH;
693 case HS_FLAG_HSTORE | hsi_key:
694 if ((*it)->i >= (*it)->nelems)
701 formAnswer(it, v, &(*it)->array[ (*it)->i * 2 ], false);
702 (*it)->state = hsi_value;
706 case HS_FLAG_HSTORE | hsi_value:
707 (*it)->state = hsi_key;
708 if (formAnswer(it, v, &(*it)->array[ ((*it)->i++) * 2 + 1],
710 res = HStoreIteratorGet(it, v, skipNested);
715 elog(PANIC,"unknown state %08x", (*it)->type & (*it)->state);
721 /****************************************************************************
722 * Transformation from tree to binary representation of hstore *
723 ****************************************************************************/
724 typedef struct CompressState
734 } *levelstate, *lptr, *pptr;
740 #define curLevelState state->lptr
741 #define prevLevelState state->pptr
744 putHEntryString(CompressState *state, HStoreValue* value,
745 uint32 level, uint32 i)
747 curLevelState = state->levelstate + level;
750 curLevelState->array[0].entry = HENTRY_ISFIRST;
752 curLevelState->array[i].entry = 0;
757 curLevelState->array[i].entry |= HENTRY_ISNULL;
760 curLevelState->array[i].entry |=
761 curLevelState->array[i - 1].entry & HENTRY_POSMASK;
764 memcpy(state->ptr, value->string.val, value->string.len);
765 state->ptr += value->string.len;
768 curLevelState->array[i].entry |= value->string.len;
770 curLevelState->array[i].entry |=
771 (curLevelState->array[i - 1].entry & HENTRY_POSMASK) +
775 curLevelState->array[i].entry |=
776 (value->boolean) ? HENTRY_ISTRUE : HENTRY_ISFALSE;
779 curLevelState->array[i].entry |=
780 curLevelState->array[i - 1].entry & HENTRY_POSMASK;
784 int addlen = INTALIGN(state->ptr - state->begin) -
785 (state->ptr - state->begin);
786 int numlen = VARSIZE_ANY(value->numeric);
791 *state->ptr = '\0'; state->ptr++;
793 *state->ptr = '\0'; state->ptr++;
795 *state->ptr = '\0'; state->ptr++;
801 memcpy(state->ptr, value->numeric, numlen);
802 state->ptr += numlen;
804 curLevelState->array[i].entry |= HENTRY_ISNUMERIC;
806 curLevelState->array[i].entry |= addlen + numlen;
808 curLevelState->array[i].entry |=
809 (curLevelState->array[i - 1].entry & HENTRY_POSMASK) +
815 int addlen = INTALIGN(state->ptr - state->begin) -
816 (state->ptr - state->begin);
821 *state->ptr = '\0'; state->ptr++;
823 *state->ptr = '\0'; state->ptr++;
825 *state->ptr = '\0'; state->ptr++;
831 memcpy(state->ptr, value->binary.data, value->binary.len);
832 state->ptr += value->binary.len;
834 curLevelState->array[i].entry |= HENTRY_ISNEST;
837 curLevelState->array[i].entry |= addlen + value->binary.len;
839 curLevelState->array[i].entry |=
840 (curLevelState->array[i - 1].entry & HENTRY_POSMASK) +
841 addlen + value->binary.len;
845 elog(PANIC,"Unsupported HStoreValue type: %d", value->type);
850 compressCallback(void *arg, HStoreValue* value, uint32 flags, uint32 level)
852 CompressState *state = arg;
854 if (level == state->maxlevel) {
855 state->maxlevel *= 2;
856 state->levelstate = repalloc(state->levelstate,
857 sizeof(*state->levelstate) * state->maxlevel);
860 curLevelState = state->levelstate + level;
862 if (flags & (WHS_BEGIN_ARRAY | WHS_BEGIN_HASH))
864 Assert(((flags & WHS_BEGIN_ARRAY) && value->type == hsvArray) ||
865 ((flags & WHS_BEGIN_HASH) && value->type == hsvHash));
867 curLevelState->begin = state->ptr;
869 switch(INTALIGN(state->ptr - state->begin) -
870 (state->ptr - state->begin))
873 *state->ptr = '\0'; state->ptr++;
875 *state->ptr = '\0'; state->ptr++;
877 *state->ptr = '\0'; state->ptr++;
883 curLevelState->header = (uint32*)state->ptr;
884 state->ptr += sizeof(*curLevelState->header);
886 curLevelState->array = (HEntry*)state->ptr;
887 curLevelState->i = 0;
889 if (value->type == hsvArray)
891 *curLevelState->header = value->array.nelems | HS_FLAG_ARRAY ;
892 state->ptr += sizeof(HEntry) * value->array.nelems;
894 if (value->array.scalar)
896 Assert(value->array.nelems == 1);
898 *curLevelState->header |= HS_FLAG_SCALAR;
903 *curLevelState->header = value->hash.npairs | HS_FLAG_HSTORE ;
904 state->ptr += sizeof(HEntry) * value->hash.npairs * 2;
908 *curLevelState->header |= HS_FLAG_NEWVERSION;
910 else if (flags & WHS_ELEM)
912 putHEntryString(state, value, level, curLevelState->i);
915 else if (flags & WHS_KEY)
917 Assert(value->type == hsvString);
919 putHEntryString(state, value, level, curLevelState->i * 2);
921 else if (flags & WHS_VALUE)
923 putHEntryString(state, value, level, curLevelState->i * 2 + 1);
926 else if (flags & (WHS_END_ARRAY | WHS_END_HASH))
930 Assert(((flags & WHS_END_ARRAY) && value->type == hsvArray) ||
931 ((flags & WHS_END_HASH) && value->type == hsvHash));
935 len = state->ptr - (char*)curLevelState->begin;
937 prevLevelState = curLevelState - 1;
939 if (*prevLevelState->header & HS_FLAG_ARRAY) {
940 i = prevLevelState->i;
942 prevLevelState->array[i].entry = HENTRY_ISNEST;
945 prevLevelState->array[0].entry |= HENTRY_ISFIRST | len;
947 prevLevelState->array[i].entry |=
948 (prevLevelState->array[i - 1].entry & HENTRY_POSMASK) + len;
950 else if (*prevLevelState->header & HS_FLAG_HSTORE)
952 i = 2 * prevLevelState->i + 1; /* VALUE, not a KEY */
954 prevLevelState->array[i].entry = HENTRY_ISNEST;
956 prevLevelState->array[i].entry |=
957 (prevLevelState->array[i - 1].entry & HENTRY_POSMASK) + len;
961 elog(PANIC, "Wrong parent");
964 Assert(state->ptr - curLevelState->begin <= value->size);
969 elog(PANIC, "Wrong flags");
974 compressHStore(HStoreValue *v, char *buffer) {
978 state.begin = state.ptr = buffer;
980 state.levelstate = palloc(sizeof(*state.levelstate) * state.maxlevel);
982 walkUncompressedHStore(v, compressCallback, &state);
984 l = state.ptr - buffer;
985 Assert(l <= v->size);
990 /****************************************************************************
991 * Iteration-like forming hstore *
992 * Note: it believ by default in already sorted keys in hash, *
993 * although with r == WHS_END_HASH and v == NULL it will sort itself *
994 ****************************************************************************/
995 static ToHStoreState*
996 pushState(ToHStoreState **state)
998 ToHStoreState *ns = palloc(sizeof(*ns));
1005 appendArray(ToHStoreState *state, HStoreValue *v)
1007 HStoreValue *a = &state->v;
1009 Assert(a->type == hsvArray);
1011 if (a->array.nelems >= state->size)
1014 a->array.elems = repalloc(a->array.elems,
1015 sizeof(*a->array.elems) * state->size);
1018 a->array.elems[a->array.nelems ++] = *v;
1024 appendKey(ToHStoreState *state, HStoreValue *v)
1026 HStoreValue *h = &state->v;
1028 Assert(h->type == hsvHash);
1030 if (h->hash.npairs >= state->size)
1033 h->hash.pairs = repalloc(h->hash.pairs,
1034 sizeof(*h->hash.pairs) * state->size);
1037 h->hash.pairs[h->hash.npairs].key = *v;
1038 h->hash.pairs[h->hash.npairs].order = h->hash.npairs;
1044 appendValue(ToHStoreState *state, HStoreValue *v)
1047 HStoreValue *h = &state->v;
1049 Assert(h->type == hsvHash);
1051 h->hash.pairs[h->hash.npairs++].value = *v;
1058 pushHStoreValue(ToHStoreState **state, int r /* WHS_* */, HStoreValue *v) {
1059 HStoreValue *h = NULL;
1063 case WHS_BEGIN_ARRAY:
1064 *state = pushState(state);
1066 (*state)->v.type = hsvArray;
1067 (*state)->v.size = 3*sizeof(HEntry);
1068 (*state)->v.array.nelems = 0;
1069 (*state)->v.array.scalar = (v && v->array.scalar) ? true : false;
1070 (*state)->size = (v && v->type == hsvArray && v->array.nelems > 0)
1071 ? v->array.nelems : 4;
1072 (*state)->v.array.elems = palloc(sizeof(*(*state)->v.array.elems) *
1075 case WHS_BEGIN_HASH:
1076 *state = pushState(state);
1078 (*state)->v.type = hsvHash;
1079 (*state)->v.size = 3*sizeof(HEntry);
1080 (*state)->v.hash.npairs = 0;
1081 (*state)->size = (v && v->type == hsvHash && v->hash.npairs > 0)
1082 ? v->hash.npairs : 4;
1083 (*state)->v.hash.pairs = palloc(sizeof(*(*state)->v.hash.pairs) *
1087 Assert(v->type == hsvNull || v->type == hsvString ||
1088 v->type == hsvBool || v->type == hsvNumeric ||
1089 v->type == hsvBinary);
1090 appendArray(*state, v);
1093 Assert(v->type == hsvString);
1094 appendKey(*state, v);
1097 Assert(v->type == hsvNull || v->type == hsvString ||
1098 v->type == hsvBool || v->type == hsvNumeric ||
1099 v->type == hsvBinary);
1100 appendValue(*state, v);
1105 uniqueHStoreValue(h);
1108 *state = (*state)->next;
1111 switch((*state)->v.type)
1114 appendArray(*state, h);
1117 appendValue(*state, h);
1120 elog(PANIC, "wrong parent type: %d", (*state)->v.type);
1125 elog(PANIC, "wrong type: %08x", r);