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 
529 
530  switch (v->type)
531  {
532  case jpiNull:
533  appendStringInfoString(buf, "null");
534  break;
535  case jpiString:
536  escape_json(buf, jspGetString(v, NULL));
537  break;
538  case jpiNumeric:
539  if (jspHasNext(v))
544  if (jspHasNext(v))
546  break;
547  case jpiBool:
548  if (jspGetBool(v))
549  appendStringInfoString(buf, "true");
550  else
551  appendStringInfoString(buf, "false");
552  break;
553  case jpiAnd:
554  case jpiOr:
555  case jpiEqual:
556  case jpiNotEqual:
557  case jpiLess:
558  case jpiGreater:
559  case jpiLessOrEqual:
560  case jpiGreaterOrEqual:
561  case jpiAdd:
562  case jpiSub:
563  case jpiMul:
564  case jpiDiv:
565  case jpiMod:
566  case jpiStartsWith:
567  if (printBracketes)
569  jspGetLeftArg(v, &elem);
570  printJsonPathItem(buf, &elem, false,
571  operationPriority(elem.type) <=
572  operationPriority(v->type));
576  jspGetRightArg(v, &elem);
577  printJsonPathItem(buf, &elem, false,
578  operationPriority(elem.type) <=
579  operationPriority(v->type));
580  if (printBracketes)
582  break;
583  case jpiNot:
585  jspGetArg(v, &elem);
586  printJsonPathItem(buf, &elem, false, false);
588  break;
589  case jpiIsUnknown:
591  jspGetArg(v, &elem);
592  printJsonPathItem(buf, &elem, false, false);
593  appendStringInfoString(buf, ") is unknown");
594  break;
595  case jpiPlus:
596  case jpiMinus:
597  if (printBracketes)
599  appendStringInfoChar(buf, v->type == jpiPlus ? '+' : '-');
600  jspGetArg(v, &elem);
601  printJsonPathItem(buf, &elem, false,
602  operationPriority(elem.type) <=
603  operationPriority(v->type));
604  if (printBracketes)
606  break;
607  case jpiAnyArray:
608  appendStringInfoString(buf, "[*]");
609  break;
610  case jpiAnyKey:
611  if (inKey)
614  break;
615  case jpiIndexArray:
617  for (i = 0; i < v->content.array.nelems; i++)
618  {
619  JsonPathItem from;
620  JsonPathItem to;
621  bool range = jspGetArraySubscript(v, &from, &to, i);
622 
623  if (i)
625 
626  printJsonPathItem(buf, &from, false, false);
627 
628  if (range)
629  {
630  appendStringInfoString(buf, " to ");
631  printJsonPathItem(buf, &to, false, false);
632  }
633  }
635  break;
636  case jpiAny:
637  if (inKey)
639 
640  if (v->content.anybounds.first == 0 &&
641  v->content.anybounds.last == PG_UINT32_MAX)
643  else if (v->content.anybounds.first == v->content.anybounds.last)
644  {
645  if (v->content.anybounds.first == PG_UINT32_MAX)
646  appendStringInfoString(buf, "**{last}");
647  else
648  appendStringInfo(buf, "**{%u}",
649  v->content.anybounds.first);
650  }
651  else if (v->content.anybounds.first == PG_UINT32_MAX)
652  appendStringInfo(buf, "**{last to %u}",
653  v->content.anybounds.last);
654  else if (v->content.anybounds.last == PG_UINT32_MAX)
655  appendStringInfo(buf, "**{%u to last}",
656  v->content.anybounds.first);
657  else
658  appendStringInfo(buf, "**{%u to %u}",
659  v->content.anybounds.first,
660  v->content.anybounds.last);
661  break;
662  case jpiKey:
663  if (inKey)
665  escape_json(buf, jspGetString(v, NULL));
666  break;
667  case jpiCurrent:
668  Assert(!inKey);
670  break;
671  case jpiRoot:
672  Assert(!inKey);
674  break;
675  case jpiVariable:
677  escape_json(buf, jspGetString(v, NULL));
678  break;
679  case jpiFilter:
681  jspGetArg(v, &elem);
682  printJsonPathItem(buf, &elem, false, false);
684  break;
685  case jpiExists:
686  appendStringInfoString(buf, "exists (");
687  jspGetArg(v, &elem);
688  printJsonPathItem(buf, &elem, false, false);
690  break;
691  case jpiType:
692  appendStringInfoString(buf, ".type()");
693  break;
694  case jpiSize:
695  appendStringInfoString(buf, ".size()");
696  break;
697  case jpiAbs:
698  appendStringInfoString(buf, ".abs()");
699  break;
700  case jpiFloor:
701  appendStringInfoString(buf, ".floor()");
702  break;
703  case jpiCeiling:
704  appendStringInfoString(buf, ".ceiling()");
705  break;
706  case jpiDouble:
707  appendStringInfoString(buf, ".double()");
708  break;
709  case jpiDatetime:
710  appendStringInfoString(buf, ".datetime(");
711  if (v->content.arg)
712  {
713  jspGetArg(v, &elem);
714  printJsonPathItem(buf, &elem, false, false);
715  }
717  break;
718  case jpiKeyValue:
719  appendStringInfoString(buf, ".keyvalue()");
720  break;
721  case jpiLast:
722  appendStringInfoString(buf, "last");
723  break;
724  case jpiLikeRegex:
725  if (printBracketes)
727 
728  jspInitByBuffer(&elem, v->base, v->content.like_regex.expr);
729  printJsonPathItem(buf, &elem, false,
730  operationPriority(elem.type) <=
731  operationPriority(v->type));
732 
733  appendStringInfoString(buf, " like_regex ");
734 
735  escape_json(buf, v->content.like_regex.pattern);
736 
737  if (v->content.like_regex.flags)
738  {
739  appendStringInfoString(buf, " flag \"");
740 
741  if (v->content.like_regex.flags & JSP_REGEX_ICASE)
743  if (v->content.like_regex.flags & JSP_REGEX_DOTALL)
745  if (v->content.like_regex.flags & JSP_REGEX_MLINE)
747  if (v->content.like_regex.flags & JSP_REGEX_WSPACE)
749  if (v->content.like_regex.flags & JSP_REGEX_QUOTE)
751 
753  }
754 
755  if (printBracketes)
757  break;
758  case jpiBigint:
759  appendStringInfoString(buf, ".bigint()");
760  break;
761  case jpiBoolean:
762  appendStringInfoString(buf, ".boolean()");
763  break;
764  case jpiDate:
765  appendStringInfoString(buf, ".date()");
766  break;
767  case jpiDecimal:
768  appendStringInfoString(buf, ".decimal(");
769  if (v->content.args.left)
770  {
771  jspGetLeftArg(v, &elem);
772  printJsonPathItem(buf, &elem, false, false);
773  }
774  if (v->content.args.right)
775  {
777  jspGetRightArg(v, &elem);
778  printJsonPathItem(buf, &elem, false, false);
779  }
781  break;
782  case jpiInteger:
783  appendStringInfoString(buf, ".integer()");
784  break;
785  case jpiNumber:
786  appendStringInfoString(buf, ".number()");
787  break;
788  case jpiStringFunc:
789  appendStringInfoString(buf, ".string()");
790  break;
791  case jpiTime:
792  appendStringInfoString(buf, ".time(");
793  if (v->content.arg)
794  {
795  jspGetArg(v, &elem);
796  printJsonPathItem(buf, &elem, false, false);
797  }
799  break;
800  case jpiTimeTz:
801  appendStringInfoString(buf, ".time_tz(");
802  if (v->content.arg)
803  {
804  jspGetArg(v, &elem);
805  printJsonPathItem(buf, &elem, false, false);
806  }
808  break;
809  case jpiTimestamp:
810  appendStringInfoString(buf, ".timestamp(");
811  if (v->content.arg)
812  {
813  jspGetArg(v, &elem);
814  printJsonPathItem(buf, &elem, false, false);
815  }
817  break;
818  case jpiTimestampTz:
819  appendStringInfoString(buf, ".timestamp_tz(");
820  if (v->content.arg)
821  {
822  jspGetArg(v, &elem);
823  printJsonPathItem(buf, &elem, false, false);
824  }
826  break;
827  default:
828  elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
829  }
830 
831  if (jspGetNext(v, &elem))
832  printJsonPathItem(buf, &elem, true, true);
833 }
834 
835 const char *
837 {
838  switch (type)
839  {
840  case jpiAnd:
841  return "&&";
842  case jpiOr:
843  return "||";
844  case jpiEqual:
845  return "==";
846  case jpiNotEqual:
847  return "!=";
848  case jpiLess:
849  return "<";
850  case jpiGreater:
851  return ">";
852  case jpiLessOrEqual:
853  return "<=";
854  case jpiGreaterOrEqual:
855  return ">=";
856  case jpiAdd:
857  case jpiPlus:
858  return "+";
859  case jpiSub:
860  case jpiMinus:
861  return "-";
862  case jpiMul:
863  return "*";
864  case jpiDiv:
865  return "/";
866  case jpiMod:
867  return "%";
868  case jpiType:
869  return "type";
870  case jpiSize:
871  return "size";
872  case jpiAbs:
873  return "abs";
874  case jpiFloor:
875  return "floor";
876  case jpiCeiling:
877  return "ceiling";
878  case jpiDouble:
879  return "double";
880  case jpiDatetime:
881  return "datetime";
882  case jpiKeyValue:
883  return "keyvalue";
884  case jpiStartsWith:
885  return "starts with";
886  case jpiLikeRegex:
887  return "like_regex";
888  case jpiBigint:
889  return "bigint";
890  case jpiBoolean:
891  return "boolean";
892  case jpiDate:
893  return "date";
894  case jpiDecimal:
895  return "decimal";
896  case jpiInteger:
897  return "integer";
898  case jpiNumber:
899  return "number";
900  case jpiStringFunc:
901  return "string";
902  case jpiTime:
903  return "time";
904  case jpiTimeTz:
905  return "time_tz";
906  case jpiTimestamp:
907  return "timestamp";
908  case jpiTimestampTz:
909  return "timestamp_tz";
910  default:
911  elog(ERROR, "unrecognized jsonpath item type: %d", type);
912  return NULL;
913  }
914 }
915 
916 static int
918 {
919  switch (op)
920  {
921  case jpiOr:
922  return 0;
923  case jpiAnd:
924  return 1;
925  case jpiEqual:
926  case jpiNotEqual:
927  case jpiLess:
928  case jpiGreater:
929  case jpiLessOrEqual:
930  case jpiGreaterOrEqual:
931  case jpiStartsWith:
932  return 2;
933  case jpiAdd:
934  case jpiSub:
935  return 3;
936  case jpiMul:
937  case jpiDiv:
938  case jpiMod:
939  return 4;
940  case jpiPlus:
941  case jpiMinus:
942  return 5;
943  default:
944  return 6;
945  }
946 }
947 
948 /******************* Support functions for JsonPath *************************/
949 
950 /*
951  * Support macros to read stored values
952  */
953 
954 #define read_byte(v, b, p) do { \
955  (v) = *(uint8*)((b) + (p)); \
956  (p) += 1; \
957 } while(0) \
958 
959 #define read_int32(v, b, p) do { \
960  (v) = *(uint32*)((b) + (p)); \
961  (p) += sizeof(int32); \
962 } while(0) \
963 
964 #define read_int32_n(v, b, p, n) do { \
965  (v) = (void *)((b) + (p)); \
966  (p) += sizeof(int32) * (n); \
967 } while(0) \
968 
969 /*
970  * Read root node and fill root node representation
971  */
972 void
974 {
976  jspInitByBuffer(v, js->data, 0);
977 }
978 
979 /*
980  * Read node from buffer and fill its representation
981  */
982 void
983 jspInitByBuffer(JsonPathItem *v, char *base, int32 pos)
984 {
985  v->base = base + pos;
986 
987  read_byte(v->type, base, pos);
988  pos = INTALIGN((uintptr_t) (base + pos)) - (uintptr_t) base;
989  read_int32(v->nextPos, base, pos);
990 
991  switch (v->type)
992  {
993  case jpiNull:
994  case jpiRoot:
995  case jpiCurrent:
996  case jpiAnyArray:
997  case jpiAnyKey:
998  case jpiType:
999  case jpiSize:
1000  case jpiAbs:
1001  case jpiFloor:
1002  case jpiCeiling:
1003  case jpiDouble:
1004  case jpiKeyValue:
1005  case jpiLast:
1006  case jpiBigint:
1007  case jpiBoolean:
1008  case jpiDate:
1009  case jpiInteger:
1010  case jpiNumber:
1011  case jpiStringFunc:
1012  break;
1013  case jpiString:
1014  case jpiKey:
1015  case jpiVariable:
1016  read_int32(v->content.value.datalen, base, pos);
1017  /* FALLTHROUGH */
1018  case jpiNumeric:
1019  case jpiBool:
1020  v->content.value.data = base + pos;
1021  break;
1022  case jpiAnd:
1023  case jpiOr:
1024  case jpiEqual:
1025  case jpiNotEqual:
1026  case jpiLess:
1027  case jpiGreater:
1028  case jpiLessOrEqual:
1029  case jpiGreaterOrEqual:
1030  case jpiAdd:
1031  case jpiSub:
1032  case jpiMul:
1033  case jpiDiv:
1034  case jpiMod:
1035  case jpiStartsWith:
1036  case jpiDecimal:
1037  read_int32(v->content.args.left, base, pos);
1038  read_int32(v->content.args.right, base, pos);
1039  break;
1040  case jpiNot:
1041  case jpiIsUnknown:
1042  case jpiExists:
1043  case jpiPlus:
1044  case jpiMinus:
1045  case jpiFilter:
1046  case jpiDatetime:
1047  case jpiTime:
1048  case jpiTimeTz:
1049  case jpiTimestamp:
1050  case jpiTimestampTz:
1051  read_int32(v->content.arg, base, pos);
1052  break;
1053  case jpiIndexArray:
1054  read_int32(v->content.array.nelems, base, pos);
1055  read_int32_n(v->content.array.elems, base, pos,
1056  v->content.array.nelems * 2);
1057  break;
1058  case jpiAny:
1059  read_int32(v->content.anybounds.first, base, pos);
1060  read_int32(v->content.anybounds.last, base, pos);
1061  break;
1062  case jpiLikeRegex:
1063  read_int32(v->content.like_regex.flags, base, pos);
1064  read_int32(v->content.like_regex.expr, base, pos);
1065  read_int32(v->content.like_regex.patternlen, base, pos);
1066  v->content.like_regex.pattern = base + pos;
1067  break;
1068  default:
1069  elog(ERROR, "unrecognized jsonpath item type: %d", v->type);
1070  }
1071 }
1072 
1073 void
1075 {
1076  Assert(v->type == jpiNot ||
1077  v->type == jpiIsUnknown ||
1078  v->type == jpiPlus ||
1079  v->type == jpiMinus ||
1080  v->type == jpiFilter ||
1081  v->type == jpiExists ||
1082  v->type == jpiDatetime ||
1083  v->type == jpiTime ||
1084  v->type == jpiTimeTz ||
1085  v->type == jpiTimestamp ||
1086  v->type == jpiTimestampTz);
1087 
1088  jspInitByBuffer(a, v->base, v->content.arg);
1089 }
1090 
1091 bool
1093 {
1094  if (jspHasNext(v))
1095  {
1096  Assert(v->type == jpiNull ||
1097  v->type == jpiString ||
1098  v->type == jpiNumeric ||
1099  v->type == jpiBool ||
1100  v->type == jpiAnd ||
1101  v->type == jpiOr ||
1102  v->type == jpiNot ||
1103  v->type == jpiIsUnknown ||
1104  v->type == jpiEqual ||
1105  v->type == jpiNotEqual ||
1106  v->type == jpiLess ||
1107  v->type == jpiGreater ||
1108  v->type == jpiLessOrEqual ||
1109  v->type == jpiGreaterOrEqual ||
1110  v->type == jpiAdd ||
1111  v->type == jpiSub ||
1112  v->type == jpiMul ||
1113  v->type == jpiDiv ||
1114  v->type == jpiMod ||
1115  v->type == jpiPlus ||
1116  v->type == jpiMinus ||
1117  v->type == jpiAnyArray ||
1118  v->type == jpiAnyKey ||
1119  v->type == jpiIndexArray ||
1120  v->type == jpiAny ||
1121  v->type == jpiKey ||
1122  v->type == jpiCurrent ||
1123  v->type == jpiRoot ||
1124  v->type == jpiVariable ||
1125  v->type == jpiFilter ||
1126  v->type == jpiExists ||
1127  v->type == jpiType ||
1128  v->type == jpiSize ||
1129  v->type == jpiAbs ||
1130  v->type == jpiFloor ||
1131  v->type == jpiCeiling ||
1132  v->type == jpiDouble ||
1133  v->type == jpiDatetime ||
1134  v->type == jpiKeyValue ||
1135  v->type == jpiLast ||
1136  v->type == jpiStartsWith ||
1137  v->type == jpiLikeRegex ||
1138  v->type == jpiBigint ||
1139  v->type == jpiBoolean ||
1140  v->type == jpiDate ||
1141  v->type == jpiDecimal ||
1142  v->type == jpiInteger ||
1143  v->type == jpiNumber ||
1144  v->type == jpiStringFunc ||
1145  v->type == jpiTime ||
1146  v->type == jpiTimeTz ||
1147  v->type == jpiTimestamp ||
1148  v->type == jpiTimestampTz);
1149 
1150  if (a)
1151  jspInitByBuffer(a, v->base, v->nextPos);
1152  return true;
1153  }
1154 
1155  return false;
1156 }
1157 
1158 void
1160 {
1161  Assert(v->type == jpiAnd ||
1162  v->type == jpiOr ||
1163  v->type == jpiEqual ||
1164  v->type == jpiNotEqual ||
1165  v->type == jpiLess ||
1166  v->type == jpiGreater ||
1167  v->type == jpiLessOrEqual ||
1168  v->type == jpiGreaterOrEqual ||
1169  v->type == jpiAdd ||
1170  v->type == jpiSub ||
1171  v->type == jpiMul ||
1172  v->type == jpiDiv ||
1173  v->type == jpiMod ||
1174  v->type == jpiStartsWith ||
1175  v->type == jpiDecimal);
1176 
1177  jspInitByBuffer(a, v->base, v->content.args.left);
1178 }
1179 
1180 void
1182 {
1183  Assert(v->type == jpiAnd ||
1184  v->type == jpiOr ||
1185  v->type == jpiEqual ||
1186  v->type == jpiNotEqual ||
1187  v->type == jpiLess ||
1188  v->type == jpiGreater ||
1189  v->type == jpiLessOrEqual ||
1190  v->type == jpiGreaterOrEqual ||
1191  v->type == jpiAdd ||
1192  v->type == jpiSub ||
1193  v->type == jpiMul ||
1194  v->type == jpiDiv ||
1195  v->type == jpiMod ||
1196  v->type == jpiStartsWith ||
1197  v->type == jpiDecimal);
1198 
1199  jspInitByBuffer(a, v->base, v->content.args.right);
1200 }
1201 
1202 bool
1204 {
1205  Assert(v->type == jpiBool);
1206 
1207  return (bool) *v->content.value.data;
1208 }
1209 
1210 Numeric
1212 {
1213  Assert(v->type == jpiNumeric);
1214 
1215  return (Numeric) v->content.value.data;
1216 }
1217 
1218 char *
1220 {
1221  Assert(v->type == jpiKey ||
1222  v->type == jpiString ||
1223  v->type == jpiVariable);
1224 
1225  if (len)
1226  *len = v->content.value.datalen;
1227  return v->content.value.data;
1228 }
1229 
1230 bool
1232  int i)
1233 {
1234  Assert(v->type == jpiIndexArray);
1235 
1236  jspInitByBuffer(from, v->base, v->content.array.elems[i].from);
1237 
1238  if (!v->content.array.elems[i].to)
1239  return false;
1240 
1241  jspInitByBuffer(to, v->base, v->content.array.elems[i].to);
1242 
1243  return true;
1244 }
1245 
1246 /* SQL/JSON datatype status: */
1248 {
1249  jpdsNonDateTime, /* null, bool, numeric, string, array, object */
1250  jpdsUnknownDateTime, /* unknown datetime type */
1251  jpdsDateTimeZoned, /* timetz, timestamptz */
1252  jpdsDateTimeNonZoned, /* time, timestamp, date */
1253 };
1254 
1255 /* Context for jspIsMutableWalker() */
1257 {
1258  List *varnames; /* list of variable names */
1259  List *varexprs; /* list of variable expressions */
1260  enum JsonPathDatatypeStatus current; /* status of @ item */
1261  bool lax; /* jsonpath is lax or strict */
1262  bool mutable; /* resulting mutability status */
1263 };
1264 
1266  struct JsonPathMutableContext *cxt);
1267 
1268 /*
1269  * Function to check whether jsonpath expression is mutable to be used in the
1270  * planner function contain_mutable_functions().
1271  */
1272 bool
1273 jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
1274 {
1275  struct JsonPathMutableContext cxt;
1276  JsonPathItem jpi;
1277 
1278  cxt.varnames = varnames;
1279  cxt.varexprs = varexprs;
1280  cxt.current = jpdsNonDateTime;
1281  cxt.lax = (path->header & JSONPATH_LAX) != 0;
1282  cxt.mutable = false;
1283 
1284  jspInit(&jpi, path);
1285  (void) jspIsMutableWalker(&jpi, &cxt);
1286 
1287  return cxt.mutable;
1288 }
1289 
1290 /*
1291  * Recursive walker for jspIsMutable()
1292  */
1293 static enum JsonPathDatatypeStatus
1295 {
1298 
1299  while (!cxt->mutable)
1300  {
1301  JsonPathItem arg;
1302  enum JsonPathDatatypeStatus leftStatus;
1303  enum JsonPathDatatypeStatus rightStatus;
1304 
1305  switch (jpi->type)
1306  {
1307  case jpiRoot:
1308  Assert(status == jpdsNonDateTime);
1309  break;
1310 
1311  case jpiCurrent:
1312  Assert(status == jpdsNonDateTime);
1313  status = cxt->current;
1314  break;
1315 
1316  case jpiFilter:
1317  {
1318  enum JsonPathDatatypeStatus prevStatus = cxt->current;
1319 
1320  cxt->current = status;
1321  jspGetArg(jpi, &arg);
1322  jspIsMutableWalker(&arg, cxt);
1323 
1324  cxt->current = prevStatus;
1325  break;
1326  }
1327 
1328  case jpiVariable:
1329  {
1330  int32 len;
1331  const char *name = jspGetString(jpi, &len);
1332  ListCell *lc1;
1333  ListCell *lc2;
1334 
1335  Assert(status == jpdsNonDateTime);
1336 
1337  forboth(lc1, cxt->varnames, lc2, cxt->varexprs)
1338  {
1339  String *varname = lfirst_node(String, lc1);
1340  Node *varexpr = lfirst(lc2);
1341 
1342  if (strncmp(varname->sval, name, len))
1343  continue;
1344 
1345  switch (exprType(varexpr))
1346  {
1347  case DATEOID:
1348  case TIMEOID:
1349  case TIMESTAMPOID:
1350  status = jpdsDateTimeNonZoned;
1351  break;
1352 
1353  case TIMETZOID:
1354  case TIMESTAMPTZOID:
1355  status = jpdsDateTimeZoned;
1356  break;
1357 
1358  default:
1359  status = jpdsNonDateTime;
1360  break;
1361  }
1362 
1363  break;
1364  }
1365  break;
1366  }
1367 
1368  case jpiEqual:
1369  case jpiNotEqual:
1370  case jpiLess:
1371  case jpiGreater:
1372  case jpiLessOrEqual:
1373  case jpiGreaterOrEqual:
1374  Assert(status == jpdsNonDateTime);
1375  jspGetLeftArg(jpi, &arg);
1376  leftStatus = jspIsMutableWalker(&arg, cxt);
1377 
1378  jspGetRightArg(jpi, &arg);
1379  rightStatus = jspIsMutableWalker(&arg, cxt);
1380 
1381  /*
1382  * Comparison of datetime type with different timezone status
1383  * is mutable.
1384  */
1385  if (leftStatus != jpdsNonDateTime &&
1386  rightStatus != jpdsNonDateTime &&
1387  (leftStatus == jpdsUnknownDateTime ||
1388  rightStatus == jpdsUnknownDateTime ||
1389  leftStatus != rightStatus))
1390  cxt->mutable = true;
1391  break;
1392 
1393  case jpiNot:
1394  case jpiIsUnknown:
1395  case jpiExists:
1396  case jpiPlus:
1397  case jpiMinus:
1398  Assert(status == jpdsNonDateTime);
1399  jspGetArg(jpi, &arg);
1400  jspIsMutableWalker(&arg, cxt);
1401  break;
1402 
1403  case jpiAnd:
1404  case jpiOr:
1405  case jpiAdd:
1406  case jpiSub:
1407  case jpiMul:
1408  case jpiDiv:
1409  case jpiMod:
1410  case jpiStartsWith:
1411  Assert(status == jpdsNonDateTime);
1412  jspGetLeftArg(jpi, &arg);
1413  jspIsMutableWalker(&arg, cxt);
1414  jspGetRightArg(jpi, &arg);
1415  jspIsMutableWalker(&arg, cxt);
1416  break;
1417 
1418  case jpiIndexArray:
1419  for (int i = 0; i < jpi->content.array.nelems; i++)
1420  {
1421  JsonPathItem from;
1422  JsonPathItem to;
1423 
1424  if (jspGetArraySubscript(jpi, &from, &to, i))
1425  jspIsMutableWalker(&to, cxt);
1426 
1427  jspIsMutableWalker(&from, cxt);
1428  }
1429  /* FALLTHROUGH */
1430 
1431  case jpiAnyArray:
1432  if (!cxt->lax)
1433  status = jpdsNonDateTime;
1434  break;
1435 
1436  case jpiAny:
1437  if (jpi->content.anybounds.first > 0)
1438  status = jpdsNonDateTime;
1439  break;
1440 
1441  case jpiDatetime:
1442  if (jpi->content.arg)
1443  {
1444  char *template;
1445 
1446  jspGetArg(jpi, &arg);
1447  if (arg.type != jpiString)
1448  {
1449  status = jpdsNonDateTime;
1450  break; /* there will be runtime error */
1451  }
1452 
1453  template = jspGetString(&arg, NULL);
1454  if (datetime_format_has_tz(template))
1455  status = jpdsDateTimeZoned;
1456  else
1457  status = jpdsDateTimeNonZoned;
1458  }
1459  else
1460  {
1461  status = jpdsUnknownDateTime;
1462  }
1463  break;
1464 
1465  case jpiLikeRegex:
1466  Assert(status == jpdsNonDateTime);
1467  jspInitByBuffer(&arg, jpi->base, jpi->content.like_regex.expr);
1468  jspIsMutableWalker(&arg, cxt);
1469  break;
1470 
1471  /* literals */
1472  case jpiNull:
1473  case jpiString:
1474  case jpiNumeric:
1475  case jpiBool:
1476  break;
1477  /* accessors */
1478  case jpiKey:
1479  case jpiAnyKey:
1480  /* special items */
1481  case jpiSubscript:
1482  case jpiLast:
1483  /* item methods */
1484  case jpiType:
1485  case jpiSize:
1486  case jpiAbs:
1487  case jpiFloor:
1488  case jpiCeiling:
1489  case jpiDouble:
1490  case jpiKeyValue:
1491  case jpiBigint:
1492  case jpiBoolean:
1493  case jpiDecimal:
1494  case jpiInteger:
1495  case jpiNumber:
1496  case jpiStringFunc:
1497  status = jpdsNonDateTime;
1498  break;
1499 
1500  case jpiTime:
1501  case jpiDate:
1502  case jpiTimestamp:
1503  status = jpdsDateTimeNonZoned;
1504  cxt->mutable = true;
1505  break;
1506 
1507  case jpiTimeTz:
1508  case jpiTimestampTz:
1509  status = jpdsDateTimeNonZoned;
1510  cxt->mutable = true;
1511  break;
1512 
1513  }
1514 
1515  if (!jspGetNext(jpi, &next))
1516  break;
1517 
1518  jpi = &next;
1519  }
1520 
1521  return status;
1522 }
Datum numeric_out(PG_FUNCTION_ARGS)
Definition: numeric.c:807
static int32 next
Definition: blutils.c:221
#define INTALIGN(LEN)
Definition: c.h:808
#define PG_UINT32_MAX
Definition: c.h:590
signed int int32
Definition: c.h:494
#define Assert(condition)
Definition: c.h:858
int errcode(int sqlerrcode)
Definition: elog.c:859
int errmsg(const char *fmt,...)
Definition: elog.c:1072
#define ereturn(context, dummy_value,...)
Definition: elog.h:276
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#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:642
#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:4618
const char * str
int a
Definition: isn.c:69
int i
Definition: isn.c:73
void escape_json(StringInfo buf, const char *str)
Definition: json.c:1549
bool jspIsMutable(JsonPath *path, List *varnames, List *varexprs)
Definition: jsonpath.c:1273
static enum JsonPathDatatypeStatus jspIsMutableWalker(JsonPathItem *jpi, struct JsonPathMutableContext *cxt)
Definition: jsonpath.c:1294
void jspGetLeftArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1159
void jspGetArg(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1074
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:954
#define read_int32_n(v, b, p, n)
Definition: jsonpath.c:964
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:983
bool jspGetBool(JsonPathItem *v)
Definition: jsonpath.c:1203
void jspInit(JsonPathItem *v, JsonPath *js)
Definition: jsonpath.c:973
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:836
Numeric jspGetNumeric(JsonPathItem *v)
Definition: jsonpath.c:1211
bool jspGetArraySubscript(JsonPathItem *v, JsonPathItem *from, JsonPathItem *to, int i)
Definition: jsonpath.c:1231
static void printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey, bool printBracketes)
Definition: jsonpath.c:521
#define read_int32(v, b, p)
Definition: jsonpath.c:959
bool jspGetNext(JsonPathItem *v, JsonPathItem *a)
Definition: jsonpath.c:1092
static int operationPriority(JsonPathItemType op)
Definition: jsonpath.c:917
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:1181
char * jspGetString(JsonPathItem *v, int32 *len)
Definition: jsonpath.c:1219
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:1248
@ jpdsDateTimeZoned
Definition: jsonpath.c:1251
@ jpdsNonDateTime
Definition: jsonpath.c:1249
@ jpdsDateTimeNonZoned
Definition: jsonpath.c:1252
@ jpdsUnknownDateTime
Definition: jsonpath.c:1250
#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:1520
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define SOFT_ERROR_OCCURRED(escontext)
Definition: miscnodes.h:52
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:3531
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::@137 content
struct JsonPathItem::@137::@141 value
struct JsonPathItem::@137::@139 array
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::@137::@142 like_regex
struct JsonPathItem::@137::@140 anybounds
struct JsonPathItem::@137::@138 args
enum JsonPathDatatypeStatus current
Definition: jsonpath.c:1260
JsonPathParseItem * arg
Definition: jsonpath.h:233
struct JsonPathParseItem::@144::@148 like_regex
struct JsonPathParseItem::@144::@146 array
struct JsonPathParseItem::@144::@149 string
struct JsonPathParseItem::@144::@147 anybounds
JsonPathParseItem * next
Definition: jsonpath.h:220
Numeric numeric
Definition: jsonpath.h:262
struct JsonPathParseItem::@144::@145 args
union JsonPathParseItem::@144 value
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