twalthr commented on code in PR #27603:
URL: https://github.com/apache/flink/pull/27603#discussion_r2822405260
##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/types/logical/utils/LogicalTypeCasts.java:
##########
@@ -110,124 +114,216 @@ public final class LogicalTypeCasts {
private static final Map<LogicalTypeRoot, Set<LogicalTypeRoot>>
explicitCastingRules;
+ private static final Map<LogicalTypeRoot, List<InjectiveRule>>
injectiveRules;
+
+ // Types with deterministic, unique string representations (for injective
casts to STRING)
+ private static final LogicalTypeRoot[] STRING_INJECTIVE_SOURCES = {
+ TINYINT,
+ SMALLINT,
+ INTEGER,
+ BIGINT,
+ FLOAT,
+ DOUBLE,
+ BOOLEAN,
+ DATE,
+ TIME_WITHOUT_TIME_ZONE,
+ TIMESTAMP_WITHOUT_TIME_ZONE,
+ TIMESTAMP_WITH_LOCAL_TIME_ZONE
+ };
+
+ // ----- Injective cast conditions -----
+
+ /** Unconditionally injective (no additional type-parameter checks
needed). */
+ private static final BiPredicate<LogicalType, LogicalType> ALWAYS = (s, t)
-> true;
+
+ /** Injective when the target length can hold any value of the source
length. */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_LENGTH_FITS =
+ (source, target) -> getLength(target) >= getLength(source);
+
+ /** Injective when the target length can hold the source type's max string
representation. */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_MAX_CHAR_LENGTH_FITS =
+ (source, target) -> getLength(target) >=
maxStringRepresentationLength(source);
+
+ /** Injective when source and target share identical precision. */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_PRECISION_MATCHES =
+ (source, target) -> getPrecision(source) == getPrecision(target);
+
+ /** Injective when source and target share identical precision and scale
(DECIMAL). */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_PRECISION_AND_SCALE_MATCH =
+ (source, target) ->
+ getPrecision(source) == getPrecision(target)
+ && getScale(source) == getScale(target);
+
static {
implicitCastingRules = new HashMap<>();
explicitCastingRules = new HashMap<>();
+ injectiveRules = new HashMap<>();
- // identity casts
-
+ // Identity casts: all types can be implicitly cast to themselves.
+ // Injective identity for parameterized types is declared per-type
with conditions.
for (LogicalTypeRoot typeRoot : allTypes()) {
castTo(typeRoot).implicitFrom(typeRoot).build();
}
- // cast specification
+ //
-----------------------------------------------------------------------------------------
+ // Character string types
+ //
-----------------------------------------------------------------------------------------
castTo(CHAR)
.implicitFrom(CHAR)
.explicitFromFamily(PREDEFINED, CONSTRUCTED)
.explicitFrom(RAW, NULL, STRUCTURED_TYPE)
+ .injectiveFrom(WHEN_LENGTH_FITS, CHAR)
+ .injectiveFrom(WHEN_MAX_CHAR_LENGTH_FITS,
STRING_INJECTIVE_SOURCES)
.build();
castTo(VARCHAR)
.implicitFromFamily(CHARACTER_STRING)
.explicitFromFamily(PREDEFINED, CONSTRUCTED)
.explicitFrom(RAW, NULL, STRUCTURED_TYPE)
+ .injectiveFrom(WHEN_LENGTH_FITS, CHAR, VARCHAR)
+ .injectiveFrom(WHEN_MAX_CHAR_LENGTH_FITS,
STRING_INJECTIVE_SOURCES)
.build();
- castTo(BOOLEAN)
- .implicitFrom(BOOLEAN)
- .explicitFromFamily(CHARACTER_STRING, INTEGER_NUMERIC)
- .build();
+ //
-----------------------------------------------------------------------------------------
+ // Binary string types
+ //
-----------------------------------------------------------------------------------------
castTo(BINARY)
.implicitFrom(BINARY)
.explicitFromFamily(CHARACTER_STRING)
- .explicitFrom(VARBINARY)
- .explicitFrom(RAW)
+ .explicitFrom(VARBINARY, RAW)
+ .injectiveFrom(WHEN_LENGTH_FITS, BINARY)
.build();
castTo(VARBINARY)
.implicitFromFamily(BINARY_STRING)
.explicitFromFamily(CHARACTER_STRING)
- .explicitFrom(BINARY)
- .explicitFrom(RAW)
+ .explicitFrom(BINARY, RAW)
+ .injectiveFrom(WHEN_LENGTH_FITS, BINARY, VARBINARY)
.build();
- castTo(DECIMAL)
- .implicitFromFamily(NUMERIC)
- .explicitFromFamily(CHARACTER_STRING, INTERVAL)
- .explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
- .build();
+ //
-----------------------------------------------------------------------------------------
+ // Exact numeric types
+ //
-----------------------------------------------------------------------------------------
castTo(TINYINT)
.implicitFrom(TINYINT)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT)
.build();
castTo(SMALLINT)
.implicitFrom(TINYINT, SMALLINT)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT, SMALLINT)
.build();
castTo(INTEGER)
.implicitFrom(TINYINT, SMALLINT, INTEGER)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT, SMALLINT, INTEGER)
.build();
castTo(BIGINT)
.implicitFrom(TINYINT, SMALLINT, INTEGER, BIGINT)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT, SMALLINT, INTEGER, BIGINT)
.build();
+ castTo(DECIMAL)
+ .implicitFromFamily(NUMERIC)
+ .explicitFromFamily(CHARACTER_STRING, INTERVAL)
+ .explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(WHEN_PRECISION_AND_SCALE_MATCH, DECIMAL)
+ .build();
+
+ //
-----------------------------------------------------------------------------------------
+ // Approximate numeric types
+ //
-----------------------------------------------------------------------------------------
+
castTo(FLOAT)
.implicitFrom(TINYINT, SMALLINT, INTEGER, BIGINT, FLOAT,
DECIMAL)
.explicitFromFamily(NUMERIC, CHARACTER_STRING)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, FLOAT)
.build();
castTo(DOUBLE)
.implicitFromFamily(NUMERIC)
.explicitFromFamily(CHARACTER_STRING)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, DOUBLE)
+ .build();
+
+ //
-----------------------------------------------------------------------------------------
+ // Boolean type
+ //
-----------------------------------------------------------------------------------------
+
+ castTo(BOOLEAN)
+ .implicitFrom(BOOLEAN)
+ .explicitFromFamily(CHARACTER_STRING, INTEGER_NUMERIC)
+ .injectiveFrom(ALWAYS, BOOLEAN)
.build();
+ //
-----------------------------------------------------------------------------------------
+ // Date and time types
+ //
-----------------------------------------------------------------------------------------
+
castTo(DATE)
.implicitFrom(DATE, TIMESTAMP_WITHOUT_TIME_ZONE)
.explicitFromFamily(TIMESTAMP, CHARACTER_STRING)
+ .injectiveFrom(ALWAYS, DATE)
.build();
castTo(TIME_WITHOUT_TIME_ZONE)
.implicitFrom(TIME_WITHOUT_TIME_ZONE,
TIMESTAMP_WITHOUT_TIME_ZONE)
.explicitFromFamily(TIME, TIMESTAMP, CHARACTER_STRING)
+ .injectiveFrom(WHEN_PRECISION_MATCHES, TIME_WITHOUT_TIME_ZONE)
.build();
castTo(TIMESTAMP_WITHOUT_TIME_ZONE)
.implicitFrom(TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.explicitFromFamily(DATETIME, CHARACTER_STRING, NUMERIC)
+ .injectiveFrom(
+ WHEN_PRECISION_MATCHES,
+ TIMESTAMP_WITHOUT_TIME_ZONE,
+ TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.build();
castTo(TIMESTAMP_WITH_TIME_ZONE)
.implicitFrom(TIMESTAMP_WITH_TIME_ZONE)
.explicitFromFamily(DATETIME, CHARACTER_STRING)
+ .injectiveFrom(WHEN_PRECISION_MATCHES,
TIMESTAMP_WITH_TIME_ZONE)
.build();
castTo(TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.implicitFrom(TIMESTAMP_WITH_LOCAL_TIME_ZONE,
TIMESTAMP_WITHOUT_TIME_ZONE)
.explicitFromFamily(DATETIME, CHARACTER_STRING, NUMERIC)
+ .injectiveFrom(
+ WHEN_PRECISION_MATCHES,
+ TIMESTAMP_WITH_LOCAL_TIME_ZONE,
+ TIMESTAMP_WITHOUT_TIME_ZONE)
.build();
+ //
-----------------------------------------------------------------------------------------
+ // Interval types
+ //
-----------------------------------------------------------------------------------------
+
castTo(INTERVAL_YEAR_MONTH)
.implicitFrom(INTERVAL_YEAR_MONTH)
.explicitFromFamily(EXACT_NUMERIC, CHARACTER_STRING)
+ .injectiveFrom(ALWAYS, INTERVAL_YEAR_MONTH)
.build();
castTo(INTERVAL_DAY_TIME)
.implicitFrom(INTERVAL_DAY_TIME)
.explicitFromFamily(EXACT_NUMERIC, CHARACTER_STRING)
+ .injectiveFrom(ALWAYS, INTERVAL_DAY_TIME)
Review Comment:
there are also precisions here, better don't support in first version
##########
flink-table/flink-table-common/src/main/java/org/apache/flink/table/types/logical/utils/LogicalTypeCasts.java:
##########
@@ -110,124 +114,216 @@ public final class LogicalTypeCasts {
private static final Map<LogicalTypeRoot, Set<LogicalTypeRoot>>
explicitCastingRules;
+ private static final Map<LogicalTypeRoot, List<InjectiveRule>>
injectiveRules;
+
+ // Types with deterministic, unique string representations (for injective
casts to STRING)
+ private static final LogicalTypeRoot[] STRING_INJECTIVE_SOURCES = {
+ TINYINT,
+ SMALLINT,
+ INTEGER,
+ BIGINT,
+ FLOAT,
+ DOUBLE,
+ BOOLEAN,
+ DATE,
+ TIME_WITHOUT_TIME_ZONE,
+ TIMESTAMP_WITHOUT_TIME_ZONE,
+ TIMESTAMP_WITH_LOCAL_TIME_ZONE
+ };
+
+ // ----- Injective cast conditions -----
+
+ /** Unconditionally injective (no additional type-parameter checks
needed). */
+ private static final BiPredicate<LogicalType, LogicalType> ALWAYS = (s, t)
-> true;
+
+ /** Injective when the target length can hold any value of the source
length. */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_LENGTH_FITS =
+ (source, target) -> getLength(target) >= getLength(source);
+
+ /** Injective when the target length can hold the source type's max string
representation. */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_MAX_CHAR_LENGTH_FITS =
+ (source, target) -> getLength(target) >=
maxStringRepresentationLength(source);
+
+ /** Injective when source and target share identical precision. */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_PRECISION_MATCHES =
+ (source, target) -> getPrecision(source) == getPrecision(target);
+
+ /** Injective when source and target share identical precision and scale
(DECIMAL). */
+ private static final BiPredicate<LogicalType, LogicalType>
WHEN_PRECISION_AND_SCALE_MATCH =
+ (source, target) ->
+ getPrecision(source) == getPrecision(target)
+ && getScale(source) == getScale(target);
+
static {
implicitCastingRules = new HashMap<>();
explicitCastingRules = new HashMap<>();
+ injectiveRules = new HashMap<>();
- // identity casts
-
+ // Identity casts: all types can be implicitly cast to themselves.
+ // Injective identity for parameterized types is declared per-type
with conditions.
for (LogicalTypeRoot typeRoot : allTypes()) {
castTo(typeRoot).implicitFrom(typeRoot).build();
}
- // cast specification
+ //
-----------------------------------------------------------------------------------------
+ // Character string types
+ //
-----------------------------------------------------------------------------------------
castTo(CHAR)
.implicitFrom(CHAR)
.explicitFromFamily(PREDEFINED, CONSTRUCTED)
.explicitFrom(RAW, NULL, STRUCTURED_TYPE)
+ .injectiveFrom(WHEN_LENGTH_FITS, CHAR)
+ .injectiveFrom(WHEN_MAX_CHAR_LENGTH_FITS,
STRING_INJECTIVE_SOURCES)
.build();
castTo(VARCHAR)
.implicitFromFamily(CHARACTER_STRING)
.explicitFromFamily(PREDEFINED, CONSTRUCTED)
.explicitFrom(RAW, NULL, STRUCTURED_TYPE)
+ .injectiveFrom(WHEN_LENGTH_FITS, CHAR, VARCHAR)
+ .injectiveFrom(WHEN_MAX_CHAR_LENGTH_FITS,
STRING_INJECTIVE_SOURCES)
.build();
- castTo(BOOLEAN)
- .implicitFrom(BOOLEAN)
- .explicitFromFamily(CHARACTER_STRING, INTEGER_NUMERIC)
- .build();
+ //
-----------------------------------------------------------------------------------------
+ // Binary string types
+ //
-----------------------------------------------------------------------------------------
castTo(BINARY)
.implicitFrom(BINARY)
.explicitFromFamily(CHARACTER_STRING)
- .explicitFrom(VARBINARY)
- .explicitFrom(RAW)
+ .explicitFrom(VARBINARY, RAW)
+ .injectiveFrom(WHEN_LENGTH_FITS, BINARY)
.build();
castTo(VARBINARY)
.implicitFromFamily(BINARY_STRING)
.explicitFromFamily(CHARACTER_STRING)
- .explicitFrom(BINARY)
- .explicitFrom(RAW)
+ .explicitFrom(BINARY, RAW)
+ .injectiveFrom(WHEN_LENGTH_FITS, BINARY, VARBINARY)
.build();
- castTo(DECIMAL)
- .implicitFromFamily(NUMERIC)
- .explicitFromFamily(CHARACTER_STRING, INTERVAL)
- .explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
- .build();
+ //
-----------------------------------------------------------------------------------------
+ // Exact numeric types
+ //
-----------------------------------------------------------------------------------------
castTo(TINYINT)
.implicitFrom(TINYINT)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT)
.build();
castTo(SMALLINT)
.implicitFrom(TINYINT, SMALLINT)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT, SMALLINT)
.build();
castTo(INTEGER)
.implicitFrom(TINYINT, SMALLINT, INTEGER)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT, SMALLINT, INTEGER)
.build();
castTo(BIGINT)
.implicitFrom(TINYINT, SMALLINT, INTEGER, BIGINT)
.explicitFromFamily(NUMERIC, CHARACTER_STRING, INTERVAL)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, TINYINT, SMALLINT, INTEGER, BIGINT)
.build();
+ castTo(DECIMAL)
+ .implicitFromFamily(NUMERIC)
+ .explicitFromFamily(CHARACTER_STRING, INTERVAL)
+ .explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(WHEN_PRECISION_AND_SCALE_MATCH, DECIMAL)
+ .build();
+
+ //
-----------------------------------------------------------------------------------------
+ // Approximate numeric types
+ //
-----------------------------------------------------------------------------------------
+
castTo(FLOAT)
.implicitFrom(TINYINT, SMALLINT, INTEGER, BIGINT, FLOAT,
DECIMAL)
.explicitFromFamily(NUMERIC, CHARACTER_STRING)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, FLOAT)
.build();
castTo(DOUBLE)
.implicitFromFamily(NUMERIC)
.explicitFromFamily(CHARACTER_STRING)
.explicitFrom(BOOLEAN, TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
+ .injectiveFrom(ALWAYS, DOUBLE)
+ .build();
+
+ //
-----------------------------------------------------------------------------------------
+ // Boolean type
+ //
-----------------------------------------------------------------------------------------
+
+ castTo(BOOLEAN)
+ .implicitFrom(BOOLEAN)
+ .explicitFromFamily(CHARACTER_STRING, INTEGER_NUMERIC)
+ .injectiveFrom(ALWAYS, BOOLEAN)
.build();
+ //
-----------------------------------------------------------------------------------------
+ // Date and time types
+ //
-----------------------------------------------------------------------------------------
+
castTo(DATE)
.implicitFrom(DATE, TIMESTAMP_WITHOUT_TIME_ZONE)
.explicitFromFamily(TIMESTAMP, CHARACTER_STRING)
+ .injectiveFrom(ALWAYS, DATE)
.build();
castTo(TIME_WITHOUT_TIME_ZONE)
.implicitFrom(TIME_WITHOUT_TIME_ZONE,
TIMESTAMP_WITHOUT_TIME_ZONE)
.explicitFromFamily(TIME, TIMESTAMP, CHARACTER_STRING)
+ .injectiveFrom(WHEN_PRECISION_MATCHES, TIME_WITHOUT_TIME_ZONE)
.build();
castTo(TIMESTAMP_WITHOUT_TIME_ZONE)
.implicitFrom(TIMESTAMP_WITHOUT_TIME_ZONE,
TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.explicitFromFamily(DATETIME, CHARACTER_STRING, NUMERIC)
+ .injectiveFrom(
+ WHEN_PRECISION_MATCHES,
+ TIMESTAMP_WITHOUT_TIME_ZONE,
+ TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.build();
castTo(TIMESTAMP_WITH_TIME_ZONE)
.implicitFrom(TIMESTAMP_WITH_TIME_ZONE)
.explicitFromFamily(DATETIME, CHARACTER_STRING)
+ .injectiveFrom(WHEN_PRECISION_MATCHES,
TIMESTAMP_WITH_TIME_ZONE)
.build();
castTo(TIMESTAMP_WITH_LOCAL_TIME_ZONE)
.implicitFrom(TIMESTAMP_WITH_LOCAL_TIME_ZONE,
TIMESTAMP_WITHOUT_TIME_ZONE)
.explicitFromFamily(DATETIME, CHARACTER_STRING, NUMERIC)
+ .injectiveFrom(
+ WHEN_PRECISION_MATCHES,
+ TIMESTAMP_WITH_LOCAL_TIME_ZONE,
+ TIMESTAMP_WITHOUT_TIME_ZONE)
.build();
+ //
-----------------------------------------------------------------------------------------
+ // Interval types
+ //
-----------------------------------------------------------------------------------------
+
castTo(INTERVAL_YEAR_MONTH)
.implicitFrom(INTERVAL_YEAR_MONTH)
.explicitFromFamily(EXACT_NUMERIC, CHARACTER_STRING)
+ .injectiveFrom(ALWAYS, INTERVAL_YEAR_MONTH)
Review Comment:
there are also precisions here, better don't support in first version
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]