use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IN in project ignite by apache.
the class H2RowFactory method getRow.
/**
* !!! This method must be invoked in read or write lock of referring index page. It is needed to
* !!! make sure that row at this link will be invisible, when the link will be removed from
* !!! from all the index pages, so that row can be safely erased from the data page.
*
* @param link Link.
* @return Row.
* @throws IgniteCheckedException If failed.
*/
public GridH2Row getRow(long link) throws IgniteCheckedException {
// TODO Avoid extra garbage generation. In upcoming H2 1.4.193 Row will become an interface,
// TODO we need to refactor all this to return CacheDataRowAdapter implementing Row here.
final CacheDataRowAdapter rowBuilder = new CacheDataRowAdapter(link);
rowBuilder.initFromLink(cctx.group(), CacheDataRowAdapter.RowData.FULL);
GridH2Row row;
try {
row = rowDesc.createRow(rowBuilder);
} catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
assert row.version() != null;
return row;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IN in project ignite by apache.
the class UpdatePlanBuilder method planForUpdate.
/**
* Prepare update plan for UPDATE or DELETE.
*
* @param stmt UPDATE or DELETE statement.
* @param loc Local query flag.
* @param idx Indexing.
* @param conn Connection.
* @param fieldsQuery Original query.
* @param errKeysPos index to inject param for re-run keys at. Null if it's not a re-run plan.
* @return Update plan.
* @throws IgniteCheckedException if failed.
*/
private static UpdatePlan planForUpdate(GridSqlStatement stmt, boolean loc, IgniteH2Indexing idx, @Nullable Connection conn, @Nullable SqlFieldsQuery fieldsQuery, @Nullable Integer errKeysPos) throws IgniteCheckedException {
GridSqlElement target;
FastUpdate fastUpdate;
UpdateMode mode;
if (stmt instanceof GridSqlUpdate) {
// Let's verify that user is not trying to mess with key's columns directly
verifyUpdateColumns(stmt);
GridSqlUpdate update = (GridSqlUpdate) stmt;
target = update.target();
fastUpdate = DmlAstUtils.getFastUpdateArgs(update);
mode = UpdateMode.UPDATE;
} else if (stmt instanceof GridSqlDelete) {
GridSqlDelete del = (GridSqlDelete) stmt;
target = del.from();
fastUpdate = DmlAstUtils.getFastDeleteArgs(del);
mode = UpdateMode.DELETE;
} else
throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', IgniteQueryErrorCode.UNEXPECTED_OPERATION);
GridSqlTable tbl = DmlAstUtils.gridTableForElement(target);
GridH2Table h2Tbl = tbl.dataTable();
GridH2RowDescriptor desc = h2Tbl.rowDescriptor();
if (desc == null)
throw new IgniteSQLException("Row descriptor undefined for table '" + h2Tbl.getName() + "'", IgniteQueryErrorCode.NULL_TABLE_DESCRIPTOR);
if (fastUpdate != null) {
return new UpdatePlan(mode, h2Tbl, null, fastUpdate, null);
} else {
GridSqlSelect sel;
if (stmt instanceof GridSqlUpdate) {
List<GridSqlColumn> updatedCols = ((GridSqlUpdate) stmt).cols();
int valColIdx = -1;
String[] colNames = new String[updatedCols.size()];
int[] colTypes = new int[updatedCols.size()];
for (int i = 0; i < updatedCols.size(); i++) {
colNames[i] = updatedCols.get(i).columnName();
colTypes[i] = updatedCols.get(i).resultType().type();
Column col = updatedCols.get(i).column();
if (desc.isValueColumn(col.getColumnId()))
valColIdx = i;
}
boolean hasNewVal = (valColIdx != -1);
// Statement updates distinct properties if it does not have _val in updated columns list
// or if its list of updated columns includes only _val, i.e. is single element.
boolean hasProps = !hasNewVal || updatedCols.size() > 1;
// Index of new _val in results of SELECT
if (hasNewVal)
valColIdx += 2;
int newValColIdx = (hasNewVal ? valColIdx : 1);
KeyValueSupplier valSupplier = createSupplier(desc.context(), desc.type(), newValColIdx, hasProps, false, true);
sel = DmlAstUtils.selectForUpdate((GridSqlUpdate) stmt, errKeysPos);
String selectSql = sel.getSQL();
DmlDistributedPlanInfo distributed = F.isEmpty(selectSql) ? null : checkPlanCanBeDistributed(idx, conn, fieldsQuery, loc, selectSql, tbl.dataTable().cacheName());
return new UpdatePlan(UpdateMode.UPDATE, h2Tbl, colNames, colTypes, null, valSupplier, -1, valColIdx, selectSql, false, null, 0, null, distributed);
} else {
sel = DmlAstUtils.selectForDelete((GridSqlDelete) stmt, errKeysPos);
String selectSql = sel.getSQL();
DmlDistributedPlanInfo distributed = F.isEmpty(selectSql) ? null : checkPlanCanBeDistributed(idx, conn, fieldsQuery, loc, selectSql, tbl.dataTable().cacheName());
return new UpdatePlan(UpdateMode.DELETE, h2Tbl, selectSql, null, distributed);
}
}
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IN in project ignite by apache.
the class DmlStatementsProcessor method streamUpdateQuery.
/**
* Perform given statement against given data streamer. Only rows based INSERT is supported.
*
* @param schemaName Schema name.
* @param streamer Streamer to feed data to.
* @param stmt Statement.
* @param args Statement arguments.
* @return Number of rows in given INSERT statement.
* @throws IgniteCheckedException if failed.
*/
@SuppressWarnings({ "unchecked", "ConstantConditions" })
long streamUpdateQuery(String schemaName, IgniteDataStreamer streamer, PreparedStatement stmt, final Object[] args) throws IgniteCheckedException {
idx.checkStatementStreamable(stmt);
Prepared p = GridSqlQueryParser.prepared(stmt);
assert p != null;
final UpdatePlan plan = getPlanForStatement(schemaName, null, p, null, true, null);
assert plan.isLocalSubquery();
final GridCacheContext cctx = plan.cacheContext();
QueryCursorImpl<List<?>> cur;
final ArrayList<List<?>> data = new ArrayList<>(plan.rowCount());
QueryCursorImpl<List<?>> stepCur = new QueryCursorImpl<>(new Iterable<List<?>>() {
@Override
public Iterator<List<?>> iterator() {
try {
Iterator<List<?>> it;
if (!F.isEmpty(plan.selectQuery())) {
GridQueryFieldsResult res = idx.queryLocalSqlFields(idx.schema(cctx.name()), plan.selectQuery(), F.asList(U.firstNotNull(args, X.EMPTY_OBJECT_ARRAY)), null, false, 0, null);
it = res.iterator();
} else
it = plan.createRows(U.firstNotNull(args, X.EMPTY_OBJECT_ARRAY)).iterator();
return new GridQueryCacheObjectsIterator(it, idx.objectContext(), cctx.keepBinary());
} catch (IgniteCheckedException e) {
throw new IgniteException(e);
}
}
}, null);
data.addAll(stepCur.getAll());
cur = new QueryCursorImpl<>(new Iterable<List<?>>() {
@Override
public Iterator<List<?>> iterator() {
return data.iterator();
}
}, null);
if (plan.rowCount() == 1) {
IgniteBiTuple t = plan.processRow(cur.iterator().next());
streamer.addData(t.getKey(), t.getValue());
return 1;
}
Map<Object, Object> rows = new LinkedHashMap<>(plan.rowCount());
for (List<?> row : cur) {
final IgniteBiTuple t = plan.processRow(row);
rows.put(t.getKey(), t.getValue());
}
streamer.addData(rows);
return rows.size();
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.IN in project ignite by apache.
the class DmlStatementsProcessor 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 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 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 GridSqlQueryParser method isLocalQuery.
/**
* Check if query may be run locally on all caches mentioned in the query.
* @param replicatedOnlyQry replicated-only query flag from original {@link SqlFieldsQuery}.
* @return {@code true} if query may be run locally on all caches mentioned in the query, i.e. there's no need
* to run distributed query.
* @see SqlFieldsQuery#isReplicatedOnly()
*/
public boolean isLocalQuery(boolean replicatedOnlyQry) {
boolean hasCaches = false;
for (Object o : h2ObjToGridObj.values()) {
if (o instanceof GridSqlAlias)
o = GridSqlAlias.unwrap((GridSqlAst) o);
if (o instanceof GridSqlTable) {
GridH2Table tbl = ((GridSqlTable) o).dataTable();
if (tbl != null) {
hasCaches = true;
GridCacheContext cctx = tbl.cache();
if (!cctx.isLocal() && !(replicatedOnlyQry && cctx.isReplicatedAffinityNode()))
return false;
}
}
}
// if there are no caches, original SqlFieldsQuery's isLocal flag will be used.
return hasCaches;
}
Aggregations