use of org.apache.phoenix.parse.TableNode in project phoenix by apache.
the class SubselectRewriter method flatten.
public static SelectStatement flatten(SelectStatement select, PhoenixConnection connection) throws SQLException {
TableNode from = select.getFrom();
while (from != null && from instanceof DerivedTableNode) {
DerivedTableNode derivedTable = (DerivedTableNode) from;
SelectStatement subselect = derivedTable.getSelect();
if (subselect.isUnion())
break;
ColumnResolver resolver = FromCompiler.getResolverForQuery(subselect, connection);
SubselectRewriter rewriter = new SubselectRewriter(resolver, subselect.getSelect(), derivedTable.getAlias());
SelectStatement ret = rewriter.flatten(select, subselect);
if (ret == select)
break;
select = ret;
from = select.getFrom();
}
return select;
}
use of org.apache.phoenix.parse.TableNode in project phoenix by apache.
the class SubqueryRewriter method visitLeave.
@Override
public ParseNode visitLeave(ComparisonParseNode node, List<ParseNode> l) throws SQLException {
boolean isTopNode = topNode == node;
if (isTopNode) {
topNode = null;
}
ParseNode secondChild = l.get(1);
if (!(secondChild instanceof SubqueryParseNode)) {
return super.visitLeave(node, l);
}
SubqueryParseNode subqueryNode = (SubqueryParseNode) secondChild;
SelectStatement subquery = fixSubqueryStatement(subqueryNode.getSelectNode());
String rhsTableAlias = ParseNodeFactory.createTempAlias();
JoinConditionExtractor conditionExtractor = new JoinConditionExtractor(subquery, resolver, connection, rhsTableAlias);
ParseNode where = subquery.getWhere() == null ? null : subquery.getWhere().accept(conditionExtractor);
if (where == subquery.getWhere()) {
// non-correlated comparison subquery, add LIMIT 2, expectSingleRow = true
subquery = NODE_FACTORY.select(subquery, NODE_FACTORY.limit(NODE_FACTORY.literal(2)));
subqueryNode = NODE_FACTORY.subquery(subquery, true);
l = Lists.newArrayList(l.get(0), subqueryNode);
node = NODE_FACTORY.comparison(node.getFilterOp(), l.get(0), l.get(1));
return super.visitLeave(node, l);
}
ParseNode rhsNode = null;
boolean isGroupby = !subquery.getGroupBy().isEmpty();
boolean isAggregate = subquery.isAggregate();
List<AliasedNode> aliasedNodes = subquery.getSelect();
if (aliasedNodes.size() == 1) {
rhsNode = aliasedNodes.get(0).getNode();
} else {
List<ParseNode> nodes = Lists.<ParseNode>newArrayListWithExpectedSize(aliasedNodes.size());
for (AliasedNode aliasedNode : aliasedNodes) {
nodes.add(aliasedNode.getNode());
}
rhsNode = NODE_FACTORY.rowValueConstructor(nodes);
}
List<AliasedNode> additionalSelectNodes = conditionExtractor.getAdditionalSelectNodes();
List<AliasedNode> selectNodes = Lists.newArrayListWithExpectedSize(additionalSelectNodes.size() + 1);
selectNodes.add(NODE_FACTORY.aliasedNode(ParseNodeFactory.createTempAlias(), rhsNode));
selectNodes.addAll(additionalSelectNodes);
if (!isAggregate) {
subquery = NODE_FACTORY.select(subquery, subquery.isDistinct(), selectNodes, where);
} else {
List<ParseNode> groupbyNodes = Lists.newArrayListWithExpectedSize(additionalSelectNodes.size() + subquery.getGroupBy().size());
for (AliasedNode aliasedNode : additionalSelectNodes) {
groupbyNodes.add(aliasedNode.getNode());
}
groupbyNodes.addAll(subquery.getGroupBy());
subquery = NODE_FACTORY.select(subquery, subquery.isDistinct(), selectNodes, where, groupbyNodes, true);
}
ParseNode onNode = conditionExtractor.getJoinCondition();
TableNode rhsTable = NODE_FACTORY.derivedTable(rhsTableAlias, subquery);
JoinType joinType = isTopNode ? JoinType.Inner : JoinType.Left;
ParseNode ret = NODE_FACTORY.comparison(node.getFilterOp(), l.get(0), NODE_FACTORY.column(NODE_FACTORY.table(null, rhsTableAlias), selectNodes.get(0).getAlias(), null));
tableNode = NODE_FACTORY.join(joinType, tableNode, rhsTable, onNode, !isAggregate || isGroupby);
return ret;
}
use of org.apache.phoenix.parse.TableNode in project phoenix by apache.
the class SubqueryRewriter method visitLeave.
@Override
public ParseNode visitLeave(ExistsParseNode node, List<ParseNode> l) throws SQLException {
boolean isTopNode = topNode == node;
if (isTopNode) {
topNode = null;
}
SubqueryParseNode subqueryNode = (SubqueryParseNode) l.get(0);
SelectStatement subquery = fixSubqueryStatement(subqueryNode.getSelectNode());
String rhsTableAlias = ParseNodeFactory.createTempAlias();
JoinConditionExtractor conditionExtractor = new JoinConditionExtractor(subquery, resolver, connection, rhsTableAlias);
ParseNode where = subquery.getWhere() == null ? null : subquery.getWhere().accept(conditionExtractor);
if (where == subquery.getWhere()) {
// non-correlated EXISTS subquery, add LIMIT 1
subquery = NODE_FACTORY.select(subquery, NODE_FACTORY.limit(NODE_FACTORY.literal(1)));
subqueryNode = NODE_FACTORY.subquery(subquery, false);
node = NODE_FACTORY.exists(subqueryNode, node.isNegate());
return super.visitLeave(node, Collections.<ParseNode>singletonList(subqueryNode));
}
List<AliasedNode> additionalSelectNodes = conditionExtractor.getAdditionalSelectNodes();
List<AliasedNode> selectNodes = Lists.newArrayListWithExpectedSize(additionalSelectNodes.size() + 1);
selectNodes.add(NODE_FACTORY.aliasedNode(ParseNodeFactory.createTempAlias(), LiteralParseNode.ONE));
selectNodes.addAll(additionalSelectNodes);
subquery = NODE_FACTORY.select(subquery, true, selectNodes, where);
ParseNode onNode = conditionExtractor.getJoinCondition();
TableNode rhsTable = NODE_FACTORY.derivedTable(rhsTableAlias, subquery);
JoinType joinType = isTopNode ? (node.isNegate() ? JoinType.Anti : JoinType.Semi) : JoinType.Left;
ParseNode ret = isTopNode ? null : NODE_FACTORY.isNull(NODE_FACTORY.column(NODE_FACTORY.table(null, rhsTableAlias), selectNodes.get(0).getAlias(), null), !node.isNegate());
tableNode = NODE_FACTORY.join(joinType, tableNode, rhsTable, onNode, false);
return ret;
}
use of org.apache.phoenix.parse.TableNode 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.TableNode 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;
}
Aggregations