Skip to content

Commit e75b621

Browse files
authored
feat(isthmus): add method to convert Plan into SQL strings using dialect (#704)
This PR adds a convenience function for translating a Substrait `Plan` to a list of SQL strings in a given Calcite `SqlDialect`. Signed-off-by: Niels Pardon <par@zurich.ibm.com>
1 parent ae0c420 commit e75b621

2 files changed

Lines changed: 36 additions & 21 deletions

File tree

examples/isthmus-api/src/main/java/io/substrait/examples/ToSql.java

Lines changed: 3 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
package io.substrait.examples;
22

33
import io.substrait.examples.IsthmusAppExamples.Action;
4-
import io.substrait.extension.DefaultExtensionCatalog;
5-
import io.substrait.extension.SimpleExtension;
6-
import io.substrait.isthmus.SubstraitToCalcite;
7-
import io.substrait.isthmus.SubstraitTypeSystem;
4+
import io.substrait.isthmus.SubstraitToSql;
85
import io.substrait.plan.Plan;
96
import io.substrait.plan.PlanProtoConverter;
107
import io.substrait.plan.ProtoPlanConverter;
118
import java.io.IOException;
129
import java.nio.file.Files;
1310
import java.nio.file.Paths;
14-
import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
15-
import org.apache.calcite.rel.rel2sql.RelToSqlConverter;
1611
import org.apache.calcite.sql.SqlDialect;
1712

1813
/**
@@ -50,28 +45,15 @@ public void run(String[] args) {
5045
final io.substrait.proto.Plan protoPlan = planToProto.toProto(substraitPlan);
5146
System.out.println(protoPlan);
5247

53-
final SimpleExtension.ExtensionCollection extensions =
54-
DefaultExtensionCatalog.DEFAULT_COLLECTION;
55-
final SubstraitToCalcite converter =
56-
new SubstraitToCalcite(
57-
extensions, new JavaTypeFactoryImpl(SubstraitTypeSystem.TYPE_SYSTEM));
58-
5948
// Determine which SQL Dialect we want the converted queries to be in
6049
final SqlDialect sqlDialect = SqlDialect.DatabaseProduct.MYSQL.getDialect();
6150

62-
// Create the Sql to Calcite Relation Parser
63-
final RelToSqlConverter relToSql = new RelToSqlConverter(sqlDialect);
51+
SubstraitToSql substraitToSql = new SubstraitToSql();
6452

6553
System.out.println("\n");
6654

6755
// Convert each of the Substrait plan roots to SQL
68-
substraitPlan.getRoots().stream()
69-
// Substrait -> Calcite Rel
70-
.map(root -> converter.convert(root).project(true))
71-
// Calcite Rel -> Calcite SQL
72-
.map(calciteRelNode -> relToSql.visitRoot(calciteRelNode).asStatement())
73-
// Calcite SQL -> SQL String
74-
.map(sqlNode -> sqlNode.toSqlString(sqlDialect).getSql())
56+
substraitToSql.convert(substraitPlan, sqlDialect).stream()
7557
.forEachOrdered(System.out::println);
7658

7759
} catch (IOException e) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,55 @@
11
package io.substrait.isthmus;
22

33
import io.substrait.extension.SimpleExtension;
4+
import io.substrait.plan.Plan;
5+
import io.substrait.plan.Plan.Root;
46
import io.substrait.relation.Rel;
7+
import java.util.ArrayList;
8+
import java.util.List;
59
import org.apache.calcite.prepare.Prepare;
610
import org.apache.calcite.rel.RelNode;
11+
import org.apache.calcite.rel.rel2sql.RelToSqlConverter;
12+
import org.apache.calcite.sql.SqlDialect;
713

814
public class SubstraitToSql extends SqlConverterBase {
915

16+
protected SubstraitToCalcite substraitToCalcite;
17+
1018
public SubstraitToSql() {
1119
super(FEATURES_DEFAULT);
1220
}
1321

1422
public SubstraitToSql(SimpleExtension.ExtensionCollection extensions) {
1523
super(FEATURES_DEFAULT, extensions);
24+
25+
substraitToCalcite = new SubstraitToCalcite(extensions, factory);
1626
}
1727

1828
public RelNode substraitRelToCalciteRel(Rel relRoot, Prepare.CatalogReader catalog) {
1929
return SubstraitRelNodeConverter.convert(
2030
relRoot, relOptCluster, catalog, parserConfig, extensionCollection);
2131
}
32+
33+
/**
34+
* Converts a Substrait {@link Plan} to a list of SQL strings in the given {@link SqlDialect}.
35+
*
36+
* @param plan the Substrait {@link Plan} to convert to SQL, must not be null
37+
* @param dialect the {@link SqlDialect} to generate the SQL strings for, must not be null
38+
* @return list containing a SQL string for each {@link Plan.Root} in {@code plan}
39+
*/
40+
public List<String> convert(Plan plan, SqlDialect dialect) {
41+
List<String> result = new ArrayList<>();
42+
RelToSqlConverter relToSql = new RelToSqlConverter(dialect);
43+
44+
for (Root root : plan.getRoots()) {
45+
result.add(
46+
relToSql
47+
.visitRoot(substraitToCalcite.convert(root).project(true))
48+
.asStatement()
49+
.toSqlString(dialect)
50+
.getSql());
51+
}
52+
53+
return result;
54+
}
2255
}

0 commit comments

Comments
 (0)