Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9d60dc7
feat(isthmus): udf support for substrait<->calcite
ZorinAnton Jul 8, 2025
556847b
chore(isthmus): handle nullability and EnumArgument in SimplExtension…
ZorinAnton Aug 13, 2025
857fe2c
feat(isthmus): udf support for substrait<->calcite
ZorinAnton Jul 8, 2025
eeb97cd
chore(isthmus): handle nullability and EnumArgument in SimplExtension…
ZorinAnton Aug 13, 2025
f30b556
Merge branch 'main' into zor-udf
ZorinAnton Oct 13, 2025
6d9cc2a
chore: resolve pmd
ZorinAnton Oct 13, 2025
1a1bf47
chore: sync submodules with main
ZorinAnton Oct 13, 2025
834ab5e
chore: sync substrait with main
ZorinAnton Oct 13, 2025
8340cc5
chore(isthmus): resolve conflicts after submodule update
ZorinAnton Oct 14, 2025
6ba115f
chore(isthmus): fix yaml for custom udf
ZorinAnton Oct 14, 2025
e739184
Merge branch 'main' into zor-udf
ZorinAnton Nov 26, 2025
838a0a7
chore(isthmus): fix regression
ZorinAnton Nov 26, 2025
32ae275
fix: add missing serialVersionUIDs (#621)
nielspardon Nov 26, 2025
e4f656d
Merge branch 'main' into zor-udf
ZorinAnton Nov 26, 2025
8d2b4ed
chore(isthmus): fix regression
ZorinAnton Nov 26, 2025
9b0c027
feat(isthmus): enable dynamic UDFs with FeatureBoard
ZorinAnton Dec 3, 2025
a9e7c60
chore(isthmus): refactor SimpleExtensionToSqlOperatorTest
ZorinAnton Dec 3, 2025
2f6cd28
chore(isthmus): address minor PR comments
ZorinAnton Dec 3, 2025
71fcdfc
feat(isthmus): make dynamic UDF configurable for substrait to sql con…
ZorinAnton Dec 3, 2025
ca3d967
Merge branch 'main' into zor-udf
ZorinAnton Dec 3, 2025
142d372
chore(isthmus): fix format violations
ZorinAnton Dec 3, 2025
74fd2e7
chore(isthmus): minor refactoring
ZorinAnton Dec 3, 2025
ec45173
chore(isthmus): check arg types in SimpleExtensionToSqlOperatorTest
ZorinAnton Dec 4, 2025
6eedacd
chore(isthmus): minor refactoring of SimpleExtensionToSqlOperator
ZorinAnton Dec 4, 2025
b002d9b
chore(isthmus): fix opt-in for dynamic operators
ZorinAnton Dec 5, 2025
fcf24bb
Merge branch 'main' into zor-udf
ZorinAnton Dec 5, 2025
fc2d576
chore(isthmus): fix regression in test
ZorinAnton Dec 5, 2025
26c15dc
Merge branch 'main' into zor-udf
ZorinAnton Dec 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
chore(isthmus): handle nullability and EnumArgument in SimplExtension…
…ToSqlOperator
  • Loading branch information
ZorinAnton committed Sep 1, 2025
commit eeb97cd73057a18d884fdb4225238fb30b19c2cb
21 changes: 5 additions & 16 deletions isthmus/src/main/java/io/substrait/isthmus/SqlToSubstrait.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@
package io.substrait.isthmus;

import io.substrait.isthmus.sql.SubstraitSqlToCalcite;
import com.google.common.annotations.VisibleForTesting;
import io.substrait.extension.SimpleExtension;
import io.substrait.isthmus.calcite.SubstraitOperatorTable;
import io.substrait.isthmus.sql.SubstraitSqlValidator;
import io.substrait.isthmus.sql.SubstraitSqlToCalcite;
import io.substrait.plan.ImmutablePlan.Builder;
import io.substrait.plan.Plan;
import io.substrait.plan.Plan.Version;
import io.substrait.plan.PlanProtoConverter;
import java.util.List;
import org.apache.calcite.prepare.Prepare;
import org.apache.calcite.rel.RelRoot;
import org.apache.calcite.rel.rules.CoreRules;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlOperatorTable;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.util.SqlOperatorTables;
import org.apache.calcite.sql.validate.SqlValidator;
import org.apache.calcite.sql2rel.SqlToRelConverter;
import org.apache.calcite.sql2rel.StandardConvertletTable;

import java.util.List;

/** Take a SQL statement and a set of table definitions and return a substrait plan. */
public class SqlToSubstrait extends SqlConverterBase {
Expand Down Expand Up @@ -84,9 +73,9 @@ public Plan convert(String sqlStatements, Prepare.CatalogReader catalogReader)
builder.version(Version.builder().from(Version.DEFAULT_VERSION).producer("isthmus").build());

// TODO: consider case in which one sql passes conversion while others don't
SubstraitSqlToCalcite.convertQueries(sqlStatements, catalogReader).stream()
.map(root -> SubstraitRelVisitor.convert(root, extensionCollection, featureBoard))
.forEach(root -> builder.addRoots(root));
SubstraitSqlToCalcite.convertQueries(sqlStatements, catalogReader, operatorTable).stream()
.map(root -> SubstraitRelVisitor.convert(root, extensionCollection, featureBoard))
.forEach(root -> builder.addRoots(root));

return builder.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.apache.calcite.rel.rules.CoreRules;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlOperatorTable;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.validate.SqlValidator;
import org.apache.calcite.sql2rel.SqlToRelConverter;
Expand All @@ -41,6 +42,23 @@ public static RelRoot convertQuery(String sqlStatement, Prepare.CatalogReader ca
return convertQuery(sqlStatement, catalogReader, validator, createDefaultRelOptCluster());
}

/**
* Converts a SQL statement to a Calcite {@link RelRoot}.
*
* @param sqlStatement a SQL statement string
* @param catalogReader the {@link Prepare.CatalogReader} for finding tables/views referenced in
* the SQL statement
* @param operatorTable the {@link SqlOperatorTable} for dynamic operators
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly speaking, you can inject a SqlOperatorTable here that incorporates dynamic operators, but you can also inject a SqlOperatorTable that doesn't. What this allows you to do is have more fine-grained control over valid operators by allowing you to control what SqlOperatorTable you use, instead of just being forced to use the default SubstraitOperatorTable that we provide.

Suggested change
* @param operatorTable the {@link SqlOperatorTable} for dynamic operators
* @param operatorTable the {@link SqlOperatorTable} for controlling valid operators

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

* @return a {@link RelRoot} corresponding to the given SQL statement
* @throws SqlParseException if there is an error while parsing the SQL statement
*/
public static RelRoot convertQuery(
String sqlStatement, Prepare.CatalogReader catalogReader, SqlOperatorTable operatorTable)
throws SqlParseException {
SqlValidator validator = new SubstraitSqlValidator(catalogReader, operatorTable);
return convertQuery(sqlStatement, catalogReader, validator, createDefaultRelOptCluster());
}

/**
* Converts a SQL statement to a Calcite {@link RelRoot}.
*
Expand Down Expand Up @@ -72,6 +90,24 @@ public static RelRoot convertQuery(
return relRoots.get(0);
}

/**
* Converts one or more SQL statements to a List of {@link RelRoot}, with one {@link RelRoot} per
* statement.
*
* @param sqlStatements a string containing one or more SQL statements
* @param catalogReader the {@link Prepare.CatalogReader} for finding tables/views referenced in
* the SQL statements
* @param operatorTable the {@link SqlOperatorTable} for dynamic operators
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @param operatorTable the {@link SqlOperatorTable} for dynamic operators
* @param operatorTable the {@link SqlOperatorTable} for controlling valid operators

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

* @return a list of {@link RelRoot}s corresponding to the given SQL statements
* @throws SqlParseException if there is an error while parsing the SQL statements
*/
public static List<RelRoot> convertQueries(
String sqlStatements, Prepare.CatalogReader catalogReader, SqlOperatorTable operatorTable)
throws SqlParseException {
SqlValidator validator = new SubstraitSqlValidator(catalogReader, operatorTable);
return convertQueries(sqlStatements, catalogReader, validator, createDefaultRelOptCluster());
}

/**
* Converts one or more SQL statements to a List of {@link RelRoot}, with one {@link RelRoot} per
* statement.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import io.substrait.extension.SimpleExtension;
import io.substrait.isthmus.sql.SubstraitSqlToCalcite;
import java.io.IOException;
import java.util.List;
import org.apache.calcite.plan.hep.HepPlanner;
import org.apache.calcite.plan.hep.HepProgram;
import org.apache.calcite.plan.hep.HepProgramBuilder;
Expand Down
6 changes: 2 additions & 4 deletions isthmus/src/test/java/io/substrait/isthmus/PlanTestBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,10 @@ protected RelRoot assertSqlSubstraitRelRoundTripWorkaroundOptimizer(
SqlToSubstrait s = new SqlToSubstrait(extensions, null);

// 1. SQL -> Calcite RelRoot
List<RelRoot> relRoots = s.sqlToRelNode(query, catalogReader);
assertEquals(1, relRoots.size());
RelRoot relRoot1 = relRoots.get(0);
Plan plan1 = s.convert(query, catalogReader);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A number of the comments in this test utility don't line up with what it's actually doing. For example, this is a Substrait Plan, not a Calcite RelRoot.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


// 2. Calcite RelRoot -> Substrait Rel
Plan.Root pojo1 = SubstraitRelVisitor.convert(relRoot1, extensions);
Plan.Root pojo1 = plan1.getRoots().get(0);

// 3. Substrait Rel -> Calcite RelNode
RelRoot relRoot2 = substraitToCalcite.convert(pojo1);
Expand Down
11 changes: 0 additions & 11 deletions isthmus/src/test/resources/extensions/functions_string_custom.yaml

This file was deleted.

Loading