use of org.h2.table.IndexColumn in project ignite by apache.
the class H2Utils method unwrapKeyColumns.
/**
* Create list of index columns. Where possible _KEY columns will be unwrapped.
*
* @param tbl GridH2Table instance
* @param idxCols List of index columns.
*
* @return Array of key and affinity columns. Key's, if it possible, splitted into simple components.
*/
@NotNull
public static IndexColumn[] unwrapKeyColumns(GridH2Table tbl, IndexColumn[] idxCols) {
ArrayList<IndexColumn> keyCols = new ArrayList<>();
boolean isSql = tbl.rowDescriptor().tableDescriptor().sql();
if (!isSql)
return idxCols;
GridQueryTypeDescriptor type = tbl.rowDescriptor().type();
for (IndexColumn idxCol : idxCols) {
if (idxCol.column.getColumnId() == KEY_COL) {
if (QueryUtils.isSqlType(type.keyClass())) {
int altKeyColId = tbl.rowDescriptor().getAlternativeColumnId(QueryUtils.KEY_COL);
// Remap simple key to alternative column.
IndexColumn idxKeyCol = new IndexColumn();
idxKeyCol.column = tbl.getColumn(altKeyColId);
idxKeyCol.columnName = idxKeyCol.column.getName();
idxKeyCol.sortType = idxCol.sortType;
keyCols.add(idxKeyCol);
} else {
boolean added = false;
for (String propName : type.fields().keySet()) {
GridQueryProperty prop = type.property(propName);
if (prop.key()) {
added = true;
Column col = tbl.getColumn(propName);
keyCols.add(tbl.indexColumn(col.getColumnId(), SortOrder.ASCENDING));
}
}
// we have to fall back to whole-key index.
if (!added)
keyCols.add(idxCol);
}
} else
keyCols.add(idxCol);
}
return keyCols.toArray(new IndexColumn[0]);
}
use of org.h2.table.IndexColumn in project ignite by apache.
the class H2Utils method indexColumnsSql.
/**
* Generate String represenation of given indexed columns.
*
* @param idxCols Indexed columns.
* @return String represenation of given indexed columns.
*/
public static String indexColumnsSql(IndexColumn[] idxCols) {
GridStringBuilder sb = new SB();
boolean first = true;
for (IndexColumn col : idxCols) {
if (first)
first = false;
else
sb.a(", ");
sb.a(withQuotes(col.columnName)).a(" ").a(col.sortType == SortOrder.ASCENDING ? "ASC" : "DESC");
}
return sb.toString();
}
use of org.h2.table.IndexColumn in project ignite by apache.
the class H2TableDescriptor method createUserIndex.
/**
* Create user index.
*
* @param idxDesc Index descriptor.
* @param cacheVisitor Cache visitor.
* @return Index.
*/
public GridH2IndexBase createUserIndex(GridQueryIndexDescriptor idxDesc, @Nullable SchemaIndexCacheVisitor cacheVisitor) {
IndexColumn keyCol = tbl.indexColumn(QueryUtils.KEY_COL, SortOrder.ASCENDING);
IndexColumn affCol = tbl.getAffinityKeyColumn();
List<IndexColumn> cols = new ArrayList<>(idxDesc.fields().size() + 2);
for (String field : idxDesc.fields()) {
Column col = tbl.getColumn(field);
cols.add(tbl.indexColumn(col.getColumnId(), idxDesc.descending(field) ? SortOrder.DESCENDING : SortOrder.ASCENDING));
}
GridH2RowDescriptor desc = tbl.rowDescriptor();
if (idxDesc.type() == QueryIndexType.SORTED) {
List<IndexColumn> unwrappedKeyCols = extractKeyColumns(tbl, keyCol, affCol);
List<IndexColumn> colsWithUnwrappedKey = new ArrayList<>(cols);
H2Utils.addUniqueColumns(colsWithUnwrappedKey, unwrappedKeyCols);
cols = H2Utils.treeIndexColumns(desc, cols, keyCol, affCol);
return idx.createSortedIndex(idxDesc.name(), tbl, false, false, colsWithUnwrappedKey, cols, idxDesc.inlineSize(), cacheVisitor);
} else if (idxDesc.type() == QueryIndexType.GEOSPATIAL)
return H2Utils.createSpatialIndex(tbl, idxDesc.name(), cols);
throw new IllegalStateException("Index type: " + idxDesc.type());
}
use of org.h2.table.IndexColumn in project ignite by apache.
the class H2TableDescriptor method createSystemIndexes.
/**
* Create list of indexes. First must be primary key, after that all unique indexes and only then non-unique
* indexes. All indexes must be subtypes of {@link H2TreeIndexBase}.
*
* @param tbl Table to create indexes for.
* @return List of indexes.
*/
public ArrayList<Index> createSystemIndexes(GridH2Table tbl) {
ArrayList<Index> idxs = new ArrayList<>();
IndexColumn keyCol = tbl.indexColumn(QueryUtils.KEY_COL, SortOrder.ASCENDING);
IndexColumn affCol = tbl.getAffinityKeyColumn();
if (affCol != null && H2Utils.equals(affCol, keyCol))
affCol = null;
List<IndexColumn> unwrappedKeyAndAffinityCols = extractKeyColumns(tbl, keyCol, affCol);
List<IndexColumn> wrappedKeyCols = H2Utils.treeIndexColumns(tbl.rowDescriptor(), new ArrayList<>(2), keyCol, affCol);
Index hashIdx = createHashIndex(tbl, wrappedKeyCols);
if (hashIdx != null)
idxs.add(hashIdx);
// Add primary key index.
Index pkIdx = idx.createSortedIndex(PK_IDX_NAME, tbl, true, false, unwrappedKeyAndAffinityCols, wrappedKeyCols, tbl.rowDescriptor().tableDescriptor().type().primaryKeyInlineSize(), null);
idxs.add(pkIdx);
if (type().valueClass() == String.class && !idx.distributedConfiguration().isDisableCreateLuceneIndexForStringValueType()) {
try {
luceneIdx = new GridLuceneIndex(idx.kernalContext(), tbl.cacheName(), type);
} catch (IgniteCheckedException e1) {
throw new IgniteException(e1);
}
}
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) {
boolean affIdxFound = false;
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 (!affIdxFound) {
List<IndexColumn> unwrappedKeyCols = extractKeyColumns(tbl, keyCol, null);
ArrayList<IndexColumn> colsWithUnwrappedKey = new ArrayList<>(unwrappedKeyCols.size());
colsWithUnwrappedKey.add(affCol);
// We need to reorder PK columns to have affinity key as first column, that's why we can't use simple PK columns
H2Utils.addUniqueColumns(colsWithUnwrappedKey, unwrappedKeyCols);
List<IndexColumn> cols = H2Utils.treeIndexColumns(tbl.rowDescriptor(), new ArrayList<>(2), affCol, keyCol);
idxs.add(idx.createSortedIndex(AFFINITY_KEY_IDX_NAME, tbl, false, true, colsWithUnwrappedKey, cols, tbl.rowDescriptor().tableDescriptor().type().affinityFieldInlineSize(), null));
}
}
return idxs;
}
use of org.h2.table.IndexColumn in project ignite by apache.
the class GridSqlQueryParser method parseCreateTable.
/**
* Parse {@code CREATE TABLE} statement.
*
* @param createTbl {@code CREATE TABLE} statement.
* @see <a href="http://h2database.com/html/grammar.html#create_table">H2 {@code CREATE TABLE} spec.</a>
*/
private GridSqlCreateTable parseCreateTable(CreateTable createTbl) {
GridSqlCreateTable res = new GridSqlCreateTable();
res.templateName(QueryUtils.TEMPLATE_PARTITIONED);
Query qry = CREATE_TABLE_QUERY.get(createTbl);
if (qry != null) {
throw new IgniteSQLException("CREATE TABLE ... AS ... syntax is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
List<DefineCommand> constraints = CREATE_TABLE_CONSTRAINTS.get(createTbl);
if (F.isEmpty(constraints)) {
throw new IgniteSQLException("No PRIMARY KEY defined for CREATE TABLE", IgniteQueryErrorCode.PARSING);
}
if (constraints.size() > 1) {
throw new IgniteSQLException("Too many constraints - only PRIMARY KEY is supported for CREATE TABLE", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
DefineCommand constraint = constraints.get(0);
if (!(constraint instanceof AlterTableAddConstraint)) {
throw new IgniteSQLException("Unsupported type of constraint for CREATE TABLE - only PRIMARY KEY " + "is supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
AlterTableAddConstraint alterTbl = (AlterTableAddConstraint) constraint;
if (alterTbl.getType() != Command.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY) {
throw new IgniteSQLException("Unsupported type of constraint for CREATE TABLE - only PRIMARY KEY " + "is supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
Schema schema = SCHEMA_COMMAND_SCHEMA.get(createTbl);
res.schemaName(schema.getName());
CreateTableData data = CREATE_TABLE_DATA.get(createTbl);
if (data.globalTemporary) {
throw new IgniteSQLException("GLOBAL TEMPORARY keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
if (data.temporary) {
throw new IgniteSQLException("TEMPORARY keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
if (data.isHidden) {
throw new IgniteSQLException("HIDDEN keyword is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
if (!data.persistIndexes) {
throw new IgniteSQLException("MEMORY and NOT PERSISTENT keywords are not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
LinkedHashMap<String, GridSqlColumn> cols = new LinkedHashMap<>(data.columns.size());
for (Column col : data.columns) {
if (cols.put(col.getName(), parseColumn(col)) != null)
throw new IgniteSQLException("Duplicate column name: " + col.getName(), IgniteQueryErrorCode.PARSING);
}
if (cols.containsKey(QueryUtils.KEY_FIELD_NAME.toUpperCase()) || cols.containsKey(QueryUtils.VAL_FIELD_NAME.toUpperCase())) {
throw new IgniteSQLException("Direct specification of _KEY and _VAL columns is forbidden", IgniteQueryErrorCode.PARSING);
}
IndexColumn[] pkIdxCols = CREATE_TABLE_PK.get(createTbl);
if (F.isEmpty(pkIdxCols))
throw new AssertionError("No PRIMARY KEY columns specified");
LinkedHashSet<String> pkCols = new LinkedHashSet<>();
for (IndexColumn pkIdxCol : pkIdxCols) {
GridSqlColumn gridCol = cols.get(pkIdxCol.columnName);
if (gridCol == null) {
throw new IgniteSQLException("PRIMARY KEY column is not defined: " + pkIdxCol.columnName, IgniteQueryErrorCode.PARSING);
}
pkCols.add(gridCol.columnName());
}
int keyColsNum = pkCols.size();
int valColsNum = cols.size() - keyColsNum;
if (valColsNum == 0) {
throw new IgniteSQLException("Table must have at least one non PRIMARY KEY column.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
res.columns(cols);
res.primaryKeyColumns(pkCols);
res.tableName(data.tableName);
res.ifNotExists(CREATE_TABLE_IF_NOT_EXISTS.get(createTbl));
List<String> extraParams = data.tableEngineParams != null ? new ArrayList<String>() : null;
if (data.tableEngineParams != null)
for (String s : data.tableEngineParams) extraParams.addAll(F.asList(s.split(",")));
res.params(extraParams);
if (!F.isEmpty(extraParams)) {
Map<String, String> params = new HashMap<>();
for (String p : extraParams) {
String[] parts = p.split(PARAM_NAME_VALUE_SEPARATOR);
if (parts.length > 2) {
throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p, IgniteQueryErrorCode.PARSING);
}
String name = parts[0].trim().toUpperCase();
String val = parts.length > 1 ? parts[1].trim() : null;
if (F.isEmpty(name)) {
throw new IgniteSQLException("Invalid parameter (key[=value] expected): " + p, IgniteQueryErrorCode.PARSING);
}
if (params.put(name, val) != null)
throw new IgniteSQLException("Duplicate parameter: " + p, IgniteQueryErrorCode.PARSING);
}
for (Map.Entry<String, String> e : params.entrySet()) processExtraParam(e.getKey(), e.getValue(), res);
}
// Process key wrapping.
Boolean wrapKey = res.wrapKey();
if (wrapKey != null && !wrapKey) {
if (keyColsNum > 1) {
throw new IgniteSQLException(PARAM_WRAP_KEY + " cannot be false when composite primary key exists.", IgniteQueryErrorCode.PARSING);
}
if (!F.isEmpty(res.keyTypeName())) {
throw new IgniteSQLException(PARAM_WRAP_KEY + " cannot be false when " + PARAM_KEY_TYPE + " is set.", IgniteQueryErrorCode.PARSING);
}
}
boolean wrapKey0 = (res.wrapKey() != null && res.wrapKey()) || !F.isEmpty(res.keyTypeName()) || keyColsNum > 1;
res.wrapKey(wrapKey0);
// Process value wrapping.
Boolean wrapVal = res.wrapValue();
if (wrapVal != null && !wrapVal) {
if (valColsNum > 1) {
throw new IgniteSQLException(PARAM_WRAP_VALUE + " cannot be false when multiple non-primary key " + "columns exist.", IgniteQueryErrorCode.PARSING);
}
if (!F.isEmpty(res.valueTypeName())) {
throw new IgniteSQLException(PARAM_WRAP_VALUE + " cannot be false when " + PARAM_VAL_TYPE + " is set.", IgniteQueryErrorCode.PARSING);
}
res.wrapValue(false);
} else
// By default value is always wrapped to allow for ALTER TABLE ADD COLUMN commands.
res.wrapValue(true);
if (!F.isEmpty(res.valueTypeName()) && F.eq(res.keyTypeName(), res.valueTypeName())) {
throw new IgniteSQLException("Key and value type names " + "should be different for CREATE TABLE: " + res.valueTypeName(), IgniteQueryErrorCode.PARSING);
}
if (res.affinityKey() == null) {
LinkedHashSet<String> pkCols0 = res.primaryKeyColumns();
if (!F.isEmpty(pkCols0) && pkCols0.size() == 1 && wrapKey0)
res.affinityKey(pkCols0.iterator().next());
}
return res;
}
Aggregations