PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
hstore_io.c
Go to the documentation of this file.
1 /*
2  * contrib/hstore/hstore_io.c
3  */
4 #include "postgres.h"
5 
6 #include <ctype.h>
7 
8 #include "access/htup_details.h"
9 #include "catalog/pg_type.h"
10 #include "funcapi.h"
11 #include "lib/stringinfo.h"
12 #include "libpq/pqformat.h"
13 #include "utils/builtins.h"
14 #include "utils/json.h"
15 #include "utils/jsonapi.h"
16 #include "utils/jsonb.h"
17 #include "utils/lsyscache.h"
18 #include "utils/memutils.h"
19 #include "utils/typcache.h"
20 
21 #include "hstore.h"
22 
24 
25 /* old names for C functions */
27 
28 
29 typedef struct
30 {
31  char *begin;
32  char *ptr;
33  char *cur;
34  char *word;
35  int wordlen;
36 
38  int pcur;
39  int plen;
40 } HSParser;
41 
42 #define RESIZEPRSBUF \
43 do { \
44  if ( state->cur - state->word + 1 >= state->wordlen ) \
45  { \
46  int32 clen = state->cur - state->word; \
47  state->wordlen *= 2; \
48  state->word = (char*)repalloc( (void*)state->word, state->wordlen ); \
49  state->cur = state->word + clen; \
50  } \
51 } while (0)
52 
53 
54 #define GV_WAITVAL 0
55 #define GV_INVAL 1
56 #define GV_INESCVAL 2
57 #define GV_WAITESCIN 3
58 #define GV_WAITESCESCIN 4
59 
60 static bool
61 get_val(HSParser *state, bool ignoreeq, bool *escaped)
62 {
63  int st = GV_WAITVAL;
64 
65  state->wordlen = 32;
66  state->cur = state->word = palloc(state->wordlen);
67  *escaped = false;
68 
69  while (1)
70  {
71  if (st == GV_WAITVAL)
72  {
73  if (*(state->ptr) == '"')
74  {
75  *escaped = true;
76  st = GV_INESCVAL;
77  }
78  else if (*(state->ptr) == '\0')
79  {
80  return false;
81  }
82  else if (*(state->ptr) == '=' && !ignoreeq)
83  {
84  elog(ERROR, "Syntax error near '%c' at position %d", *(state->ptr), (int32) (state->ptr - state->begin));
85  }
86  else if (*(state->ptr) == '\\')
87  {
88  st = GV_WAITESCIN;
89  }
90  else if (!isspace((unsigned char) *(state->ptr)))
91  {
92  *(state->cur) = *(state->ptr);
93  state->cur++;
94  st = GV_INVAL;
95  }
96  }
97  else if (st == GV_INVAL)
98  {
99  if (*(state->ptr) == '\\')
100  {
101  st = GV_WAITESCIN;
102  }
103  else if (*(state->ptr) == '=' && !ignoreeq)
104  {
105  state->ptr--;
106  return true;
107  }
108  else if (*(state->ptr) == ',' && ignoreeq)
109  {
110  state->ptr--;
111  return true;
112  }
113  else if (isspace((unsigned char) *(state->ptr)))
114  {
115  return true;
116  }
117  else if (*(state->ptr) == '\0')
118  {
119  state->ptr--;
120  return true;
121  }
122  else
123  {
124  RESIZEPRSBUF;
125  *(state->cur) = *(state->ptr);
126  state->cur++;
127  }
128  }
129  else if (st == GV_INESCVAL)
130  {
131  if (*(state->ptr) == '\\')
132  {
133  st = GV_WAITESCESCIN;
134  }
135  else if (*(state->ptr) == '"')
136  {
137  return true;
138  }
139  else if (*(state->ptr) == '\0')
140  {
141  elog(ERROR, "Unexpected end of string");
142  }
143  else
144  {
145  RESIZEPRSBUF;
146  *(state->cur) = *(state->ptr);
147  state->cur++;
148  }
149  }
150  else if (st == GV_WAITESCIN)
151  {
152  if (*(state->ptr) == '\0')
153  elog(ERROR, "Unexpected end of string");
154  RESIZEPRSBUF;
155  *(state->cur) = *(state->ptr);
156  state->cur++;
157  st = GV_INVAL;
158  }
159  else if (st == GV_WAITESCESCIN)
160  {
161  if (*(state->ptr) == '\0')
162  elog(ERROR, "Unexpected end of string");
163  RESIZEPRSBUF;
164  *(state->cur) = *(state->ptr);
165  state->cur++;
166  st = GV_INESCVAL;
167  }
168  else
169  elog(ERROR, "Unknown state %d at position line %d in file '%s'", st, __LINE__, __FILE__);
170 
171  state->ptr++;
172  }
173 }
174 
175 #define WKEY 0
176 #define WVAL 1
177 #define WEQ 2
178 #define WGT 3
179 #define WDEL 4
180 
181 
182 static void
184 {
185  int st = WKEY;
186  bool escaped = false;
187 
188  state->plen = 16;
189  state->pairs = (Pairs *) palloc(sizeof(Pairs) * state->plen);
190  state->pcur = 0;
191  state->ptr = state->begin;
192  state->word = NULL;
193 
194  while (1)
195  {
196  if (st == WKEY)
197  {
198  if (!get_val(state, false, &escaped))
199  return;
200  if (state->pcur >= state->plen)
201  {
202  state->plen *= 2;
203  state->pairs = (Pairs *) repalloc(state->pairs, sizeof(Pairs) * state->plen);
204  }
205  state->pairs[state->pcur].key = state->word;
206  state->pairs[state->pcur].keylen = hstoreCheckKeyLen(state->cur - state->word);
207  state->pairs[state->pcur].val = NULL;
208  state->word = NULL;
209  st = WEQ;
210  }
211  else if (st == WEQ)
212  {
213  if (*(state->ptr) == '=')
214  {
215  st = WGT;
216  }
217  else if (*(state->ptr) == '\0')
218  {
219  elog(ERROR, "Unexpected end of string");
220  }
221  else if (!isspace((unsigned char) *(state->ptr)))
222  {
223  elog(ERROR, "Syntax error near '%c' at position %d", *(state->ptr), (int32) (state->ptr - state->begin));
224  }
225  }
226  else if (st == WGT)
227  {
228  if (*(state->ptr) == '>')
229  {
230  st = WVAL;
231  }
232  else if (*(state->ptr) == '\0')
233  {
234  elog(ERROR, "Unexpected end of string");
235  }
236  else
237  {
238  elog(ERROR, "Syntax error near '%c' at position %d", *(state->ptr), (int32) (state->ptr - state->begin));
239  }
240  }
241  else if (st == WVAL)
242  {
243  if (!get_val(state, true, &escaped))
244  elog(ERROR, "Unexpected end of string");
245  state->pairs[state->pcur].val = state->word;
246  state->pairs[state->pcur].vallen = hstoreCheckValLen(state->cur - state->word);
247  state->pairs[state->pcur].isnull = false;
248  state->pairs[state->pcur].needfree = true;
249  if (state->cur - state->word == 4 && !escaped)
250  {
251  state->word[4] = '\0';
252  if (0 == pg_strcasecmp(state->word, "null"))
253  state->pairs[state->pcur].isnull = true;
254  }
255  state->word = NULL;
256  state->pcur++;
257  st = WDEL;
258  }
259  else if (st == WDEL)
260  {
261  if (*(state->ptr) == ',')
262  {
263  st = WKEY;
264  }
265  else if (*(state->ptr) == '\0')
266  {
267  return;
268  }
269  else if (!isspace((unsigned char) *(state->ptr)))
270  {
271  elog(ERROR, "Syntax error near '%c' at position %d", *(state->ptr), (int32) (state->ptr - state->begin));
272  }
273  }
274  else
275  elog(ERROR, "Unknown state %d at line %d in file '%s'", st, __LINE__, __FILE__);
276 
277  state->ptr++;
278  }
279 }
280 
281 static int
282 comparePairs(const void *a, const void *b)
283 {
284  const Pairs *pa = a;
285  const Pairs *pb = b;
286 
287  if (pa->keylen == pb->keylen)
288  {
289  int res = memcmp(pa->key, pb->key, pa->keylen);
290 
291  if (res)
292  return res;
293 
294  /* guarantee that needfree will be later */
295  if (pb->needfree == pa->needfree)
296  return 0;
297  else if (pa->needfree)
298  return 1;
299  else
300  return -1;
301  }
302  return (pa->keylen > pb->keylen) ? 1 : -1;
303 }
304 
305 /*
306  * this code still respects pairs.needfree, even though in general
307  * it should never be called in a context where anything needs freeing.
308  * we keep it because (a) those calls are in a rare code path anyway,
309  * and (b) who knows whether they might be needed by some caller.
310  */
311 int
313 {
314  Pairs *ptr,
315  *res;
316 
317  *buflen = 0;
318  if (l < 2)
319  {
320  if (l == 1)
321  *buflen = a->keylen + ((a->isnull) ? 0 : a->vallen);
322  return l;
323  }
324 
325  qsort((void *) a, l, sizeof(Pairs), comparePairs);
326  ptr = a + 1;
327  res = a;
328  while (ptr - a < l)
329  {
330  if (ptr->keylen == res->keylen &&
331  memcmp(ptr->key, res->key, res->keylen) == 0)
332  {
333  if (ptr->needfree)
334  {
335  pfree(ptr->key);
336  pfree(ptr->val);
337  }
338  }
339  else
340  {
341  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
342  res++;
343  memcpy(res, ptr, sizeof(Pairs));
344  }
345 
346  ptr++;
347  }
348 
349  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
350  return res + 1 - a;
351 }
352 
353 size_t
354 hstoreCheckKeyLen(size_t len)
355 {
356  if (len > HSTORE_MAX_KEY_LEN)
357  ereport(ERROR,
358  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
359  errmsg("string too long for hstore key")));
360  return len;
361 }
362 
363 size_t
364 hstoreCheckValLen(size_t len)
365 {
366  if (len > HSTORE_MAX_VALUE_LEN)
367  ereport(ERROR,
368  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
369  errmsg("string too long for hstore value")));
370  return len;
371 }
372 
373 
374 HStore *
375 hstorePairs(Pairs *pairs, int32 pcount, int32 buflen)
376 {
377  HStore *out;
378  HEntry *entry;
379  char *ptr;
380  char *buf;
381  int32 len;
382  int32 i;
383 
384  len = CALCDATASIZE(pcount, buflen);
385  out = palloc(len);
386  SET_VARSIZE(out, len);
387  HS_SETCOUNT(out, pcount);
388 
389  if (pcount == 0)
390  return out;
391 
392  entry = ARRPTR(out);
393  buf = ptr = STRPTR(out);
394 
395  for (i = 0; i < pcount; i++)
396  HS_ADDITEM(entry, buf, ptr, pairs[i]);
397 
398  HS_FINALIZE(out, pcount, buf, ptr);
399 
400  return out;
401 }
402 
403 
405 Datum
407 {
408  HSParser state;
409  int32 buflen;
410  HStore *out;
411 
412  state.begin = PG_GETARG_CSTRING(0);
413 
414  parse_hstore(&state);
415 
416  state.pcur = hstoreUniquePairs(state.pairs, state.pcur, &buflen);
417 
418  out = hstorePairs(state.pairs, state.pcur, buflen);
419 
420  PG_RETURN_POINTER(out);
421 }
422 
423 
425 Datum
427 {
428  int32 buflen;
429  HStore *out;
430  Pairs *pairs;
431  int32 i;
432  int32 pcount;
434 
435  pcount = pq_getmsgint(buf, 4);
436 
437  if (pcount == 0)
438  {
439  out = hstorePairs(NULL, 0, 0);
440  PG_RETURN_POINTER(out);
441  }
442 
443  if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs))
444  ereport(ERROR,
445  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
446  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
447  pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
448  pairs = palloc(pcount * sizeof(Pairs));
449 
450  for (i = 0; i < pcount; ++i)
451  {
452  int rawlen = pq_getmsgint(buf, 4);
453  int len;
454 
455  if (rawlen < 0)
456  ereport(ERROR,
457  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
458  errmsg("null value not allowed for hstore key")));
459 
460  pairs[i].key = pq_getmsgtext(buf, rawlen, &len);
461  pairs[i].keylen = hstoreCheckKeyLen(len);
462  pairs[i].needfree = true;
463 
464  rawlen = pq_getmsgint(buf, 4);
465  if (rawlen < 0)
466  {
467  pairs[i].val = NULL;
468  pairs[i].vallen = 0;
469  pairs[i].isnull = true;
470  }
471  else
472  {
473  pairs[i].val = pq_getmsgtext(buf, rawlen, &len);
474  pairs[i].vallen = hstoreCheckValLen(len);
475  pairs[i].isnull = false;
476  }
477  }
478 
479  pcount = hstoreUniquePairs(pairs, pcount, &buflen);
480 
481  out = hstorePairs(pairs, pcount, buflen);
482 
483  PG_RETURN_POINTER(out);
484 }
485 
486 
488 Datum
490 {
491  text *key;
492  text *val = NULL;
493  Pairs p;
494  HStore *out;
495 
496  if (PG_ARGISNULL(0))
497  PG_RETURN_NULL();
498 
499  p.needfree = false;
500  key = PG_GETARG_TEXT_PP(0);
501  p.key = VARDATA_ANY(key);
503 
504  if (PG_ARGISNULL(1))
505  {
506  p.vallen = 0;
507  p.isnull = true;
508  }
509  else
510  {
511  val = PG_GETARG_TEXT_PP(1);
512  p.val = VARDATA_ANY(val);
514  p.isnull = false;
515  }
516 
517  out = hstorePairs(&p, 1, p.keylen + p.vallen);
518 
519  PG_RETURN_POINTER(out);
520 }
521 
522 
524 Datum
526 {
527  int32 buflen;
528  HStore *out;
529  Pairs *pairs;
530  Datum *key_datums;
531  bool *key_nulls;
532  int key_count;
533  Datum *value_datums;
534  bool *value_nulls;
535  int value_count;
536  ArrayType *key_array;
537  ArrayType *value_array;
538  int i;
539 
540  if (PG_ARGISNULL(0))
541  PG_RETURN_NULL();
542 
543  key_array = PG_GETARG_ARRAYTYPE_P(0);
544 
545  Assert(ARR_ELEMTYPE(key_array) == TEXTOID);
546 
547  /*
548  * must check >1 rather than != 1 because empty arrays have 0 dimensions,
549  * not 1
550  */
551 
552  if (ARR_NDIM(key_array) > 1)
553  ereport(ERROR,
554  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
555  errmsg("wrong number of array subscripts")));
556 
557  deconstruct_array(key_array,
558  TEXTOID, -1, false, 'i',
559  &key_datums, &key_nulls, &key_count);
560 
561  /* see discussion in hstoreArrayToPairs() */
562  if (key_count > MaxAllocSize / sizeof(Pairs))
563  ereport(ERROR,
564  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
565  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
566  key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
567 
568  /* value_array might be NULL */
569 
570  if (PG_ARGISNULL(1))
571  {
572  value_array = NULL;
573  value_count = key_count;
574  value_datums = NULL;
575  value_nulls = NULL;
576  }
577  else
578  {
579  value_array = PG_GETARG_ARRAYTYPE_P(1);
580 
581  Assert(ARR_ELEMTYPE(value_array) == TEXTOID);
582 
583  if (ARR_NDIM(value_array) > 1)
584  ereport(ERROR,
585  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
586  errmsg("wrong number of array subscripts")));
587 
588  if ((ARR_NDIM(key_array) > 0 || ARR_NDIM(value_array) > 0) &&
589  (ARR_NDIM(key_array) != ARR_NDIM(value_array) ||
590  ARR_DIMS(key_array)[0] != ARR_DIMS(value_array)[0] ||
591  ARR_LBOUND(key_array)[0] != ARR_LBOUND(value_array)[0]))
592  ereport(ERROR,
593  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
594  errmsg("arrays must have same bounds")));
595 
596  deconstruct_array(value_array,
597  TEXTOID, -1, false, 'i',
598  &value_datums, &value_nulls, &value_count);
599 
600  Assert(key_count == value_count);
601  }
602 
603  pairs = palloc(key_count * sizeof(Pairs));
604 
605  for (i = 0; i < key_count; ++i)
606  {
607  if (key_nulls[i])
608  ereport(ERROR,
609  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
610  errmsg("null value not allowed for hstore key")));
611 
612  if (!value_nulls || value_nulls[i])
613  {
614  pairs[i].key = VARDATA(key_datums[i]);
615  pairs[i].val = NULL;
616  pairs[i].keylen =
617  hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
618  pairs[i].vallen = 4;
619  pairs[i].isnull = true;
620  pairs[i].needfree = false;
621  }
622  else
623  {
624  pairs[i].key = VARDATA(key_datums[i]);
625  pairs[i].val = VARDATA(value_datums[i]);
626  pairs[i].keylen =
627  hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
628  pairs[i].vallen =
629  hstoreCheckValLen(VARSIZE(value_datums[i]) - VARHDRSZ);
630  pairs[i].isnull = false;
631  pairs[i].needfree = false;
632  }
633  }
634 
635  key_count = hstoreUniquePairs(pairs, key_count, &buflen);
636 
637  out = hstorePairs(pairs, key_count, buflen);
638 
639  PG_RETURN_POINTER(out);
640 }
641 
642 
644 Datum
646 {
647  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
648  int ndims = ARR_NDIM(in_array);
649  int count;
650  int32 buflen;
651  HStore *out;
652  Pairs *pairs;
653  Datum *in_datums;
654  bool *in_nulls;
655  int in_count;
656  int i;
657 
658  Assert(ARR_ELEMTYPE(in_array) == TEXTOID);
659 
660  switch (ndims)
661  {
662  case 0:
663  out = hstorePairs(NULL, 0, 0);
664  PG_RETURN_POINTER(out);
665 
666  case 1:
667  if ((ARR_DIMS(in_array)[0]) % 2)
668  ereport(ERROR,
669  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
670  errmsg("array must have even number of elements")));
671  break;
672 
673  case 2:
674  if ((ARR_DIMS(in_array)[1]) != 2)
675  ereport(ERROR,
676  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
677  errmsg("array must have two columns")));
678  break;
679 
680  default:
681  ereport(ERROR,
682  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
683  errmsg("wrong number of array subscripts")));
684  }
685 
686  deconstruct_array(in_array,
687  TEXTOID, -1, false, 'i',
688  &in_datums, &in_nulls, &in_count);
689 
690  count = in_count / 2;
691 
692  /* see discussion in hstoreArrayToPairs() */
693  if (count > MaxAllocSize / sizeof(Pairs))
694  ereport(ERROR,
695  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
696  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
697  count, (int) (MaxAllocSize / sizeof(Pairs)))));
698 
699  pairs = palloc(count * sizeof(Pairs));
700 
701  for (i = 0; i < count; ++i)
702  {
703  if (in_nulls[i * 2])
704  ereport(ERROR,
705  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
706  errmsg("null value not allowed for hstore key")));
707 
708  if (in_nulls[i * 2 + 1])
709  {
710  pairs[i].key = VARDATA(in_datums[i * 2]);
711  pairs[i].val = NULL;
712  pairs[i].keylen =
713  hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
714  pairs[i].vallen = 4;
715  pairs[i].isnull = true;
716  pairs[i].needfree = false;
717  }
718  else
719  {
720  pairs[i].key = VARDATA(in_datums[i * 2]);
721  pairs[i].val = VARDATA(in_datums[i * 2 + 1]);
722  pairs[i].keylen =
723  hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
724  pairs[i].vallen =
725  hstoreCheckValLen(VARSIZE(in_datums[i * 2 + 1]) - VARHDRSZ);
726  pairs[i].isnull = false;
727  pairs[i].needfree = false;
728  }
729  }
730 
731  count = hstoreUniquePairs(pairs, count, &buflen);
732 
733  out = hstorePairs(pairs, count, buflen);
734 
735  PG_RETURN_POINTER(out);
736 }
737 
738 /* most of hstore_from_record is shamelessly swiped from record_out */
739 
740 /*
741  * structure to cache metadata needed for record I/O
742  */
743 typedef struct ColumnIOData
744 {
749 } ColumnIOData;
750 
751 typedef struct RecordIOData
752 {
755  int ncolumns;
756  ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
757 } RecordIOData;
758 
760 Datum
762 {
763  HeapTupleHeader rec;
764  int32 buflen;
765  HStore *out;
766  Pairs *pairs;
767  Oid tupType;
768  int32 tupTypmod;
769  TupleDesc tupdesc;
770  HeapTupleData tuple;
771  RecordIOData *my_extra;
772  int ncolumns;
773  int i,
774  j;
775  Datum *values;
776  bool *nulls;
777 
778  if (PG_ARGISNULL(0))
779  {
780  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
781 
782  /*
783  * have no tuple to look at, so the only source of type info is the
784  * argtype. The lookup_rowtype_tupdesc call below will error out if we
785  * don't have a known composite type oid here.
786  */
787  tupType = argtype;
788  tupTypmod = -1;
789 
790  rec = NULL;
791  }
792  else
793  {
794  rec = PG_GETARG_HEAPTUPLEHEADER(0);
795 
796  /* Extract type info from the tuple itself */
797  tupType = HeapTupleHeaderGetTypeId(rec);
798  tupTypmod = HeapTupleHeaderGetTypMod(rec);
799  }
800 
801  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
802  ncolumns = tupdesc->natts;
803 
804  /*
805  * We arrange to look up the needed I/O info just once per series of
806  * calls, assuming the record type doesn't change underneath us.
807  */
808  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
809  if (my_extra == NULL ||
810  my_extra->ncolumns != ncolumns)
811  {
812  fcinfo->flinfo->fn_extra =
813  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
814  offsetof(RecordIOData, columns) +
815  ncolumns * sizeof(ColumnIOData));
816  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
817  my_extra->record_type = InvalidOid;
818  my_extra->record_typmod = 0;
819  }
820 
821  if (my_extra->record_type != tupType ||
822  my_extra->record_typmod != tupTypmod)
823  {
824  MemSet(my_extra, 0,
825  offsetof(RecordIOData, columns) +
826  ncolumns * sizeof(ColumnIOData));
827  my_extra->record_type = tupType;
828  my_extra->record_typmod = tupTypmod;
829  my_extra->ncolumns = ncolumns;
830  }
831 
832  Assert(ncolumns <= MaxTupleAttributeNumber); /* thus, no overflow */
833  pairs = palloc(ncolumns * sizeof(Pairs));
834 
835  if (rec)
836  {
837  /* Build a temporary HeapTuple control structure */
839  ItemPointerSetInvalid(&(tuple.t_self));
840  tuple.t_tableOid = InvalidOid;
841  tuple.t_data = rec;
842 
843  values = (Datum *) palloc(ncolumns * sizeof(Datum));
844  nulls = (bool *) palloc(ncolumns * sizeof(bool));
845 
846  /* Break down the tuple into fields */
847  heap_deform_tuple(&tuple, tupdesc, values, nulls);
848  }
849  else
850  {
851  values = NULL;
852  nulls = NULL;
853  }
854 
855  for (i = 0, j = 0; i < ncolumns; ++i)
856  {
857  ColumnIOData *column_info = &my_extra->columns[i];
858  Oid column_type = tupdesc->attrs[i]->atttypid;
859  char *value;
860 
861  /* Ignore dropped columns in datatype */
862  if (tupdesc->attrs[i]->attisdropped)
863  continue;
864 
865  pairs[j].key = NameStr(tupdesc->attrs[i]->attname);
866  pairs[j].keylen = hstoreCheckKeyLen(strlen(NameStr(tupdesc->attrs[i]->attname)));
867 
868  if (!nulls || nulls[i])
869  {
870  pairs[j].val = NULL;
871  pairs[j].vallen = 4;
872  pairs[j].isnull = true;
873  pairs[j].needfree = false;
874  ++j;
875  continue;
876  }
877 
878  /*
879  * Convert the column value to text
880  */
881  if (column_info->column_type != column_type)
882  {
883  bool typIsVarlena;
884 
885  getTypeOutputInfo(column_type,
886  &column_info->typiofunc,
887  &typIsVarlena);
888  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
889  fcinfo->flinfo->fn_mcxt);
890  column_info->column_type = column_type;
891  }
892 
893  value = OutputFunctionCall(&column_info->proc, values[i]);
894 
895  pairs[j].val = value;
896  pairs[j].vallen = hstoreCheckValLen(strlen(value));
897  pairs[j].isnull = false;
898  pairs[j].needfree = false;
899  ++j;
900  }
901 
902  ncolumns = hstoreUniquePairs(pairs, j, &buflen);
903 
904  out = hstorePairs(pairs, ncolumns, buflen);
905 
906  ReleaseTupleDesc(tupdesc);
907 
908  PG_RETURN_POINTER(out);
909 }
910 
911 
913 Datum
915 {
916  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
917  HStore *hs;
918  HEntry *entries;
919  char *ptr;
920  HeapTupleHeader rec;
921  Oid tupType;
922  int32 tupTypmod;
923  TupleDesc tupdesc;
924  HeapTupleData tuple;
925  HeapTuple rettuple;
926  RecordIOData *my_extra;
927  int ncolumns;
928  int i;
929  Datum *values;
930  bool *nulls;
931 
932  if (!type_is_rowtype(argtype))
933  ereport(ERROR,
934  (errcode(ERRCODE_DATATYPE_MISMATCH),
935  errmsg("first argument must be a rowtype")));
936 
937  if (PG_ARGISNULL(0))
938  {
939  if (PG_ARGISNULL(1))
940  PG_RETURN_NULL();
941 
942  rec = NULL;
943 
944  /*
945  * have no tuple to look at, so the only source of type info is the
946  * argtype. The lookup_rowtype_tupdesc call below will error out if we
947  * don't have a known composite type oid here.
948  */
949  tupType = argtype;
950  tupTypmod = -1;
951  }
952  else
953  {
954  rec = PG_GETARG_HEAPTUPLEHEADER(0);
955 
956  if (PG_ARGISNULL(1))
957  PG_RETURN_POINTER(rec);
958 
959  /* Extract type info from the tuple itself */
960  tupType = HeapTupleHeaderGetTypeId(rec);
961  tupTypmod = HeapTupleHeaderGetTypMod(rec);
962  }
963 
964  hs = PG_GETARG_HS(1);
965  entries = ARRPTR(hs);
966  ptr = STRPTR(hs);
967 
968  /*
969  * if the input hstore is empty, we can only skip the rest if we were
970  * passed in a non-null record, since otherwise there may be issues with
971  * domain nulls.
972  */
973 
974  if (HS_COUNT(hs) == 0 && rec)
975  PG_RETURN_POINTER(rec);
976 
977  tupdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
978  ncolumns = tupdesc->natts;
979 
980  if (rec)
981  {
982  /* Build a temporary HeapTuple control structure */
984  ItemPointerSetInvalid(&(tuple.t_self));
985  tuple.t_tableOid = InvalidOid;
986  tuple.t_data = rec;
987  }
988 
989  /*
990  * We arrange to look up the needed I/O info just once per series of
991  * calls, assuming the record type doesn't change underneath us.
992  */
993  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
994  if (my_extra == NULL ||
995  my_extra->ncolumns != ncolumns)
996  {
997  fcinfo->flinfo->fn_extra =
998  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
999  offsetof(RecordIOData, columns) +
1000  ncolumns * sizeof(ColumnIOData));
1001  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1002  my_extra->record_type = InvalidOid;
1003  my_extra->record_typmod = 0;
1004  }
1005 
1006  if (my_extra->record_type != tupType ||
1007  my_extra->record_typmod != tupTypmod)
1008  {
1009  MemSet(my_extra, 0,
1010  offsetof(RecordIOData, columns) +
1011  ncolumns * sizeof(ColumnIOData));
1012  my_extra->record_type = tupType;
1013  my_extra->record_typmod = tupTypmod;
1014  my_extra->ncolumns = ncolumns;
1015  }
1016 
1017  values = (Datum *) palloc(ncolumns * sizeof(Datum));
1018  nulls = (bool *) palloc(ncolumns * sizeof(bool));
1019 
1020  if (rec)
1021  {
1022  /* Break down the tuple into fields */
1023  heap_deform_tuple(&tuple, tupdesc, values, nulls);
1024  }
1025  else
1026  {
1027  for (i = 0; i < ncolumns; ++i)
1028  {
1029  values[i] = (Datum) 0;
1030  nulls[i] = true;
1031  }
1032  }
1033 
1034  for (i = 0; i < ncolumns; ++i)
1035  {
1036  ColumnIOData *column_info = &my_extra->columns[i];
1037  Oid column_type = tupdesc->attrs[i]->atttypid;
1038  char *value;
1039  int idx;
1040  int vallen;
1041 
1042  /* Ignore dropped columns in datatype */
1043  if (tupdesc->attrs[i]->attisdropped)
1044  {
1045  nulls[i] = true;
1046  continue;
1047  }
1048 
1049  idx = hstoreFindKey(hs, 0,
1050  NameStr(tupdesc->attrs[i]->attname),
1051  strlen(NameStr(tupdesc->attrs[i]->attname)));
1052 
1053  /*
1054  * we can't just skip here if the key wasn't found since we might have
1055  * a domain to deal with. If we were passed in a non-null record
1056  * datum, we assume that the existing values are valid (if they're
1057  * not, then it's not our fault), but if we were passed in a null,
1058  * then every field which we don't populate needs to be run through
1059  * the input function just in case it's a domain type.
1060  */
1061  if (idx < 0 && rec)
1062  continue;
1063 
1064  /*
1065  * Prepare to convert the column value from text
1066  */
1067  if (column_info->column_type != column_type)
1068  {
1069  getTypeInputInfo(column_type,
1070  &column_info->typiofunc,
1071  &column_info->typioparam);
1072  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
1073  fcinfo->flinfo->fn_mcxt);
1074  column_info->column_type = column_type;
1075  }
1076 
1077  if (idx < 0 || HSTORE_VALISNULL(entries, idx))
1078  {
1079  /*
1080  * need InputFunctionCall to happen even for nulls, so that domain
1081  * checks are done
1082  */
1083  values[i] = InputFunctionCall(&column_info->proc, NULL,
1084  column_info->typioparam,
1085  tupdesc->attrs[i]->atttypmod);
1086  nulls[i] = true;
1087  }
1088  else
1089  {
1090  vallen = HSTORE_VALLEN(entries, idx);
1091  value = palloc(1 + vallen);
1092  memcpy(value, HSTORE_VAL(entries, ptr, idx), vallen);
1093  value[vallen] = 0;
1094 
1095  values[i] = InputFunctionCall(&column_info->proc, value,
1096  column_info->typioparam,
1097  tupdesc->attrs[i]->atttypmod);
1098  nulls[i] = false;
1099  }
1100  }
1101 
1102  rettuple = heap_form_tuple(tupdesc, values, nulls);
1103 
1104  ReleaseTupleDesc(tupdesc);
1105 
1107 }
1108 
1109 
1110 static char *
1111 cpw(char *dst, char *src, int len)
1112 {
1113  char *ptr = src;
1114 
1115  while (ptr - src < len)
1116  {
1117  if (*ptr == '"' || *ptr == '\\')
1118  *dst++ = '\\';
1119  *dst++ = *ptr++;
1120  }
1121  return dst;
1122 }
1123 
1125 Datum
1127 {
1128  HStore *in = PG_GETARG_HS(0);
1129  int buflen,
1130  i;
1131  int count = HS_COUNT(in);
1132  char *out,
1133  *ptr;
1134  char *base = STRPTR(in);
1135  HEntry *entries = ARRPTR(in);
1136 
1137  if (count == 0)
1139 
1140  buflen = 0;
1141 
1142  /*
1143  * this loop overestimates due to pessimistic assumptions about escaping,
1144  * so very large hstore values can't be output. this could be fixed, but
1145  * many other data types probably have the same issue. This replaced code
1146  * that used the original varlena size for calculations, which was wrong
1147  * in some subtle ways.
1148  */
1149 
1150  for (i = 0; i < count; i++)
1151  {
1152  /* include "" and => and comma-space */
1153  buflen += 6 + 2 * HSTORE_KEYLEN(entries, i);
1154  /* include "" only if nonnull */
1155  buflen += 2 + (HSTORE_VALISNULL(entries, i)
1156  ? 2
1157  : 2 * HSTORE_VALLEN(entries, i));
1158  }
1159 
1160  out = ptr = palloc(buflen);
1161 
1162  for (i = 0; i < count; i++)
1163  {
1164  *ptr++ = '"';
1165  ptr = cpw(ptr, HSTORE_KEY(entries, base, i), HSTORE_KEYLEN(entries, i));
1166  *ptr++ = '"';
1167  *ptr++ = '=';
1168  *ptr++ = '>';
1169  if (HSTORE_VALISNULL(entries, i))
1170  {
1171  *ptr++ = 'N';
1172  *ptr++ = 'U';
1173  *ptr++ = 'L';
1174  *ptr++ = 'L';
1175  }
1176  else
1177  {
1178  *ptr++ = '"';
1179  ptr = cpw(ptr, HSTORE_VAL(entries, base, i), HSTORE_VALLEN(entries, i));
1180  *ptr++ = '"';
1181  }
1182 
1183  if (i + 1 != count)
1184  {
1185  *ptr++ = ',';
1186  *ptr++ = ' ';
1187  }
1188  }
1189  *ptr = '\0';
1190 
1191  PG_RETURN_CSTRING(out);
1192 }
1193 
1194 
1196 Datum
1198 {
1199  HStore *in = PG_GETARG_HS(0);
1200  int i;
1201  int count = HS_COUNT(in);
1202  char *base = STRPTR(in);
1203  HEntry *entries = ARRPTR(in);
1205 
1206  pq_begintypsend(&buf);
1207 
1208  pq_sendint(&buf, count, 4);
1209 
1210  for (i = 0; i < count; i++)
1211  {
1212  int32 keylen = HSTORE_KEYLEN(entries, i);
1213 
1214  pq_sendint(&buf, keylen, 4);
1215  pq_sendtext(&buf, HSTORE_KEY(entries, base, i), keylen);
1216  if (HSTORE_VALISNULL(entries, i))
1217  {
1218  pq_sendint(&buf, -1, 4);
1219  }
1220  else
1221  {
1222  int32 vallen = HSTORE_VALLEN(entries, i);
1223 
1224  pq_sendint(&buf, vallen, 4);
1225  pq_sendtext(&buf, HSTORE_VAL(entries, base, i), vallen);
1226  }
1227  }
1228 
1230 }
1231 
1232 
1233 /*
1234  * hstore_to_json_loose
1235  *
1236  * This is a heuristic conversion to json which treats
1237  * 't' and 'f' as booleans and strings that look like numbers as numbers,
1238  * as long as they don't start with a leading zero followed by another digit
1239  * (think zip codes or phone numbers starting with 0).
1240  */
1242 Datum
1244 {
1245  HStore *in = PG_GETARG_HS(0);
1246  int i;
1247  int count = HS_COUNT(in);
1248  char *base = STRPTR(in);
1249  HEntry *entries = ARRPTR(in);
1250  StringInfoData tmp,
1251  dst;
1252 
1253  if (count == 0)
1255 
1256  initStringInfo(&tmp);
1257  initStringInfo(&dst);
1258 
1259  appendStringInfoChar(&dst, '{');
1260 
1261  for (i = 0; i < count; i++)
1262  {
1263  resetStringInfo(&tmp);
1264  appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
1265  HSTORE_KEYLEN(entries, i));
1266  escape_json(&dst, tmp.data);
1267  appendStringInfoString(&dst, ": ");
1268  if (HSTORE_VALISNULL(entries, i))
1269  appendStringInfoString(&dst, "null");
1270  /* guess that values of 't' or 'f' are booleans */
1271  else if (HSTORE_VALLEN(entries, i) == 1 &&
1272  *(HSTORE_VAL(entries, base, i)) == 't')
1273  appendStringInfoString(&dst, "true");
1274  else if (HSTORE_VALLEN(entries, i) == 1 &&
1275  *(HSTORE_VAL(entries, base, i)) == 'f')
1276  appendStringInfoString(&dst, "false");
1277  else
1278  {
1279  resetStringInfo(&tmp);
1280  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1281  HSTORE_VALLEN(entries, i));
1282  if (IsValidJsonNumber(tmp.data, tmp.len))
1283  appendBinaryStringInfo(&dst, tmp.data, tmp.len);
1284  else
1285  escape_json(&dst, tmp.data);
1286  }
1287 
1288  if (i + 1 != count)
1289  appendStringInfoString(&dst, ", ");
1290  }
1291  appendStringInfoChar(&dst, '}');
1292 
1294 }
1295 
1297 Datum
1299 {
1300  HStore *in = PG_GETARG_HS(0);
1301  int i;
1302  int count = HS_COUNT(in);
1303  char *base = STRPTR(in);
1304  HEntry *entries = ARRPTR(in);
1305  StringInfoData tmp,
1306  dst;
1307 
1308  if (count == 0)
1310 
1311  initStringInfo(&tmp);
1312  initStringInfo(&dst);
1313 
1314  appendStringInfoChar(&dst, '{');
1315 
1316  for (i = 0; i < count; i++)
1317  {
1318  resetStringInfo(&tmp);
1319  appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
1320  HSTORE_KEYLEN(entries, i));
1321  escape_json(&dst, tmp.data);
1322  appendStringInfoString(&dst, ": ");
1323  if (HSTORE_VALISNULL(entries, i))
1324  appendStringInfoString(&dst, "null");
1325  else
1326  {
1327  resetStringInfo(&tmp);
1328  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1329  HSTORE_VALLEN(entries, i));
1330  escape_json(&dst, tmp.data);
1331  }
1332 
1333  if (i + 1 != count)
1334  appendStringInfoString(&dst, ", ");
1335  }
1336  appendStringInfoChar(&dst, '}');
1337 
1339 }
1340 
1342 Datum
1344 {
1345  HStore *in = PG_GETARG_HS(0);
1346  int i;
1347  int count = HS_COUNT(in);
1348  char *base = STRPTR(in);
1349  HEntry *entries = ARRPTR(in);
1351  JsonbValue *res;
1352 
1353  (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
1354 
1355  for (i = 0; i < count; i++)
1356  {
1357  JsonbValue key,
1358  val;
1359 
1360  key.type = jbvString;
1361  key.val.string.len = HSTORE_KEYLEN(entries, i);
1362  key.val.string.val = HSTORE_KEY(entries, base, i);
1363 
1364  (void) pushJsonbValue(&state, WJB_KEY, &key);
1365 
1366  if (HSTORE_VALISNULL(entries, i))
1367  {
1368  val.type = jbvNull;
1369  }
1370  else
1371  {
1372  val.type = jbvString;
1373  val.val.string.len = HSTORE_VALLEN(entries, i);
1374  val.val.string.val = HSTORE_VAL(entries, base, i);
1375  }
1376  (void) pushJsonbValue(&state, WJB_VALUE, &val);
1377  }
1378 
1379  res = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
1380 
1382 }
1383 
1385 Datum
1387 {
1388  HStore *in = PG_GETARG_HS(0);
1389  int i;
1390  int count = HS_COUNT(in);
1391  char *base = STRPTR(in);
1392  HEntry *entries = ARRPTR(in);
1394  JsonbValue *res;
1395  StringInfoData tmp;
1396 
1397  initStringInfo(&tmp);
1398 
1399  (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
1400 
1401  for (i = 0; i < count; i++)
1402  {
1403  JsonbValue key,
1404  val;
1405 
1406  key.type = jbvString;
1407  key.val.string.len = HSTORE_KEYLEN(entries, i);
1408  key.val.string.val = HSTORE_KEY(entries, base, i);
1409 
1410  (void) pushJsonbValue(&state, WJB_KEY, &key);
1411 
1412  if (HSTORE_VALISNULL(entries, i))
1413  {
1414  val.type = jbvNull;
1415  }
1416  /* guess that values of 't' or 'f' are booleans */
1417  else if (HSTORE_VALLEN(entries, i) == 1 &&
1418  *(HSTORE_VAL(entries, base, i)) == 't')
1419  {
1420  val.type = jbvBool;
1421  val.val.boolean = true;
1422  }
1423  else if (HSTORE_VALLEN(entries, i) == 1 &&
1424  *(HSTORE_VAL(entries, base, i)) == 'f')
1425  {
1426  val.type = jbvBool;
1427  val.val.boolean = false;
1428  }
1429  else
1430  {
1431  resetStringInfo(&tmp);
1432  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1433  HSTORE_VALLEN(entries, i));
1434  if (IsValidJsonNumber(tmp.data, tmp.len))
1435  {
1436  val.type = jbvNumeric;
1437  val.val.numeric = DatumGetNumeric(
1439  CStringGetDatum(tmp.data), 0, -1));
1440  }
1441  else
1442  {
1443  val.type = jbvString;
1444  val.val.string.len = HSTORE_VALLEN(entries, i);
1445  val.val.string.val = HSTORE_VAL(entries, base, i);
1446  }
1447  }
1448  (void) pushJsonbValue(&state, WJB_VALUE, &val);
1449  }
1450 
1451  res = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
1452 
1454 }
Datum hstore_in(PG_FUNCTION_ARGS)
Definition: hstore_io.c:406
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:321
#define GV_WAITVAL
Definition: hstore_io.c:54
Definition: fmgr.h:56
Definition: hstore.h:44
FmgrInfo proc
Definition: hstore_io.c:748
Datum hstore_to_jsonb_loose(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1386
struct ColumnIOData ColumnIOData
Datum hstore_out(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1126
Datum hstore_to_jsonb(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1343
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2632
#define VARDATA_ANY(PTR)
Definition: postgres.h:347
#define VARDATA(PTR)
Definition: postgres.h:303
Jsonb * JsonbValueToJsonb(JsonbValue *val)
Definition: jsonb_util.c:79
Datum hstore_to_json(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1298
MemoryContext fn_mcxt
Definition: fmgr.h:65
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2433
TupleDesc lookup_rowtype_tupdesc(Oid type_id, int32 typmod)
Definition: typcache.c:1257
#define MaxTupleAttributeNumber
Definition: htup_details.h:33
char * word
Definition: hstore_io.c:34
Oid record_type
Definition: hstore_io.c:753
#define TEXTOID
Definition: pg_type.h:324
#define VARSIZE(PTR)
Definition: postgres.h:304
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:359
#define VARHDRSZ
Definition: c.h:445
char * pstrdup(const char *in)
Definition: mcxt.c:1077
char * val
Definition: jsonb.h:259
#define HSTORE_KEYLEN(arr_, i_)
Definition: hstore.h:81
Definition: jsonb.h:234
StringInfoData * StringInfo
Definition: stringinfo.h:43
size_t hstoreCheckValLen(size_t len)
Definition: hstore_io.c:364
Form_pg_attribute * attrs
Definition: tupdesc.h:74
#define WGT
Definition: hstore_io.c:178
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:857
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:163
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
#define HSTORE_VALLEN(arr_, i_)
Definition: hstore.h:82
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:241
Definition: jsonb.h:231
Datum hstore_from_arrays(PG_FUNCTION_ARGS)
Definition: hstore_io.c:525
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:329
size_t vallen
Definition: hstore.h:166
#define PG_GETARG_HEAPTUPLEHEADER(n)
Definition: fmgr.h:276
unsigned int Oid
Definition: postgres_ext.h:31
Datum hstore_from_text(PG_FUNCTION_ARGS)
Definition: hstore_io.c:489
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:379
Datum hstore_to_json_loose(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1243
int natts
Definition: tupdesc.h:73
bool needfree
Definition: hstore.h:168
int32 record_typmod
Definition: hstore_io.c:754
signed int int32
Definition: c.h:256
char * val
Definition: hstore.h:164
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:273
char * OutputFunctionCall(FmgrInfo *flinfo, Datum val)
Definition: fmgr.c:1667
#define ARR_LBOUND(a)
Definition: array.h:277
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:455
char * key
Definition: hstore.h:163
static char * cpw(char *dst, char *src, int len)
Definition: hstore_io.c:1111
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:244
#define HSTORE_VALISNULL(arr_, i_)
Definition: hstore.h:83
void pfree(void *pointer)
Definition: mcxt.c:950
static void parse_hstore(HSParser *state)
Definition: hstore_io.c:183
#define ERROR
Definition: elog.h:43
int hstoreFindKey(HStore *hs, int *lowbound, char *key, int keylen)
Definition: hstore_op.c:37
Oid get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)
Definition: fmgr.c:1909
bool IsValidJsonNumber(const char *str, int len)
Definition: json.c:192
#define ARR_DIMS(a)
Definition: array.h:275
ItemPointerData t_self
Definition: htup.h:65
HStore * hstorePairs(Pairs *pairs, int32 pcount, int32 buflen)
Definition: hstore_io.c:375
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:157
uint32 t_len
Definition: htup.h:64
static char * buf
Definition: pg_test_fsync.c:66
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:161
#define HS_COUNT(hsp_)
Definition: hstore.h:61
static int comparePairs(const void *a, const void *b)
Definition: hstore_io.c:282
#define PG_GETARG_HS(x)
Definition: hstore.h:154
char * cur
Definition: hstore_io.c:33
#define CStringGetDatum(X)
Definition: postgres.h:584
void resetStringInfo(StringInfo str)
Definition: stringinfo.c:62
Oid t_tableOid
Definition: htup.h:66
#define HS_ADDITEM(dent_, dbuf_, dptr_, pair_)
Definition: hstore.h:112
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:559
Definition: jsonb.h:23
#define GV_INVAL
Definition: hstore_io.c:55
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2404
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:137
#define HSTORE_KEY(arr_, str_, i_)
Definition: hstore.h:79
#define WDEL
Definition: hstore_io.c:179
HSTORE_POLLUTE(hstore_from_text, tconvert)
void getTypeInputInfo(Oid type, Oid *typInput, Oid *typIOParam)
Definition: lsyscache.c:2599
#define ereport(elevel, rest)
Definition: elog.h:122
#define HS_FINALIZE(hsp_, count_, buf_, ptr_)
Definition: hstore.h:129
struct RecordIOData RecordIOData
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:588
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:588
#define GV_INESCVAL
Definition: hstore_io.c:56
#define MaxAllocSize
Definition: memutils.h:40
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:169
void initStringInfo(StringInfo str)
Definition: stringinfo.c:46
#define CALCDATASIZE(x, lenstr)
Definition: hstore.h:72
ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER]
Definition: hstore_io.c:756
int pcur
Definition: hstore_io.c:38
uintptr_t Datum
Definition: postgres.h:372
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:313
#define HeapTupleHeaderGetTypeId(tup)
Definition: htup_details.h:445
#define RESIZEPRSBUF
Definition: hstore_io.c:42
int hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen)
Definition: hstore_io.c:312
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1623
Datum hstore_send(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1197
#define WVAL
Definition: hstore_io.c:176
#define InvalidOid
Definition: postgres_ext.h:36
size_t keylen
Definition: hstore.h:165
Datum hstore_populate_record(PG_FUNCTION_ARGS)
Definition: hstore_io.c:914
#define HSTORE_MAX_KEY_LEN
Definition: hstore.h:41
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:330
#define GV_WAITESCESCIN
Definition: hstore_io.c:58
text * cstring_to_text(const char *s)
Definition: varlena.c:149
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
Datum hstore_from_array(PG_FUNCTION_ARGS)
Definition: hstore_io.c:645
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
Definition: regguts.h:298
bool isnull
Definition: hstore.h:167
Datum hstore_from_record(PG_FUNCTION_ARGS)
Definition: hstore_io.c:761
PG_MODULE_MAGIC
Definition: hstore_io.c:23
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:322
PG_FUNCTION_INFO_V1(hstore_in)
Definition: hstore.h:18
#define HeapTupleGetDatum(tuple)
Definition: funcapi.h:222
Oid typioparam
Definition: hstore_io.c:747
#define ARR_NDIM(a)
Definition: array.h:271
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:963
Pairs * pairs
Definition: hstore_io.c:37
enum jbvType type
Definition: jsonb.h:250
char * begin
Definition: hstore_io.c:31
#define HSTORE_VAL(arr_, str_, i_)
Definition: hstore.h:80
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:933
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3475
static Datum values[MAXATTR]
Definition: bootstrap.c:163
size_t hstoreCheckKeyLen(size_t len)
Definition: hstore_io.c:354
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:149
char * ptr
Definition: hstore_io.c:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
void * palloc(Size size)
Definition: mcxt.c:849
int errmsg(const char *fmt,...)
Definition: elog.c:797
void pq_sendint(StringInfo buf, int i, int b)
Definition: pqformat.c:236
int wordlen
Definition: hstore_io.c:35
#define HSTORE_MAX_VALUE_LEN
Definition: hstore.h:42
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:707
#define STRPTR(x)
Definition: hstore.h:76
Datum hstore_recv(PG_FUNCTION_ARGS)
Definition: hstore_io.c:426
#define WEQ
Definition: hstore_io.c:177
int i
#define GV_WAITESCIN
Definition: hstore_io.c:57
#define NameStr(name)
Definition: c.h:499
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
#define WKEY
Definition: hstore_io.c:175
Definition: c.h:439
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:448
int plen
Definition: hstore_io.c:39
#define SET_VARSIZE(PTR, len)
Definition: postgres.h:328
#define ARRPTR(x)
Definition: cube.c:26
#define elog
Definition: elog.h:219
static struct @121 value
#define HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62
#define qsort(a, b, c, d)
Definition: port.h:440
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:107
static bool get_val(HSParser *state, bool ignoreeq, bool *escaped)
Definition: hstore_io.c:61
Definition: hstore.h:161
#define ARR_ELEMTYPE(a)
Definition: array.h:273
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:208
long val
Definition: informix.c:689
#define PG_RETURN_NULL()
Definition: fmgr.h:305
#define offsetof(type, field)
Definition: c.h:555
Oid column_type
Definition: hstore_io.c:745
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:439