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 b42029f  [CALCITE-2985] Implement JSON_STORAGE_SIZE function 
(xuqianjin)
b42029f is described below

commit b42029fd46958ddf4d62a29182a2dbee66c1adef
Author: XuQianJin-Stars <[email protected]>
AuthorDate: Thu May 23 15:53:05 2019 +0800

    [CALCITE-2985] Implement JSON_STORAGE_SIZE function (xuqianjin)
    
    Also, correct content about error handling of MySQL JSON functions in 
documentation.
    
    Close apache/calcite#1150
---
 .../calcite/adapter/enumerable/RexImpTable.java    |  2 +
 .../apache/calcite/runtime/CalciteResource.java    |  3 +
 .../org/apache/calcite/runtime/JsonFunctions.java  | 13 ++++
 .../sql/fun/SqlJsonStorageSizeFunction.java        | 42 +++++++++++
 .../calcite/sql/fun/SqlLibraryOperators.java       |  3 +
 .../calcite/sql/fun/SqlStdOperatorTable.java       |  3 +
 .../org/apache/calcite/util/BuiltInMethod.java     |  1 +
 .../calcite/runtime/CalciteResource.properties     |  1 +
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java |  7 ++
 .../apache/calcite/sql/parser/SqlParserTest.java   |  7 ++
 .../calcite/sql/test/SqlOperatorBaseTest.java      | 22 ++++++
 .../java/org/apache/calcite/test/JdbcTest.java     | 11 +++
 .../apache/calcite/test/SqlJsonFunctionsTest.java  | 84 ++++++++++++----------
 .../org/apache/calcite/test/SqlValidatorTest.java  |  6 ++
 site/_docs/reference.md                            | 25 ++++++-
 15 files changed, 191 insertions(+), 39 deletions(-)

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 ab7e7ae..4093c2a 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
@@ -97,6 +97,7 @@ import static 
org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_KEYS;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_LENGTH;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_PRETTY;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_REMOVE;
+import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_STORAGE_SIZE;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.JSON_TYPE;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.REPEAT;
 import static org.apache.calcite.sql.fun.SqlLibraryOperators.REVERSE;
@@ -474,6 +475,7 @@ public class RexImpTable {
     defineMethod(JSON_PRETTY, BuiltInMethod.JSON_PRETTY.method, 
NullPolicy.ARG0);
     defineMethod(JSON_LENGTH, BuiltInMethod.JSON_LENGTH.method, 
NullPolicy.ARG0);
     defineMethod(JSON_REMOVE, BuiltInMethod.JSON_REMOVE.method, 
NullPolicy.ARG0);
+    defineMethod(JSON_STORAGE_SIZE, BuiltInMethod.JSON_STORAGE_SIZE.method, 
NullPolicy.ARG0);
     defineMethod(JSON_OBJECT, BuiltInMethod.JSON_OBJECT.method, 
NullPolicy.NONE);
     defineMethod(JSON_ARRAY, BuiltInMethod.JSON_ARRAY.method, NullPolicy.NONE);
     
aggMap.put(JSON_OBJECTAGG.with(SqlJsonConstructorNullClause.ABSENT_ON_NULL),
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 3a4033b..8f1c6c6 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -885,6 +885,9 @@ public interface CalciteResource {
 
   @BaseMessage("Invalid input for JSON_REMOVE: document: ''{0}'', jsonpath 
expressions: ''{1}''")
   ExInst<CalciteException> invalidInputForJsonRemove(String value, String 
pathSpecs);
+
+  @BaseMessage("Not a valid input for JSON_STORAGE_SIZE: ''{0}''")
+  ExInst<CalciteException> invalidInputForJsonStorageSize(String value);
 }
 
 // End CalciteResource.java
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 cf38f8c..f77b87e 100644
--- a/core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java
@@ -631,6 +631,19 @@ public class JsonFunctions {
     }
   }
 
+  public static Integer jsonStorageSize(String input) {
+    return jsonStorageSize(jsonValueExpression(input));
+  }
+
+  public static Integer jsonStorageSize(JsonValueContext input) {
+    try {
+      return JSON_PATH_JSON_PROVIDER.getObjectMapper()
+          .writeValueAsBytes(input.obj).length;
+    } catch (Exception e) {
+      throw 
RESOURCE.invalidInputForJsonStorageSize(Objects.toString(input.obj)).ex();
+    }
+  }
+
   public static boolean isJsonValue(String input) {
     try {
       dejsonize(input);
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonStorageSizeFunction.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonStorageSizeFunction.java
new file mode 100644
index 0000000..3ca9d4c
--- /dev/null
+++ 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonStorageSizeFunction.java
@@ -0,0 +1,42 @@
+/*
+ * 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.SqlFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.calcite.sql.type.SqlTypeTransforms;
+
+/**
+ * The <code>JSON_STORAGE_SIZE</code> function.
+ */
+public class SqlJsonStorageSizeFunction extends SqlFunction {
+
+  public SqlJsonStorageSizeFunction() {
+    super("JSON_STORAGE_SIZE",
+        SqlKind.OTHER_FUNCTION,
+        ReturnTypes.cascade(ReturnTypes.INTEGER,
+            SqlTypeTransforms.FORCE_NULLABLE),
+        null,
+        OperandTypes.ANY,
+        SqlFunctionCategory.SYSTEM);
+  }
+}
+
+// End SqlJsonStorageSizeFunction.java
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
index be28fe8..28c7f9f 100644
--- a/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlLibraryOperators.java
@@ -150,6 +150,9 @@ public abstract class SqlLibraryOperators {
   @LibraryOperator(libraries = {MYSQL})
   public static final SqlFunction JSON_REMOVE = new SqlJsonRemoveFunction();
 
+  @LibraryOperator(libraries = {MYSQL})
+  public static final SqlFunction JSON_STORAGE_SIZE = new 
SqlJsonStorageSizeFunction();
+
   @LibraryOperator(libraries = {MYSQL, POSTGRESQL})
   public static final SqlFunction REPEAT =
       new SqlFunction(
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 9f97d71..34a862a 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
@@ -1330,6 +1330,9 @@ public class SqlStdOperatorTable extends 
ReflectiveSqlOperatorTable {
   @Deprecated // to be removed before 2.0
   public static final SqlFunction JSON_REMOVE = 
SqlLibraryOperators.JSON_REMOVE;
 
+  @Deprecated // to be removed before 2.0
+  public static final SqlFunction JSON_STORAGE_SIZE = 
SqlLibraryOperators.JSON_STORAGE_SIZE;
+
   public static final SqlJsonArrayAggAggFunction JSON_ARRAYAGG =
       new SqlJsonArrayAggAggFunction(SqlKind.JSON_ARRAYAGG,
           SqlJsonConstructorNullClause.ABSENT_ON_NULL);
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 240a9e0..2ef7a35 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -297,6 +297,7 @@ public enum BuiltInMethod {
   JSON_PRETTY(JsonFunctions.class, "jsonPretty", String.class),
   JSON_LENGTH(JsonFunctions.class, "jsonLength", String.class),
   JSON_REMOVE(JsonFunctions.class, "jsonRemove", String.class),
+  JSON_STORAGE_SIZE(JsonFunctions.class, "jsonStorageSize", String.class),
   JSON_OBJECTAGG_ADD(JsonFunctions.class, "jsonObjectAggAdd", Map.class,
       String.class, Object.class, SqlJsonConstructorNullClause.class),
   JSON_ARRAY(JsonFunctions.class, "jsonArray",
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 bd33f6f..0a01778 100644
--- 
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++ 
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -288,4 +288,5 @@ ExceptionWhileSerializingToJson=Cannot serialize object to 
JSON: ''{0}''
 InvalidInputForJsonLength=Not a valid input for JSON_LENGTH: ''{0}''
 InvalidInputForJsonKeys=Not a valid input for JSON_KEYS: ''{0}''
 InvalidInputForJsonRemove=Invalid input for JSON_REMOVE: document: ''{0}'', 
jsonpath expressions: ''{1}''
+InvalidInputForJsonStorageSize=Not a valid input for JSON_STORAGE_SIZE: ''{0}''
 # End CalciteResource.properties
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 da7dc67..337c09c 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
@@ -3312,6 +3312,13 @@ public class RelToSqlConverterTest {
     sql(query).withSpark().ok(expected);
   }
 
+  @Test public void testJsonStorageSize() {
+    String query = "select json_storage_size(\"product_name\") from 
\"product\"";
+    final String expected = "SELECT JSON_STORAGE_SIZE(\"product_name\")\n"
+        + "FROM \"foodmart\".\"product\"";
+    sql(query).ok(expected);
+  }
+
   @Test public void testJsonType() {
     String query = "select json_type(\"product_name\") from \"product\"";
     final String expected = "SELECT "
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 31547a7..f145379 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
@@ -8682,6 +8682,13 @@ public class SqlParserTest {
             "JSON_PRETTY(NULL)");
   }
 
+  @Test public void testJsonStorageSize() {
+    checkExp("json_storage_size('foo')",
+        "JSON_STORAGE_SIZE('foo')");
+    checkExp("json_storage_size(null)",
+        "JSON_STORAGE_SIZE(NULL)");
+  }
+
   @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 ec77cae..a41c48b 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
@@ -4575,6 +4575,28 @@ public abstract class SqlOperatorBaseTest {
     tester.checkNull("json_pretty(cast(null as varchar))");
   }
 
+  @Test public void testJsonStorageSize() {
+    tester.checkString("json_storage_size('[100, \"sakila\", [1, 3, 5], 
425.05]')",
+        "29", "INTEGER");
+    tester.checkString("json_storage_size('{\"a\": 1000,\"b\": \"aa\", \"c\": 
\"[1, 3, 5]\"}')",
+        "35", "INTEGER");
+    tester.checkString("json_storage_size('{\"a\": 1000, \"b\": \"wxyz\", 
\"c\": \"[1, 3]\"}')",
+        "34", "INTEGER");
+    tester.checkString("json_storage_size('[100, \"json\", [[10, 20, 30], 3, 
5], 425.05]')",
+        "36", "INTEGER");
+    tester.checkString("json_storage_size('12')",
+        "2", "INTEGER");
+    tester.checkString("json_storage_size('12' format json)",
+        "2", "INTEGER");
+    tester.checkString("json_storage_size('null')",
+        "4", "INTEGER");
+
+    // nulls
+    tester.checkFails("json_storage_size(^null^)",
+        "(?s).*Illegal use of 'NULL'.*", false);
+    tester.checkNull("json_storage_size(cast(null as varchar))");
+  }
+
   @Test public void testJsonType() {
     tester.setFor(SqlLibraryOperators.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 2d5c78e..3e0f1fc 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -6899,6 +6899,17 @@ public class JdbcTest {
         .returns("C1=[\"a\",\"d\"]\n");
   }
 
+  @Test public void testJsonStorageSize() {
+    CalciteAssert.that()
+        .query("SELECT\n"
+            + "JSON_STORAGE_SIZE('[100, \"sakila\", [1, 3, 5], 425.05]') AS 
A,\n"
+            + "JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"a\", \"c\": \"[1, 3, 5, 
7]\"}') AS B,\n"
+            + "JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"xyz\", \"c\": \"[1, 3, 
5, 7]\"}') AS C,\n"
+            + "JSON_STORAGE_SIZE('[100, \"json\", [[10, 20, 30], 3, 5], 
425.05]') AS D\n"
+            + "limit 10")
+        .returns("A=29; B=35; C=37; D=36\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 7c85f70..151f069 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java
@@ -56,14 +56,12 @@ import static org.junit.Assert.fail;
  */
 public class SqlJsonFunctionsTest {
 
-  @Test
-  public void testJsonValueExpression() {
+  @Test public void testJsonValueExpression() {
     assertJsonValueExpression("{}",
         
is(JsonFunctions.JsonValueContext.withJavaObj(Collections.emptyMap())));
   }
 
-  @Test
-  public void testJsonApiCommonSyntax() {
+  @Test public void testJsonApiCommonSyntax() {
     assertJsonApiCommonSyntax("{\"foo\": \"bar\"}", "lax $.foo",
         contextMatches(
             
JsonFunctions.JsonPathContext.withJavaObj(JsonFunctions.PathMode.LAX, "bar")));
@@ -82,8 +80,7 @@ public class SqlJsonFunctionsTest {
             
JsonFunctions.JsonPathContext.withJavaObj(JsonFunctions.PathMode.LAX, 100)));
   }
 
-  @Test
-  public void testJsonExists() {
+  @Test public void testJsonExists() {
     assertJsonExists(
         
JsonFunctions.JsonPathContext.withJavaObj(JsonFunctions.PathMode.STRICT, "bar"),
         SqlJsonExistsErrorBehavior.FALSE,
@@ -145,8 +142,7 @@ public class SqlJsonFunctionsTest {
         errorMatches(new RuntimeException("java.lang.Exception: test 
message")));
   }
 
-  @Test
-  public void testJsonValueAny() {
+  @Test public void testJsonValueAny() {
     assertJsonValueAny(
         JsonFunctions.JsonPathContext
             .withJavaObj(JsonFunctions.PathMode.LAX, "bar"),
@@ -260,8 +256,7 @@ public class SqlJsonFunctionsTest {
                 + "and the actual value is: '[]'", null)));
   }
 
-  @Test
-  public void testJsonQuery() {
+  @Test public void testJsonQuery() {
     assertJsonQuery(
         JsonFunctions.JsonPathContext
             .withJavaObj(JsonFunctions.PathMode.LAX, 
Collections.singletonList("bar")),
@@ -413,14 +408,12 @@ public class SqlJsonFunctionsTest {
         is("[\"bar\"]"));
   }
 
-  @Test
-  public void testJsonize() {
+  @Test public void testJsonize() {
     assertJsonize(new HashMap<>(),
         is("{}"));
   }
 
-  @Test
-  public void assertJsonPretty() {
+  @Test public void assertJsonPretty() {
     assertJsonPretty(
         JsonFunctions.JsonValueContext.withJavaObj(new HashMap<>()), is("{ 
}"));
     assertJsonPretty(
@@ -435,8 +428,7 @@ public class SqlJsonFunctionsTest {
         JsonFunctions.JsonValueContext.withJavaObj(input), 
errorMatches(expected));
   }
 
-  @Test
-  public void testDejsonize() {
+  @Test public void testDejsonize() {
     assertDejsonize("{}",
         is(Collections.emptyMap()));
     assertDejsonize("[]",
@@ -451,8 +443,7 @@ public class SqlJsonFunctionsTest {
         errorMatches(new InvalidJsonException(message)));
   }
 
-  @Test
-  public void testJsonObject() {
+  @Test public void testJsonObject() {
     assertJsonObject(is("{}"), SqlJsonConstructorNullClause.NULL_ON_NULL);
     assertJsonObject(
         is("{\"foo\":\"bar\"}"), SqlJsonConstructorNullClause.NULL_ON_NULL,
@@ -468,8 +459,7 @@ public class SqlJsonFunctionsTest {
         null);
   }
 
-  @Test
-  public void testJsonType() {
+  @Test public void testJsonType() {
     assertJsonType(is("OBJECT"), "{}");
     assertJsonType(is("ARRAY"),
         "[\"foo\",null]");
@@ -479,8 +469,7 @@ public class SqlJsonFunctionsTest {
     assertJsonType(is("DOUBLE"), "11.22");
   }
 
-  @Test
-  public void testJsonDepth() {
+  @Test public void testJsonDepth() {
     assertJsonDepth(is(1), "{}");
     assertJsonDepth(is(1), "false");
     assertJsonDepth(is(1), "12");
@@ -492,8 +481,7 @@ public class SqlJsonFunctionsTest {
     assertJsonDepth(nullValue(), "null");
   }
 
-  @Test
-  public void testJsonLength() {
+  @Test public void testJsonLength() {
     assertJsonLength(
         JsonFunctions.JsonPathContext
             .withJavaObj(JsonFunctions.PathMode.LAX, 
Collections.singletonList("bar")),
@@ -512,7 +500,7 @@ public class SqlJsonFunctionsTest {
         is(1));
   }
 
-  public void testJsonKeys() {
+  @Test public void testJsonKeys() {
     assertJsonKeys(
         JsonFunctions.JsonPathContext
             .withJavaObj(JsonFunctions.PathMode.LAX, 
Collections.singletonList("bar")),
@@ -531,8 +519,7 @@ public class SqlJsonFunctionsTest {
         is("null"));
   }
 
-  @Test
-  public void testJsonRemove() {
+  @Test public void testJsonRemove() {
     assertJsonRemove(
         JsonFunctions.jsonValueExpression("{\"a\": 1, \"b\": [2]}"),
         new String[]{"$.a"},
@@ -543,8 +530,13 @@ public class SqlJsonFunctionsTest {
         is("{}"));
   }
 
-  @Test
-  public void testJsonObjectAggAdd() {
+  @Test public void testJsonStorageSize() {
+    assertJsonStorageSize("[100, \"sakila\", [1, 3, 5], 425.05]", is(29));
+    assertJsonStorageSize("null", is(4));
+    assertJsonStorageSize(JsonFunctions.JsonValueContext.withJavaObj(null), 
is(4));
+  }
+
+  @Test public void testJsonObjectAggAdd() {
     Map<String, Object> map = new HashMap<>();
     Map<String, Object> expected = new HashMap<>();
     expected.put("foo", "bar");
@@ -557,8 +549,7 @@ public class SqlJsonFunctionsTest {
         SqlJsonConstructorNullClause.ABSENT_ON_NULL, is(expected));
   }
 
-  @Test
-  public void testJsonArray() {
+  @Test public void testJsonArray() {
     assertJsonArray(is("[]"), SqlJsonConstructorNullClause.NULL_ON_NULL);
     assertJsonArray(
         is("[\"foo\"]"), SqlJsonConstructorNullClause.NULL_ON_NULL, "foo");
@@ -573,8 +564,7 @@ public class SqlJsonFunctionsTest {
         null);
   }
 
-  @Test
-  public void testJsonArrayAggAdd() {
+  @Test public void testJsonArrayAggAdd() {
     List<Object> list = new ArrayList<>();
     List<Object> expected = new ArrayList<>();
     expected.add("foo");
@@ -587,8 +577,7 @@ public class SqlJsonFunctionsTest {
         SqlJsonConstructorNullClause.ABSENT_ON_NULL, is(expected));
   }
 
-  @Test
-  public void testJsonPredicate() {
+  @Test public void testJsonPredicate() {
     assertIsJsonValue("[]", is(true));
     assertIsJsonValue("{}", is(true));
     assertIsJsonValue("100", is(true));
@@ -751,8 +740,29 @@ public class SqlJsonFunctionsTest {
   private void assertJsonRemove(JsonFunctions.JsonValueContext input, String[] 
pathSpecs,
       Matcher<? super String> matcher) {
     assertThat(invocationDesc(BuiltInMethod.JSON_REMOVE.getMethodName(), 
input, pathSpecs),
-             JsonFunctions.jsonRemove(input, pathSpecs),
-             matcher);
+        JsonFunctions.jsonRemove(input, pathSpecs),
+        matcher);
+  }
+
+  private void assertJsonStorageSize(String input,
+      Matcher<? super Integer> matcher) {
+    assertThat(invocationDesc(BuiltInMethod.JSON_STORAGE_SIZE.getMethodName(), 
input),
+        JsonFunctions.jsonStorageSize(input),
+        matcher);
+  }
+
+  private void assertJsonStorageSize(JsonFunctions.JsonValueContext input,
+      Matcher<? super Integer> matcher) {
+    assertThat(invocationDesc(BuiltInMethod.JSON_STORAGE_SIZE.getMethodName(), 
input),
+        JsonFunctions.jsonStorageSize(input),
+        matcher);
+  }
+
+  private void assertJsonStorageSizeFailed(String input,
+      Matcher<? super Throwable> matcher) {
+    
assertFailed(invocationDesc(BuiltInMethod.JSON_STORAGE_SIZE.getMethodName(), 
input),
+        () -> JsonFunctions.jsonStorageSize(input),
+        matcher);
   }
 
   private void assertDejsonize(String input,
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 ca428b4..cc1a4e3 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -11011,6 +11011,12 @@ public class SqlValidatorTest extends 
SqlValidatorTestCase {
             "(.*)JSON_VALUE_EXPRESSION(.*)");
   }
 
+  @Test public void testJsonStorageSize() {
+    check("select json_storage_size(ename) from emp");
+    checkExp("json_storage_size('{\"foo\":\"bar\"}')");
+    checkExpType("json_storage_size('{\"foo\":\"bar\"}')", "INTEGER");
+  }
+
   @Test public void testJsonType() {
     check("select json_type(ename) from emp");
     checkExp("json_type('{\"foo\":\"bar\"}')");
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index b1b5e33..5def065 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -2098,6 +2098,7 @@ semantics.
 | m | JSON_LENGTH(jsonValue [, path ])               | Returns a integer 
indicating the length of *jsonValue*
 | m | JSON_KEYS(jsonValue [, path ])                 | Returns a string 
indicating the keys of a JSON *jsonValue*
 | m | JSON_REMOVE(jsonValue, path[, path])           | Removes data from 
*jsonValue* using a series of *path* expressions and returns the result
+| m | JSON_STORAGE_SIZE(jsonValue)                   | Returns the number of 
bytes used to store the binary representation of a *jsonValue*
 | m | REVERSE(string)                                | Returns the reverse 
order of *string*
 | o | DECODE(value, value1, result1 [, valueN, resultN ]* [, default ]) | 
Compares *value* to each *valueN* value one by one; if *value* is equal to a 
*valueN*, returns the corresponding *resultN*, else returns *default*, or NULL 
if *default* is not specified
 | o | NVL(value1, value2)                            | Returns *value1* if 
*value1* is not null, otherwise *value2*
@@ -2114,8 +2115,7 @@ semantics.
 
 Note:
 
-* `JSON_TYPE` / `JSON_DEPTH` / `JSON_PRETTY` return null if the argument is 
null
-* `JSON_TYPE` / `JSON_DEPTH` / `JSON_PRETTY` throw error if the argument is 
not a valid JSON value
+* `JSON_TYPE` / `JSON_DEPTH` / `JSON_PRETTY` / `JSON_STORAGE_SIZE` return null 
if the argument is null
 * `JSON_LENGTH` / `JSON_KEYS` / `JSON_REMOVE` return null if the first 
argument is null
 * `JSON_TYPE` generally returns an upper-case string flag indicating the type 
of the JSON input. Currently supported supported type flags are:
   * INTEGER
@@ -2231,6 +2231,27 @@ LIMIT 10;
 | ---------- |
 | ["a", "d"] |
 
+
+##### JSON_STORAGE_SIZE example
+
+SQL
+
+ ```SQL
+SELECT
+JSON_STORAGE_SIZE('[100, \"sakila\", [1, 3, 5], 425.05]') AS c1,
+JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"a\", \"c\": \"[1, 3, 5, 7]\"}') AS c2,
+JSON_STORAGE_SIZE('{\"a\": 10, \"b\": \"xyz\", \"c\": \"[1, 3, 5, 7]\"}') AS 
c3,
+JSON_STORAGE_SIZE('[100, \"json\", [[10, 20, 30], 3, 5], 425.05]') AS c4
+limit 10;
+```
+
+ Result
+
+| c1 | c2 | c3 | c4 |
+| -- | ---| ---| -- |
+| 29 | 35 | 37 | 36 |
+
+
 #### DECODE example
 
 SQL

Reply via email to