This is an automated email from the ASF dual-hosted git repository.
mbudiu 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 c3e0f9e3df [CALCITE-7060] Enable dumping high-level plans in quidem
tests
c3e0f9e3df is described below
commit c3e0f9e3dfe1ab3e26b1918ec216b66c160c5f83
Author: Mihai Budiu <[email protected]>
AuthorDate: Sat Jun 21 20:11:59 2025 +0200
[CALCITE-7060] Enable dumping high-level plans in quidem tests
Signed-off-by: Mihai Budiu <[email protected]>
---
.../org/apache/calcite/test/BabelQuidemTest.java | 63 ++--------------------
.../org/apache/calcite/test/CoreQuidemTest.java | 37 +++++++++++++
core/src/test/resources/sql/misc.iq | 7 +++
.../java/org/apache/calcite/test/QuidemTest.java | 60 +++++++++++++++++++++
4 files changed, 107 insertions(+), 60 deletions(-)
diff --git a/babel/src/test/java/org/apache/calcite/test/BabelQuidemTest.java
b/babel/src/test/java/org/apache/calcite/test/BabelQuidemTest.java
index 6f4dd75e79..12cdadda62 100644
--- a/babel/src/test/java/org/apache/calcite/test/BabelQuidemTest.java
+++ b/babel/src/test/java/org/apache/calcite/test/BabelQuidemTest.java
@@ -18,25 +18,14 @@
import org.apache.calcite.config.CalciteConnectionProperty;
import org.apache.calcite.config.Lex;
-import org.apache.calcite.jdbc.CalciteConnection;
import org.apache.calcite.materialize.MaterializationService;
-import org.apache.calcite.plan.Contexts;
-import org.apache.calcite.schema.SchemaPlus;
-import org.apache.calcite.sql.SqlNode;
-import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.dialect.BigQuerySqlDialect;
-import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.babel.SqlBabelParserImpl;
-import org.apache.calcite.sql.pretty.SqlPrettyWriter;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.sql.validate.SqlConformanceEnum;
-import org.apache.calcite.tools.Frameworks;
-import org.apache.calcite.tools.Planner;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
-import net.hydromatic.quidem.AbstractCommand;
import net.hydromatic.quidem.Command;
import net.hydromatic.quidem.CommandHandler;
import net.hydromatic.quidem.Quidem;
@@ -48,7 +37,6 @@
import java.util.Collection;
import java.util.List;
import java.util.Locale;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -158,54 +146,8 @@ public static void main(String[] args) throws Exception {
return new BabelCommandHandler();
}
- /** Command that prints the validated parse tree of a SQL statement. */
- static class ExplainValidatedCommand extends AbstractCommand {
- private final ImmutableList<String> lines;
- private final ImmutableList<String> content;
-
- ExplainValidatedCommand(List<String> lines, List<String> content,
- Set<String> unusedProductSet) {
- this.lines = ImmutableList.copyOf(lines);
- this.content = ImmutableList.copyOf(content);
- }
-
- @Override public void execute(Context x, boolean execute) throws Exception
{
- if (execute) {
- // use Babel parser
- final SqlParser.Config parserConfig =
- SqlParser.config().withParserFactory(SqlBabelParserImpl.FACTORY);
-
- // extract named schema from connection and use it in planner
- final CalciteConnection calciteConnection =
- x.connection().unwrap(CalciteConnection.class);
- final String schemaName = calciteConnection.getSchema();
- final SchemaPlus schema =
- schemaName != null
- ?
calciteConnection.getRootSchema().subSchemas().get(schemaName)
- : calciteConnection.getRootSchema();
- final Frameworks.ConfigBuilder config =
- Frameworks.newConfigBuilder()
- .defaultSchema(schema)
- .parserConfig(parserConfig)
- .context(Contexts.of(calciteConnection.config()));
-
- // parse, validate and un-parse
- final Quidem.SqlCommand sqlCommand = x.previousSqlCommand();
- final Planner planner = Frameworks.getPlanner(config.build());
- final SqlNode node = planner.parse(sqlCommand.sql);
- final SqlNode validateNode = planner.validate(node);
- final SqlWriter sqlWriter = new SqlPrettyWriter();
- validateNode.unparse(sqlWriter, 0, 0);
- x.echo(ImmutableList.of(sqlWriter.toSqlString().getSql()));
- } else {
- x.echo(content);
- }
- x.echo(lines);
- }
- }
-
/** Command handler that adds a "!explain-validated-on dialect..." command
- * (see {@link ExplainValidatedCommand}). */
+ * (see {@link QuidemTest.ExplainValidatedCommand}). */
private static class BabelCommandHandler implements CommandHandler {
@Override public @Nullable Command parseCommand(List<String> lines,
List<String> content, String line) {
@@ -219,7 +161,8 @@ private static class BabelCommandHandler implements
CommandHandler {
for (int i = 0; i < matcher.groupCount(); i++) {
set.add(matcher.group(i + 1));
}
- return new ExplainValidatedCommand(lines, content, set.build());
+ return new QuidemTest.ExplainValidatedCommand(
+ SqlBabelParserImpl.FACTORY, lines, content, set.build());
}
}
return null;
diff --git a/core/src/test/java/org/apache/calcite/test/CoreQuidemTest.java
b/core/src/test/java/org/apache/calcite/test/CoreQuidemTest.java
index bcf14f8a15..1aa6ab1871 100644
--- a/core/src/test/java/org/apache/calcite/test/CoreQuidemTest.java
+++ b/core/src/test/java/org/apache/calcite/test/CoreQuidemTest.java
@@ -19,12 +19,22 @@
import org.apache.calcite.config.CalciteConnectionProperty;
import org.apache.calcite.config.Lex;
import org.apache.calcite.sql.fun.SqlLibrary;
+import org.apache.calcite.sql.parser.impl.SqlParserImpl;
import org.apache.calcite.sql.validate.SqlConformanceEnum;
+import com.google.common.collect.ImmutableSet;
+
+import net.hydromatic.quidem.Command;
+import net.hydromatic.quidem.CommandHandler;
import net.hydromatic.quidem.Quidem;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
import java.sql.Connection;
import java.util.Collection;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static org.apache.calcite.util.Util.discard;
@@ -186,4 +196,31 @@ public void testSqlMisc(String path) throws Exception {
}
checkRun(path);
}
+
+ @Override protected CommandHandler createCommandHandler() {
+ return new ExtendedCommandHandler();
+ }
+
+ /** Command handler that adds a "!explain-validated-on dialect..." command
+ * (see {@link QuidemTest.ExplainValidatedCommand}). */
+ private static class ExtendedCommandHandler implements CommandHandler {
+ @Override public @Nullable Command parseCommand(List<String> lines,
+ List<String> content, String line) {
+ final String prefix = "explain-validated-on";
+ if (line.startsWith(prefix)) {
+ final Pattern pattern =
+ Pattern.compile("explain-validated-on( [-_+a-zA-Z0-9]+)*?");
+ final Matcher matcher = pattern.matcher(line);
+ if (matcher.matches()) {
+ final ImmutableSet.Builder<String> set = ImmutableSet.builder();
+ for (int i = 0; i < matcher.groupCount(); i++) {
+ set.add(matcher.group(i + 1));
+ }
+ return new QuidemTest.ExplainValidatedCommand(
+ SqlParserImpl.FACTORY, lines, content, set.build());
+ }
+ }
+ return null;
+ }
+ }
}
diff --git a/core/src/test/resources/sql/misc.iq
b/core/src/test/resources/sql/misc.iq
index 5b30a18535..4879f1eab8 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -18,6 +18,13 @@
!use post
!set outputformat mysql
+# [CALCITE-7060] Enable dumping high-level plans in quidem tests
+SELECT * FROM EMP WHERE DEPTNO > 20;
+SELECT "EMP"."ENAME", "EMP"."DEPTNO", "EMP"."GENDER"
+FROM "POST"."EMP" AS "EMP"
+WHERE "EMP"."DEPTNO" > 20
+!explain-validated-on Calcite
+
# [CALCITE-6751] Reduction of CAST from string to interval is incorrect
SELECT TIME '10:00:00' + CAST('1' AS INTERVAL SECOND);
+----------+
diff --git a/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java
b/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java
index 1ac85fb17d..ddc254e649 100644
--- a/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java
+++ b/testkit/src/main/java/org/apache/calcite/test/QuidemTest.java
@@ -20,6 +20,7 @@
import org.apache.calcite.avatica.AvaticaUtils;
import org.apache.calcite.config.CalciteConnectionProperty;
import org.apache.calcite.jdbc.CalciteConnection;
+import org.apache.calcite.plan.Contexts;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelOptRule;
import org.apache.calcite.plan.RelRule.Config;
@@ -30,17 +31,27 @@
import org.apache.calcite.rel.type.RelDataTypeFactory;
import org.apache.calcite.runtime.Hook;
import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.schema.impl.AbstractSchema;
import org.apache.calcite.schema.impl.AbstractTable;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlWriter;
+import org.apache.calcite.sql.parser.SqlParser;
+import org.apache.calcite.sql.parser.SqlParserImplFactory;
+import org.apache.calcite.sql.pretty.SqlPrettyWriter;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.test.schemata.catchall.CatchallSchema;
+import org.apache.calcite.tools.Frameworks;
+import org.apache.calcite.tools.Planner;
import org.apache.calcite.util.Bug;
import org.apache.calcite.util.Closer;
import org.apache.calcite.util.Sources;
import org.apache.calcite.util.Util;
+import com.google.common.collect.ImmutableList;
import com.google.common.io.PatternFilenameFilter;
+import net.hydromatic.quidem.AbstractCommand;
import net.hydromatic.quidem.CommandHandler;
import net.hydromatic.quidem.Quidem;
@@ -64,6 +75,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
@@ -78,6 +90,54 @@
*/
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public abstract class QuidemTest {
+ /** Command that prints the validated parse tree of a SQL statement. */
+ public static class ExplainValidatedCommand extends AbstractCommand {
+ private final ImmutableList<String> lines;
+ private final ImmutableList<String> content;
+ private final SqlParserImplFactory parserFactory;
+
+ ExplainValidatedCommand(SqlParserImplFactory parserFactory,
+ List<String> lines, List<String> content,
+ Set<String> unusedProductSet) {
+ this.lines = ImmutableList.copyOf(lines);
+ this.content = ImmutableList.copyOf(content);
+ this.parserFactory = parserFactory;
+ }
+
+ @Override public void execute(Context x, boolean execute) throws Exception
{
+ if (execute) {
+ // use Babel parser
+ final SqlParser.Config parserConfig =
+ SqlParser.config().withParserFactory(parserFactory);
+
+ // extract named schema from connection and use it in planner
+ final CalciteConnection calciteConnection =
+ x.connection().unwrap(CalciteConnection.class);
+ final String schemaName = calciteConnection.getSchema();
+ final SchemaPlus schema =
+ schemaName != null
+ ?
calciteConnection.getRootSchema().subSchemas().get(schemaName)
+ : calciteConnection.getRootSchema();
+ final Frameworks.ConfigBuilder config =
+ Frameworks.newConfigBuilder()
+ .defaultSchema(schema)
+ .parserConfig(parserConfig)
+ .context(Contexts.of(calciteConnection.config()));
+
+ // parse, validate and un-parse
+ final Quidem.SqlCommand sqlCommand = x.previousSqlCommand();
+ final Planner planner = Frameworks.getPlanner(config.build());
+ final SqlNode node = planner.parse(sqlCommand.sql);
+ final SqlNode validateNode = planner.validate(node);
+ final SqlWriter sqlWriter = new SqlPrettyWriter();
+ validateNode.unparse(sqlWriter, 0, 0);
+ x.echo(ImmutableList.of(sqlWriter.toSqlString().getSql()));
+ } else {
+ x.echo(content);
+ }
+ x.echo(lines);
+ }
+ }
private static final Pattern PATTERN = Pattern.compile("\\.iq$");