55
66package org .opensearch .sql .calcite .validate ;
77
8+ import static org .opensearch .sql .calcite .validate .ValidationUtils .createUDTWithAttributes ;
9+
810import java .util .List ;
911import java .util .Map ;
1012import java .util .Set ;
1113import java .util .stream .IntStream ;
1214import org .apache .calcite .rel .type .RelDataType ;
1315import org .apache .calcite .rel .type .RelDataTypeFactory ;
1416import org .apache .calcite .sql .SqlCallBinding ;
17+ import org .apache .calcite .sql .SqlNode ;
1518import org .apache .calcite .sql .type .SqlTypeFamily ;
19+ import org .apache .calcite .sql .type .SqlTypeMappingRule ;
20+ import org .apache .calcite .sql .type .SqlTypeName ;
21+ import org .apache .calcite .sql .type .SqlTypeUtil ;
1622import org .apache .calcite .sql .validate .SqlValidator ;
23+ import org .apache .calcite .sql .validate .SqlValidatorScope ;
1724import org .apache .calcite .sql .validate .implicit .TypeCoercionImpl ;
25+ import org .checkerframework .checker .nullness .qual .Nullable ;
26+ import org .opensearch .sql .calcite .utils .OpenSearchTypeFactory ;
1827
1928/**
2029 * Custom type coercion implementation for PPL that extends Calcite's default type coercion with
@@ -30,14 +39,14 @@ public class PplTypeCoercion extends TypeCoercionImpl {
3039
3140 static {
3241 // Initialize the blacklist for coercions that are not allowed in PPL.
33- BLACKLISTED_COERCIONS =
34- Map .of (
35- SqlTypeFamily .CHARACTER ,
36- Set .of (SqlTypeFamily .NUMERIC ),
37- SqlTypeFamily .STRING ,
38- Set .of (SqlTypeFamily .NUMERIC ),
39- SqlTypeFamily .NUMERIC ,
40- Set .of (SqlTypeFamily .CHARACTER , SqlTypeFamily .STRING ));
42+ BLACKLISTED_COERCIONS = Map . of ();
43+ // Map.of(
44+ // SqlTypeFamily.CHARACTER,
45+ // Set.of(SqlTypeFamily.NUMERIC),
46+ // SqlTypeFamily.STRING,
47+ // Set.of(SqlTypeFamily.NUMERIC),
48+ // SqlTypeFamily.NUMERIC,
49+ // Set.of(SqlTypeFamily.CHARACTER, SqlTypeFamily.STRING));
4150 }
4251
4352 public PplTypeCoercion (RelDataTypeFactory typeFactory , SqlValidator validator ) {
@@ -73,4 +82,33 @@ private boolean isBlacklistedCoercion(RelDataType operandType, SqlTypeFamily exp
7382 }
7483 return false ;
7584 }
85+
86+ @ Override
87+ public @ Nullable RelDataType implicitCast (RelDataType in , SqlTypeFamily expected ) {
88+ RelDataType casted = super .implicitCast (in , expected );
89+ return switch (casted .getSqlTypeName ()) {
90+ case SqlTypeName .DATE ->
91+ createUDTWithAttributes (factory , in , OpenSearchTypeFactory .ExprUDT .EXPR_DATE );
92+ case SqlTypeName .TIME ->
93+ createUDTWithAttributes (factory , in , OpenSearchTypeFactory .ExprUDT .EXPR_TIME );
94+ case SqlTypeName .TIMESTAMP ->
95+ createUDTWithAttributes (factory , in , OpenSearchTypeFactory .ExprUDT .EXPR_TIMESTAMP );
96+ default -> casted ;
97+ };
98+ }
99+
100+ /**
101+ * Override super implementation to add special handling for user-defined types (UDTs). Otherwise,
102+ * UDTs will be regarded as character types, invalidating string->datetime casts.
103+ */
104+ @ Override
105+ protected boolean needToCast (
106+ SqlValidatorScope scope , SqlNode node , RelDataType toType , SqlTypeMappingRule mappingRule ) {
107+ boolean need = super .needToCast (scope , node , toType , mappingRule );
108+ RelDataType fromType = validator .deriveType (scope , node );
109+ if (OpenSearchTypeFactory .isUserDefinedType (toType ) && SqlTypeUtil .isCharacter (fromType )) {
110+ need = true ;
111+ }
112+ return need ;
113+ }
76114}
0 commit comments