This is an automated email from the ASF dual-hosted git repository.
morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new e03594db0ec [fix](fe) Let INSERT write UUID values into connector
Variant columns (#68935)
e03594db0ec is described below
commit e03594db0ec93b51c9987cabbcb221b8baf8d13e
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Tue Oct 13 14:56:22 2026 +0800
[fix](fe) Let INSERT write UUID values into connector Variant columns
(#68935)
### What problem does this PR solve?
Issue Number: None
Related PR: #68919, #67627, #68320
Problem Summary:
**In short.** On master, an INSERT that writes a UUID value into the
VARIANT column of a connector table, such as a Paimon `VARIANT` column,
fails in analysis with `can not cast from origin type UUID to target
type=variant<...>`, and so does an `ARRAY<UUID>` value. This PR lets the
analyzer accept both. It is not a branch-4.x port (branch-4.x has no
UUID type); the gap came up in the review of #68919, which ports
branch-4.x write tests.
**Background.** A connector sink writes a VARIANT column through the
Variant V2 compute carrier: the sink casts the value to
`ConnectorComputeVariantType`, and `CheckCast` admits the source type
only when `VariantType.isSupportedComputeV2CastSource` accepts it. That
predicate (#68320) lists the scalar types the carrier can hold. The UUID
type (#67627) was merged the same day, and the BE carrier takes it
(`is_supported_variant_typed_identity` and the V2 CAST's
`is_supported_scalar_source` both include `TYPE_UUID`), but the FE
predicate does not: `UuidType` extends `PrimitiveType`, not
`CharacterType`, so none of the predicate's type families match it. An
internal VARIANT column accepts the same value through the strict cast
whitelist.
**The problem, and what it cost.**
| Statement on a Paimon table `t (id INT, v VARIANT)` | master | with
this PR |
|---|---|---|
| `INSERT INTO t SELECT 1, CAST('6ba7b810-9dad-11d1-80b4-00c04fd430c8'
AS UUID)` | `can not cast from origin type UUID to target
type=variant<...>`, with `enable_strict_cast` on or off | written; reads
back as `6ba7b810-9dad-11d1-80b4-00c04fd430c8`, `variant_type` `uuid` |
| `INSERT INTO t SELECT 2,
ARRAY(CAST('6ba7b811-9dad-11d1-80b4-00c04fd430c8' AS UUID), NULL)` |
`can not cast from origin type ARRAY<UUID> ...`, either mode | written;
reads back as `["6ba7b811-9dad-11d1-80b4-00c04fd430c8",null]` |
| `INSERT INTO t SELECT 3,
CAST(CAST('6ba7b810-9dad-11d1-80b4-00c04fd430c8' AS UUID) AS VARIANT)` |
written | written (unchanged) |
So a UUID could reach a connector VARIANT column only through an
explicit `CAST(... AS VARIANT)`, which an INSERT into an internal table
does not need.
**How this PR fixes it.** `isSupportedComputeV2CastSource` accepts
`UuidType`; the existing array recursion covers UUID array elements. The
predicate now admits the same scalar types as the BE carrier; TIME,
VARBINARY and 256-bit decimals stay rejected on both sides.
**Results.** On a local cluster with a file-system Paimon catalog, both
failing statements above succeed in both cast modes. The rows read back
the same through Doris and through the Paimon API
(`"6ba7b810-9dad-11d1-80b4-00c04fd430c8"` and
`["6ba7b811-9dad-11d1-80b4-00c04fd430c8",null]`), and match the row
written with the explicit cast.
---
.../org/apache/doris/nereids/types/VariantType.java | 3 ++-
.../rules/expression/check/CheckCastTest.java | 16 ++++++++++++++++
.../paimon/write/test_paimon_write_variant.out | 7 ++++++-
.../paimon/write/test_paimon_write_variant.groovy | 21 +++++++++++++++++++++
4 files changed, 45 insertions(+), 2 deletions(-)
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantType.java
b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantType.java
index 04a2e8fc372..3e4d2103405 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantType.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/types/VariantType.java
@@ -311,7 +311,8 @@ public class VariantType extends PrimitiveType {
|| dataType.isDecimalV2Type()
|| dataType.isDateLikeType()
|| dataType.isStringLikeType()
- || dataType.isIPType();
+ || dataType.isIPType()
+ || dataType.isUuidType();
}
}
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java
index 35abe7a662d..fe500079b91 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/nereids/rules/expression/check/CheckCastTest.java
@@ -50,6 +50,7 @@ import org.apache.doris.nereids.types.TimeStampNsType;
import org.apache.doris.nereids.types.TimeStampTzType;
import org.apache.doris.nereids.types.TimeV2Type;
import org.apache.doris.nereids.types.TinyIntType;
+import org.apache.doris.nereids.types.UuidType;
import org.apache.doris.nereids.types.VarBinaryType;
import org.apache.doris.nereids.types.VarcharType;
import org.apache.doris.nereids.types.VariantType;
@@ -1247,6 +1248,21 @@ public class CheckCastTest {
Assertions.assertFalse(CheckCast.check(IPv6Type.INSTANCE,
QuantileStateType.INSTANCE, false));
}
+ @Test
+ public void testCastFromUuidToVariant() {
+ // A connector Variant column (e.g. a Paimon VARIANT) takes a UUID the
way an internal VARIANT
+ // column does: the V2 compute carrier holds UUID values, also as
array elements.
+ for (boolean strictMode : new boolean[] {true, false}) {
+ Assertions.assertTrue(CheckCast.check(UuidType.INSTANCE,
VariantType.INSTANCE, strictMode));
+ Assertions.assertTrue(CheckCast.check(
+ UuidType.INSTANCE, ConnectorComputeVariantType.INSTANCE,
strictMode));
+ Assertions.assertTrue(CheckCast.check(
+ ArrayType.of(UuidType.INSTANCE),
ConnectorComputeVariantType.INSTANCE, strictMode));
+
Assertions.assertTrue(CheckCast.check(ArrayType.of(UuidType.INSTANCE),
+ ArrayType.of(ConnectorComputeVariantType.INSTANCE),
strictMode));
+ }
+ }
+
@Test
public void testCastFromChar() {
// Strict mode
diff --git
a/regression-test/data/external_table_p0/paimon/write/test_paimon_write_variant.out
b/regression-test/data/external_table_p0/paimon/write/test_paimon_write_variant.out
index c5a8e265379..7b2eab071d9 100644
---
a/regression-test/data/external_table_p0/paimon/write/test_paimon_write_variant.out
+++
b/regression-test/data/external_table_p0/paimon/write/test_paimon_write_variant.out
@@ -3,6 +3,10 @@
20 1 row-one
21 row-two 2
+-- !variant_uuid --
+30 6ba7b810-9dad-11d1-80b4-00c04fd430c8
["6ba7b811-9dad-11d1-80b4-00c04fd430c8",null] uuid uuid
+31 6ba7b812-9dad-11d1-80b4-00c04fd430c8
["6ba7b813-9dad-11d1-80b4-00c04fd430c8"] uuid uuid
+
-- !variant_object --
doris Hangzhou 1 true {} [] δΈζπ 2
@@ -23,4 +27,5 @@ doris Hangzhou 1 true {} [] δΈζπ
2
45056 large-string
-- !variant_row_count --
-15
+17
+
diff --git
a/regression-test/suites/external_table_p0/paimon/write/test_paimon_write_variant.groovy
b/regression-test/suites/external_table_p0/paimon/write/test_paimon_write_variant.groovy
index 6cd559bb467..666f0970445 100644
---
a/regression-test/suites/external_table_p0/paimon/write/test_paimon_write_variant.groovy
+++
b/regression-test/suites/external_table_p0/paimon/write/test_paimon_write_variant.groovy
@@ -103,6 +103,27 @@ suite("test_paimon_write_variant",
"p0,external,paimon,nonConcurrent") {
ORDER BY id
"""
+ // A UUID reaches a Variant column without an explicit cast, as a
scalar and as array
+ // elements, in both cast modes, and reads back as the UUID it holds.
+ sql """
+ INSERT INTO t_variant_basic VALUES
+ (30, CAST('6ba7b810-9dad-11d1-80b4-00c04fd430c8' AS UUID),
+ ARRAY(CAST('6ba7b811-9dad-11d1-80b4-00c04fd430c8' AS
UUID), NULL))
+ """
+ sql """SET enable_strict_cast = true"""
+ sql """
+ INSERT INTO t_variant_basic
+ SELECT 31, CAST('6ba7b812-9dad-11d1-80b4-00c04fd430c8' AS UUID),
+ ARRAY(CAST('6ba7b813-9dad-11d1-80b4-00c04fd430c8' AS UUID))
+ """
+ sql """SET enable_strict_cast = false"""
+ order_qt_variant_uuid """
+ SELECT id, payload, secondary, variant_type(payload),
variant_type(secondary[1])
+ FROM t_variant_basic
+ WHERE id IN (30, 31)
+ ORDER BY id
+ """
+
order_qt_variant_object """
SELECT
CAST(payload['object']['name'] AS STRING),
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]