diff --git a/isthmus/src/main/java/io/substrait/isthmus/SubstraitTypeSystem.java b/isthmus/src/main/java/io/substrait/isthmus/SubstraitTypeSystem.java index 31c40905e..a46d2bc49 100644 --- a/isthmus/src/main/java/io/substrait/isthmus/SubstraitTypeSystem.java +++ b/isthmus/src/main/java/io/substrait/isthmus/SubstraitTypeSystem.java @@ -9,21 +9,37 @@ import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.SqlTypeName; +/** + * Custom {@link RelDataTypeSystem} implementation for Substrait. + * + *
Defines type system rules such as precision, scale, and interval qualifiers for Substrait + * integration with Calcite. + */ public class SubstraitTypeSystem extends RelDataTypeSystemImpl { + + /** Singleton instance of Substrait type system. */ public static final RelDataTypeSystem TYPE_SYSTEM = new SubstraitTypeSystem(); + /** Default type factory using the Substrait type system. */ public static final RelDataTypeFactory TYPE_FACTORY = new JavaTypeFactoryImpl(TYPE_SYSTEM); - // Interval qualifier from year to month + /** Interval qualifier from year to month. */ public static final SqlIntervalQualifier YEAR_MONTH_INTERVAL = new SqlIntervalQualifier(TimeUnit.YEAR, TimeUnit.MONTH, SqlParserPos.ZERO); - // Interval qualifier from day to fractional second at microsecond precision + /** Interval qualifier from day to fractional second at microsecond precision. */ public static final SqlIntervalQualifier DAY_SECOND_INTERVAL = new SqlIntervalQualifier(TimeUnit.DAY, -1, TimeUnit.SECOND, 6, SqlParserPos.ZERO); + /** Private constructor to enforce singleton usage. */ private SubstraitTypeSystem() {} + /** + * Returns the maximum precision for the given SQL type. + * + * @param typeName The {@link SqlTypeName} for which precision is requested. + * @return Maximum precision for the type. + */ @Override public int getMaxPrecision(final SqlTypeName typeName) { switch (typeName) { @@ -41,6 +57,11 @@ public int getMaxPrecision(final SqlTypeName typeName) { return super.getMaxPrecision(typeName); } + /** + * Returns the maximum numeric scale supported by this type system. + * + * @return Maximum numeric scale (38). + */ @Override public int getDefaultPrecision(final SqlTypeName typeName) { switch (typeName) { @@ -51,6 +72,11 @@ public int getDefaultPrecision(final SqlTypeName typeName) { } } + /** + * Returns the maximum numeric precision supported by this type system. + * + * @return Maximum numeric precision (38). + */ @Override public int getMaxScale(final SqlTypeName typeName) { switch (typeName) { @@ -60,6 +86,11 @@ public int getMaxScale(final SqlTypeName typeName) { return super.getMaxScale(typeName); } + /** + * Indicates whether ragged union types should be converted to varying types. + * + * @return {@code true}, as Substrait requires conversion to varying types. + */ @Override public boolean shouldConvertRaggedUnionTypesToVarying() { return true; diff --git a/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java b/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java index ac2faf119..63dc6227b 100644 --- a/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java +++ b/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java @@ -20,11 +20,27 @@ import org.apache.calcite.sql.type.SqlTypeName; import org.jspecify.annotations.Nullable; +/** + * Utility for converting between Calcite {@link org.apache.calcite.rel.type.RelDataType} and + * Substrait {@link io.substrait.type.Type}. + * + *
Supports primitive, complex, and user-defined types in both directions. + * + * @see UserTypeMapper + * @see io.substrait.type.Type + * @see org.apache.calcite.rel.type.RelDataType + */ public class TypeConverter { private final UserTypeMapper userTypeMapper; // DEFAULT TypeConverter which does not handle user-defined types + /** + * Default {@link TypeConverter} instance that does not handle user-defined types. + * + *
Both {@link UserTypeMapper#toSubstrait(RelDataType)} and {@link + * UserTypeMapper#toCalcite(Type.UserDefined)} return {@code null} in this default configuration. + */ public static TypeConverter DEFAULT = new TypeConverter( new UserTypeMapper() { @@ -41,14 +57,39 @@ public RelDataType toCalcite(Type.UserDefined type) { } }); + /** + * Creates a {@link TypeConverter} with a provided user type mapper. + * + * @param userTypeMapper Mapper for converting user-defined types between Calcite and Substrait. + */ public TypeConverter(UserTypeMapper userTypeMapper) { this.userTypeMapper = userTypeMapper; } + /** + * Converts a Calcite {@link RelDataType} to a Substrait {@link Type}. + * + * @param type Calcite type to convert. + * @return Corresponding Substrait type. + * @throws UnsupportedOperationException if the type cannot be converted or has unsupported + * properties. + */ public Type toSubstrait(RelDataType type) { return toSubstrait(type, new ArrayList<>()); } + /** + * Converts a Calcite {@link RelDataType} of SQL type {@link SqlTypeName#ROW} to a Substrait + * {@link NamedStruct}. + * + *
Field names are extracted from the Calcite struct type and paired with the converted
+ * Substrait struct.
+ *
+ * @param type Calcite struct type ({@link SqlTypeName#ROW}).
+ * @return Substrait {@link NamedStruct} containing field names and struct type.
+ * @throws IllegalArgumentException if {@code type} is not a struct ({@code ROW}).
+ * @throws UnsupportedOperationException if any child field type cannot be converted.
+ */
public NamedStruct toNamedStruct(RelDataType type) {
if (type.getSqlTypeName() != SqlTypeName.ROW) {
throw new IllegalArgumentException("Expected type of struct.");
@@ -153,11 +194,31 @@ private Type toSubstrait(RelDataType type, List Includes helpers for computing cartesian products and building hierarchical Calcite schemas.
+ */
public class Utils {
/**
* Compute the cartesian product for n lists.
@@ -19,6 +24,12 @@ public class Utils {
* Based on Soln by
* Thomas Preissler
+ *
+ * @param > crossProduct(List
> lists) {