use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.
the class PartitionExtractor method extractFromIn.
/**
* Extract partition information from IN.
*
* @param op Operation.
* @param tblModel Table model.
* @return Partition.
*/
private PartitionNode extractFromIn(GridSqlOperation op, PartitionTableModel tblModel) throws IgniteCheckedException {
// Operation should contain at least two children: left (column) and right (const or column).
if (op.size() < 2)
return PartitionAllNode.INSTANCE;
// Left operand should be column.
GridSqlAst left = op.child();
GridSqlColumn leftCol = unwrapColumn(left);
if (leftCol == null)
return PartitionAllNode.INSTANCE;
// Can work only with Ignite tables.
if (!(leftCol.column().getTable() instanceof GridH2Table))
return PartitionAllNode.INSTANCE;
Set<PartitionSingleNode> parts = new HashSet<>();
for (int i = 1; i < op.size(); i++) {
GridSqlAst right = op.child(i);
GridSqlConst rightConst;
GridSqlParameter rightParam;
if (right instanceof GridSqlConst) {
rightConst = (GridSqlConst) right;
rightParam = null;
} else if (right instanceof GridSqlParameter) {
rightConst = null;
rightParam = (GridSqlParameter) right;
} else
// set globally. Hence, returning null.
return PartitionAllNode.INSTANCE;
// Extract.
PartitionSingleNode part = extractSingle(leftCol, rightConst, rightParam, tblModel);
// Same thing as above: single unknown partition in disjunction defeats optimization.
if (part == null)
return PartitionAllNode.INSTANCE;
parts.add(part);
}
return parts.size() == 1 ? parts.iterator().next() : new PartitionGroupNode(parts);
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.
the class PartitionExtractor method parseJoinCondition.
/**
* Try parsing condition as simple JOIN codition. Only equijoins are supported for now, so anything more complex
* than "A.a = B.b" are not processed.
*
* @param on Initial AST.
* @return Join condition or {@code null} if not simple equijoin.
*/
private static PartitionJoinCondition parseJoinCondition(GridSqlElement on) {
if (on instanceof GridSqlOperation) {
GridSqlOperation on0 = (GridSqlOperation) on;
if (on0.operationType() == GridSqlOperationType.EQUAL) {
// Check for cross-join first.
GridSqlConst leftConst = unwrapConst(on0.child(0));
GridSqlConst rightConst = unwrapConst(on0.child(1));
if (leftConst != null && rightConst != null) {
try {
int leftConstval = leftConst.value().getInt();
int rightConstVal = rightConst.value().getInt();
if (leftConstval == rightConstVal)
return PartitionJoinCondition.CROSS;
} catch (Exception ignore) {
// No-op.
}
}
// This is not cross-join, neither normal join between columns.
if (leftConst != null || rightConst != null)
return null;
// Check for normal equi-join.
GridSqlColumn left = unwrapColumn(on0.child(0));
GridSqlColumn right = unwrapColumn(on0.child(1));
if (left != null && right != null) {
String leftAlias = left.tableAlias();
String rightAlias = right.tableAlias();
String leftCol = left.columnName();
String rightCol = right.columnName();
return new PartitionJoinCondition(leftAlias, rightAlias, leftCol, rightCol);
}
}
}
return null;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.
the class DmlAstUtils method findKeyValueEqualityCondition.
/**
* @param where Element to test.
* @return Whether given element corresponds to {@code WHERE _key = ?}, and key is a literal expressed
* in query or a query param.
*/
@SuppressWarnings("RedundantCast")
private static IgnitePair<GridSqlElement> findKeyValueEqualityCondition(GridSqlElement where) {
if (!(where instanceof GridSqlOperation))
return null;
GridSqlOperation whereOp = (GridSqlOperation) where;
// Does this WHERE limit only by _key?
if (isKeyEqualityCondition(whereOp))
return new IgnitePair<>((GridSqlElement) whereOp.child(1), null);
// Or maybe it limits both by _key and _val?
if (whereOp.operationType() != GridSqlOperationType.AND)
return null;
GridSqlElement left = whereOp.child(0);
GridSqlElement right = whereOp.child(1);
if (!(left instanceof GridSqlOperation && right instanceof GridSqlOperation))
return null;
GridSqlOperation leftOp = (GridSqlOperation) left;
GridSqlOperation rightOp = (GridSqlOperation) right;
if (isKeyEqualityCondition(leftOp)) {
// _key = ? and _val = ?
if (!isValueEqualityCondition(rightOp))
return null;
return new IgnitePair<>((GridSqlElement) leftOp.child(1), (GridSqlElement) rightOp.child(1));
} else if (isKeyEqualityCondition(rightOp)) {
// _val = ? and _key = ?
if (!isValueEqualityCondition(leftOp))
return null;
return new IgnitePair<>((GridSqlElement) rightOp.child(1), (GridSqlElement) leftOp.child(1));
} else
// Neither
return null;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation 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;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperation in project ignite by apache.
the class GridSubqueryJoinOptimizer method isSimpleSelect.
/**
* Whether Select query is simple or not.
* <p>
* We call query simple if it is select query (not union) and it has neither having nor grouping,
* has no distinct clause, has no aggregations, has no limits, no sorting, no offset clause.
* Also it is not SELECT FOR UPDATE.
*
* @param subQry Sub query.
* @return {@code true} if it is simple query.
*/
private static boolean isSimpleSelect(GridSqlQuery subQry) {
if (subQry instanceof GridSqlUnion)
return false;
GridSqlSelect select = (GridSqlSelect) subQry;
boolean simple = F.isEmpty(select.sort()) && select.offset() == null && select.limit() == null && !select.isForUpdate() && !select.distinct() && select.havingColumn() < 0 && F.isEmpty(select.groupColumns());
if (!simple)
return false;
for (GridSqlAst col : select.columns(true)) {
if (!(col instanceof GridSqlElement))
continue;
// we have to traverse the tree because there may be such expressions
// like ((MAX(col) - MIN(col)) / COUNT(col)
ASTNodeFinder aggFinder = new ASTNodeFinder(col, (p, c) -> p instanceof GridSqlAggregateFunction);
if (aggFinder.findNext() != null)
return false;
// In case of query like "SELECT * FROM (SELECT i||j FROM t) u;", where subquery contains pure operation
// without an alias, we cannot determine which generated alias in the parent query the original expression
// belongs to. So the best we can do is skip the case.
ASTNodeFinder operationFinder = new ASTNodeFinder(col, (p, c) -> p instanceof GridSqlOperation, ast -> false);
if (operationFinder.findNext() != null)
return false;
}
return true;
}
Aggregations