blob: a0eb24417e626525e782cd13d347873f5d474117 [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/table_function/vstack.h"
#include <algorithm>
#include "core/assert_cast.h"
#include "core/block/block.h"
#include "core/column/column_const.h"
#include "core/column/column_nullable.h"
#include "core/column/column_struct.h"
#include "exprs/vexpr.h"
namespace doris {
VStackTableFunction::VStackTableFunction() {
_fn_name = "stack";
}
Status VStackTableFunction::process_init(Block* block, RuntimeState* /*state*/) {
const auto& children = _expr_context->root()->children();
DORIS_CHECK_GE(children.size(), 2);
int column_index = -1;
RETURN_IF_ERROR(children[0]->execute(_expr_context.get(), block, &column_index));
const auto& num_rows_column = block->get_by_position(column_index).column;
DORIS_CHECK(is_column_const(*num_rows_column));
const auto num_rows = assert_cast<const ColumnConst&>(*num_rows_column).get_int(0);
DORIS_CHECK_GT(num_rows, 0);
_num_rows = static_cast<size_t>(num_rows);
_num_fields = (children.size() - 2) / _num_rows + 1;
_value_columns.clear();
_value_columns.reserve(children.size() - 1);
for (size_t i = 1; i < children.size(); ++i) {
RETURN_IF_ERROR(children[i]->execute(_expr_context.get(), block, &column_index));
const auto& value_column = block->get_by_position(column_index).column;
const auto& [column, is_const] = unpack_if_const(value_column);
_value_columns.emplace_back(ValueColumn {.column = column, .is_const = is_const});
}
return Status::OK();
}
void VStackTableFunction::process_row(size_t row_idx) {
TableFunction::process_row(row_idx);
_row_idx = row_idx;
_cur_size = static_cast<int64_t>(_num_rows);
}
void VStackTableFunction::process_close() {
_value_columns.clear();
_row_idx = 0;
_num_rows = 0;
_num_fields = 0;
}
void VStackTableFunction::_insert_value(IColumn& destination, const IColumn& source,
size_t source_row) {
auto* nullable_destination = check_and_get_column<ColumnNullable>(&destination);
DORIS_CHECK(nullable_destination != nullptr);
if (const auto* nullable_source = check_and_get_column<ColumnNullable>(&source)) {
nullable_destination->get_nested_column().insert_from(nullable_source->get_nested_column(),
source_row);
nullable_destination->get_null_map_data().push_back(
nullable_source->get_null_map_data()[source_row]);
} else {
nullable_destination->get_nested_column().insert_from(source, source_row);
nullable_destination->get_null_map_data().push_back(0);
}
}
void VStackTableFunction::_insert_output_row(MutableColumnPtr& column, size_t output_row) const {
IColumn* output = column.get();
if (_num_fields == 1) {
const size_t value_index = output_row;
if (value_index < _value_columns.size()) {
const auto& value_column = _value_columns[value_index];
_insert_value(*output, *value_column.column, value_column.is_const ? 0 : _row_idx);
} else {
output->insert_default();
}
return;
}
if (_is_nullable) {
auto& nullable_output = assert_cast<ColumnNullable&>(*output);
nullable_output.get_null_map_data().push_back(0);
output = &nullable_output.get_nested_column();
}
auto& struct_output = assert_cast<ColumnStruct&>(*output);
for (size_t field_index = 0; field_index < _num_fields; ++field_index) {
const size_t value_index = output_row * _num_fields + field_index;
auto& field = struct_output.get_column(field_index);
if (value_index < _value_columns.size()) {
const auto& value_column = _value_columns[value_index];
_insert_value(field, *value_column.column, value_column.is_const ? 0 : _row_idx);
} else {
field.insert_default();
}
}
}
void VStackTableFunction::get_same_many_values(MutableColumnPtr& column, int length) {
for (int i = 0; i < length; ++i) {
_insert_output_row(column, static_cast<size_t>(_cur_offset));
}
}
int VStackTableFunction::get_value(MutableColumnPtr& column, int max_step) {
max_step = std::min(max_step, static_cast<int>(_cur_size - _cur_offset));
for (int i = 0; i < max_step; ++i) {
_insert_output_row(column, static_cast<size_t>(_cur_offset + i));
}
forward(max_step);
return max_step;
}
} // namespace doris