use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlJoin in project ignite by apache.
the class PartitionExtractor method prepareTableModel0.
/**
* Prepare tables which will be used in join model.
*
* @param from From flag.
* @param model Table model.
* @return {@code True} if extracted tables successfully, {@code false} if failed to extract.
*/
private List<PartitionTable> prepareTableModel0(GridSqlAst from, PartitionTableModel model) {
if (from instanceof GridSqlJoin) {
// Process JOIN recursively.
GridSqlJoin join = (GridSqlJoin) from;
List<PartitionTable> leftTbls = prepareTableModel0(join.leftTable(), model);
List<PartitionTable> rightTbls = prepareTableModel0(join.rightTable(), model);
if (join.isLeftOuter()) {
// If a condition is met on "b" afterwards, we will ignore it.
for (PartitionTable rightTbl : rightTbls) model.addExcludedTable(rightTbl.alias());
return leftTbls;
}
// Extract equi-join or cross-join from condition. For normal INNER JOINs most likely we will have "1=1"
// cross join here, real join condition will be found in WHERE clause later.
PartitionJoinCondition cond = parseJoinCondition(join.on());
if (cond != null && !cond.cross())
model.addJoin(cond);
ArrayList<PartitionTable> res = new ArrayList<>(leftTbls.size() + rightTbls.size());
res.addAll(leftTbls);
res.addAll(rightTbls);
return res;
}
PartitionTable tbl = prepareTable(from, model);
return tbl != null ? Collections.singletonList(tbl) : Collections.emptyList();
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlJoin in project ignite by apache.
the class GridSubqueryJoinOptimizer method pullOutSubQryFromSelectExpr.
/**
* Pull out sub-select from SELECT clause to the parent select level.
* <p>
* Example:
* <pre>
* Before:
* SELECT name,
* (SELECT name FROM dep d WHERE d.id = e.dep_id) as dep_name
* FROM emp e
* WHERE sal > 2000
*
* After:
* SELECT name,
* d.name as dep_name
* FROM emp e
* LEFT JOIN dep d
* ON d.id = e.dep_id
* WHERE sal > 2000
* </pre>
*
* @param parent Parent select.
* @param targetEl Target sql element. Can be {@code null}.
* @param childInd Column ind.
*/
private static boolean pullOutSubQryFromSelectExpr(GridSqlSelect parent, @Nullable GridSqlAst targetEl, int childInd) {
GridSqlSubquery subQry = targetEl != null ? targetEl.child(childInd) : (GridSqlSubquery) parent.columns(false).get(childInd);
if (!subQueryCanBePulledOut(subQry))
return false;
GridSqlSelect subS = subQry.subquery();
if (subS.allColumns() != 1)
return false;
GridSqlAst subCol = GridSqlAlias.unwrap(subS.columns(false).get(0));
if (subCol instanceof GridSqlConst)
return false;
if (targetEl != null)
targetEl.child(childInd, subCol);
else
parent.setColumn(childInd, subCol);
GridSqlElement parentFrom = parent.from() instanceof GridSqlElement ? (GridSqlElement) parent.from() : new GridSqlSubquery((GridSqlQuery) parent.from());
parent.from(new GridSqlJoin(parentFrom, GridSqlAlias.unwrap(subS.from()), true, (GridSqlElement) subS.where())).child();
return true;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlJoin in project ignite by apache.
the class GridSubqueryJoinOptimizer method pullOutSubQryFromExistsClause.
/**
* Pull out sub-select from EXISTS clause to the parent select level.
* <p>
* Example:
* <pre>
* Before:
* SELECT name
* FROM emp e
* WHERE EXISTS (SELECT 1 FROM dep d WHERE d.id = e.dep_id and d.name = 'dep1')
* AND sal > 2000
*
* After:
* SELECT name
* FROM emp e
* JOIN dep d
* WHERE sal > 2000 AND d.id = e.dep_id and d.name = 'dep1
* </pre>
*
* @param parent Parent select.
* @param targetEl Target sql element. Can be null.
* @param childInd Column ind.
*/
private static boolean pullOutSubQryFromExistsClause(GridSqlSelect parent, @Nullable GridSqlAst targetEl, int childInd) {
// extract sub-query
GridSqlSubquery subQry = targetEl != null ? targetEl.child(childInd).child() : parent.where().child();
if (!subQueryCanBePulledOut(subQry))
return false;
GridSqlSelect subS = subQry.subquery();
if (targetEl != null)
targetEl.child(childInd, subS.where());
else
parent.where(subS.where());
GridSqlElement parentFrom = parent.from() instanceof GridSqlElement ? (GridSqlElement) parent.from() : new GridSqlSubquery((GridSqlQuery) parent.from());
parent.from(new GridSqlJoin(parentFrom, GridSqlAlias.unwrap(subS.from()), false, null)).child();
return true;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlJoin in project ignite by apache.
the class SqlAstTraverser method lookForPartitionedJoin.
/**
* Traverse AST while join operation isn't found. Check it if found.
*
* @param ast AST item to check recursively.
* @param upWhere Where condition that applies to this ast.
*/
private void lookForPartitionedJoin(GridSqlAst ast, GridSqlAst upWhere) {
if (ast == null)
return;
GridSqlJoin join = null;
GridSqlAst where = null;
if (ast instanceof GridSqlJoin) {
join = (GridSqlJoin) ast;
where = upWhere;
} else if (ast instanceof GridSqlSelect) {
GridSqlSelect select = (GridSqlSelect) ast;
if (select.from() instanceof GridSqlJoin) {
join = (GridSqlJoin) select.from();
where = select.where();
}
} else if (ast instanceof GridSqlSubquery)
hasSubQueries = true;
else if (ast instanceof GridSqlTable)
hasPartitionedTables |= ((GridSqlTable) ast).dataTable().isPartitioned();
// No joins on this level. Traverse AST deeper.
if (join == null) {
for (int i = 0; i < ast.size(); i++) lookForPartitionedJoin(ast.child(i), null);
return;
}
// Check WHERE clause first.
lookForPartitionedJoin(where, null);
// Check left side of join.
GridSqlTable leftTable = getTable(join.leftTable());
GridH2Table left = null;
// Left side of join is a subquery.
if (leftTable == null) {
hasSubQueries = true;
// Check subquery on left side.
lookForPartitionedJoin(join.leftTable(), where);
} else {
left = leftTable.dataTable();
// Data table is NULL for views.
if (left != null && left.isPartitioned())
hasPartitionedTables = true;
}
// Check right side of join.
GridSqlTable rightTable = getTable(join.rightTable());
// Right side of join is a subquery.
if (rightTable == null) {
hasSubQueries = true;
// Check subquery and return (can't exctract more info there).
lookForPartitionedJoin(join.rightTable(), where);
return;
}
GridH2Table right = rightTable.dataTable();
if (right != null && right.isPartitioned())
hasPartitionedTables = true;
// Skip check of views.
if (left == null || right == null)
return;
if (join.isLeftOuter() && !left.isPartitioned() && right.isPartitioned())
hasOuterJoinReplicatedPartitioned = true;
// Skip check if at least one of tables isn't partitioned.
if (!(left.isPartitioned() && right.isPartitioned()))
return;
if (!distributedJoins)
checkPartitionedJoin(join, where, left, right, log);
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlJoin in project ignite by apache.
the class GridSubqueryJoinOptimizer method pullOutSubQryFromTableList.
/**
* Pull out sub-select from table list.
* <p>
* Example:
* <pre>
* Before:
* SELECT d.name
* FROM emp e,
* (select * from dep) d
* WHERE e.dep_id = d.id
* AND e.sal > 2000
*
* After:
* SELECT d.name
* FROM emp e
* JOIN dep d
* WHERE sal > 2000 AND d.id = e.dep_id
* </pre>
*
* @param parent Parent select.
* @param target Target sql element. Can be {@code null}.
* @param childInd Column index.
*/
private static boolean pullOutSubQryFromTableList(GridSqlSelect parent, @Nullable GridSqlAst target, int childInd) {
if (target != null && !ELEMENT_IS_JOIN.test(target))
return false;
GridSqlAlias wrappedSubQry = target != null ? target.child(childInd) : (GridSqlAlias) parent.from();
GridSqlSubquery subQry = GridSqlAlias.unwrap(wrappedSubQry);
if (!isSimpleSelect(subQry.subquery()))
return false;
GridSqlSelect subSel = subQry.subquery();
if (!(subSel.from() instanceof GridSqlAlias) && !(subSel.from() instanceof GridSqlTable))
// we can't deal with joins and others right now
return false;
GridSqlAlias subTbl = new GridSqlAlias(wrappedSubQry.alias(), GridSqlAlias.unwrap(subSel.from()));
if (target == null)
// it's true only when the subquery is only table in the table list
// so we can safely replace entire FROM expression of the parent
parent.from(subTbl);
else
target.child(childInd, subTbl);
GridSqlAst where = subSel.where();
if (where != null) {
if (target != null) {
GridSqlJoin join = (GridSqlJoin) target;
join.child(GridSqlJoin.ON_CHILD, new GridSqlOperation(AND, join.on(), where));
} else
parent.where(parent.where() == null ? where : new GridSqlOperation(AND, parent.where(), where));
}
remapColumns(parent, subSel, // reference equality used intentionally here
col -> wrappedSubQry == col.expressionInFrom(), subTbl);
return true;
}
Aggregations