use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.
the class PartitionExtractor method extractFromEqual.
/**
* Extract partition information from equality.
*
* @param op Operation.
* @param tblModel Table model.
* @param disjunct Disjunction flag. When set possible join expression will not be processed.
* @return Partition.
*/
private PartitionNode extractFromEqual(GridSqlOperation op, PartitionTableModel tblModel, boolean disjunct) throws IgniteCheckedException {
assert op.operationType() == GridSqlOperationType.EQUAL;
GridSqlElement left = op.child(0);
GridSqlElement right = op.child(1);
GridSqlColumn leftCol = unwrapColumn(left);
if (leftCol == null)
return PartitionAllNode.INSTANCE;
if (!(leftCol.column().getTable() instanceof GridH2Table))
return PartitionAllNode.INSTANCE;
GridSqlConst rightConst;
GridSqlParameter rightParam;
if (right instanceof GridSqlConst) {
rightConst = (GridSqlConst) right;
rightParam = null;
} else if (right instanceof GridSqlParameter) {
rightConst = null;
rightParam = (GridSqlParameter) right;
} else {
if (right instanceof GridSqlColumn) {
if (!disjunct) {
PartitionJoinCondition cond = parseJoinCondition(op);
if (cond != null && !cond.cross())
tblModel.addJoin(cond);
}
}
return PartitionAllNode.INSTANCE;
}
PartitionSingleNode part = extractSingle(leftCol, rightConst, rightParam, tblModel);
return part != null ? part : PartitionAllNode.INSTANCE;
}
use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table 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.processors.query.h2.opt.GridH2Table 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.processors.query.h2.opt.GridH2Table in project ignite by apache.
the class UpdatePlanBuilder method verifyUpdateColumns.
/**
* Check that UPDATE statement affects no key columns.
*
* @param statement Statement.
*/
private static void verifyUpdateColumns(GridSqlStatement statement) {
if (!(statement instanceof GridSqlUpdate))
return;
GridSqlUpdate update = (GridSqlUpdate) statement;
GridSqlElement updTarget = update.target();
Set<GridSqlTable> tbls = new HashSet<>();
DmlAstUtils.collectAllGridTablesInTarget(updTarget, tbls);
if (tbls.size() != 1)
throw new IgniteSQLException("Failed to determine target table for UPDATE", IgniteQueryErrorCode.TABLE_NOT_FOUND);
GridSqlTable tbl = tbls.iterator().next();
GridH2Table gridTbl = tbl.dataTable();
if (gridTbl != null && updateAffectsKeyColumns(gridTbl, update.set().keySet()))
throw new IgniteSQLException("SQL UPDATE can't modify key or its fields directly", IgniteQueryErrorCode.KEY_UPDATE);
if (gridTbl != null)
verifyDmlColumns(gridTbl, F.viewReadOnly(update.cols(), TO_H2_COL));
}
use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.
the class UpdatePlanBuilder method verifyDmlColumns.
/**
* Checks that DML query (insert, merge, update, bulk load aka copy) columns: <br/>
* 1) doesn't contain both entire key (_key or alias) and columns referring to part of the key; <br/>
* 2) doesn't contain both entire value (_val or alias) and columns referring to part of the value. <br/>
*
* @param tab - updated table.
* @param affectedCols - table's column names affected by dml query. Their order should be the same as in the
* dml statement only to have the same columns order in the error message.
* @throws IgniteSQLException if check failed.
*/
private static void verifyDmlColumns(GridH2Table tab, Collection<Column> affectedCols) {
GridH2RowDescriptor desc = tab.rowDescriptor();
// _key (_val) or it alias exist in the update columns.
String keyColName = null;
String valColName = null;
// Whether fields that are part of the key (value) exist in the updated columns.
boolean hasKeyProps = false;
boolean hasValProps = false;
for (Column col : affectedCols) {
int colId = col.getColumnId();
// Checking that it's not specified both _key(_val) and its alias by the way.
if (desc.isKeyColumn(colId)) {
if (keyColName == null)
keyColName = col.getName();
else
throw new IgniteSQLException("Columns " + keyColName + " and " + col + " both refer to entire cache key object.", IgniteQueryErrorCode.PARSING);
} else if (desc.isValueColumn(colId)) {
if (valColName == null)
valColName = col.getName();
else
throw new IgniteSQLException("Columns " + valColName + " and " + col + " both refer to entire cache value object.", IgniteQueryErrorCode.PARSING);
} else {
// Column ids 0..2 are _key, _val, _ver
assert colId >= QueryUtils.DEFAULT_COLUMNS_COUNT : "Unexpected column [name=" + col + ", id=" + colId + "].";
if (desc.isColumnKeyProperty(colId - QueryUtils.DEFAULT_COLUMNS_COUNT))
hasKeyProps = true;
else
hasValProps = true;
}
// And check invariants for the fast fail.
boolean hasEntireKeyCol = keyColName != null;
boolean hasEntireValcol = valColName != null;
if (hasEntireKeyCol && hasKeyProps)
throw new IgniteSQLException("Column " + keyColName + " refers to entire key cache object. " + "It must not be mixed with other columns that refer to parts of key.", IgniteQueryErrorCode.PARSING);
if (hasEntireValcol && hasValProps)
throw new IgniteSQLException("Column " + valColName + " refers to entire value cache object. " + "It must not be mixed with other columns that refer to parts of value.", IgniteQueryErrorCode.PARSING);
if (!ALLOW_KEY_VAL_UPDATES) {
if (desc.isKeyColumn(colId) && !QueryUtils.isSqlType(desc.type().keyClass())) {
throw new IgniteSQLException("Update of composite key column is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
if (desc.isValueColumn(colId) && !QueryUtils.isSqlType(desc.type().valueClass())) {
throw new IgniteSQLException("Update of composite value column is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
}
}
}
Aggregations