From 2425cb86a6af772c1b805292578a51a27378c317 Mon Sep 17 00:00:00 2001 From: duanzhengqiang Date: Wed, 20 Nov 2024 08:29:04 +0800 Subject: [PATCH] [CALCITE-6678] Calcite should support dual table query when db provides this feature Add comment for dummy.iq --- .../calcite/jdbc/CalciteConnectionImpl.java | 34 ++------- .../test/resources/sql/dual-table-query.iq | 72 +++++++++++++++++++ core/src/test/resources/sql/dummy.iq | 55 +------------- 3 files changed, 79 insertions(+), 82 deletions(-) create mode 100644 core/src/test/resources/sql/dual-table-query.iq diff --git a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java index b01b6ad9511..ac2fbc127f5 100644 --- a/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java +++ b/core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java @@ -18,7 +18,6 @@ import org.apache.calcite.DataContext; import org.apache.calcite.DataContexts; -import org.apache.calcite.adapter.java.AbstractQueryableTable; import org.apache.calcite.adapter.java.JavaTypeFactory; import org.apache.calcite.avatica.AvaticaConnection; import org.apache.calcite.avatica.AvaticaFactory; @@ -37,7 +36,6 @@ import org.apache.calcite.linq4j.BaseQueryable; import org.apache.calcite.linq4j.Enumerable; import org.apache.calcite.linq4j.Enumerator; -import org.apache.calcite.linq4j.Linq4j; import org.apache.calcite.linq4j.Ord; import org.apache.calcite.linq4j.QueryProvider; import org.apache.calcite.linq4j.Queryable; @@ -48,8 +46,6 @@ import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.prepare.CalciteCatalogReader; import org.apache.calcite.rel.type.DelegatingTypeSystem; -import org.apache.calcite.rel.type.RelDataType; -import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.rel.type.TimeFrameSet; import org.apache.calcite.rel.type.TimeFrames; @@ -59,6 +55,7 @@ import org.apache.calcite.schema.Schemas; import org.apache.calcite.schema.impl.AbstractSchema; import org.apache.calcite.schema.impl.LongSchemaVersion; +import org.apache.calcite.schema.impl.ViewTable; import org.apache.calcite.server.CalciteServer; import org.apache.calcite.server.CalciteServerStatement; import org.apache.calcite.sql.advise.SqlAdvisor; @@ -80,7 +77,6 @@ import java.lang.reflect.Type; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; @@ -156,7 +152,11 @@ protected CalciteConnectionImpl(Driver driver, AvaticaFactory factory, : CalciteSchema.createRootSchema(true)); // Add dual table metadata when isSupportedDualTable return true if (cfg.conformance().isSupportedDualTable()) { - this.rootSchema.add("DUAL", new DualTable(String.class)); + SchemaPlus schemaPlus = this.rootSchema.plus(); + // Dual table contains one row with a value X + schemaPlus.add( + "DUAL", ViewTable.viewMacro(schemaPlus, "VALUES ('X')", + ImmutableList.of(), null, false)); } checkArgument(this.rootSchema.isRoot(), "must be root schema"); this.properties.put(InternalProperty.CASE_SENSITIVE, cfg.caseSensitive()); @@ -629,26 +629,4 @@ static class CalciteServerStatementImpl this.iterator = iterator; } } - - /** Implementation of {@link AbstractQueryableTable} for dual table. */ - private static class DualTable extends AbstractQueryableTable { - - DualTable(Class clazz) { - super(clazz); - } - - @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) { - return typeFactory.createStructType( - // Dual table has one column DUMMY, and defined to be VARCHAR2(1) - Collections.singletonList(typeFactory.createJavaType(String.class)), - Collections.singletonList("DUMMY")); - } - - @SuppressWarnings("unchecked") - @Override public Queryable asQueryable(QueryProvider queryProvider, - SchemaPlus schema, String tableName) { - // Dual table contains one row with a value X - return Linq4j.asEnumerable(Collections.singletonList("X")).asQueryable(); - } - } } diff --git a/core/src/test/resources/sql/dual-table-query.iq b/core/src/test/resources/sql/dual-table-query.iq new file mode 100644 index 00000000000..ebcc61f7330 --- /dev/null +++ b/core/src/test/resources/sql/dual-table-query.iq @@ -0,0 +1,72 @@ +# dual-table-query.iq - Tests for DUAL table query +# +# 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. +# + +# [CALCITE-6678] Support dual table query (enabled in MySQL, Oracle libraries) +!set outputformat mysql +!use scott-mysql + +# MySQL supports users to specify the dual table, and also supports users not to specify the dual table. +SELECT 1 + 1 FROM DUAL; ++--------+ +| EXPR$0 | ++--------+ +| 2 | ++--------+ +(1 row) + +!ok + +SELECT 1 + 1; ++--------+ +| EXPR$0 | ++--------+ +| 2 | ++--------+ +(1 row) + +!ok + +# Oracle supports users to specify the dual table, but not supports users not to specify the dual table. +!use scott-oracle + +SELECT 1 + 1 FROM DUAL; ++--------+ +| EXPR$0 | ++--------+ +| 2 | ++--------+ +(1 row) + +!ok + +SELECT 1 + 1; +java.sql.SQLException: Error while executing SQL "SELECT 1 + 1": From line 1, column 1 to line 1, column 12: SELECT must have a FROM clause + +!error + +SELECT * FROM DUAL; ++--------+ +| EXPR$0 | ++--------+ +| X | ++--------+ +(1 row) + +!ok + +# End dual-table-query.iq diff --git a/core/src/test/resources/sql/dummy.iq b/core/src/test/resources/sql/dummy.iq index 7647c72dd6a..9e95b9e88c3 100644 --- a/core/src/test/resources/sql/dummy.iq +++ b/core/src/test/resources/sql/dummy.iq @@ -20,58 +20,5 @@ values 1; EXPR$0 1 !ok - -# [CALCITE-6678] Support dual table query (enabled in MySQL, Oracle libraries) -!set outputformat mysql -!use scott-mysql - -# MySQL supports users to specify the dual table, and also supports users not to specify the dual table. -SELECT 1 + 1 FROM DUAL; -+--------+ -| EXPR$0 | -+--------+ -| 2 | -+--------+ -(1 row) - -!ok - -SELECT 1 + 1; -+--------+ -| EXPR$0 | -+--------+ -| 2 | -+--------+ -(1 row) - -!ok - -# Oracle supports users to specify the dual table, but not supports users not to specify the dual table. -!use scott-oracle - -SELECT 1 + 1 FROM DUAL; -+--------+ -| EXPR$0 | -+--------+ -| 2 | -+--------+ -(1 row) - -!ok - -SELECT 1 + 1; -java.sql.SQLException: Error while executing SQL "SELECT 1 + 1": From line 1, column 1 to line 1, column 12: SELECT must have a FROM clause - -!error - -SELECT * FROM DUAL; -+-------+ -| DUMMY | -+-------+ -| X | -+-------+ -(1 row) - -!ok - +# do not modify this file, this is intended only for temporary debugging code # End dummy.iq