@@ -482,176 +482,6 @@ TEST_F(DataTypeDecimalTest, ser_deser) {
482482 test_func (dt_decimal256_3, *column_decimal256_3, USE_CONST_SERDE );
483483 test_func (dt_decimal256_3, *column_decimal256_3, AGGREGATION_2_1_VERSION );
484484}
485- // Regression for legacy DecimalV2 segments written by Doris < 2.1.0 (before
486- // #26572): ColumnMetaPB.precision/frac are absent and default to 0 when read
487- // back. DataTypeFactory must not pass 0 as the original precision/scale to
488- // DataTypeDecimalV2, otherwise check_type_precision throws
489- // "meet invalid precision: real_precision=0".
490- TEST_F (DataTypeDecimalTest, create_decimalv2_from_legacy_tablet_column) {
491- // Case 1: legacy segment — precision/frac missing (default 0)
492- {
493- TabletColumn col;
494- col.set_type (FieldType::OLAP_FIELD_TYPE_DECIMAL );
495- // intentionally do not set precision/frac to mimic old segments
496- DataTypePtr dt;
497- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (col, false ));
498- ASSERT_NE (dt, nullptr );
499- EXPECT_EQ (dt->get_primitive_type (), TYPE_DECIMALV2 );
500- const auto * decv2 = assert_cast<const DataTypeDecimalV2*>(dt.get ());
501- EXPECT_EQ (decv2->get_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
502- EXPECT_EQ (decv2->get_scale (), BeConsts::MAX_DECIMALV2_SCALE );
503- // When original precision/scale are unknown, get_original_* should fall
504- // back to the in-memory (27, 9) representation.
505- EXPECT_EQ (decv2->get_original_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
506- EXPECT_EQ (decv2->get_original_scale (), BeConsts::MAX_DECIMALV2_SCALE );
507- }
508- // Case 2: new segment — precision/frac are persisted (e.g. decimal(26,6))
509- {
510- TabletColumn col;
511- col.set_type (FieldType::OLAP_FIELD_TYPE_DECIMAL );
512- col.set_precision (26 );
513- col.set_frac (6 );
514- DataTypePtr dt;
515- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (col, false ));
516- ASSERT_NE (dt, nullptr );
517- EXPECT_EQ (dt->get_primitive_type (), TYPE_DECIMALV2 );
518- const auto * decv2 = assert_cast<const DataTypeDecimalV2*>(dt.get ());
519- EXPECT_EQ (decv2->get_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
520- EXPECT_EQ (decv2->get_scale (), BeConsts::MAX_DECIMALV2_SCALE );
521- EXPECT_EQ (decv2->get_original_precision (), 26U );
522- EXPECT_EQ (decv2->get_original_scale (), 6U );
523- }
524- // Case 3: same regression via the segment-read path that consumes
525- // ColumnMetaPB directly (this is the exact code path that broke after
526- // PR #35222 when reading old DecimalV2 segments).
527- {
528- segment_v2::ColumnMetaPB meta;
529- meta.set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_DECIMAL ));
530- // precision/frac intentionally unset -> default 0
531- DataTypePtr dt;
532- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (meta));
533- ASSERT_NE (dt, nullptr );
534- EXPECT_EQ (dt->get_primitive_type (), TYPE_DECIMALV2 );
535- const auto * decv2 = assert_cast<const DataTypeDecimalV2*>(dt.get ());
536- EXPECT_EQ (decv2->get_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
537- EXPECT_EQ (decv2->get_scale (), BeConsts::MAX_DECIMALV2_SCALE );
538- EXPECT_EQ (decv2->get_original_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
539- EXPECT_EQ (decv2->get_original_scale (), BeConsts::MAX_DECIMALV2_SCALE );
540- }
541- }
542-
543- // Regression for complex types wrapping legacy DecimalV2 children whose
544- // segment ColumnMetaPB.precision/frac default to 0. The fix in
545- // DataTypeFactory::create_data_type(segment_v2::ColumnMetaPB&) must
546- // propagate through Array / Map / Struct / AggState recursively.
547- TEST_F (DataTypeDecimalTest, create_complex_types_with_legacy_decimalv2) {
548- auto make_legacy_decv2_meta = []() {
549- segment_v2::ColumnMetaPB child;
550- child.set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_DECIMAL ));
551- // precision/frac intentionally unset -> default 0
552- return child;
553- };
554- auto unwrap_nullable = [](const DataTypePtr& dt) -> DataTypePtr {
555- if (dt && dt->is_nullable ()) {
556- return assert_cast<const DataTypeNullable*>(dt.get ())->get_nested_type ();
557- }
558- return dt;
559- };
560-
561- // Array<DecimalV2>
562- {
563- segment_v2::ColumnMetaPB meta;
564- meta.set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_ARRAY ));
565- *meta.add_children_columns () = make_legacy_decv2_meta ();
566- DataTypePtr dt;
567- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (meta));
568- ASSERT_NE (dt, nullptr );
569- EXPECT_EQ (dt->get_primitive_type (), TYPE_ARRAY );
570- const auto * arr = assert_cast<const DataTypeArray*>(dt.get ());
571- auto elem = unwrap_nullable (arr->get_nested_type ());
572- EXPECT_EQ (elem->get_primitive_type (), TYPE_DECIMALV2 );
573- const auto * decv2 = assert_cast<const DataTypeDecimalV2*>(elem.get ());
574- EXPECT_EQ (decv2->get_original_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
575- EXPECT_EQ (decv2->get_original_scale (), BeConsts::MAX_DECIMALV2_SCALE );
576- }
577-
578- // Map<Int, DecimalV2>
579- {
580- segment_v2::ColumnMetaPB meta;
581- meta.set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_MAP ));
582- auto * k = meta.add_children_columns ();
583- k->set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_INT ));
584- *meta.add_children_columns () = make_legacy_decv2_meta ();
585- DataTypePtr dt;
586- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (meta));
587- ASSERT_NE (dt, nullptr );
588- EXPECT_EQ (dt->get_primitive_type (), TYPE_MAP );
589- const auto * m = assert_cast<const DataTypeMap*>(dt.get ());
590- EXPECT_EQ (unwrap_nullable (m->get_key_type ())->get_primitive_type (), TYPE_INT );
591- auto v = unwrap_nullable (m->get_value_type ());
592- EXPECT_EQ (v->get_primitive_type (), TYPE_DECIMALV2 );
593- const auto * decv2 = assert_cast<const DataTypeDecimalV2*>(v.get ());
594- EXPECT_EQ (decv2->get_original_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
595- }
596-
597- // Struct<DecimalV2, Int>
598- {
599- segment_v2::ColumnMetaPB meta;
600- meta.set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_STRUCT ));
601- *meta.add_children_columns () = make_legacy_decv2_meta ();
602- auto * second = meta.add_children_columns ();
603- second->set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_INT ));
604- DataTypePtr dt;
605- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (meta));
606- ASSERT_NE (dt, nullptr );
607- EXPECT_EQ (dt->get_primitive_type (), TYPE_STRUCT );
608- const auto * s = assert_cast<const DataTypeStruct*>(dt.get ());
609- ASSERT_EQ (s->get_elements ().size (), 2u );
610- EXPECT_EQ (unwrap_nullable (s->get_element (0 ))->get_primitive_type (), TYPE_DECIMALV2 );
611- EXPECT_EQ (unwrap_nullable (s->get_element (1 ))->get_primitive_type (), TYPE_INT );
612- }
613-
614- // Nested: Array<Map<Int, DecimalV2>>
615- {
616- segment_v2::ColumnMetaPB meta;
617- meta.set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_ARRAY ));
618- auto * map_child = meta.add_children_columns ();
619- map_child->set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_MAP ));
620- auto * k = map_child->add_children_columns ();
621- k->set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_INT ));
622- *map_child->add_children_columns () = make_legacy_decv2_meta ();
623- DataTypePtr dt;
624- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (meta));
625- ASSERT_NE (dt, nullptr );
626- EXPECT_EQ (dt->get_primitive_type (), TYPE_ARRAY );
627- auto inner =
628- unwrap_nullable (assert_cast<const DataTypeArray*>(dt.get ())->get_nested_type ());
629- EXPECT_EQ (inner->get_primitive_type (), TYPE_MAP );
630- auto v = unwrap_nullable (assert_cast<const DataTypeMap*>(inner.get ())->get_value_type ());
631- EXPECT_EQ (v->get_primitive_type (), TYPE_DECIMALV2 );
632- }
633-
634- // AggState (count) with legacy DecimalV2 sub-type
635- {
636- segment_v2::ColumnMetaPB meta;
637- meta.set_type (static_cast <int >(FieldType::OLAP_FIELD_TYPE_AGG_STATE ));
638- meta.set_function_name (" count" );
639- meta.set_result_is_nullable (false );
640- meta.set_be_exec_version (BeExecVersionManager::get_newest_version ());
641- *meta.add_children_columns () = make_legacy_decv2_meta ();
642- DataTypePtr dt;
643- EXPECT_NO_THROW (dt = DataTypeFactory::instance ().create_data_type (meta));
644- ASSERT_NE (dt, nullptr );
645- EXPECT_EQ (dt->get_primitive_type (), TYPE_AGG_STATE );
646- const auto * agg = assert_cast<const DataTypeAggState*>(dt.get ());
647- ASSERT_EQ (agg->get_sub_types ().size (), 1u );
648- auto sub = unwrap_nullable (agg->get_sub_types ()[0 ]);
649- EXPECT_EQ (sub->get_primitive_type (), TYPE_DECIMALV2 );
650- const auto * decv2 = assert_cast<const DataTypeDecimalV2*>(sub.get ());
651- EXPECT_EQ (decv2->get_original_precision (), BeConsts::MAX_DECIMALV2_PRECISION );
652- EXPECT_EQ (decv2->get_original_scale (), BeConsts::MAX_DECIMALV2_SCALE );
653- }
654- }
655485
656486TEST_F (DataTypeDecimalTest, to_pb_column_meta) {
657487 auto test_func = [](auto dt, PGenericType_TypeId expected_type) {
0 commit comments