github-actions[bot] commented on code in PR #65610:
URL: https://github.com/apache/doris/pull/65610#discussion_r3585496753


##########
be/test/format/table/iceberg/iceberg_reader_create_column_ids_test.cpp:
##########
@@ -1166,4 +1167,75 @@ TEST_F(IcebergReaderCreateColumnIdsTest, 
test_create_column_ids_6) {
     }
 }
 
+// Regression: a synthesized/metadata slot (e.g. the TopN global row-id 
column) is projected but
+// is never serialized into the Iceberg schema tree, so it is absent from the 
schema-mapping
+// StructNode. Before the get_children().contains() guard, 
_create_column_ids() called
+// StructNode::children_column_exists() on that unregistered name, which hits
+// DCHECK(children.contains(name)) and aborts in debug/ASAN builds (and throws 
std::out_of_range
+// from .at() in release builds). These tests core without the guard and pass 
with it: the
+// synthesized slot is skipped and only the real column contributes a column 
id.
+TEST_F(IcebergReaderCreateColumnIdsTest, 
parquet_synthesized_slot_is_skipped_not_crash) {
+    // Physical Parquet schema: a single real column "id" (Iceberg field id 1).
+    FieldDescriptor field_desc;
+    FieldSchema id_field;
+    id_field.name = "id";
+    id_field.data_type =
+            
DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_BIGINT, true);
+    id_field.field_id = 1;
+    field_desc._fields.emplace_back(id_field);
+
+    // Schema-mapping node registers only the real table column "id" (mapped 
to file column "id").
+    // The synthesized global row-id column is intentionally NOT registered as 
a child.
+    auto struct_node = std::make_shared<TableSchemaChangeHelper::StructNode>();
+    struct_node->add_children("id", "id", 
TableSchemaChangeHelper::ConstNode::get_instance());
+    std::shared_ptr<TableSchemaChangeHelper::Node> table_info_node = 
struct_node;
+
+    // Projected tuple: the real column plus a synthesized global-row-id slot 
absent from the node.
+    SlotDescriptor id_slot;
+    id_slot._type = 
DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_BIGINT, true);
+    id_slot._col_name = "id";
+
+    SlotDescriptor row_id_slot;
+    row_id_slot._type =
+            
DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_BIGINT, true);
+    row_id_slot._col_name = BeConsts::GLOBAL_ROWID_COL;
+
+    TupleDescriptor tuple_desc;
+    tuple_desc.add_slot(&id_slot);
+    tuple_desc.add_slot(&row_id_slot);
+
+    const ColumnIdResult result =
+            IcebergParquetReader::_create_column_ids(&field_desc, &tuple_desc, 
table_info_node);
+    EXPECT_EQ(result.column_ids, (std::set<uint64_t> {1}));
+    EXPECT_TRUE(result.filter_column_ids.empty());
+}
+
+TEST_F(IcebergReaderCreateColumnIdsTest, 
orc_synthesized_slot_is_skipped_not_crash) {
+    // Physical ORC schema: a single real column "id" carrying Iceberg field 
id 1.
+    std::unique_ptr<orc::Type> 
orc_type(orc::Type::buildTypeFromString("struct<id:bigint>"));
+    
orc_type->getSubtype(0)->setAttribute(IcebergOrcReader::ICEBERG_ORC_ATTRIBUTE, 
"1");
+
+    auto struct_node = std::make_shared<TableSchemaChangeHelper::StructNode>();
+    struct_node->add_children("id", "id", 
TableSchemaChangeHelper::ConstNode::get_instance());
+    std::shared_ptr<TableSchemaChangeHelper::Node> table_info_node = 
struct_node;
+
+    SlotDescriptor id_slot;
+    id_slot._type = 
DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_BIGINT, true);
+    id_slot._col_name = "id";
+
+    SlotDescriptor row_id_slot;
+    row_id_slot._type =
+            
DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_BIGINT, true);
+    row_id_slot._col_name = BeConsts::GLOBAL_ROWID_COL;
+
+    TupleDescriptor tuple_desc;
+    tuple_desc.add_slot(&id_slot);
+    tuple_desc.add_slot(&row_id_slot);
+
+    const ColumnIdResult result =
+            IcebergOrcReader::_create_column_ids(orc_type.get(), &tuple_desc, 
table_info_node);
+    EXPECT_EQ(result.column_ids, (std::set<uint64_t> {1}));
+    EXPECT_TRUE(result.filter_column_ids.empty());
+}
+

Review Comment:
   This touched C++ file is missing its final newline (`tail -c 1` returns 
`0x73`, and the diff shows `\ No newline at end of file`). Please add the 
trailing newline so the BE style/format checks do not fail on the new test.



##########
be/test/format/table/iceberg/iceberg_reader_create_column_ids_test.cpp:
##########
@@ -1166,4 +1167,75 @@ TEST_F(IcebergReaderCreateColumnIdsTest, 
test_create_column_ids_6) {
     }
 }
 
+// Regression: a synthesized/metadata slot (e.g. the TopN global row-id 
column) is projected but
+// is never serialized into the Iceberg schema tree, so it is absent from the 
schema-mapping
+// StructNode. Before the get_children().contains() guard, 
_create_column_ids() called
+// StructNode::children_column_exists() on that unregistered name, which hits
+// DCHECK(children.contains(name)) and aborts in debug/ASAN builds (and throws 
std::out_of_range
+// from .at() in release builds). These tests core without the guard and pass 
with it: the
+// synthesized slot is skipped and only the real column contributes a column 
id.
+TEST_F(IcebergReaderCreateColumnIdsTest, 
parquet_synthesized_slot_is_skipped_not_crash) {
+    // Physical Parquet schema: a single real column "id" (Iceberg field id 1).
+    FieldDescriptor field_desc;
+    FieldSchema id_field;
+    id_field.name = "id";
+    id_field.data_type =
+            
DataTypeFactory::instance().create_data_type(PrimitiveType::TYPE_BIGINT, true);
+    id_field.field_id = 1;
+    field_desc._fields.emplace_back(id_field);
+
+    // Schema-mapping node registers only the real table column "id" (mapped 
to file column "id").
+    // The synthesized global row-id column is intentionally NOT registered as 
a child.
+    auto struct_node = std::make_shared<TableSchemaChangeHelper::StructNode>();

Review Comment:
   These new BE unit tests only cover the unregistered synthesized-slot crash 
with an identity schema mapping (`id` -> `id`). The production branch being 
protected also relies on `children_file_column_name()` to keep column-id 
pruning aligned with BY_NAME/name-mapping decisions, and the existing review 
threads already caught bugs in that non-identity partial-id boundary. Please 
add Parquet and ORC cases where the logical slot maps through `StructNode` to a 
differently named physical field, ideally with an unrelated/stale field id 
present, so the test would fail if `_create_column_ids()` regressed back to 
id-only or identity-name binding.



##########
fe/fe-core/src/main/java/org/apache/doris/qe/SessionVariable.java:
##########
@@ -3991,6 +3991,9 @@ private void setFuzzyForCatalog(Random random) {
         if (!Config.fuzzy_test_type.equals("external")) {
             return;
         }
+        // file scanner

Review Comment:
   This new randomization currently does not run in the checked-in external 
fuzzy pipeline. `setFuzzyForCatalog()` returns unless `Config.fuzzy_test_type` 
is exactly `external`, but `regression-test/pipeline/external/conf/fe.conf` 
enables fuzzy sessions with `fuzzy_test_type=p1`. Marking the variable 
`fuzzy=true` only makes it appear in `printFuzzyVariables()`; it does not 
randomize it. Since `enableFileScannerV2` defaults to `true`, those external 
fuzzy runs still keep the FileScannerV2 path on and never exercise the intended 
random legacy-scanner path from this change. Please either align this gate with 
the actual external pipeline mode or update the pipeline/config so this branch 
is reachable, and add a small check so the coverage cannot silently disappear 
again.



-- 
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]

Reply via email to