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 2015/11/26 08:50:12 UTC
[08/11] ignite git commit: Queries optimizations: - cache prepared
statements and two-step queries - skip reduce query if possible - do not use
index snapshots by default
Queries optimizations:
- cache prepared statements and two-step queries
- skip reduce query if possible
- do not use index snapshots by default
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/4af461a7
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/4af461a7
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/4af461a7
Branch: refs/heads/ignite-1956
Commit: 4af461a7f403fc0e4df13d23d0789eee49200b26
Parents: 3c42da8
Author: sboikov <sb...@gridgain.com>
Authored: Thu Nov 26 09:30:10 2015 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Thu Nov 26 09:30:10 2015 +0300
----------------------------------------------------------------------
.../configuration/CacheConfiguration.java | 30 +++
.../cache/query/GridCacheSqlQuery.java | 42 ++++
.../cache/query/GridCacheTwoStepQuery.java | 35 ++-
.../processors/query/GridQueryProcessor.java | 40 +---
.../processors/query/GridQueryProperty.java | 45 ++++
.../query/GridQueryTypeDescriptor.java | 6 +
.../query/h2/GridH2ResultSetIterator.java | 19 +-
.../processors/query/h2/IgniteH2Indexing.java | 227 ++++++++++++++++---
.../query/h2/opt/GridH2RowDescriptor.java | 5 +
.../processors/query/h2/opt/GridH2Table.java | 69 +++++-
.../query/h2/opt/GridH2TreeIndex.java | 98 +++++---
.../query/h2/sql/GridSqlQuerySplitter.java | 73 ++++--
.../processors/query/h2/sql/GridSqlSelect.java | 27 +++
.../query/h2/twostep/GridMapQueryExecutor.java | 17 +-
.../query/h2/twostep/GridMergeIndex.java | 7 +
.../h2/twostep/GridMergeIndexUnsorted.java | 14 ++
.../h2/twostep/GridReduceQueryExecutor.java | 117 +++++++---
.../cache/IgniteCacheAbstractQuerySelfTest.java | 69 +++---
...PartitionedSnapshotEnabledQuerySelfTest.java | 28 +++
.../h2/GridIndexingSpiAbstractSelfTest.java | 19 ++
.../IgniteCacheQuerySelfTestSuite.java | 2 +
21 files changed, 776 insertions(+), 213 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index e87346f..e2bf912 100644
--- a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -373,6 +373,9 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
/** */
private int sqlOnheapRowCacheSize = DFLT_SQL_ONHEAP_ROW_CACHE_SIZE;
+ /** */
+ private boolean snapshotableIdx;
+
/** Copy on read flag. */
private boolean cpOnRead = DFLT_COPY_ON_READ;
@@ -463,6 +466,7 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
rebalancePoolSize = cc.getRebalanceThreadPoolSize();
rebalanceTimeout = cc.getRebalanceTimeout();
rebalanceThrottle = cc.getRebalanceThrottle();
+ snapshotableIdx = cc.isSnapshotableIndex();
sqlEscapeAll = cc.isSqlEscapeAll();
sqlFuncCls = cc.getSqlFunctionClasses();
sqlOnheapRowCacheSize = cc.getSqlOnheapRowCacheSize();
@@ -1900,6 +1904,32 @@ public class CacheConfiguration<K, V> extends MutableConfiguration<K, V> {
}
/**
+ * Gets flag indicating whether SQL indexes should support snapshots.
+ *
+ * @return {@code True} if SQL indexes should support snapshots.
+ */
+ public boolean isSnapshotableIndex() {
+ return snapshotableIdx;
+ }
+
+ /**
+ * Sets flag indicating whether SQL indexes should support snapshots.
+ * <p>
+ * Default value is {@code false}.
+ * <p>
+ * <b>Note</b> that this flag is ignored if indexes are stored in offheap memory,
+ * for offheap indexes snapshots are always enabled.
+ *
+ * @param snapshotableIdx {@code True} if SQL indexes should support snapshots.
+ * @return {@code this} for chaining.
+ */
+ public CacheConfiguration<K, V> setSnapshotableIndex(boolean snapshotableIdx) {
+ this.snapshotableIdx = snapshotableIdx;
+
+ return this;
+ }
+
+ /**
* Gets array of cache plugin configurations.
*
* @return Cache plugin configurations.
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
index be7bbe9..e56e445 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheSqlQuery.java
@@ -55,6 +55,16 @@ public class GridCacheSqlQuery implements Message {
/** */
@GridToStringInclude
@GridDirectTransient
+ private int[] paramIdxs;
+
+ /** */
+ @GridToStringInclude
+ @GridDirectTransient
+ private int paramsSize;
+
+ /** */
+ @GridToStringInclude
+ @GridDirectTransient
private LinkedHashMap<String, ?> cols;
/** Field kept for backward compatibility. */
@@ -77,6 +87,14 @@ public class GridCacheSqlQuery implements Message {
this.qry = qry;
this.params = F.isEmpty(params) ? EMPTY_PARAMS : params;
+ paramsSize = this.params.length;
+ }
+
+ /**
+ * @param paramIdxs Parameter indexes.
+ */
+ public void parameterIndexes(int[] paramIdxs) {
+ this.paramIdxs = paramIdxs;
}
/**
@@ -222,4 +240,28 @@ public class GridCacheSqlQuery implements Message {
@Override public byte fieldsCount() {
return 3;
}
+
+ /**
+ * @param args Arguments.
+ * @return Copy.
+ */
+ public GridCacheSqlQuery copy(Object[] args) {
+ GridCacheSqlQuery cp = new GridCacheSqlQuery();
+
+ cp.qry = qry;
+ cp.cols = cols;
+ cp.paramIdxs = paramIdxs;
+ cp.paramsSize = paramsSize;
+
+ if (F.isEmpty(args))
+ cp.params = EMPTY_PARAMS;
+ else {
+ cp.params = new Object[paramsSize];
+
+ for (int paramIdx : paramIdxs)
+ cp.params[paramIdx] = args[paramIdx];
+ }
+
+ return cp;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
index 4b5fe22..da59c18 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheTwoStepQuery.java
@@ -47,16 +47,27 @@ public class GridCacheTwoStepQuery {
/** */
private Set<String> spaces;
+ /** */
+ private final boolean skipMergeTbl;
+
/**
* @param spaces All spaces accessed in query.
* @param rdc Reduce query.
+ * @param skipMergeTbl {@code True} if reduce query can skip merge table creation and
+ * get data directly from merge index.
*/
- public GridCacheTwoStepQuery(Set<String> spaces, GridCacheSqlQuery rdc) {
+ public GridCacheTwoStepQuery(Set<String> spaces, GridCacheSqlQuery rdc, boolean skipMergeTbl) {
assert rdc != null;
this.spaces = spaces;
-
this.rdc = rdc;
+ this.skipMergeTbl = skipMergeTbl;
+ }
+ /**
+ * @return {@code True} if reduce query can skip merge table creation and get data directly from merge index.
+ */
+ public boolean skipMergeTable() {
+ return skipMergeTbl;
}
/**
@@ -89,9 +100,12 @@ public class GridCacheTwoStepQuery {
/**
* @param qry SQL Query.
+ * @return {@code this}.
*/
- public void addMapQuery(GridCacheSqlQuery qry) {
+ public GridCacheTwoStepQuery addMapQuery(GridCacheSqlQuery qry) {
mapQrys.add(qry);
+
+ return this;
}
/**
@@ -122,6 +136,21 @@ public class GridCacheTwoStepQuery {
this.spaces = spaces;
}
+ /**
+ * @param args New arguments to copy with.
+ * @return Copy.
+ */
+ public GridCacheTwoStepQuery copy(Object[] args) {
+ assert !explain;
+
+ GridCacheTwoStepQuery cp = new GridCacheTwoStepQuery(spaces, rdc.copy(args), skipMergeTbl);
+ cp.pageSize = pageSize;
+ for (int i = 0; i < mapQrys.size(); i++)
+ cp.mapQrys.add(mapQrys.get(i).copy(args));
+
+ return cp;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(GridCacheTwoStepQuery.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
index d0eeeb1..814229c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProcessor.java
@@ -1672,34 +1672,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/**
- *
- */
- private abstract static class Property {
- /**
- * Gets this property value from the given object.
- *
- * @param key Key.
- * @param val Value.
- * @return Property value.
- * @throws IgniteCheckedException If failed.
- */
- public abstract Object value(Object key, Object val) throws IgniteCheckedException;
-
- /**
- * @return Property name.
- */
- public abstract String name();
-
- /**
- * @return Class member type.
- */
- public abstract Class<?> type();
- }
-
- /**
* Description of type property.
*/
- private static class ClassProperty extends Property {
+ private static class ClassProperty extends GridQueryProperty {
/** */
private final Member member;
@@ -1794,7 +1769,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
/**
*
*/
- private class PortableProperty extends Property {
+ private class PortableProperty extends GridQueryProperty {
/** Property name. */
private String propName;
@@ -1938,7 +1913,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
/** */
@GridToStringExclude
- private final Map<String, Property> props = new HashMap<>();
+ private final Map<String, GridQueryProperty> props = new HashMap<>();
/** */
@GridToStringInclude
@@ -1993,11 +1968,16 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/** {@inheritDoc} */
+ @Override public GridQueryProperty property(String name) {
+ return props.get(name);
+ }
+
+ /** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <T> T value(String field, Object key, Object val) throws IgniteCheckedException {
assert field != null;
- Property prop = props.get(field);
+ GridQueryProperty prop = props.get(field);
if (prop == null)
throw new IgniteCheckedException("Failed to find field '" + field + "' in type '" + name + "'.");
@@ -2096,7 +2076,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
* @param failOnDuplicate Fail on duplicate flag.
* @throws IgniteCheckedException In case of error.
*/
- public void addProperty(Property prop, boolean failOnDuplicate) throws IgniteCheckedException {
+ public void addProperty(GridQueryProperty prop, boolean failOnDuplicate) throws IgniteCheckedException {
String name = prop.name();
if (props.put(name, prop) != null && failOnDuplicate)
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
new file mode 100644
index 0000000..d623d25
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryProperty.java
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+import org.apache.ignite.IgniteCheckedException;
+
+/**
+ * Description and access method for query entity field.
+ */
+public abstract class GridQueryProperty {
+ /**
+ * Gets this property value from the given object.
+ *
+ * @param key Key.
+ * @param val Value.
+ * @return Property value.
+ * @throws IgniteCheckedException If failed.
+ */
+ public abstract Object value(Object key, Object val) throws IgniteCheckedException;
+
+ /**
+ * @return Property name.
+ */
+ public abstract String name();
+
+ /**
+ * @return Class member type.
+ */
+ public abstract Class<?> type();
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
index b05e1d8..45919ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryTypeDescriptor.java
@@ -50,6 +50,12 @@ public interface GridQueryTypeDescriptor {
public <T> T value(String field, Object key, Object val) throws IgniteCheckedException;
/**
+ * @param name Property name.
+ * @return Property.
+ */
+ public GridQueryProperty property(String name);
+
+ /**
* Gets indexes for this type.
*
* @return Indexes for this type.
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/GridH2ResultSetIterator.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/GridH2ResultSetIterator.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/GridH2ResultSetIterator.java
index 2c67638..3603bb5 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/GridH2ResultSetIterator.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/GridH2ResultSetIterator.java
@@ -41,14 +41,19 @@ public abstract class GridH2ResultSetIterator<T> extends GridCloseableIteratorAd
protected final Object[] row;
/** */
+ private final boolean closeStmt;
+
+ /** */
private boolean hasRow;
/**
* @param data Data array.
+ * @param closeStmt If {@code true} closes result set statement when iterator is closed.
* @throws IgniteCheckedException If failed.
*/
- protected GridH2ResultSetIterator(ResultSet data) throws IgniteCheckedException {
+ protected GridH2ResultSetIterator(ResultSet data, boolean closeStmt) throws IgniteCheckedException {
this.data = data;
+ this.closeStmt = closeStmt;
if (data != null) {
try {
@@ -115,11 +120,13 @@ public abstract class GridH2ResultSetIterator<T> extends GridCloseableIteratorAd
// Nothing to close.
return;
- try {
- U.closeQuiet(data.getStatement());
- }
- catch (SQLException e) {
- throw new IgniteCheckedException(e);
+ if (closeStmt) {
+ try {
+ U.closeQuiet(data.getStatement());
+ }
+ catch (SQLException e) {
+ throw new IgniteCheckedException(e);
+ }
}
U.closeQuiet(data);
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/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 d5efebf..cc452c1 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
@@ -79,6 +79,7 @@ import org.apache.ignite.internal.processors.query.GridQueryFieldsResult;
import org.apache.ignite.internal.processors.query.GridQueryFieldsResultAdapter;
import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
import org.apache.ignite.internal.processors.query.GridQueryIndexing;
+import org.apache.ignite.internal.processors.query.GridQueryProperty;
import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOffheap;
@@ -93,12 +94,14 @@ import org.apache.ignite.internal.processors.query.h2.opt.GridLuceneIndex;
import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter;
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.util.GridBoundedConcurrentLinkedHashMap;
import org.apache.ignite.internal.util.GridEmptyCloseableIterator;
import org.apache.ignite.internal.util.GridSpinBusyLock;
import org.apache.ignite.internal.util.lang.GridCloseableIterator;
import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeGuard;
import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemory;
import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.T3;
import org.apache.ignite.internal.util.typedef.internal.LT;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.SB;
@@ -176,6 +179,12 @@ public class IgniteH2Indexing implements GridQueryIndexing {
";DEFAULT_LOCK_TIMEOUT=10000;FUNCTIONS_IN_SCHEMA=true;OPTIMIZE_REUSE_RESULTS=0;QUERY_CACHE_SIZE=0;" +
"RECOMPILE_ALWAYS=1;MAX_OPERATION_MEMORY=0";
+ /** */
+ private static final int PREPARED_STMT_CACHE_SIZE = 256;
+
+ /** */
+ private static final int TWO_STEP_QRY_CACHE_SIZE = 1024;
+
/** Field name for key. */
public static final String KEY_FIELD_NAME = "_key";
@@ -190,6 +199,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
*/
static {
try {
+ System.setProperty("h2.objectCache", "false");
+
COMMAND_FIELD = JdbcPreparedStatement.class.getDeclaredField("command");
COMMAND_FIELD.setAccessible(true);
@@ -242,6 +253,9 @@ public class IgniteH2Indexing implements GridQueryIndexing {
c = initialValue();
set(c);
+
+ // Reset statement cache when new connection is created.
+ stmtCache.get().clear();
}
return c;
@@ -266,6 +280,17 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** */
private volatile GridKernalContext ctx;
+ /** */
+ private final ThreadLocal<StatementCache> stmtCache = new ThreadLocal<StatementCache>() {
+ @Override protected StatementCache initialValue() {
+ return new StatementCache(PREPARED_STMT_CACHE_SIZE);
+ }
+ };
+
+ /** */
+ private final GridBoundedConcurrentLinkedHashMap<T3<String, String, Boolean>, TwoStepCachedQuery> twoStepCache =
+ new GridBoundedConcurrentLinkedHashMap<>(TWO_STEP_QRY_CACHE_SIZE);
+
/**
* @param space Space.
* @return Connection.
@@ -280,6 +305,35 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
+ * @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) {
+ StatementCache cache = stmtCache.get();
+
+ PreparedStatement stmt = cache.get(sql);
+
+ if (stmt != null && !stmt.isClosed()) {
+ assert stmt.getConnection() == c;
+
+ return stmt;
+ }
+
+ stmt = c.prepareStatement(sql);
+
+ cache.put(sql, stmt);
+
+ return stmt;
+ }
+ else
+ return c.prepareStatement(sql);
+ }
+
+ /**
* Gets DB connection.
*
* @param schema Whether to set schema for connection or not.
@@ -648,7 +702,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
try {
Connection conn = connectionForThread(schema(spaceName));
- ResultSet rs = executeSqlQueryWithTimer(spaceName, conn, qry, params);
+ ResultSet rs = executeSqlQueryWithTimer(spaceName, conn, qry, params, true);
List<GridQueryFieldMetadata> meta = null;
@@ -710,15 +764,16 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @param conn Connection,.
* @param sql Sql query.
* @param params Parameters.
+ * @param useStmtCache If {@code true} uses statement cache.
* @return Result.
* @throws IgniteCheckedException If failed.
*/
- private ResultSet executeSqlQuery(Connection conn, String sql, Collection<Object> params)
+ private ResultSet executeSqlQuery(Connection conn, String sql, Collection<Object> params, boolean useStmtCache)
throws IgniteCheckedException {
PreparedStatement stmt;
try {
- stmt = conn.prepareStatement(sql);
+ stmt = prepareStatement(conn, sql, useStmtCache);
}
catch (SQLException e) {
throw new IgniteCheckedException("Failed to parse SQL query: " + sql, e);
@@ -747,18 +802,23 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/**
* Executes sql query and prints warning if query is too slow..
*
+ * @param space Space name.
* @param conn Connection,.
* @param sql Sql query.
* @param params Parameters.
+ * @param useStmtCache If {@code true} uses statement cache.
* @return Result.
* @throws IgniteCheckedException If failed.
*/
- public ResultSet executeSqlQueryWithTimer(String space, Connection conn, String sql,
- @Nullable Collection<Object> params) throws IgniteCheckedException {
+ public ResultSet executeSqlQueryWithTimer(String space,
+ Connection conn,
+ String sql,
+ @Nullable Collection<Object> params,
+ boolean useStmtCache) throws IgniteCheckedException {
long start = U.currentTimeMillis();
try {
- ResultSet rs = executeSqlQuery(conn, sql, params);
+ ResultSet rs = executeSqlQuery(conn, sql, params, useStmtCache);
long time = U.currentTimeMillis() - start;
@@ -767,7 +827,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
if (time > longQryExecTimeout) {
String msg = "Query execution is too long (" + time + " ms): " + sql;
- ResultSet plan = executeSqlQuery(conn, "EXPLAIN " + sql, params);
+ ResultSet plan = executeSqlQuery(conn, "EXPLAIN " + sql, params, false);
plan.next();
@@ -803,7 +863,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
String sql = generateQuery(qry, tbl);
- return executeSqlQueryWithTimer(space, conn, sql, params);
+ return executeSqlQueryWithTimer(space, conn, sql, params, true);
}
/**
@@ -924,41 +984,52 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** {@inheritDoc} */
@Override public QueryCursor<List<?>> queryTwoStep(GridCacheContext<?,?> cctx, SqlFieldsQuery qry) {
- String space = cctx.name();
- String sqlQry = qry.getSql();
+ final String space = cctx.name();
+ final String sqlQry = qry.getSql();
Connection c = connectionForSpace(space);
- PreparedStatement stmt;
+ GridCacheTwoStepQuery twoStepQry;
+ List<GridQueryFieldMetadata> meta;
- try {
- stmt = c.prepareStatement(sqlQry);
- }
- catch (SQLException e) {
- throw new CacheException("Failed to parse query: " + sqlQry, e);
- }
+ final T3<String, String, Boolean> cachedQryKey = new T3<>(space, sqlQry, qry.isCollocated());
+ TwoStepCachedQuery cachedQry = twoStepCache.get(cachedQryKey);
- try {
- bindParameters(stmt, F.asList(qry.getArgs()));
- }
- catch (IgniteCheckedException e) {
- throw new CacheException("Failed to bind parameters: [qry=" + sqlQry + ", params=" +
- Arrays.deepToString(qry.getArgs()) + "]", e);
+ if (cachedQry != null) {
+ twoStepQry = cachedQry.twoStepQry.copy(qry.getArgs());
+ meta = cachedQry.meta;
}
+ else {
+ PreparedStatement stmt;
- GridCacheTwoStepQuery twoStepQry;
- List<GridQueryFieldMetadata> meta;
+ try {
+ // Do not cache this statement because the whole two step query object will be cached later on.
+ stmt = prepareStatement(c, sqlQry, false);
+ }
+ catch (SQLException e) {
+ throw new CacheException("Failed to parse query: " + sqlQry, e);
+ }
+ try {
+ try {
+ bindParameters(stmt, F.asList(qry.getArgs()));
+ }
+ catch (IgniteCheckedException e) {
+ throw new CacheException("Failed to bind parameters: [qry=" + sqlQry + ", params=" +
+ Arrays.deepToString(qry.getArgs()) + "]", e);
+ }
- try {
- twoStepQry = GridSqlQuerySplitter.split((JdbcPreparedStatement)stmt, qry.getArgs(), qry.isCollocated());
+ try {
+ twoStepQry = GridSqlQuerySplitter.split((JdbcPreparedStatement)stmt, qry.getArgs(), qry.isCollocated());
- meta = meta(stmt.getMetaData());
- }
- catch (SQLException e) {
- throw new CacheException(e);
- }
- finally {
- U.close(stmt, log);
+ meta = meta(stmt.getMetaData());
+ }
+ catch (SQLException e) {
+ throw new CacheException(e);
+ }
+ }
+ finally {
+ U.close(stmt, log);
+ }
}
if (log.isDebugEnabled())
@@ -970,6 +1041,11 @@ public class IgniteH2Indexing implements GridQueryIndexing {
cursor.fieldsMeta(meta);
+ if (cachedQry == null && !twoStepQry.explain()) {
+ cachedQry = new TwoStepCachedQuery(meta, twoStepQry.copy(null));
+ twoStepCache.putIfAbsent(cachedQryKey, cachedQry);
+ }
+
return cursor;
}
@@ -1542,6 +1618,31 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
+ * Cached two-step query.
+ */
+ private static final class TwoStepCachedQuery {
+ /** */
+ final List<GridQueryFieldMetadata> meta;
+
+ /** */
+ final GridCacheTwoStepQuery twoStepQry;
+
+ /**
+ * @param meta Fields metadata.
+ * @param twoStepQry Query.
+ */
+ public TwoStepCachedQuery(List<GridQueryFieldMetadata> meta, GridCacheTwoStepQuery twoStepQry) {
+ this.meta = meta;
+ this.twoStepQry = twoStepQry;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TwoStepCachedQuery.class, this);
+ }
+ }
+
+ /**
* Wrapper to store connection and flag is schema set or not.
*/
private static class ConnectionWrapper {
@@ -1889,7 +1990,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @throws IgniteCheckedException If failed.
*/
protected FieldsIterator(ResultSet data) throws IgniteCheckedException {
- super(data);
+ super(data, false);
}
/** {@inheritDoc} */
@@ -1914,7 +2015,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @throws IgniteCheckedException If failed.
*/
protected KeyValIterator(ResultSet data) throws IgniteCheckedException {
- super(data);
+ super(data, false);
}
/** {@inheritDoc} */
@@ -2091,6 +2192,12 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** */
private final boolean preferSwapVal;
+ /** */
+ private final boolean snapshotableIdx;
+
+ /** */
+ private final GridQueryProperty[] props;
+
/**
* @param type Type descriptor.
* @param schema Schema.
@@ -2120,7 +2227,18 @@ public class IgniteH2Indexing implements GridQueryIndexing {
keyType = DataType.getTypeFromClass(type.keyClass());
valType = DataType.getTypeFromClass(type.valueClass());
+ props = new GridQueryProperty[fields.length];
+
+ for (int i = 0; i < fields.length; i++) {
+ GridQueryProperty p = type.property(fields[i]);
+
+ assert p != null : fields[i];
+
+ props[i] = p;
+ }
+
preferSwapVal = schema.ccfg.getMemoryMode() == CacheMemoryMode.OFFHEAP_TIERED;
+ snapshotableIdx = schema.ccfg.isSnapshotableIndex() || schema.offheap != null;
}
/** {@inheritDoc} */
@@ -2274,7 +2392,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** {@inheritDoc} */
@Override public Object columnValue(Object key, Object val, int col) {
try {
- return type.value(fields[col], key, val);
+ return props[col].value(key, val);
}
catch (IgniteCheckedException e) {
throw DbException.convert(e);
@@ -2298,5 +2416,40 @@ public class IgniteH2Indexing implements GridQueryIndexing {
@Override public boolean preferSwapValue() {
return preferSwapVal;
}
+
+ /** {@inheritDoc} */
+ @Override public boolean snapshotableIndex() {
+ return snapshotableIdx;
+ }
+ }
+
+ /**
+ * Statement cache.
+ */
+ private static class StatementCache extends LinkedHashMap<String, PreparedStatement> {
+ /** */
+ private int size;
+
+ /**
+ * @param size Size.
+ */
+ private StatementCache(int size) {
+ super(size, (float)0.75, true);
+
+ this.size = size;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected boolean removeEldestEntry(Map.Entry<String, PreparedStatement> eldest) {
+ boolean rmv = size() > size;
+
+ if (rmv) {
+ PreparedStatement stmt = eldest.getValue();
+
+ U.closeQuiet(stmt);
+ }
+
+ return rmv;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
index ed3ff7a..80dcfcb 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowDescriptor.java
@@ -116,4 +116,9 @@ public interface GridH2RowDescriptor extends GridOffHeapSmartPointerFactory<Grid
* @return {@code True} if should check swap value before offheap.
*/
public boolean preferSwapValue();
+
+ /**
+ * @return {@code True} if index should support snapshots.
+ */
+ public boolean snapshotableIndex();
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
index bf318b2..f1e5b16 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Table.java
@@ -54,6 +54,7 @@ import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
+import org.jsr166.LongAdder8;
import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.VAL_COL;
@@ -79,6 +80,12 @@ public class GridH2Table extends TableBase {
/** */
private volatile Object[] actualSnapshot;
+ /** */
+ private final LongAdder8 size = new LongAdder8();
+
+ /** */
+ private final boolean snapshotEnabled;
+
/**
* Creates table.
*
@@ -101,10 +108,12 @@ public class GridH2Table extends TableBase {
assert idxs != null;
assert idxs.size() >= 1;
- lock = new ReentrantReadWriteLock();
+ lock = new ReentrantReadWriteLock();
// Add scan index at 0 which is required by H2.
idxs.add(0, new ScanIndex(index(0)));
+
+ snapshotEnabled = desc == null || desc.snapshotableIndex();
}
/** {@inheritDoc} */
@@ -164,7 +173,7 @@ public class GridH2Table extends TableBase {
GridUnsafeMemory mem = desc.memory();
- lock.readLock().lock();
+ readLock();
if (mem != null)
desc.guard().begin();
@@ -183,7 +192,7 @@ public class GridH2Table extends TableBase {
return true;
}
finally {
- lock.readLock().unlock();
+ readUnlock();
if (mem != null)
desc.guard().end();
@@ -209,6 +218,9 @@ public class GridH2Table extends TableBase {
}
}
+ if (!snapshotEnabled)
+ return;
+
Object[] snapshot;
for (long waitTime = 100;; waitTime *= 2) { // Increase wait time to avoid starvation.
@@ -297,16 +309,14 @@ public class GridH2Table extends TableBase {
* Closes table and releases resources.
*/
public void close() {
- Lock l = lock.writeLock();
-
- l.lock();
+ writeLock();
try {
for (int i = 1, len = idxs.size(); i < len; i++)
index(i).close(null);
}
finally {
- l.unlock();
+ writeUnlock();
}
}
@@ -363,7 +373,7 @@ public class GridH2Table extends TableBase {
// getting updated from different threads with different rows with the same key is impossible.
GridUnsafeMemory mem = desc == null ? null : desc.memory();
- lock.readLock().lock();
+ readLock();
if (mem != null)
desc.guard().begin();
@@ -379,6 +389,8 @@ public class GridH2Table extends TableBase {
kvOld.onUnswap(kvOld.getValue(VAL_COL), true);
}
+ else if (old == null)
+ size.increment();
int len = idxs.size();
@@ -414,6 +426,8 @@ public class GridH2Table extends TableBase {
}
if (old != null) {
+ size.decrement();
+
// Remove row from all indexes.
// Start from 2 because 0 - Scan (don't need to update), 1 - PK (already updated).
for (int i = 2, len = idxs.size(); i < len; i++) {
@@ -432,7 +446,7 @@ public class GridH2Table extends TableBase {
return true;
}
finally {
- lock.readLock().unlock();
+ readUnlock();
if (mem != null)
desc.guard().end();
@@ -469,6 +483,9 @@ public class GridH2Table extends TableBase {
* Rebuilds all indexes of this table.
*/
public void rebuildIndexes() {
+ if (!snapshotEnabled)
+ return;
+
GridUnsafeMemory memory = desc == null ? null : desc.memory();
lock.writeLock().lock();
@@ -579,7 +596,7 @@ public class GridH2Table extends TableBase {
/** {@inheritDoc} */
@Override public long getRowCountApproximation() {
- return getUniqueIndex().getRowCountApproximation();
+ return size.longValue();
}
/** {@inheritDoc} */
@@ -605,6 +622,38 @@ public class GridH2Table extends TableBase {
}
/**
+ *
+ */
+ private void readLock() {
+ if (snapshotEnabled)
+ lock.readLock().lock();
+ }
+
+ /**
+ *
+ */
+ private void readUnlock() {
+ if (snapshotEnabled)
+ lock.readLock().unlock();
+ }
+
+ /**
+ *
+ */
+ private void writeLock() {
+ if (snapshotEnabled)
+ lock.writeLock().lock();
+ }
+
+ /**
+ *
+ */
+ private void writeUnlock() {
+ if (snapshotEnabled)
+ lock.writeLock().unlock();
+ }
+
+ /**
* H2 Table engine.
*/
@SuppressWarnings({"PublicInnerClass", "FieldAccessedSynchronizedAndUnsynchronized"})
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
index 387c58b..28adeee 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TreeIndex.java
@@ -23,6 +23,7 @@ import java.util.Comparator;
import java.util.Iterator;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentNavigableMap;
+import java.util.concurrent.ConcurrentSkipListMap;
import org.apache.ignite.internal.util.GridEmptyIterator;
import org.apache.ignite.internal.util.offheap.unsafe.GridOffHeapSnapTreeMap;
import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeGuard;
@@ -51,8 +52,10 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
protected final ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree;
/** */
- private final ThreadLocal<ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>> snapshot =
- new ThreadLocal<>();
+ private final ThreadLocal<ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>> snapshot = new ThreadLocal<>();
+
+ /** */
+ private final boolean snapshotEnabled;
/**
* Constructor with index initialization.
@@ -81,40 +84,68 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
final GridH2RowDescriptor desc = tbl.rowDescriptor();
- tree = desc == null || desc.memory() == null ? new SnapTreeMap<GridSearchRowPointer, GridH2Row>(this) {
- @Override protected void afterNodeUpdate_nl(Node<GridSearchRowPointer, GridH2Row> node, Object val) {
- if (val != null)
- node.key = (GridSearchRowPointer)val;
- }
+ if (desc == null || desc.memory() == null) {
+ snapshotEnabled = desc == null || desc.snapshotableIndex();
- @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
- if (key instanceof ComparableRow)
- return (Comparable<? super SearchRow>)key;
+ if (snapshotEnabled) {
+ tree = new SnapTreeMap<GridSearchRowPointer, GridH2Row>(this) {
+ @Override protected void afterNodeUpdate_nl(Node<GridSearchRowPointer, GridH2Row> node, Object val) {
+ if (val != null)
+ node.key = (GridSearchRowPointer)val;
+ }
- return super.comparable(key);
+ @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
+ if (key instanceof ComparableRow)
+ return (Comparable<? super SearchRow>)key;
+
+ return super.comparable(key);
+ }
+ };
}
- } : new GridOffHeapSnapTreeMap<GridSearchRowPointer, GridH2Row>(desc, desc, desc.memory(), desc.guard(), this) {
- @Override protected void afterNodeUpdate_nl(long node, GridH2Row val) {
- final long oldKey = keyPtr(node);
+ else {
+ tree = new ConcurrentSkipListMap<>(
+ new Comparator<GridSearchRowPointer>() {
+ @Override public int compare(GridSearchRowPointer o1, GridSearchRowPointer o2) {
+ if (o1 instanceof ComparableRow)
+ return ((ComparableRow)o1).compareTo(o2);
- if (val != null) {
- key(node, val);
+ if (o2 instanceof ComparableRow)
+ return -((ComparableRow)o2).compareTo(o1);
- guard.finalizeLater(new Runnable() {
- @Override public void run() {
- desc.createPointer(oldKey).decrementRefCount();
+ return compareRows(o1, o2);
+ }
}
- });
- }
+ );
}
+ }
+ else {
+ assert desc.snapshotableIndex() : desc;
- @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
- if (key instanceof ComparableRow)
- return (Comparable<? super SearchRow>)key;
+ snapshotEnabled = true;
- return super.comparable(key);
- }
- };
+ tree = new GridOffHeapSnapTreeMap<GridSearchRowPointer, GridH2Row>(desc, desc, desc.memory(), desc.guard(), this) {
+ @Override protected void afterNodeUpdate_nl(long node, GridH2Row val) {
+ final long oldKey = keyPtr(node);
+
+ if (val != null) {
+ key(node, val);
+
+ guard.finalizeLater(new Runnable() {
+ @Override public void run() {
+ desc.createPointer(oldKey).decrementRefCount();
+ }
+ });
+ }
+ }
+
+ @Override protected Comparable<? super GridSearchRowPointer> comparable(Object key) {
+ if (key instanceof ComparableRow)
+ return (Comparable<? super SearchRow>)key;
+
+ return super.comparable(key);
+ }
+ };
+ }
}
/**
@@ -133,6 +164,9 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
*/
@SuppressWarnings("unchecked")
@Override public Object takeSnapshot(@Nullable Object s) {
+ if (!snapshotEnabled)
+ return null;
+
assert snapshot.get() == null;
if (s == null)
@@ -148,6 +182,9 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
* Releases snapshot for current thread.
*/
@Override public void releaseSnapshot() {
+ if (!snapshotEnabled)
+ return;
+
ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> s = snapshot.get();
snapshot.remove();
@@ -160,6 +197,9 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
* @return Snapshot for current thread if there is one.
*/
private ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> treeForRead() {
+ if (!snapshotEnabled)
+ return tree;
+
ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> res = snapshot.get();
if (res == null)
@@ -199,7 +239,7 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
/** {@inheritDoc} */
@Override public long getRowCountApproximation() {
- return tree.size();
+ return table.getRowCountApproximation();
}
/** {@inheritDoc} */
@@ -372,7 +412,7 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
* Comparable row with bias. Will be used for queries to have correct bounds (in case of multicolumn index
* and query on few first columns we will multiple equal entries in tree).
*/
- private class ComparableRow implements GridSearchRowPointer, Comparable<SearchRow> {
+ private final class ComparableRow implements GridSearchRowPointer, Comparable<SearchRow> {
/** */
private final SearchRow row;
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
index 7b89824..0c9c8fe 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
@@ -28,6 +28,7 @@ import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
import org.apache.ignite.internal.util.typedef.F;
import org.h2.jdbc.JdbcPreparedStatement;
+import org.h2.util.IntArray;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.AVG;
@@ -224,13 +225,23 @@ public class GridSqlQuerySplitter {
rdcQry.distinct(true);
}
- // Build resulting two step query.
- GridCacheTwoStepQuery res = new GridCacheTwoStepQuery(spaces, new GridCacheSqlQuery(rdcQry.getSQL(),
- findParams(rdcQry, params, new ArrayList<>()).toArray()));
+ IntArray paramIdxs = new IntArray(params.length);
+
+ GridCacheSqlQuery rdc = new GridCacheSqlQuery(rdcQry.getSQL(),
+ findParams(rdcQry, params, new ArrayList<>(), paramIdxs).toArray());
+
+ rdc.parameterIndexes(toIntArray(paramIdxs));
+
+ paramIdxs = new IntArray(params.length);
- res.addMapQuery(new GridCacheSqlQuery(mapQry.getSQL(),
- findParams(mapQry, params, new ArrayList<>(params.length)).toArray())
- .columns(collectColumns(mapExps)));
+ GridCacheSqlQuery map = new GridCacheSqlQuery(mapQry.getSQL(),
+ findParams(mapQry, params, new ArrayList<>(params.length), paramIdxs).toArray())
+ .columns(collectColumns(mapExps));
+
+ map.parameterIndexes(toIntArray(paramIdxs));
+
+ // Build resulting two step query.
+ GridCacheTwoStepQuery res = new GridCacheTwoStepQuery(spaces, rdc, rdcQry.simpleQuery()).addMapQuery(map);
res.explain(explain);
@@ -238,6 +249,16 @@ public class GridSqlQuerySplitter {
}
/**
+ * @param arr Integer array.
+ * @return Primitive int array.
+ */
+ private static int[] toIntArray(IntArray arr) {
+ int[] res = new int[arr.size()];
+ arr.toArray(res);
+ return res;
+ }
+
+ /**
* @param cols Columns from SELECT clause.
* @return Map of columns with types.
*/
@@ -341,19 +362,21 @@ public class GridSqlQuerySplitter {
* @param qry Select.
* @param params Parameters.
* @param target Extracted parameters.
+ * @param paramIdxs Parameter indexes.
* @return Extracted parameters list.
*/
- private static List<Object> findParams(GridSqlQuery qry, Object[] params, ArrayList<Object> target) {
+ private static List<Object> findParams(GridSqlQuery qry, Object[] params, ArrayList<Object> target,
+ IntArray paramIdxs) {
if (qry instanceof GridSqlSelect)
- return findParams((GridSqlSelect)qry, params, target);
+ return findParams((GridSqlSelect)qry, params, target, paramIdxs);
GridSqlUnion union = (GridSqlUnion)qry;
- findParams(union.left(), params, target);
- findParams(union.right(), params, target);
+ findParams(union.left(), params, target, paramIdxs);
+ findParams(union.right(), params, target, paramIdxs);
- findParams(qry.limit(), params, target);
- findParams(qry.offset(), params, target);
+ findParams(qry.limit(), params, target, paramIdxs);
+ findParams(qry.offset(), params, target, paramIdxs);
return target;
}
@@ -362,22 +385,24 @@ public class GridSqlQuerySplitter {
* @param qry Select.
* @param params Parameters.
* @param target Extracted parameters.
+ * @param paramIdxs Parameter indexes.
* @return Extracted parameters list.
*/
- private static List<Object> findParams(GridSqlSelect qry, Object[] params, ArrayList<Object> target) {
+ private static List<Object> findParams(GridSqlSelect qry, Object[] params, ArrayList<Object> target,
+ IntArray paramIdxs) {
if (params.length == 0)
return target;
for (GridSqlElement el : qry.columns(false))
- findParams(el, params, target);
+ findParams(el, params, target, paramIdxs);
- findParams(qry.from(), params, target);
- findParams(qry.where(), params, target);
+ findParams(qry.from(), params, target, paramIdxs);
+ findParams(qry.where(), params, target, paramIdxs);
// Don't search in GROUP BY and HAVING since they expected to be in select list.
- findParams(qry.limit(), params, target);
- findParams(qry.offset(), params, target);
+ findParams(qry.limit(), params, target, paramIdxs);
+ findParams(qry.offset(), params, target, paramIdxs);
return target;
}
@@ -386,15 +411,17 @@ public class GridSqlQuerySplitter {
* @param el Element.
* @param params Parameters.
* @param target Extracted parameters.
+ * @param paramIdxs Parameter indexes.
*/
- private static void findParams(@Nullable GridSqlElement el, Object[] params, ArrayList<Object> target) {
+ private static void findParams(@Nullable GridSqlElement el, Object[] params, ArrayList<Object> target,
+ IntArray paramIdxs) {
if (el == null)
return;
if (el instanceof GridSqlParameter) {
// H2 Supports queries like "select ?5" but first 4 non-existing parameters are need to be set to any value.
// Here we will set them to NULL.
- int idx = ((GridSqlParameter)el).index();
+ final int idx = ((GridSqlParameter)el).index();
while (target.size() < idx)
target.add(null);
@@ -409,12 +436,14 @@ public class GridSqlQuerySplitter {
target.add(param);
else
target.set(idx, param);
+
+ paramIdxs.add(idx);
}
else if (el instanceof GridSqlSubquery)
- findParams(((GridSqlSubquery)el).select(), params, target);
+ findParams(((GridSqlSubquery)el).select(), params, target, paramIdxs);
else
for (GridSqlElement child : el)
- findParams(child, params, target);
+ findParams(child, params, target, paramIdxs);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java
index e537ace..e190c87 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java
@@ -103,6 +103,33 @@ public class GridSqlSelect extends GridSqlQuery {
}
/**
+ * @return {@code True} if this simple SQL query like 'SELECT A, B, C from SOME_TABLE' without any conditions
+ * and expressions.
+ */
+ public boolean simpleQuery() {
+ boolean simple = !distinct &&
+ from instanceof GridSqlTable &&
+ where == null &&
+ grpCols == null &&
+ havingCol < 0 &&
+ sort.isEmpty() &&
+ limit == null &&
+ offset == null;
+
+ if (simple) {
+ for (GridSqlElement expression : columns(true)) {
+ if (expression instanceof GridSqlAlias)
+ expression = expression.child();
+
+ if (!(expression instanceof GridSqlColumn))
+ return false;
+ }
+ }
+
+ return simple;
+ }
+
+ /**
* @param buff Statement builder.
* @param expression Alias expression.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/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 b4e1932..21541ec 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
@@ -451,8 +451,11 @@ public class GridMapQueryExecutor {
int i = 0;
for (GridCacheSqlQuery qry : qrys) {
- ResultSet rs = h2.executeSqlQueryWithTimer(req.space(), h2.connectionForSpace(req.space()), qry.query(),
- F.asList(qry.parameters()));
+ ResultSet rs = h2.executeSqlQueryWithTimer(req.space(),
+ h2.connectionForSpace(req.space()),
+ qry.query(),
+ F.asList(qry.parameters()),
+ true);
if (ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
ctx.event().record(new CacheQueryExecutedEvent<>(
@@ -820,17 +823,7 @@ public class GridMapQueryExecutor {
closed = true;
- Statement stmt;
-
- try {
- stmt = rs.getStatement();
- }
- catch (SQLException e) {
- throw new IllegalStateException(e); // Must not happen.
- }
-
U.close(rs, log);
- U.close(stmt, log);
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndex.java
index 7f8caed..12c2240 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndex.java
@@ -80,6 +80,13 @@ public abstract class GridMergeIndex extends BaseIndex {
}
/**
+ *
+ */
+ protected GridMergeIndex() {
+ // No-op.
+ }
+
+ /**
* @return Return source nodes for this merge index.
*/
public Set<UUID> sources() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndexUnsorted.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndexUnsorted.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndexUnsorted.java
index 5f5eb25..501480a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndexUnsorted.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeIndexUnsorted.java
@@ -47,6 +47,20 @@ public class GridMergeIndexUnsorted extends GridMergeIndex {
super(tbl, name, IndexType.createScan(false), IndexColumn.wrap(tbl.getColumns()));
}
+ /**
+ * @return Dummy index instance.
+ */
+ public static GridMergeIndexUnsorted createDummy() {
+ return new GridMergeIndexUnsorted();
+ }
+
+ /**
+ *
+ */
+ private GridMergeIndexUnsorted() {
+ // No-op.
+ }
+
/** {@inheritDoc} */
@Override protected void addPage0(GridResultPage page) {
assert page.rowsInPage() > 0 || page.isLast() || page.isFail();
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
index f515a78..1d4fa30 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridReduceQueryExecutor.java
@@ -79,10 +79,12 @@ import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.h2.command.ddl.CreateTableData;
import org.h2.engine.Session;
+import org.h2.index.Cursor;
import org.h2.jdbc.JdbcConnection;
import org.h2.jdbc.JdbcResultSet;
import org.h2.jdbc.JdbcStatement;
import org.h2.result.ResultInterface;
+import org.h2.result.Row;
import org.h2.table.Column;
import org.h2.util.IntArray;
import org.h2.value.Value;
@@ -184,8 +186,8 @@ public class GridReduceQueryExecutor {
UUID nodeId = ((DiscoveryEvent)evt).eventNode().id();
for (QueryRun r : runs.values()) {
- for (GridMergeTable tbl : r.tbls) {
- if (tbl.getScanIndex(null).hasSource(nodeId)) {
+ for (GridMergeIndex idx : r.idxs) {
+ if (idx.hasSource(nodeId)) {
handleNodeLeft(r, nodeId);
break;
@@ -270,7 +272,7 @@ public class GridReduceQueryExecutor {
final int pageSize = r.pageSize;
- GridMergeIndex idx = r.tbls.get(msg.query()).getScanIndex(null);
+ GridMergeIndex idx = r.idxs.get(msg.query());
GridResultPage page;
@@ -468,7 +470,7 @@ public class GridReduceQueryExecutor {
r.pageSize = qry.pageSize() <= 0 ? GridCacheTwoStepQuery.DFLT_PAGE_SIZE : qry.pageSize();
- r.tbls = new ArrayList<>(qry.mapQueries().size());
+ r.idxs = new ArrayList<>(qry.mapQueries().size());
String space = cctx.name();
@@ -501,7 +503,7 @@ public class GridReduceQueryExecutor {
assert !nodes.isEmpty();
if (cctx.isReplicated() || qry.explain()) {
- assert qry.explain() || !nodes.contains(ctx.cluster().get().localNode()) :
+ assert qry.explain() || !nodes.contains(ctx.discovery().localNode()) :
"We must be on a client node.";
// Select random data node to run query on a replicated data or get EXPLAIN PLAN from a single node.
@@ -510,27 +512,35 @@ public class GridReduceQueryExecutor {
int tblIdx = 0;
+ final boolean skipMergeTbl = !qry.explain() && qry.skipMergeTable();
+
for (GridCacheSqlQuery mapQry : qry.mapQueries()) {
- GridMergeTable tbl;
+ GridMergeIndex idx;
- try {
- tbl = createMergeTable(r.conn, mapQry, qry.explain());
- }
- catch (IgniteCheckedException e) {
- throw new IgniteException(e);
- }
+ if (!skipMergeTbl) {
+ GridMergeTable tbl;
+
+ try {
+ tbl = createMergeTable(r.conn, mapQry, qry.explain());
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException(e);
+ }
- GridMergeIndex idx = tbl.getScanIndex(null);
+ idx = tbl.getScanIndex(null);
+
+ fakeTable(r.conn, tblIdx++).setInnerTable(tbl);
+ }
+ else
+ idx = GridMergeIndexUnsorted.createDummy();
for (ClusterNode node : nodes)
idx.addSource(node.id());
- r.tbls.add(tbl);
-
- fakeTable(r.conn, tblIdx++).setInnerTable(tbl);
+ r.idxs.add(idx);
}
- r.latch = new CountDownLatch(r.tbls.size() * nodes.size());
+ r.latch = new CountDownLatch(r.idxs.size() * nodes.size());
runs.put(qryReqId, r);
@@ -586,19 +596,52 @@ public class GridReduceQueryExecutor {
else // Send failed.
retry = true;
- ResultSet res = null;
+ Iterator<List<?>> resIter = null;
if (!retry) {
if (qry.explain())
return explainPlan(r.conn, space, qry);
- GridCacheSqlQuery rdc = qry.reduceQuery();
+ if (skipMergeTbl) {
+ List<List<?>> res = new ArrayList<>();
+
+ assert r.idxs.size() == 1 : r.idxs;
- res = h2.executeSqlQueryWithTimer(space, r.conn, rdc.query(), F.asList(rdc.parameters()));
+ GridMergeIndex idx = r.idxs.get(0);
+
+ Cursor cur = idx.findInStream(null, null);
+
+ while (cur.next()) {
+ Row row = cur.get();
+
+ int cols = row.getColumnCount();
+
+ List<Object> resRow = new ArrayList<>(cols);
+
+ for (int c = 0; c < cols; c++)
+ resRow.add(row.getValue(c).getObject());
+
+ res.add(resRow);
+ }
+
+ resIter = res.iterator();
+ }
+ else {
+ GridCacheSqlQuery rdc = qry.reduceQuery();
+
+ // Statement caching is prohibited here because we can't guarantee correct merge index reuse.
+ ResultSet res = h2.executeSqlQueryWithTimer(space,
+ r.conn,
+ rdc.query(),
+ F.asList(rdc.parameters()),
+ false);
+
+ resIter = new Iter(res);
+ }
}
- for (GridMergeTable tbl : r.tbls) {
- if (!tbl.getScanIndex(null).fetchedAll()) // We have to explicitly cancel queries on remote nodes.
+ for (GridMergeIndex idx : r.idxs) {
+ if (!idx.fetchedAll()) // We have to explicitly cancel queries on remote nodes.
send(nodes, new GridQueryCancelRequest(qryReqId), null);
}
@@ -609,7 +652,7 @@ public class GridReduceQueryExecutor {
continue;
}
- return new GridQueryCacheObjectsIterator(new Iter(res), cctx, keepPortable);
+ return new GridQueryCacheObjectsIterator(resIter, cctx, keepPortable);
}
catch (IgniteCheckedException | RuntimeException e) {
U.closeQuiet(r.conn);
@@ -633,8 +676,10 @@ public class GridReduceQueryExecutor {
if (!runs.remove(qryReqId, r))
U.warn(log, "Query run was already removed: " + qryReqId);
- for (int i = 0, mapQrys = qry.mapQueries().size(); i < mapQrys; i++)
- fakeTable(null, i).setInnerTable(null); // Drop all merge tables.
+ if (!skipMergeTbl) {
+ for (int i = 0, mapQrys = qry.mapQueries().size(); i < mapQrys; i++)
+ fakeTable(null, i).setInnerTable(null); // Drop all merge tables.
+ }
}
}
}
@@ -941,7 +986,7 @@ public class GridReduceQueryExecutor {
List<List<?>> lists = new ArrayList<>();
for (int i = 0, mapQrys = qry.mapQueries().size(); i < mapQrys; i++) {
- ResultSet rs = h2.executeSqlQueryWithTimer(space, c, "SELECT PLAN FROM " + table(i), null);
+ ResultSet rs = h2.executeSqlQueryWithTimer(space, c, "SELECT PLAN FROM " + table(i), null, false);
lists.add(F.asList(getPlan(rs)));
}
@@ -956,7 +1001,11 @@ public class GridReduceQueryExecutor {
GridCacheSqlQuery rdc = qry.reduceQuery();
- ResultSet rs = h2.executeSqlQueryWithTimer(space, c, "EXPLAIN " + rdc.query(), F.asList(rdc.parameters()));
+ ResultSet rs = h2.executeSqlQueryWithTimer(space,
+ c,
+ "EXPLAIN " + rdc.query(),
+ F.asList(rdc.parameters()),
+ false);
lists.add(F.asList(getPlan(rs)));
@@ -1013,7 +1062,7 @@ public class GridReduceQueryExecutor {
}
if (locNodeFound) // Local node goes the last to allow parallel execution.
- h2.mapQueryExecutor().onMessage(ctx.localNodeId(), copy(msg, ctx.cluster().get().localNode(), partsMap));
+ h2.mapQueryExecutor().onMessage(ctx.localNodeId(), copy(msg, ctx.discovery().localNode(), partsMap));
return ok;
}
@@ -1120,7 +1169,7 @@ public class GridReduceQueryExecutor {
*/
private static class QueryRun {
/** */
- private List<GridMergeTable> tbls;
+ private List<GridMergeIndex> idxs;
/** */
private CountDownLatch latch;
@@ -1148,8 +1197,8 @@ public class GridReduceQueryExecutor {
while (latch.getCount() != 0) // We don't need to wait for all nodes to reply.
latch.countDown();
- for (GridMergeTable tbl : tbls) // Fail all merge indexes.
- tbl.getScanIndex(null).fail(nodeId);
+ for (GridMergeIndex idx : idxs) // Fail all merge indexes.
+ idx.fail(nodeId);
}
/**
@@ -1162,8 +1211,8 @@ public class GridReduceQueryExecutor {
while (latch.getCount() != 0) // We don't need to wait for all nodes to reply.
latch.countDown();
- for (GridMergeTable tbl : tbls) // Fail all merge indexes.
- tbl.getScanIndex(null).fail(e);
+ for (GridMergeIndex idx : idxs) // Fail all merge indexes.
+ idx.fail(e);
}
}
@@ -1179,7 +1228,7 @@ public class GridReduceQueryExecutor {
* @throws IgniteCheckedException If failed.
*/
protected Iter(ResultSet data) throws IgniteCheckedException {
- super(data);
+ super(data, true);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
index f3fbf15..c510600 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheAbstractQuerySelfTest.java
@@ -156,36 +156,38 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
if (i > 0)
cc.setName("c" + i);
- cc.setCacheMode(cacheMode());
- cc.setAtomicityMode(atomicityMode());
- cc.setNearConfiguration(nearCacheConfiguration());
- cc.setWriteSynchronizationMode(FULL_SYNC);
- cc.setCacheStoreFactory(new StoreFactory());
- cc.setReadThrough(true);
- cc.setWriteThrough(true);
- cc.setLoadPreviousValue(true);
- cc.setRebalanceMode(SYNC);
- cc.setSwapEnabled(true);
- cc.setSqlFunctionClasses(SqlFunctions.class);
- cc.setIndexedTypes(
- BadHashKeyObject.class, Byte.class,
- ObjectValue.class, Long.class,
- Integer.class, Integer.class,
- Integer.class, String.class,
- Integer.class, ObjectValue.class,
- String.class, ObjectValueOther.class,
- Integer.class, ArrayObject.class,
- Key.class, GridCacheQueryTestValue.class,
- UUID.class, Person.class,
- IgniteCacheReplicatedQuerySelfTest.CacheKey.class, IgniteCacheReplicatedQuerySelfTest.CacheValue.class
- );
-
- if (cacheMode() != CacheMode.LOCAL)
- cc.setAffinity(new RendezvousAffinityFunction());
-
- // Explicitly set number of backups equal to number of grids.
- if (cacheMode() == CacheMode.PARTITIONED)
- cc.setBackups(gridCount());
+ cc.setCacheMode(cacheMode());
+ cc.setAtomicityMode(atomicityMode());
+ cc.setNearConfiguration(nearCacheConfiguration());
+ cc.setWriteSynchronizationMode(FULL_SYNC);
+ cc.setCacheStoreFactory(new StoreFactory());
+ cc.setReadThrough(true);
+ cc.setWriteThrough(true);
+ cc.setLoadPreviousValue(true);
+ cc.setRebalanceMode(SYNC);
+ cc.setSwapEnabled(true);
+ cc.setSqlFunctionClasses(SqlFunctions.class);
+ cc.setIndexedTypes(
+ BadHashKeyObject.class, Byte.class,
+ ObjectValue.class, Long.class,
+ Integer.class, Integer.class,
+ Integer.class, String.class,
+ Integer.class, ObjectValue.class,
+ String.class, ObjectValueOther.class,
+ Integer.class, ArrayObject.class,
+ Key.class, GridCacheQueryTestValue.class,
+ UUID.class, Person.class,
+ IgniteCacheReplicatedQuerySelfTest.CacheKey.class, IgniteCacheReplicatedQuerySelfTest.CacheValue.class
+ );
+
+ if (cacheMode() != CacheMode.LOCAL)
+ cc.setAffinity(new RendezvousAffinityFunction());
+
+ // Explicitly set number of backups equal to number of grids.
+ if (cacheMode() == CacheMode.PARTITIONED)
+ cc.setBackups(gridCount());
+
+ cc.setSnapshotableIndex(snapshotableIndex());
ccs[i] = cc;
}
@@ -198,6 +200,13 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
return c;
}
+ /**
+ * @return {@code True} if index snapshot is enabled.
+ */
+ protected boolean snapshotableIndex() {
+ return false;
+ }
+
/** {@inheritDoc} */
@Override protected void beforeTest() throws Exception {
ignite = startGridsMultiThreaded(gridCount());
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCachePartitionedSnapshotEnabledQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCachePartitionedSnapshotEnabledQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCachePartitionedSnapshotEnabledQuerySelfTest.java
new file mode 100644
index 0000000..9a68b16
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCachePartitionedSnapshotEnabledQuerySelfTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.cache.distributed.near;
+
+/**
+ *
+ */
+public class IgniteCachePartitionedSnapshotEnabledQuerySelfTest extends IgniteCachePartitionedQuerySelfTest {
+ /** {@inheritDoc} */
+ @Override protected boolean snapshotableIndex() {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
index 194fb82..c027b26 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/GridIndexingSpiAbstractSelfTest.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.processors.query.GridQueryFieldsResult;
import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor;
import org.apache.ignite.internal.processors.query.GridQueryIndexType;
+import org.apache.ignite.internal.processors.query.GridQueryProperty;
import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
@@ -505,6 +506,24 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
}
/** {@inheritDoc} */
+ @Override public GridQueryProperty property(final String name) {
+ return new GridQueryProperty() {
+ @Override public Object value(Object key, Object val) throws IgniteCheckedException {
+ return TypeDesc.this.value(name, key, val);
+ }
+
+ @Override public String name() {
+ return name;
+ }
+
+ @Override
+ public Class<?> type() {
+ return Object.class;
+ }
+ };
+ }
+
+ /** {@inheritDoc} */
@SuppressWarnings("unchecked")
@Override public <T> T value(String field, Object key, Object val) throws IgniteSpiException {
assert !F.isEmpty(field);
http://git-wip-us.apache.org/repos/asf/ignite/blob/4af461a7/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
index 6cc2599..0745cd7 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite.java
@@ -55,6 +55,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheP
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCachePartitionedFieldsQuerySelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCachePartitionedQueryP2PDisabledSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCachePartitionedQuerySelfTest;
+import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCachePartitionedSnapshotEnabledQuerySelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartSelfTest2;
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedFieldsQueryP2PEnabledSelfTest;
@@ -118,6 +119,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
suite.addTestSuite(IgniteCacheReplicatedQuerySelfTest.class);
suite.addTestSuite(IgniteCacheReplicatedQueryP2PDisabledSelfTest.class);
suite.addTestSuite(IgniteCachePartitionedQuerySelfTest.class);
+ suite.addTestSuite(IgniteCachePartitionedSnapshotEnabledQuerySelfTest.class);
suite.addTestSuite(IgniteCacheAtomicQuerySelfTest.class);
suite.addTestSuite(IgniteCacheAtomicNearEnabledQuerySelfTest.class);
suite.addTestSuite(IgniteCachePartitionedQueryP2PDisabledSelfTest.class);