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-2024, 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 
78 static Datum jsonPathFromCstring(char *in, int len, struct Node *escontext);
79 static char *jsonPathToCstring(StringInfo out, JsonPath *in,
80  int estimated_len);
81 static bool flattenJsonPathParseItem(StringInfo buf, int *result,
82  struct Node *escontext,
83  JsonPathParseItem *item,
84  int nestingLevel, bool insideArraySubscript);
85 static void alignStringInfoInt(StringInfo buf);
87 static void printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
88  bool printBracketes);
89 static int operationPriority(JsonPathItemType op);
90 
91 
92 /**************************** INPUT/OUTPUT ********************************/
93 
94 /*
95  * jsonpath type input function
96  */
97 Datum
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  */
114 Datum
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  */
133 Datum
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  */
146 Datum
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  */
172 static Datum
173 jsonPathFromCstring(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  */
212 static char *
213 jsonPathToCstring(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  */
238 static bool
239 flattenJsonPathParseItem(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);
276  appendStringInfoChar(buf, '\0');
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:
293  case jpiGreaterOrEqual:
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));
338  &item->value.like_regex.patternlen,
339  sizeof(item->value.like_regex.patternlen));
341  item->value.like_regex.patternlen);
342  appendStringInfoChar(buf, '\0');
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  */
483 static 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  */
506 static 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  */
520 static 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:
535  appendStringInfoString(buf, "null");
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))
552  appendStringInfoString(buf, "true");
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:
563  case jpiGreaterOrEqual:
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) <=
575  operationPriority(v->type));
579  jspGetRightArg(v, &elem);
580  printJsonPathItem(buf, &elem, false,
581  operationPriority(elem.type) <=
582  operationPriority(v->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) <=
606  operationPriority(v->type));
607  if (printBracketes)
609  break;
610  case jpiAnyArray:
611  appendStringInfoString(buf, "[*]");
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  {
633  appendStringInfoString(buf, " to ");
634  printJsonPathItem(buf, &to, false, false);
635  }
636  }
638  break;
639  case jpiAny:
640  if (inKey)
642 
643  if (v->content.anybounds.first == 0 &&
644  v->content.anybounds.last == PG_UINT32_MAX)
646  else if (v->content.anybounds.first == v->content.anybounds.last)
647  {
648  if (v->content.anybounds.first == PG_UINT32_MAX)
649  appendStringInfoString(buf, "**{last}");
650  else
651  appendStringInfo(buf, "**{%u}",
652  v->content.anybounds.first);
653  }
654  else if (v->content.anybounds.first == PG_UINT32_MAX)
655  appendStringInfo(buf, "**{last to %u}",
656  v->content.anybounds.last);
657  else if (v->content.anybounds.last == PG_UINT32_MAX)
658  appendStringInfo(buf, "**{%u to last}",
659  v->content.anybounds.first);
660  else
661  appendStringInfo(buf, "**{%u to %u}",
662  v->content.anybounds.first,
663  v->content.anybounds.last);
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:
727  appendStringInfoString(buf, "last");
728  break;
729  case jpiLikeRegex:
730  if (printBracketes)
732 
733  jspInitByBuffer(&elem, v->base, v->content.like_regex.expr);
734  printJsonPathItem(buf, &elem, false,
735  operationPriority(elem.type) <=
736  operationPriority(v->type));
737 
738  appendStringInfoString(buf, " like_regex ");
739 
741  v->content.like_regex.pattern,
742  v->content.like_regex.patternlen);
743 
744  if (v->content.like_regex.flags)
745  {
746  appendStringInfoString(buf, " flag \"");
747 
748  if (v->content.like_regex.flags & JSP_REGEX_ICASE)
750  if (v->content.like_regex.flags & JSP_REGEX_DOTALL)
752  if (v->content.like_regex.flags & JSP_REGEX_MLINE)
754  if (v->content.like_regex.flags & JSP_REGEX_WSPACE)
756  if (v->content.like_regex.flags & JSP_REGEX_QUOTE)
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 
842 const 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 "<=";
861  case jpiGreaterOrEqual:
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 
923 static 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:
937  case jpiGreaterOrEqual:
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  */
979 void
981 {
983  jspInitByBuffer(v, js->data, 0);
984 }
985 
986 /*
987  * Read node from buffer and fill its representation
988  */
989 void
990 jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
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 
1080 void
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 
1098 bool
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 
1165 void
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 
1184  jspInitByBuffer(a, v->base, v->content.args.left);
1185 }
1186 
1187 void
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 
1206  jspInitByBuffer(a, v->base, v->content.args.right);
1207 }
1208 
1209 bool
1211 {
1212  Assert(v->type == jpiBool);
1213 
1214  return (bool) *v->content.value.data;
1215 }
1216 
1217 Numeric
1219 {
1220  Assert(v->type == jpiNumeric);
1221 
1222  return (Numeric) v->content.value.data;
1223 }
1224 
1225 char *
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 
1237 bool
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  */
1279 bool
1280 jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
1281 {
1282  struct JsonPathMutableContext cxt;
1283  JsonPathItem jpi;
1284 
1285  cxt.varnames = varnames;
1286  cxt.varexprs = varexprs;
1287  cxt.current = jpdsNonDateTime;
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  */
1300 static enum JsonPathDatatypeStatus
1302 {
1305 
1306  while (!cxt->mutable)
1307  {
1308  JsonPathItem arg;
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);
1474  jspInitByBuffer(&arg, jpi->base, jpi->content.like_regex.expr);
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:815
static int32 next
Definition: blutils.c:222
#define INTALIGN(LEN)
Definition: c.h:799
#define PG_UINT32_MAX
Definition: c.h:581
signed int int32
Definition: c.h:496
#define Assert(condition)
Definition: c.h:849
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:4573
const char * str
int a
Definition: isn.c:69
int i
Definition: isn.c:73
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
const char * jspOperationName(JsonPathItemType type)
Definition: jsonpath.c:843
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
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
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1226
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
JsonPathParseResult * parsejsonpath(const char *str, int len, struct Node *escontext)
#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
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:73
void check_stack_depth(void)
Definition: postgres.c:3564
static char * DatumGetCString(Datum X)
Definition: postgres.h:335
uintptr_t Datum
Definition: postgres.h:64
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 appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void enlargeStringInfo(StringInfo str, int needed)
Definition: stringinfo.c:289
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:233
void appendStringInfoSpaces(StringInfo str, int count)
Definition: stringinfo.c:212
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
StringInfoData * StringInfo
Definition: stringinfo.h:54
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204
union JsonPathItem::@139 content
struct JsonPathItem::@139::@144 like_regex
struct JsonPathItem::@139::@141 array
struct JsonPathItem::@139::@140 args
char * base
Definition: jsonpath.h:146
int32 nextPos
Definition: jsonpath.h:140
int32 arg
Definition: jsonpath.h:158
JsonPathItemType type
Definition: jsonpath.h:137
struct JsonPathItem::@139::@143 value
struct JsonPathItem::@139::@142 anybounds
enum JsonPathDatatypeStatus current
Definition: jsonpath.c:1267
JsonPathParseItem * arg
Definition: jsonpath.h:233
struct JsonPathParseItem::@146::@150 like_regex
JsonPathParseItem * next
Definition: jsonpath.h:220
struct JsonPathParseItem::@146::@147 args
Numeric numeric
Definition: jsonpath.h:262
union JsonPathParseItem::@146 value
struct JsonPathParseItem::@146::@149 anybounds
struct JsonPathParseItem::@146::@148 array
struct JsonPathParseItem::@146::@151 string
JsonPathItemType type
Definition: jsonpath.h:219
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