}
return ret;
}
public static SelectStatement optimize(PhoenixStatement statement, SelectStatement select, final ColumnResolver resolver) throws SQLException {
TableRef groupByTableRef = null;
TableRef orderByTableRef = null;
if (select.getGroupBy() != null && !select.getGroupBy().isEmpty()) {
ColumnParseNodeVisitor groupByVisitor = new ColumnParseNodeVisitor(resolver);
for (ParseNode node : select.getGroupBy()) {
node.accept(groupByVisitor);
}
Set<TableRef> set = groupByVisitor.getTableRefSet();
if (set.size() == 1) {
groupByTableRef = set.iterator().next();
}
} else if (select.getOrderBy() != null && !select.getOrderBy().isEmpty()) {
ColumnParseNodeVisitor orderByVisitor = new ColumnParseNodeVisitor(resolver);
for (OrderByNode node : select.getOrderBy()) {
node.getNode().accept(orderByVisitor);
}
Set<TableRef> set = orderByVisitor.getTableRefSet();
if (set.size() == 1) {
orderByTableRef = set.iterator().next();
}
}
JoinTable join = compile(statement, select, resolver);
if (groupByTableRef != null || orderByTableRef != null) {
QueryCompiler compiler = new QueryCompiler(statement, select, resolver);
List<Object> binds = statement.getParameters();
StatementContext ctx = new StatementContext(statement, resolver, new Scan(), new SequenceManager(statement));
QueryPlan plan = compiler.compileJoinQuery(ctx, binds, join, false);
TableRef table = plan.getTableRef();
if (groupByTableRef != null && !groupByTableRef.equals(table)) {
groupByTableRef = null;
}
if (orderByTableRef != null && !orderByTableRef.equals(table)) {
orderByTableRef = null;
}
}
final Map<TableRef, TableRef> replacement = new HashMap<TableRef, TableRef>();
for (Table table : join.getTables()) {
if (table.isSubselect())
continue;
TableRef tableRef = table.getTableRef();
List<ParseNode> groupBy = tableRef.equals(groupByTableRef) ? select.getGroupBy() : null;
List<OrderByNode> orderBy = tableRef.equals(orderByTableRef) ? select.getOrderBy() : null;
SelectStatement stmt = getSubqueryForOptimizedPlan(select.getHint(), table.getDynamicColumns(), tableRef, join.getColumnRefs(), table.getPreFiltersCombined(), groupBy, orderBy, table.isWildCardSelect(), select.hasSequence());
QueryPlan plan = statement.getConnection().getQueryServices().getOptimizer().optimize(statement, stmt);
if (!plan.getTableRef().equals(tableRef)) {
replacement.put(tableRef, plan.getTableRef());
}
}
if (replacement.isEmpty())
return select;
List<TableNode> from = select.getFrom();
List<TableNode> newFrom = Lists.newArrayListWithExpectedSize(from.size());
for (TableNode node : from) {
newFrom.add(node.accept(new TableNodeVisitor<TableNode>() {
private TableRef resolveTable(String alias, TableName name) throws SQLException {
if (alias != null)
return resolver.resolveTable(null, alias);
return resolver.resolveTable(name.getSchemaName(), name.getTableName());
}
private TableName getReplacedTableName(TableRef tableRef) {
String schemaName = tableRef.getTable().getSchemaName().getString();
return TableName.create(schemaName.length() == 0 ? null : schemaName, tableRef.getTable().getTableName().getString());
}
@Override
public TableNode visit(BindTableNode boundTableNode) throws SQLException {
TableRef tableRef = resolveTable(boundTableNode.getAlias(), boundTableNode.getName());
TableRef replaceRef = replacement.get(tableRef);
if (replaceRef == null)
return boundTableNode;
String alias = boundTableNode.getAlias();
return NODE_FACTORY.bindTable(alias == null ? null : '"' + alias + '"', getReplacedTableName(replaceRef));
}
@Override
public TableNode visit(JoinTableNode joinNode) throws SQLException {
TableNode lhs = joinNode.getLHS();
TableNode rhs = joinNode.getRHS();
TableNode lhsReplace = lhs.accept(this);
TableNode rhsReplace = rhs.accept(this);
if (lhs == lhsReplace && rhs == rhsReplace)
return joinNode;
return NODE_FACTORY.join(joinNode.getType(), lhsReplace, rhsReplace, joinNode.getOnNode());
}
@Override
public TableNode visit(NamedTableNode namedTableNode)
throws SQLException {
TableRef tableRef = resolveTable(namedTableNode.getAlias(), namedTableNode.getName());
TableRef replaceRef = replacement.get(tableRef);
if (replaceRef == null)
return namedTableNode;
String alias = namedTableNode.getAlias();
return NODE_FACTORY.namedTable(alias == null ? null : '"' + alias + '"', getReplacedTableName(replaceRef), namedTableNode.getDynamicColumns());