use of org.apache.phoenix.parse.SelectStatement in project phoenix by apache.
the class QueryCompiler method compileJoinQuery.
/**
* Call compileJoinQuery() for join queries recursively down to the leaf JoinTable nodes.
* If it is a leaf node, call compileSingleFlatQuery() or compileSubquery(), otherwise:
* 1) If option COST_BASED_OPTIMIZER_ENABLED is on and stats are available, return the
* join plan with the best cost. Note that the "best" plan is only locally optimal,
* and might or might not be globally optimal.
* 2) Otherwise, return the join plan compiled with the default strategy.
* @see JoinCompiler.JoinTable#getApplicableJoinStrategies()
*/
protected QueryPlan compileJoinQuery(StatementContext context, List<Object> binds, JoinTable joinTable, boolean asSubquery, boolean projectPKColumns, List<OrderByNode> orderBy) throws SQLException {
if (joinTable.getJoinSpecs().isEmpty()) {
Table table = joinTable.getTable();
SelectStatement subquery = table.getAsSubquery(orderBy);
if (!table.isSubselect()) {
context.setCurrentTable(table.getTableRef());
PTable projectedTable = table.createProjectedTable(!projectPKColumns, context);
TupleProjector projector = new TupleProjector(projectedTable);
TupleProjector.serializeProjectorIntoScan(context.getScan(), projector);
context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable, context.getConnection(), subquery.getUdfParseNodes()));
table.projectColumns(context.getScan());
return compileSingleFlatQuery(context, subquery, binds, asSubquery, !asSubquery, null, projectPKColumns ? projector : null, true);
}
QueryPlan plan = compileSubquery(subquery, false);
PTable projectedTable = table.createProjectedTable(plan.getProjector());
context.setResolver(FromCompiler.getResolverForProjectedTable(projectedTable, context.getConnection(), subquery.getUdfParseNodes()));
return new TupleProjectionPlan(plan, new TupleProjector(plan.getProjector()), table.compilePostFilterExpression(context));
}
List<JoinCompiler.Strategy> strategies = joinTable.getApplicableJoinStrategies();
assert strategies.size() > 0;
if (!costBased || strategies.size() == 1) {
return compileJoinQuery(strategies.get(0), context, binds, joinTable, asSubquery, projectPKColumns, orderBy);
}
QueryPlan bestPlan = null;
Cost bestCost = null;
for (JoinCompiler.Strategy strategy : strategies) {
StatementContext newContext = new StatementContext(context.getStatement(), context.getResolver(), new Scan(), context.getSequenceManager());
QueryPlan plan = compileJoinQuery(strategy, newContext, binds, joinTable, asSubquery, projectPKColumns, orderBy);
Cost cost = plan.getCost();
if (bestPlan == null || cost.compareTo(bestCost) < 0) {
bestPlan = plan;
bestCost = cost;
}
}
context.setResolver(bestPlan.getContext().getResolver());
context.setCurrentTable(bestPlan.getContext().getCurrentTable());
return bestPlan;
}
use of org.apache.phoenix.parse.SelectStatement in project phoenix by apache.
the class MetaDataClient method getParentOfView.
private PTable getParentOfView(PTable view) throws SQLException {
// TODO just use view.getParentName().getString() after implementing https://issues.apache.org/jira/browse/PHOENIX-2114
SelectStatement select = new SQLParser(view.getViewStatement()).parseQuery();
String parentName = SchemaUtil.normalizeFullTableName(select.getFrom().toString().trim());
return connection.getTable(new PTableKey(view.getTenantId(), parentName));
}
use of org.apache.phoenix.parse.SelectStatement in project phoenix by apache.
the class JoinCompiler method optimize.
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()) {
ColumnRefParseNodeVisitor groupByVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection());
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()) {
ColumnRefParseNodeVisitor orderByVisitor = new ColumnRefParseNodeVisitor(resolver, statement.getConnection());
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, false);
List<Object> binds = statement.getParameters();
StatementContext ctx = new StatementContext(statement, resolver, new Scan(), new SequenceManager(statement));
QueryPlan plan = compiler.compileJoinQuery(ctx, binds, join, false, false, null);
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(), select.getUdfParseNodes());
QueryPlan plan = statement.getConnection().getQueryServices().getOptimizer().optimize(statement, stmt);
if (!plan.getTableRef().equals(tableRef)) {
replacement.put(tableRef, plan.getTableRef());
}
}
if (replacement.isEmpty())
return select;
TableNode from = select.getFrom();
TableNode newFrom = from.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(), joinNode.isSingleValueOnly());
}
@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());
}
@Override
public TableNode visit(DerivedTableNode subselectNode) throws SQLException {
return subselectNode;
}
});
SelectStatement indexSelect = IndexStatementRewriter.translate(NODE_FACTORY.select(select, newFrom), resolver, replacement);
for (TableRef indexTableRef : replacement.values()) {
// replace expressions with corresponding matching columns for functional indexes
indexSelect = ParseNodeRewriter.rewrite(indexSelect, new IndexExpressionParseNodeRewriter(indexTableRef.getTable(), indexTableRef.getTableAlias(), statement.getConnection(), indexSelect.getUdfParseNodes()));
}
return indexSelect;
}
use of org.apache.phoenix.parse.SelectStatement in project phoenix by apache.
the class QueryCompiler method compileSingleQuery.
protected QueryPlan compileSingleQuery(StatementContext context, SelectStatement select, List<Object> binds, boolean asSubquery, boolean allowPageFilter) throws SQLException {
SelectStatement innerSelect = select.getInnerSelectStatement();
if (innerSelect == null) {
return compileSingleFlatQuery(context, select, binds, asSubquery, allowPageFilter, null, null, true);
}
QueryPlan innerPlan = compileSubquery(innerSelect, false);
TupleProjector tupleProjector = new TupleProjector(innerPlan.getProjector());
innerPlan = new TupleProjectionPlan(innerPlan, tupleProjector, null);
// Replace the original resolver and table with those having compiled type info.
TableRef tableRef = context.getResolver().getTables().get(0);
ColumnResolver resolver = FromCompiler.getResolverForCompiledDerivedTable(statement.getConnection(), tableRef, innerPlan.getProjector());
context.setResolver(resolver);
tableRef = resolver.getTables().get(0);
context.setCurrentTable(tableRef);
boolean isInRowKeyOrder = innerPlan.getGroupBy() == GroupBy.EMPTY_GROUP_BY && innerPlan.getOrderBy() == OrderBy.EMPTY_ORDER_BY;
return compileSingleFlatQuery(context, select, binds, asSubquery, allowPageFilter, innerPlan, tupleProjector, isInRowKeyOrder);
}
use of org.apache.phoenix.parse.SelectStatement in project phoenix by apache.
the class QueryCompiler method compileUnionAll.
public QueryPlan compileUnionAll(SelectStatement select) throws SQLException {
List<SelectStatement> unionAllSelects = select.getSelects();
List<QueryPlan> plans = new ArrayList<QueryPlan>();
for (int i = 0; i < unionAllSelects.size(); i++) {
SelectStatement subSelect = unionAllSelects.get(i);
// Push down order-by and limit into sub-selects.
if (!select.getOrderBy().isEmpty() || select.getLimit() != null) {
if (select.getOffset() == null) {
subSelect = NODE_FACTORY.select(subSelect, select.getOrderBy(), select.getLimit(), null);
} else {
subSelect = NODE_FACTORY.select(subSelect, select.getOrderBy(), null, null);
}
}
QueryPlan subPlan = compileSubquery(subSelect, true);
plans.add(subPlan);
}
TableRef tableRef = UnionCompiler.contructSchemaTable(statement, plans, select.hasWildcard() ? null : select.getSelect());
ColumnResolver resolver = FromCompiler.getResolver(tableRef);
StatementContext context = new StatementContext(statement, resolver, scan, sequenceManager);
QueryPlan plan = compileSingleFlatQuery(context, select, statement.getParameters(), false, false, null, null, false);
plan = new UnionPlan(context, select, tableRef, plan.getProjector(), plan.getLimit(), plan.getOffset(), plan.getOrderBy(), GroupBy.EMPTY_GROUP_BY, plans, context.getBindManager().getParameterMetaData());
return plan;
}
Aggregations