Get rid of jsonpath_gram.h and jsonpath_scanner.h
Jsonpath grammar and scanner are both quite small. It doesn't worth complexity to compile them separately. This commit makes grammar and scanner be compiled at once. Therefore, jsonpath_gram.h and jsonpath_gram.h are no longer needed. This commit also does some reorganization of code in jsonpath_gram.y. Discussion: https://postgr.es/m/d47b2023-3ecb-5f04-d253-d557547cf74f%402ndQuadrant.com
This commit is contained in:
parent
641fde2523
commit
550b9d26f8
@ -136,9 +136,6 @@ parser/gram.h: parser/gram.y
|
|||||||
storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt
|
storage/lmgr/lwlocknames.h: storage/lmgr/generate-lwlocknames.pl storage/lmgr/lwlocknames.txt
|
||||||
$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
|
$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
|
||||||
|
|
||||||
utils/adt/jsonpath_gram.h: utils/adt/jsonpath_gram.y
|
|
||||||
$(MAKE) -C utils/adt jsonpath_gram.h
|
|
||||||
|
|
||||||
# run this unconditionally to avoid needing to know its dependencies here:
|
# run this unconditionally to avoid needing to know its dependencies here:
|
||||||
submake-catalog-headers:
|
submake-catalog-headers:
|
||||||
$(MAKE) -C catalog distprep generated-header-symlinks
|
$(MAKE) -C catalog distprep generated-header-symlinks
|
||||||
@ -162,7 +159,7 @@ submake-utils-headers:
|
|||||||
|
|
||||||
.PHONY: generated-headers
|
.PHONY: generated-headers
|
||||||
|
|
||||||
generated-headers: $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/storage/lwlocknames.h $(top_builddir)/src/include/utils/jsonpath_gram.h submake-catalog-headers submake-utils-headers
|
generated-headers: $(top_builddir)/src/include/parser/gram.h $(top_builddir)/src/include/storage/lwlocknames.h submake-catalog-headers submake-utils-headers
|
||||||
|
|
||||||
$(top_builddir)/src/include/parser/gram.h: parser/gram.h
|
$(top_builddir)/src/include/parser/gram.h: parser/gram.h
|
||||||
prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
|
prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
|
||||||
@ -174,11 +171,6 @@ $(top_builddir)/src/include/storage/lwlocknames.h: storage/lmgr/lwlocknames.h
|
|||||||
cd '$(dir $@)' && rm -f $(notdir $@) && \
|
cd '$(dir $@)' && rm -f $(notdir $@) && \
|
||||||
$(LN_S) "$$prereqdir/$(notdir $<)" .
|
$(LN_S) "$$prereqdir/$(notdir $<)" .
|
||||||
|
|
||||||
$(top_builddir)/src/include/utils/jsonpath_gram.h: utils/adt/jsonpath_gram.h
|
|
||||||
prereqdir=`cd '$(dir $<)' >/dev/null && pwd` && \
|
|
||||||
cd '$(dir $@)' && rm -f $(notdir $@) && \
|
|
||||||
$(LN_S) "$$prereqdir/$(notdir $<)" .
|
|
||||||
|
|
||||||
utils/probes.o: utils/probes.d $(SUBDIROBJS)
|
utils/probes.o: utils/probes.d $(SUBDIROBJS)
|
||||||
$(DTRACE) $(DTRACEFLAGS) -C -G -s $(call expand_subsys,$^) -o $@
|
$(DTRACE) $(DTRACEFLAGS) -C -G -s $(call expand_subsys,$^) -o $@
|
||||||
|
|
||||||
@ -193,7 +185,7 @@ distprep:
|
|||||||
$(MAKE) -C replication repl_gram.c repl_scanner.c syncrep_gram.c syncrep_scanner.c
|
$(MAKE) -C replication repl_gram.c repl_scanner.c syncrep_gram.c syncrep_scanner.c
|
||||||
$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
|
$(MAKE) -C storage/lmgr lwlocknames.h lwlocknames.c
|
||||||
$(MAKE) -C utils distprep
|
$(MAKE) -C utils distprep
|
||||||
$(MAKE) -C utils/adt jsonpath_gram.c jsonpath_gram.h jsonpath_scan.c
|
$(MAKE) -C utils/adt jsonpath_gram.c jsonpath_scan.c
|
||||||
$(MAKE) -C utils/misc guc-file.c
|
$(MAKE) -C utils/misc guc-file.c
|
||||||
$(MAKE) -C utils/sort qsort_tuple.c
|
$(MAKE) -C utils/sort qsort_tuple.c
|
||||||
|
|
||||||
@ -316,7 +308,6 @@ maintainer-clean: distclean
|
|||||||
storage/lmgr/lwlocknames.c \
|
storage/lmgr/lwlocknames.c \
|
||||||
storage/lmgr/lwlocknames.h \
|
storage/lmgr/lwlocknames.h \
|
||||||
utils/adt/jsonpath_gram.c \
|
utils/adt/jsonpath_gram.c \
|
||||||
utils/adt/jsonpath_gram.h \
|
|
||||||
utils/adt/jsonpath_scan.c \
|
utils/adt/jsonpath_scan.c \
|
||||||
utils/misc/guc-file.c \
|
utils/misc/guc-file.c \
|
||||||
utils/sort/qsort_tuple.c
|
utils/sort/qsort_tuple.c
|
||||||
|
1
src/backend/utils/adt/.gitignore
vendored
1
src/backend/utils/adt/.gitignore
vendored
@ -1,3 +1,2 @@
|
|||||||
/jsonpath_gram.h
|
|
||||||
/jsonpath_gram.c
|
/jsonpath_gram.c
|
||||||
/jsonpath_scan.c
|
/jsonpath_scan.c
|
||||||
|
@ -17,7 +17,7 @@ OBJS = acl.o amutils.o arrayfuncs.o array_expanded.o array_selfuncs.o \
|
|||||||
float.o format_type.o formatting.o genfile.o \
|
float.o format_type.o formatting.o genfile.o \
|
||||||
geo_ops.o geo_selfuncs.o geo_spgist.o inet_cidr_ntop.o inet_net_pton.o \
|
geo_ops.o geo_selfuncs.o geo_spgist.o inet_cidr_ntop.o inet_net_pton.o \
|
||||||
int.o int8.o json.o jsonb.o jsonb_gin.o jsonb_op.o jsonb_util.o \
|
int.o int8.o json.o jsonb.o jsonb_gin.o jsonb_op.o jsonb_util.o \
|
||||||
jsonfuncs.o jsonpath_gram.o jsonpath_scan.o jsonpath.o jsonpath_exec.o \
|
jsonfuncs.o jsonpath_gram.o jsonpath.o jsonpath_exec.o \
|
||||||
like.o like_support.o lockfuncs.o mac.o mac8.o misc.o name.o \
|
like.o like_support.o lockfuncs.o mac.o mac8.o misc.o name.o \
|
||||||
network.o network_gist.o network_selfuncs.o network_spgist.o \
|
network.o network_gist.o network_selfuncs.o network_spgist.o \
|
||||||
numeric.o numutils.o oid.o oracle_compat.o \
|
numeric.o numutils.o oid.o oracle_compat.o \
|
||||||
@ -33,26 +33,13 @@ OBJS = acl.o amutils.o arrayfuncs.o array_expanded.o array_selfuncs.o \
|
|||||||
txid.o uuid.o varbit.o varchar.o varlena.o version.o \
|
txid.o uuid.o varbit.o varchar.o varlena.o version.o \
|
||||||
windowfuncs.o xid.o xml.o
|
windowfuncs.o xid.o xml.o
|
||||||
|
|
||||||
# There is no correct way to write a rule that generates two files.
|
|
||||||
# See comment in src/backend/parser/Makefile for the explanation of
|
|
||||||
# the trick used here.
|
|
||||||
|
|
||||||
jsonpath_gram.h: jsonpath_gram.c
|
|
||||||
touch $@
|
|
||||||
|
|
||||||
jsonpath_gram.c: BISONFLAGS += -d
|
|
||||||
|
|
||||||
jsonpath_scan.c: FLEXFLAGS = -CF -p -p
|
jsonpath_scan.c: FLEXFLAGS = -CF -p -p
|
||||||
|
|
||||||
|
|
||||||
# Force these dependencies to be known even without dependency info built:
|
# Force these dependencies to be known even without dependency info built:
|
||||||
jsonpath_gram.o jsonpath_scan.o jsonpath_parser.o: jsonpath_gram.h
|
jsonpath_gram.o: jsonpath_scan.c
|
||||||
|
|
||||||
# jsonpath_gram.c, jsonpath_gram.h, and jsonpath_scan.c are in the
|
|
||||||
# distribution tarball, so they are not cleaned here.
|
|
||||||
clean distclean maintainer-clean:
|
|
||||||
rm -f lex.backup
|
|
||||||
|
|
||||||
|
# jsonpath_gram.c and jsonpath_scan.c are in the distribution tarball,
|
||||||
|
# so they are not cleaned here.
|
||||||
|
|
||||||
like.o: like.c like_match.c
|
like.o: like.c like_match.c
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
%{
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* jsonpath_gram.y
|
* jsonpath_gram.y
|
||||||
@ -11,7 +12,6 @@
|
|||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%{
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "catalog/pg_collation.h"
|
#include "catalog/pg_collation.h"
|
||||||
@ -21,7 +21,37 @@
|
|||||||
#include "regex/regex.h"
|
#include "regex/regex.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/jsonpath.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,
|
* Bison doesn't allocate anything that needs to live across parser calls,
|
||||||
@ -34,230 +64,6 @@
|
|||||||
#define YYMALLOC palloc
|
#define YYMALLOC palloc
|
||||||
#define YYFREE pfree
|
#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 */
|
/* BISON Declarations */
|
||||||
@ -478,3 +284,230 @@ method:
|
|||||||
| KEYVALUE_P { $$ = jpiKeyValue; }
|
| 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"
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
%{
|
||||||
/*-------------------------------------------------------------------------
|
/*-------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
* jsonpath_scan.l
|
* jsonpath_scan.l
|
||||||
@ -11,12 +12,10 @@
|
|||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
%{
|
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "mb/pg_wchar.h"
|
#include "mb/pg_wchar.h"
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
#include "utils/jsonpath_scanner.h"
|
|
||||||
|
|
||||||
static JsonPathString scanstring;
|
static JsonPathString scanstring;
|
||||||
|
|
||||||
@ -46,7 +45,6 @@ fprintf_to_ereport(const char *fmt, const char *msg)
|
|||||||
ereport(ERROR, (errmsg_internal("%s", msg)));
|
ereport(ERROR, (errmsg_internal("%s", msg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define yyerror jsonpath_yyerror
|
|
||||||
%}
|
%}
|
||||||
|
|
||||||
%option 8bit
|
%option 8bit
|
||||||
|
@ -54,7 +54,7 @@ install: all installdirs
|
|||||||
cp $(srcdir)/$$dir/*.h '$(DESTDIR)$(includedir_server)'/$$dir/ || exit; \
|
cp $(srcdir)/$$dir/*.h '$(DESTDIR)$(includedir_server)'/$$dir/ || exit; \
|
||||||
done
|
done
|
||||||
ifeq ($(vpath_build),yes)
|
ifeq ($(vpath_build),yes)
|
||||||
for file in catalog/schemapg.h catalog/pg_*_d.h parser/gram.h storage/lwlocknames.h utils/probes.h utils/jsonpath_gram.h; do \
|
for file in catalog/schemapg.h catalog/pg_*_d.h parser/gram.h storage/lwlocknames.h utils/probes.h; do \
|
||||||
cp $$file '$(DESTDIR)$(includedir_server)'/$$file || exit; \
|
cp $$file '$(DESTDIR)$(includedir_server)'/$$file || exit; \
|
||||||
done
|
done
|
||||||
endif
|
endif
|
||||||
@ -78,7 +78,7 @@ uninstall:
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f utils/fmgroids.h utils/fmgrprotos.h utils/errcodes.h utils/header-stamp
|
rm -f utils/fmgroids.h utils/fmgrprotos.h utils/errcodes.h utils/header-stamp
|
||||||
rm -f parser/gram.h storage/lwlocknames.h utils/probes.h utils/jsonpath_gram.h
|
rm -f parser/gram.h storage/lwlocknames.h utils/probes.h
|
||||||
rm -f catalog/schemapg.h catalog/pg_*_d.h catalog/header-stamp
|
rm -f catalog/schemapg.h catalog/pg_*_d.h catalog/header-stamp
|
||||||
|
|
||||||
distclean maintainer-clean: clean
|
distclean maintainer-clean: clean
|
||||||
|
1
src/include/utils/.gitignore
vendored
1
src/include/utils/.gitignore
vendored
@ -3,4 +3,3 @@
|
|||||||
/probes.h
|
/probes.h
|
||||||
/errcodes.h
|
/errcodes.h
|
||||||
/header-stamp
|
/header-stamp
|
||||||
/jsonpath_gram.h
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
/*-------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* jsonpath_scanner.h
|
|
||||||
* Definitions for jsonpath scanner & parser
|
|
||||||
*
|
|
||||||
* Portions Copyright (c) 2019, PostgreSQL Global Development Group
|
|
||||||
*
|
|
||||||
* src/include/utils/jsonpath_scanner.h
|
|
||||||
*
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef JSONPATH_SCANNER_H
|
|
||||||
#define JSONPATH_SCANNER_H
|
|
||||||
|
|
||||||
/* struct JsonPathString is shared between scan and gram */
|
|
||||||
typedef struct JsonPathString
|
|
||||||
{
|
|
||||||
char *val;
|
|
||||||
int len;
|
|
||||||
int total;
|
|
||||||
} JsonPathString;
|
|
||||||
|
|
||||||
#include "utils/jsonpath.h"
|
|
||||||
#include "utils/jsonpath_gram.h"
|
|
||||||
|
|
||||||
/* flex 2.5.4 doesn't bother with a decl for this */
|
|
||||||
extern int jsonpath_yylex(YYSTYPE *yylval_param);
|
|
||||||
extern int jsonpath_yyparse(JsonPathParseResult **result);
|
|
||||||
extern void jsonpath_yyerror(JsonPathParseResult **result, const char *message);
|
|
||||||
|
|
||||||
#endif
|
|
@ -327,24 +327,6 @@ sub GenerateFiles
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNewer(
|
|
||||||
'src/backend/utils/adt/jsonpath_gram.h',
|
|
||||||
'src/backend/utils/adt/jsonpath_gram.y'))
|
|
||||||
{
|
|
||||||
print "Generating jsonpath_gram.h...\n";
|
|
||||||
chdir('src/backend/utils/adt');
|
|
||||||
system('perl ../../../tools/msvc/pgbison.pl jsonpath_gram.y');
|
|
||||||
chdir('../../../..');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsNewer(
|
|
||||||
'src/include/utils/jsonpath_gram.h',
|
|
||||||
'src/backend/utils/adt/jsonpath_gram.h'))
|
|
||||||
{
|
|
||||||
copyFile('src/backend/utils/adt/jsonpath_gram.h',
|
|
||||||
'src/include/utils/jsonpath_gram.h');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($self->{options}->{python}
|
if ($self->{options}->{python}
|
||||||
&& IsNewer(
|
&& IsNewer(
|
||||||
'src/pl/plpython/spiexceptions.h',
|
'src/pl/plpython/spiexceptions.h',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user