You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2018/01/22 19:25:41 UTC
[2/3] ignite git commit: IGNITE-5571: Decoupled SQL fields query from
cache. This closes #2283.
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index 1784496..96b8935 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -107,8 +107,10 @@ import org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2Row;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowDescriptor;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
+import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuery;
import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser;
import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter;
+import org.apache.ignite.internal.processors.query.h2.sql.GridSqlStatement;
import org.apache.ignite.internal.processors.query.h2.twostep.GridMapQueryExecutor;
import org.apache.ignite.internal.processors.query.h2.twostep.GridReduceQueryExecutor;
import org.apache.ignite.internal.processors.query.h2.twostep.MapQueryLazyWorker;
@@ -156,6 +158,7 @@ import org.h2.server.web.WebServer;
import org.h2.table.IndexColumn;
import org.h2.tools.Server;
import org.h2.util.JdbcUtils;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
@@ -380,38 +383,65 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/**
* @param c Connection.
* @param sql SQL.
+ * @return <b>Cached</b> prepared statement.
+ */
+ @SuppressWarnings("ConstantConditions")
+ @Nullable private PreparedStatement cachedStatement(Connection c, String sql) {
+ try {
+ return prepareStatement(c, sql, true, true);
+ }
+ catch (SQLException e) {
+ // We actually don't except anything SQL related here as we're supposed to work with cache only.
+ throw new AssertionError(e);
+ }
+ }
+
+ /**
+ * @param c Connection.
+ * @param sql SQL.
* @param useStmtCache If {@code true} uses statement cache.
* @return Prepared statement.
* @throws SQLException If failed.
*/
- private PreparedStatement prepareStatement(Connection c, String sql, boolean useStmtCache) throws SQLException {
- if (useStmtCache) {
- Thread curThread = Thread.currentThread();
-
- H2StatementCache cache = stmtCache.get(curThread);
-
- if (cache == null) {
- H2StatementCache cache0 = new H2StatementCache(PREPARED_STMT_CACHE_SIZE);
+ @SuppressWarnings("ConstantConditions")
+ @NotNull private PreparedStatement prepareStatement(Connection c, String sql, boolean useStmtCache)
+ throws SQLException {
+ return prepareStatement(c, sql, useStmtCache, false);
+ }
- cache = stmtCache.putIfAbsent(curThread, cache0);
+ /**
+ * @param c Connection.
+ * @param sql SQL.
+ * @param useStmtCache If {@code true} uses statement cache.
+ * @param cachedOnly Whether parsing should be avoided if statement has not been found in cache.
+ * @return Prepared statement.
+ * @throws SQLException If failed.
+ */
+ @Nullable private PreparedStatement prepareStatement(Connection c, String sql, boolean useStmtCache,
+ boolean cachedOnly) throws SQLException {
+ // We can't avoid parsing and avoid using cache at the same time.
+ assert useStmtCache || !cachedOnly;
- if (cache == null)
- cache = cache0;
- }
+ if (useStmtCache) {
+ H2StatementCache cache = getStatementsCacheForCurrentThread();
- cache.updateLastUsage();
+ H2CachedStatementKey key = new H2CachedStatementKey(c.getSchema(), sql);
- PreparedStatement stmt = cache.get(sql);
+ PreparedStatement stmt = cache.get(key);
- if (stmt != null && !stmt.isClosed() && !((JdbcStatement)stmt).isCancelled()) {
+ if (stmt != null && !stmt.isClosed() && !((JdbcStatement)stmt).isCancelled() &&
+ !GridSqlQueryParser.prepared(stmt).needRecompile()) {
assert stmt.getConnection() == c;
return stmt;
}
+ if (cachedOnly)
+ return null;
+
stmt = prepare0(c, sql);
- cache.put(sql, stmt);
+ cache.put(key, stmt);
return stmt;
}
@@ -444,6 +474,28 @@ public class IgniteH2Indexing implements GridQueryIndexing {
return c.prepareStatement(sql);
}
+ /**
+ * @return {@link H2StatementCache} associated with current thread.
+ */
+ @NotNull private H2StatementCache getStatementsCacheForCurrentThread() {
+ Thread curThread = Thread.currentThread();
+
+ H2StatementCache cache = stmtCache.get(curThread);
+
+ if (cache == null) {
+ H2StatementCache cache0 = new H2StatementCache(PREPARED_STMT_CACHE_SIZE);
+
+ cache = stmtCache.putIfAbsent(curThread, cache0);
+
+ if (cache == null)
+ cache = cache0;
+ }
+
+ cache.updateLastUsage();
+
+ return cache;
+ }
+
/** {@inheritDoc} */
@Override public PreparedStatement prepareNativeStatement(String schemaName, String sql) throws SQLException {
Connection conn = connectionForSchema(schemaName);
@@ -822,7 +874,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @param inlineSize Index inline size.
* @return Index.
*/
- public GridH2IndexBase createSortedIndex(String name, GridH2Table tbl, boolean pk, List<IndexColumn> cols,
+ GridH2IndexBase createSortedIndex(String name, GridH2Table tbl, boolean pk, List<IndexColumn> cols,
int inlineSize) {
try {
GridCacheContext cctx = tbl.cache();
@@ -878,7 +930,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings("unchecked")
- public GridQueryFieldsResult queryLocalSqlFields(final String schemaName, final String qry,
+ GridQueryFieldsResult queryLocalSqlFields(final String schemaName, final String qry,
@Nullable final Collection<Object> params, final IndexingQueryFilter filter, boolean enforceJoinOrder,
final int timeout, final GridQueryCancel cancel) throws IgniteCheckedException {
final Connection conn = connectionForSchema(schemaName);
@@ -901,7 +953,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
fldsQry.setEnforceJoinOrder(enforceJoinOrder);
fldsQry.setTimeout(timeout, TimeUnit.MILLISECONDS);
- return dmlProc.updateSqlFieldsLocal(schemaName, conn, stmt, fldsQry, filter, cancel);
+ return dmlProc.updateSqlFieldsLocal(schemaName, conn, p, fldsQry, filter, cancel);
}
else if (DdlStatementsProcessor.isDdlStatement(p))
throw new IgniteSQLException("DDL statements are supported for the whole cluster only",
@@ -1224,7 +1276,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @throws IgniteCheckedException If failed.
*/
@SuppressWarnings("unchecked")
- public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryLocalSql(String schemaName, String cacheName,
+ <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryLocalSql(String schemaName, String cacheName,
final String qry, String alias, @Nullable final Collection<Object> params, String type,
final IndexingQueryFilter filter, GridQueryCancel cancel) throws IgniteCheckedException {
final H2TableDescriptor tbl = tableDescriptor(schemaName, cacheName, type);
@@ -1314,7 +1366,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <K, V> QueryCursor<Cache.Entry<K, V>> queryDistributedSql(String schemaName, String cacheName,
- SqlQuery qry, boolean keepBinary, int mainCacheId) {
+ SqlQuery qry, boolean keepBinary) {
String type = qry.getType();
H2TableDescriptor tblDesc = tableDescriptor(schemaName, cacheName, type);
@@ -1344,7 +1396,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
fqry.setTimeout(qry.getTimeout(), TimeUnit.MILLISECONDS);
final QueryCursor<List<?>> res =
- queryDistributedSqlFields(schemaName, fqry, keepBinary, null, mainCacheId, true).get(0);
+ querySqlFields(schemaName, fqry, keepBinary, true, null).get(0);
final Iterable<Cache.Entry<K, V>> converted = new Iterable<Cache.Entry<K, V>>() {
@Override public Iterator<Cache.Entry<K, V>> iterator() {
@@ -1425,222 +1477,339 @@ public class IgniteH2Indexing implements GridQueryIndexing {
// Execute.
try {
- List<FieldsQueryCursor<List<?>>> ress = new ArrayList<>(1);
-
FieldsQueryCursor<List<?>> res = ddlProc.runDdlStatement(qry.getSql(), cmd);
- ress.add(res);
-
- return ress;
+ return Collections.singletonList(res);
}
catch (IgniteCheckedException e) {
throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + qry.getSql() + ']', e);
}
}
+ /**
+ * Check expected statement type (when it is set by JDBC) and given statement type.
+ *
+ * @param qry Query.
+ * @param isQry {@code true} for select queries, otherwise (DML/DDL queries) {@code false}.
+ */
+ private void checkQueryType(SqlFieldsQuery qry, boolean isQry) {
+ Boolean qryFlag = qry instanceof SqlFieldsQueryEx ? ((SqlFieldsQueryEx) qry).isQuery() : null;
+
+ if (qryFlag != null && qryFlag != isQry)
+ throw new IgniteSQLException("Given statement type does not match that declared by JDBC driver",
+ IgniteQueryErrorCode.STMT_TYPE_MISMATCH);
+ }
+
+
/** {@inheritDoc} */
- @Override public List<FieldsQueryCursor<List<?>>> queryDistributedSqlFields(String schemaName, SqlFieldsQuery qry,
- boolean keepBinary, GridQueryCancel cancel, @Nullable Integer mainCacheId, boolean failOnMultipleStmts) {
+ @SuppressWarnings("StringEquality")
+ @Override public List<FieldsQueryCursor<List<?>>> querySqlFields(String schemaName, SqlFieldsQuery qry,
+ boolean keepBinary, boolean failOnMultipleStmts, GridQueryCancel cancel) {
List<FieldsQueryCursor<List<?>>> res = tryQueryDistributedSqlFieldsNative(schemaName, qry);
if (res != null)
return res;
- Connection c = connectionForSchema(schemaName);
+ {
+ // First, let's check if we already have a two-step query for this statement...
+ H2TwoStepCachedQueryKey cachedQryKey = new H2TwoStepCachedQueryKey(schemaName, qry.getSql(),
+ qry.isCollocated(), qry.isDistributedJoins(), qry.isEnforceJoinOrder(), qry.isLocal());
- final boolean enforceJoinOrder = qry.isEnforceJoinOrder();
- final boolean distributedJoins = qry.isDistributedJoins();
- final boolean grpByCollocated = qry.isCollocated();
+ H2TwoStepCachedQuery cachedQry;
- final DistributedJoinMode distributedJoinMode = distributedJoinMode(qry.isLocal(), distributedJoins);
+ if ((cachedQry = twoStepCache.get(cachedQryKey)) != null) {
+ checkQueryType(qry, true);
- String sqlQry = qry.getSql();
+ GridCacheTwoStepQuery twoStepQry = cachedQry.query().copy();
- H2TwoStepCachedQueryKey cachedQryKey = new H2TwoStepCachedQueryKey(schemaName, sqlQry, grpByCollocated,
- distributedJoins, enforceJoinOrder, qry.isLocal());
+ List<GridQueryFieldMetadata> meta = cachedQry.meta();
- H2TwoStepCachedQuery cachedQry = twoStepCache.get(cachedQryKey);
+ res = Collections.singletonList(doRunDistributedQuery(schemaName, qry, twoStepQry, meta, keepBinary,
+ cancel));
- if (cachedQry != null) {
- checkQueryType(qry, true);
+ if (!twoStepQry.explain())
+ twoStepCache.putIfAbsent(cachedQryKey, new H2TwoStepCachedQuery(meta, twoStepQry.copy()));
- GridCacheTwoStepQuery twoStepQry = cachedQry.query().copy();
+ return res;
+ }
+ }
- List<GridQueryFieldMetadata> meta = cachedQry.meta();
+ {
+ // Second, let's check if we already have a parsed statement...
+ PreparedStatement cachedStmt;
+
+ if ((cachedStmt = cachedStatement(connectionForSchema(schemaName), qry.getSql())) != null) {
+ Prepared prepared = GridSqlQueryParser.prepared(cachedStmt);
- return Collections.singletonList(executeTwoStepsQuery(schemaName, qry.getPageSize(), qry.getPartitions(),
- qry.getArgs(), keepBinary, qry.isLazy(), qry.getTimeout(), cancel, sqlQry, enforceJoinOrder,
- twoStepQry, meta));
+ // We may use this cached statement only for local queries and non queries.
+ if (qry.isLocal() || !prepared.isQuery())
+ return (List<FieldsQueryCursor<List<?>>>)doRunPrepared(schemaName, prepared, qry, null, null,
+ keepBinary, cancel);
+ }
}
res = new ArrayList<>(1);
- Object[] argsOrig = qry.getArgs();
int firstArg = 0;
- Object[] args;
- String remainingSql = sqlQry;
+
+ String remainingSql = qry.getSql();
while (remainingSql != null) {
- args = null;
- GridCacheTwoStepQuery twoStepQry = null;
- List<GridQueryFieldMetadata> meta;
+ ParsingResult parseRes = parseAndSplit(schemaName,
+ remainingSql != qry.getSql() ? cloneFieldsQuery(qry).setSql(remainingSql) : qry, firstArg);
- final UUID locNodeId = ctx.localNodeId();
+ // Let's avoid second reflection getter call by returning Prepared object too
+ Prepared prepared = parseRes.prepared();
- // Here we will just parse the statement, no need to optimize it at all.
- H2Utils.setupConnection(c, /*distributedJoins*/false, /*enforceJoinOrder*/true);
+ GridCacheTwoStepQuery twoStepQry = parseRes.twoStepQuery();
- GridH2QueryContext.set(new GridH2QueryContext(locNodeId, locNodeId, 0, PREPARE)
- .distributedJoinMode(distributedJoinMode));
+ List<GridQueryFieldMetadata> meta = parseRes.meta();
- PreparedStatement stmt = null;
- Prepared prepared;
+ SqlFieldsQuery newQry = parseRes.newQuery();
- boolean cachesCreated = false;
+ remainingSql = parseRes.remainingSql();
- try {
+ if (remainingSql != null && failOnMultipleStmts)
+ throw new IgniteSQLException("Multiple statements queries are not supported");
+
+ firstArg += prepared.getParameters().size();
+
+ res.addAll(doRunPrepared(schemaName, prepared, newQry, twoStepQry, meta, keepBinary, cancel));
+
+ if (parseRes.twoStepQuery() != null && parseRes.twoStepQueryKey() != null &&
+ !parseRes.twoStepQuery().explain())
+ twoStepCache.putIfAbsent(parseRes.twoStepQueryKey(), new H2TwoStepCachedQuery(meta, twoStepQry.copy()));
+ }
+
+ return res;
+ }
+
+ /**
+ * Execute an all-ready {@link SqlFieldsQuery}.
+ * @param schemaName Schema name.
+ * @param prepared H2 command.
+ * @param qry Fields query with flags.
+ * @param twoStepQry Two-step query if this query must be executed in a distributed way.
+ * @param meta Metadata for {@code twoStepQry}.
+ * @param keepBinary Whether binary objects must not be deserialized automatically.
+ * @param cancel Query cancel state holder.
+ * @return Query result.
+ */
+ private List<? extends FieldsQueryCursor<List<?>>> doRunPrepared(String schemaName, Prepared prepared,
+ SqlFieldsQuery qry, GridCacheTwoStepQuery twoStepQry, List<GridQueryFieldMetadata> meta, boolean keepBinary,
+ GridQueryCancel cancel) {
+ String sqlQry = qry.getSql();
+
+ boolean loc = qry.isLocal();
+
+ IndexingQueryFilter filter = (loc ? backupFilter(null, qry.getPartitions()) : null);
+
+ if (!prepared.isQuery()) {
+ if (DmlStatementsProcessor.isDmlStatement(prepared)) {
try {
- while (true) {
- try {
- // Do not cache this statement because the whole query object will be cached later on.
- stmt = prepareStatement(c, remainingSql, false);
+ Connection conn = connectionForSchema(schemaName);
- 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)
- ) {
+ if (!loc)
+ return dmlProc.updateSqlFieldsDistributed(schemaName, conn, prepared, qry, cancel);
+ else {
+ final GridQueryFieldsResult updRes =
+ dmlProc.updateSqlFieldsLocal(schemaName, conn, prepared, qry, filter, cancel);
+
+ return Collections.singletonList(new QueryCursorImpl<>(new Iterable<List<?>>() {
+ @Override public Iterator<List<?>> iterator() {
try {
- ctx.cache().createMissingQueryCaches();
+ return new GridQueryCacheObjectsIterator(updRes.iterator(), objectContext(),
+ true);
}
- catch (IgniteCheckedException ignored) {
- throw new CacheException("Failed to create missing caches.", e);
+ catch (IgniteCheckedException e) {
+ throw new IgniteException(e);
}
-
- cachesCreated = true;
}
- else
- throw new IgniteSQLException("Failed to parse query. " + e.getMessage(),
- IgniteQueryErrorCode.PARSING, e);
- }
+ }, cancel));
}
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteSQLException("Failed to execute DML statement [stmt=" + sqlQry +
+ ", params=" + Arrays.deepToString(qry.getArgs()) + "]", e);
+ }
+ }
- GridSqlQueryParser.PreparedWithRemaining prep = GridSqlQueryParser.preparedWithRemaining(stmt);
+ if (DdlStatementsProcessor.isDdlStatement(prepared)) {
+ if (loc)
+ throw new IgniteSQLException("DDL statements are not supported for LOCAL caches",
+ IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
- // remaining == null if the query string contains single SQL statement.
- remainingSql = prep.remainingSql();
+ try {
+ return Collections.singletonList(ddlProc.runDdlStatement(sqlQry, prepared));
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + sqlQry + ']', e);
+ }
+ }
- if (remainingSql != null && failOnMultipleStmts)
- throw new IgniteSQLException("Multiple statements queries are not supported");
+ if (prepared instanceof NoOperation) {
+ QueryCursorImpl<List<?>> resCur = (QueryCursorImpl<List<?>>)new QueryCursorImpl(
+ Collections.singletonList(Collections.singletonList(0L)), null, false);
- sqlQry = prep.prepared().getSQL();
+ resCur.fieldsMeta(UPDATE_RESULT_META);
- prepared = prep.prepared();
+ return Collections.singletonList(resCur);
+ }
- int paramsCnt = prepared.getParameters().size();
+ throw new IgniteSQLException("Unsupported DDL/DML operation: " + prepared.getClass().getName());
+ }
- if (!DmlUtils.isBatched(qry) && paramsCnt > 0) {
- if (argsOrig == null || argsOrig.length < firstArg + paramsCnt) {
- throw new IgniteException("Invalid number of query parameters. " +
- "Cannot find " + (argsOrig.length + 1 - firstArg) + " parameter.");
- }
+ if (twoStepQry != null) {
+ if (log.isDebugEnabled())
+ log.debug("Parsed query: `" + sqlQry + "` into two step query: " + twoStepQry);
- args = Arrays.copyOfRange(argsOrig, firstArg, firstArg + paramsCnt);
+ checkQueryType(qry, true);
- firstArg += paramsCnt;
- }
+ return Collections.singletonList(doRunDistributedQuery(schemaName, qry, twoStepQry, meta, keepBinary,
+ cancel));
+ }
+
+ // We've encountered a local query, let's just run it.
+ try {
+ return Collections.singletonList(queryLocalSqlFields(schemaName, qry, keepBinary, filter, cancel));
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteSQLException("Failed to execute local statement [stmt=" + sqlQry +
+ ", params=" + Arrays.deepToString(qry.getArgs()) + "]", e);
+ }
+ }
+
+ /**
+ * Parse and split query if needed, cache either two-step query or statement.
+ * @param schemaName Schema name.
+ * @param qry Query.
+ * @param firstArg Position of the first argument of the following {@code Prepared}.
+ * @return Result: prepared statement, H2 command, two-step query (if needed),
+ * metadata for two-step query (if needed), evaluated query local execution flag.
+ */
+ private ParsingResult parseAndSplit(String schemaName, SqlFieldsQuery qry, int firstArg) {
+ Connection c = connectionForSchema(schemaName);
- cachedQryKey = new H2TwoStepCachedQueryKey(schemaName, sqlQry, grpByCollocated,
- distributedJoins, enforceJoinOrder, qry.isLocal());
+ // For queries that are explicitly local, we rely on the flag specified in the query
+ // because this parsing result will be cached and used for queries directly.
+ // For other queries, we enforce join order at this stage to avoid premature optimizations
+ // (and therefore longer parsing) as long as there'll be more parsing at split stage.
+ boolean enforceJoinOrderOnParsing = (!qry.isLocal() || qry.isEnforceJoinOrder());
- cachedQry = twoStepCache.get(cachedQryKey);
+ H2Utils.setupConnection(c, /*distributedJoins*/false, /*enforceJoinOrder*/enforceJoinOrderOnParsing);
- if (cachedQry != null) {
- checkQueryType(qry, true);
+ boolean loc = qry.isLocal();
- twoStepQry = cachedQry.query().copy();
- meta = cachedQry.meta();
+ PreparedStatement stmt = prepareStatementAndCaches(c, qry.getSql());
- res.add(executeTwoStepsQuery(schemaName, qry.getPageSize(), qry.getPartitions(), args, keepBinary,
- qry.isLazy(), qry.getTimeout(), cancel, sqlQry, enforceJoinOrder,
- twoStepQry, meta));
+ if (loc && GridSqlQueryParser.checkMultipleStatements(stmt))
+ throw new IgniteSQLException("Multiple statements queries are not supported for local queries");
- continue;
- }
- else {
- checkQueryType(qry, prepared.isQuery());
+ GridSqlQueryParser.PreparedWithRemaining prep = GridSqlQueryParser.preparedWithRemaining(stmt);
- if (prepared.isQuery()) {
- bindParameters(stmt, F.asList(args));
+ Prepared prepared = prep.prepared();
- twoStepQry = GridSqlQuerySplitter.split(c, prepared, args,
- grpByCollocated, distributedJoins, enforceJoinOrder, this);
+ checkQueryType(qry, prepared.isQuery());
- assert twoStepQry != null;
- }
- }
- }
- finally {
- GridH2QueryContext.clearThreadLocal();
- }
+ String remainingSql = prep.remainingSql();
- // It is a DML statement if we did not create a twoStepQuery.
- if (twoStepQry == null) {
- if (DmlStatementsProcessor.isDmlStatement(prepared)) {
- try {
- res.addAll(dmlProc.updateSqlFieldsDistributed(schemaName, c, prepared,
- qry.copy().setSql(sqlQry).setArgs(args), cancel));
+ int paramsCnt = prepared.getParameters().size();
- continue;
- }
- catch (IgniteCheckedException e) {
- throw new IgniteSQLException("Failed to execute DML statement [stmt=" + sqlQry +
- ", params=" + Arrays.deepToString(args) + "]", e);
- }
- }
+ Object[] argsOrig = qry.getArgs();
- if (DdlStatementsProcessor.isDdlStatement(prepared)) {
- try {
- res.add(ddlProc.runDdlStatement(sqlQry, prepared));
+ Object[] args = null;
- continue;
- }
- catch (IgniteCheckedException e) {
- throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + sqlQry + ']', e);
- }
- }
+ if (!DmlUtils.isBatched(qry) && paramsCnt > 0) {
+ if (argsOrig == null || argsOrig.length < firstArg + paramsCnt) {
+ throw new IgniteException("Invalid number of query parameters. " +
+ "Cannot find " + (argsOrig != null ? argsOrig.length + 1 - firstArg : 1) + " parameter.");
+ }
- if (prepared instanceof NoOperation) {
- QueryCursorImpl<List<?>> resCur = (QueryCursorImpl<List<?>>)new QueryCursorImpl(
- Collections.singletonList(Collections.singletonList(0L)), null, false);
+ args = Arrays.copyOfRange(argsOrig, firstArg, firstArg + paramsCnt);
+ }
- resCur.fieldsMeta(UPDATE_RESULT_META);
+ if (prepared.isQuery()) {
+ try {
+ bindParameters(stmt, F.asList(args));
+ }
+ catch (IgniteCheckedException e) {
+ U.closeQuiet(stmt);
- res.add(resCur);
+ throw new IgniteSQLException("Failed to bind parameters: [qry=" + prepared.getSQL() + ", params=" +
+ Arrays.deepToString(args) + "]", IgniteQueryErrorCode.PARSING, e);
+ }
- continue;
- }
+ GridSqlQueryParser parser = null;
+
+ if (!loc) {
+ parser = new GridSqlQueryParser(false);
+
+ GridSqlStatement parsedStmt = parser.parse(prepared);
+
+ // Legit assertion - we have H2 query flag above.
+ assert parsedStmt instanceof GridSqlQuery;
+
+ loc = parser.isLocalQuery(qry.isReplicatedOnly());
+ }
+
+ if (loc) {
+ if (parser == null) {
+ parser = new GridSqlQueryParser(false);
+
+ parser.parse(prepared);
}
- assert twoStepQry != null;
+ GridCacheContext cctx = parser.getFirstPartitionedCache();
- List<Integer> cacheIds = collectCacheIds(mainCacheId, twoStepQry);
+ if (cctx != null && cctx.config().getQueryParallelism() > 1) {
+ loc = false;
- if (F.isEmpty(cacheIds))
- twoStepQry.local(true);
- else {
- twoStepQry.cacheIds(cacheIds);
- twoStepQry.local(qry.isLocal());
+ qry.setDistributedJoins(true);
}
+ }
+ }
+
+ SqlFieldsQuery newQry = cloneFieldsQuery(qry).setSql(prepared.getSQL()).setArgs(args);
+
+ boolean hasTwoStep = !loc && prepared.isQuery();
+
+ // Let's not cache multiple statements and distributed queries as whole two step query will be cached later on.
+ if (remainingSql != null || hasTwoStep)
+ getStatementsCacheForCurrentThread().remove(schemaName, qry.getSql());
+
+ if (!hasTwoStep)
+ return new ParsingResult(prepared, newQry, remainingSql, null, null, null);
+
+ final UUID locNodeId = ctx.localNodeId();
+
+ // Now we're sure to have a distributed query. Let's try to get a two-step plan from the cache, or perform the
+ // split if needed.
+ H2TwoStepCachedQueryKey cachedQryKey = new H2TwoStepCachedQueryKey(schemaName, qry.getSql(),
+ qry.isCollocated(), qry.isDistributedJoins(), qry.isEnforceJoinOrder(), qry.isLocal());
+
+ H2TwoStepCachedQuery cachedQry;
+
+ if ((cachedQry = twoStepCache.get(cachedQryKey)) != null) {
+ checkQueryType(qry, true);
+
+ GridCacheTwoStepQuery twoStepQry = cachedQry.query().copy();
+
+ List<GridQueryFieldMetadata> meta = cachedQry.meta();
+
+ return new ParsingResult(prepared, newQry, remainingSql, twoStepQry, cachedQryKey, meta);
+ }
+
+ try {
+ GridH2QueryContext.set(new GridH2QueryContext(locNodeId, locNodeId, 0, PREPARE)
+ .distributedJoinMode(distributedJoinMode(qry.isLocal(), qry.isDistributedJoins())));
- meta = H2Utils.meta(stmt.getMetaData());
+ try {
+ return new ParsingResult(prepared, newQry, remainingSql, split(prepared, newQry),
+ cachedQryKey, H2Utils.meta(stmt.getMetaData()));
}
catch (IgniteCheckedException e) {
- throw new CacheException("Failed to bind parameters: [qry=" + sqlQry + ", params=" +
- Arrays.deepToString(qry.getArgs()) + "]", e);
+ throw new IgniteSQLException("Failed to bind parameters: [qry=" + newQry.getSql() + ", params=" +
+ Arrays.deepToString(newQry.getArgs()) + "]", IgniteQueryErrorCode.PARSING, e);
}
catch (SQLException e) {
throw new IgniteSQLException(e);
@@ -1648,73 +1817,84 @@ public class IgniteH2Indexing implements GridQueryIndexing {
finally {
U.close(stmt, log);
}
-
- res.add(executeTwoStepsQuery(schemaName, qry.getPageSize(), qry.getPartitions(), args, keepBinary,
- qry.isLazy(), qry.getTimeout(), cancel, sqlQry, enforceJoinOrder,
- twoStepQry, meta));
-
- if (cachedQry == null && !twoStepQry.explain()) {
- cachedQry = new H2TwoStepCachedQuery(meta, twoStepQry.copy());
-
- twoStepCache.putIfAbsent(cachedQryKey, cachedQry);
- }
}
+ finally {
+ GridH2QueryContext.clearThreadLocal();
+ }
+ }
- return res;
+ /**
+ * Make a copy of {@link SqlFieldsQuery} with all flags and preserving type.
+ * @param oldQry Query to copy.
+ * @return Query copy.
+ */
+ private SqlFieldsQuery cloneFieldsQuery(SqlFieldsQuery oldQry) {
+ return oldQry.copy().setLocal(oldQry.isLocal()).setPageSize(oldQry.getPageSize());
}
/**
- * Check expected statement type (when it is set by JDBC) and given statement type.
- *
- * @param qry Query.
- * @param isQry {@code true} for select queries, otherwise (DML/DDL queries) {@code false}.
+ * Split query into two-step query.
+ * @param prepared JDBC prepared statement.
+ * @param qry Original fields query.
+ * @return Two-step query.
+ * @throws IgniteCheckedException in case of error inside {@link GridSqlQuerySplitter}.
+ * @throws SQLException in case of error inside {@link GridSqlQuerySplitter}.
*/
- private void checkQueryType(SqlFieldsQuery qry, boolean isQry) {
- if (qry instanceof SqlFieldsQueryEx && ((SqlFieldsQueryEx)qry).isQuery() != null &&
- ((SqlFieldsQueryEx)qry).isQuery() != isQry)
- throw new IgniteSQLException("Given statement type does not match that declared by JDBC driver",
- IgniteQueryErrorCode.STMT_TYPE_MISMATCH);
+ private GridCacheTwoStepQuery split(Prepared prepared, SqlFieldsQuery qry) throws IgniteCheckedException,
+ SQLException {
+ GridCacheTwoStepQuery res = GridSqlQuerySplitter.split(connectionForThread(qry.getSchema()), prepared,
+ qry.getArgs(), qry.isCollocated(), qry.isDistributedJoins(), qry.isEnforceJoinOrder(), this);
+
+ List<Integer> cacheIds = collectCacheIds(null, res);
+
+ if (F.isEmpty(cacheIds))
+ res.local(true);
+ else {
+ res.cacheIds(cacheIds);
+ res.local(qry.isLocal());
+ }
+
+ res.pageSize(qry.getPageSize());
+
+ return res;
}
/**
+ * Run distributed query on detected set of partitions.
* @param schemaName Schema name.
- * @param pageSize Page size.
- * @param partitions Partitions.
- * @param args Arguments.
+ * @param qry Original query.
+ * @param twoStepQry Two-step query.
+ * @param meta Metadata to set to cursor.
* @param keepBinary Keep binary flag.
- * @param lazy Lazy flag.
- * @param timeout Timeout.
- * @param cancel Cancel.
- * @param sqlQry SQL query string.
- * @param enforceJoinOrder Enforce join orded flag.
- * @param twoStepQry Two-steps query.
- * @param meta Metadata.
- * @return Cursor.
- */
- private FieldsQueryCursor<List<?>> executeTwoStepsQuery(String schemaName, int pageSize, int partitions[],
- Object[] args, boolean keepBinary, boolean lazy, int timeout,
- GridQueryCancel cancel, String sqlQry, boolean enforceJoinOrder, GridCacheTwoStepQuery twoStepQry,
- List<GridQueryFieldMetadata> meta) {
+ * @param cancel Cancel handler.
+ * @return Cursor representing distributed query result.
+ */
+ private FieldsQueryCursor<List<?>> doRunDistributedQuery(String schemaName, SqlFieldsQuery qry,
+ GridCacheTwoStepQuery twoStepQry, List<GridQueryFieldMetadata> meta, boolean keepBinary,
+ GridQueryCancel cancel) {
if (log.isDebugEnabled())
- log.debug("Parsed query: `" + sqlQry + "` into two step query: " + twoStepQry);
+ log.debug("Parsed query: `" + qry.getSql() + "` into two step query: " + twoStepQry);
- twoStepQry.pageSize(pageSize);
+ 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(), args);
- } catch (IgniteCheckedException e) {
- throw new CacheException("Failed to calculate derived partitions: [qry=" + sqlQry + ", params=" +
- Arrays.deepToString(args) + "]", e);
+ partitions = calculateQueryPartitions(twoStepQry.derivedPartitions(), qry.getArgs());
+ }
+ catch (IgniteCheckedException e) {
+ throw new CacheException("Failed to calculate derived partitions: [qry=" + qry.getSql() + ", params=" +
+ Arrays.deepToString(qry.getArgs()) + "]", e);
}
}
QueryCursorImpl<List<?>> cursor = new QueryCursorImpl<>(
- runQueryTwoStep(schemaName, twoStepQry, keepBinary, enforceJoinOrder, timeout, cancel,
- args, partitions, lazy), cancel);
+ runQueryTwoStep(schemaName, twoStepQry, keepBinary, qry.isEnforceJoinOrder(), qry.getTimeout(), cancel,
+ qry.getArgs(), partitions, qry.isLazy()), cancel);
cursor.fieldsMeta(meta);
@@ -1722,6 +1902,41 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
+ * Do initial parsing of the statement and create query caches, if needed.
+ * @param c Connection.
+ * @param sqlQry Query.
+ * @return H2 prepared statement.
+ */
+ private PreparedStatement prepareStatementAndCaches(Connection c, String sqlQry) {
+ boolean cachesCreated = false;
+
+ while (true) {
+ try {
+ return prepareStatement(c, sqlQry, true);
+ }
+ 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. " + e.getMessage(),
+ IgniteQueryErrorCode.PARSING, e);
+ }
+ }
+ }
+
+ /**
* Run DML request from other node.
*
* @param schemaName Schema name.
@@ -1748,7 +1963,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @param cacheIds Caches identifiers.
* @throws IllegalStateException if segmented indices used with non-segmented indices.
*/
- private void checkCacheIndexSegmentation(List<Integer> cacheIds) {
+ private void checkCacheIndexSegmentation(Collection<Integer> cacheIds) {
if (cacheIds.isEmpty())
return; // Nothing to check
@@ -2692,7 +2907,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @param twoStepQry Two-step query.
* @return Result.
*/
- public List<Integer> collectCacheIds(@Nullable Integer mainCacheId, GridCacheTwoStepQuery twoStepQry) {
+ @Nullable public List<Integer> collectCacheIds(@Nullable Integer mainCacheId, GridCacheTwoStepQuery twoStepQry) {
LinkedHashSet<Integer> caches0 = new LinkedHashSet<>();
int tblCnt = twoStepQry.tablesCount();
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ParsingResult.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ParsingResult.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ParsingResult.java
new file mode 100644
index 0000000..98d2848
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ParsingResult.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.h2;
+
+import java.util.List;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
+import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
+import org.h2.command.Prepared;
+
+/**
+ * Result of parsing and splitting SQL from {@link SqlFieldsQuery}.
+ */
+final class ParsingResult {
+ /** H2 command. */
+ private final Prepared prepared;
+
+ /** New fields query that may be executed right away. */
+ private final SqlFieldsQuery newQry;
+
+ /** Remaining SQL statements. */
+ private final String remainingSql;
+
+ /** Two-step query, or {@code} null if this result is for local query. */
+ private final GridCacheTwoStepQuery twoStepQry;
+
+ /** Two-step query key to cache {@link #twoStepQry}, or {@code null} if there's no need to worry
+ * about two-step caching. */
+ private final H2TwoStepCachedQueryKey twoStepQryKey;
+
+ /** Metadata for two-step query, or {@code} null if this result is for local query. */
+ private final List<GridQueryFieldMetadata> meta;
+
+ /** Simple constructor. */
+ ParsingResult(Prepared prepared, SqlFieldsQuery newQry, String remainingSql, GridCacheTwoStepQuery twoStepQry,
+ H2TwoStepCachedQueryKey twoStepQryKey, List<GridQueryFieldMetadata> meta) {
+ this.prepared = prepared;
+ this.newQry = newQry;
+ this.remainingSql = remainingSql;
+ this.twoStepQry = twoStepQry;
+ this.twoStepQryKey = twoStepQryKey;
+ this.meta = meta;
+ }
+
+ /**
+ * @return Metadata for two-step query, or {@code} null if this result is for local query.
+ */
+ List<GridQueryFieldMetadata> meta() {
+ return meta;
+ }
+
+ /**
+ * @return New fields query that may be executed right away.
+ */
+ SqlFieldsQuery newQuery() {
+ return newQry;
+ }
+
+ /**
+ * @return H2 command.
+ */
+ Prepared prepared() {
+ return prepared;
+ }
+
+ /**
+ * @return Remaining SQL statements.
+ */
+ String remainingSql() {
+ return remainingSql;
+ }
+
+ /**
+ * @return Two-step query, or {@code} null if this result is for local query.
+ */
+ GridCacheTwoStepQuery twoStepQuery() {
+ return twoStepQry;
+ }
+
+ /**
+ * @return Two-step query key to cache {@link #twoStepQry}, or {@code null} if there's no need to worry
+ * about two-step caching.
+ */
+ H2TwoStepCachedQueryKey twoStepQueryKey() {
+ return twoStepQryKey;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
index 67137d4..2630239 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/ddl/DdlStatementsProcessor.java
@@ -34,6 +34,7 @@ import org.apache.ignite.cache.query.FieldsQueryCursor;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
import org.apache.ignite.internal.processors.query.GridQueryProperty;
@@ -118,6 +119,8 @@ public class DdlStatementsProcessor {
assert tbl.rowDescriptor() != null;
+ isDdlSupported(tbl);
+
QueryIndex newIdx = new QueryIndex();
newIdx.setName(cmd0.indexName());
@@ -150,6 +153,8 @@ public class DdlStatementsProcessor {
GridH2Table tbl = idx.dataTableForIndex(cmd0.schemaName(), cmd0.indexName());
if (tbl != null) {
+ isDdlSupported(tbl);
+
fut = ctx.query().dynamicIndexDrop(tbl.cacheName(), cmd0.schemaName(), cmd0.indexName(),
cmd0.ifExists());
}
@@ -241,6 +246,8 @@ public class DdlStatementsProcessor {
assert tbl.rowDescriptor() != null;
+ isDdlSupported(tbl);
+
QueryIndex newIdx = new QueryIndex();
newIdx.setName(cmd.index().getName());
@@ -272,6 +279,8 @@ public class DdlStatementsProcessor {
GridH2Table tbl = idx.dataTableForIndex(cmd.schemaName(), cmd.indexName());
if (tbl != null) {
+ isDdlSupported(tbl);
+
fut = ctx.query().dynamicIndexDrop(tbl.cacheName(), cmd.schemaName(), cmd.indexName(),
cmd.ifExists());
}
@@ -477,6 +486,21 @@ public class DdlStatementsProcessor {
}
/**
+ * Check if table supports DDL statement.
+ *
+ * @param tbl Table.
+ */
+ private static void isDdlSupported(GridH2Table tbl) {
+ GridCacheContext cctx = tbl.cache();
+
+ assert cctx != null;
+
+ if (cctx.isLocal())
+ throw new IgniteSQLException("DDL statements are not supported on LOCAL caches",
+ IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
+ }
+
+ /**
* @return {@link IgniteSQLException} with the message same as of {@code this}'s and
*/
private IgniteSQLException convert(SchemaOperationException e) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
index 52dee60..04bc212 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -33,6 +33,8 @@ import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.QueryIndex;
import org.apache.ignite.cache.QueryIndexType;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import org.apache.ignite.internal.processors.query.QueryUtils;
@@ -90,6 +92,7 @@ import org.h2.schema.Schema;
import org.h2.table.Column;
import org.h2.table.FunctionTable;
import org.h2.table.IndexColumn;
+import org.h2.table.MetaTable;
import org.h2.table.RangeTable;
import org.h2.table.Table;
import org.h2.table.TableBase;
@@ -626,6 +629,8 @@ public class GridSqlQueryParser {
res.addChild(parseExpression(RANGE_MIN.get((RangeTable)tbl), false));
res.addChild(parseExpression(RANGE_MAX.get((RangeTable)tbl), false));
}
+ else if (tbl instanceof MetaTable)
+ res = new GridSqlTable(tbl);
else
assert0(false, "Unexpected Table implementation [cls=" + tbl.getClass().getSimpleName() + ']');
@@ -1551,6 +1556,61 @@ public class GridSqlQueryParser {
}
/**
+ * Check if query may be run locally on all caches mentioned in the query.
+ * @param replicatedOnlyQry replicated-only query flag from original {@link SqlFieldsQuery}.
+ * @return {@code true} if query may be run locally on all caches mentioned in the query, i.e. there's no need
+ * to run distributed query.
+ * @see SqlFieldsQuery#isReplicatedOnly()
+ */
+ public boolean isLocalQuery(boolean replicatedOnlyQry) {
+ boolean hasCaches = false;
+
+ for (Object o : h2ObjToGridObj.values()) {
+ if (o instanceof GridSqlAlias)
+ o = GridSqlAlias.unwrap((GridSqlAst)o);
+
+ if (o instanceof GridSqlTable) {
+ GridH2Table tbl = ((GridSqlTable)o).dataTable();
+
+ if (tbl != null) {
+ hasCaches = true;
+
+ GridCacheContext cctx = tbl.cache();
+
+ if (!cctx.isLocal() && !(replicatedOnlyQry && cctx.isReplicatedAffinityNode()))
+ return false;
+ }
+ }
+ }
+
+ // For consistency with old logic, let's not force locality in absence of caches -
+ // if there are no caches, original SqlFieldsQuery's isLocal flag will be used.
+ return hasCaches;
+ }
+
+ /**
+ * Get first (i.e. random, as we need any one) partitioned cache from parsed query
+ * to determine expected query parallelism.
+ * @return Context for the first of partitioned caches mentioned in the query,
+ * or {@code null} if it does not involve partitioned caches.
+ */
+ public GridCacheContext getFirstPartitionedCache() {
+ for (Object o : h2ObjToGridObj.values()) {
+ if (o instanceof GridSqlAlias)
+ o = GridSqlAlias.unwrap((GridSqlAst)o);
+
+ if (o instanceof GridSqlTable) {
+ GridH2Table tbl = ((GridSqlTable)o).dataTable();
+
+ if (tbl != null && tbl.cache().isPartitioned())
+ return tbl.cache();
+ }
+ }
+
+ return null;
+ }
+
+ /**
* @param stmt Prepared statement.
* @return Parsed AST.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
index ca7fcd9..52b641e 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
@@ -77,8 +77,8 @@ import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.X;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.plugin.extensions.communication.Message;
-import org.apache.ignite.thread.IgniteThread;
import org.apache.ignite.spi.indexing.IndexingQueryFilter;
+import org.apache.ignite.thread.IgniteThread;
import org.h2.jdbc.JdbcResultSet;
import org.h2.value.Value;
import org.jetbrains.annotations.Nullable;
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
index bbd3d0d..069bdd7 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheCrossCacheQuerySelfTest.java
@@ -140,7 +140,7 @@ public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
SqlFieldsQuery qry = new SqlFieldsQuery("select f.productId, p.name, f.price " +
"from FactPurchase f, \"replicated-prod\".DimProduct p where p.id = f.productId ");
- for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false).getAll()) {
+ for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false, true).get(0).getAll()) {
X.println("___ -> " + o);
set1.add((Integer)o.get(0));
@@ -154,7 +154,7 @@ public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
qry = new SqlFieldsQuery("select productId from FactPurchase group by productId");
- for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false).getAll()) {
+ for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false, true).get(0).getAll()) {
X.println("___ -> " + o);
assertTrue(set0.add((Integer) o.get(0)));
@@ -173,7 +173,7 @@ public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
"where p.id = f.productId " +
"group by f.productId, p.name");
- for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false).getAll()) {
+ for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false, true).get(0).getAll()) {
X.println("___ -> " + o);
assertTrue(names.add((String)o.get(0)));
@@ -190,7 +190,7 @@ public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
"group by f.productId, p.name " +
"having s >= 15");
- for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false).getAll()) {
+ for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false, true).get(0).getAll()) {
X.println("___ -> " + o);
assertTrue(i(o, 1) >= 15);
@@ -203,7 +203,7 @@ public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
qry = new SqlFieldsQuery("select top 3 distinct productId " +
"from FactPurchase f order by productId desc ");
- for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false).getAll()) {
+ for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false, true).get(0).getAll()) {
X.println("___ -> " + o);
assertEquals(top--, o.get(0));
@@ -216,7 +216,7 @@ public class GridCacheCrossCacheQuerySelfTest extends GridCommonAbstractTest {
qry = new SqlFieldsQuery("select distinct productId " +
"from FactPurchase f order by productId desc limit 2 offset 1");
- for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false).getAll()) {
+ for (List<?> o : qryProc.querySqlFields(cache.context(), qry, false, true).get(0).getAll()) {
X.println("___ -> " + o);
assertEquals(top--, o.get(0));
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java
index aae6a0c..f57a8c6 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCheckClusterStateBeforeExecuteQueryTest.java
@@ -80,7 +80,7 @@ public class IgniteCheckClusterStateBeforeExecuteQueryTest extends GridCommonAbs
assertThrows(log, new Callable<Void>() {
@Override public Void call() throws Exception {
- ig.context().query().querySqlFieldsNoCache(new SqlFieldsQuery("SELECT 1"), false);
+ ig.context().query().querySqlFields(new SqlFieldsQuery("SELECT 1"), false);
return null;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/SqlFieldsQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/SqlFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/SqlFieldsQuerySelfTest.java
index 8860b2b..f684841 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/SqlFieldsQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/SqlFieldsQuerySelfTest.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.processors.cache;
import java.io.Serializable;
+import java.sql.PreparedStatement;
import java.util.List;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheMode;
@@ -25,12 +26,16 @@ import org.apache.ignite.cache.query.FieldsQueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
/**
*
*/
public class SqlFieldsQuerySelfTest extends GridCommonAbstractTest {
+ /** INSERT statement. */
+ private final static String INSERT = "insert into Person(_key, name) values (5, 'x')";
+
/** {@inheritDoc} */
@Override protected void afterTest() throws Exception {
stopAllGrids();
@@ -61,6 +66,50 @@ public class SqlFieldsQuerySelfTest extends GridCommonAbstractTest {
}
/**
+ * @throws Exception If error.
+ */
+ public void testQueryCaching() throws Exception {
+ startGrid(0);
+
+ PreparedStatement stmt = null;
+
+ for (int i = 0; i < 2; i++) {
+ createAndFillCache();
+
+ PreparedStatement stmt0 = grid(0).context().query().prepareNativeStatement("person", INSERT);
+
+ // Statement should either be parsed initially or in response to schema change...
+ assertTrue(stmt != stmt0);
+
+ stmt = stmt0;
+
+ // ...and be properly compiled considering schema changes to be properly parsed
+ new GridSqlQueryParser(false).parse(GridSqlQueryParser.prepared(stmt));
+
+ destroyCache();
+ }
+
+ stmt = null;
+
+ createAndFillCache();
+
+ // Now let's do the same without restarting the cache.
+ for (int i = 0; i < 2; i++) {
+ PreparedStatement stmt0 = grid(0).context().query().prepareNativeStatement("person", INSERT);
+
+ // Statement should either be parsed or taken from cache as no schema changes occurred...
+ assertTrue(stmt == null || stmt == stmt0);
+
+ stmt = stmt0;
+
+ // ...and be properly compiled considering schema changes to be properly parsed
+ new GridSqlQueryParser(false).parse(GridSqlQueryParser.prepared(stmt));
+ }
+
+ destroyCache();
+ }
+
+ /**
*
*/
private void executeQuery() {
@@ -101,6 +150,10 @@ public class SqlFieldsQuerySelfTest extends GridCommonAbstractTest {
return cache;
}
+ private void destroyCache() {
+ grid(0).destroyCache("person");
+ }
+
/**
*
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/IgniteCacheReplicatedQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/IgniteCacheReplicatedQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/IgniteCacheReplicatedQuerySelfTest.java
index a679b15..ec1a16d 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/IgniteCacheReplicatedQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/replicated/IgniteCacheReplicatedQuerySelfTest.java
@@ -196,7 +196,22 @@ public class IgniteCacheReplicatedQuerySelfTest extends IgniteCacheAbstractQuery
/**
* @throws Exception If test failed.
*/
- public void testLocalQuery() throws Exception {
+ public void testLocalQueryWithExplicitFlag() throws Exception {
+ doTestLocalQuery(true);
+ }
+
+ /**
+ * @throws Exception If test failed.
+ */
+ public void testLocalQueryWithoutExplicitFlag() throws Exception {
+ doTestLocalQuery(false);
+ }
+
+ /**
+ * @param loc Explicit query locality flag.
+ * @throws Exception if failed.
+ */
+ private void doTestLocalQuery(boolean loc) throws Exception {
cache1.clear();
Transaction tx = ignite1.transactions().txStart();
@@ -217,9 +232,9 @@ public class IgniteCacheReplicatedQuerySelfTest extends IgniteCacheAbstractQuery
throw e;
}
- checkQueryResults(cache1);
- checkQueryResults(cache2);
- checkQueryResults(cache3);
+ checkLocalQueryResults(cache1, loc);
+ checkLocalQueryResults(cache2, loc);
+ checkLocalQueryResults(cache3, loc);
}
/**
@@ -403,11 +418,13 @@ public class IgniteCacheReplicatedQuerySelfTest extends IgniteCacheAbstractQuery
/**
* @param cache Cache.
+ * @param loc Explicit query locality flag.
* @throws Exception If check failed.
*/
- private void checkQueryResults(IgniteCache<CacheKey, CacheValue> cache) throws Exception {
+ private void checkLocalQueryResults(IgniteCache<CacheKey, CacheValue> cache, boolean loc) throws Exception {
QueryCursor<Cache.Entry<CacheKey, CacheValue>> qry =
- cache.query(new SqlQuery<CacheKey, CacheValue>(CacheValue.class, "val > 1 and val < 4").setLocal(true));
+ cache.query(new SqlQuery<CacheKey, CacheValue>(CacheValue.class, "val > 1 and val < 4")
+ .setReplicatedOnly(true).setLocal(loc));
Iterator<Cache.Entry<CacheKey, CacheValue>> iter = qry.iterator();
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
index dbc6290..0a0efc7 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/AbstractSchemaSelfTest.java
@@ -80,6 +80,9 @@ public abstract class AbstractSchemaSelfTest extends GridCommonAbstractTest {
/** Index name 2 escaped. */
protected static final String IDX_NAME_2_ESCAPED = "idx_2";
+ /** Index name 2. */
+ protected static final String IDX_NAME_LOCAL = "IDX_LOC";
+
/** Key ID field. */
protected static final String FIELD_KEY = "id";
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
index e507217..2cbd3a5 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java
@@ -210,7 +210,7 @@ public abstract class DynamicColumnsAbstractTest extends GridCommonAbstractTest
*/
protected List<List<?>> run(Ignite node, String sql) {
return ((IgniteEx)node).context().query()
- .querySqlFieldsNoCache(new SqlFieldsQuery(sql).setSchema(QueryUtils.DFLT_SCHEMA), true).getAll();
+ .querySqlFields(new SqlFieldsQuery(sql).setSchema(QueryUtils.DFLT_SCHEMA), true).getAll();
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
index db874c2..97720d5 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractBasicSelfTest.java
@@ -42,7 +42,6 @@ import org.apache.ignite.testframework.GridTestUtils;
import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
-import static org.apache.ignite.cache.CacheMode.LOCAL;
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheMode.REPLICATED;
@@ -200,7 +199,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
assertIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1, QueryIndex.DFLT_INLINE_SIZE, field(FIELD_NAME_1_ESCAPED));
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
}
@@ -443,7 +442,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
dynamicIndexCreate(CACHE_NAME, randomString(), idx, false, 0);
}
@@ -519,7 +518,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
final QueryIndex idx = index(IDX_NAME_1, field(randomString()));
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, 0);
}
@@ -594,7 +593,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
throws Exception {
initialize(mode, atomicityMode, near);
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_2_ESCAPED));
@@ -732,7 +731,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
* @throws Exception If failed for any other reason than the expected exception.
*/
private void checkNoIndexIsCreatedForInlineSize(final int inlineSize, int igniteQryErrorCode) throws Exception {
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
idx.setInlineSize(inlineSize);
@@ -863,7 +862,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
* @throws Exception If failed for any other reason than the expected exception.
*/
private void checkNoIndexIsCreatedForParallelism(final int parallel, int igniteQryErrorCode) throws Exception {
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, false, parallel);
@@ -1034,7 +1033,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
private void checkDropNoIndex(CacheMode mode, CacheAtomicityMode atomicityMode, boolean near) throws Exception {
initialize(mode, atomicityMode, near);
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, false);
}
@@ -1138,12 +1137,12 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
public void testFailOnLocalCache() throws Exception {
for (Ignite node : Ignition.allGrids()) {
if (!node.configuration().isClientMode())
- createSqlCache(node, cacheConfiguration().setCacheMode(LOCAL));
+ createSqlCache(node, localCacheConfiguration());
}
final QueryIndex idx = index(IDX_NAME_1, field(FIELD_NAME_1_ESCAPED));
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
dynamicIndexCreate(CACHE_NAME, TBL_NAME, idx, true, 0);
}
@@ -1151,9 +1150,9 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
assertNoIndex(CACHE_NAME, TBL_NAME, IDX_NAME_1);
- assertSchemaException(new RunnableX() {
+ assertIgniteSqlException(new RunnableX() {
@Override public void run() throws Exception {
- dynamicIndexDrop(CACHE_NAME, IDX_NAME_1, true);
+ dynamicIndexDrop(CACHE_NAME, IDX_NAME_LOCAL, true);
}
}, IgniteQueryErrorCode.UNSUPPORTED_OPERATION);
}
@@ -1368,8 +1367,8 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
* @param r Runnable.
* @param expCode Error code.
*/
- protected static void assertSchemaException(RunnableX r, int expCode) {
- assertSchemaException(r, null, expCode);
+ protected static void assertIgniteSqlException(RunnableX r, int expCode) {
+ assertIgniteSqlException(r, null, expCode);
}
/**
@@ -1379,7 +1378,7 @@ public abstract class DynamicIndexAbstractBasicSelfTest extends DynamicIndexAbst
* @param msg Exception message to expect, or {@code null} if it can be waived.
* @param expCode Error code.
*/
- protected static void assertSchemaException(RunnableX r, String msg, int expCode) {
+ private static void assertIgniteSqlException(RunnableX r, String msg, int expCode) {
try {
r.run();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java
index a39283b..452ac96 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicIndexAbstractSelfTest.java
@@ -17,20 +17,29 @@
package org.apache.ignite.internal.processors.cache.index;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+import javax.cache.Cache;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteDataStreamer;
import org.apache.ignite.Ignition;
import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.SqlQuery;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataRegionConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.util.typedef.T2;
@@ -39,14 +48,6 @@ import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
-import javax.cache.Cache;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.UUID;
-
/**
* Tests for dynamic index creation.
*/
@@ -182,6 +183,20 @@ public abstract class DynamicIndexAbstractSelfTest extends AbstractSchemaSelfTes
}
/**
+ * @return Local cache configuration with a pre-configured index.
+ */
+ CacheConfiguration<KeyClass, ValueClass> localCacheConfiguration() {
+ CacheConfiguration<KeyClass, ValueClass> res = cacheConfiguration();
+
+ res.getQueryEntities().iterator().next().setIndexes(Collections.singletonList(
+ new QueryIndex(FIELD_NAME_2_ESCAPED, true, IDX_NAME_LOCAL)));
+
+ res.setCacheMode(CacheMode.LOCAL);
+
+ return res;
+ }
+
+ /**
* Ensure index is used in plan.
*
* @param idxName Index name.
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
index 02e48ed..d7a351b 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicIndexingComplexTest.java
@@ -330,7 +330,7 @@ public abstract class H2DynamicIndexingComplexTest extends DynamicIndexAbstractS
* @return Run result.
*/
private List<List<?>> executeSql(IgniteEx node, String stmt, Object... args) {
- return node.context().query().querySqlFieldsNoCache(new SqlFieldsQuery(stmt).setArgs(args), true).getAll();
+ return node.context().query().querySqlFields(new SqlFieldsQuery(stmt).setArgs(args), true).getAll();
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
index fb38c46..b20bb59 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java
@@ -891,11 +891,11 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
personId2cityCode.put(i, cityCode);
- queryProcessor(client()).querySqlFieldsNoCache(new SqlFieldsQuery("insert into \"Person2\"(\"id\", " +
+ queryProcessor(client()).querySqlFields(new SqlFieldsQuery("insert into \"Person2\"(\"id\", " +
"\"city\") values (?, ?)").setArgs(i, cityName), true).getAll();
}
- List<List<?>> res = queryProcessor(client()).querySqlFieldsNoCache(new SqlFieldsQuery("select \"id\", " +
+ List<List<?>> res = queryProcessor(client()).querySqlFields(new SqlFieldsQuery("select \"id\", " +
"c.\"code\" from \"Person2\" p left join \"City\" c on p.\"city\" = c.\"name\" where c.\"name\" " +
"is not null"), true).getAll();
@@ -1555,7 +1555,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
* @param sql Statement.
*/
private List<List<?>> execute(Ignite node, String sql) {
- return queryProcessor(node).querySqlFieldsNoCache(new SqlFieldsQuery(sql).setSchema("PUBLIC"), true).getAll();
+ return queryProcessor(node).querySqlFields(new SqlFieldsQuery(sql).setSchema("PUBLIC"), true).getAll();
}
/**
@@ -1564,7 +1564,7 @@ public class H2DynamicTableSelfTest extends AbstractSchemaSelfTest {
* @param sql Statement.
*/
private List<List<?>> executeLocal(GridCacheContext cctx, String sql) {
- return queryProcessor(cctx.grid()).querySqlFields(cctx, new SqlFieldsQuery(sql).setLocal(true), true).getAll();
+ return queryProcessor(cctx.grid()).querySqlFields(new SqlFieldsQuery(sql).setLocal(true), true).getAll();
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/local/IgniteCacheLocalQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/local/IgniteCacheLocalQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/local/IgniteCacheLocalQuerySelfTest.java
index e0c6396..2570bc8 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/local/IgniteCacheLocalQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/local/IgniteCacheLocalQuerySelfTest.java
@@ -47,44 +47,50 @@ public class IgniteCacheLocalQuerySelfTest extends IgniteCacheAbstractQuerySelfT
* @throws Exception If test failed.
*/
public void testQueryLocal() throws Exception {
- IgniteCache<Integer, String> cache = jcache(Integer.class, String.class);
+ // Let's do it twice to see how prepared statement caching behaves - without recompilation
+ // check for cached prepared statements this would fail.
+ for (int i = 0; i < 2; i ++) {
+ IgniteCache<Integer, String> cache = jcache(Integer.class, String.class);
- cache.put(1, "value1");
- cache.put(2, "value2");
- cache.put(3, "value3");
- cache.put(4, "value4");
- cache.put(5, "value5");
+ cache.put(1, "value1");
+ cache.put(2, "value2");
+ cache.put(3, "value3");
+ cache.put(4, "value4");
+ cache.put(5, "value5");
- // Tests equals query.
- QueryCursor<Cache.Entry<Integer, String>> qry =
- cache.query(new SqlQuery<Integer, String>(String.class, "_val='value1'").setLocal(true));
+ // Tests equals query.
+ QueryCursor<Cache.Entry<Integer, String>> qry =
+ cache.query(new SqlQuery<Integer, String>(String.class, "_val='value1'").setLocal(true));
- Iterator<Cache.Entry<Integer, String>> iter = qry.iterator();
+ Iterator<Cache.Entry<Integer, String>> iter = qry.iterator();
- Cache.Entry<Integer, String> entry = iter.next();
+ Cache.Entry<Integer, String> entry = iter.next();
- assert !iter.hasNext();
+ assert !iter.hasNext();
- assert entry != null;
- assert entry.getKey() == 1;
- assert "value1".equals(entry.getValue());
+ assert entry != null;
+ assert entry.getKey() == 1;
+ assert "value1".equals(entry.getValue());
- // Tests like query.
- qry = cache.query(new SqlQuery<Integer, String>(String.class, "_val like 'value%'").setLocal(true));
+ // Tests like query.
+ qry = cache.query(new SqlQuery<Integer, String>(String.class, "_val like 'value%'").setLocal(true));
- iter = qry.iterator();
+ iter = qry.iterator();
- assert iter.next() != null;
- assert iter.next() != null;
- assert iter.next() != null;
- assert iter.next() != null;
- assert iter.next() != null;
- assert !iter.hasNext();
+ assert iter.next() != null;
+ assert iter.next() != null;
+ assert iter.next() != null;
+ assert iter.next() != null;
+ assert iter.next() != null;
+ assert !iter.hasNext();
- // Test explain for primitive index.
- List<List<?>> res = cache.query(new SqlFieldsQuery(
- "explain select _key from String where _val > 'value1'").setLocal(true)).getAll();
+ // Test explain for primitive index.
+ List<List<?>> res = cache.query(new SqlFieldsQuery(
+ "explain select _key from String where _val > 'value1'").setLocal(true)).getAll();
- assertTrue("__ explain: \n" + res, ((String)res.get(0).get(0)).toLowerCase().contains("_val_idx"));
+ assertTrue("__ explain: \n" + res, ((String) res.get(0).get(0)).toLowerCase().contains("_val_idx"));
+
+ cache.destroy();
+ }
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/53c03c19/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
index 2f6977a..2b7c5c2 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/database/IgnitePersistentStoreSchemaLoadTest.java
@@ -193,8 +193,8 @@ public class IgnitePersistentStoreSchemaLoadTest extends GridCommonAbstractTest
CountDownLatch cnt = checkpointLatch(node);
- node.context().query().querySqlFieldsNoCache(
- new SqlFieldsQuery("create table \"Person\" (\"id\" int primary key, \"name\" varchar)"), false).getAll();
+ node.context().query().querySqlFields(
+ new SqlFieldsQuery("create table \"Person\" (\"id\" int primary key, \"name\" varchar)"), false);
assertEquals(0, indexCnt(node, SQL_CACHE_NAME));
@@ -212,7 +212,7 @@ public class IgnitePersistentStoreSchemaLoadTest extends GridCommonAbstractTest
checkDynamicSchemaChanges(node, SQL_CACHE_NAME);
- node.context().query().querySqlFieldsNoCache(new SqlFieldsQuery("drop table \"Person\""), false).getAll();
+ node.context().query().querySqlFields(new SqlFieldsQuery("drop table \"Person\""), false).getAll();
}
/** */
@@ -280,15 +280,15 @@ public class IgnitePersistentStoreSchemaLoadTest extends GridCommonAbstractTest
* @param schema Schema name.
*/
private void makeDynamicSchemaChanges(IgniteEx node, String schema) {
- node.context().query().querySqlFieldsNoCache(
+ node.context().query().querySqlFields(
new SqlFieldsQuery("create index \"my_idx\" on \"Person\" (\"id\", \"name\")").setSchema(schema), false)
.getAll();
- node.context().query().querySqlFieldsNoCache(
+ node.context().query().querySqlFields(
new SqlFieldsQuery("alter table \"Person\" add column (\"age\" int, \"city\" char)")
.setSchema(schema), false).getAll();
- node.context().query().querySqlFieldsNoCache(
+ node.context().query().querySqlFields(
new SqlFieldsQuery("alter table \"Person\" drop column \"city\"").setSchema(schema), false)
.getAll();
}