use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery in project ignite by apache.
the class UpdatePlanBuilder method planForInsert.
/**
* Prepare update plan for INSERT or MERGE.
*
* @param stmt INSERT or MERGE statement.
* @return Update plan.
* @throws IgniteCheckedException if failed.
*/
@SuppressWarnings("ConstantConditions")
private static UpdatePlan planForInsert(GridSqlStatement stmt) throws IgniteCheckedException {
GridSqlQuery sel;
GridSqlElement target;
GridSqlColumn[] cols;
boolean isTwoStepSubqry;
int rowsNum;
GridSqlTable tbl;
GridH2RowDescriptor desc;
if (stmt instanceof GridSqlInsert) {
GridSqlInsert ins = (GridSqlInsert) stmt;
target = ins.into();
tbl = gridTableForElement(target);
desc = tbl.dataTable().rowDescriptor();
cols = ins.columns();
sel = DmlAstUtils.selectForInsertOrMerge(cols, ins.rows(), ins.query(), desc);
isTwoStepSubqry = (ins.query() != null);
rowsNum = isTwoStepSubqry ? 0 : ins.rows().size();
} else if (stmt instanceof GridSqlMerge) {
GridSqlMerge merge = (GridSqlMerge) stmt;
target = merge.into();
tbl = gridTableForElement(target);
desc = tbl.dataTable().rowDescriptor();
// This check also protects us from attempts to update key or its fields directly -
// when no key except cache key can be used, it will serve only for uniqueness checks,
// not for updates, and hence will allow putting new pairs only.
// We don't quote _key and _val column names on CREATE TABLE, so they are always uppercase here.
GridSqlColumn[] keys = merge.keys();
if (keys.length != 1 || !desc.isKeyColumn(tbl.dataTable().getColumn(keys[0].columnName()).getColumnId()))
throw new CacheException("SQL MERGE does not support arbitrary keys");
cols = merge.columns();
sel = DmlAstUtils.selectForInsertOrMerge(cols, merge.rows(), merge.query(), desc);
isTwoStepSubqry = (merge.query() != null);
rowsNum = isTwoStepSubqry ? 0 : merge.rows().size();
} else
throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', IgniteQueryErrorCode.UNEXPECTED_OPERATION);
// Let's set the flag only for subqueries that have their FROM specified.
isTwoStepSubqry = (isTwoStepSubqry && (sel instanceof GridSqlUnion || (sel instanceof GridSqlSelect && ((GridSqlSelect) sel).from() != null)));
int keyColIdx = -1;
int valColIdx = -1;
boolean hasKeyProps = false;
boolean hasValProps = false;
if (desc == null)
throw new IgniteSQLException("Row descriptor undefined for table '" + tbl.dataTable().getName() + "'", IgniteQueryErrorCode.NULL_TABLE_DESCRIPTOR);
GridCacheContext<?, ?> cctx = desc.context();
String[] colNames = new String[cols.length];
int[] colTypes = new int[cols.length];
for (int i = 0; i < cols.length; i++) {
GridSqlColumn col = cols[i];
String colName = col.columnName();
colNames[i] = colName;
colTypes[i] = col.resultType().type();
int colId = col.column().getColumnId();
if (desc.isKeyColumn(colId)) {
keyColIdx = i;
continue;
}
if (desc.isValueColumn(colId)) {
valColIdx = i;
continue;
}
GridQueryProperty prop = desc.type().property(colName);
assert prop != null : "Property '" + colName + "' not found.";
if (prop.key())
hasKeyProps = true;
else
hasValProps = true;
}
KeyValueSupplier keySupplier = createSupplier(cctx, desc.type(), keyColIdx, hasKeyProps, true, false);
KeyValueSupplier valSupplier = createSupplier(cctx, desc.type(), valColIdx, hasValProps, false, false);
if (stmt instanceof GridSqlMerge)
return UpdatePlan.forMerge(tbl.dataTable(), colNames, colTypes, keySupplier, valSupplier, keyColIdx, valColIdx, sel.getSQL(), !isTwoStepSubqry, rowsNum);
else
return UpdatePlan.forInsert(tbl.dataTable(), colNames, colTypes, keySupplier, valSupplier, keyColIdx, valColIdx, sel.getSQL(), !isTwoStepSubqry, rowsNum);
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery in project ignite by apache.
the class UpdatePlanBuilder method planForInsert.
/**
* Prepare update plan for INSERT or MERGE.
*
* @param stmt INSERT or MERGE statement.
* @param loc Local query flag.
* @param idx Indexing.
* @param conn Connection.
* @param fieldsQuery Original query.
* @return Update plan.
* @throws IgniteCheckedException if failed.
*/
@SuppressWarnings("ConstantConditions")
private static UpdatePlan planForInsert(GridSqlStatement stmt, boolean loc, IgniteH2Indexing idx, @Nullable Connection conn, @Nullable SqlFieldsQuery fieldsQuery) throws IgniteCheckedException {
GridSqlQuery sel;
GridSqlElement target;
GridSqlColumn[] cols;
boolean isTwoStepSubqry;
int rowsNum;
GridSqlTable tbl;
GridH2RowDescriptor desc;
List<GridSqlElement[]> elRows = null;
if (stmt instanceof GridSqlInsert) {
GridSqlInsert ins = (GridSqlInsert) stmt;
target = ins.into();
tbl = DmlAstUtils.gridTableForElement(target);
desc = tbl.dataTable().rowDescriptor();
cols = ins.columns();
sel = DmlAstUtils.selectForInsertOrMerge(cols, ins.rows(), ins.query());
if (sel == null)
elRows = ins.rows();
isTwoStepSubqry = (ins.query() != null);
rowsNum = isTwoStepSubqry ? 0 : ins.rows().size();
} else if (stmt instanceof GridSqlMerge) {
GridSqlMerge merge = (GridSqlMerge) stmt;
target = merge.into();
tbl = DmlAstUtils.gridTableForElement(target);
desc = tbl.dataTable().rowDescriptor();
cols = merge.columns();
sel = DmlAstUtils.selectForInsertOrMerge(cols, merge.rows(), merge.query());
if (sel == null)
elRows = merge.rows();
isTwoStepSubqry = (merge.query() != null);
rowsNum = isTwoStepSubqry ? 0 : merge.rows().size();
} else {
throw new IgniteSQLException("Unexpected DML operation [cls=" + stmt.getClass().getName() + ']', IgniteQueryErrorCode.UNEXPECTED_OPERATION);
}
// Let's set the flag only for subqueries that have their FROM specified.
isTwoStepSubqry &= (sel != null && (sel instanceof GridSqlUnion || (sel instanceof GridSqlSelect && ((GridSqlSelect) sel).from() != null)));
int keyColIdx = -1;
int valColIdx = -1;
boolean hasKeyProps = false;
boolean hasValProps = false;
if (desc == null)
throw new IgniteSQLException("Row descriptor undefined for table '" + tbl.dataTable().getName() + "'", IgniteQueryErrorCode.NULL_TABLE_DESCRIPTOR);
GridCacheContext<?, ?> cctx = desc.context();
String[] colNames = new String[cols.length];
int[] colTypes = new int[cols.length];
for (int i = 0; i < cols.length; i++) {
GridSqlColumn col = cols[i];
String colName = col.columnName();
colNames[i] = colName;
colTypes[i] = col.resultType().type();
int colId = col.column().getColumnId();
if (desc.isKeyColumn(colId)) {
keyColIdx = i;
continue;
}
if (desc.isValueColumn(colId)) {
valColIdx = i;
continue;
}
GridQueryProperty prop = desc.type().property(colName);
assert prop != null : "Property '" + colName + "' not found.";
if (prop.key())
hasKeyProps = true;
else
hasValProps = true;
}
KeyValueSupplier keySupplier = createSupplier(cctx, desc.type(), keyColIdx, hasKeyProps, true, false);
KeyValueSupplier valSupplier = createSupplier(cctx, desc.type(), valColIdx, hasValProps, false, false);
String selectSql = sel != null ? sel.getSQL() : null;
DmlDistributedPlanInfo distributed = (rowsNum == 0 && !F.isEmpty(selectSql)) ? checkPlanCanBeDistributed(idx, conn, fieldsQuery, loc, selectSql, tbl.dataTable().cacheName()) : null;
UpdateMode mode = stmt instanceof GridSqlMerge ? UpdateMode.MERGE : UpdateMode.INSERT;
List<List<DmlArgument>> rows = null;
if (elRows != null) {
assert sel == null;
rows = new ArrayList<>(elRows.size());
for (GridSqlElement[] elRow : elRows) {
List<DmlArgument> row = new ArrayList<>(cols.length);
for (GridSqlElement el : elRow) {
DmlArgument arg = DmlArguments.create(el);
row.add(arg);
}
rows.add(row);
}
}
return new UpdatePlan(mode, tbl.dataTable(), colNames, colTypes, keySupplier, valSupplier, keyColIdx, valColIdx, selectSql, !isTwoStepSubqry, rows, rowsNum, null, distributed);
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery in project ignite by apache.
the class GridSubqueryJoinOptimizer method subQueryCanBePulledOut.
/**
* Whether sub-query can be pulled out or not.
*
* @param subQry Sub-query.
* @return {@code true} if sub-query cound be pulled out, {@code false} otherwise.
*/
private static boolean subQueryCanBePulledOut(GridSqlSubquery subQry) {
GridSqlQuery subQ = subQry.subquery();
if (!isSimpleSelect(subQ))
return false;
assert subQ instanceof GridSqlSelect;
GridSqlSelect subS = (GridSqlSelect) subQ;
if (subS.where() == null)
return false;
Predicate<GridSqlAst> andOrEqPre = ELEMENT_IS_AND_OPERATION.or(ELEMENT_IS_EQ);
if (!andOrEqPre.test(subS.where()))
return false;
ASTNodeFinder opEqFinder = new ASTNodeFinder(subS.where(), (parent, child) -> ELEMENT_IS_EQ.test(parent), andOrEqPre);
List<GridSqlColumn> sqlCols = new ArrayList<>();
ASTNodeFinder.Result res;
while ((res = opEqFinder.findNext()) != null) {
GridSqlOperation op = (GridSqlOperation) res.getEl();
assert op.size() == 2;
GridSqlColumn[] colArr = new GridSqlColumn[2];
for (int i = 0; i < 2; i++) {
if (op.child(i) instanceof GridSqlColumn)
colArr[i] = op.child(i);
else if (op.child(i) instanceof GridSqlOperation && ((GridSqlOperation) op.child(i)).operationType() == NEGATE && op.child() instanceof GridSqlColumn)
colArr[i] = op.child(i).child();
}
if (colArr[0] == null || colArr[1] == null || // whether the column refers to exactly the same table
colArr[0].expressionInFrom() != colArr[1].expressionInFrom()) {
if (colArr[0] != null && colArr[0].expressionInFrom() == subS.from())
sqlCols.add(colArr[0]);
if (colArr[1] != null && colArr[1].expressionInFrom() == subS.from())
sqlCols.add(colArr[1]);
}
}
GridSqlAst subTbl = GridSqlAlias.unwrap(subS.from());
return subTbl instanceof GridSqlTable && isUniqueIndexExists(sqlCols, (GridSqlTable) subTbl);
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery in project ignite by apache.
the class PartitionExtractor method extract.
/**
* Extract partitions.
*
* @param qry Query.
* @return Partitions.
*/
public PartitionResult extract(GridSqlQuery qry) throws IgniteCheckedException {
// No unions support yet.
if (!(qry instanceof GridSqlSelect))
return null;
GridSqlSelect select = (GridSqlSelect) qry;
// Prepare table model.
PartitionTableModel tblModel = prepareTableModel(select.from());
// Do extract.
PartitionNode tree = extractFromExpression(select.where(), tblModel, false);
assert tree != null;
// Reduce tree if possible.
tree = tree.optimize();
if (tree instanceof PartitionAllNode)
return null;
// Done.
return new PartitionResult(tree, tblModel.joinGroupAffinity(tree.joinGroup()), ctx.cache().context().exchange().readyAffinityVersion());
}
use of org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery in project ignite by apache.
the class DmlAstUtils method findParams.
/**
* @param qry Select.
* @param params Parameters.
* @param target Extracted parameters.
* @param paramIdxs Parameter indexes.
* @return Extracted parameters list.
*/
@SuppressWarnings("unused")
private static List<Object> findParams(GridSqlQuery qry, Object[] params, ArrayList<Object> target, IntArray paramIdxs) {
if (qry instanceof GridSqlSelect)
return findParams((GridSqlSelect) qry, params, target, paramIdxs);
GridSqlUnion union = (GridSqlUnion) qry;
findParams(union.left(), params, target, paramIdxs);
findParams(union.right(), params, target, paramIdxs);
findParams((GridSqlElement) qry.limit(), params, target, paramIdxs);
findParams((GridSqlElement) qry.offset(), params, target, paramIdxs);
return target;
}
Aggregations