PostgreSQL Source Code git master
jsonpath.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * jsonpath.c
4 * Input/output and supporting routines for jsonpath
5 *
6 * jsonpath expression is a chain of path items. First path item is $, $var,
7 * literal or arithmetic expression. Subsequent path items are accessors
8 * (.key, .*, [subscripts], [*]), filters (? (predicate)) and methods (.type(),
9 * .size() etc).
10 *
11 * For instance, structure of path items for simple expression:
12 *
13 * $.a[*].type()
14 *
15 * is pretty evident:
16 *
17 * $ => .a => [*] => .type()
18 *
19 * Some path items such as arithmetic operations, predicates or array
20 * subscripts may comprise subtrees. For instance, more complex expression
21 *
22 * ($.a + $[1 to 5, 7] ? (@ > 3).double()).type()
23 *
24 * have following structure of path items:
25 *
26 * + => .type()
27 * ___/ \___
28 * / \
29 * $ => .a $ => [] => ? => .double()
30 * _||_ |
31 * / \ >
32 * to to / \
33 * / \ / @ 3
34 * 1 5 7
35 *
36 * Binary encoding of jsonpath constitutes a sequence of 4-bytes aligned
37 * variable-length path items connected by links. Every item has a header
38 * consisting of item type (enum JsonPathItemType) and offset of next item
39 * (zero means no next item). After the header, item may have payload
40 * depending on item type. For instance, payload of '.key' accessor item is
41 * length of key name and key name itself. Payload of '>' arithmetic operator
42 * item is offsets of right and left operands.
43 *
44 * So, binary representation of sample expression above is:
45 * (bottom arrows are next links, top lines are argument links)
46 *
47 * _____
48 * _____ ___/____ \ __
49 * _ /_ \ _____/__/____ \ \ __ _ /_ \
50 * / / \ \ / / / \ \ \ / \ / / \ \
51 * +(LR) $ .a $ [](* to *, * to *) 1 5 7 ?(A) >(LR) @ 3 .double() .type()
52 * | | ^ | ^| ^| ^ ^
53 * | |__| |__||________________________||___________________| |
54 * |_______________________________________________________________________|
55 *
56 * Copyright (c) 2019-2025, PostgreSQL Global Development Group
57 *
58 * IDENTIFICATION
59 * src/backend/utils/adt/jsonpath.c
60 *
61 *-------------------------------------------------------------------------
62 */
63
64#include "postgres.h"
65
66#include "catalog/pg_type.h"
67#include "lib/stringinfo.h"
68#include "libpq/pqformat.h"
69#include "miscadmin.h"
70#include "nodes/miscnodes.h"
71#include "nodes/nodeFuncs.h"
72#include "utils/fmgrprotos.h"
73#include "utils/formatting.h"
74#include "utils/json.h"
75#include "utils/jsonpath.h"
76
77
78static Datum jsonPathFromCstring(char *in, int len, struct Node *escontext);
79static char *jsonPathToCstring(StringInfo out, JsonPath *in,
80 int estimated_len);
81static bool flattenJsonPathParseItem(StringInfo buf, int *result,
82 struct Node *escontext,
84 int nestingLevel, bool insideArraySubscript);
87static void printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
88 bool printBracketes);
90
91
92/**************************** INPUT/OUTPUT ********************************/
93
94/*
95 * jsonpath type input function
96 */
99{
100 char *in = PG_GETARG_CSTRING(0);
101 int len = strlen(in);
102
103 return jsonPathFromCstring(in, len, fcinfo->context);
104}
105
106/*
107 * jsonpath type recv function
108 *
109 * The type is sent as text in binary mode, so this is almost the same
110 * as the input function, but it's prefixed with a version number so we
111 * can change the binary format sent in future if necessary. For now,
112 * only version 1 is supported.
113 */
114Datum
116{
118 int version = pq_getmsgint(buf, 1);
119 char *str;
120 int nbytes;
121
122 if (version == JSONPATH_VERSION)
123 str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
124 else
125 elog(ERROR, "unsupported jsonpath version number: %d", version);
126
127 return jsonPathFromCstring(str, nbytes, NULL);
128}
129
130/*
131 * jsonpath type output function
132 */
133Datum
135{
137
139}
140
141/*
142 * jsonpath type send function
143 *
144 * Just send jsonpath as a version number, then a string of text
145 */
146Datum
148{
151 StringInfoData jtext;
152 int version = JSONPATH_VERSION;
153
154 initStringInfo(&jtext);
155 (void) jsonPathToCstring(&jtext, in, VARSIZE(in));
156
158 pq_sendint8(&buf, version);
159 pq_sendtext(&buf, jtext.data, jtext.len);
160 pfree(jtext.data);
161
163}
164
165/*
166 * Converts C-string to a jsonpath value.
167 *
168 * Uses jsonpath parser to turn string into an AST, then
169 * flattenJsonPathParseItem() does second pass turning AST into binary
170 * representation of jsonpath.
171 */
172static Datum
173jsonPathFromCstring(char *in, int len, struct Node *escontext)
174{
175 JsonPathParseResult *jsonpath = parsejsonpath(in, len, escontext);
176 JsonPath *res;
178
179 if (SOFT_ERROR_OCCURRED(escontext))
180 return (Datum) 0;
181
182 if (!jsonpath)
183 ereturn(escontext, (Datum) 0,
184 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
185 errmsg("invalid input syntax for type %s: \"%s\"", "jsonpath",
186 in)));
187
189 enlargeStringInfo(&buf, 4 * len /* estimation */ );
190
192
193 if (!flattenJsonPathParseItem(&buf, NULL, escontext,
194 jsonpath->expr, 0, false))
195 return (Datum) 0;
196
197 res = (JsonPath *) buf.data;
198 SET_VARSIZE(res, buf.len);
199 res->header = JSONPATH_VERSION;
200 if (jsonpath->lax)
201 res->header |= JSONPATH_LAX;
202
204}
205
206/*
207 * Converts jsonpath value to a C-string.
208 *
209 * If 'out' argument is non-null, the resulting C-string is stored inside the
210 * StringBuffer. The resulting string is always returned.
211 */
212static char *
213jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
214{
216 JsonPathItem v;
217
218 if (!out)
219 {
220 out = &buf;
221 initStringInfo(out);
222 }
223 enlargeStringInfo(out, estimated_len);
224
225 if (!(in->header & JSONPATH_LAX))
226 appendStringInfoString(out, "strict ");
227
228 jspInit(&v, in);
229 printJsonPathItem(out, &v, false, true);
230
231 return out->data;
232}
233
234/*
235 * Recursive function converting given jsonpath parse item and all its
236 * children into a binary representation.
237 */
238static bool
239flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext,
240 JsonPathParseItem *item, int nestingLevel,
241 bool insideArraySubscript)
242{
243 /* position from beginning of jsonpath data */
244 int32 pos = buf->len - JSONPATH_HDRSZ;
245 int32 chld;
246 int32 next;
247 int argNestingLevel = 0;
248
251
252 appendStringInfoChar(buf, (char) (item->type));
253
254 /*
255 * We align buffer to int32 because a series of int32 values often goes
256 * after the header, and we want to read them directly by dereferencing
257 * int32 pointer (see jspInitByBuffer()).
258 */
260
261 /*
262 * Reserve space for next item pointer. Actual value will be recorded
263 * later, after next and children items processing.
264 */
266
267 switch (item->type)
268 {
269 case jpiString:
270 case jpiVariable:
271 case jpiKey:
273 sizeof(item->value.string.len));
275 item->value.string.len);
277 break;
278 case jpiNumeric:
280 VARSIZE(item->value.numeric));
281 break;
282 case jpiBool:
284 sizeof(item->value.boolean));
285 break;
286 case jpiAnd:
287 case jpiOr:
288 case jpiEqual:
289 case jpiNotEqual:
290 case jpiLess:
291 case jpiGreater:
292 case jpiLessOrEqual:
294 case jpiAdd:
295 case jpiSub:
296 case jpiMul:
297 case jpiDiv:
298 case jpiMod:
299 case jpiStartsWith:
300 case jpiDecimal:
301 {
302 /*
303 * First, reserve place for left/right arg's positions, then
304 * record both args and sets actual position in reserved
305 * places.
306 */
309
310 if (!item->value.args.left)
311 chld = pos;
312 else if (!flattenJsonPathParseItem(buf, &chld, escontext,
313 item->value.args.left,
314 nestingLevel + argNestingLevel,
315 insideArraySubscript))
316 return false;
317 *(int32 *) (buf->data + left) = chld - pos;
318
319 if (!item->value.args.right)
320 chld = pos;
321 else if (!flattenJsonPathParseItem(buf, &chld, escontext,
322 item->value.args.right,
323 nestingLevel + argNestingLevel,
324 insideArraySubscript))
325 return false;
326 *(int32 *) (buf->data + right) = chld - pos;
327 }
328 break;
329 case jpiLikeRegex:
330 {
331 int32 offs;
332
334 &item->value.like_regex.flags,
335 sizeof(item->value.like_regex.flags));
339 sizeof(item->value.like_regex.patternlen));
343
344 if (!flattenJsonPathParseItem(buf, &chld, escontext,
345 item->value.like_regex.expr,
346 nestingLevel,
347 insideArraySubscript))
348 return false;
349 *(int32 *) (buf->data + offs) = chld - pos;
350 }
351 break;
352 case jpiFilter:
353 argNestingLevel++;
354 /* FALLTHROUGH */
355 case jpiIsUnknown:
356 case jpiNot:
357 case jpiPlus:
358 case jpiMinus:
359 case jpiExists:
360 case jpiDatetime:
361 case jpiTime:
362 case jpiTimeTz:
363 case jpiTimestamp:
364 case jpiTimestampTz:
365 {
367
368 if (!item->value.arg)
369 chld = pos;
370 else if (!flattenJsonPathParseItem(buf, &chld, escontext,
371 item->value.arg,
372 nestingLevel + argNestingLevel,
373 insideArraySubscript))
374 return false;
375 *(int32 *) (buf->data + arg) = chld - pos;
376 }
377 break;
378 case jpiNull:
379 break;
380 case jpiRoot:
381 break;
382 case jpiAnyArray:
383 case jpiAnyKey:
384 break;
385 case jpiCurrent:
386 if (nestingLevel <= 0)
387 ereturn(escontext, false,
388 (errcode(ERRCODE_SYNTAX_ERROR),
389 errmsg("@ is not allowed in root expressions")));
390 break;
391 case jpiLast:
392 if (!insideArraySubscript)
393 ereturn(escontext, false,
394 (errcode(ERRCODE_SYNTAX_ERROR),
395 errmsg("LAST is allowed only in array subscripts")));
396 break;
397 case jpiIndexArray:
398 {
399 int32 nelems = item->value.array.nelems;
400 int offset;
401 int i;
402
403 appendBinaryStringInfo(buf, &nelems, sizeof(nelems));
404
405 offset = buf->len;
406
407 appendStringInfoSpaces(buf, sizeof(int32) * 2 * nelems);
408
409 for (i = 0; i < nelems; i++)
410 {
411 int32 *ppos;
412 int32 topos;
413 int32 frompos;
414
415 if (!flattenJsonPathParseItem(buf, &frompos, escontext,
416 item->value.array.elems[i].from,
417 nestingLevel, true))
418 return false;
419 frompos -= pos;
420
421 if (item->value.array.elems[i].to)
422 {
423 if (!flattenJsonPathParseItem(buf, &topos, escontext,
424 item->value.array.elems[i].to,
425 nestingLevel, true))
426 return false;
427 topos -= pos;
428 }
429 else
430 topos = 0;
431
432 ppos = (int32 *) &buf->data[offset + i * 2 * sizeof(int32)];
433
434 ppos[0] = frompos;
435 ppos[1] = topos;
436 }
437 }
438 break;
439 case jpiAny:
441 &item->value.anybounds.first,
442 sizeof(item->value.anybounds.first));
444 &item->value.anybounds.last,
445 sizeof(item->value.anybounds.last));
446 break;
447 case jpiType:
448 case jpiSize:
449 case jpiAbs:
450 case jpiFloor:
451 case jpiCeiling:
452 case jpiDouble:
453 case jpiKeyValue:
454 case jpiBigint:
455 case jpiBoolean:
456 case jpiDate:
457 case jpiInteger:
458 case jpiNumber:
459 case jpiStringFunc:
460 break;
461 default:
462 elog(ERROR, "unrecognized jsonpath item type: %d", item->type);
463 }
464
465 if (item->next)
466 {
467 if (!flattenJsonPathParseItem(buf, &chld, escontext,
468 item->next, nestingLevel,
469 insideArraySubscript))
470 return false;
471 chld -= pos;
472 *(int32 *) (buf->data + next) = chld;
473 }
474
475 if (result)
476 *result = pos;
477 return true;
478}
479
480/*
481 * Align StringInfo to int by adding zero padding bytes
482 */
483static void
485{
486 switch (INTALIGN(buf->len) - buf->len)
487 {
488 case 3:
490 /* FALLTHROUGH */
491 case 2:
493 /* FALLTHROUGH */
494 case 1:
496 /* FALLTHROUGH */
497 default:
498 break;
499 }
500}
501
502/*
503 * Reserve space for int32 JsonPathItem pointer. Now zero pointer is written,
504 * actual value will be recorded at '(int32 *) &buf->data[pos]' later.
505 */
506static int32
508{
509 int32 pos = buf->len;
510 int32 ptr = 0;
511
512 appendBinaryStringInfo(buf, &ptr, sizeof(ptr));
513
514 return pos;
515}
516
517/*
518 * Prints text representation of given jsonpath item and all its children.
519 */
520static void
522 bool printBracketes)
523{
524 JsonPathItem elem;
525 int i;
526 int32 len;
527 char *str;
528
531
532 switch (v->type)
533 {
534 case jpiNull:
536 break;
537 case jpiString:
538 str = jspGetString(v, &len);
540 break;
541 case jpiNumeric:
542 if (jspHasNext(v))
547 if (jspHasNext(v))
549 break;
550 case jpiBool:
551 if (jspGetBool(v))
553 else
554 appendStringInfoString(buf, "false");
555 break;
556 case jpiAnd:
557 case jpiOr:
558 case jpiEqual:
559 case jpiNotEqual:
560 case jpiLess:
561 case jpiGreater:
562 case jpiLessOrEqual:
564 case jpiAdd:
565 case jpiSub:
566 case jpiMul:
567 case jpiDiv:
568 case jpiMod:
569 case jpiStartsWith:
570 if (printBracketes)
572 jspGetLeftArg(v, &elem);
573 printJsonPathItem(buf, &elem, false,
574 operationPriority(elem.type) <=
579 jspGetRightArg(v, &elem);
580 printJsonPathItem(buf, &elem, false,
581 operationPriority(elem.type) <=
583 if (printBracketes)
585 break;
586 case jpiNot:
588 jspGetArg(v, &elem);
589 printJsonPathItem(buf, &elem, false, false);
591 break;
592 case jpiIsUnknown:
594 jspGetArg(v, &elem);
595 printJsonPathItem(buf, &elem, false, false);
596 appendStringInfoString(buf, ") is unknown");
597 break;
598 case jpiPlus:
599 case jpiMinus:
600 if (printBracketes)
602 appendStringInfoChar(buf, v->type == jpiPlus ? '+' : '-');
603 jspGetArg(v, &elem);
604 printJsonPathItem(buf, &elem, false,
605 operationPriority(elem.type) <=
607 if (printBracketes)
609 break;
610 case jpiAnyArray:
612 break;
613 case jpiAnyKey:
614 if (inKey)
617 break;
618 case jpiIndexArray:
620 for (i = 0; i < v->content.array.nelems; i++)
621 {
622 JsonPathItem from;
623 JsonPathItem to;
624 bool range = jspGetArraySubscript(v, &from, &to, i);
625
626 if (i)
628
629 printJsonPathItem(buf, &from, false, false);
630
631 if (range)
632 {
634 printJsonPathItem(buf, &to, false, false);
635 }
636 }
638 break;
639 case jpiAny:
640 if (inKey)
642
643 if (v->content.anybounds.first == 0 &&
646 else if (v->content.anybounds.first == v->content.anybounds.last)
647 {
649 appendStringInfoString(buf, "**{last}");
650 else
651 appendStringInfo(buf, "**{%u}",
653 }
654 else if (v->content.anybounds.first == PG_UINT32_MAX)
655 appendStringInfo(buf, "**{last to %u}",
657 else if (v->content.anybounds.last == PG_UINT32_MAX)
658 appendStringInfo(buf, "**{%u to last}",
660 else
661 appendStringInfo(buf, "**{%u to %u}",
664 break;
665 case jpiKey:
666 if (inKey)
668 str = jspGetString(v, &len);
670 break;
671 case jpiCurrent:
672 Assert(!inKey);
674 break;
675 case jpiRoot:
676 Assert(!inKey);
678 break;
679 case jpiVariable:
681 str = jspGetString(v, &len);
683 break;
684 case jpiFilter:
686 jspGetArg(v, &elem);
687 printJsonPathItem(buf, &elem, false, false);
689 break;
690 case jpiExists:
691 appendStringInfoString(buf, "exists (");
692 jspGetArg(v, &elem);
693 printJsonPathItem(buf, &elem, false, false);
695 break;
696 case jpiType:
697 appendStringInfoString(buf, ".type()");
698 break;
699 case jpiSize:
700 appendStringInfoString(buf, ".size()");
701 break;
702 case jpiAbs:
703 appendStringInfoString(buf, ".abs()");
704 break;
705 case jpiFloor:
706 appendStringInfoString(buf, ".floor()");
707 break;
708 case jpiCeiling:
709 appendStringInfoString(buf, ".ceiling()");
710 break;
711 case jpiDouble:
712 appendStringInfoString(buf, ".double()");
713 break;
714 case jpiDatetime:
715 appendStringInfoString(buf, ".datetime(");
716 if (v->content.arg)
717 {
718 jspGetArg(v, &elem);
719 printJsonPathItem(buf, &elem, false, false);
720 }
722 break;
723 case jpiKeyValue:
724 appendStringInfoString(buf, ".keyvalue()");
725 break;
726 case jpiLast:
728 break;
729 case jpiLikeRegex:
730 if (printBracketes)
732
734 printJsonPathItem(buf, &elem, false,
735 operationPriority(elem.type) <=
737
738 appendStringInfoString(buf, " like_regex ");
739
743
744 if (v->content.like_regex.flags)
745 {
746 appendStringInfoString(buf, " flag \"");
747
758
760 }
761
762 if (printBracketes)
764 break;
765 case jpiBigint:
766 appendStringInfoString(buf, ".bigint()");
767 break;
768 case jpiBoolean:
769 appendStringInfoString(buf, ".boolean()");
770 break;
771 case jpiDate:
772 appendStringInfoString(buf, ".date()");
773 break;
774 case jpiDecimal:
775 appendStringInfoString(buf, ".decimal(");
776 if (v->content.args.left)
777 {
778 jspGetLeftArg(v, &elem);
779 printJsonPathItem(buf, &elem, false, false);
780 }
781 if (v->content.args.right)
782 {
784 jspGetRightArg(v, &elem);
785 printJsonPathItem(buf, &elem, false, false);
786 }
788 break;
789 case jpiInteger:
790 appendStringInfoString(buf, ".integer()");
791 break;
792 case jpiNumber:
793 appendStringInfoString(buf, ".number()");
794 break;
795 case jpiStringFunc:
796 appendStringInfoString(buf, ".string()");
797 break;
798 case jpiTime:
799 appendStringInfoString(buf, ".time(");
800 if (v->content.arg)
801 {
802 jspGetArg(v, &elem);
803 printJsonPathItem(buf, &elem, false, false);
804 }
806 break;
807 case jpiTimeTz:
808 appendStringInfoString(buf, ".time_tz(");
809 if (v->content.arg)
810 {
811 jspGetArg(v, &elem);
812 printJsonPathItem(buf, &elem, false, false);
813 }
815 break;
816 case jpiTimestamp:
817 appendStringInfoString(buf, ".timestamp(");
818 if (v->content.arg)
819 {
820 jspGetArg(v, &elem);
821 printJsonPathItem(buf, &elem, false, false);
822 }
824 break;
825 case jpiTimestampTz:
826 appendStringInfoString(buf, ".timestamp_tz(");
827 if (v->content.arg)
828 {
829 jspGetArg(v, &elem);
830 printJsonPathItem(buf, &elem, false, false);
831 }
833 break;
834 default:
835 elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
836 }
837
838 if (jspGetNext(v, &elem))
839 printJsonPathItem(buf, &elem, true, true);
840}
841
842const char *
844{
845 switch (type)
846 {
847 case jpiAnd:
848 return "&&";
849 case jpiOr:
850 return "||";
851 case jpiEqual:
852 return "==";
853 case jpiNotEqual:
854 return "!=";
855 case jpiLess:
856 return "<";
857 case jpiGreater:
858 return ">";
859 case jpiLessOrEqual:
860 return "<=";
862 return ">=";
863 case jpiAdd:
864 case jpiPlus:
865 return "+";
866 case jpiSub:
867 case jpiMinus:
868 return "-";
869 case jpiMul:
870 return "*";
871 case jpiDiv:
872 return "/";
873 case jpiMod:
874 return "%";
875 case jpiType:
876 return "type";
877 case jpiSize:
878 return "size";
879 case jpiAbs:
880 return "abs";
881 case jpiFloor:
882 return "floor";
883 case jpiCeiling:
884 return "ceiling";
885 case jpiDouble:
886 return "double";
887 case jpiDatetime:
888 return "datetime";
889 case jpiKeyValue:
890 return "keyvalue";
891 case jpiStartsWith:
892 return "starts with";
893 case jpiLikeRegex:
894 return "like_regex";
895 case jpiBigint:
896 return "bigint";
897 case jpiBoolean:
898 return "boolean";
899 case jpiDate:
900 return "date";
901 case jpiDecimal:
902 return "decimal";
903 case jpiInteger:
904 return "integer";
905 case jpiNumber:
906 return "number";
907 case jpiStringFunc:
908 return "string";
909 case jpiTime:
910 return "time";
911 case jpiTimeTz:
912 return "time_tz";
913 case jpiTimestamp:
914 return "timestamp";
915 case jpiTimestampTz:
916 return "timestamp_tz";
917 default:
918 elog(ERROR, "unrecognized jsonpath item type: %d", type);
919 return NULL;
920 }
921}
922
923static int
925{
926 switch (op)
927 {
928 case jpiOr:
929 return 0;
930 case jpiAnd:
931 return 1;
932 case jpiEqual:
933 case jpiNotEqual:
934 case jpiLess:
935 case jpiGreater:
936 case jpiLessOrEqual:
938 case jpiStartsWith:
939 return 2;
940 case jpiAdd:
941 case jpiSub:
942 return 3;
943 case jpiMul:
944 case jpiDiv:
945 case jpiMod:
946 return 4;
947 case jpiPlus:
948 case jpiMinus:
949 return 5;
950 default:
951 return 6;
952 }
953}
954
955/******************* Support functions for JsonPath *************************/
956
957/*
958 * Support macros to read stored values
959 */
960
961#define read_byte(v, b, p) do { \
962 (v) = *(uint8*)((b) + (p)); \
963 (p) += 1; \
964} while(0) \
965
966#define read_int32(v, b, p) do { \
967 (v) = *(uint32*)((b) + (p)); \
968 (p) += sizeof(int32); \
969} while(0) \
970
971#define read_int32_n(v, b, p, n) do { \
972 (v) = (void *)((b) + (p)); \
973 (p) += sizeof(int32) * (n); \
974} while(0) \
975
976/*
977 * Read root node and fill root node representation
978 */
979void
981{
983 jspInitByBuffer(v, js->data, 0);
984}
985
986/*
987 * Read node from buffer and fill its representation
988 */
989void
991{
992 v->base = base + pos;
993
994 read_byte(v->type, base, pos);
995 pos = INTALIGN((uintptr_t) (base + pos)) - (uintptr_t) base;
996 read_int32(v->nextPos, base, pos);
997
998 switch (v->type)
999 {
1000 case jpiNull:
1001 case jpiRoot:
1002 case jpiCurrent:
1003 case jpiAnyArray:
1004 case jpiAnyKey:
1005 case jpiType:
1006 case jpiSize:
1007 case jpiAbs:
1008 case jpiFloor:
1009 case jpiCeiling:
1010 case jpiDouble:
1011 case jpiKeyValue:
1012 case jpiLast:
1013 case jpiBigint:
1014 case jpiBoolean:
1015 case jpiDate:
1016 case jpiInteger:
1017 case jpiNumber:
1018 case jpiStringFunc:
1019 break;
1020 case jpiString:
1021 case jpiKey:
1022 case jpiVariable:
1023 read_int32(v->content.value.datalen, base, pos);
1024 /* FALLTHROUGH */
1025 case jpiNumeric:
1026 case jpiBool:
1027 v->content.value.data = base + pos;
1028 break;
1029 case jpiAnd:
1030 case jpiOr:
1031 case jpiEqual:
1032 case jpiNotEqual:
1033 case jpiLess:
1034 case jpiGreater:
1035 case jpiLessOrEqual:
1036 case jpiGreaterOrEqual:
1037 case jpiAdd:
1038 case jpiSub:
1039 case jpiMul:
1040 case jpiDiv:
1041 case jpiMod:
1042 case jpiStartsWith:
1043 case jpiDecimal:
1044 read_int32(v->content.args.left, base, pos);
1045 read_int32(v->content.args.right, base, pos);
1046 break;
1047 case jpiNot:
1048 case jpiIsUnknown:
1049 case jpiExists:
1050 case jpiPlus:
1051 case jpiMinus:
1052 case jpiFilter:
1053 case jpiDatetime:
1054 case jpiTime:
1055 case jpiTimeTz:
1056 case jpiTimestamp:
1057 case jpiTimestampTz:
1058 read_int32(v->content.arg, base, pos);
1059 break;
1060 case jpiIndexArray:
1061 read_int32(v->content.array.nelems, base, pos);
1062 read_int32_n(v->content.array.elems, base, pos,
1063 v->content.array.nelems * 2);
1064 break;
1065 case jpiAny:
1066 read_int32(v->content.anybounds.first, base, pos);
1067 read_int32(v->content.anybounds.last, base, pos);
1068 break;
1069 case jpiLikeRegex:
1070 read_int32(v->content.like_regex.flags, base, pos);
1071 read_int32(v->content.like_regex.expr, base, pos);
1072 read_int32(v->content.like_regex.patternlen, base, pos);
1073 v->content.like_regex.pattern = base + pos;
1074 break;
1075 default:
1076 elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
1077 }
1078}
1079
1080void
1082{
1083 Assert(v->type == jpiNot ||
1084 v->type == jpiIsUnknown ||
1085 v->type == jpiPlus ||
1086 v->type == jpiMinus ||
1087 v->type == jpiFilter ||
1088 v->type == jpiExists ||
1089 v->type == jpiDatetime ||
1090 v->type == jpiTime ||
1091 v->type == jpiTimeTz ||
1092 v->type == jpiTimestamp ||
1093 v->type == jpiTimestampTz);
1094
1095 jspInitByBuffer(a, v->base, v->content.arg);
1096}
1097
1098bool
1100{
1101 if (jspHasNext(v))
1102 {
1103 Assert(v->type == jpiNull ||
1104 v->type == jpiString ||
1105 v->type == jpiNumeric ||
1106 v->type == jpiBool ||
1107 v->type == jpiAnd ||
1108 v->type == jpiOr ||
1109 v->type == jpiNot ||
1110 v->type == jpiIsUnknown ||
1111 v->type == jpiEqual ||
1112 v->type == jpiNotEqual ||
1113 v->type == jpiLess ||
1114 v->type == jpiGreater ||
1115 v->type == jpiLessOrEqual ||
1116 v->type == jpiGreaterOrEqual ||
1117 v->type == jpiAdd ||
1118 v->type == jpiSub ||
1119 v->type == jpiMul ||
1120 v->type == jpiDiv ||
1121 v->type == jpiMod ||
1122 v->type == jpiPlus ||
1123 v->type == jpiMinus ||
1124 v->type == jpiAnyArray ||
1125 v->type == jpiAnyKey ||
1126 v->type == jpiIndexArray ||
1127 v->type == jpiAny ||
1128 v->type == jpiKey ||
1129 v->type == jpiCurrent ||
1130 v->type == jpiRoot ||
1131 v->type == jpiVariable ||
1132 v->type == jpiFilter ||
1133 v->type == jpiExists ||
1134 v->type == jpiType ||
1135 v->type == jpiSize ||
1136 v->type == jpiAbs ||
1137 v->type == jpiFloor ||
1138 v->type == jpiCeiling ||
1139 v->type == jpiDouble ||
1140 v->type == jpiDatetime ||
1141 v->type == jpiKeyValue ||
1142 v->type == jpiLast ||
1143 v->type == jpiStartsWith ||
1144 v->type == jpiLikeRegex ||
1145 v->type == jpiBigint ||
1146 v->type == jpiBoolean ||
1147 v->type == jpiDate ||
1148 v->type == jpiDecimal ||
1149 v->type == jpiInteger ||
1150 v->type == jpiNumber ||
1151 v->type == jpiStringFunc ||
1152 v->type == jpiTime ||
1153 v->type == jpiTimeTz ||
1154 v->type == jpiTimestamp ||
1155 v->type == jpiTimestampTz);
1156
1157 if (a)
1158 jspInitByBuffer(a, v->base, v->nextPos);
1159 return true;
1160 }
1161
1162 return false;
1163}
1164
1165void
1167{
1168 Assert(v->type == jpiAnd ||
1169 v->type == jpiOr ||
1170 v->type == jpiEqual ||
1171 v->type == jpiNotEqual ||
1172 v->type == jpiLess ||
1173 v->type == jpiGreater ||
1174 v->type == jpiLessOrEqual ||
1175 v->type == jpiGreaterOrEqual ||
1176 v->type == jpiAdd ||
1177 v->type == jpiSub ||
1178 v->type == jpiMul ||
1179 v->type == jpiDiv ||
1180 v->type == jpiMod ||
1181 v->type == jpiStartsWith ||
1182 v->type == jpiDecimal);
1183
1185}
1186
1187void
1189{
1190 Assert(v->type == jpiAnd ||
1191 v->type == jpiOr ||
1192 v->type == jpiEqual ||
1193 v->type == jpiNotEqual ||
1194 v->type == jpiLess ||
1195 v->type == jpiGreater ||
1196 v->type == jpiLessOrEqual ||
1197 v->type == jpiGreaterOrEqual ||
1198 v->type == jpiAdd ||
1199 v->type == jpiSub ||
1200 v->type == jpiMul ||
1201 v->type == jpiDiv ||
1202 v->type == jpiMod ||
1203 v->type == jpiStartsWith ||
1204 v->type == jpiDecimal);
1205
1207}
1208
1209bool
1211{
1212 Assert(v->type == jpiBool);
1213
1214 return (bool) *v->content.value.data;
1215}
1216
1217Numeric
1219{
1220 Assert(v->type == jpiNumeric);
1221
1222 return (Numeric) v->content.value.data;
1223}
1224
1225char *
1227{
1228 Assert(v->type == jpiKey ||
1229 v->type == jpiString ||
1230 v->type == jpiVariable);
1231
1232 if (len)
1233 *len = v->content.value.datalen;
1234 return v->content.value.data;
1235}
1236
1237bool
1239 int i)
1240{
1241 Assert(v->type == jpiIndexArray);
1242
1243 jspInitByBuffer(from, v->base, v->content.array.elems[i].from);
1244
1245 if (!v->content.array.elems[i].to)
1246 return false;
1247
1248 jspInitByBuffer(to, v->base, v->content.array.elems[i].to);
1249
1250 return true;
1251}
1252
1253/* SQL/JSON datatype status: */
1255{
1256 jpdsNonDateTime, /* null, bool, numeric, string, array, object */
1257 jpdsUnknownDateTime, /* unknown datetime type */
1258 jpdsDateTimeZoned, /* timetz, timestamptz */
1259 jpdsDateTimeNonZoned, /* time, timestamp, date */
1260};
1261
1262/* Context for jspIsMutableWalker() */
1264{
1265 List *varnames; /* list of variable names */
1266 List *varexprs; /* list of variable expressions */
1267 enum JsonPathDatatypeStatus current; /* status of @ item */
1268 bool lax; /* jsonpath is lax or strict */
1269 bool mutable; /* resulting mutability status */
1270};
1271
1273 struct JsonPathMutableContext *cxt);
1274
1275/*
1276 * Function to check whether jsonpath expression is mutable to be used in the
1277 * planner function contain_mutable_functions().
1278 */
1279bool
1280jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
1281{
1282 struct JsonPathMutableContext cxt;
1283 JsonPathItem jpi;
1284
1285 cxt.varnames = varnames;
1286 cxt.varexprs = varexprs;
1288 cxt.lax = (path->header & JSONPATH_LAX) != 0;
1289 cxt.mutable = false;
1290
1291 jspInit(&jpi, path);
1292 (void) jspIsMutableWalker(&jpi, &cxt);
1293
1294 return cxt.mutable;
1295}
1296
1297/*
1298 * Recursive walker for jspIsMutable()
1299 */
1300static enum JsonPathDatatypeStatus
1302{
1305
1306 while (!cxt->mutable)
1307 {
1309 enum JsonPathDatatypeStatus leftStatus;
1310 enum JsonPathDatatypeStatus rightStatus;
1311
1312 switch (jpi->type)
1313 {
1314 case jpiRoot:
1315 Assert(status == jpdsNonDateTime);
1316 break;
1317
1318 case jpiCurrent:
1319 Assert(status == jpdsNonDateTime);
1320 status = cxt->current;
1321 break;
1322
1323 case jpiFilter:
1324 {
1325 enum JsonPathDatatypeStatus prevStatus = cxt->current;
1326
1327 cxt->current = status;
1328 jspGetArg(jpi, &arg);
1329 jspIsMutableWalker(&arg, cxt);
1330
1331 cxt->current = prevStatus;
1332 break;
1333 }
1334
1335 case jpiVariable:
1336 {
1337 int32 len;
1338 const char *name = jspGetString(jpi, &len);
1339 ListCell *lc1;
1340 ListCell *lc2;
1341
1342 Assert(status == jpdsNonDateTime);
1343
1344 forboth(lc1, cxt->varnames, lc2, cxt->varexprs)
1345 {
1346 String *varname = lfirst_node(String, lc1);
1347 Node *varexpr = lfirst(lc2);
1348
1349 if (strncmp(varname->sval, name, len))
1350 continue;
1351
1352 switch (exprType(varexpr))
1353 {
1354 case DATEOID:
1355 case TIMEOID:
1356 case TIMESTAMPOID:
1357 status = jpdsDateTimeNonZoned;
1358 break;
1359
1360 case TIMETZOID:
1361 case TIMESTAMPTZOID:
1362 status = jpdsDateTimeZoned;
1363 break;
1364
1365 default:
1366 status = jpdsNonDateTime;
1367 break;
1368 }
1369
1370 break;
1371 }
1372 break;
1373 }
1374
1375 case jpiEqual:
1376 case jpiNotEqual:
1377 case jpiLess:
1378 case jpiGreater:
1379 case jpiLessOrEqual:
1380 case jpiGreaterOrEqual:
1381 Assert(status == jpdsNonDateTime);
1382 jspGetLeftArg(jpi, &arg);
1383 leftStatus = jspIsMutableWalker(&arg, cxt);
1384
1385 jspGetRightArg(jpi, &arg);
1386 rightStatus = jspIsMutableWalker(&arg, cxt);
1387
1388 /*
1389 * Comparison of datetime type with different timezone status
1390 * is mutable.
1391 */
1392 if (leftStatus != jpdsNonDateTime &&
1393 rightStatus != jpdsNonDateTime &&
1394 (leftStatus == jpdsUnknownDateTime ||
1395 rightStatus == jpdsUnknownDateTime ||
1396 leftStatus != rightStatus))
1397 cxt->mutable = true;
1398 break;
1399
1400 case jpiNot:
1401 case jpiIsUnknown:
1402 case jpiExists:
1403 case jpiPlus:
1404 case jpiMinus:
1405 Assert(status == jpdsNonDateTime);
1406 jspGetArg(jpi, &arg);
1407 jspIsMutableWalker(&arg, cxt);
1408 break;
1409
1410 case jpiAnd:
1411 case jpiOr:
1412 case jpiAdd:
1413 case jpiSub:
1414 case jpiMul:
1415 case jpiDiv:
1416 case jpiMod:
1417 case jpiStartsWith:
1418 Assert(status == jpdsNonDateTime);
1419 jspGetLeftArg(jpi, &arg);
1420 jspIsMutableWalker(&arg, cxt);
1421 jspGetRightArg(jpi, &arg);
1422 jspIsMutableWalker(&arg, cxt);
1423 break;
1424
1425 case jpiIndexArray:
1426 for (int i = 0; i < jpi->content.array.nelems; i++)
1427 {
1428 JsonPathItem from;
1429 JsonPathItem to;
1430
1431 if (jspGetArraySubscript(jpi, &from, &to, i))
1432 jspIsMutableWalker(&to, cxt);
1433
1434 jspIsMutableWalker(&from, cxt);
1435 }
1436 /* FALLTHROUGH */
1437
1438 case jpiAnyArray:
1439 if (!cxt->lax)
1440 status = jpdsNonDateTime;
1441 break;
1442
1443 case jpiAny:
1444 if (jpi->content.anybounds.first > 0)
1445 status = jpdsNonDateTime;
1446 break;
1447
1448 case jpiDatetime:
1449 if (jpi->content.arg)
1450 {
1451 char *template;
1452
1453 jspGetArg(jpi, &arg);
1454 if (arg.type != jpiString)
1455 {
1456 status = jpdsNonDateTime;
1457 break; /* there will be runtime error */
1458 }
1459
1460 template = jspGetString(&arg, NULL);
1461 if (datetime_format_has_tz(template))
1462 status = jpdsDateTimeZoned;
1463 else
1464 status = jpdsDateTimeNonZoned;
1465 }
1466 else
1467 {
1468 status = jpdsUnknownDateTime;
1469 }
1470 break;
1471
1472 case jpiLikeRegex:
1473 Assert(status == jpdsNonDateTime);
1475 jspIsMutableWalker(&arg, cxt);
1476 break;
1477
1478 /* literals */
1479 case jpiNull:
1480 case jpiString:
1481 case jpiNumeric:
1482 case jpiBool:
1483 break;
1484 /* accessors */
1485 case jpiKey:
1486 case jpiAnyKey:
1487 /* special items */
1488 case jpiSubscript:
1489 case jpiLast:
1490 /* item methods */
1491 case jpiType:
1492 case jpiSize:
1493 case jpiAbs:
1494 case jpiFloor:
1495 case jpiCeiling:
1496 case jpiDouble:
1497 case jpiKeyValue:
1498 case jpiBigint:
1499 case jpiBoolean:
1500 case jpiDecimal:
1501 case jpiInteger:
1502 case jpiNumber:
1503 case jpiStringFunc:
1504 status = jpdsNonDateTime;
1505 break;
1506
1507 case jpiTime:
1508 case jpiDate:
1509 case jpiTimestamp:
1510 status = jpdsDateTimeNonZoned;
1511 cxt->mutable = true;
1512 break;
1513
1514 case jpiTimeTz:
1515 case jpiTimestampTz:
1516 status = jpdsDateTimeNonZoned;
1517 cxt->mutable = true;
1518 break;
1519
1520 }
1521
1522 if (!jspGetNext(jpi, &next))
1523 break;
1524
1525 jpi = &next;
1526 }
1527
1528 return status;
1529}
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:816
static int32 next
Definition: blutils.c:219
#define INTALIGN(LEN)
Definition: c.h:762
#define PG_UINT32_MAX
Definition: c.h:544
#define Assert(condition)
Definition: c.h:812
int32_t int32
Definition: c.h:481
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:641
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
bool datetime_format_has_tz(const char *fmt_str)
Definition: formatting.c:4250
const char * str
int a
Definition: isn.c:68
int i
Definition: isn.c:72
void escape_json_with_len(StringInfo buf, const char *str, int len)
Definition: json.c:1631
bool jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
Definition: jsonpath.c:1280
static enum JsonPathDatatypeStatus jspIsMutableWalker(JsonPathItem *jpi, struct JsonPathMutableContext *cxt)
Definition: jsonpath.c:1301
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1166
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1081
static Datum jsonPathFromCstring(char *in, int len, struct Node *escontext)
Definition: jsonpath.c:173
Datum jsonpath_send(PG_FUNCTION_ARGS)
Definition: jsonpath.c:147
#define read_byte(v, b, p)
Definition: jsonpath.c:961
#define read_int32_n(v, b, p, n)
Definition: jsonpath.c:971
Datum jsonpath_out(PG_FUNCTION_ARGS)
Definition: jsonpath.c:134
static void alignStringInfoInt(StringInfo buf)
Definition: jsonpath.c:484
void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
Definition: jsonpath.c:990
bool jspGetBool(JsonPathItem *v)
Definition: jsonpath.c:1210
void jspInit(JsonPathItem *v, JsonPath *js)
Definition: jsonpath.c:980
static bool flattenJsonPathParseItem(StringInfo buf, int *result, struct Node *escontext, JsonPathParseItem *item, int nestingLevel, bool insideArraySubscript)
Definition: jsonpath.c:239
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1226
Numeric jspGetNumeric(JsonPathItem *v)
Definition: jsonpath.c:1218
bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to, int i)
Definition: jsonpath.c:1238
static void printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracketes)
Definition: jsonpath.c:521
#define read_int32(v, b, p)
Definition: jsonpath.c:966
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:843
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1099
static int operationPriority(JsonPathItemType op)
Definition: jsonpath.c:924
Datum jsonpath_recv(PG_FUNCTION_ARGS)
Definition: jsonpath.c:115
Datum jsonpath_in(PG_FUNCTION_ARGS)
Definition: jsonpath.c:98
void jspGetRightArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1188
static int32 reserveSpaceForItemPointer(StringInfo buf)
Definition: jsonpath.c:507
static char * jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
Definition: jsonpath.c:213
JsonPathDatatypeStatus
Definition: jsonpath.c:1255
@ jpdsDateTimeZoned
Definition: jsonpath.c:1258
@ jpdsNonDateTime
Definition: jsonpath.c:1256
@ jpdsDateTimeNonZoned
Definition: jsonpath.c:1259
@ jpdsUnknownDateTime
Definition: jsonpath.c:1257
#define JSP_REGEX_WSPACE
Definition: jsonpath.h:124
#define JSP_REGEX_MLINE
Definition: jsonpath.h:123
#define PG_RETURN_JSONPATH_P(p)
Definition: jsonpath.h:48
#define JSP_REGEX_ICASE
Definition: jsonpath.h:121
#define jspHasNext(jsp)
Definition: jsonpath.h:194
#define PG_GETARG_JSONPATH_P(x)
Definition: jsonpath.h:46
#define JSONPATH_VERSION
Definition: jsonpath.h:30
#define JSP_REGEX_DOTALL
Definition: jsonpath.h:122
JsonPathItemType
Definition: jsonpath.h:63
@ jpiAdd
Definition: jsonpath.h:78
@ jpiString
Definition: jsonpath.h:65
@ jpiAbs
Definition: jsonpath.h:97
@ jpiIndexArray
Definition: jsonpath.h:87
@ jpiAny
Definition: jsonpath.h:88
@ jpiDatetime
Definition: jsonpath.h:101
@ jpiBigint
Definition: jsonpath.h:107
@ jpiBool
Definition: jsonpath.h:67
@ jpiType
Definition: jsonpath.h:95
@ jpiFloor
Definition: jsonpath.h:98
@ jpiAnyArray
Definition: jsonpath.h:85
@ jpiExists
Definition: jsonpath.h:94
@ jpiSize
Definition: jsonpath.h:96
@ jpiSub
Definition: jsonpath.h:79
@ jpiSubscript
Definition: jsonpath.h:103
@ jpiNotEqual
Definition: jsonpath.h:73
@ jpiMul
Definition: jsonpath.h:80
@ jpiVariable
Definition: jsonpath.h:92
@ jpiTimeTz
Definition: jsonpath.h:115
@ jpiNot
Definition: jsonpath.h:70
@ jpiDate
Definition: jsonpath.h:109
@ jpiGreaterOrEqual
Definition: jsonpath.h:77
@ jpiPlus
Definition: jsonpath.h:83
@ jpiDouble
Definition: jsonpath.h:100
@ jpiGreater
Definition: jsonpath.h:75
@ jpiNumber
Definition: jsonpath.h:112
@ jpiAnd
Definition: jsonpath.h:68
@ jpiStartsWith
Definition: jsonpath.h:105
@ jpiOr
Definition: jsonpath.h:69
@ jpiMod
Definition: jsonpath.h:82
@ jpiTimestamp
Definition: jsonpath.h:116
@ jpiLikeRegex
Definition: jsonpath.h:106
@ jpiTimestampTz
Definition: jsonpath.h:117
@ jpiInteger
Definition: jsonpath.h:111
@ jpiRoot
Definition: jsonpath.h:91
@ jpiFilter
Definition: jsonpath.h:93
@ jpiNull
Definition: jsonpath.h:64
@ jpiLess
Definition: jsonpath.h:74
@ jpiCurrent
Definition: jsonpath.h:90
@ jpiEqual
Definition: jsonpath.h:72
@ jpiKey
Definition: jsonpath.h:89
@ jpiDiv
Definition: jsonpath.h:81
@ jpiTime
Definition: jsonpath.h:114
@ jpiLast
Definition: jsonpath.h:104
@ jpiMinus
Definition: jsonpath.h:84
@ jpiLessOrEqual
Definition: jsonpath.h:76
@ jpiCeiling
Definition: jsonpath.h:99
@ jpiIsUnknown
Definition: jsonpath.h:71
@ jpiKeyValue
Definition: jsonpath.h:102
@ jpiNumeric
Definition: jsonpath.h:66
@ jpiBoolean
Definition: jsonpath.h:108
@ jpiStringFunc
Definition: jsonpath.h:113
@ jpiDecimal
Definition: jsonpath.h:110
@ jpiAnyKey
Definition: jsonpath.h:86
#define JSONPATH_LAX
Definition: jsonpath.h:31
#define JSONPATH_HDRSZ
Definition: jsonpath.h:32
#define JSP_REGEX_QUOTE
Definition: jsonpath.h:125
JsonPathParseResult * parsejsonpath(const char *str, int len, struct Node *escontext)
void pfree(void *pointer)
Definition: mcxt.c:1521
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:53
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
void * arg
const void size_t len
#define lfirst(lc)
Definition: pg_list.h:172
#define lfirst_node(type, lc)
Definition: pg_list.h:176
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
static char * buf
Definition: pg_test_fsync.c:72
uintptr_t Datum
Definition: postgres.h:64
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
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:546
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint8(StringInfo buf, uint8 i)
Definition: pqformat.h:128
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412
void check_stack_depth(void)
Definition: stack_depth.c:95
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:337
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:281
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:260
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
StringInfoData * StringInfo
Definition: stringinfo.h:54
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:231
uint32 first
Definition: jsonpath.h:174
int32 datalen
Definition: jsonpath.h:181
struct JsonPathItem::@143::@145 array
struct JsonPathItem::@143::@147 value
int32 nelems
Definition: jsonpath.h:163
struct JsonPathItem::@143::@148 like_regex
uint32 flags
Definition: jsonpath.h:189
union JsonPathItem::@143 content
struct JsonPathItem::@143::@144 args
int32 left
Definition: jsonpath.h:153
struct JsonPathItem::@143::@145::@149 * elems
char * base
Definition: jsonpath.h:146
int32 nextPos
Definition: jsonpath.h:140
int32 arg
Definition: jsonpath.h:158
JsonPathItemType type
Definition: jsonpath.h:137
char * data
Definition: jsonpath.h:180
uint32 last
Definition: jsonpath.h:175
struct JsonPathItem::@143::@146 anybounds
int32 right
Definition: jsonpath.h:154
int32 patternlen
Definition: jsonpath.h:188
char * pattern
Definition: jsonpath.h:187
int32 expr
Definition: jsonpath.h:186
enum JsonPathDatatypeStatus current
Definition: jsonpath.c:1267
JsonPathParseItem * arg
Definition: jsonpath.h:233
union JsonPathParseItem::@150 value
struct JsonPathParseItem::@150::@152::@156 * elems
struct JsonPathParseItem::@150::@155 string
JsonPathParseItem * expr
Definition: jsonpath.h:255
JsonPathParseItem * left
Definition: jsonpath.h:228
JsonPathParseItem * right
Definition: jsonpath.h:229
struct JsonPathParseItem::@150::@151 args
JsonPathParseItem * next
Definition: jsonpath.h:220
Numeric numeric
Definition: jsonpath.h:262
JsonPathItemType type
Definition: jsonpath.h:219
uint32 patternlen
Definition: jsonpath.h:257
struct JsonPathParseItem::@150::@152 array
struct JsonPathParseItem::@150::@153 anybounds
struct JsonPathParseItem::@150::@154 like_regex
JsonPathParseItem * expr
Definition: jsonpath.h:274
char data[FLEXIBLE_ARRAY_MEMBER]
Definition: jsonpath.h:27
uint32 header
Definition: jsonpath.h:26
Definition: pg_list.h:54
Definition: nodes.h:129
Definition: value.h:64
char * sval
Definition: value.h:68
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
#define VARSIZE(PTR)
Definition: varatt.h:279
const char * type
const char * name