use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionTable in project ignite by apache.
the class PartitionExtractor method tryExtractBetween.
/**
* Try to extract partitions from {@code op} assuming that it's between operation or simple range.
*
* @param op Sql operation.
* @param tblModel Table model.
* @return {@code PartitionSingleNode} if operation reduced to one partition,
* {@code PartitionGroupNode} if operation reduced to multiple partitions or null if operation is neither
* between nor simple range. Null also returns if it's not possible to extract partitions from given operation.
* @throws IgniteCheckedException If failed.
*/
private PartitionNode tryExtractBetween(GridSqlOperation op, PartitionTableModel tblModel) throws IgniteCheckedException {
// Between operation (or similar range) should contain exact two children.
assert op.size() == 2;
GridSqlAst left = op.child();
GridSqlAst right = op.child(1);
GridSqlOperationType leftOpType = retrieveOperationType(left);
GridSqlOperationType rightOpType = retrieveOperationType(right);
if ((GridSqlOperationType.BIGGER == rightOpType || GridSqlOperationType.BIGGER_EQUAL == rightOpType) && (GridSqlOperationType.SMALLER == leftOpType || GridSqlOperationType.SMALLER_EQUAL == leftOpType)) {
GridSqlAst tmp = left;
left = right;
right = tmp;
} else if (!((GridSqlOperationType.BIGGER == leftOpType || GridSqlOperationType.BIGGER_EQUAL == leftOpType) && (GridSqlOperationType.SMALLER == rightOpType || GridSqlOperationType.SMALLER_EQUAL == rightOpType)))
return null;
// Try parse left AST.
GridSqlColumn leftCol;
if (left instanceof GridSqlOperation && left.child() instanceof GridSqlColumn && (((GridSqlColumn) left.child()).column().getTable() instanceof GridH2Table))
leftCol = left.child();
else
return null;
// Try parse right AST.
GridSqlColumn rightCol;
if (right instanceof GridSqlOperation && right.child() instanceof GridSqlColumn)
rightCol = right.child();
else
return null;
GridH2Table tbl = (GridH2Table) leftCol.column().getTable();
// Check that columns might be used for partition pruning.
if (!tbl.isColumnForPartitionPruning(leftCol.column()))
return null;
// Check that both left and right AST use same column.
if (!F.eq(leftCol.schema(), rightCol.schema()) || !F.eq(leftCol.columnName(), rightCol.columnName()) || !F.eq(leftCol.tableAlias(), rightCol.tableAlias()))
return null;
// Check columns type
if (!(leftCol.column().getType() == Value.BYTE || leftCol.column().getType() == Value.SHORT || leftCol.column().getType() == Value.INT || leftCol.column().getType() == Value.LONG))
return null;
// Try parse left AST right value (value to the right of '>' or '>=').
GridSqlConst leftConst;
if (left.child(1) instanceof GridSqlConst)
leftConst = left.child(1);
else
return null;
// Try parse right AST right value (value to the right of '<' or '<=').
GridSqlConst rightConst;
if (right.child(1) instanceof GridSqlConst)
rightConst = right.child(1);
else
return null;
long leftLongVal;
long rightLongVal;
try {
leftLongVal = leftConst.value().getLong();
rightLongVal = rightConst.value().getLong();
} catch (Exception e) {
return null;
}
// Increment left long value if '>' is used.
if (((GridSqlOperation) left).operationType() == GridSqlOperationType.BIGGER)
leftLongVal++;
// Decrement right long value if '<' is used.
if (((GridSqlOperation) right).operationType() == GridSqlOperationType.SMALLER)
rightLongVal--;
Set<PartitionSingleNode> parts = new HashSet<>();
PartitionTable tbl0 = tblModel.table(leftCol.tableAlias());
// If table is in ignored set, then we cannot use it for partition extraction.
if (tbl0 == null)
return null;
for (long i = leftLongVal; i <= rightLongVal; i++) {
int part = partResolver.partition(i, leftCol.column().getType(), tbl0.cacheName());
parts.add(new PartitionConstantNode(tbl0, part));
if (parts.size() > maxPartsCntBetween)
return null;
}
return parts.isEmpty() ? PartitionNoneNode.INSTANCE : parts.size() == 1 ? parts.iterator().next() : new PartitionGroupNode(parts);
}
use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionTable in project ignite by apache.
the class PartitionExtractor method prepareTable.
/**
* Prepare single table.
*
* @param from Expression.
* @param tblModel Table model.
* @return Added table or {@code null} if table is exlcuded from the model.
*/
private static PartitionTable prepareTable(GridSqlAst from, PartitionTableModel tblModel) {
// Unwrap alias. We assume that every table must be aliased.
assert from instanceof GridSqlAlias;
String alias = ((GridSqlAlias) from).alias();
from = from.child();
if (from instanceof GridSqlTable) {
// Normal table.
GridSqlTable from0 = (GridSqlTable) from;
GridH2Table tbl0 = from0.dataTable();
// Unknown table type, e.g. temp table.
if (tbl0 == null) {
tblModel.addExcludedTable(alias);
return null;
}
String cacheName = tbl0.cacheName();
String affColName = null;
String secondAffColName = null;
for (Column col : tbl0.getColumns()) {
if (tbl0.isColumnForPartitionPruningStrict(col)) {
if (affColName == null)
affColName = col.getName();
else {
secondAffColName = col.getName();
// Break as we cannot have more than two affinity key columns.
break;
}
}
}
PartitionTable tbl = new PartitionTable(alias, cacheName, affColName, secondAffColName);
PartitionTableAffinityDescriptor aff = affinityForCache(tbl0.cacheInfo().config());
if (aff == null) {
// Non-standard affinity, exclude table.
tblModel.addExcludedTable(alias);
return null;
}
tblModel.addTable(tbl, aff);
return tbl;
} else {
// Subquery/union/view, etc.
assert alias != null;
tblModel.addExcludedTable(alias);
return null;
}
}
use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionTable in project ignite by apache.
the class PartitionExtractor method extractSingle.
/**
* Extract single partition.
*
* @param leftCol Left column.
* @param rightConst Right constant.
* @param rightParam Right parameter.
* @param tblModel Table model.
* @return Partition or {@code null} if failed to extract.
*/
@Nullable
private PartitionSingleNode extractSingle(GridSqlColumn leftCol, GridSqlConst rightConst, GridSqlParameter rightParam, PartitionTableModel tblModel) throws IgniteCheckedException {
assert leftCol != null;
Column leftCol0 = leftCol.column();
assert leftCol0.getTable() != null;
assert leftCol0.getTable() instanceof GridH2Table;
GridH2Table tbl = (GridH2Table) leftCol0.getTable();
if (!tbl.isColumnForPartitionPruning(leftCol0))
return null;
PartitionTable tbl0 = tblModel.table(leftCol.tableAlias());
// If table is in ignored set, then we cannot use it for partition extraction.
if (tbl0 == null)
return null;
if (rightConst != null) {
int part = partResolver.partition(rightConst.value().getObject(), leftCol0.getType(), tbl.cacheName());
return new PartitionConstantNode(tbl0, part);
} else if (rightParam != null) {
int colType = leftCol0.getType();
return new PartitionParameterNode(tbl0, partResolver, rightParam.index(), leftCol0.getType(), mappedType(colType));
} else
return null;
}
use of org.apache.ignite.internal.sql.optimizer.affinity.PartitionTable 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();
}
Aggregations