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]