use of org.h2.expression.Alias in project ignite by apache.
the class GridReduceQueryExecutor method createMergeTable.
/**
* @param conn Connection.
* @param qry Query.
* @param explain Explain.
* @return Table.
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings("unchecked")
private ReduceTable createMergeTable(H2PooledConnection conn, GridCacheSqlQuery qry, boolean explain) throws IgniteCheckedException {
try {
Session ses = H2Utils.session(conn);
CreateTableData data = new CreateTableData();
data.tableName = "T___";
data.schema = ses.getDatabase().getSchema(ses.getCurrentSchemaName());
data.create = true;
if (!explain) {
LinkedHashMap<String, ?> colsMap = qry.columns();
assert colsMap != null;
ArrayList<Column> cols = new ArrayList<>(colsMap.size());
for (Map.Entry<String, ?> e : colsMap.entrySet()) {
String alias = e.getKey();
GridSqlType type = (GridSqlType) e.getValue();
assert !F.isEmpty(alias);
Column col0;
if (type == GridSqlType.UNKNOWN) {
// Special case for parameter being set at the top of the query (e.g. SELECT ? FROM ...).
// Re-map it to STRING in the same way it is done in H2, because any argument can be cast
// to string.
col0 = new Column(alias, Value.STRING);
} else {
col0 = new Column(alias, type.type(), type.precision(), type.scale(), type.displaySize());
}
cols.add(col0);
}
data.columns = cols;
} else
data.columns = planColumns();
boolean sortedIndex = !F.isEmpty(qry.sortColumns());
ReduceTable tbl = new ReduceTable(data);
ArrayList<Index> idxs = new ArrayList<>(2);
if (explain) {
idxs.add(new UnsortedReduceIndexAdapter(ctx, tbl, sortedIndex ? MERGE_INDEX_SORTED : MERGE_INDEX_UNSORTED));
} else if (sortedIndex) {
List<GridSqlSortColumn> sortCols = (List<GridSqlSortColumn>) qry.sortColumns();
SortedReduceIndexAdapter sortedMergeIdx = new SortedReduceIndexAdapter(ctx, tbl, MERGE_INDEX_SORTED, GridSqlSortColumn.toIndexColumns(tbl, sortCols));
idxs.add(ReduceTable.createScanIndex(sortedMergeIdx));
idxs.add(sortedMergeIdx);
} else
idxs.add(new UnsortedReduceIndexAdapter(ctx, tbl, MERGE_INDEX_UNSORTED));
tbl.indexes(idxs);
return tbl;
} catch (Exception e) {
throw new IgniteCheckedException(e);
}
}
use of org.h2.expression.Alias 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.h2.expression.Alias 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);
}
}
}
}
use of org.h2.expression.Alias 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.h2.expression.Alias 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;
}
}
Aggregations