Ramin Gharib created FLINK-40840:
------------------------------------
Summary: INSERT with a column list fails when an omitted column is
of type BITMAP, RAW or STRUCTURED
Key: FLINK-40840
URL: https://issues.apache.org/jira/browse/FLINK-40840
Project: Flink
Issue Type: Bug
Components: Table SQL / Planner
Affects Versions: 2.3.0, 2.2.0, 2.1.0
Reporter: Ramin Gharib
Assignee: Ramin Gharib
An INSERT with an explicit column list fails during validation when an omitted
column has a type that only Flink knows.
{code:sql}
CREATE TABLE src (k INT) WITH ('connector' = 'datagen', 'number-of-rows' = '1');
CREATE TABLE bm_snk (k INT, b BITMAP) WITH ('connector' = 'blackhole');
CREATE TABLE st_snk (k INT, s STRUCTURED<'com.example.User', name STRING>) WITH
('connector' = 'blackhole');
INSERT INTO bm_snk (k) SELECT k FROM src;
INSERT INTO st_snk (k) SELECT k FROM src;
{code}
|| Omitted column type || Error ||
| \{{BITMAP}} | \{{Unsupported type when convertTypeToSpec: OTHER}} |
| \{{ARRAY<BITMAP>}} | \{{Unsupported type when convertTypeToSpec: OTHER}} |
| \{{RAW}}, for example \{{DataTypes.RAW(Integer.class,
IntSerializer.INSTANCE)}} | \{{Unsupported type when convertTypeToSpec: OTHER}}
|
| \{{STRUCTURED<'com.example.User', name STRING>}} | \{{Unsupported type when
convertTypeToSpec: STRUCTURED}} |
Writing the cast explicitly works, for example \{{CAST(NULL AS BITMAP)}}.
*Cause*
{\{PreValidateReWriter}} pads every omitted column with \{{CAST(NULL AS <column
type>)}}. \{{FlinkCalciteSqlValidator.maybeCast}} delegates to Calcite, which
builds the cast target with \{{SqlTypeUtil.convertTypeToSpec}}. That method
only knows Calcite types. \{{BitmapRelDataType}} and \{{RawRelDataType}} report
\{{SqlTypeName.OTHER}}, and \{{StructuredRelDataType}} reports
\{{SqlTypeName.STRUCTURED}}, so no branch matches.
FLINK-40839 fixes the same failure for VARIANT by backporting a Calcite fix.
That approach does not fit here. These types are not native to Calcite, so a
branch in Flink's copy of \{{SqlTypeUtil}} would never be removed by a Calcite
upgrade.
*Proposed fix*
Build the cast target on the Flink side, in
\{{FlinkCalciteSqlValidator.maybeCast}}, and leave the copied Calcite class
unchanged. There are two options:
# Map each Flink-only type to the type name spec the parser already has:
\{{SqlBitmapTypeNameSpec}}, \{{SqlRawTypeNameSpec}} and
\{{SqlStructuredTypeNameSpec}}. FLINK-38682 already does this for RAW in
\{{TypeInferenceOperandChecker.castTo}}, and both places could share the code.
This only covers top-level columns. \{{ARRAY<BITMAP>}} would still fail,
because \{{convertTypeToSpec}} recurses into its own code for nested types.
# Add one planner-side \{{SqlTypeNameSpec}} that wraps a Flink
\{{LogicalType}}. It derives its type through \{{FlinkTypeFactory}} and
unparses as Flink SQL, for example \{{ARRAY<BITMAP>}}. \{{maybeCast}} uses it
when the target type contains a Flink-only type. This covers nested types and
any future Flink-only type. The unparsed SQL must parse back to the same type,
because some places store SQL text, such as materialized table definition
queries.
Option 2 is preferred, because it is the only one that fixes nested types
without changing the copied Calcite class.
The workaround is to list every column and write the cast explicitly, for
example \{{CAST(NULL AS BITMAP)}}.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)