http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/case-expr.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/case-expr.cc b/be/src/exprs/case-expr.cc index 6847e82..322c975 100644 --- a/be/src/exprs/case-expr.cc +++ b/be/src/exprs/case-expr.cc @@ -20,8 +20,8 @@ #include "codegen/codegen-anyval.h" #include "codegen/llvm-codegen.h" #include "exprs/anyval-util.h" -#include "exprs/expr-context.h" #include "exprs/conditional-functions.h" +#include "exprs/scalar-expr-evaluator.h" #include "runtime/runtime-state.h" #include "gen-cpp/Exprs_types.h" @@ -35,75 +35,68 @@ namespace impala { struct CaseExprState { // Space to store the values being compared in the interpreted path. This makes it // easier to pass around AnyVal subclasses. Allocated from the runtime state's object - // pool in Prepare(). + // pool in OpenEvaluator(). AnyVal* case_val; AnyVal* when_val; }; CaseExpr::CaseExpr(const TExprNode& node) - : Expr(node), + : ScalarExpr(node), has_case_expr_(node.case_expr.has_case_expr), has_else_expr_(node.case_expr.has_else_expr) { } -Status CaseExpr::Prepare(RuntimeState* state, const RowDescriptor& desc, - ExprContext* ctx) { - RETURN_IF_ERROR(Expr::Prepare(state, desc, ctx)); - RegisterFunctionContext(ctx, state); - return Status::OK(); -} - -Status CaseExpr::Open(RuntimeState* state, ExprContext* ctx, - FunctionContext::FunctionStateScope scope) { - RETURN_IF_ERROR(Expr::Open(state, ctx, scope)); - FunctionContext* fn_ctx = ctx->fn_context(fn_context_index_); +Status CaseExpr::OpenEvaluator(FunctionContext::FunctionStateScope scope, + RuntimeState* state, ScalarExprEvaluator* eval) const { + RETURN_IF_ERROR(ScalarExpr::OpenEvaluator(scope, state, eval)); + DCHECK_GE(fn_ctx_idx_, 0); + FunctionContext* fn_ctx = eval->fn_context(fn_ctx_idx_); CaseExprState* case_state = fn_ctx->Allocate<CaseExprState>(); - if (UNLIKELY(case_state == NULL)) { + if (UNLIKELY(case_state == nullptr)) { DCHECK(!fn_ctx->impl()->state()->GetQueryStatus().ok()); return fn_ctx->impl()->state()->GetQueryStatus(); } fn_ctx->SetFunctionState(FunctionContext::THREAD_LOCAL, case_state); - const ColumnType& case_val_type = has_case_expr_ ? children_[0]->type() : TYPE_BOOLEAN; - RETURN_IF_ERROR(AllocateAnyVal(state, ctx->pool_.get(), case_val_type, + const ColumnType& case_val_type = has_case_expr_ ? GetChild(0)->type() : TYPE_BOOLEAN; + RETURN_IF_ERROR(AllocateAnyVal(state, eval->mem_pool(), case_val_type, "Could not allocate expression value", &case_state->case_val)); const ColumnType& when_val_type = - has_case_expr_ ? children_[1]->type() : children_[0]->type(); - RETURN_IF_ERROR(AllocateAnyVal(state, ctx->pool_.get(), when_val_type, + has_case_expr_ ? GetChild(1)->type() : GetChild(0)->type(); + RETURN_IF_ERROR(AllocateAnyVal(state, eval->mem_pool(), when_val_type, "Could not allocate expression value", &case_state->when_val)); return Status::OK(); } -void CaseExpr::Close(RuntimeState* state, ExprContext* ctx, - FunctionContext::FunctionStateScope scope) { - if (fn_context_index_ != -1) { - FunctionContext* fn_ctx = ctx->fn_context(fn_context_index_); - void* case_state = fn_ctx->GetFunctionState(FunctionContext::THREAD_LOCAL); - fn_ctx->Free(reinterpret_cast<uint8_t*>(case_state)); - fn_ctx->SetFunctionState(FunctionContext::THREAD_LOCAL, nullptr); - } - Expr::Close(state, ctx, scope); +void CaseExpr::CloseEvaluator(FunctionContext::FunctionStateScope scope, + RuntimeState* state, ScalarExprEvaluator* eval) const { + DCHECK_GE(fn_ctx_idx_, 0); + FunctionContext* fn_ctx = eval->fn_context(fn_ctx_idx_); + void* case_state = fn_ctx->GetFunctionState(FunctionContext::THREAD_LOCAL); + fn_ctx->Free(reinterpret_cast<uint8_t*>(case_state)); + fn_ctx->SetFunctionState(FunctionContext::THREAD_LOCAL, nullptr); + ScalarExpr::CloseEvaluator(scope, state, eval); } string CaseExpr::DebugString() const { stringstream out; out << "CaseExpr(has_case_expr=" << has_case_expr_ << " has_else_expr=" << has_else_expr_ - << " " << Expr::DebugString() << ")"; + << " " << ScalarExpr::DebugString() << ")"; return out.str(); } // Sample IR output when there is a case expression and else expression -// define i16 @CaseExpr(%"class.impala::ExprContext"* %context, +// define i16 @CaseExpr(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) #20 { // eval_case_expr: -// %case_val = call i64 @GetSlotRef(%"class.impala::ExprContext"* %context, +// %case_val = call i64 @GetSlotRef(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // %is_null = trunc i64 %case_val to i1 // br i1 %is_null, label %return_else_expr, label %eval_first_when_expr // // eval_first_when_expr: ; preds = %eval_case_expr -// %when_val = call i64 @Literal(%"class.impala::ExprContext"* %context, +// %when_val = call i64 @Literal(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // %is_null1 = trunc i64 %when_val to i1 // br i1 %is_null1, label %return_else_expr, label %check_when_expr_block @@ -117,27 +110,27 @@ string CaseExpr::DebugString() const { // br i1 %eq, label %return_then_expr, label %return_else_expr // // return_then_expr: ; preds = %check_when_expr_block -// %then_val = call i16 @Literal12(%"class.impala::ExprContext"* %context, +// %then_val = call i16 @Literal12(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // ret i16 %then_val // // return_else_expr: ; preds = %check_when_expr_block, %eval_first_when_expr, %eval_case_expr -// %else_val = call i16 @Literal13(%"class.impala::ExprContext"* %context, +// %else_val = call i16 @Literal13(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // ret i16 %else_val // } // // Sample IR output when there is case expression and no else expression -// define i16 @CaseExpr(%"class.impala::ExprContext"* %context, +// define i16 @CaseExpr(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) #20 { // eval_case_expr: -// %case_val = call i64 @GetSlotRef(%"class.impala::ExprContext"* %context, +// %case_val = call i64 @GetSlotRef(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // %is_null = trunc i64 %case_val to i1 // br i1 %is_null, label %return_null, label %eval_first_when_expr // // eval_first_when_expr: ; preds = %eval_case_expr -// %when_val = call i64 @Literal(%"class.impala::ExprContext"* %context, +// %when_val = call i64 @Literal(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // %is_null1 = trunc i64 %when_val to i1 // br i1 %is_null1, label %return_null, label %check_when_expr_block @@ -151,7 +144,7 @@ string CaseExpr::DebugString() const { // br i1 %eq, label %return_then_expr, label %return_null // // return_then_expr: ; preds = %check_when_expr_block -// %then_val = call i16 @Literal12(%"class.impala::ExprContext"* %context, +// %then_val = call i16 @Literal12(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // ret i16 %then_val // @@ -160,11 +153,11 @@ string CaseExpr::DebugString() const { // } // // Sample IR output when there is no case expr and else expression -// define i16 @CaseExpr(%"class.impala::ExprContext"* %context, +// define i16 @CaseExpr(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) #20 { // eval_first_when_expr: // %when_val = call i16 @Eq_IntVal_IntValWrapper1( -// %"class.impala::ExprContext"* %context, %"class.impala::TupleRow"* %row) +// %"class.impala::ScalarExprEvaluator"* %context, %"class.impala::TupleRow"* %row) // %is_null = trunc i16 %when_val to i1 // br i1 %is_null, label %return_else_expr, label %check_when_expr_block // @@ -175,17 +168,17 @@ string CaseExpr::DebugString() const { // br i1 %val, label %return_then_expr, label %return_else_expr // // return_then_expr: ; preds = %check_when_expr_block -// %then_val = call i16 @Literal14(%"class.impala::ExprContext"* %context, +// %then_val = call i16 @Literal14(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // ret i16 %then_val // // return_else_expr: ; preds = %check_when_expr_block, %eval_first_when_expr -// %else_val = call i16 @Literal15(%"class.impala::ExprContext"* %context, +// %else_val = call i16 @Literal15(%"class.impala::ScalarExprEvaluator"* %context, // %"class.impala::TupleRow"* %row) // ret i16 %else_val // } Status CaseExpr::GetCodegendComputeFn(LlvmCodeGen* codegen, Function** fn) { - if (ir_compute_fn_ != NULL) { + if (ir_compute_fn_ != nullptr) { *fn = ir_compute_fn_; return Status::OK(); } @@ -193,15 +186,15 @@ Status CaseExpr::GetCodegendComputeFn(LlvmCodeGen* codegen, Function** fn) { const int num_children = GetNumChildren(); Function* child_fns[num_children]; for (int i = 0; i < num_children; ++i) { - RETURN_IF_ERROR(children()[i]->GetCodegendComputeFn(codegen, &child_fns[i])); + RETURN_IF_ERROR(GetChild(i)->GetCodegendComputeFn(codegen, &child_fns[i])); } LLVMContext& context = codegen->context(); LlvmBuilder builder(context); Value* args[2]; - Function* function = CreateIrFunctionPrototype(codegen, "CaseExpr", &args); - BasicBlock* eval_case_expr_block = NULL; + Function* function = CreateIrFunctionPrototype("CaseExpr", codegen, &args); + BasicBlock* eval_case_expr_block = nullptr; // This is the block immediately after the when/then exprs. It will either point to a // block which returns the else expr, or returns NULL if no else expr is specified. @@ -215,7 +208,7 @@ Status CaseExpr::GetCodegendComputeFn(LlvmCodeGen* codegen, Function** fn) { BasicBlock* current_when_expr_block = eval_first_when_expr_block; if (has_case_expr()) { // Need at least case, when and then expr, and optionally an else expr - DCHECK_GE(num_children, (has_else_expr()) ? 4 : 3); + DCHECK_GE(num_children, has_else_expr() ? 4 : 3); // If there is a case expr, create block eval_case_expr to evaluate the // case expr. Place this block before eval_first_when_expr_block eval_case_expr_block = BasicBlock::Create(context, "eval_case_expr", @@ -226,15 +219,15 @@ Status CaseExpr::GetCodegendComputeFn(LlvmCodeGen* codegen, Function** fn) { builder.CreateCondBr( case_val.GetIsNull(), default_value_block, eval_first_when_expr_block); } else { - DCHECK_GE(num_children, (has_else_expr()) ? 3 : 2); + DCHECK_GE(num_children, has_else_expr() ? 3 : 2); } - const int loop_end = (has_else_expr()) ? num_children - 1 : num_children; + const int loop_end = has_else_expr() ? num_children - 1 : num_children; const int last_loop_iter = loop_end - 2; // The loop increments by two each time, because each iteration handles one when/then // pair. Both when and then subexpressions are single children. If there is a case expr - // start loop at index 1. (case expr is children()[0] and has already be evaluated. - for (int i = (has_case_expr()) ? 1 : 0; i < loop_end; i += 2) { + // start loop at index 1. (case expr is GetChild(0) and has already be evaluated. + for (int i = has_case_expr() ? 1 : 0; i < loop_end; i += 2) { BasicBlock* check_when_expr_block = BasicBlock::Create( context, "check_when_expr_block", function, default_value_block); BasicBlock* return_then_expr_block = @@ -242,7 +235,7 @@ Status CaseExpr::GetCodegendComputeFn(LlvmCodeGen* codegen, Function** fn) { // continue_or_exit_block either points to the next eval_next_when_expr block, // or points to the defaut_value_block if there are no more when/then expressions. - BasicBlock* continue_or_exit_block = NULL; + BasicBlock* continue_or_exit_block = nullptr; if (i == last_loop_iter) { continue_or_exit_block = default_value_block; } else { @@ -254,7 +247,7 @@ Status CaseExpr::GetCodegendComputeFn(LlvmCodeGen* codegen, Function** fn) { // statement builder.SetInsertPoint(current_when_expr_block); CodegenAnyVal when_val = CodegenAnyVal::CreateCallWrapped( - codegen, &builder, children()[i]->type(), child_fns[i], args, "when_val"); + codegen, &builder, GetChild(i)->type(), child_fns[i], args, "when_val"); builder.CreateCondBr( when_val.GetIsNull(), continue_or_exit_block, check_when_expr_block); @@ -286,53 +279,53 @@ Status CaseExpr::GetCodegendComputeFn(LlvmCodeGen* codegen, Function** fn) { } else { builder.CreateRet(CodegenAnyVal::GetNullVal(codegen, type())); } - *fn = codegen->FinalizeFunction(function); - DCHECK(*fn != NULL); + if (UNLIKELY(*fn == nullptr)) return Status(TErrorCode::IR_VERIFY_FAILED, "CaseExpr"); ir_compute_fn_ = *fn; return Status::OK(); } -void CaseExpr::GetChildVal(int child_idx, ExprContext* ctx, const TupleRow* row, AnyVal* dst) { - switch (children()[child_idx]->type().type) { +void CaseExpr::GetChildVal(int child_idx, ScalarExprEvaluator* eval, + const TupleRow* row, AnyVal* dst) const { + ScalarExpr* child = GetChild(child_idx); + switch (child->type().type) { case TYPE_BOOLEAN: - *reinterpret_cast<BooleanVal*>(dst) = children()[child_idx]->GetBooleanVal(ctx, row); + *reinterpret_cast<BooleanVal*>(dst) = child->GetBooleanVal(eval, row); break; case TYPE_TINYINT: - *reinterpret_cast<TinyIntVal*>(dst) = children()[child_idx]->GetTinyIntVal(ctx, row); + *reinterpret_cast<TinyIntVal*>(dst) = child->GetTinyIntVal(eval, row); break; case TYPE_SMALLINT: - *reinterpret_cast<SmallIntVal*>(dst) = - children()[child_idx]->GetSmallIntVal(ctx, row); + *reinterpret_cast<SmallIntVal*>(dst) = child->GetSmallIntVal(eval, row); break; case TYPE_INT: - *reinterpret_cast<IntVal*>(dst) = children()[child_idx]->GetIntVal(ctx, row); + *reinterpret_cast<IntVal*>(dst) = child->GetIntVal(eval, row); break; case TYPE_BIGINT: - *reinterpret_cast<BigIntVal*>(dst) = children()[child_idx]->GetBigIntVal(ctx, row); + *reinterpret_cast<BigIntVal*>(dst) = child->GetBigIntVal(eval, row); break; case TYPE_FLOAT: - *reinterpret_cast<FloatVal*>(dst) = children()[child_idx]->GetFloatVal(ctx, row); + *reinterpret_cast<FloatVal*>(dst) = child->GetFloatVal(eval, row); break; case TYPE_DOUBLE: - *reinterpret_cast<DoubleVal*>(dst) = children()[child_idx]->GetDoubleVal(ctx, row); + *reinterpret_cast<DoubleVal*>(dst) = child->GetDoubleVal(eval, row); break; case TYPE_TIMESTAMP: - *reinterpret_cast<TimestampVal*>(dst) = - children()[child_idx]->GetTimestampVal(ctx, row); + *reinterpret_cast<TimestampVal*>(dst) = child->GetTimestampVal(eval, row); break; case TYPE_STRING: - *reinterpret_cast<StringVal*>(dst) = children()[child_idx]->GetStringVal(ctx, row); + *reinterpret_cast<StringVal*>(dst) = child->GetStringVal(eval, row); break; case TYPE_DECIMAL: - *reinterpret_cast<DecimalVal*>(dst) = children()[child_idx]->GetDecimalVal(ctx, row); + *reinterpret_cast<DecimalVal*>(dst) = child->GetDecimalVal(eval, row); break; default: - DCHECK(false) << children()[child_idx]->type(); + DCHECK(false) << child->type(); } } -bool CaseExpr::AnyValEq(const ColumnType& type, const AnyVal* v1, const AnyVal* v2) { +bool CaseExpr::AnyValEq( + const ColumnType& type, const AnyVal* v1, const AnyVal* v2) const { switch (type.type) { case TYPE_BOOLEAN: return AnyValUtil::Equals(type, *reinterpret_cast<const BooleanVal*>(v1), @@ -371,17 +364,19 @@ bool CaseExpr::AnyValEq(const ColumnType& type, const AnyVal* v1, const AnyVal* } #define CASE_COMPUTE_FN(THEN_TYPE) \ - THEN_TYPE CaseExpr::Get##THEN_TYPE(ExprContext* ctx, const TupleRow* row) { \ - FunctionContext* fn_ctx = ctx->fn_context(fn_context_index_); \ + THEN_TYPE CaseExpr::Get##THEN_TYPE( \ + ScalarExprEvaluator* eval, const TupleRow* row) const { \ + DCHECK(eval->opened()); \ + FunctionContext* fn_ctx = eval->fn_context(fn_ctx_idx_); \ CaseExprState* state = reinterpret_cast<CaseExprState*>( \ fn_ctx->GetFunctionState(FunctionContext::THREAD_LOCAL)); \ - DCHECK(state->case_val != NULL); \ - DCHECK(state->when_val != NULL); \ + DCHECK(state->case_val != nullptr); \ + DCHECK(state->when_val != nullptr); \ int num_children = GetNumChildren(); \ if (has_case_expr()) { \ /* All case and when exprs return the same type */ \ /* (we guaranteed that during analysis). */ \ - GetChildVal(0, ctx, row, state->case_val); \ + GetChildVal(0, eval, row, state->case_val); \ } else { \ /* If there's no case expression, compare the when values to "true". */ \ *reinterpret_cast<BooleanVal*>(state->case_val) = BooleanVal(true); \ @@ -389,7 +384,7 @@ bool CaseExpr::AnyValEq(const ColumnType& type, const AnyVal* v1, const AnyVal* if (state->case_val->is_null) { \ if (has_else_expr()) { \ /* Return else value. */ \ - return children()[num_children - 1]->Get##THEN_TYPE(ctx, row); \ + return children()[num_children - 1]->Get##THEN_TYPE(eval, row); \ } else { \ return THEN_TYPE::null(); \ } \ @@ -397,16 +392,16 @@ bool CaseExpr::AnyValEq(const ColumnType& type, const AnyVal* v1, const AnyVal* int loop_start = has_case_expr() ? 1 : 0; \ int loop_end = (has_else_expr()) ? num_children - 1 : num_children; \ for (int i = loop_start; i < loop_end; i += 2) { \ - GetChildVal(i, ctx, row, state->when_val); \ + GetChildVal(i, eval, row, state->when_val); \ if (state->when_val->is_null) continue; \ - if (AnyValEq(children()[0]->type(), state->case_val, state->when_val)) { \ + if (AnyValEq(children()[0]->type(), state->case_val, state->when_val)) { \ /* Return then value. */ \ - return children()[i + 1]->Get##THEN_TYPE(ctx, row); \ + return GetChild(i + 1)->Get##THEN_TYPE(eval, row); \ } \ } \ if (has_else_expr()) { \ /* Return else value. */ \ - return children()[num_children - 1]->Get##THEN_TYPE(ctx, row); \ + return GetChild(num_children - 1)->Get##THEN_TYPE(eval, row); \ } \ return THEN_TYPE::null(); \ }
http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/case-expr.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/case-expr.h b/be/src/exprs/case-expr.h index a59f5c2..a70b44f 100644 --- a/be/src/exprs/case-expr.h +++ b/be/src/exprs/case-expr.h @@ -20,46 +20,61 @@ #define IMPALA_EXPRS_CASE_EXPR_H_ #include <string> -#include "expr.h" - -using namespace impala_udf; +#include "scalar-expr.h" namespace impala { +using impala_udf::FunctionContext; +using impala_udf::AnyVal; +using impala_udf::BooleanVal; +using impala_udf::TinyIntVal; +using impala_udf::SmallIntVal; +using impala_udf::IntVal; +using impala_udf::BigIntVal; +using impala_udf::FloatVal; +using impala_udf::DoubleVal; +using impala_udf::TimestampVal; +using impala_udf::StringVal; +using impala_udf::DecimalVal; + +class ScalarExprEvaluator; class TExprNode; -class CaseExpr: public Expr { +class CaseExpr: public ScalarExpr { public: - virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn); - - virtual BooleanVal GetBooleanVal(ExprContext* ctx, const TupleRow* row); - virtual TinyIntVal GetTinyIntVal(ExprContext* ctx, const TupleRow* row); - virtual SmallIntVal GetSmallIntVal(ExprContext* ctx, const TupleRow* row); - virtual IntVal GetIntVal(ExprContext* ctx, const TupleRow* row); - virtual BigIntVal GetBigIntVal(ExprContext* ctx, const TupleRow* row); - virtual FloatVal GetFloatVal(ExprContext* ctx, const TupleRow* row); - virtual DoubleVal GetDoubleVal(ExprContext* ctx, const TupleRow* row); - virtual StringVal GetStringVal(ExprContext* ctx, const TupleRow* row); - virtual TimestampVal GetTimestampVal(ExprContext* ctx, const TupleRow* row); - virtual DecimalVal GetDecimalVal(ExprContext* ctx, const TupleRow* row); + virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn) + override WARN_UNUSED_RESULT; + virtual std::string DebugString() const override; protected: - friend class Expr; + friend class ScalarExpr; friend class ConditionalFunctions; - friend class DecimalOperators; - - CaseExpr(const TExprNode& node); - virtual Status Prepare(RuntimeState* state, const RowDescriptor& row_desc, - ExprContext* context); - virtual Status Open(RuntimeState* state, ExprContext* context, - FunctionContext::FunctionStateScope scope = FunctionContext::FRAGMENT_LOCAL); - virtual void Close(RuntimeState* state, ExprContext* context, - FunctionContext::FunctionStateScope scope = FunctionContext::FRAGMENT_LOCAL); - virtual std::string DebugString() const; + virtual bool HasFnCtx() const override { return true; } - bool has_case_expr() { return has_case_expr_; } - bool has_else_expr() { return has_else_expr_; } + CaseExpr(const TExprNode& node); + virtual Status OpenEvaluator(FunctionContext::FunctionStateScope scope, + RuntimeState* state, ScalarExprEvaluator* eval) + const override WARN_UNUSED_RESULT; + virtual void CloseEvaluator(FunctionContext::FunctionStateScope scope, + RuntimeState* state, ScalarExprEvaluator* eval) + const override; + + virtual BooleanVal GetBooleanVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TinyIntVal GetTinyIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual SmallIntVal GetSmallIntVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual IntVal GetIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual BigIntVal GetBigIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual FloatVal GetFloatVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual DoubleVal GetDoubleVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual StringVal GetStringVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TimestampVal GetTimestampVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual DecimalVal GetDecimalVal(ScalarExprEvaluator*, const TupleRow*) const override; + + bool has_case_expr() const { return has_case_expr_; } + bool has_else_expr() const { return has_else_expr_; } private: const bool has_case_expr_; @@ -67,10 +82,11 @@ class CaseExpr: public Expr { /// Populates 'dst' with the result of calling the appropriate Get*Val() function on the /// specified child expr. - void GetChildVal(int child_idx, ExprContext* ctx, const TupleRow* row, AnyVal* dst); + void GetChildVal(int child_idx, ScalarExprEvaluator* eval, + const TupleRow* row, AnyVal* dst) const; /// Return true iff *v1 == *v2. v1 and v2 should both be of the specified type. - bool AnyValEq(const ColumnType& type, const AnyVal* v1, const AnyVal* v2); + bool AnyValEq(const ColumnType& type, const AnyVal* v1, const AnyVal* v2) const; }; } http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/cast-functions.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/cast-functions.h b/be/src/exprs/cast-functions.h index bdbbb93..f5389ce 100644 --- a/be/src/exprs/cast-functions.h +++ b/be/src/exprs/cast-functions.h @@ -21,10 +21,21 @@ #include "udf/udf.h" -using namespace impala_udf; - namespace impala { +using impala_udf::FunctionContext; +using impala_udf::AnyVal; +using impala_udf::BooleanVal; +using impala_udf::TinyIntVal; +using impala_udf::SmallIntVal; +using impala_udf::IntVal; +using impala_udf::BigIntVal; +using impala_udf::FloatVal; +using impala_udf::DoubleVal; +using impala_udf::TimestampVal; +using impala_udf::StringVal; +using impala_udf::DecimalVal; + class CastFunctions { public: static BooleanVal CastToBooleanVal(FunctionContext* context, const TinyIntVal& val); http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/compound-predicates.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/compound-predicates.cc b/be/src/exprs/compound-predicates.cc index d367e5a..2474995 100644 --- a/be/src/exprs/compound-predicates.cc +++ b/be/src/exprs/compound-predicates.cc @@ -28,12 +28,13 @@ using namespace impala; using namespace llvm; // (<> && false) is false, (true && NULL) is NULL -BooleanVal AndPredicate::GetBooleanVal(ExprContext* context, const TupleRow* row) { +BooleanVal AndPredicate::GetBooleanVal(ScalarExprEvaluator* eval, + const TupleRow* row) const { DCHECK_EQ(children_.size(), 2); - BooleanVal val1 = children_[0]->GetBooleanVal(context, row); + BooleanVal val1 = children_[0]->GetBooleanVal(eval, row); if (!val1.is_null && !val1.val) return BooleanVal(false); // short-circuit - BooleanVal val2 = children_[1]->GetBooleanVal(context, row); + BooleanVal val2 = children_[1]->GetBooleanVal(eval, row); if (!val2.is_null && !val2.val) return BooleanVal(false); if (val1.is_null || val2.is_null) return BooleanVal::null(); @@ -42,17 +43,18 @@ BooleanVal AndPredicate::GetBooleanVal(ExprContext* context, const TupleRow* row string AndPredicate::DebugString() const { stringstream out; - out << "AndPredicate(" << Expr::DebugString() << ")"; + out << "AndPredicate(" << ScalarExpr::DebugString() << ")"; return out.str(); } // (<> || true) is true, (false || NULL) is NULL -BooleanVal OrPredicate::GetBooleanVal(ExprContext* context, const TupleRow* row) { +BooleanVal OrPredicate::GetBooleanVal(ScalarExprEvaluator* eval, + const TupleRow* row) const { DCHECK_EQ(children_.size(), 2); - BooleanVal val1 = children_[0]->GetBooleanVal(context, row); + BooleanVal val1 = children_[0]->GetBooleanVal(eval, row); if (!val1.is_null && val1.val) return BooleanVal(true); // short-circuit - BooleanVal val2 = children_[1]->GetBooleanVal(context, row); + BooleanVal val2 = children_[1]->GetBooleanVal(eval, row); if (!val2.is_null && val2.val) return BooleanVal(true); if (val1.is_null || val2.is_null) return BooleanVal::null(); @@ -61,7 +63,7 @@ BooleanVal OrPredicate::GetBooleanVal(ExprContext* context, const TupleRow* row) string OrPredicate::DebugString() const { stringstream out; - out << "OrPredicate(" << Expr::DebugString() << ")"; + out << "OrPredicate(" << ScalarExpr::DebugString() << ")"; return out.str(); } @@ -69,13 +71,14 @@ string OrPredicate::DebugString() const { // null handling as well as many branches so this is pretty complicated. The IR // for x && y is: // -// define i16 @CompoundPredicate(%"class.impala::ExprContext"* %context, +// define i16 @CompoundPredicate(%"class.impala::ScalarExprEvaluator"* %eval, // %"class.impala::TupleRow"* %row) #20 { // entry: -// %lhs_call = call i16 @GetSlotRef1(%"class.impala::ExprContext"* %context, +// %lhs_call = call i16 @GetSlotRef1(%"class.impala::ScalarExprEvaluator"* %eval, // %"class.impala::TupleRow"* %row) -// %rhs_call = call i16 @Eq_IntVal_IntValWrapper(%"class.impala::ExprContext"* %context, -// %"class.impala::TupleRow"* %row) +// %rhs_call = call i16 @Eq_IntVal_IntValWrapper( +// %"class.impala::ScalarExprEvaluator"* %eval, +// %"class.impala::TupleRow"* %row) // %is_null = trunc i16 %lhs_call to i1 // %is_null1 = trunc i16 %rhs_call to i1 // %0 = ashr i16 %lhs_call, 8 @@ -133,7 +136,7 @@ Status CompoundPredicate::CodegenComputeFn( LLVMContext& context = codegen->context(); LlvmBuilder builder(context); Value* args[2]; - Function* function = CreateIrFunctionPrototype(codegen, "CompoundPredicate", &args); + Function* function = CreateIrFunctionPrototype("CompoundPredicate", codegen, &args); BasicBlock* entry_block = BasicBlock::Create(context, "entry", function); builder.SetInsertPoint(entry_block); http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/compound-predicates.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/compound-predicates.h b/be/src/exprs/compound-predicates.h index cafc30c..1b64208 100644 --- a/be/src/exprs/compound-predicates.h +++ b/be/src/exprs/compound-predicates.h @@ -23,10 +23,11 @@ #include "exprs/predicate.h" #include "gen-cpp/Exprs_types.h" -using namespace impala_udf; - namespace impala { +using impala_udf::FunctionContext; +using impala_udf::BooleanVal; + class CompoundPredicate: public Predicate { public: static BooleanVal Not(FunctionContext* context, const BooleanVal&); @@ -40,14 +41,14 @@ class CompoundPredicate: public Predicate { /// Expr for evaluating and (&&) operators class AndPredicate: public CompoundPredicate { public: - virtual impala_udf::BooleanVal GetBooleanVal(ExprContext* context, const TupleRow*); + virtual BooleanVal GetBooleanVal(ScalarExprEvaluator*, const TupleRow*) const; virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn) { return CompoundPredicate::CodegenComputeFn(true, codegen, fn); } protected: - friend class Expr; + friend class ScalarExpr; AndPredicate(const TExprNode& node) : CompoundPredicate(node) { } virtual std::string DebugString() const; @@ -59,14 +60,14 @@ class AndPredicate: public CompoundPredicate { /// Expr for evaluating or (||) operators class OrPredicate: public CompoundPredicate { public: - virtual impala_udf::BooleanVal GetBooleanVal(ExprContext* context, const TupleRow*); + virtual BooleanVal GetBooleanVal(ScalarExprEvaluator*, const TupleRow*) const; virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn) { return CompoundPredicate::CodegenComputeFn(false, codegen, fn); } protected: - friend class Expr; + friend class ScalarExpr; OrPredicate(const TExprNode& node) : CompoundPredicate(node) { } virtual std::string DebugString() const; http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/conditional-functions-ir.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/conditional-functions-ir.cc b/be/src/exprs/conditional-functions-ir.cc index 662f167..d984c90 100644 --- a/be/src/exprs/conditional-functions-ir.cc +++ b/be/src/exprs/conditional-functions-ir.cc @@ -17,17 +17,19 @@ #include "exprs/anyval-util.h" #include "exprs/conditional-functions.h" +#include "exprs/scalar-expr-evaluator.h" #include "udf/udf.h" using namespace impala; using namespace impala_udf; #define IS_NULL_COMPUTE_FUNCTION(type) \ - type IsNullExpr::Get##type(ExprContext* ctx, const TupleRow* row) { \ + type IsNullExpr::Get##type( \ + ScalarExprEvaluator* eval, const TupleRow* row) const { \ DCHECK_EQ(children_.size(), 2); \ - type val = children_[0]->Get##type(ctx, row); \ + type val = GetChild(0)->Get##type(eval, row); \ if (!val.is_null) return val; /* short-circuit */ \ - return children_[1]->Get##type(ctx, row); \ + return GetChild(1)->Get##type(eval, row); \ } IS_NULL_COMPUTE_FUNCTION(BooleanVal); @@ -42,16 +44,17 @@ IS_NULL_COMPUTE_FUNCTION(TimestampVal); IS_NULL_COMPUTE_FUNCTION(DecimalVal); #define NULL_IF_COMPUTE_FUNCTION(AnyValType) \ - AnyValType NullIfExpr::Get##AnyValType(ExprContext* ctx, const TupleRow* row) { \ + AnyValType NullIfExpr::Get##AnyValType(ScalarExprEvaluator* eval, \ + const TupleRow* row) const { \ DCHECK_EQ(children_.size(), 2); \ - AnyValType lhs_val = children_[0]->Get##AnyValType(ctx, row); \ + AnyValType lhs_val = GetChild(0)->Get##AnyValType(eval, row); \ /* Short-circuit in case lhs_val is NULL. Can never be equal to RHS. */ \ if (lhs_val.is_null) return AnyValType::null(); \ /* Get rhs and return NULL if lhs == rhs, lhs otherwise */ \ - AnyValType rhs_val = children_[1]->Get##AnyValType(ctx, row); \ + AnyValType rhs_val = GetChild(1)->Get##AnyValType(eval, row); \ if (!rhs_val.is_null && \ - AnyValUtil::Equals(children_[0]->type(), lhs_val, rhs_val)) { \ - return AnyValType::null(); \ + AnyValUtil::Equals(GetChild(0)->type(), lhs_val, rhs_val)) { \ + return AnyValType::null(); \ } \ return lhs_val; \ } @@ -114,13 +117,13 @@ ZERO_IF_NULL_COMPUTE_FUNCTION(DoubleVal); ZERO_IF_NULL_COMPUTE_FUNCTION(DecimalVal); #define IF_COMPUTE_FUNCTION(type) \ - type IfExpr::Get##type(ExprContext* ctx, const TupleRow* row) { \ + type IfExpr::Get##type(ScalarExprEvaluator* eval, const TupleRow* row) const { \ DCHECK_EQ(children_.size(), 3); \ - BooleanVal cond = children_[0]->GetBooleanVal(ctx, row); \ + BooleanVal cond = GetChild(0)->GetBooleanVal(eval, row); \ if (cond.is_null || !cond.val) { \ - return children_[2]->Get##type(ctx, row); \ + return GetChild(2)->Get##type(eval, row); \ } \ - return children_[1]->Get##type(ctx, row); \ + return GetChild(1)->Get##type(eval, row); \ } IF_COMPUTE_FUNCTION(BooleanVal); @@ -135,10 +138,11 @@ IF_COMPUTE_FUNCTION(TimestampVal); IF_COMPUTE_FUNCTION(DecimalVal); #define COALESCE_COMPUTE_FUNCTION(type) \ - type CoalesceExpr::Get##type(ExprContext* ctx, const TupleRow* row) { \ + type CoalesceExpr::Get##type( \ + ScalarExprEvaluator* eval, const TupleRow* row) const { \ DCHECK_GE(children_.size(), 1); \ - for (int i = 0; i < children_.size(); ++i) { \ - type val = children_[i]->Get##type(ctx, row); \ + for (int i = 0; i < children_.size(); ++i) { \ + type val = GetChild(i)->Get##type(eval, row); \ if (!val.is_null) return val; \ } \ return type::null(); \ http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/conditional-functions.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/conditional-functions.h b/be/src/exprs/conditional-functions.h index 12c9b1e..28d0b53 100644 --- a/be/src/exprs/conditional-functions.h +++ b/be/src/exprs/conditional-functions.h @@ -21,13 +21,25 @@ #include <stdint.h> -#include "exprs/expr.h" +#include "exprs/scalar-expr.h" #include "udf/udf.h" -using namespace impala_udf; - namespace impala { +using impala_udf::FunctionContext; +using impala_udf::AnyVal; +using impala_udf::BooleanVal; +using impala_udf::TinyIntVal; +using impala_udf::SmallIntVal; +using impala_udf::IntVal; +using impala_udf::BigIntVal; +using impala_udf::FloatVal; +using impala_udf::DoubleVal; +using impala_udf::TimestampVal; +using impala_udf::StringVal; +using impala_udf::DecimalVal; + +class ScalarExprEvaluator; class TupleRow; /// Conditional functions that can be expressed as UDFs @@ -60,88 +72,112 @@ class ConditionalFunctions { /// The following conditional functions require separate Expr classes to take advantage of /// short circuiting -class IsNullExpr : public Expr { +class IsNullExpr : public ScalarExpr { public: - virtual BooleanVal GetBooleanVal(ExprContext* context, const TupleRow* row); - virtual TinyIntVal GetTinyIntVal(ExprContext* context, const TupleRow* row); - virtual SmallIntVal GetSmallIntVal(ExprContext* context, const TupleRow* row); - virtual IntVal GetIntVal(ExprContext* context, const TupleRow* row); - virtual BigIntVal GetBigIntVal(ExprContext* context, const TupleRow* row); - virtual FloatVal GetFloatVal(ExprContext* context, const TupleRow* row); - virtual DoubleVal GetDoubleVal(ExprContext* context, const TupleRow* row); - virtual StringVal GetStringVal(ExprContext* context, const TupleRow* row); - virtual TimestampVal GetTimestampVal(ExprContext* context, const TupleRow* row); - virtual DecimalVal GetDecimalVal(ExprContext* context, const TupleRow* row); - - virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn); - virtual std::string DebugString() const { return Expr::DebugString("IsNullExpr"); } + virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn) + override WARN_UNUSED_RESULT; + virtual std::string DebugString() const override { + return ScalarExpr::DebugString("IsNullExpr"); + } protected: - friend class Expr; - IsNullExpr(const TExprNode& node) : Expr(node) { } + friend class ScalarExpr; + friend class ScalarExprEvaluator; + + IsNullExpr(const TExprNode& node) : ScalarExpr(node) { } + virtual BooleanVal GetBooleanVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TinyIntVal GetTinyIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual SmallIntVal GetSmallIntVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual IntVal GetIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual BigIntVal GetBigIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual FloatVal GetFloatVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual DoubleVal GetDoubleVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual StringVal GetStringVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TimestampVal GetTimestampVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual DecimalVal GetDecimalVal(ScalarExprEvaluator*, const TupleRow*) const override; }; -class NullIfExpr : public Expr { +class NullIfExpr : public ScalarExpr { public: - virtual BooleanVal GetBooleanVal(ExprContext* context, const TupleRow* row); - virtual TinyIntVal GetTinyIntVal(ExprContext* context, const TupleRow* row); - virtual SmallIntVal GetSmallIntVal(ExprContext* context, const TupleRow* row); - virtual IntVal GetIntVal(ExprContext* context, const TupleRow* row); - virtual BigIntVal GetBigIntVal(ExprContext* context, const TupleRow* row); - virtual FloatVal GetFloatVal(ExprContext* context, const TupleRow* row); - virtual DoubleVal GetDoubleVal(ExprContext* context, const TupleRow* row); - virtual StringVal GetStringVal(ExprContext* context, const TupleRow* row); - virtual TimestampVal GetTimestampVal(ExprContext* context, const TupleRow* row); - virtual DecimalVal GetDecimalVal(ExprContext* context, const TupleRow* row); - - virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn); - virtual std::string DebugString() const { return Expr::DebugString("NullIfExpr"); } + virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn) + override WARN_UNUSED_RESULT; + virtual std::string DebugString() const override { + return ScalarExpr::DebugString("NullIfExpr"); + } protected: - friend class Expr; - NullIfExpr(const TExprNode& node) : Expr(node) { } + friend class ScalarExpr; + friend class ScalarExprEvaluator; + + NullIfExpr(const TExprNode& node) : ScalarExpr(node) { } + virtual BooleanVal GetBooleanVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TinyIntVal GetTinyIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual SmallIntVal GetSmallIntVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual IntVal GetIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual BigIntVal GetBigIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual FloatVal GetFloatVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual DoubleVal GetDoubleVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual StringVal GetStringVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TimestampVal GetTimestampVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual DecimalVal GetDecimalVal(ScalarExprEvaluator*, const TupleRow*) const override; }; -class IfExpr : public Expr { +class IfExpr : public ScalarExpr { public: - virtual BooleanVal GetBooleanVal(ExprContext* context, const TupleRow* row); - virtual TinyIntVal GetTinyIntVal(ExprContext* context, const TupleRow* row); - virtual SmallIntVal GetSmallIntVal(ExprContext* context, const TupleRow* row); - virtual IntVal GetIntVal(ExprContext* context, const TupleRow* row); - virtual BigIntVal GetBigIntVal(ExprContext* context, const TupleRow* row); - virtual FloatVal GetFloatVal(ExprContext* context, const TupleRow* row); - virtual DoubleVal GetDoubleVal(ExprContext* context, const TupleRow* row); - virtual StringVal GetStringVal(ExprContext* context, const TupleRow* row); - virtual TimestampVal GetTimestampVal(ExprContext* context, const TupleRow* row); - virtual DecimalVal GetDecimalVal(ExprContext* context, const TupleRow* row); - - virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn); - virtual std::string DebugString() const { return Expr::DebugString("IfExpr"); } + virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn) + override WARN_UNUSED_RESULT; + virtual std::string DebugString() const override { + return ScalarExpr::DebugString("IfExpr"); + } protected: - friend class Expr; - IfExpr(const TExprNode& node) : Expr(node) { } + friend class ScalarExpr; + friend class ScalarExprEvaluator; + + IfExpr(const TExprNode& node) : ScalarExpr(node) { } + virtual BooleanVal GetBooleanVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TinyIntVal GetTinyIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual SmallIntVal GetSmallIntVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual IntVal GetIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual BigIntVal GetBigIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual FloatVal GetFloatVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual DoubleVal GetDoubleVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual StringVal GetStringVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TimestampVal GetTimestampVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual DecimalVal GetDecimalVal(ScalarExprEvaluator*, const TupleRow*) const override; }; -class CoalesceExpr : public Expr { +class CoalesceExpr : public ScalarExpr { public: - virtual BooleanVal GetBooleanVal(ExprContext* context, const TupleRow* row); - virtual TinyIntVal GetTinyIntVal(ExprContext* context, const TupleRow* row); - virtual SmallIntVal GetSmallIntVal(ExprContext* context, const TupleRow* row); - virtual IntVal GetIntVal(ExprContext* context, const TupleRow* row); - virtual BigIntVal GetBigIntVal(ExprContext* context, const TupleRow* row); - virtual FloatVal GetFloatVal(ExprContext* context, const TupleRow* row); - virtual DoubleVal GetDoubleVal(ExprContext* context, const TupleRow* row); - virtual StringVal GetStringVal(ExprContext* context, const TupleRow* row); - virtual TimestampVal GetTimestampVal(ExprContext* context, const TupleRow* row); - virtual DecimalVal GetDecimalVal(ExprContext* context, const TupleRow* row); - - virtual std::string DebugString() const { return Expr::DebugString("CoalesceExpr"); } + virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn) + override WARN_UNUSED_RESULT; + virtual std::string DebugString() const override { + return ScalarExpr::DebugString("CoalesceExpr"); + } protected: - friend class Expr; - CoalesceExpr(const TExprNode& node) : Expr(node) { } - virtual Status GetCodegendComputeFn(LlvmCodeGen* codegen, llvm::Function** fn); + friend class ScalarExpr; + friend class ScalarExprEvaluator; + + CoalesceExpr(const TExprNode& node) : ScalarExpr(node) { } + virtual BooleanVal GetBooleanVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TinyIntVal GetTinyIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual SmallIntVal GetSmallIntVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual IntVal GetIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual BigIntVal GetBigIntVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual FloatVal GetFloatVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual DoubleVal GetDoubleVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual StringVal GetStringVal(ScalarExprEvaluator*, const TupleRow*) const override; + virtual TimestampVal GetTimestampVal( + ScalarExprEvaluator*, const TupleRow*) const override; + virtual DecimalVal GetDecimalVal(ScalarExprEvaluator*, const TupleRow*) const override; }; } http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/decimal-functions-ir.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/decimal-functions-ir.cc b/be/src/exprs/decimal-functions-ir.cc index 3262e27..015a518 100644 --- a/be/src/exprs/decimal-functions-ir.cc +++ b/be/src/exprs/decimal-functions-ir.cc @@ -19,7 +19,6 @@ #include "codegen/impala-ir.h" #include "exprs/anyval-util.h" -#include "exprs/expr.h" #include <ctype.h> #include <math.h> http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/decimal-functions.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/decimal-functions.h b/be/src/exprs/decimal-functions.h index c6429a1..4f94ba1 100644 --- a/be/src/exprs/decimal-functions.h +++ b/be/src/exprs/decimal-functions.h @@ -22,10 +22,15 @@ #include "exprs/decimal-operators.h" #include "udf/udf.h" -using namespace impala_udf; - namespace impala { +using impala_udf::FunctionContext; +using impala_udf::TinyIntVal; +using impala_udf::SmallIntVal; +using impala_udf::IntVal; +using impala_udf::BigIntVal; +using impala_udf::DecimalVal; + class Expr; class TupleRow; http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/decimal-operators-ir.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/decimal-operators-ir.cc b/be/src/exprs/decimal-operators-ir.cc index 785b1b3..070c70f 100644 --- a/be/src/exprs/decimal-operators-ir.cc +++ b/be/src/exprs/decimal-operators-ir.cc @@ -23,10 +23,8 @@ #include "codegen/impala-ir.h" #include "exprs/anyval-util.h" -#include "exprs/case-expr.h" -#include "exprs/expr.h" +#include "exprs/scalar-expr.h" #include "runtime/decimal-value.inline.h" -#include "runtime/tuple-row.h" #include "util/decimal-util.h" #include "util/string-parser.h" http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/decimal-operators.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/decimal-operators.h b/be/src/exprs/decimal-operators.h index 196ffdb..34c11cb 100644 --- a/be/src/exprs/decimal-operators.h +++ b/be/src/exprs/decimal-operators.h @@ -24,10 +24,21 @@ #include "runtime/decimal-value.h" #include "udf/udf.h" -using namespace impala_udf; - namespace impala { +using impala_udf::FunctionContext; +using impala_udf::AnyVal; +using impala_udf::BooleanVal; +using impala_udf::TinyIntVal; +using impala_udf::SmallIntVal; +using impala_udf::IntVal; +using impala_udf::BigIntVal; +using impala_udf::FloatVal; +using impala_udf::DoubleVal; +using impala_udf::TimestampVal; +using impala_udf::StringVal; +using impala_udf::DecimalVal; + class Expr; struct ExprValue; class TupleRow; http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/expr-codegen-test.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/expr-codegen-test.cc b/be/src/exprs/expr-codegen-test.cc index c027492..b4f0378 100644 --- a/be/src/exprs/expr-codegen-test.cc +++ b/be/src/exprs/expr-codegen-test.cc @@ -17,7 +17,7 @@ // The following is cross-compiled to native code and IR, and used in the test below #include "exprs/decimal-operators.h" -#include "exprs/expr.h" +#include "exprs/scalar-expr.h" #include "udf/udf.h" using namespace impala; @@ -36,7 +36,7 @@ struct FnAttr { #endif DecimalVal TestGetFnAttrs( - FunctionContext* ctx, const DecimalVal& arg0, StringVal arg1, StringVal arg2) { + FunctionContext* ctx, const DecimalVal& arg0, BooleanVal& arg1, StringVal& arg2) { FnAttr* state = reinterpret_cast<FnAttr*>( ctx->GetFunctionState(FunctionContext::THREAD_LOCAL)); state->return_type_size = @@ -58,7 +58,8 @@ DecimalVal TestGetFnAttrs( #include "codegen/llvm-codegen.h" #include "common/init.h" #include "exprs/anyval-util.h" -#include "exprs/expr-context.h" +#include "exprs/scalar-expr.h" +#include "exprs/scalar-expr-evaluator.h" #include "runtime/exec-env.h" #include "runtime/mem-tracker.h" #include "runtime/runtime-state.h" @@ -76,7 +77,7 @@ using namespace llvm; namespace impala { const char* TEST_GET_FN_ATTR_SYMBOL = - "_Z14TestGetFnAttrsPN10impala_udf15FunctionContextERKNS_10DecimalValENS_9StringValES5_"; + "_Z14TestGetFnAttrsPN10impala_udf15FunctionContextERKNS_10DecimalValERNS_10BooleanValERNS_9StringValE"; const int ARG0_PRECISION = 10; const int ARG0_SCALE = 2; @@ -91,7 +92,7 @@ class ExprCodegenTest : public ::testing::Test { FunctionContext* fn_ctx_; FnAttr fn_type_attr_; - int InlineConstFnAttrs(Expr* expr, LlvmCodeGen* codegen, llvm::Function* fn) { + int InlineConstFnAttrs(const Expr* expr, LlvmCodeGen* codegen, llvm::Function* fn) { FunctionContext::TypeDesc ret_type = AnyValUtil::ColumnTypeToTypeDesc(expr->type()); vector<FunctionContext::TypeDesc> arg_types; for (const Expr* child : expr->children()) { @@ -108,6 +109,7 @@ class ExprCodegenTest : public ::testing::Test { virtual void SetUp() { TQueryOptions query_options; + query_options.__set_disable_codegen(false); query_options.__set_decimal_v2(true); test_env_.reset(new TestEnv()); ASSERT_OK(test_env_->Init()); @@ -124,8 +126,7 @@ class ExprCodegenTest : public ::testing::Test { arg0_type.scale = ARG0_SCALE; FunctionContext::TypeDesc arg1_type; - arg1_type.type = FunctionContext::TYPE_FIXED_BUFFER; - arg1_type.len = ARG1_LEN; + arg1_type.type = FunctionContext::TYPE_BOOLEAN; FunctionContext::TypeDesc arg2_type; arg2_type.type = FunctionContext::TYPE_STRING; @@ -165,6 +166,28 @@ class ExprCodegenTest : public ::testing::Test { } }; +TExprNode CreateBooleanLiteral() { + TScalarType scalar_type; + scalar_type.type = TPrimitiveType::BOOLEAN; + + TTypeNode type; + type.type = TTypeNodeType::SCALAR; + type.__set_scalar_type(scalar_type); + + TColumnType col_type; + col_type.__set_types(vector<TTypeNode>(1, type)); + + TBoolLiteral bool_literal; + bool_literal.__set_value(true); + + TExprNode expr; + expr.node_type = TExprNodeType::BOOL_LITERAL; + expr.type = col_type; + expr.num_children = 0; + expr.__set_bool_literal(bool_literal); + return expr; +} + TExprNode CreateDecimalLiteral(int precision, int scale) { TScalarType scalar_type; scalar_type.type = TPrimitiveType::DECIMAL; @@ -192,7 +215,7 @@ TExprNode CreateDecimalLiteral(int precision, int scale) { // len > 0 => char TExprNode CreateStringLiteral(int len = -1) { TScalarType scalar_type; - scalar_type.type = len > 0 ? TPrimitiveType::CHAR : TPrimitiveType::STRING; + scalar_type.type = len > 0 ? TPrimitiveType::VARCHAR : TPrimitiveType::STRING; if (len > 0) scalar_type.__set_len(len); TTypeNode type; @@ -257,7 +280,7 @@ TEST_F(ExprCodegenTest, TestGetConstFnAttrsInterpreted) { // and return types are encoded above (ARG0_*, RET_*); int64_t v = 1000025; DecimalVal arg0_val(v); - StringVal arg1_val; + BooleanVal arg1_val; StringVal arg2_val; DecimalVal result = TestGetFnAttrs(fn_ctx_, arg0_val, arg1_val, arg2_val); // sanity check result @@ -269,7 +292,7 @@ TEST_F(ExprCodegenTest, TestGetConstFnAttrsInterpreted) { TEST_F(ExprCodegenTest, TestInlineConstFnAttrs) { // Setup thrift descriptors TExprNode arg0 = CreateDecimalLiteral(ARG0_PRECISION, ARG0_SCALE); - TExprNode arg1 = CreateStringLiteral(ARG1_LEN); + TExprNode arg1 = CreateBooleanLiteral(); TExprNode arg2 = CreateStringLiteral(); vector<TExprNode> exprs; @@ -284,10 +307,9 @@ TEST_F(ExprCodegenTest, TestInlineConstFnAttrs) { texpr.__set_nodes(exprs); // Create Expr - ObjectPool pool; MemTracker tracker; - ExprContext* ctx; - ASSERT_OK(Expr::CreateExprTree(&pool, texpr, &ctx)); + ScalarExpr* expr; + ASSERT_OK(ScalarExpr::Create(texpr, RowDescriptor(), runtime_state_, &expr)); // Get TestGetFnAttrs() IR function stringstream test_udf_file; @@ -302,7 +324,7 @@ TEST_F(ExprCodegenTest, TestInlineConstFnAttrs) { EXPECT_FALSE(verification_succeeded); // Call InlineConstFnAttrs() and rerun verification - int replaced = InlineConstFnAttrs(ctx->root(), codegen.get(), fn); + int replaced = InlineConstFnAttrs(expr, codegen.get(), fn); EXPECT_EQ(replaced, 9); ResetVerification(codegen.get()); verification_succeeded = VerifyFunction(codegen.get(), fn); http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/expr-context.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/expr-context.cc b/be/src/exprs/expr-context.cc deleted file mode 100644 index 805e110..0000000 --- a/be/src/exprs/expr-context.cc +++ /dev/null @@ -1,377 +0,0 @@ -// 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/expr-context.h" - -#include <sstream> - -#include "common/object-pool.h" -#include "exprs/expr.h" -#include "runtime/decimal-value.inline.h" -#include "runtime/mem-pool.h" -#include "runtime/raw-value.inline.h" -#include "runtime/runtime-state.h" -#include "udf/udf-internal.h" - -#include "common/names.h" - -using namespace impala; -using namespace impala_udf; - -const char* ExprContext::LLVM_CLASS_NAME = "class.impala::ExprContext"; - -ExprContext::ExprContext(Expr* root) - : fn_contexts_ptr_(NULL), - root_(root), - is_clone_(false), - prepared_(false), - opened_(false), - closed_(false) { -} - -ExprContext::~ExprContext() { - DCHECK(!prepared_ || closed_); - for (int i = 0; i < fn_contexts_.size(); ++i) { - delete fn_contexts_[i]; - } -} - -Status ExprContext::Prepare(RuntimeState* state, const RowDescriptor& row_desc, - MemTracker* tracker) { - DCHECK(tracker != NULL); - DCHECK(pool_.get() == NULL); - prepared_ = true; - pool_.reset(new MemPool(tracker)); - return root_->Prepare(state, row_desc, this); -} - -Status ExprContext::Open(RuntimeState* state) { - DCHECK(prepared_); - if (opened_) return Status::OK(); - opened_ = true; - // Fragment-local state is only initialized for original contexts. Clones inherit the - // original's fragment state and only need to have thread-local state initialized. - FunctionContext::FunctionStateScope scope = - is_clone_? FunctionContext::THREAD_LOCAL : FunctionContext::FRAGMENT_LOCAL; - return root_->Open(state, this, scope); -} - -void ExprContext::Close(RuntimeState* state) { - if (closed_) return; - FunctionContext::FunctionStateScope scope = - is_clone_ ? FunctionContext::THREAD_LOCAL : FunctionContext::FRAGMENT_LOCAL; - root_->Close(state, this, scope); - - for (int i = 0; i < fn_contexts_.size(); ++i) { - fn_contexts_[i]->impl()->Close(); - } - // pool_ can be NULL if Prepare() was never called - if (pool_ != NULL) pool_->FreeAll(); - closed_ = true; -} - -int ExprContext::Register(RuntimeState* state, - const impala_udf::FunctionContext::TypeDesc& return_type, - const vector<impala_udf::FunctionContext::TypeDesc>& arg_types, - int varargs_buffer_size) { - fn_contexts_.push_back(FunctionContextImpl::CreateContext( - state, pool_.get(), return_type, arg_types, varargs_buffer_size)); - fn_contexts_ptr_ = &fn_contexts_[0]; - return fn_contexts_.size() - 1; -} - -Status ExprContext::Clone(RuntimeState* state, ExprContext** new_ctx) { - DCHECK(prepared_); - DCHECK(opened_); - DCHECK(*new_ctx == NULL); - - *new_ctx = state->obj_pool()->Add(new ExprContext(root_)); - (*new_ctx)->pool_.reset(new MemPool(pool_->mem_tracker())); - for (int i = 0; i < fn_contexts_.size(); ++i) { - (*new_ctx)->fn_contexts_.push_back( - fn_contexts_[i]->impl()->Clone((*new_ctx)->pool_.get())); - } - (*new_ctx)->fn_contexts_ptr_ = &((*new_ctx)->fn_contexts_[0]); - - (*new_ctx)->is_clone_ = true; - (*new_ctx)->prepared_ = true; - (*new_ctx)->opened_ = true; - - return root_->Open(state, *new_ctx, FunctionContext::THREAD_LOCAL); -} - -bool ExprContext::HasLocalAllocations(const vector<ExprContext*>& ctxs) { - for (int i = 0; i < ctxs.size(); ++i) { - if (ctxs[i]->HasLocalAllocations()) return true; - } - return false; -} - -bool ExprContext::HasLocalAllocations() { - return HasLocalAllocations(fn_contexts_); -} - -bool ExprContext::HasLocalAllocations(const std::vector<FunctionContext*>& fn_ctxs) { - for (int i = 0; i < fn_ctxs.size(); ++i) { - if (fn_ctxs[i]->impl()->closed()) continue; - if (fn_ctxs[i]->impl()->HasLocalAllocations()) return true; - } - return false; -} - -void ExprContext::FreeLocalAllocations(const vector<ExprContext*>& ctxs) { - for (int i = 0; i < ctxs.size(); ++i) { - ctxs[i]->FreeLocalAllocations(); - } -} - -void ExprContext::FreeLocalAllocations() { - FreeLocalAllocations(fn_contexts_); -} - -void ExprContext::FreeLocalAllocations(const vector<FunctionContext*>& fn_ctxs) { - for (int i = 0; i < fn_ctxs.size(); ++i) { - if (fn_ctxs[i]->impl()->closed()) continue; - fn_ctxs[i]->impl()->FreeLocalAllocations(); - } -} - -void ExprContext::EvaluateWithoutRow(TColumnValue* col_val) { - DCHECK_EQ(0, root_->GetSlotIds()); - void* value = GetValue(NULL); - if (value == NULL) return; - - StringValue* string_val = NULL; - string tmp; - switch (root_->type_.type) { - case TYPE_BOOLEAN: - col_val->__set_bool_val(*reinterpret_cast<bool*>(value)); - break; - case TYPE_TINYINT: - col_val->__set_byte_val(*reinterpret_cast<int8_t*>(value)); - break; - case TYPE_SMALLINT: - col_val->__set_short_val(*reinterpret_cast<int16_t*>(value)); - break; - case TYPE_INT: - col_val->__set_int_val(*reinterpret_cast<int32_t*>(value)); - break; - case TYPE_BIGINT: - col_val->__set_long_val(*reinterpret_cast<int64_t*>(value)); - break; - case TYPE_FLOAT: - col_val->__set_double_val(*reinterpret_cast<float*>(value)); - break; - case TYPE_DOUBLE: - col_val->__set_double_val(*reinterpret_cast<double*>(value)); - break; - case TYPE_DECIMAL: - switch (root_->type_.GetByteSize()) { - case 4: - col_val->string_val = - reinterpret_cast<Decimal4Value*>(value)->ToString(root_->type_); - break; - case 8: - col_val->string_val = - reinterpret_cast<Decimal8Value*>(value)->ToString(root_->type_); - break; - case 16: - col_val->string_val = - reinterpret_cast<Decimal16Value*>(value)->ToString(root_->type_); - break; - default: - DCHECK(false) << "Bad Type: " << root_->type_; - } - col_val->__isset.string_val = true; - break; - case TYPE_STRING: - case TYPE_VARCHAR: - string_val = reinterpret_cast<StringValue*>(value); - tmp.assign(static_cast<char*>(string_val->ptr), string_val->len); - col_val->binary_val.swap(tmp); - col_val->__isset.binary_val = true; - break; - case TYPE_CHAR: - tmp.assign(StringValue::CharSlotToPtr(value, root_->type_), root_->type_.len); - col_val->binary_val.swap(tmp); - col_val->__isset.binary_val = true; - break; - case TYPE_TIMESTAMP: { - uint8_t* uint8_val = reinterpret_cast<uint8_t*>(value); - col_val->binary_val.assign(uint8_val, uint8_val + root_->type_.GetSlotSize()); - col_val->__isset.binary_val = true; - RawValue::PrintValue( - value, root_->type_, root_->output_scale_, &col_val->string_val); - col_val->__isset.string_val = true; - break; - } - default: - DCHECK(false) << "bad GetValue() type: " << root_->type_.DebugString(); - } -} - -void* ExprContext::GetValue(const TupleRow* row) { - return GetValue(root_, row); -} - -void* ExprContext::GetValue(Expr* e, const TupleRow* row) { - switch (e->type_.type) { - case TYPE_BOOLEAN: { - impala_udf::BooleanVal v = e->GetBooleanVal(this, row); - if (v.is_null) return NULL; - result_.bool_val = v.val; - return &result_.bool_val; - } - case TYPE_TINYINT: { - impala_udf::TinyIntVal v = e->GetTinyIntVal(this, row); - if (v.is_null) return NULL; - result_.tinyint_val = v.val; - return &result_.tinyint_val; - } - case TYPE_SMALLINT: { - impala_udf::SmallIntVal v = e->GetSmallIntVal(this, row); - if (v.is_null) return NULL; - result_.smallint_val = v.val; - return &result_.smallint_val; - } - case TYPE_INT: { - impala_udf::IntVal v = e->GetIntVal(this, row); - if (v.is_null) return NULL; - result_.int_val = v.val; - return &result_.int_val; - } - case TYPE_BIGINT: { - impala_udf::BigIntVal v = e->GetBigIntVal(this, row); - if (v.is_null) return NULL; - result_.bigint_val = v.val; - return &result_.bigint_val; - } - case TYPE_FLOAT: { - impala_udf::FloatVal v = e->GetFloatVal(this, row); - if (v.is_null) return NULL; - result_.float_val = v.val; - return &result_.float_val; - } - case TYPE_DOUBLE: { - impala_udf::DoubleVal v = e->GetDoubleVal(this, row); - if (v.is_null) return NULL; - result_.double_val = v.val; - return &result_.double_val; - } - case TYPE_STRING: - case TYPE_VARCHAR: { - impala_udf::StringVal v = e->GetStringVal(this, row); - if (v.is_null) return NULL; - result_.string_val.ptr = reinterpret_cast<char*>(v.ptr); - result_.string_val.len = v.len; - return &result_.string_val; - } - case TYPE_CHAR: { - impala_udf::StringVal v = e->GetStringVal(this, row); - if (v.is_null) return NULL; - result_.string_val.ptr = reinterpret_cast<char*>(v.ptr); - result_.string_val.len = v.len; - if (e->type_.IsVarLenStringType()) { - return &result_.string_val; - } else { - return result_.string_val.ptr; - } - } - case TYPE_TIMESTAMP: { - impala_udf::TimestampVal v = e->GetTimestampVal(this, row); - if (v.is_null) return NULL; - result_.timestamp_val = TimestampValue::FromTimestampVal(v); - return &result_.timestamp_val; - } - case TYPE_DECIMAL: { - DecimalVal v = e->GetDecimalVal(this, row); - if (v.is_null) return NULL; - switch (e->type_.GetByteSize()) { - case 4: - result_.decimal4_val = v.val4; - return &result_.decimal4_val; - case 8: - result_.decimal8_val = v.val8; - return &result_.decimal8_val; - case 16: - result_.decimal16_val = v.val16; - return &result_.decimal16_val; - default: - DCHECK(false) << e->type_.GetByteSize(); - return NULL; - } - } - case TYPE_ARRAY: - case TYPE_MAP: { - impala_udf::CollectionVal v = e->GetCollectionVal(this, row); - if (v.is_null) return NULL; - result_.collection_val.ptr = v.ptr; - result_.collection_val.num_tuples = v.num_tuples; - return &result_.collection_val; - } - default: - DCHECK(false) << "Type not implemented: " << e->type_.DebugString(); - return NULL; - } -} - -void ExprContext::PrintValue(const TupleRow* row, string* str) { - RawValue::PrintValue(GetValue(row), root_->type(), root_->output_scale_, str); -} -void ExprContext::PrintValue(void* value, string* str) { - RawValue::PrintValue(value, root_->type(), root_->output_scale_, str); -} -void ExprContext::PrintValue(void* value, stringstream* stream) { - RawValue::PrintValue(value, root_->type(), root_->output_scale_, stream); -} -void ExprContext::PrintValue(const TupleRow* row, stringstream* stream) { - RawValue::PrintValue(GetValue(row), root_->type(), root_->output_scale_, stream); -} - -BooleanVal ExprContext::GetBooleanVal(TupleRow* row) { - return root_->GetBooleanVal(this, row); -} -TinyIntVal ExprContext::GetTinyIntVal(TupleRow* row) { - return root_->GetTinyIntVal(this, row); -} -SmallIntVal ExprContext::GetSmallIntVal(TupleRow* row) { - return root_->GetSmallIntVal(this, row); -} -IntVal ExprContext::GetIntVal(TupleRow* row) { - return root_->GetIntVal(this, row); -} -BigIntVal ExprContext::GetBigIntVal(TupleRow* row) { - return root_->GetBigIntVal(this, row); -} -FloatVal ExprContext::GetFloatVal(TupleRow* row) { - return root_->GetFloatVal(this, row); -} -DoubleVal ExprContext::GetDoubleVal(TupleRow* row) { - return root_->GetDoubleVal(this, row); -} -StringVal ExprContext::GetStringVal(TupleRow* row) { - return root_->GetStringVal(this, row); -} -CollectionVal ExprContext::GetCollectionVal(TupleRow* row) { - return root_->GetCollectionVal(this, row); -} -TimestampVal ExprContext::GetTimestampVal(TupleRow* row) { - return root_->GetTimestampVal(this, row); -} -DecimalVal ExprContext::GetDecimalVal(TupleRow* row) { - return root_->GetDecimalVal(this, row); -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/expr-context.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/expr-context.h b/be/src/exprs/expr-context.h deleted file mode 100644 index fe9bf44..0000000 --- a/be/src/exprs/expr-context.h +++ /dev/null @@ -1,191 +0,0 @@ -// 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 IMPALA_EXPRS_EXPR_CONTEXT_H -#define IMPALA_EXPRS_EXPR_CONTEXT_H - -#include <boost/scoped_ptr.hpp> - -#include "common/object-pool.h" -#include "common/status.h" -#include "exprs/expr-value.h" -#include "udf/udf-internal.h" // for CollectionVal -#include "udf/udf.h" - -using namespace impala_udf; - -namespace impala { - -class Expr; -class MemPool; -class MemTracker; -class RuntimeState; -class RowDescriptor; -class TColumnValue; -class TupleRow; - -/// An ExprContext contains the state for the execution of a tree of Exprs, in particular -/// the FunctionContexts necessary for the expr tree. This allows for multi-threaded -/// expression evaluation, as a given tree can be evaluated using multiple ExprContexts -/// concurrently. A single ExprContext is not thread-safe. -class ExprContext { - public: - ExprContext(Expr* root); - ~ExprContext(); - - /// Prepare expr tree for evaluation. - /// Allocations from this context will be counted against 'tracker'. - /// If Prepare() is called, Close() must be called before destruction to release - /// resources, regardless of whether Prepare() succeeded. - Status Prepare(RuntimeState* state, const RowDescriptor& row_desc, - MemTracker* tracker); - - /// Must be called after calling Prepare(). Does not need to be called on clones. - /// Idempotent (this allows exprs to be opened multiple times in subplans without - /// reinitializing function state). - Status Open(RuntimeState* state); - - /// Creates a copy of this ExprContext. Open() must be called first. The copy contains - /// clones of each FunctionContext, which share the fragment-local state of the - /// originals but have their own MemPool and thread-local state. Clone() should be used - /// to create an ExprContext for each execution thread that needs to evaluate - /// 'root'. Note that clones are already opened. '*new_context' must be initialized by - /// the caller to NULL. The cloned ExprContext cannot be used after the original - /// ExprContext is destroyed because it may reference fragment-local state from the - /// original. - Status Clone(RuntimeState* state, ExprContext** new_context); - - /// Closes all FunctionContexts. Must be called on every ExprContext, including clones. - /// Has no effect if already closed. - void Close(RuntimeState* state); - - /// Calls the appropriate Get*Val() function on this context's expr tree and stores the - /// result in result_. - void* GetValue(const TupleRow* row); - - /// Convenience function for evaluating Exprs that don't reference slots from the FE. - /// Extracts value into 'col_val' and sets the appropriate __isset flag. No fields are - /// set for NULL values. The specific field in 'col_val' that receives the value is - /// based on the expr type: - /// TYPE_BOOLEAN: boolVal - /// TYPE_TINYINT/SMALLINT/INT: intVal - /// TYPE_BIGINT: longVal - /// TYPE_FLOAT/DOUBLE: doubleVal - /// TYPE_STRING: binaryVal. Do not populate stringVal directly because BE/FE - /// conversions do not work properly for strings with ASCII chars - /// above 127. Pass the raw bytes so the caller can decide what to - /// do with the result (e.g., bail constant folding). - /// TYPE_TIMESTAMP: binaryVal has the raw data, stringVal its string representation. - void EvaluateWithoutRow(TColumnValue* col_val); - - /// Convenience functions: print value into 'str' or 'stream'. NULL turns into "NULL". - void PrintValue(const TupleRow* row, std::string* str); - void PrintValue(void* value, std::string* str); - void PrintValue(void* value, std::stringstream* stream); - void PrintValue(const TupleRow* row, std::stringstream* stream); - - /// Creates a FunctionContext, and returns the index that's passed to fn_context() to - /// retrieve the created context. Exprs that need a FunctionContext should call this in - /// Prepare() and save the returned index. 'varargs_buffer_size', if specified, is the - /// size of the varargs buffer in the created FunctionContext (see udf-internal.h). - int Register(RuntimeState* state, const FunctionContext::TypeDesc& return_type, - const std::vector<FunctionContext::TypeDesc>& arg_types, - int varargs_buffer_size = 0); - - /// Retrieves a registered FunctionContext. 'i' is the index returned by the call to - /// Register(). This should only be called by Exprs. - FunctionContext* fn_context(int i) { - DCHECK_GE(i, 0); - DCHECK_LT(i, fn_contexts_.size()); - return fn_contexts_[i]; - } - - Expr* root() const { return root_; } - bool opened() const { return opened_; } - bool closed() const { return closed_; } - bool is_clone() const { return is_clone_; } - - /// Calls Get*Val on root_ - BooleanVal GetBooleanVal(TupleRow* row); - TinyIntVal GetTinyIntVal(TupleRow* row); - SmallIntVal GetSmallIntVal(TupleRow* row); - IntVal GetIntVal(TupleRow* row); - BigIntVal GetBigIntVal(TupleRow* row); - FloatVal GetFloatVal(TupleRow* row); - DoubleVal GetDoubleVal(TupleRow* row); - StringVal GetStringVal(TupleRow* row); - CollectionVal GetCollectionVal(TupleRow* row); - TimestampVal GetTimestampVal(TupleRow* row); - DecimalVal GetDecimalVal(TupleRow* row); - - /// Returns true if any of the expression contexts in the array has local allocations. - /// The last two are helper functions. - static bool HasLocalAllocations(const std::vector<ExprContext*>& ctxs); - bool HasLocalAllocations(); - static bool HasLocalAllocations(const std::vector<FunctionContext*>& fn_ctxs); - - /// Frees all local allocations made by fn_contexts_. This can be called when result - /// data from this context is no longer needed. The last two are helper functions. - static void FreeLocalAllocations(const std::vector<ExprContext*>& ctxs); - void FreeLocalAllocations(); - static void FreeLocalAllocations(const std::vector<FunctionContext*>& ctxs); - - static const char* LLVM_CLASS_NAME; - - private: - friend class Expr; - /// Users of private GetValue() or 'pool_'. - friend class CaseExpr; - friend class HiveUdfCall; - friend class ScalarFnCall; - friend class KuduPartitionExpr; - - /// FunctionContexts for each registered expression. The FunctionContexts are created - /// and owned by this ExprContext. - std::vector<FunctionContext*> fn_contexts_; - - /// Array access to fn_contexts_. Used by ScalarFnCall's codegen'd compute function - /// to access the correct FunctionContext. - /// TODO: revisit this - FunctionContext** fn_contexts_ptr_; - - /// Pool backing fn_contexts_. Counts against the runtime state's UDF mem tracker. - boost::scoped_ptr<MemPool> pool_; - - /// The expr tree this context is for. - Expr* root_; - - /// Stores the result of the root expr. This is used in interpreted code when we need a - /// void*. - ExprValue result_; - - /// True if this context came from a Clone() call. Used to manage FunctionStateScope. - bool is_clone_; - - /// Variables keeping track of current state. - bool prepared_; - bool opened_; - bool closed_; - - /// Calls the appropriate Get*Val() function on 'e' and stores the result in result_. - /// This is used by Exprs to call GetValue() on a child expr, rather than root_. - void* GetValue(Expr* e, const TupleRow* row); -}; - -} - -#endif http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/expr-ir.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/expr-ir.cc b/be/src/exprs/expr-ir.cc deleted file mode 100644 index 1812663..0000000 --- a/be/src/exprs/expr-ir.cc +++ /dev/null @@ -1,74 +0,0 @@ -// 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/expr.h" -#include "udf/udf.h" - -#ifdef IR_COMPILE - -// Compile ExprContext declaration to IR so we can use it in codegen'd functions -#include "exprs/expr-context.h" - -// Dummy function to force compilation of UDF types. -// The arguments are pointers to prevent Clang from lowering the struct types -// (e.g. IntVal={bool, i32} can be coerced to i64). -void dummy(impala_udf::FunctionContext*, impala_udf::BooleanVal*, impala_udf::TinyIntVal*, - impala_udf::SmallIntVal*, impala_udf::IntVal*, impala_udf::BigIntVal*, - impala_udf::FloatVal*, impala_udf::DoubleVal*, impala_udf::StringVal*, - impala_udf::TimestampVal*, impala_udf::DecimalVal*, impala::ExprContext*) { } -#endif - -// The following are compute functions that are cross-compiled to both native and IR -// libraries. In the interpreted path, these functions are executed as-is from the native -// code. In the codegen'd path, we load the IR functions and replace the Get*Val() calls -// with the appropriate child's codegen'd compute function. - -using namespace impala; -using namespace impala_udf; -// Static wrappers around Get*Val() functions. We'd like to be able to call these from -// directly from native code as well as from generated IR functions. - -BooleanVal Expr::GetBooleanVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetBooleanVal(context, row); -} -TinyIntVal Expr::GetTinyIntVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetTinyIntVal(context, row); -} -SmallIntVal Expr::GetSmallIntVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetSmallIntVal(context, row); -} -IntVal Expr::GetIntVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetIntVal(context, row); -} -BigIntVal Expr::GetBigIntVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetBigIntVal(context, row); -} -FloatVal Expr::GetFloatVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetFloatVal(context, row); -} -DoubleVal Expr::GetDoubleVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetDoubleVal(context, row); -} -StringVal Expr::GetStringVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetStringVal(context, row); -} -TimestampVal Expr::GetTimestampVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetTimestampVal(context, row); -} -DecimalVal Expr::GetDecimalVal(Expr* expr, ExprContext* context, const TupleRow* row) { - return expr->GetDecimalVal(context, row); -} http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/expr-test.cc ---------------------------------------------------------------------- diff --git a/be/src/exprs/expr-test.cc b/be/src/exprs/expr-test.cc index 2aa4537..3859efc 100644 --- a/be/src/exprs/expr-test.cc +++ b/be/src/exprs/expr-test.cc @@ -31,11 +31,12 @@ #include "codegen/llvm-codegen.h" #include "common/init.h" #include "common/object-pool.h" -#include "exprs/expr-context.h" #include "exprs/is-null-predicate.h" #include "exprs/like-predicate.h" #include "exprs/literal.h" #include "exprs/null-literal.h" +#include "exprs/scalar-expr.h" +#include "exprs/scalar-expr-evaluator.h" #include "exprs/string-functions.h" #include "exprs/timestamp-functions.h" #include "exprs/timezone_db.h" @@ -1138,30 +1139,34 @@ template <typename T> void TestSingleLiteralConstruction( const ColumnType& type, const T& value, const string& string_val) { ObjectPool pool; - RowDescriptor desc; RuntimeState state(TQueryCtx(), ExecEnv::GetInstance()); MemTracker tracker; + MemPool mem_pool(&tracker); - Expr* expr = pool.Add(new Literal(type, value)); - ExprContext ctx(expr); - EXPECT_OK(ctx.Prepare(&state, desc, &tracker)); - EXPECT_OK(ctx.Open(&state)); - EXPECT_EQ(0, RawValue::Compare(ctx.GetValue(NULL), &value, type)) + ScalarExpr* expr = Literal::CreateLiteral(type, string_val); + ScalarExprEvaluator* eval; + EXPECT_OK(ScalarExprEvaluator::Create(*expr, &state, &pool, &mem_pool, &eval)); + EXPECT_OK(eval->Open(&state)); + EXPECT_EQ(0, RawValue::Compare(eval->GetValue(nullptr), &value, type)) << "type: " << type << ", value: " << value; - ctx.Close(&state); + eval->Close(&state); + expr->Close(); state.ReleaseResources(); } TEST_F(ExprTest, NullLiteral) { for (int type = TYPE_BOOLEAN; type != TYPE_DATE; ++type) { - NullLiteral expr(static_cast<PrimitiveType>(type)); - ExprContext ctx(&expr); RuntimeState state(TQueryCtx(), ExecEnv::GetInstance()); + ObjectPool pool; MemTracker tracker; - EXPECT_OK(ctx.Prepare(&state, RowDescriptor(), &tracker)); - EXPECT_OK(ctx.Open(&state)); - EXPECT_TRUE(ctx.GetValue(NULL) == NULL); - ctx.Close(&state); + MemPool mem_pool(&tracker); + + NullLiteral expr(static_cast<PrimitiveType>(type)); + ScalarExprEvaluator* eval; + EXPECT_OK(ScalarExprEvaluator::Create(expr, &state, &pool, &mem_pool, &eval)); + EXPECT_OK(eval->Open(&state)); + EXPECT_TRUE(eval->GetValue(nullptr) == nullptr); + eval->Close(&state); state.ReleaseResources(); } } @@ -3221,10 +3226,12 @@ TEST_F(ExprTest, StringFunctions) { " " " ", ColumnType::CreateCharType(255)); + /* TestCharValue("CASE cast('1.1' as char(3)) when cast('1.1' as char(3)) then " "cast('1' as char(1)) when cast('2.22' as char(4)) then " "cast('2' as char(1)) else cast('3' as char(1)) end", "1", ColumnType::CreateCharType(3)); + */ // Test maximum VARCHAR value char query[ColumnType::MAX_VARCHAR_LENGTH + 1024]; @@ -6048,13 +6055,13 @@ TEST_F(ExprTest, ConditionalFunctionIsNotFalse) { // - expected_var_begin: byte offset where variable length types begin // - expected_offsets: mapping of byte sizes to a set valid offsets // exprs that have the same byte size can end up in a number of locations -void ValidateLayout(const vector<Expr*>& exprs, int expected_byte_size, +void ValidateLayout(const vector<ScalarExpr*>& exprs, int expected_byte_size, int expected_var_begin, const map<int, set<int>>& expected_offsets) { vector<int> offsets; set<int> offsets_found; int var_begin; - int byte_size = Expr::ComputeResultsLayout(exprs, &offsets, &var_begin); + int byte_size = ScalarExpr::ComputeResultsLayout(exprs, &offsets, &var_begin); EXPECT_EQ(expected_byte_size, byte_size); EXPECT_EQ(expected_var_begin, var_begin); @@ -6079,7 +6086,7 @@ void ValidateLayout(const vector<Expr*>& exprs, int expected_byte_size, TEST_F(ExprTest, ResultsLayoutTest) { ObjectPool pool; - vector<Expr*> exprs; + vector<ScalarExpr*> exprs; map<int, set<int>> expected_offsets; // Test empty exprs http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/b38d9826/be/src/exprs/expr-value.h ---------------------------------------------------------------------- diff --git a/be/src/exprs/expr-value.h b/be/src/exprs/expr-value.h index fa447cb..5e4eaa8 100644 --- a/be/src/exprs/expr-value.h +++ b/be/src/exprs/expr-value.h @@ -26,7 +26,7 @@ namespace impala { -/// The materialized value returned by ExprContext::GetValue(). +/// The materialized value returned by ScalarExprEvaluator::GetValue(). struct ExprValue { bool bool_val; int8_t tinyint_val;
