use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias 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;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias in project ignite by apache.
the class DmlAstUtils method selectForInsertOrMerge.
/**
* Create SELECT on which subsequent INSERT or MERGE will be based.
*
* @param cols Columns to insert values into.
* @param rows Rows to create pseudo-SELECT upon.
* @param subQry Subquery to use rather than rows.
* @return Subquery or pseudo-SELECT to evaluate inserted expressions, or {@code null} no query needs to be run.
*/
public static GridSqlQuery selectForInsertOrMerge(GridSqlColumn[] cols, List<GridSqlElement[]> rows, GridSqlQuery subQry) {
if (!F.isEmpty(rows)) {
assert !F.isEmpty(cols);
GridSqlSelect sel = new GridSqlSelect();
GridSqlFunction from = new GridSqlFunction(GridSqlFunctionType.TABLE);
sel.from(from);
GridSqlArray[] args = new GridSqlArray[cols.length];
for (int i = 0; i < cols.length; i++) {
GridSqlArray arr = new GridSqlArray(rows.size());
String colName = cols[i].columnName();
GridSqlAlias alias = new GridSqlAlias(colName, arr);
alias.resultType(cols[i].resultType());
from.addChild(alias);
args[i] = arr;
GridSqlColumn newCol = new GridSqlColumn(null, from, null, "TABLE", colName);
newCol.resultType(cols[i].resultType());
sel.addColumn(newCol, true);
}
for (GridSqlElement[] row : rows) {
assert cols.length == row.length;
for (int i = 0; i < row.length; i++) args[i].addChild(row[i]);
}
return sel;
} else {
assert subQry != null;
return subQry;
}
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias in project ignite by apache.
the class GridSqlQuerySplitter method keyColumn.
/**
* Retrieves _KEY column from SELECT. This column is used for SELECT FOR UPDATE statements.
*
* @param sel Select statement.
* @return Key column alias.
*/
public static GridSqlAlias keyColumn(GridSqlSelect sel) {
GridSqlAst from = sel.from();
GridSqlTable tbl = from instanceof GridSqlTable ? (GridSqlTable) from : ((GridSqlElement) from).child();
GridH2Table gridTbl = tbl.dataTable();
Column h2KeyCol = gridTbl.getColumn(QueryUtils.KEY_COL);
GridSqlColumn keyCol = new GridSqlColumn(h2KeyCol, tbl, h2KeyCol.getName());
keyCol.resultType(GridSqlType.fromColumn(h2KeyCol));
GridSqlAlias al = SplitterUtils.alias(QueryUtils.KEY_FIELD_NAME, keyCol);
return al;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias in project ignite by apache.
the class DmlAstUtils method selectForUpdate.
/**
* Generate SQL SELECT based on UPDATE's WHERE, LIMIT, etc.
*
* @param update Update statement.
* @param keysParamIdx Index of new param for the array of keys.
* @return SELECT statement.
*/
public static GridSqlSelect selectForUpdate(GridSqlUpdate update, @Nullable Integer keysParamIdx) {
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(GridH2KeyValueRowOnheap.KEY_COL);
Column h2ValCol = gridTbl.getColumn(GridH2KeyValueRowOnheap.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();
if (keysParamIdx != null)
where = injectKeysFilterParam(where, keyCol, keysParamIdx);
mapQry.where(where);
mapQry.limit(update.limit());
return mapQry;
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlAlias 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