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;

Reply via email to