use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IN 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.processors.query.h2.sql.GridSqlOperationType.IN 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.GridSqlOperationType.IN in project ignite by apache.
the class DmlUtils method dmlDoInsert.
/**
* Execute INSERT statement plan.
* @param cursor Cursor to take inserted data from.
* @param pageSize Batch size for streaming, anything <= 0 for single page operations.
* @return Number of items affected.
* @throws IgniteCheckedException if failed, particularly in case of duplicate keys.
*/
@SuppressWarnings({ "unchecked" })
private static long dmlDoInsert(UpdatePlan plan, Iterable<List<?>> cursor, int pageSize) throws IgniteCheckedException {
GridCacheContext cctx = plan.cacheContext();
// If we have just one item to put, just do so
if (plan.rowCount() == 1) {
IgniteBiTuple t = plan.processRow(cursor.iterator().next());
try (MTC.TraceSurroundings ignored = MTC.support(cctx.kernalContext().tracing().create(SQL_CACHE_UPDATE, MTC.span()).addTag(SQL_CACHE_UPDATES, () -> "1"))) {
if (cctx.cache().putIfAbsent(t.getKey(), t.getValue()))
return 1;
else
throw new TransactionDuplicateKeyException("Duplicate key during INSERT [key=" + t.getKey() + ']');
}
} else {
// Keys that failed to INSERT due to duplication.
DmlBatchSender sender = new DmlBatchSender(cctx, pageSize, 1);
for (List<?> row : cursor) {
final IgniteBiTuple keyValPair = plan.processRow(row);
sender.add(keyValPair.getKey(), new DmlStatementsProcessor.InsertEntryProcessor(keyValPair.getValue()), 0);
}
sender.flush();
SQLException resEx = sender.error();
if (!F.isEmpty(sender.failedKeys())) {
String msg = "Failed to INSERT some keys because they are already in cache " + "[keys=" + sender.failedKeys() + ']';
SQLException dupEx = new SQLException(msg, SqlStateCode.CONSTRAINT_VIOLATION);
if (resEx == null)
resEx = dupEx;
else
resEx.setNextException(dupEx);
}
if (resEx != null)
throw new IgniteSQLException(resEx);
return sender.updateCount();
}
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IN in project ignite by apache.
the class DmlUtils method doInsertBatched.
/**
* Execute INSERT statement plan.
*
* @param plan Plan to execute.
* @param cursor Cursor to take inserted data from. I.e. list of batch arguments for each query.
* @param pageSize Batch size for streaming, anything <= 0 for single page operations.
* @return Number of items affected.
* @throws IgniteCheckedException if failed, particularly in case of duplicate keys.
*/
private static List<UpdateResult> doInsertBatched(UpdatePlan plan, List<List<List<?>>> cursor, int pageSize) throws IgniteCheckedException {
GridCacheContext cctx = plan.cacheContext();
DmlBatchSender snd = new DmlBatchSender(cctx, pageSize, cursor.size());
int rowNum = 0;
SQLException resEx = null;
for (List<List<?>> qryRow : cursor) {
for (List<?> row : qryRow) {
try {
final IgniteBiTuple keyValPair = plan.processRow(row);
snd.add(keyValPair.getKey(), new DmlStatementsProcessor.InsertEntryProcessor(keyValPair.getValue()), rowNum);
} catch (Exception e) {
String sqlState;
int code;
if (e instanceof IgniteSQLException) {
sqlState = ((IgniteSQLException) e).sqlState();
code = ((IgniteSQLException) e).statusCode();
} else {
sqlState = SqlStateCode.INTERNAL_ERROR;
code = IgniteQueryErrorCode.UNKNOWN;
}
resEx = chainException(resEx, new SQLException(e.getMessage(), sqlState, code, e));
snd.setFailed(rowNum);
}
}
rowNum++;
}
try {
snd.flush();
} catch (Exception e) {
resEx = chainException(resEx, new SQLException(e.getMessage(), SqlStateCode.INTERNAL_ERROR, IgniteQueryErrorCode.UNKNOWN, e));
}
resEx = chainException(resEx, snd.error());
if (!F.isEmpty(snd.failedKeys())) {
SQLException e = new SQLException("Failed to INSERT some keys because they are already in cache [keys=" + snd.failedKeys() + ']', SqlStateCode.CONSTRAINT_VIOLATION, DUPLICATE_KEY);
resEx = chainException(resEx, e);
}
if (resEx != null) {
BatchUpdateException e = new BatchUpdateException(resEx.getMessage(), resEx.getSQLState(), resEx.getErrorCode(), snd.perRowCounterAsArray(), resEx);
throw new IgniteCheckedException(e);
}
int[] cntPerRow = snd.perRowCounterAsArray();
List<UpdateResult> res = new ArrayList<>(cntPerRow.length);
for (int i = 0; i < cntPerRow.length; i++) {
int cnt = cntPerRow[i];
res.add(new UpdateResult(cnt, X.EMPTY_OBJECT_ARRAY));
}
return res;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IN in project ignite by apache.
the class DmlAstUtils method selectForUpdate.
/**
* Generate SQL SELECT based on UPDATE's WHERE, LIMIT, etc.
*
* @param update Update statement.
* @return SELECT statement.
*/
public static GridSqlSelect selectForUpdate(GridSqlUpdate update) {
GridSqlSelect mapQry = new GridSqlSelect();
mapQry.from(update.target());
Set<GridSqlTable> tbls = new HashSet<>();
collectAllGridTablesInTarget(update.target(), tbls);
assert tbls.size() == 1 : "Failed to determine target table for UPDATE";
GridSqlTable tbl = tbls.iterator().next();
GridH2Table gridTbl = tbl.dataTable();
assert gridTbl != null : "Failed to determine target grid table for UPDATE";
Column h2KeyCol = gridTbl.getColumn(QueryUtils.KEY_COL);
Column h2ValCol = gridTbl.getColumn(QueryUtils.VAL_COL);
GridSqlColumn keyCol = new GridSqlColumn(h2KeyCol, tbl, h2KeyCol.getName());
keyCol.resultType(GridSqlType.fromColumn(h2KeyCol));
GridSqlColumn valCol = new GridSqlColumn(h2ValCol, tbl, h2ValCol.getName());
valCol.resultType(GridSqlType.fromColumn(h2ValCol));
mapQry.addColumn(keyCol, true);
mapQry.addColumn(valCol, true);
for (GridSqlColumn c : update.cols()) {
String newColName = Parser.quoteIdentifier("_upd_" + c.columnName());
// We have to use aliases to cover cases when the user
// wants to update _val field directly (if it's a literal)
GridSqlAlias alias = new GridSqlAlias(newColName, elementOrDefault(update.set().get(c.columnName()), c), true);
alias.resultType(c.resultType());
mapQry.addColumn(alias, true);
}
GridSqlElement where = update.where();
// On no MVCC mode we cannot use lazy mode when UPDATE query contains index with updated columns
// and that index may be chosen to scan by WHERE condition
// because in this case any rows update may be updated several times.
// e.g. in the cases below we cannot use lazy mode:
//
// 1. CREATE INDEX idx on test(val)
// UPDATE test SET val = val + 1 WHERE val >= ?
//
// 2. CREATE INDEX idx on test(val0, val1)
// UPDATE test SET val1 = val1 + 1 WHERE val0 >= ?
mapQry.canBeLazy(!isIndexWithUpdateColumnsMayBeUsed(gridTbl, update.cols().stream().map(GridSqlColumn::column).collect(Collectors.toSet()), extractColumns(gridTbl, where)));
mapQry.where(where);
mapQry.limit(update.limit());
return mapQry;
}
Aggregations