/**
* Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com)
*
* Licensed 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.
*/
package com.linkedin.pinot.pql.parsers.pql2.ast;
import com.linkedin.pinot.common.request.BrokerRequest;
import com.linkedin.pinot.common.request.GroupBy;
import com.linkedin.pinot.common.request.QuerySource;
import com.linkedin.pinot.common.request.Selection;
import com.linkedin.pinot.pql.parsers.Pql2CompilationException;
/**
* AST node for a SELECT statement.
*/
public class SelectAstNode extends BaseAstNode {
private String _tableName;
private String _resourceName;
private int _recordLimit = -1;
private int _offset = -1;
private int _topN = -1;
// Optional clauses can be given in any order, so we keep track of whether we've already seen one
private boolean _hasWhereClause = false;
private boolean _hasGroupByClause = false;
private boolean _hasHavingClause = false;
private boolean _hasOrderByClause = false;
private boolean _hasTopClause = false;
private boolean _hasLimitClause = false;
public SelectAstNode() {
}
@Override
public void addChild(AstNode childNode) {
if (childNode instanceof LimitAstNode) {
if (_hasLimitClause) {
throw new Pql2CompilationException("More than one LIMIT clause specified!");
}
LimitAstNode node = (LimitAstNode) childNode;
_recordLimit = node.getCount();
_offset = node.getOffset();
_hasLimitClause = true;
} else if (childNode instanceof TableNameAstNode) {
TableNameAstNode node = (TableNameAstNode) childNode;
_tableName = node.getTableName();
_resourceName = node.getResourceName();
} else if (childNode instanceof TopAstNode) {
if (_hasTopClause) {
throw new Pql2CompilationException("More than one TOP clause specified!");
}
TopAstNode node = (TopAstNode) childNode;
_topN = node.getCount();
_hasTopClause = true;
} else if (childNode instanceof WhereAstNode) {
if (_hasWhereClause) {
throw new Pql2CompilationException("More than one WHERE clause specified!");
}
super.addChild(childNode);
_hasWhereClause = true;
} else if (childNode instanceof GroupByAstNode) {
if (_hasGroupByClause) {
throw new Pql2CompilationException("More than one GROUP BY clause specified!");
}
super.addChild(childNode);
_hasGroupByClause = true;
} else if (childNode instanceof HavingAstNode) {
if (_hasHavingClause) {
throw new Pql2CompilationException("More than one HAVING clause specified!");
}
super.addChild(childNode);
_hasHavingClause = true;
} else if (childNode instanceof OrderByAstNode) {
if (_hasOrderByClause) {
throw new Pql2CompilationException("More than one ORDER BY clause specified!");
}
super.addChild(childNode);
_hasOrderByClause = true;
} else {
super.addChild(childNode);
}
}
@Override
public String toString() {
return "SelectAstNode{" +
"_tableName='" + _tableName + '\'' +
", _resourceName='" + _resourceName + '\'' +
", _recordLimit=" + _recordLimit +
", _offset=" + _offset +
'}';
}
@Override
public void updateBrokerRequest(BrokerRequest brokerRequest) {
// Set the query source
QuerySource querySource = new QuerySource();
querySource.setTableName(_resourceName);
brokerRequest.setQuerySource(querySource);
sendBrokerRequestUpdateToChildren(brokerRequest);
// If there is a selection, set its limit if applicable
Selection selections = brokerRequest.getSelections();
if (selections != null) {
if (_recordLimit != -1) {
selections.setSize(_recordLimit);
}
if (_offset != -1) {
selections.setOffset(_offset);
}
}
// If there is a topN clause, set it on the group by
GroupBy groupBy = brokerRequest.getGroupBy();
if (groupBy != null) {
if (_topN != -1) {
groupBy.setTopN(_topN);
} else {
// Pinot quirk: default to top 10
groupBy.setTopN(10);
}
}
// Pinot quirk: if there is both a selection and an aggregation, remove the selection
if (brokerRequest.getAggregationsInfoSize() != 0 && brokerRequest.isSetSelections()) {
brokerRequest.setSelections(null);
}
}
}