use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.
the class IgniteH2Indexing method queryDistributedSqlFields.
/** {@inheritDoc} */
@Override
public FieldsQueryCursor<List<?>> queryDistributedSqlFields(String schemaName, SqlFieldsQuery qry, boolean keepBinary, GridQueryCancel cancel, @Nullable Integer mainCacheId) {
final String sqlQry = qry.getSql();
Connection c = connectionForSchema(schemaName);
final boolean enforceJoinOrder = qry.isEnforceJoinOrder();
final boolean distributedJoins = qry.isDistributedJoins();
final boolean grpByCollocated = qry.isCollocated();
final DistributedJoinMode distributedJoinMode = distributedJoinMode(qry.isLocal(), distributedJoins);
GridCacheTwoStepQuery twoStepQry = null;
List<GridQueryFieldMetadata> meta;
final H2TwoStepCachedQueryKey cachedQryKey = new H2TwoStepCachedQueryKey(schemaName, sqlQry, grpByCollocated, distributedJoins, enforceJoinOrder, qry.isLocal());
H2TwoStepCachedQuery cachedQry = twoStepCache.get(cachedQryKey);
if (cachedQry != null) {
twoStepQry = cachedQry.query().copy();
meta = cachedQry.meta();
} else {
final UUID locNodeId = ctx.localNodeId();
// Here we will just parse the statement, no need to optimize it at all.
H2Utils.setupConnection(c, /*distributedJoins*/
false, /*enforceJoinOrder*/
true);
GridH2QueryContext.set(new GridH2QueryContext(locNodeId, locNodeId, 0, PREPARE).distributedJoinMode(distributedJoinMode));
PreparedStatement stmt = null;
Prepared prepared;
boolean cachesCreated = false;
try {
try {
while (true) {
try {
// Do not cache this statement because the whole query object will be cached later on.
stmt = prepareStatement(c, sqlQry, false);
break;
} catch (SQLException e) {
if (!cachesCreated && (e.getErrorCode() == ErrorCode.SCHEMA_NOT_FOUND_1 || e.getErrorCode() == ErrorCode.TABLE_OR_VIEW_NOT_FOUND_1 || e.getErrorCode() == ErrorCode.INDEX_NOT_FOUND_1)) {
try {
ctx.cache().createMissingQueryCaches();
} catch (IgniteCheckedException ignored) {
throw new CacheException("Failed to create missing caches.", e);
}
cachesCreated = true;
} else
throw new IgniteSQLException("Failed to parse query: " + sqlQry, IgniteQueryErrorCode.PARSING, e);
}
}
prepared = GridSqlQueryParser.prepared(stmt);
if (qry instanceof JdbcSqlFieldsQuery && ((JdbcSqlFieldsQuery) qry).isQuery() != prepared.isQuery())
throw new IgniteSQLException("Given statement type does not match that declared by JDBC driver", IgniteQueryErrorCode.STMT_TYPE_MISMATCH);
if (prepared.isQuery()) {
bindParameters(stmt, F.asList(qry.getArgs()));
twoStepQry = GridSqlQuerySplitter.split((JdbcPreparedStatement) stmt, qry.getArgs(), grpByCollocated, distributedJoins, enforceJoinOrder, this);
assert twoStepQry != null;
}
} finally {
GridH2QueryContext.clearThreadLocal();
}
// It is a DML statement if we did not create a twoStepQuery.
if (twoStepQry == null) {
if (DmlStatementsProcessor.isDmlStatement(prepared)) {
try {
return dmlProc.updateSqlFieldsDistributed(schemaName, stmt, qry, cancel);
} catch (IgniteCheckedException e) {
throw new IgniteSQLException("Failed to execute DML statement [stmt=" + sqlQry + ", params=" + Arrays.deepToString(qry.getArgs()) + "]", e);
}
}
if (DdlStatementsProcessor.isDdlStatement(prepared)) {
try {
return ddlProc.runDdlStatement(sqlQry, stmt);
} catch (IgniteCheckedException e) {
throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + sqlQry + ']', e);
}
}
}
LinkedHashSet<Integer> caches0 = new LinkedHashSet<>();
assert twoStepQry != null;
int tblCnt = twoStepQry.tablesCount();
if (mainCacheId != null)
caches0.add(mainCacheId);
if (tblCnt > 0) {
for (QueryTable tblKey : twoStepQry.tables()) {
GridH2Table tbl = dataTable(tblKey);
int cacheId = CU.cacheId(tbl.cacheName());
caches0.add(cacheId);
}
}
if (caches0.isEmpty())
twoStepQry.local(true);
else {
//Prohibit usage indices with different numbers of segments in same query.
List<Integer> cacheIds = new ArrayList<>(caches0);
checkCacheIndexSegmentation(cacheIds);
twoStepQry.cacheIds(cacheIds);
twoStepQry.local(qry.isLocal());
}
meta = H2Utils.meta(stmt.getMetaData());
} catch (IgniteCheckedException e) {
throw new CacheException("Failed to bind parameters: [qry=" + sqlQry + ", params=" + Arrays.deepToString(qry.getArgs()) + "]", e);
} catch (SQLException e) {
throw new IgniteSQLException(e);
} finally {
U.close(stmt, log);
}
}
if (log.isDebugEnabled())
log.debug("Parsed query: `" + sqlQry + "` into two step query: " + twoStepQry);
twoStepQry.pageSize(qry.getPageSize());
if (cancel == null)
cancel = new GridQueryCancel();
int[] partitions = qry.getPartitions();
if (partitions == null && twoStepQry.derivedPartitions() != null) {
try {
partitions = calculateQueryPartitions(twoStepQry.derivedPartitions(), qry.getArgs());
} catch (IgniteCheckedException e) {
throw new CacheException("Failed to calculate derived partitions: [qry=" + sqlQry + ", params=" + Arrays.deepToString(qry.getArgs()) + "]", e);
}
}
QueryCursorImpl<List<?>> cursor = new QueryCursorImpl<>(runQueryTwoStep(schemaName, twoStepQry, keepBinary, enforceJoinOrder, qry.getTimeout(), cancel, qry.getArgs(), partitions), cancel);
cursor.fieldsMeta(meta);
if (cachedQry == null && !twoStepQry.explain()) {
cachedQry = new H2TwoStepCachedQuery(meta, twoStepQry.copy());
twoStepCache.putIfAbsent(cachedQryKey, cachedQry);
}
return cursor;
}
use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.
the class IgniteH2Indexing method createTable.
/**
* Create db table by using given table descriptor.
*
* @param schemaName Schema name.
* @param schema Schema.
* @param tbl Table descriptor.
* @param conn Connection.
* @throws SQLException If failed to create db table.
* @throws IgniteCheckedException If failed.
*/
private void createTable(String schemaName, H2Schema schema, H2TableDescriptor tbl, Connection conn) throws SQLException, IgniteCheckedException {
assert schema != null;
assert tbl != null;
String keyType = dbTypeFromClass(tbl.type().keyClass());
String valTypeStr = dbTypeFromClass(tbl.type().valueClass());
SB sql = new SB();
String keyValVisibility = tbl.type().fields().isEmpty() ? " VISIBLE" : " INVISIBLE";
sql.a("CREATE TABLE ").a(tbl.fullTableName()).a(" (").a(KEY_FIELD_NAME).a(' ').a(keyType).a(keyValVisibility).a(" NOT NULL");
sql.a(',').a(VAL_FIELD_NAME).a(' ').a(valTypeStr).a(keyValVisibility);
sql.a(',').a(VER_FIELD_NAME).a(" OTHER INVISIBLE");
for (Map.Entry<String, Class<?>> e : tbl.type().fields().entrySet()) sql.a(',').a(H2Utils.withQuotes(e.getKey())).a(' ').a(dbTypeFromClass(e.getValue()));
sql.a(')');
if (log.isDebugEnabled())
log.debug("Creating DB table with SQL: " + sql);
GridH2RowDescriptor rowDesc = new H2RowDescriptor(this, tbl, tbl.type(), schema);
H2RowFactory rowFactory = tbl.rowFactory(rowDesc);
GridH2Table h2Tbl = H2TableEngine.createTable(conn, sql.toString(), rowDesc, rowFactory, tbl);
for (GridH2IndexBase usrIdx : tbl.createUserIndexes()) addInitialUserIndex(schemaName, tbl, usrIdx);
if (dataTables.putIfAbsent(h2Tbl.identifier(), h2Tbl) != null)
throw new IllegalStateException("Table already exists: " + h2Tbl.identifierString());
}
use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table 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(schema, "_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(), schema.offheap(), 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(), schema.offheap(), 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(schema, "AFFINITY_KEY", tbl, false, H2Utils.treeIndexColumns(desc, new ArrayList<IndexColumn>(2), affCol, keyCol), -1));
}
return idxs;
}
use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.
the class UpdatePlanBuilder method verifyUpdateColumns.
/**
* Check that UPDATE statement affects no key columns.
*
* @param statement Statement.
*/
private static void verifyUpdateColumns(GridSqlStatement statement) {
if (statement == null || !(statement instanceof GridSqlUpdate))
return;
GridSqlUpdate update = (GridSqlUpdate) statement;
GridSqlElement updTarget = update.target();
Set<GridSqlTable> tbls = new HashSet<>();
DmlAstUtils.collectAllGridTablesInTarget(updTarget, tbls);
if (tbls.size() != 1)
throw new IgniteSQLException("Failed to determine target table for UPDATE", IgniteQueryErrorCode.TABLE_NOT_FOUND);
GridSqlTable tbl = tbls.iterator().next();
GridH2Table gridTbl = tbl.dataTable();
if (updateAffectsKeyColumns(gridTbl, update.set().keySet()))
throw new IgniteSQLException("SQL UPDATE can't modify key or its fields directly", IgniteQueryErrorCode.KEY_UPDATE);
}
use of org.apache.ignite.internal.processors.query.h2.opt.GridH2Table in project ignite by apache.
the class DdlStatementsProcessor method runDdlStatement.
/**
* Execute DDL statement.
*
* @param sql SQL.
* @param stmt H2 statement to parse and execute.
*/
@SuppressWarnings("unchecked")
public FieldsQueryCursor<List<?>> runDdlStatement(String sql, PreparedStatement stmt) throws IgniteCheckedException {
assert stmt instanceof JdbcPreparedStatement;
IgniteInternalFuture fut = null;
try {
GridSqlStatement stmt0 = new GridSqlQueryParser(false).parse(GridSqlQueryParser.prepared(stmt));
if (stmt0 instanceof GridSqlCreateIndex) {
GridSqlCreateIndex cmd = (GridSqlCreateIndex) stmt0;
GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
if (tbl == null)
throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName());
assert tbl.rowDescriptor() != null;
QueryIndex newIdx = new QueryIndex();
newIdx.setName(cmd.index().getName());
newIdx.setIndexType(cmd.index().getIndexType());
LinkedHashMap<String, Boolean> flds = new LinkedHashMap<>();
// Let's replace H2's table and property names by those operated by GridQueryProcessor.
GridQueryTypeDescriptor typeDesc = tbl.rowDescriptor().type();
for (Map.Entry<String, Boolean> e : cmd.index().getFields().entrySet()) {
GridQueryProperty prop = typeDesc.property(e.getKey());
if (prop == null)
throw new SchemaOperationException(SchemaOperationException.CODE_COLUMN_NOT_FOUND, e.getKey());
flds.put(prop.name(), e.getValue());
}
newIdx.setFields(flds);
fut = ctx.query().dynamicIndexCreate(tbl.cacheName(), cmd.schemaName(), typeDesc.tableName(), newIdx, cmd.ifNotExists());
} else if (stmt0 instanceof GridSqlDropIndex) {
GridSqlDropIndex cmd = (GridSqlDropIndex) stmt0;
GridH2Table tbl = idx.dataTableForIndex(cmd.schemaName(), cmd.indexName());
if (tbl != null) {
fut = ctx.query().dynamicIndexDrop(tbl.cacheName(), cmd.schemaName(), cmd.indexName(), cmd.ifExists());
} else {
if (cmd.ifExists())
fut = new GridFinishedFuture();
else
throw new SchemaOperationException(SchemaOperationException.CODE_INDEX_NOT_FOUND, cmd.indexName());
}
} else if (stmt0 instanceof GridSqlCreateTable) {
GridSqlCreateTable cmd = (GridSqlCreateTable) stmt0;
if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName()))
throw new SchemaOperationException("CREATE TABLE can only be executed on " + QueryUtils.DFLT_SCHEMA + " schema.");
GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
if (tbl != null) {
if (!cmd.ifNotExists())
throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS, cmd.tableName());
} else {
ctx.query().dynamicTableCreate(cmd.schemaName(), toQueryEntity(cmd), cmd.templateName(), cmd.atomicityMode(), cmd.backups(), cmd.ifNotExists());
}
} else if (stmt0 instanceof GridSqlDropTable) {
GridSqlDropTable cmd = (GridSqlDropTable) stmt0;
if (!F.eq(QueryUtils.DFLT_SCHEMA, cmd.schemaName()))
throw new SchemaOperationException("DROP TABLE can only be executed on " + QueryUtils.DFLT_SCHEMA + " schema.");
GridH2Table tbl = idx.dataTable(cmd.schemaName(), cmd.tableName());
if (tbl == null) {
if (!cmd.ifExists())
throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_NOT_FOUND, cmd.tableName());
} else
ctx.query().dynamicTableDrop(tbl.cacheName(), cmd.tableName(), cmd.ifExists());
} else
throw new IgniteSQLException("Unsupported DDL operation: " + sql, IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
if (fut != null)
fut.get();
QueryCursorImpl<List<?>> resCur = (QueryCursorImpl<List<?>>) new QueryCursorImpl(Collections.singletonList(Collections.singletonList(0L)), null, false);
resCur.fieldsMeta(UPDATE_RESULT_META);
return resCur;
} catch (SchemaOperationException e) {
throw convert(e);
} catch (IgniteSQLException e) {
throw e;
} catch (Exception e) {
throw new IgniteSQLException("Unexpected DLL operation failure: " + e.getMessage(), e);
}
}
Aggregations