PostgreSQL Source Code  git master
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  if (res != ptr)
344  memcpy(res, ptr, sizeof(Pairs));
345  }
346 
347  ptr++;
348  }
349 
350  *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
351  return res + 1 - a;
352 }
353 
354 size_t
355 hstoreCheckKeyLen(size_t len)
356 {
357  if (len > HSTORE_MAX_KEY_LEN)
358  ereport(ERROR,
359  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
360  errmsg("string too long for hstore key")));
361  return len;
362 }
363 
364 size_t
365 hstoreCheckValLen(size_t len)
366 {
367  if (len > HSTORE_MAX_VALUE_LEN)
368  ereport(ERROR,
369  (errcode(ERRCODE_STRING_DATA_RIGHT_TRUNCATION),
370  errmsg("string too long for hstore value")));
371  return len;
372 }
373 
374 
375 HStore *
376 hstorePairs(Pairs *pairs, int32 pcount, int32 buflen)
377 {
378  HStore *out;
379  HEntry *entry;
380  char *ptr;
381  char *buf;
382  int32 len;
383  int32 i;
384 
385  len = CALCDATASIZE(pcount, buflen);
386  out = palloc(len);
387  SET_VARSIZE(out, len);
388  HS_SETCOUNT(out, pcount);
389 
390  if (pcount == 0)
391  return out;
392 
393  entry = ARRPTR(out);
394  buf = ptr = STRPTR(out);
395 
396  for (i = 0; i < pcount; i++)
397  HS_ADDITEM(entry, buf, ptr, pairs[i]);
398 
399  HS_FINALIZE(out, pcount, buf, ptr);
400 
401  return out;
402 }
403 
404 
406 Datum
408 {
409  HSParser state;
410  int32 buflen;
411  HStore *out;
412 
413  state.begin = PG_GETARG_CSTRING(0);
414 
415  parse_hstore(&state);
416 
417  state.pcur = hstoreUniquePairs(state.pairs, state.pcur, &buflen);
418 
419  out = hstorePairs(state.pairs, state.pcur, buflen);
420 
421  PG_RETURN_POINTER(out);
422 }
423 
424 
426 Datum
428 {
429  int32 buflen;
430  HStore *out;
431  Pairs *pairs;
432  int32 i;
433  int32 pcount;
435 
436  pcount = pq_getmsgint(buf, 4);
437 
438  if (pcount == 0)
439  {
440  out = hstorePairs(NULL, 0, 0);
441  PG_RETURN_POINTER(out);
442  }
443 
444  if (pcount < 0 || pcount > MaxAllocSize / sizeof(Pairs))
445  ereport(ERROR,
446  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
447  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
448  pcount, (int) (MaxAllocSize / sizeof(Pairs)))));
449  pairs = palloc(pcount * sizeof(Pairs));
450 
451  for (i = 0; i < pcount; ++i)
452  {
453  int rawlen = pq_getmsgint(buf, 4);
454  int len;
455 
456  if (rawlen < 0)
457  ereport(ERROR,
458  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
459  errmsg("null value not allowed for hstore key")));
460 
461  pairs[i].key = pq_getmsgtext(buf, rawlen, &len);
462  pairs[i].keylen = hstoreCheckKeyLen(len);
463  pairs[i].needfree = true;
464 
465  rawlen = pq_getmsgint(buf, 4);
466  if (rawlen < 0)
467  {
468  pairs[i].val = NULL;
469  pairs[i].vallen = 0;
470  pairs[i].isnull = true;
471  }
472  else
473  {
474  pairs[i].val = pq_getmsgtext(buf, rawlen, &len);
475  pairs[i].vallen = hstoreCheckValLen(len);
476  pairs[i].isnull = false;
477  }
478  }
479 
480  pcount = hstoreUniquePairs(pairs, pcount, &buflen);
481 
482  out = hstorePairs(pairs, pcount, buflen);
483 
484  PG_RETURN_POINTER(out);
485 }
486 
487 
489 Datum
491 {
492  text *key;
493  text *val = NULL;
494  Pairs p;
495  HStore *out;
496 
497  if (PG_ARGISNULL(0))
498  PG_RETURN_NULL();
499 
500  p.needfree = false;
501  key = PG_GETARG_TEXT_PP(0);
502  p.key = VARDATA_ANY(key);
504 
505  if (PG_ARGISNULL(1))
506  {
507  p.vallen = 0;
508  p.isnull = true;
509  }
510  else
511  {
512  val = PG_GETARG_TEXT_PP(1);
513  p.val = VARDATA_ANY(val);
515  p.isnull = false;
516  }
517 
518  out = hstorePairs(&p, 1, p.keylen + p.vallen);
519 
520  PG_RETURN_POINTER(out);
521 }
522 
523 
525 Datum
527 {
528  int32 buflen;
529  HStore *out;
530  Pairs *pairs;
531  Datum *key_datums;
532  bool *key_nulls;
533  int key_count;
534  Datum *value_datums;
535  bool *value_nulls;
536  int value_count;
537  ArrayType *key_array;
538  ArrayType *value_array;
539  int i;
540 
541  if (PG_ARGISNULL(0))
542  PG_RETURN_NULL();
543 
544  key_array = PG_GETARG_ARRAYTYPE_P(0);
545 
546  Assert(ARR_ELEMTYPE(key_array) == TEXTOID);
547 
548  /*
549  * must check >1 rather than != 1 because empty arrays have 0 dimensions,
550  * not 1
551  */
552 
553  if (ARR_NDIM(key_array) > 1)
554  ereport(ERROR,
555  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
556  errmsg("wrong number of array subscripts")));
557 
558  deconstruct_array(key_array,
559  TEXTOID, -1, false, 'i',
560  &key_datums, &key_nulls, &key_count);
561 
562  /* see discussion in hstoreArrayToPairs() */
563  if (key_count > MaxAllocSize / sizeof(Pairs))
564  ereport(ERROR,
565  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
566  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
567  key_count, (int) (MaxAllocSize / sizeof(Pairs)))));
568 
569  /* value_array might be NULL */
570 
571  if (PG_ARGISNULL(1))
572  {
573  value_array = NULL;
574  value_count = key_count;
575  value_datums = NULL;
576  value_nulls = NULL;
577  }
578  else
579  {
580  value_array = PG_GETARG_ARRAYTYPE_P(1);
581 
582  Assert(ARR_ELEMTYPE(value_array) == TEXTOID);
583 
584  if (ARR_NDIM(value_array) > 1)
585  ereport(ERROR,
586  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
587  errmsg("wrong number of array subscripts")));
588 
589  if ((ARR_NDIM(key_array) > 0 || ARR_NDIM(value_array) > 0) &&
590  (ARR_NDIM(key_array) != ARR_NDIM(value_array) ||
591  ARR_DIMS(key_array)[0] != ARR_DIMS(value_array)[0] ||
592  ARR_LBOUND(key_array)[0] != ARR_LBOUND(value_array)[0]))
593  ereport(ERROR,
594  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
595  errmsg("arrays must have same bounds")));
596 
597  deconstruct_array(value_array,
598  TEXTOID, -1, false, 'i',
599  &value_datums, &value_nulls, &value_count);
600 
601  Assert(key_count == value_count);
602  }
603 
604  pairs = palloc(key_count * sizeof(Pairs));
605 
606  for (i = 0; i < key_count; ++i)
607  {
608  if (key_nulls[i])
609  ereport(ERROR,
610  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
611  errmsg("null value not allowed for hstore key")));
612 
613  if (!value_nulls || value_nulls[i])
614  {
615  pairs[i].key = VARDATA(key_datums[i]);
616  pairs[i].val = NULL;
617  pairs[i].keylen =
618  hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
619  pairs[i].vallen = 4;
620  pairs[i].isnull = true;
621  pairs[i].needfree = false;
622  }
623  else
624  {
625  pairs[i].key = VARDATA(key_datums[i]);
626  pairs[i].val = VARDATA(value_datums[i]);
627  pairs[i].keylen =
628  hstoreCheckKeyLen(VARSIZE(key_datums[i]) - VARHDRSZ);
629  pairs[i].vallen =
630  hstoreCheckValLen(VARSIZE(value_datums[i]) - VARHDRSZ);
631  pairs[i].isnull = false;
632  pairs[i].needfree = false;
633  }
634  }
635 
636  key_count = hstoreUniquePairs(pairs, key_count, &buflen);
637 
638  out = hstorePairs(pairs, key_count, buflen);
639 
640  PG_RETURN_POINTER(out);
641 }
642 
643 
645 Datum
647 {
648  ArrayType *in_array = PG_GETARG_ARRAYTYPE_P(0);
649  int ndims = ARR_NDIM(in_array);
650  int count;
651  int32 buflen;
652  HStore *out;
653  Pairs *pairs;
654  Datum *in_datums;
655  bool *in_nulls;
656  int in_count;
657  int i;
658 
659  Assert(ARR_ELEMTYPE(in_array) == TEXTOID);
660 
661  switch (ndims)
662  {
663  case 0:
664  out = hstorePairs(NULL, 0, 0);
665  PG_RETURN_POINTER(out);
666 
667  case 1:
668  if ((ARR_DIMS(in_array)[0]) % 2)
669  ereport(ERROR,
670  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
671  errmsg("array must have even number of elements")));
672  break;
673 
674  case 2:
675  if ((ARR_DIMS(in_array)[1]) != 2)
676  ereport(ERROR,
677  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
678  errmsg("array must have two columns")));
679  break;
680 
681  default:
682  ereport(ERROR,
683  (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
684  errmsg("wrong number of array subscripts")));
685  }
686 
687  deconstruct_array(in_array,
688  TEXTOID, -1, false, 'i',
689  &in_datums, &in_nulls, &in_count);
690 
691  count = in_count / 2;
692 
693  /* see discussion in hstoreArrayToPairs() */
694  if (count > MaxAllocSize / sizeof(Pairs))
695  ereport(ERROR,
696  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
697  errmsg("number of pairs (%d) exceeds the maximum allowed (%d)",
698  count, (int) (MaxAllocSize / sizeof(Pairs)))));
699 
700  pairs = palloc(count * sizeof(Pairs));
701 
702  for (i = 0; i < count; ++i)
703  {
704  if (in_nulls[i * 2])
705  ereport(ERROR,
706  (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
707  errmsg("null value not allowed for hstore key")));
708 
709  if (in_nulls[i * 2 + 1])
710  {
711  pairs[i].key = VARDATA(in_datums[i * 2]);
712  pairs[i].val = NULL;
713  pairs[i].keylen =
714  hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
715  pairs[i].vallen = 4;
716  pairs[i].isnull = true;
717  pairs[i].needfree = false;
718  }
719  else
720  {
721  pairs[i].key = VARDATA(in_datums[i * 2]);
722  pairs[i].val = VARDATA(in_datums[i * 2 + 1]);
723  pairs[i].keylen =
724  hstoreCheckKeyLen(VARSIZE(in_datums[i * 2]) - VARHDRSZ);
725  pairs[i].vallen =
726  hstoreCheckValLen(VARSIZE(in_datums[i * 2 + 1]) - VARHDRSZ);
727  pairs[i].isnull = false;
728  pairs[i].needfree = false;
729  }
730  }
731 
732  count = hstoreUniquePairs(pairs, count, &buflen);
733 
734  out = hstorePairs(pairs, count, buflen);
735 
736  PG_RETURN_POINTER(out);
737 }
738 
739 /* most of hstore_from_record is shamelessly swiped from record_out */
740 
741 /*
742  * structure to cache metadata needed for record I/O
743  */
744 typedef struct ColumnIOData
745 {
750 } ColumnIOData;
751 
752 typedef struct RecordIOData
753 {
756  /* this field is used only if target type is domain over composite: */
757  void *domain_info; /* opaque cache for domain checks */
758  int ncolumns;
759  ColumnIOData columns[FLEXIBLE_ARRAY_MEMBER];
760 } RecordIOData;
761 
763 Datum
765 {
766  HeapTupleHeader rec;
767  int32 buflen;
768  HStore *out;
769  Pairs *pairs;
770  Oid tupType;
771  int32 tupTypmod;
772  TupleDesc tupdesc;
773  HeapTupleData tuple;
774  RecordIOData *my_extra;
775  int ncolumns;
776  int i,
777  j;
778  Datum *values;
779  bool *nulls;
780 
781  if (PG_ARGISNULL(0))
782  {
783  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
784 
785  /*
786  * We have no tuple to look at, so the only source of type info is the
787  * argtype --- which might be domain over composite, but we don't care
788  * here, since we have no need to be concerned about domain
789  * constraints. The lookup_rowtype_tupdesc_domain call below will
790  * error out if we don't have a known composite type oid here.
791  */
792  tupType = argtype;
793  tupTypmod = -1;
794 
795  rec = NULL;
796  }
797  else
798  {
799  rec = PG_GETARG_HEAPTUPLEHEADER(0);
800 
801  /*
802  * Extract type info from the tuple itself -- this will work even for
803  * anonymous record types.
804  */
805  tupType = HeapTupleHeaderGetTypeId(rec);
806  tupTypmod = HeapTupleHeaderGetTypMod(rec);
807  }
808 
809  tupdesc = lookup_rowtype_tupdesc_domain(tupType, tupTypmod, false);
810  ncolumns = tupdesc->natts;
811 
812  /*
813  * We arrange to look up the needed I/O info just once per series of
814  * calls, assuming the record type doesn't change underneath us.
815  */
816  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
817  if (my_extra == NULL ||
818  my_extra->ncolumns != ncolumns)
819  {
820  fcinfo->flinfo->fn_extra =
821  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
822  offsetof(RecordIOData, columns) +
823  ncolumns * sizeof(ColumnIOData));
824  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
825  my_extra->record_type = InvalidOid;
826  my_extra->record_typmod = 0;
827  }
828 
829  if (my_extra->record_type != tupType ||
830  my_extra->record_typmod != tupTypmod)
831  {
832  MemSet(my_extra, 0,
833  offsetof(RecordIOData, columns) +
834  ncolumns * sizeof(ColumnIOData));
835  my_extra->record_type = tupType;
836  my_extra->record_typmod = tupTypmod;
837  my_extra->ncolumns = ncolumns;
838  }
839 
840  Assert(ncolumns <= MaxTupleAttributeNumber); /* thus, no overflow */
841  pairs = palloc(ncolumns * sizeof(Pairs));
842 
843  if (rec)
844  {
845  /* Build a temporary HeapTuple control structure */
847  ItemPointerSetInvalid(&(tuple.t_self));
848  tuple.t_tableOid = InvalidOid;
849  tuple.t_data = rec;
850 
851  values = (Datum *) palloc(ncolumns * sizeof(Datum));
852  nulls = (bool *) palloc(ncolumns * sizeof(bool));
853 
854  /* Break down the tuple into fields */
855  heap_deform_tuple(&tuple, tupdesc, values, nulls);
856  }
857  else
858  {
859  values = NULL;
860  nulls = NULL;
861  }
862 
863  for (i = 0, j = 0; i < ncolumns; ++i)
864  {
865  ColumnIOData *column_info = &my_extra->columns[i];
866  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
867  Oid column_type = att->atttypid;
868  char *value;
869 
870  /* Ignore dropped columns in datatype */
871  if (att->attisdropped)
872  continue;
873 
874  pairs[j].key = NameStr(att->attname);
875  pairs[j].keylen = hstoreCheckKeyLen(strlen(NameStr(att->attname)));
876 
877  if (!nulls || nulls[i])
878  {
879  pairs[j].val = NULL;
880  pairs[j].vallen = 4;
881  pairs[j].isnull = true;
882  pairs[j].needfree = false;
883  ++j;
884  continue;
885  }
886 
887  /*
888  * Convert the column value to text
889  */
890  if (column_info->column_type != column_type)
891  {
892  bool typIsVarlena;
893 
894  getTypeOutputInfo(column_type,
895  &column_info->typiofunc,
896  &typIsVarlena);
897  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
898  fcinfo->flinfo->fn_mcxt);
899  column_info->column_type = column_type;
900  }
901 
902  value = OutputFunctionCall(&column_info->proc, values[i]);
903 
904  pairs[j].val = value;
905  pairs[j].vallen = hstoreCheckValLen(strlen(value));
906  pairs[j].isnull = false;
907  pairs[j].needfree = false;
908  ++j;
909  }
910 
911  ncolumns = hstoreUniquePairs(pairs, j, &buflen);
912 
913  out = hstorePairs(pairs, ncolumns, buflen);
914 
915  ReleaseTupleDesc(tupdesc);
916 
917  PG_RETURN_POINTER(out);
918 }
919 
920 
922 Datum
924 {
925  Oid argtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
926  HStore *hs;
927  HEntry *entries;
928  char *ptr;
929  HeapTupleHeader rec;
930  Oid tupType;
931  int32 tupTypmod;
932  TupleDesc tupdesc;
933  HeapTupleData tuple;
934  HeapTuple rettuple;
935  RecordIOData *my_extra;
936  int ncolumns;
937  int i;
938  Datum *values;
939  bool *nulls;
940 
941  if (!type_is_rowtype(argtype))
942  ereport(ERROR,
943  (errcode(ERRCODE_DATATYPE_MISMATCH),
944  errmsg("first argument must be a rowtype")));
945 
946  if (PG_ARGISNULL(0))
947  {
948  if (PG_ARGISNULL(1))
949  PG_RETURN_NULL();
950 
951  rec = NULL;
952 
953  /*
954  * We have no tuple to look at, so the only source of type info is the
955  * argtype. The lookup_rowtype_tupdesc_domain call below will error
956  * out if we don't have a known composite type oid here.
957  */
958  tupType = argtype;
959  tupTypmod = -1;
960  }
961  else
962  {
963  rec = PG_GETARG_HEAPTUPLEHEADER(0);
964 
965  if (PG_ARGISNULL(1))
966  PG_RETURN_POINTER(rec);
967 
968  /*
969  * Extract type info from the tuple itself -- this will work even for
970  * anonymous record types.
971  */
972  tupType = HeapTupleHeaderGetTypeId(rec);
973  tupTypmod = HeapTupleHeaderGetTypMod(rec);
974  }
975 
976  hs = PG_GETARG_HSTORE_P(1);
977  entries = ARRPTR(hs);
978  ptr = STRPTR(hs);
979 
980  /*
981  * if the input hstore is empty, we can only skip the rest if we were
982  * passed in a non-null record, since otherwise there may be issues with
983  * domain nulls.
984  */
985 
986  if (HS_COUNT(hs) == 0 && rec)
987  PG_RETURN_POINTER(rec);
988 
989  /*
990  * Lookup the input record's tupdesc. For the moment, we don't worry
991  * about whether it is a domain over composite.
992  */
993  tupdesc = lookup_rowtype_tupdesc_domain(tupType, tupTypmod, false);
994  ncolumns = tupdesc->natts;
995 
996  if (rec)
997  {
998  /* Build a temporary HeapTuple control structure */
1000  ItemPointerSetInvalid(&(tuple.t_self));
1001  tuple.t_tableOid = InvalidOid;
1002  tuple.t_data = rec;
1003  }
1004 
1005  /*
1006  * We arrange to look up the needed I/O info just once per series of
1007  * calls, assuming the record type doesn't change underneath us.
1008  */
1009  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1010  if (my_extra == NULL ||
1011  my_extra->ncolumns != ncolumns)
1012  {
1013  fcinfo->flinfo->fn_extra =
1014  MemoryContextAlloc(fcinfo->flinfo->fn_mcxt,
1015  offsetof(RecordIOData, columns) +
1016  ncolumns * sizeof(ColumnIOData));
1017  my_extra = (RecordIOData *) fcinfo->flinfo->fn_extra;
1018  my_extra->record_type = InvalidOid;
1019  my_extra->record_typmod = 0;
1020  my_extra->domain_info = NULL;
1021  }
1022 
1023  if (my_extra->record_type != tupType ||
1024  my_extra->record_typmod != tupTypmod)
1025  {
1026  MemSet(my_extra, 0,
1027  offsetof(RecordIOData, columns) +
1028  ncolumns * sizeof(ColumnIOData));
1029  my_extra->record_type = tupType;
1030  my_extra->record_typmod = tupTypmod;
1031  my_extra->ncolumns = ncolumns;
1032  }
1033 
1034  values = (Datum *) palloc(ncolumns * sizeof(Datum));
1035  nulls = (bool *) palloc(ncolumns * sizeof(bool));
1036 
1037  if (rec)
1038  {
1039  /* Break down the tuple into fields */
1040  heap_deform_tuple(&tuple, tupdesc, values, nulls);
1041  }
1042  else
1043  {
1044  for (i = 0; i < ncolumns; ++i)
1045  {
1046  values[i] = (Datum) 0;
1047  nulls[i] = true;
1048  }
1049  }
1050 
1051  for (i = 0; i < ncolumns; ++i)
1052  {
1053  ColumnIOData *column_info = &my_extra->columns[i];
1054  Form_pg_attribute att = TupleDescAttr(tupdesc, i);
1055  Oid column_type = att->atttypid;
1056  char *value;
1057  int idx;
1058  int vallen;
1059 
1060  /* Ignore dropped columns in datatype */
1061  if (att->attisdropped)
1062  {
1063  nulls[i] = true;
1064  continue;
1065  }
1066 
1067  idx = hstoreFindKey(hs, 0,
1068  NameStr(att->attname),
1069  strlen(NameStr(att->attname)));
1070 
1071  /*
1072  * we can't just skip here if the key wasn't found since we might have
1073  * a domain to deal with. If we were passed in a non-null record
1074  * datum, we assume that the existing values are valid (if they're
1075  * not, then it's not our fault), but if we were passed in a null,
1076  * then every field which we don't populate needs to be run through
1077  * the input function just in case it's a domain type.
1078  */
1079  if (idx < 0 && rec)
1080  continue;
1081 
1082  /*
1083  * Prepare to convert the column value from text
1084  */
1085  if (column_info->column_type != column_type)
1086  {
1087  getTypeInputInfo(column_type,
1088  &column_info->typiofunc,
1089  &column_info->typioparam);
1090  fmgr_info_cxt(column_info->typiofunc, &column_info->proc,
1091  fcinfo->flinfo->fn_mcxt);
1092  column_info->column_type = column_type;
1093  }
1094 
1095  if (idx < 0 || HSTORE_VALISNULL(entries, idx))
1096  {
1097  /*
1098  * need InputFunctionCall to happen even for nulls, so that domain
1099  * checks are done
1100  */
1101  values[i] = InputFunctionCall(&column_info->proc, NULL,
1102  column_info->typioparam,
1103  att->atttypmod);
1104  nulls[i] = true;
1105  }
1106  else
1107  {
1108  vallen = HSTORE_VALLEN(entries, idx);
1109  value = palloc(1 + vallen);
1110  memcpy(value, HSTORE_VAL(entries, ptr, idx), vallen);
1111  value[vallen] = 0;
1112 
1113  values[i] = InputFunctionCall(&column_info->proc, value,
1114  column_info->typioparam,
1115  att->atttypmod);
1116  nulls[i] = false;
1117  }
1118  }
1119 
1120  rettuple = heap_form_tuple(tupdesc, values, nulls);
1121 
1122  /*
1123  * If the target type is domain over composite, all we know at this point
1124  * is that we've made a valid value of the base composite type. Must
1125  * check domain constraints before deciding we're done.
1126  */
1127  if (argtype != tupdesc->tdtypeid)
1128  domain_check(HeapTupleGetDatum(rettuple), false,
1129  argtype,
1130  &my_extra->domain_info,
1131  fcinfo->flinfo->fn_mcxt);
1132 
1133  ReleaseTupleDesc(tupdesc);
1134 
1136 }
1137 
1138 
1139 static char *
1140 cpw(char *dst, char *src, int len)
1141 {
1142  char *ptr = src;
1143 
1144  while (ptr - src < len)
1145  {
1146  if (*ptr == '"' || *ptr == '\\')
1147  *dst++ = '\\';
1148  *dst++ = *ptr++;
1149  }
1150  return dst;
1151 }
1152 
1154 Datum
1156 {
1157  HStore *in = PG_GETARG_HSTORE_P(0);
1158  int buflen,
1159  i;
1160  int count = HS_COUNT(in);
1161  char *out,
1162  *ptr;
1163  char *base = STRPTR(in);
1164  HEntry *entries = ARRPTR(in);
1165 
1166  if (count == 0)
1168 
1169  buflen = 0;
1170 
1171  /*
1172  * this loop overestimates due to pessimistic assumptions about escaping,
1173  * so very large hstore values can't be output. this could be fixed, but
1174  * many other data types probably have the same issue. This replaced code
1175  * that used the original varlena size for calculations, which was wrong
1176  * in some subtle ways.
1177  */
1178 
1179  for (i = 0; i < count; i++)
1180  {
1181  /* include "" and => and comma-space */
1182  buflen += 6 + 2 * HSTORE_KEYLEN(entries, i);
1183  /* include "" only if nonnull */
1184  buflen += 2 + (HSTORE_VALISNULL(entries, i)
1185  ? 2
1186  : 2 * HSTORE_VALLEN(entries, i));
1187  }
1188 
1189  out = ptr = palloc(buflen);
1190 
1191  for (i = 0; i < count; i++)
1192  {
1193  *ptr++ = '"';
1194  ptr = cpw(ptr, HSTORE_KEY(entries, base, i), HSTORE_KEYLEN(entries, i));
1195  *ptr++ = '"';
1196  *ptr++ = '=';
1197  *ptr++ = '>';
1198  if (HSTORE_VALISNULL(entries, i))
1199  {
1200  *ptr++ = 'N';
1201  *ptr++ = 'U';
1202  *ptr++ = 'L';
1203  *ptr++ = 'L';
1204  }
1205  else
1206  {
1207  *ptr++ = '"';
1208  ptr = cpw(ptr, HSTORE_VAL(entries, base, i), HSTORE_VALLEN(entries, i));
1209  *ptr++ = '"';
1210  }
1211 
1212  if (i + 1 != count)
1213  {
1214  *ptr++ = ',';
1215  *ptr++ = ' ';
1216  }
1217  }
1218  *ptr = '\0';
1219 
1220  PG_RETURN_CSTRING(out);
1221 }
1222 
1223 
1225 Datum
1227 {
1228  HStore *in = PG_GETARG_HSTORE_P(0);
1229  int i;
1230  int count = HS_COUNT(in);
1231  char *base = STRPTR(in);
1232  HEntry *entries = ARRPTR(in);
1234 
1235  pq_begintypsend(&buf);
1236 
1237  pq_sendint32(&buf, count);
1238 
1239  for (i = 0; i < count; i++)
1240  {
1241  int32 keylen = HSTORE_KEYLEN(entries, i);
1242 
1243  pq_sendint32(&buf, keylen);
1244  pq_sendtext(&buf, HSTORE_KEY(entries, base, i), keylen);
1245  if (HSTORE_VALISNULL(entries, i))
1246  {
1247  pq_sendint32(&buf, -1);
1248  }
1249  else
1250  {
1251  int32 vallen = HSTORE_VALLEN(entries, i);
1252 
1253  pq_sendint32(&buf, vallen);
1254  pq_sendtext(&buf, HSTORE_VAL(entries, base, i), vallen);
1255  }
1256  }
1257 
1259 }
1260 
1261 
1262 /*
1263  * hstore_to_json_loose
1264  *
1265  * This is a heuristic conversion to json which treats
1266  * 't' and 'f' as booleans and strings that look like numbers as numbers,
1267  * as long as they don't start with a leading zero followed by another digit
1268  * (think zip codes or phone numbers starting with 0).
1269  */
1271 Datum
1273 {
1274  HStore *in = PG_GETARG_HSTORE_P(0);
1275  int i;
1276  int count = HS_COUNT(in);
1277  char *base = STRPTR(in);
1278  HEntry *entries = ARRPTR(in);
1279  StringInfoData tmp,
1280  dst;
1281 
1282  if (count == 0)
1284 
1285  initStringInfo(&tmp);
1286  initStringInfo(&dst);
1287 
1288  appendStringInfoChar(&dst, '{');
1289 
1290  for (i = 0; i < count; i++)
1291  {
1292  resetStringInfo(&tmp);
1293  appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
1294  HSTORE_KEYLEN(entries, i));
1295  escape_json(&dst, tmp.data);
1296  appendStringInfoString(&dst, ": ");
1297  if (HSTORE_VALISNULL(entries, i))
1298  appendStringInfoString(&dst, "null");
1299  /* guess that values of 't' or 'f' are booleans */
1300  else if (HSTORE_VALLEN(entries, i) == 1 &&
1301  *(HSTORE_VAL(entries, base, i)) == 't')
1302  appendStringInfoString(&dst, "true");
1303  else if (HSTORE_VALLEN(entries, i) == 1 &&
1304  *(HSTORE_VAL(entries, base, i)) == 'f')
1305  appendStringInfoString(&dst, "false");
1306  else
1307  {
1308  resetStringInfo(&tmp);
1309  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1310  HSTORE_VALLEN(entries, i));
1311  if (IsValidJsonNumber(tmp.data, tmp.len))
1312  appendBinaryStringInfo(&dst, tmp.data, tmp.len);
1313  else
1314  escape_json(&dst, tmp.data);
1315  }
1316 
1317  if (i + 1 != count)
1318  appendStringInfoString(&dst, ", ");
1319  }
1320  appendStringInfoChar(&dst, '}');
1321 
1323 }
1324 
1326 Datum
1328 {
1329  HStore *in = PG_GETARG_HSTORE_P(0);
1330  int i;
1331  int count = HS_COUNT(in);
1332  char *base = STRPTR(in);
1333  HEntry *entries = ARRPTR(in);
1334  StringInfoData tmp,
1335  dst;
1336 
1337  if (count == 0)
1339 
1340  initStringInfo(&tmp);
1341  initStringInfo(&dst);
1342 
1343  appendStringInfoChar(&dst, '{');
1344 
1345  for (i = 0; i < count; i++)
1346  {
1347  resetStringInfo(&tmp);
1348  appendBinaryStringInfo(&tmp, HSTORE_KEY(entries, base, i),
1349  HSTORE_KEYLEN(entries, i));
1350  escape_json(&dst, tmp.data);
1351  appendStringInfoString(&dst, ": ");
1352  if (HSTORE_VALISNULL(entries, i))
1353  appendStringInfoString(&dst, "null");
1354  else
1355  {
1356  resetStringInfo(&tmp);
1357  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1358  HSTORE_VALLEN(entries, i));
1359  escape_json(&dst, tmp.data);
1360  }
1361 
1362  if (i + 1 != count)
1363  appendStringInfoString(&dst, ", ");
1364  }
1365  appendStringInfoChar(&dst, '}');
1366 
1368 }
1369 
1371 Datum
1373 {
1374  HStore *in = PG_GETARG_HSTORE_P(0);
1375  int i;
1376  int count = HS_COUNT(in);
1377  char *base = STRPTR(in);
1378  HEntry *entries = ARRPTR(in);
1379  JsonbParseState *state = NULL;
1380  JsonbValue *res;
1381 
1382  (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
1383 
1384  for (i = 0; i < count; i++)
1385  {
1386  JsonbValue key,
1387  val;
1388 
1389  key.type = jbvString;
1390  key.val.string.len = HSTORE_KEYLEN(entries, i);
1391  key.val.string.val = HSTORE_KEY(entries, base, i);
1392 
1393  (void) pushJsonbValue(&state, WJB_KEY, &key);
1394 
1395  if (HSTORE_VALISNULL(entries, i))
1396  {
1397  val.type = jbvNull;
1398  }
1399  else
1400  {
1401  val.type = jbvString;
1402  val.val.string.len = HSTORE_VALLEN(entries, i);
1403  val.val.string.val = HSTORE_VAL(entries, base, i);
1404  }
1405  (void) pushJsonbValue(&state, WJB_VALUE, &val);
1406  }
1407 
1408  res = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
1409 
1411 }
1412 
1414 Datum
1416 {
1417  HStore *in = PG_GETARG_HSTORE_P(0);
1418  int i;
1419  int count = HS_COUNT(in);
1420  char *base = STRPTR(in);
1421  HEntry *entries = ARRPTR(in);
1422  JsonbParseState *state = NULL;
1423  JsonbValue *res;
1424  StringInfoData tmp;
1425 
1426  initStringInfo(&tmp);
1427 
1428  (void) pushJsonbValue(&state, WJB_BEGIN_OBJECT, NULL);
1429 
1430  for (i = 0; i < count; i++)
1431  {
1432  JsonbValue key,
1433  val;
1434 
1435  key.type = jbvString;
1436  key.val.string.len = HSTORE_KEYLEN(entries, i);
1437  key.val.string.val = HSTORE_KEY(entries, base, i);
1438 
1439  (void) pushJsonbValue(&state, WJB_KEY, &key);
1440 
1441  if (HSTORE_VALISNULL(entries, i))
1442  {
1443  val.type = jbvNull;
1444  }
1445  /* guess that values of 't' or 'f' are booleans */
1446  else if (HSTORE_VALLEN(entries, i) == 1 &&
1447  *(HSTORE_VAL(entries, base, i)) == 't')
1448  {
1449  val.type = jbvBool;
1450  val.val.boolean = true;
1451  }
1452  else if (HSTORE_VALLEN(entries, i) == 1 &&
1453  *(HSTORE_VAL(entries, base, i)) == 'f')
1454  {
1455  val.type = jbvBool;
1456  val.val.boolean = false;
1457  }
1458  else
1459  {
1460  resetStringInfo(&tmp);
1461  appendBinaryStringInfo(&tmp, HSTORE_VAL(entries, base, i),
1462  HSTORE_VALLEN(entries, i));
1463  if (IsValidJsonNumber(tmp.data, tmp.len))
1464  {
1465  val.type = jbvNumeric;
1466  val.val.numeric = DatumGetNumeric(
1468  CStringGetDatum(tmp.data), 0, -1));
1469  }
1470  else
1471  {
1472  val.type = jbvString;
1473  val.val.string.len = HSTORE_VALLEN(entries, i);
1474  val.val.string.val = HSTORE_VAL(entries, base, i);
1475  }
1476  }
1477  (void) pushJsonbValue(&state, WJB_VALUE, &val);
1478  }
1479 
1480  res = pushJsonbValue(&state, WJB_END_OBJECT, NULL);
1481 
1483 }
Datum hstore_in(PG_FUNCTION_ARGS)
Definition: hstore_io.c:407
#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:749
Datum hstore_to_jsonb_loose(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1415
Oid tdtypeid
Definition: tupdesc.h:80
struct ColumnIOData ColumnIOData
Datum hstore_out(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1155
Datum hstore_to_jsonb(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1372
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2665
#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:1327
MemoryContext fn_mcxt
Definition: fmgr.h:65
void escape_json(StringInfo buf, const char *str)
Definition: json.c:2397
#define PG_GETARG_HSTORE_P(x)
Definition: hstore.h:154
#define MaxTupleAttributeNumber
Definition: htup_details.h:33
char * word
Definition: hstore_io.c:34
Oid record_type
Definition: hstore_io.c:754
#define TEXTOID
Definition: pg_type.h:324
#define VARSIZE(PTR)
Definition: postgres.h:304
static void pq_sendint32(StringInfo buf, int32 i)
Definition: pqformat.h:148
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:90
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
#define VARHDRSZ
Definition: c.h:503
char * pstrdup(const char *in)
Definition: mcxt.c:1063
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:365
#define WGT
Definition: hstore_io.c:178
void * domain_info
Definition: hstore_io.c:757
int errcode(int sqlerrcode)
Definition: elog.c:575
#define MemSet(start, val, len)
Definition: c.h:863
void pq_sendtext(StringInfo buf, const char *str, int slen)
Definition: pqformat.c:174
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:526
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:695
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:330
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:490
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
Datum hstore_to_json_loose(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1272
int natts
Definition: tupdesc.h:79
bool needfree
Definition: hstore.h:168
int32 record_typmod
Definition: hstore_io.c:755
TupleDesc lookup_rowtype_tupdesc_domain(Oid type_id, int32 typmod, bool noError)
Definition: typcache.c:1674
signed int int32
Definition: c.h:294
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:1662
#define ARR_LBOUND(a)
Definition: array.h:281
HeapTupleHeader t_data
Definition: htup.h:67
#define HeapTupleHeaderGetTypMod(tup)
Definition: htup_details.h:460
char * key
Definition: hstore.h:163
static char * cpw(char *dst, char *src, int len)
Definition: hstore_io.c:1140
JsonbValue * pushJsonbValue(JsonbParseState **pstate, JsonbIteratorToken seq, JsonbValue *jbval)
Definition: jsonb_util.c:517
#define PG_GETARG_ARRAYTYPE_P(n)
Definition: array.h:248
#define HSTORE_VALISNULL(arr_, i_)
Definition: hstore.h:83
void pfree(void *pointer)
Definition: mcxt.c:936
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:1904
bool IsValidJsonNumber(const char *str, int len)
Definition: json.c:193
#define ARR_DIMS(a)
Definition: array.h:279
static struct @121 value
ItemPointerData t_self
Definition: htup.h:65
HStore * hstorePairs(Pairs *pairs, int32 pcount, int32 buflen)
Definition: hstore_io.c:376
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:67
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:162
#define HS_COUNT(hsp_)
Definition: hstore.h:61
static int comparePairs(const void *a, const void *b)
Definition: hstore_io.c:282
char * cur
Definition: hstore_io.c:33
#define CStringGetDatum(X)
Definition: postgres.h:584
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:187
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:570
Definition: jsonb.h:23
#define GV_INVAL
Definition: hstore_io.c:55
bool type_is_rowtype(Oid typid)
Definition: lsyscache.c:2424
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
Definition: fmgr.c:132
#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:2632
#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:589
char * pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes)
Definition: pqformat.c:548
#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:759
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:450
#define RESIZEPRSBUF
Definition: hstore_io.c:42
int hstoreUniquePairs(Pairs *a, int32 l, int32 *buflen)
Definition: hstore_io.c:312
void domain_check(Datum value, bool isnull, Oid domainType, void **extra, MemoryContext mcxt)
Definition: domains.c:327
Datum InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
Definition: fmgr.c:1618
Datum hstore_send(PG_FUNCTION_ARGS)
Definition: hstore_io.c:1226
#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:923
#define HSTORE_MAX_KEY_LEN
Definition: hstore.h:41
#define PG_RETURN_TEXT_P(x)
Definition: fmgr.h:331
#define GV_WAITESCESCIN
Definition: hstore_io.c:58
text * cstring_to_text(const char *s)
Definition: varlena.c:150
#define PG_ARGISNULL(n)
Definition: fmgr.h:174
Datum hstore_from_array(PG_FUNCTION_ARGS)
Definition: hstore_io.c:646
#define DatumGetNumeric(X)
Definition: numeric.h:49
#define Assert(condition)
Definition: c.h:680
Definition: regguts.h:298
bool isnull
Definition: hstore.h:167
Datum hstore_from_record(PG_FUNCTION_ARGS)
Definition: hstore_io.c:764
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:230
Oid typioparam
Definition: hstore_io.c:748
#define ARR_NDIM(a)
Definition: array.h:275
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:949
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:936
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3449
static Datum values[MAXATTR]
Definition: bootstrap.c:164
size_t hstoreCheckKeyLen(size_t len)
Definition: hstore_io.c:355
#define ItemPointerSetInvalid(pointer)
Definition: itemptr.h:150
char * ptr
Definition: hstore_io.c:32
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:340
void * palloc(Size size)
Definition: mcxt.c:835
int errmsg(const char *fmt,...)
Definition: elog.c:797
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:693
#define STRPTR(x)
Definition: hstore.h:76
Datum hstore_recv(PG_FUNCTION_ARGS)
Definition: hstore_io.c:427
#define WEQ
Definition: hstore_io.c:177
int i
#define GV_WAITESCIN
Definition: hstore_io.c:57
#define NameStr(name)
Definition: c.h:557
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:242
#define WKEY
Definition: hstore_io.c:175
Definition: c.h:497
#define PG_FUNCTION_ARGS
Definition: fmgr.h:158
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
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
#define HS_SETCOUNT(hsp_, c_)
Definition: hstore.h:62
#define qsort(a, b, c, d)
Definition: port.h:408
#define ReleaseTupleDesc(tupdesc)
Definition: tupdesc.h:121
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:277
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:603
Oid column_type
Definition: hstore_io.c:746
#define HeapTupleHeaderGetDatumLength(tup)
Definition: htup_details.h:444