github-actions[bot] commented on code in PR #68786:
URL: https://github.com/apache/doris/pull/68786#discussion_r4237173029
##########
fe/be-java-extensions/jdbc-scanner/src/main/java/org/apache/doris/jdbc/OracleTypeHandler.java:
##########
@@ -108,6 +111,15 @@ public PreparedStatement initializeStatement(Connection
conn, String sql,
int fetchSize) throws
SQLException {
// Detect driver version when creating the statement (first time we
have access to connection)
detectDriverVersion(conn);
+ // ALTER SESSION alone leaves the driver's TSLTZ zone unset.
Initialize every borrowed connection.
+ try {
+ Connection physical = conn.unwrap(Connection.class);
+ Class<?> oracleConnection =
Class.forName("oracle.jdbc.OracleConnection", true,
Review Comment:
[P1] Preserve Oracle-mode OceanBase scans. OCEANBASE_ORACLE selects this
handler, but those catalogs use com.oceanbase.jdbc.Driver. This unconditional
lookup and unwrap require oracle.jdbc.OracleConnection from the OceanBase
driver classloader before any SQL is prepared, so ordinary scans fail with the
session-time-zone initialization error, even when no TIMESTAMPTZ column is
read. Apply this Oracle-specific call only to Oracle JDBC connections and use
an OceanBase-compatible setup for its mode; cover an Oracle-mode OceanBase scan.
##########
fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergTypeMapping.java:
##########
@@ -124,28 +124,25 @@ private static ConnectorType
fromPrimitive(Type.PrimitiveType primitive,
case STRING:
return ConnectorType.of("STRING");
case UUID:
- return enableMappingVarbinary
- ? ConnectorType.of("VARBINARY", 16, 0) :
ConnectorType.of("STRING");
+ // Preserve logical UUID semantics independently of the binary
mapping option.
+ return ConnectorType.of("UUID");
case BINARY:
// Iceberg BINARY is unbounded. Emit VARBINARY with NO
explicit length so
// ConnectorColumnConverter applies
ScalarType.MAX_VARBINARY_LENGTH — byte-identical to
// legacy IcebergUtils
createVarbinaryType(VarBinaryType.MAX_VARBINARY_LENGTH). A
// concrete length (e.g. 65535) would render a different
DESCRIBE / SHOW CREATE type.
- return enableMappingVarbinary
- ? ConnectorType.of("VARBINARY") :
ConnectorType.of("STRING");
+ // Binary payloads need not be valid UTF-8.
+ return ConnectorType.of("VARBINARY");
case FIXED:
int fixedLen = ((Types.FixedType) primitive).length();
- return enableMappingVarbinary
- ? ConnectorType.of("VARBINARY", fixedLen, 0)
- : ConnectorType.of("CHAR", fixedLen, 0);
+ return ConnectorType.of("VARBINARY", fixedLen, 0);
case DECIMAL:
Types.DecimalType decimal = (Types.DecimalType) primitive;
return ConnectorType.of("DECIMALV3", decimal.precision(),
decimal.scale());
case DATE:
return ConnectorType.of("DATEV2");
case TIMESTAMP:
- if (enableMappingTimestampTz
- && ((Types.TimestampType)
primitive).shouldAdjustToUTC()) {
+ if (((Types.TimestampType) primitive).shouldAdjustToUTC()) {
Review Comment:
[P2] Preserve partitioned Iceberg INSERTs during an FE-first upgrade. A new
FE now sends TIMESTAMPTZ (and native UUID) write slots, but an older BE has no
cases for these types in Iceberg partition transforms or
_get_iceberg_partition_value. An identity-partitioned write reaches Unsupported
type for partition; bucket/time transforms can fail earlier. Gate typed write
plans on BE capability or keep compatible carriers until all BEs are upgraded,
and cover a mixed-version partitioned INSERT. The existing UUID scan issue is a
separate reader path.
##########
be/src/format/transformer/vorc_transformer.cpp:
##########
@@ -424,6 +424,11 @@ std::unique_ptr<orc::Type>
VOrcTransformer::_build_orc_type(
};
switch (nested_field->field_type()->type_id()) {
case iceberg::TypeID::UUID:
+ // Native UUID serde already writes network-order bytes; retain
its ORC annotation.
+ if (primitive_type == TYPE_UUID) {
Review Comment:
[P1] Gate native UUID Iceberg ORC writes until every BE supports them. An
upgraded FE now sends TYPE_UUID for an Iceberg UUID column, including on an
unpartitioned ORC table. An older BE reaches use_iceberg_binary_type in
VOrcTransformer::_build_orc_type, whose DORIS_CHECK accepts only string,
varbinary, or binary, and aborts the BE while opening the writer. This new
TYPE_UUID branch exists only on upgraded BEs. Retain the old write carrier or
gate this plan on BE capability; cover an FE-first unpartitioned ORC INSERT.
##########
fe/fe-connector/fe-connector-maxcompute/src/main/java/org/apache/doris/connector/maxcompute/MCTypeMapping.java:
##########
@@ -87,6 +87,8 @@ public static ConnectorType toConnectorType(TypeInfo
typeInfo) {
case DATETIME:
return ConnectorType.of("DATETIMEV2", 3, 0);
case TIMESTAMP:
+ // MaxCompute TIMESTAMP is an instant; TIMESTAMP_NTZ remains a
wall clock.
+ return ConnectorType.of("TIMESTAMPTZ", 6, 0);
Review Comment:
[P2] Keep MaxCompute TIMESTAMP scans correct on older BEs. This new
TIMESTAMPTZ mapping reaches the old MaxComputeColumnValue.getTimeStampTz, which
converts an Arrow instant into the query timezone; VectorColumn then packs
those local fields as UTC. A 04:00 UTC value in an Asia/Shanghai session is
stored as 12:00 UTC and displayed as 20:00. Gate the new FE slot until scanners
have the added UTC conversion, and cover a non-UTC FE-first scan.
##########
fe/fe-connector/fe-connector-trino/src/main/java/org/apache/doris/connector/trino/TrinoTypeMapping.java:
##########
@@ -74,8 +74,11 @@ public static ConnectorType toConnectorType(Type type) {
return new ConnectorType("CHAR");
} else if (type instanceof VarcharType) {
return new ConnectorType("STRING");
+ } else if (type instanceof io.trino.spi.type.UuidType) {
+ // Preserve the logical type instead of exposing its physical
16-byte storage.
+ return ConnectorType.of("UUID");
Review Comment:
[P2] Keep native Trino UUID scans compatible with older BEs. This mapping
sends a UUID slot to the Trino JNI scanner; on an older BE,
TrinoConnectorColumnValue lacks the new getUuid override, so the interface
default runs UUID.fromString(getString()). Its getString decodes Trino's raw
16-byte UUID block as UTF-8, and an ordinary non-null UUID scan throws. Gate
this newly supported type on scanner capability during rollout; cover an
FE-first scan.
##########
fe/fe-connector/fe-connector-hudi/src/main/java/org/apache/doris/connector/hudi/HudiTypeMapping.java:
##########
@@ -186,9 +190,17 @@ private static ConnectorType mapLongType(LogicalType
logicalType) {
return ConnectorType.of("TIMEV2", 6, 0);
}
if (logicalType instanceof LogicalTypes.TimestampMillis) {
- return ConnectorType.of("DATETIMEV2", 3, 0);
+ // Avro timestamp logical types are instants, not local wall-clock
timestamps.
+ return ConnectorType.of("TIMESTAMPTZ", 3, 0);
}
if (logicalType instanceof LogicalTypes.TimestampMicros) {
+ return ConnectorType.of("TIMESTAMPTZ", 6, 0);
Review Comment:
[P2] Read historical Hudi COW Parquet timestamps with the new instant slot.
Hudi files written with Parquet Java 1.10.1 can have INT64
TIMESTAMP_MILLIS/MICROS in converted_type without the newer LogicalType field.
COW routes those files to the native reader, which still infers DATETIMEV2; V1
has no DATETIMEV2-to-TIMESTAMPTZ conversion for this new FE slot and fails an
ordinary scan with Unsupported type change, even on an upgraded BE. Preserve a
UTC-aware conversion for legacy footers in V1/V2 or keep a compatible slot, and
add a converted-only file fixture.
##########
fe/fe-connector/fe-connector-hudi/src/main/java/org/apache/doris/connector/hudi/HudiTypeMapping.java:
##########
@@ -186,9 +190,17 @@ private static ConnectorType mapLongType(LogicalType
logicalType) {
return ConnectorType.of("TIMEV2", 6, 0);
}
if (logicalType instanceof LogicalTypes.TimestampMillis) {
- return ConnectorType.of("DATETIMEV2", 3, 0);
+ // Avro timestamp logical types are instants, not local wall-clock
timestamps.
+ return ConnectorType.of("TIMESTAMPTZ", 3, 0);
Review Comment:
[P2] Gate Hudi instant slots until older MOR scanners are gone. This new
TIMESTAMPTZ mapping calls HadoopHudiColumnValue.getTimeStampTz on an old BE;
that method casts every value to java.sql.Timestamp. Hudi also supplies
LongWritable and TimestampWritableV2 timestamp carriers, which throw
ClassCastException there on ordinary MOR log scans. The added branches handle
them only on new BEs. Keep the previous carrier during rollout or gate this
mapping; cover both writable carriers in a mixed-version scan.
##########
fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/client/JdbcClickHouseConnectorClient.java:
##########
@@ -199,12 +199,13 @@ private ConnectorType mapClickHouseType(String chType,
JdbcFieldInfo fieldInfo)
// DateTime64
if (chType.startsWith("DateTime64(")) {
+ fieldInfo.setAllowNull(true);
return parseDateTimeType(chType);
}
// DateTime('timezone') — DateTime with timezone parameter, second
precision
if (chType.startsWith("DateTime(")) {
- return ConnectorType.of("DATETIMEV2", 0, -1);
+ return ConnectorType.of("TIMESTAMPTZ", 0, -1);
Review Comment:
[P2] Keep JDBC scans readable while BEs are upgraded. This new FE mapping
sends TIMESTAMPTZ for ClickHouse DateTime, but an older BE JDBC scanner parses
that slot and its ClickHouseTypeHandler has no TIMESTAMPTZ branch, so the first
row throws Unsupported column type. The new PostgreSQL/Trino UUID mappings have
the same old-handler gap. Preserve the previous carriers until all BEs have the
new handlers, or gate these plans on BE capability; cover a new-FE/old-BE scan.
This is separate from the Iceberg file-reader upgrade issue.
##########
fe/fe-connector/fe-connector-iceberg/src/main/java/org/apache/doris/connector/iceberg/IcebergTypeMapping.java:
##########
@@ -124,28 +124,25 @@ private static ConnectorType
fromPrimitive(Type.PrimitiveType primitive,
case STRING:
return ConnectorType.of("STRING");
case UUID:
- return enableMappingVarbinary
- ? ConnectorType.of("VARBINARY", 16, 0) :
ConnectorType.of("STRING");
+ // Preserve logical UUID semantics independently of the binary
mapping option.
+ return ConnectorType.of("UUID");
Review Comment:
[P2] Keep UUID reads working while BEs are upgraded. A new FE now plans
Iceberg UUID as native UUID, but a pre-upgrade BE V1 Parquet reader maps a
UUID-annotated file to STRING or VARBINARY and has no conversion from either
carrier to a UUID slot. Thus an FE-first upgrade breaks ordinary UUID scans
until every BE is replaced. Preserve the old carrier while older BEs can
receive scans, or gate native UUID plans on BE capability; cover this upgrade
direction. The existing thread covers the reverse old-FE/new-BE direction.
##########
fe/fe-connector/fe-connector-jdbc/src/main/java/org/apache/doris/connector/jdbc/JdbcCatalogProperties.java:
##########
@@ -390,11 +390,13 @@ public String getExcludeDatabaseList() {
}
public boolean isEnableMappingVarbinary() {
- return enableMappingVarbinary;
+ // Legacy properties remain parseable, but binary values always retain
their bytes.
+ return true;
}
public boolean isEnableMappingTimestampTz() {
- return enableMappingTimestampTz;
+ // Instant types cannot be downgraded to session-local wall clocks.
+ return true;
Review Comment:
[P2] Preserve JDBC TIMESTAMPTZ writes on older BEs. For a PostgreSQL catalog
that previously disabled zoned mapping, this now forces a TIMESTAMPTZ sink
slot. An old BE writer binds its UTC JNI fields with Timestamp.valueOf, which
interprets them in the BE JVM timezone; with a +08 JVM, 04:00 UTC is sent as
the previous day 20:00 UTC. The new UTC/OffsetDateTime bind is only on upgraded
BEs. Gate this slot on writer capability or retain the compatible carrier until
rollout finishes; cover a non-UTC JVM write.
##########
fe/fe-connector/fe-connector-trino/src/main/java/org/apache/doris/connector/trino/TrinoTypeMapping.java:
##########
@@ -88,7 +91,7 @@ public static ConnectorType toConnectorType(Type type) {
return new ConnectorType("DATETIMEV2", precision, -1);
} else if (type instanceof TimestampWithTimeZoneType) {
int precision = Math.min(((TimestampWithTimeZoneType)
type).getPrecision(), 6);
- return new ConnectorType("DATETIMEV2", precision, -1);
+ return new ConnectorType("TIMESTAMPTZ", precision, -1);
Review Comment:
[P2] Preserve Trino zoned timestamp instants during an FE-first rollout.
This new TIMESTAMPTZ slot reaches an older BE scanner whose getTimeStampTz
returns the source zone's local fields, while the JNI vector treats those
fields as UTC. For example, 12:00 Asia/Shanghai (04:00 UTC) is stored as 12:00
UTC and displays eight hours late. The added UTC conversion exists only on
upgraded BEs. Gate the new slot or keep the old carrier until scanners are
upgraded.
##########
fe/fe-connector/fe-connector-maxcompute/src/main/java/org/apache/doris/connector/maxcompute/MCTypeMapping.java:
##########
@@ -197,6 +199,8 @@ private static TypeInfo toMcScalarType(String name,
ConnectorType type) {
case "DATETIME":
case "DATETIMEV2":
return TypeInfoFactory.DATETIME;
+ case "TIMESTAMPTZ":
Review Comment:
[P2] Keep MaxCompute TIMESTAMP INSERTs working during FE-first upgrades. A
new FE now sends TIMESTAMPTZ for this sink column, but the old
MaxComputeJniWriter handles TIMESTAMP in its DATETIME branch and calls
VectorColumn.getDateTime. That decodes the TIMESTAMPTZ V2 carrier as
DateTimeV1, producing invalid fields and failing before the Arrow write. The
new getTimeStampTz branch exists only on upgraded BEs. Gate this sink slot or
keep its old carrier until writers are upgraded.
##########
fe/fe-connector/fe-connector-hudi/src/main/java/org/apache/doris/connector/hudi/HudiTypeMapping.java:
##########
@@ -59,7 +59,9 @@ public static ConnectorType fromAvroSchema(Schema avroSchema)
{
case DOUBLE:
return ConnectorType.of("DOUBLE");
case STRING:
- return ConnectorType.of("STRING");
+ // Avro stores logical UUIDs as strings, but the connector
must retain UUID semantics.
+ return logicalType instanceof LogicalTypes.Uuid
+ ? ConnectorType.of("UUID") :
ConnectorType.of("STRING");
Review Comment:
[P2] Preserve Hudi COW UUID scans for Parquet Avro string files. Avro
logical uuid is carried as STRING, and the default Parquet Avro writer stores
it as a BINARY STRING leaf; COW base files use Doris's native Parquet reader.
This new UUID slot then asks the V1 reader to convert file STRING to UUID, but
ColumnTypeConverter has no such conversion and returns Unsupported type change
even on an upgraded BE. The new UUID decoder only covers UUID-annotated 16-byte
fixed fields. Keep the compatible string mapping for these files or add
canonical text-to-UUID conversion in native readers, and test a default-written
COW UUID file.
--
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]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]