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$");
 

Reply via email to