PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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-2026, 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);
82 struct Node *escontext,
84 int nestingLevel, bool insideArraySubscript);
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
140
141/*
142 * jsonpath type send function
143 *
144 * Just send jsonpath as a version number, then a string of text
145 */
146Datum
148{
152 int version = JSONPATH_VERSION;
153
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{
176 JsonPath *res;
178
179 if (SOFT_ERROR_OCCURRED(escontext))
180 return (Datum) 0;
181
182 if (!jsonpath)
183 ereturn(escontext, (Datum) 0,
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);
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 *
214{
216 JsonPathItem v;
217
218 if (!out)
219 {
220 out = &buf;
221 initStringInfo(out);
222 }
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
240 JsonPathParseItem *item, int nestingLevel,
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 case jpiStrReplace:
302 case jpiStrSplitPart:
303 {
304 /*
305 * First, reserve place for left/right arg's positions, then
306 * record both args and sets actual position in reserved
307 * places.
308 */
311
312 if (!item->value.args.left)
313 chld = pos;
314 else if (!flattenJsonPathParseItem(buf, &chld, escontext,
315 item->value.args.left,
316 nestingLevel + argNestingLevel,
318 return false;
319 *(int32 *) (buf->data + left) = chld - pos;
320
321 if (!item->value.args.right)
322 chld = pos;
323 else if (!flattenJsonPathParseItem(buf, &chld, escontext,
324 item->value.args.right,
325 nestingLevel + argNestingLevel,
327 return false;
328 *(int32 *) (buf->data + right) = chld - pos;
329 }
330 break;
331 case jpiLikeRegex:
332 {
333 int32 offs;
334
336 &item->value.like_regex.flags,
337 sizeof(item->value.like_regex.flags));
341 sizeof(item->value.like_regex.patternlen));
345
346 if (!flattenJsonPathParseItem(buf, &chld, escontext,
347 item->value.like_regex.expr,
348 nestingLevel,
350 return false;
351 *(int32 *) (buf->data + offs) = chld - pos;
352 }
353 break;
354 case jpiFilter:
357 case jpiIsUnknown:
358 case jpiNot:
359 case jpiPlus:
360 case jpiMinus:
361 case jpiExists:
362 case jpiDatetime:
363 case jpiTime:
364 case jpiTimeTz:
365 case jpiTimestamp:
366 case jpiTimestampTz:
367 case jpiStrLtrim:
368 case jpiStrRtrim:
369 case jpiStrBtrim:
370 {
372
373 if (!item->value.arg)
374 chld = pos;
375 else if (!flattenJsonPathParseItem(buf, &chld, escontext,
376 item->value.arg,
377 nestingLevel + argNestingLevel,
379 return false;
380 *(int32 *) (buf->data + arg) = chld - pos;
381 }
382 break;
383 case jpiNull:
384 break;
385 case jpiRoot:
386 break;
387 case jpiAnyArray:
388 case jpiAnyKey:
389 break;
390 case jpiCurrent:
391 if (nestingLevel <= 0)
392 ereturn(escontext, false,
394 errmsg("@ is not allowed in root expressions")));
395 break;
396 case jpiLast:
398 ereturn(escontext, false,
400 errmsg("LAST is allowed only in array subscripts")));
401 break;
402 case jpiIndexArray:
403 {
404 int32 nelems = item->value.array.nelems;
405 int offset;
406 int i;
407
408 appendBinaryStringInfo(buf, &nelems, sizeof(nelems));
409
410 offset = buf->len;
411
412 appendStringInfoSpaces(buf, sizeof(int32) * 2 * nelems);
413
414 for (i = 0; i < nelems; i++)
415 {
416 int32 *ppos;
417 int32 topos;
419
420 if (!flattenJsonPathParseItem(buf, &frompos, escontext,
421 item->value.array.elems[i].from,
422 nestingLevel, true))
423 return false;
424 frompos -= pos;
425
426 if (item->value.array.elems[i].to)
427 {
428 if (!flattenJsonPathParseItem(buf, &topos, escontext,
429 item->value.array.elems[i].to,
430 nestingLevel, true))
431 return false;
432 topos -= pos;
433 }
434 else
435 topos = 0;
436
437 ppos = (int32 *) &buf->data[offset + i * 2 * sizeof(int32)];
438
439 ppos[0] = frompos;
440 ppos[1] = topos;
441 }
442 }
443 break;
444 case jpiAny:
446 &item->value.anybounds.first,
447 sizeof(item->value.anybounds.first));
449 &item->value.anybounds.last,
450 sizeof(item->value.anybounds.last));
451 break;
452 case jpiType:
453 case jpiSize:
454 case jpiAbs:
455 case jpiFloor:
456 case jpiCeiling:
457 case jpiDouble:
458 case jpiKeyValue:
459 case jpiBigint:
460 case jpiBoolean:
461 case jpiDate:
462 case jpiInteger:
463 case jpiNumber:
464 case jpiStringFunc:
465 case jpiStrLower:
466 case jpiStrUpper:
467 case jpiStrInitcap:
468 break;
469 default:
470 elog(ERROR, "unrecognized jsonpath item type: %d", item->type);
471 }
472
473 if (item->next)
474 {
475 if (!flattenJsonPathParseItem(buf, &chld, escontext,
476 item->next, nestingLevel,
478 return false;
479 chld -= pos;
480 *(int32 *) (buf->data + next) = chld;
481 }
482
483 if (result)
484 *result = pos;
485 return true;
486}
487
488/*
489 * Align StringInfo to int by adding zero padding bytes
490 */
491static void
493{
494 switch (INTALIGN(buf->len) - buf->len)
495 {
496 case 3:
499 case 2:
502 case 1:
505 default:
506 break;
507 }
508}
509
510/*
511 * Reserve space for int32 JsonPathItem pointer. Now zero pointer is written,
512 * actual value will be recorded at '(int32 *) &buf->data[pos]' later.
513 */
514static int32
516{
517 int32 pos = buf->len;
518 int32 ptr = 0;
519
520 appendBinaryStringInfo(buf, &ptr, sizeof(ptr));
521
522 return pos;
523}
524
525/*
526 * Prints text representation of given jsonpath item and all its children.
527 */
528static void
530 bool printBracketes)
531{
532 JsonPathItem elem;
533 int i;
534 int32 len;
535 char *str;
536
539
540 switch (v->type)
541 {
542 case jpiNull:
544 break;
545 case jpiString:
546 str = jspGetString(v, &len);
548 break;
549 case jpiNumeric:
550 if (jspHasNext(v))
555 if (jspHasNext(v))
557 break;
558 case jpiBool:
559 if (jspGetBool(v))
561 else
562 appendStringInfoString(buf, "false");
563 break;
564 case jpiAnd:
565 case jpiOr:
566 case jpiEqual:
567 case jpiNotEqual:
568 case jpiLess:
569 case jpiGreater:
570 case jpiLessOrEqual:
572 case jpiAdd:
573 case jpiSub:
574 case jpiMul:
575 case jpiDiv:
576 case jpiMod:
577 case jpiStartsWith:
578 if (printBracketes)
580 jspGetLeftArg(v, &elem);
581 printJsonPathItem(buf, &elem, false,
582 operationPriority(elem.type) <=
587 jspGetRightArg(v, &elem);
588 printJsonPathItem(buf, &elem, false,
589 operationPriority(elem.type) <=
591 if (printBracketes)
593 break;
594 case jpiNot:
596 jspGetArg(v, &elem);
597 printJsonPathItem(buf, &elem, false, false);
599 break;
600 case jpiIsUnknown:
602 jspGetArg(v, &elem);
603 printJsonPathItem(buf, &elem, false, false);
604 appendStringInfoString(buf, ") is unknown");
605 break;
606 case jpiPlus:
607 case jpiMinus:
608 if (printBracketes)
610 appendStringInfoChar(buf, v->type == jpiPlus ? '+' : '-');
611 jspGetArg(v, &elem);
612 printJsonPathItem(buf, &elem, false,
613 operationPriority(elem.type) <=
615 if (printBracketes)
617 break;
618 case jpiAnyArray:
620 break;
621 case jpiAnyKey:
622 if (inKey)
625 break;
626 case jpiIndexArray:
628 for (i = 0; i < v->content.array.nelems; i++)
629 {
630 JsonPathItem from;
631 JsonPathItem to;
632 bool range = jspGetArraySubscript(v, &from, &to, i);
633
634 if (i)
636
637 printJsonPathItem(buf, &from, false, false);
638
639 if (range)
640 {
642 printJsonPathItem(buf, &to, false, false);
643 }
644 }
646 break;
647 case jpiAny:
648 if (inKey)
650
651 if (v->content.anybounds.first == 0 &&
654 else if (v->content.anybounds.first == v->content.anybounds.last)
655 {
657 appendStringInfoString(buf, "**{last}");
658 else
659 appendStringInfo(buf, "**{%u}",
661 }
662 else if (v->content.anybounds.first == PG_UINT32_MAX)
663 appendStringInfo(buf, "**{last to %u}",
665 else if (v->content.anybounds.last == PG_UINT32_MAX)
666 appendStringInfo(buf, "**{%u to last}",
668 else
669 appendStringInfo(buf, "**{%u to %u}",
672 break;
673 case jpiKey:
674 if (inKey)
676 str = jspGetString(v, &len);
678 break;
679 case jpiCurrent:
680 Assert(!inKey);
682 break;
683 case jpiRoot:
684 Assert(!inKey);
686 break;
687 case jpiVariable:
689 str = jspGetString(v, &len);
691 break;
692 case jpiFilter:
694 jspGetArg(v, &elem);
695 printJsonPathItem(buf, &elem, false, false);
697 break;
698 case jpiExists:
699 appendStringInfoString(buf, "exists (");
700 jspGetArg(v, &elem);
701 printJsonPathItem(buf, &elem, false, false);
703 break;
704 case jpiType:
705 appendStringInfoString(buf, ".type()");
706 break;
707 case jpiSize:
708 appendStringInfoString(buf, ".size()");
709 break;
710 case jpiAbs:
711 appendStringInfoString(buf, ".abs()");
712 break;
713 case jpiFloor:
714 appendStringInfoString(buf, ".floor()");
715 break;
716 case jpiCeiling:
717 appendStringInfoString(buf, ".ceiling()");
718 break;
719 case jpiDouble:
720 appendStringInfoString(buf, ".double()");
721 break;
722 case jpiDatetime:
723 appendStringInfoString(buf, ".datetime(");
724 if (v->content.arg)
725 {
726 jspGetArg(v, &elem);
727 printJsonPathItem(buf, &elem, false, false);
728 }
730 break;
731 case jpiKeyValue:
732 appendStringInfoString(buf, ".keyvalue()");
733 break;
734 case jpiLast:
736 break;
737 case jpiLikeRegex:
738 if (printBracketes)
740
742 printJsonPathItem(buf, &elem, false,
743 operationPriority(elem.type) <=
745
746 appendStringInfoString(buf, " like_regex ");
747
751
752 if (v->content.like_regex.flags)
753 {
754 appendStringInfoString(buf, " flag \"");
755
766
768 }
769
770 if (printBracketes)
772 break;
773 case jpiBigint:
774 appendStringInfoString(buf, ".bigint()");
775 break;
776 case jpiBoolean:
777 appendStringInfoString(buf, ".boolean()");
778 break;
779 case jpiDate:
780 appendStringInfoString(buf, ".date()");
781 break;
782 case jpiDecimal:
783 appendStringInfoString(buf, ".decimal(");
784 if (v->content.args.left)
785 {
786 jspGetLeftArg(v, &elem);
787 printJsonPathItem(buf, &elem, false, false);
788 }
789 if (v->content.args.right)
790 {
792 jspGetRightArg(v, &elem);
793 printJsonPathItem(buf, &elem, false, false);
794 }
796 break;
797 case jpiInteger:
798 appendStringInfoString(buf, ".integer()");
799 break;
800 case jpiNumber:
801 appendStringInfoString(buf, ".number()");
802 break;
803 case jpiStringFunc:
804 appendStringInfoString(buf, ".string()");
805 break;
806 case jpiTime:
807 appendStringInfoString(buf, ".time(");
808 if (v->content.arg)
809 {
810 jspGetArg(v, &elem);
811 printJsonPathItem(buf, &elem, false, false);
812 }
814 break;
815 case jpiTimeTz:
816 appendStringInfoString(buf, ".time_tz(");
817 if (v->content.arg)
818 {
819 jspGetArg(v, &elem);
820 printJsonPathItem(buf, &elem, false, false);
821 }
823 break;
824 case jpiTimestamp:
825 appendStringInfoString(buf, ".timestamp(");
826 if (v->content.arg)
827 {
828 jspGetArg(v, &elem);
829 printJsonPathItem(buf, &elem, false, false);
830 }
832 break;
833 case jpiTimestampTz:
834 appendStringInfoString(buf, ".timestamp_tz(");
835 if (v->content.arg)
836 {
837 jspGetArg(v, &elem);
838 printJsonPathItem(buf, &elem, false, false);
839 }
841 break;
842 case jpiStrReplace:
843 appendStringInfoString(buf, ".replace(");
844 jspGetLeftArg(v, &elem);
845 printJsonPathItem(buf, &elem, false, false);
847 jspGetRightArg(v, &elem);
848 printJsonPathItem(buf, &elem, false, false);
850 break;
851 case jpiStrLower:
852 appendStringInfoString(buf, ".lower()");
853 break;
854 case jpiStrUpper:
855 appendStringInfoString(buf, ".upper()");
856 break;
857 case jpiStrSplitPart:
858 appendStringInfoString(buf, ".split_part(");
859 jspGetLeftArg(v, &elem);
860 printJsonPathItem(buf, &elem, false, false);
862 jspGetRightArg(v, &elem);
863 printJsonPathItem(buf, &elem, false, false);
865 break;
866 case jpiStrLtrim:
867 appendStringInfoString(buf, ".ltrim(");
868 if (v->content.arg)
869 {
870 jspGetArg(v, &elem);
871 printJsonPathItem(buf, &elem, false, false);
872 }
874 break;
875 case jpiStrRtrim:
876 appendStringInfoString(buf, ".rtrim(");
877 if (v->content.arg)
878 {
879 jspGetArg(v, &elem);
880 printJsonPathItem(buf, &elem, false, false);
881 }
883 break;
884 case jpiStrBtrim:
885 appendStringInfoString(buf, ".btrim(");
886 if (v->content.arg)
887 {
888 jspGetArg(v, &elem);
889 printJsonPathItem(buf, &elem, false, false);
890 }
892 break;
893 case jpiStrInitcap:
894 appendStringInfoString(buf, ".initcap()");
895 break;
896 default:
897 elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
898 }
899
900 if (jspGetNext(v, &elem))
901 printJsonPathItem(buf, &elem, true, true);
902}
903
904const char *
906{
907 switch (type)
908 {
909 case jpiAnd:
910 return "&&";
911 case jpiOr:
912 return "||";
913 case jpiEqual:
914 return "==";
915 case jpiNotEqual:
916 return "!=";
917 case jpiLess:
918 return "<";
919 case jpiGreater:
920 return ">";
921 case jpiLessOrEqual:
922 return "<=";
924 return ">=";
925 case jpiAdd:
926 case jpiPlus:
927 return "+";
928 case jpiSub:
929 case jpiMinus:
930 return "-";
931 case jpiMul:
932 return "*";
933 case jpiDiv:
934 return "/";
935 case jpiMod:
936 return "%";
937 case jpiType:
938 return "type";
939 case jpiSize:
940 return "size";
941 case jpiAbs:
942 return "abs";
943 case jpiFloor:
944 return "floor";
945 case jpiCeiling:
946 return "ceiling";
947 case jpiDouble:
948 return "double";
949 case jpiDatetime:
950 return "datetime";
951 case jpiKeyValue:
952 return "keyvalue";
953 case jpiStartsWith:
954 return "starts with";
955 case jpiLikeRegex:
956 return "like_regex";
957 case jpiBigint:
958 return "bigint";
959 case jpiBoolean:
960 return "boolean";
961 case jpiDate:
962 return "date";
963 case jpiDecimal:
964 return "decimal";
965 case jpiInteger:
966 return "integer";
967 case jpiNumber:
968 return "number";
969 case jpiStringFunc:
970 return "string";
971 case jpiTime:
972 return "time";
973 case jpiTimeTz:
974 return "time_tz";
975 case jpiTimestamp:
976 return "timestamp";
977 case jpiTimestampTz:
978 return "timestamp_tz";
979 case jpiStrReplace:
980 return "replace";
981 case jpiStrLower:
982 return "lower";
983 case jpiStrUpper:
984 return "upper";
985 case jpiStrLtrim:
986 return "ltrim";
987 case jpiStrRtrim:
988 return "rtrim";
989 case jpiStrBtrim:
990 return "btrim";
991 case jpiStrInitcap:
992 return "initcap";
993 case jpiStrSplitPart:
994 return "split_part";
995 default:
996 elog(ERROR, "unrecognized jsonpath item type: %d", type);
997 return NULL;
998 }
999}
1000
1001static int
1003{
1004 switch (op)
1005 {
1006 case jpiOr:
1007 return 0;
1008 case jpiAnd:
1009 return 1;
1010 case jpiEqual:
1011 case jpiNotEqual:
1012 case jpiLess:
1013 case jpiGreater:
1014 case jpiLessOrEqual:
1015 case jpiGreaterOrEqual:
1016 case jpiStartsWith:
1017 return 2;
1018 case jpiAdd:
1019 case jpiSub:
1020 return 3;
1021 case jpiMul:
1022 case jpiDiv:
1023 case jpiMod:
1024 return 4;
1025 case jpiPlus:
1026 case jpiMinus:
1027 return 5;
1028 default:
1029 return 6;
1030 }
1031}
1032
1033/******************* Support functions for JsonPath *************************/
1034
1035/*
1036 * Support macros to read stored values
1037 */
1038
1039#define read_byte(v, b, p) do { \
1040 (v) = *(uint8*)((b) + (p)); \
1041 (p) += 1; \
1042} while(0) \
1043
1044#define read_int32(v, b, p) do { \
1045 (v) = *(uint32*)((b) + (p)); \
1046 (p) += sizeof(int32); \
1047} while(0) \
1048
1049#define read_int32_n(v, b, p, n) do { \
1050 (v) = (void *)((b) + (p)); \
1051 (p) += sizeof(int32) * (n); \
1052} while(0) \
1053
1054/*
1055 * Read root node and fill root node representation
1056 */
1057void
1059{
1061 jspInitByBuffer(v, js->data, 0);
1062}
1063
1064/*
1065 * Read node from buffer and fill its representation
1066 */
1067void
1069{
1070 v->base = base + pos;
1071
1072 read_byte(v->type, base, pos);
1073 pos = INTALIGN((uintptr_t) (base + pos)) - (uintptr_t) base;
1074 read_int32(v->nextPos, base, pos);
1075
1076 switch (v->type)
1077 {
1078 case jpiNull:
1079 case jpiRoot:
1080 case jpiCurrent:
1081 case jpiAnyArray:
1082 case jpiAnyKey:
1083 case jpiType:
1084 case jpiSize:
1085 case jpiAbs:
1086 case jpiFloor:
1087 case jpiCeiling:
1088 case jpiDouble:
1089 case jpiKeyValue:
1090 case jpiLast:
1091 case jpiBigint:
1092 case jpiBoolean:
1093 case jpiDate:
1094 case jpiInteger:
1095 case jpiNumber:
1096 case jpiStringFunc:
1097 case jpiStrLower:
1098 case jpiStrUpper:
1099 case jpiStrInitcap:
1100 break;
1101 case jpiString:
1102 case jpiKey:
1103 case jpiVariable:
1104 read_int32(v->content.value.datalen, base, pos);
1106 case jpiNumeric:
1107 case jpiBool:
1108 v->content.value.data = base + pos;
1109 break;
1110 case jpiAnd:
1111 case jpiOr:
1112 case jpiEqual:
1113 case jpiNotEqual:
1114 case jpiLess:
1115 case jpiGreater:
1116 case jpiLessOrEqual:
1117 case jpiGreaterOrEqual:
1118 case jpiAdd:
1119 case jpiSub:
1120 case jpiMul:
1121 case jpiDiv:
1122 case jpiMod:
1123 case jpiStartsWith:
1124 case jpiDecimal:
1125 case jpiStrReplace:
1126 case jpiStrSplitPart:
1127 read_int32(v->content.args.left, base, pos);
1128 read_int32(v->content.args.right, base, pos);
1129 break;
1130 case jpiNot:
1131 case jpiIsUnknown:
1132 case jpiExists:
1133 case jpiPlus:
1134 case jpiMinus:
1135 case jpiFilter:
1136 case jpiDatetime:
1137 case jpiTime:
1138 case jpiTimeTz:
1139 case jpiTimestamp:
1140 case jpiTimestampTz:
1141 case jpiStrLtrim:
1142 case jpiStrRtrim:
1143 case jpiStrBtrim:
1144 read_int32(v->content.arg, base, pos);
1145 break;
1146 case jpiIndexArray:
1147 read_int32(v->content.array.nelems, base, pos);
1148 read_int32_n(v->content.array.elems, base, pos,
1149 v->content.array.nelems * 2);
1150 break;
1151 case jpiAny:
1152 read_int32(v->content.anybounds.first, base, pos);
1153 read_int32(v->content.anybounds.last, base, pos);
1154 break;
1155 case jpiLikeRegex:
1156 read_int32(v->content.like_regex.flags, base, pos);
1157 read_int32(v->content.like_regex.expr, base, pos);
1158 read_int32(v->content.like_regex.patternlen, base, pos);
1159 v->content.like_regex.pattern = base + pos;
1160 break;
1161 default:
1162 elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
1163 }
1164}
1165
1166void
1168{
1169 Assert(v->type == jpiNot ||
1170 v->type == jpiIsUnknown ||
1171 v->type == jpiPlus ||
1172 v->type == jpiMinus ||
1173 v->type == jpiFilter ||
1174 v->type == jpiExists ||
1175 v->type == jpiDatetime ||
1176 v->type == jpiTime ||
1177 v->type == jpiTimeTz ||
1178 v->type == jpiTimestamp ||
1179 v->type == jpiTimestampTz ||
1180 v->type == jpiStrLtrim ||
1181 v->type == jpiStrRtrim ||
1182 v->type == jpiStrBtrim);
1183
1184 jspInitByBuffer(a, v->base, v->content.arg);
1185}
1186
1187bool
1189{
1190 if (jspHasNext(v))
1191 {
1192 Assert(v->type == jpiNull ||
1193 v->type == jpiString ||
1194 v->type == jpiNumeric ||
1195 v->type == jpiBool ||
1196 v->type == jpiAnd ||
1197 v->type == jpiOr ||
1198 v->type == jpiNot ||
1199 v->type == jpiIsUnknown ||
1200 v->type == jpiEqual ||
1201 v->type == jpiNotEqual ||
1202 v->type == jpiLess ||
1203 v->type == jpiGreater ||
1204 v->type == jpiLessOrEqual ||
1205 v->type == jpiGreaterOrEqual ||
1206 v->type == jpiAdd ||
1207 v->type == jpiSub ||
1208 v->type == jpiMul ||
1209 v->type == jpiDiv ||
1210 v->type == jpiMod ||
1211 v->type == jpiPlus ||
1212 v->type == jpiMinus ||
1213 v->type == jpiAnyArray ||
1214 v->type == jpiAnyKey ||
1215 v->type == jpiIndexArray ||
1216 v->type == jpiAny ||
1217 v->type == jpiKey ||
1218 v->type == jpiCurrent ||
1219 v->type == jpiRoot ||
1220 v->type == jpiVariable ||
1221 v->type == jpiFilter ||
1222 v->type == jpiExists ||
1223 v->type == jpiType ||
1224 v->type == jpiSize ||
1225 v->type == jpiAbs ||
1226 v->type == jpiFloor ||
1227 v->type == jpiCeiling ||
1228 v->type == jpiDouble ||
1229 v->type == jpiDatetime ||
1230 v->type == jpiKeyValue ||
1231 v->type == jpiLast ||
1232 v->type == jpiStartsWith ||
1233 v->type == jpiLikeRegex ||
1234 v->type == jpiBigint ||
1235 v->type == jpiBoolean ||
1236 v->type == jpiDate ||
1237 v->type == jpiDecimal ||
1238 v->type == jpiInteger ||
1239 v->type == jpiNumber ||
1240 v->type == jpiStringFunc ||
1241 v->type == jpiTime ||
1242 v->type == jpiTimeTz ||
1243 v->type == jpiTimestamp ||
1244 v->type == jpiTimestampTz ||
1245 v->type == jpiStrReplace ||
1246 v->type == jpiStrLower ||
1247 v->type == jpiStrUpper ||
1248 v->type == jpiStrLtrim ||
1249 v->type == jpiStrRtrim ||
1250 v->type == jpiStrBtrim ||
1251 v->type == jpiStrInitcap ||
1252 v->type == jpiStrSplitPart);
1253
1254 if (a)
1255 jspInitByBuffer(a, v->base, v->nextPos);
1256 return true;
1257 }
1258
1259 return false;
1260}
1261
1262void
1264{
1265 Assert(v->type == jpiAnd ||
1266 v->type == jpiOr ||
1267 v->type == jpiEqual ||
1268 v->type == jpiNotEqual ||
1269 v->type == jpiLess ||
1270 v->type == jpiGreater ||
1271 v->type == jpiLessOrEqual ||
1272 v->type == jpiGreaterOrEqual ||
1273 v->type == jpiAdd ||
1274 v->type == jpiSub ||
1275 v->type == jpiMul ||
1276 v->type == jpiDiv ||
1277 v->type == jpiMod ||
1278 v->type == jpiStartsWith ||
1279 v->type == jpiDecimal ||
1280 v->type == jpiStrReplace ||
1281 v->type == jpiStrSplitPart);
1282
1284}
1285
1286void
1288{
1289 Assert(v->type == jpiAnd ||
1290 v->type == jpiOr ||
1291 v->type == jpiEqual ||
1292 v->type == jpiNotEqual ||
1293 v->type == jpiLess ||
1294 v->type == jpiGreater ||
1295 v->type == jpiLessOrEqual ||
1296 v->type == jpiGreaterOrEqual ||
1297 v->type == jpiAdd ||
1298 v->type == jpiSub ||
1299 v->type == jpiMul ||
1300 v->type == jpiDiv ||
1301 v->type == jpiMod ||
1302 v->type == jpiStartsWith ||
1303 v->type == jpiDecimal ||
1304 v->type == jpiStrReplace ||
1305 v->type == jpiStrSplitPart);
1306
1308}
1309
1310bool
1312{
1313 Assert(v->type == jpiBool);
1314
1315 return (bool) *v->content.value.data;
1316}
1317
1318Numeric
1320{
1321 Assert(v->type == jpiNumeric);
1322
1323 return (Numeric) v->content.value.data;
1324}
1325
1326char *
1328{
1329 Assert(v->type == jpiKey ||
1330 v->type == jpiString ||
1331 v->type == jpiVariable);
1332
1333 if (len)
1334 *len = v->content.value.datalen;
1335 return v->content.value.data;
1336}
1337
1338bool
1340 int i)
1341{
1342 Assert(v->type == jpiIndexArray);
1343
1344 jspInitByBuffer(from, v->base, v->content.array.elems[i].from);
1345
1346 if (!v->content.array.elems[i].to)
1347 return false;
1348
1349 jspInitByBuffer(to, v->base, v->content.array.elems[i].to);
1350
1351 return true;
1352}
1353
1354/* SQL/JSON datatype status: */
1356{
1357 jpdsNonDateTime, /* null, bool, numeric, string, array, object */
1358 jpdsUnknownDateTime, /* unknown datetime type */
1359 jpdsDateTimeZoned, /* timetz, timestamptz */
1360 jpdsDateTimeNonZoned, /* time, timestamp, date */
1361};
1362
1363/* Context for jspIsMutableWalker() */
1365{
1366 List *varnames; /* list of variable names */
1367 List *varexprs; /* list of variable expressions */
1368 enum JsonPathDatatypeStatus current; /* status of @ item */
1369 bool lax; /* jsonpath is lax or strict */
1370 bool mutable; /* resulting mutability status */
1371};
1372
1374 struct JsonPathMutableContext *cxt);
1375
1376/*
1377 * Function to check whether jsonpath expression is mutable to be used in the
1378 * planner function contain_mutable_functions().
1379 */
1380bool
1381jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
1382{
1383 struct JsonPathMutableContext cxt;
1385
1386 cxt.varnames = varnames;
1387 cxt.varexprs = varexprs;
1389 cxt.lax = (path->header & JSONPATH_LAX) != 0;
1390 cxt.mutable = false;
1391
1392 jspInit(&jpi, path);
1393 (void) jspIsMutableWalker(&jpi, &cxt);
1394
1395 return cxt.mutable;
1396}
1397
1398/*
1399 * Recursive walker for jspIsMutable()
1400 */
1401static enum JsonPathDatatypeStatus
1403{
1406
1407 while (!cxt->mutable)
1408 {
1412
1413 switch (jpi->type)
1414 {
1415 case jpiRoot:
1416 Assert(status == jpdsNonDateTime);
1417 break;
1418
1419 case jpiCurrent:
1420 Assert(status == jpdsNonDateTime);
1421 status = cxt->current;
1422 break;
1423
1424 case jpiFilter:
1425 {
1427
1428 cxt->current = status;
1429 jspGetArg(jpi, &arg);
1430 jspIsMutableWalker(&arg, cxt);
1431
1432 cxt->current = prevStatus;
1433 break;
1434 }
1435
1436 case jpiVariable:
1437 {
1438 int32 len;
1439 const char *name = jspGetString(jpi, &len);
1440 ListCell *lc1;
1441 ListCell *lc2;
1442
1443 Assert(status == jpdsNonDateTime);
1444
1445 forboth(lc1, cxt->varnames, lc2, cxt->varexprs)
1446 {
1447 String *varname = lfirst_node(String, lc1);
1448 Node *varexpr = lfirst(lc2);
1449
1450 if (strncmp(varname->sval, name, len))
1451 continue;
1452
1453 switch (exprType(varexpr))
1454 {
1455 case DATEOID:
1456 case TIMEOID:
1457 case TIMESTAMPOID:
1458 status = jpdsDateTimeNonZoned;
1459 break;
1460
1461 case TIMETZOID:
1462 case TIMESTAMPTZOID:
1463 status = jpdsDateTimeZoned;
1464 break;
1465
1466 default:
1467 status = jpdsNonDateTime;
1468 break;
1469 }
1470
1471 break;
1472 }
1473 break;
1474 }
1475
1476 case jpiEqual:
1477 case jpiNotEqual:
1478 case jpiLess:
1479 case jpiGreater:
1480 case jpiLessOrEqual:
1481 case jpiGreaterOrEqual:
1482 Assert(status == jpdsNonDateTime);
1485
1488
1489 /*
1490 * Comparison of datetime type with different timezone status
1491 * is mutable.
1492 */
1493 if (leftStatus != jpdsNonDateTime &&
1498 cxt->mutable = true;
1499 break;
1500
1501 case jpiNot:
1502 case jpiIsUnknown:
1503 case jpiExists:
1504 case jpiPlus:
1505 case jpiMinus:
1506 Assert(status == jpdsNonDateTime);
1507 jspGetArg(jpi, &arg);
1508 jspIsMutableWalker(&arg, cxt);
1509 break;
1510
1511 case jpiAnd:
1512 case jpiOr:
1513 case jpiAdd:
1514 case jpiSub:
1515 case jpiMul:
1516 case jpiDiv:
1517 case jpiMod:
1518 case jpiStartsWith:
1519 Assert(status == jpdsNonDateTime);
1521 jspIsMutableWalker(&arg, cxt);
1523 jspIsMutableWalker(&arg, cxt);
1524 break;
1525
1526 case jpiIndexArray:
1527 for (int i = 0; i < jpi->content.array.nelems; i++)
1528 {
1529 JsonPathItem from;
1530 JsonPathItem to;
1531
1532 if (jspGetArraySubscript(jpi, &from, &to, i))
1533 jspIsMutableWalker(&to, cxt);
1534
1535 jspIsMutableWalker(&from, cxt);
1536 }
1538
1539 case jpiAnyArray:
1540 if (!cxt->lax)
1541 status = jpdsNonDateTime;
1542 break;
1543
1544 case jpiAny:
1545 if (jpi->content.anybounds.first > 0)
1546 status = jpdsNonDateTime;
1547 break;
1548
1549 case jpiDatetime:
1550 if (jpi->content.arg)
1551 {
1552 char *template;
1553
1554 jspGetArg(jpi, &arg);
1555 if (arg.type != jpiString)
1556 {
1557 status = jpdsNonDateTime;
1558 break; /* there will be runtime error */
1559 }
1560
1561 template = jspGetString(&arg, NULL);
1562 if (datetime_format_has_tz(template))
1563 status = jpdsDateTimeZoned;
1564 else
1565 status = jpdsDateTimeNonZoned;
1566 }
1567 else
1568 {
1569 status = jpdsUnknownDateTime;
1570 }
1571 break;
1572
1573 case jpiLikeRegex:
1574 Assert(status == jpdsNonDateTime);
1575 jspInitByBuffer(&arg, jpi->base, jpi->content.like_regex.expr);
1576 jspIsMutableWalker(&arg, cxt);
1577 break;
1578
1579 /* literals */
1580 case jpiNull:
1581 case jpiString:
1582 case jpiNumeric:
1583 case jpiBool:
1584 break;
1585 /* accessors */
1586 case jpiKey:
1587 case jpiAnyKey:
1588 /* special items */
1589 case jpiSubscript:
1590 case jpiLast:
1591 /* item methods */
1592 case jpiType:
1593 case jpiSize:
1594 case jpiAbs:
1595 case jpiFloor:
1596 case jpiCeiling:
1597 case jpiDouble:
1598 case jpiKeyValue:
1599 case jpiBigint:
1600 case jpiBoolean:
1601 case jpiDecimal:
1602 case jpiInteger:
1603 case jpiNumber:
1604 case jpiStringFunc:
1605 case jpiStrReplace:
1606 case jpiStrLower:
1607 case jpiStrUpper:
1608 case jpiStrLtrim:
1609 case jpiStrRtrim:
1610 case jpiStrBtrim:
1611 case jpiStrInitcap:
1612 case jpiStrSplitPart:
1613 status = jpdsNonDateTime;
1614 break;
1615
1616 case jpiTime:
1617 case jpiDate:
1618 case jpiTimestamp:
1619 status = jpdsDateTimeNonZoned;
1620 cxt->mutable = true;
1621 break;
1622
1623 case jpiTimeTz:
1624 case jpiTimestampTz:
1625 status = jpdsDateTimeNonZoned;
1626 cxt->mutable = true;
1627 break;
1628
1629 }
1630
1631 if (!jspGetNext(jpi, &next))
1632 break;
1633
1634 jpi = &next;
1635 }
1636
1637 return status;
1638}
Datum numeric_out(PG_FUNCTION_ARGS)
Definition numeric.c:799
static int32 next
Definition blutils.c:225
#define INTALIGN(LEN)
Definition c.h:893
#define PG_UINT32_MAX
Definition c.h:674
#define Assert(condition)
Definition c.h:943
int32_t int32
Definition c.h:620
#define pg_fallthrough
Definition c.h:161
uint32 result
Datum arg
Definition elog.c:1322
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereturn(context, dummy_value,...)
Definition elog.h:280
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define PG_RETURN_BYTEA_P(x)
Definition fmgr.h:373
#define PG_GETARG_POINTER(n)
Definition fmgr.h:277
#define PG_RETURN_CSTRING(x)
Definition fmgr.h:364
#define DirectFunctionCall1(func, arg1)
Definition fmgr.h:684
#define PG_GETARG_CSTRING(n)
Definition fmgr.h:278
#define PG_FUNCTION_ARGS
Definition fmgr.h:193
bool datetime_format_has_tz(const char *fmt_str)
const char * str
int a
Definition isn.c:73
int i
Definition isn.c:77
void escape_json_with_len(StringInfo buf, const char *str, int len)
Definition json.c:1601
bool jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
Definition jsonpath.c:1381
static enum JsonPathDatatypeStatus jspIsMutableWalker(JsonPathItem *jpi, struct JsonPathMutableContext *cxt)
Definition jsonpath.c:1402
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition jsonpath.c:1263
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition jsonpath.c:1167
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:1039
#define read_int32_n(v, b, p, n)
Definition jsonpath.c:1049
Datum jsonpath_out(PG_FUNCTION_ARGS)
Definition jsonpath.c:134
static void alignStringInfoInt(StringInfo buf)
Definition jsonpath.c:492
void jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
Definition jsonpath.c:1068
bool jspGetBool(JsonPathItem *v)
Definition jsonpath.c:1311
void jspInit(JsonPathItem *v, JsonPath *js)
Definition jsonpath.c:1058
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:1327
Numeric jspGetNumeric(JsonPathItem *v)
Definition jsonpath.c:1319
bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to, int i)
Definition jsonpath.c:1339
static void printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracketes)
Definition jsonpath.c:529
#define read_int32(v, b, p)
Definition jsonpath.c:1044
const char * jspOperationName(JsonPathItemType type)
Definition jsonpath.c:905
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition jsonpath.c:1188
static int operationPriority(JsonPathItemType op)
Definition jsonpath.c:1002
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:1287
static int32 reserveSpaceForItemPointer(StringInfo buf)
Definition jsonpath.c:515
static char * jsonPathToCstring(StringInfo out, JsonPath *in, int estimated_len)
Definition jsonpath.c:213
JsonPathDatatypeStatus
Definition jsonpath.c:1356
@ jpdsDateTimeZoned
Definition jsonpath.c:1359
@ jpdsNonDateTime
Definition jsonpath.c:1357
@ jpdsDateTimeNonZoned
Definition jsonpath.c:1360
@ jpdsUnknownDateTime
Definition jsonpath.c:1358
#define JSP_REGEX_WSPACE
Definition jsonpath.h:132
#define JSP_REGEX_MLINE
Definition jsonpath.h:131
#define PG_RETURN_JSONPATH_P(p)
Definition jsonpath.h:48
#define JSP_REGEX_ICASE
Definition jsonpath.h:129
#define jspHasNext(jsp)
Definition jsonpath.h:202
#define PG_GETARG_JSONPATH_P(x)
Definition jsonpath.h:46
#define JSONPATH_VERSION
Definition jsonpath.h:30
#define JSP_REGEX_DOTALL
Definition jsonpath.h:130
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
@ jpiStrRtrim
Definition jsonpath.h:122
@ jpiBigint
Definition jsonpath.h:107
@ jpiBool
Definition jsonpath.h:67
@ jpiType
Definition jsonpath.h:95
@ jpiStrUpper
Definition jsonpath.h:120
@ jpiFloor
Definition jsonpath.h:98
@ jpiStrBtrim
Definition jsonpath.h:123
@ jpiAnyArray
Definition jsonpath.h:85
@ jpiExists
Definition jsonpath.h:94
@ jpiSize
Definition jsonpath.h:96
@ jpiStrReplace
Definition jsonpath.h:118
@ 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
@ jpiStrInitcap
Definition jsonpath.h:124
@ jpiDouble
Definition jsonpath.h:100
@ jpiGreater
Definition jsonpath.h:75
@ jpiNumber
Definition jsonpath.h:112
@ jpiStrLtrim
Definition jsonpath.h:121
@ 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
@ jpiStrSplitPart
Definition jsonpath.h:125
@ 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
@ jpiStrLower
Definition jsonpath.h:119
@ 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:133
JsonPathParseResult * parsejsonpath(const char *str, int len, struct Node *escontext)
void pfree(void *pointer)
Definition mcxt.c:1616
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:125
#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:76
static char * errmsg
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:550
static char buf[DEFAULT_XLOG_SEG_SIZE]
static char * DatumGetCString(Datum X)
Definition postgres.h:355
uint64_t Datum
Definition postgres.h:70
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_sendint8(StringInfo buf, uint8 i)
Definition pqformat.h:128
static int fb(int x)
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
void check_stack_depth(void)
Definition stack_depth.c:95
struct StringInfoData * StringInfo
Definition string.h:15
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
#define appendStringInfoCharMacro(str, ch)
Definition stringinfo.h:231
struct JsonPathItem::@152::@155 anybounds
uint32 first
Definition jsonpath.h:182
int32 datalen
Definition jsonpath.h:189
int32 nelems
Definition jsonpath.h:171
uint32 flags
Definition jsonpath.h:197
union JsonPathItem::@152 content
char * base
Definition jsonpath.h:154
struct JsonPathItem::@152::@157 like_regex
int32 nextPos
Definition jsonpath.h:148
JsonPathItemType type
Definition jsonpath.h:145
struct JsonPathItem::@152::@154::@158 * elems
char * data
Definition jsonpath.h:188
uint32 last
Definition jsonpath.h:183
struct JsonPathItem::@152::@153 args
struct JsonPathItem::@152::@154 array
int32 right
Definition jsonpath.h:162
int32 patternlen
Definition jsonpath.h:196
char * pattern
Definition jsonpath.h:195
struct JsonPathItem::@152::@156 value
enum JsonPathDatatypeStatus current
Definition jsonpath.c:1368
struct JsonPathParseItem::@159::@164 string
JsonPathParseItem * arg
Definition jsonpath.h:241
JsonPathParseItem * expr
Definition jsonpath.h:263
JsonPathParseItem * left
Definition jsonpath.h:236
JsonPathParseItem * right
Definition jsonpath.h:237
JsonPathParseItem * next
Definition jsonpath.h:228
struct JsonPathParseItem::@159::@160 args
union JsonPathParseItem::@159 value
struct JsonPathParseItem::@159::@163 like_regex
struct JsonPathParseItem::@159::@161::@165 * elems
JsonPathItemType type
Definition jsonpath.h:227
struct JsonPathParseItem::@159::@162 anybounds
struct JsonPathParseItem::@159::@161 array
char data[FLEXIBLE_ARRAY_MEMBER]
Definition jsonpath.h:27
uint32 header
Definition jsonpath.h:26
Definition pg_list.h:54
Definition nodes.h:135
Definition value.h:64
char * sval
Definition value.h:68
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432
const char * type
const char * name