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