-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[CALCITE-5529] Improve dialect tests, part 1: check each query agains…
…t a reference dialect Create class RelToSqlFixture (was inner class RelToSqlConverterTest.Sql). This fixture has a list of dialects for which the test is enabled, and a reference dialect (currently always Calcite). When the test calls 'done()' on the fixture, the fixture checks the query against the reference dialect. In future, it will also execute the query against each enabled dialect. To ensure that each test remembers to call 'done'()', add a 'token pool' to the test framework. If a token has been opened but not closed, the framework prints the call stack of the 'open' call and fails the test. Add enum DialectCode, which defines the dialects (or dialect configurations) that are possible to test. Adding a DialectCode has a cost (e.g. a bunch of new Quidem recording files) so we should not add one without a good reason. After this change, all queries succeed against the reference dialect (Calcite). A few cases are disabled due to bugs; we should fix these bugs and enable the tests. This is just part 1. Part 2 will be to get the tests to succeed against another dialect (probably a local instance of Postgres). Part 3 will be to use a Quidem recording rather than a live Postgres instance. Part 4 will be to enable this framework for other tests (e.g. SqlOperatorTest). Close #4206
- Loading branch information
1 parent
ce64da0
commit d7e1d02
Showing
12 changed files
with
3,647 additions
and
2,029 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -150,6 +150,16 @@ protected CalciteConnectionImpl(Driver driver, AvaticaFactory factory, | |
requireNonNull(rootSchema != null | ||
? rootSchema | ||
: CalciteSchema.createRootSchema(true)); | ||
|
||
final String schema = cfg.schema(); | ||
if (schema != null && !schema.isEmpty()) { | ||
try { | ||
setSchema(schema); | ||
Check failure on line 157 in core/src/main/java/org/apache/calcite/jdbc/CalciteConnectionImpl.java
|
||
} catch (SQLException e) { | ||
throw new AssertionError(e); // not possible | ||
} | ||
} | ||
|
||
// Add dual table metadata when isSupportedDualTable return true | ||
if (cfg.conformance().isSupportedDualTable()) { | ||
SchemaPlus schemaPlus = this.rootSchema.plus(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
/* | ||
* 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.util; | ||
|
||
import java.util.Map; | ||
import java.util.concurrent.ConcurrentHashMap; | ||
import java.util.concurrent.atomic.AtomicInteger; | ||
|
||
/** Hands out tokens, and throws if they are not all released. | ||
* | ||
* <p>Typical use: | ||
* | ||
* <blockquote><pre>{@code | ||
* Token.Pool pool = Token.pool(); | ||
* Token token1 = pool.token(); | ||
* Token token2 = pool.token(); | ||
* token1.close(); | ||
* pool.assertEmpty(); // throws because token2 has not been closed | ||
* }</pre></blockquote> | ||
* */ | ||
public class Token implements AutoCloseable { | ||
private final Pool pool; | ||
private final int id; | ||
private final StackTraceElement[] stackElements; | ||
|
||
/** Creates a Token. Should only be called from {@link Pool#token()}. */ | ||
private Token(Pool pool, int id, StackTraceElement[] stackElements) { | ||
this.pool = pool; | ||
this.id = id; | ||
this.stackElements = stackElements; | ||
} | ||
|
||
@Override public String toString() { | ||
return Integer.toString(id); | ||
} | ||
|
||
/** Releases this Token. */ | ||
@Override public void close() { | ||
if (!pool.release(id)) { | ||
final RuntimeException x = | ||
new RuntimeException("token " + id + " has already released"); | ||
x.setStackTrace(stackElements); | ||
throw x; | ||
} | ||
} | ||
|
||
/** Creates a pool. */ | ||
public static Pool pool() { | ||
return new Pool(); | ||
} | ||
|
||
/** A collection of tokens. | ||
* | ||
* <p>It is thread-safe. */ | ||
public static class Pool { | ||
private final Map<Integer, Token> map = new ConcurrentHashMap<>(); | ||
private final AtomicInteger ordinal = new AtomicInteger(); | ||
|
||
/** Creates a token. */ | ||
public Token token() { | ||
return map.computeIfAbsent(ordinal.getAndIncrement(), | ||
id -> | ||
new Token(Pool.this, id, Thread.currentThread().getStackTrace())); | ||
} | ||
|
||
/** Releases a token id. Should be called from {@link Token#close()}. */ | ||
@SuppressWarnings("resource") | ||
private boolean release(int id) { | ||
return map.remove(id) != null; | ||
} | ||
|
||
/** Throws if not all fixtures have been released. */ | ||
public void assertEmpty() { | ||
int size = map.size(); | ||
if (!map.isEmpty()) { | ||
final RuntimeException x = | ||
new RuntimeException("map should be empty, but contains " + size | ||
+ " tokens"); | ||
x.setStackTrace(map.values().iterator().next().stackElements); | ||
throw x; | ||
} | ||
} | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
core/src/test/java/org/apache/calcite/rel/rel2sql/DialectCode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* | ||
* 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.rel.rel2sql; | ||
|
||
import org.apache.calcite.config.NullCollation; | ||
import org.apache.calcite.sql.SqlDialect; | ||
import org.apache.calcite.sql.dialect.AnsiSqlDialect; | ||
|
||
import static org.apache.calcite.rel.rel2sql.DialectTestConfigs.JETHRO_DIALECT_SUPPLIER; | ||
|
||
/** Dialect code. */ | ||
enum DialectCode { | ||
ANSI(new AnsiSqlDialect(SqlDialect.EMPTY_CONTEXT)), | ||
BIG_QUERY(SqlDialect.DatabaseProduct.BIG_QUERY), | ||
CALCITE(SqlDialect.DatabaseProduct.CALCITE), | ||
CLICKHOUSE(SqlDialect.DatabaseProduct.CLICKHOUSE), | ||
DB2(SqlDialect.DatabaseProduct.DB2), | ||
EXASOL(SqlDialect.DatabaseProduct.EXASOL), | ||
FIREBOLT(SqlDialect.DatabaseProduct.FIREBOLT), | ||
HIVE(SqlDialect.DatabaseProduct.HIVE), | ||
HIVE_2_0(DialectTestConfigs.hiveDialect(2, 0)), | ||
HIVE_2_1(DialectTestConfigs.hiveDialect(2, 1)), | ||
HIVE_2_2(DialectTestConfigs.hiveDialect(2, 2)), | ||
HSQLDB(SqlDialect.DatabaseProduct.HSQLDB), | ||
INFORMIX(SqlDialect.DatabaseProduct.INFORMIX), | ||
JETHRO(JETHRO_DIALECT_SUPPLIER.get()), | ||
MOCK(new MockSqlDialect()), | ||
MSSQL_2008(DialectTestConfigs.mssqlDialect(10)), | ||
MSSQL_2012(DialectTestConfigs.mssqlDialect(11)), | ||
MSSQL_2017(DialectTestConfigs.mssqlDialect(14)), | ||
MYSQL(SqlDialect.DatabaseProduct.MYSQL), | ||
MYSQL_8(DialectTestConfigs.mysqlDialect(8, null)), | ||
MYSQL_FIRST(DialectTestConfigs.mysqlDialect(8, NullCollation.FIRST)), | ||
MYSQL_HIGH(DialectTestConfigs.mysqlDialect(8, NullCollation.HIGH)), | ||
MYSQL_LAST(DialectTestConfigs.mysqlDialect(8, NullCollation.LAST)), | ||
NON_ORDINAL(DialectTestConfigs.nonOrdinalDialect()), | ||
ORACLE(SqlDialect.DatabaseProduct.ORACLE), | ||
ORACLE_11(DialectTestConfigs.oracleDialect(11, null)), | ||
ORACLE_12(DialectTestConfigs.oracleDialect(12, null)), | ||
ORACLE_19(DialectTestConfigs.oracleDialect(19, null)), | ||
ORACLE_23(DialectTestConfigs.oracleDialect(23, null)), | ||
/** Oracle dialect with max length for varchar set to 512. */ | ||
ORACLE_MODIFIED(DialectTestConfigs.oracleDialect(12, 512)), | ||
POSTGRESQL(SqlDialect.DatabaseProduct.POSTGRESQL), | ||
/** Postgresql dialect with max length for varchar set to 256. */ | ||
POSTGRESQL_MODIFIED(DialectTestConfigs.postgresqlDialect(256, false)), | ||
/** Postgresql dialect with modified decimal type. */ | ||
POSTGRESQL_MODIFIED_DECIMAL( | ||
DialectTestConfigs.postgresqlDialect(null, true)), | ||
PRESTO(SqlDialect.DatabaseProduct.PRESTO), | ||
REDSHIFT(SqlDialect.DatabaseProduct.REDSHIFT), | ||
SNOWFLAKE(SqlDialect.DatabaseProduct.SNOWFLAKE), | ||
SPARK(SqlDialect.DatabaseProduct.SPARK), | ||
STARROCKS(SqlDialect.DatabaseProduct.STARROCKS), | ||
SYBASE(SqlDialect.DatabaseProduct.SYBASE), | ||
VERTICA(SqlDialect.DatabaseProduct.VERTICA); | ||
|
||
private final DialectTestConfig.Dialect dialect; | ||
|
||
DialectCode(SqlDialect.DatabaseProduct databaseProduct) { | ||
dialect = DialectTestConfig.Dialect.of(this, databaseProduct); | ||
} | ||
|
||
DialectCode(SqlDialect sqlDialect) { | ||
dialect = DialectTestConfig.Dialect.of(this, sqlDialect); | ||
} | ||
|
||
DialectTestConfig.Dialect toDialect() { | ||
return dialect; | ||
} | ||
} |
Oops, something went wrong.