use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class OrderByCompiler method compile.
/**
* Gets a list of columns in the ORDER BY clause
* @param context the query context for tracking various states
* associated with the given select statement
* @param statement TODO
* @param groupBy the list of columns in the GROUP BY clause
* @param limit the row limit or null if no limit
* @return the compiled ORDER BY clause
* @throws SQLException
*/
public static OrderBy compile(StatementContext context, SelectStatement statement, GroupBy groupBy, Integer limit, Integer offset, RowProjector rowProjector, TupleProjector tupleProjector, boolean isInRowKeyOrder) throws SQLException {
List<OrderByNode> orderByNodes = statement.getOrderBy();
if (orderByNodes.isEmpty()) {
return OrderBy.EMPTY_ORDER_BY;
}
// for ungroupedAggregates as GROUP BY expression, check against an empty group by
ExpressionCompiler compiler;
if (groupBy.isUngroupedAggregate()) {
compiler = new ExpressionCompiler(context, GroupBy.EMPTY_GROUP_BY) {
@Override
protected Expression addExpression(Expression expression) {
return expression;
}
@Override
protected void addColumn(PColumn column) {
}
};
} else {
compiler = new ExpressionCompiler(context, groupBy);
}
// accumulate columns in ORDER BY
OrderPreservingTracker tracker = new OrderPreservingTracker(context, groupBy, Ordering.ORDERED, orderByNodes.size(), tupleProjector);
LinkedHashSet<OrderByExpression> orderByExpressions = Sets.newLinkedHashSetWithExpectedSize(orderByNodes.size());
for (OrderByNode node : orderByNodes) {
ParseNode parseNode = node.getNode();
Expression expression = null;
if (parseNode instanceof LiteralParseNode && ((LiteralParseNode) parseNode).getType() == PInteger.INSTANCE) {
Integer index = (Integer) ((LiteralParseNode) parseNode).getValue();
int size = rowProjector.getColumnProjectors().size();
if (index > size || index <= 0) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.PARAM_INDEX_OUT_OF_BOUND).build().buildException();
}
expression = rowProjector.getColumnProjector(index - 1).getExpression();
} else {
expression = node.getNode().accept(compiler);
// Detect mix of aggregate and non aggregates (i.e. ORDER BY txns, SUM(txns)
if (!expression.isStateless() && !compiler.isAggregate()) {
if (statement.isAggregate() || statement.isDistinct()) {
// Detect ORDER BY not in SELECT DISTINCT: SELECT DISTINCT count(*) FROM t ORDER BY x
if (statement.isDistinct()) {
throw new SQLExceptionInfo.Builder(SQLExceptionCode.ORDER_BY_NOT_IN_SELECT_DISTINCT).setMessage(expression.toString()).build().buildException();
}
ExpressionCompiler.throwNonAggExpressionInAggException(expression.toString());
}
}
}
if (!expression.isStateless()) {
boolean isAscending = node.isAscending();
boolean isNullsLast = node.isNullsLast();
tracker.track(expression, isAscending ? SortOrder.ASC : SortOrder.DESC, isNullsLast);
// since this is the order they actually are in.
if (expression.getSortOrder() == SortOrder.DESC) {
isAscending = !isAscending;
}
OrderByExpression orderByExpression = new OrderByExpression(expression, isNullsLast, isAscending);
orderByExpressions.add(orderByExpression);
}
compiler.reset();
}
// we can remove ORDER BY clauses in case of only COUNT(DISTINCT...) clauses
if (orderByExpressions.isEmpty() || groupBy.isUngroupedAggregate()) {
return OrderBy.EMPTY_ORDER_BY;
}
// If we're ordering by the order returned by the scan, we don't need an order by
if (isInRowKeyOrder && tracker.isOrderPreserving()) {
if (tracker.isReverse()) {
// REV_ROW_KEY_ORDER_BY scan would not take effect for a projected table, so don't return it for such table types.
if (context.getConnection().getQueryServices().getProps().getBoolean(QueryServices.USE_REVERSE_SCAN_ATTRIB, QueryServicesOptions.DEFAULT_USE_REVERSE_SCAN) && !context.getScanRanges().useSkipScanFilter() && context.getCurrentTable().getTable().getType() != PTableType.PROJECTED && context.getCurrentTable().getTable().getType() != PTableType.SUBQUERY) {
return OrderBy.REV_ROW_KEY_ORDER_BY;
}
} else {
return OrderBy.FWD_ROW_KEY_ORDER_BY;
}
}
return new OrderBy(Lists.newArrayList(orderByExpressions.iterator()));
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class JoinCompiler method getSubqueryForOptimizedPlan.
private static SelectStatement getSubqueryForOptimizedPlan(HintNode hintNode, List<ColumnDef> dynamicCols, TableRef tableRef, Map<ColumnRef, ColumnRefType> columnRefs, ParseNode where, List<ParseNode> groupBy, List<OrderByNode> orderBy, boolean isWildCardSelect, boolean hasSequence, Map<String, UDFParseNode> udfParseNodes) {
String schemaName = tableRef.getTable().getSchemaName().getString();
TableName tName = TableName.create(schemaName.length() == 0 ? null : schemaName, tableRef.getTable().getTableName().getString());
List<AliasedNode> selectList = new ArrayList<AliasedNode>();
if (isWildCardSelect) {
selectList.add(NODE_FACTORY.aliasedNode(null, WildcardParseNode.INSTANCE));
} else {
for (ColumnRef colRef : columnRefs.keySet()) {
if (colRef.getTableRef().equals(tableRef)) {
ParseNode node = NODE_FACTORY.column(tName, '"' + colRef.getColumn().getName().getString() + '"', null);
if (groupBy != null) {
node = NODE_FACTORY.function(CountAggregateFunction.NAME, Collections.singletonList(node));
}
selectList.add(NODE_FACTORY.aliasedNode(null, node));
}
}
}
String tableAlias = tableRef.getTableAlias();
TableNode from = NODE_FACTORY.namedTable(tableAlias == null ? null : '"' + tableAlias + '"', tName, dynamicCols);
return NODE_FACTORY.select(from, hintNode, false, selectList, where, groupBy, null, orderBy, null, null, 0, groupBy != null, hasSequence, Collections.<SelectStatement>emptyList(), udfParseNodes);
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class JoinCompiler method compilePostFilterExpression.
private static Expression compilePostFilterExpression(StatementContext context, List<ParseNode> postFilters) throws SQLException {
if (postFilters.isEmpty())
return null;
ExpressionCompiler expressionCompiler = new ExpressionCompiler(context);
List<Expression> expressions = new ArrayList<Expression>(postFilters.size());
for (ParseNode postFilter : postFilters) {
expressionCompiler.reset();
Expression expression = postFilter.accept(expressionCompiler);
expressions.add(expression);
}
if (expressions.size() == 1)
return expressions.get(0);
return AndExpression.create(expressions);
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class JoinCompiler method extractFromSelect.
private List<AliasedNode> extractFromSelect(List<AliasedNode> select, TableRef tableRef, ColumnResolver resolver) throws SQLException {
List<AliasedNode> ret = new ArrayList<AliasedNode>();
ColumnRefParseNodeVisitor visitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection());
for (AliasedNode aliasedNode : select) {
ParseNode node = aliasedNode.getNode();
if (node instanceof TableWildcardParseNode) {
TableName tableName = ((TableWildcardParseNode) node).getTableName();
if (tableRef.equals(resolver.resolveTable(tableName.getSchemaName(), tableName.getTableName()))) {
ret.clear();
ret.add(aliasedNode);
return ret;
}
continue;
}
node.accept(visitor);
ColumnRefParseNodeVisitor.ColumnRefType type = visitor.getContentType(Collections.singletonList(tableRef));
if (type == ColumnRefParseNodeVisitor.ColumnRefType.SELF_ONLY) {
ret.add(aliasedNode);
} else if (type == ColumnRefParseNodeVisitor.ColumnRefType.COMPLEX) {
for (Map.Entry<ColumnRef, ColumnParseNode> entry : visitor.getColumnRefMap().entrySet()) {
if (entry.getKey().getTableRef().equals(tableRef)) {
ret.add(NODE_FACTORY.aliasedNode(null, entry.getValue()));
}
}
}
visitor.reset();
}
return ret;
}
use of org.apache.phoenix.parse.ParseNode in project phoenix by apache.
the class JoinCompiler method compile.
public static JoinTable compile(PhoenixStatement statement, SelectStatement select, ColumnResolver resolver) throws SQLException {
JoinCompiler compiler = new JoinCompiler(statement, select, resolver);
JoinTableConstructor constructor = compiler.new JoinTableConstructor();
Pair<Table, List<JoinSpec>> res = select.getFrom().accept(constructor);
JoinTable joinTable = res.getSecond() == null ? compiler.new JoinTable(res.getFirst()) : compiler.new JoinTable(res.getFirst(), res.getSecond());
if (select.getWhere() != null) {
joinTable.addFilter(select.getWhere());
}
ColumnRefParseNodeVisitor generalRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection());
ColumnRefParseNodeVisitor joinLocalRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection());
ColumnRefParseNodeVisitor prefilterRefVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection());
joinTable.pushDownColumnRefVisitors(generalRefVisitor, joinLocalRefVisitor, prefilterRefVisitor);
for (AliasedNode node : select.getSelect()) {
node.getNode().accept(generalRefVisitor);
}
if (select.getGroupBy() != null) {
for (ParseNode node : select.getGroupBy()) {
node.accept(generalRefVisitor);
}
}
if (select.getHaving() != null) {
select.getHaving().accept(generalRefVisitor);
}
if (select.getOrderBy() != null) {
for (OrderByNode node : select.getOrderBy()) {
node.getNode().accept(generalRefVisitor);
}
}
for (ColumnRef ref : generalRefVisitor.getColumnRefMap().keySet()) {
compiler.columnRefs.put(ref, ColumnRefType.GENERAL);
}
for (ColumnRef ref : joinLocalRefVisitor.getColumnRefMap().keySet()) {
if (!compiler.columnRefs.containsKey(ref))
compiler.columnRefs.put(ref, ColumnRefType.JOINLOCAL);
}
return joinTable;
}
Aggregations