/** * Copyright (C) 2009-2013 FoundationDB, LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.foundationdb.sql.optimizer.plan; import com.foundationdb.server.types.TInstance; import com.foundationdb.server.types.TPreptimeContext; import com.foundationdb.server.types.texpressions.TValidatedAggregator; import com.foundationdb.sql.optimizer.plan.Sort.OrderByExpression; import com.foundationdb.sql.types.DataTypeDescriptor; import com.foundationdb.sql.parser.ValueNode; import java.util.List; /** An expression representing the result (total) of an aggregate function. */ public class AggregateFunctionExpression extends BaseExpression implements ResolvableExpression<TValidatedAggregator> { private String function; private ExpressionNode operand; private boolean distinct; private Object option; private List<OrderByExpression> orderBy; private TValidatedAggregator tAggregator; public AggregateFunctionExpression(String function, ExpressionNode operand, boolean distinct, DataTypeDescriptor sqlType, ValueNode sqlSource, TInstance type, Object option, List<OrderByExpression> orderBy) { super(sqlType, sqlSource, type); this.function = function; this.operand = operand; this.distinct = distinct; this.option = option; this.orderBy = orderBy; } @Override public String getFunction() { return function; } public ExpressionNode getOperand() { return operand; } public boolean isDistinct() { return distinct; } public void setOperand(ExpressionNode operand) { this.operand = operand; } public Object getOption() { return option; } public List<OrderByExpression> getOrderBy() { return orderBy; } @Override public void setResolved(TValidatedAggregator resolved) { this.tAggregator = resolved; } @Override public TValidatedAggregator getResolved() { return tAggregator; } @Override public TPreptimeContext getPreptimeContext() { throw new UnsupportedOperationException(); } @Override public void setPreptimeContext(TPreptimeContext context) { throw new UnsupportedOperationException(); } @Override public boolean equals(Object obj) { if (!(obj instanceof AggregateFunctionExpression)) return false; AggregateFunctionExpression other = (AggregateFunctionExpression)obj; return (function.equals(other.function) && ((operand == null) ? (other.operand == null) : operand.equals(other.operand)) && (distinct == other.distinct) && (option == null ? other.option == null : option.equals(other.option))); } @Override public int hashCode() { int hash = function.hashCode(); if (operand != null) hash += operand.hashCode(); if (distinct) hash ^= 1; return hash; } @Override public boolean accept(ExpressionVisitor v) { if (v.visitEnter(this)) { if (operand != null) operand.accept(v); } return v.visitLeave(this); } @Override public ExpressionNode accept(ExpressionRewriteVisitor v) { boolean childrenFirst = v.visitChildrenFirst(this); if (!childrenFirst) { ExpressionNode result = v.visit(this); if (result != this) return result; } if (operand != null) operand = operand.accept(v); return (childrenFirst) ? v.visit(this) : this; } @Override public String toString() { StringBuilder str = new StringBuilder(function); str.append("("); if (distinct) str.append("DISTINCT "); if (operand == null) str.append("*"); else str.append(operand); str.append(")"); return str.toString(); } @Override protected void deepCopy(DuplicateMap map) { super.deepCopy(map); if (operand != null) operand = (ExpressionNode)operand.duplicate(map); } }