IMPALA-4435: Fix in-predicate-benchmark linking by moving templates

In C++ (without export, which was removed in C++11), templates
definitions (and not just declarations) must be in headers in order to
be implicitly instantiated by callers. in-predicate-benchmark was
http://gerrit.cloudera.org:8080/4758; this patch fixes the linker
errors that were caused in some build modes by #including only the
template declarations.

Change-Id: Ie95ec71242b97f28c68e37d6f44956f2eeff8105
Reviewed-on: http://gerrit.cloudera.org:8080/4966
Reviewed-by: Jim Apple <[email protected]>
Tested-by: Internal Jenkins


Project: http://git-wip-us.apache.org/repos/asf/incubator-impala/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-impala/commit/7c001888
Tree: http://git-wip-us.apache.org/repos/asf/incubator-impala/tree/7c001888
Diff: http://git-wip-us.apache.org/repos/asf/incubator-impala/diff/7c001888

Branch: refs/heads/hadoop-next
Commit: 7c0018881b5c111ab175bbbc678bebc902126f5a
Parents: 120f34b
Author: Jim Apple <[email protected]>
Authored: Sat Nov 5 07:08:27 2016 -0700
Committer: Internal Jenkins <[email protected]>
Committed: Sun Nov 6 01:51:59 2016 +0000

----------------------------------------------------------------------
 be/src/exprs/in-predicate-ir.cc | 110 --------------------------------
 be/src/exprs/in-predicate.h     | 117 ++++++++++++++++++++++++++++++++++-
 2 files changed, 114 insertions(+), 113 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/7c001888/be/src/exprs/in-predicate-ir.cc
----------------------------------------------------------------------
diff --git a/be/src/exprs/in-predicate-ir.cc b/be/src/exprs/in-predicate-ir.cc
index 51aeec9..998fae0 100644
--- a/be/src/exprs/in-predicate-ir.cc
+++ b/be/src/exprs/in-predicate-ir.cc
@@ -19,118 +19,12 @@
 
 #include "exprs/in-predicate.h"
 
-#include "exprs/anyval-util.h"
-#include "runtime/decimal-value.h"
-#include "runtime/string-value.inline.h"
-
 #include "common/names.h"
 
 using namespace impala_udf;
 
 namespace impala {
 
-// Templated getter functions for extracting 'SetType' values from AnyVals
-template<typename T, typename SetType>
-SetType GetVal(const FunctionContext::TypeDesc* type, const T& x) {
-  DCHECK(!x.is_null);
-  return x.val;
-}
-
-template<> StringValue GetVal(const FunctionContext::TypeDesc* type, const 
StringVal& x) {
-  DCHECK(!x.is_null);
-  return StringValue::FromStringVal(x);
-}
-
-template<> TimestampValue GetVal(
-    const FunctionContext::TypeDesc* type, const TimestampVal& x) {
-  return TimestampValue::FromTimestampVal(x);
-}
-
-template<> Decimal16Value GetVal(
-    const FunctionContext::TypeDesc* type, const DecimalVal& x) {
-  if (type->precision <= ColumnType::MAX_DECIMAL4_PRECISION) {
-    return Decimal16Value(x.val4);
-  } else if (type->precision <= ColumnType::MAX_DECIMAL8_PRECISION) {
-    return Decimal16Value(x.val8);
-  } else {
-    return Decimal16Value(x.val16);
-  }
-}
-
-template<typename T, typename SetType>
-void InPredicate::SetLookupPrepare(
-    FunctionContext* ctx, FunctionContext::FunctionStateScope scope) {
-  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
-
-  SetLookupState<SetType>* state = new SetLookupState<SetType>;
-  state->type = ctx->GetArgType(0);
-  state->contains_null = false;
-  for (int i = 1; i < ctx->GetNumArgs(); ++i) {
-    DCHECK(ctx->IsArgConstant(i));
-    T* arg = reinterpret_cast<T*>(ctx->GetConstantArg(i));
-    if (arg->is_null) {
-      state->contains_null = true;
-    } else {
-      state->val_set.insert(GetVal<T, SetType>(state->type, *arg));
-    }
-  }
-  ctx->SetFunctionState(scope, state);
-}
-
-template<typename SetType>
-void InPredicate::SetLookupClose(
-    FunctionContext* ctx, FunctionContext::FunctionStateScope scope) {
-  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
-  SetLookupState<SetType>* state =
-      reinterpret_cast<SetLookupState<SetType>*>(ctx->GetFunctionState(scope));
-  delete state;
-}
-
-template<typename T, typename SetType, bool not_in, InPredicate::Strategy 
strategy>
-BooleanVal InPredicate::TemplatedIn(
-    FunctionContext* ctx, const T& val, int num_args, const T* args) {
-  if (val.is_null) return BooleanVal::null();
-
-  BooleanVal found;
-  if (strategy == SET_LOOKUP) {
-    SetLookupState<SetType>* state = 
reinterpret_cast<SetLookupState<SetType>*>(
-        ctx->GetFunctionState(FunctionContext::FRAGMENT_LOCAL));
-    DCHECK(state != NULL);
-    found = SetLookup(state, val);
-  } else {
-    DCHECK_EQ(strategy, ITERATE);
-    found = Iterate(ctx->GetArgType(0), val, num_args, args);
-  }
-  if (found.is_null) return BooleanVal::null();
-  return BooleanVal(found.val ^ not_in);
-}
-
-template<typename T, typename SetType>
-BooleanVal InPredicate::SetLookup(
-    SetLookupState<SetType>* state, const T& v) {
-  DCHECK(state != NULL);
-  SetType val = GetVal<T, SetType>(state->type, v);
-  bool found = state->val_set.find(val) != state->val_set.end();
-  if (found) return BooleanVal(true);
-  if (state->contains_null) return BooleanVal::null();
-  return BooleanVal(false);
-}
-
-template<typename T>
-BooleanVal InPredicate::Iterate(
-    const FunctionContext::TypeDesc* type, const T& val, int num_args, const 
T* args) {
-  bool found_null = false;
-  for (int i = 0; i < num_args; ++i) {
-    if (args[i].is_null) {
-      found_null = true;
-    } else if (AnyValUtil::Equals(*type, val, args[i])) {
-      return BooleanVal(true);
-    }
-  }
-  if (found_null) return BooleanVal::null();
-  return BooleanVal(false);
-}
-
 #define IN_FUNCTIONS(AnyValType, SetType, type_name) \
   BooleanVal InPredicate::InSetLookup( \
       FunctionContext* context, const AnyValType& val, int num_args, \
@@ -181,8 +75,4 @@ IN_FUNCTIONS(StringVal, StringValue, string)
 IN_FUNCTIONS(TimestampVal, TimestampValue, timestamp)
 IN_FUNCTIONS(DecimalVal, Decimal16Value, decimal)
 
-// Needed for in-predicate-benchmark to build
-template BooleanVal InPredicate::Iterate<IntVal>(
-    const FunctionContext::TypeDesc*, const IntVal&, int, const IntVal*);
-
 }

http://git-wip-us.apache.org/repos/asf/incubator-impala/blob/7c001888/be/src/exprs/in-predicate.h
----------------------------------------------------------------------
diff --git a/be/src/exprs/in-predicate.h b/be/src/exprs/in-predicate.h
index d01d844..fd53a42 100644
--- a/be/src/exprs/in-predicate.h
+++ b/be/src/exprs/in-predicate.h
@@ -21,6 +21,9 @@
 
 #include <string>
 #include "exprs/predicate.h"
+#include "exprs/anyval-util.h"
+#include "runtime/decimal-value.h"
+#include "runtime/string-value.inline.h"
 #include "udf/udf.h"
 
 namespace impala {
@@ -293,7 +296,7 @@ class InPredicate : public Predicate {
   /// functions.
   template<typename T, typename SetType, bool not_in, Strategy strategy>
   static inline impala_udf::BooleanVal TemplatedIn(
-      impala_udf::FunctionContext* context, const T& val, int num_args, const 
T* args);
+      impala_udf::FunctionContext* ctx, const T& val, int num_args, const T* 
args);
 
   /// Initializes an SetLookupState in ctx.
   template<typename T, typename SetType>
@@ -308,12 +311,120 @@ class InPredicate : public Predicate {
   template<typename T, typename SetType>
   static BooleanVal SetLookup(SetLookupState<SetType>* state, const T& v);
 
-  /// Iterates through each vararg looking for val. 'type' is the type of 
'val' and 'args'.
-  template<typename T>
+  /// Iterates through each vararg looking for val. 'type' is the type of 
'val' and
+  /// 'args'.
+  template <typename T>
   static BooleanVal Iterate(
       const FunctionContext::TypeDesc* type, const T& val, int num_args, const 
T* args);
+
+  // Templated getter functions for extracting 'SetType' values from AnyVals
+  template <typename T, typename SetType>
+  static inline SetType GetVal(const FunctionContext::TypeDesc* type, const T& 
x);
 };
 
+template <typename T, typename SetType, bool not_in, InPredicate::Strategy 
strategy>
+inline impala_udf::BooleanVal InPredicate::TemplatedIn(
+    impala_udf::FunctionContext* ctx, const T& val, int num_args, const T* 
args) {
+  if (val.is_null) return BooleanVal::null();
+
+  BooleanVal found;
+  if (strategy == SET_LOOKUP) {
+    SetLookupState<SetType>* state = 
reinterpret_cast<SetLookupState<SetType>*>(
+        ctx->GetFunctionState(FunctionContext::FRAGMENT_LOCAL));
+    DCHECK(state != NULL);
+    found = SetLookup(state, val);
+  } else {
+    DCHECK_EQ(strategy, ITERATE);
+    found = Iterate(ctx->GetArgType(0), val, num_args, args);
+  }
+  if (found.is_null) return BooleanVal::null();
+  return BooleanVal(found.val ^ not_in);
+}
+
+template <typename T, typename SetType>
+void InPredicate::SetLookupPrepare(
+    FunctionContext* ctx, FunctionContext::FunctionStateScope scope) {
+  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
+
+  SetLookupState<SetType>* state = new SetLookupState<SetType>;
+  state->type = ctx->GetArgType(0);
+  state->contains_null = false;
+  for (int i = 1; i < ctx->GetNumArgs(); ++i) {
+    DCHECK(ctx->IsArgConstant(i));
+    T* arg = reinterpret_cast<T*>(ctx->GetConstantArg(i));
+    if (arg->is_null) {
+      state->contains_null = true;
+    } else {
+      state->val_set.insert(GetVal<T, SetType>(state->type, *arg));
+    }
+  }
+  ctx->SetFunctionState(scope, state);
+}
+
+template <typename SetType>
+void InPredicate::SetLookupClose(
+    FunctionContext* ctx, FunctionContext::FunctionStateScope scope) {
+  if (scope != FunctionContext::FRAGMENT_LOCAL) return;
+  SetLookupState<SetType>* state =
+      reinterpret_cast<SetLookupState<SetType>*>(ctx->GetFunctionState(scope));
+  delete state;
+}
+
+template <typename T, typename SetType>
+BooleanVal InPredicate::SetLookup(SetLookupState<SetType>* state, const T& v) {
+  DCHECK(state != NULL);
+  SetType val = GetVal<T, SetType>(state->type, v);
+  bool found = state->val_set.find(val) != state->val_set.end();
+  if (found) return BooleanVal(true);
+  if (state->contains_null) return BooleanVal::null();
+  return BooleanVal(false);
+}
+
+template <typename T>
+BooleanVal InPredicate::Iterate(
+    const FunctionContext::TypeDesc* type, const T& val, int num_args, const 
T* args) {
+  bool found_null = false;
+  for (int i = 0; i < num_args; ++i) {
+    if (args[i].is_null) {
+      found_null = true;
+    } else if (AnyValUtil::Equals(*type, val, args[i])) {
+      return BooleanVal(true);
+    }
+  }
+  if (found_null) return BooleanVal::null();
+  return BooleanVal(false);
+}
+
+template <typename T, typename SetType>
+inline SetType InPredicate::GetVal(const FunctionContext::TypeDesc* type, 
const T& x) {
+  DCHECK(!x.is_null);
+  return x.val;
+}
+
+template <>
+inline StringValue InPredicate::GetVal(
+    const FunctionContext::TypeDesc* type, const StringVal& x) {
+  DCHECK(!x.is_null);
+  return StringValue::FromStringVal(x);
+}
+
+template <>
+inline TimestampValue InPredicate::GetVal(
+    const FunctionContext::TypeDesc* type, const TimestampVal& x) {
+  return TimestampValue::FromTimestampVal(x);
+}
+
+template <>
+inline Decimal16Value InPredicate::GetVal(
+    const FunctionContext::TypeDesc* type, const DecimalVal& x) {
+  if (type->precision <= ColumnType::MAX_DECIMAL4_PRECISION) {
+    return Decimal16Value(x.val4);
+  } else if (type->precision <= ColumnType::MAX_DECIMAL8_PRECISION) {
+    return Decimal16Value(x.val8);
+  } else {
+    return Decimal16Value(x.val16);
+  }
+}
 }
 
 #endif

Reply via email to