blob: c8eaa6094986fecf19c5ff50a3fa4c2852093f51 [file]
// 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::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