Noticed while reviewing #4617.
The problem
ArithmeticValue.getResultType() derives only the type code from the physical operator and takes the default nullability:
// ArithmeticValue.java
@Override
public Type getResultType() {
return Type.primitiveType(operator.getResultTypeCode());
}
and the single-argument overload is nullable:
// Type.java
static Type primitiveType(@Nonnull final TypeCode typeCode) {
return primitiveType(typeCode, true);
}
So a + b is typed nullable even when a and b are both not-nullable. Arithmetic on not-null operands cannot produce null, so this loses information for every arithmetic expression in the system.
Where it bites
In LogicalOperator.generateCorrelatedFieldAccess, the SQL AT ordinal is built as explodeOrdinal + 1, where the ordinal is a field of the explode result typed Type.primitiveType(INT, false) and the literal comes from LiteralValue.ofScalar(1), which is Type.fromObject(1) = Type.primitiveType(INT, false). Both operands are not-nullable, yet the sum is nullable, while the column is declared with DataType.Primitives.INTEGER.type(), i.e. IntegerType.notNullable(). The declared SQL type and the underlying value type therefore disagree.
Noticed while reviewing #4617.
The problem
ArithmeticValue.getResultType()derives only the type code from the physical operator and takes the default nullability:and the single-argument overload is nullable:
So
a + bis typed nullable even whenaandbare both not-nullable. Arithmetic on not-null operands cannot produce null, so this loses information for every arithmetic expression in the system.Where it bites
In
LogicalOperator.generateCorrelatedFieldAccess, the SQLATordinal is built asexplodeOrdinal + 1, where the ordinal is a field of the explode result typedType.primitiveType(INT, false)and the literal comes fromLiteralValue.ofScalar(1), which isType.fromObject(1)=Type.primitiveType(INT, false). Both operands are not-nullable, yet the sum is nullable, while the column is declared withDataType.Primitives.INTEGER.type(), i.e.IntegerType.notNullable(). The declared SQL type and the underlying value type therefore disagree.