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