diff --git a/core/src/main/antlr/SubstraitType.g4 b/core/src/main/antlr/SubstraitType.g4 index 9323a598e..9a7c0e7f9 100644 --- a/core/src/main/antlr/SubstraitType.g4 +++ b/core/src/main/antlr/SubstraitType.g4 @@ -49,6 +49,7 @@ Date : D A T E; Time : T I M E; IntervalYear: I N T E R V A L '_' Y E A R; IntervalDay: I N T E R V A L '_' D A Y; +IntervalCompound: I N T E R V A L '_' C O M P O U N D; UUID : U U I D; Decimal : D E C I M A L; PrecisionTimestamp: P R E C I S I O N '_' T I M E S T A M P; @@ -158,7 +159,6 @@ scalarType | TimestampTZ #timestampTz | Date #date | Time #time - | IntervalDay #intervalDay | IntervalYear #intervalYear | UUID #uuid | UserDefined Identifier #userDefined @@ -169,6 +169,8 @@ parameterizedType | VarChar isnull='?'? Lt len=numericParameter Gt #varChar | FixedBinary isnull='?'? Lt len=numericParameter Gt #fixedBinary | Decimal isnull='?'? Lt precision=numericParameter Comma scale=numericParameter Gt #decimal + | IntervalDay isnull='?'? Lt precision=numericParameter Gt #intervalDay + | IntervalCompound isnull='?'? Lt precision=numericParameter Gt #intervalCompound | PrecisionTimestamp isnull='?'? Lt precision=numericParameter Gt #precisionTimestamp | PrecisionTimestampTZ isnull='?'? Lt precision=numericParameter Gt #precisionTimestampTZ | Struct isnull='?'? Lt expr (Comma expr)* Gt #struct @@ -205,4 +207,3 @@ expr | (Bang) expr #NotExpr | ifExpr=expr QMark thenExpr=expr Colon elseExpr=expr #Ternary ; - diff --git a/core/src/main/java/io/substrait/expression/AbstractExpressionVisitor.java b/core/src/main/java/io/substrait/expression/AbstractExpressionVisitor.java index 6b1c9177c..5193c5b53 100644 --- a/core/src/main/java/io/substrait/expression/AbstractExpressionVisitor.java +++ b/core/src/main/java/io/substrait/expression/AbstractExpressionVisitor.java @@ -94,6 +94,11 @@ public OUTPUT visit(Expression.IntervalDayLiteral expr) throws EXCEPTION { return visitFallback(expr); } + @Override + public OUTPUT visit(Expression.IntervalCompoundLiteral expr) throws EXCEPTION { + return visitFallback(expr); + } + @Override public OUTPUT visit(Expression.UUIDLiteral expr) throws EXCEPTION { return visitFallback(expr); diff --git a/core/src/main/java/io/substrait/expression/Expression.java b/core/src/main/java/io/substrait/expression/Expression.java index b592341b5..5ca881bcb 100644 --- a/core/src/main/java/io/substrait/expression/Expression.java +++ b/core/src/main/java/io/substrait/expression/Expression.java @@ -333,10 +333,12 @@ abstract static class IntervalDayLiteral implements Literal { public abstract int seconds(); - public abstract int microseconds(); + public abstract long subseconds(); + + public abstract int precision(); public Type getType() { - return Type.withNullability(nullable()).INTERVAL_DAY; + return Type.withNullability(nullable()).intervalDay(precision()); } public static ImmutableExpression.IntervalDayLiteral.Builder builder() { @@ -348,6 +350,35 @@ public R accept(ExpressionVisitor visitor) throws } } + @Value.Immutable + abstract static class IntervalCompoundLiteral implements Literal { + // Flattened IntervalYearLiteral + public abstract int years(); + + public abstract int months(); + + // Flattened IntervalDayLiteral + public abstract int days(); + + public abstract int seconds(); + + public abstract long subseconds(); + + public abstract int precision(); + + public Type getType() { + return Type.withNullability(nullable()).intervalCompound(precision()); + } + + public static ImmutableExpression.IntervalCompoundLiteral.Builder builder() { + return ImmutableExpression.IntervalCompoundLiteral.builder(); + } + + public R accept(ExpressionVisitor visitor) throws E { + return visitor.visit(this); + } + } + @Value.Immutable abstract static class UUIDLiteral implements Literal { public abstract UUID value(); diff --git a/core/src/main/java/io/substrait/expression/ExpressionCreator.java b/core/src/main/java/io/substrait/expression/ExpressionCreator.java index 671d9d465..2ec0b3b40 100644 --- a/core/src/main/java/io/substrait/expression/ExpressionCreator.java +++ b/core/src/main/java/io/substrait/expression/ExpressionCreator.java @@ -161,16 +161,36 @@ public static Expression.IntervalYearLiteral intervalYear( } public static Expression.IntervalDayLiteral intervalDay(boolean nullable, int days, int seconds) { - return intervalDay(nullable, days, seconds, 0); + return intervalDay(nullable, days, seconds, 0, 0); } public static Expression.IntervalDayLiteral intervalDay( - boolean nullable, int days, int seconds, int microseconds) { + boolean nullable, int days, int seconds, long subseconds, int precision) { return Expression.IntervalDayLiteral.builder() .nullable(nullable) .days(days) .seconds(seconds) - .microseconds(microseconds) + .subseconds(subseconds) + .precision(precision) + .build(); + } + + public static Expression.IntervalCompoundLiteral intervalCompound( + boolean nullable, + int years, + int months, + int days, + int seconds, + long subseconds, + int precision) { + return Expression.IntervalCompoundLiteral.builder() + .nullable(nullable) + .years(years) + .months(months) + .days(days) + .seconds(seconds) + .subseconds(subseconds) + .precision(precision) .build(); } diff --git a/core/src/main/java/io/substrait/expression/ExpressionVisitor.java b/core/src/main/java/io/substrait/expression/ExpressionVisitor.java index 42c78c184..7bcdd4eab 100644 --- a/core/src/main/java/io/substrait/expression/ExpressionVisitor.java +++ b/core/src/main/java/io/substrait/expression/ExpressionVisitor.java @@ -39,6 +39,8 @@ public interface ExpressionVisitor { R visit(Expression.IntervalDayLiteral expr) throws E; + R visit(Expression.IntervalCompoundLiteral expr) throws E; + R visit(Expression.UUIDLiteral expr) throws E; R visit(Expression.FixedCharLiteral expr) throws E; diff --git a/core/src/main/java/io/substrait/expression/proto/ExpressionProtoConverter.java b/core/src/main/java/io/substrait/expression/proto/ExpressionProtoConverter.java index 7b0bb687b..a400522b1 100644 --- a/core/src/main/java/io/substrait/expression/proto/ExpressionProtoConverter.java +++ b/core/src/main/java/io/substrait/expression/proto/ExpressionProtoConverter.java @@ -159,7 +159,27 @@ public Expression visit(io.substrait.expression.Expression.IntervalDayLiteral ex Expression.Literal.IntervalDayToSecond.newBuilder() .setDays(expr.days()) .setSeconds(expr.seconds()) - .setMicroseconds(expr.microseconds()))); + .setSubseconds(expr.subseconds()) + .setPrecision(expr.precision()))); + } + + @Override + public Expression visit(io.substrait.expression.Expression.IntervalCompoundLiteral expr) { + return lit( + bldr -> + bldr.setNullable(expr.nullable()) + .setIntervalCompound( + Expression.Literal.IntervalCompound.newBuilder() + .setIntervalYearToMonth( + Expression.Literal.IntervalYearToMonth.newBuilder() + .setYears(expr.years()) + .setMonths(expr.months())) + .setIntervalDayToSecond( + Expression.Literal.IntervalDayToSecond.newBuilder() + .setDays(expr.days()) + .setSeconds(expr.seconds()) + .setSubseconds(expr.subseconds()) + .setPrecision(expr.precision())))); } @Override diff --git a/core/src/main/java/io/substrait/expression/proto/ProtoExpressionConverter.java b/core/src/main/java/io/substrait/expression/proto/ProtoExpressionConverter.java index b429338ea..44a4aa24e 100644 --- a/core/src/main/java/io/substrait/expression/proto/ProtoExpressionConverter.java +++ b/core/src/main/java/io/substrait/expression/proto/ProtoExpressionConverter.java @@ -340,11 +340,38 @@ public Expression.Literal from(io.substrait.proto.Expression.Literal literal) { literal.getNullable(), literal.getIntervalYearToMonth().getYears(), literal.getIntervalYearToMonth().getMonths()); - case INTERVAL_DAY_TO_SECOND -> ExpressionCreator.intervalDay( - literal.getNullable(), - literal.getIntervalDayToSecond().getDays(), - literal.getIntervalDayToSecond().getSeconds(), - literal.getIntervalDayToSecond().getMicroseconds()); + case INTERVAL_DAY_TO_SECOND -> { + // Handle deprecated version that doesn't provide precision and that uses microseconds + // instead of subseconds, for backwards compatibility + int precision = + literal.getIntervalDayToSecond().hasPrecision() + ? literal.getIntervalDayToSecond().getPrecision() + : 6; // microseconds + long subseconds = + literal.getIntervalDayToSecond().hasPrecision() + ? literal.getIntervalDayToSecond().getSubseconds() + : literal.getIntervalDayToSecond().getMicroseconds(); + yield ExpressionCreator.intervalDay( + literal.getNullable(), + literal.getIntervalDayToSecond().getDays(), + literal.getIntervalDayToSecond().getSeconds(), + subseconds, + precision); + } + case INTERVAL_COMPOUND -> { + if (!literal.getIntervalCompound().getIntervalDayToSecond().hasPrecision()) { + throw new RuntimeException( + "Interval compound with deprecated version of interval day (ie. no precision) is not supported"); + } + yield ExpressionCreator.intervalCompound( + literal.getNullable(), + literal.getIntervalCompound().getIntervalYearToMonth().getYears(), + literal.getIntervalCompound().getIntervalYearToMonth().getMonths(), + literal.getIntervalCompound().getIntervalDayToSecond().getDays(), + literal.getIntervalCompound().getIntervalDayToSecond().getSeconds(), + literal.getIntervalCompound().getIntervalDayToSecond().getSubseconds(), + literal.getIntervalCompound().getIntervalDayToSecond().getPrecision()); + } case FIXED_CHAR -> ExpressionCreator.fixedChar(literal.getNullable(), literal.getFixedChar()); case VAR_CHAR -> ExpressionCreator.varChar( literal.getNullable(), literal.getVarChar().getValue(), literal.getVarChar().getLength()); diff --git a/core/src/main/java/io/substrait/function/ParameterizedType.java b/core/src/main/java/io/substrait/function/ParameterizedType.java index 767ad9253..c66c75fa9 100644 --- a/core/src/main/java/io/substrait/function/ParameterizedType.java +++ b/core/src/main/java/io/substrait/function/ParameterizedType.java @@ -106,6 +106,36 @@ public static ImmutableParameterizedType.Decimal.Builder builder() { } } + @Value.Immutable + abstract static class IntervalDay extends BaseParameterizedType implements NullableType { + public abstract StringLiteral precision(); + + @Override + R accept(final ParameterizedTypeVisitor parameterizedTypeVisitor) + throws E { + return parameterizedTypeVisitor.visit(this); + } + + public static ImmutableParameterizedType.IntervalDay.Builder builder() { + return ImmutableParameterizedType.IntervalDay.builder(); + } + } + + @Value.Immutable + abstract static class IntervalCompound extends BaseParameterizedType implements NullableType { + public abstract StringLiteral precision(); + + @Override + R accept(final ParameterizedTypeVisitor parameterizedTypeVisitor) + throws E { + return parameterizedTypeVisitor.visit(this); + } + + public static ImmutableParameterizedType.IntervalCompound.Builder builder() { + return ImmutableParameterizedType.IntervalCompound.builder(); + } + } + @Value.Immutable abstract static class PrecisionTimestamp extends BaseParameterizedType implements NullableType { public abstract StringLiteral precision(); diff --git a/core/src/main/java/io/substrait/function/ParameterizedTypeCreator.java b/core/src/main/java/io/substrait/function/ParameterizedTypeCreator.java index 63db88887..be73b732c 100644 --- a/core/src/main/java/io/substrait/function/ParameterizedTypeCreator.java +++ b/core/src/main/java/io/substrait/function/ParameterizedTypeCreator.java @@ -49,6 +49,20 @@ public ParameterizedType decimalE(String precision, String scale) { .build(); } + public ParameterizedType intervalDayE(String precision) { + return ParameterizedType.IntervalDay.builder() + .nullable(nullable) + .precision(parameter(precision, false)) + .build(); + } + + public ParameterizedType intervalCompoundE(String precision) { + return ParameterizedType.IntervalCompound.builder() + .nullable(nullable) + .precision(parameter(precision, false)) + .build(); + } + public ParameterizedType precisionTimestampE(String precision) { return ParameterizedType.PrecisionTimestamp.builder() .nullable(nullable) diff --git a/core/src/main/java/io/substrait/function/ParameterizedTypeVisitor.java b/core/src/main/java/io/substrait/function/ParameterizedTypeVisitor.java index 67e685cc5..30cc9fda8 100644 --- a/core/src/main/java/io/substrait/function/ParameterizedTypeVisitor.java +++ b/core/src/main/java/io/substrait/function/ParameterizedTypeVisitor.java @@ -11,6 +11,10 @@ public interface ParameterizedTypeVisitor extends TypeVi R visit(ParameterizedType.Decimal expr) throws E; + R visit(ParameterizedType.IntervalDay expr) throws E; + + R visit(ParameterizedType.IntervalCompound expr) throws E; + R visit(ParameterizedType.PrecisionTimestamp expr) throws E; R visit(ParameterizedType.PrecisionTimestampTZ expr) throws E; @@ -60,6 +64,16 @@ public R visit(ParameterizedType.PrecisionTimestampTZ expr) throws E { throw t(); } + @Override + public R visit(ParameterizedType.IntervalDay expr) throws E { + throw t(); + } + + @Override + public R visit(ParameterizedType.IntervalCompound expr) throws E { + throw t(); + } + @Override public R visit(ParameterizedType.Struct expr) throws E { throw t(); diff --git a/core/src/main/java/io/substrait/function/ToTypeString.java b/core/src/main/java/io/substrait/function/ToTypeString.java index f68733cc6..a689ad245 100644 --- a/core/src/main/java/io/substrait/function/ToTypeString.java +++ b/core/src/main/java/io/substrait/function/ToTypeString.java @@ -90,6 +90,11 @@ public String visit(final Type.IntervalDay expr) { return "iday"; } + @Override + public String visit(final Type.IntervalCompound expr) { + return "icompound"; + } + @Override public String visit(final Type.UUID expr) { return "uuid"; @@ -165,6 +170,16 @@ public String visit(ParameterizedType.Decimal expr) throws RuntimeException { return "dec"; } + @Override + public String visit(ParameterizedType.IntervalDay expr) throws RuntimeException { + return "iday"; + } + + @Override + public String visit(ParameterizedType.IntervalCompound expr) throws RuntimeException { + return "icompound"; + } + @Override public String visit(ParameterizedType.PrecisionTimestamp expr) throws RuntimeException { return "pts"; diff --git a/core/src/main/java/io/substrait/function/TypeExpression.java b/core/src/main/java/io/substrait/function/TypeExpression.java index e9f7c5ce1..35cc802ae 100644 --- a/core/src/main/java/io/substrait/function/TypeExpression.java +++ b/core/src/main/java/io/substrait/function/TypeExpression.java @@ -84,6 +84,36 @@ public static ImmutableTypeExpression.Decimal.Builder builder() { } } + @Value.Immutable + abstract static class IntervalDay extends BaseTypeExpression implements NullableType { + + public abstract TypeExpression precision(); + + @Override + R acceptE(final TypeExpressionVisitor visitor) throws E { + return visitor.visit(this); + } + + public static ImmutableTypeExpression.IntervalDay.Builder builder() { + return ImmutableTypeExpression.IntervalDay.builder(); + } + } + + @Value.Immutable + abstract static class IntervalCompound extends BaseTypeExpression implements NullableType { + + public abstract TypeExpression precision(); + + @Override + R acceptE(final TypeExpressionVisitor visitor) throws E { + return visitor.visit(this); + } + + public static ImmutableTypeExpression.IntervalCompound.Builder builder() { + return ImmutableTypeExpression.IntervalCompound.builder(); + } + } + @Value.Immutable abstract static class PrecisionTimestamp extends BaseTypeExpression implements NullableType { diff --git a/core/src/main/java/io/substrait/function/TypeExpressionCreator.java b/core/src/main/java/io/substrait/function/TypeExpressionCreator.java index 5dc56584f..90a741cf1 100644 --- a/core/src/main/java/io/substrait/function/TypeExpressionCreator.java +++ b/core/src/main/java/io/substrait/function/TypeExpressionCreator.java @@ -35,6 +35,17 @@ public TypeExpression decimalE(TypeExpression precision, TypeExpression scale) { .build(); } + public TypeExpression intervalDayE(TypeExpression precision) { + return TypeExpression.IntervalDay.builder().nullable(nullable).precision(precision).build(); + } + + public TypeExpression intervalCompoundE(TypeExpression precision) { + return TypeExpression.IntervalCompound.builder() + .nullable(nullable) + .precision(precision) + .build(); + } + public TypeExpression precisionTimestampE(TypeExpression precision) { return TypeExpression.PrecisionTimestamp.builder() .nullable(nullable) diff --git a/core/src/main/java/io/substrait/function/TypeExpressionVisitor.java b/core/src/main/java/io/substrait/function/TypeExpressionVisitor.java index a30891e75..334d7609c 100644 --- a/core/src/main/java/io/substrait/function/TypeExpressionVisitor.java +++ b/core/src/main/java/io/substrait/function/TypeExpressionVisitor.java @@ -10,6 +10,10 @@ public interface TypeExpressionVisitor R visit(TypeExpression.Decimal expr) throws E; + R visit(TypeExpression.IntervalDay expr) throws E; + + R visit(TypeExpression.IntervalCompound expr) throws E; + R visit(TypeExpression.PrecisionTimestamp expr) throws E; R visit(TypeExpression.PrecisionTimestampTZ expr) throws E; @@ -68,6 +72,16 @@ public R visit(TypeExpression.PrecisionTimestampTZ expr) throws E { throw t(); } + @Override + public R visit(TypeExpression.IntervalDay expr) throws E { + throw t(); + } + + @Override + public R visit(TypeExpression.IntervalCompound expr) throws E { + throw t(); + } + @Override public R visit(TypeExpression.Struct expr) throws E { throw t(); diff --git a/core/src/main/java/io/substrait/relation/ExpressionCopyOnWriteVisitor.java b/core/src/main/java/io/substrait/relation/ExpressionCopyOnWriteVisitor.java index c88f7e68d..8a2fefb37 100644 --- a/core/src/main/java/io/substrait/relation/ExpressionCopyOnWriteVisitor.java +++ b/core/src/main/java/io/substrait/relation/ExpressionCopyOnWriteVisitor.java @@ -118,6 +118,11 @@ public Optional visit(Expression.IntervalDayLiteral expr) throws EXC return visitLiteral(expr); } + @Override + public Optional visit(Expression.IntervalCompoundLiteral expr) throws EXCEPTION { + return visitLiteral(expr); + } + @Override public Optional visit(Expression.UUIDLiteral expr) throws EXCEPTION { return visitLiteral(expr); diff --git a/core/src/main/java/io/substrait/relation/Join.java b/core/src/main/java/io/substrait/relation/Join.java index b571c7327..c3f9387b3 100644 --- a/core/src/main/java/io/substrait/relation/Join.java +++ b/core/src/main/java/io/substrait/relation/Join.java @@ -17,14 +17,14 @@ public abstract class Join extends BiRel implements HasExtension { public abstract JoinType getJoinType(); - public static enum JoinType { + public enum JoinType { UNKNOWN(JoinRel.JoinType.JOIN_TYPE_UNSPECIFIED), INNER(JoinRel.JoinType.JOIN_TYPE_INNER), OUTER(JoinRel.JoinType.JOIN_TYPE_OUTER), LEFT(JoinRel.JoinType.JOIN_TYPE_LEFT), RIGHT(JoinRel.JoinType.JOIN_TYPE_RIGHT), - SEMI(JoinRel.JoinType.JOIN_TYPE_SEMI), - ANTI(JoinRel.JoinType.JOIN_TYPE_ANTI); + SEMI(JoinRel.JoinType.JOIN_TYPE_LEFT_SEMI), + ANTI(JoinRel.JoinType.JOIN_TYPE_LEFT_ANTI); private JoinRel.JoinType proto; diff --git a/core/src/main/java/io/substrait/relation/ProtoRelConverter.java b/core/src/main/java/io/substrait/relation/ProtoRelConverter.java index 2d66c5c4c..84f7fcd3d 100644 --- a/core/src/main/java/io/substrait/relation/ProtoRelConverter.java +++ b/core/src/main/java/io/substrait/relation/ProtoRelConverter.java @@ -302,6 +302,8 @@ private FileOrFiles newFileOrFiles(ReadRel.LocalFiles.FileOrFiles file) { builder.fileFormat(ImmutableFileFormat.ArrowReadOptions.builder().build()); } else if (file.hasDwrf()) { builder.fileFormat(ImmutableFileFormat.DwrfReadOptions.builder().build()); + } else if (file.hasText()) { + throw new RuntimeException("Delimiter separated text files not supported yet"); // TODO } else if (file.hasExtension()) { builder.fileFormat( ImmutableFileFormat.Extension.builder().extension(file.getExtension()).build()); diff --git a/core/src/main/java/io/substrait/relation/VirtualTableScan.java b/core/src/main/java/io/substrait/relation/VirtualTableScan.java index c35dab8cb..e30836af5 100644 --- a/core/src/main/java/io/substrait/relation/VirtualTableScan.java +++ b/core/src/main/java/io/substrait/relation/VirtualTableScan.java @@ -140,6 +140,11 @@ public Integer visit(Type.IntervalDay type) throws RuntimeException { return 0; } + @Override + public Integer visit(Type.IntervalCompound type) throws RuntimeException { + return 0; + } + @Override public Integer visit(Type.UUID type) throws RuntimeException { return 0; diff --git a/core/src/main/java/io/substrait/type/StringTypeVisitor.java b/core/src/main/java/io/substrait/type/StringTypeVisitor.java index 668b770cd..16651c8d2 100644 --- a/core/src/main/java/io/substrait/type/StringTypeVisitor.java +++ b/core/src/main/java/io/substrait/type/StringTypeVisitor.java @@ -84,6 +84,11 @@ public String visit(Type.IntervalDay type) throws RuntimeException { return "interval_day" + n(type); } + @Override + public String visit(Type.IntervalCompound type) throws RuntimeException { + return "interval_compound" + n(type); + } + @Override public String visit(Type.UUID type) throws RuntimeException { return "uuid" + n(type); diff --git a/core/src/main/java/io/substrait/type/Type.java b/core/src/main/java/io/substrait/type/Type.java index 43d1fd60c..35b9b318d 100644 --- a/core/src/main/java/io/substrait/type/Type.java +++ b/core/src/main/java/io/substrait/type/Type.java @@ -202,6 +202,8 @@ public R accept(final TypeVisitor typeVisitor) th @Value.Immutable abstract static class IntervalDay implements Type { + public abstract int precision(); + public static ImmutableType.IntervalDay.Builder builder() { return ImmutableType.IntervalDay.builder(); } @@ -212,6 +214,20 @@ public R accept(final TypeVisitor typeVisitor) th } } + @Value.Immutable + abstract static class IntervalCompound implements Type { + public abstract int precision(); + + public static ImmutableType.IntervalCompound.Builder builder() { + return ImmutableType.IntervalCompound.builder(); + } + + @Override + public R accept(final TypeVisitor typeVisitor) throws E { + return typeVisitor.visit(this); + } + } + @Value.Immutable abstract static class UUID implements Type { public static ImmutableType.UUID.Builder builder() { diff --git a/core/src/main/java/io/substrait/type/TypeCreator.java b/core/src/main/java/io/substrait/type/TypeCreator.java index adaedd0b1..a53d71aa6 100644 --- a/core/src/main/java/io/substrait/type/TypeCreator.java +++ b/core/src/main/java/io/substrait/type/TypeCreator.java @@ -22,7 +22,6 @@ public class TypeCreator { public final Type TIMESTAMP_TZ; public final Type DATE; public final Type TIME; - public final Type INTERVAL_DAY; public final Type INTERVAL_YEAR; public final Type UUID; @@ -41,7 +40,6 @@ protected TypeCreator(boolean nullable) { TIMESTAMP_TZ = Type.TimestampTZ.builder().nullable(nullable).build(); DATE = Type.Date.builder().nullable(nullable).build(); TIME = Type.Time.builder().nullable(nullable).build(); - INTERVAL_DAY = Type.IntervalDay.builder().nullable(nullable).build(); INTERVAL_YEAR = Type.IntervalYear.builder().nullable(nullable).build(); UUID = Type.UUID.builder().nullable(nullable).build(); } @@ -74,6 +72,14 @@ public final Type precisionTimestampTZ(int precision) { return Type.PrecisionTimestampTZ.builder().nullable(nullable).precision(precision).build(); } + public final Type intervalDay(int precision) { + return Type.IntervalDay.builder().nullable(nullable).precision(precision).build(); + } + + public final Type intervalCompound(int precision) { + return Type.IntervalCompound.builder().nullable(nullable).precision(precision).build(); + } + public Type.Struct struct(Iterable types) { return Type.Struct.builder().nullable(nullable).addAllFields(types).build(); } @@ -198,6 +204,11 @@ public Type visit(Type.IntervalDay type) throws RuntimeException { return Type.IntervalDay.builder().from(type).nullable(nullability).build(); } + @Override + public Type visit(Type.IntervalCompound type) throws RuntimeException { + return Type.IntervalCompound.builder().from(type).nullable(nullability).build(); + } + @Override public Type visit(Type.UUID type) throws RuntimeException { return Type.UUID.builder().from(type).nullable(nullability).build(); diff --git a/core/src/main/java/io/substrait/type/TypeVisitor.java b/core/src/main/java/io/substrait/type/TypeVisitor.java index 9d377499c..e89bf1049 100644 --- a/core/src/main/java/io/substrait/type/TypeVisitor.java +++ b/core/src/main/java/io/substrait/type/TypeVisitor.java @@ -37,6 +37,8 @@ public interface TypeVisitor { R visit(Type.IntervalDay type) throws E; + R visit(Type.IntervalCompound type) throws E; + R visit(Type.UUID type) throws E; R visit(Type.FixedChar type) throws E; @@ -143,6 +145,11 @@ public R visit(Type.IntervalDay type) throws E { throw t(); } + @Override + public R visit(Type.IntervalCompound type) throws E { + throw t(); + } + @Override public R visit(Type.UUID type) throws E { throw t(); diff --git a/core/src/main/java/io/substrait/type/parser/ParseToPojo.java b/core/src/main/java/io/substrait/type/parser/ParseToPojo.java index 9ae85f438..d27bd03e2 100644 --- a/core/src/main/java/io/substrait/type/parser/ParseToPojo.java +++ b/core/src/main/java/io/substrait/type/parser/ParseToPojo.java @@ -152,13 +152,41 @@ public Type visitTime(final SubstraitTypeParser.TimeContext ctx) { } @Override - public Type visitIntervalDay(final SubstraitTypeParser.IntervalDayContext ctx) { - return withNull(ctx).INTERVAL_DAY; + public Type visitIntervalYear(final SubstraitTypeParser.IntervalYearContext ctx) { + return withNull(ctx).INTERVAL_YEAR; } @Override - public Type visitIntervalYear(final SubstraitTypeParser.IntervalYearContext ctx) { - return withNull(ctx).INTERVAL_YEAR; + public TypeExpression visitIntervalDay(final SubstraitTypeParser.IntervalDayContext ctx) { + boolean nullable = ctx.isnull != null; + Object precision = i(ctx.precision); + if (precision instanceof Integer p) { + return withNull(nullable).intervalDay(p); + } + if (precision instanceof String s) { + checkParameterizedOrExpression(); + return withNullP(nullable).intervalDayE(s); + } + + checkExpression(); + return withNullE(nullable).intervalDayE(ctx.precision.accept(this)); + } + + @Override + public TypeExpression visitIntervalCompound( + final SubstraitTypeParser.IntervalCompoundContext ctx) { + boolean nullable = ctx.isnull != null; + Object precision = i(ctx.precision); + if (precision instanceof Integer p) { + return withNull(nullable).intervalCompound(p); + } + if (precision instanceof String s) { + checkParameterizedOrExpression(); + return withNullP(nullable).intervalCompoundE(s); + } + + checkExpression(); + return withNullE(nullable).intervalCompoundE(ctx.precision.accept(this)); } @Override @@ -233,6 +261,16 @@ public TypeExpression visitDecimal(final SubstraitTypeParser.DecimalContext ctx) return withNullP(nullable).decimalE((String) precision, (String) scale); } + if (precision instanceof String && scale instanceof Integer) { + checkParameterizedOrExpression(); + return withNullP(nullable).decimalE((String) precision, String.valueOf(scale)); + } + + if (precision instanceof Integer && scale instanceof String) { + checkParameterizedOrExpression(); + return withNullP(nullable).decimalE(String.valueOf(precision), (String) scale); + } + checkExpression(); return withNullE(nullable).decimalE(ctx.precision.accept(this), ctx.scale.accept(this)); } diff --git a/core/src/main/java/io/substrait/type/proto/BaseProtoConverter.java b/core/src/main/java/io/substrait/type/proto/BaseProtoConverter.java index f21a03f79..2d0d12049 100644 --- a/core/src/main/java/io/substrait/type/proto/BaseProtoConverter.java +++ b/core/src/main/java/io/substrait/type/proto/BaseProtoConverter.java @@ -96,7 +96,12 @@ public final T visit(final Type.IntervalYear expr) { @Override public final T visit(final Type.IntervalDay expr) { - return typeContainer(expr).INTERVAL_DAY; + return typeContainer(expr).intervalDay(expr.precision()); + } + + @Override + public final T visit(final Type.IntervalCompound expr) { + return typeContainer(expr).intervalCompound(expr.precision()); } @Override diff --git a/core/src/main/java/io/substrait/type/proto/BaseProtoTypes.java b/core/src/main/java/io/substrait/type/proto/BaseProtoTypes.java index ac4c13521..21711068b 100644 --- a/core/src/main/java/io/substrait/type/proto/BaseProtoTypes.java +++ b/core/src/main/java/io/substrait/type/proto/BaseProtoTypes.java @@ -19,7 +19,6 @@ abstract class BaseProtoTypes { public final T TIMESTAMP_TZ; public final T DATE; public final T TIME; - public final T INTERVAL_DAY; public final T INTERVAL_YEAR; public final T UUID; @@ -38,7 +37,6 @@ public BaseProtoTypes(Type.Nullability nullability) { TIMESTAMP_TZ = wrap(Type.TimestampTZ.newBuilder().setNullability(nullability).build()); DATE = wrap(Type.Date.newBuilder().setNullability(nullability).build()); TIME = wrap(Type.Time.newBuilder().setNullability(nullability).build()); - INTERVAL_DAY = wrap(Type.IntervalDay.newBuilder().setNullability(nullability).build()); INTERVAL_YEAR = wrap(Type.IntervalYear.newBuilder().setNullability(nullability).build()); UUID = wrap(Type.UUID.newBuilder().setNullability(nullability).build()); } @@ -81,6 +79,14 @@ public final T decimal(int scale, I precision) { return decimal(i(scale), precision); } + public final T intervalDay(int precision) { + return intervalDay(i(precision)); + } + + public final T intervalCompound(int precision) { + return intervalCompound(i(precision)); + } + public final T precisionTimestamp(int precision) { return precisionTimestamp(i(precision)); } @@ -103,6 +109,10 @@ public final T precisionTimestampTZ(int precision) { public abstract T precisionTimestampTZ(I precision); + public abstract T intervalDay(I precision); + + public abstract T intervalCompound(I precision); + public final T struct(T... types) { return struct(Arrays.asList(types)); } diff --git a/core/src/main/java/io/substrait/type/proto/ParameterizedProtoConverter.java b/core/src/main/java/io/substrait/type/proto/ParameterizedProtoConverter.java index f2270b822..7697c93d4 100644 --- a/core/src/main/java/io/substrait/type/proto/ParameterizedProtoConverter.java +++ b/core/src/main/java/io/substrait/type/proto/ParameterizedProtoConverter.java @@ -186,6 +186,24 @@ public ParameterizedType decimal( .build()); } + @Override + public ParameterizedType intervalDay(ParameterizedType.IntegerOption precision) { + return wrap( + ParameterizedType.ParameterizedIntervalDay.newBuilder() + .setPrecision(precision) + .setNullability(nullability) + .build()); + } + + @Override + public ParameterizedType intervalCompound(ParameterizedType.IntegerOption precision) { + return wrap( + ParameterizedType.ParameterizedIntervalCompound.newBuilder() + .setPrecision(precision) + .setNullability(nullability) + .build()); + } + @Override public ParameterizedType precisionTimestamp(ParameterizedType.IntegerOption precision) { return wrap( @@ -266,8 +284,10 @@ protected ParameterizedType wrap(final Object o) { return bldr.setTimestampTz(t).build(); } else if (o instanceof Type.IntervalYear t) { return bldr.setIntervalYear(t).build(); - } else if (o instanceof Type.IntervalDay t) { + } else if (o instanceof ParameterizedType.ParameterizedIntervalDay t) { return bldr.setIntervalDay(t).build(); + } else if (o instanceof ParameterizedType.ParameterizedIntervalCompound t) { + return bldr.setIntervalCompound(t).build(); } else if (o instanceof ParameterizedType.ParameterizedFixedChar t) { return bldr.setFixedChar(t).build(); } else if (o instanceof ParameterizedType.ParameterizedVarChar t) { diff --git a/core/src/main/java/io/substrait/type/proto/ProtoTypeConverter.java b/core/src/main/java/io/substrait/type/proto/ProtoTypeConverter.java index a4352c463..90776ba23 100644 --- a/core/src/main/java/io/substrait/type/proto/ProtoTypeConverter.java +++ b/core/src/main/java/io/substrait/type/proto/ProtoTypeConverter.java @@ -32,7 +32,12 @@ public Type from(io.substrait.proto.Type type) { case DATE -> n(type.getDate().getNullability()).DATE; case TIME -> n(type.getTime().getNullability()).TIME; case INTERVAL_YEAR -> n(type.getIntervalYear().getNullability()).INTERVAL_YEAR; - case INTERVAL_DAY -> n(type.getIntervalDay().getNullability()).INTERVAL_DAY; + case INTERVAL_DAY -> n(type.getIntervalDay().getNullability()) + // precision defaults to 6 (micros) for backwards compatibility, see protobuf + .intervalDay( + type.getIntervalDay().hasPrecision() ? type.getIntervalDay().getPrecision() : 6); + case INTERVAL_COMPOUND -> n(type.getIntervalCompound().getNullability()) + .intervalCompound(type.getIntervalCompound().getPrecision()); case TIMESTAMP_TZ -> n(type.getTimestampTz().getNullability()).TIMESTAMP_TZ; case UUID -> n(type.getUuid().getNullability()).UUID; case FIXED_CHAR -> n(type.getFixedChar().getNullability()) diff --git a/core/src/main/java/io/substrait/type/proto/TypeExpressionProtoVisitor.java b/core/src/main/java/io/substrait/type/proto/TypeExpressionProtoVisitor.java index 07e5b1071..8949e366e 100644 --- a/core/src/main/java/io/substrait/type/proto/TypeExpressionProtoVisitor.java +++ b/core/src/main/java/io/substrait/type/proto/TypeExpressionProtoVisitor.java @@ -121,6 +121,16 @@ public DerivationExpression visit(ParameterizedType.Decimal expr) { return typeContainer(expr).decimal(expr.precision().accept(this), expr.scale().accept(this)); } + @Override + public DerivationExpression visit(ParameterizedType.IntervalDay expr) { + return typeContainer(expr).intervalDay(expr.precision().accept(this)); + } + + @Override + public DerivationExpression visit(ParameterizedType.IntervalCompound expr) { + return typeContainer(expr).intervalCompound(expr.precision().accept(this)); + } + @Override public DerivationExpression visit(ParameterizedType.PrecisionTimestamp expr) { return typeContainer(expr).precisionTimestamp(expr.precision().accept(this)); @@ -263,6 +273,24 @@ public DerivationExpression precisionTimestampTZ(DerivationExpression precision) .build()); } + @Override + public DerivationExpression intervalDay(DerivationExpression precision) { + return wrap( + DerivationExpression.ExpressionIntervalDay.newBuilder() + .setPrecision(precision) + .setNullability(nullability) + .build()); + } + + @Override + public DerivationExpression intervalCompound(DerivationExpression precision) { + return wrap( + DerivationExpression.ExpressionIntervalCompound.newBuilder() + .setPrecision(precision) + .setNullability(nullability) + .build()); + } + public DerivationExpression struct(Iterable types) { return wrap( DerivationExpression.ExpressionStruct.newBuilder() @@ -329,8 +357,10 @@ protected DerivationExpression wrap(final Object o) { return bldr.setTimestampTz(t).build(); } else if (o instanceof Type.IntervalYear t) { return bldr.setIntervalYear(t).build(); - } else if (o instanceof Type.IntervalDay t) { + } else if (o instanceof DerivationExpression.ExpressionIntervalDay t) { return bldr.setIntervalDay(t).build(); + } else if (o instanceof DerivationExpression.ExpressionIntervalCompound t) { + return bldr.setIntervalCompound(t).build(); } else if (o instanceof DerivationExpression.ExpressionFixedChar t) { return bldr.setFixedChar(t).build(); } else if (o instanceof DerivationExpression.ExpressionVarChar t) { diff --git a/core/src/main/java/io/substrait/type/proto/TypeProtoConverter.java b/core/src/main/java/io/substrait/type/proto/TypeProtoConverter.java index e21cc158a..3c734dcf1 100644 --- a/core/src/main/java/io/substrait/type/proto/TypeProtoConverter.java +++ b/core/src/main/java/io/substrait/type/proto/TypeProtoConverter.java @@ -61,6 +61,22 @@ public Type decimal(Integer scale, Integer precision) { .build()); } + public Type intervalDay(Integer precision) { + return wrap( + Type.IntervalDay.newBuilder() + .setPrecision(precision) + .setNullability(nullability) + .build()); + } + + public Type intervalCompound(Integer precision) { + return wrap( + Type.IntervalCompound.newBuilder() + .setPrecision(precision) + .setNullability(nullability) + .build()); + } + public Type precisionTimestamp(Integer precision) { return wrap( Type.PrecisionTimestamp.newBuilder() @@ -129,6 +145,8 @@ protected Type wrap(final Object o) { return bldr.setIntervalYear(t).build(); } else if (o instanceof Type.IntervalDay t) { return bldr.setIntervalDay(t).build(); + } else if (o instanceof Type.IntervalCompound t) { + return bldr.setIntervalCompound(t).build(); } else if (o instanceof Type.FixedChar t) { return bldr.setFixedChar(t).build(); } else if (o instanceof Type.VarChar t) { diff --git a/core/src/test/java/io/substrait/type/parser/TestTypeParser.java b/core/src/test/java/io/substrait/type/parser/TestTypeParser.java index 56a6ce51f..980c494cd 100644 --- a/core/src/test/java/io/substrait/type/parser/TestTypeParser.java +++ b/core/src/test/java/io/substrait/type/parser/TestTypeParser.java @@ -119,6 +119,9 @@ private void parameterizedTests(ParseToPojo.Visitor v) { test(v, pn.listE(pr.parameter("any")), "list?"); test(v, pn.listE(pn.parameter("any")), "list?"); test(v, pn.structE(r.I8, r.I16, n.I8, pr.parameter("K")), "STRUCT?"); + test(v, pr.decimalE("P", "S"), "DECIMAL"); + test(v, pr.decimalE("P", "0"), "DECIMAL"); + test(v, pr.decimalE("14", "S"), "DECIMAL<14, S>"); } private static void test(ParseToPojo.Visitor visitor, TypeExpression expected, String toParse) { diff --git a/core/src/test/java/io/substrait/type/proto/LocalFilesRoundtripTest.java b/core/src/test/java/io/substrait/type/proto/LocalFilesRoundtripTest.java index a54232292..7166eef6c 100644 --- a/core/src/test/java/io/substrait/type/proto/LocalFilesRoundtripTest.java +++ b/core/src/test/java/io/substrait/type/proto/LocalFilesRoundtripTest.java @@ -75,6 +75,7 @@ private ImmutableFileOrFiles.Builder setFileFormat( case ARROW -> builder.fileFormat(ImmutableFileFormat.ArrowReadOptions.builder().build()); case ORC -> builder.fileFormat(ImmutableFileFormat.OrcReadOptions.builder().build()); case DWRF -> builder.fileFormat(ImmutableFileFormat.DwrfReadOptions.builder().build()); + case TEXT -> builder; // TODO case EXTENSION -> builder.fileFormat( ImmutableFileFormat.Extension.builder() .extension(com.google.protobuf.Any.newBuilder().build()) diff --git a/core/src/test/java/io/substrait/type/proto/TestTypeRoundtrip.java b/core/src/test/java/io/substrait/type/proto/TestTypeRoundtrip.java index 0f7af8b29..d43a996a3 100644 --- a/core/src/test/java/io/substrait/type/proto/TestTypeRoundtrip.java +++ b/core/src/test/java/io/substrait/type/proto/TestTypeRoundtrip.java @@ -28,12 +28,15 @@ public void roundtrip(boolean n) { t(creator(n).TIMESTAMP); t(creator(n).TIMESTAMP_TZ); t(creator(n).INTERVAL_YEAR); - t(creator(n).INTERVAL_DAY); t(creator(n).UUID); t(creator(n).fixedChar(25)); t(creator(n).varChar(35)); t(creator(n).fixedBinary(45)); t(creator(n).decimal(34, 3)); + t(creator(n).intervalDay(6)); + t(creator(n).intervalCompound(3)); + t(creator(n).precisionTimestamp(1)); + t(creator(n).precisionTimestampTZ(2)); t(creator(n).map(creator(n).I8, creator(n).I16)); t(creator(n).list(creator(n).TIME)); t(creator(n).struct(creator(n).TIME, creator(n).TIMESTAMP, creator(n).TIMESTAMP_TZ)); diff --git a/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java b/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java index e4ce67009..1adf5b861 100644 --- a/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java +++ b/isthmus/src/main/java/io/substrait/isthmus/TypeConverter.java @@ -102,7 +102,7 @@ private Type toSubstrait(RelDataType type, List names) { INTERVAL_HOUR_SECOND, INTERVAL_MINUTE, INTERVAL_MINUTE_SECOND, - INTERVAL_SECOND -> creator.INTERVAL_DAY; + INTERVAL_SECOND -> creator.intervalDay(type.getScale()); case VARBINARY -> creator.BINARY; case BINARY -> creator.fixedBinary(type.getPrecision()); case MAP -> { diff --git a/isthmus/src/main/java/io/substrait/isthmus/expression/ExpressionRexConverter.java b/isthmus/src/main/java/io/substrait/isthmus/expression/ExpressionRexConverter.java index 8f0cf24ec..9dd32e072 100644 --- a/isthmus/src/main/java/io/substrait/isthmus/expression/ExpressionRexConverter.java +++ b/isthmus/src/main/java/io/substrait/isthmus/expression/ExpressionRexConverter.java @@ -229,17 +229,17 @@ public RexNode visit(Expression.IntervalYearLiteral expr) throws RuntimeExceptio new BigDecimal(expr.years() * 12 + expr.months()), YEAR_MONTH_INTERVAL); } - private static final long MICROS_IN_DAY = TimeUnit.DAYS.toMicros(1); + private static final long MILLIS_IN_DAY = TimeUnit.DAYS.toMillis(1); @Override public RexNode visit(Expression.IntervalDayLiteral expr) throws RuntimeException { + long milliseconds = + expr.precision() > 3 + ? (expr.subseconds() / (int) Math.pow(10, expr.precision() - 3)) + : (expr.subseconds() * (int) Math.pow(10, 3 - expr.precision())); return rexBuilder.makeIntervalLiteral( // Current Calcite behavior is to store milliseconds since Epoch - // microseconds version: new BigDecimal(expr.days() * MICROS_IN_DAY + expr.seconds() * - // 100000L + expr.microseconds()), DAY_SECOND_INTERVAL); - new BigDecimal( - (expr.days() * MICROS_IN_DAY + expr.seconds() * 1_000_000L + expr.microseconds()) - / 1000L), + new BigDecimal((expr.days() * MILLIS_IN_DAY + expr.seconds() * 1_000L + milliseconds)), DAY_SECOND_INTERVAL); } diff --git a/isthmus/src/main/java/io/substrait/isthmus/expression/IgnoreNullableAndParameters.java b/isthmus/src/main/java/io/substrait/isthmus/expression/IgnoreNullableAndParameters.java index a170268ff..34a2b591b 100644 --- a/isthmus/src/main/java/io/substrait/isthmus/expression/IgnoreNullableAndParameters.java +++ b/isthmus/src/main/java/io/substrait/isthmus/expression/IgnoreNullableAndParameters.java @@ -85,7 +85,14 @@ public Boolean visit(Type.IntervalYear type) { @Override public Boolean visit(Type.IntervalDay type) { - return typeToMatch instanceof Type.IntervalDay; + return typeToMatch instanceof Type.IntervalDay + || typeToMatch instanceof ParameterizedType.IntervalDay; + } + + @Override + public Boolean visit(Type.IntervalCompound type) { + return typeToMatch instanceof Type.IntervalCompound + || typeToMatch instanceof ParameterizedType.IntervalCompound; } @Override @@ -171,6 +178,18 @@ public Boolean visit(ParameterizedType.Decimal expr) throws RuntimeException { return typeToMatch instanceof Type.Decimal || typeToMatch instanceof ParameterizedType.Decimal; } + @Override + public Boolean visit(ParameterizedType.IntervalDay expr) throws RuntimeException { + return typeToMatch instanceof Type.IntervalDay + || typeToMatch instanceof ParameterizedType.IntervalDay; + } + + @Override + public Boolean visit(ParameterizedType.IntervalCompound expr) throws RuntimeException { + return typeToMatch instanceof Type.IntervalCompound + || typeToMatch instanceof ParameterizedType.IntervalCompound; + } + @Override public Boolean visit(ParameterizedType.PrecisionTimestamp expr) throws RuntimeException { return typeToMatch instanceof Type.PrecisionTimestamp diff --git a/isthmus/src/main/java/io/substrait/isthmus/expression/LiteralConverter.java b/isthmus/src/main/java/io/substrait/isthmus/expression/LiteralConverter.java index 433284b24..777ad33ea 100644 --- a/isthmus/src/main/java/io/substrait/isthmus/expression/LiteralConverter.java +++ b/isthmus/src/main/java/io/substrait/isthmus/expression/LiteralConverter.java @@ -172,6 +172,7 @@ public Expression.Literal convert(RexLiteral literal) { INTERVAL_MINUTE_SECOND, INTERVAL_SECOND -> { // we need to convert to microseconds. + // TODO: don't need to anymore int scale = literal.getType().getScale(); var intervalLength = literal.getValueAs(BigDecimal.class).longValue(); var adjustedLength = @@ -182,7 +183,7 @@ public Expression.Literal convert(RexLiteral literal) { var totalMicroseconds = adjustedLength - days * MICROS_IN_DAY; var seconds = totalMicroseconds / 1_000_000; var microseconds = totalMicroseconds - 1_000_000 * seconds; - yield intervalDay(n, (int) days, (int) seconds, (int) microseconds); + yield intervalDay(n, (int) days, (int) seconds, microseconds, 6 /* micros */); } case ROW -> { diff --git a/isthmus/src/test/java/io/substrait/isthmus/CalciteLiteralTest.java b/isthmus/src/test/java/io/substrait/isthmus/CalciteLiteralTest.java index 5029b678f..d6279226f 100644 --- a/isthmus/src/test/java/io/substrait/isthmus/CalciteLiteralTest.java +++ b/isthmus/src/test/java/io/substrait/isthmus/CalciteLiteralTest.java @@ -211,7 +211,7 @@ void tIntervalMillisecond() { org.apache.calcite.avatica.util.TimeUnit.SECOND, 3, SqlParserPos.ZERO)); - var intervalDaySecondExpr = intervalDay(false, 3, 5 * 3600 + 7 * 60 + 9, 500_000); + var intervalDaySecondExpr = intervalDay(false, 3, 5 * 3600 + 7 * 60 + 9, 500_000, 6); bitest(intervalDaySecondExpr, intervalDaySecond); } diff --git a/isthmus/src/test/java/io/substrait/isthmus/CalciteTypeTest.java b/isthmus/src/test/java/io/substrait/isthmus/CalciteTypeTest.java index 20cbd962f..731c9fef4 100644 --- a/isthmus/src/test/java/io/substrait/isthmus/CalciteTypeTest.java +++ b/isthmus/src/test/java/io/substrait/isthmus/CalciteTypeTest.java @@ -118,7 +118,7 @@ void intervalYear(boolean nullable) { @ValueSource(booleans = {true, false}) void intervalDay(boolean nullable) { testType( - Type.withNullability(nullable).INTERVAL_DAY, + Type.withNullability(nullable).intervalDay(6), type.createSqlIntervalType(SubstraitTypeSystem.DAY_SECOND_INTERVAL), nullable); } diff --git a/spark/src/main/scala/io/substrait/spark/expression/IgnoreNullableAndParameters.scala b/spark/src/main/scala/io/substrait/spark/expression/IgnoreNullableAndParameters.scala index 962a98b16..00076ce63 100644 --- a/spark/src/main/scala/io/substrait/spark/expression/IgnoreNullableAndParameters.scala +++ b/spark/src/main/scala/io/substrait/spark/expression/IgnoreNullableAndParameters.scala @@ -55,7 +55,11 @@ class IgnoreNullableAndParameters(val typeToMatch: ParameterizedType) override def visit(`type`: Type.IntervalYear): Boolean = typeToMatch.isInstanceOf[Type.IntervalYear] - override def visit(`type`: Type.IntervalDay): Boolean = typeToMatch.isInstanceOf[Type.IntervalDay] + override def visit(`type`: Type.IntervalDay): Boolean = + typeToMatch.isInstanceOf[Type.IntervalDay] || typeToMatch.isInstanceOf[ParameterizedType.IntervalDay] + + override def visit(`type`: Type.IntervalCompound): Boolean = + typeToMatch.isInstanceOf[Type.IntervalCompound] || typeToMatch.isInstanceOf[ParameterizedType.IntervalCompound] override def visit(`type`: Type.UUID): Boolean = typeToMatch.isInstanceOf[Type.UUID] @@ -103,6 +107,14 @@ class IgnoreNullableAndParameters(val typeToMatch: ParameterizedType) override def visit(expr: ParameterizedType.Decimal): Boolean = typeToMatch.isInstanceOf[Type.Decimal] || typeToMatch.isInstanceOf[ParameterizedType.Decimal] + @throws[RuntimeException] + override def visit(expr: ParameterizedType.IntervalDay): Boolean = + typeToMatch.isInstanceOf[Type.IntervalDay] || typeToMatch.isInstanceOf[ParameterizedType.IntervalDay] + + @throws[RuntimeException] + override def visit(expr: ParameterizedType.IntervalCompound): Boolean = + typeToMatch.isInstanceOf[Type.IntervalCompound] || typeToMatch.isInstanceOf[ParameterizedType.IntervalCompound] + @throws[RuntimeException] override def visit(expr: ParameterizedType.Struct): Boolean = typeToMatch.isInstanceOf[Type.Struct] || typeToMatch.isInstanceOf[ParameterizedType.Struct] diff --git a/substrait b/substrait index a68c1ac62..bc4d6fb9b 160000 --- a/substrait +++ b/substrait @@ -1 +1 @@ -Subproject commit a68c1ac62f92d703da624cb8ac0cef854dd2b35f +Subproject commit bc4d6fb9bc0435c3db24172566c343e119fc50a9