aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/adt
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/adt')
-rw-r--r--src/backend/utils/adt/jsonpath.c2
-rw-r--r--src/backend/utils/adt/jsonpath_exec.c26
-rw-r--r--src/backend/utils/adt/jsonpath_gram.y64
3 files changed, 52 insertions, 40 deletions
diff --git a/src/backend/utils/adt/jsonpath.c b/src/backend/utils/adt/jsonpath.c
index 87ae60e490f..7f322485e7b 100644
--- a/src/backend/utils/adt/jsonpath.c
+++ b/src/backend/utils/adt/jsonpath.c
@@ -557,7 +557,7 @@ printJsonPathItem(StringInfo buf, JsonPathItem *v, bool inKey,
if (v->content.like_regex.flags & JSP_REGEX_ICASE)
appendStringInfoChar(buf, 'i');
- if (v->content.like_regex.flags & JSP_REGEX_SLINE)
+ if (v->content.like_regex.flags & JSP_REGEX_DOTALL)
appendStringInfoChar(buf, 's');
if (v->content.like_regex.flags & JSP_REGEX_MLINE)
appendStringInfoChar(buf, 'm');
diff --git a/src/backend/utils/adt/jsonpath_exec.c b/src/backend/utils/adt/jsonpath_exec.c
index 22ec578d778..fbb8392fe96 100644
--- a/src/backend/utils/adt/jsonpath_exec.c
+++ b/src/backend/utils/adt/jsonpath_exec.c
@@ -1645,34 +1645,10 @@ executeLikeRegex(JsonPathItem *jsp, JsonbValue *str, JsonbValue *rarg,
/* Cache regex text and converted flags. */
if (!cxt->regex)
{
- uint32 flags = jsp->content.like_regex.flags;
-
cxt->regex =
cstring_to_text_with_len(jsp->content.like_regex.pattern,
jsp->content.like_regex.patternlen);
-
- /* Convert regex flags. */
- cxt->cflags = REG_ADVANCED;
-
- if (flags & JSP_REGEX_ICASE)
- cxt->cflags |= REG_ICASE;
- if (flags & JSP_REGEX_MLINE)
- cxt->cflags |= REG_NEWLINE;
- if (flags & JSP_REGEX_SLINE)
- cxt->cflags &= ~REG_NEWLINE;
- if (flags & JSP_REGEX_WSPACE)
- cxt->cflags |= REG_EXPANDED;
-
- /*
- * 'q' flag can work together only with 'i'. When other is specified,
- * then 'q' has no effect.
- */
- if ((flags & JSP_REGEX_QUOTE) &&
- !(flags & (JSP_REGEX_MLINE | JSP_REGEX_SLINE | JSP_REGEX_WSPACE)))
- {
- cxt->cflags &= ~REG_ADVANCED;
- cxt->cflags |= REG_QUOTE;
- }
+ cxt->cflags = jspConvertRegexFlags(jsp->content.like_regex.flags);
}
if (RE_compile_and_execute(cxt->regex, str->val.string.val,
diff --git a/src/backend/utils/adt/jsonpath_gram.y b/src/backend/utils/adt/jsonpath_gram.y
index a0a930ccf0c..4681f1f0d00 100644
--- a/src/backend/utils/adt/jsonpath_gram.y
+++ b/src/backend/utils/adt/jsonpath_gram.y
@@ -481,42 +481,32 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
{
JsonPathParseItem *v = makeItemType(jpiLikeRegex);
int i;
- int cflags = REG_ADVANCED;
+ int cflags;
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;
+ /* Parse the flags string, convert to bitmask. Duplicate flags are OK. */
+ 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;
+ v->value.like_regex.flags |= JSP_REGEX_DOTALL;
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;
case 'q':
v->value.like_regex.flags |= JSP_REGEX_QUOTE;
- if (!(v->value.like_regex.flags & (JSP_REGEX_MLINE | JSP_REGEX_SLINE | JSP_REGEX_WSPACE)))
- {
- cflags &= ~REG_ADVANCED;
- cflags |= REG_QUOTE;
- }
break;
default:
ereport(ERROR,
@@ -528,6 +518,9 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
}
}
+ /* Convert flags to what RE_compile_and_cache needs */
+ cflags = jspConvertRegexFlags(v->value.like_regex.flags);
+
/* check regex validity */
(void) RE_compile_and_cache(cstring_to_text_with_len(pattern->val,
pattern->len),
@@ -537,6 +530,49 @@ makeItemLikeRegex(JsonPathParseItem *expr, JsonPathString *pattern,
}
/*
+ * Convert from XQuery regex flags to those recognized by our regex library.
+ */
+int
+jspConvertRegexFlags(uint32 xflags)
+{
+ /* By default, XQuery is very nearly the same as Spencer's AREs */
+ int cflags = REG_ADVANCED;
+
+ /* Ignore-case means the same thing, too, modulo locale issues */
+ if (xflags & JSP_REGEX_ICASE)
+ cflags |= REG_ICASE;
+
+ /* Per XQuery spec, if 'q' is specified then 'm', 's', 'x' are ignored */
+ if (xflags & JSP_REGEX_QUOTE)
+ {
+ cflags &= ~REG_ADVANCED;
+ cflags |= REG_QUOTE;
+ }
+ else
+ {
+ /* Note that dotall mode is the default in POSIX */
+ if (!(xflags & JSP_REGEX_DOTALL))
+ cflags |= REG_NLSTOP;
+ if (xflags & JSP_REGEX_MLINE)
+ cflags |= REG_NLANCH;
+
+ /*
+ * XQuery's 'x' mode is related to Spencer's expanded mode, but it's
+ * not really enough alike to justify treating JSP_REGEX_WSPACE as
+ * REG_EXPANDED. For now we treat 'x' as unimplemented; perhaps in
+ * future we'll modify the regex library to have an option for
+ * XQuery-style ignore-whitespace mode.
+ */
+ if (xflags & JSP_REGEX_WSPACE)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("XQuery \"x\" flag (expanded regular expressions) is not implemented")));
+ }
+
+ return cflags;
+}
+
+/*
* jsonpath_scan.l is compiled as part of jsonpath_gram.y. Currently, this is
* unavoidable because jsonpath_gram does not create a .h file to export its
* token symbols. If these files ever grow large enough to be worth compiling