julianhyde commented on code in PR #3480:
URL: https://github.com/apache/calcite/pull/3480#discussion_r1375148442
##########
core/src/main/java/org/apache/calcite/plan/RelOptUtil.java:
##########
@@ -3304,6 +3304,29 @@ public static RelNode createProject(RelNode child,
Mappings.TargetMapping mappin
return createProject(projectFactory, child,
Mappings.asListNonNull(mapping.inverse()));
}
+ /** Returns the relational table node for {@code tableName} if it occurs
within a
+ * relational expression {@code root} otherwise an empty option is returned.
*/
+ public static @Nullable RelOptTable findTable(RelNode root, final String
tableName) {
+ RelOptTable[] table = new RelOptTable[1];
+ try {
+ RelShuttle visitor = new RelHomogeneousShuttle() {
+ @Override public RelNode visit(TableScan scan) {
+ final RelOptTable scanTable = scan.getTable();
+ final List<String> qualifiedName = scanTable.getQualifiedName();
+ if (qualifiedName.get(qualifiedName.size() - 1).equals(tableName)) {
+ table[0] = scanTable;
+ throw Util.FoundOne.NULL;
Review Comment:
a bit simpler is `throw new Util.FoundOne(scanTable)`; then you don't need
the `table[]` variable.
##########
core/src/main/java/org/apache/calcite/sql/validate/WithItemRecursiveNameSpace.java:
##########
@@ -0,0 +1,78 @@
+/*
+ * 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.validate;
+
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.sql.SqlBasicCall;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlWith;
+import org.apache.calcite.sql.SqlWithItem;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.util.Pair;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Objects;
+
+/** Very similar to {@link WithItemNamespace} but created only for RECURSIVE
queries. */
+class WithItemRecursiveNameSpace extends WithItemNamespace {
+ private final SqlWithItem withItem;
+ private final SqlWithItemTableRef withItemTableRef;
+ WithItemRecursiveNameSpace(SqlValidatorImpl validator,
Review Comment:
and blank line and javadoc comment before constructor
##########
core/src/main/java/org/apache/calcite/sql/SqlKind.java:
##########
@@ -195,6 +195,9 @@ public enum SqlKind {
/** Item in WITH clause. */
WITH_ITEM,
+ /** Represents a recursive CTE as a table ref. **/
+ WITH_ITEM_TABLE_REF,
Review Comment:
change `**/` to `*/`
##########
core/src/main/java/org/apache/calcite/sql/validate/WithRecursiveScope.java:
##########
@@ -0,0 +1,76 @@
+/*
+ * 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.validate;
+
+import org.apache.calcite.rel.type.StructKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlWithItem;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/** Scope providing the objects that are being defined using the with clause to
+ * the with clause query definitions.
+ *
+ * <p>For example, in
+ *
+ * <blockquote>{@code WITH t1 AS (q1_can_use_t1) t2 AS (q2_can_use_t1_and_t2)
q3}</blockquote>
+ *
+ * <p>{@code t1} provides a scope that is used to validate {@code q2} and
{@code q1 with union}
+ * (and therefore {@code q2} may reference {@code t1} and {@code t2}),
+ * and {@code t2} provides a scope that is used to validate {@code q3}
+ * (and therefore q3 may reference {@code t1} and {@code t2}).
+ */
+class WithRecursiveScope extends ListScope {
+ private final SqlWithItem withItem;
+
+ /** Creates a WithScope. */
+ WithRecursiveScope(SqlValidatorScope parent, SqlWithItem withItem) {
Review Comment:
should be 'Creates a WithRecursiveScope'.
##########
core/src/main/java/org/apache/calcite/sql/validate/WithRecursiveScope.java:
##########
@@ -0,0 +1,76 @@
+/*
+ * 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.validate;
+
+import org.apache.calcite.rel.type.StructKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlWithItem;
+
+import com.google.common.collect.ImmutableList;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.List;
+
+/** Scope providing the objects that are being defined using the with clause to
Review Comment:
change "with clause" to "{@code WITH} clause"
##########
core/src/test/resources/sql/recursive_queries.iq:
##########
@@ -0,0 +1,507 @@
+# recursive_queries.iq - recursive queries using WITH CTE
+#
+# 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.
+#
+!use scott
+!set outputformat mysql
+
+WITH RECURSIVE FactorialCTE(n, a) AS (
+ SELECT 1, 1
+ UNION ALL
+ SELECT n + 1, a * (n + 1)
+ FROM FactorialCTE
+ WHERE n < 11
+)
+SELECT a FROM FactorialCTE WHERE n = 10;
++---------+
+| A |
++---------+
+| 3628800 |
++---------+
+(1 row)
+
+!ok
+
+WITH RECURSIVE FibonacciCTE(n, a, b) AS (
Review Comment:
Thanks for all these fabulous test queries.
I don't think I saw any mutually recursive queries. E.g.
```
WITH RECURSIVE f AS (SELECT ... FROM g),
g AS (SELECT ... FROM f),
z AS (SELECT ... FROM somethingElse)
SELECT ... FROM f, z
```
Are mutually recursive queries valid (per the SQL standard)? Does your
implementation support them?
##########
core/src/main/java/org/apache/calcite/sql/SqlWithItem.java:
##########
@@ -30,13 +30,16 @@
public class SqlWithItem extends SqlCall {
public SqlIdentifier name;
public @Nullable SqlNodeList columnList; // may be null
+ public SqlLiteral recursive;
public SqlNode query;
public SqlWithItem(SqlParserPos pos, SqlIdentifier name,
- @Nullable SqlNodeList columnList, SqlNode query) {
+ @Nullable SqlNodeList columnList, SqlNode query,
+ SqlLiteral recursive) {
Review Comment:
@HanumathRao Thanks keeping the old constructor, as @zabetak requested.
Please add '// to be removed before 2.0'.
And make it call the new constructor (via `this(...)`); it prevents the code
diverging, and is a single place to put a debugger break-point.
##########
core/src/main/java/org/apache/calcite/sql/validate/WithItemRecursiveNameSpace.java:
##########
@@ -0,0 +1,78 @@
+/*
+ * 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.validate;
+
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.sql.SqlBasicCall;
+import org.apache.calcite.sql.SqlIdentifier;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlWith;
+import org.apache.calcite.sql.SqlWithItem;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.util.Pair;
+
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+import java.util.Objects;
Review Comment:
In new code, I am doing `import static java.util.Objects.requireNonNull`
rather than `import java.util.Objects`.
##########
core/src/main/java/org/apache/calcite/sql/validate/WithScope.java:
##########
@@ -70,4 +73,8 @@ class WithScope extends ListScope {
}
super.resolveTable(names, nameMatcher, path, resolved);
}
+
+ public @Nullable WithRecursiveScope getRecursiveScope() {
+ return recursiveScope;
+ }
}
Review Comment:
Since the class is not `public`, there's no need for a `public` method. I'd
remove this method, and just make the `recursiveScope` field package-protected.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]