+%{
/*-------------------------------------------------------------------------
*
* jsonpath_gram.y
*-------------------------------------------------------------------------
*/
-%{
#include "postgres.h"
#include "catalog/pg_collation.h"
#include "regex/regex.h"
#include "utils/builtins.h"
#include "utils/jsonpath.h"
-#include "utils/jsonpath_scanner.h"
+
+/* struct JsonPathString is shared between scan and gram */
+typedef struct JsonPathString
+{
+ char *val;
+ int len;
+ int total;
+} JsonPathString;
+
+union YYSTYPE;
+
+/* flex 2.5.4 doesn't bother with a decl for this */
+int jsonpath_yylex(union YYSTYPE *yylval_param);
+int jsonpath_yyparse(JsonPathParseResult **result);
+void jsonpath_yyerror(JsonPathParseResult **result, const char *message);
+
+static JsonPathParseItem *makeItemType(int type);
+static JsonPathParseItem *makeItemString(JsonPathString *s);
+static JsonPathParseItem *makeItemVariable(JsonPathString *s);
+static JsonPathParseItem *makeItemKey(JsonPathString *s);
+static JsonPathParseItem *makeItemNumeric(JsonPathString *s);
+static JsonPathParseItem *makeItemBool(bool val);
+static JsonPathParseItem *makeItemBinary(int type, JsonPathParseItem *la,
+ JsonPathParseItem *ra);
+static JsonPathParseItem *makeItemUnary(int type, JsonPathParseItem *a);
+static JsonPathParseItem *makeItemList(List *list);
+static JsonPathParseItem *makeIndexArray(List *list);
+static JsonPathParseItem *makeAny(int first, int last);
+static JsonPathParseItem *makeItemLikeRegex(JsonPathParseItem *expr,
+ JsonPathString *pattern,
+ JsonPathString *flags);
/*
* Bison doesn't allocate anything that needs to live across parser calls,
#define YYMALLOC palloc
#define YYFREE pfree
-static JsonPathParseItem*
-makeItemType(int type)
-{
- JsonPathParseItem* v = palloc(sizeof(*v));
-
- CHECK_FOR_INTERRUPTS();
-
- v->type = type;
- v->next = NULL;
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemString(JsonPathString *s)
-{
- JsonPathParseItem *v;
-
- if (s == NULL)
- {
- v = makeItemType(jpiNull);
- }
- else
- {
- v = makeItemType(jpiString);
- v->value.string.val = s->val;
- v->value.string.len = s->len;
- }
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemVariable(JsonPathString *s)
-{
- JsonPathParseItem *v;
-
- v = makeItemType(jpiVariable);
- v->value.string.val = s->val;
- v->value.string.len = s->len;
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemKey(JsonPathString *s)
-{
- JsonPathParseItem *v;
-
- v = makeItemString(s);
- v->type = jpiKey;
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemNumeric(JsonPathString *s)
-{
- JsonPathParseItem *v;
-
- v = makeItemType(jpiNumeric);
- v->value.numeric =
- DatumGetNumeric(DirectFunctionCall3(numeric_in,
- CStringGetDatum(s->val), 0, -1));
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemBool(bool val) {
- JsonPathParseItem *v = makeItemType(jpiBool);
-
- v->value.boolean = val;
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemBinary(int type, JsonPathParseItem* la, JsonPathParseItem *ra)
-{
- JsonPathParseItem *v = makeItemType(type);
-
- v->value.args.left = la;
- v->value.args.right = ra;
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemUnary(int type, JsonPathParseItem* a)
-{
- JsonPathParseItem *v;
-
- if (type == jpiPlus && a->type == jpiNumeric && !a->next)
- return a;
-
- if (type == jpiMinus && a->type == jpiNumeric && !a->next)
- {
- v = makeItemType(jpiNumeric);
- v->value.numeric =
- DatumGetNumeric(DirectFunctionCall1(numeric_uminus,
- NumericGetDatum(a->value.numeric)));
- return v;
- }
-
- v = makeItemType(type);
-
- v->value.arg = a;
-
- return v;
-}
-
-static JsonPathParseItem*
-makeItemList(List *list)
-{
- JsonPathParseItem *head, *end;
- ListCell *cell = list_head(list);
-
- head = end = (JsonPathParseItem *) lfirst(cell);
-
- if (!lnext(cell))
- return head;
-
- /* append items to the end of already existing list */
- while (end->next)
- end = end->next;
-
- for_each_cell(cell, lnext(cell))
- {
- JsonPathParseItem *c = (JsonPathParseItem *) lfirst(cell);
-
- end->next = c;
- end = c;
- }
-
- return head;
-}
-
-static JsonPathParseItem*
-makeIndexArray(List *list)
-{
- JsonPathParseItem *v = makeItemType(jpiIndexArray);
- ListCell *cell;
- int i = 0;
-
- Assert(list_length(list) > 0);
- v->value.array.nelems = list_length(list);
-
- v->value.array.elems = palloc(sizeof(v->value.array.elems[0]) *
- v->value.array.nelems);
-
- foreach(cell, list)
- {
- JsonPathParseItem *jpi = lfirst(cell);
-
- Assert(jpi->type == jpiSubscript);
-
- v->value.array.elems[i].from = jpi->value.args.left;
- v->value.array.elems[i++].to = jpi->value.args.right;
- }
-
- return v;
-}
-
-static JsonPathParseItem*
-makeAny(int first, int last)
-{
- JsonPathParseItem *v = makeItemType(jpiAny);
-
- v->value.anybounds.first = (first >= 0) ? first : PG_UINT32_MAX;
- v->value.anybounds.last = (last >= 0) ? last : PG_UINT32_MAX;
-
- return v;
-}
-
-static JsonPathParseItem *
-makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
- JsonPathString *flags)
-{
- JsonPathParseItem *v = makeItemType(jpiLikeRegex);
- int i;
- int cflags = REG_ADVANCED;
-
- v->value.like_regex.expr = expr;
- v->value.like_regex.pattern = pattern->val;
- v->value.like_regex.patternlen = pattern->len;
- v->value.like_regex.flags = 0;
-
- for (i = 0; flags && i < flags->len; i++)
- {
- switch (flags->val[i])
- {
- case 'i':
- v->value.like_regex.flags |= JSP_REGEX_ICASE;
- cflags |= REG_ICASE;
- break;
- case 's':
- v->value.like_regex.flags &= ~JSP_REGEX_MLINE;
- v->value.like_regex.flags |= JSP_REGEX_SLINE;
- cflags |= REG_NEWLINE;
- break;
- case 'm':
- v->value.like_regex.flags &= ~JSP_REGEX_SLINE;
- v->value.like_regex.flags |= JSP_REGEX_MLINE;
- cflags &= ~REG_NEWLINE;
- break;
- case 'x':
- v->value.like_regex.flags |= JSP_REGEX_WSPACE;
- cflags |= REG_EXPANDED;
- break;
- default:
- yyerror(NULL, "unrecognized flag of LIKE_REGEX predicate");
- break;
- }
- }
-
- /* check regex validity */
- (void) RE_compile_and_cache(cstring_to_text_with_len(pattern->val,
- pattern->len),
- cflags, DEFAULT_COLLATION_OID);
-
- return v;
-}
-
%}
/* BISON Declarations */
| KEYVALUE_P { $$ = jpiKeyValue; }
;
%%
+
+static JsonPathParseItem*
+makeItemType(int type)
+{
+ JsonPathParseItem* v = palloc(sizeof(*v));
+
+ CHECK_FOR_INTERRUPTS();
+
+ v->type = type;
+ v->next = NULL;
+
+ return v;
+}
+
+static JsonPathParseItem*
+makeItemString(JsonPathString *s)
+{
+ JsonPathParseItem *v;
+
+ if (s == NULL)
+ {
+ v = makeItemType(jpiNull);
+ }
+ else
+ {
+ v = makeItemType(jpiString);
+ v->value.string.val = s->val;
+ v->value.string.len = s->len;
+ }
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemVariable(JsonPathString *s)
+{
+ JsonPathParseItem *v;
+
+ v = makeItemType(jpiVariable);
+ v->value.string.val = s->val;
+ v->value.string.len = s->len;
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemKey(JsonPathString *s)
+{
+ JsonPathParseItem *v;
+
+ v = makeItemString(s);
+ v->type = jpiKey;
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemNumeric(JsonPathString *s)
+{
+ JsonPathParseItem *v;
+
+ v = makeItemType(jpiNumeric);
+ v->value.numeric =
+ DatumGetNumeric(DirectFunctionCall3(numeric_in,
+ CStringGetDatum(s->val), 0, -1));
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemBool(bool val)
+{
+ JsonPathParseItem *v = makeItemType(jpiBool);
+
+ v->value.boolean = val;
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemBinary(int type, JsonPathParseItem* la, JsonPathParseItem *ra)
+{
+ JsonPathParseItem *v = makeItemType(type);
+
+ v->value.args.left = la;
+ v->value.args.right = ra;
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemUnary(int type, JsonPathParseItem* a)
+{
+ JsonPathParseItem *v;
+
+ if (type == jpiPlus && a->type == jpiNumeric && !a->next)
+ return a;
+
+ if (type == jpiMinus && a->type == jpiNumeric && !a->next)
+ {
+ v = makeItemType(jpiNumeric);
+ v->value.numeric =
+ DatumGetNumeric(DirectFunctionCall1(numeric_uminus,
+ NumericGetDatum(a->value.numeric)));
+ return v;
+ }
+
+ v = makeItemType(type);
+
+ v->value.arg = a;
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemList(List *list)
+{
+ JsonPathParseItem *head, *end;
+ ListCell *cell = list_head(list);
+
+ head = end = (JsonPathParseItem *) lfirst(cell);
+
+ if (!lnext(cell))
+ return head;
+
+ /* append items to the end of already existing list */
+ while (end->next)
+ end = end->next;
+
+ for_each_cell(cell, lnext(cell))
+ {
+ JsonPathParseItem *c = (JsonPathParseItem *) lfirst(cell);
+
+ end->next = c;
+ end = c;
+ }
+
+ return head;
+}
+
+static JsonPathParseItem *
+makeIndexArray(List *list)
+{
+ JsonPathParseItem *v = makeItemType(jpiIndexArray);
+ ListCell *cell;
+ int i = 0;
+
+ Assert(list_length(list) > 0);
+ v->value.array.nelems = list_length(list);
+
+ v->value.array.elems = palloc(sizeof(v->value.array.elems[0]) *
+ v->value.array.nelems);
+
+ foreach(cell, list)
+ {
+ JsonPathParseItem *jpi = lfirst(cell);
+
+ Assert(jpi->type == jpiSubscript);
+
+ v->value.array.elems[i].from = jpi->value.args.left;
+ v->value.array.elems[i++].to = jpi->value.args.right;
+ }
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeAny(int first, int last)
+{
+ JsonPathParseItem *v = makeItemType(jpiAny);
+
+ v->value.anybounds.first = (first >= 0) ? first : PG_UINT32_MAX;
+ v->value.anybounds.last = (last >= 0) ? last : PG_UINT32_MAX;
+
+ return v;
+}
+
+static JsonPathParseItem *
+makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
+ JsonPathString *flags)
+{
+ JsonPathParseItem *v = makeItemType(jpiLikeRegex);
+ int i;
+ int cflags = REG_ADVANCED;
+
+ v->value.like_regex.expr = expr;
+ v->value.like_regex.pattern = pattern->val;
+ v->value.like_regex.patternlen = pattern->len;
+ v->value.like_regex.flags = 0;
+
+ for (i = 0; flags && i < flags->len; i++)
+ {
+ switch (flags->val[i])
+ {
+ case 'i':
+ v->value.like_regex.flags |= JSP_REGEX_ICASE;
+ cflags |= REG_ICASE;
+ break;
+ case 's':
+ v->value.like_regex.flags &= ~JSP_REGEX_MLINE;
+ v->value.like_regex.flags |= JSP_REGEX_SLINE;
+ cflags |= REG_NEWLINE;
+ break;
+ case 'm':
+ v->value.like_regex.flags &= ~JSP_REGEX_SLINE;
+ v->value.like_regex.flags |= JSP_REGEX_MLINE;
+ cflags &= ~REG_NEWLINE;
+ break;
+ case 'x':
+ v->value.like_regex.flags |= JSP_REGEX_WSPACE;
+ cflags |= REG_EXPANDED;
+ break;
+ default:
+ yyerror(NULL, "unrecognized flag of LIKE_REGEX predicate");
+ break;
+ }
+ }
+
+ /* check regex validity */
+ (void) RE_compile_and_cache(cstring_to_text_with_len(pattern->val,
+ pattern->len),
+ cflags, DEFAULT_COLLATION_OID);
+
+ return v;
+}
+
+#include "jsonpath_scan.c"