This is an automated email from the ASF dual-hosted git repository. chunwei pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/master by this push: new 057186d [CALCITE-3941] Add the default strict mode to the path in the Json functions 057186d is described below commit 057186d1c462ce06f72ed296d50e2836fe0d35df Author: XuQianJin-Stars <forwar...@apache.com> AuthorDate: Fri May 1 15:04:02 2020 +0800 [CALCITE-3941] Add the default strict mode to the path in the Json functions --- .../org/apache/calcite/runtime/JsonFunctions.java | 24 ++++++++++++++++------ .../calcite/sql/test/SqlOperatorBaseTest.java | 15 ++++++++++++++ .../apache/calcite/test/SqlJsonFunctionsTest.java | 3 +++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java b/core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java index 75cce8a..21d42d7 100644 --- a/core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java +++ b/core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java @@ -29,6 +29,7 @@ import com.fasterxml.jackson.core.util.DefaultIndenter; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.jayway.jsonpath.Configuration; import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.InvalidPathException; import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.Option; import com.jayway.jsonpath.spi.json.JacksonJsonProvider; @@ -112,18 +113,22 @@ public class JsonFunctions { } public static JsonPathContext jsonApiCommonSyntax(JsonValueContext input, String pathSpec) { + PathMode mode; + String pathStr; try { Matcher matcher = JSON_PATH_BASE.matcher(pathSpec); if (!matcher.matches()) { - throw RESOURCE.illegalJsonPathSpec(pathSpec).ex(); + mode = PathMode.STRICT; + pathStr = pathSpec; + } else { + mode = PathMode.valueOf(matcher.group(1).toUpperCase(Locale.ROOT)); + pathStr = matcher.group(2); } - PathMode mode = PathMode.valueOf(matcher.group(1).toUpperCase(Locale.ROOT)); - String pathWff = matcher.group(2); DocumentContext ctx; switch (mode) { case STRICT: if (input.hasException()) { - return JsonPathContext.withStrictException(input.exc); + return JsonPathContext.withStrictException(pathSpec, input.exc); } ctx = JsonPath.parse(input.obj, Configuration @@ -148,9 +153,9 @@ public class JsonFunctions { throw RESOURCE.illegalJsonPathModeInPathSpec(mode.toString(), pathSpec).ex(); } try { - return JsonPathContext.withJavaObj(mode, ctx.read(pathWff)); + return JsonPathContext.withJavaObj(mode, ctx.read(pathStr)); } catch (Exception e) { - return JsonPathContext.withStrictException(e); + return JsonPathContext.withStrictException(pathSpec, e); } } catch (Exception e) { return JsonPathContext.withUnknownException(e); @@ -715,6 +720,13 @@ public class JsonFunctions { return new JsonPathContext(PathMode.STRICT, null, exc); } + public static JsonPathContext withStrictException(String pathSpec, Exception exc) { + if (exc.getClass() == InvalidPathException.class) { + exc = RESOURCE.illegalJsonPathSpec(pathSpec).ex(); + } + return withStrictException(exc); + } + public static JsonPathContext withJavaObj(PathMode mode, Object obj) { if (mode == PathMode.UNKNOWN) { throw RESOURCE.illegalJsonPathMode(mode.toString()).ex(); diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java index 18a3313..f4e055a 100644 --- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java +++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java @@ -4655,6 +4655,10 @@ public abstract class SqlOperatorBaseTest { } @Test void testJsonExists() { + // default pathmode the default is: strict mode + tester.checkBoolean("json_exists('{\"foo\":\"bar\"}', " + + "'$.foo')", Boolean.TRUE); + tester.checkBoolean("json_exists('{\"foo\":\"bar\"}', " + "'strict $.foo' false on error)", Boolean.TRUE); tester.checkBoolean("json_exists('{\"foo\":\"bar\"}', " @@ -4707,6 +4711,9 @@ public abstract class SqlOperatorBaseTest { true); } + // default pathmode the default is: strict mode + tester.checkString("json_value('{\"foo\":100}', '$.foo')", + "100", "VARCHAR(2000)"); // type casting test tester.checkString("json_value('{\"foo\":100}', 'strict $.foo')", "100", "VARCHAR(2000)"); @@ -4786,6 +4793,10 @@ public abstract class SqlOperatorBaseTest { } @Test void testJsonQuery() { + // default pathmode the default is: strict mode + tester.checkString("json_query('{\"foo\":100}', '$' null on empty)", + "{\"foo\":100}", "VARCHAR(2000)"); + // lax test tester.checkString("json_query('{\"foo\":100}', 'lax $' null on empty)", "{\"foo\":100}", "VARCHAR(2000)"); @@ -4993,6 +5004,10 @@ public abstract class SqlOperatorBaseTest { tester.checkString("json_length('[1, 2, {\"a\": 3}]')", "3", "INTEGER"); + // default pathmode the default is: strict mode + tester.checkString("json_length('{\"foo\":100}', '$')", + "1", "INTEGER"); + // lax test tester.checkString("json_length('{}', 'lax $')", "0", "INTEGER"); diff --git a/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java b/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java index b8758d5..0b019d2 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java @@ -62,6 +62,9 @@ class SqlJsonFunctionsTest { } @Test void testJsonApiCommonSyntax() { + assertJsonApiCommonSyntax("{\"foo\": \"bar\"}", "$.foo", + contextMatches( + JsonFunctions.JsonPathContext.withJavaObj(JsonFunctions.PathMode.STRICT, "bar"))); assertJsonApiCommonSyntax("{\"foo\": \"bar\"}", "lax $.foo", contextMatches( JsonFunctions.JsonPathContext.withJavaObj(JsonFunctions.PathMode.LAX, "bar")));