This is an automated email from the ASF dual-hosted git repository.

Mryange 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 af933bf5d75 [fix](be) Report TIME column metadata correctly (#68828)
af933bf5d75 is described below

commit af933bf5d75b421594ba6436f5ba4d665b282c12
Author: Mryange <[email protected]>
AuthorDate: Mon Oct 12 19:41:24 2026 +0800

    [fix](be) Report TIME column metadata correctly (#68828)
    
    [fix](be) Report TIME column metadata correctly
    
    ### What problem does this PR solve?
    
    Issue Number: N/A
    
    Problem Summary: Views containing TIME expressions report `unknown` for
    both `DATA_TYPE` and `COLUMN_TYPE` in `information_schema.columns`,
    preventing clients from identifying the type. Root cause: the BE schema
    scanner does not handle TIMEV2 in its type-name mappings or temporal
    precision rules. Return `time` / `time(n)`, populate
    `DATETIME_PRECISION`, and leave numeric precision fields NULL, following
    DATETIMEV2 behavior.
    
    ### Release note
    
    Fix TIME column type names and precision metadata in
    `information_schema.columns`.
    
    ### Check List (For Author)
    
    - Test
        - [ ] Regression test
        - [x] Unit Test
    - `bash run-be-ut.sh -j48 --run --filter='SchemaColumnsScannerTest.*'`
    passed under ASAN (1 test). Covers missing scale, scales 0/3/6, and
    DATETIME/DECIMAL controls. Tested before moving the unchanged patch to
    the latest master base.
        - [ ] Manual test
        - [ ] No need to test or manual test
    
    - Behavior changed:
        - [ ] No.
        - [x] Yes. Correct TIME metadata; runtime values are unchanged.
    
    - Does this need documentation?
        - [x] No.
        - [ ] Yes.
    
    ### Check List (For Reviewer who merge this PR)
    
    - [ ] Confirm the release note
    - [ ] Confirm test cases
    - [ ] Confirm document
    - [ ] Add branch pick label
---
 .../information_schema/schema_columns_scanner.cpp  | 15 +++-
 .../schema_scanner/schema_columns_scanner_test.cpp | 98 ++++++++++++++++++++++
 2 files changed, 109 insertions(+), 4 deletions(-)

diff --git a/be/src/information_schema/schema_columns_scanner.cpp 
b/be/src/information_schema/schema_columns_scanner.cpp
index 13bb475b411..289782d47de 100644
--- a/be/src/information_schema/schema_columns_scanner.cpp
+++ b/be/src/information_schema/schema_columns_scanner.cpp
@@ -134,6 +134,8 @@ std::string 
SchemaColumnsScanner::_to_mysql_data_type_string(TColumnDesc& desc)
     case TPrimitiveType::DATETIME:
     case TPrimitiveType::DATETIMEV2:
         return "datetime";
+    case TPrimitiveType::TIMEV2:
+        return "time";
     case TPrimitiveType::TIMESTAMP_NS:
         return "timestamp_ns";
     case TPrimitiveType::TIMESTAMPTZ:
@@ -231,6 +233,11 @@ std::string 
SchemaColumnsScanner::_type_to_string(TColumnDesc& desc) {
     }
     case TPrimitiveType::DATEV2:
         return "date";
+    case TPrimitiveType::TIMEV2:
+        if (!desc.__isset.columnScale || desc.columnScale == 0) {
+            return "time";
+        }
+        return fmt::format("time({})", desc.columnScale);
     case TPrimitiveType::DATETIMEV2: {
         fmt::memory_buffer debug_string_buffer;
         if (!desc.__isset.columnScale || desc.columnScale == 0) {
@@ -558,7 +565,7 @@ Status SchemaColumnsScanner::_fill_block_impl(Block* block) 
{
         for (int i = 0; i < columns_num; ++i) {
             int data_type = _desc_result.columns[i].columnDesc.columnType;
             if (_desc_result.columns[i].columnDesc.__isset.columnPrecision &&
-                data_type != TPrimitiveType::DATETIMEV2 &&
+                data_type != TPrimitiveType::TIMEV2 && data_type != 
TPrimitiveType::DATETIMEV2 &&
                 data_type != TPrimitiveType::TIMESTAMP_NS) {
                 srcs[i] = _desc_result.columns[i].columnDesc.columnPrecision;
                 datas[i] = srcs.data() + i;
@@ -574,7 +581,7 @@ Status SchemaColumnsScanner::_fill_block_impl(Block* block) 
{
         for (int i = 0; i < columns_num; ++i) {
             int data_type = _desc_result.columns[i].columnDesc.columnType;
             if (_desc_result.columns[i].columnDesc.__isset.columnScale &&
-                data_type != TPrimitiveType::DATETIMEV2 &&
+                data_type != TPrimitiveType::TIMEV2 && data_type != 
TPrimitiveType::DATETIMEV2 &&
                 data_type != TPrimitiveType::TIMESTAMP_NS) {
                 srcs[i] = _desc_result.columns[i].columnDesc.columnScale;
                 datas[i] = srcs.data() + i;
@@ -590,7 +597,7 @@ Status SchemaColumnsScanner::_fill_block_impl(Block* block) 
{
         for (int i = 0; i < columns_num; ++i) {
             int data_type = _desc_result.columns[i].columnDesc.columnType;
             if (_desc_result.columns[i].columnDesc.__isset.columnScale &&
-                (data_type == TPrimitiveType::DATETIMEV2 ||
+                (data_type == TPrimitiveType::TIMEV2 || data_type == 
TPrimitiveType::DATETIMEV2 ||
                  data_type == TPrimitiveType::TIMESTAMP_NS ||
                  data_type == TPrimitiveType::TIMESTAMPTZ)) {
                 srcs[i] = _desc_result.columns[i].columnDesc.columnScale;
@@ -672,7 +679,7 @@ Status SchemaColumnsScanner::_fill_block_impl(Block* block) 
{
         for (int i = 0; i < columns_num; ++i) {
             int data_type = _desc_result.columns[i].columnDesc.columnType;
             if (_desc_result.columns[i].columnDesc.__isset.columnScale &&
-                data_type != TPrimitiveType::DATETIMEV2 &&
+                data_type != TPrimitiveType::TIMEV2 && data_type != 
TPrimitiveType::DATETIMEV2 &&
                 data_type != TPrimitiveType::TIMESTAMP_NS) {
                 srcs[i] = _desc_result.columns[i].columnDesc.columnScale;
                 datas[i] = srcs.data() + i;
diff --git a/be/test/exec/schema_scanner/schema_columns_scanner_test.cpp 
b/be/test/exec/schema_scanner/schema_columns_scanner_test.cpp
new file mode 100644
index 00000000000..24f81d35c4f
--- /dev/null
+++ b/be/test/exec/schema_scanner/schema_columns_scanner_test.cpp
@@ -0,0 +1,98 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+#include "information_schema/schema_columns_scanner.h"
+
+#include <gen_cpp/Types_types.h>
+#include <gtest/gtest.h>
+
+#include <string>
+#include <vector>
+
+#include "core/block/block.h"
+#include "core/data_type/define_primitive_type.h"
+
+namespace doris {
+
+TEST(SchemaColumnsScannerTest, time_metadata_in_block) {
+    struct TestCase {
+        TPrimitiveType::type type;
+        int scale;
+        const char* data_type;
+        const char* column_type;
+    };
+    const std::vector<TestCase> cases = {
+            {TPrimitiveType::TIMEV2, -1, "time", "time"},
+            {TPrimitiveType::TIMEV2, 0, "time", "time"},
+            {TPrimitiveType::TIMEV2, 3, "time", "time(3)"},
+            {TPrimitiveType::TIMEV2, 6, "time", "time(6)"},
+            {TPrimitiveType::DATETIMEV2, 6, "datetime", "datetime(6)"},
+            {TPrimitiveType::DECIMAL64, 3, "decimal", "decimalv3(18, 3)"},
+    };
+
+    SchemaColumnsScanner scanner;
+    scanner._db_result.__set_dbs({"test_time_metadata"});
+    scanner._db_index = 1;
+    scanner._table_result.__set_tables({"time_view"});
+    scanner._table_index = 1;
+    // Feed the same type/precision/scale fields as FE describe_tables, 
without an RPC.
+    for (size_t i = 0; i < cases.size(); ++i) {
+        TColumnDesc desc;
+        desc.__set_columnName("c" + std::to_string(i));
+        desc.__set_columnType(cases[i].type);
+        desc.__set_columnPrecision(18);
+        if (cases[i].scale >= 0) {
+            desc.__set_columnScale(cases[i].scale);
+        }
+        TColumnDef column;
+        column.__set_columnDesc(desc);
+        scanner._desc_result.columns.push_back(column);
+    }
+    scanner._desc_result.__set_tables_offset({static_cast<int>(cases.size())});
+
+    auto block = Block::create_unique();
+    scanner._init_block(block.get());
+    ASSERT_TRUE(scanner._fill_block_impl(block.get()).ok());
+    ASSERT_EQ(cases.size(), block->rows());
+    const auto value_at = [&](const char* name, size_t row) {
+        return 
(*block->get_by_position(block->get_position_by_name(name)).column)[row];
+    };
+    for (size_t i = 0; i < cases.size(); ++i) {
+        SCOPED_TRACE(i);
+        EXPECT_EQ(cases[i].data_type, value_at("DATA_TYPE", 
i).get<TYPE_STRING>());
+        EXPECT_EQ(cases[i].column_type, value_at("COLUMN_TYPE", 
i).get<TYPE_STRING>());
+        const auto datetime_precision = value_at("DATETIME_PRECISION", i);
+        if (cases[i].type == TPrimitiveType::DECIMAL64 || cases[i].scale < 0) {
+            EXPECT_TRUE(datetime_precision.is_null());
+        } else {
+            ASSERT_FALSE(datetime_precision.is_null());
+            EXPECT_EQ(cases[i].scale, datetime_precision.get<TYPE_BIGINT>());
+        }
+        for (const auto* name : {"NUMERIC_PRECISION", "NUMERIC_SCALE", 
"DECIMAL_DIGITS"}) {
+            const auto value = value_at(name, i);
+            if (cases[i].type == TPrimitiveType::DECIMAL64) {
+                ASSERT_FALSE(value.is_null());
+                EXPECT_EQ(std::string(name) == "NUMERIC_PRECISION" ? 18 : 3,
+                          value.get<TYPE_BIGINT>());
+            } else {
+                EXPECT_TRUE(value.is_null());
+            }
+        }
+    }
+}
+
+} // namespace doris


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to