This is an automated email from the ASF dual-hosted git repository.
Gabriel39 pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.1 by this push:
new ca02e7b3839 [fix](regression) Stabilize external table guardrail cases
(#66509)
ca02e7b3839 is described below
commit ca02e7b38399201ea8fec4716de350fac5031fe4
Author: Gabriel <[email protected]>
AuthorDate: Fri Aug 7 09:35:16 2026 +0800
[fix](regression) Stabilize external table guardrail cases (#66509)
### What problem does this PR solve?
The external-table regression suite had two environment-dependent
failures:
- The Paimon guardrail case attempted to create a table with an empty
field name. Paimon rejects empty and whitespace-only field names while
constructing the table schema, before Doris can scan it.
- The Iceberg Variant case required more than one scanner to report
rows. File scanner tasks pull ranges dynamically, so minimum scanner
concurrency does not guarantee that every scheduled scanner consumes
rows from a small multi-file fixture.
### What is changed?
- Remove the unsupported empty-field Paimon fixture and its expected
results. Delimiter-rich field names remain covered end to end, while
empty-segment framing remains covered by the codec unit test.
- Keep the parallel Iceberg Variant correctness query, but remove the
assertion on nondeterministic per-scanner range assignment.
### Validation
- `test_paimon_jni_reader_guardrails`: passed
- `test_iceberg_variant_read`: passed twice consecutively
### Release note
None. These are test-only corrections.
---
.../paimon/test_paimon_jni_reader_guardrails.out | 6 ------
.../iceberg/test_iceberg_variant_read.groovy | 14 +++-----------
.../paimon/test_paimon_jni_reader_guardrails.groovy | 7 ++-----
3 files changed, 5 insertions(+), 22 deletions(-)
diff --git
a/regression-test/data/external_table_p0/paimon/test_paimon_jni_reader_guardrails.out
b/regression-test/data/external_table_p0/paimon/test_paimon_jni_reader_guardrails.out
index b149c4535db..363efe80f40 100644
---
a/regression-test/data/external_table_p0/paimon/test_paimon_jni_reader_guardrails.out
+++
b/regression-test/data/external_table_p0/paimon/test_paimon_jni_reader_guardrails.out
@@ -7,16 +7,10 @@
1 east,01 nested-one east,01 a:1
2 west,02 nested-two west,02 b:2
--- !scanner_v1_empty_identifier --
-empty-name
-
-- !scanner_v2_quoted_nested --
1 east,01 nested-one east,01 a:1
2 west,02 nested-two west,02 b:2
--- !scanner_v2_empty_identifier --
-empty-name
-
-- !catalog_override_physical_batch --
1
diff --git
a/regression-test/suites/external_table_p0/iceberg/test_iceberg_variant_read.groovy
b/regression-test/suites/external_table_p0/iceberg/test_iceberg_variant_read.groovy
index 72f0c73e23c..fb2fecb5ac2 100644
---
a/regression-test/suites/external_table_p0/iceberg/test_iceberg_variant_read.groovy
+++
b/regression-test/suites/external_table_p0/iceberg/test_iceberg_variant_read.groovy
@@ -482,17 +482,6 @@ public class AppendVariantEqualityDelete {
}
return sum
}
- def profileInfoValues = { String profile, String infoName ->
- Pattern pattern = Pattern.compile(
- Pattern.quote(infoName) + ":\\s*\\[([^\\]]*)\\]")
- Matcher matcher = pattern.matcher(profile)
- if (!matcher.find()) {
- return []
- }
- return matcher.group(1).split(",").collect { String value ->
value.trim() }
- .findAll { String value -> !value.isEmpty() }
- .collect { String value -> Long.parseLong(value.replace(",",
"")) }
- }
def getProfileByToken = { String token, List<String> positiveCounters = []
->
String lastProfile = profileAction.getProfileBySql(token,
positiveCounters)
if (positiveCounters.every { String counter -> counterSum(lastProfile,
counter) > 0 }) {
@@ -649,6 +638,9 @@ public class AppendVariantEqualityDelete {
sql "set parallel_pipeline_task_num=4"
sql "set max_file_scanners_concurrency=8"
sql "set min_file_scanners_concurrency=4"
+ // Scanner tasks pull file ranges dynamically, so minimum concurrency does
not guarantee that
+ // every scheduled scanner consumes rows. Validate parallel correctness
without pinning the
+ // scheduler's nondeterministic range assignment.
order_qt_variant_multi_file_parallel """
SELECT id,
CAST(v['shared'] AS INT),
diff --git
a/regression-test/suites/external_table_p0/paimon/test_paimon_jni_reader_guardrails.groovy
b/regression-test/suites/external_table_p0/paimon/test_paimon_jni_reader_guardrails.groovy
index 0f8780e2e6b..e6167d39db8 100644
---
a/regression-test/suites/external_table_p0/paimon/test_paimon_jni_reader_guardrails.groovy
+++
b/regression-test/suites/external_table_p0/paimon/test_paimon_jni_reader_guardrails.groovy
@@ -72,6 +72,8 @@ suite("test_paimon_jni_reader_guardrails",
"p0,external,paimon") {
"""))
try {
+ // Paimon rejects empty field names, so E2E framing coverage uses
supported
+ // delimiter-rich identifiers; empty-segment decoding remains
unit-tested.
spark_paimon_multi """
create database if not exists paimon.${dbName};
drop table if exists paimon.${dbName}.quoted_reader_options;
@@ -103,9 +105,6 @@ suite("test_paimon_jni_reader_guardrails",
"p0,external,paimon") {
partitioned by (part)
tblproperties ('scan.manifest.parallelism'='0');
insert into paimon.${dbName}.unsafe_physical_manifest values (1,
10);
- drop table if exists paimon.${dbName}.empty_identifier;
- create table paimon.${dbName}.empty_identifier (`` string) using
paimon;
- insert into paimon.${dbName}.empty_identifier values
('empty-name');
"""
sql "switch ${catalogName}"
@@ -129,7 +128,6 @@ suite("test_paimon_jni_reader_guardrails",
"p0,external,paimon") {
from quoted_reader_options
order by id
"""
- qt_scanner_v1_empty_identifier "select * from empty_identifier"
sql "set enable_file_scanner_v2=true"
order_qt_scanner_v2_quoted_nested """
select id, `region,code`, `nested#value`.`hash#name`,
@@ -137,7 +135,6 @@ suite("test_paimon_jni_reader_guardrails",
"p0,external,paimon") {
from quoted_reader_options
order by id
"""
- qt_scanner_v2_empty_identifier "select * from empty_identifier"
// The safe catalog value must override the physical read.batch-size=0
value.
order_qt_catalog_override_physical_batch "select * from
unsafe_physical_batch order by id"
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]