This is an automated email from the ASF dual-hosted git repository. rubenql pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/calcite.git
The following commit(s) were added to refs/heads/main by this push: new 5151168e9a [CALCITE-6014] Create a SqlOperatorFixture that parses, unparses, and then parses again before executing 5151168e9a is described below commit 5151168e9a9035595939c2ae0f21a06984229209 Author: Mihai Budiu <mbu...@gmail.com> AuthorDate: Fri Oct 13 11:42:07 2023 -0700 [CALCITE-6014] Create a SqlOperatorFixture that parses, unparses, and then parses again before executing Signed-off-by: Mihai Budiu <mbu...@gmail.com> --- .../calcite/test/SqlOperatorUnparseTest.java | 116 +++++++++++++++++++++ .../calcite/test/SqlOperatorFixtureImpl.java | 2 +- 2 files changed, 117 insertions(+), 1 deletion(-) diff --git a/core/src/test/java/org/apache/calcite/test/SqlOperatorUnparseTest.java b/core/src/test/java/org/apache/calcite/test/SqlOperatorUnparseTest.java new file mode 100644 index 0000000000..13512d1aa4 --- /dev/null +++ b/core/src/test/java/org/apache/calcite/test/SqlOperatorUnparseTest.java @@ -0,0 +1,116 @@ +/* + * 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.test; + +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.parser.SqlParseException; +import org.apache.calcite.sql.parser.SqlParser; +import org.apache.calcite.sql.test.SqlOperatorFixture; +import org.apache.calcite.sql.test.SqlTestFactory; + +import org.junit.jupiter.api.Disabled; + +import java.util.function.Consumer; +import java.util.function.UnaryOperator; + +/** + * Version of a SqlOperatorTest which first parses and unparses + * the test program before executing it. Although similar to + * {@link org.apache.calcite.sql.parser.SqlUnParserTest}, + * this test also validates the code after unparsing. + */ +@SuppressWarnings("JavadocReference") +public class SqlOperatorUnparseTest extends CalciteSqlOperatorTest { + /** Fixture that runs an operator test after parsing and unparsing a query. */ + static class SqlOperatorFixtureUnparseImpl extends SqlOperatorFixtureImpl { + SqlOperatorFixtureUnparseImpl(SqlTestFactory factory) { + super(factory, new UnparseTester(factory), false); + } + + /** + * Retrieve the tester as an UnparseTester. A downcast is needed because + * our tester implements a richer API than a regular SqlTester -- for example, + * it has a method withFactory. + */ + UnparseTester getUnparseTester() { + return (UnparseTester) this.getTester(); + } + + public static final SqlOperatorFixtureImpl DEFAULT = + new SqlOperatorFixtureUnparseImpl(SqlTestFactory.INSTANCE); + + @Override public SqlOperatorFixture withFactory(UnaryOperator<SqlTestFactory> transform) { + return super + .withFactory(transform) + // Pass the transform to the tester + .withTester(t -> this.getUnparseTester().withFactory(transform)); + } + } + + @Override protected SqlOperatorFixture fixture() { + return SqlOperatorFixtureUnparseImpl.DEFAULT; + } + + /** A tester which parses, unparses, and then tests a query. */ + static class UnparseTester extends TesterImpl { + public final SqlTestFactory factory; + + UnparseTester(SqlTestFactory factory) { + this.factory = factory; + } + + TesterImpl withFactory(UnaryOperator<SqlTestFactory> transform) { + return new UnparseTester(transform.apply(this.factory)); + } + + String rewrite(String sql) throws SqlParseException { + final SqlParser parser = factory.createParser(sql); + final SqlNode sqlNode = parser.parseStmt(); + return sqlNode.toSqlString(c -> c).getSql(); + } + + @Override public void forEachQuery( + SqlTestFactory factory, String expression, Consumer<String> consumer) { + consumer.accept(buildQuery2(factory, expression)); + } + + @Override public void check(SqlTestFactory factory, String sql, TypeChecker typeChecker, + ParameterChecker parameterChecker, ResultChecker resultChecker) { + try { + String optQuery = this.rewrite(sql); + super.check(factory, optQuery, typeChecker, parameterChecker, resultChecker); + } catch (SqlParseException e) { + throw new RuntimeException(e); + } + } + } + + // Every test that is Disabled below corresponds to a bug. + // These tests should just be deleted when the corresponding bugs are fixed. + + @Override @Disabled("https://issues.apache.org/jira/browse/CALCITE-5998 " + + "The SAFE_OFFSET operator can cause an index out of bounds exception") + void testSafeOffsetOperator() { + super.testSafeOffsetOperator(); + } + + @Override @Disabled("https://issues.apache.org/jira/browse/CALCITE-6002 " + + "CONTAINS_SUBSTR does not unparse correctly") + void testContainsSubstrFunc() { + super.testContainsSubstrFunc(); + } +} diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorFixtureImpl.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorFixtureImpl.java index ef847d2a90..0f7a4d0e1d 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorFixtureImpl.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorFixtureImpl.java @@ -76,7 +76,7 @@ class SqlOperatorFixtureImpl implements SqlOperatorFixture { return tester; } - @Override public SqlOperatorFixtureImpl withFactory( + @Override public SqlOperatorFixture withFactory( UnaryOperator<SqlTestFactory> transform) { final SqlTestFactory factory = transform.apply(this.factory); if (factory == this.factory) {