http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/parser/preprocessed/SqlParser_gen.hpp ---------------------------------------------------------------------- diff --git a/parser/preprocessed/SqlParser_gen.hpp b/parser/preprocessed/SqlParser_gen.hpp index 18a3aa0..02f090e 100644 --- a/parser/preprocessed/SqlParser_gen.hpp +++ b/parser/preprocessed/SqlParser_gen.hpp @@ -185,7 +185,7 @@ extern int quickstep_yydebug; union YYSTYPE { -#line 117 "../SqlParser.ypp" /* yacc.c:1915 */ +#line 114 "../SqlParser.ypp" /* yacc.c:1915 */ quickstep::ParseString *string_value_; @@ -257,7 +257,7 @@ union YYSTYPE const quickstep::Comparison *comparison_; quickstep::ParseString *unary_operation_; - const quickstep::BinaryOperation *binary_operation_; + quickstep::ParseString *binary_operation_; quickstep::ParseFunctionCall *function_call_; quickstep::PtrList<quickstep::ParseExpression> *expression_list_;
http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/LogicalGenerator.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/LogicalGenerator.cpp b/query_optimizer/LogicalGenerator.cpp index 49481d3..940b728 100644 --- a/query_optimizer/LogicalGenerator.cpp +++ b/query_optimizer/LogicalGenerator.cpp @@ -51,7 +51,8 @@ L::LogicalPtr LogicalGenerator::generatePlan( const CatalogDatabase &catalog_database, const ParseStatement &parse_statement) { resolver::Resolver resolver(catalog_database, optimizer_context_); - DVLOG(4) << "Parse tree:\n" << parse_statement.toString(); +// DVLOG(4) << "Parse tree:\n" << parse_statement.toString(); + std::cerr << "Parse tree:\n" << parse_statement.toString(); logical_plan_ = resolver.resolve(parse_statement); std::cerr << "Initial logical plan:\n" << logical_plan_->toString(); // exit(0); http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/expressions/BinaryExpression.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/expressions/BinaryExpression.cpp b/query_optimizer/expressions/BinaryExpression.cpp index 446dd55..2178e2e 100644 --- a/query_optimizer/expressions/BinaryExpression.cpp +++ b/query_optimizer/expressions/BinaryExpression.cpp @@ -29,8 +29,8 @@ #include "query_optimizer/expressions/ExprId.hpp" #include "query_optimizer/expressions/Expression.hpp" #include "query_optimizer/expressions/PatternMatcher.hpp" +#include "query_optimizer/expressions/ScalarLiteral.hpp" #include "types/operations/binary_operations/BinaryOperation.hpp" -#include "types/operations/binary_operations/BinaryOperationID.hpp" #include "glog/logging.h" @@ -41,37 +41,8 @@ class Type; namespace optimizer { namespace expressions { -BinaryExpression::BinaryExpression(const BinaryOperation &operation, - const ScalarPtr &left, - const ScalarPtr &right) - : operation_(operation), left_(left), right_(right) { - DCHECK(operation_.canApplyToTypes(left_->getValueType(), - right_->getValueType())) - << toString(); - addChild(left_); - addChild(right_); -} - std::string BinaryExpression::getName() const { - switch (operation_.getBinaryOperationID()) { - case BinaryOperationID::kAdd: - return "Add"; - case BinaryOperationID::kSubtract: - return "Subtract"; - case BinaryOperationID::kMultiply: - return "Multiply"; - case BinaryOperationID::kDivide: - return "Divide"; - case BinaryOperationID::kModulo: - return "Modulo"; - default: - LOG(FATAL) << "Unknown binary operation"; - } -} - -const Type &BinaryExpression::getValueType() const { - return *operation_.resultTypeForArgumentTypes(left_->getValueType(), - right_->getValueType()); + return op_signature_->getName(); } ExpressionPtr BinaryExpression::copyWithNewChildren( @@ -80,9 +51,12 @@ ExpressionPtr BinaryExpression::copyWithNewChildren( DCHECK(SomeScalar::Matches(new_children[0])); DCHECK(SomeScalar::Matches(new_children[1])); return BinaryExpression::Create( + op_signature_, operation_, std::static_pointer_cast<const Scalar>(new_children[0]), - std::static_pointer_cast<const Scalar>(new_children[1])); + std::static_pointer_cast<const Scalar>(new_children[1]), + static_arguments_, + static_argument_types_); } std::vector<AttributeReferencePtr> BinaryExpression::getReferencedAttributes() const { @@ -99,9 +73,11 @@ std::vector<AttributeReferencePtr> BinaryExpression::getReferencedAttributes() c ::quickstep::Scalar *BinaryExpression::concretize( const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const { return new ::quickstep::ScalarBinaryExpression( + op_signature_, operation_, left_->concretize(substitution_map), - right_->concretize(substitution_map)); + right_->concretize(substitution_map), + static_arguments_); } void BinaryExpression::getFieldStringItems( @@ -111,8 +87,26 @@ void BinaryExpression::getFieldStringItems( std::vector<OptimizerTreeBaseNodePtr> *non_container_child_fields, std::vector<std::string> *container_child_field_names, std::vector<std::vector<OptimizerTreeBaseNodePtr>> *container_child_fields) const { - container_child_field_names->push_back(""); - container_child_fields->push_back({left_, right_}); + inline_field_names->emplace_back("op_signature"); + inline_field_values->emplace_back(op_signature_->toString()); + + inline_field_names->emplace_back("result_type"); + inline_field_values->emplace_back(result_type_.getName()); + + non_container_child_field_names->emplace_back("left_operand"); + non_container_child_fields->emplace_back(left_); + non_container_child_field_names->emplace_back("right_operand"); + non_container_child_fields->emplace_back(right_); + + if (!static_arguments_->empty()) { + container_child_field_names->emplace_back("static_arguments"); + container_child_fields->emplace_back(); + for (std::size_t i = 0; i < static_arguments_->size(); ++i) { + container_child_fields->back().emplace_back( + ScalarLiteral::Create(static_arguments_->at(i), + *static_argument_types_->at(i))); + } + } } } // namespace expressions http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/expressions/BinaryExpression.hpp ---------------------------------------------------------------------- diff --git a/query_optimizer/expressions/BinaryExpression.hpp b/query_optimizer/expressions/BinaryExpression.hpp index 9b11ed1..9692dff 100644 --- a/query_optimizer/expressions/BinaryExpression.hpp +++ b/query_optimizer/expressions/BinaryExpression.hpp @@ -31,6 +31,8 @@ #include "query_optimizer/expressions/Expression.hpp" #include "query_optimizer/expressions/ExpressionType.hpp" #include "query_optimizer/expressions/Scalar.hpp" +#include "types/operations/OperationSignature.hpp" +#include "types/operations/binary_operations/BinaryOperation.hpp" #include "utility/Macros.hpp" namespace quickstep { @@ -61,7 +63,9 @@ class BinaryExpression : public Scalar { std::string getName() const override; - const Type& getValueType() const override; + const Type& getValueType() const override { + return result_type_; + } bool isConstant() const override { return left_->isConstant() && right_->isConstant(); @@ -70,7 +74,7 @@ class BinaryExpression : public Scalar { /** * @return The binary operation. */ - const BinaryOperation& operation() const { return operation_; } + const BinaryOperationPtr& operation() const { return operation_; } /** * @return The left operand. @@ -90,10 +94,20 @@ class BinaryExpression : public Scalar { ::quickstep::Scalar* concretize( const std::unordered_map<ExprId, const CatalogAttribute*> &substitution_map) const override; - static BinaryExpressionPtr Create(const BinaryOperation &operation, - const ScalarPtr &left, - const ScalarPtr &right) { - return BinaryExpressionPtr(new BinaryExpression(operation, left, right)); + static BinaryExpressionPtr Create( + const OperationSignaturePtr &op_signature, + const BinaryOperationPtr &operation, + const ScalarPtr &left, + const ScalarPtr &right, + const std::shared_ptr<const std::vector<TypedValue>> &static_arguments, + const std::shared_ptr<const std::vector<const Type*>> &static_argument_types) { + return BinaryExpressionPtr( + new BinaryExpression(op_signature, + operation, + left, + right, + static_arguments, + static_argument_types)); } protected: @@ -106,14 +120,32 @@ class BinaryExpression : public Scalar { std::vector<std::vector<OptimizerTreeBaseNodePtr>> *container_child_fields) const override; private: - BinaryExpression(const BinaryOperation &operation, + BinaryExpression(const OperationSignaturePtr &op_signature, + const BinaryOperationPtr &operation, const ScalarPtr &left, - const ScalarPtr &right); - - const BinaryOperation &operation_; + const ScalarPtr &right, + const std::shared_ptr<const std::vector<TypedValue>> &static_arguments, + const std::shared_ptr<const std::vector<const Type*>> &static_argument_types) + : op_signature_(op_signature), + operation_(operation), + left_(left), + right_(right), + static_arguments_(static_arguments), + static_argument_types_(static_argument_types), + result_type_(*(operation_->getResultType(left_->getValueType(), + right_->getValueType(), + *static_arguments))) { + addChild(left); + addChild(right); + } - ScalarPtr left_; - ScalarPtr right_; + const OperationSignaturePtr op_signature_; + const BinaryOperationPtr operation_; + const ScalarPtr left_; + const ScalarPtr right_; + const std::shared_ptr<const std::vector<TypedValue>> static_arguments_; + const std::shared_ptr<const std::vector<const Type*>> static_argument_types_; + const Type &result_type_; DISALLOW_COPY_AND_ASSIGN(BinaryExpression); }; http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/expressions/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/expressions/CMakeLists.txt b/query_optimizer/expressions/CMakeLists.txt index d7ce686..086636c 100644 --- a/query_optimizer/expressions/CMakeLists.txt +++ b/query_optimizer/expressions/CMakeLists.txt @@ -89,8 +89,9 @@ target_link_libraries(quickstep_queryoptimizer_expressions_BinaryExpression quickstep_queryoptimizer_expressions_ExpressionType quickstep_queryoptimizer_expressions_PatternMatcher quickstep_queryoptimizer_expressions_Scalar + quickstep_queryoptimizer_expressions_ScalarLiteral + quickstep_types_operations_OperationSignature quickstep_types_operations_binaryoperations_BinaryOperation - quickstep_types_operations_binaryoperations_BinaryOperationID quickstep_utility_Macros) target_link_libraries(quickstep_queryoptimizer_expressions_Cast glog http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/expressions/UnaryExpression.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/expressions/UnaryExpression.cpp b/query_optimizer/expressions/UnaryExpression.cpp index d7bde71..6780802 100644 --- a/query_optimizer/expressions/UnaryExpression.cpp +++ b/query_optimizer/expressions/UnaryExpression.cpp @@ -39,7 +39,7 @@ namespace optimizer { namespace expressions { std::string UnaryExpression::getName() const { - return operation_->getName(); + return op_signature_->getName(); } ExpressionPtr UnaryExpression::copyWithNewChildren( @@ -73,6 +73,9 @@ void UnaryExpression::getFieldStringItems( inline_field_names->emplace_back("op_signature"); inline_field_values->emplace_back(op_signature_->toString()); + inline_field_names->emplace_back("result_type"); + inline_field_values->emplace_back(result_type_.getName()); + non_container_child_field_names->emplace_back("operand"); non_container_child_fields->emplace_back(operand_); http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/expressions/UnaryExpression.hpp ---------------------------------------------------------------------- diff --git a/query_optimizer/expressions/UnaryExpression.hpp b/query_optimizer/expressions/UnaryExpression.hpp index c08519f..e742990 100644 --- a/query_optimizer/expressions/UnaryExpression.hpp +++ b/query_optimizer/expressions/UnaryExpression.hpp @@ -129,7 +129,6 @@ class UnaryExpression : public Scalar { static_arguments_(static_arguments), static_argument_types_(static_argument_types), result_type_(*(operation_->getResultType(operand_->getValueType(), *static_arguments_))) { - DCHECK(operation_->canApplyTo(operand_->getValueType(), *static_arguments)) << toString(); addChild(operand); } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/resolver/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/resolver/CMakeLists.txt b/query_optimizer/resolver/CMakeLists.txt index 27497a2..be33972 100644 --- a/query_optimizer/resolver/CMakeLists.txt +++ b/query_optimizer/resolver/CMakeLists.txt @@ -124,13 +124,13 @@ target_link_libraries(quickstep_queryoptimizer_resolver_Resolver quickstep_types_TypeUtil quickstep_types_TypedValue quickstep_types_TypeFactory + quickstep_types_operations_OperationFactory quickstep_types_operations_OperationSignature quickstep_types_operations_binaryoperations_BinaryOperation quickstep_types_operations_comparisons_Comparison quickstep_types_operations_comparisons_ComparisonFactory quickstep_types_operations_comparisons_ComparisonID quickstep_types_operations_unaryoperations_UnaryOperation - quickstep_types_operations_unaryoperations_UnaryOperationFactory quickstep_utility_Macros quickstep_utility_PtrList quickstep_utility_PtrVector http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/resolver/Resolver.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/resolver/Resolver.cpp b/query_optimizer/resolver/Resolver.cpp index 1741409..892c183 100644 --- a/query_optimizer/resolver/Resolver.cpp +++ b/query_optimizer/resolver/Resolver.cpp @@ -22,6 +22,7 @@ #include <algorithm> #include <map> #include <memory> +#include <set> #include <string> #include <unordered_map> #include <unordered_set> @@ -118,13 +119,13 @@ #include "types/TypeFactory.hpp" #include "types/TypeUtil.hpp" #include "types/TypedValue.hpp" +#include "types/operations/OperationFactory.hpp" #include "types/operations/OperationSignature.hpp" #include "types/operations/binary_operations/BinaryOperation.hpp" #include "types/operations/comparisons/Comparison.hpp" #include "types/operations/comparisons/ComparisonFactory.hpp" #include "types/operations/comparisons/ComparisonID.hpp" #include "types/operations/unary_operations/UnaryOperation.hpp" -#include "types/operations/unary_operations/UnaryOperationFactory.hpp" #include "utility/PtrList.hpp" #include "utility/PtrVector.hpp" #include "utility/SqlError.hpp" @@ -2120,109 +2121,6 @@ E::ScalarPtr Resolver::resolveExpression( parse_attribute_scalar.attr_name(), parse_attribute_scalar.rel_name()); } - case ParseExpression::kBinaryExpression: { - const ParseBinaryExpression &parse_binary_scalar = - static_cast<const ParseBinaryExpression&>(parse_expression); - - std::pair<const Type*, const Type*> argument_type_hints - = parse_binary_scalar.op().pushDownTypeHint(type_hint); - - ExpressionResolutionInfo left_resolution_info( - *expression_resolution_info); - E::ScalarPtr left_argument = resolveExpression( - *parse_binary_scalar.left_operand(), - argument_type_hints.first, - &left_resolution_info); - - ExpressionResolutionInfo right_resolution_info( - *expression_resolution_info); - E::ScalarPtr right_argument = resolveExpression( - *parse_binary_scalar.right_operand(), - argument_type_hints.second, - &right_resolution_info); - - if (left_resolution_info.hasAggregate()) { - expression_resolution_info->parse_aggregate_expression = - left_resolution_info.parse_aggregate_expression; - } else if (right_resolution_info.hasAggregate()) { - expression_resolution_info->parse_aggregate_expression = - right_resolution_info.parse_aggregate_expression; - } - - // Check if either argument is a NULL literal of an unknown type. - const bool left_is_nulltype = (left_argument->getValueType().getTypeID() == kNullType); - const bool right_is_nulltype = (right_argument->getValueType().getTypeID() == kNullType); - - // If either argument is a NULL of unknown type, we try to resolve the - // type of this BinaryExpression as follows: - // - // 1. If there is only one possible result type for the expression - // based on what is known about its argument types, then the - // result is a NULL of that type. - // 2. Otherwise, if there is a type hint for the BinaryExpression's - // result, and if it is a plausible result type based on what we - // know about argument types, then the result is a NULL of the - // hint type. - // 3. Otherwise, check if the BinaryExpression can plausibly be - // applied to the known argument types at all. If so, then the - // result is a NULL of unknown type (i.e. NullType). - // 4. If all of the above steps fail, then the BinaryExpression is - // not possibly applicable to the given arguments. - // - // NOTE(chasseur): Step #3 above does not completely capture knowledge - // about the result type of a BinaryExpression with one or more unknown - // arguments. For instance, DivideBinaryOperation can never return a - // DateTime or any string type, so even if we do not know its specific - // return type, we do know that there are some restrictions on what it - // may be. However, NullType is implicitly convertable to ANY Type, so - // such restrictions could be violated if a parent node in the expression - // tree converts a value of NullType to something that it shouldn't be. - if (left_is_nulltype || right_is_nulltype) { - const Type *fixed_result_type - = parse_binary_scalar.op().resultTypeForPartialArgumentTypes( - left_is_nulltype ? nullptr : &(left_argument->getValueType()), - right_is_nulltype ? nullptr : &(right_argument->getValueType())); - if (fixed_result_type != nullptr) { - return E::ScalarLiteral::Create(fixed_result_type->makeNullValue(), - *fixed_result_type); - } - - if (type_hint != nullptr) { - const Type &nullable_type_hint = type_hint->getNullableVersion(); - if (parse_binary_scalar.op().partialTypeSignatureIsPlausible( - &nullable_type_hint, - left_is_nulltype ? nullptr : &(left_argument->getValueType()), - right_is_nulltype ? nullptr : &(right_argument->getValueType()))) { - return E::ScalarLiteral::Create(nullable_type_hint.makeNullValue(), - nullable_type_hint); - } - } - - if (parse_binary_scalar.op().partialTypeSignatureIsPlausible( - nullptr, - left_is_nulltype ? nullptr : &(left_argument->getValueType()), - right_is_nulltype ? nullptr : &(right_argument->getValueType()))) { - const Type &null_type = TypeFactory::GetType(kNullType, true); - return E::ScalarLiteral::Create(null_type.makeNullValue(), - null_type); - } - - // If nothing above worked, fall through to canApplyToTypes() below, - // which should fail. - } - - if (!parse_binary_scalar.op().canApplyToTypes(left_argument->getValueType(), - right_argument->getValueType())) { - THROW_SQL_ERROR_AT(&parse_binary_scalar) - << "Can not apply binary operation \"" << parse_binary_scalar.op().getName() - << "\" to arguments of types " << left_argument->getValueType().getName() - << " and " << right_argument->getValueType().getName(); - } - - return E::BinaryExpression::Create(parse_binary_scalar.op(), - left_argument, - right_argument); - } case ParseExpression::kScalarLiteral: { const ParseScalarLiteral &parse_literal_scalar = static_cast<const ParseScalarLiteral&>(parse_expression); @@ -2525,118 +2423,77 @@ E::ScalarPtr Resolver::resolveScalarFunction( const std::vector<E::ScalarPtr> &resolved_arguments, ExpressionResolutionInfo *expression_resolution_info) { const std::size_t arity = resolved_arguments.size(); - std::vector<const Type*> argument_types; - std::vector<TypeID> argument_type_ids; std::size_t first_static_argument_position = 0; for (std::size_t i = 0; i < arity; ++i) { const E::ScalarPtr &argument = resolved_arguments[i]; if (argument->getExpressionType() != E::ExpressionType::kScalarLiteral) { first_static_argument_position = i + 1; } - - const Type &type = argument->getValueType(); - argument_types.emplace_back(&type); - argument_type_ids.emplace_back(type.getTypeID()); + argument_types.emplace_back(&argument->getValueType()); } - std::vector<TypedValue> maximal_static_arguments; + std::vector<TypedValue> static_arguments; for (std::size_t i = first_static_argument_position; i < arity; ++i) { - maximal_static_arguments.emplace_back( + static_arguments.emplace_back( std::static_pointer_cast<const E::ScalarLiteral>( resolved_arguments[i])->value()); - DCHECK(maximal_static_arguments.back().getTypeID() == argument_type_ids[i]); - } - const std::size_t max_num_static_arguments = maximal_static_arguments.size(); - - const UnaryOperationFactory &factory = UnaryOperationFactory::Instance(); - - // First, check exact matching of name + non static types, possibly safe - // coercion of static arguments. - const auto &op_sig_candidates = factory.getUnaryOperations(function_name, arity); - for (const OperationSignaturePtr &op_sig : op_sig_candidates) { - const std::size_t op_num_static_arguments = op_sig->getNumStaticArguments(); - if (op_num_static_arguments > max_num_static_arguments) { - continue; - } - - bool is_match = true; - for (std::size_t i = 0; i < arity - op_num_static_arguments; ++i) { - if (op_sig->getArgumentTypeIDs().at(i) != argument_type_ids[i]) { - is_match = false; - break; - } - } - if (!is_match) { - continue; - } - - std::vector<TypedValue> coerced_static_arguments; - std::vector<const Type*> coerced_static_argument_types; - bool is_coercible = true; - for (std::size_t i = arity - op_num_static_arguments; i < arity; ++i) { - const Type &arg_type = *argument_types.at(i); - const TypedValue &arg_value = - maximal_static_arguments.at(i - first_static_argument_position); - const TypeID expected_type_id = op_sig->getArgumentTypeIDs().at(i); - if (arg_type.getTypeID() == expected_type_id) { - coerced_static_arguments.emplace_back(arg_value); - coerced_static_argument_types.emplace_back(&arg_type); - } else { - const Type *expected_type = nullptr; - if (TypeUtil::IsParameterized(expected_type_id)) { - // TODO: refactor type system to make this coercion extensible. - if (expected_type_id == kChar && arg_type.getTypeID() == kVarChar) { - expected_type = &TypeFactory::GetType( - expected_type_id, arg_type.maximumByteLength() - 1); - } else if (expected_type_id == kVarChar && arg_type.getTypeID() == kChar) { - expected_type = &TypeFactory::GetType( - expected_type_id, arg_type.maximumByteLength() + 1); - } - } else { - expected_type = &TypeFactory::GetType(expected_type_id); - } - if (expected_type != nullptr && expected_type->isSafelyCoercibleFrom(arg_type)) { - coerced_static_arguments.emplace_back( - expected_type->coerceValue(arg_value, arg_type)); - coerced_static_argument_types.emplace_back(expected_type); - } else { - is_coercible = false; - break; - } - } - } - if (!is_coercible) { - continue; - } - - // TODO: switch on operation non-static arity here. - CHECK_EQ(1u, arity - op_num_static_arguments); - - const UnaryOperationPtr op = factory.getUnaryOperation(op_sig); - const auto static_arguments = - std::make_shared<const std::vector<TypedValue>>( - std::move(coerced_static_arguments)); - const auto static_argument_types = - std::make_shared<const std::vector<const Type*>>( - std::move(coerced_static_argument_types)); - - std::string message; - if (op->canApplyTo(*argument_types.front(), *static_arguments, &message)) { - return E::UnaryExpression::Create(op_sig, - op, - resolved_arguments.front(), - static_arguments, - static_argument_types); - } else { + DCHECK(static_arguments.back().getTypeID() == argument_types[i]->getTypeID()); + } + + std::shared_ptr<const std::vector<const Type*>> coerced_argument_types; + std::shared_ptr<const std::vector<TypedValue>> coerced_static_arguments; + std::string message; + const OperationSignaturePtr op_signature = + OperationFactory::Instance().resolveOperation( + function_name, + std::make_shared<const std::vector<const Type*>>(std::move(argument_types)), + std::make_shared<const std::vector<TypedValue>>(std::move(static_arguments)), + &coerced_argument_types, + &coerced_static_arguments, + &message); + + if (op_signature == nullptr) { + if (message.empty()) { THROW_SQL_ERROR_AT(&parse_function_call) << message; + } else { + THROW_SQL_ERROR_AT(&parse_function_call) + << "Cannot resolve scalar function " << function_name; + } + } + + // TODO: add cast if neccessary. + + const auto coerced_static_argument_types = + std::make_shared<const std::vector<const Type*>>( + coerced_argument_types->begin() + op_signature->getNonStaticArity(), + coerced_argument_types->end()); + + const OperationPtr operation = + OperationFactory::Instance().getOperation(op_signature); + switch (operation->getOperationSuperTypeID()) { + case Operation::kUnaryOperation: + return E::UnaryExpression::Create( + op_signature, + std::static_pointer_cast<const UnaryOperation>(operation), + resolved_arguments[0], + coerced_static_arguments, + coerced_static_argument_types); + case Operation::kBinaryOperation: + return E::BinaryExpression::Create( + op_signature, + std::static_pointer_cast<const BinaryOperation>(operation), + resolved_arguments[0], + resolved_arguments[1], + coerced_static_arguments, + coerced_static_argument_types); + default: { + const auto operation_id = + static_cast<std::underlying_type_t<Operation::OperationSuperTypeID>>( + operation->getOperationSuperTypeID()); + LOG(FATAL) << "Unknown opeation super type id: " << operation_id; } } - - THROW_SQL_ERROR_AT(&parse_function_call) - << "Cannot resolve scalar function"; - - return nullptr; } // TODO(chasseur): For now this only handles resolving aggregate functions. In @@ -2686,8 +2543,8 @@ E::ScalarPtr Resolver::resolveFunctionCall( } } - if (UnaryOperationFactory::Instance().hasUnaryOperation(function_name, - resolved_arguments.size())) { + if (OperationFactory::Instance().hasOperation(function_name, + resolved_arguments.size())) { E::ScalarPtr scalar = resolveScalarFunction(parse_function_call, function_name, resolved_arguments, http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/rules/tests/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/rules/tests/CMakeLists.txt b/query_optimizer/rules/tests/CMakeLists.txt index 0d913e2..cdb5fe6 100644 --- a/query_optimizer/rules/tests/CMakeLists.txt +++ b/query_optimizer/rules/tests/CMakeLists.txt @@ -85,7 +85,6 @@ target_link_libraries(quickstep_queryoptimizer_rules_tests quickstep_queryoptimizer_rules_tests_RuleTest quickstep_types_operations_binaryoperations_BinaryOperation quickstep_types_operations_binaryoperations_BinaryOperationFactory - quickstep_types_operations_binaryoperations_BinaryOperationID quickstep_types_operations_comparisons_Comparison quickstep_types_operations_comparisons_ComparisonFactory quickstep_types_operations_comparisons_ComparisonID http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/strategy/tests/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/strategy/tests/CMakeLists.txt b/query_optimizer/strategy/tests/CMakeLists.txt index 97675f0..1a60344 100644 --- a/query_optimizer/strategy/tests/CMakeLists.txt +++ b/query_optimizer/strategy/tests/CMakeLists.txt @@ -74,7 +74,6 @@ target_link_libraries(quickstep_queryoptimizer_strategy_tests quickstep_types_TypeID quickstep_types_operations_binaryoperations_BinaryOperation quickstep_types_operations_binaryoperations_BinaryOperationFactory - quickstep_types_operations_binaryoperations_BinaryOperationID quickstep_types_operations_comparisons_Comparison quickstep_types_operations_comparisons_ComparisonFactory quickstep_types_operations_comparisons_ComparisonID http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/tests/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/tests/CMakeLists.txt b/query_optimizer/tests/CMakeLists.txt index 5ef1d0a..4357c6a 100644 --- a/query_optimizer/tests/CMakeLists.txt +++ b/query_optimizer/tests/CMakeLists.txt @@ -51,7 +51,6 @@ target_link_libraries(quickstep_queryoptimizer_tests_OptimizerTest quickstep_types_TypeID quickstep_types_operations_binaryoperations_BinaryOperation quickstep_types_operations_binaryoperations_BinaryOperationFactory - quickstep_types_operations_binaryoperations_BinaryOperationID quickstep_types_operations_comparisons_Comparison quickstep_types_operations_comparisons_ComparisonFactory quickstep_types_operations_comparisons_ComparisonID http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/query_optimizer/tests/OptimizerTest.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/tests/OptimizerTest.cpp b/query_optimizer/tests/OptimizerTest.cpp index 7eb7a11..36436c0 100644 --- a/query_optimizer/tests/OptimizerTest.cpp +++ b/query_optimizer/tests/OptimizerTest.cpp @@ -44,7 +44,6 @@ #include "types/TypeID.hpp" #include "types/operations/binary_operations/BinaryOperation.hpp" #include "types/operations/binary_operations/BinaryOperationFactory.hpp" -#include "types/operations/binary_operations/BinaryOperationID.hpp" #include "types/operations/comparisons/Comparison.hpp" #include "types/operations/comparisons/ComparisonFactory.hpp" #include "types/operations/comparisons/ComparisonID.hpp" http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/relational_operators/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/relational_operators/CMakeLists.txt b/relational_operators/CMakeLists.txt index 1693ec2..8ba00b0 100644 --- a/relational_operators/CMakeLists.txt +++ b/relational_operators/CMakeLists.txt @@ -663,7 +663,6 @@ target_link_libraries(AggregationOperator_unittest quickstep_types_TypedValue quickstep_types_containers_Tuple quickstep_types_operations_binaryoperations_BinaryOperationFactory - quickstep_types_operations_binaryoperations_BinaryOperationID quickstep_types_operations_comparisons_ComparisonFactory quickstep_types_operations_comparisons_ComparisonID quickstep_utility_Macros http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/storage/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/storage/CMakeLists.txt b/storage/CMakeLists.txt index 8b68150..7789881 100644 --- a/storage/CMakeLists.txt +++ b/storage/CMakeLists.txt @@ -863,7 +863,6 @@ target_link_libraries(quickstep_storage_SMAIndexSubBlock quickstep_types_TypedValue quickstep_types_operations_binaryoperations_BinaryOperation quickstep_types_operations_binaryoperations_BinaryOperationFactory - quickstep_types_operations_binaryoperations_BinaryOperationID quickstep_types_operations_comparisons_Comparison quickstep_types_operations_comparisons_ComparisonFactory quickstep_types_operations_comparisons_ComparisonID http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/storage/SMAIndexSubBlock.cpp ---------------------------------------------------------------------- diff --git a/storage/SMAIndexSubBlock.cpp b/storage/SMAIndexSubBlock.cpp index 3b3b879..fda8c30 100644 --- a/storage/SMAIndexSubBlock.cpp +++ b/storage/SMAIndexSubBlock.cpp @@ -46,7 +46,6 @@ #include "types/TypedValue.hpp" #include "types/operations/binary_operations/BinaryOperation.hpp" #include "types/operations/binary_operations/BinaryOperationFactory.hpp" -#include "types/operations/binary_operations/BinaryOperationID.hpp" #include "types/operations/comparisons/Comparison.hpp" #include "types/operations/comparisons/ComparisonFactory.hpp" #include "types/operations/comparisons/ComparisonID.hpp" @@ -360,8 +359,8 @@ SMAIndexSubBlock::SMAIndexSubBlock(const TupleStorageSubBlock &tuple_store, if (add_operations_.elementIsNullAt(attr_typeid)) { add_operations_.replaceElement(attr_typeid, BinaryOperationFactory::GetBinaryOperation(BinaryOperationID::kAdd) - .makeUncheckedBinaryOperatorForTypes(TypeFactory::GetType(attr_typeid), - TypeFactory::GetType(attr_sum_typeid))); + .makeUncheckedBinaryOperator(TypeFactory::GetType(attr_typeid), + TypeFactory::GetType(attr_sum_typeid))); } } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/types/CMakeLists.txt b/types/CMakeLists.txt index 1fac11a..0c7ee07 100644 --- a/types/CMakeLists.txt +++ b/types/CMakeLists.txt @@ -49,7 +49,6 @@ add_library(quickstep_types_NullType ../empty_src.cpp NullType.hpp) add_library(quickstep_types_NumericSuperType ../empty_src.cpp NumericSuperType.hpp) add_library(quickstep_types_NumericTypeUnifier ../empty_src.cpp NumericTypeUnifier.hpp) add_library(quickstep_types_Type Type.cpp Type.hpp) -add_library(quickstep_types_TypeConcept ../empty_src.cpp TypeConcept.hpp) add_library(quickstep_types_TypeErrors ../empty_src.cpp TypeErrors.hpp) add_library(quickstep_types_TypeFactory TypeFactory.cpp TypeFactory.hpp) add_library(quickstep_types_TypeID TypeID.cpp TypeID.hpp) @@ -167,8 +166,6 @@ target_link_libraries(quickstep_types_Type quickstep_types_TypeID quickstep_types_TypedValue quickstep_utility_Macros) -target_link_libraries(quickstep_types_TypeConcept - glog) target_link_libraries(quickstep_types_TypeFactory glog quickstep_types_CharType @@ -204,7 +201,8 @@ target_link_libraries(quickstep_types_TypeUtil quickstep_types_Type_proto quickstep_types_VarCharType quickstep_types_YearMonthIntervalType - quickstep_utility_Macros) + quickstep_utility_Macros + quickstep_utility_TemplateUtil) target_link_libraries(quickstep_types_TypedValue farmhash glog http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/NumericSuperType.hpp ---------------------------------------------------------------------- diff --git a/types/NumericSuperType.hpp b/types/NumericSuperType.hpp index ceb24b6..77f028a 100644 --- a/types/NumericSuperType.hpp +++ b/types/NumericSuperType.hpp @@ -55,7 +55,7 @@ class NumericSuperType : public TypeConcept<type_id, false, kNativeEmbedded, Cpp } protected: - NumericSuperType(const bool nullable) + explicit NumericSuperType(const bool nullable) : TypeConcept<type_id, false, kNativeEmbedded, CppType>( Type::kNumeric, type_id, nullable, sizeof(CppType), sizeof(CppType)) { } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/Type.hpp ---------------------------------------------------------------------- diff --git a/types/Type.hpp b/types/Type.hpp index afc46eb..066b2b5 100644 --- a/types/Type.hpp +++ b/types/Type.hpp @@ -485,7 +485,7 @@ class TypeConcept : public Type { protected: template <typename ...ArgTypes> - TypeConcept(ArgTypes &&...args) + explicit TypeConcept(ArgTypes &&...args) : Type(std::forward<ArgTypes>(args)...) {} private: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/TypeUtil.hpp ---------------------------------------------------------------------- diff --git a/types/TypeUtil.hpp b/types/TypeUtil.hpp index fe55952..6c58ef1 100644 --- a/types/TypeUtil.hpp +++ b/types/TypeUtil.hpp @@ -138,7 +138,6 @@ inline auto InvokeOnTypeID(const TypeID type_id, std::integral_constant<TypeID, type_id>, FunctorT>::Invoke(functor) switch (type_id) { - REGISTER_TYPE_ID(kInt); REGISTER_TYPE_ID(kLong); REGISTER_TYPE_ID(kFloat); @@ -150,7 +149,6 @@ inline auto InvokeOnTypeID(const TypeID type_id, REGISTER_TYPE_ID(kChar); REGISTER_TYPE_ID(kVarChar); REGISTER_TYPE_ID(kNullType); - default: FATAL_ERROR("Unrecognized TypeID in InvokeOnTypeID()"); } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/containers/ColumnVector.cpp ---------------------------------------------------------------------- diff --git a/types/containers/ColumnVector.cpp b/types/containers/ColumnVector.cpp index dfc0fae..ef3587e 100644 --- a/types/containers/ColumnVector.cpp +++ b/types/containers/ColumnVector.cpp @@ -41,4 +41,8 @@ ColumnVector* ColumnVector::MakeVectorOfValue( } } +constexpr bool NativeColumnVector::kNative; + +constexpr bool IndirectColumnVector::kNative; + } // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/containers/ColumnVector.hpp ---------------------------------------------------------------------- diff --git a/types/containers/ColumnVector.hpp b/types/containers/ColumnVector.hpp index f0a2cd5..5d11098 100644 --- a/types/containers/ColumnVector.hpp +++ b/types/containers/ColumnVector.hpp @@ -119,6 +119,8 @@ class ColumnVector { **/ class NativeColumnVector : public ColumnVector { public: + static constexpr bool kNative = true; + /** * @brief Constructor for a NativeColumnVector which owns its own array of * values. @@ -400,6 +402,8 @@ class NativeColumnVector : public ColumnVector { **/ class IndirectColumnVector : public ColumnVector { public: + static constexpr bool kNative = false; + /** * @brief Constructor. * @@ -494,7 +498,7 @@ class IndirectColumnVector : public ColumnVector { * @param value A value to append to this NativeColumnVector. **/ inline void appendTypedValue(TypedValue &&value) { - DCHECK(value.isPlausibleInstanceOf(type_.getSignature())); + DCHECK(value.isPlausibleInstanceOf(type_.getSignature())) << type_.getName(); DCHECK_LT(values_.size(), reserved_length_); values_.emplace_back(std::move(value)); } @@ -505,6 +509,10 @@ class IndirectColumnVector : public ColumnVector { values_.emplace_back(type_.makeNullValue()); } + inline void fillWithNulls() { + fillWithValue(type_.makeNullValue()); + } + /** * @brief Fill this entire ColumnVector with copies of value. * http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/operations/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/types/operations/CMakeLists.txt b/types/operations/CMakeLists.txt index 6d38d80..baaaf55 100644 --- a/types/operations/CMakeLists.txt +++ b/types/operations/CMakeLists.txt @@ -25,12 +25,41 @@ QS_PROTOBUF_GENERATE_CPP(types_operations_Operation_proto_srcs # Declare micro-libs: add_library(quickstep_types_operations_Operation Operation.cpp Operation.hpp) +add_library(quickstep_types_operations_OperationFactory OperationFactory.cpp OperationFactory.hpp) +add_library(quickstep_types_operations_OperationUtil ../../empty_src.cpp OperationUtil.hpp) add_library(quickstep_types_operations_OperationSignature OperationSignature.cpp OperationSignature.hpp) add_library(quickstep_types_operations_Operation_proto ${types_operations_Operation_proto_srcs}) # Link dependencies: target_link_libraries(quickstep_types_operations_Operation + quickstep_types_operations_OperationSignature quickstep_utility_Macros) +target_link_libraries(quickstep_types_operations_OperationFactory + quickstep_types_Type + quickstep_types_TypeFactory + quickstep_types_TypeID + quickstep_types_TypeUtil + quickstep_types_TypedValue + quickstep_types_operations_Operation + quickstep_types_operations_OperationSignature + quickstep_types_operations_binaryoperations_ArithmeticBinaryOperations + quickstep_types_operations_binaryoperations_BinaryOperation + quickstep_types_operations_binaryoperations_BinaryOperationWrapper + quickstep_types_operations_unaryoperations_ArithmeticUnaryOperations + quickstep_types_operations_unaryoperations_CMathUnaryOperations + quickstep_types_operations_unaryoperations_CastOperation + quickstep_types_operations_unaryoperations_DateExtractOperation + quickstep_types_operations_unaryoperations_SubstringOperation + quickstep_types_operations_unaryoperations_UnaryOperation + quickstep_types_operations_unaryoperations_UnaryOperationWrapper + quickstep_utility_HashPair + quickstep_utility_Macros + quickstep_utility_StringUtil) +target_link_libraries(quickstep_types_operations_OperationUtil + quickstep_catalog_CatalogTypedefs + quickstep_types_Type + quickstep_types_TypedValue + quickstep_types_containers_ColumnVector) target_link_libraries(quickstep_types_operations_OperationSignature quickstep_types_TypeID quickstep_types_Type_proto @@ -46,6 +75,8 @@ target_link_libraries(quickstep_types_operations_Operation_proto add_library(quickstep_types_operations ../../empty_src.cpp) target_link_libraries(quickstep_types_operations quickstep_types_operations_Operation + quickstep_types_operations_OperationFactory + quickstep_types_operations_OperationUtil quickstep_types_operations_OperationSignature quickstep_types_operations_Operation_proto quickstep_types_operations_binaryoperations http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/operations/Operation.hpp ---------------------------------------------------------------------- diff --git a/types/operations/Operation.hpp b/types/operations/Operation.hpp index ad7c868..6da0f4c 100644 --- a/types/operations/Operation.hpp +++ b/types/operations/Operation.hpp @@ -23,6 +23,7 @@ #include <string> #include <vector> +#include "types/operations/OperationSignature.hpp" #include "utility/Macros.hpp" namespace quickstep { @@ -31,6 +32,9 @@ namespace quickstep { * @{ */ +class Operation; +typedef std::shared_ptr<const Operation> OperationPtr; + /** * @brief An operation which can be applied to typed values. Each exact * concrete Operation is a singleton. @@ -87,6 +91,10 @@ class Operation { return "NoShortName"; } + virtual std::vector<OperationSignaturePtr> getSignatures() const { + return {}; + } + /** * @brief Determine whether this Operation is exactly the same as another. * @note Because all exact operations are singletons, a simple pointer @@ -101,7 +109,7 @@ class Operation { } protected: - Operation(const OperationSuperTypeID super_type_id) + explicit Operation(const OperationSuperTypeID super_type_id) : super_type_id_(super_type_id) { } http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/operations/Operation.proto ---------------------------------------------------------------------- diff --git a/types/operations/Operation.proto b/types/operations/Operation.proto index 006b07c..da2a282 100644 --- a/types/operations/Operation.proto +++ b/types/operations/Operation.proto @@ -44,15 +44,3 @@ message OperationSignature { repeated TypeID argument_type_ids = 2; required uint32 num_static_arguments = 3; } - -message BinaryOperation { - enum BinaryOperationID { - ADD = 0; - SUBTRACT = 1; - MULTIPLY = 2; - DIVIDE = 3; - MODULO = 4; - } - - required BinaryOperationID operation_id = 1; -} http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/operations/OperationFactory.cpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationFactory.cpp b/types/operations/OperationFactory.cpp new file mode 100644 index 0000000..5743cfc --- /dev/null +++ b/types/operations/OperationFactory.cpp @@ -0,0 +1,358 @@ +/** + * 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 "types/operations/OperationFactory.hpp" + +#include <list> +#include <memory> +#include <string> +#include <vector> + +#include "types/Type.hpp" +#include "types/TypeFactory.hpp" +#include "types/TypeID.hpp" +#include "types/TypeUtil.hpp" +#include "types/TypedValue.hpp" +#include "types/operations/Operation.hpp" +#include "types/operations/OperationSignature.hpp" +#include "types/operations/binary_operations/ArithmeticBinaryOperations.hpp" +#include "types/operations/binary_operations/AsciiStringBinaryOperations.hpp" +#include "types/operations/binary_operations/BinaryOperationWrapper.hpp" +#include "types/operations/unary_operations/ArithmeticUnaryOperations.hpp" +#include "types/operations/unary_operations/AsciiStringUnaryOperations.hpp" +#include "types/operations/unary_operations/CMathUnaryOperations.hpp" +#include "types/operations/unary_operations/CastOperation.hpp" +#include "types/operations/unary_operations/DateExtractOperation.hpp" +#include "types/operations/unary_operations/SubstringOperation.hpp" +#include "types/operations/unary_operations/UnaryOperationWrapper.hpp" +#include "utility/StringUtil.hpp" + +namespace quickstep { + +namespace { + +struct FunctorPackDispatcher { + template <typename FunctorT> + inline static std::list<OperationPtr> Generate( + std::enable_if_t<FunctorT::kOperationSuperTypeID == Operation::kUnaryOperation>* = 0) { + return { std::make_shared<const UnaryOperationWrapper<FunctorT>>() }; + } + + template <typename FunctorT> + inline static std::list<OperationPtr> Generate( + std::enable_if_t<FunctorT::kOperationSuperTypeID == Operation::kBinaryOperation>* = 0) { + return { std::make_shared<const BinaryOperationWrapper<FunctorT>>() }; + } + + template <typename FunctorT> + inline static std::list<OperationPtr> Generate( + decltype(FunctorT::template GenerateOperations<FunctorPackDispatcher>())* = 0) { + return FunctorT::template GenerateOperations<FunctorPackDispatcher>(); + } +}; + +} // namespace + +OperationFactory::OperationFactory() { + registerOperation<CastOperation>(); + registerOperation<DateExtractOperation>(); + registerOperation<SubstringOperation>(); + + registerFunctorPack<ArithmeticUnaryFunctorPack>(); + registerFunctorPack<AsciiStringUnaryFunctorPack>(); + registerFunctorPack<CMathUnaryFunctorPack>(); + + registerFunctorPack<ArithmeticBinaryFunctorPack>(); + registerFunctorPack<AsciiStringBinaryFunctorPack>(); +} + +OperationSignaturePtr OperationFactory::resolveOperation( + const std::string &operation_name, + const std::shared_ptr<const std::vector<const Type*>> &argument_types, + const std::shared_ptr<const std::vector<TypedValue>> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + std::string *message) const { + const std::string lower_case_name = ToLower(operation_name); + const std::size_t arity = argument_types->size(); + const auto &indices_it = + primary_index_.find(std::make_pair(lower_case_name, arity)); + + if (indices_it == primary_index_.end()) { + *message = "Unrecognized function " + operation_name + + " with " + std::to_string(arity) + " arguments"; + } + + ResolveStatus status; + OperationSignaturePtr op_signature = nullptr; + const auto &secondary_indices = indices_it->second; + + std::vector<TypeID> argument_type_ids; + for (const auto *type : *argument_types) { + argument_type_ids.emplace_back(type->getTypeID()); + } + + // First, try full exact matching. + status = resolveOperationWithFullTypeMatch(secondary_indices.full_match_index, + argument_type_ids, + *argument_types, + *static_arguments, + coerced_static_arguments, + &op_signature, + message); + if (status == ResolveStatus::kSuccess) { + DCHECK(op_signature != nullptr); + *coerced_argument_types = argument_types; + return op_signature; + } else if (status == ResolveStatus::kError) { + return nullptr; + } + + // Otherwise, try partial (non-static arguments) exact matching. + status = resolveOperationWithPartialTypeMatch(secondary_indices.non_static_match_index, + argument_type_ids, + *argument_types, + *static_arguments, + coerced_argument_types, + coerced_static_arguments, + &op_signature, + message); + if (status == ResolveStatus::kSuccess) { + DCHECK(op_signature != nullptr); + return op_signature; + } else if (status == ResolveStatus::kError) { + return nullptr; + } + + // TODO + *message = "Cannot resolve function " + operation_name; + return nullptr; +} + +OperationFactory::ResolveStatus OperationFactory::resolveOperationWithFullTypeMatch( + const FullSignatureIndex &full_match_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<TypedValue>> *partial_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const { + const std::size_t max_num_static_arguments = static_arguments.size(); + auto it = full_match_index.lower_bound( + std::make_pair(&argument_type_ids, max_num_static_arguments)); + + if (it != full_match_index.end() && *it->first.first == argument_type_ids) { + const OperationSignaturePtr op_signature = it->second; + const OperationPtr operation = getOperation(op_signature); + + *partial_static_arguments = + std::make_shared<const std::vector<TypedValue>>( + static_arguments.begin() + + (max_num_static_arguments - op_signature->getNumStaticArguments()), + static_arguments.end()); + + if (canApplyOperationTo(operation, + argument_types, + **partial_static_arguments, + message)) { + *resolved_op_signature = op_signature; + return ResolveStatus::kSuccess; + } else { + return ResolveStatus::kError; + } + } + + return ResolveStatus::kNotFound; +} + +OperationFactory::ResolveStatus OperationFactory::resolveOperationWithPartialTypeMatch( + const PartialSignatureIndex &non_static_match_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const { + const std::size_t arity = argument_types.size(); + const std::size_t max_num_static_arguments = static_arguments.size(); + const std::size_t first_static_argument_position = arity - max_num_static_arguments; + + auto it = non_static_match_index.lower_bound( + std::make_pair(&argument_type_ids, max_num_static_arguments)); + while (it != non_static_match_index.end()) { + const std::vector<TypeID> &expected_type_ids = *it->first.first; + DCHECK_GE(expected_type_ids.size(), it->first.second); + const std::size_t num_non_static_arguments = + expected_type_ids.size() - it->first.second; + + if (!std::equal(expected_type_ids.begin(), + expected_type_ids.begin() + num_non_static_arguments, + argument_type_ids.begin())) { + break; + } + + // Coerce static arguments + std::vector<const Type*> coerced_static_arg_types; + std::vector<TypedValue> coerced_static_args; + + bool is_coercible = true; + for (std::size_t i = num_non_static_arguments; i < arity; ++i) { + const Type &arg_type = *argument_types.at(i); + const TypedValue &arg_value = + static_arguments.at(i - first_static_argument_position); + const TypeID &expected_type_id = expected_type_ids.at(i); + + if (arg_type.getTypeID() == expected_type_id) { + coerced_static_arg_types.emplace_back(&arg_type); + coerced_static_args.emplace_back(arg_value); + } else { + const Type *expected_type = nullptr; + if (TypeUtil::IsParameterized(expected_type_id)) { + // TODO: refactor type system to make this coercion extensible. + if (expected_type_id == kChar && arg_type.getTypeID() == kVarChar) { + expected_type = &TypeFactory::GetType( + expected_type_id, arg_type.maximumByteLength() - 1); + } else if (expected_type_id == kVarChar && arg_type.getTypeID() == kChar) { + expected_type = &TypeFactory::GetType( + expected_type_id, arg_type.maximumByteLength() + 1); + } + } else { + expected_type = &TypeFactory::GetType(expected_type_id); + } + + if (expected_type != nullptr && expected_type->isSafelyCoercibleFrom(arg_type)) { + coerced_static_arg_types.emplace_back(expected_type); + coerced_static_args.emplace_back( + expected_type->coerceValue(arg_value, arg_type)); + } else { + is_coercible = false; + break; + } + } + } + + if (is_coercible) { + std::vector<const Type*> coerced_arg_types( + argument_types.begin(), + argument_types.begin() + num_non_static_arguments); + for (const Type *type : coerced_static_arg_types) { + coerced_arg_types.emplace_back(type); + } + + const OperationPtr operation = getOperation(it->second); + if (canApplyOperationTo(operation, + coerced_arg_types, + coerced_static_args, + message)) { + *coerced_argument_types = + std::make_shared<const std::vector<const Type*>>(std::move(coerced_arg_types)); + *coerced_static_arguments = + std::make_shared<const std::vector<TypedValue>>(std::move(coerced_static_args)); + *resolved_op_signature = it->second; + return ResolveStatus::kSuccess; + } + } + + ++it; + } + + return ResolveStatus::kNotFound; +} + +bool OperationFactory::canApplyOperationTo( + const OperationPtr operation, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::string *message) const { + switch (operation->getOperationSuperTypeID()) { + case Operation::kUnaryOperation: { + const UnaryOperationPtr unary_operation = + std::static_pointer_cast<const UnaryOperation>(operation); + return unary_operation->canApplyTo(*argument_types[0], + static_arguments, + message); + } + case Operation::kBinaryOperation: { + const BinaryOperationPtr binary_operation = + std::static_pointer_cast<const BinaryOperation>(operation); + return binary_operation->canApplyTo(*argument_types[0], + *argument_types[1], + static_arguments, + message); + } + default: { + const auto operation_id = + static_cast<std::underlying_type_t<Operation::OperationSuperTypeID>>( + operation->getOperationSuperTypeID()); + LOG(FATAL) << "Unknown opeation super type id: " << operation_id; + } + } +} + + +const OperationFactory& OperationFactory::Instance() { + static OperationFactory instance; + return instance; +} + +template <typename OperationT> +void OperationFactory::registerOperation() { + registerOperationInternal(std::make_shared<const OperationT>()); +} + +template <typename FunctorPackT> +void OperationFactory::registerFunctorPack() { + for (const OperationPtr &operation : + FunctorPackT::template GenerateOperations<FunctorPackDispatcher>()) { + registerOperationInternal(operation); + } +} + +void OperationFactory::registerOperationInternal(const OperationPtr &operation) { + DCHECK(operation->getOperationSuperTypeID() == Operation::kUnaryOperation || + operation->getOperationSuperTypeID() == Operation::kBinaryOperation); + + for (const OperationSignaturePtr op_sig_orig : operation->getSignatures()) { + DCHECK(operation->getOperationSuperTypeID() != Operation::kUnaryOperation || + op_sig_orig->getNonStaticArity() == 1u); + DCHECK(operation->getOperationSuperTypeID() != Operation::kBinaryOperation || + op_sig_orig->getNonStaticArity() == 2u); + + const OperationSignaturePtr op_sig = + OperationSignature::Create(ToLower(op_sig_orig->getName()), + op_sig_orig->getArgumentTypeIDs(), + op_sig_orig->getNumStaticArguments()); + + // TODO: print error message for collision + operations_.emplace(op_sig, operation); + + OperationSecondaryIndices &indices = + primary_index_[std::make_pair(op_sig->getName(), op_sig->getArity())]; + const SignatureReference sig_ref = + std::make_pair(&op_sig->getArgumentTypeIDs(), + op_sig->getNumStaticArguments()); + indices.full_match_index.emplace(sig_ref, op_sig); + indices.non_static_match_index.emplace(sig_ref, op_sig); + indices.signatures.emplace(op_sig); + } +} + + +} // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/operations/OperationFactory.hpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationFactory.hpp b/types/operations/OperationFactory.hpp new file mode 100644 index 0000000..5a73cbd --- /dev/null +++ b/types/operations/OperationFactory.hpp @@ -0,0 +1,205 @@ +/** + * 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_TYPES_OPERATIONS_OPERATION_FACTORY_HPP_ +#define QUICKSTEP_TYPES_OPERATIONS_OPERATION_FACTORY_HPP_ + +#include <memory> +#include <set> +#include <unordered_map> +#include <utility> +#include <vector> + +#include "types/TypeID.hpp" +#include "types/TypedValue.hpp" +#include "types/operations/Operation.hpp" +#include "types/operations/OperationSignature.hpp" +#include "types/operations/binary_operations/BinaryOperation.hpp" +#include "types/operations/unary_operations/UnaryOperation.hpp" +#include "utility/HashPair.hpp" +#include "utility/Macros.hpp" + +#include "glog/logging.h" + +namespace quickstep { + +class Type; + +/** \addtogroup Types + * @{ + */ + +class OperationFactory { + public: + static const OperationFactory& Instance(); + + inline bool hasOperation(const std::string &operation_name, + const std::size_t arity) const { + const auto indices_it = + primary_index_.find(std::make_pair(operation_name, arity)); + return indices_it != primary_index_.end(); + } + + inline OperationPtr getOperation(const OperationSignaturePtr &op_signature) const { + DCHECK(operations_.find(op_signature) != operations_.end()); + return operations_.at(op_signature); + } + + inline UnaryOperationPtr getUnaryOperation( + const OperationSignaturePtr &op_signature) const { + const OperationPtr operation = getOperation(op_signature); + DCHECK(operation->getOperationSuperTypeID() == Operation::kUnaryOperation); + return std::static_pointer_cast<const UnaryOperation>(operation); + } + + inline BinaryOperationPtr getBinaryOperation( + const OperationSignaturePtr &op_signature) const { + const OperationPtr operation = getOperation(op_signature); + DCHECK(operation->getOperationSuperTypeID() == Operation::kBinaryOperation); + return std::static_pointer_cast<const BinaryOperation>(operation); + } + + OperationSignaturePtr resolveOperation( + const std::string &operation_name, + const std::shared_ptr<const std::vector<const Type*>> &argument_types, + const std::shared_ptr<const std::vector<TypedValue>> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + std::string *message) const; + + private: + OperationFactory(); + + template <typename OperationT> + void registerOperation(); + + template <typename FunctorPackT> + void registerFunctorPack(); + + void registerOperationInternal(const OperationPtr &operation); + + using SignatureReference = std::pair<const std::vector<TypeID>*, std::size_t>; + + struct FullSignatureLess { + inline bool operator()(const SignatureReference &lhs, + const SignatureReference &rhs) const { + int cmp_code = static_cast<int>(lhs.first->size()) + - static_cast<int>(lhs.first->size()); + if (cmp_code != 0) { + return cmp_code < 0; + } + for (std::size_t i = 0; i < lhs.first->size(); ++i) { + cmp_code = static_cast<int>(lhs.first->at(i)) + - static_cast<int>(rhs.first->at(i)); + if (cmp_code != 0) { + return cmp_code < 0; + } + } + return lhs.second > rhs.second; + } + }; + using FullSignatureIndex = std::map<SignatureReference, + OperationSignaturePtr, + FullSignatureLess>; + + struct PartialSignatureLess { + inline bool operator()(const SignatureReference &lhs, + const SignatureReference &rhs) const { + const std::size_t l_arity = lhs.first->size() - lhs.second; + const std::size_t r_arity = rhs.first->size() - rhs.second; + int cmp_code = static_cast<int>(l_arity) - static_cast<int>(r_arity); + if (cmp_code != 0) { + return cmp_code < 0; + } + for (std::size_t i = 0; i < l_arity; ++i) { + cmp_code = static_cast<int>(lhs.first->at(i)) + - static_cast<int>(rhs.first->at(i)); + if (cmp_code != 0) { + return cmp_code < 0; + } + } + return lhs.second > rhs.second; + } + }; + using PartialSignatureIndex = std::map<SignatureReference, + OperationSignaturePtr, + PartialSignatureLess>; + + struct OperationSecondaryIndices { + std::set<OperationSignaturePtr> signatures; + FullSignatureIndex full_match_index; + PartialSignatureIndex non_static_match_index; + }; + + enum class ResolveStatus { + kSuccess = 0, + kError, + kNotFound + }; + + ResolveStatus resolveOperationWithFullTypeMatch( + const FullSignatureIndex &full_match_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<TypedValue>> *trimmed_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const; + + ResolveStatus resolveOperationWithPartialTypeMatch( + const PartialSignatureIndex &non_static_match_index, + const std::vector<TypeID> &argument_type_ids, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, + std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, + OperationSignaturePtr *resolved_op_signature, + std::string *message) const; + +// ResolveStatus resolveOperationGeneric( +// const std::set<OperationSignaturePtr> signatures, +// const std::vector<TypeID> &argument_type_ids, +// const std::vector<const Type*> &argument_types, +// const std::vector<TypedValue> &static_arguments, +// std::shared_ptr<const std::vector<const Type*>> *coerced_argument_types, +// std::shared_ptr<const std::vector<TypedValue>> *coerced_static_arguments, +// OperationSignaturePtr *op_signature, +// std::string *message) const; + + bool canApplyOperationTo(const OperationPtr operation, + const std::vector<const Type*> &argument_types, + const std::vector<TypedValue> &static_arguments, + std::string *message) const; + + std::unordered_map<OperationSignaturePtr, + OperationPtr, + OperationSignatureHash, + OperationSignatureEqual> operations_; + + std::unordered_map<std::pair<std::string, std::size_t>, + OperationSecondaryIndices> primary_index_; + + DISALLOW_COPY_AND_ASSIGN(OperationFactory); +}; + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_OPERATIONS_OPERATION_FACTORY_HPP_ http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/operations/OperationSignature.hpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationSignature.hpp b/types/operations/OperationSignature.hpp index 7020e50..b326aef 100644 --- a/types/operations/OperationSignature.hpp +++ b/types/operations/OperationSignature.hpp @@ -86,7 +86,7 @@ class OperationSignature { } cmp_code = static_cast<int>(num_static_arguments_ - r.num_static_arguments_); if (cmp_code != 0) { - return cmp_code < 0; + return cmp_code > 0; } for (std::size_t i = 0; i < getArity(); ++i) { const auto l_tid = http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/4005df6e/types/operations/OperationUtil.hpp ---------------------------------------------------------------------- diff --git a/types/operations/OperationUtil.hpp b/types/operations/OperationUtil.hpp new file mode 100644 index 0000000..076dc0c --- /dev/null +++ b/types/operations/OperationUtil.hpp @@ -0,0 +1,334 @@ +/** + * 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_TYPES_OPERATIONS_OPERATION_UTIL_HPP_ +#define QUICKSTEP_TYPES_OPERATIONS_OPERATION_UTIL_HPP_ + +#include <cstddef> +#include <list> +#include <string> +#include <type_traits> + +#include "catalog/CatalogTypedefs.hpp" +#include "types/Type.hpp" +#include "types/TypedValue.hpp" +#include "types/containers/ColumnVector.hpp" + +namespace quickstep { + +/** \addtogroup Types + * @{ + */ + +template <typename FunctorT, typename ...SpecArgs> +struct FunctorSpecializer { + template <bool specialize = (sizeof...(SpecArgs) != 0), + typename EnableT = void> + struct Implementation; + + typedef Implementation<> type; +}; + +template <typename FunctorT, typename ...SpecArgs> +template <bool specialize> +struct FunctorSpecializer<FunctorT, SpecArgs...> + ::Implementation<specialize, std::enable_if_t<specialize>> { + template <typename ...FuncArgs> + inline static auto Invoke(const FunctorT &functor, FuncArgs &&...args) { + return functor.template apply<SpecArgs...>(std::forward<FuncArgs>(args)...); + } + typedef FunctorT FunctorType; +}; + +template <typename FunctorT, typename ...SpecArgs> +template <bool specialize> +struct FunctorSpecializer<FunctorT, SpecArgs...> + ::Implementation<specialize, std::enable_if_t<!specialize>> { + template <typename ...FuncArgs> + inline static auto Invoke(const FunctorT &functor, FuncArgs &&...args) { + return functor.apply(std::forward<FuncArgs>(args)...); + } + typedef FunctorT FunctorType; +}; + +template <typename ColumnVectorT> +struct ColumnVectorValueAccessor { + explicit ColumnVectorValueAccessor(const ColumnVectorT &column_vector_in) + : column_vector(column_vector_in), + length(column_vector.size()) {} + + inline void beginIteration() { + pos = static_cast<std::size_t>(-1); + } + + inline bool next() { + return (++pos) < length; + } + + inline std::size_t getNumTuples() const { + return length; + } + + template <bool nullable> + inline const void* getUntypedValue(const attribute_id) const { + return column_vector.template getUntypedValue<nullable>(pos); + } + + inline TypedValue getTypedValue(const attribute_id) const { + return column_vector.getTypedValue(pos); + } + + const ColumnVectorT &column_vector; + const std::size_t length; + std::size_t pos; +}; + +template <typename FuncSpec, typename T, typename EnableT = void> +struct Codegen; + +template <typename FuncSpec, typename T> +struct Codegen<FuncSpec, T, std::enable_if_t<T::kLayout == kNativeEmbedded>> { + using ColumnVectorType = NativeColumnVector; + using FunctorSpecializer = FuncSpec; + + using NativeType = typename T::cpptype; + using NativeTypeConst = const typename T::cpptype; + using NativeTypeConstRef = const NativeType&; + using NativeTypeConstPtr = const NativeType*; + + template <typename ArgumentGen> + inline static TypedValue ApplyUnaryTypedValue( + typename ArgumentGen::NativeTypeConstRef argument, + const Type &result_type, + const typename FuncSpec::FunctorType &functor) { + return TypedValue(FuncSpec::Invoke(functor, argument)); + } + + template <typename ArgumentGen> + inline static void ApplyUnaryColumnVector( + const typename ArgumentGen::NativeTypeConstRef argument, + const typename FuncSpec::FunctorType &functor, + ColumnVectorType *cv) { + *static_cast<NativeType *>(cv->getPtrForDirectWrite()) = + FuncSpec::Invoke(functor, argument); + } + + template <typename LeftGen, typename RightGen> + inline static TypedValue ApplyBinaryTypedValue( + typename LeftGen::NativeTypeConstRef left, + typename RightGen::NativeTypeConstRef right, + const Type &result_type, + const typename FuncSpec::FunctorType &functor) { + return TypedValue(FuncSpec::Invoke(functor, left, right)); + } + + template <typename LeftGen, typename RightGen> + inline static void ApplyBinaryColumnVector( + const typename LeftGen::NativeTypeConstRef left, + const typename RightGen::NativeTypeConstRef right, + const typename FuncSpec::FunctorType &functor, + ColumnVectorType *cv) { + *static_cast<NativeType *>(cv->getPtrForDirectWrite()) = + FuncSpec::Invoke(functor, left, right); + } + + template <bool nullable, typename AccessorT> + inline static NativeTypeConstPtr GetValuePtr( + const AccessorT *accessor, + const attribute_id attr_id) { + return static_cast<NativeTypeConstPtr>( + accessor->template getUntypedValue<nullable>(attr_id)); + } + + inline static bool IsNull(const NativeType *value) { + return value == nullptr; + } + + // Dereference: NativeTypeConstPtr& -> const NativeType& + inline static const NativeType& Dereference(const NativeType *value) { + return *value; + } + + inline static const NativeType ToNativeValueConst(const TypedValue &value) { + return value.getLiteral<NativeType>(); + } +}; + +template <typename FuncSpec, typename T> +struct Codegen<FuncSpec, T, std::enable_if_t<T::kLayout == kNonNativeInline>> { + using ColumnVectorType = NativeColumnVector; + using FunctorSpecializer = FuncSpec; + + using NativeType = void*; + using NativeTypeConst = const void*; + using NativeTypeConstRef = const void*; + using NativeTypeConstPtr = const void*; + + template <typename ArgumentGen> + inline static TypedValue ApplyUnaryTypedValue( + typename ArgumentGen::NativeTypeConstRef argument, + const Type &result_type, + const typename FuncSpec::FunctorType &functor) { + void *result = std::malloc(result_type.maximumByteLength()); + FuncSpec::Invoke(functor, argument, result); + return TypedValue::CreateWithOwnedData(T::kStaticTypeID, + result, + result_type.maximumByteLength()); + } + + template <typename ArgumentGen> + inline static void ApplyUnaryColumnVector( + const typename ArgumentGen::NativeTypeConstRef argument, + const typename FuncSpec::FunctorType &functor, + ColumnVectorType *cv) { + FuncSpec::Invoke(functor, argument, cv->getPtrForDirectWrite()); + } + + template <typename LeftGen, typename RightGen> + inline static TypedValue ApplyBinaryTypedValue( + typename LeftGen::NativeTypeConstRef left, + typename RightGen::NativeTypeConstRef right, + const Type &result_type, + const typename FuncSpec::FunctorType &functor) { + void *result = std::malloc(result_type.maximumByteLength()); + FuncSpec::Invoke(functor, left, right, result); + return TypedValue::CreateWithOwnedData(T::kStaticTypeID, + result, + result_type.maximumByteLength()); + } + + template <typename LeftGen, typename RightGen> + inline static void ApplyBinaryColumnVector( + const typename LeftGen::NativeTypeConstRef left, + const typename RightGen::NativeTypeConstRef right, + const typename FuncSpec::FunctorType &functor, + ColumnVectorType *cv) { + FuncSpec::Invoke(functor, left, right, cv->getPtrForDirectWrite()); + } + + template <bool nullable, typename AccessorT> + inline static NativeTypeConstPtr GetValuePtr( + const AccessorT *accessor, + const attribute_id attr_id) { + return accessor->template getUntypedValue<nullable>(attr_id); + } + + inline static bool IsNull(const void *value) { + return value == nullptr; + } + + // Dereference: NativeTypeConstPtr& -> const NativeType& + inline static const void* Dereference(const void *value) { + return value; + } + + inline static const void* ToNativeValueConst(const TypedValue &value) { + return value.getDataPtr(); + } +}; + +template <typename FuncSpec, typename T> +struct Codegen<FuncSpec, T, std::enable_if_t<T::kLayout == kOutOfLine>> { + using ColumnVectorType = IndirectColumnVector; + using FunctorSpecializer = FuncSpec; + + using NativeType = TypedValue; + using NativeTypeConst = const TypedValue; + using NativeTypeConstRef = const TypedValue&; + using NativeTypeConstPtr = const TypedValue; + + template <typename ArgumentGen> + inline static TypedValue ApplyUnaryTypedValue( + typename ArgumentGen::NativeTypeConstRef argument, + const Type &result_type, + const typename FuncSpec::FunctorType &functor) { + return FuncSpec::Invoke(functor, argument); + } + + template <typename ArgumentGen> + inline static void ApplyUnaryColumnVector( + const typename ArgumentGen::NativeTypeConstRef argument, + const typename FuncSpec::FunctorType &functor, + ColumnVectorType *cv) { + cv->appendTypedValue(FuncSpec::Invoke(functor, argument)); + } + + template <typename LeftGen, typename RightGen> + inline static TypedValue ApplyBinaryTypedValue( + typename LeftGen::NativeTypeConstRef left, + typename RightGen::NativeTypeConstRef right, + const Type &result_type, + const typename FuncSpec::FunctorType &functor) { + return FuncSpec::Invoke(functor, left, right); + } + + template <typename LeftGen, typename RightGen> + inline static void ApplyBinaryColumnVector( + const typename LeftGen::NativeTypeConstRef left, + const typename RightGen::NativeTypeConstRef right, + const typename FuncSpec::FunctorType &functor, + ColumnVectorType *cv) { + cv->appendTypedValue(FuncSpec::Invoke(functor, left, right)); + } + + template <bool nullable, typename AccessorT> + inline static NativeTypeConstPtr GetValuePtr( + const AccessorT *accessor, + const attribute_id attr_id) { + return accessor->getTypedValue(attr_id); + } + + inline static bool IsNull(NativeTypeConstPtr &value) { + return value.isNull(); + } + + // Dereference: NativeTypeConstPtr& -> const NativeType& + inline static const NativeType& Dereference(NativeTypeConstPtr &value) { + return value; + } + + inline static const NativeType& ToNativeValueConst(const TypedValue &value) { + return value; + } +}; + +template <typename ...FunctorTypes> +struct FunctorPack { + template <typename Dispatcher> + inline static std::list<OperationPtr> GenerateOperations() { + std::vector<std::list<OperationPtr>> op_list_groups = + { Dispatcher::template Generate<FunctorTypes>()... }; + + std::list<OperationPtr> operations; + for (std::list<OperationPtr> &op_list : op_list_groups) { + operations.splice(operations.end(), std::move(op_list)); + } + return operations; + } +}; + +struct OperationPack { + virtual std::vector<OperationPtr> generateOperations() = 0; +}; + +/** @} */ + +} // namespace quickstep + +#endif // QUICKSTEP_TYPES_OPERATIONS_OPERATION_UTIL_HPP_