blob: 594f12bae9820787d4e5b11748fc2380d769c294 [file] [log] [blame]
/**
* 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.
**/
#ifndef QUICKSTEP_EXPRESSIONS_TABLE_GENERATOR_GENERATE_SERIES_HANDLE_HPP_
#define QUICKSTEP_EXPRESSIONS_TABLE_GENERATOR_GENERATE_SERIES_HANDLE_HPP_
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include "expressions/table_generator/GeneratorFunctionHandle.hpp"
#include "types/Type.hpp"
#include "types/TypeID.hpp"
#include "types/TypedValue.hpp"
#include "types/containers/ColumnVector.hpp"
#include "types/containers/ColumnVectorsValueAccessor.hpp"
#include "utility/Macros.hpp"
#include "glog/logging.h"
namespace quickstep {
/** \addtogroup Expressions
* @{
*/
/**
* @brief Handle for the instantiated GenerateSeries function.
*/
class GenerateSeriesHandle : public GeneratorFunctionHandle {
public:
int getNumberOfOutputColumns() const override {
return 1;
}
const std::string getOutputColumnName(int index) const override {
if (index > 0) {
LOG(FATAL) << "generate_series function has only 1 output column";
}
// Use the function name as the column name.
return getName();
}
const Type& getOutputColumnType(int index) const override {
if (index > 0) {
LOG(FATAL) << "generate_series function has only 1 output column";
}
return type_;
}
std::size_t getEstimatedCardinality() const override {
switch (type_.getTypeID()) {
case TypeID::kInt: {
return estimateCardinality<int>();
}
case TypeID::kLong: {
return estimateCardinality<std::int64_t>();
}
case TypeID::kFloat: {
return estimateCardinality<float>();
}
case TypeID::kDouble: {
return estimateCardinality<double>();
}
default:
LOG(FATAL) << "GenerateSeries cannot handle arguments with type "
<< type_.getName();
}
return 0;
}
void populateColumns(ColumnVectorsValueAccessor *results) const override {
DCHECK(results != nullptr);
// Generate the output column.
NativeColumnVector *result_vec;
switch (type_.getTypeID()) {
case TypeID::kInt: {
result_vec = generateColumn<int>();
break;
}
case TypeID::kLong: {
result_vec = generateColumn<std::int64_t>();
break;
}
case TypeID::kFloat: {
result_vec = generateColumn<float>();
break;
}
case TypeID::kDouble: {
result_vec = generateColumn<double>();
break;
}
default:
// Should not reach here -- type checking should be done inside
// GenerateSeries::createHandle() at query compile time.
LOG(FATAL) << "GenerateSeries cannot handle arguments with type "
<< type_.getName();
}
// Add the output column into the ColumnVectorsValueAccessor container.
results->addColumn(result_vec);
}
private:
/**
* @brief Constructor. A GenerateSeriesHandle object should only be
* instantiated inside method GenerateSeries::createHandle().
*
* @param func_name The registered name of the GenerateSeries function.
* @param orig_args The original constant arguments to this function
* @param type The unified type for the arguments.
* @param start The start value. Its type should equal unified_type.
* @param end The end value. Its type should equal unified_type.
* @param step The step size. Its type should equal unified_type.
*/
GenerateSeriesHandle(const std::string &func_name,
const std::vector<TypedValue> &orig_args,
const Type &unified_type,
const TypedValue &start,
const TypedValue &end,
const TypedValue &step)
: GeneratorFunctionHandle(func_name, orig_args),
type_(unified_type),
start_(start),
end_(end),
step_(step) {
}
template <typename T>
NativeColumnVector* generateColumn() const {
T start = start_.getLiteral<T>();
T end = end_.getLiteral<T>();
T step = step_.getLiteral<T>();
DCHECK_NE(step, static_cast<T>(0));
std::size_t length = static_cast<std::size_t>((end - start) / step + 1);
DCHECK_GE(length, static_cast<std::size_t>(0));
NativeColumnVector *result_vec = new NativeColumnVector(type_, length);
T value = start;
for (std::size_t i = 0; i < length; ++i) {
result_vec->appendUntypedValue(&value);
value += step;
}
return result_vec;
}
template <typename T>
std::size_t estimateCardinality() const {
T step = step_.getLiteral<T>();
DCHECK_NE(step, static_cast<T>(0));
return static_cast<std::size_t>(
(end_.getLiteral<T>() - start_.getLiteral<T>()) / step + 1);
}
const Type &type_;
const TypedValue start_;
const TypedValue end_;
const TypedValue step_;
friend class GenerateSeries;
DISALLOW_COPY_AND_ASSIGN(GenerateSeriesHandle);
};
/** @} */
} // namespace quickstep
#endif /* QUICKSTEP_EXPRESSIONS_TABLE_GENERATOR_GENERATE_SERIES_HANDLE_HPP_ */