This is an automated email from the ASF dual-hosted git repository.
hongze 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 7c905ff [CALCITE-2881] Add the JSON_PRETTY function (Ritesh Kapoor)
7c905ff is described below
commit 7c905ff3263bcc6cec826789305f1be9fba0962e
Author: Ritesh Kapoor <[email protected]>
AuthorDate: Thu Feb 28 15:04:33 2019 +0530
[CALCITE-2881] Add the JSON_PRETTY function (Ritesh Kapoor)
Also refactor SqlJsonFunctionsTest a little to better generate invocation
descriptions.
Close apache/calcite#1075
---
babel/src/main/codegen/config.fmpp | 3 +
core/src/main/codegen/config.fmpp | 1 +
core/src/main/codegen/templates/Parser.jj | 19 +++++
.../calcite/adapter/enumerable/RexImpTable.java | 2 +
.../apache/calcite/runtime/CalciteResource.java | 3 +
.../org/apache/calcite/runtime/SqlFunctions.java | 12 ++-
.../calcite/sql/fun/SqlJsonPrettyFunction.java | 68 ++++++++++++++++
.../calcite/sql/fun/SqlStdOperatorTable.java | 3 +
.../org/apache/calcite/util/BuiltInMethod.java | 6 ++
.../calcite/runtime/CalciteResource.properties | 1 +
core/src/test/codegen/config.fmpp | 1 +
.../calcite/rel/rel2sql/RelToSqlConverterTest.java | 7 ++
.../apache/calcite/sql/parser/SqlParserTest.java | 7 ++
.../calcite/sql/test/SqlOperatorBaseTest.java | 9 ++
.../java/org/apache/calcite/test/JdbcTest.java | 12 +++
.../apache/calcite/test/SqlJsonFunctionsTest.java | 95 ++++++++++++----------
.../org/apache/calcite/test/SqlValidatorTest.java | 11 ++-
server/src/main/codegen/config.fmpp | 1 +
site/_docs/reference.md | 2 +
19 files changed, 216 insertions(+), 47 deletions(-)
diff --git a/babel/src/main/codegen/config.fmpp
b/babel/src/main/codegen/config.fmpp
index de1efb7..dab4251 100644
--- a/babel/src/main/codegen/config.fmpp
+++ b/babel/src/main/codegen/config.fmpp
@@ -555,6 +555,9 @@ data: {
"JSON_ARRAYAGG",
"JSON_EXISTS",
"JSON_VALUE",
+ "JSON_TYPE",
+ "JSON_DEPTH"
+ "JSON_PRETTY",
"JSON_OBJECT",
"JSON_OBJECTAGG",
"JSON_QUERY",
diff --git a/core/src/main/codegen/config.fmpp
b/core/src/main/codegen/config.fmpp
index a28294a..c8f9ec8 100644
--- a/core/src/main/codegen/config.fmpp
+++ b/core/src/main/codegen/config.fmpp
@@ -161,6 +161,7 @@ data: {
"JSON"
"JSON_TYPE"
"JSON_DEPTH"
+ "JSON_PRETTY"
"K"
"KEY"
"KEY_MEMBER"
diff --git a/core/src/main/codegen/templates/Parser.jj
b/core/src/main/codegen/templates/Parser.jj
index 9bdae0d..56a3a7f 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -4823,6 +4823,8 @@ SqlNode BuiltinFunctionCall() :
|
node = JsonValueFunctionCall() { return node; }
|
+ node = JsonPrettyFunctionCall() { return node; }
+ |
node = JsonQueryFunctionCall() { return node; }
|
node = JsonObjectFunctionCall() { return node; }
@@ -5072,6 +5074,22 @@ SqlCall JsonValueFunctionCall() :
}
}
+SqlCall JsonPrettyFunctionCall() :
+{
+ final SqlNode[] args = new SqlNode[1];
+ SqlNode e;
+ final Span span;
+}
+{
+ <JSON_PRETTY> { span = span(); }
+ <LPAREN> e = JsonValueExpression(true) {
+ args[0] = e;
+ }
+ <RPAREN> {
+ return SqlStdOperatorTable.JSON_PRETTY.createCall(span.end(this),
args);
+ }
+}
+
List<SqlNode> JsonQueryEmptyOrErrorBehavior() :
{
final List<SqlNode> list = new ArrayList<SqlNode>();
@@ -6355,6 +6373,7 @@ SqlPostfixOperator PostfixRowOperator() :
| < JSON_ARRAYAGG: "JSON_ARRAYAGG">
| < JSON_EXISTS: "JSON_EXISTS" >
| < JSON_VALUE: "JSON_VALUE" >
+| < JSON_PRETTY: "JSON_PRETTY" >
| < JSON_OBJECT: "JSON_OBJECT">
| < JSON_TYPE: "JSON_TYPE">
| < JSON_DEPTH: "JSON_DEPTH">
diff --git
a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
index e44af2b..dcab895 100644
--- a/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
+++ b/core/src/main/java/org/apache/calcite/adapter/enumerable/RexImpTable.java
@@ -167,6 +167,7 @@ import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_DEPTH;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_EXISTS;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECT;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_OBJECTAGG;
+import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_PRETTY;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_QUERY;
import static
org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_STRUCTURED_VALUE_EXPRESSION;
import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_TYPE;
@@ -456,6 +457,7 @@ public class RexImpTable {
defineMethod(JSON_ARRAY, BuiltInMethod.JSON_ARRAY.method, NullPolicy.NONE);
defineMethod(JSON_TYPE, BuiltInMethod.JSON_TYPE.method, NullPolicy.NONE);
defineMethod(JSON_DEPTH, BuiltInMethod.JSON_DEPTH.method, NullPolicy.NONE);
+ defineMethod(JSON_PRETTY, BuiltInMethod.JSON_PRETTY.method,
NullPolicy.NONE);
aggMap.put(JSON_OBJECTAGG.with(SqlJsonConstructorNullClause.ABSENT_ON_NULL),
JsonObjectAggImplementor
.supplierFor(BuiltInMethod.JSON_OBJECTAGG_ADD.method));
diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
index a7f2203..2aeb60d 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -861,6 +861,9 @@ public interface CalciteResource {
@BaseMessage("Unknown JSON depth in JSON_DEPTH function, and the object is:
''{0}''")
ExInst<CalciteException> unknownObjectOfJsonDepth(String value);
+
+ @BaseMessage("Cannot serialize object to JSON, and the object is: ''{0}''")
+ ExInst<CalciteException> exceptionWhileSerializingToJson(String value);
}
// End CalciteResource.java
diff --git a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
index fed1d97..888c8a2 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -48,7 +48,6 @@ import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.Option;
import com.jayway.jsonpath.spi.json.JacksonJsonProvider;
-import com.jayway.jsonpath.spi.json.JsonProvider;
import com.jayway.jsonpath.spi.mapper.JacksonMappingProvider;
import com.jayway.jsonpath.spi.mapper.MappingProvider;
@@ -131,7 +130,7 @@ public class SqlFunctions {
Pattern.compile("^\\s*(?<mode>strict|lax)\\s+(?<spec>.+)$",
Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE);
- private static final JsonProvider JSON_PATH_JSON_PROVIDER =
+ private static final JacksonJsonProvider JSON_PATH_JSON_PROVIDER =
new JacksonJsonProvider();
private static final MappingProvider JSON_PATH_MAPPING_PROVIDER =
new JacksonMappingProvider();
@@ -2677,6 +2676,15 @@ public class SqlFunctions {
}
}
+ public static String jsonPretty(Object input) {
+ try {
+ return
JSON_PATH_JSON_PROVIDER.getObjectMapper().writerWithDefaultPrettyPrinter()
+ .writeValueAsString(input);
+ } catch (Exception e) {
+ throw RESOURCE.exceptionWhileSerializingToJson(input.toString()).ex();
+ }
+ }
+
public static String jsonType(Object o) {
final String result;
try {
diff --git
a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonPrettyFunction.java
b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonPrettyFunction.java
new file mode 100644
index 0000000..cc33d31
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonPrettyFunction.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.calcite.sql.fun;
+
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlLiteral;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlOperandCountRange;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlOperandCountRanges;
+import org.apache.calcite.sql.type.SqlOperandTypeChecker;
+import org.apache.calcite.sql.validate.SqlValidator;
+
+/**
+ * The <code>JSON_TYPE</code> function.
+ */
+public class SqlJsonPrettyFunction extends SqlFunction {
+
+ public SqlJsonPrettyFunction() {
+ super("JSON_PRETTY",
+ SqlKind.OTHER_FUNCTION,
+ ReturnTypes.VARCHAR_2000,
+ null,
+ OperandTypes.ANY,
+ SqlFunctionCategory.SYSTEM);
+ }
+
+ @Override public SqlOperandCountRange getOperandCountRange() {
+ return SqlOperandCountRanges.of(1);
+ }
+
+ @Override protected void checkOperandCount(SqlValidator validator,
+ SqlOperandTypeChecker argType, SqlCall call) {
+ assert call.operandCount() == 1;
+ }
+
+ @Override public SqlCall createCall(SqlLiteral functionQualifier,
+ SqlParserPos pos, SqlNode... operands) {
+ return super.createCall(functionQualifier, pos, operands);
+ }
+
+ @Override public void unparse(SqlWriter writer, SqlCall call, int leftPrec,
+ int rightPrec) {
+ super.unparse(writer, call, 0, 0);
+ }
+}
+
+// End SqlJsonPrettyFunction.java
diff --git
a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
index 5843835..3e66b9c 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java
@@ -1297,6 +1297,9 @@ public class SqlStdOperatorTable extends
ReflectiveSqlOperatorTable {
public static final SqlFunction JSON_VALUE =
new SqlJsonValueFunction("JSON_VALUE", false);
+ public static final SqlFunction JSON_PRETTY =
+ new SqlJsonPrettyFunction();
+
public static final SqlFunction JSON_VALUE_ANY =
new SqlJsonValueFunction("JSON_VALUE_ANY", true);
diff --git a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
index f0ce346..fc7cb60 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -266,6 +266,7 @@ public enum BuiltInMethod {
UPPER(SqlFunctions.class, "upper", String.class),
LOWER(SqlFunctions.class, "lower", String.class),
JSONIZE(SqlFunctions.class, "jsonize", Object.class),
+ DEJSONIZE(SqlFunctions.class, "dejsonize", String.class),
JSON_VALUE_EXPRESSION(SqlFunctions.class, "jsonValueExpression",
String.class),
JSON_STRUCTURED_VALUE_EXPRESSION(SqlFunctions.class,
@@ -284,6 +285,7 @@ public enum BuiltInMethod {
SqlJsonConstructorNullClause.class),
JSON_TYPE(SqlFunctions.class, "jsonType", Object.class),
JSON_DEPTH(SqlFunctions.class, "jsonDepth", Object.class),
+ JSON_PRETTY(SqlFunctions.class, "jsonPretty", Object.class),
JSON_OBJECTAGG_ADD(SqlFunctions.class, "jsonObjectAggAdd", Map.class,
String.class, Object.class, SqlJsonConstructorNullClause.class),
JSON_ARRAY(SqlFunctions.class, "jsonArray",
@@ -533,6 +535,10 @@ public enum BuiltInMethod {
this(null, null, Types.lookupField(clazz, fieldName));
assert dummy : "dummy value for method overloading must be true";
}
+
+ public String getMethodName() {
+ return method.getName();
+ }
}
// End BuiltInMethod.java
diff --git
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
index acb35d1..fc6ef27 100644
---
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -280,4 +280,5 @@ AmbiguousSortOrderInJsonArrayAggFunc=Including both WITHIN
GROUP(...) and inside
ExceptionWhilePerformingQueryOnJdbcSubSchema = While executing SQL [{0}] on
JDBC sub-schema
UnknownObjectOfJsonType=Unknown JSON type in JSON_TYPE function, and the
object is: ''{0}''
UnknownObjectOfJsonDepth=Unknown JSON depth in JSON_DEPTH function, and the
object is: ''{0}''
+ExceptionWhileSerializingToJson=Cannot serialize object to JSON, and the
object is: ''{0}''
# End CalciteResource.properties
diff --git a/core/src/test/codegen/config.fmpp
b/core/src/test/codegen/config.fmpp
index c1096b0..d9ae98b 100644
--- a/core/src/test/codegen/config.fmpp
+++ b/core/src/test/codegen/config.fmpp
@@ -145,6 +145,7 @@ data: {
"JSON"
"JSON_TYPE"
"JSON_DEPTH"
+ "JSON_PRETTY"
"K"
"KEY"
"KEY_MEMBER"
diff --git
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
index 31c51e7..9a79b50 100644
---
a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
+++
b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java
@@ -2990,6 +2990,13 @@ public class RelToSqlConverterTest {
sql(query).ok(expected);
}
+ @Test public void testJsonPretty() {
+ String query = "select json_pretty(\"product_name\") from \"product\"";
+ final String expected = "SELECT JSON_PRETTY(\"product_name\" FORMAT
JSON)\n"
+ + "FROM \"foodmart\".\"product\"";
+ sql(query).ok(expected);
+ }
+
@Test public void testJsonValue() {
String query = "select json_value(\"product_name\", 'lax $') from
\"product\"";
// todo translate to JSON_VALUE rather than CAST
diff --git
a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 6badf4c..62d7852 100644
--- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -8427,6 +8427,13 @@ public class SqlParserTest {
"JSON_ARRAY(JSON_ARRAY('foo', 'bar' ABSENT ON NULL) FORMAT JSON ABSENT
ON NULL)");
}
+ @Test public void testJsonPretty() {
+ checkExp("json_pretty('foo')",
+ "JSON_PRETTY('foo' FORMAT JSON)");
+ checkExp("json_pretty(null)",
+ "JSON_PRETTY(NULL FORMAT JSON)");
+ }
+
@Test public void testJsonArrayAgg1() {
checkExp("json_arrayagg(\"column\")",
"JSON_ARRAYAGG(`column` ABSENT ON NULL)");
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 22a13e8..bb9c880 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
@@ -4475,6 +4475,15 @@ public abstract class SqlOperatorBaseTest {
"{\"foo\":{\"foo\":\"bar\"}}", "VARCHAR(2000) NOT NULL");
}
+ @Test public void testJsonPretty() {
+ tester.checkString("json_pretty('{\"foo\":100}')",
+ "{\n \"foo\" : 100\n}", "VARCHAR(2000) NOT NULL");
+ tester.checkString("json_pretty('[1,2,3]')",
+ "[ 1, 2, 3 ]", "VARCHAR(2000) NOT NULL");
+ tester.checkString("json_pretty('null')",
+ "null", "VARCHAR(2000) NOT NULL");
+ }
+
@Test public void testJsonType() {
tester.setFor(SqlStdOperatorTable.JSON_TYPE);
tester.checkString("json_type('\"1\"')",
diff --git a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
index 959aa12..86482a4 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -6817,6 +6817,18 @@ public class JdbcTest {
.returns("C1=3; C2=2; C3=1; C4=1\n");
}
+ @Test
+ public void testJsonPretty() {
+ CalciteAssert.that()
+ .query("SELECT JSON_PRETTY(v) AS c1\n"
+ + "FROM (VALUES ('{\"a\": [10, true],\"b\": [10, true]}')) as
t(v)\n"
+ + "limit 10")
+ .returns("C1={\n"
+ + " \"a\" : [ 10, true ],\n"
+ + " \"b\" : [ 10, true ]\n"
+ + "}\n");
+ }
+
/**
* Test case for
* <a
href="https://issues.apache.org/jira/browse/CALCITE-2609">[CALCITE-2609]
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 262a010..3912a3d 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java
@@ -23,8 +23,10 @@ import org.apache.calcite.sql.SqlJsonExistsErrorBehavior;
import org.apache.calcite.sql.SqlJsonQueryEmptyOrErrorBehavior;
import org.apache.calcite.sql.SqlJsonQueryWrapperBehavior;
import org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior;
+import org.apache.calcite.util.BuiltInMethod;
import com.google.common.collect.ImmutableMap;
+import com.google.common.primitives.Longs;
import com.jayway.jsonpath.InvalidJsonException;
import com.jayway.jsonpath.PathNotFoundException;
@@ -53,28 +55,6 @@ import static org.junit.Assert.fail;
* Unit test for the methods in {@link SqlFunctions} that implement JSON
processing functions.
*/
public class SqlJsonFunctionsTest {
- public static final String INVOC_DESC_JSON_VALUE_EXPRESSION =
- "jsonValueExpression";
- public static final String INVOC_DESC_JSON_STRUCTURED_VALUE_EXPRESSION =
- "jsonStructuredValueExpression";
- public static final String INVOC_DESC_JSON_API_COMMON_SYNTAX =
- "jsonApiCommonSyntax";
- public static final String INVOC_DESC_JSON_EXISTS = "jsonExists";
- public static final String INVOC_DESC_JSON_VALUE_ANY = "jsonValueAny";
- public static final String INVOC_DESC_JSON_QUERY = "jsonQuery";
- public static final String INVOC_DESC_JSONIZE = "jsonize";
- public static final String INVOC_DESC_DEJSONIZE = "dejsonize";
- public static final String INVOC_DESC_JSON_OBJECT = "jsonObject";
- public static final String INVOC_DESC_JSON_TYPE = "jsonType";
- public static final String INVOC_DESC_JSON_DEPTH = "jsonDepth";
- public static final String INVOC_DESC_JSON_OBJECT_AGG_ADD =
- "jsonObjectAggAdd";
- public static final String INVOC_DESC_JSON_ARRAY = "jsonArray";
- public static final String INVOC_DESC_JSON_ARRAY_AGG_ADD = "jsonArrayAggAdd";
- public static final String INVOC_DESC_IS_JSON_VALUE = "isJsonValue";
- public static final String INVOC_DESC_IS_JSON_SCALAR = "isJsonScalar";
- public static final String INVOC_DESC_IS_JSON_ARRAY = "isJsonArray";
- public static final String INVOC_DESC_IS_JSON_OBJECT = "isJsonObject";
@Test
public void testJsonValueExpression() {
@@ -445,6 +425,19 @@ public class SqlJsonFunctionsTest {
}
@Test
+ public void assertJsonPretty() {
+ assertJsonPretty(new HashMap<>(), is("{ }"));
+ assertJsonPretty(Longs.asList(1, 2), is("[ 1, 2 ]"));
+
+ Object input = new Object() {
+ private final Object self = this;
+ };
+ CalciteException expected = new CalciteException(
+ "Cannot serialize object to JSON, and the object is: '" + input + "'",
null);
+ assertJsonPrettyFailed(input, errorMatches(expected));
+ }
+
+ @Test
public void testDejsonize() {
assertDejsonize("{}",
is(Collections.emptyMap()));
@@ -568,34 +561,34 @@ public class SqlJsonFunctionsTest {
private void assertJsonValueExpression(String input,
Matcher<Object> matcher) {
assertThat(
- invocationDesc(INVOC_DESC_JSON_VALUE_EXPRESSION, input),
+ invocationDesc(BuiltInMethod.JSON_VALUE_EXPRESSION.getMethodName(),
input),
SqlFunctions.jsonValueExpression(input), matcher);
}
private void assertJsonStructuredValueExpression(Object input,
Matcher<Object> matcher) {
assertThat(
- invocationDesc(INVOC_DESC_JSON_STRUCTURED_VALUE_EXPRESSION, input),
+
invocationDesc(BuiltInMethod.JSON_STRUCTURED_VALUE_EXPRESSION.getMethodName(),
input),
SqlFunctions.jsonStructuredValueExpression(input), matcher);
}
private void assertJsonApiCommonSyntax(Object input, String pathSpec,
Matcher<? super SqlFunctions.PathContext> matcher) {
assertThat(
- invocationDesc(INVOC_DESC_JSON_API_COMMON_SYNTAX, input, pathSpec),
+ invocationDesc(BuiltInMethod.JSON_API_COMMON_SYNTAX.getMethodName(),
input, pathSpec),
SqlFunctions.jsonApiCommonSyntax(input, pathSpec), matcher);
}
private void assertJsonExists(Object input, SqlJsonExistsErrorBehavior
errorBehavior,
Matcher<? super Boolean> matcher) {
- assertThat(invocationDesc(INVOC_DESC_JSON_EXISTS, input, errorBehavior),
+ assertThat(invocationDesc(BuiltInMethod.JSON_EXISTS.getMethodName(),
input, errorBehavior),
SqlFunctions.jsonExists(input, errorBehavior), matcher);
}
private void assertJsonExistsFailed(Object input,
SqlJsonExistsErrorBehavior errorBehavior,
Matcher<? super Throwable> matcher) {
- assertFailed(invocationDesc(INVOC_DESC_JSON_EXISTS, input, errorBehavior),
+ assertFailed(invocationDesc(BuiltInMethod.JSON_EXISTS.getMethodName(),
input, errorBehavior),
() -> SqlFunctions.jsonExists(input, errorBehavior), matcher);
}
@@ -606,7 +599,7 @@ public class SqlJsonFunctionsTest {
Object defaultValueOnError,
Matcher<Object> matcher) {
assertThat(
- invocationDesc(INVOC_DESC_JSON_VALUE_ANY, input, emptyBehavior,
+ invocationDesc(BuiltInMethod.JSON_VALUE_ANY.getMethodName(), input,
emptyBehavior,
defaultValueOnEmpty, errorBehavior, defaultValueOnError),
SqlFunctions.jsonValueAny(input, emptyBehavior, defaultValueOnEmpty,
errorBehavior, defaultValueOnError),
@@ -620,7 +613,7 @@ public class SqlJsonFunctionsTest {
Object defaultValueOnError,
Matcher<? super Throwable> matcher) {
assertFailed(
- invocationDesc(INVOC_DESC_JSON_VALUE_ANY, input, emptyBehavior,
+ invocationDesc(BuiltInMethod.JSON_VALUE_ANY.getMethodName(), input,
emptyBehavior,
defaultValueOnEmpty, errorBehavior, defaultValueOnError),
() -> SqlFunctions.jsonValueAny(input, emptyBehavior,
defaultValueOnEmpty, errorBehavior, defaultValueOnError),
@@ -633,7 +626,7 @@ public class SqlJsonFunctionsTest {
SqlJsonQueryEmptyOrErrorBehavior errorBehavior,
Matcher<? super String> matcher) {
assertThat(
- invocationDesc(INVOC_DESC_JSON_QUERY, input, wrapperBehavior,
+ invocationDesc(BuiltInMethod.JSON_QUERY.getMethodName(), input,
wrapperBehavior,
emptyBehavior, errorBehavior),
SqlFunctions.jsonQuery(input, wrapperBehavior, emptyBehavior,
errorBehavior),
@@ -646,7 +639,7 @@ public class SqlJsonFunctionsTest {
SqlJsonQueryEmptyOrErrorBehavior errorBehavior,
Matcher<? super Throwable> matcher) {
assertFailed(
- invocationDesc(INVOC_DESC_JSON_QUERY, input, wrapperBehavior,
+ invocationDesc(BuiltInMethod.JSON_QUERY.getMethodName(), input,
wrapperBehavior,
emptyBehavior, errorBehavior),
() -> SqlFunctions.jsonQuery(input, wrapperBehavior, emptyBehavior,
errorBehavior),
@@ -655,21 +648,35 @@ public class SqlJsonFunctionsTest {
private void assertJsonize(Object input,
Matcher<? super String> matcher) {
- assertThat(invocationDesc(INVOC_DESC_JSONIZE, input),
+ assertThat(invocationDesc(BuiltInMethod.JSONIZE.getMethodName(), input),
SqlFunctions.jsonize(input),
matcher);
}
+ private void assertJsonPretty(Object input,
+ Matcher<? super String> matcher) {
+ assertThat(invocationDesc(BuiltInMethod.JSON_PRETTY.getMethodName(),
input),
+ SqlFunctions.jsonPretty(input),
+ matcher);
+ }
+
+ private void assertJsonPrettyFailed(Object input,
+ Matcher<? super Throwable> matcher) {
+ assertFailed(invocationDesc(BuiltInMethod.JSON_PRETTY.getMethodName(),
input),
+ () -> SqlFunctions.jsonPretty(input),
+ matcher);
+ }
+
private void assertDejsonize(String input,
Matcher<Object> matcher) {
- assertThat(invocationDesc(INVOC_DESC_DEJSONIZE, input),
+ assertThat(invocationDesc(BuiltInMethod.DEJSONIZE.getMethodName(), input),
SqlFunctions.dejsonize(input),
matcher);
}
private void assertDejsonizeFailed(String input,
Matcher<? super Throwable> matcher) {
- assertFailed(invocationDesc(INVOC_DESC_DEJSONIZE, input),
+ assertFailed(invocationDesc(BuiltInMethod.DEJSONIZE.getMethodName(),
input),
() -> SqlFunctions.dejsonize(input),
matcher);
}
@@ -677,7 +684,7 @@ public class SqlJsonFunctionsTest {
private void assertJsonObject(Matcher<? super String> matcher,
SqlJsonConstructorNullClause nullClause,
Object... kvs) {
- assertThat(invocationDesc(INVOC_DESC_JSON_OBJECT, nullClause, kvs),
+ assertThat(invocationDesc(BuiltInMethod.JSON_OBJECT.getMethodName(),
nullClause, kvs),
SqlFunctions.jsonObject(nullClause, kvs),
matcher);
}
@@ -685,7 +692,7 @@ public class SqlJsonFunctionsTest {
private void assertJsonType(Matcher<? super String> matcher,
String input) {
assertThat(
- invocationDesc(INVOC_DESC_JSON_TYPE, input),
+ invocationDesc(BuiltInMethod.JSON_TYPE.getMethodName(), input),
SqlFunctions.jsonType(
SqlFunctions.dejsonize(input)),
matcher);
@@ -694,7 +701,7 @@ public class SqlJsonFunctionsTest {
private void assertJsonDepth(Matcher<? super Integer> matcher,
String input) {
assertThat(
- invocationDesc(INVOC_DESC_JSON_DEPTH, input),
+ invocationDesc(BuiltInMethod.JSON_DEPTH.getMethodName(), input),
SqlFunctions.jsonDepth(
SqlFunctions.dejsonize(input)),
matcher);
@@ -705,13 +712,13 @@ public class SqlJsonFunctionsTest {
Matcher<? super Map> matcher) {
SqlFunctions.jsonObjectAggAdd(map, k, v, nullClause);
assertThat(
- invocationDesc(INVOC_DESC_JSON_OBJECT_AGG_ADD, map, k, v, nullClause),
+ invocationDesc(BuiltInMethod.JSON_ARRAYAGG_ADD.getMethodName(), map,
k, v, nullClause),
map, matcher);
}
private void assertJsonArray(Matcher<? super String> matcher,
SqlJsonConstructorNullClause nullClause, Object... elements) {
- assertThat(invocationDesc(INVOC_DESC_JSON_ARRAY, nullClause, elements),
+ assertThat(invocationDesc(BuiltInMethod.JSON_ARRAY.getMethodName(),
nullClause, elements),
SqlFunctions.jsonArray(nullClause, elements),
matcher);
}
@@ -721,35 +728,35 @@ public class SqlJsonFunctionsTest {
Matcher<? super List> matcher) {
SqlFunctions.jsonArrayAggAdd(list, element, nullClause);
assertThat(
- invocationDesc(INVOC_DESC_JSON_ARRAY_AGG_ADD, list, element,
+ invocationDesc(BuiltInMethod.JSON_ARRAYAGG_ADD.getMethodName(), list,
element,
nullClause),
list, matcher);
}
private void assertIsJsonValue(String input,
Matcher<? super Boolean> matcher) {
- assertThat(invocationDesc(INVOC_DESC_IS_JSON_VALUE, input),
+ assertThat(invocationDesc(BuiltInMethod.IS_JSON_VALUE.getMethodName(),
input),
SqlFunctions.isJsonValue(input),
matcher);
}
private void assertIsJsonScalar(String input,
Matcher<? super Boolean> matcher) {
- assertThat(invocationDesc(INVOC_DESC_IS_JSON_SCALAR, input),
+ assertThat(invocationDesc(BuiltInMethod.IS_JSON_SCALAR.getMethodName(),
input),
SqlFunctions.isJsonScalar(input),
matcher);
}
private void assertIsJsonArray(String input,
Matcher<? super Boolean> matcher) {
- assertThat(invocationDesc(INVOC_DESC_IS_JSON_ARRAY, input),
+ assertThat(invocationDesc(BuiltInMethod.IS_JSON_ARRAY.getMethodName(),
input),
SqlFunctions.isJsonArray(input),
matcher);
}
private void assertIsJsonObject(String input,
Matcher<? super Boolean> matcher) {
- assertThat(invocationDesc(INVOC_DESC_IS_JSON_OBJECT, input),
+ assertThat(invocationDesc(BuiltInMethod.IS_JSON_OBJECT.getMethodName(),
input),
SqlFunctions.isJsonObject(input),
matcher);
}
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index 434d284..158848c 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -10769,12 +10769,21 @@ public class SqlValidatorTest extends
SqlValidatorTestCase {
"(?s).*Expected a character type*");
}
+ @Test public void testJsonPretty() {
+ check("select json_pretty(ename) from emp");
+ checkExp("json_pretty('{\"foo\":\"bar\"}')");
+ checkExpType("json_pretty('{\"foo\":\"bar\"}')", "VARCHAR(2000) NOT NULL");
+ checkFails("select json_pretty(^NULL^) from emp", "(?s).*Illegal use of
.NULL.*");
+ checkFails("select json_pretty(^1^) from emp",
+ "(.*)JSON_VALUE_EXPRESSION(.*)");
+ }
+
@Test public void testJsonType() {
check("select json_type(ename) from emp");
checkExp("json_type('{\"foo\":\"bar\"}')");
checkExpType("json_type('{\"foo\":\"bar\"}')", "VARCHAR(20) NOT NULL");
checkFails("select json_type(^1^) from emp",
- "(.*)JSON_VALUE_EXPRESSION(.*)");
+ "(.*)JSON_VALUE_EXPRESSION(.*)");
}
@Test public void testJsonDepth() {
diff --git a/server/src/main/codegen/config.fmpp
b/server/src/main/codegen/config.fmpp
index f7d2318..0a110fd 100644
--- a/server/src/main/codegen/config.fmpp
+++ b/server/src/main/codegen/config.fmpp
@@ -153,6 +153,7 @@ data: {
"JSON"
"JSON_TYPE"
"JSON_DEPTH"
+ "JSON_PRETTY"
"K"
"KEY"
"KEY_MEMBER"
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 708ea79..198a236 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -567,6 +567,7 @@ JSON_DEPTH,
**JSON_EXISTS**,
**JSON_OBJECT**,
**JSON_OBJECTAGG**,
+JSON_PRETTY,
**JSON_QUERY**,
JSON_TYPE,
**JSON_VALUE**,
@@ -2003,6 +2004,7 @@ Note:
|:------------------------------------------------- |:-----------
| JSON_TYPE(value) | Returns a string
indicating the type of a JSON **value**. This can be an object, an array, or a
scalar type
| JSON_DEPTH(value) | Returns a integer
indicating the depth of a JSON **value**. This can be an object, an array, or a
scalar type
+| JSON_PRETTY(value) | Returns a
pretty-printing of JSON **value**.
* JSON_TYPE