15 package com.cloudera.impala.analysis;
17 import java.util.List;
28 import com.cloudera.impala.common.TreeNode;
29 import com.cloudera.impala.thrift.TAggregateExpr;
30 import com.cloudera.impala.thrift.TExprNode;
31 import com.cloudera.impala.thrift.TExprNodeType;
32 import com.cloudera.impala.thrift.TFunctionBinaryType;
33 import com.google.common.base.Joiner;
34 import com.google.common.base.Objects;
35 import com.google.common.base.Preconditions;
60 this(fnName, params,
false);
69 if (params.
exprs() != null) children_.addAll(params.
exprs());
79 && (fnName.getDb() == null) || Catalog.BUILTINS_DB.equals(fnName.getDb())) {
82 return new CaseExpr(functionCallExpr);
84 return functionCallExpr;
93 Preconditions.checkState(agg.isAnalyzed_);
94 Preconditions.checkState(agg.isAggregateFunction());
99 result.type_ = agg.type_;
102 result.label_ = agg.label_;
106 agg.fnName_.toString() +
":merge");
108 Preconditions.checkState(!result.type_.isWildcardDecimal());
140 if (!super.equals(obj))
return false;
142 return fnName_.equals(o.fnName_) &&
152 StringBuilder sb =
new StringBuilder();
153 sb.append(
fnName_).append(
"(");
156 sb.append(Joiner.on(
", ").join(
childrenToSql())).append(
")");
157 return sb.toString();
162 return Objects.toStringHelper(
this)
164 .add(
"isStar", params_.isStar())
165 .add(
"isDistinct", params_.isDistinct())
166 .addValue(super.debugString())
172 Preconditions.checkNotNull(
fn_);
177 Preconditions.checkNotNull(
fn_);
178 return fn_.getReturnType();
185 Preconditions.checkNotNull(
fn_);
194 Preconditions.checkNotNull(
fn_);
201 return params_.isDistinct();
211 msg.node_type = TExprNodeType.AGGREGATE_EXPR;
214 msg.node_type = TExprNodeType.FUNCTION_CALL;
224 return super.isConstant();
235 return "'*' can only be used in conjunction with COUNT";
239 return "COUNT must have DISTINCT for multiple arguments: " +
toSql();
243 return "SUM requires a numeric parameter: " +
toSql();
246 return "AVG requires a numeric or timestamp parameter: " +
toSql();
250 String[] argTypesSql =
new String[argTypes.length];
251 for (
int i = 0; i < argTypes.length; ++i) {
252 argTypesSql[i] = argTypes[i].toSql();
254 return String.format(
255 "No matching function with signature: %s(%s).",
256 fnName_, params_.isStar() ?
"*" : Joiner.on(
", ").join(argTypesSql));
271 Preconditions.checkState(type_.isWildcardDecimal());
272 Preconditions.checkState(fn_.getBinaryType() == TFunctionBinaryType.BUILTIN);
273 Preconditions.checkState(children_.size() > 0);
278 for (
Expr child : children_) {
279 if (child.type_.isDecimal()) {
284 Preconditions.checkState(childType != null && !childType.isWildcardDecimal());
285 Type returnType = childType;
288 return childType.getMaxResolutionType();
291 int digitsBefore = childType.decimalPrecision() - childType.
decimalScale();
292 int digitsAfter = childType.decimalScale();
302 if (children_.size() > 1) {
305 Preconditions.checkState(children_.size() == 2);
306 if (children_.get(1).isNullLiteral()) {
308 "() cannot be called with a NULL second argument.");
311 if (!children_.get(1).isConstant()) {
318 "() must be called with a constant second argument.");
321 children_.get(1), analyzer.getQueryCtx());
330 digitsAfter = Math.max(digitsAfter, 0);
343 Preconditions.checkState(returnType.isDecimal() && !returnType.
isWildcardDecimal());
344 return ScalarType.createDecimalTypeInternal(digitsBefore + digitsAfter, digitsAfter);
350 super.analyze(analyzer);
351 fnName_.analyze(analyzer);
358 Preconditions.checkNotNull(aggFn);
359 Type intermediateType = aggFn.getIntermediateType();
360 if (intermediateType == null) intermediateType =
type_;
361 Preconditions.checkState(!type_.isWildcardDecimal());
378 argTypes =
new Type[0];
380 fn_ = db.getFunction(searchDesc, Function.CompareMode.IS_SUPERTYPE_OF);
381 type_ = fn_.getReturnType();
383 for (
int i = 0; i < children_.size(); ++i) {
384 if (getChild(i).getType().isNull()) {
397 children_.size() == 1 && children_.get(0).
getType().isStringType()) {
399 "AVG requires a numeric or timestamp parameter: " +
toSql());
403 fn_ = db.getFunction(searchDesc, Function.CompareMode.IS_SUPERTYPE_OF);
413 "aggregate function must not contain aggregate parameters: " + this.
toSql());
419 "aggregate function must not contain analytic parameters: " + this.
toSql());
451 "Analytic function requires an OVER clause: " +
toSql());
455 type_ = fn_.getReturnType();
474 if (params.isStar()) {
477 if (params.isDistinct()) {
void toThrift(TExprNode msg)
final FunctionParams params_
boolean isWildcardDecimal()
List< String > childrenToSql()
void setIsAnalyticFnCall(boolean v)
boolean ignoresDistinct()
void uncheckedCastChild(Type targetType, int childIndex)
FunctionCallExpr(FunctionName fnName, List< Expr > params)
boolean isInternalFnCall_
final FunctionName fnName_
boolean returnsNonNullOnEmpty()
static com.google.common.base.Predicate< Expr > isAggregatePredicate()
void castForFunctionCall(boolean ignoreWildcardDecimals)
String getFunctionNotFoundError(Type[] argTypes)
TFunctionBinaryType getBinaryType()
static final ScalarType STRING
static LiteralExpr create(String value, Type type)
static Expr createExpr(FunctionName fnName, FunctionParams params)
void setIsInternalFnCall(boolean v)
boolean isScalarFunction()
static void validateScalarFnParams(FunctionParams params)
static final ScalarType BOOLEAN
static final int MAX_SCALE
FunctionParams getParams()
Type[] collectChildReturnTypes()
final boolean isMergeAggFn_
FunctionCallExpr(FunctionCallExpr other)
FunctionCallExpr(String functionName, List< Expr > params)
FunctionCallExpr(FunctionName fnName, FunctionParams params, boolean isMergeAggFn)
boolean isAnalyticFnCall_
Type resolveDecimalReturnType(Analyzer analyzer)
void setIsDistinct(boolean v)
ArrayList< String > getFnNamePath()
static FunctionCallExpr createMergeAggCall(FunctionCallExpr agg, List< Expr > params)
void resetAnalysisState()
boolean isAggregateFunction()
boolean containsFunction(String name)
void analyze(Analyzer analyzer)
static final ScalarType INVALID
FunctionCallExpr(FunctionName fnName, FunctionParams params)
final PrimitiveType type_
boolean equals(Object obj)