This is an automated email from the ASF dual-hosted git repository.

mmior 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 cfc6a4d  [CALCITE-2864]Add the JSON_DEPTH function
cfc6a4d is described below

commit cfc6a4df50b49c697a2a4aba36279946140d86cc
Author: XuQianJin-Stars <[email protected]>
AuthorDate: Tue Feb 26 11:43:13 2019 +0800

    [CALCITE-2864]Add the JSON_DEPTH function
---
 babel/src/main/codegen/config.fmpp                 |  1 +
 core/custom-schema-model.json                      | 15 +++++
 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   | 44 ++++++++++++++
 .../calcite/sql/fun/SqlJsonDepthFunction.java      | 68 ++++++++++++++++++++++
 .../calcite/sql/fun/SqlStdOperatorTable.java       |  2 +
 .../org/apache/calcite/util/BuiltInMethod.java     |  1 +
 .../calcite/runtime/CalciteResource.properties     |  1 +
 core/src/test/codegen/config.fmpp                  |  1 +
 .../calcite/rel/rel2sql/RelToSqlConverterTest.java |  8 +++
 .../apache/calcite/sql/parser/SqlParserTest.java   | 10 ++++
 .../calcite/sql/test/SqlOperatorBaseTest.java      | 28 +++++++++
 .../java/org/apache/calcite/test/JdbcTest.java     | 12 ++++
 .../apache/calcite/test/SqlJsonFunctionsTest.java  | 23 ++++++++
 .../org/apache/calcite/test/SqlValidatorTest.java  |  8 +++
 server/src/main/codegen/config.fmpp                |  1 +
 site/_docs/reference.md                            | 25 +++++++-
 20 files changed, 272 insertions(+), 1 deletion(-)

diff --git a/babel/src/main/codegen/config.fmpp 
b/babel/src/main/codegen/config.fmpp
index f8f4a0b..de1efb7 100644
--- a/babel/src/main/codegen/config.fmpp
+++ b/babel/src/main/codegen/config.fmpp
@@ -140,6 +140,7 @@ data: {
         "JAVA"
         "JSON"
         "JSON_TYPE"
+        "JSON_DEPTH"
         "K"
         "KEY"
         "KEY_MEMBER"
diff --git a/core/custom-schema-model.json b/core/custom-schema-model.json
new file mode 100644
index 0000000..bde460d
--- /dev/null
+++ b/core/custom-schema-model.json
@@ -0,0 +1,15 @@
+{
+  version: '1.0',
+  defaultSchema: 'adhoc',
+  schemas: [
+    {
+      name: 'empty'
+    },
+    {
+      name: 'adhoc',
+      type: 'custom',
+      factory: 'org.apache.calcite.test.JdbcTest$MySchemaFactory',
+      operand: {'tableName': 'ELVIS'}
+    }
+  ]
+}
diff --git a/core/src/main/codegen/config.fmpp 
b/core/src/main/codegen/config.fmpp
index 4021ab1..a28294a 100644
--- a/core/src/main/codegen/config.fmpp
+++ b/core/src/main/codegen/config.fmpp
@@ -160,6 +160,7 @@ data: {
         "JAVA"
         "JSON"
         "JSON_TYPE"
+        "JSON_DEPTH"
         "K"
         "KEY"
         "KEY_MEMBER"
diff --git a/core/src/main/codegen/templates/Parser.jj 
b/core/src/main/codegen/templates/Parser.jj
index 07c8cf8..9bdae0d 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -4829,6 +4829,8 @@ SqlNode BuiltinFunctionCall() :
     |
         node = JsonTypeFunctionCall() { return node; }
     |
+        node = JsonDepthFunctionCall() { return node; }
+    |
         node = JsonObjectAggFunctionCall() { return node; }
     |
         node = JsonArrayFunctionCall() { return node; }
@@ -5264,6 +5266,22 @@ SqlCall JsonTypeFunctionCall() :
     }
 }
 
+SqlCall JsonDepthFunctionCall() :
+{
+    final SqlNode[] args = new SqlNode[1];
+    SqlNode e;
+    final Span span;
+}
+{
+    <JSON_DEPTH> { span = span(); }
+    <LPAREN> e = JsonValueExpression(true) {
+        args[0] = e;
+    }
+    <RPAREN> {
+        return SqlStdOperatorTable.JSON_DEPTH.createCall(span.end(this), args);
+    }
+}
+
 SqlCall JsonObjectAggFunctionCall() :
 {
     final SqlNode[] args = new SqlNode[2];
@@ -6339,6 +6357,7 @@ SqlPostfixOperator PostfixRowOperator() :
 |   < JSON_VALUE: "JSON_VALUE" >
 |   < JSON_OBJECT: "JSON_OBJECT">
 |   < JSON_TYPE: "JSON_TYPE">
+|   < JSON_DEPTH: "JSON_DEPTH">
 |   < JSON_OBJECTAGG: "JSON_OBJECTAGG">
 |   < JSON_QUERY: "JSON_QUERY" >
 |   < K: "K" >
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 6059d5e..a8112d2 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
@@ -162,6 +162,7 @@ import static 
org.apache.calcite.sql.fun.SqlStdOperatorTable.ITEM;
 import static 
org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_API_COMMON_SYNTAX;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAY;
 import static org.apache.calcite.sql.fun.SqlStdOperatorTable.JSON_ARRAYAGG;
+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;
@@ -452,6 +453,7 @@ public class RexImpTable {
     defineMethod(JSON_QUERY, BuiltInMethod.JSON_QUERY.method, NullPolicy.NONE);
     defineMethod(JSON_OBJECT, BuiltInMethod.JSON_OBJECT.method, 
NullPolicy.NONE);
     defineMethod(JSON_TYPE, BuiltInMethod.JSON_TYPE.method, NullPolicy.NONE);
+    defineMethod(JSON_DEPTH, BuiltInMethod.JSON_DEPTH.method, NullPolicy.NONE);
     aggMap.put(JSON_OBJECTAGG,
         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 c9da744..a7f2203 100644
--- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
+++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java
@@ -858,6 +858,9 @@ public interface CalciteResource {
 
   @BaseMessage("Unknown JSON type in JSON_TYPE function, and the object is: 
''{0}''")
   ExInst<CalciteException> unknownObjectOfJsonType(String value);
+
+  @BaseMessage("Unknown JSON depth in JSON_DEPTH function, and the object is: 
''{0}''")
+  ExInst<CalciteException> unknownObjectOfJsonDepth(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 6f17efd..2c35aba 100644
--- a/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
+++ b/core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java
@@ -67,12 +67,14 @@ import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Queue;
 import java.util.Set;
 import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicLong;
@@ -2712,6 +2714,48 @@ public class SqlFunctions {
     }
   }
 
+  public static Integer jsonDepth(Object o) {
+    final Integer result;
+    try {
+      if (o == null) {
+        result = null;
+      } else {
+        result = getJsonDepth(o);
+      }
+      return result;
+    } catch (Exception ex) {
+      throw RESOURCE.unknownObjectOfJsonDepth(o.toString()).ex();
+    }
+  }
+
+  private static Integer getJsonDepth(Object o) {
+    if (isScalarObject(o)) {
+      return 1;
+    }
+    Queue<Object> q = new LinkedList<>();
+    int depth = 0;
+    q.add(o);
+
+    while (!q.isEmpty()) {
+      int size = q.size();
+      for (int i = 0; i < size; ++i) {
+        Object obj = q.poll();
+        if (obj instanceof Map) {
+          for (Object value : ((LinkedHashMap) obj).values()) {
+            q.add(value);
+          }
+        } else if (obj instanceof Collection) {
+          for (Object value : (Collection) obj) {
+            q.add(value);
+          }
+        }
+      }
+      ++depth;
+    }
+
+    return depth;
+  }
+
   public static boolean isJsonValue(String input) {
     try {
       dejsonize(input);
diff --git 
a/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonDepthFunction.java 
b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonDepthFunction.java
new file mode 100644
index 0000000..3c9b360
--- /dev/null
+++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlJsonDepthFunction.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_DEPTH</code> function.
+ */
+public class SqlJsonDepthFunction extends SqlFunction {
+  public SqlJsonDepthFunction() {
+    super("JSON_DEPTH",
+            SqlKind.OTHER_FUNCTION,
+            ReturnTypes.INTEGER_NULLABLE,
+            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 SqlJsonDepthFunction.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 754f9c3..2e5b66b 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
@@ -1306,6 +1306,8 @@ public class SqlStdOperatorTable extends 
ReflectiveSqlOperatorTable {
 
   public static final SqlFunction JSON_TYPE = new SqlJsonTypeFunction();
 
+  public static final SqlFunction JSON_DEPTH = new SqlJsonDepthFunction();
+
   public static final SqlJsonObjectAggAggFunction JSON_OBJECTAGG =
       new SqlJsonObjectAggAggFunction("JSON_OBJECTAGG",
           SqlJsonConstructorNullClause.NULL_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 5e2c06f..f0ce346 100644
--- a/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
+++ b/core/src/main/java/org/apache/calcite/util/BuiltInMethod.java
@@ -283,6 +283,7 @@ public enum BuiltInMethod {
   JSON_OBJECT(SqlFunctions.class, "jsonObject",
       SqlJsonConstructorNullClause.class),
   JSON_TYPE(SqlFunctions.class, "jsonType", Object.class),
+  JSON_DEPTH(SqlFunctions.class, "jsonDepth", Object.class),
   JSON_OBJECTAGG_ADD(SqlFunctions.class, "jsonObjectAggAdd", Map.class,
       String.class, Object.class, SqlJsonConstructorNullClause.class),
   JSON_ARRAY(SqlFunctions.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 7c90a9b..acb35d1 100644
--- 
a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
+++ 
b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties
@@ -279,4 +279,5 @@ QueryExecutionTimeoutReached=Timeout of ''{0}'' ms for 
query execution is reache
 AmbiguousSortOrderInJsonArrayAggFunc=Including both WITHIN GROUP(...) and 
inside ORDER BY in a single JSON_ARRAYAGG call is not allowed
 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}''
 # End CalciteResource.properties
diff --git a/core/src/test/codegen/config.fmpp 
b/core/src/test/codegen/config.fmpp
index 991914e..c1096b0 100644
--- a/core/src/test/codegen/config.fmpp
+++ b/core/src/test/codegen/config.fmpp
@@ -144,6 +144,7 @@ data: {
         "JAVA"
         "JSON"
         "JSON_TYPE"
+        "JSON_DEPTH"
         "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 84f3047..31c51e7 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
@@ -3081,6 +3081,14 @@ public class RelToSqlConverterTest {
     sql(query).ok(expected);
   }
 
+  @Test public void testJsonDepth() {
+    String query = "select json_depth(\"product_name\") from \"product\"";
+    final String expected = "SELECT "
+            + "JSON_DEPTH(\"product_name\" FORMAT JSON)\n"
+            + "FROM \"foodmart\".\"product\"";
+    sql(query).ok(expected);
+  }
+
   /** Fluid interface to run tests. */
   static class Sql {
     private final SchemaPlus schema;
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 d431f51..6badf4c 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
@@ -8389,6 +8389,16 @@ public class SqlParserTest {
             "JSON_TYPE('{\"foo\": \"100\"}' FORMAT JSON)");
   }
 
+  @Test public void testJsonDepth() {
+    checkExp("json_depth('11.56')", "JSON_DEPTH('11.56' FORMAT JSON)");
+    checkExp("json_depth('{}')", "JSON_DEPTH('{}' FORMAT JSON)");
+    checkExp("json_depth(null)", "JSON_DEPTH(NULL FORMAT JSON)");
+    checkExp("json_depth('[\"foo\",null]')",
+            "JSON_DEPTH('[\"foo\",null]' FORMAT JSON)");
+    checkExp("json_depth('{\"foo\": \"100\"}')",
+            "JSON_DEPTH('{\"foo\": \"100\"}' FORMAT JSON)");
+  }
+
   @Test public void testJsonObjectAgg() {
     checkExp("json_objectagg(k_column: v_column)",
         "JSON_OBJECTAGG(KEY `K_COLUMN` VALUE `V_COLUMN` NULL 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 873f3bd..a5bc2e6 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
@@ -4498,6 +4498,34 @@ public abstract class SqlOperatorBaseTest {
             "STRING", "VARCHAR(20) NOT NULL");
   }
 
+  @Test public void testJsonDepth() {
+    tester.setFor(SqlStdOperatorTable.JSON_DEPTH);
+    tester.checkString("json_depth('1')",
+            "1", "INTEGER");
+    tester.checkString("json_depth('11.45')",
+            "1", "INTEGER");
+    tester.checkString("json_depth('true')",
+            "1", "INTEGER");
+    tester.checkString("json_depth('\"2019-01-27 21:24:00\"')",
+            "1", "INTEGER");
+    tester.checkString("json_depth('{}')",
+            "1", "INTEGER");
+    tester.checkString("json_depth('[]')",
+              "1", "INTEGER");
+    tester.checkString("json_depth('null')",
+            null, "INTEGER");
+    tester.checkString("json_depth(cast(null as varchar(1)))",
+            null, "INTEGER");
+    tester.checkString("json_depth('[10, true]')",
+            "2", "INTEGER");
+    tester.checkString("json_depth('[[], {}]')",
+              "2", "INTEGER");
+    tester.checkString("json_depth('{\"a\": [10, true]}')",
+            "3", "INTEGER");
+    tester.checkString("json_depth('[10, {\"a\": [[1,2]]}]')",
+            "5", "INTEGER");
+  }
+
   @Test public void testJsonObjectAgg() {
     checkAggType(tester, "json_objectagg('foo': 'bar')", "VARCHAR(2000) NOT 
NULL");
     tester.checkFails("^json_objectagg(100: 'bar')^",
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 fdab4d3..d64c90f 100644
--- a/core/src/test/java/org/apache/calcite/test/JdbcTest.java
+++ b/core/src/test/java/org/apache/calcite/test/JdbcTest.java
@@ -6804,6 +6804,18 @@ public class JdbcTest {
         .returns("C1=OBJECT; C2=ARRAY; C3=INTEGER; C4=BOOLEAN\n");
   }
 
+  @Ignore
+  @Test public void testJsonDepth() {
+    CalciteAssert.that()
+        .query("SELECT JSON_DEPTH(v) AS c1\n"
+            + ",JSON_DEPTH(JSON_VALUE(v, 'lax $.b' ERROR ON ERROR)) AS c2\n"
+            + ",JSON_DEPTH(JSON_VALUE(v, 'strict $.a[0]' ERROR ON ERROR)) AS 
c3\n"
+            + ",JSON_DEPTH(JSON_VALUE(v, 'strict $.a[1]' ERROR ON ERROR)) AS 
c4\n"
+            + "FROM (VALUES ('{\"a\": [10, true],\"b\": \"[10, true]\"}')) AS 
t(v)\n"
+            + "limit 10")
+        .returns("C1=3; C2=2; C3=1; C4=1\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 311f2c8..262a010 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlJsonFunctionsTest.java
@@ -66,6 +66,7 @@ public class SqlJsonFunctionsTest {
   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";
@@ -488,6 +489,19 @@ public class SqlJsonFunctionsTest {
   }
 
   @Test
+  public void testJsonDepth() {
+    assertJsonDepth(is(1), "{}");
+    assertJsonDepth(is(1), "false");
+    assertJsonDepth(is(1), "12");
+    assertJsonDepth(is(1), "11.22");
+    assertJsonDepth(is(2),
+            "[\"foo\",null]");
+    assertJsonDepth(is(3),
+            "{\"a\": [10, true]}");
+    assertJsonDepth(nullValue(), "null");
+  }
+
+  @Test
   public void testJsonObjectAggAdd() {
     Map<String, Object> map = new HashMap<>();
     Map<String, Object> expected = new HashMap<>();
@@ -677,6 +691,15 @@ public class SqlJsonFunctionsTest {
         matcher);
   }
 
+  private void assertJsonDepth(Matcher<? super Integer> matcher,
+                              String input) {
+    assertThat(
+            invocationDesc(INVOC_DESC_JSON_DEPTH, input),
+            SqlFunctions.jsonDepth(
+                    SqlFunctions.dejsonize(input)),
+            matcher);
+  }
+
   private void assertJsonObjectAggAdd(Map map, String k, Object v,
       SqlJsonConstructorNullClause nullClause,
       Matcher<? super Map> 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 882ab4b..434d284 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -10777,6 +10777,14 @@ public class SqlValidatorTest extends 
SqlValidatorTestCase {
             "(.*)JSON_VALUE_EXPRESSION(.*)");
   }
 
+  @Test public void testJsonDepth() {
+    check("select json_depth(ename) from emp");
+    checkExp("json_depth('{\"foo\":\"bar\"}')");
+    checkExpType("json_depth('{\"foo\":\"bar\"}')", "INTEGER");
+    checkFails("select json_depth(^1^) from emp",
+            "(.*)JSON_VALUE_EXPRESSION(.*)");
+  }
+
   @Test public void testJsonObjectAgg() {
     check("select json_objectagg(ename: empno) from emp");
     checkFails("select ^json_objectagg(empno: ename)^ from emp",
diff --git a/server/src/main/codegen/config.fmpp 
b/server/src/main/codegen/config.fmpp
index d4d7243..f7d2318 100644
--- a/server/src/main/codegen/config.fmpp
+++ b/server/src/main/codegen/config.fmpp
@@ -152,6 +152,7 @@ data: {
         "JAVA"
         "JSON"
         "JSON_TYPE"
+        "JSON_DEPTH"
         "K"
         "KEY"
         "KEY_MEMBER"
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 2ade413..708ea79 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -563,6 +563,7 @@ JAVA,
 JSON,
 **JSON_ARRAY**,
 **JSON_ARRAYAGG**,
+JSON_DEPTH,
 **JSON_EXISTS**,
 **JSON_OBJECT**,
 **JSON_OBJECTAGG**,
@@ -2000,7 +2001,10 @@ Note:
 
 | Operator syntax                                   | Description
 |:------------------------------------------------- |:-----------
-| 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_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_TYPE
 
 Example SQL:
 
@@ -2019,6 +2023,25 @@ Result:
 | ------ | ----- | ------- | ------- |
 | OBJECT | ARRAY | INTEGER | BOOLEAN |
 
+* JSON_DEPTH
+
+Example SQL:
+
+```SQL
+SELECT JSON_DEPTH(v) AS c1
+,JSON_DEPTH(JSON_VALUE(v, 'lax $.b' ERROR ON ERROR)) AS c2
+,JSON_DEPTH(JSON_VALUE(v, 'strict $.a[0]' ERROR ON ERROR)) AS c3
+,JSON_DEPTH(JSON_VALUE(v, 'strict $.a[1]' ERROR ON ERROR)) AS c4
+FROM (VALUES ('{"a": [10, true],"b": "[10, true]"}')) AS t(v)
+LIMIT 10;
+```
+
+Result:
+
+| c1     | c2    | c3      | c4      |
+| ------ | ----- | ------- | ------- |
+| 3      | 2     | 1       | 1       |
+
 ## User-defined functions
 
 Calcite is extensible. You can define each kind of function using user code.

Reply via email to