Skip to content

Commit 171d7d5

Browse files
committed
fix(javadoc): partial isthmus
Signed-off-by: MBWhite <whitemat@uk.ibm.com>
1 parent bad328b commit 171d7d5

5 files changed

Lines changed: 185 additions & 8 deletions

File tree

isthmus/src/main/java/io/substrait/isthmus/SimpleExtensionToSqlOperator.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,21 @@
2323
import org.apache.calcite.sql.type.SqlTypeFamily;
2424
import org.apache.calcite.sql.type.SqlTypeName;
2525

26+
/**
27+
* Utility class for converting Substrait {@link SimpleExtension} function definitions (scalar and
28+
* aggregate) into Calcite {@link SqlOperator}s.
29+
*
30+
* <p>This enables Calcite to recognize and use Substrait-defined functions during query planning
31+
* and execution. Conversion includes:
32+
*
33+
* <ul>
34+
* <li>Mapping Substrait types to Calcite {@link SqlTypeName}
35+
* <li>Building {@link SqlFunction} instances with proper argument families
36+
* <li>Inferring return types based on Substrait type expressions and nullability rules
37+
* </ul>
38+
*
39+
* <p>Currently supports scalar and aggregate functions; window functions are not yet implemented.
40+
*/
2641
public final class SimpleExtensionToSqlOperator {
2742

2843
private static final RelDataTypeFactory DEFAULT_TYPE_FACTORY =
@@ -32,15 +47,40 @@ public final class SimpleExtensionToSqlOperator {
3247

3348
private SimpleExtensionToSqlOperator() {}
3449

50+
/**
51+
* Converts all functions in a Substrait {@link SimpleExtension.ExtensionCollection} (scalar and
52+
* aggregate) into Calcite {@link SqlOperator}s using the default type factory.
53+
*
54+
* @param collection The Substrait extension collection containing function definitions.
55+
* @return A list of Calcite {@link SqlOperator}s corresponding to the Substrait functions.
56+
*/
3557
public static List<SqlOperator> from(SimpleExtension.ExtensionCollection collection) {
3658
return from(collection, DEFAULT_TYPE_FACTORY);
3759
}
3860

61+
/**
62+
* Converts all functions in a Substrait {@link SimpleExtension.ExtensionCollection} (scalar and
63+
* aggregate) into Calcite {@link SqlOperator}s using a provided type factory.
64+
*
65+
* @param collection The Substrait extension collection containing function definitions.
66+
* @param typeFactory Calcite {@link RelDataTypeFactory} for type creation and inference.
67+
* @return A list of Calcite {@link SqlOperator}s corresponding to the Substrait functions.
68+
*/
3969
public static List<SqlOperator> from(
4070
SimpleExtension.ExtensionCollection collection, RelDataTypeFactory typeFactory) {
4171
return from(collection, typeFactory, TypeConverter.DEFAULT);
4272
}
4373

74+
/**
75+
* Converts all functions in a Substrait {@link SimpleExtension.ExtensionCollection} (scalar and
76+
* aggregate) into Calcite {@link SqlOperator}s with a custom type factory and {@link
77+
* TypeConverter}.
78+
*
79+
* @param collection The Substrait extension collection containing function definitions.
80+
* @param typeFactory Calcite {@link RelDataTypeFactory} for type creation and inference.
81+
* @param typeConverter Converter for Substrait/Calcite type mappings.
82+
* @return A list of Calcite {@link SqlOperator}s corresponding to the Substrait functions.
83+
*/
4484
public static List<SqlOperator> from(
4585
SimpleExtension.ExtensionCollection collection,
4686
RelDataTypeFactory typeFactory,

isthmus/src/main/java/io/substrait/isthmus/SqlConverterBase.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,41 @@
1414
import org.apache.calcite.sql.parser.SqlParser;
1515
import org.apache.calcite.sql2rel.SqlToRelConverter;
1616

17+
/**
18+
* Base class for Substrait SQL conversion pipelines.
19+
*
20+
* <p>Configures Calcite parser, connection, planner, and cluster. Holds the Substrait extensions
21+
* and feature flags. Subclasses can build conversions from SQL to Calcite/Substrait using this
22+
* shared setup.
23+
*/
1724
public class SqlConverterBase {
1825
protected final ConverterProvider converterProvider;
1926

27+
/** Default Calcite connection config (case-insensitive). */
2028
public static final CalciteConnectionConfig CONNECTION_CONFIG =
2129
CalciteConnectionConfig.DEFAULT.set(
2230
CalciteConnectionProperty.CASE_SENSITIVE, Boolean.FALSE.toString());
2331

32+
/** Calcite type factory using the Substrait type system. */
2433
final RelDataTypeFactory factory;
34+
35+
/** Calcite optimization cluster with planner, type factory, and RexBuilder. */
2536
final RelOptCluster relOptCluster;
37+
38+
/** Connection configuration used for SQL parsing and validation. */
2639
final CalciteConnectionConfig config;
40+
41+
/** Configuration for SQL-to-Rel conversion. */
2742
final SqlToRelConverter.Config converterConfig;
2843

44+
/** Parser configuration, including casing and DDL parser factory. */
2945
final SqlParser.Config parserConfig;
3046

47+
/**
48+
* Creates a converter base with explicit features and extensions.
49+
*
50+
* @param converterProvider Converter Provider for configuration
51+
*/
3152
protected SqlConverterBase(ConverterProvider converterProvider) {
3253
this.converterProvider = converterProvider;
3354
this.factory = converterProvider.getTypeFactory();

isthmus/src/main/java/io/substrait/isthmus/SqlExpressionToSubstrait.java

Lines changed: 65 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,47 @@
2727
import org.apache.calcite.sql2rel.SqlToRelConverter;
2828
import org.apache.calcite.sql2rel.StandardConvertletTable;
2929

30+
/**
31+
* Converts SQL expressions to Substrait {@link io.substrait.proto.ExtendedExpression} payloads.
32+
*
33+
* <p>Supports optional CREATE TABLE statements to provide schema and column bindings for expression
34+
* validation and Rex conversion.
35+
*/
3036
public class SqlExpressionToSubstrait extends SqlConverterBase {
3137

38+
/** Converter for RexNodes to Substrait expressions. */
3239
protected final RexExpressionConverter rexConverter;
3340

41+
/** Creates a converter with default features and the default extension catalog. */
3442
public SqlExpressionToSubstrait() {
3543
this(new ConverterProvider());
3644
}
3745

46+
/**
47+
* Creates a converter with the given feature board and extension collection.
48+
*
49+
* @param converterProvider Converter Provider to use for configuration
50+
*/
3851
public SqlExpressionToSubstrait(ConverterProvider converterProvider) {
3952
super(converterProvider);
4053
this.rexConverter = new RexExpressionConverter(converterProvider.getScalarFunctionConverter());
4154
}
4255

56+
/** Bundled result carrying validator, catalog reader, and name/type and name/node maps. */
4357
private static final class Result {
4458
final SqlValidator validator;
4559
final CalciteCatalogReader catalogReader;
4660
final Map<String, RelDataType> nameToTypeMap;
4761
final Map<String, RexNode> nameToNodeMap;
4862

63+
/**
64+
* Creates a result bundle.
65+
*
66+
* @param validator SQL validator
67+
* @param catalogReader Calcite catalog reader
68+
* @param nameToTypeMap mapping from column name to Calcite type
69+
* @param nameToNodeMap mapping from column name to Rex input ref
70+
*/
4971
Result(
5072
SqlValidator validator,
5173
CalciteCatalogReader catalogReader,
@@ -59,25 +81,25 @@ private static final class Result {
5981
}
6082

6183
/**
62-
* Converts the given SQL expression to an {@link io.substrait.proto.ExtendedExpression }
84+
* Converts a single SQL expression to a Substrait {@link io.substrait.proto.ExtendedExpression}.
6385
*
6486
* @param sqlExpression a SQL expression
6587
* @param createStatements table creation statements defining fields referenced by the expression
66-
* @return a {@link io.substrait.proto.ExtendedExpression }
67-
* @throws SqlParseException
88+
* @return the Substrait extended expression proto
89+
* @throws SqlParseException if parsing or validation fails
6890
*/
6991
public io.substrait.proto.ExtendedExpression convert(
7092
String sqlExpression, List<String> createStatements) throws SqlParseException {
7193
return convert(new String[] {sqlExpression}, createStatements);
7294
}
7395

7496
/**
75-
* Converts the given SQL expressions to an {@link io.substrait.proto.ExtendedExpression }
97+
* Converts multiple SQL expressions to a Substrait {@link io.substrait.proto.ExtendedExpression}.
7698
*
77-
* @param sqlExpressions an array of SQL expressions
78-
* @param createStatements table creation statements defining fields referenced by the expression
79-
* @return a {@link io.substrait.proto.ExtendedExpression }
80-
* @throws SqlParseException
99+
* @param sqlExpressions array of SQL expressions
100+
* @param createStatements table creation statements defining fields referenced by the expressions
101+
* @return the Substrait extended expression proto
102+
* @throws SqlParseException if parsing or validation fails
81103
*/
82104
public io.substrait.proto.ExtendedExpression convert(
83105
String[] sqlExpressions, List<String> createStatements) throws SqlParseException {
@@ -90,6 +112,17 @@ public io.substrait.proto.ExtendedExpression convert(
90112
result.nameToNodeMap);
91113
}
92114

115+
/**
116+
* Converts the given SQL expressions using the provided validator/catalog and column bindings.
117+
*
118+
* @param sqlExpressions array of SQL expressions
119+
* @param validator SQL validator
120+
* @param catalogReader Calcite catalog reader
121+
* @param nameToTypeMap mapping from column name to Calcite type
122+
* @param nameToNodeMap mapping from column name to Rex input ref
123+
* @return the Substrait extended expression proto
124+
* @throws SqlParseException if parsing or validation fails
125+
*/
93126
private io.substrait.proto.ExtendedExpression executeInnerSQLExpressions(
94127
String[] sqlExpressions,
95128
SqlValidator validator,
@@ -120,6 +153,17 @@ private io.substrait.proto.ExtendedExpression executeInnerSQLExpressions(
120153
return new ExtendedExpressionProtoConverter().toProto(extendedExpression.build());
121154
}
122155

156+
/**
157+
* Parses and validates a SQL expression, then converts it to a {@link RexNode}.
158+
*
159+
* @param sql SQL expression string
160+
* @param validator SQL validator
161+
* @param catalogReader Calcite catalog reader
162+
* @param nameToTypeMap mapping from column name to Calcite type
163+
* @param nameToNodeMap mapping from column name to Rex input ref
164+
* @return the converted RexNode
165+
* @throws SqlParseException if parsing or validation fails
166+
*/
123167
private RexNode sqlToRexNode(
124168
String sql,
125169
SqlValidator validator,
@@ -141,6 +185,13 @@ private RexNode sqlToRexNode(
141185
return converter.convertExpression(validSqlNode, nameToNodeMap);
142186
}
143187

188+
/**
189+
* Registers tables from CREATE statements and prepares validator, catalog, and column bindings.
190+
*
191+
* @param tables list of CREATE TABLE statements; may be null
192+
* @return result bundle containing validator, catalog reader, and name/type and name/node maps
193+
* @throws SqlParseException if any CREATE statement is invalid
194+
*/
144195
private Result registerCreateTablesForExtendedExpression(List<String> tables)
145196
throws SqlParseException {
146197
Map<String, RelDataType> nameToTypeMap = new LinkedHashMap<>();
@@ -177,6 +228,12 @@ private Result registerCreateTablesForExtendedExpression(List<String> tables)
177228
return new Result(validator, catalogReader, nameToTypeMap, nameToNodeMap);
178229
}
179230

231+
/**
232+
* Converts a name-to-type map into a {@link NamedStruct} in Substrait types.
233+
*
234+
* @param nameToTypeMap mapping from column name to Calcite type
235+
* @return a {@link NamedStruct} with non-nullable struct type
236+
*/
180237
private NamedStruct toNamedStruct(Map<String, RelDataType> nameToTypeMap) {
181238
ArrayList<String> names = new ArrayList<String>();
182239
ArrayList<Type> types = new ArrayList<Type>();

isthmus/src/main/java/io/substrait/isthmus/SqlToSubstrait.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,18 @@
1919
public class SqlToSubstrait extends SqlConverterBase {
2020
private final SqlOperatorTable operatorTable;
2121

22+
/**
23+
* Creates a SQL-to-Substrait converter using the default extension catalog and default features.
24+
*/
2225
public SqlToSubstrait() {
2326
this(new ConverterProvider());
2427
}
2528

29+
/**
30+
* Creates a SQL-to-Substrait converter with explicit extensions and features.
31+
*
32+
* @param converterProvider Converter Provider for the configuration
33+
*/
2634
public SqlToSubstrait(ConverterProvider converterProvider) {
2735
super(converterProvider);
2836
this.operatorTable = converterProvider.getSqlOperatorTable();

isthmus/src/main/java/io/substrait/isthmus/SubstraitRelNodeConverter.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,25 +90,51 @@
9090
public class SubstraitRelNodeConverter
9191
extends AbstractRelVisitor<RelNode, SubstraitRelNodeConverter.Context, RuntimeException> {
9292

93+
/** Calcite type factory used to construct row and field types. */
9394
protected final RelDataTypeFactory typeFactory;
9495

96+
/** Converter for Substrait scalar functions to Calcite operators. */
9597
protected final ScalarFunctionConverter scalarFunctionConverter;
98+
99+
/** Converter for Substrait aggregate functions to Calcite operators. */
96100
protected final AggregateFunctionConverter aggregateFunctionConverter;
101+
102+
/** Converts Substrait {@code Expression}s into Calcite {@code RexNode}s. */
97103
protected final ExpressionRexConverter expressionRexConverter;
98104

105+
/** Calcite {@link RelBuilder} used to construct relational expressions during conversion. */
99106
protected final RelBuilder relBuilder;
107+
108+
/** Calcite {@link RexBuilder} used to build Rex nodes (e.g., input refs, literals). */
100109
protected final RexBuilder rexBuilder;
110+
111+
/** Type converter to translate between Calcite and Substrait type systems. */
101112
private final TypeConverter typeConverter;
102113

103114
/** Use {@link #SubstraitRelNodeConverter(RelBuilder, ConverterProvider)} instead */
104115
@Deprecated
116+
/**
117+
* Creates a new SubstraitRelNodeConverter with the specified extensions, type factory, and
118+
* relation builder.
119+
*
120+
* @param extensions the Substrait extension collection
121+
* @param typeFactory the Calcite type factory
122+
* @param relBuilder the Calcite relation builder
123+
*/
105124
public SubstraitRelNodeConverter(
106125
SimpleExtension.ExtensionCollection extensions,
107126
RelDataTypeFactory typeFactory,
108127
RelBuilder relBuilder) {
109128
this(relBuilder, new ConverterProvider(extensions, typeFactory));
110129
}
111130

131+
/**
132+
* Creates a new SubstraitRelNodeConverter with the specified relation builder and converter
133+
* provider.
134+
*
135+
* @param relBuilder the Calcite relation builder
136+
* @param converterProvider the converter provider containing configuration and converters
137+
*/
112138
public SubstraitRelNodeConverter(RelBuilder relBuilder, ConverterProvider converterProvider) {
113139
this.typeFactory = converterProvider.getTypeFactory();
114140
this.typeConverter = converterProvider.getTypeConverter();
@@ -119,6 +145,18 @@ public SubstraitRelNodeConverter(RelBuilder relBuilder, ConverterProvider conver
119145
this.expressionRexConverter = converterProvider.getExpressionRexConverter(this);
120146
}
121147

148+
/**
149+
* Converts a Substrait {@link Rel} plan to a Calcite {@link RelNode} using default feature
150+
* settings.
151+
*
152+
* <p>This method creates a {@link RelBuilder} configured with the provided cluster and catalog,
153+
* then delegates to the converter with default features.
154+
*
155+
* @param relRoot the root Substrait relation to convert
156+
* @param catalogReader the Calcite catalog reader for schema resolution
157+
* @param converterProvider the converter provider containing configuration and converters
158+
* @return the converted Calcite {@link RelNode}
159+
*/
122160
public static RelNode convert(
123161
Rel relRoot, Prepare.CatalogReader catalogReader, ConverterProvider converterProvider) {
124162
RelBuilder relBuilder =
@@ -736,6 +774,16 @@ public RelNode visitFallback(Rel rel, Context context) throws RuntimeException {
736774
rel, rel.getClass().getCanonicalName(), this.getClass().getCanonicalName()));
737775
}
738776

777+
/**
778+
* Applies an optional field remap to the given node.
779+
*
780+
* <p>If {@code remap} is present, the node is projected according to the provided indices;
781+
* otherwise the original node is returned unchanged.
782+
*
783+
* @param relNode the node to remap
784+
* @param remap optional field index remap
785+
* @return remapped node or original node if no remap is present
786+
*/
739787
protected RelNode applyRemap(RelNode relNode, Optional<Rel.Remap> remap) {
740788
if (remap.isPresent()) {
741789
return applyRemap(relNode, remap.get());
@@ -759,8 +807,10 @@ private RelNode applyRemap(RelNode relNode, Rel.Remap remap) {
759807

760808
/** A shared context for the Substrait to RelNode conversion. */
761809
public static class Context implements VisitationContext {
810+
/** Stack of outer row type range maps used to resolve correlated references. */
762811
protected final Stack<RangeMap<Integer, RelDataType>> outerRowTypes = new Stack<>();
763812

813+
/** Stack of correlation ids collected while visiting subqueries. */
764814
protected final Stack<java.util.Set<CorrelationId>> correlationIds = new Stack<>();
765815

766816
private int subqueryDepth;
@@ -798,6 +848,7 @@ public void pushOuterRowType(final RelDataType... inputs) {
798848
this.correlationIds.push(new HashSet<>());
799849
}
800850

851+
/** Pops the most recent outer row type from the stack. */
801852
public void popOuterRowType() {
802853
outerRowTypes.pop();
803854
}

0 commit comments

Comments
 (0)