mirror of
https://github.com/apache/doris.git
synced 2026-11-04 15:39:47 +00:00
### What problem does this PR solve?
Issue Number: N/A
Problem Summary:
Root cause: unscoped enums implicitly convert to integers, and integer
parameters accept unrelated enum values, weakening compile-time type
checking in BE execution and expressions.
Use scoped enums for tablet routing, function state scope, and geometry
types/statuses. Replace integer Hash Join template parameters and
runtime-filter/WKB interfaces with their actual enum types, and update
source, test, grammar, and benchmark callers. Use constexpr constants
for scalar-group indexes and remove an unused JSON enum. Existing
encoded values and DateTime value types remain unchanged.
### Release note
None
### Check List (For Author)
- Test:
- [x] No need to test or manual test. Explain why:
- [x] This is a refactor/code format and no logic has been changed in
supported execution paths.
- [x] Previous test can cover this change.
- Validation: clang-format 16, git diff --check, and
build-support/check-build-hygiene.sh passed. BE compilation, unit tests,
regression tests, and clang-tidy have not been run locally.
- Behavior changed:
- [x] No.
- Does this need documentation?
- [x] No.
### Check List (For Reviewer who merge this PR)
- [ ] Confirm the release note
- [ ] Confirm test cases
- [ ] Confirm document
- [ ] Add branch pick label
150 lines
4.9 KiB
C++
150 lines
4.9 KiB
C++
// 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 "exprs/vcolumn_ref.h"
|
|
|
|
#include <gen_cpp/Exprs_types.h>
|
|
#include <gen_cpp/Types_types.h>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "common/exception.h"
|
|
#include "core/assert_cast.h"
|
|
#include "core/block/block.h"
|
|
#include "core/column/column_vector.h"
|
|
#include "core/data_type/data_type_number.h"
|
|
#include "exprs/vexpr_context.h"
|
|
#include "runtime/descriptors.h"
|
|
#include "runtime/runtime_state.h"
|
|
|
|
namespace doris {
|
|
|
|
static TTypeDesc make_int_type_desc() {
|
|
TTypeDesc type_desc;
|
|
TTypeNode type_node;
|
|
TScalarType scalar_type;
|
|
scalar_type.__set_type(TPrimitiveType::INT);
|
|
type_node.__set_type(TTypeNodeType::SCALAR);
|
|
type_node.__set_scalar_type(scalar_type);
|
|
type_desc.types.push_back(type_node);
|
|
return type_desc;
|
|
}
|
|
|
|
static TExprNode make_column_ref_node(int column_id, const std::string& column_name) {
|
|
TExprNode node;
|
|
node.__set_node_type(TExprNodeType::COLUMN_REF);
|
|
node.__set_num_children(0);
|
|
node.__set_type(make_int_type_desc());
|
|
node.__set_is_nullable(false);
|
|
|
|
TColumnRef column_ref;
|
|
column_ref.__set_column_id(column_id);
|
|
column_ref.__set_column_name(column_name);
|
|
node.__set_column_ref(column_ref);
|
|
return node;
|
|
}
|
|
|
|
static ColumnPtr make_int_column(const std::vector<int32_t>& values) {
|
|
auto column = ColumnInt32::create();
|
|
for (auto value : values) {
|
|
column->insert_value(value);
|
|
}
|
|
return column;
|
|
}
|
|
|
|
static Block make_int_block() {
|
|
auto int_type = std::make_shared<DataTypeInt32>();
|
|
Block block;
|
|
block.insert({make_int_column({10, 11}), int_type, "c0"});
|
|
block.insert({make_int_column({20, 21}), int_type, "c1"});
|
|
block.insert({make_int_column({30, 31}), int_type, "c2"});
|
|
return block;
|
|
}
|
|
|
|
static void open_expr(const VExprSPtr& expr, VExprContext* context) {
|
|
RuntimeState state;
|
|
RowDescriptor row_desc;
|
|
ASSERT_TRUE(expr->prepare(&state, row_desc, context).ok());
|
|
ASSERT_TRUE(
|
|
expr->open(&state, context, FunctionContext::FunctionStateScope::THREAD_LOCAL).ok());
|
|
}
|
|
|
|
static std::vector<int32_t> get_int_values(const ColumnPtr& column) {
|
|
const auto* int_column = assert_cast<const ColumnInt32*>(column.get());
|
|
std::vector<int32_t> values;
|
|
for (auto value : int_column->get_data()) {
|
|
values.push_back(value);
|
|
}
|
|
return values;
|
|
}
|
|
|
|
TEST(VColumnRefTest, SetGapOverridesPreviousGap) {
|
|
auto ref = VColumnRef::create_shared(make_column_ref_node(0, "x"));
|
|
VExprContext context(ref);
|
|
open_expr(ref, &context);
|
|
|
|
auto block = make_int_block();
|
|
ColumnPtr result;
|
|
|
|
EXPECT_FALSE(ref->has_gap());
|
|
ref->set_gap(0);
|
|
EXPECT_TRUE(ref->has_gap());
|
|
|
|
ref->set_gap(1);
|
|
auto status = ref->execute_column(&context, &block, nullptr, block.rows(), result);
|
|
ASSERT_TRUE(status.ok()) << status.to_string();
|
|
EXPECT_EQ(get_int_values(result), std::vector<int32_t>({20, 21}));
|
|
|
|
result.reset();
|
|
ref->set_gap(2);
|
|
status = ref->execute_column(&context, &block, nullptr, block.rows(), result);
|
|
ASSERT_TRUE(status.ok()) << status.to_string();
|
|
EXPECT_EQ(get_int_values(result), std::vector<int32_t>({30, 31}));
|
|
}
|
|
|
|
TEST(VColumnRefTest, OutOfRangeColumnPositionReturnsError) {
|
|
auto ref = VColumnRef::create_shared(make_column_ref_node(1, "x"));
|
|
VExprContext context(ref);
|
|
open_expr(ref, &context);
|
|
|
|
auto block = make_int_block();
|
|
ref->set_gap(3);
|
|
|
|
ColumnPtr result;
|
|
auto status = ref->execute_column(&context, &block, nullptr, block.rows(), result);
|
|
EXPECT_FALSE(status.ok());
|
|
EXPECT_NE(status.to_string().find("input block not contain column ref x"), std::string::npos);
|
|
EXPECT_NE(status.to_string().find("column_id=1"), std::string::npos);
|
|
EXPECT_NE(status.to_string().find("gap=3"), std::string::npos);
|
|
}
|
|
|
|
TEST(VColumnRefTest, OutOfRangeExecuteTypeThrowsException) {
|
|
auto ref = VColumnRef::create_shared(make_column_ref_node(1, "x"));
|
|
VExprContext context(ref);
|
|
open_expr(ref, &context);
|
|
|
|
auto block = make_int_block();
|
|
ref->set_gap(3);
|
|
|
|
EXPECT_THROW({ static_cast<void>(ref->execute_type(&block)); }, Exception);
|
|
}
|
|
|
|
} // namespace doris
|