use of org.h2.table.Column in project ignite by apache.
the class GridSqlQueryParser method parseInsert.
/**
* @param insert Insert.
* @see <a href="http://h2database.com/html/grammar.html#insert">H2 insert spec</a>
*/
private GridSqlInsert parseInsert(Insert insert) {
GridSqlInsert res = (GridSqlInsert) h2ObjToGridObj.get(insert);
if (res != null)
return res;
res = new GridSqlInsert();
h2ObjToGridObj.put(insert, res);
Table srcTbl = INSERT_TABLE.get(insert);
GridSqlElement tbl = parseTable(srcTbl);
res.into(tbl).direct(INSERT_DIRECT.get(insert)).sorted(INSERT_SORTED.get(insert));
Column[] srcCols = INSERT_COLUMNS.get(insert);
GridSqlColumn[] cols = new GridSqlColumn[srcCols.length];
for (int i = 0; i < srcCols.length; i++) {
cols[i] = new GridSqlColumn(srcCols[i], tbl, null, null, srcCols[i].getName());
cols[i].resultType(fromColumn(srcCols[i]));
}
res.columns(cols);
List<Expression[]> srcRows = INSERT_ROWS.get(insert);
if (!srcRows.isEmpty()) {
List<GridSqlElement[]> rows = new ArrayList<>(srcRows.size());
for (Expression[] srcRow : srcRows) {
GridSqlElement[] row = new GridSqlElement[srcRow.length];
for (int i = 0; i < srcRow.length; i++) row[i] = parseExpression(srcRow[i], false);
rows.add(row);
}
res.rows(rows);
} else {
res.rows(Collections.<GridSqlElement[]>emptyList());
res.query(parseQuery(INSERT_QUERY.get(insert)));
}
return res;
}
use of org.h2.table.Column in project ignite by apache.
the class GridSqlQuerySplitter method extractPartitionFromEquality.
/**
* Analyses the equality operation and extracts the partition if possible
*
* @param op AST equality operation.
* @param ctx Kernal Context.
* @return partition info, or {@code null} if none identified
*/
private static CacheQueryPartitionInfo extractPartitionFromEquality(GridSqlOperation op, GridKernalContext ctx) throws IgniteCheckedException {
assert op.operationType() == GridSqlOperationType.EQUAL;
GridSqlElement left = op.child(0);
GridSqlElement right = op.child(1);
if (!(left instanceof GridSqlColumn))
return null;
if (!(right instanceof GridSqlConst) && !(right instanceof GridSqlParameter))
return null;
GridSqlColumn column = (GridSqlColumn) left;
assert column.column().getTable() instanceof GridH2Table;
GridH2Table tbl = (GridH2Table) column.column().getTable();
GridH2RowDescriptor desc = tbl.rowDescriptor();
IndexColumn affKeyCol = tbl.getAffinityKeyColumn();
int colId = column.column().getColumnId();
if ((affKeyCol == null || colId != affKeyCol.column.getColumnId()) && !desc.isKeyColumn(colId))
return null;
if (right instanceof GridSqlConst) {
GridSqlConst constant = (GridSqlConst) right;
return new CacheQueryPartitionInfo(ctx.affinity().partition(tbl.cacheName(), constant.value().getObject()), null, null, -1, -1);
}
GridSqlParameter param = (GridSqlParameter) right;
return new CacheQueryPartitionInfo(-1, tbl.cacheName(), tbl.getName(), column.column().getType(), param.index());
}
use of org.h2.table.Column in project ignite by apache.
the class H2TableDescriptor method createSystemIndexes.
/**
* {@inheritDoc}
*/
@Override
public ArrayList<Index> createSystemIndexes(GridH2Table tbl) {
ArrayList<Index> idxs = new ArrayList<>();
IndexColumn keyCol = tbl.indexColumn(KEY_COL, SortOrder.ASCENDING);
IndexColumn affCol = tbl.getAffinityKeyColumn();
if (affCol != null && H2Utils.equals(affCol, keyCol))
affCol = null;
GridH2RowDescriptor desc = tbl.rowDescriptor();
Index hashIdx = createHashIndex(tbl, "_key_PK_hash", H2Utils.treeIndexColumns(desc, new ArrayList<IndexColumn>(2), keyCol, affCol));
if (hashIdx != null)
idxs.add(hashIdx);
// Add primary key index.
Index pkIdx = idx.createSortedIndex("_key_PK", tbl, true, H2Utils.treeIndexColumns(desc, new ArrayList<IndexColumn>(2), keyCol, affCol), -1);
idxs.add(pkIdx);
if (type().valueClass() == String.class) {
try {
luceneIdx = new GridLuceneIndex(idx.kernalContext(), tbl.cacheName(), type);
} catch (IgniteCheckedException e1) {
throw new IgniteException(e1);
}
}
boolean affIdxFound = false;
GridQueryIndexDescriptor textIdx = type.textIndex();
if (textIdx != null) {
try {
luceneIdx = new GridLuceneIndex(idx.kernalContext(), tbl.cacheName(), type);
} catch (IgniteCheckedException e1) {
throw new IgniteException(e1);
}
}
// Locate index where affinity column is first (if any).
if (affCol != null) {
for (GridQueryIndexDescriptor idxDesc : type.indexes().values()) {
if (idxDesc.type() != QueryIndexType.SORTED)
continue;
String firstField = idxDesc.fields().iterator().next();
Column col = tbl.getColumn(firstField);
IndexColumn idxCol = tbl.indexColumn(col.getColumnId(), idxDesc.descending(firstField) ? SortOrder.DESCENDING : SortOrder.ASCENDING);
affIdxFound |= H2Utils.equals(idxCol, affCol);
}
}
// Add explicit affinity key index if nothing alike was found.
if (affCol != null && !affIdxFound) {
idxs.add(idx.createSortedIndex("AFFINITY_KEY", tbl, false, H2Utils.treeIndexColumns(desc, new ArrayList<IndexColumn>(2), affCol, keyCol), -1));
}
return idxs;
}
use of org.h2.table.Column in project ignite by apache.
the class UpdatePlan method processRowForUpdate.
/**
* Convert a row into value.
*
* @param row Row to process.
* @throws IgniteCheckedException if failed.
* @return Tuple contains: [key, old value, new value]
*/
public T3<Object, Object, Object> processRowForUpdate(List<?> row) throws IgniteCheckedException {
GridH2RowDescriptor rowDesc = tbl.rowDescriptor();
GridQueryTypeDescriptor desc = rowDesc.type();
GridCacheContext cctx = rowDesc.context();
boolean hasNewVal = (valColIdx != -1);
boolean hasProps = !hasNewVal || colNames.length > 1;
Object key = row.get(0);
Object oldVal = row.get(1);
if (cctx.binaryMarshaller() && !(oldVal instanceof BinaryObject))
oldVal = cctx.grid().binary().toBinary(oldVal);
Object newVal;
Map<String, Object> newColVals = new HashMap<>();
for (int i = 0; i < colNames.length; i++) {
if (hasNewVal && i == valColIdx - 2)
continue;
GridQueryProperty prop = tbl.rowDescriptor().type().property(colNames[i]);
assert prop != null : "Unknown property: " + colNames[i];
newColVals.put(colNames[i], DmlUtils.convert(row.get(i + 2), rowDesc, prop.type(), colTypes[i]));
}
newVal = valSupplier.apply(row);
if (newVal == null)
throw new IgniteSQLException("New value for UPDATE must not be null", IgniteQueryErrorCode.NULL_VALUE);
// Skip key and value - that's why we start off with 3rd column
for (int i = 0; i < tbl.getColumns().length - DEFAULT_COLUMNS_COUNT; i++) {
Column c = tbl.getColumn(i + DEFAULT_COLUMNS_COUNT);
if (rowDesc.isKeyValueOrVersionColumn(c.getColumnId()))
continue;
GridQueryProperty prop = desc.property(c.getName());
if (prop.key())
// Don't get values of key's columns - we won't use them anyway
continue;
boolean hasNewColVal = newColVals.containsKey(c.getName());
if (!hasNewColVal)
continue;
Object colVal = newColVals.get(c.getName());
// UPDATE currently does not allow to modify key or its fields, so we must be safe to pass null as key.
rowDesc.setColumnValue(null, newVal, colVal, i);
}
if (cctx.binaryMarshaller() && hasProps) {
assert newVal instanceof BinaryObjectBuilder;
newVal = ((BinaryObjectBuilder) newVal).build();
}
desc.validateKeyAndValue(key, newVal);
return new T3<>(key, oldVal, newVal);
}
use of org.h2.table.Column in project ignite by apache.
the class UpdatePlan method processRow.
/**
* Convert a row into key-value pair.
*
* @param row Row to process.
* @throws IgniteCheckedException if failed.
*/
public IgniteBiTuple<?, ?> processRow(List<?> row) throws IgniteCheckedException {
if (mode != BULK_LOAD && row.size() != colNames.length)
throw new IgniteSQLException("Not enough values in a row: " + row.size() + " instead of " + colNames.length, IgniteQueryErrorCode.ENTRY_PROCESSING);
GridH2RowDescriptor rowDesc = tbl.rowDescriptor();
GridQueryTypeDescriptor desc = rowDesc.type();
GridCacheContext cctx = rowDesc.context();
Object key = keySupplier.apply(row);
if (QueryUtils.isSqlType(desc.keyClass())) {
assert keyColIdx != -1;
key = DmlUtils.convert(key, rowDesc, desc.keyClass(), colTypes[keyColIdx]);
}
Object val = valSupplier.apply(row);
if (QueryUtils.isSqlType(desc.valueClass())) {
assert valColIdx != -1;
val = DmlUtils.convert(val, rowDesc, desc.valueClass(), colTypes[valColIdx]);
}
if (key == null) {
if (F.isEmpty(desc.keyFieldName()))
throw new IgniteSQLException("Key for INSERT, COPY, or MERGE must not be null", IgniteQueryErrorCode.NULL_KEY);
else
throw new IgniteSQLException("Null value is not allowed for column '" + desc.keyFieldName() + "'", IgniteQueryErrorCode.NULL_KEY);
}
if (val == null) {
if (F.isEmpty(desc.valueFieldName()))
throw new IgniteSQLException("Value for INSERT, COPY, MERGE, or UPDATE must not be null", IgniteQueryErrorCode.NULL_VALUE);
else
throw new IgniteSQLException("Null value is not allowed for column '" + desc.valueFieldName() + "'", IgniteQueryErrorCode.NULL_VALUE);
}
int actualColCnt = Math.min(colNames.length, row.size());
Map<String, Object> newColVals = new HashMap<>();
for (int i = 0; i < actualColCnt; i++) {
if (i == keyColIdx || i == valColIdx)
continue;
String colName = colNames[i];
GridQueryProperty prop = desc.property(colName);
assert prop != null;
Class<?> expCls = prop.type();
newColVals.put(colName, DmlUtils.convert(row.get(i), rowDesc, expCls, colTypes[i]));
}
desc.setDefaults(key, val);
// We update columns in the order specified by the table for a reason - table's
// column order preserves their precedence for correct update of nested properties.
Column[] tblCols = tbl.getColumns();
// First 3 columns are _key, _val and _ver. Skip 'em.
for (int i = DEFAULT_COLUMNS_COUNT; i < tblCols.length; i++) {
if (tbl.rowDescriptor().isKeyValueOrVersionColumn(i))
continue;
String colName = tblCols[i].getName();
if (!newColVals.containsKey(colName))
continue;
Object colVal = newColVals.get(colName);
desc.setValue(colName, key, val, colVal);
}
if (cctx.binaryMarshaller()) {
if (key instanceof BinaryObjectBuilder)
key = ((BinaryObjectBuilder) key).build();
if (val instanceof BinaryObjectBuilder)
val = ((BinaryObjectBuilder) val).build();
}
desc.validateKeyAndValue(key, val);
return new IgniteBiTuple<>(key, val);
}
Aggregations