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 2016/07/28 11:06:26 UTC
[01/50] [abbrv] ignite git commit: IGNITE-466: IGFS: Added "IgfsMode
mode(IgfsPath)" method.
Repository: ignite
Updated Branches:
refs/heads/ignite-3553 b77bee0fe -> 7d05b6500
IGNITE-466: IGFS: Added "IgfsMode mode(IgfsPath)" method.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f7e8a6d6
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f7e8a6d6
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f7e8a6d6
Branch: refs/heads/ignite-3553
Commit: f7e8a6d66466fb561b5e2aa49fc45db7958f98fb
Parents: 80b3c4c
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Thu Jul 21 16:00:45 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Thu Jul 21 16:00:45 2016 +0300
----------------------------------------------------------------------
.../src/main/java/org/apache/ignite/IgniteFileSystem.java | 9 +++++++++
.../ignite/internal/processors/igfs/IgfsAsyncImpl.java | 6 ++++++
.../apache/ignite/internal/processors/igfs/IgfsImpl.java | 7 +++++++
.../apache/ignite/internal/processors/igfs/IgfsMock.java | 8 ++++++++
4 files changed, 30 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/f7e8a6d6/modules/core/src/main/java/org/apache/ignite/IgniteFileSystem.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteFileSystem.java b/modules/core/src/main/java/org/apache/ignite/IgniteFileSystem.java
index def2965..bbc5bea 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteFileSystem.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteFileSystem.java
@@ -24,6 +24,7 @@ import org.apache.ignite.igfs.IgfsBlockLocation;
import org.apache.ignite.igfs.IgfsFile;
import org.apache.ignite.igfs.IgfsInputStream;
import org.apache.ignite.igfs.IgfsMetrics;
+import org.apache.ignite.igfs.IgfsMode;
import org.apache.ignite.igfs.IgfsOutputStream;
import org.apache.ignite.igfs.IgfsPath;
import org.apache.ignite.igfs.IgfsPathSummary;
@@ -456,6 +457,14 @@ public interface IgniteFileSystem extends IgniteAsyncSupport {
@Nullable public IgfsFile info(IgfsPath path) throws IgniteException;
/**
+ * Get mode for the given path.
+ *
+ * @param path Path.
+ * @return Mode used for this path.
+ */
+ public IgfsMode mode(IgfsPath path);
+
+ /**
* Gets used space in bytes.
*
* @return Used space in bytes.
http://git-wip-us.apache.org/repos/asf/ignite/blob/f7e8a6d6/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsAsyncImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsAsyncImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsAsyncImpl.java
index 7530557..bf3d22b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsAsyncImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsAsyncImpl.java
@@ -26,6 +26,7 @@ import org.apache.ignite.configuration.FileSystemConfiguration;
import org.apache.ignite.igfs.IgfsBlockLocation;
import org.apache.ignite.igfs.IgfsFile;
import org.apache.ignite.igfs.IgfsMetrics;
+import org.apache.ignite.igfs.IgfsMode;
import org.apache.ignite.igfs.IgfsOutputStream;
import org.apache.ignite.igfs.IgfsPath;
import org.apache.ignite.igfs.IgfsPathSummary;
@@ -308,6 +309,11 @@ public class IgfsAsyncImpl extends AsyncSupportAdapter<IgniteFileSystem> impleme
}
/** {@inheritDoc} */
+ @Override public IgfsMode mode(IgfsPath path) {
+ return igfs.mode(path);
+ }
+
+ /** {@inheritDoc} */
@Override public long usedSpaceSize() {
return igfs.usedSpaceSize();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/f7e8a6d6/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
index efb347f..35e387c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
@@ -578,6 +578,13 @@ public final class IgfsImpl implements IgfsEx {
}
/** {@inheritDoc} */
+ @Override public IgfsMode mode(IgfsPath path) {
+ A.notNull(path, "path");
+
+ return modeRslvr.resolveMode(path);
+ }
+
+ /** {@inheritDoc} */
@Override public IgfsPathSummary summary(final IgfsPath path) {
A.notNull(path, "path");
http://git-wip-us.apache.org/repos/asf/ignite/blob/f7e8a6d6/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java
index dccab4a..a2bd9ca 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsMock.java
@@ -24,6 +24,7 @@ import org.apache.ignite.configuration.FileSystemConfiguration;
import org.apache.ignite.igfs.IgfsBlockLocation;
import org.apache.ignite.igfs.IgfsFile;
import org.apache.ignite.igfs.IgfsMetrics;
+import org.apache.ignite.igfs.IgfsMode;
import org.apache.ignite.igfs.IgfsOutputStream;
import org.apache.ignite.igfs.IgfsPath;
import org.apache.ignite.igfs.IgfsPathSummary;
@@ -361,6 +362,13 @@ public class IgfsMock implements IgfsEx {
}
/** {@inheritDoc} */
+ @Override public IgfsMode mode(IgfsPath path) {
+ throwUnsupported();
+
+ return null;
+ }
+
+ /** {@inheritDoc} */
@Override public long usedSpaceSize() throws IgniteException {
throwUnsupported();
[44/50] [abbrv] ignite git commit: ignite-1232 Added possibility to
test distributedJoins in IgniteCacheRandomOperationBenchmark
Posted by vo...@apache.org.
ignite-1232 Added possibility to test distributedJoins in IgniteCacheRandomOperationBenchmark
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2f36ae55
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2f36ae55
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2f36ae55
Branch: refs/heads/ignite-3553
Commit: 2f36ae559a83dc9d294de100e11fb4bbf3bae248
Parents: 77781e9
Author: sboikov <sb...@gridgain.com>
Authored: Wed Jul 27 14:56:31 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Wed Jul 27 14:56:31 2016 +0300
----------------------------------------------------------------------
modules/yardstick/config/queries.sql | 1 +
.../IgniteCacheRandomOperationBenchmark.java | 71 ++++++++++++++++----
2 files changed, 60 insertions(+), 12 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/2f36ae55/modules/yardstick/config/queries.sql
----------------------------------------------------------------------
diff --git a/modules/yardstick/config/queries.sql b/modules/yardstick/config/queries.sql
index 8271100..7326b31 100644
--- a/modules/yardstick/config/queries.sql
+++ b/modules/yardstick/config/queries.sql
@@ -1,2 +1,3 @@
SELECT Person.firstName FROM "query".Person, "orgCache".Organization WHERE Person.orgId = Organization.id AND lower(Organization.name) = lower('Organization 55')
SELECT Organization.name FROM "orgCache".Organization WHERE lower(Organization.name) LIKE lower('%55%')
+SELECT Person.firstName FROM "query".Person, "orgCache".Organization WHERE Person.orgId = Organization.id AND lower(Organization.name) = lower('Organization 55') #distributedJoins
http://git-wip-us.apache.org/repos/asf/ignite/blob/2f36ae55/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
index e62df45..d37cdca 100644
--- a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
@@ -61,6 +61,7 @@ import org.apache.ignite.cache.query.SqlQuery;
import org.apache.ignite.cluster.ClusterGroup;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.lang.IgniteRunnable;
import org.apache.ignite.resources.IgniteInstanceResource;
@@ -110,7 +111,7 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
private Map<String, List<SqlCacheDescriptor>> cacheSqlDescriptors;
/** List of SQL queries. */
- private List<String> queries;
+ private List<TestQuery> queries;
/** List of allowed cache operations which will be executed. */
private List<Operation> allowedLoadTestOps;
@@ -237,7 +238,7 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
throw new IgniteException("Class is unknown for the load test. Make sure you " +
"specified its full name [clsName=" + queryEntity.getKeyType() + ']');
- cofigureCacheSqlDescriptor(cacheName, queryEntity, valCls);
+ configureCacheSqlDescriptor(cacheName, queryEntity, valCls);
}
} catch (ClassNotFoundException e) {
BenchmarkUtils.println(e.getMessage());
@@ -307,11 +308,13 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
*/
private void loadAllowedOperations() {
allowedLoadTestOps = new ArrayList<>();
+
if (args.allowedLoadTestOps().isEmpty())
Collections.addAll(allowedLoadTestOps, Operation.values());
- else
+ else {
for (String opName : args.allowedLoadTestOps())
allowedLoadTestOps.add(Operation.valueOf(opName.toUpperCase()));
+ }
}
/**
@@ -330,7 +333,24 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
if (line.trim().isEmpty())
continue;
- queries.add(line.trim());
+ boolean distributedJoins = false;
+
+ int commentIdx = line.lastIndexOf('#');
+
+ if (commentIdx >= 0) {
+ if (line.toUpperCase().indexOf("DISTRIBUTEDJOINS", commentIdx) > 0)
+ distributedJoins = true;
+
+ line = line.substring(0, commentIdx);
+ }
+
+ line = line.trim();
+
+ TestQuery qry = new TestQuery(line, distributedJoins);
+
+ queries.add(qry);
+
+ BenchmarkUtils.println("Loaded query: " + qry);
}
}
}
@@ -343,7 +363,7 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
* @param valCls Class of value.
* @throws ClassNotFoundException If fail.
*/
- private void cofigureCacheSqlDescriptor(String cacheName, QueryEntity qryEntity, Class valCls)
+ private void configureCacheSqlDescriptor(String cacheName, QueryEntity qryEntity, Class valCls)
throws ClassNotFoundException {
List<SqlCacheDescriptor> descs = cacheSqlDescriptors.get(cacheName);
@@ -883,9 +903,13 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
}
}
else {
- String sql = rendomizeSql();
+ TestQuery qry = queries.get(nextRandom(queries.size()));
+
+ String sql = randomizeSql(qry.sql);
sq = new SqlFieldsQuery(sql);
+
+ ((SqlFieldsQuery)sq).setDistributedJoins(qry.distributedJoin);
}
if (sq != null)
@@ -900,14 +924,12 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
/**
* @return SQL string.
*/
- private String rendomizeSql() {
- String sql = queries.get(nextRandom(queries.size()));
-
- int count = StringUtils.countOccurrencesOf(sql, "%s");
+ private String randomizeSql(String sql) {
+ int cnt = StringUtils.countOccurrencesOf(sql, "%s");
- Integer[] sub = new Integer[count];
+ Integer[] sub = new Integer[cnt];
- for (int i=0; i<count; i++)
+ for (int i = 0; i< cnt; i++)
sub[i] = nextRandom(args.range());
sql = String.format(sql, sub);
@@ -1196,4 +1218,29 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
return values()[num];
}
}
+
+ /**
+ *
+ */
+ private static class TestQuery {
+ /** */
+ private final String sql;
+
+ /** */
+ private final boolean distributedJoin;
+
+ /**
+ * @param sql SQL.
+ * @param distributedJoin Distributed join flag.
+ */
+ public TestQuery(String sql, boolean distributedJoin) {
+ this.sql = sql;
+ this.distributedJoin = distributedJoin;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TestQuery.class, this);
+ }
+ }
}
[31/50] [abbrv] ignite git commit: ignite-1232 Stop idx pool on node
stop
Posted by vo...@apache.org.
ignite-1232 Stop idx pool on node stop
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fb884ec3
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fb884ec3
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fb884ec3
Branch: refs/heads/ignite-3553
Commit: fb884ec37cc362764a84c3d4d8feb69648346964
Parents: e70adde
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jul 26 11:13:52 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jul 26 11:13:52 2016 +0300
----------------------------------------------------------------------
.../ignite/internal/managers/communication/GridIoManager.java | 2 ++
1 file changed, 2 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/fb884ec3/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
index 99cb7f4..3fdda30 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
@@ -559,6 +559,8 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
U.shutdownNow(getClass(), affPool, log);
+ U.shutdownNow(getClass(), idxPool, log);
+
GridEventStorageManager evtMgr = ctx.event();
if (evtMgr != null && discoLsnr != null)
[40/50] [abbrv] ignite git commit: Merge remote-tracking branch
'origin/ignite-1.7' into ignite-1.7
Posted by vo...@apache.org.
Merge remote-tracking branch 'origin/ignite-1.7' into ignite-1.7
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/34d553ad
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/34d553ad
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/34d553ad
Branch: refs/heads/ignite-3553
Commit: 34d553adaa5716faa67b84917e2aab24274c7327
Parents: 9a80838 a32eb87
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Wed Jul 27 13:42:44 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Jul 27 13:42:44 2016 +0300
----------------------------------------------------------------------
parent/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
[10/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinPartitionedAndReplicatedTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinPartitionedAndReplicatedTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinPartitionedAndReplicatedTest.java
new file mode 100644
index 0000000..d7610dc
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinPartitionedAndReplicatedTest.java
@@ -0,0 +1,487 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheDistributedJoinPartitionedAndReplicatedTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String PERSON_CACHE = "person";
+
+ /** */
+ private static final String ORG_CACHE = "org";
+
+ /** */
+ private static final String ACCOUNT_CACHE = "acc";
+
+ /** */
+ private boolean client;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi spi = ((TcpDiscoverySpi)cfg.getDiscoverySpi());
+
+ spi.setIpFinder(IP_FINDER);
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /**
+ * @param name Cache name.
+ * @param cacheMode Cache mode.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration configuration(String name, CacheMode cacheMode) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+ ccfg.setAtomicityMode(ATOMIC);
+ ccfg.setCacheMode(cacheMode);
+
+ if (cacheMode == PARTITIONED)
+ ccfg.setBackups(1);
+
+ return ccfg;
+ }
+
+ /**
+ * @param idx Use index flag.
+ * @param persCacheMode Person cache mode.
+ * @param orgCacheMode Organization cache mode.
+ * @param accCacheMode Account cache mode.
+ * @return Configurations.
+ */
+ private List<CacheConfiguration> caches(boolean idx,
+ CacheMode persCacheMode,
+ CacheMode orgCacheMode,
+ CacheMode accCacheMode) {
+ List<CacheConfiguration> ccfgs = new ArrayList<>();
+
+ {
+ CacheConfiguration ccfg = configuration(PERSON_CACHE, persCacheMode);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Person.class.getName());
+ entity.addQueryField("orgId", Integer.class.getName(), null);
+ entity.addQueryField("name", String.class.getName(), null);
+
+ if (idx)
+ entity.setIndexes(F.asList(new QueryIndex("orgId"), new QueryIndex("name")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(ORG_CACHE, orgCacheMode);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Organization.class.getName());
+ entity.addQueryField("name", String.class.getName(), null);
+
+ if (idx)
+ entity.setIndexes(F.asList(new QueryIndex("name")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(ACCOUNT_CACHE, accCacheMode);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Account.class.getName());
+ entity.addQueryField("orgId", Integer.class.getName(), null);
+ entity.addQueryField("personId", Integer.class.getName(), null);
+ entity.addQueryField("name", String.class.getName(), null);
+
+ if (idx) {
+ entity.setIndexes(F.asList(new QueryIndex("orgId"),
+ new QueryIndex("personId"),
+ new QueryIndex("name")));
+ }
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ return ccfgs;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(2);
+
+ client = true;
+
+ startGrid(2);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin1() throws Exception {
+ join(true, REPLICATED, PARTITIONED, PARTITIONED);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin2() throws Exception {
+ join(true, PARTITIONED, REPLICATED, PARTITIONED);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin3() throws Exception {
+ join(true, PARTITIONED, PARTITIONED, REPLICATED);
+ }
+
+ /**
+ * @param idx Use index flag.
+ * @param persCacheMode Person cache mode.
+ * @param orgCacheMode Organization cache mode.
+ * @param accCacheMode Account cache mode.
+ * @throws Exception If failed.
+ */
+ private void join(boolean idx, CacheMode persCacheMode, CacheMode orgCacheMode, CacheMode accCacheMode)
+ throws Exception {
+ Ignite client = grid(2);
+
+ for (CacheConfiguration ccfg : caches(idx, persCacheMode, orgCacheMode, accCacheMode))
+ client.createCache(ccfg);
+
+ try {
+ IgniteCache<Object, Object> personCache = client.cache(PERSON_CACHE);
+ IgniteCache<Object, Object> orgCache = client.cache(ORG_CACHE);
+ IgniteCache<Object, Object> accCache = client.cache(ACCOUNT_CACHE);
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ AtomicInteger pKey = new AtomicInteger(100_000);
+ AtomicInteger orgKey = new AtomicInteger();
+ AtomicInteger accKey = new AtomicInteger();
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ /**
+ * One organization, one person, two accounts.
+ */
+
+ {
+ int orgId1 = keyForNode(aff, orgKey, node0);
+
+ orgCache.put(orgId1, new Organization("obj-" + orgId1));
+
+ int pid1 = keyForNode(aff, pKey, node0);
+ personCache.put(pid1, new Person(orgId1, "o1-p1"));
+
+ accCache.put(keyForNode(aff, accKey, node0), new Account(pid1, orgId1, "a0"));
+ accCache.put(keyForNode(aff, accKey, node1), new Account(pid1, orgId1, "a1"));
+ }
+
+ IgniteCache<Object, Object> qryCache = replicated(orgCache) ? personCache : orgCache;
+
+ checkQuery("select p._key, p.name, a.name " +
+ "from \"person\".Person p, \"acc\".Account a " +
+ "where p._key = a.personId", qryCache, false, 2);
+
+ checkQuery("select o.name, p._key, p.name, a.name " +
+ "from \"org\".Organization o, \"person\".Person p, \"acc\".Account a " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key", qryCache, false, 2);
+
+ checkQuery("select o.name, p._key, p.name, a.name " +
+ "from \"org\".Organization o, \"acc\".Account a, \"person\".Person p " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key", qryCache, false, 2);
+
+ checkQuery("select o.name, p._key, p.name, a.name " +
+ "from \"person\".Person p, \"org\".Organization o, \"acc\".Account a " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key", qryCache, false, 2);
+
+ checkQuery("select * from (select o.name n1, p._key, p.name n2, a.name n3 " +
+ "from \"acc\".Account a, \"person\".Person p, \"org\".Organization o " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key)", qryCache, false, 2);
+
+ checkQuery("select * from (select o.name n1, p._key, p.name n2, a.name n3 " +
+ "from \"person\".Person p, \"acc\".Account a, \"org\".Organization o " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key)", qryCache, false, 2);
+
+ List<List<?>> res = checkQuery("select count(*) " +
+ "from \"org\".Organization o, \"person\".Person p, \"acc\".Account a " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key", qryCache, false, 1);
+
+ assertEquals(2L, res.get(0).get(0));
+
+ checkQueries(qryCache, 2);
+
+ {
+ int orgId2 = keyForNode(aff, orgKey, node1);
+
+ orgCache.put(orgId2, new Organization("obj-" + orgId2));
+
+ int pid2 = keyForNode(aff, pKey, node0);
+ personCache.put(pid2, new Person(orgId2, "o2-p1"));
+
+ accCache.put(keyForNode(aff, accKey, node0), new Account(pid2, orgId2, "a3"));
+ accCache.put(keyForNode(aff, accKey, node1), new Account(pid2, orgId2, "a4"));
+ }
+
+ checkQuery("select o.name, p._key, p.name, a.name " +
+ "from \"org\".Organization o, \"person\".Person p, \"acc\".Account a " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key", qryCache, false, 4);
+
+ checkQuery("select o.name, p._key, p.name, a.name " +
+ "from \"org\".Organization o inner join \"person\".Person p on p.orgId = o._key " +
+ "inner join \"acc\".Account a on p._key = a.personId and a.orgId=o._key", qryCache, false, 4);
+
+ res = checkQuery("select count(*) " +
+ "from \"org\".Organization o, \"person\".Person p, \"acc\".Account a " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key", qryCache, false, 1);
+
+ assertEquals(4L, res.get(0).get(0));
+
+ checkQuery("select o.name, p._key, p.name, a.name " +
+ "from \"org\".Organization o, \"person\".Person p, \"acc\".Account a " +
+ "where p.orgId = o._key and a.orgId = o._key and a.orgId=o._key", qryCache, false, 4);
+
+ res = checkQuery("select count(*) " +
+ "from \"org\".Organization o, \"person\".Person p, \"acc\".Account a " +
+ "where p.orgId = o._key and a.orgId = o._key and a.orgId=o._key", qryCache, false, 1);
+
+ assertEquals(4L, res.get(0).get(0));
+
+ checkQueries(qryCache, 4);
+ }
+ finally {
+ client.destroyCache(PERSON_CACHE);
+ client.destroyCache(ORG_CACHE);
+ client.destroyCache(ACCOUNT_CACHE);
+ }
+ }
+
+ /**
+ * @param qryCache Query cache.
+ * @param expSize Expected results size.
+ */
+ private void checkQueries(IgniteCache<Object, Object> qryCache, int expSize) {
+ String[] cacheNames = {"\"org\".Organization o", "\"person\".Person p", "\"acc\".Account a"};
+
+ for (int c1 = 0; c1 < cacheNames.length; c1++) {
+ for (int c2 = 0; c2 < cacheNames.length; c2++) {
+ if (c2 == c1)
+ continue;
+
+ for (int c3 = 0; c3 < cacheNames.length; c3++) {
+ if (c3 == c1 || c3 == c2)
+ continue;
+
+ String cache1 = cacheNames[c1];
+ String cache2 = cacheNames[c2];
+ String cache3 = cacheNames[c3];
+
+ String qry = "select o.name, p._key, p.name, a.name from " +
+ cache1 + ", " +
+ cache2 + ", " +
+ cache3 + " " +
+ "where p.orgId = o._key and p._key = a.personId and a.orgId=o._key";
+
+ checkQuery(qry, qryCache, false, expSize);
+
+ qry = "select o.name, p._key, p.name, a.name from " +
+ cache1 + ", " +
+ cache2 + ", " +
+ cache3 + " " +
+ "where p.orgId = o._key and a.orgId = o._key and a.orgId=o._key";
+
+ checkQuery(qry, qryCache, false, expSize);
+ }
+ }
+ }
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @param expSize Expected results size.
+ * @param args Arguments.
+ * @return Results.
+ */
+ private List<List<?>> checkQuery(String sql,
+ IgniteCache<Object, Object> cache,
+ boolean enforceJoinOrder,
+ int expSize,
+ Object... args) {
+ SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ qry.setDistributedJoins(true);
+ qry.setEnforceJoinOrder(enforceJoinOrder);
+ qry.setArgs(args);
+
+ log.info("Plan: " + queryPlan(cache, qry));
+
+ QueryCursor<List<?>> cur = cache.query(qry);
+
+ List<List<?>> res = cur.getAll();
+
+ if (expSize != res.size())
+ log.info("Results: " + res);
+
+ assertEquals(expSize, res.size());
+
+ return res;
+ }
+
+ /**
+ * @param cache Cache.
+ * @return {@code True} if cache is replicated.
+ */
+ private boolean replicated(IgniteCache<?, ?> cache) {
+ return cache.getConfiguration(CacheConfiguration.class).getCacheMode() == REPLICATED;
+ }
+
+ /**
+ *
+ */
+ private static class Account implements Serializable {
+ /** */
+ int personId;
+
+ /** */
+ int orgId;
+
+ /** */
+ String name;
+
+ /**
+ * @param personId Person ID.
+ * @param orgId Organization ID.
+ * @param name Name.
+ */
+ public Account(int personId, int orgId, String name) {
+ this.personId = personId;
+ this.orgId = orgId;
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Account.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ int orgId;
+
+ /** */
+ String name;
+
+ /**
+ * @param orgId Organization ID.
+ * @param name Name.
+ */
+ public Person(int orgId, String name) {
+ this.orgId = orgId;
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Person.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ /** */
+ String name;
+
+ /**
+ * @param name Name.
+ */
+ public Organization(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Organization.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java
new file mode 100644
index 0000000..af56c91
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinQueryConditionsTest.java
@@ -0,0 +1,624 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheMemoryMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheDistributedJoinQueryConditionsTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String PERSON_CACHE = "person";
+
+ /** */
+ private static final String ORG_CACHE = "org";
+
+ /** */
+ private boolean client;
+
+ /** */
+ private int total;
+
+ /** */
+ private CacheMemoryMode memMode = ONHEAP_TIERED;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi spi = ((TcpDiscoverySpi) cfg.getDiscoverySpi());
+
+ spi.setIpFinder(IP_FINDER);
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(2);
+
+ client = true;
+
+ startGrid(2);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQuery1() throws Exception {
+ joinQuery1(true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQuery1Offheap() throws Exception {
+ memMode = OFFHEAP_TIERED;
+
+ testJoinQuery1();
+ }
+
+ /**
+ * @param idx Use index flag.
+ * @throws Exception If failed.
+ */
+ private void joinQuery1(boolean idx) throws Exception {
+ Ignite client = grid(2);
+
+ try {
+ CacheConfiguration ccfg1 =
+ cacheConfiguration(PERSON_CACHE).setQueryEntities(F.asList(personEntity(idx, idx)));
+ CacheConfiguration ccfg2 =
+ cacheConfiguration(ORG_CACHE).setQueryEntities(F.asList(organizationEntity(idx)));
+
+ IgniteCache<Object, Object> pCache = client.createCache(ccfg1);
+ client.createCache(ccfg2);
+
+ List<Integer> orgIds = putData1();
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key", pCache, total);
+
+ checkQuery("select * from (select o._key, o.name, p._key pKey, p.name pName " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key)", pCache, total);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o inner join Person p " +
+ "on p.orgId = o._key", pCache, total);
+
+ checkQuery("select * from (select o._key o_key, o.name o_name, p._key p_key, p.name p_name " +
+ "from \"org\".Organization o inner join Person p " +
+ "on p.orgId = o._key)", pCache, total);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and o._key=" + orgIds.get(3), pCache, 3);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and o._key IN (" + orgIds.get(2) + "," + orgIds.get(3) + ")", pCache, 5);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and o._key IN (" + orgIds.get(2) + "," + orgIds.get(3) + ")", pCache, 5);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and o._key > " + orgIds.get(2), pCache, total - 3);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and o._key > " + orgIds.get(1) + " and o._key < " + orgIds.get(4), pCache, 5);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.name = o.name", pCache, total);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.name = o.name and o._key=" + orgIds.get(0), pCache, 0);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.name = o.name and o._key=" + orgIds.get(3), pCache, 3);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.name = o.name and o._key IN (" + orgIds.get(2) + "," + orgIds.get(3) + ")", pCache, 5);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.name = o.name and o.name='obj-" + orgIds.get(3) + "'", pCache, 3);
+ }
+ finally {
+ client.destroyCache(PERSON_CACHE);
+ client.destroyCache(ORG_CACHE);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQuery2() throws Exception {
+ Ignite client = grid(2);
+
+ try {
+ CacheConfiguration ccfg1 = cacheConfiguration(PERSON_CACHE).setQueryEntities(F.asList(personEntity(false, true)));
+ CacheConfiguration ccfg2 = cacheConfiguration(ORG_CACHE).setQueryEntities(F.asList(organizationEntity(false)));
+
+ IgniteCache<Object, Object> pCache = client.createCache(ccfg1);
+ IgniteCache<Object, Object> orgCache = client.createCache(ccfg2);
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ AtomicInteger orgKey = new AtomicInteger();
+ AtomicInteger pKey = new AtomicInteger();
+
+ List<Integer> pIds = new ArrayList<>();
+
+ for (int i = 0; i < 3; i++) {
+ Integer orgId = keyForNode(aff, orgKey, node0);
+
+ orgCache.put(orgId, new Organization("org-" + orgId));
+
+ Integer pId = keyForNode(aff, pKey, node1);
+
+ pCache.put(pId, new Person(orgId, "p-" + orgId));
+
+ pIds.add(pId);
+ }
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and p._key >= 0", pCache, 3);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and p._key=" + pIds.get(0), pCache, 1);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId = o._key and p._key in (" + pIds.get(0) + ", " + pIds.get(1) + ")", pCache, 2);
+ }
+ finally {
+ client.destroyCache(PERSON_CACHE);
+ client.destroyCache(ORG_CACHE);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void _testJoinQuery3() throws Exception {
+ Ignite client = grid(2);
+
+ try {
+ CacheConfiguration ccfg1 = cacheConfiguration(PERSON_CACHE).setQueryEntities(F.asList(personEntity(false, true)));
+ CacheConfiguration ccfg2 = cacheConfiguration(ORG_CACHE).setQueryEntities(F.asList(organizationEntity(false)));
+
+ IgniteCache<Object, Object> pCache = client.createCache(ccfg1);
+ IgniteCache<Object, Object> orgCache = client.createCache(ccfg2);
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ AtomicInteger orgKey = new AtomicInteger();
+ AtomicInteger pKey = new AtomicInteger();
+
+ List<Integer> pIds = new ArrayList<>();
+
+ for (int i = 0; i < 3; i++) {
+ Integer orgId = keyForNode(aff, orgKey, node0);
+
+ orgCache.put(orgId, new Organization("org-" + orgId));
+
+ Integer pId = keyForNode(aff, pKey, node1);
+
+ pCache.put(pId, new Person(orgId + 100_000, "p-" + orgId));
+
+ pIds.add(pId);
+ }
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId != o._key", pCache, 9);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId != o._key and p._key=" + pIds.get(0), pCache, 3);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId != o._key and p._key in (" + pIds.get(0) + ", " + pIds.get(1) + ")", pCache, 6);
+
+ checkQuery("select o._key, o.name, p._key, p.name " +
+ "from \"org\".Organization o, Person p " +
+ "where p.orgId != o._key and p._key >=" + pIds.get(0) + "and p._key <= " + pIds.get(2), pCache, 9);
+ }
+ finally {
+ client.destroyCache(PERSON_CACHE);
+ client.destroyCache(ORG_CACHE);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQuery4() throws Exception {
+ Ignite client = grid(2);
+
+ try {
+ CacheConfiguration ccfg1 =
+ cacheConfiguration(PERSON_CACHE).setQueryEntities(F.asList(personEntity(true, false)));
+
+ IgniteCache<Object, Object> pCache = client.createCache(ccfg1);
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ AtomicInteger pKey = new AtomicInteger();
+
+ Integer pId0 = keyForNode(aff, pKey, node0);
+
+ pCache.put(pId0, new Person(0, "p0"));
+
+ for (int i = 0; i < 3; i++) {
+ Integer pId = keyForNode(aff, pKey, node1);
+
+ pCache.put(pId, new Person(0, "p"));
+ }
+
+ checkQuery("select p1._key, p1.name, p2._key, p2.name " +
+ "from Person p1, Person p2 " +
+ "where p2._key > p1._key", pCache, 6);
+
+ checkQuery("select p1._key, p1.name, p2._key, p2.name " +
+ "from Person p1, Person p2 " +
+ "where p2._key > p1._key and p1._key=" + pId0, pCache, 3);
+
+ checkQuery("select p1._key, p1.name, p2._key, p2.name " +
+ "from Person p1, Person p2 " +
+ "where p2._key > p1._key and p1.name='p0'", pCache, 3);
+
+ checkQuery("select p1._key, p1.name, p2._key, p2.name " +
+ "from Person p1, Person p2 " +
+ "where p1.name > p2.name", pCache, 3);
+ }
+ finally {
+ client.destroyCache(PERSON_CACHE);
+ client.destroyCache(ORG_CACHE);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQuery5() throws Exception {
+ Ignite client = grid(2);
+
+ try {
+ CacheConfiguration ccfg1 = cacheConfiguration(PERSON_CACHE).setQueryEntities(F.asList(personEntity(false, true)));
+ CacheConfiguration ccfg2 = cacheConfiguration(ORG_CACHE).setQueryEntities(F.asList(organizationEntity(false)));
+
+ IgniteCache<Object, Object> pCache = client.createCache(ccfg1);
+ IgniteCache<Object, Object> orgCache = client.createCache(ccfg2);
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ AtomicInteger orgKey = new AtomicInteger();
+ AtomicInteger pKey = new AtomicInteger();
+
+ Integer orgId = keyForNode(aff, orgKey, node0);
+
+ orgCache.put(orgId, new Organization("org-" + orgId));
+
+ Integer pId = keyForNode(aff, pKey, node1);
+
+ pCache.put(pId, new Person(orgId, "p-" + orgId));
+
+ checkQuery("select o._key from \"org\".Organization o, Person p where p.orgId = o._key", pCache, 1);
+
+ // Distributed join is not enabled for expressions, just check query does not fail.
+ checkQuery("select o.name from \"org\".Organization o where o._key in " +
+ "(select o._key from \"org\".Organization o, Person p where p.orgId = o._key)", pCache, 0);
+ }
+ finally {
+ client.destroyCache(PERSON_CACHE);
+ client.destroyCache(ORG_CACHE);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQuery6() throws Exception {
+ Ignite client = grid(2);
+
+ try {
+ CacheConfiguration ccfg1 =
+ cacheConfiguration(PERSON_CACHE).setQueryEntities(F.asList(personEntity(true, true)));
+ CacheConfiguration ccfg2 =
+ cacheConfiguration(ORG_CACHE).setQueryEntities(F.asList(organizationEntity(true)));
+
+ IgniteCache<Object, Object> pCache = client.createCache(ccfg1);
+
+ client.createCache(ccfg2);
+
+ putData1();
+
+ checkQuery("select _key, name from \"org\".Organization o " +
+ "inner join (select orgId from Person) p on p.orgId = o._key", pCache, total);
+
+ checkQuery("select o._key, o.name from (select _key, name from \"org\".Organization) o " +
+ "inner join Person p on p.orgId = o._key", pCache, total);
+
+ checkQuery("select o._key, o.name from (select _key, name from \"org\".Organization) o " +
+ "inner join (select orgId from Person) p on p.orgId = o._key", pCache, total);
+
+ checkQuery("select * from " +
+ "(select _key, name from \"org\".Organization) o " +
+ "inner join " +
+ "(select orgId from Person) p " +
+ "on p.orgId = o._key", pCache, total);
+ }
+ finally {
+ client.destroyCache(PERSON_CACHE);
+ client.destroyCache(ORG_CACHE);
+ }
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ * @param expSize Expected results size.
+ * @param args Arguments.
+ */
+ private void checkQuery(String sql, IgniteCache<Object, Object> cache, int expSize, Object... args) {
+ log.info("Execute query: " + sql);
+
+ checkQuery(sql, cache, false, expSize, args);
+
+ checkQuery(sql, cache, true, expSize, args);
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @param expSize Expected results size.
+ * @param args Arguments.
+ */
+ private void checkQuery(String sql,
+ IgniteCache<Object, Object> cache,
+ boolean enforceJoinOrder,
+ int expSize,
+ Object... args) {
+ SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ qry.setDistributedJoins(true);
+ qry.setEnforceJoinOrder(enforceJoinOrder);
+ qry.setArgs(args);
+
+ log.info("Plan: " + queryPlan(cache, qry));
+
+ QueryCursor<List<?>> cur = cache.query(qry);
+
+ List<List<?>> res = cur.getAll();
+
+ if (expSize != res.size())
+ log.info("Results: " + res);
+
+ assertEquals(expSize, res.size());
+ }
+
+ /**
+ * @param idxName Name index flag.
+ * @param idxOrgId Org ID index flag.
+ * @return Entity.
+ */
+ private QueryEntity personEntity(boolean idxName, boolean idxOrgId) {
+ QueryEntity entity = new QueryEntity();
+
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Person.class.getName());
+
+ entity.addQueryField("orgId", Integer.class.getName(), null);
+ entity.addQueryField("name", String.class.getName(), null);
+
+ List<QueryIndex> idxs = new ArrayList<>();
+
+ if (idxName) {
+ QueryIndex idx = new QueryIndex("name");
+
+ idxs.add(idx);
+ }
+
+ if (idxOrgId) {
+ QueryIndex idx = new QueryIndex("orgId");
+
+ idxs.add(idx);
+ }
+
+ entity.setIndexes(idxs);
+
+ return entity;
+ }
+
+ /**
+ * @param idxName Name index flag.
+ * @return Entity.
+ */
+ private QueryEntity organizationEntity(boolean idxName) {
+ QueryEntity entity = new QueryEntity();
+
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Organization.class.getName());
+
+ entity.addQueryField("name", String.class.getName(), null);
+
+ if (idxName) {
+ QueryIndex idx = new QueryIndex("name");
+
+ entity.setIndexes(F.asList(idx));
+ }
+
+ return entity;
+ }
+
+ /**
+ * @return Organization ids.
+ */
+ private List<Integer> putData1() {
+ total = 0;
+
+ Ignite client = grid(2);
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ IgniteCache<Object, Object> personCache = client.cache(PERSON_CACHE);
+ IgniteCache<Object, Object> orgCache = client.cache(ORG_CACHE);
+
+ AtomicInteger pKey = new AtomicInteger();
+ AtomicInteger orgKey = new AtomicInteger();
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ List<Integer> data = new ArrayList<>();
+
+ for (int i = 0; i < 5; i++) {
+ int orgId = keyForNode(aff, orgKey, node0);
+
+ orgCache.put(orgId, new Organization("obj-" + orgId));
+
+ for (int j = 0; j < i; j++) {
+ personCache.put(keyForNode(aff, pKey, node1), new Person(orgId, "obj-" + orgId));
+
+ total++;
+ }
+
+ data.add(orgId);
+ }
+
+ return data;
+ }
+
+ /**
+ * @param name Cache name.
+ * @return Configuration.
+ */
+ private CacheConfiguration cacheConfiguration(String name) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+ ccfg.setAtomicityMode(ATOMIC);
+ ccfg.setBackups(0);
+ ccfg.setMemoryMode(memMode);
+
+ return ccfg;
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ int orgId;
+
+ /** */
+ String name;
+
+ /**
+ * @param orgId Organization ID.
+ * @param name Name.
+ */
+ public Person(int orgId, String name) {
+ this.orgId = orgId;
+ this.name = name;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ /** */
+ String name;
+
+ /**
+ * @param name Name.
+ */
+ public Organization(String name) {
+ this.name = name;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinTest.java
new file mode 100644
index 0000000..ea3b141
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinTest.java
@@ -0,0 +1,316 @@
+/*
+ * 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;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Iterator;
+import java.util.List;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.query.QueryCursor;
+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.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.GridRandom;
+import org.apache.ignite.internal.util.typedef.internal.U;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+/**
+ */
+public class IgniteCacheDistributedJoinTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static Connection conn;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi spi = ((TcpDiscoverySpi)cfg.getDiscoverySpi());
+
+ spi.setIpFinder(IP_FINDER);
+
+ CacheConfiguration<Integer, A> ccfga = new CacheConfiguration<>();
+
+ ccfga.setName("a");
+ ccfga.setSqlSchema("A");
+ ccfga.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+ ccfga.setBackups(1);
+ ccfga.setCacheMode(CacheMode.PARTITIONED);
+ ccfga.setIndexedTypes(Integer.class, A.class);
+
+ CacheConfiguration<Integer, B> ccfgb = new CacheConfiguration<>();
+
+ ccfgb.setName("b");
+ ccfgb.setSqlSchema("B");
+ ccfgb.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+ ccfgb.setBackups(1);
+ ccfgb.setCacheMode(CacheMode.PARTITIONED);
+ ccfgb.setIndexedTypes(Integer.class, B.class);
+
+ CacheConfiguration<Integer, C> ccfgc = new CacheConfiguration<>();
+
+ ccfgc.setName("c");
+ ccfgc.setSqlSchema("C");
+ ccfgc.setAtomicityMode(CacheAtomicityMode.ATOMIC);
+ ccfgc.setBackups(1);
+ ccfgc.setCacheMode(CacheMode.PARTITIONED);
+ ccfgc.setIndexedTypes(Integer.class, C.class);
+
+ cfg.setCacheConfiguration(ccfga, ccfgb, ccfgc);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ startGridsMultiThreaded(4);
+
+ awaitPartitionMapExchange();
+
+ conn = DriverManager.getConnection("jdbc:h2:mem:");
+
+ Statement s = conn.createStatement();
+
+ s.execute("create schema a");
+ s.execute("create schema b");
+ s.execute("create schema c");
+
+ s.execute("create table a.a(a bigint, b bigint, c bigint)");
+ s.execute("create table b.b(a bigint, b bigint, c bigint)");
+ s.execute("create table c.c(a bigint, b bigint, c bigint)");
+
+ s.execute("create index on a.a(a)");
+ s.execute("create index on a.a(b)");
+ s.execute("create index on a.a(c)");
+
+ s.execute("create index on b.b(a)");
+ s.execute("create index on b.b(b)");
+ s.execute("create index on b.b(c)");
+
+ s.execute("create index on c.c(a)");
+ s.execute("create index on c.c(b)");
+ s.execute("create index on c.c(c)");
+
+ GridRandom rnd = new GridRandom();
+ Ignite ignite = ignite(0);
+
+ IgniteCache<Integer,A> a = ignite.cache("a");
+ IgniteCache<Integer,B> b = ignite.cache("b");
+ IgniteCache<Integer,C> c = ignite.cache("c");
+
+ for (int i = 0; i < 100; i++) {
+ a.put(i, insert(s, new A(rnd.nextInt(50), rnd.nextInt(100), rnd.nextInt(150))));
+ b.put(i, insert(s, new B(rnd.nextInt(100), rnd.nextInt(50), rnd.nextInt(150))));
+ c.put(i, insert(s, new C(rnd.nextInt(150), rnd.nextInt(100), rnd.nextInt(50))));
+ }
+
+ checkSameResult(s, a, "select a, count(*) from a group by a order by a");
+ checkSameResult(s, a, "select b, count(*) from a group by b order by b");
+ checkSameResult(s, a, "select c, count(*) from a group by c order by c");
+
+ checkSameResult(s, b, "select a, count(*) from b group by a order by a");
+ checkSameResult(s, b, "select b, count(*) from b group by b order by b");
+ checkSameResult(s, b, "select c, count(*) from b group by c order by c");
+
+ checkSameResult(s, c, "select a, count(*) from c group by a order by a");
+ checkSameResult(s, c, "select b, count(*) from c group by b order by b");
+ checkSameResult(s, c, "select c, count(*) from c group by c order by c");
+
+ s.close();
+ }
+
+ /**
+ * @param s Statement.
+ * @param c Cache.
+ * @param qry Query.
+ * @throws SQLException If failed.
+ */
+ private <Z extends X> void checkSameResult(Statement s, IgniteCache<Integer, Z> c, String qry) throws SQLException {
+ s.executeUpdate("SET SCHEMA " + c.getName());
+
+ try (
+ ResultSet rs1 = s.executeQuery(qry);
+ QueryCursor<List<?>> rs2 = c.query(new SqlFieldsQuery(qry).setDistributedJoins(true))
+ ) {
+ Iterator<List<?>> iter = rs2.iterator();
+
+ for (;;) {
+ if (!rs1.next()) {
+ assertFalse(iter.hasNext());
+
+ return;
+ }
+
+ assertTrue(iter.hasNext());
+
+ List<?> row = iter.next();
+
+ for (int i = 0; i < row.size(); i++)
+ assertEquals(rs1.getLong(i + 1), row.get(i));
+ }
+ }
+ }
+
+ /**
+ * @param s Statement.
+ * @param z Value.
+ * @return Value.
+ * @throws SQLException If failed.
+ */
+ private static <Z extends X> Z insert(Statement s, Z z) throws SQLException {
+ String tbl = z.getClass().getSimpleName();
+
+ tbl = tbl + "." + tbl;
+
+ String insert = "insert into " + tbl + " values(" + z.a + ", " + z.b + ", " + z.c + ")";
+
+ s.executeUpdate(insert);
+
+ return z;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoins() throws Exception {
+ Ignite ignite = ignite(0);
+
+ IgniteCache<Integer,A> a = ignite.cache("a");
+ IgniteCache<Integer,B> b = ignite.cache("b");
+ IgniteCache<Integer,C> c = ignite.cache("c");
+
+ Statement s = conn.createStatement();
+
+ checkSameResult(s, a, "select a.c, b.b, c.a from a.a, b.b, c.c where a.a = b.a and b.c = c.c order by a.c, b.b, c.a");
+ checkSameResult(s, b, "select a.a, b.c, c.b from a.a, b.b, c.c where a.b = b.b and b.a = c.a order by a.a, b.c, c.b");
+ checkSameResult(s, c, "select a.b, b.a, c.c from a.a, b.b, c.c where a.c = b.c and b.b = c.b order by a.b, b.a, c.c");
+
+ for (int i = 0; i < 150; i++) {
+ checkSameResult(s, a, "select a.c, b.b, c.a from a.a, b.b, c.c where " +
+ i + " = a.c and a.a = b.a and b.c = c.c order by a.c, b.b, c.a");
+ checkSameResult(s, b, "select a.a, b.c, c.b from a.a, b.b, c.c where " +
+ i + " = c.b and a.b = b.b and b.a = c.a order by a.a, b.c, c.b");
+ checkSameResult(s, c, "select a.b, b.a, c.c from a.a, b.b, c.c where " +
+ i + " = b.c and a.c = b.c and b.b = c.b order by a.b, b.a, c.c");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ U.closeQuiet(conn);
+ stopAllGrids();
+ }
+
+ /**
+ *
+ */
+ public static class X {
+ /** */
+ public long a;
+
+ /** */
+ public long b;
+
+ /** */
+ public long c;
+
+ /**
+ * @param a A.
+ * @param b B.
+ * @param c C.
+ */
+ public X(int a, int b, int c) {
+ this.a = a;
+ this.b = b;
+ this.c = c;
+ }
+
+ /** */
+ @QuerySqlField(index = true)
+ public long getA() {
+ return a;
+ }
+
+ /** */
+ @QuerySqlField(index = true)
+ public long getB() {
+ return b;
+ }
+
+ /** */
+ @QuerySqlField(index = true)
+ public long getC() {
+ return c;
+ }
+ }
+
+ /**
+ *
+ */
+ public static class A extends X {
+ /**
+ * @param a A.
+ * @param b B.
+ * @param c C.
+ */
+ public A(int a, int b, int c) {
+ super(a, b, c);
+ }
+ }
+
+ /**
+ *
+ */
+ public static class B extends X {
+ /**
+ * @param a A.
+ * @param b B.
+ * @param c C.
+ */
+ public B(int a, int b, int c) {
+ super(a, b, c);
+ }
+ }
+
+ /**
+ *
+ */
+ public static class C extends X {
+ /**
+ * @param a A.
+ * @param b B.
+ * @param c C.
+ */
+ public C(int a, int b, int c) {
+ super(a, b, c);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedCollocationTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedCollocationTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedCollocationTest.java
new file mode 100644
index 0000000..fa9032d
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedCollocationTest.java
@@ -0,0 +1,399 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.query.h2.sql.AbstractH2CompareQueryTest;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+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 static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheJoinPartitionedAndReplicatedCollocationTest extends AbstractH2CompareQueryTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String PERSON_CACHE = "person";
+
+ /** */
+ private static final String ACCOUNT_CACHE = "acc";
+
+ /** */
+ private boolean client;
+
+ /** */
+ private boolean h2DataInserted;
+
+ /** {@inheritDoc} */
+ @Override protected void setIndexedTypes(CacheConfiguration<?, ?> cc, CacheMode mode) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void initCacheAndDbData() throws Exception {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void checkAllDataEquals() throws Exception {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi spi = ((TcpDiscoverySpi)cfg.getDiscoverySpi());
+
+ spi.setIpFinder(IP_FINDER);
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /**
+ * @return Cache configuration.
+ */
+ private CacheConfiguration personCache() {
+ CacheConfiguration ccfg = configuration(PERSON_CACHE, 0);
+
+ // Person cache is replicated.
+ ccfg.setCacheMode(REPLICATED);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Person.class.getName());
+ entity.addQueryField("name", String.class.getName(), null);
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ return ccfg;
+ }
+
+ /**
+ * @param backups Number of backups.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration accountCache(int backups) {
+ CacheConfiguration ccfg = configuration(ACCOUNT_CACHE, backups);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Account.class.getName());
+ entity.addQueryField("personId", Integer.class.getName(), null);
+ entity.addQueryField("name", String.class.getName(), null);
+ entity.setIndexes(F.asList(new QueryIndex("personId")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ return ccfg;
+ }
+
+ /**
+ * @param name Cache name.
+ * @param backups Number of backups.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration configuration(String name, int backups) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+ ccfg.setAtomicityMode(ATOMIC);
+ ccfg.setBackups(backups);
+
+ return ccfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ client = true;
+
+ startGrid(SRVS);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Statement initializeH2Schema() throws SQLException {
+ Statement st = super.initializeH2Schema();
+
+ st.execute("CREATE SCHEMA \"person\"");
+ st.execute("CREATE SCHEMA \"acc\"");
+
+ st.execute("create table \"person\".PERSON" +
+ " (_key int not null," +
+ " _val other not null," +
+ " name varchar(255))");
+
+ st.execute("create table \"acc\".ACCOUNT" +
+ " (_key int not null," +
+ " _val other not null," +
+ " personId int," +
+ " name varchar(255))");
+
+ return st;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin() throws Exception {
+ Ignite client = grid(SRVS);
+
+ client.createCache(personCache());
+
+ checkJoin(0);
+
+ h2DataInserted = true;
+
+ checkJoin(1);
+
+ checkJoin(2);
+ }
+
+ /**
+ * @param accBackups Account cache backups.
+ * @throws Exception If failed.
+ */
+ private void checkJoin(int accBackups) throws Exception {
+ Ignite client = grid(SRVS);
+
+ IgniteCache<Object, Object> personCache = client.cache(PERSON_CACHE);
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ AtomicInteger pKey = new AtomicInteger(100_000);
+ AtomicInteger accKey = new AtomicInteger();
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ try {
+ IgniteCache<Object, Object> accCache = client.createCache(accountCache(accBackups));
+
+ Integer pKey1 = keyForNode(aff, pKey, node0); // No accounts.
+ insert(personCache, pKey1, new Person("p1"));
+
+ Integer pKey2 = keyForNode(aff, pKey, node0); // 1 collocated account.
+ insert(personCache, pKey2, new Person("p2"));
+ insert(accCache, keyForNode(aff, accKey, node0), new Account(pKey2, "a-p2"));
+
+ Integer pKey3 = keyForNode(aff, pKey, node0); // 1 non-collocated account.
+ insert(personCache, pKey3, new Person("p3"));
+ insert(accCache, keyForNode(aff, accKey, node1), new Account(pKey3, "a-p3"));
+
+ Integer pKey4 = keyForNode(aff, pKey, node0); // 1 collocated, 1 non-collocated account.
+ insert(personCache, pKey4, new Person("p4"));
+ insert(accCache, keyForNode(aff, accKey, node0), new Account(pKey4, "a-p4-1"));
+ insert(accCache, keyForNode(aff, accKey, node1), new Account(pKey4, "a-p4-2"));
+
+ Integer pKey5 = keyForNode(aff, pKey, node0); // 2 collocated accounts.
+ insert(personCache, pKey5, new Person("p5"));
+ insert(accCache, keyForNode(aff, accKey, node0), new Account(pKey5, "a-p5-1"));
+ insert(accCache, keyForNode(aff, accKey, node0), new Account(pKey5, "a-p5-1"));
+
+ Integer pKey6 = keyForNode(aff, pKey, node0); // 2 non-collocated accounts.
+ insert(personCache, pKey6, new Person("p6"));
+ insert(accCache, keyForNode(aff, accKey, node1), new Account(pKey6, "a-p5-1"));
+ insert(accCache, keyForNode(aff, accKey, node1), new Account(pKey6, "a-p5-1"));
+
+ Integer[] keys = {pKey1, pKey2, pKey3, pKey4, pKey5, pKey6};
+
+ for (int i = 0; i < keys.length; i++) {
+ log.info("Test key: " + i);
+
+ Integer key = keys[i];
+
+ checkQuery("select p._key, p.name, a.name " +
+ "from \"person\".Person p, \"acc\".Account a " +
+ "where p._key = a.personId and p._key=?", accCache, true, key);
+
+ checkQuery("select p._key, p.name, a.name " +
+ "from \"acc\".Account a, \"person\".Person p " +
+ "where p._key = a.personId and p._key=?", accCache, true, key);
+
+ checkQuery("select p._key, p.name, a.name " +
+ "from \"person\".Person p right outer join \"acc\".Account a " +
+ "on (p._key = a.personId) and p._key=?", accCache, true, key);
+
+ checkQuery("select p._key, p.name, a.name " +
+ "from \"acc\".Account a left outer join \"person\".Person p " +
+ "on (p._key = a.personId) and p._key=?", accCache, true, key);
+
+// checkQuery("select p._key, p.name, a.name " +
+// "from \"acc\".Account a right outer join \"person\".Person p " +
+// "on (p._key = a.personId) and p._key=?", accCache, true, key);
+//
+// checkQuery("select p._key, p.name, a.name " +
+// "from \"person\".Person p left outer join \"acc\".Account a " +
+// "on (p._key = a.personId) and p._key=?", accCache, true, key);
+ }
+ }
+ finally {
+ client.destroyCache(ACCOUNT_CACHE);
+
+ personCache.removeAll();
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @param key Key.
+ * @param p Person.
+ * @throws Exception If failed.
+ */
+ private void insert(IgniteCache<Object, Object> cache, int key, Person p) throws Exception {
+ cache.put(key, p);
+
+ if (h2DataInserted)
+ return;
+
+ try(PreparedStatement st = conn.prepareStatement("insert into \"person\".PERSON " +
+ "(_key, _val, name) values(?, ?, ?)")) {
+ st.setObject(1, key);
+ st.setObject(2, p);
+ st.setObject(3, p.name);
+
+ st.executeUpdate();
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @param key Key.
+ * @param a Account.
+ * @throws Exception If failed.
+ */
+ private void insert(IgniteCache<Object, Object> cache, int key, Account a) throws Exception {
+ cache.put(key, a);
+
+ if (h2DataInserted)
+ return;
+
+ try(PreparedStatement st = conn.prepareStatement("insert into \"acc\".ACCOUNT " +
+ "(_key, _val, personId, name) values(?, ?, ?, ?)")) {
+ st.setObject(1, key);
+ st.setObject(2, a);
+ st.setObject(3, a.personId);
+ st.setObject(4, a.name);
+
+ st.executeUpdate();
+ }
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @param args Arguments.
+ * @throws Exception If failed.
+ */
+ private void checkQuery(String sql,
+ IgniteCache<Object, Object> cache,
+ boolean enforceJoinOrder,
+ Object... args) throws Exception {
+ String plan = (String)cache.query(new SqlFieldsQuery("explain " + sql)
+ .setArgs(args)
+ .setDistributedJoins(true)
+ .setEnforceJoinOrder(enforceJoinOrder))
+ .getAll().get(0).get(0);
+
+ log.info("Plan: " + plan);
+
+ compareQueryRes0(cache, sql, true, enforceJoinOrder, args, Ordering.RANDOM);
+ }
+
+ /**
+ *
+ */
+ private static class Account implements Serializable {
+ /** */
+ int personId;
+
+ /** */
+ String name;
+
+ /**
+ * @param personId Person ID.
+ * @param name Name.
+ */
+ public Account(int personId, String name) {
+ this.personId = personId;
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Account.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ String name;
+
+ /**
+ * @param name Name.
+ */
+ public Person(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Person.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedTest.java
index 39c0cb5..1d528c9 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinPartitionedAndReplicatedTest.java
@@ -17,9 +17,6 @@
package org.apache.ignite.internal.processors.cache;
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.QueryEntity;
@@ -32,8 +29,15 @@ import org.apache.ignite.internal.util.typedef.internal.S;
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 org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import javax.cache.CacheException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+
import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
import static org.apache.ignite.cache.CacheMode.REPLICATED;
@@ -53,6 +57,9 @@ public class IgniteCacheJoinPartitionedAndReplicatedTest extends GridCommonAbstr
private static final String ORG_CACHE = "org";
/** */
+ private static final String ORG_CACHE_REPLICATED = "orgRepl";
+
+ /** */
private boolean client;
/** {@inheritDoc} */
@@ -95,6 +102,22 @@ public class IgniteCacheJoinPartitionedAndReplicatedTest extends GridCommonAbstr
ccfgs.add(ccfg);
}
+ {
+ CacheConfiguration ccfg = configuration(ORG_CACHE_REPLICATED);
+
+ ccfg.setCacheMode(REPLICATED);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Organization.class.getName());
+ entity.addQueryField("id", Integer.class.getName(), null);
+ entity.addQueryField("name", String.class.getName(), null);
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
cfg.setCacheConfiguration(ccfgs.toArray(new CacheConfiguration[ccfgs.size()]));
cfg.setClientMode(client);
@@ -144,10 +167,12 @@ public class IgniteCacheJoinPartitionedAndReplicatedTest extends GridCommonAbstr
IgniteCache<Object, Object> personCache = client.cache(PERSON_CACHE);
IgniteCache<Object, Object> orgCache = client.cache(ORG_CACHE);
+ IgniteCache<Object, Object> orgCacheRepl = client.cache(ORG_CACHE_REPLICATED);
List<Integer> keys = primaryKeys(ignite(0).cache(PERSON_CACHE), 3, 200_000);
orgCache.put(keys.get(0), new Organization(0, "org1"));
+ orgCacheRepl.put(keys.get(0), new Organization(0, "org1"));
personCache.put(keys.get(1), new Person(0, "p1"));
personCache.put(keys.get(2), new Person(0, "p2"));
@@ -160,12 +185,54 @@ public class IgniteCacheJoinPartitionedAndReplicatedTest extends GridCommonAbstr
"on (p.orgId = o.id)", orgCache, 2);
checkQuery("select o.name, p._key, p.name " +
- "from \"person\".Person p left join \"org\".Organization o " +
- "on (p.orgId = o.id)", orgCache, 2);
+ "from \"person\".Person p join \"orgRepl\".Organization o " +
+ "on (p.orgId = o.id)", orgCacheRepl, 2);
+
+ checkQuery("select o.name, p._key, p.name " +
+ "from \"orgRepl\".Organization o join \"person\".Person p " +
+ "on (p.orgId = o.id)", orgCacheRepl, 2);
+
+ checkQuery("select p.name from \"person\".Person p", ignite(0).cache(PERSON_CACHE), 2);
+ checkQuery("select p.name from \"person\".Person p", ignite(1).cache(PERSON_CACHE), 2);
+
+ for (int i = 0; i < 10; i++)
+ checkQuery("select p.name from \"person\".Person p", personCache, 2);
checkQuery("select o.name, p._key, p.name " +
"from \"org\".Organization o left join \"person\".Person p " +
"on (p.orgId = o.id)", orgCache, 2);
+
+ checkQuery("select o.name, p._key, p.name " +
+ "from \"person\".Person p left join \"orgRepl\".Organization o " +
+ "on (p.orgId = o.id)", orgCacheRepl, 2);
+
+ checkQuery("select o.name, p._key, p.name " +
+ "from \"orgRepl\".Organization o left join \"person\".Person p " +
+ "on (p.orgId = o.id)", orgCacheRepl, 2);
+
+ checkQueryFails("select o.name, p._key, p.name " +
+ "from \"person\".Person p left join \"org\".Organization o " +
+ "on (p.orgId = o.id)", personCache);
+
+ checkQueryFails("select o.name, p._key, p.name " +
+ "from \"org\".Organization o right join \"person\".Person p " +
+ "on (p.orgId = o.id)", personCache);
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ */
+ private void checkQueryFails(final String sql, final IgniteCache<Object, Object> cache) {
+ GridTestUtils.assertThrows(log, new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ cache.query(qry).getAll();
+
+ return null;
+ }
+ }, CacheException.class, null);
}
/**
@@ -233,6 +300,7 @@ public class IgniteCacheJoinPartitionedAndReplicatedTest extends GridCommonAbstr
int id;
/**
+ * @param id ID.
* @param name Name.
*/
public Organization(int id, String name) {
[35/50] [abbrv] ignite git commit: ignite-3300 Fixed issue with
partition value changing stored in KeyCacheObject.
Posted by vo...@apache.org.
ignite-3300 Fixed issue with partition value changing stored in KeyCacheObject.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a441bb9c
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a441bb9c
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a441bb9c
Branch: refs/heads/ignite-3553
Commit: a441bb9cc4ef07f28fbee3a78480c1ffbc68058f
Parents: 422c9a8
Author: sboikov <sb...@gridgain.com>
Authored: Wed Jul 27 09:19:12 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Wed Jul 27 09:19:12 2016 +0300
----------------------------------------------------------------------
.../internal/binary/BinaryObjectImpl.java | 11 +
.../affinity/GridAffinityProcessor.java | 117 +++++---
.../processors/cache/CacheObjectContext.java | 12 +
.../processors/cache/GridCacheAdapter.java | 8 +-
.../cache/GridCacheAffinityManager.java | 22 +-
.../processors/cache/GridCacheContext.java | 26 +-
.../processors/cache/GridCacheEntryInfo.java | 2 +-
.../processors/cache/KeyCacheObject.java | 7 +
.../processors/cache/KeyCacheObjectImpl.java | 8 +
.../cache/binary/CacheObjectBinaryContext.java | 10 +-
.../binary/CacheObjectBinaryProcessorImpl.java | 38 ++-
.../dht/atomic/GridDhtAtomicCache.java | 6 +-
.../dht/atomic/GridNearAtomicUpdateFuture.java | 4 +-
.../cacheobject/IgniteCacheObjectProcessor.java | 15 +-
.../IgniteCacheObjectProcessorImpl.java | 69 ++++-
.../datastreamer/DataStreamerImpl.java | 6 +-
.../affinity/AffinityClientNodeSelfTest.java | 73 ++++-
.../binary/BinaryMarshallerSelfTest.java | 7 +-
.../BinaryObjectBuilderAdditionalSelfTest.java | 46 ++-
.../cache/CacheGetEntryAbstractTest.java | 2 +-
.../expiry/IgniteCacheTtlCleanupSelfTest.java | 2 +-
.../CacheBinaryKeyConcurrentQueryTest.java | 298 +++++++++++++++++++
.../IgniteCacheWithIndexingTestSuite.java | 2 +
23 files changed, 621 insertions(+), 170 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
index ae110f1..7b42c03 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryObjectImpl.java
@@ -98,6 +98,17 @@ public final class BinaryObjectImpl extends BinaryObjectExImpl implements Extern
}
/** {@inheritDoc} */
+ @Override public KeyCacheObject copy(int part) {
+ if (this.part == part)
+ return this;
+
+ BinaryObjectImpl cp = new BinaryObjectImpl(ctx, arr, start);
+ cp.part = part;
+
+ return cp;
+ }
+
+ /** {@inheritDoc} */
@Override public int partition() {
return part;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java
index 0d3d36d..19e0842 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/affinity/GridAffinityProcessor.java
@@ -47,6 +47,7 @@ import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.KeyCacheObject;
import org.apache.ignite.internal.processors.timeout.GridTimeoutObjectAdapter;
import org.apache.ignite.internal.util.GridLeanMap;
import org.apache.ignite.internal.util.future.GridFinishedFuture;
@@ -144,6 +145,56 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
}
/**
+ * @param cacheName Cache name.
+ * @param key Key.
+ * @return Key partition.
+ * @throws IgniteCheckedException If failed.
+ */
+ public int partition(@Nullable String cacheName, Object key) throws IgniteCheckedException {
+ return partition(cacheName, key, null);
+ }
+
+ /**
+ * @param cacheName Cache name (needed only if {@code aff} is not provided.
+ * @param key Key.
+ * @param aff Affinity information.
+ * @return Key partition.
+ * @throws IgniteCheckedException If failed.
+ */
+ public int partition(@Nullable String cacheName,
+ Object key,
+ @Nullable AffinityInfo aff) throws IgniteCheckedException {
+ if (key instanceof KeyCacheObject) {
+ int part = ((KeyCacheObject)key).partition();
+
+ if (part >= 0)
+ return part;
+ }
+
+ return partition0(cacheName, key, aff);
+ }
+
+ /**
+ * @param cacheName Cache name (needed only if {@code aff} is not provided.
+ * @param key Key.
+ * @param aff Affinity.
+ * @return Key partition.
+ * @throws IgniteCheckedException If failed.
+ */
+ public int partition0(@Nullable String cacheName,
+ Object key,
+ @Nullable AffinityInfo aff) throws IgniteCheckedException {
+ if (aff == null) {
+ aff = affinityCache(cacheName, ctx.discovery().topologyVersionEx());
+
+ if (aff == null)
+ throw new IgniteCheckedException("Failed to get cache affinity.");
+ }
+
+ return aff.affFunc.partition(aff.affinityKey(key));
+ }
+
+ /**
* Maps keys to nodes for given cache.
*
* @param cacheName Cache name.
@@ -206,7 +257,9 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
if (affInfo == null)
return Collections.emptyList();
- return primaryAndBackups(affInfo, key);
+ int part = partition(cacheName, key, affInfo);
+
+ return affInfo.assignment.get(part);
}
/**
@@ -224,13 +277,10 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
AffinityInfo affInfo = affinityCache(cacheName, ctx.discovery().topologyVersionEx());
- if (affInfo == null || affInfo.mapper == null)
+ if (affInfo == null)
return null;
- if (key instanceof CacheObject)
- key = ((CacheObject)key).value(affInfo.cacheObjCtx, false);
-
- return affInfo.mapper.affinityKey(key);
+ return affInfo.affinityKey(key);
}
/**
@@ -484,10 +534,7 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
* @throws IgniteCheckedException In case of error.
*/
private <K> ClusterNode primary(AffinityInfo aff, K key) throws IgniteCheckedException {
- if (key instanceof CacheObject && !(key instanceof BinaryObject))
- key = ((CacheObject)key).value(aff.cacheObjCtx, false);
-
- int part = aff.affFunc.partition(aff.mapper.affinityKey(key));
+ int part = partition(null, key, aff);
Collection<ClusterNode> nodes = aff.assignment.get(part);
@@ -497,20 +544,6 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
return nodes.iterator().next();
}
- /**
- * @param aff Affinity function.
- * @param key Key to check.
- * @return Primary and backup nodes.
- */
- private <K> List<ClusterNode> primaryAndBackups(AffinityInfo aff, K key) {
- if (key instanceof CacheObject && !(key instanceof BinaryObject))
- key = ((CacheObject)key).value(aff.cacheObjCtx, false);
-
- int part = aff.affFunc.partition(aff.mapper.affinityKey(key));
-
- return aff.assignment.get(part);
- }
-
/** {@inheritDoc} */
@Override public void printMemoryStats() {
X.println(">>>");
@@ -551,6 +584,17 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
}
/**
+ * @param key Key.
+ * @return Affinity key.
+ */
+ private Object affinityKey(Object key) {
+ if (key instanceof CacheObject && !(key instanceof BinaryObject))
+ key = ((CacheObject)key).value(cacheObjCtx, false);
+
+ return mapper.affinityKey(key);
+ }
+
+ /**
* @return Cache affinity function.
*/
private AffinityFunction affinityFunction() {
@@ -564,13 +608,6 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
return assignment;
}
- /**
- * @return Key mapper.
- */
- private AffinityKeyMapper keyMapper() {
- return mapper;
- }
-
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(AffinityInfo.class, this);
@@ -658,7 +695,7 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
ctx.gateway().readLock();
try {
- return cache().affinityFunction().partition(key);
+ return partition0(cacheName, key, cache());
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
@@ -769,10 +806,7 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
ctx.gateway().readLock();
try {
- if (key instanceof CacheObject)
- key = ((CacheObject)key).value(cache().cacheObjCtx, false);
-
- return cache().keyMapper().affinityKey(key);
+ return cache().affinityKey(key);
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
@@ -828,7 +862,9 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
ctx.gateway().readLock();
try {
- return cache().assignment().get(partition(key));
+ AffinityInfo aff = cache();
+
+ return aff.assignment().get(GridAffinityProcessor.this.partition(cacheName, key, aff));
}
catch (IgniteCheckedException e) {
throw new IgniteException(e);
@@ -861,12 +897,17 @@ public class GridAffinityProcessor extends GridProcessorAdapter {
Map<Integer, ClusterNode> map = new HashMap<>();
if (!F.isEmpty(parts)) {
+ AffinityInfo aff = cache();
+
for (int p : parts)
- map.put(p, mapPartitionToNode(p));
+ map.put(p, F.first(aff.assignment().get(p)));
}
return map;
}
+ catch (IgniteCheckedException e) {
+ throw new IgniteException(e);
+ }
finally {
ctx.gateway().readUnlock();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
index d7fdb83..c4203ef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/CacheObjectContext.java
@@ -41,6 +41,9 @@ import org.apache.ignite.internal.util.typedef.F;
private IgniteCacheObjectProcessor proc;
/** */
+ private String cacheName;
+
+ /** */
private AffinityKeyMapper dfltAffMapper;
/** */
@@ -63,11 +66,13 @@ import org.apache.ignite.internal.util.typedef.F;
* @param addDepInfo {@code true} if deployment info should be associated with the objects of this cache.
*/
public CacheObjectContext(GridKernalContext kernalCtx,
+ String cacheName,
AffinityKeyMapper dfltAffMapper,
boolean cpyOnGet,
boolean storeVal,
boolean addDepInfo) {
this.kernalCtx = kernalCtx;
+ this.cacheName = cacheName;
this.dfltAffMapper = dfltAffMapper;
this.cpyOnGet = cpyOnGet;
this.storeVal = storeVal;
@@ -78,6 +83,13 @@ import org.apache.ignite.internal.util.typedef.F;
}
/**
+ * @return Cache name.
+ */
+ public String cacheName() {
+ return cacheName;
+ }
+
+ /**
* @return {@code True} if peer class loading is enabled.
*/
public boolean p2pEnabled() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
index 90669e0..1ac94a4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAdapter.java
@@ -1387,15 +1387,15 @@ public abstract class GridCacheAdapter<K, V> implements IgniteInternalCache<K, V
long start = statsEnabled ? System.nanoTime() : 0L;
- boolean keeyBinary = ctx.keepBinary();
+ boolean keepBinary = ctx.keepBinary();
- if (keeyBinary)
+ if (keepBinary)
key = (K)ctx.toCacheKeyObject(key);
- V val = get(key, !keeyBinary, false);
+ V val = get(key, !keepBinary, false);
if (ctx.config().getInterceptor() != null) {
- key = keeyBinary ? (K) ctx.unwrapBinaryIfNeeded(key, true, false) : key;
+ key = keepBinary ? (K) ctx.unwrapBinaryIfNeeded(key, true, false) : key;
val = (V)ctx.config().getInterceptor().onGet(key, val);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
index e0e8031..98c7682 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
@@ -187,34 +187,36 @@ public class GridCacheAffinityManager extends GridCacheManagerAdapter {
}
/**
+ * @param key Key.
+ * @return Partition.
+ */
+ public int partition(Object key) {
+ return partition(key, true);
+ }
+
+ /**
* NOTE: Use this method always when you need to calculate partition id for
* a key provided by user. It's required since we should apply affinity mapper
* logic in order to find a key that will eventually be passed to affinity function.
*
* @param key Key.
+ * @param useKeyPart If {@code true} can use pre-calculated partition stored in KeyCacheObject.
* @return Partition.
*/
- public int partition(Object key) {
+ public int partition(Object key, boolean useKeyPart) {
GridAffinityAssignmentCache aff0 = aff;
if (aff0 == null)
throw new IgniteException(FAILED_TO_FIND_CACHE_ERR_MSG + cctx.name());
- boolean keyObj = key instanceof KeyCacheObject;
-
- if (keyObj) {
+ if (useKeyPart && (key instanceof KeyCacheObject)) {
int part = ((KeyCacheObject)key).partition();
if (part != -1)
return part;
}
- int p = affFunction.partition(affinityKey(key));
-
- if (keyObj)
- ((KeyCacheObject)key).partition(p);
-
- return p;
+ return affFunction.partition(affinityKey(key));
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
index fec43d0..e0ecf1c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
@@ -1807,20 +1807,9 @@ public class GridCacheContext<K, V> implements Externalizable {
* @return Cache key object.
*/
public KeyCacheObject toCacheKeyObject(Object obj) {
- return toCacheKeyObject(obj, false);
- }
-
- /**
- * @param obj Object.
- * @return Cache key object.
- */
- public KeyCacheObject toCacheKeyObject(Object obj, boolean includePartition) {
assert validObjectForCache(obj) : obj;
- if (includePartition)
- return cacheObjects().toCacheKeyObject(cacheObjCtx, obj, true, affinity().partition(obj));
- else
- return cacheObjects().toCacheKeyObject(cacheObjCtx, obj, true);
+ return cacheObjects().toCacheKeyObject(cacheObjCtx, this, obj, true);
}
/**
@@ -1841,7 +1830,7 @@ public class GridCacheContext<K, V> implements Externalizable {
public KeyCacheObject toCacheKeyObject(byte[] bytes) throws IgniteCheckedException {
Object obj = ctx.cacheObjects().unmarshal(cacheObjCtx, bytes, deploy().localLoader());
- return cacheObjects().toCacheKeyObject(cacheObjCtx, obj, false);
+ return cacheObjects().toCacheKeyObject(cacheObjCtx, this, obj, false);
}
/**
@@ -1989,21 +1978,12 @@ public class GridCacheContext<K, V> implements Externalizable {
* @return Read-only collection of KeyCacheObject instances.
*/
public Collection<KeyCacheObject> cacheKeysView(Collection<?> keys) {
- return cacheKeysView(keys, false);
- }
-
- /**
- * @param keys Keys.
- * @param includePartition Include partition.
- * @return Read-only collection of KeyCacheObject instances.
- */
- public Collection<KeyCacheObject> cacheKeysView(Collection<?> keys, final boolean includePartition) {
return F.viewReadOnly(keys, new C1<Object, KeyCacheObject>() {
@Override public KeyCacheObject apply(Object key) {
if (key == null)
throw new NullPointerException("Null key.");
- return toCacheKeyObject(key, includePartition);
+ return toCacheKeyObject(key);
}
});
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
index c42e788..f281227 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheEntryInfo.java
@@ -407,7 +407,7 @@ public class GridCacheEntryInfo implements Message {
Object key0 = ctx.cacheObjects().unmarshal(cacheObjCtx, keyBytes, clsLdr);
- key = ctx.cacheObjects().toCacheKeyObject(cacheObjCtx, key0, false);
+ key = ctx.cacheObjects().toCacheKeyObject(cacheObjCtx, ctx, key0, false);
}
else
key.finishUnmarshal(ctx.cacheObjectContext(), clsLdr);
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObject.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObject.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObject.java
index ffb846c..21b1f89 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObject.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObject.java
@@ -38,7 +38,14 @@ public interface KeyCacheObject extends CacheObject {
/**
* Sets partition ID for this key.
+ *
* @param part Partition ID.
*/
public void partition(int part);
+
+ /**
+ * @param part Partition ID.
+ * @return Copy of this object with given partition set.
+ */
+ public KeyCacheObject copy(int part);
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObjectImpl.java
index 35e681c..146e554 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/KeyCacheObjectImpl.java
@@ -61,6 +61,14 @@ public class KeyCacheObjectImpl extends CacheObjectAdapter implements KeyCacheOb
}
/** {@inheritDoc} */
+ @Override public KeyCacheObject copy(int part) {
+ if (this.part == part)
+ return this;
+
+ return new KeyCacheObjectImpl(val, valBytes, part);
+ }
+
+ /** {@inheritDoc} */
@Override public int partition() {
return part;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryContext.java
index ec01f48..26c713c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryContext.java
@@ -31,18 +31,24 @@ public class CacheObjectBinaryContext extends CacheObjectContext {
/**
* @param kernalCtx Kernal context.
+ * @param cacheName Cache name.
* @param binaryEnabled Binary enabled flag.
* @param cpyOnGet Copy on get flag.
* @param storeVal {@code True} if should store unmarshalled value in cache.
* @param depEnabled {@code true} if deployment is enabled for the given cache.
*/
public CacheObjectBinaryContext(GridKernalContext kernalCtx,
+ String cacheName,
boolean cpyOnGet,
boolean storeVal,
boolean binaryEnabled,
boolean depEnabled) {
- super(kernalCtx, binaryEnabled ? new CacheDefaultBinaryAffinityKeyMapper() :
- new GridCacheDefaultAffinityKeyMapper(), cpyOnGet, storeVal, depEnabled);
+ super(kernalCtx,
+ cacheName,
+ binaryEnabled ? new CacheDefaultBinaryAffinityKeyMapper() : new GridCacheDefaultAffinityKeyMapper(),
+ cpyOnGet,
+ storeVal,
+ depEnabled);
this.binaryEnabled = binaryEnabled;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
index f4d1d6e..3ab01e7 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
@@ -736,6 +736,7 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
CacheObjectContext ctx0 = super.contextForCache(cfg);
CacheObjectContext res = new CacheObjectBinaryContext(ctx,
+ cfg.getName(),
ctx0.copyOnGet(),
ctx0.storeValue(),
binaryEnabled,
@@ -768,43 +769,38 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
}
/** {@inheritDoc} */
- @Override public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, Object obj, boolean userObj) {
- return toCacheKeyObject(ctx, obj, userObj, -1);
- }
-
- /** {@inheritDoc} */
@Override public KeyCacheObject toCacheKeyObject(
CacheObjectContext ctx,
+ @Nullable GridCacheContext cctx,
Object obj,
- boolean userObj,
- int partition
+ boolean userObj
) {
if (!((CacheObjectBinaryContext)ctx).binaryEnabled())
- return super.toCacheKeyObject(ctx, obj, userObj, partition);
+ return super.toCacheKeyObject(ctx, cctx, obj, userObj);
if (obj instanceof KeyCacheObject) {
- if (obj instanceof BinaryObjectImpl) {
+ KeyCacheObject key = (KeyCacheObject)obj;
+
+ if (key instanceof BinaryObjectImpl) {
// Need to create a copy because the key can be reused at the application layer after that (IGNITE-3505).
- BinaryObjectImpl bObj = (BinaryObjectImpl)obj;
- obj = new BinaryObjectImpl(bObj.context(), bObj.array(), bObj.start());
+ key = key.copy(partition(ctx, cctx, key));
}
+ else if (key.partition() == -1)
+ // Assume others KeyCacheObjects can not be reused for another cache.
+ key.partition(partition(ctx, cctx, key));
- ((KeyCacheObject)obj).partition(partition);
-
- return (KeyCacheObject)obj;
+ return key;
}
- if (((CacheObjectBinaryContext)ctx).binaryEnabled()) {
- obj = toBinary(obj);
+ obj = toBinary(obj);
- if (obj instanceof KeyCacheObject) {
- ((KeyCacheObject)obj).partition(partition);
+ if (obj instanceof BinaryObjectImpl) {
+ ((BinaryObjectImpl)obj).partition(partition(ctx, cctx, obj));
- return (KeyCacheObject)obj;
- }
+ return (KeyCacheObject)obj;
}
- return toCacheKeyObject0(obj, userObj, partition);
+ return toCacheKeyObject0(ctx, cctx, obj, userObj);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
index 561c6c6..3616082 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridDhtAtomicCache.java
@@ -344,7 +344,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
final boolean skipStore = opCtx != null && opCtx.skipStore();
try {
- return getAsync0(ctx.toCacheKeyObject(key, true),
+ return getAsync0(ctx.toCacheKeyObject(key),
!ctx.config().isReadFromBackup(),
subjId,
taskName,
@@ -390,7 +390,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
return asyncOp(new CO<IgniteInternalFuture<V>>() {
@Override public IgniteInternalFuture<V> apply() {
- return getAsync0(ctx.toCacheKeyObject(key, true),
+ return getAsync0(ctx.toCacheKeyObject(key),
forcePrimary,
subjId0,
taskName,
@@ -436,7 +436,7 @@ public class GridDhtAtomicCache<K, V> extends GridDhtCacheAdapter<K, V> {
return asyncOp(new CO<IgniteInternalFuture<Map<K, V>>>() {
@Override public IgniteInternalFuture<Map<K, V>> apply() {
- return getAllAsync0(ctx.cacheKeysView(keys, true),
+ return getAllAsync0(ctx.cacheKeysView(keys),
forcePrimary,
subjId0,
taskName,
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
index b2f2704..0d88ef8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/atomic/GridNearAtomicUpdateFuture.java
@@ -883,7 +883,7 @@ public class GridNearAtomicUpdateFuture extends GridNearAtomicAbstractUpdateFutu
if (val == null && op != GridCacheOperation.DELETE)
continue;
- KeyCacheObject cacheKey = cctx.toCacheKeyObject(key, true);
+ KeyCacheObject cacheKey = cctx.toCacheKeyObject(key);
if (remapKeys != null && !remapKeys.contains(cacheKey))
continue;
@@ -1000,7 +1000,7 @@ public class GridNearAtomicUpdateFuture extends GridNearAtomicAbstractUpdateFutu
if (val == null && op != GridCacheOperation.DELETE)
throw new NullPointerException("Null value.");
- KeyCacheObject cacheKey = cctx.toCacheKeyObject(key, true);
+ KeyCacheObject cacheKey = cctx.toCacheKeyObject(key);
if (op != TRANSFORM)
val = cctx.toCacheObject(val);
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
index c488b3f..5ca3da8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
@@ -133,23 +133,14 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
public CacheObjectContext contextForCache(CacheConfiguration ccfg) throws IgniteCheckedException;
/**
- * @param ctx Cache context.
- * @param obj Key value.
- * @param userObj If {@code true} then given object is object provided by user and should be copied
- * before stored in cache.
- * @return Cache key object.
- */
- public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, Object obj, boolean userObj);
-
- /**
- * @param ctx Cache context.
+ * @param ctx Cache objects context.
+ * @param cctx Cache context if cache is available.
* @param obj Key value.
* @param userObj If {@code true} then given object is object provided by user and should be copied
* before stored in cache.
- * @param partition ID of partition this key belongs to.
* @return Cache key object.
*/
- public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, Object obj, boolean userObj, int partition);
+ public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, @Nullable GridCacheContext cctx, Object obj, boolean userObj);
/**
* @param ctx Cache context.
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
index f62ce36..78a1838 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
@@ -113,18 +113,21 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
}
/** {@inheritDoc} */
- @Override @Nullable public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, Object obj, boolean userObj) {
- return toCacheKeyObject(ctx, obj, userObj, -1);
- }
-
- /** {@inheritDoc} */
- @Override public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx, Object obj, boolean userObj, int partition) {
+ @Override public KeyCacheObject toCacheKeyObject(CacheObjectContext ctx,
+ @Nullable GridCacheContext cctx,
+ Object obj,
+ boolean userObj) {
if (obj instanceof KeyCacheObject) {
- ((KeyCacheObject)obj).partition(partition);
+ KeyCacheObject key = (KeyCacheObject)obj;
+
+ if (key.partition() == -1)
+ // Assume all KeyCacheObjects except BinaryObject can not be reused for another cache.
+ key.partition(partition(ctx, cctx, key));
+
return (KeyCacheObject)obj;
}
- return toCacheKeyObject0(obj, userObj, partition);
+ return toCacheKeyObject0(ctx, cctx, obj, userObj);
}
/**
@@ -134,11 +137,16 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
* @return Key cache object.
*/
@SuppressWarnings("ExternalizableWithoutPublicNoArgConstructor")
- protected KeyCacheObject toCacheKeyObject0(Object obj, boolean userObj, int partititon) {
+ protected KeyCacheObject toCacheKeyObject0(CacheObjectContext ctx,
+ @Nullable GridCacheContext cctx,
+ Object obj,
+ boolean userObj) {
+ int part = partition(ctx, cctx, obj);
+
if (!userObj)
- return new KeyCacheObjectImpl(obj, null, partititon);
+ return new KeyCacheObjectImpl(obj, null, part);
- return new UserKeyCacheObjectImpl(obj, partititon);
+ return new UserKeyCacheObjectImpl(obj, part);
}
/** {@inheritDoc} */
@@ -212,6 +220,25 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
return new UserCacheObjectImpl(obj, null);
}
+ /**
+ * @param ctx Cache objects context.
+ * @param cctx Cache context.
+ * @param obj Object.
+ * @return Object partition.
+ */
+ protected final int partition(CacheObjectContext ctx, @Nullable GridCacheContext cctx, Object obj) {
+ try {
+ return cctx != null ?
+ cctx.affinity().partition(obj, false) :
+ ctx.kernalContext().affinity().partition0(ctx.cacheName(), obj, null);
+ }
+ catch (IgniteCheckedException e) {
+ U.error(log, "Failed to get partition");
+
+ return -1;
+ }
+ }
+
/** {@inheritDoc} */
@Override public CacheObjectContext contextForCache(CacheConfiguration ccfg) throws IgniteCheckedException {
assert ccfg != null;
@@ -223,6 +250,7 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
!ccfg.isCopyOnRead();
CacheObjectContext res = new CacheObjectContext(ctx,
+ ccfg.getName(),
ccfg.getAffinityMapper() != null ? ccfg.getAffinityMapper() : new GridCacheDefaultAffinityKeyMapper(),
ccfg.isCopyOnRead() && memMode != OFFHEAP_VALUES,
storeVal,
@@ -309,8 +337,23 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
/**
* @param key Key.
*/
- UserKeyCacheObjectImpl(Object key, int partition) {
- super(key, null, partition);
+ UserKeyCacheObjectImpl(Object key, int part) {
+ super(key, null, part);
+ }
+
+ /**
+ * @param key Key.
+ */
+ UserKeyCacheObjectImpl(Object key, byte[] valBytes, int part) {
+ super(key, valBytes, part);
+ }
+
+ /** {@inheritDoc} */
+ @Override public KeyCacheObject copy(int part) {
+ if (this.partition() == part)
+ return this;
+
+ return new UserKeyCacheObjectImpl(val, valBytes, part);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
index 21df559..e565cba 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastreamer/DataStreamerImpl.java
@@ -519,12 +519,12 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
keys = new GridConcurrentHashSet<>(entries.size(), U.capacity(entries.size()), 1);
for (Map.Entry<K, V> entry : entries)
- keys.add(cacheObjProc.toCacheKeyObject(cacheObjCtx, entry.getKey(), true));
+ keys.add(cacheObjProc.toCacheKeyObject(cacheObjCtx, null, entry.getKey(), true));
}
Collection<? extends DataStreamerEntry> entries0 = F.viewReadOnly(entries, new C1<Entry<K, V>, DataStreamerEntry>() {
@Override public DataStreamerEntry apply(Entry<K, V> e) {
- KeyCacheObject key = cacheObjProc.toCacheKeyObject(cacheObjCtx, e.getKey(), true);
+ KeyCacheObject key = cacheObjProc.toCacheKeyObject(cacheObjCtx, null, e.getKey(), true);
CacheObject val = cacheObjProc.toCacheObject(cacheObjCtx, e.getValue(), true);
return new DataStreamerEntry(key, val);
@@ -619,7 +619,7 @@ public class DataStreamerImpl<K, V> implements IgniteDataStreamer<K, V>, Delayed
else
checkSecurityPermission(SecurityPermission.CACHE_PUT);
- KeyCacheObject key0 = cacheObjProc.toCacheKeyObject(cacheObjCtx, key, true);
+ KeyCacheObject key0 = cacheObjProc.toCacheKeyObject(cacheObjCtx, null, key, true);
CacheObject val0 = cacheObjProc.toCacheObject(cacheObjCtx, val, true);
return addDataInternal(Collections.singleton(new DataStreamerEntry(key0, val0)));
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/test/java/org/apache/ignite/cache/affinity/AffinityClientNodeSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/cache/affinity/AffinityClientNodeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/cache/affinity/AffinityClientNodeSelfTest.java
index 47b01f4..fc50541 100644
--- a/modules/core/src/test/java/org/apache/ignite/cache/affinity/AffinityClientNodeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/cache/affinity/AffinityClientNodeSelfTest.java
@@ -57,15 +57,15 @@ public class AffinityClientNodeSelfTest extends GridCommonAbstractTest {
/** */
private static final String CACHE4 = "cache4";
+ /** */
+ private static final String CACHE5 = "cache5";
+
/** {@inheritDoc} */
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(gridName);
((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
- if (gridName.equals(getTestGridName(NODE_CNT - 1)))
- cfg.setClientMode(true);
-
CacheConfiguration ccfg1 = new CacheConfiguration();
ccfg1.setBackups(1);
@@ -92,7 +92,18 @@ public class AffinityClientNodeSelfTest extends GridCommonAbstractTest {
ccfg4.setName(CACHE4);
ccfg4.setNodeFilter(new TestNodesFilter());
- cfg.setCacheConfiguration(ccfg1, ccfg2, ccfg3, ccfg4);
+ CacheConfiguration ccfg5 = new CacheConfiguration();
+
+ ccfg5.setBackups(1);
+ ccfg5.setName(CACHE5);
+
+ if (gridName.equals(getTestGridName(NODE_CNT - 1))) {
+ cfg.setClientMode(true);
+
+ cfg.setCacheConfiguration(ccfg5);
+ }
+ else
+ cfg.setCacheConfiguration(ccfg1, ccfg2, ccfg3, ccfg4);
return cfg;
}
@@ -123,6 +134,8 @@ public class AffinityClientNodeSelfTest extends GridCommonAbstractTest {
checkCache(CACHE4, 3);
+ checkCache(CACHE5, 2);
+
Ignite client = ignite(NODE_CNT - 1);
CacheConfiguration ccfg = new CacheConfiguration();
@@ -157,6 +170,8 @@ public class AffinityClientNodeSelfTest extends GridCommonAbstractTest {
private void checkCache(String cacheName, int expNodes) {
log.info("Test cache: " + cacheName);
+ Affinity<Object> aff0 = ignite(0).affinity(cacheName);
+
Ignite client = ignite(NODE_CNT - 1);
assertTrue(client.configuration().isClientMode());
@@ -166,14 +181,22 @@ public class AffinityClientNodeSelfTest extends GridCommonAbstractTest {
for (int i = 0; i < NODE_CNT; i++) {
Ignite ignite = ignite(i);
- Affinity<Integer> aff = ignite.affinity(cacheName);
+ Affinity<Object> aff = ignite.affinity(cacheName);
for (int part = 0; part < aff.partitions(); part++) {
Collection<ClusterNode> nodes = aff.mapPartitionToPrimaryAndBackups(part);
assertEquals(expNodes, nodes.size());
+ assertEquals(aff0.mapPartitionToPrimaryAndBackups(part), nodes);
assertFalse(nodes.contains(clientNode));
+
+ assertEquals(aff0.partition(part), aff.partition(part));
+
+ TestKey key = new TestKey(part, part + 1);
+
+ assertEquals(aff0.partition(key), aff.partition(key));
+ assertEquals(aff0.mapKeyToPrimaryAndBackups(key), aff.mapKeyToPrimaryAndBackups(key));
}
}
}
@@ -181,6 +204,46 @@ public class AffinityClientNodeSelfTest extends GridCommonAbstractTest {
/**
*
*/
+ static class TestKey {
+ /** */
+ private int id;
+
+ /** */
+ @AffinityKeyMapped
+ private int affId;
+
+ /**
+ * @param id ID.
+ * @param affId Affinity ID.
+ */
+ public TestKey(int id, int affId) {
+ this.id = id;
+ this.affId = affId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TestKey testKey = (TestKey)o;
+
+ return id == testKey.id;
+
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return id;
+ }
+ }
+
+ /**
+ *
+ */
private static class TestNodesFilter implements IgnitePredicate<ClusterNode> {
/** {@inheritDoc} */
@Override public boolean apply(ClusterNode clusterNode) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
index 1285db7..f4c1bf7 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryMarshallerSelfTest.java
@@ -26,7 +26,6 @@ import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.math.BigDecimal;
import java.math.BigInteger;
@@ -90,13 +89,11 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
-import static org.apache.ignite.IgniteSystemProperties.IGNITE_BINARY_MARSHALLER_USE_STRING_SERIALIZATION_VER_2;
+import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.ignite.internal.binary.streams.BinaryMemoryAllocator.INSTANCE;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertNotEquals;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
/**
* Binary marshaller tests.
*/
@@ -2401,7 +2398,7 @@ public class BinaryMarshallerSelfTest extends GridCommonAbstractTest {
BinaryObjectImpl po = marshal(simpleObject(), marsh);
- CacheObjectContext coCtx = new CacheObjectContext(newContext(), null, false, true, false);
+ CacheObjectContext coCtx = new CacheObjectContext(newContext(), null, null, false, true, false);
assert po.value(coCtx, false) == po.value(coCtx, false);
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
index be2ce9b..f999ad3 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/binary/BinaryObjectBuilderAdditionalSelfTest.java
@@ -21,6 +21,26 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.sql.Timestamp;
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.UUID;
import junit.framework.TestCase;
import org.apache.ignite.IgniteBinary;
import org.apache.ignite.IgniteCache;
@@ -29,9 +49,6 @@ import org.apache.ignite.binary.BinaryObject;
import org.apache.ignite.binary.BinaryObjectBuilder;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.binary.BinaryType;
-import org.apache.ignite.cache.CacheAtomicityMode;
-import org.apache.ignite.cache.CacheMode;
-import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.configuration.BinaryConfiguration;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
@@ -46,27 +63,6 @@ import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Assert;
-import java.lang.reflect.Field;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.sql.Timestamp;
-import java.util.AbstractMap;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-
import static org.apache.ignite.cache.CacheMode.PARTITIONED;
import static org.apache.ignite.cache.CacheMode.REPLICATED;
@@ -1497,7 +1493,5 @@ public class BinaryObjectBuilderAdditionalSelfTest extends GridCommonAbstractTes
assert OBJ.equals(binaryObj.type().fieldTypeName("asListHint"));
assert OBJ.equals(binaryObj.type().fieldTypeName("asSetHint"));
assert OBJ.equals(binaryObj.type().fieldTypeName("asMapHint"));
-
}
-
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheGetEntryAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheGetEntryAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheGetEntryAbstractTest.java
index c0ba42c..34480a2 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheGetEntryAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/CacheGetEntryAbstractTest.java
@@ -463,7 +463,7 @@ public abstract class CacheGetEntryAbstractTest extends GridCacheAbstractSelfTes
CacheObjectContext cacheObjCtx = cacheAdapter.context().cacheObjectContext();
GridCacheMapEntry mapEntry = cacheAdapter.map().getEntry(cacheObjects.toCacheKeyObject(
- cacheObjCtx, e.getKey(), true));
+ cacheObjCtx, null, e.getKey(), true));
assertNotNull("No entry for key: " + e.getKey(), mapEntry);
assertEquals(mapEntry.version(), e.version());
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheTtlCleanupSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheTtlCleanupSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheTtlCleanupSelfTest.java
index e166acb..42027e4 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheTtlCleanupSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/expiry/IgniteCacheTtlCleanupSelfTest.java
@@ -82,6 +82,6 @@ public class IgniteCacheTtlCleanupSelfTest extends GridCacheAbstractSelfTest {
CacheObjectContext cacheObjCtx = cacheAdapter.context().cacheObjectContext();
for (int i = 0; i < 100; i++)
- assertNull(cacheAdapter.map().getEntry(cacheObjects.toCacheKeyObject(cacheObjCtx, i, true)));
+ assertNull(cacheAdapter.map().getEntry(cacheObjects.toCacheKeyObject(cacheObjCtx, null, i, true)));
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheBinaryKeyConcurrentQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheBinaryKeyConcurrentQueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheBinaryKeyConcurrentQueryTest.java
new file mode 100644
index 0000000..e2de281
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheBinaryKeyConcurrentQueryTest.java
@@ -0,0 +1,298 @@
+/*
+ * 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;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.Cache;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheEntry;
+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.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.typedef.F;
+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 org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+@SuppressWarnings("unchecked")
+public class CacheBinaryKeyConcurrentQueryTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final int NODES = 3;
+
+ /** */
+ private static final int KEYS = 1000;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(ipFinder);
+
+ cfg.setMarshaller(null);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(NODES);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testPutAndQueries() throws Exception {
+ Ignite ignite = ignite(0);
+
+ IgniteCache cache1 = ignite.createCache(cacheConfiguration("cache1", ATOMIC));
+ IgniteCache cache2 = ignite.createCache(cacheConfiguration("cache2", TRANSACTIONAL));
+
+ insertData(ignite, cache1.getName());
+ insertData(ignite, cache2.getName());
+
+ IgniteInternalFuture<?> fut1 = startUpdate(cache1.getName());
+ IgniteInternalFuture<?> fut2 = startUpdate(cache2.getName());
+
+ fut1.get();
+ fut2.get();
+ }
+
+ /**
+ * @param cacheName Cache name.
+ * @return Future.
+ */
+ private IgniteInternalFuture<?> startUpdate(final String cacheName) {
+ final long stopTime = System.currentTimeMillis() + 30_000;
+
+ final AtomicInteger idx = new AtomicInteger();
+
+ return GridTestUtils.runMultiThreadedAsync(new Callable<Object>() {
+ @Override public Void call() {
+ ThreadLocalRandom rnd = ThreadLocalRandom.current();
+
+ IgniteCache cache = ignite(idx.getAndIncrement() % NODES).cache(cacheName).withKeepBinary();
+
+ while (System.currentTimeMillis() < stopTime) {
+ switch (rnd.nextInt(5)) {
+ case 0: {
+ TestKey key = new TestKey(rnd.nextInt(KEYS));
+
+ CacheEntry e = cache.getEntry(key);
+
+ assertNotNull(e);
+ assertTrue(e.getKey() instanceof BinaryObject);
+
+ cache.put(e.getKey(), new TestValue(rnd.nextInt(KEYS)));
+
+ break;
+ }
+
+ case 1: {
+ Iterator<Cache.Entry> it = cache.iterator();
+
+ for (int i = 0; i < 100 && it.hasNext(); i++) {
+ Cache.Entry e = it.next();
+
+ assertTrue(e.getKey() instanceof BinaryObject);
+
+ cache.put(e.getKey(), new TestValue(rnd.nextInt(KEYS)));
+ }
+
+ break;
+ }
+
+ case 2: {
+ SqlFieldsQuery qry = new SqlFieldsQuery("select _key " +
+ "from \"" + cache.getName() + "\".TestValue where id=?");
+
+ qry.setArgs(rnd.nextInt(KEYS));
+
+ List<List> res = cache.query(qry).getAll();
+
+ assertEquals(1, res.size());
+
+ BinaryObject key = (BinaryObject)res.get(0).get(0);
+
+ cache.put(key, new TestValue(rnd.nextInt(KEYS)));
+
+ break;
+ }
+
+ case 3: {
+ SqlQuery qry = new SqlQuery("TestValue", "id=?");
+
+ qry.setArgs(rnd.nextInt(KEYS));
+
+ List<Cache.Entry> res = cache.query(qry).getAll();
+
+ assertEquals(1, res.size());
+
+ break;
+ }
+
+ case 4: {
+ SqlQuery qry = new SqlQuery("TestValue", "order by id");
+
+ int cnt = 0;
+
+ for (Cache.Entry e : (Iterable<Cache.Entry>)cache.query(qry)) {
+ assertNotNull(cache.get(e.getKey()));
+
+ cnt++;
+ }
+
+ assertTrue(cnt > 0);
+
+ break;
+ }
+
+ default:
+ fail();
+ }
+ }
+
+ return null;
+ }
+ }, NODES * 2, "test-thread");
+ }
+
+ /**
+ * @param ignite Node.
+ * @param cacheName Cache name.
+ */
+ private void insertData(Ignite ignite, String cacheName) {
+ try (IgniteDataStreamer streamer = ignite.dataStreamer(cacheName)) {
+ for (int i = 0; i < KEYS; i++)
+ streamer.addData(new TestKey(i), new TestValue(i));
+ }
+ }
+
+ /**
+ * @param name Cache name.
+ * @param atomicityMode Cache atomicity mode.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration cacheConfiguration(String name, CacheAtomicityMode atomicityMode) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setCacheMode(PARTITIONED);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicityMode(atomicityMode);
+ ccfg.setBackups(1);
+
+ QueryEntity qryEntity = new QueryEntity();
+
+ qryEntity.setKeyType(TestKey.class.getName());
+ qryEntity.setValueType(TestValue.class.getName());
+
+ qryEntity.addQueryField("id", Integer.class.getName(), null);
+ qryEntity.addQueryField("val", Integer.class.getName(), null);
+
+ qryEntity.setIndexes(F.asList(new QueryIndex("id"), new QueryIndex("val")));
+
+ ccfg.setQueryEntities(F.asList(qryEntity));
+
+ return ccfg;
+ }
+
+ /**
+ *
+ */
+ static class TestKey {
+ /** */
+ @QuerySqlField(index = true)
+ private int id;
+
+ /**
+ * @param id ID.
+ */
+ public TestKey(int id) {
+ this.id = id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TestKey testKey = (TestKey)o;
+
+ return id == testKey.id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return id;
+ }
+ }
+
+ /**
+ *
+ */
+ static class TestValue {
+ /** */
+ @QuerySqlField(index = true)
+ private int val;
+
+ /**
+ * @param val Value.
+ */
+ public TestValue(int val) {
+ this.val = val;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a441bb9c/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
index 5cdd744..a264a2f 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
@@ -18,6 +18,7 @@
package org.apache.ignite.testsuites;
import junit.framework.TestSuite;
+import org.apache.ignite.internal.processors.cache.CacheBinaryKeyConcurrentQueryTest;
import org.apache.ignite.internal.processors.cache.CacheConfigurationP2PTest;
import org.apache.ignite.internal.processors.cache.CacheIndexStreamerTest;
import org.apache.ignite.internal.processors.cache.CacheIndexingOffheapCleanupTest;
@@ -77,6 +78,7 @@ public class IgniteCacheWithIndexingTestSuite extends TestSuite {
suite.addTestSuite(CacheRandomOperationsMultithreadedTest.class);
suite.addTestSuite(IgniteCacheStarvationOnRebalanceTest.class);
suite.addTestSuite(CacheOperationsWithExpirationTest.class);
+ suite.addTestSuite(CacheBinaryKeyConcurrentQueryTest.class);
suite.addTestSuite(CacheIndexingOffheapCleanupTest.class);
return suite;
[18/50] [abbrv] ignite git commit: IGNITE-3389 metadata result set
throws NPE when closed - fixed
Posted by vo...@apache.org.
IGNITE-3389 metadata result set throws NPE when closed - fixed
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ca5c8d80
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ca5c8d80
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ca5c8d80
Branch: refs/heads/ignite-3553
Commit: ca5c8d8051e5bfb9c17e34738e2a4555e2b8c3f8
Parents: 68891e8
Author: Alexandre Boudnik <Al...@epam.com>
Authored: Fri Jul 22 18:40:47 2016 +0300
Committer: agura <ag...@gridgain.com>
Committed: Fri Jul 22 18:42:24 2016 +0300
----------------------------------------------------------------------
.../internal/jdbc2/JdbcMetadataSelfTest.java | 63 ++++++++++++++------
.../ignite/jdbc/JdbcMetadataSelfTest.java | 18 ++++++
.../ignite/internal/jdbc2/JdbcResultSet.java | 2 +-
3 files changed, 64 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/ca5c8d80/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
old mode 100644
new mode 100755
index f601dbc..7184b8d
--- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcMetadataSelfTest.java
@@ -17,24 +17,33 @@
package org.apache.ignite.internal.jdbc2;
-import org.apache.ignite.*;
-import org.apache.ignite.cache.affinity.*;
-import org.apache.ignite.cache.query.annotations.*;
-import org.apache.ignite.configuration.*;
-import org.apache.ignite.internal.util.typedef.*;
-import org.apache.ignite.spi.discovery.tcp.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.*;
-import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*;
-import org.apache.ignite.testframework.junits.common.*;
-
-import java.io.*;
-import java.sql.*;
-import java.util.*;
-
-import static java.sql.Types.*;
-import static org.apache.ignite.IgniteJdbcDriver.*;
-import static org.apache.ignite.cache.CacheMode.*;
-import static org.apache.ignite.cache.CacheWriteSynchronizationMode.*;
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.affinity.AffinityKey;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ConnectorConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static java.sql.Types.INTEGER;
+import static java.sql.Types.OTHER;
+import static java.sql.Types.VARCHAR;
+import static org.apache.ignite.IgniteJdbcDriver.CFG_URL_PREFIX;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
/**
* Metadata tests.
@@ -277,6 +286,24 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
}
/**
+ * @throws Exception If failed.
+ */
+ public void testMetadataResultSetClose() throws Exception {
+ try (Connection conn = DriverManager.getConnection(BASE_URL);
+ ResultSet tbls = conn.getMetaData().getTables(null, null, "%", null)) {
+ int colCnt = tbls.getMetaData().getColumnCount();
+
+ while (tbls.next()) {
+ for (int i = 0; i < colCnt; i++)
+ tbls.getObject(i + 1);
+ }
+ }
+ catch (Exception e) {
+ fail();
+ }
+ }
+
+ /**
* Person.
*/
@SuppressWarnings("UnusedDeclaration")
http://git-wip-us.apache.org/repos/asf/ignite/blob/ca5c8d80/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
index 0deb45d..72d93c9 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcMetadataSelfTest.java
@@ -289,6 +289,24 @@ public class JdbcMetadataSelfTest extends GridCommonAbstractTest {
}
/**
+ * @throws Exception If failed.
+ */
+ public void testMetadataResultSetClose() throws Exception {
+ try (Connection conn = DriverManager.getConnection(URL);
+ ResultSet tbls = conn.getMetaData().getTables(null, null, "%", null)) {
+ int colCnt = tbls.getMetaData().getColumnCount();
+
+ while (tbls.next()) {
+ for (int i = 0; i < colCnt; i++)
+ tbls.getObject(i + 1);
+ }
+ }
+ catch (Exception e) {
+ fail();
+ }
+ }
+
+ /**
* Person.
*/
@SuppressWarnings("UnusedDeclaration")
http://git-wip-us.apache.org/repos/asf/ignite/blob/ca5c8d80/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
old mode 100644
new mode 100755
index 5092b42..69dddad
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
@@ -182,7 +182,7 @@ public class JdbcResultSet implements ResultSet {
* If this result set is associated with locally executed query then query cursor will also closed.
*/
void closeInternal() throws SQLException {
- if (((JdbcConnection)stmt.getConnection()).nodeId() == null)
+ if (((JdbcConnection)stmt.getConnection()).nodeId() == null && uuid != null)
JdbcQueryTask.remove(uuid);
closed = true;
[11/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRange.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRange.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRange.java
new file mode 100644
index 0000000..bc8aa75
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRange.java
@@ -0,0 +1,181 @@
+/*
+ * 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.twostep.msg;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Range of rows.
+ */
+public class GridH2RowRange implements Message {
+ /** */
+ private static int FLAG_PARTIAL = 1;
+
+ /** */
+ private int rangeId;
+
+ /** */
+ @GridDirectCollection(Message.class)
+ @GridToStringInclude
+ private List<GridH2RowMessage> rows;
+
+ /** */
+ private byte flags;
+
+ /**
+ * @param rangeId Range ID.
+ */
+ public void rangeId(int rangeId) {
+ this.rangeId = rangeId;
+ }
+
+ /**
+ * @return Range ID.
+ */
+ public int rangeId() {
+ return rangeId;
+ }
+
+ /**
+ * @param rows Rows.
+ */
+ public void rows(List<GridH2RowMessage> rows) {
+ this.rows = rows;
+ }
+
+ /**
+ * @return Rows.
+ */
+ public List<GridH2RowMessage> rows() {
+ return rows;
+ }
+
+ /**
+ * Sets that this is a partial range.
+ */
+ public void setPartial() {
+ flags |= FLAG_PARTIAL;
+ }
+
+ /**
+ * @return {@code true} If this is a partial range.
+ */
+ public boolean isPartial() {
+ return (flags & FLAG_PARTIAL) == FLAG_PARTIAL;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeByte("flags", flags))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeInt("rangeId", rangeId))
+ return false;
+
+ writer.incrementState();
+
+ case 2:
+ if (!writer.writeCollection("rows", rows, MessageCollectionItemType.MSG))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ flags = reader.readByte("flags");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ rangeId = reader.readInt("rangeId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 2:
+ rows = reader.readCollection("rows", MessageCollectionItemType.MSG);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GridH2RowRange.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ return -34;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridH2RowRange.class, this, "rowsSize", rows != null ? rows.size() : 0);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRangeBounds.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRangeBounds.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRangeBounds.java
new file mode 100644
index 0000000..e32e449
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowRangeBounds.java
@@ -0,0 +1,188 @@
+/*
+ * 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.twostep.msg;
+
+import java.nio.ByteBuffer;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Bounds of row range.
+ */
+public class GridH2RowRangeBounds implements Message {
+ /** */
+ private int rangeId;
+
+ /** */
+ private GridH2RowMessage first;
+
+ /** */
+ private GridH2RowMessage last;
+
+ /**
+ * @param rangeId Range ID.
+ * @param first First.
+ * @param last Last.
+ * @return Range bounds.
+ */
+ public static GridH2RowRangeBounds rangeBounds(int rangeId, GridH2RowMessage first, GridH2RowMessage last) {
+ GridH2RowRangeBounds res = new GridH2RowRangeBounds();
+
+ res.rangeId(rangeId);
+ res.first(first);
+ res.last(last);
+
+ return res;
+ }
+
+ /**
+ * @param rangeId Range ID.
+ */
+ public void rangeId(int rangeId) {
+ this.rangeId = rangeId;
+ }
+
+ /**
+ * @return Range ID.
+ */
+ public int rangeId() {
+ return rangeId;
+ }
+
+ /**
+ * @param first First.
+ */
+ public void first(GridH2RowMessage first) {
+ this.first = first;
+ }
+
+ /**
+ * @return First.
+ */
+ public GridH2RowMessage first() {
+ return first;
+ }
+
+ /**
+ * @param last Last.
+ */
+ public void last(GridH2RowMessage last) {
+ this.last = last;
+ }
+
+ /**
+ * @return Last.
+ */
+ public GridH2RowMessage last() {
+ return last;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeMessage("first", first))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeMessage("last", last))
+ return false;
+
+ writer.incrementState();
+
+ case 2:
+ if (!writer.writeInt("rangeId", rangeId))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ first = reader.readMessage("first");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ last = reader.readMessage("last");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 2:
+ rangeId = reader.readInt("rangeId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GridH2RowRangeBounds.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ return -35;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 3;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridH2RowRangeBounds.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Short.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Short.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Short.java
index 841e01e..ebeca9d 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Short.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Short.java
@@ -99,7 +99,7 @@ public class GridH2Short extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Short.class);
}
/** {@inheritDoc} */
@@ -111,4 +111,9 @@ public class GridH2Short extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2String.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2String.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2String.java
index 50b4d58..f2f9fdc 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2String.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2String.java
@@ -101,7 +101,7 @@ public class GridH2String extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2String.class);
}
/** {@inheritDoc} */
@@ -113,4 +113,9 @@ public class GridH2String extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return x;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Time.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Time.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Time.java
index 1c6c7ae..172d695 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Time.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Time.java
@@ -102,7 +102,7 @@ public class GridH2Time extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Time.class);
}
/** {@inheritDoc} */
@@ -114,4 +114,9 @@ public class GridH2Time extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(nanos);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Timestamp.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Timestamp.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Timestamp.java
index ccdba92..b020799 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Timestamp.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Timestamp.java
@@ -50,7 +50,7 @@ public class GridH2Timestamp extends GridH2ValueMessage {
ValueTimestamp t = (ValueTimestamp)val;
date = t.getDateValue();
- nanos = t.getNanos();
+ nanos = t.getTimeNanos();
}
/** {@inheritDoc} */
@@ -119,7 +119,7 @@ public class GridH2Timestamp extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Timestamp.class);
}
/** {@inheritDoc} */
@@ -131,4 +131,9 @@ public class GridH2Timestamp extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 2;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return date + "_" + nanos;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Uuid.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Uuid.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Uuid.java
index fd14d90..fa9360b 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Uuid.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Uuid.java
@@ -119,7 +119,7 @@ public class GridH2Uuid extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Uuid.class);
}
/** {@inheritDoc} */
@@ -131,4 +131,9 @@ public class GridH2Uuid extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 2;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return ValueUuid.get(high, low).getString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessage.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessage.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessage.java
index d528c47..18f8880 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessage.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessage.java
@@ -52,4 +52,4 @@ public abstract class GridH2ValueMessage implements Message {
@Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
return true;
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessageFactory.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessageFactory.java
index d414e5a..aa84e4b 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessageFactory.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2ValueMessageFactory.java
@@ -90,6 +90,24 @@ public class GridH2ValueMessageFactory implements MessageFactory {
case -22:
return new GridH2CacheObject();
+
+ case -30:
+ return new GridH2IndexRangeRequest();
+
+ case -31:
+ return new GridH2IndexRangeResponse();
+
+ case -32:
+ return new GridH2RowMessage();
+
+ case -33:
+ return new GridH2QueryRequest();
+
+ case -34:
+ return new GridH2RowRange();
+
+ case -35:
+ return new GridH2RowRangeBounds();
}
return null;
@@ -118,7 +136,7 @@ public class GridH2ValueMessageFactory implements MessageFactory {
* @return Filled array.
* @throws IgniteCheckedException If failed.
*/
- public static Value[] fillArray(Iterator<Message> src, Value[] dst, GridKernalContext ctx)
+ public static Value[] fillArray(Iterator<? extends Message> src, Value[] dst, GridKernalContext ctx)
throws IgniteCheckedException {
for (int i = 0; i < dst.length; i++) {
Message msg = src.next();
@@ -134,7 +152,7 @@ public class GridH2ValueMessageFactory implements MessageFactory {
* @return Message.
* @throws IgniteCheckedException If failed.
*/
- public static Message toMessage(Value v) throws IgniteCheckedException {
+ public static GridH2ValueMessage toMessage(Value v) throws IgniteCheckedException {
switch (v.getType()) {
case Value.NULL:
return GridH2Null.INSTANCE;
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java
deleted file mode 100644
index 170ab65..0000000
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheReduceQueryMultithreadedSelfTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.IgniteInternalFuture;
-import org.apache.ignite.internal.processors.cache.query.CacheQuery;
-import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.internal.util.typedef.R1;
-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 static org.apache.ignite.cache.CacheMode.PARTITIONED;
-import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
-
-/**
- * Multithreaded reduce query tests with lots of data.
- */
-public class GridCacheReduceQueryMultithreadedSelfTest extends GridCacheAbstractSelfTest {
- /** */
- private static final int GRID_CNT = 5;
-
- /** */
- private static final int TEST_TIMEOUT = 2 * 60 * 1000;
-
- /** */
- private static final TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
-
- /** {@inheritDoc} */
- @Override protected int gridCount() {
- return GRID_CNT;
- }
-
- /** {@inheritDoc} */
- @Override protected long getTestTimeout() {
- return TEST_TIMEOUT;
- }
-
- /** {@inheritDoc} */
- @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
- IgniteConfiguration cfg = super.getConfiguration(gridName);
-
- TcpDiscoverySpi disco = new TcpDiscoverySpi();
-
- disco.setIpFinder(ipFinder);
-
- cfg.setDiscoverySpi(disco);
-
- return cfg;
- }
-
- /** {@inheritDoc} */
- @Override protected CacheConfiguration cacheConfiguration(String gridName) throws Exception {
- CacheConfiguration<?,?> cfg = super.cacheConfiguration(gridName);
-
- cfg.setCacheMode(PARTITIONED);
- cfg.setBackups(1);
- cfg.setWriteSynchronizationMode(FULL_SYNC);
-
- cfg.setIndexedTypes(
- String.class, Integer.class
- );
-
- return cfg;
- }
-
- /**
- * @throws Exception In case of error.
- */
- public void testReduceQuery() throws Exception {
- final int keyCnt = 5000;
- final int logFreq = 500;
-
- final GridCacheAdapter<String, Integer> c = internalCache(jcache());
-
- final CountDownLatch startLatch = new CountDownLatch(1);
-
- IgniteInternalFuture<?> fut1 = multithreadedAsync(new Callable() {
- @Override public Object call() throws Exception {
- for (int i = 1; i < keyCnt; i++) {
- c.getAndPut(String.valueOf(i), i);
-
- startLatch.countDown();
-
- if (i % logFreq == 0)
- info("Stored entries: " + i);
- }
-
- return null;
- }
- }, 1);
-
- // Create query.
- final CacheQuery<List<?>> sumQry = c.context().queries().
- createSqlFieldsQuery("select _val from Integer", false).timeout(TEST_TIMEOUT);
-
- final R1<List<?>, Integer> rmtRdc = new R1<List<?>, Integer>() {
- /** */
- private AtomicInteger sum = new AtomicInteger();
-
- @Override public boolean collect(List<?> e) {
- sum.addAndGet((Integer)e.get(0));
-
- return true;
- }
-
- @Override public Integer reduce() {
- return sum.get();
- }
- };
-
- final AtomicBoolean stop = new AtomicBoolean();
-
- startLatch.await();
-
- IgniteInternalFuture<?> fut2 = multithreadedAsync(new Callable() {
- @Override public Object call() throws Exception {
- int cnt = 0;
-
- while (!stop.get()) {
- Collection<Integer> res = sumQry.execute(rmtRdc).get();
-
- int sum = F.sumInt(res);
-
- cnt++;
-
- assertTrue(sum > 0);
-
- if (cnt % logFreq == 0) {
- info("Reduced value: " + sum);
- info("Executed queries: " + cnt);
- }
- }
-
- return null;
- }
- }, 1);
-
- fut1.get();
-
- stop.set(true);
-
- fut2.get();
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 65d479d..7c5b472 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
@@ -69,7 +69,6 @@ import org.apache.ignite.events.Event;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.binary.BinaryMarshaller;
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQuerySelfTest;
-import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager;
import org.apache.ignite.internal.processors.cache.query.QueryCursorEx;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
import org.apache.ignite.internal.util.tostring.GridToStringExclude;
@@ -969,22 +968,6 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
/**
* @throws Exception If failed.
*/
- public void testEmptyObject() throws Exception {
- IgniteCache<EmptyObject, EmptyObject> cache = ignite().cache(null);
-
- cache.put(new EmptyObject(1), new EmptyObject(2));
-
- for (int i = 0; i < gridCount(); i++) {
- GridCacheQueryManager<Object, Object> qryMgr =
- ((IgniteKernal)grid(i)).internalCache().context().queries();
-
- assert !hasIndexTable(EmptyObject.class, qryMgr);
- }
- }
-
- /**
- * @throws Exception If failed.
- */
public void testPrimitiveType() throws Exception {
IgniteCache<Integer, Integer> cache = ignite().cache(null);
@@ -1536,7 +1519,7 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
}
try {
- IgniteCache<UUID, Person> cache = ignite().cache(null);
+ IgniteCache<UUID,Person> cache = ignite().cache(null);
for (int i = 1; i <= 20; i++)
cache.put(UUID.randomUUID(), new Person("Person " + i, i));
@@ -1555,17 +1538,6 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
}
/**
- * @param cls Class to check index table for.
- * @param qryMgr Query manager.
- * @return {@code true} if index has a table for given class.
- * @throws IgniteCheckedException If failed.
- */
- private boolean hasIndexTable(Class<?> cls, GridCacheQueryManager<Object, Object> qryMgr)
- throws IgniteCheckedException {
- return qryMgr.size(cls) != -1;
- }
-
- /**
*
*/
private static class ArrayObject implements Serializable {
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheCrossCacheJoinRandomTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheCrossCacheJoinRandomTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheCrossCacheJoinRandomTest.java
new file mode 100644
index 0000000..4d5a44e
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheCrossCacheJoinRandomTest.java
@@ -0,0 +1,442 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Stack;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.query.h2.sql.AbstractH2CompareQueryTest;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.internal.S;
+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 org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheCrossCacheJoinRandomTest extends AbstractH2CompareQueryTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private boolean client;
+
+ /** */
+ private static final int OBJECTS = 200;
+
+ /** */
+ private static final int MAX_CACHES = 5;
+
+ /** */
+ private static Random rnd;
+
+ /** */
+ private static List<Map<Integer, Integer>> cachesData;
+
+ /** */
+ private static final List<T2<CacheMode, Integer>> MODES_1 = F.asList(
+ //new T2<>(REPLICATED, 0),
+ new T2<>(PARTITIONED, 0),
+ new T2<>(PARTITIONED, 1),
+ new T2<>(PARTITIONED, 2));
+
+ /** */
+ private static final List<T2<CacheMode, Integer>> MODES_2 = F.asList(
+ //new T2<>(REPLICATED, 0),
+ new T2<>(PARTITIONED, 0),
+ new T2<>(PARTITIONED, 1));
+
+ /** {@inheritDoc} */
+ @Override protected void setIndexedTypes(CacheConfiguration<?, ?> cc, CacheMode mode) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void initCacheAndDbData() throws Exception {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void checkAllDataEquals() throws Exception {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long getTestTimeout() {
+ return 10 * 60_000;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi spi = ((TcpDiscoverySpi)cfg.getDiscoverySpi());
+
+ spi.setIpFinder(IP_FINDER);
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ client = true;
+
+ startGrid(SRVS);
+
+ long seed = System.currentTimeMillis();
+
+ rnd = new Random(seed);
+
+ log.info("Random seed: " + seed);
+
+ cachesData = new ArrayList<>(MAX_CACHES);
+
+ for (int i = 0; i < MAX_CACHES; i++) {
+ Map<Integer, Integer> data = createData(OBJECTS * 2);
+
+ insertH2(data, i);
+
+ cachesData.add(data);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ cachesData = null;
+
+ super.afterTestsStopped();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Statement initializeH2Schema() throws SQLException {
+ Statement st = super.initializeH2Schema();
+
+ for (int i = 0; i < MAX_CACHES; i++) {
+ st.execute("CREATE SCHEMA \"cache" + i + "\"");
+
+ st.execute("create table \"cache" + i + "\".TESTOBJECT" +
+ " (_key int not null," +
+ " _val other not null," +
+ " parentId int)");
+ }
+
+ return st;
+ }
+
+ /**
+ * @param name Cache name.
+ * @param cacheMode Cache mode.
+ * @param backups Number of backups.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration configuration(String name, CacheMode cacheMode, int backups) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+ ccfg.setAtomicityMode(ATOMIC);
+ ccfg.setCacheMode(cacheMode);
+
+ if (cacheMode == PARTITIONED)
+ ccfg.setBackups(backups);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(TestObject.class.getName());
+ entity.addQueryField("parentId", Integer.class.getName(), null);
+ entity.setIndexes(F.asList(new QueryIndex("parentId")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ return ccfg;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin2Caches() throws Exception {
+ testJoin(2, MODES_1);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin3Caches() throws Exception {
+ testJoin(3, MODES_1);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin4Caches() throws Exception {
+ testJoin(4, MODES_2);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin5Caches() throws Exception {
+ testJoin(5, MODES_2);
+ }
+
+ /**
+ * @param caches Number of caches.
+ * @param allModes Cache modes.
+ * @throws Exception If failed.
+ */
+ private void testJoin(int caches, List<T2<CacheMode, Integer>> allModes) throws Exception {
+ checkJoin(cachesData, allModes, new Stack<T2<CacheMode, Integer>>(), caches);
+ }
+
+ /**
+ * @param cachesData Caches data.
+ * @param allModes Modes to test.
+ * @param modes Select modes.
+ * @param caches Caches number.
+ * @throws Exception If failed.
+ */
+ private void checkJoin(List<Map<Integer, Integer>> cachesData,
+ List<T2<CacheMode, Integer>> allModes,
+ Stack<T2<CacheMode, Integer>> modes,
+ int caches) throws Exception {
+ if (modes.size() == caches) {
+ List<CacheConfiguration> ccfgs = new ArrayList<>();
+
+ for (int i = 0; i < modes.size(); i++) {
+ T2<CacheMode, Integer> mode = modes.get(i);
+
+ CacheConfiguration ccfg = configuration("cache" + i, mode.get1(), mode.get2());
+
+ ccfgs.add(ccfg);
+ }
+
+ log.info("Check configurations: " + modes);
+
+ checkJoinQueries(ccfgs, cachesData);
+ }
+ else {
+ for (T2<CacheMode, Integer> mode : allModes) {
+ modes.push(mode);
+
+ checkJoin(cachesData, allModes, modes, caches);
+
+ modes.pop();
+ }
+ }
+ }
+
+ /**
+ * @param ccfgs Configurations.
+ * @param cachesData Caches data.
+ * @throws Exception If failed.
+ */
+ private void checkJoinQueries(List<CacheConfiguration> ccfgs, List<Map<Integer, Integer>> cachesData) throws Exception {
+ Ignite client = ignite(SRVS);
+
+ final int CACHES = ccfgs.size();
+
+ try {
+ IgniteCache cache = null;
+
+ boolean hasReplicated = false;
+
+ for (int i = 0; i < CACHES; i++) {
+ CacheConfiguration ccfg = ccfgs.get(i);
+
+ IgniteCache cache0 = client.createCache(ccfg);
+
+ if (ccfg.getCacheMode() == REPLICATED)
+ hasReplicated = true;
+
+ if (cache == null && ccfg.getCacheMode() == PARTITIONED)
+ cache = cache0;
+
+ insertCache(cachesData.get(i), cache0);
+ }
+
+ boolean distributedJoin = true;
+
+ // Do not use distributed join if all caches are REPLICATED.
+ if (cache == null) {
+ cache = client.cache(ccfgs.get(0).getName());
+
+ distributedJoin = false;
+ }
+
+ Object[] args = {};
+
+ compareQueryRes0(cache, createQuery(CACHES, false, null), distributedJoin, false, args, Ordering.RANDOM);
+
+ if (!hasReplicated) {
+ compareQueryRes0(cache, createQuery(CACHES, false, null), distributedJoin, true, args, Ordering.RANDOM);
+
+ compareQueryRes0(cache, createQuery(CACHES, true, null), distributedJoin, true, args, Ordering.RANDOM);
+ }
+
+ Map<Integer, Integer> data = cachesData.get(CACHES - 1);
+
+ final int QRY_CNT = CACHES > 4 ? 2 : 50;
+
+ int cnt = 0;
+
+ for (Integer objId : data.keySet()) {
+ compareQueryRes0(cache, createQuery(CACHES, false, objId), distributedJoin, false, args, Ordering.RANDOM);
+
+ if (!hasReplicated) {
+ compareQueryRes0(cache, createQuery(CACHES, false, objId), distributedJoin, true, args, Ordering.RANDOM);
+
+ compareQueryRes0(cache, createQuery(CACHES, true, objId), distributedJoin, true, args, Ordering.RANDOM);
+ }
+
+ if (cnt++ == QRY_CNT)
+ break;
+ }
+ }
+ finally {
+ for (CacheConfiguration ccfg : ccfgs)
+ client.destroyCache(ccfg.getName());
+ }
+ }
+
+ /**
+ * @param caches Number of caches to join.
+ * @param outer If {@code true} creates outer join query, otherwise inner join.
+ * @param objId Object ID.
+ * @return SQL.
+ */
+ @SuppressWarnings("StringConcatenationInsideStringBufferAppend")
+ private String createQuery(int caches, boolean outer, @Nullable Integer objId) {
+ StringBuilder qry = new StringBuilder("select ");
+
+ for (int i = 0; i < caches; i++) {
+ if (i != 0)
+ qry.append(", ");
+
+ qry.append("o" + i + "._key");
+ }
+
+ qry.append(" from \"cache0\".TestObject o0 ");
+
+ for (int i = 1; i < caches; i++) {
+ String cacheName = "cache" + i;
+
+ String cur = "o" + i;
+ String prev = "o" + (i - 1);
+
+ qry.append(outer ? "left outer join " : "inner join ");
+ qry.append("\"" + cacheName + "\".TestObject " + cur);
+
+ if (i == caches - 1 && objId != null)
+ qry.append(" on (" + prev + ".parentId=" + cur + "._key and " + cur + "._key=" + objId + ") ");
+ else
+ qry.append(" on (" + prev + ".parentId=" + cur + "._key) ");
+ }
+
+ return qry.toString();
+ }
+
+ /**
+ * @param data Data.
+ * @param cache Cache.
+ */
+ private void insertCache(Map<Integer, Integer> data, IgniteCache<Object, Object> cache) {
+ for (Map.Entry<Integer, Integer> e : data.entrySet())
+ cache.put(e.getKey(), new TestObject(e.getValue()));
+ }
+
+ /**
+ * @param data Data.
+ * @param cache Cache index.
+ * @throws Exception If failed.
+ */
+ private void insertH2(Map<Integer, Integer> data, int cache) throws Exception {
+ for (Map.Entry<Integer, Integer> e : data.entrySet()) {
+ try (PreparedStatement st = conn.prepareStatement("insert into \"cache" + cache + "\".TESTOBJECT " +
+ "(_key, _val, parentId) values(?, ?, ?)")) {
+ st.setObject(1, e.getKey());
+ st.setObject(2, new TestObject(e.getValue()));
+ st.setObject(3, e.getValue());
+
+ st.executeUpdate();
+ }
+ }
+ }
+
+ /**
+ * @param cnt Objects count.
+ * @return Generated data.
+ */
+ private Map<Integer, Integer> createData(int cnt) {
+ Map<Integer, Integer> res = new LinkedHashMap<>();
+
+ while (res.size() < cnt)
+ res.put(rnd.nextInt(cnt), rnd.nextInt(OBJECTS + 1));
+
+ return res;
+ }
+
+ /**
+ *
+ */
+ static class TestObject implements Serializable {
+ /** */
+ int parentId;
+
+ /**
+ * @param parentId Parent object ID.
+ */
+ public TestObject(int parentId) {
+ this.parentId = parentId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TestObject.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCollocatedAndNotTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCollocatedAndNotTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCollocatedAndNotTest.java
new file mode 100644
index 0000000..7881c44
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCollocatedAndNotTest.java
@@ -0,0 +1,365 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheKeyConfiguration;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.affinity.AffinityKeyMapped;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheDistributedJoinCollocatedAndNotTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String PERSON_CACHE = "person";
+
+ /** */
+ private static final String ORG_CACHE = "org";
+
+ /** */
+ private static final String ACCOUNT_CACHE = "acc";
+
+ /** */
+ private boolean client;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ CacheKeyConfiguration keyCfg = new CacheKeyConfiguration(PersonKey.class.getName(), "affKey");
+
+ cfg.setCacheKeyConfiguration(keyCfg);
+
+ TcpDiscoverySpi spi = ((TcpDiscoverySpi)cfg.getDiscoverySpi());
+
+ spi.setIpFinder(IP_FINDER);
+
+ List<CacheConfiguration> ccfgs = new ArrayList<>();
+
+ {
+ CacheConfiguration ccfg = configuration(PERSON_CACHE);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(PersonKey.class.getName());
+ entity.setValueType(Person.class.getName());
+ entity.addQueryField("id", Integer.class.getName(), null);
+ entity.addQueryField("affKey", Integer.class.getName(), null);
+ entity.addQueryField("name", String.class.getName(), null);
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(ORG_CACHE);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Organization.class.getName());
+ entity.addQueryField("name", String.class.getName(), null);
+ entity.setIndexes(F.asList(new QueryIndex("name")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(ACCOUNT_CACHE);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Account.class.getName());
+ entity.addQueryField("personId", Integer.class.getName(), null);
+ entity.addQueryField("name", String.class.getName(), null);
+ entity.setIndexes(F.asList(new QueryIndex("personId"), new QueryIndex("name")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ cfg.setCacheConfiguration(ccfgs.toArray(new CacheConfiguration[ccfgs.size()]));
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(2);
+
+ client = true;
+
+ startGrid(2);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /**
+ * @param name Cache name.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration configuration(String name) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+ ccfg.setAtomicityMode(ATOMIC);
+ ccfg.setBackups(1);
+
+ return ccfg;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin() throws Exception {
+ Ignite client = grid(2);
+
+ IgniteCache<Object, Object> personCache = client.cache(PERSON_CACHE);
+ IgniteCache<Object, Object> orgCache = client.cache(ORG_CACHE);
+ IgniteCache<Object, Object> accCache = client.cache(ACCOUNT_CACHE);
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ AtomicInteger orgKey = new AtomicInteger();
+ AtomicInteger accKey = new AtomicInteger();
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ /**
+ * One organization, one person, two accounts.
+ */
+
+ int orgId1 = keyForNode(aff, orgKey, node0);
+
+ orgCache.put(orgId1, new Organization("obj-" + orgId1));
+
+ personCache.put(new PersonKey(1, orgId1), new Person(1, "o1-p1"));
+ personCache.put(new PersonKey(2, orgId1), new Person(2, "o1-p2"));
+
+ accCache.put(keyForNode(aff, accKey, node0), new Account(1, "a0"));
+ accCache.put(keyForNode(aff, accKey, node1), new Account(1, "a1"));
+
+ // Join on affinity keys equals condition should not be distributed.
+ String qry = "select o.name, p._key, p.name " +
+ "from \"org\".Organization o, \"person\".Person p " +
+ "where p.affKey = o._key";
+
+ assertFalse(plan(qry, orgCache, false).contains("batched"));
+
+ checkQuery(qry, orgCache, false, 2);
+
+ checkQuery("select o.name, p._key, p.name, a.name " +
+ "from \"org\".Organization o, \"person\".Person p, \"acc\".Account a " +
+ "where p.affKey = o._key and p.id = a.personId", orgCache, true, 2);
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @return Query plan.
+ */
+ private String plan(String sql,
+ IgniteCache<?, ?> cache,
+ boolean enforceJoinOrder) {
+ return (String)cache.query(new SqlFieldsQuery("explain " + sql)
+ .setDistributedJoins(true)
+ .setEnforceJoinOrder(enforceJoinOrder))
+ .getAll().get(0).get(0);
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @param expSize Expected results size.
+ */
+ private void checkQuery(String sql,
+ IgniteCache<Object, Object> cache,
+ boolean enforceJoinOrder,
+ int expSize) {
+ String plan = (String)cache.query(new SqlFieldsQuery("explain " + sql)
+ .setDistributedJoins(true)
+ .setEnforceJoinOrder(enforceJoinOrder))
+ .getAll().get(0).get(0);
+
+ log.info("Plan: " + plan);
+
+ SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ qry.setDistributedJoins(true);
+ qry.setEnforceJoinOrder(enforceJoinOrder);
+
+ QueryCursor<List<?>> cur = cache.query(qry);
+
+ List<List<?>> res = cur.getAll();
+
+ if (expSize != res.size())
+ log.info("Results: " + res);
+
+ assertEquals(expSize, res.size());
+ }
+ /**
+ *
+ */
+ public static class PersonKey {
+ /** */
+ private int id;
+
+ /** */
+ @AffinityKeyMapped
+ private int affKey;
+
+ /**
+ * @param id Key.
+ * @param affKey Affinity key.
+ */
+ public PersonKey(int id, int affKey) {
+ this.id = id;
+ this.affKey = affKey;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ PersonKey other = (PersonKey)o;
+
+ return id == other.id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return id;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Account implements Serializable {
+ /** */
+ int personId;
+
+ /** */
+ String name;
+
+ /**
+ * @param personId Person ID.
+ * @param name Name.
+ */
+ public Account(int personId, String name) {
+ this.personId = personId;
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Account.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ int id;
+
+ /** */
+ String name;
+
+ /**
+ * @param id Person ID.
+ * @param name Name.
+ */
+ public Person(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Person.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ /** */
+ String name;
+
+ /**
+ * @param name Name.
+ */
+ public Organization(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Organization.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCustomAffinityMapper.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCustomAffinityMapper.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCustomAffinityMapper.java
new file mode 100644
index 0000000..1d4f7b2
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinCustomAffinityMapper.java
@@ -0,0 +1,262 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import javax.cache.CacheException;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.AffinityKeyMapper;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+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 org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheDistributedJoinCustomAffinityMapper extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String PERSON_CACHE = "person";
+
+ /** */
+ private static final String PERSON_CACHE_CUSTOM_AFF = "personCustomAff";
+
+ /** */
+ private static final String ORG_CACHE = "org";
+
+ /** */
+ private static final String ORG_CACHE_REPL_CUSTOM = "orgReplCustomAff";
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+ List<CacheConfiguration> ccfgs = new ArrayList<>();
+
+ {
+ CacheConfiguration ccfg = configuration(PERSON_CACHE);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Person.class.getName());
+ entity.addQueryField("orgId", Integer.class.getName(), null);
+ entity.setIndexes(F.asList(new QueryIndex("orgId")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(PERSON_CACHE_CUSTOM_AFF);
+
+ ccfg.setAffinityMapper(new TestMapper());
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Person.class.getName());
+ entity.addQueryField("orgId", Integer.class.getName(), null);
+ entity.setIndexes(F.asList(new QueryIndex("orgId")));
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(ORG_CACHE);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Organization.class.getName());
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(ORG_CACHE_REPL_CUSTOM);
+
+ ccfg.setCacheMode(REPLICATED);
+ ccfg.setAffinityMapper(new TestMapper());
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Organization.class.getName());
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ cfg.setCacheConfiguration(ccfgs.toArray(new CacheConfiguration[ccfgs.size()]));
+
+ return cfg;
+ }
+
+ /**
+ * @param name Cache name.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration configuration(String name) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+ ccfg.setAtomicityMode(ATOMIC);
+ ccfg.setBackups(0);
+
+ return ccfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(3);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinCustomAffinityMapper() throws Exception {
+ Ignite ignite = ignite(0);
+
+ IgniteCache<Object, Object> cache = ignite.cache(PERSON_CACHE);
+
+ checkQueryFails(cache, "select o._key k1, p._key k2 " +
+ "from \"org\".Organization o, \"personCustomAff\".Person p where o._key=p.orgId", false);
+
+ checkQueryFails(cache, "select o._key k1, p._key k2 " +
+ "from \"personCustomAff\".Person p, \"org\".Organization o where o._key=p.orgId", false);
+
+ {
+ // Check regular query does not fail.
+ SqlFieldsQuery qry = new SqlFieldsQuery("select o._key k1, p._key k2 " +
+ "from \"org\".Organization o, \"personCustomAff\".Person p where o._key=p.orgId");
+
+ cache.query(qry).getAll();
+ }
+
+ {
+ // Should not check affinity for replicated cache.
+ SqlFieldsQuery qry = new SqlFieldsQuery("select o1._key k1, p._key k2, o2._key k3 " +
+ "from \"org\".Organization o1, \"person\".Person p, \"orgReplCustomAff\".Organization o2 where " +
+ "o1._key=p.orgId and o2._key=p.orgId");
+
+ cache.query(qry).getAll();
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @param sql SQL.
+ * @param enforceJoinOrder Enforce join order flag.
+ */
+ private void checkQueryFails(final IgniteCache<Object, Object> cache,
+ String sql,
+ boolean enforceJoinOrder) {
+ final SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ qry.setDistributedJoins(true);
+ qry.setEnforceJoinOrder(enforceJoinOrder);
+
+ Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ cache.query(qry);
+
+ return null;
+ }
+ }, CacheException.class, null);
+
+ assertTrue("Unexpected error message: " + err.getMessage(),
+ err.getMessage().contains("can not use distributed joins for cache with custom AffinityKeyMapper configured."));
+ }
+
+ /**
+ *
+ */
+ static class TestMapper implements AffinityKeyMapper {
+ /** {@inheritDoc} */
+ @Override public Object affinityKey(Object key) {
+ return key;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void reset() {
+ // No-op.
+ }
+ }
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ int orgId;
+
+ /**
+ * @param orgId Organization ID.
+ */
+ public Person(int orgId) {
+ this.orgId = orgId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Person.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ // No-op.
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinNoIndexTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinNoIndexTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinNoIndexTest.java
new file mode 100644
index 0000000..95c56fa
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheDistributedJoinNoIndexTest.java
@@ -0,0 +1,299 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicInteger;
+import javax.cache.CacheException;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.affinity.Affinity;
+import org.apache.ignite.cache.query.QueryCursor;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+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 org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicWriteOrderMode.PRIMARY;
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+public class IgniteCacheDistributedJoinNoIndexTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String PERSON_CACHE = "person";
+
+ /** */
+ private static final String ORG_CACHE = "org";
+
+ /** */
+ private boolean client;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi spi = ((TcpDiscoverySpi)cfg.getDiscoverySpi());
+
+ spi.setIpFinder(IP_FINDER);
+
+ List<CacheConfiguration> ccfgs = new ArrayList<>();
+
+ {
+ CacheConfiguration ccfg = configuration(PERSON_CACHE);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Person.class.getName());
+ entity.addQueryField("orgId", Integer.class.getName(), null);
+ entity.addQueryField("orgName", String.class.getName(), null);
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ {
+ CacheConfiguration ccfg = configuration(ORG_CACHE);
+
+ QueryEntity entity = new QueryEntity();
+ entity.setKeyType(Integer.class.getName());
+ entity.setValueType(Organization.class.getName());
+ entity.addQueryField("name", String.class.getName(), null);
+
+ ccfg.setQueryEntities(F.asList(entity));
+
+ ccfgs.add(ccfg);
+ }
+
+ cfg.setCacheConfiguration(ccfgs.toArray(new CacheConfiguration[ccfgs.size()]));
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /**
+ * @param name Cache name.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration configuration(String name) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(name);
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+ ccfg.setAtomicWriteOrderMode(PRIMARY);
+ ccfg.setAtomicityMode(ATOMIC);
+ ccfg.setBackups(0);
+
+ return ccfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(2);
+
+ client = true;
+
+ startGrid(2);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin() throws Exception {
+ Ignite client = grid(2);
+
+ Affinity<Object> aff = client.affinity(PERSON_CACHE);
+
+ final IgniteCache<Object, Object> personCache = client.cache(PERSON_CACHE);
+ IgniteCache<Object, Object> orgCache = client.cache(ORG_CACHE);
+
+ AtomicInteger pKey = new AtomicInteger(100_000);
+ AtomicInteger orgKey = new AtomicInteger();
+
+ ClusterNode node0 = ignite(0).cluster().localNode();
+ ClusterNode node1 = ignite(1).cluster().localNode();
+
+ for (int i = 0; i < 3; i++) {
+ int orgId = keyForNode(aff, orgKey, node0);
+
+ orgCache.put(orgId, new Organization("org-" + i));
+
+ for (int j = 0; j < i; j++)
+ personCache.put(keyForNode(aff, pKey, node1), new Person(orgId, "org-" + i));
+ }
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from \"org\".Organization o, \"person\".Person p " +
+ "where p.orgName = o.name");
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from \"org\".Organization o inner join \"person\".Person p " +
+ "on p.orgName = o.name");
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from \"org\".Organization o, \"person\".Person p " +
+ "where p.orgName > o.name");
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from (select * from \"org\".Organization) o, \"person\".Person p " +
+ "where p.orgName = o.name");
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from \"org\".Organization o, (select * from \"person\".Person) p " +
+ "where p.orgName = o.name");
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from (select * from \"org\".Organization) o, (select * from \"person\".Person) p " +
+ "where p.orgName = o.name");
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from \"org\".Organization o, \"person\".Person p");
+
+ checkNoIndexError(personCache, "select o.name, p._key, p.orgName " +
+ "from \"org\".Organization o, \"person\".Person p where o._key != p._key");
+
+ checkQuery("select o.name, p._key, p.orgName " +
+ "from \"org\".Organization o, \"person\".Person p " +
+ "where p._key = o._key and o.name=?", personCache, 0, "aaa");
+ }
+
+ /**
+ * @param cache Cache.
+ * @param sql SQL.
+ */
+ private void checkNoIndexError(final IgniteCache<Object, Object> cache, final String sql) {
+ Throwable err = GridTestUtils.assertThrows(log, new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ qry.setDistributedJoins(true);
+
+ cache.query(qry).getAll();
+
+ return null;
+ }
+ }, CacheException.class, null);
+
+ log.info("Error: " + err.getMessage());
+
+ assertTrue("Unexpected error message: " + err.getMessage(),
+ err.getMessage().contains("join condition does not use index"));
+ }
+
+ /**
+ * @param sql SQL.
+ * @param cache Cache.
+ * @param expSize Expected results size.
+ * @param args Arguments.
+ * @return Results.
+ */
+ private List<List<?>> checkQuery(String sql,
+ IgniteCache<Object, Object> cache,
+ int expSize,
+ Object... args) {
+ SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ qry.setDistributedJoins(true);
+ qry.setArgs(args);
+
+ log.info("Plan: " + queryPlan(cache, qry));
+
+ QueryCursor<List<?>> cur = cache.query(qry);
+
+ List<List<?>> res = cur.getAll();
+
+ if (expSize != res.size())
+ log.info("Results: " + res);
+
+ assertEquals(expSize, res.size());
+
+ return res;
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ int orgId;
+
+ /** */
+ String orgName;
+
+ /**
+ * @param orgId Organization ID.
+ * @param orgName Organization name.
+ */
+ public Person(int orgId, String orgName) {
+ this.orgId = orgId;
+ this.orgName = orgName;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Person.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ /** */
+ String name;
+
+ /**
+ * @param name Name.
+ */
+ public Organization(String name) {
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Organization.class, this);
+ }
+ }
+}
[48/50] [abbrv] ignite git commit: IGNITE-3578: CPP: Added properties
to support distributed joins in CPP. This closes #894.
Posted by vo...@apache.org.
IGNITE-3578: CPP: Added properties to support distributed joins in CPP. This closes #894.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/33d35b3e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/33d35b3e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/33d35b3e
Branch: refs/heads/ignite-3553
Commit: 33d35b3ed87f986918f87838d4c9f12d23ec8dda
Parents: a7cf124
Author: isapego <is...@gridgain.com>
Authored: Thu Jul 28 08:59:26 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Thu Jul 28 08:59:26 2016 +0300
----------------------------------------------------------------------
.../cpp/core-test/config/cache-query.xml | 39 +-
.../cpp/core-test/src/cache_query_test.cpp | 443 ++++++++++++++++---
.../core/include/ignite/cache/query/query_sql.h | 61 ++-
.../ignite/cache/query/query_sql_fields.h | 112 ++++-
4 files changed, 569 insertions(+), 86 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/modules/platforms/cpp/core-test/config/cache-query.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/config/cache-query.xml b/modules/platforms/cpp/core-test/config/cache-query.xml
index 232b6da..06bc7f5 100644
--- a/modules/platforms/cpp/core-test/config/cache-query.xml
+++ b/modules/platforms/cpp/core-test/config/cache-query.xml
@@ -35,7 +35,7 @@
<property name="cacheConfiguration">
<list>
<bean class="org.apache.ignite.configuration.CacheConfiguration">
- <property name="name" value="cache"/>
+ <property name="name" value="QueryPerson"/>
<property name="cacheMode" value="PARTITIONED"/>
<property name="atomicityMode" value="TRANSACTIONAL"/>
<property name="writeSynchronizationMode" value="FULL_SYNC"/>
@@ -69,6 +69,43 @@
</list>
</property>
</bean>
+
+ <bean class="org.apache.ignite.cache.CacheTypeMetadata">
+ <property name="valueType" value="QueryRelation"/>
+ <property name="queryFields">
+ <map>
+ <entry key="personId" value="java.lang.Integer"/>
+ <entry key="someVal" value="java.lang.Integer"/>
+ </map>
+ </property>
+ </bean>
+ </list>
+ </property>
+ </bean>
+
+ <bean class="org.apache.ignite.configuration.CacheConfiguration">
+ <property name="name" value="QueryRelation"/>
+ <property name="cacheMode" value="PARTITIONED"/>
+ <property name="atomicityMode" value="TRANSACTIONAL"/>
+ <property name="writeSynchronizationMode" value="FULL_SYNC"/>
+
+ <property name="affinity">
+ <bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction">
+ <property name="partitions" value="256"/>
+ </bean>
+ </property>
+
+ <property name="typeMetadata">
+ <list>
+ <bean class="org.apache.ignite.cache.CacheTypeMetadata">
+ <property name="valueType" value="QueryRelation"/>
+ <property name="queryFields">
+ <map>
+ <entry key="personId" value="java.lang.Integer"/>
+ <entry key="someVal" value="java.lang.Integer"/>
+ </map>
+ </property>
+ </bean>
</list>
</property>
</bean>
http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/modules/platforms/cpp/core-test/src/cache_query_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/src/cache_query_test.cpp b/modules/platforms/cpp/core-test/src/cache_query_test.cpp
index 168f3f9..e3fba02 100644
--- a/modules/platforms/cpp/core-test/src/cache_query_test.cpp
+++ b/modules/platforms/cpp/core-test/src/cache_query_test.cpp
@@ -175,12 +175,71 @@ private:
Timestamp recordCreated;
};
+/**
+ * Relation class for query tests.
+ */
+class IGNITE_IMPORT_EXPORT QueryRelation
+{
+public:
+ /**
+ * Constructor.
+ */
+ QueryRelation() :
+ personId(),
+ someVal()
+ {
+ // No-op.
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name Name.
+ * @param age Age.
+ */
+ QueryRelation(int32_t personId, int32_t someVal) :
+ personId(personId),
+ someVal(someVal)
+ {
+ // No-op.
+ }
+
+ /**
+ * Get person ID.
+ *
+ * @return Person ID.
+ */
+ int32_t GetPersonId() const
+ {
+ return personId;
+ }
+
+ /**
+ * Get hobby ID.
+ *
+ * @return Some test value.
+ */
+ int32_t GetHobbyId() const
+ {
+ return someVal;
+ }
+
+private:
+ /** Person ID. */
+ int32_t personId;
+
+ /** Some test value. */
+ int32_t someVal;
+};
+
+
+
namespace ignite
{
namespace binary
{
/**
- * Binary type definition.
+ * Binary type definition for QueryPerson.
*/
IGNITE_BINARY_TYPE_START(QueryPerson)
IGNITE_BINARY_GET_TYPE_ID_AS_HASH(QueryPerson)
@@ -207,31 +266,45 @@ namespace ignite
return QueryPerson(name, age, birthday, recordCreated);
}
-
IGNITE_BINARY_TYPE_END
- }
-}
-/** Node started during the test. */
-Ignite grid = Ignite();
+ /**
+ * Binary type definition for QueryRelation.
+ */
+ IGNITE_BINARY_TYPE_START(QueryRelation)
+ IGNITE_BINARY_GET_TYPE_ID_AS_HASH(QueryRelation)
+ IGNITE_BINARY_GET_TYPE_NAME_AS_IS(QueryRelation)
+ IGNITE_BINARY_GET_FIELD_ID_AS_HASH
+ IGNITE_BINARY_GET_HASH_CODE_ZERO(QueryRelation)
+ IGNITE_BINARY_IS_NULL_FALSE(QueryRelation)
+ IGNITE_BINARY_GET_NULL_DEFAULT_CTOR(QueryRelation)
-/** Cache accessor. */
-Cache<int, QueryPerson> GetCache()
-{
- return grid.GetCache<int, QueryPerson>("cache");
+ void Write(BinaryWriter& writer, QueryRelation obj)
+ {
+ writer.WriteInt32("personId", obj.GetPersonId());
+ writer.WriteInt32("someVal", obj.GetHobbyId());
+ }
+
+ QueryRelation Read(BinaryReader& reader)
+ {
+ int32_t personId = reader.ReadInt32("personId");
+ int32_t someVal = reader.ReadInt32("someVal");
+
+ return QueryRelation(personId, someVal);
+ }
+ IGNITE_BINARY_TYPE_END
+ }
}
/**
* Test setup fixture.
*/
-struct CacheQueryTestSuiteFixture {
- /**
- * Constructor.
- */
- CacheQueryTestSuiteFixture()
+struct CacheQueryTestSuiteFixture
+{
+ Ignite StartNode(const char* name)
{
IgniteConfiguration cfg;
-
+
cfg.jvmOpts.push_back("-Xdebug");
cfg.jvmOpts.push_back("-Xnoagent");
cfg.jvmOpts.push_back("-Djava.compiler=NONE");
@@ -246,18 +319,26 @@ struct CacheQueryTestSuiteFixture {
cfg.jvmMaxMem = 4096;
#endif
- char* cfgPath = getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH");
-
- cfg.springCfgPath = std::string(cfgPath).append("/").append("cache-query.xml");
+ cfg.springCfgPath.assign(getenv("IGNITE_NATIVE_TEST_CPP_CONFIG_PATH")).append("/cache-query.xml");
IgniteError err;
- Ignite grid0 = Ignition::Start(cfg, &err);
+ Ignite grid0 = Ignition::Start(cfg, name, &err);
if (err.GetCode() != IgniteError::IGNITE_SUCCESS)
BOOST_ERROR(err.GetText());
- grid = grid0;
+ return grid0;
+ }
+
+
+ /**
+ * Constructor.
+ */
+ CacheQueryTestSuiteFixture() :
+ grid(StartNode("Node1"))
+ {
+ // No-op.
}
/**
@@ -265,11 +346,44 @@ struct CacheQueryTestSuiteFixture {
*/
~CacheQueryTestSuiteFixture()
{
- Ignition::Stop(grid.GetName(), true);
+ Ignition::StopAll(true);
}
+
+ /** Person cache accessor. */
+ Cache<int, QueryPerson> GetPersonCache()
+ {
+ return grid.GetCache<int, QueryPerson>("QueryPerson");
+ }
+
+ /** Relation cache accessor. */
+ Cache<int, QueryRelation> GetRelationCache()
+ {
+ return grid.GetCache<int, QueryRelation>("QueryRelation");
+ }
+
+ /** Node started during the test. */
+ Ignite grid;
};
/**
+ * Count number of records returned by cursor.
+ *
+ * @param cur Cursor.
+ */
+template<typename Cursor>
+int CountRecords(Cursor& cur)
+{
+ int number = 0;
+ while (cur.HasNext())
+ {
+ ++number;
+ cur.GetNext();
+ }
+
+ return number;
+}
+
+/**
* Ensure that HasNext() fails.
*
* @param cur Cursor.
@@ -314,8 +428,7 @@ void CheckGetNextFail(Cursor& cur)
*
* @param cur Cursor.
*/
-template<typename Cursor>
-void CheckGetAllFail(Cursor& cur)
+void CheckGetAllFail(QueryCursor<int, QueryPerson>& cur)
{
try
{
@@ -361,8 +474,7 @@ void CheckEmpty(QueryFieldsCursor& cur)
*
* @param cur Cursor.
*/
-template<typename Cursor>
-void CheckEmptyGetAll(Cursor& cur)
+void CheckEmptyGetAll(QueryCursor<int, QueryPerson>& cur)
{
std::vector<CacheEntry<int, QueryPerson>> res;
@@ -382,8 +494,7 @@ void CheckEmptyGetAll(Cursor& cur)
* @param name1 Name.
* @param age1 Age.
*/
-template<typename Cursor>
-void CheckSingle(Cursor& cur, int key, const std::string& name, int age)
+void CheckSingle(QueryCursor<int, QueryPerson>& cur, int key, const std::string& name, int age)
{
BOOST_REQUIRE(cur.HasNext());
@@ -404,6 +515,30 @@ void CheckSingle(Cursor& cur, int key, const std::string& name, int age)
}
/**
+ * Check single result through iteration.
+ *
+ * @param cur Cursor.
+ * @param key Key.
+ * @param name Name.
+ * @param age Age.
+ */
+void CheckSingle(QueryFieldsCursor& cur, int key, const std::string& name, int age)
+{
+ BOOST_REQUIRE(cur.HasNext());
+
+ QueryFieldsRow row = cur.GetNext();
+
+ BOOST_REQUIRE_EQUAL(row.GetNext<int32_t>(), key);
+ BOOST_REQUIRE_EQUAL(row.GetNext<std::string>(), name);
+ BOOST_REQUIRE_EQUAL(row.GetNext<int32_t>(), age);
+
+ BOOST_REQUIRE(!row.HasNext());
+ BOOST_REQUIRE(!cur.HasNext());
+
+ CheckGetNextFail(cur);
+}
+
+/**
* Check single result through GetAll().
*
* @param cur Cursor.
@@ -411,8 +546,7 @@ void CheckSingle(Cursor& cur, int key, const std::string& name, int age)
* @param name1 Name.
* @param age1 Age.
*/
-template<typename Cursor>
-void CheckSingleGetAll(Cursor& cur, int key, const std::string& name, int age)
+void CheckSingleGetAll(QueryCursor<int, QueryPerson>& cur, int key, const std::string& name, int age)
{
std::vector<CacheEntry<int, QueryPerson>> res;
@@ -444,8 +578,7 @@ void CheckSingleGetAll(Cursor& cur, int key, const std::string& name, int age)
* @param name2 Name 2.
* @param age2 Age 2.
*/
-template<typename Cursor>
-void CheckMultiple(Cursor& cur, int key1, const std::string& name1,
+void CheckMultiple(QueryCursor<int, QueryPerson>& cur, int key1, const std::string& name1,
int age1, int key2, const std::string& name2, int age2)
{
for (int i = 0; i < 2; i++)
@@ -489,8 +622,7 @@ void CheckMultiple(Cursor& cur, int key1, const std::string& name1,
* @param name2 Name 2.
* @param age2 Age 2.
*/
-template<typename Cursor>
-void CheckMultipleGetAll(Cursor& cur, int key1, const std::string& name1,
+void CheckMultipleGetAll(QueryCursor<int, QueryPerson>& cur, int key1, const std::string& name1,
int age1, int key2, const std::string& name2, int age2)
{
std::vector<CacheEntry<int, QueryPerson>> res;
@@ -529,7 +661,7 @@ BOOST_FIXTURE_TEST_SUITE(CacheQueryTestSuite, CacheQueryTestSuiteFixture)
*/
BOOST_AUTO_TEST_CASE(TestSqlQuery)
{
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with no results.
SqlQuery qry("QueryPerson", "age < 20");
@@ -541,8 +673,11 @@ BOOST_AUTO_TEST_CASE(TestSqlQuery)
CheckEmptyGetAll(cursor);
// Test simple query.
- cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
- cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
+ cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
+
+ cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
cursor = cache.Query(qry);
CheckSingle(cursor, 1, "A1", 10);
@@ -550,8 +685,23 @@ BOOST_AUTO_TEST_CASE(TestSqlQuery)
cursor = cache.Query(qry);
CheckSingleGetAll(cursor, 1, "A1", 10);
+ // Test simple distributed joins query.
+ BOOST_CHECK(!qry.IsDistributedJoins());
+ qry.SetDistributedJoins(true);
+ BOOST_CHECK(qry.IsDistributedJoins());
+
+ cursor = cache.Query(qry);
+ CheckSingle(cursor, 1, "A1", 10);
+
+ cursor = cache.Query(qry);
+ CheckSingleGetAll(cursor, 1, "A1", 10);
+
+ qry.SetDistributedJoins(false);
+
// Test simple local query.
+ BOOST_CHECK(!qry.IsLocal());
qry.SetLocal(true);
+ BOOST_CHECK(qry.IsLocal());
cursor = cache.Query(qry);
CheckSingle(cursor, 1, "A1", 10);
@@ -581,11 +731,60 @@ BOOST_AUTO_TEST_CASE(TestSqlQuery)
}
/**
+ * Test SQL query distributed joins.
+ */
+BOOST_AUTO_TEST_CASE(TestSqlQueryDistributedJoins)
+{
+ Cache<int, QueryPerson> cache1 = GetPersonCache();
+ Cache<int, QueryRelation> cache2 = GetRelationCache();
+
+ // Starting second node.
+ Ignite node2 = StartNode("Node2");
+
+ int entryCnt = 1000;
+
+ // Filling caches
+ for (int i = 0; i < entryCnt; i++)
+ {
+ std::stringstream stream;
+
+ stream << "A" << i;
+
+ cache1.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i),
+ BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60)));
+
+ cache2.Put(i + 1, QueryRelation(i, i * 10));
+ }
+
+ // Test query with no results.
+ SqlQuery qry("QueryPerson",
+ "from \"QueryPerson\".QueryPerson, \"QueryRelation\".QueryRelation "
+ "where \"QueryPerson\".QueryPerson.age = \"QueryRelation\".QueryRelation.someVal");
+
+ QueryCursor<int, QueryPerson> cursor = cache1.Query(qry);
+
+ // Ensure that data is not collocated, so not full result set is returned.
+ int recordsNum = CountRecords(cursor);
+
+ BOOST_CHECK_GT(recordsNum, 0);
+ BOOST_CHECK_LT(recordsNum, entryCnt);
+
+ qry.SetDistributedJoins(true);
+
+ cursor = cache1.Query(qry);
+
+ // Check that full result set is returned.
+ recordsNum = CountRecords(cursor);
+
+ BOOST_CHECK_EQUAL(recordsNum, entryCnt);
+}
+
+/**
* Test text query.
*/
BOOST_AUTO_TEST_CASE(TestTextQuery)
{
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with no results.
TextQuery qry("QueryPerson", "A1");
@@ -597,8 +796,11 @@ BOOST_AUTO_TEST_CASE(TestTextQuery)
CheckEmptyGetAll(cursor);
// Test simple query.
- cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
- cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
+ cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
+
+ cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
cursor = cache.Query(qry);
CheckSingle(cursor, 1, "A1", 10);
@@ -631,7 +833,7 @@ BOOST_AUTO_TEST_CASE(TestTextQuery)
BOOST_AUTO_TEST_CASE(TestScanQuery)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with no results.
ScanQuery qry;
@@ -643,7 +845,8 @@ BOOST_AUTO_TEST_CASE(TestScanQuery)
CheckEmptyGetAll(cursor);
// Test simple query.
- cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
+ cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
cursor = cache.Query(qry);
CheckSingle(cursor, 1, "A1", 10);
@@ -652,7 +855,8 @@ BOOST_AUTO_TEST_CASE(TestScanQuery)
CheckSingleGetAll(cursor, 1, "A1", 10);
// Test query returning multiple entries.
- cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
+ cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
cursor = cache.Query(qry);
CheckMultiple(cursor, 1, "A1", 10, 2, "A2", 20);
@@ -667,9 +871,9 @@ BOOST_AUTO_TEST_CASE(TestScanQuery)
BOOST_AUTO_TEST_CASE(TestScanQueryPartitioned)
{
// Populate cache with data.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
- int32_t partCnt = 256; // Defined in configuration explicitly.
+ int32_t partCnt = 256; // Defined in configuration explicitly.
int32_t entryCnt = 1000; // Should be greater than partCnt.
for (int i = 0; i < entryCnt; i++)
@@ -678,7 +882,8 @@ BOOST_AUTO_TEST_CASE(TestScanQueryPartitioned)
stream << "A" << i;
- cache.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i), BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60)));
+ cache.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i),
+ BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60)));
}
// Iterate over all partitions and collect data.
@@ -711,12 +916,125 @@ BOOST_AUTO_TEST_CASE(TestScanQueryPartitioned)
}
/**
+ * Basic test for SQL fields query.
+ */
+BOOST_AUTO_TEST_CASE(TestSqlFieldsQueryBasic)
+{
+ Cache<int, QueryPerson> cache = GetPersonCache();
+
+ // Test query with no results.
+ SqlFieldsQuery qry("select _key, name, age from QueryPerson where age < 20");
+
+ QueryFieldsCursor cursor = cache.Query(qry);
+ CheckEmpty(cursor);
+
+ // Test simple query.
+ cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
+
+ cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
+
+ cursor = cache.Query(qry);
+ CheckSingle(cursor, 1, "A1", 10);
+
+ // Test simple distributed joins query.
+ BOOST_CHECK(!qry.IsDistributedJoins());
+ BOOST_CHECK(!qry.IsEnforceJoinOrder());
+
+ qry.SetDistributedJoins(true);
+
+ BOOST_CHECK(qry.IsDistributedJoins());
+ BOOST_CHECK(!qry.IsEnforceJoinOrder());
+
+ qry.SetEnforceJoinOrder(true);
+
+ BOOST_CHECK(qry.IsDistributedJoins());
+ BOOST_CHECK(qry.IsEnforceJoinOrder());
+
+ cursor = cache.Query(qry);
+ CheckSingle(cursor, 1, "A1", 10);
+
+ qry.SetDistributedJoins(false);
+ qry.SetEnforceJoinOrder(false);
+
+ // Test simple local query.
+ BOOST_CHECK(!qry.IsLocal());
+
+ qry.SetLocal(true);
+
+ BOOST_CHECK(qry.IsLocal());
+
+ cursor = cache.Query(qry);
+ CheckSingle(cursor, 1, "A1", 10);
+
+ // Test query with arguments.
+ qry.SetSql("select _key, name, age from QueryPerson where age < ? AND name = ?");
+ qry.AddArgument<int>(20);
+ qry.AddArgument<std::string>("A1");
+
+ cursor = cache.Query(qry);
+ CheckSingle(cursor, 1, "A1", 10);
+}
+
+/**
+ * Test SQL fields query distributed joins.
+ */
+BOOST_AUTO_TEST_CASE(TestSqlFieldsQueryDistributedJoins)
+{
+ Cache<int, QueryPerson> cache1 = GetPersonCache();
+ Cache<int, QueryRelation> cache2 = GetRelationCache();
+
+ // Starting second node.
+ Ignite node2 = StartNode("Node2");
+
+ int entryCnt = 1000;
+
+ // Filling caches
+ for (int i = 0; i < entryCnt; i++)
+ {
+ std::stringstream stream;
+
+ stream << "A" << i;
+
+ cache1.Put(i, QueryPerson(stream.str(), i * 10, BinaryUtils::MakeDateLocal(1970 + i),
+ BinaryUtils::MakeTimestampLocal(2016, 1, 1, i / 60, i % 60)));
+
+ cache2.Put(i + 1, QueryRelation(i, i * 10));
+ }
+
+ // Test query with no results.
+ SqlFieldsQuery qry(
+ "select age, name "
+ "from \"QueryPerson\".QueryPerson "
+ "inner join \"QueryRelation\".QueryRelation "
+ "on \"QueryPerson\".QueryPerson.age = \"QueryRelation\".QueryRelation.someVal");
+
+ QueryFieldsCursor cursor = cache1.Query(qry);
+
+ // Ensure that data is not collocated, so not full result set is returned.
+ int recordsNum = CountRecords(cursor);
+
+ BOOST_CHECK_GT(recordsNum, 0);
+ BOOST_CHECK_LT(recordsNum, entryCnt);
+
+ qry.SetDistributedJoins(true);
+
+ cursor = cache1.Query(qry);
+
+ // Check that full result set is returned.
+ recordsNum = CountRecords(cursor);
+
+ BOOST_CHECK_EQUAL(recordsNum, entryCnt);
+}
+
+/**
* Test fields query with single entry.
*/
BOOST_AUTO_TEST_CASE(TestFieldsQuerySingle)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with two fields of different type.
SqlFieldsQuery qry("select age, name from QueryPerson");
@@ -725,7 +1043,8 @@ BOOST_AUTO_TEST_CASE(TestFieldsQuerySingle)
CheckEmpty(cursor);
// Test simple query.
- cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
+ cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
cursor = cache.Query(qry);
@@ -761,7 +1080,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQuerySingle)
BOOST_AUTO_TEST_CASE(TestFieldsQueryExceptions)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with two fields of different type.
SqlFieldsQuery qry("select age, name from QueryPerson");
@@ -770,7 +1089,8 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryExceptions)
CheckEmpty(cursor);
// Test simple query.
- cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
+ cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
cursor = cache.Query(qry);
@@ -806,7 +1126,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryExceptions)
BOOST_AUTO_TEST_CASE(TestFieldsQueryTwo)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with two fields of different type.
SqlFieldsQuery qry("select age, name from QueryPerson");
@@ -815,8 +1135,11 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTwo)
CheckEmpty(cursor);
// Test simple query.
- cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
- cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26), BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
+ cache.Put(1, QueryPerson("A1", 10, BinaryUtils::MakeDateLocal(1990, 03, 18),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 34, 579304685)));
+
+ cache.Put(2, QueryPerson("A2", 20, BinaryUtils::MakeDateLocal(1989, 10, 26),
+ BinaryUtils::MakeTimestampLocal(2016, 02, 10, 17, 39, 35, 678403201)));
cursor = cache.Query(qry);
@@ -869,7 +1192,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTwo)
BOOST_AUTO_TEST_CASE(TestFieldsQuerySeveral)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with two fields of different type.
SqlFieldsQuery qry("select name, age from QueryPerson");
@@ -935,7 +1258,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQuerySeveral)
BOOST_AUTO_TEST_CASE(TestFieldsQueryDateLess)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with field of type 'Date'.
SqlFieldsQuery qry("select birthday from QueryPerson where birthday<'1990-01-01'");
@@ -996,7 +1319,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryDateLess)
BOOST_AUTO_TEST_CASE(TestFieldsQueryDateMore)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with field of type 'Date'.
SqlFieldsQuery qry("select birthday from QueryPerson where birthday>'2070-01-01'");
@@ -1057,7 +1380,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryDateMore)
BOOST_AUTO_TEST_CASE(TestFieldsQueryDateEqual)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with field of type 'Date'.
SqlFieldsQuery qry("select birthday from QueryPerson where birthday='2032-01-01'");
@@ -1109,7 +1432,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryDateEqual)
BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampLess)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with field of type 'Timestamp'.
SqlFieldsQuery qry("select recordCreated from QueryPerson where recordCreated<'2016-01-01 01:00:00'");
@@ -1170,7 +1493,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampLess)
BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampMore)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with field of type 'Timestamp'.
SqlFieldsQuery qry("select recordCreated from QueryPerson where recordCreated>'2016-01-01 15:30:00'");
@@ -1233,7 +1556,7 @@ BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampMore)
BOOST_AUTO_TEST_CASE(TestFieldsQueryTimestampEqual)
{
// Test simple query.
- Cache<int, QueryPerson> cache = GetCache();
+ Cache<int, QueryPerson> cache = GetPersonCache();
// Test query with field of type 'Timestamp'.
SqlFieldsQuery qry("select recordCreated from QueryPerson where recordCreated='2016-01-01 09:18:00'");
http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
index cb7a739..0ec5d5f 100644
--- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
+++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
@@ -48,8 +48,13 @@ namespace ignite
* @param type Type name.
* @param sql SQL string.
*/
- SqlQuery(const std::string& type, const std::string& sql)
- : type(type), sql(sql), pageSize(1024), loc(false), args()
+ SqlQuery(const std::string& type, const std::string& sql) :
+ type(type),
+ sql(sql),
+ pageSize(1024),
+ loc(false),
+ distributedJoins(false),
+ args()
{
// No-op.
}
@@ -60,13 +65,18 @@ namespace ignite
* @param other Other instance.
*/
SqlQuery(const SqlQuery& other) :
- type(other.type), sql(other.sql), pageSize(other.pageSize),
- loc(other.loc), args()
+ type(other.type),
+ sql(other.sql),
+ pageSize(other.pageSize),
+ loc(other.loc),
+ distributedJoins(other.distributedJoins),
+ args()
{
args.reserve(other.args.size());
- for (std::vector<QueryArgumentBase*>::const_iterator i = other.args.begin();
- i != other.args.end(); ++i)
+ typedef std::vector<QueryArgumentBase*>::const_iterator Iter;
+
+ for (Iter i = other.args.begin(); i != other.args.end(); ++i)
args.push_back((*i)->Copy());
}
@@ -81,11 +91,7 @@ namespace ignite
{
SqlQuery tmp(other);
- std::swap(type, tmp.type);
- std::swap(sql, tmp.sql);
- std::swap(pageSize, tmp.pageSize);
- std::swap(loc, tmp.loc);
- std::swap(args, tmp.args);
+ Swap(tmp);
}
return *this;
@@ -96,7 +102,9 @@ namespace ignite
*/
~SqlQuery()
{
- for (std::vector<QueryArgumentBase*>::iterator it = args.begin(); it != args.end(); ++it)
+ typedef std::vector<QueryArgumentBase*>::const_iterator Iter;
+
+ for (Iter it = args.begin(); it != args.end(); ++it)
delete *it;
}
@@ -113,6 +121,7 @@ namespace ignite
std::swap(sql, other.sql);
std::swap(pageSize, other.pageSize);
std::swap(loc, other.loc);
+ std::swap(distributedJoins, other.distributedJoins);
std::swap(args, other.args);
}
}
@@ -198,6 +207,29 @@ namespace ignite
}
/**
+ * Check if distributed joins are enabled for this query.
+ *
+ * @return True If distributed joind enabled.
+ */
+ bool IsDistributedJoins() const
+ {
+ return distributedJoins;
+ }
+
+ /**
+ * Specify if distributed joins are enabled for this query.
+ *
+ * When disabled, join results will only contain colocated data (joins work locally).
+ * When enabled, joins work as expected, no matter how the data is distributed.
+ *
+ * @param enabled Distributed joins enabled.
+ */
+ void SetDistributedJoins(bool enabled)
+ {
+ distributedJoins = enabled;
+ }
+
+ /**
* Add argument.
*
* Template argument type should be copy-constructable and
@@ -229,7 +261,7 @@ namespace ignite
for (std::vector<QueryArgumentBase*>::const_iterator it = args.begin(); it != args.end(); ++it)
(*it)->Write(writer);
- writer.WriteBool(false); // distributed joins
+ writer.WriteBool(distributedJoins);
}
private:
@@ -245,6 +277,9 @@ namespace ignite
/** Local flag. */
bool loc;
+ /** Distributed joins flag. */
+ bool distributedJoins;
+
/** Arguments. */
std::vector<QueryArgumentBase*> args;
};
http://git-wip-us.apache.org/repos/asf/ignite/blob/33d35b3e/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
index 1c8570b..10dd6ab 100644
--- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
+++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
@@ -48,7 +48,12 @@ namespace ignite
* @param sql SQL string.
*/
SqlFieldsQuery(const std::string& sql) :
- sql(sql), pageSize(1024), loc(false), args()
+ sql(sql),
+ pageSize(1024),
+ loc(false),
+ distributedJoins(false),
+ enforceJoinOrder(false),
+ args()
{
// No-op.
}
@@ -60,7 +65,12 @@ namespace ignite
* @param loc Whether query should be executed locally.
*/
SqlFieldsQuery(const std::string& sql, bool loc) :
- sql(sql), pageSize(1024), loc(false), args()
+ sql(sql),
+ pageSize(1024),
+ loc(false),
+ distributedJoins(false),
+ enforceJoinOrder(false),
+ args()
{
// No-op.
}
@@ -71,13 +81,18 @@ namespace ignite
* @param other Other instance.
*/
SqlFieldsQuery(const SqlFieldsQuery& other) :
- sql(other.sql), pageSize(other.pageSize), loc(other.loc),
+ sql(other.sql),
+ pageSize(other.pageSize),
+ loc(other.loc),
+ distributedJoins(other.distributedJoins),
+ enforceJoinOrder(other.enforceJoinOrder),
args()
{
args.reserve(other.args.size());
- for (std::vector<QueryArgumentBase*>::const_iterator i = other.args.begin();
- i != other.args.end(); ++i)
+ typedef std::vector<QueryArgumentBase*>::const_iterator Iter;
+
+ for (Iter i = other.args.begin(); i != other.args.end(); ++i)
args.push_back((*i)->Copy());
}
@@ -92,10 +107,7 @@ namespace ignite
{
SqlFieldsQuery tmp(other);
- std::swap(sql, tmp.sql);
- std::swap(pageSize, tmp.pageSize);
- std::swap(loc, tmp.loc);
- std::swap(args, tmp.args);
+ Swap(tmp);
}
return *this;
@@ -106,11 +118,31 @@ namespace ignite
*/
~SqlFieldsQuery()
{
- for (std::vector<QueryArgumentBase*>::iterator it = args.begin(); it != args.end(); ++it)
+ typedef std::vector<QueryArgumentBase*>::const_iterator Iter;
+
+ for (Iter it = args.begin(); it != args.end(); ++it)
delete *it;
}
/**
+ * Efficiently swaps contents with another SqlQuery instance.
+ *
+ * @param other Other instance.
+ */
+ void Swap(SqlFieldsQuery& other)
+ {
+ if (this != &other)
+ {
+ std::swap(sql, other.sql);
+ std::swap(pageSize, other.pageSize);
+ std::swap(loc, other.loc);
+ std::swap(distributedJoins, other.distributedJoins);
+ std::swap(enforceJoinOrder, other.enforceJoinOrder);
+ std::swap(args, other.args);
+ }
+ }
+
+ /**
* Get SQL string.
*
* @return SQL string.
@@ -171,6 +203,56 @@ namespace ignite
}
/**
+ * Checks if join order of tables if enforced.
+ *
+ * @return Flag value.
+ */
+ bool IsEnforceJoinOrder() const
+ {
+ return enforceJoinOrder;
+ }
+
+ /**
+ * Sets flag to enforce join order of tables in the query.
+ * If set to true query optimizer will not reorder tables in
+ * join. By default is false.
+ *
+ * It is not recommended to enable this property unless you are
+ * sure that your indexes and the query itself are correct and
+ * tuned as much as possible but query optimizer still produces
+ * wrong join order.
+ *
+ * @param enforce Flag value.
+ */
+ void SetEnforceJoinOrder(bool enforce)
+ {
+ enforceJoinOrder = enforce;
+ }
+
+ /**
+ * Check if distributed joins are enabled for this query.
+ *
+ * @return True If distributed joind enabled.
+ */
+ bool IsDistributedJoins() const
+ {
+ return distributedJoins;
+ }
+
+ /**
+ * Specify if distributed joins are enabled for this query.
+ *
+ * When disabled, join results will only contain colocated data (joins work locally).
+ * When enabled, joins work as expected, no matter how the data is distributed.
+ *
+ * @param enabled Distributed joins enabled.
+ */
+ void SetDistributedJoins(bool enabled)
+ {
+ distributedJoins = enabled;
+ }
+
+ /**
* Add argument.
*
* Template argument type should be copy-constructable and
@@ -201,8 +283,8 @@ namespace ignite
for (std::vector<QueryArgumentBase*>::const_iterator it = args.begin(); it != args.end(); ++it)
(*it)->Write(writer);
- writer.WriteBool(false); // distributed joins
- writer.WriteBool(false); // enforce join order
+ writer.WriteBool(distributedJoins);
+ writer.WriteBool(enforceJoinOrder);
}
private:
@@ -215,6 +297,12 @@ namespace ignite
/** Local flag. */
bool loc;
+ /** Distributed joins flag. */
+ bool distributedJoins;
+
+ /** Enforce join order flag. */
+ bool enforceJoinOrder;
+
/** Arguments. */
std::vector<QueryArgumentBase*> args;
};
[28/50] [abbrv] ignite git commit: IGNITE-3561 .NET: DistributedJoins
property in SqlQuery & SqlFieldsQuery
Posted by vo...@apache.org.
IGNITE-3561 .NET: DistributedJoins property in SqlQuery & SqlFieldsQuery
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/856b536d
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/856b536d
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/856b536d
Branch: refs/heads/ignite-3553
Commit: 856b536db66edf9e7e6fc1b96da55a0e846c70c3
Parents: 37195a0
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Mon Jul 25 18:54:11 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Mon Jul 25 18:54:11 2016 +0300
----------------------------------------------------------------------
.../org/apache/ignite/cache/query/SqlQuery.java | 3 +
.../platform/cache/PlatformCache.java | 10 +-
.../core/include/ignite/cache/query/query_sql.h | 2 +
.../ignite/cache/query/query_sql_fields.h | 3 +
.../Cache/Query/CacheLinqTest.cs | 20 +-
.../Cache/Query/CacheQueriesTest.cs | 252 +++++--------------
.../Cache/Query/SqlFieldsQuery.cs | 27 +-
.../Apache.Ignite.Core/Cache/Query/SqlQuery.cs | 13 +
.../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs | 3 +
.../Apache.Ignite.Linq/CacheExtensions.cs | 39 ++-
.../Impl/CacheFieldsQueryExecutor.cs | 63 ++++-
.../Apache.Ignite.Linq/Impl/CacheQueryable.cs | 11 +-
.../Impl/CacheQueryableBase.cs | 7 +-
13 files changed, 257 insertions(+), 196 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
index e05ff13..f809b8d 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
@@ -154,6 +154,9 @@ public final class SqlQuery<K, V> extends Query<Cache.Entry<K, V>> {
/**
* Specify if distributed joins are enabled for this query.
*
+ * When disabled, join results will only contain colocated data (joins work locally).
+ * When enabled, joins work as expected, no matter how the data is distributed.
+ *
* @param distributedJoins Distributed joins enabled.
* @return {@code this} For chaining.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
index 9bf330c..d572e8b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/cache/PlatformCache.java
@@ -943,7 +943,9 @@ public class PlatformCache extends PlatformAbstractTarget {
Object[] args = readQueryArgs(reader);
- return new SqlQuery(typ, sql).setPageSize(pageSize).setArgs(args).setLocal(loc);
+ boolean distrJoins = reader.readBoolean();
+
+ return new SqlQuery(typ, sql).setPageSize(pageSize).setArgs(args).setLocal(loc).setDistributedJoins(distrJoins);
}
/**
@@ -956,7 +958,11 @@ public class PlatformCache extends PlatformAbstractTarget {
Object[] args = readQueryArgs(reader);
- return new SqlFieldsQuery(sql).setPageSize(pageSize).setArgs(args).setLocal(loc);
+ boolean distrJoins = reader.readBoolean();
+ boolean enforceJoinOrder = reader.readBoolean();
+
+ return new SqlFieldsQuery(sql).setPageSize(pageSize).setArgs(args).setLocal(loc)
+ .setDistributedJoins(distrJoins).setEnforceJoinOrder(enforceJoinOrder);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
index f7a00fa..cb7a739 100644
--- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
+++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql.h
@@ -228,6 +228,8 @@ namespace ignite
for (std::vector<QueryArgumentBase*>::const_iterator it = args.begin(); it != args.end(); ++it)
(*it)->Write(writer);
+
+ writer.WriteBool(false); // distributed joins
}
private:
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
index e21fc93..1c8570b 100644
--- a/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
+++ b/modules/platforms/cpp/core/include/ignite/cache/query/query_sql_fields.h
@@ -200,6 +200,9 @@ namespace ignite
for (std::vector<QueryArgumentBase*>::const_iterator it = args.begin(); it != args.end(); ++it)
(*it)->Write(writer);
+
+ writer.WriteBool(false); // distributed joins
+ writer.WriteBool(false); // enforce join order
}
private:
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
index 08a4bdc..f76a74c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
@@ -35,6 +35,8 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache;
using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Cache.Query;
+ using Apache.Ignite.Core.Common;
using Apache.Ignite.Linq;
using NUnit.Framework;
@@ -953,7 +955,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
var cache = GetPersonCache();
// Check regular query
- var query = (ICacheQueryable) cache.AsCacheQueryable(true).Where(x => x.Key > 10);
+ var query = (ICacheQueryable) cache.AsCacheQueryable(true, null, 999, false, true).Where(x => x.Key > 10);
Assert.AreEqual(cache.Name, query.CacheName);
Assert.AreEqual(cache.Ignite, query.Ignite);
@@ -963,6 +965,9 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
Assert.AreEqual(new[] {10}, fq.Arguments);
Assert.IsTrue(fq.Local);
Assert.AreEqual(PersonCount - 11, cache.QueryFields(fq).GetAll().Count);
+ Assert.AreEqual(999, fq.PageSize);
+ Assert.IsFalse(fq.EnableDistributedJoins);
+ Assert.IsTrue(fq.EnforceJoinOrder);
// Check fields query
var fieldsQuery = (ICacheQueryable) cache.AsCacheQueryable().Select(x => x.Value.Name);
@@ -973,6 +978,19 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
fq = fieldsQuery.GetFieldsQuery();
Assert.AreEqual("select _T0.Name from \"\".Person as _T0", fq.Sql);
Assert.IsFalse(fq.Local);
+ Assert.AreEqual(SqlFieldsQuery.DfltPageSize, fq.PageSize);
+ Assert.IsFalse(fq.EnableDistributedJoins);
+ Assert.IsFalse(fq.EnforceJoinOrder);
+
+ // Check distributed joins flag propagation
+ var distrQuery = cache.AsCacheQueryable(true, null, 999, true, true).Where(x => x.Key > 10);
+ query = (ICacheQueryable) distrQuery;
+ Assert.IsTrue(query.GetFieldsQuery().EnableDistributedJoins);
+
+ // Easy check that EnableDistributedJoins is propagated to Java: it throws an error on replicated cache
+ var ex = Assert.Throws<IgniteException>(() => Assert.AreEqual(0, distrQuery.ToArray().Length));
+ Assert.AreEqual("Queries using distributed JOINs have to be run on partitioned cache, not on replicated.",
+ ex.Message);
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
index 6ed76678..7bfd202 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
@@ -25,6 +25,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
using System.Text;
using Apache.Ignite.Core.Binary;
using Apache.Ignite.Core.Cache;
+ using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Cache.Query;
using Apache.Ignite.Core.Common;
using Apache.Ignite.Core.Impl.Binary;
@@ -33,7 +34,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// <summary>
/// Queries tests.
/// </summary>
- public class CacheQueriesTest
+ public sealed class CacheQueriesTest
{
/** Grid count. */
private const int GridCnt = 2;
@@ -51,7 +52,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
///
/// </summary>
[TestFixtureSetUp]
- public virtual void StartGrids()
+ public void StartGrids()
{
TestUtils.JvmDebug = true;
TestUtils.KillProcesses();
@@ -84,7 +85,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
///
/// </summary>
[TestFixtureTearDown]
- public virtual void StopGrids()
+ public void StopGrids()
{
for (int i = 0; i < GridCnt; i++)
Ignition.Stop("grid-" + i, true);
@@ -94,7 +95,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
///
/// </summary>
[SetUp]
- public virtual void BeforeTest()
+ public void BeforeTest()
{
Console.WriteLine("Test started: " + TestContext.CurrentContext.Test.Name);
}
@@ -103,7 +104,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
///
/// </summary>
[TearDown]
- public virtual void AfterTest()
+ public void AfterTest()
{
var cache = Cache();
@@ -126,7 +127,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
- public IIgnite GetIgnite(int idx)
+ private IIgnite GetIgnite(int idx)
{
return Ignition.GetIgnite("grid-" + idx);
}
@@ -136,7 +137,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
- public ICache<int, QueryPerson> Cache(int idx)
+ private ICache<int, QueryPerson> Cache(int idx)
{
return GetIgnite(idx).GetCache<int, QueryPerson>(CacheName);
}
@@ -145,7 +146,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
///
/// </summary>
/// <returns></returns>
- public ICache<int, QueryPerson> Cache()
+ private ICache<int, QueryPerson> Cache()
{
return Cache(0);
}
@@ -270,6 +271,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// <summary>
/// Test SQL query arguments passing.
/// </summary>
+ [Test]
public void TestSqlQueryArguments()
{
Cache().Put(1, new QueryPerson("Ivanov", 30));
@@ -289,6 +291,7 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// <summary>
/// Test SQL fields query arguments passing.
/// </summary>
+ [Test]
public void TestSqlFieldsQueryArguments()
{
Cache().Put(1, new QueryPerson("Ivanov", 30));
@@ -352,53 +355,19 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// Check SQL query.
/// </summary>
[Test]
- public void TestSqlQuery()
- {
- CheckSqlQuery(MaxItemCnt, false, false);
- }
-
- /// <summary>
- /// Check SQL query in binary mode.
- /// </summary>
- [Test]
- public void TestSqlQueryBinary()
- {
- CheckSqlQuery(MaxItemCnt, false, true);
- }
-
- /// <summary>
- /// Check local SQL query.
- /// </summary>
- [Test]
- public void TestSqlQueryLocal()
- {
- CheckSqlQuery(MaxItemCnt, true, false);
- }
-
- /// <summary>
- /// Check local SQL query in binary mode.
- /// </summary>
- [Test]
- public void TestSqlQueryLocalBinary()
- {
- CheckSqlQuery(MaxItemCnt, true, true);
- }
-
- /// <summary>
- /// Check SQL query.
- /// </summary>
- /// <param name="cnt">Amount of cache entries to create.</param>
- /// <param name="loc">Local query flag.</param>
- /// <param name="keepBinary">Keep binary flag.</param>
- private void CheckSqlQuery(int cnt, bool loc, bool keepBinary)
+ public void TestSqlQuery([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary,
+ [Values(true, false)] bool distrJoin)
{
var cache = Cache();
// 1. Populate cache with data, calculating expected count in parallel.
- var exp = PopulateCache(cache, loc, cnt, x => x < 50);
+ var exp = PopulateCache(cache, loc, MaxItemCnt, x => x < 50);
// 2. Validate results.
- var qry = new SqlQuery(typeof(QueryPerson), "age < 50", loc);
+ var qry = new SqlQuery(typeof(QueryPerson), "age < 50", loc)
+ {
+ EnableDistributedJoins = distrJoin
+ };
ValidateQueryResults(cache, qry, exp, keepBinary);
}
@@ -407,35 +376,22 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// Check SQL fields query.
/// </summary>
[Test]
- public void TestSqlFieldsQuery()
+ public void TestSqlFieldsQuery([Values(true, false)] bool loc, [Values(true, false)] bool distrJoin,
+ [Values(true, false)] bool enforceJoinOrder)
{
- CheckSqlFieldsQuery(MaxItemCnt, false);
- }
+ int cnt = MaxItemCnt;
- /// <summary>
- /// Check local SQL fields query.
- /// </summary>
- [Test]
- public void TestSqlFieldsQueryLocal()
- {
- CheckSqlFieldsQuery(MaxItemCnt, true);
- }
-
- /// <summary>
- /// Check SQL fields query.
- /// </summary>
- /// <param name="cnt">Amount of cache entries to create.</param>
- /// <param name="loc">Local query flag.</param>
- private void CheckSqlFieldsQuery(int cnt, bool loc)
- {
var cache = Cache();
// 1. Populate cache with data, calculating expected count in parallel.
var exp = PopulateCache(cache, loc, cnt, x => x < 50);
- // 2. Vlaidate results.
- SqlFieldsQuery qry = loc ? new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50", true) :
- new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50");
+ // 2. Validate results.
+ var qry = new SqlFieldsQuery("SELECT name, age FROM QueryPerson WHERE age < 50", loc)
+ {
+ EnableDistributedJoins = distrJoin,
+ EnforceJoinOrder = enforceJoinOrder
+ };
using (IQueryCursor<IList> cursor = cache.QueryFields(qry))
{
@@ -471,113 +427,20 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// Check text query.
/// </summary>
[Test]
- public void TestTextQuery()
- {
- CheckTextQuery(MaxItemCnt, false, false);
- }
-
- /// <summary>
- /// Check SQL query in binary mode.
- /// </summary>
- [Test]
- public void TestTextQueryBinary()
- {
- CheckTextQuery(MaxItemCnt, false, true);
- }
-
- /// <summary>
- /// Check local SQL query.
- /// </summary>
- [Test]
- public void TestTextQueryLocal()
- {
- CheckTextQuery(MaxItemCnt, true, false);
- }
-
- /// <summary>
- /// Check local SQL query in binary mode.
- /// </summary>
- [Test]
- public void TestTextQueryLocalBinary()
- {
- CheckTextQuery(MaxItemCnt, true, true);
- }
-
- /// <summary>
- /// Check text query.
- /// </summary>
- /// <param name="cnt">Amount of cache entries to create.</param>
- /// <param name="loc">Local query flag.</param>
- /// <param name="keepBinary">Keep binary flag.</param>
- private void CheckTextQuery(int cnt, bool loc, bool keepBinary)
+ public void TestTextQuery([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary)
{
var cache = Cache();
// 1. Populate cache with data, calculating expected count in parallel.
- var exp = PopulateCache(cache, loc, cnt, x => x.ToString().StartsWith("1"));
+ var exp = PopulateCache(cache, loc, MaxItemCnt, x => x.ToString().StartsWith("1"));
// 2. Validate results.
- TextQuery qry = loc ? new TextQuery(typeof(QueryPerson), "1*", true) :
- new TextQuery(typeof(QueryPerson), "1*");
+ var qry = new TextQuery(typeof(QueryPerson), "1*", loc);
ValidateQueryResults(cache, qry, exp, keepBinary);
}
/// <summary>
- /// Check scan query.
- /// </summary>
- [Test]
- public void TestScanQuery()
- {
- CheckScanQuery<QueryPerson>(MaxItemCnt, false, false);
- }
-
- /// <summary>
- /// Check scan query in binary mode.
- /// </summary>
- [Test]
- public void TestScanQueryBinary()
- {
- CheckScanQuery<BinaryObject>(MaxItemCnt, false, true);
- }
-
- /// <summary>
- /// Check local scan query.
- /// </summary>
- [Test]
- public void TestScanQueryLocal()
- {
- CheckScanQuery<QueryPerson>(MaxItemCnt, true, false);
- }
-
- /// <summary>
- /// Check local scan query in binary mode.
- /// </summary>
- [Test]
- public void TestScanQueryLocalBinary()
- {
- CheckScanQuery<BinaryObject>(MaxItemCnt, true, true);
- }
-
- /// <summary>
- /// Check scan query with partitions.
- /// </summary>
- [Test]
- public void TestScanQueryPartitions([Values(true, false)] bool loc)
- {
- CheckScanQueryPartitions<QueryPerson>(MaxItemCnt, loc, false);
- }
-
- /// <summary>
- /// Check scan query with partitions in binary mode.
- /// </summary>
- [Test]
- public void TestScanQueryPartitionsBinary([Values(true, false)] bool loc)
- {
- CheckScanQueryPartitions<BinaryObject>(MaxItemCnt, loc, true);
- }
-
- /// <summary>
/// Tests that query attempt on non-indexed cache causes an exception.
/// </summary>
[Test]
@@ -603,12 +466,11 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// <summary>
/// Check scan query.
/// </summary>
- /// <param name="cnt">Amount of cache entries to create.</param>
- /// <param name="loc">Local query flag.</param>
- /// <param name="keepBinary">Keep binary flag.</param>
- private void CheckScanQuery<TV>(int cnt, bool loc, bool keepBinary)
+ [Test]
+ public void TestScanQuery<TV>([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary)
{
var cache = Cache();
+ var cnt = MaxItemCnt;
// No predicate
var exp = PopulateCache(cache, loc, cnt, x => true);
@@ -641,15 +503,14 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// <summary>
/// Checks scan query with partitions.
/// </summary>
- /// <param name="cnt">Amount of cache entries to create.</param>
- /// <param name="loc">Local query flag.</param>
- /// <param name="keepBinary">Keep binary flag.</param>
- private void CheckScanQueryPartitions<TV>(int cnt, bool loc, bool keepBinary)
+ [Test]
+ public void TestScanQueryPartitions<TV>([Values(true, false)] bool loc, [Values(true, false)] bool keepBinary)
{
StopGrids();
StartGrids();
var cache = Cache();
+ var cnt = MaxItemCnt;
var aff = cache.Ignite.GetAffinity(CacheName);
var exp = PopulateCache(cache, loc, cnt, x => true); // populate outside the loop (slow)
@@ -686,6 +547,39 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
}
/// <summary>
+ /// Tests the distributed joins flag.
+ /// </summary>
+ [Test]
+ public void TestDistributedJoins()
+ {
+ // Easy check that EnableDistributedJoins is propagated to Java: it throws an error on replicated cache
+ var cache = GetIgnite(0).GetOrCreateCache<int, QueryPerson>(
+ new CacheConfiguration("replicatedCache")
+ {
+ CacheMode = CacheMode.Replicated,
+ QueryEntities = new[]
+ {
+ new QueryEntity(typeof(QueryPerson))
+ {
+ Fields = new[] {new QueryField("age", typeof(int))}
+ }
+ }
+ });
+
+ cache[1] = new QueryPerson("Test", 150);
+
+ // Distributed joins disabled: query works
+ var qry = new SqlQuery(typeof(QueryPerson), "age < 50");
+ Assert.AreEqual(0, cache.Query(qry).GetAll().Count);
+
+ // Distributed joins enabled: query fails
+ qry.EnableDistributedJoins = true;
+ var ex = Assert.Throws<IgniteException>(() => Assert.AreEqual(0, cache.Query(qry).GetAll().Count));
+ Assert.AreEqual("Queries using distributed JOINs have to be run on partitioned cache, not on replicated.",
+ ex.Message);
+ }
+
+ /// <summary>
/// Validates the query results.
/// </summary>
/// <param name="cache">Cache.</param>
@@ -853,14 +747,6 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
/// <summary>
/// Constructor.
/// </summary>
- public QueryPerson()
- {
- // No-op.
- }
-
- /// <summary>
- /// Constructor.
- /// </summary>
/// <param name="name">Name.</param>
/// <param name="age">Age.</param>
public QueryPerson(string name, int age)
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
index 1753a8b..ed9d0eb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlFieldsQuery.cs
@@ -74,8 +74,33 @@ namespace Apache.Ignite.Core.Cache.Query
/// <summary>
/// Optional page size.
/// <para />
- /// Defautls to <see cref="DfltPageSize"/>.
+ /// Defaults to <see cref="DfltPageSize"/>.
/// </summary>
public int PageSize { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether distributed joins should be enabled for this query.
+ /// <para />
+ /// When disabled, join results will only contain colocated data (joins work locally).
+ /// When enabled, joins work as expected, no matter how the data is distributed.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if enable distributed joins should be enabled; otherwise, <c>false</c>.
+ /// </value>
+ public bool EnableDistributedJoins { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether join order of tables should be enforced.
+ /// <para />
+ /// When true, query optimizer will not reorder tables in join.
+ /// <para />
+ /// It is not recommended to enable this property until you are sure that your indexes
+ /// and the query itself are correct and tuned as much as possible but
+ /// query optimizer still produces wrong join order.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if join order should be enforced; otherwise, <c>false</c>.
+ /// </value>
+ public bool EnforceJoinOrder { get; set; }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs
index 0e3c887..70e08b2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Query/SqlQuery.cs
@@ -97,6 +97,17 @@ namespace Apache.Ignite.Core.Cache.Query
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays")]
public object[] Arguments { get; set; }
+ /// <summary>
+ /// Gets or sets a value indicating whether distributed joins should be enabled for this query.
+ /// <para />
+ /// When disabled, join results will only contain colocated data (joins work locally).
+ /// When enabled, joins work as expected, no matter how the data is distributed.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if enable distributed joins should be enabled; otherwise, <c>false</c>.
+ /// </value>
+ public bool EnableDistributedJoins { get; set; }
+
/** <inheritDoc /> */
internal override void Write(BinaryWriter writer, bool keepBinary)
{
@@ -113,6 +124,8 @@ namespace Apache.Ignite.Core.Cache.Query
writer.WriteInt(PageSize);
WriteQueryArgs(writer, Arguments);
+
+ writer.WriteBoolean(EnableDistributedJoins);
}
/** <inheritDoc /> */
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
index 6afbc67..32c59de 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Cache/CacheImpl.cs
@@ -977,6 +977,9 @@ namespace Apache.Ignite.Core.Impl.Cache
WriteQueryArgs(writer, qry.Arguments);
+ writer.WriteBoolean(qry.EnableDistributedJoins);
+ writer.WriteBoolean(qry.EnforceJoinOrder);
+
FinishMarshal(writer);
cursor = UU.CacheOutOpQueryCursor(Target, (int) CacheOp.QrySqlFields, stream.SynchronizeOutput());
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
index ecea4ed..e6d585c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
@@ -20,6 +20,7 @@ namespace Apache.Ignite.Linq
using System.Linq;
using Apache.Ignite.Core.Cache;
using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Cache.Query;
using Apache.Ignite.Linq.Impl;
/// <summary>
@@ -92,7 +93,43 @@ namespace Apache.Ignite.Linq
public static IQueryable<ICacheEntry<TKey, TValue>> AsCacheQueryable<TKey, TValue>(
this ICache<TKey, TValue> cache, bool local, string tableName)
{
- return new CacheQueryable<TKey, TValue>(cache, local, tableName);
+ return cache.AsCacheQueryable(local, tableName, SqlFieldsQuery.DfltPageSize, false, false);
+ }
+
+ /// <summary>
+ /// Gets an <see cref="IQueryable{T}" /> instance over this cache.
+ /// <para />
+ /// Resulting query will be translated to cache SQL query and executed over the cache instance
+ /// via either <see cref="ICache{TK,TV}.Query" /> or <see cref="ICache{TK,TV}.QueryFields" />,
+ /// depending on requested result.
+ /// <para />
+ /// Result of this method (and subsequent query) can be cast to <see cref="ICacheQueryable" /> for introspection.
+ /// </summary>
+ /// <typeparam name="TKey">The type of the key.</typeparam>
+ /// <typeparam name="TValue">The type of the value.</typeparam>
+ /// <param name="cache">The cache.</param>
+ /// <param name="local">Local flag. When set query will be executed only on local node, so only local
+ /// entries will be returned as query result.</param>
+ /// <param name="tableName">Name of the table.
+ /// <para />
+ /// Table name is equal to short class name of a cache value.
+ /// When a cache has only one type of values, or only one <see cref="QueryEntity" /> defined,
+ /// table name will be inferred and can be omitted.</param>
+ /// <param name="pageSize">Query cursor page size.
+ /// Defaults to <see cref="SqlFieldsQuery.DfltPageSize"/>.</param>
+ /// <param name="enableDistributedJoins">Distributed joins option, see
+ /// <see cref="SqlFieldsQuery.EnableDistributedJoins" />.</param>
+ /// <param name="enforceJoinOrder">Enforce join order flag,
+ /// see <see cref="SqlFieldsQuery.EnforceJoinOrder" />.</param>
+ /// <returns>
+ /// <see cref="IQueryable{T}" /> instance over this cache.
+ /// </returns>
+ public static IQueryable<ICacheEntry<TKey, TValue>> AsCacheQueryable<TKey, TValue>(
+ this ICache<TKey, TValue> cache, bool local, string tableName, int pageSize,
+ bool enableDistributedJoins, bool enforceJoinOrder)
+ {
+ return new CacheQueryable<TKey, TValue>(cache, local, tableName, pageSize, enableDistributedJoins,
+ enforceJoinOrder);
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
index c715e4c..7464a03 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheFieldsQueryExecutor.cs
@@ -46,17 +46,33 @@ namespace Apache.Ignite.Linq.Impl
/** */
private readonly bool _local;
+ /** */
+ private readonly int _pageSize;
+
+ /** */
+ private readonly bool _enableDistributedJoins;
+
+ /** */
+ private readonly bool _enforceJoinOrder;
+
/// <summary>
/// Initializes a new instance of the <see cref="CacheFieldsQueryExecutor" /> class.
/// </summary>
/// <param name="cache">The executor function.</param>
/// <param name="local">Local flag.</param>
- public CacheFieldsQueryExecutor(ICacheInternal cache, bool local)
+ /// <param name="pageSize">Size of the page.</param>
+ /// <param name="enableDistributedJoins">Distributed joins flag.</param>
+ /// <param name="enforceJoinOrder">Enforce join order flag.</param>
+ public CacheFieldsQueryExecutor(ICacheInternal cache, bool local, int pageSize, bool enableDistributedJoins,
+ bool enforceJoinOrder)
{
Debug.Assert(cache != null);
_cache = cache;
_local = local;
+ _pageSize = pageSize;
+ _enableDistributedJoins = enableDistributedJoins;
+ _enforceJoinOrder = enforceJoinOrder;
}
/// <summary>
@@ -67,6 +83,30 @@ namespace Apache.Ignite.Linq.Impl
get { return _local; }
}
+ /// <summary>
+ /// Gets the size of the page.
+ /// </summary>
+ public int PageSize
+ {
+ get { return _pageSize; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether distributed joins are enabled.
+ /// </summary>
+ public bool EnableDistributedJoins
+ {
+ get { return _enableDistributedJoins; }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether join order should be enforced.
+ /// </summary>
+ public bool EnforceJoinOrder
+ {
+ get { return _enforceJoinOrder; }
+ }
+
/** <inheritdoc /> */
public T ExecuteScalar<T>(QueryModel queryModel)
{
@@ -92,7 +132,12 @@ namespace Apache.Ignite.Linq.Impl
Debug.WriteLine("\nFields Query: {0} | {1}", qryData.QueryText,
string.Join(", ", qryData.Parameters.Select(x => x == null ? "null" : x.ToString())));
- var qry = new SqlFieldsQuery(qryData.QueryText, _local, qryData.Parameters.ToArray());
+ var qry = new SqlFieldsQuery(qryData.QueryText, _local, qryData.Parameters.ToArray())
+ {
+ EnableDistributedJoins = _enableDistributedJoins,
+ PageSize = _pageSize,
+ EnforceJoinOrder = _enforceJoinOrder
+ };
var selector = GetResultSelector<T>(queryModel.SelectClause.Selector);
@@ -132,11 +177,21 @@ namespace Apache.Ignite.Linq.Impl
// Check if user param order is already correct
if (indices.SequenceEqual(Enumerable.Range(0, indices.Length)))
- return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local, args), selector);
+ return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local, args)
+ {
+ EnableDistributedJoins = _enableDistributedJoins,
+ PageSize = _pageSize,
+ EnforceJoinOrder = _enforceJoinOrder
+ }, selector);
// Return delegate with reorder
return args => _cache.QueryFields(new SqlFieldsQuery(qryText, _local,
- args.Select((x, i) => args[indices[i]]).ToArray()), selector);
+ args.Select((x, i) => args[indices[i]]).ToArray())
+ {
+ EnableDistributedJoins = _enableDistributedJoins,
+ PageSize = _pageSize,
+ EnforceJoinOrder = _enforceJoinOrder
+ }, selector);
}
/** <inheritdoc /> */
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
index 959cc4b..7ade159 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
@@ -32,10 +32,15 @@ namespace Apache.Ignite.Linq.Impl
/// <param name="cache">The cache.</param>
/// <param name="local">Local flag.</param>
/// <param name="tableName">Name of the table.</param>
- public CacheQueryable(ICache<TKey, TValue> cache, bool local, string tableName)
+ /// <param name="pageSize">Size of the page.</param>
+ /// <param name="enableDistributedJoins">Distributed joins flag.</param>
+ /// <param name="enforceJoinOrder">Enforce join order flag.</param>
+ public CacheQueryable(ICache<TKey, TValue> cache, bool local, string tableName, int pageSize,
+ bool enableDistributedJoins,
+ bool enforceJoinOrder)
: base(new CacheFieldsQueryProvider(CacheQueryParser.Instance,
- new CacheFieldsQueryExecutor((ICacheInternal) cache, local),
- cache.Ignite, cache.GetConfiguration(), tableName, typeof(TValue)))
+ new CacheFieldsQueryExecutor((ICacheInternal) cache, local, pageSize, enableDistributedJoins,
+ enforceJoinOrder), cache.Ignite, cache.GetConfiguration(), tableName, typeof(TValue)))
{
// No-op.
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/856b536d/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs
index d3115be..4b461bf 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryableBase.cs
@@ -66,7 +66,12 @@ namespace Apache.Ignite.Linq.Impl
var data = GetQueryData();
var executor = CacheQueryProvider.Executor;
- return new SqlFieldsQuery(data.QueryText, executor.Local, data.Parameters.ToArray());
+ return new SqlFieldsQuery(data.QueryText, executor.Local, data.Parameters.ToArray())
+ {
+ EnableDistributedJoins = executor.EnableDistributedJoins,
+ EnforceJoinOrder = executor.EnforceJoinOrder,
+ PageSize = executor.PageSize
+ };
}
/** <inheritdoc /> */
[12/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 6a079f0..04449ac 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
@@ -31,6 +31,7 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.NavigableMap;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
@@ -59,11 +60,13 @@ import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionFullMap;
import org.apache.ignite.internal.processors.cache.distributed.dht.preloader.GridDhtPartitionMap2;
+import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
import org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator;
import org.apache.ignite.internal.processors.query.h2.GridH2ResultSetIterator;
import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext;
import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter;
import org.apache.ignite.internal.processors.query.h2.sql.GridSqlType;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryCancelRequest;
@@ -71,11 +74,14 @@ import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQuery
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryNextPageRequest;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryNextPageResponse;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryRequest;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2QueryRequest;
import org.apache.ignite.internal.util.GridSpinBusyLock;
+import org.apache.ignite.internal.util.typedef.CIX2;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiClosure;
import org.apache.ignite.lang.IgniteFuture;
-import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.lang.IgniteProductVersion;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.h2.command.ddl.CreateTableData;
import org.h2.engine.Session;
@@ -92,6 +98,7 @@ import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
import static org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion.NONE;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.REDUCE;
/**
* Reduce query executor.
@@ -101,6 +108,9 @@ public class GridReduceQueryExecutor {
public static final byte QUERY_POOL = GridIoPolicy.SYSTEM_POOL;
/** */
+ private static final IgniteProductVersion DISTRIBUTED_JOIN_SINCE = IgniteProductVersion.fromString("1.7.0");
+
+ /** */
private GridKernalContext ctx;
/** */
@@ -149,6 +159,13 @@ public class GridReduceQueryExecutor {
/** */
private final GridSpinBusyLock busyLock;
+ /** */
+ private final CIX2<ClusterNode,Message> locNodeHnd = new CIX2<ClusterNode,Message>() {
+ @Override public void applyx(ClusterNode locNode, Message msg) {
+ h2.mapQueryExecutor().onMessage(locNode.id(), msg);
+ }
+ };
+
/**
* @param busyLock Busy lock.
*/
@@ -173,6 +190,9 @@ public class GridReduceQueryExecutor {
return;
try {
+ if (msg instanceof GridCacheQueryMarshallable)
+ ((GridCacheQueryMarshallable)msg).unmarshall(ctx.config().getMarshaller(), ctx);
+
GridReduceQueryExecutor.this.onMessage(nodeId, msg);
}
finally {
@@ -339,13 +359,13 @@ public class GridReduceQueryExecutor {
* @param extraSpaces Extra spaces.
* @return {@code true} If preloading is active.
*/
- private boolean isPreloadingActive(final GridCacheContext<?,?> cctx, List<String> extraSpaces) {
+ private boolean isPreloadingActive(final GridCacheContext<?, ?> cctx, List<Integer> extraSpaces) {
if (hasMovingPartitions(cctx))
return true;
if (extraSpaces != null) {
- for (String extraSpace : extraSpaces) {
- if (hasMovingPartitions(cacheContext(extraSpace)))
+ for (int i = 0; i < extraSpaces.size(); i++) {
+ if (hasMovingPartitions(cacheContext(extraSpaces.get(i))))
return true;
}
}
@@ -357,7 +377,7 @@ public class GridReduceQueryExecutor {
* @param cctx Cache context.
* @return {@code true} If cache context
*/
- private boolean hasMovingPartitions(GridCacheContext<?,?> cctx) {
+ private boolean hasMovingPartitions(GridCacheContext<?, ?> cctx) {
GridDhtPartitionFullMap fullMap = cctx.topology().partitionMap(false);
for (GridDhtPartitionMap2 map : fullMap.values()) {
@@ -369,34 +389,34 @@ public class GridReduceQueryExecutor {
}
/**
- * @param name Cache name.
+ * @param cacheId Cache ID.
* @return Cache context.
*/
- private GridCacheContext<?,?> cacheContext(String name) {
- return ctx.cache().internalCache(name).context();
+ private GridCacheContext<?,?> cacheContext(Integer cacheId) {
+ return ctx.cache().context().cacheContext(cacheId);
}
/**
* @param topVer Topology version.
* @param cctx Cache context for main space.
* @param extraSpaces Extra spaces.
- * @return Data nodes or {@code null} if repartitioning started and we need to retry..
+ * @return Data nodes or {@code null} if repartitioning started and we need to retry.
*/
private Collection<ClusterNode> stableDataNodes(
AffinityTopologyVersion topVer,
- final GridCacheContext<?,?> cctx,
- List<String> extraSpaces
+ final GridCacheContext<?, ?> cctx,
+ List<Integer> extraSpaces
) {
- String space = cctx.name();
-
Set<ClusterNode> nodes = new HashSet<>(cctx.affinity().assignment(topVer).primaryPartitionNodes());
if (F.isEmpty(nodes))
- throw new CacheException("Failed to find data nodes for cache: " + space);
+ throw new CacheException("Failed to find data nodes for cache: " + cctx.name());
if (!F.isEmpty(extraSpaces)) {
- for (String extraSpace : extraSpaces) {
- GridCacheContext<?,?> extraCctx = cacheContext(extraSpace);
+ for (int i = 0; i < extraSpaces.size(); i++) {
+ GridCacheContext<?,?> extraCctx = cacheContext(extraSpaces.get(i));
+
+ String extraSpace = extraCctx.name();
if (extraCctx.isLocal())
continue; // No consistency guaranties for local caches.
@@ -448,10 +468,16 @@ public class GridReduceQueryExecutor {
/**
* @param cctx Cache context.
* @param qry Query.
- * @param keepBinary Keep binary.
+ * @param keepPortable Keep portable.
+ * @param enforceJoinOrder Enforce join order of tables.
* @return Cursor.
*/
- public Iterator<List<?>> query(GridCacheContext<?,?> cctx, GridCacheTwoStepQuery qry, boolean keepBinary) {
+ public Iterator<List<?>> query(
+ GridCacheContext<?, ?> cctx,
+ GridCacheTwoStepQuery qry,
+ boolean keepPortable,
+ boolean enforceJoinOrder
+ ) {
for (int attempt = 0;; attempt++) {
if (attempt != 0) {
try {
@@ -464,21 +490,15 @@ public class GridReduceQueryExecutor {
}
}
- long qryReqId = reqIdGen.incrementAndGet();
+ final long qryReqId = reqIdGen.incrementAndGet();
- QueryRun r = new QueryRun();
+ final String space = cctx.name();
- r.pageSize = qry.pageSize() <= 0 ? GridCacheTwoStepQuery.DFLT_PAGE_SIZE : qry.pageSize();
-
- r.idxs = new ArrayList<>(qry.mapQueries().size());
-
- String space = cctx.name();
-
- r.conn = (JdbcConnection)h2.connectionForSpace(space);
+ final QueryRun r = new QueryRun(h2.connectionForSpace(space), qry.mapQueries().size(), qry.pageSize());
AffinityTopologyVersion topVer = h2.readyTopologyVersion();
- List<String> extraSpaces = extraSpaces(space, qry.spaces());
+ List<Integer> extraSpaces = qry.extraCaches();
Collection<ClusterNode> nodes;
@@ -529,13 +549,12 @@ public class GridReduceQueryExecutor {
idx = tbl.getScanIndex(null);
- fakeTable(r.conn, tblIdx++).setInnerTable(tbl);
+ fakeTable(r.conn, tblIdx++).innerTable(tbl);
}
else
idx = GridMergeIndexUnsorted.createDummy(ctx);
- for (ClusterNode node : nodes)
- idx.addSource(node.id());
+ idx.setSources(nodes);
r.idxs.add(idx);
}
@@ -548,10 +567,10 @@ public class GridReduceQueryExecutor {
if (ctx.clientDisconnected()) {
throw new CacheException("Query was cancelled, client node disconnected.",
new IgniteClientDisconnectedException(ctx.cluster().clientReconnectFuture(),
- "Client node disconnected."));
+ "Client node disconnected."));
}
- Collection<GridCacheSqlQuery> mapQrys = qry.mapQueries();
+ List<GridCacheSqlQuery> mapQrys = qry.mapQueries();
if (qry.explain()) {
mapQrys = new ArrayList<>(qry.mapQueries().size());
@@ -560,17 +579,37 @@ public class GridReduceQueryExecutor {
mapQrys.add(new GridCacheSqlQuery("EXPLAIN " + mapQry.query(), mapQry.parameters()));
}
- if (nodes.size() != 1 || !F.first(nodes).isLocal()) { // Marshall params for remotes.
- Marshaller m = ctx.config().getMarshaller();
+ boolean retry = false;
- for (GridCacheSqlQuery mapQry : mapQrys)
- mapQry.marshallParams(m);
- }
+ IgniteProductVersion minNodeVer = cctx.shared().exchange().minimumNodeVersion(topVer);
- boolean retry = false;
+ final boolean oldStyle = minNodeVer.compareToIgnoreTimestamp(DISTRIBUTED_JOIN_SINCE) < 0;
+ final boolean distributedJoins = qry.distributedJoins();
+
+ if (oldStyle && distributedJoins)
+ throw new CacheException("Failed to enable distributed joins. Topology contains older data nodes.");
if (send(nodes,
- new GridQueryRequest(qryReqId, r.pageSize, space, mapQrys, topVer, extraSpaces, null), partsMap)) {
+ oldStyle ?
+ new GridQueryRequest(qryReqId,
+ r.pageSize,
+ space,
+ mapQrys,
+ topVer,
+ extraSpaces(space, qry.spaces()),
+ null) :
+ new GridH2QueryRequest()
+ .requestId(qryReqId)
+ .topologyVersion(topVer)
+ .pageSize(r.pageSize)
+ .caches(qry.caches())
+ .tables(distributedJoins ? qry.tables() : null)
+ .partitions(convert(partsMap))
+ .queries(mapQrys)
+ .flags(distributedJoins ? GridH2QueryRequest.FLAG_DISTRIBUTED_JOINS : 0),
+ oldStyle && partsMap != null ? new ExplicitPartitionsSpecializer(partsMap) : null,
+ distributedJoins)
+ ) {
awaitAllReplies(r, nodes);
Object state = r.state.get();
@@ -599,9 +638,6 @@ public class GridReduceQueryExecutor {
Iterator<List<?>> resIter = null;
if (!retry) {
- if (qry.explain())
- return explainPlan(r.conn, space, qry);
-
if (skipMergeTbl) {
List<List<?>> res = new ArrayList<>();
@@ -616,7 +652,7 @@ public class GridReduceQueryExecutor {
int cols = row.getColumnCount();
- List<Object> resRow = new ArrayList<>(cols);
+ List<Object> resRow = new ArrayList<>(cols);
for (int c = 0; c < cols; c++)
resRow.add(row.getValue(c).getObject());
@@ -627,32 +663,52 @@ public class GridReduceQueryExecutor {
resIter = res.iterator();
}
else {
- GridCacheSqlQuery rdc = qry.reduceQuery();
+ UUID locNodeId = ctx.localNodeId();
- // 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);
+ h2.setupConnection(r.conn, false, enforceJoinOrder);
- resIter = new Iter(res);
- }
- }
+ GridH2QueryContext.set(new GridH2QueryContext(locNodeId, locNodeId, qryReqId, REDUCE)
+ .pageSize(r.pageSize).distributedJoins(false));
- for (GridMergeIndex idx : r.idxs) {
- if (!idx.fetchedAll()) // We have to explicitly cancel queries on remote nodes.
- send(nodes, new GridQueryCancelRequest(qryReqId), null);
+ try {
+ if (qry.explain())
+ return explainPlan(r.conn, space, qry);
+
+ GridCacheSqlQuery rdc = qry.reduceQuery();
+
+ ResultSet res = h2.executeSqlQueryWithTimer(space,
+ r.conn,
+ rdc.query(),
+ F.asList(rdc.parameters()),
+ false);
+
+ resIter = new Iter(res);
+ }
+ finally {
+ GridH2QueryContext.clearThreadLocal();
+ }
+ }
}
if (retry) {
+ send(nodes, new GridQueryCancelRequest(qryReqId), null, false);
+
if (Thread.currentThread().isInterrupted())
throw new IgniteInterruptedCheckedException("Query was interrupted.");
continue;
}
- return new GridQueryCacheObjectsIterator(resIter, cctx, keepBinary);
+ final Collection<ClusterNode> finalNodes = nodes;
+
+ return new GridQueryCacheObjectsIterator(resIter, cctx, keepPortable) {
+ @Override public void close() throws Exception {
+ super.close();
+
+ if (distributedJoins || !allIndexesFetched(r.idxs))
+ send(finalNodes, new GridQueryCancelRequest(qryReqId), null, false);
+ }
+ };
}
catch (IgniteCheckedException | RuntimeException e) {
U.closeQuiet(r.conn);
@@ -678,13 +734,26 @@ public class GridReduceQueryExecutor {
if (!skipMergeTbl) {
for (int i = 0, mapQrys = qry.mapQueries().size(); i < mapQrys; i++)
- fakeTable(null, i).setInnerTable(null); // Drop all merge tables.
+ fakeTable(null, i).innerTable(null); // Drop all merge tables.
}
}
}
}
/**
+ * @param idxs Merge indexes.
+ * @return {@code true} If all remote data was fetched.
+ */
+ private static boolean allIndexesFetched(List<GridMergeIndex> idxs) {
+ for (int i = 0; i < idxs.size(); i++) {
+ if (!idxs.get(i).fetchedAll())
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
* @param r Query run.
* @param nodes Nodes to check periodically if they alive.
* @throws IgniteInterruptedCheckedException If interrupted.
@@ -715,6 +784,7 @@ public class GridReduceQueryExecutor {
/**
* Gets or creates new fake table for index.
*
+ * @param c Connection.
* @param idx Index of table.
* @return Table.
*/
@@ -759,8 +829,8 @@ public class GridReduceQueryExecutor {
* @param extraSpaces Extra spaces.
* @return Collection of all data nodes owning all the caches or {@code null} for retry.
*/
- private Collection<ClusterNode> replicatedUnstableDataNodes(final GridCacheContext<?,?> cctx,
- List<String> extraSpaces) {
+ private Collection<ClusterNode> replicatedUnstableDataNodes(final GridCacheContext<?, ?> cctx,
+ List<Integer> extraSpaces) {
assert cctx.isReplicated() : cctx.name() + " must be replicated";
Set<ClusterNode> nodes = replicatedUnstableDataNodes(cctx);
@@ -769,15 +839,15 @@ public class GridReduceQueryExecutor {
return null; // Retry.
if (!F.isEmpty(extraSpaces)) {
- for (String extraSpace : extraSpaces) {
- GridCacheContext<?,?> extraCctx = cacheContext(extraSpace);
+ for (int i = 0; i < extraSpaces.size(); i++) {
+ GridCacheContext<?, ?> extraCctx = cacheContext(extraSpaces.get(i));
if (extraCctx.isLocal())
continue;
if (!extraCctx.isReplicated())
throw new CacheException("Queries running on replicated cache should not contain JOINs " +
- "with tables in partitioned caches [rCache=" + cctx.name() + ", pCache=" + extraSpace + "]");
+ "with tables in partitioned caches [rCache=" + cctx.name() + ", pCache=" + extraCctx.name() + "]");
Set<ClusterNode> extraOwners = replicatedUnstableDataNodes(extraCctx);
@@ -846,14 +916,14 @@ public class GridReduceQueryExecutor {
*/
@SuppressWarnings("unchecked")
private Map<ClusterNode, IntArray> partitionedUnstableDataNodes(final GridCacheContext<?,?> cctx,
- List<String> extraSpaces) {
+ List<Integer> extraSpaces) {
assert !cctx.isReplicated() && !cctx.isLocal() : cctx.name() + " must be partitioned";
final int partsCnt = cctx.affinity().partitions();
if (extraSpaces != null) { // Check correct number of partitions for partitioned caches.
- for (String extraSpace : extraSpaces) {
- GridCacheContext<?,?> extraCctx = cacheContext(extraSpace);
+ for (int i = 0; i < extraSpaces.size(); i++) {
+ GridCacheContext<?, ?> extraCctx = cacheContext(extraSpaces.get(i));
if (extraCctx.isReplicated() || extraCctx.isLocal())
continue;
@@ -862,7 +932,7 @@ public class GridReduceQueryExecutor {
if (parts != partsCnt)
throw new CacheException("Number of partitions must be the same for correct collocation [cache1=" +
- cctx.name() + ", parts1=" + partsCnt + ", cache2=" + extraSpace + ", parts2=" + parts + "]");
+ cctx.name() + ", parts1=" + partsCnt + ", cache2=" + extraCctx.name() + ", parts2=" + parts + "]");
}
}
@@ -885,8 +955,8 @@ public class GridReduceQueryExecutor {
if (extraSpaces != null) {
// Find owner intersections for each participating partitioned cache partition.
// We need this for logical collocation between different partitioned caches with the same affinity.
- for (String extraSpace : extraSpaces) {
- GridCacheContext<?,?> extraCctx = cacheContext(extraSpace);
+ for (int i = 0; i < extraSpaces.size(); i++) {
+ GridCacheContext<?, ?> extraCctx = cacheContext(extraSpaces.get(i));
if (extraCctx.isReplicated() || extraCctx.isLocal())
continue;
@@ -895,10 +965,10 @@ public class GridReduceQueryExecutor {
List<ClusterNode> owners = extraCctx.topology().owners(p);
if (F.isEmpty(owners)) {
- if (!F.isEmpty(dataNodes(extraSpace, NONE)))
+ if (!F.isEmpty(dataNodes(extraCctx.name(), NONE)))
return null; // Retry.
- throw new CacheException("Failed to find data nodes [cache=" + extraSpace + ", part=" + p + "]");
+ throw new CacheException("Failed to find data nodes [cache=" + extraCctx.name() + ", part=" + p + "]");
}
if (partLocs[p] == null)
@@ -913,8 +983,8 @@ public class GridReduceQueryExecutor {
}
// Filter nodes where not all the replicated caches loaded.
- for (String extraSpace : extraSpaces) {
- GridCacheContext<?,?> extraCctx = cacheContext(extraSpace);
+ for (int i = 0; i < extraSpaces.size(); i++) {
+ GridCacheContext<?,?> extraCctx = cacheContext(extraSpaces.get(i));
if (!extraCctx.isReplicated())
continue;
@@ -960,7 +1030,7 @@ public class GridReduceQueryExecutor {
* @param allSpaces All spaces.
* @return List of all extra spaces or {@code null} if none.
*/
- private List<String> extraSpaces(String mainSpace, Set<String> allSpaces) {
+ private List<String> extraSpaces(String mainSpace, Collection<String> allSpaces) {
if (F.isEmpty(allSpaces) || (allSpaces.size() == 1 && allSpaces.contains(mainSpace)))
return null;
@@ -996,7 +1066,7 @@ public class GridReduceQueryExecutor {
for (GridCacheSqlQuery mapQry : qry.mapQueries()) {
GridMergeTable tbl = createMergeTable(c, mapQry, false);
- fakeTable(c, tblIdx++).setInnerTable(tbl);
+ fakeTable(c, tblIdx++).innerTable(tbl);
}
GridCacheSqlQuery rdc = qry.reduceQuery();
@@ -1032,39 +1102,27 @@ public class GridReduceQueryExecutor {
/**
* @param nodes Nodes.
* @param msg Message.
- * @param partsMap Partitions.
+ * @param specialize Optional closure to specialize message for each node.
+ * @param runLocParallel Run local handler in parallel thread.
* @return {@code true} If all messages sent successfully.
*/
private boolean send(
Collection<ClusterNode> nodes,
Message msg,
- Map<ClusterNode,IntArray> partsMap
+ @Nullable IgniteBiClosure<ClusterNode, Message, Message> specialize,
+ boolean runLocParallel
) {
- boolean locNodeFound = false;
-
- boolean ok = true;
-
- for (ClusterNode node : nodes) {
- if (node.isLocal()) {
- locNodeFound = true;
-
- continue;
- }
-
- try {
- ctx.io().send(node, GridTopic.TOPIC_QUERY, copy(msg, node, partsMap), QUERY_POOL);
- }
- catch (IgniteCheckedException e) {
- ok = false;
-
- U.warn(log, e.getMessage());
- }
- }
-
- if (locNodeFound) // Local node goes the last to allow parallel execution.
- h2.mapQueryExecutor().onMessage(ctx.localNodeId(), copy(msg, ctx.discovery().localNode(), partsMap));
-
- return ok;
+ if (log.isDebugEnabled())
+ log.debug("Sending: [msg=" + msg + ", nodes=" + nodes + ", specialize=" + specialize + "]");
+
+ return h2.send(GridTopic.TOPIC_QUERY,
+ GridTopic.TOPIC_QUERY.ordinal(),
+ nodes,
+ msg,
+ specialize,
+ locNodeHnd,
+ QUERY_POOL,
+ runLocParallel);
}
/**
@@ -1074,8 +1132,7 @@ public class GridReduceQueryExecutor {
* @return Copy of message with partitions set.
*/
private Message copy(Message msg, ClusterNode node, Map<ClusterNode,IntArray> partsMap) {
- if (partsMap == null)
- return msg;
+ assert partsMap != null;
GridQueryRequest res = new GridQueryRequest((GridQueryRequest)msg);
@@ -1083,11 +1140,35 @@ public class GridReduceQueryExecutor {
assert parts != null : node;
- int[] partsArr = new int[parts.size()];
+ res.partitions(toArray(parts));
- parts.toArray(partsArr);
+ return res;
+ }
- res.partitions(partsArr);
+ /**
+ * @param ints Ints.
+ * @return Array.
+ */
+ public static int[] toArray(IntArray ints) {
+ int[] res = new int[ints.size()];
+
+ ints.toArray(res);
+
+ return res;
+ }
+
+ /**
+ * @param m Map.
+ * @return Converted map.
+ */
+ private static Map<UUID, int[]> convert(Map<ClusterNode, IntArray> m) {
+ if (m == null)
+ return null;
+
+ Map<UUID, int[]> res = U.newHashMap(m.size());
+
+ for (Map.Entry<ClusterNode,IntArray> entry : m.entrySet())
+ res.put(entry.getKey().id(), toArray(entry.getValue()));
return res;
}
@@ -1097,7 +1178,7 @@ public class GridReduceQueryExecutor {
* @param qry Query.
* @param explain Explain.
* @return Table.
- * @throws IgniteCheckedException
+ * @throws IgniteCheckedException If failed.
*/
private GridMergeTable createMergeTable(JdbcConnection conn, GridCacheSqlQuery qry, boolean explain)
throws IgniteCheckedException {
@@ -1165,25 +1246,36 @@ public class GridReduceQueryExecutor {
}
/**
- *
+ * Query run.
*/
private static class QueryRun {
/** */
- private List<GridMergeIndex> idxs;
+ private final List<GridMergeIndex> idxs;
/** */
private CountDownLatch latch;
/** */
- private JdbcConnection conn;
+ private final JdbcConnection conn;
/** */
- private int pageSize;
+ private final int pageSize;
/** Can be either CacheException in case of error or AffinityTopologyVersion to retry if needed. */
private final AtomicReference<Object> state = new AtomicReference<>();
/**
+ * @param conn Connection.
+ * @param idxsCnt Number of indexes.
+ * @param pageSize Page size.
+ */
+ private QueryRun(Connection conn, int idxsCnt, int pageSize) {
+ this.conn = (JdbcConnection)conn;
+ this.idxs = new ArrayList<>(idxsCnt);
+ this.pageSize = pageSize > 0 ? pageSize : GridCacheTwoStepQuery.DFLT_PAGE_SIZE;
+ }
+
+ /**
* @param o Fail state object.
* @param nodeId Node ID.
*/
@@ -1240,4 +1332,24 @@ public class GridReduceQueryExecutor {
return res;
}
}
+
+ /**
+ *
+ */
+ private class ExplicitPartitionsSpecializer implements IgniteBiClosure<ClusterNode,Message,Message> {
+ /** */
+ private final Map<ClusterNode,IntArray> partsMap;
+
+ /**
+ * @param partsMap Partitions map.
+ */
+ private ExplicitPartitionsSpecializer(Map<ClusterNode,IntArray> partsMap) {
+ this.partsMap = partsMap;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Message apply(ClusterNode n, Message msg) {
+ return copy(msg, n, partsMap);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridThreadLocalTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridThreadLocalTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridThreadLocalTable.java
index a38d137..d46fb2f 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridThreadLocalTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridThreadLocalTable.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.query.h2.twostep;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
+import javax.cache.CacheException;
import org.h2.api.TableEngine;
import org.h2.command.ddl.CreateTableData;
import org.h2.engine.DbObject;
@@ -59,61 +60,74 @@ public class GridThreadLocalTable extends Table {
/**
* @param t Table or {@code null} to reset existing.
*/
- public void setInnerTable(Table t) {
+ public void innerTable(Table t) {
if (t == null)
tbl.remove();
else
tbl.set(t);
}
+ /**
+ * @return Inner table.
+ */
+ private Table innerTable() {
+ Table t = tbl.get();
+
+ if (t == null)
+ throw new CacheException("Table `" + getName() + "` can be accessed only within Ignite query context.");
+
+ return t;
+ }
+
/** {@inheritDoc} */
@Override public Index getPrimaryKey() {
- return tbl.get().getPrimaryKey();
+ return innerTable().getPrimaryKey();
}
/** {@inheritDoc} */
@Override public Column getRowIdColumn() {
- return tbl.get().getRowIdColumn();
+ return innerTable().getRowIdColumn();
}
/** {@inheritDoc} */
- @Override public PlanItem getBestPlanItem(Session session, int[] masks, TableFilter filter, SortOrder sortOrder) {
- return tbl.get().getBestPlanItem(session, masks, filter, sortOrder);
+ @Override public PlanItem getBestPlanItem(Session session, int[] masks, TableFilter[] filters, int filter,
+ SortOrder sortOrder) {
+ return innerTable().getBestPlanItem(session, masks, filters, filter, sortOrder);
}
/** {@inheritDoc} */
@Override public Value getDefaultValue(Session session, Column column) {
- return tbl.get().getDefaultValue(session, column);
+ return innerTable().getDefaultValue(session, column);
}
/** {@inheritDoc} */
@Override public SearchRow getTemplateSimpleRow(boolean singleColumn) {
- return tbl.get().getTemplateSimpleRow(singleColumn);
+ return innerTable().getTemplateSimpleRow(singleColumn);
}
/** {@inheritDoc} */
@Override public Row getTemplateRow() {
- return tbl.get().getTemplateRow();
+ return innerTable().getTemplateRow();
}
/** {@inheritDoc} */
@Override public Column getColumn(String columnName) {
- return tbl.get().getColumn(columnName);
+ return innerTable().getColumn(columnName);
}
/** {@inheritDoc} */
@Override public Column getColumn(int index) {
- return tbl.get().getColumn(index);
+ return innerTable().getColumn(index);
}
/** {@inheritDoc} */
@Override public Index getIndexForColumn(Column column) {
- return tbl.get().getIndexForColumn(column);
+ return innerTable().getIndexForColumn(column);
}
/** {@inheritDoc} */
@Override public Column[] getColumns() {
- return tbl.get().getColumns();
+ return innerTable().getColumns();
}
/** {@inheritDoc} */
@@ -122,8 +136,8 @@ public class GridThreadLocalTable extends Table {
}
/** {@inheritDoc} */
- @Override public void lock(Session session, boolean exclusive, boolean force) {
- tbl.get().lock(session, exclusive, force);
+ @Override public boolean lock(Session session, boolean exclusive, boolean force) {
+ return innerTable().lock(session, exclusive, force);
}
/** {@inheritDoc} */
@@ -133,33 +147,33 @@ public class GridThreadLocalTable extends Table {
/** {@inheritDoc} */
@Override public void unlock(Session s) {
- tbl.get().unlock(s);
+ innerTable().unlock(s);
}
/** {@inheritDoc} */
@Override public Index addIndex(Session session, String indexName, int indexId, IndexColumn[] cols,
IndexType indexType, boolean create, String indexComment) {
- return tbl.get().addIndex(session, indexName, indexId, cols, indexType, create, indexComment);
+ return innerTable().addIndex(session, indexName, indexId, cols, indexType, create, indexComment);
}
/** {@inheritDoc} */
@Override public void removeRow(Session session, Row row) {
- tbl.get().removeRow(session, row);
+ innerTable().removeRow(session, row);
}
/** {@inheritDoc} */
@Override public void truncate(Session session) {
- tbl.get().truncate(session);
+ innerTable().truncate(session);
}
/** {@inheritDoc} */
@Override public void addRow(Session session, Row row) {
- tbl.get().addRow(session, row);
+ innerTable().addRow(session, row);
}
/** {@inheritDoc} */
@Override public void checkSupportAlter() {
- tbl.get().checkSupportAlter();
+ innerTable().checkSupportAlter();
}
/** {@inheritDoc} */
@@ -169,22 +183,22 @@ public class GridThreadLocalTable extends Table {
/** {@inheritDoc} */
@Override public Index getUniqueIndex() {
- return tbl.get().getUniqueIndex();
+ return innerTable().getUniqueIndex();
}
/** {@inheritDoc} */
@Override public Index getScanIndex(Session session) {
- return tbl.get().getScanIndex(session);
+ return innerTable().getScanIndex(session);
}
/** {@inheritDoc} */
@Override public ArrayList<Index> getIndexes() {
- return tbl.get().getIndexes();
+ return innerTable().getIndexes();
}
/** {@inheritDoc} */
@Override public boolean isLockedExclusively() {
- return tbl.get().isLockedExclusively();
+ return innerTable().isLockedExclusively();
}
/** {@inheritDoc} */
@@ -194,12 +208,12 @@ public class GridThreadLocalTable extends Table {
/** {@inheritDoc} */
@Override public boolean isDeterministic() {
- return tbl.get().isDeterministic();
+ return innerTable().isDeterministic();
}
/** {@inheritDoc} */
@Override public boolean canGetRowCount() {
- return tbl.get().canGetRowCount();
+ return innerTable().canGetRowCount();
}
/** {@inheritDoc} */
@@ -209,7 +223,7 @@ public class GridThreadLocalTable extends Table {
/** {@inheritDoc} */
@Override public long getRowCount(Session session) {
- return tbl.get().getRowCount(session);
+ return innerTable().getRowCount(session);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Array.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Array.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Array.java
index 362a760..571f9ac 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Array.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Array.java
@@ -115,7 +115,7 @@ public class GridH2Array extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Array.class);
}
/** {@inheritDoc} */
@@ -127,4 +127,9 @@ public class GridH2Array extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Boolean.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Boolean.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Boolean.java
index 0628764..edd404e 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Boolean.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Boolean.java
@@ -99,7 +99,7 @@ public class GridH2Boolean extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Boolean.class);
}
/** {@inheritDoc} */
@@ -107,7 +107,13 @@ public class GridH2Boolean extends GridH2ValueMessage {
return -5;
}
+ /** {@inheritDoc} */
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Byte.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Byte.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Byte.java
index 9f608b9..894794e 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Byte.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Byte.java
@@ -99,7 +99,7 @@ public class GridH2Byte extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Byte.class);
}
/** {@inheritDoc} */
@@ -111,4 +111,9 @@ public class GridH2Byte extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Bytes.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Bytes.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Bytes.java
index 0fb9e5d..29a52be 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Bytes.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Bytes.java
@@ -24,6 +24,8 @@ import org.apache.ignite.plugin.extensions.communication.MessageWriter;
import org.h2.value.Value;
import org.h2.value.ValueBytes;
+import static org.h2.util.StringUtils.convertBytesToHex;
+
/**
* H2 Bytes.
*/
@@ -99,7 +101,7 @@ public class GridH2Bytes extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Bytes.class);
}
/** {@inheritDoc} */
@@ -111,4 +113,9 @@ public class GridH2Bytes extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "b_" + convertBytesToHex(b);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2CacheObject.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2CacheObject.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2CacheObject.java
index 1a81234..942ab7c 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2CacheObject.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2CacheObject.java
@@ -102,7 +102,7 @@ public class GridH2CacheObject extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2CacheObject.class);
}
/** {@inheritDoc} */
@@ -146,4 +146,9 @@ public class GridH2CacheObject extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 2;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(obj);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Date.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Date.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Date.java
index 6bd5237..8025257 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Date.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Date.java
@@ -101,7 +101,7 @@ public class GridH2Date extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Date.class);
}
/** {@inheritDoc} */
@@ -113,4 +113,9 @@ public class GridH2Date extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(date);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Decimal.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Decimal.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Decimal.java
index f5d4865..a3ad444 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Decimal.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Decimal.java
@@ -26,6 +26,8 @@ import org.apache.ignite.plugin.extensions.communication.MessageWriter;
import org.h2.value.Value;
import org.h2.value.ValueDecimal;
+import static org.h2.util.StringUtils.convertBytesToHex;
+
/**
* H2 Decimal.
*/
@@ -121,7 +123,7 @@ public class GridH2Decimal extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Decimal.class);
}
/** {@inheritDoc} */
@@ -133,4 +135,9 @@ public class GridH2Decimal extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 2;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return scale + "_" + convertBytesToHex(b);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Double.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Double.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Double.java
index 481db30..2ceea8d 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Double.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Double.java
@@ -99,7 +99,7 @@ public class GridH2Double extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Double.class);
}
/** {@inheritDoc} */
@@ -111,4 +111,9 @@ public class GridH2Double extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Float.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Float.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Float.java
index 55f9380..6923470 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Float.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Float.java
@@ -99,7 +99,7 @@ public class GridH2Float extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Float.class);
}
/** {@inheritDoc} */
@@ -111,4 +111,9 @@ public class GridH2Float extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Geometry.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Geometry.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Geometry.java
index 21070d1..0d118b4 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Geometry.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Geometry.java
@@ -25,6 +25,8 @@ import org.apache.ignite.plugin.extensions.communication.MessageReader;
import org.apache.ignite.plugin.extensions.communication.MessageWriter;
import org.h2.value.Value;
+import static org.h2.util.StringUtils.convertBytesToHex;
+
/**
* H2 Geometry.
*/
@@ -120,7 +122,7 @@ public class GridH2Geometry extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Geometry.class);
}
/** {@inheritDoc} */
@@ -132,4 +134,9 @@ public class GridH2Geometry extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "g_" + convertBytesToHex(b);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeRequest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeRequest.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeRequest.java
new file mode 100644
index 0000000..e49c48f
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeRequest.java
@@ -0,0 +1,208 @@
+/*
+ * 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.twostep.msg;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.UUID;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Range request.
+ */
+public class GridH2IndexRangeRequest implements Message {
+ /** */
+ private UUID originNodeId;
+
+ /** */
+ private long qryId;
+
+ /** */
+ private int batchLookupId;
+
+ /** */
+ @GridDirectCollection(Message.class)
+ private List<GridH2RowRangeBounds> bounds;
+
+ /**
+ * @param bounds Range bounds list.
+ */
+ public void bounds(List<GridH2RowRangeBounds> bounds) {
+ this.bounds = bounds;
+ }
+
+ /**
+ * @return Range bounds list.
+ */
+ public List<GridH2RowRangeBounds> bounds() {
+ return bounds;
+ }
+
+ /**
+ * @return Origin node ID.
+ */
+ public UUID originNodeId() {
+ return originNodeId;
+ }
+
+ /**
+ * @param originNodeId Origin node ID.
+ */
+ public void originNodeId(UUID originNodeId) {
+ this.originNodeId = originNodeId;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public long queryId() {
+ return qryId;
+ }
+
+ /**
+ * @param qryId Query ID.
+ */
+ public void queryId(long qryId) {
+ this.qryId = qryId;
+ }
+
+ /**
+ * @param batchLookupId Batch lookup ID.
+ */
+ public void batchLookupId(int batchLookupId) {
+ this.batchLookupId = batchLookupId;
+ }
+
+ /**
+ * @return Batch lookup ID.
+ */
+ public int batchLookupId() {
+ return batchLookupId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeInt("batchLookupId", batchLookupId))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeCollection("bounds", bounds, MessageCollectionItemType.MSG))
+ return false;
+
+ writer.incrementState();
+
+ case 2:
+ if (!writer.writeUuid("originNodeId", originNodeId))
+ return false;
+
+ writer.incrementState();
+
+ case 3:
+ if (!writer.writeLong("qryId", qryId))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ batchLookupId = reader.readInt("batchLookupId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ bounds = reader.readCollection("bounds", MessageCollectionItemType.MSG);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 2:
+ originNodeId = reader.readUuid("originNodeId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 3:
+ qryId = reader.readLong("qryId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GridH2IndexRangeRequest.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ return -30;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 4;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridH2IndexRangeRequest.class, this, "boundsSize", bounds == null ? null : bounds.size());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeResponse.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeResponse.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeResponse.java
new file mode 100644
index 0000000..c6414bd
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2IndexRangeResponse.java
@@ -0,0 +1,279 @@
+/*
+ * 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.twostep.msg;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import java.util.UUID;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Range response message.
+ */
+public class GridH2IndexRangeResponse implements Message {
+ /** */
+ public static final byte STATUS_OK = 0;
+
+ /** */
+ public static final byte STATUS_ERROR = 1;
+
+ /** */
+ public static final byte STATUS_NOT_FOUND = 2;
+
+ /** */
+ private UUID originNodeId;
+
+ /** */
+ private long qryId;
+
+ /** */
+ private int batchLookupId;
+
+ /** */
+ @GridDirectCollection(Message.class)
+ private List<GridH2RowRange> ranges;
+
+ /** */
+ private byte status;
+
+ /** */
+ private String err;
+
+ /**
+ * @param ranges Ranges.
+ */
+ public void ranges(List<GridH2RowRange> ranges) {
+ this.ranges = ranges;
+ }
+
+ /**
+ * @return Ranges.
+ */
+ public List<GridH2RowRange> ranges() {
+ return ranges;
+ }
+
+ /**
+ * @return Origin node ID.
+ */
+ public UUID originNodeId() {
+ return originNodeId;
+ }
+
+ /**
+ * @param originNodeId Origin node ID.
+ */
+ public void originNodeId(UUID originNodeId) {
+ this.originNodeId = originNodeId;
+ }
+
+ /**
+ * @return Query ID.
+ */
+ public long queryId() {
+ return qryId;
+ }
+
+ /**
+ * @param qryId Query ID.
+ */
+ public void queryId(long qryId) {
+ this.qryId = qryId;
+ }
+
+ /**
+ * @param err Error message.
+ */
+ public void error(String err) {
+ this.err = err;
+ }
+
+ /**
+ * @return Error message or {@code null} if everything is ok.
+ */
+ public String error() {
+ return err;
+ }
+
+ /**
+ * @param status Status.
+ */
+ public void status(byte status) {
+ this.status = status;
+ }
+
+ /**
+ * @return Status.
+ */
+ public byte status() {
+ return status;
+ }
+
+ /**
+ * @param batchLookupId Batch lookup ID.
+ */
+ public void batchLookupId(int batchLookupId) {
+ this.batchLookupId = batchLookupId;
+ }
+
+ /**
+ * @return Batch lookup ID.
+ */
+ public int batchLookupId() {
+ return batchLookupId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeInt("batchLookupId", batchLookupId))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeString("err", err))
+ return false;
+
+ writer.incrementState();
+
+ case 2:
+ if (!writer.writeUuid("originNodeId", originNodeId))
+ return false;
+
+ writer.incrementState();
+
+ case 3:
+ if (!writer.writeLong("qryId", qryId))
+ return false;
+
+ writer.incrementState();
+
+ case 4:
+ if (!writer.writeCollection("ranges", ranges, MessageCollectionItemType.MSG))
+ return false;
+
+ writer.incrementState();
+
+ case 5:
+ if (!writer.writeByte("status", status))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ batchLookupId = reader.readInt("batchLookupId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ err = reader.readString("err");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 2:
+ originNodeId = reader.readUuid("originNodeId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 3:
+ qryId = reader.readLong("qryId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 4:
+ ranges = reader.readCollection("ranges", MessageCollectionItemType.MSG);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 5:
+ status = reader.readByte("status");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GridH2IndexRangeResponse.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ return -31;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 6;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridH2IndexRangeResponse.class, this, "rangesSize", ranges == null ? null : ranges.size());
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Integer.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Integer.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Integer.java
index 30c7623..7c6046c 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Integer.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Integer.java
@@ -99,7 +99,7 @@ public class GridH2Integer extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Integer.class);
}
/** {@inheritDoc} */
@@ -111,4 +111,20 @@ public class GridH2Integer extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object obj) {
+ return obj == this || (obj != null && obj.getClass() == GridH2Integer.class && x == ((GridH2Integer)obj).x);
+
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return x;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2JavaObject.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2JavaObject.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2JavaObject.java
index edfde33..b989171 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2JavaObject.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2JavaObject.java
@@ -24,6 +24,8 @@ import org.apache.ignite.plugin.extensions.communication.MessageWriter;
import org.h2.value.Value;
import org.h2.value.ValueJavaObject;
+import static org.h2.util.StringUtils.convertBytesToHex;
+
/**
* H2 Java Object.
*/
@@ -99,7 +101,7 @@ public class GridH2JavaObject extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2JavaObject.class);
}
/** {@inheritDoc} */
@@ -111,4 +113,9 @@ public class GridH2JavaObject extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "j_" + convertBytesToHex(b);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Long.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Long.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Long.java
index e6af9e1..3d360f0 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Long.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Long.java
@@ -99,7 +99,7 @@ public class GridH2Long extends GridH2ValueMessage {
}
- return true;
+ return reader.afterMessageRead(GridH2Long.class);
}
/** {@inheritDoc} */
@@ -111,4 +111,9 @@ public class GridH2Long extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return String.valueOf(x);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
index 2394b78..50a49ba 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2Null.java
@@ -64,7 +64,13 @@ public class GridH2Null extends GridH2ValueMessage {
@Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
reader.setBuffer(buf);
- return reader.beforeMessageRead() && super.readFrom(buf, reader);
+ if (!reader.beforeMessageRead())
+ return false;
+
+ if (!super.readFrom(buf, reader))
+ return false;
+
+ return reader.afterMessageRead(GridH2Null.class);
}
/** {@inheritDoc} */
@@ -76,4 +82,9 @@ public class GridH2Null extends GridH2ValueMessage {
@Override public byte fieldsCount() {
return 0;
}
-}
\ No newline at end of file
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "NULL";
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java
new file mode 100644
index 0000000..dc82b2c
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2QueryRequest.java
@@ -0,0 +1,401 @@
+/*
+ * 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.twostep.msg;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.GridDirectMap;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
+import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.marshaller.Marshaller;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * Query request.
+ */
+public class GridH2QueryRequest implements Message, GridCacheQueryMarshallable {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /**
+ * Map query will not destroy context until explicit query cancel request
+ * will be received because distributed join requests can be received.
+ */
+ public static int FLAG_DISTRIBUTED_JOINS = 1;
+
+ /** */
+ private long reqId;
+
+ /** */
+ @GridToStringInclude
+ @GridDirectCollection(Integer.class)
+ private List<Integer> caches;
+
+ /** Topology version. */
+ private AffinityTopologyVersion topVer;
+
+ /** Explicit partitions mappings for nodes. */
+ @GridToStringInclude
+ @GridDirectMap(keyType = UUID.class, valueType = int[].class)
+ private Map<UUID, int[]> parts;
+
+ /** */
+ private int pageSize;
+
+ /** */
+ @GridToStringInclude
+ @GridDirectCollection(Message.class)
+ private List<GridCacheSqlQuery> qrys;
+
+ /** */
+ private byte flags;
+
+ /** */
+ @GridToStringInclude
+ @GridDirectCollection(String.class)
+ private Collection<String> tbls;
+
+ /**
+ * @param tbls Tables.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest tables(Collection<String> tbls) {
+ this.tbls = tbls;
+
+ return this;
+ }
+
+ /**
+ * @return Tables.
+ */
+ public Collection<String> tables() {
+ return tbls;
+ }
+
+ /**
+ * @param reqId Request ID.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest requestId(long reqId) {
+ this.reqId = reqId;
+
+ return this;
+ }
+
+ /**
+ * @return Request ID.
+ */
+ public long requestId() {
+ return reqId;
+ }
+
+ /**
+ * @param caches Caches.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest caches(List<Integer> caches) {
+ this.caches = caches;
+
+ return this;
+ }
+
+ /**
+ * @return Caches.
+ */
+ public List<Integer> caches() {
+ return caches;
+ }
+
+ /**
+ * @param topVer Topology version.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest topologyVersion(AffinityTopologyVersion topVer) {
+ this.topVer = topVer;
+
+ return this;
+ }
+
+ /**
+ * @return Topology version.
+ */
+ public AffinityTopologyVersion topologyVersion() {
+ return topVer;
+ }
+
+ /**
+ * @return Explicit partitions mapping.
+ */
+ public Map<UUID,int[]> partitions() {
+ return parts;
+ }
+
+ /**
+ * @param parts Explicit partitions mapping.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest partitions(Map<UUID,int[]> parts) {
+ this.parts = parts;
+
+ return this;
+ }
+
+ /**
+ * @param pageSize Page size.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest pageSize(int pageSize) {
+ this.pageSize = pageSize;
+
+ return this;
+ }
+
+ /**
+ * @return Page size.
+ */
+ public int pageSize() {
+ return pageSize;
+ }
+
+ /**
+ * @param qrys SQL Queries.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest queries(List<GridCacheSqlQuery> qrys) {
+ this.qrys = qrys;
+
+ return this;
+ }
+
+ /**
+ * @return SQL Queries.
+ */
+ public List<GridCacheSqlQuery> queries() {
+ return qrys;
+ }
+
+ /**
+ * @param flags Flags.
+ * @return {@code this}.
+ */
+ public GridH2QueryRequest flags(int flags) {
+ this.flags = (byte)flags;
+
+ return this;
+ }
+
+ /**
+ * @param flags Flags to check.
+ * @return {@code true} If all the requested flags are set to {@code true}.
+ */
+ public boolean isFlagSet(int flags) {
+ return (this.flags & flags) == flags;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void marshall(Marshaller m) {
+ if (F.isEmpty(qrys))
+ return;
+
+ for (GridCacheSqlQuery qry : qrys)
+ qry.marshall(m);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void unmarshall(Marshaller m, GridKernalContext ctx) {
+ if (F.isEmpty(qrys))
+ return;
+
+ for (GridCacheSqlQuery qry : qrys)
+ qry.unmarshall(m, ctx);
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeCollection("caches", caches, MessageCollectionItemType.INT))
+ return false;
+
+ writer.incrementState();
+
+ case 1:
+ if (!writer.writeByte("flags", flags))
+ return false;
+
+ writer.incrementState();
+
+ case 2:
+ if (!writer.writeInt("pageSize", pageSize))
+ return false;
+
+ writer.incrementState();
+
+ case 3:
+ if (!writer.writeMap("parts", parts, MessageCollectionItemType.UUID, MessageCollectionItemType.INT_ARR))
+ return false;
+
+ writer.incrementState();
+
+ case 4:
+ if (!writer.writeCollection("qrys", qrys, MessageCollectionItemType.MSG))
+ return false;
+
+ writer.incrementState();
+
+ case 5:
+ if (!writer.writeLong("reqId", reqId))
+ return false;
+
+ writer.incrementState();
+
+ case 6:
+ if (!writer.writeCollection("tbls", tbls, MessageCollectionItemType.STRING))
+ return false;
+
+ writer.incrementState();
+
+ case 7:
+ if (!writer.writeMessage("topVer", topVer))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ caches = reader.readCollection("caches", MessageCollectionItemType.INT);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 1:
+ flags = reader.readByte("flags");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 2:
+ pageSize = reader.readInt("pageSize");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 3:
+ parts = reader.readMap("parts", MessageCollectionItemType.UUID, MessageCollectionItemType.INT_ARR, false);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 4:
+ qrys = reader.readCollection("qrys", MessageCollectionItemType.MSG);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 5:
+ reqId = reader.readLong("reqId");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 6:
+ tbls = reader.readCollection("tbls", MessageCollectionItemType.STRING);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ case 7:
+ topVer = reader.readMessage("topVer");
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GridH2QueryRequest.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ return -33;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 8;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridH2QueryRequest.class, this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowMessage.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowMessage.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowMessage.java
new file mode 100644
index 0000000..59c548d
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/msg/GridH2RowMessage.java
@@ -0,0 +1,116 @@
+/*
+ * 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.twostep.msg;
+
+import java.nio.ByteBuffer;
+import java.util.List;
+import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.plugin.extensions.communication.Message;
+import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
+import org.apache.ignite.plugin.extensions.communication.MessageReader;
+import org.apache.ignite.plugin.extensions.communication.MessageWriter;
+
+/**
+ * SQL Row message.
+ */
+public class GridH2RowMessage implements Message {
+ /** */
+ @GridDirectCollection(Message.class)
+ @GridToStringInclude
+ private List<GridH2ValueMessage> vals;
+
+ /**
+ * @return Values of row.
+ */
+ public List<GridH2ValueMessage> values() {
+ return vals;
+ }
+
+ /**
+ * @param vals Values of row.
+ */
+ public void values(List<GridH2ValueMessage> vals) {
+ this.vals = vals;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean writeTo(ByteBuffer buf, MessageWriter writer) {
+ writer.setBuffer(buf);
+
+ if (!writer.isHeaderWritten()) {
+ if (!writer.writeHeader(directType(), fieldsCount()))
+ return false;
+
+ writer.onHeaderWritten();
+ }
+
+ switch (writer.state()) {
+ case 0:
+ if (!writer.writeCollection("vals", vals, MessageCollectionItemType.MSG))
+ return false;
+
+ writer.incrementState();
+
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean readFrom(ByteBuffer buf, MessageReader reader) {
+ reader.setBuffer(buf);
+
+ if (!reader.beforeMessageRead())
+ return false;
+
+ switch (reader.state()) {
+ case 0:
+ vals = reader.readCollection("vals", MessageCollectionItemType.MSG);
+
+ if (!reader.isLastRead())
+ return false;
+
+ reader.incrementState();
+
+ }
+
+ return reader.afterMessageRead(GridH2RowMessage.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte directType() {
+ return -32;
+ }
+
+ /** {@inheritDoc} */
+ @Override public byte fieldsCount() {
+ return 1;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onAckReceived() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridH2RowMessage.class, this);
+ }
+}
[08/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartDistributedJoinSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartDistributedJoinSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartDistributedJoinSelfTest.java
new file mode 100644
index 0000000..0e6806f
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/IgniteCacheQueryNodeRestartDistributedJoinSelfTest.java
@@ -0,0 +1,476 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicIntegerArray;
+import javax.cache.CacheException;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction;
+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.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.IgniteInternalFuture;
+import org.apache.ignite.internal.util.GridRandom;
+import org.apache.ignite.internal.util.typedef.CAX;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.X;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Test for distributed queries with node restarts.
+ */
+public class IgniteCacheQueryNodeRestartDistributedJoinSelfTest extends GridCommonAbstractTest {
+ /** */
+ private static final String QRY_0 = "select co._key, count(*) cnt\n" +
+ "from \"pe\".Person pe, \"pr\".Product pr, \"co\".Company co, \"pu\".Purchase pu\n" +
+ "where pe._key = pu.personId and pu.productId = pr._key and pr.companyId = co._key \n" +
+ "group by co._key order by cnt desc, co._key";
+
+ /** */
+ private static final String QRY_0_BROADCAST = "select co._key, count(*) cnt\n" +
+ "from \"co\".Company co, \"pr\".Product pr, \"pu\".Purchase pu, \"pe\".Person pe \n" +
+ "where pe._key = pu.personId and pu.productId = pr._key and pr.companyId = co._key \n" +
+ "group by co._key order by cnt desc, co._key";
+
+ /** */
+ private static final String QRY_1 = "select pr._key, co._key\n" +
+ "from \"pr\".Product pr, \"co\".Company co\n" +
+ "where pr.companyId = co._key\n" +
+ "order by co._key, pr._key ";
+
+ /** */
+ private static final String QRY_1_BROADCAST = "select pr._key, co._key\n" +
+ "from \"co\".Company co, \"pr\".Product pr \n" +
+ "where pr.companyId = co._key\n" +
+ "order by co._key, pr._key ";
+
+ /** */
+ private static final int GRID_CNT = 6;
+
+ /** */
+ private static final int PERS_CNT = 600;
+
+ /** */
+ private static final int PURCHASE_CNT = 6000;
+
+ /** */
+ private static final int COMPANY_CNT = 25;
+
+ /** */
+ private static final int PRODUCT_CNT = 100;
+
+ /** */
+ private static TcpDiscoveryIpFinder ipFinder = new TcpDiscoveryVmIpFinder(true);
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration c = super.getConfiguration(gridName);
+
+ TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+ disco.setIpFinder(ipFinder);
+
+ c.setDiscoverySpi(disco);
+
+ int i = 0;
+
+ CacheConfiguration<?, ?>[] ccs = new CacheConfiguration[4];
+
+ for (String name : F.asList("pe", "pu", "co", "pr")) {
+ CacheConfiguration<?, ?> cc = defaultCacheConfiguration();
+
+ cc.setName(name);
+ cc.setCacheMode(PARTITIONED);
+ cc.setBackups(2);
+ cc.setWriteSynchronizationMode(FULL_SYNC);
+ cc.setAtomicityMode(TRANSACTIONAL);
+ cc.setRebalanceMode(SYNC);
+ cc.setLongQueryWarningTimeout(15_000);
+ cc.setAffinity(new RendezvousAffinityFunction(false, 60));
+
+ switch (name) {
+ case "pe":
+ cc.setIndexedTypes(
+ Integer.class, Person.class
+ );
+
+ break;
+
+ case "pu":
+ cc.setIndexedTypes(
+ Integer.class, Purchase.class
+ );
+
+ break;
+
+ case "co":
+ cc.setIndexedTypes(
+ Integer.class, Company.class
+ );
+
+ break;
+
+ case "pr":
+ cc.setIndexedTypes(
+ Integer.class, Product.class
+ );
+
+ break;
+ }
+
+ ccs[i++] = cc;
+ }
+
+ c.setCacheConfiguration(ccs);
+
+ return c;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(GRID_CNT);
+
+ fillCaches();
+ }
+
+ /**
+ *
+ */
+ private void fillCaches() {
+ IgniteCache<Integer, Company> co = grid(0).cache("co");
+
+ for (int i = 0; i < COMPANY_CNT; i++)
+ co.put(i, new Company(i));
+
+ IgniteCache<Integer, Product> pr = grid(0).cache("pr");
+
+ Random rnd = new GridRandom();
+
+ for (int i = 0; i < PRODUCT_CNT; i++)
+ pr.put(i, new Product(i, rnd.nextInt(COMPANY_CNT)));
+
+ IgniteCache<Integer, Person> pe = grid(0).cache("pe");
+
+ for (int i = 0; i < PERS_CNT; i++)
+ pe.put(i, new Person(i));
+
+ IgniteCache<Integer, Purchase> pu = grid(0).cache("pu");
+
+ for (int i = 0; i < PURCHASE_CNT; i++) {
+ int persId = rnd.nextInt(PERS_CNT);
+ int prodId = rnd.nextInt(PRODUCT_CNT);
+
+ pu.put(i, new Purchase(persId, prodId));
+ }
+ }
+ /**
+ * @throws Exception If failed.
+ */
+ public void testRestarts() throws Exception {
+ restarts(false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testRestartsBroadcast() throws Exception {
+ restarts(true);
+ }
+
+ /**
+ * @param broadcastQry If {@code true} tests broadcast query.
+ * @throws Exception If failed.
+ */
+ private void restarts(final boolean broadcastQry) throws Exception {
+ int duration = 90 * 1000;
+ int qryThreadNum = 4;
+ int restartThreadsNum = 2; // 4 + 2 = 6 nodes
+ final int nodeLifeTime = 4000;
+ final int logFreq = 100;
+
+ final AtomicIntegerArray locks = new AtomicIntegerArray(GRID_CNT);
+
+ SqlFieldsQuery qry0 ;
+
+ if (broadcastQry)
+ qry0 = new SqlFieldsQuery(QRY_0_BROADCAST).setDistributedJoins(true).setEnforceJoinOrder(true);
+ else
+ qry0 = new SqlFieldsQuery(QRY_0).setDistributedJoins(true);
+
+ String plan = queryPlan(grid(0).cache("pu"), qry0);
+
+ X.println("Plan1: " + plan);
+
+ assertEquals(broadcastQry, plan.contains("batched:broadcast"));
+
+ final List<List<?>> pRes = grid(0).cache("pu").query(qry0).getAll();
+
+ Thread.sleep(3000);
+
+ assertEquals(pRes, grid(0).cache("pu").query(qry0).getAll());
+
+ final SqlFieldsQuery qry1;
+
+ if (broadcastQry)
+ qry1 = new SqlFieldsQuery(QRY_1_BROADCAST).setDistributedJoins(true).setEnforceJoinOrder(true);
+ else
+ qry1 = new SqlFieldsQuery(QRY_1).setDistributedJoins(true);
+
+ plan = queryPlan(grid(0).cache("co"), qry1);
+
+ X.println("Plan2: " + plan);
+
+ assertEquals(broadcastQry, plan.contains("batched:broadcast"));
+
+ final List<List<?>> rRes = grid(0).cache("co").query(qry1).getAll();
+
+ assertFalse(pRes.isEmpty());
+ assertFalse(rRes.isEmpty());
+
+ final AtomicInteger qryCnt = new AtomicInteger();
+ final AtomicBoolean qrysDone = new AtomicBoolean();
+
+ IgniteInternalFuture<?> fut1 = multithreadedAsync(new CAX() {
+ @Override public void applyx() throws IgniteCheckedException {
+ GridRandom rnd = new GridRandom();
+
+ while (!qrysDone.get()) {
+ int g;
+
+ do {
+ g = rnd.nextInt(locks.length());
+ }
+ while (!locks.compareAndSet(g, 0, 1));
+
+ if (rnd.nextBoolean()) {
+ IgniteCache<?, ?> cache = grid(g).cache("pu");
+
+ SqlFieldsQuery qry;
+
+ if (broadcastQry)
+ qry = new SqlFieldsQuery(QRY_0_BROADCAST).setDistributedJoins(true).setEnforceJoinOrder(true);
+ else
+ qry = new SqlFieldsQuery(QRY_0).setDistributedJoins(true);
+
+ boolean smallPageSize = rnd.nextBoolean();
+
+ qry.setPageSize(smallPageSize ? 30 : 1000);
+
+ try {
+ assertEquals(pRes, cache.query(qry).getAll());
+ }
+ catch (CacheException e) {
+ assertTrue("On large page size must retry.", smallPageSize);
+
+ boolean failedOnRemoteFetch = false;
+
+ for (Throwable th = e; th != null; th = th.getCause()) {
+ if (!(th instanceof CacheException))
+ continue;
+
+ if (th.getMessage() != null &&
+ th.getMessage().startsWith("Failed to fetch data from node:")) {
+ failedOnRemoteFetch = true;
+
+ break;
+ }
+ }
+
+ if (!failedOnRemoteFetch) {
+ e.printStackTrace();
+
+ fail("Must fail inside of GridResultPage.fetchNextPage or subclass.");
+ }
+ }
+ }
+ else {
+ IgniteCache<?, ?> cache = grid(g).cache("co");
+
+ SqlFieldsQuery qry;
+
+ if (broadcastQry)
+ qry = new SqlFieldsQuery(QRY_1_BROADCAST).setDistributedJoins(true).setEnforceJoinOrder(true);
+ else
+ qry = new SqlFieldsQuery(QRY_1).setDistributedJoins(true);
+
+ assertEquals(rRes, cache.query(qry1).getAll());
+ }
+
+ locks.set(g, 0);
+
+ int c = qryCnt.incrementAndGet();
+
+ if (c % logFreq == 0)
+ info("Executed queries: " + c);
+ }
+ }
+ }, qryThreadNum, "query-thread");
+
+ final AtomicInteger restartCnt = new AtomicInteger();
+
+ final AtomicBoolean restartsDone = new AtomicBoolean();
+
+ IgniteInternalFuture<?> fut2 = multithreadedAsync(new Callable<Object>() {
+ @SuppressWarnings({"BusyWait"})
+ @Override public Object call() throws Exception {
+ GridRandom rnd = new GridRandom();
+
+ while (!restartsDone.get()) {
+ int g;
+
+ do {
+ g = rnd.nextInt(locks.length());
+ }
+ while (!locks.compareAndSet(g, 0, -1));
+
+ log.info("Stop node: " + g);
+
+ stopGrid(g);
+
+ Thread.sleep(rnd.nextInt(nodeLifeTime));
+
+ log.info("Start node: " + g);
+
+ startGrid(g);
+
+ Thread.sleep(rnd.nextInt(nodeLifeTime));
+
+ locks.set(g, 0);
+
+ int c = restartCnt.incrementAndGet();
+
+ if (c % logFreq == 0)
+ info("Node restarts: " + c);
+ }
+
+ return true;
+ }
+ }, restartThreadsNum, "restart-thread");
+
+ Thread.sleep(duration);
+
+ info("Stopping..");
+
+ restartsDone.set(true);
+ qrysDone.set(true);
+
+ fut2.get();
+ fut1.get();
+
+ info("Stopped.");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ @QuerySqlField(index = true)
+ int id;
+
+ /**
+ * @param id ID.
+ */
+ Person(int id) {
+ this.id = id;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Purchase implements Serializable {
+ /** */
+ @QuerySqlField(index = true)
+ int personId;
+
+ /** */
+ @QuerySqlField(index = true)
+ int productId;
+
+ /**
+ * @param personId Person ID.
+ * @param productId Product ID.
+ */
+ Purchase(int personId, int productId) {
+ this.personId = personId;
+ this.productId = productId;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Company implements Serializable {
+ /** */
+ @QuerySqlField(index = true)
+ int id;
+
+ /**
+ * @param id ID.
+ */
+ Company(int id) {
+ this.id = id;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Product implements Serializable {
+ /** */
+ @QuerySqlField(index = true)
+ int id;
+
+ /** */
+ @QuerySqlField(index = true)
+ int companyId;
+
+ /**
+ * @param id ID.
+ * @param companyId Company ID.
+ */
+ Product(int id, int companyId) {
+ this.id = id;
+ this.companyId = companyId;
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheAbstractReduceFieldsQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheAbstractReduceFieldsQuerySelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheAbstractReduceFieldsQuerySelfTest.java
deleted file mode 100644
index 82456fb..0000000
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheAbstractReduceFieldsQuerySelfTest.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * 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.reducefields;
-
-import java.io.Serializable;
-import java.util.Collection;
-import java.util.List;
-import org.apache.ignite.IgniteCache;
-import org.apache.ignite.cache.CacheAtomicityMode;
-import org.apache.ignite.cache.CacheMode;
-import org.apache.ignite.cache.affinity.AffinityKey;
-import org.apache.ignite.cache.query.annotations.QuerySqlField;
-import org.apache.ignite.configuration.CacheConfiguration;
-import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.configuration.NearCacheConfiguration;
-import org.apache.ignite.internal.IgniteKernal;
-import org.apache.ignite.internal.processors.cache.query.CacheQuery;
-import org.apache.ignite.internal.util.typedef.F;
-import org.apache.ignite.lang.IgniteBiTuple;
-import org.apache.ignite.lang.IgniteReducer;
-import org.apache.ignite.spi.discovery.DiscoverySpi;
-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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.jetbrains.annotations.Nullable;
-
-import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
-import static org.apache.ignite.cache.CacheMode.PARTITIONED;
-import static org.apache.ignite.cache.CacheMode.REPLICATED;
-import static org.apache.ignite.cache.CacheRebalanceMode.SYNC;
-import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
-
-/**
- * Tests for reduce fields queries.
- */
-public abstract class GridCacheAbstractReduceFieldsQuerySelfTest extends GridCommonAbstractTest {
- /** IP finder. */
- private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
-
- /** Flag indicating if starting node should have cache. */
- protected boolean hasCache;
-
- /** {@inheritDoc} */
- @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
- IgniteConfiguration cfg = super.getConfiguration(gridName);
-
- if (hasCache)
- cfg.setCacheConfiguration(cache(null));
- else
- cfg.setCacheConfiguration();
-
- cfg.setDiscoverySpi(discovery());
-
- return cfg;
- }
-
- /**
- * @return Distribution.
- */
- protected NearCacheConfiguration nearConfiguration() {
- return new NearCacheConfiguration();
- }
-
- /**
- * @param name Cache name.
- * @return Cache.
- */
- private CacheConfiguration cache(@Nullable String name) {
- CacheConfiguration<?,?> cache = defaultCacheConfiguration();
-
- cache.setName(name);
- cache.setCacheMode(cacheMode());
- cache.setAtomicityMode(atomicityMode());
- cache.setNearConfiguration(nearConfiguration());
- cache.setWriteSynchronizationMode(FULL_SYNC);
- cache.setRebalanceMode(SYNC);
- cache.setIndexedTypes(
- String.class, Organization.class,
- AffinityKey.class, Person.class
- );
-
- if (cacheMode() == PARTITIONED)
- cache.setBackups(1);
-
- return cache;
- }
-
- /**
- * @return Discovery SPI.
- */
- private static DiscoverySpi discovery() {
- TcpDiscoverySpi spi = new TcpDiscoverySpi();
-
- spi.setIpFinder(IP_FINDER);
-
- return spi;
- }
-
- /** {@inheritDoc} */
- @Override protected void beforeTestsStarted() throws Exception {
- hasCache = true;
-
- startGridsMultiThreaded(gridCount());
-
- hasCache = false;
-
- startGrid(gridCount());
-
- IgniteCache<String, Organization> orgCache = grid(0).cache(null);
-
- assert orgCache != null;
-
- orgCache.put("o1", new Organization(1, "A"));
- orgCache.put("o2", new Organization(2, "B"));
-
- IgniteCache<AffinityKey<String>, Person> personCache = grid(0).cache(null);
-
- assert personCache != null;
-
- personCache.put(new AffinityKey<>("p1", "o1"), new Person("John White", 25, 1));
- personCache.put(new AffinityKey<>("p2", "o1"), new Person("Joe Black", 35, 1));
- personCache.put(new AffinityKey<>("p3", "o2"), new Person("Mike Green", 40, 2));
- }
-
- /** {@inheritDoc} */
- @Override protected void afterTestsStopped() throws Exception {
- stopAllGrids();
- }
-
- /**
- * @return cache mode.
- */
- protected abstract CacheMode cacheMode();
-
- /**
- * @return Number of grids to start.
- */
- protected abstract int gridCount();
-
- /**
- * @return Cache atomicity mode.
- */
- protected CacheAtomicityMode atomicityMode() {
- return TRANSACTIONAL;
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testNoDataInCache() throws Exception {
- CacheQuery<List<?>> qry = ((IgniteKernal)grid(0))
- .getCache(null).context().queries().createSqlFieldsQuery("select age from Person where orgId = 999", false);
-
- Collection<IgniteBiTuple<Integer, Integer>> res = qry.execute(new AverageRemoteReducer()).get();
-
- assertEquals("Result", 0, F.reduce(res, new AverageLocalReducer()).intValue());
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testAverageQuery() throws Exception {
- CacheQuery<List<?>> qry = ((IgniteKernal)grid(0)).getCache(null).context().queries().
- createSqlFieldsQuery("select age from Person", false);
-
- Collection<IgniteBiTuple<Integer, Integer>> res = qry.execute(new AverageRemoteReducer()).get();
-
- assertEquals("Average", 33, F.reduce(res, new AverageLocalReducer()).intValue());
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testAverageQueryWithArguments() throws Exception {
- CacheQuery<List<?>> qry = ((IgniteKernal)grid(0)).getCache(null).context().queries().createSqlFieldsQuery(
- "select age from Person where orgId = ?", false);
-
- Collection<IgniteBiTuple<Integer, Integer>> res = qry.execute(new AverageRemoteReducer(), 1).get();
-
- assertEquals("Average", 30, F.reduce(res, new AverageLocalReducer()).intValue());
- }
-
-// /**
-// * @throws Exception If failed.
-// */
-// public void testFilters() throws Exception {
-// GridCacheReduceFieldsQuery<Object, Object, GridBiTuple<Integer, Integer>, Integer> qry = ((IgniteKernal)grid(0)).cache(null)
-// .queries().createReduceFieldsQuery("select age from Person");
-//
-// qry = qry.remoteKeyFilter(
-// new GridPredicate<Object>() {
-// @Override public boolean apply(Object e) {
-// return !"p2".equals(((AffinityKey)e).key());
-// }
-// }
-// ).remoteValueFilter(
-// new P1<Object>() {
-// @Override public boolean apply(Object e) {
-// return !"Mike Green".equals(((Person)e).name);
-// }
-// }
-// );
-//
-// qry = qry.remoteReducer(new AverageRemoteReducer()).localReducer(new AverageLocalReducer());
-//
-// Integer avg = qry.reduce().get();
-//
-// assertNotNull("Average", avg);
-// assertEquals("Average", 25, avg.intValue());
-// }
-
-// /**
-// * @throws Exception If failed.
-// */
-// public void testOnProjectionWithFilter() throws Exception {
-// P2<AffinityKey<String>, Person> p = new P2<AffinityKey<String>, Person>() {
-// @Override public boolean apply(AffinityKey<String> key, Person val) {
-// return val.orgId == 1;
-// }
-// };
-//
-// InternalCache<AffinityKey<String>, Person> cachePrj =
-// grid(0).<AffinityKey<String>, Person>cache(null).projection(p);
-//
-// GridCacheReduceFieldsQuery<AffinityKey<String>, Person, GridBiTuple<Integer, Integer>, Integer> qry =
-// cachePrj.queries().createReduceFieldsQuery("select age from Person");
-//
-// qry = qry.remoteValueFilter(
-// new P1<Person>() {
-// @Override public boolean apply(Person e) {
-// return !"Joe Black".equals(e.name);
-// }
-// });
-//
-// qry = qry.remoteReducer(new AverageRemoteReducer()).localReducer(new AverageLocalReducer());
-//
-// Integer avg = qry.reduce().get();
-//
-// assertNotNull("Average", avg);
-// assertEquals("Average", 25, avg.intValue());
-// }
-
- /**
- * @return true if cache mode is replicated, false otherwise.
- */
- private boolean isReplicatedMode() {
- return cacheMode() == REPLICATED;
- }
-
- /**
- * Person.
- */
- @SuppressWarnings("UnusedDeclaration")
- private static class Person implements Serializable {
- /** Name. */
- @QuerySqlField(index = false)
- private final String name;
-
- /** Age. */
- @QuerySqlField(index = true)
- private final int age;
-
- /** Organization ID. */
- @QuerySqlField(index = true)
- private final int orgId;
-
- /**
- * @param name Name.
- * @param age Age.
- * @param orgId Organization ID.
- */
- private Person(String name, int age, int orgId) {
- assert !F.isEmpty(name);
- assert age > 0;
- assert orgId > 0;
-
- this.name = name;
- this.age = age;
- this.orgId = orgId;
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(Object o) {
- if (this == o)
- return true;
-
- if (o == null || getClass() != o.getClass())
- return false;
-
- Person person = (Person)o;
-
- return age == person.age && orgId == person.orgId && name.equals(person.name);
-
- }
-
- /** {@inheritDoc} */
- @Override public int hashCode() {
- int res = name.hashCode();
-
- res = 31 * res + age;
- res = 31 * res + orgId;
-
- return res;
- }
- }
-
- /**
- * Organization.
- */
- @SuppressWarnings("UnusedDeclaration")
- private static class Organization implements Serializable {
- /** ID. */
- @QuerySqlField
- private final int id;
-
- /** Name. */
- @QuerySqlField(index = false)
- private final String name;
-
- /**
- * @param id ID.
- * @param name Name.
- */
- private Organization(int id, String name) {
- assert id > 0;
- assert !F.isEmpty(name);
-
- this.id = id;
- this.name = name;
- }
-
- /** {@inheritDoc} */
- @Override public boolean equals(Object o) {
- if (this == o)
- return true;
-
- if (o == null || getClass() != o.getClass())
- return false;
-
- Organization that = (Organization)o;
-
- return id == that.id && name.equals(that.name);
-
- }
-
- /** {@inheritDoc} */
- @Override public int hashCode() {
- int res = id;
-
- res = 31 * res + name.hashCode();
-
- return res;
- }
- }
-
- /**
- * Average remote reducer factory.
- */
- protected static class AverageRemoteReducer implements IgniteReducer<List<?>, IgniteBiTuple<Integer, Integer>> {
- /** */
- private int sum;
-
- /** */
- private int cnt;
-
- /** {@inheritDoc} */
- @Override public boolean collect(List<?> e) {
- sum += (Integer)e.get(0);
-
- cnt++;
-
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public IgniteBiTuple<Integer, Integer> reduce() {
- return F.t(sum, cnt);
- }
- }
-
- /**
- * Average local reducer factory.
- */
- protected static class AverageLocalReducer implements IgniteReducer<IgniteBiTuple<Integer, Integer>, Integer> {
- /** */
- private int sum;
-
- /** */
- private int cnt;
-
- /** {@inheritDoc} */
- @Override public boolean collect(IgniteBiTuple<Integer, Integer> t) {
- sum += t.get1();
- cnt += t.get2();
-
- return true;
- }
-
- /** {@inheritDoc} */
- @Override public Integer reduce() {
- return cnt == 0 ? 0 : sum / cnt;
- }
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryAtomicSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryAtomicSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryAtomicSelfTest.java
deleted file mode 100644
index 6aa467b..0000000
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryAtomicSelfTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.reducefields;
-
-import org.apache.ignite.cache.CacheAtomicityMode;
-import org.apache.ignite.configuration.NearCacheConfiguration;
-
-import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
-
-/**
- * Reduce fields queries tests for partitioned cache.
- */
-public class GridCacheReduceFieldsQueryAtomicSelfTest extends GridCacheReduceFieldsQueryPartitionedSelfTest {
- /** {@inheritDoc} */
- @Override protected CacheAtomicityMode atomicityMode() {
- return ATOMIC;
- }
-
- /** {@inheritDoc} */
- @Override protected NearCacheConfiguration nearConfiguration() {
- return null;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryLocalSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryLocalSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryLocalSelfTest.java
deleted file mode 100644
index 17f024e..0000000
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryLocalSelfTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.reducefields;
-
-import org.apache.ignite.cache.CacheMode;
-
-import static org.apache.ignite.cache.CacheMode.LOCAL;
-
-/**
- * Reduce fields queries tests for local cache.
- */
-public class GridCacheReduceFieldsQueryLocalSelfTest extends GridCacheAbstractReduceFieldsQuerySelfTest {
- /** {@inheritDoc} */
- @Override protected CacheMode cacheMode() {
- return LOCAL;
- }
-
- /** {@inheritDoc} */
- @Override protected int gridCount() {
- return 1;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryPartitionedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryPartitionedSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryPartitionedSelfTest.java
deleted file mode 100644
index f5b16f5..0000000
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryPartitionedSelfTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.reducefields;
-
-import java.util.List;
-import org.apache.ignite.cache.CacheMode;
-import org.apache.ignite.internal.IgniteKernal;
-import org.apache.ignite.internal.processors.cache.query.CacheQuery;
-import org.apache.ignite.lang.IgniteBiTuple;
-
-import static org.apache.ignite.cache.CacheMode.PARTITIONED;
-
-/**
- * Reduce fields queries tests for partitioned cache.
- */
-public class GridCacheReduceFieldsQueryPartitionedSelfTest extends GridCacheAbstractReduceFieldsQuerySelfTest {
- /** {@inheritDoc} */
- @Override protected CacheMode cacheMode() {
- return PARTITIONED;
- }
-
- /** {@inheritDoc} */
- @Override protected int gridCount() {
- return 3;
- }
-
- /**
- * @throws Exception If failed.
- */
- public void testIncludeBackups() throws Exception {
- CacheQuery<List<?>> qry = ((IgniteKernal)grid(0)).getCache(null).context().queries().
- createSqlFieldsQuery("select age from Person", false);
-
- qry.includeBackups(true);
-
- int sum = 0;
-
- for (IgniteBiTuple<Integer, Integer> tuple : qry.execute(new AverageRemoteReducer()).get())
- sum += tuple.get1();
-
- // One backup, so sum is two times greater
- assertEquals("Sum", 200, sum);
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryReplicatedSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryReplicatedSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryReplicatedSelfTest.java
deleted file mode 100644
index 3e08d6d..0000000
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/reducefields/GridCacheReduceFieldsQueryReplicatedSelfTest.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.reducefields;
-
-import org.apache.ignite.cache.CacheMode;
-
-import static org.apache.ignite.cache.CacheMode.REPLICATED;
-
-/**
- * Reduce fields queries tests for replicated cache.
- */
-public class GridCacheReduceFieldsQueryReplicatedSelfTest extends GridCacheAbstractReduceFieldsQuerySelfTest {
- /** {@inheritDoc} */
- @Override protected CacheMode cacheMode() {
- return REPLICATED;
- }
-
- /** {@inheritDoc} */
- @Override protected int gridCount() {
- return 3;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
index 5c9acb5..88f1f1e 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSchemaIndexingTest.java
@@ -19,6 +19,7 @@ package org.apache.ignite.internal.processors.query;
import java.util.List;
import java.util.concurrent.Callable;
+import javax.cache.CacheException;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteLogger;
@@ -102,7 +103,7 @@ public class IgniteSqlSchemaIndexingTest extends GridCommonAbstractTest {
return null;
}
- }, IgniteException.class, "Schema for cache already registered");
+ }, IgniteException.class, "Cache already registered: ");
}
/**
@@ -185,7 +186,7 @@ public class IgniteSqlSchemaIndexingTest extends GridCommonAbstractTest {
cache.query(qryWrong);
return null;
}
- }, IgniteException.class, "Failed to parse query");
+ }, CacheException.class, "Failed to parse query");
SqlFieldsQuery qryCorrect = new SqlFieldsQuery("select f.\"id\", f.\"name\" " +
"from \""+schemaName+"\".\"Fact\" f");
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java
index fd52469..8ab70ba 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/IgniteSqlSplitterSelfTest.java
@@ -24,10 +24,15 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicLong;
+import javax.cache.CacheException;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.cache.CacheKeyConfiguration;
import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.CachePeekMode;
+import org.apache.ignite.cache.affinity.AffinityKeyMapped;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.configuration.CacheConfiguration;
@@ -38,7 +43,9 @@ import org.apache.ignite.internal.util.typedef.X;
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 org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.springframework.util.StringUtils;
/**
* Tests for correct distributed partitioned queries.
@@ -52,6 +59,10 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
@Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(gridName);
+ CacheKeyConfiguration keyCfg = new CacheKeyConfiguration(TestKey.class.getName(), "affKey");
+
+ cfg.setCacheKeyConfiguration(keyCfg);
+
cfg.setPeerClassLoadingEnabled(false);
TcpDiscoverySpi disco = new TcpDiscoverySpi();
@@ -97,6 +108,8 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
Integer.class, Integer.class));
try {
+ awaitPartitionMapExchange();
+
List<Integer> res = new ArrayList<>();
Random rnd = new GridRandom();
@@ -136,6 +149,8 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
Integer.class, GroupIndexTestValue.class));
try {
+ awaitPartitionMapExchange();
+
// Check group index usage.
String qry = "select 1 from GroupIndexTestValue ";
@@ -207,10 +222,659 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
}
/**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoins() throws Exception {
+ CacheConfiguration ccfg = cacheConfig("persOrg", true,
+ Integer.class, Person2.class, Integer.class, Organization.class);
+
+ IgniteCache<Integer, Object> c = ignite(0).getOrCreateCache(ccfg);
+
+ try {
+ awaitPartitionMapExchange();
+
+ doTestDistributedJoins(c, 30, 100, 1000, false);
+ doTestDistributedJoins(c, 30, 100, 1000, true);
+
+ doTestDistributedJoins(c, 3, 10, 3, false);
+ doTestDistributedJoins(c, 3, 10, 3, true);
+
+ doTestDistributedJoins(c, 300, 2000, 5, false);
+ doTestDistributedJoins(c, 300, 2000, 5, true);
+ }
+ finally {
+ c.destroy();
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoinsUnion() throws Exception {
+ CacheConfiguration ccfg = cacheConfig("persOrg", true,
+ Integer.class, Person2.class, Integer.class, Organization.class);
+
+ IgniteCache<Integer, Object> c = ignite(0).getOrCreateCache(ccfg);
+
+ try {
+ c.put(1, new Organization("o1"));
+ c.put(2, new Organization("o2"));
+ c.put(3, new Person2(1, "p1"));
+ c.put(4, new Person2(2, "p2"));
+ c.put(5, new Person2(3, "p3"));
+
+ String select = "select o.name n1, p.name n2 from Person2 p, Organization o where p.orgId = o._key and o._key=1" +
+ " union select o.name n1, p.name n2 from Person2 p, Organization o where p.orgId = o._key and o._key=2";
+
+ String plan = (String)c.query(new SqlFieldsQuery("explain " + select)
+ .setDistributedJoins(true).setEnforceJoinOrder(true))
+ .getAll().get(0).get(0);
+
+ X.println("Plan : " + plan);
+
+ assertEquals(2, StringUtils.countOccurrencesOf(plan, "batched"));
+ assertEquals(2, StringUtils.countOccurrencesOf(plan, "batched:unicast"));
+
+ assertEquals(2, c.query(new SqlFieldsQuery(select).setDistributedJoins(true)
+ .setEnforceJoinOrder(false)).getAll().size());
+
+ select = "select * from (" + select + ")";
+
+ plan = (String)c.query(new SqlFieldsQuery("explain " + select)
+ .setDistributedJoins(true).setEnforceJoinOrder(true))
+ .getAll().get(0).get(0);
+
+ X.println("Plan : " + plan);
+
+ assertEquals(2, StringUtils.countOccurrencesOf(plan, "batched"));
+ assertEquals(2, StringUtils.countOccurrencesOf(plan, "batched:unicast"));
+
+ assertEquals(2, c.query(new SqlFieldsQuery(select).setDistributedJoins(true)
+ .setEnforceJoinOrder(false)).getAll().size());
+ }
+ finally {
+ c.destroy();
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoinsUnionPartitionedReplicated() throws Exception {
+ CacheConfiguration ccfg1 = cacheConfig("pers", true,
+ Integer.class, Person2.class);
+ CacheConfiguration ccfg2 = cacheConfig("org", false,
+ Integer.class, Organization.class);
+
+ IgniteCache<Integer, Object> c1 = ignite(0).getOrCreateCache(ccfg1);
+ IgniteCache<Integer, Object> c2 = ignite(0).getOrCreateCache(ccfg2);
+
+ try {
+ c2.put(1, new Organization("o1"));
+ c2.put(2, new Organization("o2"));
+ c1.put(3, new Person2(1, "p1"));
+ c1.put(4, new Person2(2, "p2"));
+ c1.put(5, new Person2(3, "p3"));
+
+ String select0 = "select o.name n1, p.name n2 from \"pers\".Person2 p, \"org\".Organization o where p.orgId = o._key and o._key=1" +
+ " union select o.name n1, p.name n2 from \"org\".Organization o, \"pers\".Person2 p where p.orgId = o._key and o._key=2";
+
+ String plan = (String)c1.query(new SqlFieldsQuery("explain " + select0)
+ .setDistributedJoins(true))
+ .getAll().get(0).get(0);
+
+ X.println("Plan: " + plan);
+
+ assertEquals(0, StringUtils.countOccurrencesOf(plan, "batched"));
+ assertEquals(2, c1.query(new SqlFieldsQuery(select0).setDistributedJoins(true)).getAll().size());
+
+ String select = "select * from (" + select0 + ")";
+
+ plan = (String)c1.query(new SqlFieldsQuery("explain " + select)
+ .setDistributedJoins(true))
+ .getAll().get(0).get(0);
+
+ X.println("Plan : " + plan);
+
+ assertEquals(0, StringUtils.countOccurrencesOf(plan, "batched"));
+ assertEquals(2, c1.query(new SqlFieldsQuery(select).setDistributedJoins(true)).getAll().size());
+
+ String select1 = "select o.name n1, p.name n2 from \"pers\".Person2 p, \"org\".Organization o where p.orgId = o._key and o._key=1" +
+ " union select * from (select o.name n1, p.name n2 from \"org\".Organization o, \"pers\".Person2 p where p.orgId = o._key and o._key=2)";
+
+ plan = (String)c1.query(new SqlFieldsQuery("explain " + select1)
+ .setDistributedJoins(true)).getAll().get(0).get(0);
+
+ X.println("Plan: " + plan);
+
+ assertEquals(0, StringUtils.countOccurrencesOf(plan, "batched"));
+ assertEquals(2, c1.query(new SqlFieldsQuery(select).setDistributedJoins(true)).getAll().size());
+
+ select = "select * from (" + select1 + ")";
+
+ plan = (String)c1.query(new SqlFieldsQuery("explain " + select)
+ .setDistributedJoins(true)).getAll().get(0).get(0);
+
+ X.println("Plan : " + plan);
+
+ assertEquals(0, StringUtils.countOccurrencesOf(plan, "batched"));
+ assertEquals(2, c1.query(new SqlFieldsQuery(select).setDistributedJoins(true)).getAll().size());
+ }
+ finally {
+ c1.destroy();
+ c2.destroy();
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoinsPlan() throws Exception {
+ List<IgniteCache<Object, Object>> caches = new ArrayList<>();
+
+ IgniteCache<Object, Object> persPart =
+ ignite(0).createCache(cacheConfig("persPart", true, Integer.class, Person2.class));
+ caches.add(persPart);
+
+ IgniteCache<Object, Object> persPartAff =
+ ignite(0).createCache(cacheConfig("persPartAff", true, TestKey.class, Person2.class));
+ caches.add(persPartAff);
+
+ IgniteCache<Object, Object> orgPart =
+ ignite(0).createCache(cacheConfig("orgPart", true, Integer.class, Organization.class));
+ caches.add(orgPart);
+
+ IgniteCache<Object, Object> orgPartAff =
+ ignite(0).createCache(cacheConfig("orgPartAff", true, TestKey.class, Organization.class));
+ caches.add(orgPartAff);
+
+ IgniteCache<Object, Object> orgRepl =
+ ignite(0).createCache(cacheConfig("orgRepl", false, Integer.class, Organization.class));
+ caches.add(orgRepl);
+
+ IgniteCache<Object, Object> orgRepl2 =
+ ignite(0).createCache(cacheConfig("orgRepl2", false, Integer.class, Organization.class));
+ caches.add(orgRepl2);
+
+ try {
+ // Join two partitioned.
+
+ checkQueryPlan(persPart,
+ true,
+ 1,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p, \"orgPart\".Organization o " +
+ "where p.orgId = o._key",
+ "batched:unicast");
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p, \"orgPartAff\".Organization o " +
+ "where p.orgId = o.affKey",
+ "batched:unicast");
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p, \"orgPart\".Organization o " +
+ "where p.orgId = o._key",
+ "batched:unicast");
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p inner join \"orgPart\".Organization o " +
+ "on p.orgId = o._key",
+ "batched:unicast");
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p left outer join \"orgPart\".Organization o " +
+ "on p.orgId = o._key",
+ "batched:unicast");
+
+ checkQueryPlan(persPart,
+ true,
+ 1,
+ "select p._key k1, o._key k2 " +
+ "from \"orgPart\".Organization o, \"persPart\".Person2 p " +
+ "where p.orgId = o._key",
+ "batched:broadcast");
+
+ checkQueryPlan(persPart,
+ true,
+ 1,
+ "select p._key k1, o._key k2 " +
+ "from \"orgPartAff\".Organization o, \"persPart\".Person2 p " +
+ "where p.orgId = o.affKey",
+ "batched:broadcast");
+
+ // Join partitioned and replicated.
+
+ checkQueryPlan(persPart,
+ true,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p, \"orgRepl\".Organization o " +
+ "where p.orgId = o._key");
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p, \"orgRepl\".Organization o " +
+ "where p.orgId = o._key");
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p, (select * from \"orgRepl\".Organization) o " +
+ "where p.orgId = o._key");
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from (select * from \"orgRepl\".Organization) o, \"persPart\".Person2 p " +
+ "where p.orgId = o._key");
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p inner join \"orgRepl\".Organization o " +
+ "on p.orgId = o._key");
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from \"persPart\".Person2 p left outer join \"orgRepl\".Organization o " +
+ "on p.orgId = o._key");
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from \"orgRepl\".Organization o, \"persPart\".Person2 p " +
+ "where p.orgId = o._key");
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ "select p._key k1, o._key k2 " +
+ "from \"orgRepl\".Organization o inner join \"persPart\".Person2 p " +
+ "on p.orgId = o._key");
+
+// checkQueryPlan(persPart,
+// true,
+// 1,
+// "select p._key k1, o._key k2 " +
+// "from \"orgRepl\".Organization o left outer join \"persPart\".Person2 p " +
+// "on p.orgId = o._key",
+// "batched:broadcast");
+
+ // Join on affinity keys.
+
+ checkNoBatchedJoin(persPart, "select p._key k1, o._key k2 ",
+ "\"persPart\".Person2 p",
+ "\"orgPart\".Organization o",
+ "where p._key = o._key", true);
+
+ checkNoBatchedJoin(persPart, "select p._key k1, o._key k2 ",
+ "\"persPart\".Person2 p",
+ "\"orgRepl\".Organization o",
+ "where p._key = o._key", true);
+
+ checkNoBatchedJoin(persPartAff, "select p._key k1, o._key k2 ",
+ "\"persPartAff\".Person2 p",
+ "\"orgPart\".Organization o",
+ "where p.affKey = o._key", true);
+
+ checkNoBatchedJoin(persPartAff, "select p._key k1, o._key k2 ",
+ "\"persPartAff\".Person2 p",
+ "\"orgRepl\".Organization o",
+ "where p.affKey = o._key", true);
+
+ checkNoBatchedJoin(persPart, "select p._key k1, o._key k2 ",
+ "(select * from \"persPart\".Person2) p",
+ "\"orgPart\".Organization o",
+ "where p._key = o._key", false);
+
+ checkNoBatchedJoin(persPart, "select p._key k1, o._key k2 ",
+ "\"persPart\".Person2 p",
+ "(select * from \"orgPart\".Organization) o",
+ "where p._key = o._key", false);
+
+ // Join multiple.
+
+ {
+ String sql = "select * from " +
+ "(select o1._key k1, o2._key k2 from \"orgRepl\".Organization o1, \"orgRepl2\".Organization o2 where o1._key > o2._key) o, " +
+ "\"persPart\".Person2 p where p.orgId = o.k1";
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ sql);
+
+ checkQueryPlan(persPart,
+ true,
+ 0,
+ sql);
+
+ sql = "select o.k1, p1._key k2, p2._key k3 from " +
+ "(select o1._key k1, o2._key k2 from \"orgRepl\".Organization o1, \"orgRepl2\".Organization o2 where o1._key > o2._key) o, " +
+ "\"persPartAff\".Person2 p1, \"persPart\".Person2 p2 where p1._key=p2._key and p2.orgId = o.k1";
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ sql,
+ "persPartAff", "persPart", "batched:unicast", "orgRepl");
+
+ checkQueryFails(persPart, sql, true);
+
+ sql = "select o.k1, p._key k2 from " +
+ "(select o1._key k1, p1._key k2 from \"orgRepl\".Organization o1, \"persPart\".Person2 p1 where o1._key = p1.orgId) o, " +
+ "\"persPartAff\".Person2 p where p._key=o.k1";
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ sql,
+ "FROM \"persPart\"", "INNER JOIN \"orgRepl\"", "INNER JOIN \"persPartAff\"", "batched:broadcast");
+
+ checkQueryFails(persPart, sql, true);
+ }
+
+ {
+ String sql = "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"persPartAff\".Person2 p1, \"persPart\".Person2 p2, \"orgPart\".Organization o " +
+ "where p1.affKey=p2._key and p2.orgId = o._key";
+
+ checkQueryPlan(persPart,
+ true,
+ 2,
+ sql,
+ "batched:unicast", "batched:unicast");
+
+ checkQueryPlan(persPart,
+ false,
+ 2,
+ sql,
+ "batched:unicast", "batched:unicast");
+ }
+
+ {
+ String sql = "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"persPartAff\".Person2 p1, \"persPart\".Person2 p2, \"orgPart\".Organization o " +
+ "where p1.affKey > p2._key and p2.orgId = o._key";
+
+ checkQueryPlan(persPart,
+ true,
+ 2,
+ sql,
+ "batched:broadcast", "batched:unicast");
+
+ checkQueryPlan(persPart,
+ false,
+ 2,
+ sql,
+ "batched:broadcast", "batched:unicast");
+ }
+
+ {
+ // First join is collocated, second is replicated.
+
+ String sql = "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"persPartAff\".Person2 p1, \"persPart\".Person2 p2, \"orgRepl\".Organization o " +
+ "where p1.affKey=p2._key and p2.orgId = o._key";
+
+ checkQueryPlan(persPart,
+ true,
+ 0,
+ sql);
+
+ checkQueryPlan(persPart,
+ false,
+ 0,
+ sql);
+ }
+
+ {
+ String sql = "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"persPartAff\".Person2 p1, \"persPart\".Person2 p2, \"orgRepl\".Organization o " +
+ "where p1._key=p2._key and p2.orgId = o._key";
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ sql,
+ "batched:unicast");
+
+ sql = "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"orgRepl\".Organization o, \"persPartAff\".Person2 p1, \"persPart\".Person2 p2 " +
+ "where p1._key=p2._key and p2.orgId = o._key";
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ sql,
+ "batched:unicast");
+
+ sql = "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"persPartAff\".Person2 p1, \"orgRepl\".Organization o, \"persPart\".Person2 p2 " +
+ "where p1._key=p2._key and p2.orgId = o._key";
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ sql,
+ "batched:unicast");
+
+ sql = "select p1._key k1, p2._key k2, o._key k3 " +
+ "from (select * from \"orgRepl\".Organization) o, \"persPartAff\".Person2 p1, \"persPart\".Person2 p2 " +
+ "where p1._key=p2._key and p2.orgId = o._key";
+
+ checkQueryPlan(persPart,
+ false,
+ 1,
+ sql,
+ "batched:unicast");
+ }
+ }
+ finally {
+ for (IgniteCache<Object, Object> cache : caches)
+ ignite(0).destroyCache(cache.getName());
+ }
+ }
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoinsEnforceReplicatedNotLast() throws Exception {
+ List<IgniteCache<Object, Object>> caches = new ArrayList<>();
+
+ IgniteCache<Object, Object> persPart =
+ ignite(0).createCache(cacheConfig("persPart", true, Integer.class, Person2.class));
+ caches.add(persPart);
+
+ IgniteCache<Object, Object> persPartAff =
+ ignite(0).createCache(cacheConfig("persPartAff", true, TestKey.class, Person2.class));
+ caches.add(persPartAff);
+
+ IgniteCache<Object, Object> orgRepl =
+ ignite(0).createCache(cacheConfig("orgRepl", false, Integer.class, Organization.class));
+ caches.add(orgRepl);
+
+ try {
+ checkQueryFails(persPart, "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"orgRepl\".Organization o, \"persPartAff\".Person2 p1, \"persPart\".Person2 p2 " +
+ "where p1._key=p2._key and p2.orgId = o._key", true);
+
+ checkQueryFails(persPart, "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"persPartAff\".Person2 p1, \"orgRepl\".Organization o, \"persPart\".Person2 p2 " +
+ "where p1._key=p2._key and p2.orgId = o._key", true);
+
+ checkQueryFails(persPart, "select p1._key k1, p2._key k2, o._key k3 " +
+ "from \"persPartAff\".Person2 p1, (select * from \"orgRepl\".Organization) o, \"persPart\".Person2 p2 " +
+ "where p1._key=p2._key and p2.orgId = o._key", true);
+
+ checkQueryPlan(persPart,
+ true,
+ 0,
+ "select p._key k1, o._key k2 from \"orgRepl\".Organization o, \"persPart\".Person2 p");
+
+ checkQueryPlan(persPart,
+ true,
+ 0,
+ "select p._key k1, o._key k2 from \"orgRepl\".Organization o, \"persPart\".Person2 p union " +
+ "select p._key k1, o._key k2 from \"persPart\".Person2 p, \"orgRepl\".Organization o");
+ }
+ finally {
+ for (IgniteCache<Object, Object> cache : caches)
+ ignite(0).destroyCache(cache.getName());
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @param sql SQL.
+ * @param enforceJoinOrder Enforce join order flag.
+ */
+ private void checkQueryFails(final IgniteCache<Object, Object> cache,
+ String sql,
+ boolean enforceJoinOrder) {
+ final SqlFieldsQuery qry = new SqlFieldsQuery(sql);
+
+ qry.setDistributedJoins(true);
+ qry.setEnforceJoinOrder(enforceJoinOrder);
+
+ GridTestUtils.assertThrows(log, new Callable<Void>() {
+ @Override public Void call() throws Exception {
+ cache.query(qry);
+
+ return null;
+ }
+ }, CacheException.class, null);
+ }
+
+ /**
+ * @param cache Query cache.
+ * @param select Select clause.
+ * @param cache1 Cache name1.
+ * @param cache2 Cache name2.
+ * @param where Where clause.
+ * @param testEnforceJoinOrder If {@code true} tests query with enforced join order.
+ */
+ private void checkNoBatchedJoin(IgniteCache<Object, Object> cache,
+ String select,
+ String cache1,
+ String cache2,
+ String where,
+ boolean testEnforceJoinOrder) {
+ checkQueryPlan(cache,
+ false,
+ 0,
+ select +
+ "from " + cache1 + "," + cache2 + " "+ where);
+
+ checkQueryPlan(cache,
+ false,
+ 0,
+ select +
+ "from " + cache2 + "," + cache1 + " "+ where);
+
+ if (testEnforceJoinOrder) {
+ checkQueryPlan(cache,
+ true,
+ 0,
+ select +
+ "from " + cache1 + "," + cache2 + " "+ where);
+
+ checkQueryPlan(cache,
+ true,
+ 0,
+ select +
+ "from " + cache2 + "," + cache1 + " "+ where);
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @param expBatchedJoins Expected batched joins count.
+ * @param sql Query.
+ * @param expText Expected text to find in plan.
+ */
+ private void checkQueryPlan(IgniteCache<Object, Object> cache,
+ boolean enforceJoinOrder,
+ int expBatchedJoins,
+ String sql,
+ String...expText) {
+ checkQueryPlan(cache,
+ enforceJoinOrder,
+ expBatchedJoins,
+ new SqlFieldsQuery(sql),
+ expText);
+
+ checkQueryPlan(cache,
+ enforceJoinOrder,
+ expBatchedJoins,
+ new SqlFieldsQuery("select * from (" + sql + ")"),
+ expText);
+ }
+
+ /**
+ * @param cache Cache.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @param expBatchedJoins Expected batched joins count.
+ * @param qry Query.
+ * @param expText Expected text to find in plan.
+ */
+ private void checkQueryPlan(IgniteCache<Object, Object> cache,
+ boolean enforceJoinOrder,
+ int expBatchedJoins,
+ SqlFieldsQuery qry,
+ String...expText) {
+ qry.setEnforceJoinOrder(enforceJoinOrder);
+ qry.setDistributedJoins(true);
+
+ String plan = queryPlan(cache, qry);
+
+ log.info("Plan: " + plan);
+
+ assertEquals("Unexpected number of batched joins in plan [plan=" + plan + ", qry=" + qry + ']',
+ expBatchedJoins,
+ StringUtils.countOccurrencesOf(plan, "batched"));
+
+ int startIdx = 0;
+
+ for (String exp : expText) {
+ int idx = plan.indexOf(exp, startIdx);
+
+ if (idx == -1) {
+ fail("Plan does not contain expected string [startIdx=" + startIdx +
+ ", plan=" + plan +
+ ", exp=" + exp + ']');
+ }
+
+ startIdx = idx + 1;
+ }
+ }
+
+ /**
* Test HAVING clause.
*/
public void testHaving() {
- IgniteCache<Integer, Integer> c = ignite(0).getOrCreateCache(cacheConfig("ints", true,
+ IgniteCache<Integer, Integer> c = ignite(0).getOrCreateCache(cacheConfig("having", true,
Integer.class, Integer.class));
try {
@@ -256,6 +920,61 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
/**
* @param c Cache.
+ * @param orgs Number of organizations.
+ * @param persons Number of persons.
+ * @param pageSize Page size.
+ * @param enforceJoinOrder Enforce join order.
+ */
+ private void doTestDistributedJoins(IgniteCache<Integer, Object> c, int orgs, int persons, int pageSize,
+ boolean enforceJoinOrder) {
+ assertEquals(0, c.size(CachePeekMode.ALL));
+
+ int key = 0;
+
+ for (int i = 0; i < orgs; i++) {
+ Organization o = new Organization();
+
+ o.name = "Org" + i;
+
+ c.put(key++, o);
+ }
+
+ Random rnd = new GridRandom();
+
+ for (int i = 0; i < persons; i++) {
+ Person2 p = new Person2();
+
+ p.name = "Person" + i;
+ p.orgId = rnd.nextInt(orgs);
+
+ c.put(key++, p);
+ }
+
+ String select = "select count(*) from Organization o, Person2 p where p.orgId = o._key";
+
+ String plan = (String)c.query(new SqlFieldsQuery("explain " + select)
+ .setDistributedJoins(true).setEnforceJoinOrder(enforceJoinOrder).setPageSize(pageSize))
+ .getAll().get(0).get(0);
+
+ X.println("Plan : " + plan);
+
+ if (enforceJoinOrder)
+ assertTrue(plan, plan.contains("batched:broadcast"));
+ else
+ assertTrue(plan, plan.contains("batched:unicast"));
+
+ assertEquals(Long.valueOf(persons), c.query(new SqlFieldsQuery(select).setDistributedJoins(true)
+ .setEnforceJoinOrder(enforceJoinOrder).setPageSize(pageSize)).getAll().get(0).get(0));
+
+ c.clear();
+
+ assertEquals(0, c.size(CachePeekMode.ALL));
+ assertEquals(0L, c.query(new SqlFieldsQuery(select).setDistributedJoins(true)
+ .setEnforceJoinOrder(enforceJoinOrder).setPageSize(pageSize)).getAll().get(0).get(0));
+ }
+
+ /**
+ * @param c Cache.
* @param qry Query.
* @param args Arguments.
* @return Column as list.
@@ -282,8 +1001,6 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
*
*/
public void testFunctionNpe() {
- assert false : "https://issues.apache.org/jira/browse/IGNITE-1886";
-
IgniteCache<Integer, User> userCache = ignite(0).createCache(
cacheConfig("UserCache", true, Integer.class, User.class));
IgniteCache<Integer, UserOrder> userOrderCache = ignite(0).createCache(
@@ -391,9 +1108,11 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
* Test value.
*/
private static class GroupIndexTestValue implements Serializable {
+ /** */
@QuerySqlField(orderedGroups = @QuerySqlField.Group(name = "grpIdx", order = 0))
private int a;
+ /** */
@QuerySqlField(orderedGroups = @QuerySqlField.Group(name = "grpIdx", order = 1))
private int b;
@@ -407,23 +1126,131 @@ public class IgniteSqlSplitterSelfTest extends GridCommonAbstractTest {
}
}
+ /**
+ *
+ */
+ private static class Person2 implements Serializable {
+ /** */
+ @QuerySqlField(index = true)
+ int orgId;
+
+ /** */
+ @QuerySqlField
+ String name;
+
+ /**
+ *
+ */
+ public Person2() {
+ // No-op.
+ }
+
+ /**
+ * @param orgId Organization ID.
+ * @param name Name.
+ */
+ public Person2(int orgId, String name) {
+ this.orgId = orgId;
+ this.name = name;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class TestKey implements Serializable {
+ /** */
+ @QuerySqlField(index = true)
+ @AffinityKeyMapped
+ int affKey;
+
+ /** */
+ @QuerySqlField()
+ int id;
+
+ /**
+ * @param affKey Affinity key.
+ * @param id ID.
+ */
+ public TestKey(int affKey, int id) {
+ this.affKey = affKey;
+ this.id = id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TestKey personKey = (TestKey)o;
+
+ return id == personKey.id;
+
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return id;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ /** */
+ @QuerySqlField
+ String name;
+
+ /**
+ *
+ */
+ public Organization() {
+ // No-op.
+ }
+
+ /**
+ * @param name Organization name.
+ */
+ public Organization(String name) {
+ this.name = name;
+ }
+ }
+
+ /**
+ *
+ */
private static class User implements Serializable {
+ /** */
@QuerySqlField
private int id;
}
+ /**
+ *
+ */
private static class UserOrder implements Serializable {
+ /** */
@QuerySqlField
private int id;
+ /** */
@QuerySqlField
private int userId;
}
+ /**
+ *
+ */
private static class OrderGood implements Serializable {
+ /** */
@QuerySqlField
private int orderId;
+ /** */
@QuerySqlField
private int goodId;
}
[25/50] [abbrv] ignite git commit: ignite-3573 Support of Distributed
joins queries in REST API
Posted by vo...@apache.org.
ignite-3573 Support of Distributed joins queries in REST API
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/855281ed
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/855281ed
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/855281ed
Branch: refs/heads/ignite-3553
Commit: 855281ed33563f861921c5f93b39625db0206f72
Parents: 763f067
Author: agura <ag...@gridgain.com>
Authored: Mon Jul 25 14:31:10 2016 +0300
Committer: agura <ag...@gridgain.com>
Committed: Mon Jul 25 15:24:41 2016 +0300
----------------------------------------------------------------------
.../JettyRestProcessorAbstractSelfTest.java | 121 ++++++++++++++++++-
.../handlers/query/QueryCommandHandler.java | 4 +
.../rest/request/RestQueryRequest.java | 17 +++
.../http/jetty/GridJettyRestHandler.java | 5 +
4 files changed, 142 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/855281ed/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
index 81bffcf..637099b 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
@@ -1679,6 +1679,32 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
/**
* @throws Exception If failed.
*/
+ public void testDistributedJoinsQuery() throws Exception {
+ String qry = "select * from Person, \"organization\".Organization " +
+ "where \"organization\".Organization.id = Person.orgId " +
+ "and \"organization\".Organization.name = ?";
+
+ Map<String, String> params = new HashMap<>();
+ params.put("cmd", GridRestCommand.EXECUTE_SQL_QUERY.key());
+ params.put("type", "Person");
+ params.put("distributedJoins", "true");
+ params.put("pageSize", "10");
+ params.put("cacheName", "person");
+ params.put("qry", URLEncoder.encode(qry, CHARSET));
+ params.put("arg1", "o1");
+
+ String ret = content(params);
+
+ JsonNode items = jsonResponse(ret).get("items");
+
+ assertEquals(2, items.size());
+
+ assertFalse(queryCursorFound());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
public void testSqlFieldsQuery() throws Exception {
String qry = "select concat(firstName, ' ', lastName) from Person";
@@ -1700,6 +1726,28 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
/**
* @throws Exception If failed.
*/
+ public void testDistributedJoinsSqlFieldsQuery() throws Exception {
+ String qry = "select * from \"person\".Person p, \"organization\".Organization o where o.id = p.orgId";
+
+ Map<String, String> params = new HashMap<>();
+ params.put("cmd", GridRestCommand.EXECUTE_SQL_FIELDS_QUERY.key());
+ params.put("distributedJoins", "true");
+ params.put("pageSize", "10");
+ params.put("cacheName", "person");
+ params.put("qry", URLEncoder.encode(qry, CHARSET));
+
+ String ret = content(params);
+
+ JsonNode items = jsonResponse(ret).get("items");
+
+ assertEquals(4, items.size());
+
+ assertFalse(queryCursorFound());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
public void testSqlFieldsMetadataQuery() throws Exception {
String qry = "select firstName, lastName from Person";
@@ -1823,6 +1871,20 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
* Init cache.
*/
private void initCache() {
+ CacheConfiguration<Integer, Organization> orgCacheCfg = new CacheConfiguration<>("organization");
+
+ orgCacheCfg.setIndexedTypes(Integer.class, Organization.class);
+
+ IgniteCache<Integer, Organization> orgCache = ignite(0).getOrCreateCache(orgCacheCfg);
+
+ orgCache.clear();
+
+ Organization o1 = new Organization(1, "o1");
+ Organization o2 = new Organization(2, "o2");
+
+ orgCache.put(1, o1);
+ orgCache.put(2, o2);
+
CacheConfiguration<Integer, Person> personCacheCfg = new CacheConfiguration<>("person");
personCacheCfg.setIndexedTypes(Integer.class, Person.class);
@@ -1831,10 +1893,10 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
personCache.clear();
- Person p1 = new Person("John", "Doe", 2000);
- Person p2 = new Person("Jane", "Doe", 1000);
- Person p3 = new Person("John", "Smith", 1000);
- Person p4 = new Person("Jane", "Smith", 2000);
+ Person p1 = new Person(1, "John", "Doe", 2000);
+ Person p2 = new Person(1, "Jane", "Doe", 1000);
+ Person p3 = new Person(2, "John", "Smith", 1000);
+ Person p4 = new Person(2, "Jane", "Smith", 2000);
personCache.put(p1.getId(), p1);
personCache.put(p2.getId(), p2);
@@ -1848,6 +1910,43 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
assertEquals(2, personCache.query(qry).getAll().size());
}
+
+ /**
+ * Organization class.
+ */
+ public static class Organization implements Serializable {
+ /** Organization ID (indexed). */
+ @QuerySqlField(index = true)
+ private Integer id;
+
+ /** First name (not-indexed). */
+ @QuerySqlField(index = true)
+ private String name;
+
+ /**
+ * @param id Id.
+ * @param name Name.
+ */
+ Organization(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ /**
+ * @return Id.
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ * @return Name.
+ */
+ public String getName() {
+ return name;
+ }
+ }
+
/**
* Person class.
*/
@@ -1859,6 +1958,10 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
@QuerySqlField(index = true)
private Integer id;
+ /** Organization id. */
+ @QuerySqlField(index = true)
+ private Integer orgId;
+
/** First name (not-indexed). */
@QuerySqlField
private String firstName;
@@ -1876,15 +1979,23 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
* @param lastName Last name.
* @param salary Salary.
*/
- Person(String firstName, String lastName, double salary) {
+ Person(Integer orgId, String firstName, String lastName, double salary) {
id = PERSON_ID++;
+ this.orgId = orgId;
this.firstName = firstName;
this.lastName = lastName;
this.salary = salary;
}
/**
+ * @return Organization ID.
+ */
+ public Integer getOrganizationId() {
+ return orgId;
+ }
+
+ /**
* @return First name.
*/
public String getFirstName() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/855281ed/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
index 67e146b..4317dd9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
@@ -278,6 +278,8 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
((SqlQuery)qry).setArgs(req.arguments());
+ ((SqlQuery)qry).setDistributedJoins(req.distributedJoins());
+
break;
case SQL_FIELDS:
@@ -285,6 +287,8 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
((SqlFieldsQuery)qry).setArgs(req.arguments());
+ ((SqlFieldsQuery)qry).setDistributedJoins(req.distributedJoins());
+
break;
case SCAN:
http://git-wip-us.apache.org/repos/asf/ignite/blob/855281ed/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
index a719776..7159c83 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
@@ -32,6 +32,9 @@ public class RestQueryRequest extends GridRestRequest {
/** Page size. */
private Integer pageSize;
+ /** Distributed joins. */
+ private boolean distributedJoins;
+
/** Cache name. */
private String cacheName;
@@ -90,6 +93,20 @@ public class RestQueryRequest extends GridRestRequest {
}
/**
+ * @param distributedJoins New distributed joins.
+ */
+ public void distributedJoins(boolean distributedJoins) {
+ this.distributedJoins = distributedJoins;
+ }
+
+ /**
+ * @return Distributed joins.
+ */
+ public boolean distributedJoins() {
+ return distributedJoins;
+ }
+
+ /**
* @param cacheName Cache name.
*/
public void cacheName(String cacheName) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/855281ed/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
----------------------------------------------------------------------
diff --git a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
index c2679df..c864a10 100644
--- a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
+++ b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
@@ -566,6 +566,11 @@ public class GridJettyRestHandler extends AbstractHandler {
if (pageSize != null)
restReq0.pageSize(Integer.parseInt(pageSize));
+ String distributedJoins = (String)params.get("distributedJoins");
+
+ if (distributedJoins != null)
+ restReq0.distributedJoins(Boolean.parseBoolean(distributedJoins));
+
restReq0.cacheName((String)params.get("cacheName"));
if (cmd == EXECUTE_SQL_QUERY)
[22/50] [abbrv] ignite git commit: ignite-3563 Support
distributedJoins flag in JDBC driver
Posted by vo...@apache.org.
ignite-3563 Support distributedJoins flag in JDBC driver
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/0e15cf1d
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/0e15cf1d
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/0e15cf1d
Branch: refs/heads/ignite-3553
Commit: 0e15cf1df8b161dbc44f8d3810feca3192f05f73
Parents: 58d0544
Author: agura <ag...@gridgain.com>
Authored: Mon Jul 25 12:31:24 2016 +0300
Committer: agura <ag...@gridgain.com>
Committed: Mon Jul 25 15:11:12 2016 +0300
----------------------------------------------------------------------
.../jdbc2/JdbcDistributedJoinsQueryTest.java | 319 +++++++++++++++++++
.../jdbc/suite/IgniteJdbcDriverTestSuite.java | 2 +
.../org/apache/ignite/IgniteJdbcDriver.java | 14 +-
.../ignite/internal/jdbc2/JdbcConnection.java | 12 +
.../ignite/internal/jdbc2/JdbcQueryTask.java | 9 +-
.../ignite/internal/jdbc2/JdbcResultSet.java | 4 +-
.../ignite/internal/jdbc2/JdbcStatement.java | 2 +-
7 files changed, 357 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/0e15cf1d/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
new file mode 100644
index 0000000..53bfa73
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
@@ -0,0 +1,319 @@
+/*
+ * 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.jdbc2;
+
+import java.io.Serializable;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ConnectorConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.IgniteJdbcDriver.CFG_URL_PREFIX;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Tests for complex queries with distributed joins enabled (joins, etc.).
+ */
+public class JdbcDistributedJoinsQueryTest extends GridCommonAbstractTest {
+ /** IP finder. */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** JDBC URL. */
+ private static final String BASE_URL = CFG_URL_PREFIX + "distributedJoins=true@modules/clients/src/test/config/jdbc-config.xml";
+
+ /** Statement. */
+ private Statement stmt;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+ cache.setCacheMode(PARTITIONED);
+ cache.setBackups(1);
+ cache.setWriteSynchronizationMode(FULL_SYNC);
+ cache.setAtomicityMode(TRANSACTIONAL);
+ cache.setIndexedTypes(String.class, Organization.class, String.class, Person.class);
+
+ cfg.setCacheConfiguration(cache);
+
+ TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+ disco.setIpFinder(IP_FINDER);
+
+ cfg.setDiscoverySpi(disco);
+
+ cfg.setConnectorConfiguration(new ConnectorConfiguration());
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ startGrids(3);
+
+ IgniteCache<String, Organization> orgCache = grid(0).cache(null);
+
+ assert orgCache != null;
+
+ orgCache.put("o1", new Organization(1, "A"));
+ orgCache.put("o2", new Organization(2, "B"));
+
+ IgniteCache<String, Person> personCache = grid(0).cache(null);
+
+ assert personCache != null;
+
+ personCache.put("p1", new Person(1, "John White", 25, 1));
+ personCache.put("p2", new Person(2, "Joe Black", 35, 1));
+ personCache.put("p3", new Person(3, "Mike Green", 40, 2));
+
+ Class.forName("org.apache.ignite.IgniteJdbcDriver");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ stmt = DriverManager.getConnection(BASE_URL).createStatement();
+
+ assert stmt != null;
+ assert !stmt.isClosed();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ if (stmt != null) {
+ stmt.getConnection().close();
+ stmt.close();
+
+ assert stmt.isClosed();
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin() throws Exception {
+ ResultSet rs = stmt.executeQuery(
+ "select p.id, p.name, o.name as orgName from Person p, Organization o where p.orgId = o.id");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ int id = rs.getInt("id");
+
+ if (id == 1) {
+ assert "John White".equals(rs.getString("name"));
+ assert "A".equals(rs.getString("orgName"));
+ }
+ else if (id == 2) {
+ assert "Joe Black".equals(rs.getString("name"));
+ assert "A".equals(rs.getString("orgName"));
+ }
+ else if (id == 3) {
+ assert "Mike Green".equals(rs.getString("name"));
+ assert "B".equals(rs.getString("orgName"));
+ }
+ else
+ assert false : "Wrong ID: " + id;
+
+ cnt++;
+ }
+
+ assertEquals(3, cnt);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinWithoutAlias() throws Exception {
+ ResultSet rs = stmt.executeQuery(
+ "select p.id, p.name, o.name from Person p, Organization o where p.orgId = o.id");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ int id = rs.getInt(1);
+
+ if (id == 1) {
+ assert "John White".equals(rs.getString("name"));
+ assert "John White".equals(rs.getString(2));
+ assert "A".equals(rs.getString(3));
+ }
+ else if (id == 2) {
+ assert "Joe Black".equals(rs.getString("name"));
+ assert "Joe Black".equals(rs.getString(2));
+ assert "A".equals(rs.getString(3));
+ }
+ else if (id == 3) {
+ assert "Mike Green".equals(rs.getString("name"));
+ assert "Mike Green".equals(rs.getString(2));
+ assert "B".equals(rs.getString(3));
+ }
+ else
+ assert false : "Wrong ID: " + id;
+
+ cnt++;
+ }
+
+ assert cnt == 3;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testIn() throws Exception {
+ ResultSet rs = stmt.executeQuery("select name from Person where age in (25, 35)");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ assert "John White".equals(rs.getString("name")) ||
+ "Joe Black".equals(rs.getString("name"));
+
+ cnt++;
+ }
+
+ assert cnt == 2;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testBetween() throws Exception {
+ ResultSet rs = stmt.executeQuery("select name from Person where age between 24 and 36");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ assert "John White".equals(rs.getString("name")) ||
+ "Joe Black".equals(rs.getString("name"));
+
+ cnt++;
+ }
+
+ assert cnt == 2;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCalculatedValue() throws Exception {
+ ResultSet rs = stmt.executeQuery("select age * 2 from Person");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ assert rs.getInt(1) == 50 ||
+ rs.getInt(1) == 70 ||
+ rs.getInt(1) == 80;
+
+ cnt++;
+ }
+
+ assert cnt == 3;
+ }
+
+ /**
+ * Person.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ private static class Person implements Serializable {
+ /** ID. */
+ @QuerySqlField
+ private final int id;
+
+ /** Name. */
+ @QuerySqlField(index = false)
+ private final String name;
+
+ /** Age. */
+ @QuerySqlField
+ private final int age;
+
+ /** Organization ID. */
+ @QuerySqlField(index = true)
+ private final int orgId;
+
+ /**
+ * @param id ID.
+ * @param name Name.
+ * @param age Age.
+ * @param orgId Organization ID.
+ */
+ private Person(int id, String name, int age, int orgId) {
+ assert !F.isEmpty(name);
+ assert age > 0;
+ assert orgId > 0;
+
+ this.id = id;
+ this.name = name;
+ this.age = age;
+ this.orgId = orgId;
+ }
+ }
+
+ /**
+ * Organization.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ private static class Organization implements Serializable {
+ /** ID. */
+ @QuerySqlField
+ private final int id;
+
+ /** Name. */
+ @QuerySqlField(index = false)
+ private final String name;
+
+ /**
+ * @param id ID.
+ * @param name Name.
+ */
+ private Organization(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/0e15cf1d/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index 603ee81..b1053b0 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -18,6 +18,7 @@
package org.apache.ignite.jdbc.suite;
import junit.framework.TestSuite;
+import org.apache.ignite.internal.jdbc2.JdbcDistributedJoinsQueryTest;
import org.apache.ignite.jdbc.JdbcComplexQuerySelfTest;
import org.apache.ignite.jdbc.JdbcConnectionSelfTest;
import org.apache.ignite.jdbc.JdbcEmptyCacheSelfTest;
@@ -56,6 +57,7 @@ public class IgniteJdbcDriverTestSuite extends TestSuite {
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcPreparedStatementSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcResultSetSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcComplexQuerySelfTest.class));
+ suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcDistributedJoinsQueryTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcMetadataSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcEmptyCacheSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcLocalCachesSelfTest.class));
http://git-wip-us.apache.org/repos/asf/ignite/blob/0e15cf1d/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
index 567ff9f..d432c1e4 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
@@ -104,6 +104,11 @@ import org.apache.ignite.logger.java.JavaLogger;
* can make significant performance and network optimizations.
* Default value is {@code false}.
* </li>
+ * <li>
+ * {@code distributedJoins} - enables support of distributed joins feature. This flag does not make sense in
+ * combination with {@code local} and/or {@code collocated} flags with {@code true} value or in case of querying
+ * of local cache. Default value is {@code false}.
+ * </li>
* </ul>
*
* <h2 class="header">Configuration of Ignite Java client based connection</h2>
@@ -284,6 +289,9 @@ public class IgniteJdbcDriver implements Driver {
/** Collocated parameter name. */
private static final String PARAM_COLLOCATED = "collocated";
+ /** Distributed joins parameter name. */
+ private static final String PARAM_DISTRIBUTED_JOINS = "distributedJoins";
+
/** Hostname property name. */
public static final String PROP_HOST = PROP_PREFIX + "host";
@@ -302,6 +310,9 @@ public class IgniteJdbcDriver implements Driver {
/** Collocated property name. */
public static final String PROP_COLLOCATED = PROP_PREFIX + PARAM_COLLOCATED;
+ /** Distributed joins property name. */
+ public static final String PROP_DISTRIBUTED_JOINS = PROP_PREFIX + PARAM_DISTRIBUTED_JOINS;
+
/** Cache name property name. */
public static final String PROP_CFG = PROP_PREFIX + "cfg";
@@ -366,7 +377,8 @@ public class IgniteJdbcDriver implements Driver {
new PropertyInfo("Cache name", info.getProperty(PROP_CACHE), ""),
new PropertyInfo("Node ID", info.getProperty(PROP_NODE_ID), ""),
new PropertyInfo("Local", info.getProperty(PROP_LOCAL), ""),
- new PropertyInfo("Collocated", info.getProperty(PROP_COLLOCATED), "")
+ new PropertyInfo("Collocated", info.getProperty(PROP_COLLOCATED), ""),
+ new PropertyInfo("Distributed Joins", info.getProperty(PROP_DISTRIBUTED_JOINS), "")
);
if (info.getProperty(PROP_CFG) != null)
http://git-wip-us.apache.org/repos/asf/ignite/blob/0e15cf1d/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
index 2d2ce5d..6f0d9c4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
@@ -69,6 +69,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.ignite.IgniteJdbcDriver.PROP_CACHE;
import static org.apache.ignite.IgniteJdbcDriver.PROP_CFG;
import static org.apache.ignite.IgniteJdbcDriver.PROP_COLLOCATED;
+import static org.apache.ignite.IgniteJdbcDriver.PROP_DISTRIBUTED_JOINS;
import static org.apache.ignite.IgniteJdbcDriver.PROP_LOCAL;
import static org.apache.ignite.IgniteJdbcDriver.PROP_NODE_ID;
@@ -113,6 +114,9 @@ public class JdbcConnection implements Connection {
/** Collocated query flag. */
private boolean collocatedQry;
+ /** Distributed joins flag. */
+ private boolean distributedJoins;
+
/** Statements. */
final Set<JdbcStatement> statements = new HashSet<>();
@@ -132,6 +136,7 @@ public class JdbcConnection implements Connection {
this.cacheName = props.getProperty(PROP_CACHE);
this.locQry = Boolean.parseBoolean(props.getProperty(PROP_LOCAL));
this.collocatedQry = Boolean.parseBoolean(props.getProperty(PROP_COLLOCATED));
+ this.distributedJoins = Boolean.parseBoolean(props.getProperty(PROP_DISTRIBUTED_JOINS));
String nodeIdProp = props.getProperty(PROP_NODE_ID);
@@ -706,6 +711,13 @@ public class JdbcConnection implements Connection {
}
/**
+ * @return Distributed joins flag.
+ */
+ boolean isDistributedJoins() {
+ return distributedJoins;
+ }
+
+ /**
* Ensures that connection is not closed.
*
* @throws SQLException If connection is closed.
http://git-wip-us.apache.org/repos/asf/ignite/blob/0e15cf1d/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
index 1a5793a..c4911cb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
@@ -92,6 +92,9 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
/** Collocated query flag. */
private final boolean collocatedQry;
+ /** Distributed joins flag. */
+ private final boolean distributedJoins;
+
/**
* @param ignite Ignite.
* @param cacheName Cache name.
@@ -102,9 +105,11 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
* @param uuid UUID.
* @param locQry Local query flag.
* @param collocatedQry Collocated query flag.
+ * @param distributedJoins Distributed joins flag.
*/
public JdbcQueryTask(Ignite ignite, String cacheName, String sql,
- boolean loc, Object[] args, int fetchSize, UUID uuid, boolean locQry, boolean collocatedQry) {
+ boolean loc, Object[] args, int fetchSize, UUID uuid,
+ boolean locQry, boolean collocatedQry, boolean distributedJoins) {
this.ignite = ignite;
this.args = args;
this.uuid = uuid;
@@ -114,6 +119,7 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
this.loc = loc;
this.locQry = locQry;
this.collocatedQry = collocatedQry;
+ this.distributedJoins = distributedJoins;
}
/** {@inheritDoc} */
@@ -147,6 +153,7 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
qry.setPageSize(fetchSize);
qry.setLocal(locQry);
qry.setCollocated(collocatedQry);
+ qry.setDistributedJoins(distributedJoins);
QueryCursor<List<?>> qryCursor = cache.query(qry);
http://git-wip-us.apache.org/repos/asf/ignite/blob/0e15cf1d/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
index 69dddad..8e0e9d0 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
@@ -146,8 +146,8 @@ public class JdbcResultSet implements ResultSet {
boolean loc = nodeId == null;
- JdbcQueryTask qryTask = new JdbcQueryTask(loc ? ignite : null, conn.cacheName(),
- null, loc, null, fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery());
+ JdbcQueryTask qryTask = new JdbcQueryTask(loc ? ignite : null, conn.cacheName(), null, loc, null,
+ fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery(), conn.isDistributedJoins());
try {
JdbcQueryTask.QueryResult res =
http://git-wip-us.apache.org/repos/asf/ignite/blob/0e15cf1d/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
index 6b806f3..e187dc0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
@@ -96,7 +96,7 @@ public class JdbcStatement implements Statement {
boolean loc = nodeId == null;
JdbcQueryTask qryTask = new JdbcQueryTask(loc ? ignite : null, conn.cacheName(),
- sql, loc, args, fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery());
+ sql, loc, args, fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery(), conn.isDistributedJoins());
try {
JdbcQueryTask.QueryResult res =
[42/50] [abbrv] ignite git commit: Merge branch 'ignite-1.6.3' into
ignite-1.7
Posted by vo...@apache.org.
Merge branch 'ignite-1.6.3' into ignite-1.7
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/db99becc
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/db99becc
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/db99becc
Branch: refs/heads/ignite-3553
Commit: db99becc2071674c90720cfe0035443d85f4df95
Parents: 34d553a 4979c87
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Wed Jul 27 13:51:55 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Jul 27 13:51:55 2016 +0300
----------------------------------------------------------------------
.../visor/node/VisorNodeDataCollectorJob.java | 25 +++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
[49/50] [abbrv] ignite git commit: IGNITE-3577: ODBC: Added
simplified "Address" porperty. This closes #898.
Posted by vo...@apache.org.
IGNITE-3577: ODBC: Added simplified "Address" porperty. This closes #898.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/8386dd86
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/8386dd86
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/8386dd86
Branch: refs/heads/ignite-3553
Commit: 8386dd867a82e9814b43d54cca588a5d7a82ef4b
Parents: 33d35b3
Author: isapego <is...@gridgain.com>
Authored: Thu Jul 28 13:42:32 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Thu Jul 28 13:42:32 2016 +0300
----------------------------------------------------------------------
.../cpp/common/include/ignite/common/utils.h | 18 ++
.../cpp/core-test/config/cache-query.xml | 3 +-
.../cpp/odbc-test/config/queries-test.xml | 9 +-
.../cpp/odbc-test/src/configuration_test.cpp | 110 ++++++---
.../cpp/odbc-test/src/queries_test.cpp | 91 +++++---
.../include/ignite/odbc/config/configuration.h | 121 ++++++++--
.../cpp/odbc/include/ignite/odbc/connection.h | 38 ++--
.../cpp/odbc/src/config/configuration.cpp | 227 +++++++++----------
modules/platforms/cpp/odbc/src/connection.cpp | 47 ++--
modules/platforms/cpp/odbc/src/odbc.cpp | 27 ++-
10 files changed, 436 insertions(+), 255 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/common/include/ignite/common/utils.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/common/include/ignite/common/utils.h b/modules/platforms/cpp/common/include/ignite/common/utils.h
index c1046e2..331fcb2 100644
--- a/modules/platforms/cpp/common/include/ignite/common/utils.h
+++ b/modules/platforms/cpp/common/include/ignite/common/utils.h
@@ -179,6 +179,24 @@ namespace ignite
return res;
}
+
+ /**
+ * Check if the predicate returns true for all the elements of the
+ * sequence.
+ *
+ * @return True if the predicate returns true for all the elements
+ * of the sequence and false otherwise.
+ */
+ template<typename Iter, typename Pred>
+ bool AllOf(Iter begin, Iter end, Pred pred)
+ {
+ Iter i = begin;
+
+ while (i != end && pred(*i))
+ ++i;
+
+ return i == end;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/core-test/config/cache-query.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/core-test/config/cache-query.xml b/modules/platforms/cpp/core-test/config/cache-query.xml
index 06bc7f5..c3b5389 100644
--- a/modules/platforms/cpp/core-test/config/cache-query.xml
+++ b/modules/platforms/cpp/core-test/config/cache-query.xml
@@ -119,11 +119,12 @@
<property name="addresses">
<list>
<!-- In distributed environment, replace with actual host IP address. -->
- <value>127.0.0.1:47500..47501</value>
+ <value>127.0.0.1:47500</value>
</list>
</property>
</bean>
</property>
+ <property name="socketTimeout" value="300" />
</bean>
</property>
</bean>
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc-test/config/queries-test.xml
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/config/queries-test.xml b/modules/platforms/cpp/odbc-test/config/queries-test.xml
index f08f86d..054da42 100644
--- a/modules/platforms/cpp/odbc-test/config/queries-test.xml
+++ b/modules/platforms/cpp/odbc-test/config/queries-test.xml
@@ -26,12 +26,14 @@
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd">
<bean id="grid.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
- <!-- Set to true to enable distributed class loading for examples, default is false. -->
- <property name="peerClassLoadingEnabled" value="true"/>
+ <property name="localHost" value="127.0.0.1"/>
+ <property name="connectorConfiguration"><null/></property>
<!-- Enabling ODBC. -->
<property name="odbcConfiguration">
- <bean class="org.apache.ignite.configuration.OdbcConfiguration"></bean>
+ <bean class="org.apache.ignite.configuration.OdbcConfiguration">
+ <property name="endpointAddress" value="127.0.0.1:11110"/>
+ </bean>
</property>
<property name="cacheConfiguration">
@@ -89,6 +91,7 @@
</property>
</bean>
</property>
+ <property name="socketTimeout" value="300" />
</bean>
</property>
</bean>
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/configuration_test.cpp b/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
index 85aa3ff..10fd137 100644
--- a/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/configuration_test.cpp
@@ -24,47 +24,70 @@
#include <boost/test/unit_test.hpp>
#include <ignite/odbc/config/configuration.h>
+#include <ignite/ignite_error.h>
+#include <ignite/common/utils.h>
using namespace ignite::odbc::config;
namespace
{
- const char* testDriverName = "Ignite";
- const char* testServerHost = "testhost.com";
+ const std::string testDriverName = "Ignite Driver";
+ const std::string testServerHost = "testhost.com";
const uint16_t testServerPort = 4242;
- const char* testCacheName = "TestCache";
- const char* testDsn = "Ignite DSN";
+ const std::string testCacheName = "TestCache";
+ const std::string testDsn = "Ignite DSN";
+
+ const std::string testAddress = testServerHost + ':' + ignite::common::LexicalCast<std::string>(testServerPort);
}
-BOOST_AUTO_TEST_SUITE(ConfigurationTestSuite)
+void CheckValidAddress(const char* connectStr, uint16_t port)
+{
+ Configuration cfg;
+
+ BOOST_CHECK_NO_THROW(cfg.FillFromConnectString(connectStr));
+
+ BOOST_CHECK_EQUAL(cfg.GetPort(), port);
+}
void CheckConnectionConfig(const Configuration& cfg)
{
- BOOST_REQUIRE(cfg.GetDriver() == testDriverName);
- BOOST_REQUIRE(cfg.GetHost() == testServerHost);
- BOOST_REQUIRE(cfg.GetPort() == testServerPort);
- BOOST_REQUIRE(cfg.GetCache() == testCacheName);
- BOOST_REQUIRE(cfg.GetDsn().empty());
+ BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName);
+ BOOST_CHECK_EQUAL(cfg.GetHost(), testServerHost);
+ BOOST_CHECK_EQUAL(cfg.GetPort(), testServerPort);
+ BOOST_CHECK_EQUAL(cfg.GetAddress(), testAddress);
+ BOOST_CHECK_EQUAL(cfg.GetCache(), testCacheName);
+ BOOST_CHECK_EQUAL(cfg.GetDsn(), std::string());
std::stringstream constructor;
- constructor << "driver={" << testDriverName << "};"
- << "server=" << testServerHost << ";"
- << "port=" << testServerPort << ";"
- << "cache=" << testCacheName << ";";
+ constructor << "address=" << testAddress << ';'
+ << "cache=" << testCacheName << ';'
+ << "driver={" << testDriverName << "};";
const std::string& expectedStr = constructor.str();
- BOOST_REQUIRE(cfg.ToConnectString() == expectedStr);
+ BOOST_CHECK_EQUAL(cfg.ToConnectString(), expectedStr);
}
void CheckDsnConfig(const Configuration& cfg)
{
- BOOST_REQUIRE(cfg.GetDriver() == testDriverName);
- BOOST_REQUIRE(cfg.GetDsn() == testDsn);
- BOOST_REQUIRE(cfg.GetHost().empty());
- BOOST_REQUIRE(cfg.GetCache().empty());
- BOOST_REQUIRE(cfg.GetPort() == 0);
+ BOOST_CHECK_EQUAL(cfg.GetDriver(), testDriverName);
+ BOOST_CHECK_EQUAL(cfg.GetDsn(), testDsn);
+ BOOST_CHECK_EQUAL(cfg.GetCache(), Configuration::DefaultValue::cache);
+ BOOST_CHECK_EQUAL(cfg.GetAddress(), Configuration::DefaultValue::address);
+ BOOST_CHECK_EQUAL(cfg.GetHost(), std::string());
+ BOOST_CHECK_EQUAL(cfg.GetPort(), Configuration::DefaultValue::uintPort);
+}
+
+BOOST_AUTO_TEST_SUITE(ConfigurationTestSuite)
+
+BOOST_AUTO_TEST_CASE(CheckTestValuesNotEquealDefault)
+{
+ BOOST_CHECK_NE(testDriverName, Configuration::DefaultValue::driver);
+ BOOST_CHECK_NE(testAddress, Configuration::DefaultValue::address);
+ BOOST_CHECK_NE(testServerPort, Configuration::DefaultValue::uintPort);
+ BOOST_CHECK_NE(testCacheName, Configuration::DefaultValue::cache);
+ BOOST_CHECK_NE(testDsn, Configuration::DefaultValue::dsn);
}
BOOST_AUTO_TEST_CASE(TestConnectStringUppercase)
@@ -74,13 +97,12 @@ BOOST_AUTO_TEST_CASE(TestConnectStringUppercase)
std::stringstream constructor;
constructor << "DRIVER={" << testDriverName << "};"
- << "SERVER=" << testServerHost <<";"
- << "PORT=" << testServerPort << ";"
+ << "ADDRESS=" << testAddress << ';'
<< "CACHE=" << testCacheName;
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr.c_str(), connectStr.size());
+ cfg.FillFromConnectString(connectStr);
CheckConnectionConfig(cfg);
}
@@ -92,13 +114,12 @@ BOOST_AUTO_TEST_CASE(TestConnectStringLowercase)
std::stringstream constructor;
constructor << "driver={" << testDriverName << "};"
- << "server=" << testServerHost << ";"
- << "port=" << testServerPort << ";"
+ << "address=" << testAddress << ';'
<< "cache=" << testCacheName;
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr.c_str(), connectStr.size());
+ cfg.FillFromConnectString(connectStr);
CheckConnectionConfig(cfg);
}
@@ -110,8 +131,7 @@ BOOST_AUTO_TEST_CASE(TestConnectStringZeroTerminated)
std::stringstream constructor;
constructor << "driver={" << testDriverName << "};"
- << "server=" << testServerHost << ";"
- << "port=" << testServerPort << ";"
+ << "address=" << testAddress << ';'
<< "cache=" << testCacheName;
const std::string& connectStr = constructor.str();
@@ -128,13 +148,12 @@ BOOST_AUTO_TEST_CASE(TestConnectStringMixed)
std::stringstream constructor;
constructor << "Driver={" << testDriverName << "};"
- << "Server=" << testServerHost << ";"
- << "Port=" << testServerPort << ";"
+ << "Address=" << testAddress << ';'
<< "Cache=" << testCacheName;
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr.c_str(), connectStr.size());
+ cfg.FillFromConnectString(connectStr);
CheckConnectionConfig(cfg);
}
@@ -146,17 +165,40 @@ BOOST_AUTO_TEST_CASE(TestConnectStringWhitepaces)
std::stringstream constructor;
constructor << "DRIVER = {" << testDriverName << "} ;\n"
- << " SERVER =" << testServerHost << " ; \n"
- << "PORT= " << testServerPort << "; "
+ << " ADDRESS =" << testAddress << "; "
<< "CACHE = \n\r" << testCacheName;
const std::string& connectStr = constructor.str();
- cfg.FillFromConnectString(connectStr.c_str(), connectStr.size());
+ cfg.FillFromConnectString(connectStr);
CheckConnectionConfig(cfg);
}
+BOOST_AUTO_TEST_CASE(TestConnectStringInvalidAddress)
+{
+ Configuration cfg;
+
+ BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:0;"), ignite::IgniteError);
+ BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:00000;"), ignite::IgniteError);
+ BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:fdsf;"), ignite::IgniteError);
+ BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:123:1;"), ignite::IgniteError);
+ BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:12322221;"), ignite::IgniteError);
+ BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:12322a;"), ignite::IgniteError);
+ BOOST_CHECK_THROW(cfg.FillFromConnectString("Address=example.com:;"), ignite::IgniteError);
+}
+
+BOOST_AUTO_TEST_CASE(TestConnectStringValidAddress)
+{
+ Configuration cfg;
+
+ CheckValidAddress("Address=example.com:1;", 1);
+ CheckValidAddress("Address=example.com:31242;", 31242);
+ CheckValidAddress("Address=example.com:55555;", 55555);
+ CheckValidAddress("Address=example.com:110;", 110);
+ CheckValidAddress("Address=example.com;", Configuration::DefaultValue::uintPort);
+}
+
BOOST_AUTO_TEST_CASE(TestDsnStringUppercase)
{
Configuration cfg;
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc-test/src/queries_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
index cc3fa8e..ccb3a4d 100644
--- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp
@@ -24,6 +24,7 @@
#include <vector>
#include <string>
+#include <algorithm>
#ifndef _MSC_VER
# define BOOST_TEST_DYN_LINK
@@ -76,39 +77,12 @@ std::string GetOdbcErrorMessage(SQLSMALLINT handleType, SQLHANDLE handle)
struct QueriesTestSuiteFixture
{
/**
- * Constructor.
+ * Establish connection to node.
+ *
+ * @param connectStr Connection string.
*/
- QueriesTestSuiteFixture() : testCache(0), env(NULL), dbc(NULL), stmt(NULL)
+ void Connect(const std::string& connectStr)
{
- IgniteConfiguration cfg;
-
- cfg.jvmOpts.push_back("-Xdebug");
- cfg.jvmOpts.push_back("-Xnoagent");
- cfg.jvmOpts.push_back("-Djava.compiler=NONE");
- cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005");
- cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError");
-
-#ifdef IGNITE_TESTS_32
- cfg.jvmInitMem = 256;
- cfg.jvmMaxMem = 768;
-#else
- cfg.jvmInitMem = 1024;
- cfg.jvmMaxMem = 4096;
-#endif
-
- char* cfgPath = getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH");
-
- cfg.springCfgPath = std::string(cfgPath).append("/").append("queries-test.xml");
-
- IgniteError err;
-
- grid = Ignition::Start(cfg, &err);
-
- if (err.GetCode() != IgniteError::IGNITE_SUCCESS)
- BOOST_FAIL(err.GetText());
-
- testCache = grid.GetCache<int64_t, TestType>("cache");
-
// Allocate an environment handle
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
@@ -123,13 +97,16 @@ struct QueriesTestSuiteFixture
BOOST_REQUIRE(dbc != NULL);
// Connect string
- SQLCHAR connectStr[] = "DRIVER={Apache Ignite};SERVER=localhost;PORT=10800;CACHE=cache";
+ std::vector<SQLCHAR> connectStr0;
+
+ connectStr0.reserve(connectStr.size() + 1);
+ std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0));
SQLCHAR outstr[ODBC_BUFFER_SIZE];
SQLSMALLINT outstrlen;
// Connecting to ODBC server.
- SQLRETURN ret = SQLDriverConnect(dbc, NULL, connectStr, static_cast<SQLSMALLINT>(sizeof(connectStr)),
+ SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast<SQLSMALLINT>(connectStr0.size()),
outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
if (!SQL_SUCCEEDED(ret))
@@ -146,6 +123,41 @@ struct QueriesTestSuiteFixture
}
/**
+ * Constructor.
+ */
+ QueriesTestSuiteFixture() : testCache(0), env(NULL), dbc(NULL), stmt(NULL)
+ {
+ IgniteConfiguration cfg;
+
+ cfg.jvmOpts.push_back("-Xdebug");
+ cfg.jvmOpts.push_back("-Xnoagent");
+ cfg.jvmOpts.push_back("-Djava.compiler=NONE");
+ cfg.jvmOpts.push_back("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005");
+ cfg.jvmOpts.push_back("-XX:+HeapDumpOnOutOfMemoryError");
+
+#ifdef IGNITE_TESTS_32
+ cfg.jvmInitMem = 256;
+ cfg.jvmMaxMem = 768;
+#else
+ cfg.jvmInitMem = 1024;
+ cfg.jvmMaxMem = 4096;
+#endif
+
+ char* cfgPath = getenv("IGNITE_NATIVE_TEST_ODBC_CONFIG_PATH");
+
+ cfg.springCfgPath = std::string(cfgPath).append("/").append("queries-test.xml");
+
+ IgniteError err;
+
+ grid = Ignition::Start(cfg, &err);
+
+ if (err.GetCode() != IgniteError::IGNITE_SUCCESS)
+ BOOST_FAIL(err.GetText());
+
+ testCache = grid.GetCache<int64_t, TestType>("cache");
+ }
+
+ /**
* Destructor.
*/
~QueriesTestSuiteFixture()
@@ -166,6 +178,8 @@ struct QueriesTestSuiteFixture
template<typename T>
void CheckTwoRowsInt(SQLSMALLINT type)
{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
SQLRETURN ret;
TestType in1(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
@@ -273,6 +287,11 @@ struct QueriesTestSuiteFixture
BOOST_FIXTURE_TEST_SUITE(QueriesTestSuite, QueriesTestSuiteFixture)
+BOOST_AUTO_TEST_CASE(TestLegacyConnection)
+{
+ Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;CACHE=cache");
+}
+
BOOST_AUTO_TEST_CASE(TestTwoRowsInt8)
{
CheckTwoRowsInt<int8_t>(SQL_C_STINYINT);
@@ -315,6 +334,8 @@ BOOST_AUTO_TEST_CASE(TestTwoRowsUint64)
BOOST_AUTO_TEST_CASE(TestTwoRowsString)
{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
SQLRETURN ret;
TestType in1(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
@@ -408,6 +429,8 @@ BOOST_AUTO_TEST_CASE(TestTwoRowsString)
BOOST_AUTO_TEST_CASE(TestOneRowString)
{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
SQLRETURN ret;
TestType in(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
@@ -469,6 +492,8 @@ BOOST_AUTO_TEST_CASE(TestOneRowString)
BOOST_AUTO_TEST_CASE(TestOneRowStringLen)
{
+ Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;CACHE=cache");
+
SQLRETURN ret;
TestType in(1, 2, 3, 4, "5", 6.0f, 7.0, true, Guid(8, 9), BinaryUtils::MakeDateGmt(1987, 6, 5), BinaryUtils::MakeTimestampGmt(1998, 12, 27, 1, 2, 3, 456));
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
index d6d7944..05fe8bf 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/config/configuration.h
@@ -23,6 +23,7 @@
#include <map>
#include <ignite/common/common.h>
+#include <ignite/common/utils.h>
namespace ignite
{
@@ -36,6 +37,68 @@ namespace ignite
class Configuration
{
public:
+ /** Map containing connect arguments. */
+ typedef std::map<std::string, std::string> ArgumentMap;
+
+ /** Connection attribute keywords. */
+ struct Key
+ {
+ /** Connection attribute keyword for DSN attribute. */
+ static const std::string dsn;
+
+ /** Connection attribute keyword for Driver attribute. */
+ static const std::string driver;
+
+ /** Connection attribute keyword for cache attribute. */
+ static const std::string cache;
+
+ /** Connection attribute keyword for address attribute. */
+ static const std::string address;
+
+ /** Connection attribute keyword for server attribute. */
+ static const std::string server;
+
+ /** Connection attribute keyword for port attribute. */
+ static const std::string port;
+ };
+
+ /** Default values for configuration. */
+ struct DefaultValue
+ {
+ /** Default value for DSN attribute. */
+ static const std::string dsn;
+
+ /** Default value for Driver attribute. */
+ static const std::string driver;
+
+ /** Default value for cache attribute. */
+ static const std::string cache;
+
+ /** Default value for address attribute. */
+ static const std::string address;
+
+ /** Default value for server attribute. */
+ static const std::string server;
+
+ /** Default value for port attribute. */
+ static const std::string port;
+
+ /** Default value for port attribute. Uint16 value. */
+ static const uint16_t uintPort;
+ };
+
+ /**
+ * Connection end point structure.
+ */
+ struct EndPoint
+ {
+ /** Remote host. */
+ std::string host;
+
+ /** TCP port. */
+ uint16_t port;
+ };
+
/**
* Default constructor.
*/
@@ -83,7 +146,7 @@ namespace ignite
*/
uint16_t GetPort() const
{
- return port;
+ return endPoint.port;
}
/**
@@ -93,7 +156,7 @@ namespace ignite
*/
const std::string& GetDsn() const
{
- return dsn;
+ return GetStringValue(Key::dsn, DefaultValue::dsn);
}
/**
@@ -103,7 +166,7 @@ namespace ignite
*/
const std::string& GetDriver() const
{
- return driver;
+ return GetStringValue(Key::driver, DefaultValue::driver);
}
/**
@@ -113,7 +176,7 @@ namespace ignite
*/
const std::string& GetHost() const
{
- return host;
+ return endPoint.host;
}
/**
@@ -123,15 +186,29 @@ namespace ignite
*/
const std::string& GetCache() const
{
- return cache;
+ return GetStringValue(Key::cache, DefaultValue::cache);
}
- private:
- IGNITE_NO_COPY_ASSIGNMENT(Configuration);
+ /**
+ * Get address.
+ *
+ * @return Address.
+ */
+ const std::string& GetAddress() const
+ {
+ return GetStringValue(Key::address, DefaultValue::address);
+ }
- /** Map containing connect arguments. */
- typedef std::map<std::string, std::string> ArgumentMap;
+ /**
+ * Get string value from the config.
+ *
+ * @param key Configuration key.
+ * @param dflt Default value to be returned if there is no value stored.
+ * @return Found or default value.
+ */
+ const std::string& GetStringValue(const std::string& key, const std::string& dflt) const;
+ private:
/**
* Parse connect string into key-value storage.
*
@@ -139,22 +216,22 @@ namespace ignite
* @param len String length.
* @param params Parsing result.
*/
- void ParseAttributeList(const char* str, size_t len, char delimeter, ArgumentMap& args) const;
+ static void ParseAttributeList(const char* str, size_t len, char delimeter, ArgumentMap& args);
- /** Data Source Name. */
- std::string dsn;
-
- /** Driver name. */
- std::string driver;
-
- /** Server hostname. */
- std::string host;
+ /**
+ * Parse address and extract connection end-point.
+ *
+ * @throw IgniteException if address can not be parsed.
+ * @param address Address string to parse.
+ * @param res Result is placed here.
+ */
+ static void ParseAddress(const std::string& address, EndPoint& res);
- /** Port of the server. */
- uint16_t port;
+ /** Arguments. */
+ ArgumentMap arguments;
- /** Cache name. */
- std::string cache;
+ /** Connection end-point. */
+ EndPoint endPoint;
};
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
index 10ceb19..00bdfc8 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/connection.h
@@ -25,6 +25,7 @@
#include "ignite/odbc/parser.h"
#include "ignite/odbc/system/socket_client.h"
#include "ignite/odbc/config/connection_info.h"
+#include "ignite/odbc/config/configuration.h"
#include "ignite/odbc/diagnostic/diagnosable_adapter.h"
namespace ignite
@@ -74,18 +75,16 @@ namespace ignite
/**
* Establish connection to ODBC server.
*
- * @param server Server (DSN).
+ * @param connectStr Connection string.
*/
- void Establish(const std::string& server);
+ void Establish(const std::string& connectStr);
/**
* Establish connection to ODBC server.
*
- * @param host Host.
- * @param port Port.
- * @param cache Cache name to connect to.
+ * @param cfg Configuration.
*/
- void Establish(const std::string& host, uint16_t port, const std::string& cache);
+ void Establish(const config::Configuration cfg);
/**
* Release established connection.
@@ -124,6 +123,13 @@ namespace ignite
const std::string& GetCache() const;
/**
+ * Get configuration.
+ *
+ * @return Connection configuration.
+ */
+ const config::Configuration& GetConfiguration() const;
+
+ /**
* Create diagnostic record associated with the Connection instance.
*
* @param sqlState SQL state.
@@ -132,8 +138,8 @@ namespace ignite
* @param columnNum Associated column number.
* @return DiagnosticRecord associated with the instance.
*/
- diagnostic::DiagnosticRecord CreateStatusRecord(SqlState sqlState,
- const std::string& message, int32_t rowNum = 0, int32_t columnNum = 0) const;
+ static diagnostic::DiagnosticRecord CreateStatusRecord(SqlState sqlState,
+ const std::string& message, int32_t rowNum = 0, int32_t columnNum = 0);
/**
* Synchronously send request message and receive response.
@@ -172,21 +178,19 @@ namespace ignite
* Establish connection to ODBC server.
* Internal call.
*
- * @param server Server (DNS).
+ * @param connectStr Connection string.
* @return Operation result.
*/
- SqlResult InternalEstablish(const std::string& server);
+ SqlResult InternalEstablish(const std::string& connectStr);
/**
* Establish connection to ODBC server.
* Internal call.
*
- * @param host Host.
- * @param port Port.
- * @param cache Cache name to connect to.
+ * @param cfg Configuration.
* @return Operation result.
*/
- SqlResult InternalEstablish(const std::string& host, uint16_t port, const std::string& cache);
+ SqlResult InternalEstablish(const config::Configuration cfg);
/**
* Release established connection.
@@ -269,11 +273,11 @@ namespace ignite
/** State flag. */
bool connected;
- /** Cache name. */
- std::string cache;
-
/** Message parser. */
Parser parser;
+
+ /** Configuration. */
+ config::Configuration config;
};
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc/src/config/configuration.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/config/configuration.cpp b/modules/platforms/cpp/odbc/src/config/configuration.cpp
index 8d57dee..45b0507 100644
--- a/modules/platforms/cpp/odbc/src/config/configuration.cpp
+++ b/modules/platforms/cpp/odbc/src/config/configuration.cpp
@@ -15,8 +15,6 @@
* limitations under the License.
*/
-#include <cstring>
-
#include <string>
#include <sstream>
#include <algorithm>
@@ -31,50 +29,25 @@ namespace ignite
{
namespace config
{
- /** Default values for configuration. */
- namespace dflt
- {
- /** Default value for DSN attribute. */
- const std::string dsn = "Default Apache Ignite DSN";
-
- /** Default value for Driver attribute. */
- const std::string driver = "Apache Ignite";
-
- /** Default value for host attribute. */
- const std::string host = "localhost";
-
- /** Default value for port attribute. */
- const uint16_t port = 10800;
-
- /** Default value for cache attribute. */
- const std::string cache = "";
- }
-
- /** Connection attribute keywords. */
- namespace attrkey
- {
- /** Connection attribute keyword for DSN attribute. */
- const std::string dsn = "dsn";
-
- /** Connection attribute keyword for Driver attribute. */
- const std::string driver = "driver";
-
- /** Connection attribute keyword for server host attribute. */
- const std::string host = "server";
-
- /** Connection attribute keyword for server port attribute. */
- const std::string port = "port";
-
- /** Connection attribute keyword for cache attribute. */
- const std::string cache = "cache";
- }
+ const std::string Configuration::Key::dsn = "dsn";
+ const std::string Configuration::Key::driver = "driver";
+ const std::string Configuration::Key::cache = "cache";
+ const std::string Configuration::Key::address = "address";
+ const std::string Configuration::Key::server = "server";
+ const std::string Configuration::Key::port = "port";
+
+ const std::string Configuration::DefaultValue::dsn = "Apache Ignite DSN";
+ const std::string Configuration::DefaultValue::driver = "Apache Ignite";
+ const std::string Configuration::DefaultValue::cache = "";
+ const std::string Configuration::DefaultValue::address = "";
+ const std::string Configuration::DefaultValue::server = "";
+ const std::string Configuration::DefaultValue::port = "10800";
+ const uint16_t Configuration::DefaultValue::uintPort = common::LexicalCast<uint16_t>(port);
Configuration::Configuration() :
- dsn(dflt::dsn), driver(dflt::driver),
- host(dflt::host), port(dflt::port),
- cache(dflt::cache)
+ arguments()
{
- // No-op.
+ ParseAddress(DefaultValue::address, endPoint);
}
Configuration::~Configuration()
@@ -84,7 +57,11 @@ namespace ignite
void Configuration::FillFromConnectString(const char* str, size_t len)
{
- ArgumentMap connect_attributes;
+ // Initializing map.
+ arguments.clear();
+
+ // Initializing DSN to empty string.
+ arguments[Key::dsn].clear();
// Ignoring terminating zero byte if present.
// Some Driver Managers pass zero-terminated connection string
@@ -92,39 +69,19 @@ namespace ignite
if (len && !str[len - 1])
--len;
- ParseAttributeList(str, len, ';', connect_attributes);
-
- ArgumentMap::const_iterator it;
+ ParseAttributeList(str, len, ';', arguments);
- it = connect_attributes.find(attrkey::dsn);
- if (it != connect_attributes.end())
- dsn = it->second;
- else
- dsn.clear();
-
- it = connect_attributes.find(attrkey::driver);
- if (it != connect_attributes.end())
- driver = it->second;
- else
- driver = dflt::driver;
-
- it = connect_attributes.find(attrkey::host);
- if (it != connect_attributes.end())
- host = it->second;
- else
- host = dflt::host;
-
- it = connect_attributes.find(attrkey::port);
- if (it != connect_attributes.end())
- port = atoi(it->second.c_str());
- else
- port = dflt::port;
-
- it = connect_attributes.find(attrkey::cache);
- if (it != connect_attributes.end())
- cache = it->second;
+ ArgumentMap::const_iterator it = arguments.find(Key::address);
+ if (it != arguments.end())
+ {
+ // Parsing address.
+ ParseAddress(it->second, endPoint);
+ }
else
- cache = dflt::cache;
+ {
+ endPoint.host = GetStringValue(Key::server, DefaultValue::server);
+ endPoint.port = common::LexicalCast<uint16_t>(GetStringValue(Key::port, DefaultValue::port));
+ }
}
void Configuration::FillFromConnectString(const std::string& str)
@@ -136,27 +93,27 @@ namespace ignite
{
std::stringstream connect_string_buffer;
- if (!driver.empty())
- connect_string_buffer << attrkey::driver << "={" << driver << "};";
-
- if (!host.empty())
- connect_string_buffer << attrkey::host << '=' << host << ';';
-
- if (port)
- connect_string_buffer << attrkey::port << '=' << port << ';';
+ for (ArgumentMap::const_iterator it = arguments.begin(); it != arguments.end(); ++it)
+ {
+ const std::string& key = it->first;
+ const std::string& value = it->second;
- if (!dsn.empty())
- connect_string_buffer << attrkey::dsn << '=' << dsn << ';';
+ if (value.empty())
+ continue;
- if (!cache.empty())
- connect_string_buffer << attrkey::cache << '=' << cache << ';';
+ if (value.find(' ') == std::string::npos)
+ connect_string_buffer << key << '=' << value << ';';
+ else
+ connect_string_buffer << key << "={" << value << "};";
+ }
return connect_string_buffer.str();
}
void Configuration::FillFromConfigAttributes(const char * attributes)
{
- ArgumentMap config_attributes;
+ // Initializing map.
+ arguments.clear();
size_t len = 0;
@@ -166,45 +123,34 @@ namespace ignite
++len;
- ParseAttributeList(attributes, len, '\0', config_attributes);
-
- ArgumentMap::const_iterator it;
-
- it = config_attributes.find(attrkey::dsn);
- if (it != config_attributes.end())
- dsn = it->second;
- else
- dsn = dflt::dsn;
+ ParseAttributeList(attributes, len, '\0', arguments);
- it = config_attributes.find(attrkey::driver);
- if (it != config_attributes.end())
- driver = it->second;
+ ArgumentMap::const_iterator it = arguments.find(Key::address);
+ if (it != arguments.end())
+ {
+ // Parsing address.
+ ParseAddress(it->second, endPoint);
+ }
else
- driver.clear();
+ {
+ endPoint.host = GetStringValue(Key::server, DefaultValue::server);
+ endPoint.port = common::LexicalCast<uint16_t>(GetStringValue(Key::port, DefaultValue::port));
+ }
+ }
- it = config_attributes.find(attrkey::host);
- if (it != config_attributes.end())
- host = it->second;
- else
- host.clear();
+ const std::string& Configuration::GetStringValue(const std::string& key, const std::string& dflt) const
+ {
+ ArgumentMap::const_iterator it = arguments.find(common::ToLower(key));
- it = config_attributes.find(attrkey::port);
- if (it != config_attributes.end())
- port = atoi(it->second.c_str());
- else
- port = 0;
+ if (it != arguments.end())
+ return it->second;
- it = config_attributes.find(attrkey::cache);
- if (it != config_attributes.end())
- cache = it->second;
- else
- cache.clear();
+ return dflt;
}
- void Configuration::ParseAttributeList(const char * str, size_t len, char delimeter, ArgumentMap & args) const
+ void Configuration::ParseAttributeList(const char * str, size_t len, char delimeter, ArgumentMap & args)
{
std::string connect_str(str, len);
- args.clear();
while (!connect_str.empty())
{
@@ -245,6 +191,51 @@ namespace ignite
connect_str.erase(attr_begin - 1);
}
}
+
+ void Configuration::ParseAddress(const std::string& address, EndPoint& res)
+ {
+ int64_t colonNum = std::count(address.begin(), address.end(), ':');
+
+ if (colonNum == 0)
+ {
+ res.host = address;
+ res.port = DefaultValue::uintPort;
+ }
+ else if (colonNum == 1)
+ {
+ size_t pos = address.find(':');
+
+ if (pos == address.size() - 1)
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
+ "Invalid address format: no port after colon");
+
+ res.host = address.substr(0, pos);
+
+ std::string port = address.substr(pos + 1);
+
+ if (!common::AllOf(port.begin(), port.end(), isdigit))
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
+ "Invalid address format: port can only contain digits");
+
+ int32_t intPort = common::LexicalCast<int32_t>(port);
+
+ if (port.size() > sizeof("65535") - 1 || intPort > UINT16_MAX)
+ {
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
+ "Invalid address format: Port value is too large,"
+ " valid value should be in range from 1 to 65535");
+ }
+
+ if (intPort == 0)
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
+ "Invalid address format: Port value can not be zero");
+
+ res.port = static_cast<uint16_t>(intPort);
+ }
+ else
+ throw IgniteError(IgniteError::IGNITE_ERR_GENERIC,
+ "Invalid address format: too many colons");
+ }
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc/src/connection.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp
index 2441759..844ad70 100644
--- a/modules/platforms/cpp/odbc/src/connection.cpp
+++ b/modules/platforms/cpp/odbc/src/connection.cpp
@@ -41,7 +41,11 @@ namespace ignite
{
const std::string Connection::PROTOCOL_VERSION_SINCE = "1.6.0";
- Connection::Connection() : socket(), connected(false), cache(), parser()
+ Connection::Connection() :
+ socket(),
+ connected(false),
+ parser(),
+ config()
{
// No-op.
}
@@ -53,8 +57,8 @@ namespace ignite
const config::ConnectionInfo& Connection::GetInfo() const
{
- // Connection info is the same for all connections now.
- static config::ConnectionInfo info;
+ // Connection info is constant and the same for all connections now.
+ const static config::ConnectionInfo info;
return info;
}
@@ -76,32 +80,38 @@ namespace ignite
return res;
}
- void Connection::Establish(const std::string& server)
+ void Connection::Establish(const std::string& connectStr)
{
- IGNITE_ODBC_API_CALL(InternalEstablish(server));
+ IGNITE_ODBC_API_CALL(InternalEstablish(connectStr));
}
- SqlResult Connection::InternalEstablish(const std::string& server)
+ SqlResult Connection::InternalEstablish(const std::string& connectStr)
{
config::Configuration config;
- if (server != config.GetDsn())
+ try
+ {
+ config.FillFromConnectString(connectStr);
+ }
+ catch (IgniteError& e)
{
- AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, "Unknown server.");
+ AddStatusRecord(SQL_STATE_HY000_GENERAL_ERROR, e.GetText());
return SQL_RESULT_ERROR;
}
- return InternalEstablish(config.GetHost(), config.GetPort(), config.GetCache());
+ return InternalEstablish(config);
}
- void Connection::Establish(const std::string& host, uint16_t port, const std::string& cache)
+ void Connection::Establish(const config::Configuration cfg)
{
- IGNITE_ODBC_API_CALL(InternalEstablish(host, port, cache));
+ IGNITE_ODBC_API_CALL(InternalEstablish(cfg));
}
- SqlResult Connection::InternalEstablish(const std::string & host, uint16_t port, const std::string & cache)
+ SqlResult Connection::InternalEstablish(const config::Configuration cfg)
{
+ config = cfg;
+
if (connected)
{
AddStatusRecord(SQL_STATE_08002_ALREADY_CONNECTED, "Already connected.");
@@ -109,9 +119,7 @@ namespace ignite
return SQL_RESULT_ERROR;
}
- this->cache = cache;
-
- connected = socket.Connect(host.c_str(), port);
+ connected = socket.Connect(cfg.GetHost().c_str(), cfg.GetPort());
if (!connected)
{
@@ -262,11 +270,16 @@ namespace ignite
const std::string& Connection::GetCache() const
{
- return cache;
+ return config.GetCache();
+ }
+
+ const config::Configuration& Connection::GetConfiguration() const
+ {
+ return config;
}
diagnostic::DiagnosticRecord Connection::CreateStatusRecord(SqlState sqlState,
- const std::string& message, int32_t rowNum, int32_t columnNum) const
+ const std::string& message, int32_t rowNum, int32_t columnNum)
{
return diagnostic::DiagnosticRecord(sqlState, message, "", "", rowNum, columnNum);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/8386dd86/modules/platforms/cpp/odbc/src/odbc.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc/src/odbc.cpp b/modules/platforms/cpp/odbc/src/odbc.cpp
index 3b31f1d..9b4179e 100644
--- a/modules/platforms/cpp/odbc/src/odbc.cpp
+++ b/modules/platforms/cpp/odbc/src/odbc.cpp
@@ -42,7 +42,16 @@ namespace ignite
ignite::odbc::config::Configuration config;
- config.FillFromConfigAttributes(attributes);
+ try
+ {
+ config.FillFromConfigAttributes(attributes);
+ }
+ catch (IgniteError& e)
+ {
+ SQLPostInstallerError(e.GetCode(), e.GetText());
+
+ return SQL_FALSE;
+ }
if (!SQLValidDSN(config.GetDsn().c_str()))
return SQL_FALSE;
@@ -323,18 +332,14 @@ namespace ignite
std::string connectStr = SqlStringToString(inConnectionString, inConnectionStringLen);
- ignite::odbc::config::Configuration config;
-
- config.FillFromConnectString(connectStr);
-
- connection->Establish(config.GetHost(), config.GetPort(), config.GetCache());
+ connection->Establish(connectStr);
const DiagnosticRecordStorage& diag = connection->GetDiagnosticRecords();
if (!diag.IsSuccessful())
return diag.GetReturnCode();
- std::string outConnectStr = config.ToConnectString();
+ std::string outConnectStr = connection->GetConfiguration().ToConnectString();
size_t reslen = CopyStringToBuffer(outConnectStr,
reinterpret_cast<char*>(outConnectionString),
@@ -357,7 +362,7 @@ namespace ignite
SQLSMALLINT authLen)
{
using ignite::odbc::Connection;
- using ignite::odbc::diagnostic::DiagnosticRecordStorage;
+ using ignite::odbc::config::Configuration;
using ignite::utility::SqlStringToString;
LOG_MSG("SQLConnect called\n");
@@ -367,9 +372,11 @@ namespace ignite
if (!connection)
return SQL_INVALID_HANDLE;
- std::string server = SqlStringToString(serverName, serverNameLen);
+ //std::string server = SqlStringToString(serverName, serverNameLen);
+
+ Configuration config;
- connection->Establish(server);
+ connection->Establish(config);
return connection->GetDiagnosticRecords().GetReturnCode();
}
[14/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2MetaTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2MetaTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2MetaTable.java
new file mode 100644
index 0000000..d8f2e08
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2MetaTable.java
@@ -0,0 +1,383 @@
+/*
+ * 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.opt;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicLong;
+import org.h2.command.ddl.CreateTableData;
+import org.h2.engine.Session;
+import org.h2.index.BaseIndex;
+import org.h2.index.Cursor;
+import org.h2.index.Index;
+import org.h2.index.IndexCondition;
+import org.h2.index.IndexType;
+import org.h2.index.SingleRowCursor;
+import org.h2.message.DbException;
+import org.h2.result.Row;
+import org.h2.result.SearchRow;
+import org.h2.result.SortOrder;
+import org.h2.table.Column;
+import org.h2.table.IndexColumn;
+import org.h2.table.TableBase;
+import org.h2.table.TableFilter;
+import org.h2.value.Value;
+import org.h2.value.ValueInt;
+import org.jsr166.ConcurrentHashMap8;
+
+/**
+ * Meta table.
+ */
+public class GridH2MetaTable extends TableBase {
+ /** */
+ private static final int ID = 0;
+
+ /** */
+ private final MetaIndex index;
+
+ /** */
+ private final AtomicLong dataModificationId = new AtomicLong();
+
+ /** */
+ private final Set<Session> fakeExclusiveSet = Collections.newSetFromMap(
+ new ConcurrentHashMap8<Session,Boolean>());
+
+ /**
+ * @param data Data.
+ */
+ public GridH2MetaTable(CreateTableData data) {
+ super(data);
+
+ ArrayList<Column> cols = data.columns;
+ assert cols.size() == 4 : cols;
+
+ Column id = cols.get(ID);
+ assert "ID".equals(id.getName()) && id.getType() == Value.INT : cols;
+ assert id.getColumnId() == ID;
+
+ index = new MetaIndex();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Row getTemplateRow() {
+ return new MetaRow();
+ }
+
+ /** {@inheritDoc} */
+ @Override public SearchRow getTemplateSimpleRow(boolean singleColumn) {
+ if (singleColumn)
+ return GridH2RowFactory.create((Value)null);
+
+ return new MetaRow();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean lock(Session session, boolean exclusive, boolean forceLockEvenInMvcc) {
+ if (fakeExclusiveSet.contains(session))
+ return true;
+
+ if (exclusive)
+ fakeExclusiveSet.add(session);
+
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void unlock(Session s) {
+ fakeExclusiveSet.remove(s);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close(Session session) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public Index addIndex(Session session, String indexName, int indexId,
+ IndexColumn[] cols, IndexType indexType, boolean create, String indexComment) {
+ assert cols.length == 1 : "len: " + cols.length;
+
+ int colId = cols[0].column.getColumnId();
+ assert colId == ID : "colId: " + colId;
+
+ return index;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void removeRow(Session session, Row row) {
+ dataModificationId.incrementAndGet();
+ index.remove(session, row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void truncate(Session session) {
+ dataModificationId.incrementAndGet();
+ index.truncate(session);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void addRow(Session session, Row row) {
+ dataModificationId.incrementAndGet();
+ index.add(session, row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void checkSupportAlter() {
+ throw DbException.getUnsupportedException("alter");
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getTableType() {
+ return SYSTEM_TABLE;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Index getScanIndex(Session session) {
+ return index;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Index getUniqueIndex() {
+ return index;
+ }
+
+ /** {@inheritDoc} */
+ @Override public ArrayList<Index> getIndexes() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isLockedExclusively() {
+ return !fakeExclusiveSet.isEmpty();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isLockedExclusivelyBy(Session s) {
+ return fakeExclusiveSet.contains(s);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getMaxDataModificationId() {
+ return dataModificationId.get();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isDeterministic() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canGetRowCount() {
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canDrop() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCount(Session session) {
+ return index.getRowCount(session);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ return index.getRowCountApproximation();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDiskSpaceUsed() {
+ return 0;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void checkRename() {
+ throw DbException.getUnsupportedException("rename");
+ }
+
+ /**
+ * Get value row.
+ */
+ private static class MetaRow extends GridH2Row {
+ /** */
+ private Value v0;
+
+ /** */
+ private Value v1;
+
+ /** */
+ private Value v2;
+
+ /** */
+ private Value v3;
+
+ /** {@inheritDoc} */
+ @Override public int getColumnCount() {
+ return 4;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Value getValue(int idx) {
+ switch (idx) {
+ case 0:
+ return v0;
+
+ case 1:
+ return v1;
+
+ case 2:
+ return v2;
+
+ case 3:
+ return v3;
+
+ default:
+ throw new IllegalStateException("Index: " + idx);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setValue(int idx, Value v) {
+ switch (idx) {
+ case 0:
+ v0 = v;
+
+ break;
+
+ case 1:
+ v1 = v;
+
+ break;
+
+ case 2:
+ v2 = v;
+
+ break;
+
+ case 3:
+ v3 = v;
+
+ break;
+
+ default:
+ throw new IllegalStateException("Index: " + idx);
+ }
+ }
+ }
+
+ /**
+ * Met index.
+ */
+ private static class MetaIndex extends BaseIndex {
+ /** */
+ private final ConcurrentMap<ValueInt, GridH2Row> rows = new ConcurrentHashMap8<>();
+
+ /** {@inheritDoc} */
+ @Override public void checkRename() {
+ throw DbException.getUnsupportedException("rename");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close(Session session) {
+ // No-op.
+ }
+
+ /**
+ * @param row Row.
+ * @return ID.
+ */
+ private static ValueInt id(SearchRow row) {
+ Value id = row.getValue(ID);
+
+ assert id != null;
+
+ return (ValueInt)id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void add(Session session, Row row) {
+ rows.put(id(row), (GridH2Row)row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(Session session, Row row) {
+ rows.remove(id(row), row);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor find(Session session, SearchRow first, SearchRow last) {
+ if (first == null || last == null || !Objects.equals(id(first), id(last)))
+ return new GridH2Cursor(rows.values().iterator());
+
+ return new SingleRowCursor(rows.get(id(first)));
+ }
+
+ /** {@inheritDoc} */
+ @Override public double getCost(Session session, int[] masks, TableFilter[] filters,
+ int filter, SortOrder sortOrder) {
+ if ((masks[ID] & IndexCondition.EQUALITY) == IndexCondition.EQUALITY)
+ return 1;
+
+ return 1000 + rows.size();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void remove(Session session) {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public void truncate(Session session) {
+ rows.clear();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean canGetFirstOrLast() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Cursor findFirstOrLast(Session session, boolean first) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean needRebuild() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCount(Session session) {
+ return rows.size();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getRowCountApproximation() {
+ return getRowCount(null);
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getDiskSpaceUsed() {
+ return 0;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryContext.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryContext.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryContext.java
new file mode 100644
index 0000000..19ea2b2
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryContext.java
@@ -0,0 +1,612 @@
+/*
+ * 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.opt;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentMap;
+import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.spi.indexing.IndexingQueryFilter;
+import org.jetbrains.annotations.Nullable;
+import org.jsr166.ConcurrentHashMap8;
+
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.MAP;
+
+/**
+ * Thread local SQL query context which is intended to be accessible from everywhere.
+ */
+public class GridH2QueryContext {
+ /** */
+ private static final ThreadLocal<GridH2QueryContext> qctx = new ThreadLocal<>();
+
+ /** */
+ private static final ConcurrentMap<Key, GridH2QueryContext> qctxs = new ConcurrentHashMap8<>();
+
+ /** */
+ private final Key key;
+
+ /** */
+ private volatile boolean cleared;
+
+ /** Index snapshots. */
+ @GridToStringInclude
+ private Map<Long, Object> snapshots;
+
+ /** */
+ private List<GridReservable> reservations;
+
+ /** Range streams for indexes. */
+ private Map<Integer, Object> streams;
+
+ /** Range sources for indexes. */
+ private Map<SourceKey, Object> sources;
+
+ /** */
+ private int batchLookupIdGen;
+
+ /** */
+ private IndexingQueryFilter filter;
+
+ /** */
+ private AffinityTopologyVersion topVer;
+
+ /** */
+ private Map<UUID, int[]> partsMap;
+
+ /** */
+ private UUID[] partsNodes;
+
+ /** */
+ private boolean distributedJoins;
+
+ /** */
+ private int pageSize;
+
+ /** */
+ private GridH2CollocationModel qryCollocationMdl;
+
+ /**
+ * @param locNodeId Local node ID.
+ * @param nodeId The node who initiated the query.
+ * @param qryId The query ID.
+ * @param type Query type.
+ */
+ public GridH2QueryContext(UUID locNodeId, UUID nodeId, long qryId, GridH2QueryType type) {
+ key = new Key(locNodeId, nodeId, qryId, type);
+ }
+
+ /**
+ * @return Type.
+ */
+ public GridH2QueryType type() {
+ return key.type;
+ }
+
+ /**
+ * @return Origin node ID.
+ */
+ public UUID originNodeId() {
+ return key.nodeId;
+ }
+
+ /**
+ * @return Query request ID.
+ */
+ public long queryId() {
+ return key.qryId;
+ }
+
+ /**
+ * @return Query collocation model.
+ */
+ public GridH2CollocationModel queryCollocationModel() {
+ return qryCollocationMdl;
+ }
+
+ /**
+ * @param qryCollocationMdl Query collocation model.
+ */
+ public void queryCollocationModel(GridH2CollocationModel qryCollocationMdl) {
+ this.qryCollocationMdl = qryCollocationMdl;
+ }
+
+ /**
+ * @param distributedJoins Distributed joins can be run in this query.
+ * @return {@code this}.
+ */
+ public GridH2QueryContext distributedJoins(boolean distributedJoins) {
+ this.distributedJoins = distributedJoins;
+
+ return this;
+ }
+
+ /**
+ * @return {@code true} If distributed joins can be run in this query.
+ */
+ public boolean distributedJoins() {
+ return distributedJoins;
+ }
+
+ /**
+ * @param reservations Reserved partitions or group reservations.
+ * @return {@code this}.
+ */
+ public GridH2QueryContext reservations(List<GridReservable> reservations) {
+ this.reservations = reservations;
+
+ return this;
+ }
+
+ /**
+ * @param topVer Topology version.
+ * @return {@code this}.
+ */
+ public GridH2QueryContext topologyVersion(AffinityTopologyVersion topVer) {
+ this.topVer = topVer;
+
+ return this;
+ }
+
+ /**
+ * @return Topology version.
+ */
+ public AffinityTopologyVersion topologyVersion() {
+ return topVer;
+ }
+
+ /**
+ * @param partsMap Partitions map.
+ * @return {@code this}.
+ */
+ public GridH2QueryContext partitionsMap(Map<UUID,int[]> partsMap) {
+ this.partsMap = partsMap;
+
+ return this;
+ }
+
+ /**
+ * @return Partitions map.
+ */
+ public Map<UUID,int[]> partitionsMap() {
+ return partsMap;
+ }
+
+ /**
+ * @param p Partition.
+ * @param cctx Cache context.
+ * @return Owning node ID.
+ */
+ public UUID nodeForPartition(int p, GridCacheContext<?, ?> cctx) {
+ UUID[] nodeIds = partsNodes;
+
+ if (nodeIds == null) {
+ assert partsMap != null;
+
+ nodeIds = new UUID[cctx.affinity().partitions()];
+
+ for (Map.Entry<UUID, int[]> e : partsMap.entrySet()) {
+ UUID nodeId = e.getKey();
+ int[] nodeParts = e.getValue();
+
+ assert nodeId != null;
+ assert !F.isEmpty(nodeParts);
+
+ for (int part : nodeParts) {
+ assert nodeIds[part] == null;
+
+ nodeIds[part] = nodeId;
+ }
+ }
+
+ partsNodes = nodeIds;
+ }
+
+ return nodeIds[p];
+ }
+
+ /**
+ * @param idxId Index ID.
+ * @param snapshot Index snapshot.
+ */
+ public void putSnapshot(long idxId, Object snapshot) {
+ assert snapshot != null;
+ assert get() == null : "need to snapshot indexes before setting query context for correct visibility";
+
+ if (snapshot instanceof GridReservable && !((GridReservable)snapshot).reserve())
+ throw new IllegalStateException("Must be already reserved before.");
+
+ if (snapshots == null)
+ snapshots = new HashMap<>();
+
+ if (snapshots.put(idxId, snapshot) != null)
+ throw new IllegalStateException("Index already snapshoted.");
+ }
+
+ /**
+ * Clear taken snapshots.
+ */
+ public void clearSnapshots() {
+ if (F.isEmpty(snapshots))
+ return;
+
+ for (Object snapshot : snapshots.values()) {
+ if (snapshot instanceof GridReservable)
+ ((GridReservable)snapshot).release();
+ }
+
+ snapshots = null;
+ }
+
+ /**
+ * @param idxId Index ID.
+ * @return Index snapshot or {@code null} if none.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T getSnapshot(long idxId) {
+ if (snapshots == null)
+ return null;
+
+ return (T)snapshots.get(idxId);
+ }
+
+ /**
+ * @param batchLookupId Batch lookup ID.
+ * @param streams Range streams.
+ */
+ public synchronized void putStreams(int batchLookupId, Object streams) {
+ if (this.streams == null) {
+ if (streams == null)
+ return;
+
+ this.streams = new HashMap<>();
+ }
+
+ if (streams == null)
+ this.streams.remove(batchLookupId);
+ else
+ this.streams.put(batchLookupId, streams);
+ }
+
+ /**
+ * @param batchLookupId Batch lookup ID.
+ * @return Range streams.
+ */
+ @SuppressWarnings("unchecked")
+ public synchronized <T> T getStreams(int batchLookupId) {
+ if (streams == null)
+ return null;
+
+ return (T)streams.get(batchLookupId);
+ }
+
+ /**
+ * @param ownerId Owner node ID.
+ * @param batchLookupId Batch lookup ID.
+ * @param src Range source.
+ */
+ public synchronized void putSource(UUID ownerId, int batchLookupId, Object src) {
+ SourceKey srcKey = new SourceKey(ownerId, batchLookupId);
+
+ if (src != null) {
+ if (sources == null)
+ sources = new HashMap<>();
+
+ sources.put(srcKey, src);
+ }
+ else if (sources != null)
+ sources.remove(srcKey);
+ }
+
+ /**
+ * @param ownerId Owner node ID.
+ * @param batchLookupId Batch lookup ID.
+ * @return Range source.
+ */
+ @SuppressWarnings("unchecked")
+ public synchronized <T> T getSource(UUID ownerId, int batchLookupId) {
+ if (sources == null)
+ return null;
+
+ return (T)sources.get(new SourceKey(ownerId, batchLookupId));
+ }
+
+ /**
+ * @return Next batch ID.
+ */
+ public int nextBatchLookupId() {
+ return ++batchLookupIdGen;
+ }
+
+ /**
+ * @return If indexes were snapshotted before query execution.
+ */
+ public boolean hasIndexSnapshots() {
+ return snapshots != null;
+ }
+
+ /**
+ * Sets current thread local context. This method must be called when all the non-volatile properties are
+ * already set to ensure visibility for other threads.
+ *
+ * @param x Query context.
+ */
+ public static void set(GridH2QueryContext x) {
+ assert qctx.get() == null;
+
+ // We need MAP query context to be available to other threads to run distributed joins.
+ if (x.key.type == MAP && x.distributedJoins() && qctxs.putIfAbsent(x.key, x) != null)
+ throw new IllegalStateException("Query context is already set.");
+
+ qctx.set(x);
+ }
+
+ /**
+ * Drops current thread local context.
+ */
+ public static void clearThreadLocal() {
+ GridH2QueryContext x = qctx.get();
+
+ assert x != null;
+
+ qctx.remove();
+ }
+
+ /**
+ * @param locNodeId Local node ID.
+ * @param nodeId The node who initiated the query.
+ * @param qryId The query ID.
+ * @param type Query type.
+ * @return {@code True} if context was found.
+ */
+ public static boolean clear(UUID locNodeId, UUID nodeId, long qryId, GridH2QueryType type) {
+ return doClear(new Key(locNodeId, nodeId, qryId, type), false);
+ }
+
+ /**
+ * @param key Context key.
+ * @param nodeStop Node is stopping.
+ * @return {@code True} if context was found.
+ */
+ private static boolean doClear(Key key, boolean nodeStop) {
+ assert key.type == MAP : key.type;
+
+ GridH2QueryContext x = qctxs.remove(key);
+
+ if (x == null)
+ return false;
+
+ assert x.key.equals(key);
+
+ x.clearContext(nodeStop);
+
+ return true;
+ }
+
+ /**
+ * @param nodeStop Node is stopping.
+ */
+ public void clearContext(boolean nodeStop) {
+ cleared = true;
+
+ clearSnapshots();
+
+ List<GridReservable> r = reservations;
+
+ if (!nodeStop && !F.isEmpty(r)) {
+ for (int i = 0; i < r.size(); i++)
+ r.get(i).release();
+ }
+ }
+
+ /**
+ * @return {@code true} If the context is cleared.
+ */
+ public boolean isCleared() {
+ return cleared;
+ }
+
+ /**
+ * @param locNodeId Local node ID.
+ * @param nodeId Dead node ID.
+ */
+ public static void clearAfterDeadNode(UUID locNodeId, UUID nodeId) {
+ for (Key key : qctxs.keySet()) {
+ if (key.locNodeId.equals(locNodeId) && key.nodeId.equals(nodeId))
+ doClear(key, false);
+ }
+ }
+
+ /**
+ * @param locNodeId Local node ID.
+ */
+ public static void clearLocalNodeStop(UUID locNodeId) {
+ for (Key key : qctxs.keySet()) {
+ if (key.locNodeId.equals(locNodeId))
+ doClear(key, true);
+ }
+ }
+
+ /**
+ * Access current thread local query context (if it was set).
+ *
+ * @return Current thread local query context or {@code null} if the query runs outside of Ignite context.
+ */
+ @Nullable public static GridH2QueryContext get() {
+ return qctx.get();
+ }
+
+ /**
+ * Access query context from another thread.
+ *
+ * @param locNodeId Local node ID.
+ * @param nodeId The node who initiated the query.
+ * @param qryId The query ID.
+ * @param type Query type.
+ * @return Query context.
+ */
+ @Nullable public static GridH2QueryContext get(
+ UUID locNodeId,
+ UUID nodeId,
+ long qryId,
+ GridH2QueryType type
+ ) {
+ return qctxs.get(new Key(locNodeId, nodeId, qryId, type));
+ }
+
+ /**
+ * @return Filter.
+ */
+ public IndexingQueryFilter filter() {
+ return filter;
+ }
+
+ /**
+ * @param filter Filter.
+ * @return {@code this}.
+ */
+ public GridH2QueryContext filter(IndexingQueryFilter filter) {
+ this.filter = filter;
+
+ return this;
+ }
+
+ /**
+ * @return Page size.
+ */
+ public int pageSize() {
+ return pageSize;
+ }
+
+ /**
+ * @param pageSize Page size.
+ * @return {@code this}.
+ */
+ public GridH2QueryContext pageSize(int pageSize) {
+ this.pageSize = pageSize;
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridH2QueryContext.class, this);
+ }
+
+ /**
+ * Unique key for the query context.
+ */
+ private static class Key {
+ /** */
+ private final UUID locNodeId;
+
+ /** */
+ private final UUID nodeId;
+
+ /** */
+ private final long qryId;
+
+ /** */
+ private final GridH2QueryType type;
+
+ /**
+ * @param locNodeId Local node ID.
+ * @param nodeId The node who initiated the query.
+ * @param qryId The query ID.
+ * @param type Query type.
+ */
+ private Key(UUID locNodeId, UUID nodeId, long qryId, GridH2QueryType type) {
+ assert locNodeId != null;
+ assert nodeId != null;
+ assert type != null;
+
+ this.locNodeId = locNodeId;
+ this.nodeId = nodeId;
+ this.qryId = qryId;
+ this.type = type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ Key key = (Key)o;
+
+ return qryId == key.qryId && nodeId.equals(key.nodeId) && type == key.type &&
+ locNodeId.equals(key.locNodeId) ;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = locNodeId.hashCode();
+
+ res = 31 * res + nodeId.hashCode();
+ res = 31 * res + (int)(qryId ^ (qryId >>> 32));
+ res = 31 * res + type.hashCode();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Key.class, this);
+ }
+ }
+
+ /**
+ * Key for source.
+ */
+ private static final class SourceKey {
+ /** */
+ UUID ownerId;
+
+ /** */
+ int batchLookupId;
+
+ /**
+ * @param ownerId Owner node ID.
+ * @param batchLookupId Batch lookup ID.
+ */
+ SourceKey(UUID ownerId, int batchLookupId) {
+ this.ownerId = ownerId;
+ this.batchLookupId = batchLookupId;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ SourceKey srcKey = (SourceKey)o;
+
+ return batchLookupId == srcKey.batchLookupId && ownerId.equals(srcKey.ownerId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return 31 * ownerId.hashCode() + batchLookupId;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryType.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryType.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryType.java
new file mode 100644
index 0000000..f6d0408
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2QueryType.java
@@ -0,0 +1,49 @@
+/*
+ * 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.opt;
+
+/**
+ * Query type.
+ */
+public enum GridH2QueryType {
+ /**
+ * Map query. Runs over local partitions, possibly with distributed joins.
+ */
+ MAP,
+
+ /**
+ * Reduce query. Local query on a node which initiated the original query.
+ */
+ REDUCE,
+
+ /**
+ * Local query. It may be also a query over replicated cache but all the data is available locally.
+ */
+ LOCAL,
+
+ /**
+ * Replicated query over a network. Such a query can be sent from a client node or node which
+ * did not load all the partitions yet.
+ */
+ REPLICATED,
+
+ /**
+ * Parsing and optimization stage.
+ */
+ PREPARE,
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RetryException.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RetryException.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RetryException.java
new file mode 100644
index 0000000..e333d71
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RetryException.java
@@ -0,0 +1,32 @@
+/*
+ * 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.opt;
+
+import org.apache.ignite.IgniteException;
+
+/**
+ * Internal exception.
+ */
+public class GridH2RetryException extends IgniteException {
+ /**
+ * @param msg Message.
+ */
+ public GridH2RetryException(String msg) {
+ super(msg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
index 3b6b56e..9486a2e 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Row.java
@@ -18,19 +18,14 @@
package org.apache.ignite.internal.processors.query.h2.opt;
import org.h2.result.Row;
+import org.h2.result.SearchRow;
+import org.h2.store.Data;
import org.h2.value.Value;
/**
* Row with locking support needed for unique key conflicts resolution.
*/
-public class GridH2Row extends Row implements GridSearchRowPointer {
- /**
- * @param data Column values.
- */
- public GridH2Row(Value... data) {
- super(data, MEMORY_CALCULATE);
- }
-
+public abstract class GridH2Row extends Row implements GridSearchRowPointer {
/** {@inheritDoc} */
@Override public long pointer() {
throw new IllegalStateException();
@@ -45,4 +40,79 @@ public class GridH2Row extends Row implements GridSearchRowPointer {
@Override public void decrementRefCount() {
throw new IllegalStateException();
}
+
+ /** {@inheritDoc} */
+ @Override public Row getCopy() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setVersion(int version) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getByteCount(Data dummy) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isEmpty() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setDeleted(boolean deleted) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setSessionId(int sessionId) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getSessionId() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void commit() {
+ // No-op.
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isDeleted() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setKeyAndVersion(SearchRow old) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getVersion() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setKey(long key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public long getKey() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getMemory() {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Value[] getValueList() {
+ throw new UnsupportedOperationException();
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 80dcfcb..f519c30 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
@@ -18,7 +18,10 @@
package org.apache.ignite.internal.processors.query.h2.opt;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.processors.cache.CacheObject;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor;
import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
import org.apache.ignite.internal.util.offheap.unsafe.GridOffHeapSmartPointerFactory;
import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeGuard;
@@ -31,9 +34,30 @@ import org.jetbrains.annotations.Nullable;
*/
public interface GridH2RowDescriptor extends GridOffHeapSmartPointerFactory<GridH2KeyValueRowOffheap> {
/**
- * @return Owner.
+ * Gets indexing.
+ *
+ * @return indexing.
+ */
+ public IgniteH2Indexing indexing();
+
+ /**
+ * Gets type descriptor.
+ *
+ * @return Type descriptor.
+ */
+ public GridQueryTypeDescriptor type();
+
+ /**
+ * Gets cache context for this row descriptor.
+ *
+ * @return Cache context.
+ */
+ public GridCacheContext<?, ?> context();
+
+ /**
+ * @return Cache configuration.
*/
- public IgniteH2Indexing owner();
+ public CacheConfiguration configuration();
/**
* Creates new row.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowFactory.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowFactory.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowFactory.java
new file mode 100644
index 0000000..00ff3f2
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2RowFactory.java
@@ -0,0 +1,179 @@
+/*
+ * 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.opt;
+
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.h2.result.RowFactory;
+import org.h2.value.Value;
+
+/**
+ * Row factory.
+ */
+public class GridH2RowFactory extends RowFactory {
+ /**
+ * @param v Value.
+ * @return Row.
+ */
+ public static GridH2Row create(Value v) {
+ return new RowKey(v);
+ }
+
+ /**
+ * @param v1 Value 1.
+ * @param v2 Value 2.
+ * @return Row.
+ */
+ public static GridH2Row create(Value v1, Value v2) {
+ return new RowPair(v1, v2);
+ }
+
+ /**
+ * @param data Values.
+ * @return Row.
+ */
+ public static GridH2Row create(Value... data) {
+ switch (data.length) {
+ case 0:
+ throw new IllegalStateException("Zero columns row.");
+
+ case 1:
+ return new RowKey(data[0]);
+
+ case 2:
+ return new RowPair(data[0], data[1]);
+
+ default:
+ return new RowSimple(data);
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2Row createRow(Value[] data, int memory) {
+ return create(data);
+ }
+
+ /**
+ * Single value row.
+ */
+ private static final class RowKey extends GridH2Row {
+ /** */
+ private Value key;
+
+ /**
+ * @param key Key.
+ */
+ public RowKey(Value key) {
+ this.key = key;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getColumnCount() {
+ return 1;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Value getValue(int idx) {
+ assert idx == 0 : idx;
+ return key;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setValue(int idx, Value v) {
+ assert idx == 0 : idx;
+ key = v;
+ }
+ }
+
+ /**
+ * Row of two values.
+ */
+ private static final class RowPair extends GridH2Row {
+ /** */
+ private Value v1;
+
+ /** */
+ private Value v2;
+
+ /**
+ * @param v1 First value.
+ * @param v2 Second value.
+ */
+ private RowPair(Value v1, Value v2) {
+ this.v1 = v1;
+ this.v2 = v2;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getColumnCount() {
+ return 2;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Value getValue(int idx) {
+ return idx == 0 ? v1 : v2;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setValue(int idx, Value v) {
+ if (idx == 0)
+ v1 = v;
+ else {
+ assert idx == 1 : idx;
+
+ v2 = v;
+ }
+ }
+ }
+
+ /**
+ * Simple array based row.
+ */
+ private static final class RowSimple extends GridH2Row {
+ /** */
+ @GridToStringInclude
+ private Value[] vals;
+
+ /**
+ * @param vals Values.
+ */
+ private RowSimple(Value[] vals) {
+ this.vals = vals;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int getColumnCount() {
+ return vals.length;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Value getValue(int idx) {
+ return vals[idx];
+ }
+
+ /** {@inheritDoc} */
+ @Override public void setValue(int idx, Value v) {
+ vals[idx] = v;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(RowSimple.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 bea4dd8..8d080ae 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
@@ -23,22 +23,24 @@ import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Set;
-import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.IgniteException;
+import org.apache.ignite.IgniteInterruptedException;
import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemory;
import org.h2.api.TableEngine;
import org.h2.command.ddl.CreateTableData;
-import org.h2.engine.Constants;
import org.h2.engine.Database;
import org.h2.engine.DbObject;
import org.h2.engine.Session;
+import org.h2.index.BaseIndex;
import org.h2.index.Cursor;
import org.h2.index.Index;
+import org.h2.index.IndexLookupBatch;
import org.h2.index.IndexType;
import org.h2.message.DbException;
import org.h2.result.Row;
@@ -55,7 +57,10 @@ import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
import org.jsr166.LongAdder8;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.KEY_COL;
import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.VAL_COL;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.MAP;
/**
* H2 Table implementation.
@@ -74,10 +79,16 @@ public class GridH2Table extends TableBase {
private final ReadWriteLock lock;
/** */
- private final Set<Session> sessions = Collections.newSetFromMap(new ConcurrentHashMap8<Session, Boolean>());
+ private boolean destroyed;
/** */
- private volatile Object[] actualSnapshot;
+ private final Set<Session> sessions = Collections.newSetFromMap(new ConcurrentHashMap8<Session,Boolean>());
+
+ /** */
+ private final AtomicReference<Object[]> actualSnapshot = new AtomicReference<>();
+
+ /** */
+ private IndexColumn affKeyCol;
/** */
private final LongAdder8 size = new LongAdder8();
@@ -102,17 +113,57 @@ public class GridH2Table extends TableBase {
this.desc = desc;
this.spaceName = spaceName;
+ if (desc != null && desc.context() != null && !desc.context().customAffinityMapper()) {
+ boolean affinityColExists = true;
+
+ String affKey = desc.type().affinityKey();
+
+ int affKeyColId = -1;
+
+ if (affKey != null) {
+ String colName = desc.context().config().isSqlEscapeAll() ? affKey : affKey.toUpperCase();
+
+ if (doesColumnExist(colName))
+ affKeyColId = getColumn(colName).getColumnId();
+ else
+ affinityColExists = false;
+ }
+ else
+ affKeyColId = KEY_COL;
+
+ if (affinityColExists) {
+ affKeyCol = indexColumn(affKeyColId, SortOrder.ASCENDING);
+
+ assert affKeyCol != null;
+ }
+ }
+
+ // Indexes must be created in the end when everything is ready.
idxs = idxsFactory.createIndexes(this);
assert idxs != null;
assert idxs.size() >= 1;
- 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();
+
+ lock = snapshotEnabled ? new ReentrantReadWriteLock() : null;
+ }
+
+ /**
+ * @return {@code true} If this is a partitioned table.
+ */
+ public boolean isPartitioned() {
+ return desc != null && desc.configuration().getCacheMode() == PARTITIONED;
+ }
+
+ /**
+ * @return Affinity key column or {@code null} if not available.
+ */
+ @Nullable public IndexColumn getAffinityKeyColumn() {
+ return affKeyCol;
}
/** {@inheritDoc} */
@@ -172,7 +223,7 @@ public class GridH2Table extends TableBase {
GridUnsafeMemory mem = desc.memory();
- readLock();
+ Lock l = lock(false, Long.MAX_VALUE);
if (mem != null)
desc.guard().begin();
@@ -191,7 +242,7 @@ public class GridH2Table extends TableBase {
return true;
}
finally {
- readUnlock();
+ unlock(l);
if (mem != null)
desc.guard().end();
@@ -207,118 +258,219 @@ public class GridH2Table extends TableBase {
/** {@inheritDoc} */
@SuppressWarnings({"LockAcquiredButNotSafelyReleased", "SynchronizationOnLocalVariableOrMethodParameter", "unchecked"})
- @Override public void lock(@Nullable final Session ses, boolean exclusive, boolean force) {
+ @Override public boolean lock(@Nullable final Session ses, boolean exclusive, boolean force) {
if (ses != null) {
if (!sessions.add(ses))
- return;
+ return false;
- synchronized (ses) {
- ses.addLock(this);
- }
+ ses.addLock(this);
}
+ if (snapshotInLock())
+ snapshotIndexes(null);
+
+ return false;
+ }
+
+ /**
+ * @return {@code True} If we must snapshot and release index snapshots in {@link #lock(Session, boolean, boolean)}
+ * and {@link #unlock(Session)} methods.
+ */
+ private boolean snapshotInLock() {
+ if (!snapshotEnabled)
+ return false;
+
+ GridH2QueryContext qctx = GridH2QueryContext.get();
+
+ // On MAP queries with distributed joins we lock tables before the queries.
+ return qctx == null || qctx.type() != MAP || !qctx.hasIndexSnapshots();
+ }
+
+ /**
+ * @param qctx Query context.
+ */
+ public void snapshotIndexes(GridH2QueryContext qctx) {
if (!snapshotEnabled)
return;
- Object[] snapshot;
+ Object[] snapshots;
- for (long waitTime = 100;; waitTime *= 2) { // Increase wait time to avoid starvation.
- snapshot = actualSnapshot;
+ Lock l;
- if (snapshot != null) {
- // Reuse existing snapshot without locking.
- for (int i = 1, len = idxs.size(); i < len; i++)
- index(i).takeSnapshot(snapshot[i - 1]);
+ // Try to reuse existing snapshots outside of the lock.
+ for (long waitTime = 200;; waitTime *= 2) { // Increase wait time to avoid starvation.
+ snapshots = actualSnapshot.get();
- return;
- }
+ if (snapshots != null) { // Reuse existing snapshot without locking.
+ snapshots = doSnapshotIndexes(snapshots, qctx);
- try {
- if (lock.writeLock().tryLock(waitTime, TimeUnit.MILLISECONDS))
- break;
- }
- catch (InterruptedException e) {
- throw new IgniteException("Thread got interrupted while trying to acquire index lock.", e);
+ if (snapshots != null)
+ return; // Reused successfully.
}
- }
- boolean snapshoted = false;
+ l = lock(true, waitTime);
+
+ if (l != null)
+ break;
+ }
try {
- snapshot = actualSnapshot; // Try again inside of the lock.
+ // Try again inside of the lock.
+ snapshots = actualSnapshot.get();
+
+ if (snapshots != null) // Try reusing.
+ snapshots = doSnapshotIndexes(snapshots, qctx);
- if (snapshot == null) {
- snapshot = takeIndexesSnapshot();
+ if (snapshots == null) { // Reuse failed, produce new snapshots.
+ snapshots = doSnapshotIndexes(null, qctx);
- if (desc == null || desc.memory() == null) // This optimization is disabled for off-heap index.
- actualSnapshot = snapshot;
+ assert snapshots != null;
- snapshoted = true;
+ actualSnapshot.set(snapshots);
}
}
finally {
- lock.writeLock().unlock();
+ unlock(l);
}
+ }
- if (!snapshoted) {
- for (int i = 1, len = idxs.size(); i < len; i++)
- index(i).takeSnapshot(snapshot[i - 1]);
+ /**
+ * @return Table identifier.
+ */
+ public String identifier() {
+ return getSchema().getName() + '.' + getName();
+ }
+
+ /**
+ * @param l Lock.
+ */
+ private static void unlock(Lock l) {
+ if (l != null)
+ l.unlock();
+ }
+
+ /**
+ * @param exclusive Exclusive lock.
+ * @param waitMillis Milliseconds to wait for the lock.
+ * @return The acquired lock or {@code null} if the lock time out occurred.
+ */
+ public Lock lock(boolean exclusive, long waitMillis) {
+ if (!snapshotEnabled)
+ return null;
+
+ Lock l = exclusive ? lock.writeLock() : lock.readLock();
+
+ try {
+ if (!l.tryLock(waitMillis, TimeUnit.MILLISECONDS))
+ return null;
+ }
+ catch (InterruptedException e) {
+ throw new IgniteInterruptedException("Thread got interrupted while trying to acquire table lock.", e);
}
+
+ if (destroyed) {
+ unlock(l);
+
+ throw new IllegalStateException("Table " + identifier() + " already destroyed.");
+ }
+
+ return l;
}
/**
* Must be called inside of write lock because when using multiple indexes we have to ensure that all of them have
* the same contents at snapshot taking time.
*
+ * @param qctx Query context.
* @return New indexes data snapshot.
*/
@SuppressWarnings("unchecked")
- private Object[] takeIndexesSnapshot() {
- int len = idxs.size();
+ private Object[] doSnapshotIndexes(Object[] snapshots, GridH2QueryContext qctx) {
+ assert snapshotEnabled;
- Object[] snapshot = new ConcurrentNavigableMap[len - 1];
+ if (snapshots == null) // Nothing to reuse, create new snapshots.
+ snapshots = new Object[idxs.size() - 1];
- for (int i = 1; i < len; i++) { // Take snapshots on all except first which is scan.
- Object s = index(i).takeSnapshot(null);
+ // Take snapshots on all except first which is scan.
+ for (int i = 1, len = idxs.size(); i < len; i++) {
+ Object s = snapshots[i - 1];
- snapshot[i - 1] = s;
- }
+ boolean reuseExisting = s != null;
- return snapshot;
- }
+ s = index(i).takeSnapshot(s, qctx);
- /** {@inheritDoc} */
- @Override public void close(Session ses) {
- assert !sessions.contains(ses);
- }
+ if (reuseExisting && s == null) { // Existing snapshot was invalidated before we were able to reserve it.
+ // Release already taken snapshots.
+ if (qctx != null)
+ qctx.clearSnapshots();
- /** {@inheritDoc} */
- @Override public void unlock(@Nullable Session ses) {
- if (ses != null) {
- boolean res = sessions.remove(ses);
+ for (int j = 1; j < i; j++)
+ index(j).releaseSnapshot();
+
+ // Drop invalidated snapshot.
+ actualSnapshot.compareAndSet(snapshots, null);
+
+ return null;
+ }
- assert res;
+ snapshots[i - 1] = s;
}
- for (int i = 1, len = idxs.size(); i < len; i++) // Release snapshots on all except first which is scan.
- index(i).releaseSnapshot();
+ return snapshots;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void close(Session ses) {
+ // No-op.
}
/**
- * Closes table and releases resources.
+ * Destroy the table.
*/
- public void close() {
- writeLock();
+ public void destroy() {
+ Lock l = lock(true, Long.MAX_VALUE);
try {
+ assert sessions.isEmpty() : sessions;
+
+ destroyed = true;
+
for (int i = 1, len = idxs.size(); i < len; i++)
- index(i).close(null);
+ index(i).destroy();
}
finally {
- writeUnlock();
+ unlock(l);
}
}
+ /** {@inheritDoc} */
+ @Override public void unlock(@Nullable Session ses) {
+ if (ses != null && !sessions.remove(ses))
+ return;
+
+ if (snapshotInLock())
+ releaseSnapshots();
+ }
+
+ /**
+ * Releases snapshots.
+ */
+ public void releaseSnapshots() {
+ if (!snapshotEnabled)
+ return;
+
+ releaseSnapshots0(idxs);
+ }
+
+ /**
+ * @param idxs Indexes.
+ */
+ private void releaseSnapshots0(ArrayList<Index> idxs) {
+ // Release snapshots on all except first which is scan.
+ for (int i = 1, len = idxs.size(); i < len; i++)
+ ((GridH2IndexBase)idxs.get(i)).releaseSnapshot();
+ }
+
/**
* Updates table for given key. If value is null then row with given key will be removed from table,
* otherwise value and expiration time will be updated or new row will be added.
@@ -336,7 +488,16 @@ public class GridH2Table extends TableBase {
GridH2Row row = desc.createRow(key, val, expirationTime);
- return doUpdate(row, rmv);
+ if (!rmv)
+ ((GridH2AbstractKeyValueRow)row).valuesCache(new Value[getColumns().length]);
+
+ try {
+ return doUpdate(row, rmv);
+ }
+ finally {
+ if (!rmv)
+ ((GridH2AbstractKeyValueRow)row).valuesCache(null);
+ }
}
/**
@@ -372,7 +533,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();
- readLock();
+ Lock l = lock(false, Long.MAX_VALUE);
if (mem != null)
desc.guard().begin();
@@ -400,7 +561,7 @@ public class GridH2Table extends TableBase {
while (++i < len) {
GridH2IndexBase idx = index(i);
- assert !idx.getIndexType().isUnique() : "Unique indexes are not supported.";
+ assert !idx.getIndexType().isUnique() : "Unique indexes are not supported: " + idx;
GridH2Row old2 = idx.put(row);
@@ -417,7 +578,7 @@ public class GridH2Table extends TableBase {
// index(1) is PK, get full row from there (search row here contains only key but no other columns).
GridH2Row old = pk.remove(row);
- if (old instanceof GridH2AbstractKeyValueRow) { // Unswap value.
+ if (row.getColumnCount() != 1 && old instanceof GridH2AbstractKeyValueRow) { // Unswap value.
Value v = row.getValue(VAL_COL);
if (v != null)
@@ -440,12 +601,12 @@ public class GridH2Table extends TableBase {
}
// The snapshot is not actual after update.
- actualSnapshot = null;
+ actualSnapshot.set(null);
return true;
}
finally {
- readUnlock();
+ unlock(l);
if (mem != null)
desc.guard().end();
@@ -485,13 +646,12 @@ public class GridH2Table extends TableBase {
if (!snapshotEnabled)
return;
- GridUnsafeMemory memory = desc == null ? null : desc.memory();
+ Lock l = lock(true, Long.MAX_VALUE);
- lock.writeLock().lock();
+ ArrayList<Index> idxs0 = new ArrayList<>(idxs);
try {
- if (memory == null && actualSnapshot == null)
- actualSnapshot = takeIndexesSnapshot(); // Allow read access while we are rebuilding indexes.
+ snapshotIndexes(null); // Allow read access while we are rebuilding indexes.
for (int i = 1, len = idxs.size(); i < len; i++) {
GridH2IndexBase newIdx = index(i).rebuild();
@@ -502,13 +662,13 @@ public class GridH2Table extends TableBase {
idxs.set(0, new ScanIndex(newIdx));
}
}
- catch (InterruptedException ignored) {
- // No-op.
+ catch (InterruptedException e) {
+ throw new IgniteInterruptedException(e);
}
finally {
- lock.writeLock().unlock();
+ releaseSnapshots0(idxs0);
- actualSnapshot = null;
+ unlock(l);
}
}
@@ -621,38 +781,6 @@ 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"})
@@ -729,7 +857,7 @@ public class GridH2Table extends TableBase {
* Wrapper type for primary key.
*/
@SuppressWarnings("PackageVisibleInnerClass")
- static class ScanIndex implements Index {
+ static class ScanIndex extends BaseIndex {
/** */
static final String SCAN_INDEX_NAME_SUFFIX = "__SCAN_";
@@ -774,8 +902,8 @@ public class GridH2Table extends TableBase {
}
/** {@inheritDoc} */
- @Override public void close(Session ses) {
- delegate.close(ses);
+ @Override public final void close(Session ses) {
+ // No-op.
}
/** {@inheritDoc} */
@@ -819,8 +947,13 @@ public class GridH2Table extends TableBase {
}
/** {@inheritDoc} */
- @Override public double getCost(Session ses, int[] masks, TableFilter tblFilter, SortOrder sortOrder) {
- return getRowCountApproximation() + Constants.COST_ROW_OFFSET;
+ @Override public double getCost(Session ses, int[] masks, TableFilter[] filters, int filter,
+ SortOrder sortOrder) {
+ long rows = getRowCountApproximation();
+ double baseCost = getCostRangeIndex(masks, rows, filters, filter, sortOrder, true);
+ int mul = delegate.getDistributedMultiplier(ses, filters, filter);
+
+ return mul * baseCost;
}
/** {@inheritDoc} */
@@ -884,6 +1017,11 @@ public class GridH2Table extends TableBase {
}
/** {@inheritDoc} */
+ @Override public IndexLookupBatch createLookupBatch(TableFilter filter) {
+ return delegate.createLookupBatch(filter);
+ }
+
+ /** {@inheritDoc} */
@Override public void truncate(Session ses) {
// No-op.
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 2c95b66..33aaf7b 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
@@ -17,10 +17,9 @@
package org.apache.ignite.internal.processors.query.h2.opt;
-import java.io.Closeable;
-import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
+import java.util.List;
import java.util.NavigableMap;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
@@ -28,14 +27,14 @@ 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;
import org.apache.ignite.internal.util.snaptree.SnapTreeMap;
+import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.SB;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.spi.indexing.IndexingQueryFilter;
import org.h2.engine.Session;
import org.h2.index.Cursor;
import org.h2.index.IndexType;
-import org.h2.index.SingleRowCursor;
-import org.h2.result.Row;
+import org.h2.message.DbException;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.IndexColumn;
@@ -49,10 +48,7 @@ import org.jetbrains.annotations.Nullable;
@SuppressWarnings("ComparatorNotSerializable")
public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridSearchRowPointer> {
/** */
- protected final ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree;
-
- /** */
- private final ThreadLocal<ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>> snapshot = new ThreadLocal<>();
+ private final ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree;
/** */
private final boolean snapshotEnabled;
@@ -63,19 +59,11 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
* @param name Index name.
* @param tbl Table.
* @param pk If this index is primary key.
- * @param keyCol Primary key column index.
- * @param valCol Value column index.
- * @param cols Index columns list.
+ * @param colsList Index columns list.
*/
@SuppressWarnings("unchecked")
- public GridH2TreeIndex(String name, GridH2Table tbl, boolean pk, int keyCol, int valCol, IndexColumn... cols) {
- super(keyCol, valCol);
- if (!pk) {
- // For other indexes we add primary key at the end to avoid conflicts.
- cols = Arrays.copyOf(cols, cols.length + 1);
-
- cols[cols.length - 1] = tbl.indexColumn(keyCol, SortOrder.ASCENDING);
- }
+ public GridH2TreeIndex(String name, GridH2Table tbl, boolean pk, List<IndexColumn> colsList) {
+ IndexColumn[] cols = colsList.toArray(new IndexColumn[colsList.size()]);
IndexColumn.mapColumns(cols, tbl);
@@ -146,61 +134,25 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
}
};
}
- }
-
- /**
- * Closes index and releases resources.
- */
- public void close() {
- if (tree instanceof Closeable)
- U.closeQuiet((Closeable)tree);
- }
-
- /**
- * Takes snapshot to be used in current thread. If argument is null it will be taken from current trees.
- *
- * @param s Map to be used as snapshot if not null.
- * @return Taken snapshot or given argument back.
- */
- @SuppressWarnings("unchecked")
- @Override public Object takeSnapshot(@Nullable Object s) {
- if (!snapshotEnabled)
- return null;
-
- assert snapshot.get() == null;
-
- if (s == null)
- s = tree instanceof SnapTreeMap ? ((SnapTreeMap)tree).clone() :
- ((GridOffHeapSnapTreeMap)tree).clone();
-
- snapshot.set((ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row>)s);
- return s;
+ initDistributedJoinMessaging(tbl);
}
- /**
- * Releases snapshot for current thread.
- */
- @Override public void releaseSnapshot() {
- if (!snapshotEnabled)
- return;
-
- ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> s = snapshot.get();
-
- snapshot.set(null);
+ /** {@inheritDoc} */
+ @Override protected Object doTakeSnapshot() {
+ assert snapshotEnabled;
- if (s instanceof Closeable)
- U.closeQuiet((Closeable)s);
+ return tree instanceof SnapTreeMap ?
+ ((SnapTreeMap)tree).clone() :
+ ((GridOffHeapSnapTreeMap)tree).clone();
}
- /**
- * @return Snapshot for current thread if there is one.
- */
- private ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> treeForRead() {
+ /** {@inheritDoc} */
+ protected final ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> treeForRead() {
if (!snapshotEnabled)
return tree;
- ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> res = snapshot.get();
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> res = threadLocalSnapshot();
if (res == null)
res = tree;
@@ -209,19 +161,21 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
}
/** {@inheritDoc} */
- @Override public void close(Session ses) {
- assert snapshot.get() == null;
+ @Override public void destroy() {
+ assert threadLocalSnapshot() == null;
+
+ if (tree instanceof AutoCloseable)
+ U.closeQuiet((AutoCloseable)tree);
- if (tree instanceof Closeable)
- U.closeQuiet((Closeable)tree);
+ super.destroy();
}
/** {@inheritDoc} */
@Override public long getRowCount(@Nullable Session ses) {
- IndexingQueryFilter f = filters.get();
+ IndexingQueryFilter f = threadLocalFilter();
// Fast path if we don't need to perform any filtering.
- if (f == null || f.forSpace(((GridH2Table)getTable()).spaceName()) == null)
+ if (f == null || f.forSpace((getTable()).spaceName()) == null)
return treeForRead().size();
Iterator<GridH2Row> iter = doFind(null, false, null);
@@ -269,13 +223,17 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
}
/** {@inheritDoc} */
- @Override public double getCost(Session ses, int[] masks, TableFilter filter, SortOrder sortOrder) {
- return getCostRangeIndex(masks, getRowCountApproximation(), filter, sortOrder);
+ @Override public double getCost(Session ses, int[] masks, TableFilter[] filters, int filter, SortOrder sortOrder) {
+ long rowCnt = getRowCountApproximation();
+ double baseCost = getCostRangeIndex(masks, rowCnt, filters, filter, sortOrder, false);
+ int mul = getDistributedMultiplier(ses, filters, filter);
+
+ return mul * baseCost;
}
/** {@inheritDoc} */
@Override public boolean canFindNext() {
- return true;
+ return false;
}
/** {@inheritDoc} */
@@ -309,10 +267,20 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
* @return Iterator over rows in given range.
*/
@SuppressWarnings("unchecked")
- private Iterator<GridH2Row> doFind(@Nullable SearchRow first, boolean includeFirst,
- @Nullable SearchRow last) {
+ private Iterator<GridH2Row> doFind(@Nullable SearchRow first, boolean includeFirst, @Nullable SearchRow last) {
ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> t = treeForRead();
+ return doFind0(t, first, includeFirst, last, threadLocalFilter());
+ }
+
+ /** {@inheritDoc} */
+ @Override protected final Iterator<GridH2Row> doFind0(
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> t,
+ @Nullable SearchRow first,
+ boolean includeFirst,
+ @Nullable SearchRow last,
+ IndexingQueryFilter filter
+ ) {
includeFirst &= first != null;
NavigableMap<GridSearchRowPointer, GridH2Row> range = subTree(t, comparable(first, includeFirst ? -1 : 1),
@@ -321,7 +289,7 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
if (range == null)
return new GridEmptyIterator<>();
- return filter(range.values().iterator());
+ return filter(range.values().iterator(), filter);
}
/**
@@ -381,21 +349,12 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
/** {@inheritDoc} */
@Override public boolean canGetFirstOrLast() {
- return true;
+ return false;
}
/** {@inheritDoc} */
@Override public Cursor findFirstOrLast(Session ses, boolean first) {
- ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree = treeForRead();
-
- Iterator<GridH2Row> iter = filter(first ? tree.values().iterator() : tree.descendingMap().values().iterator());
-
- GridSearchRowPointer res = null;
-
- if (iter.hasNext())
- res = iter.next();
-
- return new SingleRowCursor((Row)res);
+ throw DbException.throwInternalError();
}
/** {@inheritDoc} */
@@ -503,11 +462,8 @@ public class GridH2TreeIndex extends GridH2IndexBase implements Comparator<GridS
@Override public GridH2TreeIndex rebuild() throws InterruptedException {
IndexColumn[] cols = getIndexColumns();
- if (!getIndexType().isUnique())
- cols = Arrays.copyOf(cols, cols.length - 1);
-
- GridH2TreeIndex idx = new GridH2TreeIndex(getName(), (GridH2Table)getTable(), getIndexType().isUnique(),
- keyCol, valCol, cols);
+ GridH2TreeIndex idx = new GridH2TreeIndex(getName(), getTable(),
+ getIndexType().isUnique(), F.asList(cols));
Thread thread = Thread.currentThread();
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Utils.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Utils.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Utils.java
deleted file mode 100644
index aafcfcc..0000000
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Utils.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * 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.opt;
-
-import java.sql.Timestamp;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import org.h2.value.ValueTimestamp;
-
-/**
- *
- */
-@SuppressWarnings({"JavaAbbreviationUsage", "GridBracket"})
-public class GridH2Utils {
- /** Copy/pasted from org.h2.util.DateTimeUtils */
- private static final int SHIFT_YEAR = 9;
-
- /** Copy/pasted from org.h2.util.DateTimeUtils */
- private static final int SHIFT_MONTH = 5;
-
- /** Static calendar. */
- private static final Calendar staticCalendar = Calendar.getInstance();
-
- /** */
- private static final ThreadLocal<Calendar> localCalendar = new ThreadLocal<>();
-
- /**
- * @return The instance of calendar for local thread.
- */
- public static Calendar getLocalCalendar() {
- Calendar res = localCalendar.get();
-
- if (res == null) {
- res = (Calendar)staticCalendar.clone();
-
- localCalendar.set(res);
- }
-
- return res;
- }
-
- /**
- * Get or create a timestamp value for the given timestamp.
- *
- * Copy/pasted from org.h2.value.ValueTimestamp#get(java.sql.Timestamp)
- *
- * @param timestamp The timestamp.
- * @return The value.
- */
- public static ValueTimestamp toValueTimestamp(Timestamp timestamp) {
- long ms = timestamp.getTime();
- long nanos = timestamp.getNanos() % 1000000;
-
- Calendar calendar = getLocalCalendar();
-
- calendar.clear();
- calendar.setTimeInMillis(ms);
-
- long dateValue = dateValueFromCalendar(calendar);
-
- nanos += nanosFromCalendar(calendar);
-
- return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
- }
-
- /**
- * Calculate the nanoseconds since midnight from a given calendar.
- *
- * Copy/pasted from org.h2.util.DateTimeUtils#nanosFromCalendar(java.util.Calendar).
- *
- * @param cal The calendar.
- * @return Nanoseconds.
- */
- private static long nanosFromCalendar(Calendar cal) {
- int h = cal.get(Calendar.HOUR_OF_DAY);
- int m = cal.get(Calendar.MINUTE);
- int s = cal.get(Calendar.SECOND);
- int millis = cal.get(Calendar.MILLISECOND);
-
- return ((((((h * 60L) + m) * 60) + s) * 1000) + millis) * 1000000;
- }
-
- /**
- * Calculate the date value from a given calendar.
- *
- * Copy/pasted from org.h2.util.DateTimeUtils#dateValueFromCalendar(java.util.Calendar)
- *
- * @param cal The calendar.
- * @return The date value.
- */
- private static long dateValueFromCalendar(Calendar cal) {
- int year, month, day;
-
- year = getYear(cal);
- month = cal.get(Calendar.MONTH) + 1;
- day = cal.get(Calendar.DAY_OF_MONTH);
-
- return ((long) year << SHIFT_YEAR) | (month << SHIFT_MONTH) | day;
- }
-
- /**
- * Get the year (positive or negative) from a calendar.
- *
- * Copy/pasted from org.h2.util.DateTimeUtils#getYear(java.util.Calendar)
- *
- * @param calendar The calendar.
- * @return The year.
- */
- private static int getYear(Calendar calendar) {
- int year = calendar.get(Calendar.YEAR);
-
- if (calendar.get(Calendar.ERA) == GregorianCalendar.BC) {
- year = 1 - year;
- }
-
- return year;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
index 29f9675..80e8504 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2ValueCacheObject.java
@@ -27,6 +27,7 @@ import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.h2.message.DbException;
+import org.h2.util.JdbcUtils;
import org.h2.util.Utils;
import org.h2.value.CompareMode;
import org.h2.value.Value;
@@ -117,7 +118,7 @@ public class GridH2ValueCacheObject extends Value {
}
// For user-provided and array types.
- return Utils.serialize(obj, null);
+ return JdbcUtils.serialize(obj, null);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java
index 957e5f6..716c9cb 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridLuceneIndex.java
@@ -17,7 +17,6 @@
package org.apache.ignite.internal.processors.query.h2.opt;
-import java.io.Closeable;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicLong;
@@ -51,7 +50,7 @@ import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermRangeFilter;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Version;
-import org.h2.util.Utils;
+import org.h2.util.JdbcUtils;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.KEY_FIELD_NAME;
@@ -60,7 +59,7 @@ import static org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing.VA
/**
* Lucene fulltext index.
*/
-public class GridLuceneIndex implements Closeable {
+public class GridLuceneIndex implements AutoCloseable {
/** Field name for string representation of value. */
public static final String VAL_STR_FIELD_NAME = "_gg_val_str__";
@@ -363,7 +362,7 @@ public class GridLuceneIndex implements Closeable {
@SuppressWarnings("unchecked")
private <Z> Z unmarshall(byte[] bytes, ClassLoader ldr) throws IgniteCheckedException {
if (coctx == null) // For tests.
- return (Z)Utils.deserialize(bytes, null);
+ return (Z)JdbcUtils.deserialize(bytes, null);
return (Z)coctx.processor().unmarshal(coctx, bytes, ldr);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java
index 245b88e..3fb6f3c 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java
@@ -52,6 +52,18 @@ public class GridSqlAlias extends GridSqlElement {
this.alias = alias;
}
+ /**
+ * @param el Element.
+ * @return Unwrapped from alias element.
+ */
+ public static GridSqlElement unwrap(GridSqlElement el) {
+ el = el instanceof GridSqlAlias ? el.child() : el;
+
+ assert el != null;
+
+ return el;
+ }
+
/** {@inheritDoc} */
@Override public String getSQL() {
return child().getSQL() + (useAs ? " AS " : " ") + Parser.quoteIdentifier(alias);
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
index aca1398..6ef4446 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.processors.query.h2.sql;
import java.util.Collections;
+import org.h2.table.Column;
/**
* Column.
@@ -32,12 +33,16 @@ public class GridSqlColumn extends GridSqlElement implements GridSqlValue {
/** SQL from original query. May be qualified or unqualified column name. */
private final String sqlText;
+ /** */
+ private Column col;
+
/**
+ * @param col Column.
* @param from From.
* @param name Name.
* @param sqlText Text.
*/
- public GridSqlColumn(GridSqlElement from, String name, String sqlText) {
+ public GridSqlColumn(Column col, GridSqlElement from, String name, String sqlText) {
super(Collections.<GridSqlElement>emptyList());
assert sqlText != null;
@@ -45,13 +50,7 @@ public class GridSqlColumn extends GridSqlElement implements GridSqlValue {
expressionInFrom = from;
colName = name;
this.sqlText = sqlText;
- }
-
- /**
- * @return Simple unqualified column with only name.
- */
- public GridSqlColumn simplify() {
- return new GridSqlColumn(null, colName, colName);
+ this.col = col;
}
/**
@@ -72,4 +71,11 @@ public class GridSqlColumn extends GridSqlElement implements GridSqlValue {
public GridSqlElement expressionInFrom() {
return expressionInFrom;
}
+
+ /**
+ * @return H2 Column.
+ */
+ public Column column() {
+ return col;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java
index 57d3c57..d95c14a 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java
@@ -119,4 +119,15 @@ public abstract class GridSqlElement implements Iterable<GridSqlElement> {
@Override public String toString() {
return getSQL();
}
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ throw new IllegalStateException();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ return this == o || (!(o == null || getClass() != o.getClass()) &&
+ children.equals(((GridSqlElement)o).children));
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java
index 18d8bdf..737c5b1 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java
@@ -63,7 +63,7 @@ public class GridSqlOperation extends GridSqlElement {
/**
* @return Operation type.
*/
- public GridSqlOperationType opType() {
+ public GridSqlOperationType operationType() {
return opType;
}
[03/50] [abbrv] ignite git commit: IGNITE-3515: NullPointerException
when stopping IgniteSemaphore and no method has been called previously to
initialize semaphore with initializeSemaphore(). Reviewed by Denis Magda.
Posted by vo...@apache.org.
IGNITE-3515: NullPointerException when stopping IgniteSemaphore and no method has been called previously to initialize semaphore with initializeSemaphore().
Reviewed by Denis Magda.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ab4963a6
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ab4963a6
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ab4963a6
Branch: refs/heads/ignite-3553
Commit: ab4963a686ea7ca560604079c52b8939b605cfcf
Parents: a989f04
Author: Krome Plasma <re...@some.invalid.address>
Authored: Fri Jul 22 14:53:39 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Fri Jul 22 14:53:39 2016 +0300
----------------------------------------------------------------------
.../datastructures/GridCacheSemaphoreImpl.java | 108 ++++++++++++-------
.../IgniteSemaphoreAbstractSelfTest.java | 25 ++++-
2 files changed, 94 insertions(+), 39 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/ab4963a6/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
index 8f196be..a11c79d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/datastructures/GridCacheSemaphoreImpl.java
@@ -36,6 +36,7 @@ import org.apache.ignite.IgniteInterruptedException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteSemaphore;
import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
import org.apache.ignite.internal.IgnitionEx;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
@@ -51,11 +52,11 @@ import static org.apache.ignite.transactions.TransactionConcurrency.PESSIMISTIC;
import static org.apache.ignite.transactions.TransactionIsolation.REPEATABLE_READ;
/**
- * Cache semaphore implementation based on AbstractQueuedSynchronizer.
- * Current implementation supports only unfair semaphores.
- * If any node fails after acquiring permissions on cache semaphore, there are two different behaviors controlled with the
- * parameter failoverSafe. If this parameter is true, other nodes can reacquire permits that were acquired by the failing node.
- * In case this parameter is false, IgniteInterruptedException is called on every node waiting on this semaphore.
+ * Cache semaphore implementation based on AbstractQueuedSynchronizer. Current implementation supports only unfair
+ * semaphores. If any node fails after acquiring permissions on cache semaphore, there are two different behaviors
+ * controlled with the parameter failoverSafe. If this parameter is true, other nodes can reacquire permits that were
+ * acquired by the failing node. In case this parameter is false, IgniteInterruptedException is called on every node
+ * waiting on this semaphore.
*/
public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Externalizable {
/** */
@@ -104,8 +105,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
}
/**
- * Synchronization implementation for semaphore.
- * Uses AQS state to represent permits.
+ * Synchronization implementation for semaphore. Uses AQS state to represent permits.
*/
final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1192457210091910933L;
@@ -155,10 +155,10 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
* Get number of permits for node.
*
* @param nodeID Node ID.
- * @return Number of permits node has acquired at this semaphore. Can be less than 0 if
- * more permits were released than acquired on node.
+ * @return Number of permits node has acquired at this semaphore. Can be less than 0 if more permits were
+ * released than acquired on node.
*/
- public int getPermitsForNode(UUID nodeID){
+ public int getPermitsForNode(UUID nodeID) {
return nodeMap.containsKey(nodeID) ? nodeMap.get(nodeID) : 0;
}
@@ -182,12 +182,10 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
}
/**
- * Set a flag indicating that it is not safe to continue using this semaphore.
- * This is the case only if one of two things happened:
- * 1. A node that previously acquired on this semaphore failed and
- * semaphore is created in non-failoversafe mode;
- * 2. Local node failed (is closed), so any any threads on this node
- * waiting to acquire are notified, and semaphore is not safe to be used anymore.
+ * Set a flag indicating that it is not safe to continue using this semaphore. This is the case only if one of
+ * two things happened: 1. A node that previously acquired on this semaphore failed and semaphore is created in
+ * non-failoversafe mode; 2. Local node failed (is closed), so any any threads on this node waiting to acquire
+ * are notified, and semaphore is not safe to be used anymore.
*
* @return True is semaphore is not safe to be used anymore.
*/
@@ -195,11 +193,12 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
return broken;
}
- /** Flag indicating that a node failed and it is not safe to continue using this semaphore.
- * Any attempt to acquire on broken semaphore will result in {@linkplain IgniteInterruptedException}.
+ /**
+ * Flag indicating that a node failed and it is not safe to continue using this semaphore. Any attempt to
+ * acquire on broken semaphore will result in {@linkplain IgniteInterruptedException}.
*
* @param broken True if semaphore should not be used anymore.
- * */
+ */
protected void setBroken(boolean broken) {
this.broken = broken;
}
@@ -211,9 +210,9 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
* @return Negative number if thread should block, positive if thread successfully acquires permits.
*/
final int nonfairTryAcquireShared(int acquires) {
- for (;;) {
+ for (; ; ) {
// If broken, return immediately, exception will be thrown anyway.
- if(broken)
+ if (broken)
return 1;
int available = getState();
@@ -238,9 +237,9 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
if (releases == 0)
return true;
- for (;;) {
+ for (; ; ) {
// If broken, return immediately, exception will be thrown anyway.
- if(broken)
+ if (broken)
return true;
int cur = getState();
@@ -261,9 +260,9 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
* @return Number of permits to drain.
*/
final int drainPermits() {
- for (;;) {
+ for (; ; ) {
// If broken, return immediately, exception will be thrown anyway.
- if(broken)
+ if (broken)
return 1;
int current = getState();
@@ -288,7 +287,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
@Override public Boolean call() throws Exception {
try (IgniteInternalTx tx = CU.txStartInternal(ctx,
semView,
- PESSIMISTIC, REPEATABLE_READ)
+ PESSIMISTIC, REPEATABLE_READ)
) {
GridCacheSemaphoreState val = semView.get(key);
@@ -304,11 +303,11 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
if (!draining) {
UUID nodeID = ctx.localNodeId();
- Map<UUID,Integer> map = val.getWaiters();
+ Map<UUID, Integer> map = val.getWaiters();
int waitingCnt = expVal - newVal;
- if(map.containsKey(nodeID))
+ if (map.containsKey(nodeID))
waitingCnt += map.get(nodeID);
map.put(nodeID, waitingCnt);
@@ -370,9 +369,9 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
throw new IgniteCheckedException("Failed to find semaphore with given name: " +
name);
- Map<UUID,Integer> map = val.getWaiters();
+ Map<UUID, Integer> map = val.getWaiters();
- if(!map.containsKey(nodeId)){
+ if (!map.containsKey(nodeId)) {
tx.rollback();
return false;
@@ -380,7 +379,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
int numPermits = map.get(nodeId);
- if(numPermits > 0)
+ if (numPermits > 0)
val.setCount(val.getCount() + numPermits);
map.remove(nodeId);
@@ -552,7 +551,42 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
}
}
+ /** {@inheritDoc} */
@Override public void stop() {
+ if (initGuard.get()) {
+ try {
+ // Wait while initialization is in progress.
+ U.await(initLatch);
+ }
+ catch (IgniteInterruptedCheckedException e) {
+ if (log.isDebugEnabled())
+ log.error("Failed waiting while initialization is completed.", e);
+ }
+ }
+ else {
+ // Preventing concurrent initialization.
+ if (initGuard.compareAndSet(false, true)) {
+ initLatch.countDown();
+
+ if (log.isDebugEnabled())
+ log.debug("Semaphore wasn't initialized. Prevented further initialization.");
+
+ return;
+ }
+ else {
+ try {
+ // Wait while initialization is in progress.
+ U.await(initLatch);
+ }
+ catch (IgniteInterruptedCheckedException e) {
+ if (log.isDebugEnabled())
+ log.error("Failed waiting while initialization is completed.", e);
+ }
+ }
+ }
+
+ assert sync != null;
+
sync.setBroken(true);
// Try to notify any waiting threads.
@@ -580,7 +614,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
sync.acquireSharedInterruptibly(permits);
- if(isBroken())
+ if (isBroken())
throw new InterruptedException();
}
catch (IgniteCheckedException e) {
@@ -697,7 +731,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
boolean result = sync.nonfairTryAcquireShared(1) >= 0;
- if(isBroken())
+ if (isBroken())
throw new InterruptedException();
return result;
@@ -722,7 +756,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
boolean result = sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
- if(isBroken())
+ if (isBroken())
throw new InterruptedException();
return result;
@@ -789,9 +823,9 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
try {
initializeSemaphore();
- boolean result = sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
+ boolean result = sync.tryAcquireSharedNanos(permits, unit.toNanos(timeout));
- if(isBroken())
+ if (isBroken())
throw new InterruptedException();
return result;
@@ -859,7 +893,7 @@ public final class GridCacheSemaphoreImpl implements GridCacheSemaphoreEx, Exter
}
/** {@inheritDoc} */
- @Override public boolean isBroken(){
+ @Override public boolean isBroken() {
ctx.kernalContext().gateway().readLock();
try {
http://git-wip-us.apache.org/repos/asf/ignite/blob/ab4963a6/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteSemaphoreAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteSemaphoreAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteSemaphoreAbstractSelfTest.java
index 200e276..5241dd1 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteSemaphoreAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/datastructures/IgniteSemaphoreAbstractSelfTest.java
@@ -30,6 +30,7 @@ import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteCompute;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteSemaphore;
+import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.IgniteKernal;
@@ -39,6 +40,7 @@ import org.apache.ignite.lang.IgniteCallable;
import org.apache.ignite.lang.IgniteFuture;
import org.apache.ignite.resources.IgniteInstanceResource;
import org.apache.ignite.resources.LoggerResource;
+import org.apache.ignite.testframework.GridStringLogger;
import org.apache.ignite.testframework.GridTestUtils;
import org.jetbrains.annotations.Nullable;
import org.junit.Rule;
@@ -234,6 +236,25 @@ public abstract class IgniteSemaphoreAbstractSelfTest extends IgniteAtomicsAbstr
/**
* @throws Exception If failed.
*/
+ public void testSemaphoreClosing() throws Exception {
+ IgniteConfiguration cfg;
+ GridStringLogger stringLogger;
+
+ stringLogger = new GridStringLogger();
+
+ cfg = optimize(getConfiguration("npeGrid"));
+ cfg.setGridLogger(stringLogger);
+
+ try (Ignite ignite = startGrid(cfg.getGridName(), cfg)) {
+ ignite.semaphore("semaphore", 1, true, true);
+ }
+
+ assertFalse(stringLogger.toString().contains(NullPointerException.class.getName()));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
private void checkSemaphoreSerialization() throws Exception {
final IgniteSemaphore sem = grid(0).semaphore("semaphore", -gridCount() + 1, true, true);
@@ -276,8 +297,8 @@ public abstract class IgniteSemaphoreAbstractSelfTest extends IgniteAtomicsAbstr
}
/**
- * This method only checks if parameter of new semaphore is initialized properly.
- * For tests considering failure recovery see @GridCachePartitionedNodeFailureSelfTest.
+ * This method only checks if parameter of new semaphore is initialized properly. For tests considering failure
+ * recovery see
*
* @throws Exception Exception.
*/
[47/50] [abbrv] ignite git commit: Release Notes 1.7
Posted by vo...@apache.org.
Release Notes 1.7
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a7cf1249
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a7cf1249
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a7cf1249
Branch: refs/heads/ignite-3553
Commit: a7cf12491203c4aa3106a1b27e2d23a7e014d154
Parents: 5f4563c
Author: Anton Vinogradov <av...@apache.org>
Authored: Wed Jul 27 18:06:23 2016 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Wed Jul 27 18:06:23 2016 +0300
----------------------------------------------------------------------
RELEASE_NOTES.txt | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a7cf1249/RELEASE_NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE_NOTES.txt b/RELEASE_NOTES.txt
index cef51bd..60bb248 100644
--- a/RELEASE_NOTES.txt
+++ b/RELEASE_NOTES.txt
@@ -1,6 +1,23 @@
Apache Ignite Release Notes
===========================
+Apache Ignite In-Memory Data Fabric 1.7
+---------------------------------------
+Ignite .NET:
+* Added NuGet distribution.
+* Fixed a bug in IBinaryObjectBuilder causing type name to be lost.
+
+Ignite C++:
+* Fixed string deserialization performance issue.
+
+Ignite:
+* DR: Fixed a bug causing retention of unused file store data.
+* Fixed CountDownLatch recreation.
+* Node can be assigned as primary only after preloading is finished.
+* ODBC: Added decimal type support.
+* Supported distributed SQL JOIN.
+* Visor: Fixed data nodes calculation when node filter is set for cache.
+
Apache Ignite In-Memory Data Fabric 1.6
---------------------------------------
Ignite .NET:
[39/50] [abbrv] ignite git commit: IGNITE-3561: .NET: Improved
distributed joins API for LINQ,
added more tests. This closes #893. This closes #900.
Posted by vo...@apache.org.
IGNITE-3561: .NET: Improved distributed joins API for LINQ, added more tests. This closes #893. This closes #900.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/9a808386
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/9a808386
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/9a808386
Branch: refs/heads/ignite-3553
Commit: 9a8083860ed61dde981cb6da65de869dc4205ae0
Parents: 42f42ea
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Jul 27 13:42:30 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Wed Jul 27 13:42:30 2016 +0300
----------------------------------------------------------------------
.../Cache/Query/CacheLinqTest.cs | 55 ++++++++++--
.../Cache/Query/CacheQueriesTest.cs | 29 ++++---
.../Apache.Ignite.Linq.csproj | 1 +
.../Apache.Ignite.Linq/CacheExtensions.cs | 23 +----
.../Apache.Ignite.Linq/Impl/CacheQueryable.cs | 15 ++--
.../dotnet/Apache.Ignite.Linq/QueryOptions.cs | 91 ++++++++++++++++++++
6 files changed, 165 insertions(+), 49 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/9a808386/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
index f76a74c..679f03a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
@@ -36,7 +36,6 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
using Apache.Ignite.Core.Cache;
using Apache.Ignite.Core.Cache.Configuration;
using Apache.Ignite.Core.Cache.Query;
- using Apache.Ignite.Core.Common;
using Apache.Ignite.Linq;
using NUnit.Framework;
@@ -955,7 +954,12 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
var cache = GetPersonCache();
// Check regular query
- var query = (ICacheQueryable) cache.AsCacheQueryable(true, null, 999, false, true).Where(x => x.Key > 10);
+ var query = (ICacheQueryable) cache.AsCacheQueryable(new QueryOptions
+ {
+ Local = true,
+ PageSize = 999,
+ EnforceJoinOrder = true
+ }).Where(x => x.Key > 10);
Assert.AreEqual(cache.Name, query.CacheName);
Assert.AreEqual(cache.Ignite, query.Ignite);
@@ -983,14 +987,10 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
Assert.IsFalse(fq.EnforceJoinOrder);
// Check distributed joins flag propagation
- var distrQuery = cache.AsCacheQueryable(true, null, 999, true, true).Where(x => x.Key > 10);
+ var distrQuery = cache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true})
+ .Where(x => x.Key > 10);
query = (ICacheQueryable) distrQuery;
Assert.IsTrue(query.GetFieldsQuery().EnableDistributedJoins);
-
- // Easy check that EnableDistributedJoins is propagated to Java: it throws an error on replicated cache
- var ex = Assert.Throws<IgniteException>(() => Assert.AreEqual(0, distrQuery.ToArray().Length));
- Assert.AreEqual("Queries using distributed JOINs have to be run on partitioned cache, not on replicated.",
- ex.Message);
}
/// <summary>
@@ -1022,6 +1022,45 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
}
/// <summary>
+ /// Tests the distributed joins.
+ /// </summary>
+ [Test]
+ public void TestDistributedJoins()
+ {
+ var ignite = Ignition.GetIgnite();
+
+ // Create and populate partitioned caches
+ var personCache = ignite.CreateCache<int, Person>(new CacheConfiguration("partitioned_persons",
+ new QueryEntity(typeof(int), typeof(Person))));
+
+ personCache.PutAll(GetSecondPersonCache().ToDictionary(x => x.Key, x => x.Value));
+
+ var roleCache = ignite.CreateCache<int, Role>(new CacheConfiguration("partitioned_roles",
+ new QueryEntity(typeof(int), typeof(Role))));
+
+ roleCache.PutAll(GetRoleCache().ToDictionary(x => x.Key.Foo, x => x.Value));
+
+ // Test non-distributed join: returns partial results
+ var persons = personCache.AsCacheQueryable();
+ var roles = roleCache.AsCacheQueryable();
+
+ var res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+ .ToArray();
+
+ Assert.Greater(res.Length, 0);
+ Assert.Less(res.Length, RoleCount);
+
+ // Test distributed join: returns complete results
+ persons = personCache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true});
+ roles = roleCache.AsCacheQueryable(new QueryOptions {EnableDistributedJoins = true});
+
+ res = persons.Join(roles, person => person.Key - PersonCount, role => role.Key, (person, role) => role)
+ .ToArray();
+
+ Assert.AreEqual(RoleCount, res.Length);
+ }
+
+ /// <summary>
/// Gets the person cache.
/// </summary>
/// <returns></returns>
http://git-wip-us.apache.org/repos/asf/ignite/blob/9a808386/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
index 7bfd202..a8ffe13 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheQueriesTest.cs
@@ -552,31 +552,36 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
[Test]
public void TestDistributedJoins()
{
- // Easy check that EnableDistributedJoins is propagated to Java: it throws an error on replicated cache
var cache = GetIgnite(0).GetOrCreateCache<int, QueryPerson>(
new CacheConfiguration("replicatedCache")
{
- CacheMode = CacheMode.Replicated,
QueryEntities = new[]
{
- new QueryEntity(typeof(QueryPerson))
+ new QueryEntity(typeof(int), typeof(QueryPerson))
{
Fields = new[] {new QueryField("age", typeof(int))}
}
}
});
- cache[1] = new QueryPerson("Test", 150);
+ const int count = 100;
- // Distributed joins disabled: query works
- var qry = new SqlQuery(typeof(QueryPerson), "age < 50");
- Assert.AreEqual(0, cache.Query(qry).GetAll().Count);
+ cache.PutAll(Enumerable.Range(0, count).ToDictionary(x => x, x => new QueryPerson("Name" + x, x)));
- // Distributed joins enabled: query fails
- qry.EnableDistributedJoins = true;
- var ex = Assert.Throws<IgniteException>(() => Assert.AreEqual(0, cache.Query(qry).GetAll().Count));
- Assert.AreEqual("Queries using distributed JOINs have to be run on partitioned cache, not on replicated.",
- ex.Message);
+ // Test non-distributed join: returns partial results
+ var sql = "select T0.Age from QueryPerson as T0 " +
+ "inner join QueryPerson as T1 on ((? - T1.Age - 1) = T0._key)";
+
+ var res = cache.QueryFields(new SqlFieldsQuery(sql, count)).GetAll().Distinct().Count();
+
+ Assert.Greater(res, 0);
+ Assert.Less(res, count);
+
+ // Test distributed join: returns complete results
+ res = cache.QueryFields(new SqlFieldsQuery(sql, count) {EnableDistributedJoins = true})
+ .GetAll().Distinct().Count();
+
+ Assert.AreEqual(count, res);
}
/// <summary>
http://git-wip-us.apache.org/repos/asf/ignite/blob/9a808386/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj b/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
index 3abfa56..72e5f68 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
@@ -71,6 +71,7 @@
<Compile Include="Impl\ExpressionWalker.cs" />
<Compile Include="Package-Info.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="QueryOptions.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Apache.Ignite.Linq.nuspec" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/9a808386/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
index e6d585c..4b536f4 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/CacheExtensions.cs
@@ -20,7 +20,6 @@ namespace Apache.Ignite.Linq
using System.Linq;
using Apache.Ignite.Core.Cache;
using Apache.Ignite.Core.Cache.Configuration;
- using Apache.Ignite.Core.Cache.Query;
using Apache.Ignite.Linq.Impl;
/// <summary>
@@ -93,7 +92,7 @@ namespace Apache.Ignite.Linq
public static IQueryable<ICacheEntry<TKey, TValue>> AsCacheQueryable<TKey, TValue>(
this ICache<TKey, TValue> cache, bool local, string tableName)
{
- return cache.AsCacheQueryable(local, tableName, SqlFieldsQuery.DfltPageSize, false, false);
+ return cache.AsCacheQueryable(new QueryOptions {Local = local, TableName = tableName});
}
/// <summary>
@@ -108,28 +107,14 @@ namespace Apache.Ignite.Linq
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
/// <param name="cache">The cache.</param>
- /// <param name="local">Local flag. When set query will be executed only on local node, so only local
- /// entries will be returned as query result.</param>
- /// <param name="tableName">Name of the table.
- /// <para />
- /// Table name is equal to short class name of a cache value.
- /// When a cache has only one type of values, or only one <see cref="QueryEntity" /> defined,
- /// table name will be inferred and can be omitted.</param>
- /// <param name="pageSize">Query cursor page size.
- /// Defaults to <see cref="SqlFieldsQuery.DfltPageSize"/>.</param>
- /// <param name="enableDistributedJoins">Distributed joins option, see
- /// <see cref="SqlFieldsQuery.EnableDistributedJoins" />.</param>
- /// <param name="enforceJoinOrder">Enforce join order flag,
- /// see <see cref="SqlFieldsQuery.EnforceJoinOrder" />.</param>
+ /// <param name="queryOptions">The query options.</param>
/// <returns>
/// <see cref="IQueryable{T}" /> instance over this cache.
/// </returns>
public static IQueryable<ICacheEntry<TKey, TValue>> AsCacheQueryable<TKey, TValue>(
- this ICache<TKey, TValue> cache, bool local, string tableName, int pageSize,
- bool enableDistributedJoins, bool enforceJoinOrder)
+ this ICache<TKey, TValue> cache, QueryOptions queryOptions)
{
- return new CacheQueryable<TKey, TValue>(cache, local, tableName, pageSize, enableDistributedJoins,
- enforceJoinOrder);
+ return new CacheQueryable<TKey, TValue>(cache, queryOptions);
}
}
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/9a808386/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
index 7ade159..7372776 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryable.cs
@@ -30,17 +30,12 @@ namespace Apache.Ignite.Linq.Impl
/// Initializes a new instance of the <see cref="CacheQueryable{TKey, TValue}" /> class.
/// </summary>
/// <param name="cache">The cache.</param>
- /// <param name="local">Local flag.</param>
- /// <param name="tableName">Name of the table.</param>
- /// <param name="pageSize">Size of the page.</param>
- /// <param name="enableDistributedJoins">Distributed joins flag.</param>
- /// <param name="enforceJoinOrder">Enforce join order flag.</param>
- public CacheQueryable(ICache<TKey, TValue> cache, bool local, string tableName, int pageSize,
- bool enableDistributedJoins,
- bool enforceJoinOrder)
+ /// <param name="queryOptions">The query options.</param>
+ public CacheQueryable(ICache<TKey, TValue> cache, QueryOptions queryOptions)
: base(new CacheFieldsQueryProvider(CacheQueryParser.Instance,
- new CacheFieldsQueryExecutor((ICacheInternal) cache, local, pageSize, enableDistributedJoins,
- enforceJoinOrder), cache.Ignite, cache.GetConfiguration(), tableName, typeof(TValue)))
+ new CacheFieldsQueryExecutor((ICacheInternal) cache, queryOptions.Local, queryOptions.PageSize,
+ queryOptions.EnableDistributedJoins, queryOptions.EnforceJoinOrder),
+ cache.Ignite, cache.GetConfiguration(), queryOptions.TableName, typeof(TValue)))
{
// No-op.
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/9a808386/modules/platforms/dotnet/Apache.Ignite.Linq/QueryOptions.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/QueryOptions.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/QueryOptions.cs
new file mode 100644
index 0000000..4fe3ee5
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/QueryOptions.cs
@@ -0,0 +1,91 @@
+\ufeff/*
+ * 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.
+ */
+
+namespace Apache.Ignite.Linq
+{
+ using System.ComponentModel;
+ using Apache.Ignite.Core.Cache.Configuration;
+ using Apache.Ignite.Core.Cache.Query;
+
+ /// <summary>
+ /// Cache query options.
+ /// </summary>
+ public class QueryOptions
+ {
+ /// <summary> Default page size. </summary>
+ public const int DefaultPageSize = SqlFieldsQuery.DfltPageSize;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="QueryOptions"/> class.
+ /// </summary>
+ public QueryOptions()
+ {
+ PageSize = DefaultPageSize;
+ }
+
+ /// <summary>
+ /// Local flag. When set query will be executed only on local node, so only local
+ /// entries will be returned as query result.
+ /// <para />
+ /// Defaults to <c>false</c>.
+ /// </summary>
+ public bool Local { get; set; }
+
+ /// <summary>
+ /// Page size, defaults to <see cref="DefaultPageSize"/>.
+ /// </summary>
+ [DefaultValue(DefaultPageSize)]
+ public int PageSize { get; set; }
+
+ /// <summary>
+ /// Gets or sets the name of the table.
+ /// <para />
+ /// Table name is equal to short class name of a cache value.
+ /// When a cache has only one type of values, or only one <see cref="QueryEntity" /> defined,
+ /// table name will be inferred and can be omitted (null).
+ /// </summary>
+ /// <value>
+ /// The name of the table.
+ /// </value>
+ public string TableName { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether distributed joins should be enabled for this query.
+ /// <para />
+ /// When disabled, join results will only contain colocated data (joins work locally).
+ /// When enabled, joins work as expected, no matter how the data is distributed.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if enable distributed joins should be enabled; otherwise, <c>false</c>.
+ /// </value>
+ public bool EnableDistributedJoins { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether join order of tables should be enforced.
+ /// <para />
+ /// When true, query optimizer will not reorder tables in join.
+ /// <para />
+ /// It is not recommended to enable this property until you are sure that your indexes
+ /// and the query itself are correct and tuned as much as possible but
+ /// query optimizer still produces wrong join order.
+ /// </summary>
+ /// <value>
+ /// <c>true</c> if join order should be enforced; otherwise, <c>false</c>.
+ /// </value>
+ public bool EnforceJoinOrder { get; set; }
+ }
+}
[23/50] [abbrv] ignite git commit: ignite-3563 Support
distributedJoins flag in JDBC driver
Posted by vo...@apache.org.
ignite-3563 Support distributedJoins flag in JDBC driver
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/763f0676
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/763f0676
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/763f0676
Branch: refs/heads/ignite-3553
Commit: 763f0676b4cef169f41f648b6e41b8bcb16203d9
Parents: fd50502
Author: agura <ag...@gridgain.com>
Authored: Mon Jul 25 12:31:24 2016 +0300
Committer: agura <ag...@gridgain.com>
Committed: Mon Jul 25 15:16:44 2016 +0300
----------------------------------------------------------------------
.../jdbc2/JdbcDistributedJoinsQueryTest.java | 319 +++++++++++++++++++
.../jdbc/suite/IgniteJdbcDriverTestSuite.java | 2 +
.../org/apache/ignite/IgniteJdbcDriver.java | 14 +-
.../ignite/internal/jdbc2/JdbcConnection.java | 12 +
.../ignite/internal/jdbc2/JdbcQueryTask.java | 9 +-
.../ignite/internal/jdbc2/JdbcResultSet.java | 4 +-
.../ignite/internal/jdbc2/JdbcStatement.java | 2 +-
7 files changed, 357 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/763f0676/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
new file mode 100644
index 0000000..53bfa73
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDistributedJoinsQueryTest.java
@@ -0,0 +1,319 @@
+/*
+ * 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.jdbc2;
+
+import java.io.Serializable;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.Statement;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.ConnectorConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.F;
+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 org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.IgniteJdbcDriver.CFG_URL_PREFIX;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ * Tests for complex queries with distributed joins enabled (joins, etc.).
+ */
+public class JdbcDistributedJoinsQueryTest extends GridCommonAbstractTest {
+ /** IP finder. */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** JDBC URL. */
+ private static final String BASE_URL = CFG_URL_PREFIX + "distributedJoins=true@modules/clients/src/test/config/jdbc-config.xml";
+
+ /** Statement. */
+ private Statement stmt;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ CacheConfiguration<?,?> cache = defaultCacheConfiguration();
+
+ cache.setCacheMode(PARTITIONED);
+ cache.setBackups(1);
+ cache.setWriteSynchronizationMode(FULL_SYNC);
+ cache.setAtomicityMode(TRANSACTIONAL);
+ cache.setIndexedTypes(String.class, Organization.class, String.class, Person.class);
+
+ cfg.setCacheConfiguration(cache);
+
+ TcpDiscoverySpi disco = new TcpDiscoverySpi();
+
+ disco.setIpFinder(IP_FINDER);
+
+ cfg.setDiscoverySpi(disco);
+
+ cfg.setConnectorConfiguration(new ConnectorConfiguration());
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ startGrids(3);
+
+ IgniteCache<String, Organization> orgCache = grid(0).cache(null);
+
+ assert orgCache != null;
+
+ orgCache.put("o1", new Organization(1, "A"));
+ orgCache.put("o2", new Organization(2, "B"));
+
+ IgniteCache<String, Person> personCache = grid(0).cache(null);
+
+ assert personCache != null;
+
+ personCache.put("p1", new Person(1, "John White", 25, 1));
+ personCache.put("p2", new Person(2, "Joe Black", 35, 1));
+ personCache.put("p3", new Person(3, "Mike Green", 40, 2));
+
+ Class.forName("org.apache.ignite.IgniteJdbcDriver");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ stmt = DriverManager.getConnection(BASE_URL).createStatement();
+
+ assert stmt != null;
+ assert !stmt.isClosed();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ if (stmt != null) {
+ stmt.getConnection().close();
+ stmt.close();
+
+ assert stmt.isClosed();
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoin() throws Exception {
+ ResultSet rs = stmt.executeQuery(
+ "select p.id, p.name, o.name as orgName from Person p, Organization o where p.orgId = o.id");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ int id = rs.getInt("id");
+
+ if (id == 1) {
+ assert "John White".equals(rs.getString("name"));
+ assert "A".equals(rs.getString("orgName"));
+ }
+ else if (id == 2) {
+ assert "Joe Black".equals(rs.getString("name"));
+ assert "A".equals(rs.getString("orgName"));
+ }
+ else if (id == 3) {
+ assert "Mike Green".equals(rs.getString("name"));
+ assert "B".equals(rs.getString("orgName"));
+ }
+ else
+ assert false : "Wrong ID: " + id;
+
+ cnt++;
+ }
+
+ assertEquals(3, cnt);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinWithoutAlias() throws Exception {
+ ResultSet rs = stmt.executeQuery(
+ "select p.id, p.name, o.name from Person p, Organization o where p.orgId = o.id");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ int id = rs.getInt(1);
+
+ if (id == 1) {
+ assert "John White".equals(rs.getString("name"));
+ assert "John White".equals(rs.getString(2));
+ assert "A".equals(rs.getString(3));
+ }
+ else if (id == 2) {
+ assert "Joe Black".equals(rs.getString("name"));
+ assert "Joe Black".equals(rs.getString(2));
+ assert "A".equals(rs.getString(3));
+ }
+ else if (id == 3) {
+ assert "Mike Green".equals(rs.getString("name"));
+ assert "Mike Green".equals(rs.getString(2));
+ assert "B".equals(rs.getString(3));
+ }
+ else
+ assert false : "Wrong ID: " + id;
+
+ cnt++;
+ }
+
+ assert cnt == 3;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testIn() throws Exception {
+ ResultSet rs = stmt.executeQuery("select name from Person where age in (25, 35)");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ assert "John White".equals(rs.getString("name")) ||
+ "Joe Black".equals(rs.getString("name"));
+
+ cnt++;
+ }
+
+ assert cnt == 2;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testBetween() throws Exception {
+ ResultSet rs = stmt.executeQuery("select name from Person where age between 24 and 36");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ assert "John White".equals(rs.getString("name")) ||
+ "Joe Black".equals(rs.getString("name"));
+
+ cnt++;
+ }
+
+ assert cnt == 2;
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCalculatedValue() throws Exception {
+ ResultSet rs = stmt.executeQuery("select age * 2 from Person");
+
+ assert rs != null;
+
+ int cnt = 0;
+
+ while (rs.next()) {
+ assert rs.getInt(1) == 50 ||
+ rs.getInt(1) == 70 ||
+ rs.getInt(1) == 80;
+
+ cnt++;
+ }
+
+ assert cnt == 3;
+ }
+
+ /**
+ * Person.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ private static class Person implements Serializable {
+ /** ID. */
+ @QuerySqlField
+ private final int id;
+
+ /** Name. */
+ @QuerySqlField(index = false)
+ private final String name;
+
+ /** Age. */
+ @QuerySqlField
+ private final int age;
+
+ /** Organization ID. */
+ @QuerySqlField(index = true)
+ private final int orgId;
+
+ /**
+ * @param id ID.
+ * @param name Name.
+ * @param age Age.
+ * @param orgId Organization ID.
+ */
+ private Person(int id, String name, int age, int orgId) {
+ assert !F.isEmpty(name);
+ assert age > 0;
+ assert orgId > 0;
+
+ this.id = id;
+ this.name = name;
+ this.age = age;
+ this.orgId = orgId;
+ }
+ }
+
+ /**
+ * Organization.
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ private static class Organization implements Serializable {
+ /** ID. */
+ @QuerySqlField
+ private final int id;
+
+ /** Name. */
+ @QuerySqlField(index = false)
+ private final String name;
+
+ /**
+ * @param id ID.
+ * @param name Name.
+ */
+ private Organization(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/763f0676/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
index 603ee81..b1053b0 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java
@@ -18,6 +18,7 @@
package org.apache.ignite.jdbc.suite;
import junit.framework.TestSuite;
+import org.apache.ignite.internal.jdbc2.JdbcDistributedJoinsQueryTest;
import org.apache.ignite.jdbc.JdbcComplexQuerySelfTest;
import org.apache.ignite.jdbc.JdbcConnectionSelfTest;
import org.apache.ignite.jdbc.JdbcEmptyCacheSelfTest;
@@ -56,6 +57,7 @@ public class IgniteJdbcDriverTestSuite extends TestSuite {
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcPreparedStatementSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcResultSetSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcComplexQuerySelfTest.class));
+ suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcDistributedJoinsQueryTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcMetadataSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcEmptyCacheSelfTest.class));
suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcLocalCachesSelfTest.class));
http://git-wip-us.apache.org/repos/asf/ignite/blob/763f0676/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
index 567ff9f..d432c1e4 100644
--- a/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
+++ b/modules/core/src/main/java/org/apache/ignite/IgniteJdbcDriver.java
@@ -104,6 +104,11 @@ import org.apache.ignite.logger.java.JavaLogger;
* can make significant performance and network optimizations.
* Default value is {@code false}.
* </li>
+ * <li>
+ * {@code distributedJoins} - enables support of distributed joins feature. This flag does not make sense in
+ * combination with {@code local} and/or {@code collocated} flags with {@code true} value or in case of querying
+ * of local cache. Default value is {@code false}.
+ * </li>
* </ul>
*
* <h2 class="header">Configuration of Ignite Java client based connection</h2>
@@ -284,6 +289,9 @@ public class IgniteJdbcDriver implements Driver {
/** Collocated parameter name. */
private static final String PARAM_COLLOCATED = "collocated";
+ /** Distributed joins parameter name. */
+ private static final String PARAM_DISTRIBUTED_JOINS = "distributedJoins";
+
/** Hostname property name. */
public static final String PROP_HOST = PROP_PREFIX + "host";
@@ -302,6 +310,9 @@ public class IgniteJdbcDriver implements Driver {
/** Collocated property name. */
public static final String PROP_COLLOCATED = PROP_PREFIX + PARAM_COLLOCATED;
+ /** Distributed joins property name. */
+ public static final String PROP_DISTRIBUTED_JOINS = PROP_PREFIX + PARAM_DISTRIBUTED_JOINS;
+
/** Cache name property name. */
public static final String PROP_CFG = PROP_PREFIX + "cfg";
@@ -366,7 +377,8 @@ public class IgniteJdbcDriver implements Driver {
new PropertyInfo("Cache name", info.getProperty(PROP_CACHE), ""),
new PropertyInfo("Node ID", info.getProperty(PROP_NODE_ID), ""),
new PropertyInfo("Local", info.getProperty(PROP_LOCAL), ""),
- new PropertyInfo("Collocated", info.getProperty(PROP_COLLOCATED), "")
+ new PropertyInfo("Collocated", info.getProperty(PROP_COLLOCATED), ""),
+ new PropertyInfo("Distributed Joins", info.getProperty(PROP_DISTRIBUTED_JOINS), "")
);
if (info.getProperty(PROP_CFG) != null)
http://git-wip-us.apache.org/repos/asf/ignite/blob/763f0676/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
index 2d2ce5d..6f0d9c4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcConnection.java
@@ -69,6 +69,7 @@ import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.ignite.IgniteJdbcDriver.PROP_CACHE;
import static org.apache.ignite.IgniteJdbcDriver.PROP_CFG;
import static org.apache.ignite.IgniteJdbcDriver.PROP_COLLOCATED;
+import static org.apache.ignite.IgniteJdbcDriver.PROP_DISTRIBUTED_JOINS;
import static org.apache.ignite.IgniteJdbcDriver.PROP_LOCAL;
import static org.apache.ignite.IgniteJdbcDriver.PROP_NODE_ID;
@@ -113,6 +114,9 @@ public class JdbcConnection implements Connection {
/** Collocated query flag. */
private boolean collocatedQry;
+ /** Distributed joins flag. */
+ private boolean distributedJoins;
+
/** Statements. */
final Set<JdbcStatement> statements = new HashSet<>();
@@ -132,6 +136,7 @@ public class JdbcConnection implements Connection {
this.cacheName = props.getProperty(PROP_CACHE);
this.locQry = Boolean.parseBoolean(props.getProperty(PROP_LOCAL));
this.collocatedQry = Boolean.parseBoolean(props.getProperty(PROP_COLLOCATED));
+ this.distributedJoins = Boolean.parseBoolean(props.getProperty(PROP_DISTRIBUTED_JOINS));
String nodeIdProp = props.getProperty(PROP_NODE_ID);
@@ -706,6 +711,13 @@ public class JdbcConnection implements Connection {
}
/**
+ * @return Distributed joins flag.
+ */
+ boolean isDistributedJoins() {
+ return distributedJoins;
+ }
+
+ /**
* Ensures that connection is not closed.
*
* @throws SQLException If connection is closed.
http://git-wip-us.apache.org/repos/asf/ignite/blob/763f0676/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
index 1a5793a..c4911cb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcQueryTask.java
@@ -92,6 +92,9 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
/** Collocated query flag. */
private final boolean collocatedQry;
+ /** Distributed joins flag. */
+ private final boolean distributedJoins;
+
/**
* @param ignite Ignite.
* @param cacheName Cache name.
@@ -102,9 +105,11 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
* @param uuid UUID.
* @param locQry Local query flag.
* @param collocatedQry Collocated query flag.
+ * @param distributedJoins Distributed joins flag.
*/
public JdbcQueryTask(Ignite ignite, String cacheName, String sql,
- boolean loc, Object[] args, int fetchSize, UUID uuid, boolean locQry, boolean collocatedQry) {
+ boolean loc, Object[] args, int fetchSize, UUID uuid,
+ boolean locQry, boolean collocatedQry, boolean distributedJoins) {
this.ignite = ignite;
this.args = args;
this.uuid = uuid;
@@ -114,6 +119,7 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
this.loc = loc;
this.locQry = locQry;
this.collocatedQry = collocatedQry;
+ this.distributedJoins = distributedJoins;
}
/** {@inheritDoc} */
@@ -147,6 +153,7 @@ class JdbcQueryTask implements IgniteCallable<JdbcQueryTask.QueryResult> {
qry.setPageSize(fetchSize);
qry.setLocal(locQry);
qry.setCollocated(collocatedQry);
+ qry.setDistributedJoins(distributedJoins);
QueryCursor<List<?>> qryCursor = cache.query(qry);
http://git-wip-us.apache.org/repos/asf/ignite/blob/763f0676/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
index 69dddad..8e0e9d0 100755
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcResultSet.java
@@ -146,8 +146,8 @@ public class JdbcResultSet implements ResultSet {
boolean loc = nodeId == null;
- JdbcQueryTask qryTask = new JdbcQueryTask(loc ? ignite : null, conn.cacheName(),
- null, loc, null, fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery());
+ JdbcQueryTask qryTask = new JdbcQueryTask(loc ? ignite : null, conn.cacheName(), null, loc, null,
+ fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery(), conn.isDistributedJoins());
try {
JdbcQueryTask.QueryResult res =
http://git-wip-us.apache.org/repos/asf/ignite/blob/763f0676/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
index 6b806f3..e187dc0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java
@@ -96,7 +96,7 @@ public class JdbcStatement implements Statement {
boolean loc = nodeId == null;
JdbcQueryTask qryTask = new JdbcQueryTask(loc ? ignite : null, conn.cacheName(),
- sql, loc, args, fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery());
+ sql, loc, args, fetchSize, uuid, conn.isLocalQuery(), conn.isCollocatedQuery(), conn.isDistributedJoins());
try {
JdbcQueryTask.QueryResult res =
[36/50] [abbrv] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.6.3'
Posted by vo...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.6.3'
# Conflicts:
# modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
# modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/da563701
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/da563701
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/da563701
Branch: refs/heads/ignite-3553
Commit: da563701caec058db4a264a4b08f0a35c4cd9b17
Parents: a441bb9 9d07e3e
Author: sboikov <sb...@gridgain.com>
Authored: Wed Jul 27 10:17:16 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Wed Jul 27 10:17:16 2016 +0300
----------------------------------------------------------------------
.../org/apache/ignite/internal/IgnitionEx.java | 2 +
.../distributed/dht/GridDhtLocalPartition.java | 2 +-
.../dht/GridDhtPartitionTopologyImpl.java | 52 +++++++-
.../ServicePredicateAccessCacheTest.java | 4 +-
.../ignite/cache/spring/SpringCacheManager.java | 17 ++-
.../spring/SpringTransactionManager.java | 59 +++++----
.../test/java/config/spring-transactions.xml | 4 +-
.../ignite/TestInjectionLifecycleBean.java | 42 +++++++
.../org/apache/ignite/spring-injection-test.xml | 43 +++++++
.../SpringCacheManagerContextInjectionTest.java | 126 +++++++++++++++++++
.../testsuites/IgniteSpringTestSuite.java | 5 +
...gTransactionManagerContextInjectionTest.java | 125 ++++++++++++++++++
12 files changed, 448 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/da563701/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
----------------------------------------------------------------------
diff --cc modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
index 3692022,50f7f0f..1299d20
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
@@@ -23,16 -23,17 +23,18 @@@ import java.util.Collections
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReferenceArray;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteLogger;
+ import org.apache.ignite.IgniteSystemProperties;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.events.DiscoveryEvent;
+ import org.apache.ignite.internal.IgniteFutureTimeoutCheckedException;
import org.apache.ignite.internal.IgniteInterruptedCheckedException;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.affinity.GridAffinityAssignment;
@@@ -178,10 -179,27 +181,27 @@@ class GridDhtPartitionTopologyImpl impl
private boolean waitForRent() throws IgniteCheckedException {
boolean changed = false;
+ GridDhtLocalPartition[] locPartsCopy = new GridDhtLocalPartition[locParts.length];
+
+ lock.readLock().lock();
+
+ try {
+ for (int i = 0; i < locParts.length; i++)
+ locPartsCopy[i] = locParts[i];
+ }
+ finally {
+ lock.readLock().unlock();
+ }
+
+ final long longOpDumpTimeout =
+ IgniteSystemProperties.getLong(IgniteSystemProperties.IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, 60_000);
+
+ int dumpCnt = 0;
+
GridDhtLocalPartition part;
- for (int i = 0; i < locParts.length(); i++) {
- part = locParts.get(i);
- for (int i = 0; i < locPartsCopy.length; i++) {
- part = locPartsCopy[i];
++ for (int i = 0; i < locPartsCopy.length(); i++) {
++ part = locPartsCopy.get(i);
if (part == null)
continue;
http://git-wip-us.apache.org/repos/asf/ignite/blob/da563701/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
----------------------------------------------------------------------
[19/50] [abbrv] ignite git commit: IGNITE-3399 Add support for
primitive type names in QueryEntity - Fixes #878.
Posted by vo...@apache.org.
IGNITE-3399 Add support for primitive type names in QueryEntity - Fixes #878.
Signed-off-by: Sergi Vladykin <se...@gmail.com>
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/df5a842f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/df5a842f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/df5a842f
Branch: refs/heads/ignite-3553
Commit: df5a842f2ad3a676fcd0fd29b00a0eb361709488
Parents: ca5c8d8
Author: Jens Hoffmann <jc...@gmail.com>
Authored: Mon Jul 25 08:47:35 2016 +0300
Committer: Sergi Vladykin <se...@gmail.com>
Committed: Mon Jul 25 08:47:35 2016 +0300
----------------------------------------------------------------------
.../processors/query/GridQueryProcessor.java | 2 +-
.../ignite/internal/util/IgniteUtils.java | 32 ++++++++++++++++----
.../IgniteCacheQuerySelfTestSuite.java | 2 ++
3 files changed, 29 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/df5a842f/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 04c6cb0..0dd542e 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
@@ -1386,7 +1386,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
aliases = Collections.emptyMap();
for (Map.Entry<String, String> entry : qryEntity.getFields().entrySet()) {
- BinaryProperty prop = buildBinaryProperty(entry.getKey(), U.classForName(entry.getValue(), Object.class), aliases);
+ BinaryProperty prop = buildBinaryProperty(entry.getKey(), U.classForName(entry.getValue(), Object.class, true), aliases);
d.addProperty(prop, false);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/df5a842f/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index 7a81cf8..31128ca 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -1361,13 +1361,33 @@ public abstract class IgniteUtils {
* @param dflt Default class to return.
* @return Class or default given class if it can't be found.
*/
- @Nullable public static Class<?> classForName(String cls, @Nullable Class<?> dflt) {
- try {
- return cls == null ? dflt : Class.forName(cls);
- }
- catch (ClassNotFoundException ignore) {
- return dflt;
+ @Nullable public static Class<?> classForName(@Nullable String cls, @Nullable Class<?> dflt) {
+ return classForName(cls, dflt, false);
+ }
+
+ /**
+ * Gets class for the given name if it can be loaded or default given class.
+ *
+ * @param cls Class.
+ * @param dflt Default class to return.
+ * @param includePrimitiveTypes Whether class resolution should include primitive types (i.e. "int" will resolve to int.class if flag is set)
+ * @return Class or default given class if it can't be found.
+ */
+ @Nullable
+ public static Class<?> classForName(@Nullable String cls, @Nullable Class<?> dflt, boolean includePrimitiveTypes) {
+ Class<?> clazz;
+ if (cls == null)
+ clazz = dflt;
+ else if (includePrimitiveTypes && primitiveMap.containsKey(cls))
+ clazz = primitiveMap.get(cls);
+ else {
+ try {
+ clazz = Class.forName(cls);
+ } catch (ClassNotFoundException ignore) {
+ clazz = dflt;
+ }
}
+ return clazz;
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/df5a842f/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 65a94dd..0203354 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
@@ -40,6 +40,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapEvictQueryT
import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapIndexScanTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapTieredMultithreadedSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteCachePartitionedQueryMultiThreadedSelfTest;
+import org.apache.ignite.internal.processors.cache.IgniteCachePrimitiveFieldsQuerySelfTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheQueryEvictsMultiThreadedSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheQueryH2IndexingLeakTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheQueryIndexSelfTest;
@@ -125,6 +126,7 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
suite.addTestSuite(IgniteBinaryWrappedObjectFieldsQuerySelfTest.class);
suite.addTestSuite(IgniteCacheQueryH2IndexingLeakTest.class);
suite.addTestSuite(IgniteCacheQueryNoRebalanceSelfTest.class);
+ suite.addTestSuite(IgniteCachePrimitiveFieldsQuerySelfTest.class);
suite.addTestSuite(IgniteCacheJoinQueryWithAffinityKeyTest.class);
suite.addTestSuite(IgniteCacheDistributedJoinCollocatedAndNotTest.class);
[37/50] [abbrv] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.6.3'
Posted by vo...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.6.3'
# Conflicts:
# modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
# modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/42f42eac
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/42f42eac
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/42f42eac
Branch: refs/heads/ignite-3553
Commit: 42f42eac58c718f7debdd5f6e1ed989bae48de69
Parents: da56370
Author: sboikov <sb...@gridgain.com>
Authored: Wed Jul 27 10:17:36 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Wed Jul 27 10:17:36 2016 +0300
----------------------------------------------------------------------
.../dht/GridDhtPartitionTopologyImpl.java | 16 ++--------------
.../org/apache/ignite/spring-injection-test.xml | 2 +-
2 files changed, 3 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/42f42eac/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
index 1299d20..558a654 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionTopologyImpl.java
@@ -181,18 +181,6 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
private boolean waitForRent() throws IgniteCheckedException {
boolean changed = false;
- GridDhtLocalPartition[] locPartsCopy = new GridDhtLocalPartition[locParts.length];
-
- lock.readLock().lock();
-
- try {
- for (int i = 0; i < locParts.length; i++)
- locPartsCopy[i] = locParts[i];
- }
- finally {
- lock.readLock().unlock();
- }
-
final long longOpDumpTimeout =
IgniteSystemProperties.getLong(IgniteSystemProperties.IGNITE_LONG_OPERATIONS_DUMP_TIMEOUT, 60_000);
@@ -200,8 +188,8 @@ class GridDhtPartitionTopologyImpl implements GridDhtPartitionTopology {
GridDhtLocalPartition part;
- for (int i = 0; i < locPartsCopy.length(); i++) {
- part = locPartsCopy.get(i);
+ for (int i = 0; i < locParts.length(); i++) {
+ part = locParts.get(i);
if (part == null)
continue;
http://git-wip-us.apache.org/repos/asf/ignite/blob/42f42eac/modules/spring/src/test/java/org/apache/ignite/spring-injection-test.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/spring-injection-test.xml b/modules/spring/src/test/java/org/apache/ignite/spring-injection-test.xml
index b8368a3..7401986 100644
--- a/modules/spring/src/test/java/org/apache/ignite/spring-injection-test.xml
+++ b/modules/spring/src/test/java/org/apache/ignite/spring-injection-test.xml
@@ -18,7 +18,7 @@
-->
<!--
- GridGain Spring configuration file to startup grid cache.
+ Ignite Spring configuration file to startup grid cache.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
[46/50] [abbrv] ignite git commit: Added support for distributed join
flag in Visor.
Posted by vo...@apache.org.
Added support for distributed join flag in Visor.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/5f4563ce
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/5f4563ce
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/5f4563ce
Branch: refs/heads/ignite-3553
Commit: 5f4563cea930a8320593918d879554e6aba1abf7
Parents: f96b568
Author: AKuznetsov <ak...@gridgain.com>
Authored: Wed Jul 27 21:52:59 2016 +0700
Committer: AKuznetsov <ak...@gridgain.com>
Committed: Wed Jul 27 21:52:59 2016 +0700
----------------------------------------------------------------------
.../internal/visor/query/VisorQueryArgV2.java | 49 ++++++++++++++++++++
.../internal/visor/query/VisorQueryJob.java | 1 +
2 files changed, 50 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/5f4563ce/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryArgV2.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryArgV2.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryArgV2.java
new file mode 100644
index 0000000..8ed3976
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryArgV2.java
@@ -0,0 +1,49 @@
+/*
+ * 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.visor.query;
+
+/**
+ * Arguments for {@link VisorQueryTask}.
+ */
+public class VisorQueryArgV2 extends VisorQueryArg {
+ /** */
+ private static final long serialVersionUID = 0L;
+
+ /** Distributed joins enabled flag. */
+ private final boolean distributedJoins;
+
+ /**
+ * @param cacheName Cache name for query.
+ * @param qryTxt Query text.
+ * @param distributedJoins If {@code true} then distributed joins enabled.
+ * @param loc Flag whether to execute query locally.
+ * @param pageSize Result batch size.
+ */
+ public VisorQueryArgV2(String cacheName, String qryTxt, boolean distributedJoins, boolean loc, int pageSize) {
+ super(cacheName, qryTxt, loc, pageSize);
+
+ this.distributedJoins = distributedJoins;
+ }
+
+ /**
+ * @return Distributed joins enabled flag.
+ */
+ public boolean distributedJoins() {
+ return distributedJoins;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/5f4563ce/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryJob.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryJob.java b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryJob.java
index 0f2f82e..5d0a82e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryJob.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/visor/query/VisorQueryJob.java
@@ -139,6 +139,7 @@ public class VisorQueryJob extends VisorJob<VisorQueryArg, IgniteBiTuple<? exten
SqlFieldsQuery qry = new SqlFieldsQuery(arg.queryTxt());
qry.setPageSize(arg.pageSize());
qry.setLocal(arg.local());
+ qry.setDistributedJoins(arg instanceof VisorQueryArgV2 && ((VisorQueryArgV2)arg).distributedJoins());
long start = U.currentTimeMillis();
[16/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageResponse.java
index b220291..4889069 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageResponse.java
@@ -144,11 +144,6 @@ public class GridQueryNextPageResponse implements Message {
}
/** {@inheritDoc} */
- @Override public String toString() {
- return S.toString(GridQueryNextPageResponse.class, this);
- }
-
- /** {@inheritDoc} */
@Override public void onAckReceived() {
// No-op.
}
@@ -304,4 +299,11 @@ public class GridQueryNextPageResponse implements Message {
public void retry(AffinityTopologyVersion retry) {
this.retry = retry;
}
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(GridQueryNextPageResponse.class, this,
+ "valsSize", vals != null ? vals.size() : 0,
+ "rowsSize", plainRows != null ? plainRows.size() : 0);
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryRequest.java
index 60d348b..f7de86c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryRequest.java
@@ -20,13 +20,16 @@ package org.apache.ignite.internal.processors.query.h2.twostep.messages;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.List;
-import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.GridDirectCollection;
+import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.IgniteCodeGeneratingFail;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
+import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.plugin.extensions.communication.MessageCollectionItemType;
import org.apache.ignite.plugin.extensions.communication.MessageReader;
@@ -35,8 +38,9 @@ import org.apache.ignite.plugin.extensions.communication.MessageWriter;
/**
* Query request.
*/
+@Deprecated
@IgniteCodeGeneratingFail
-public class GridQueryRequest implements Message {
+public class GridQueryRequest implements Message, GridCacheQueryMarshallable {
/** */
private static final long serialVersionUID = 0L;
@@ -165,11 +169,29 @@ public class GridQueryRequest implements Message {
/**
* @return Queries.
*/
- public Collection<GridCacheSqlQuery> queries() throws IgniteCheckedException {
+ public Collection<GridCacheSqlQuery> queries() {
return qrys;
}
/** {@inheritDoc} */
+ @Override public void marshall(Marshaller m) {
+ if (F.isEmpty(qrys))
+ return;
+
+ for (GridCacheSqlQuery qry : qrys)
+ qry.marshall(m);
+ }
+
+ /** {@inheritDoc} */
+ @Override public void unmarshall(Marshaller m, GridKernalContext ctx) {
+ if (F.isEmpty(qrys))
+ return;
+
+ for (GridCacheSqlQuery qry : qrys)
+ qry.unmarshall(m, ctx);
+ }
+
+ /** {@inheritDoc} */
@Override public String toString() {
return S.toString(GridQueryRequest.class, this);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index 269795b..7a81cf8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -6703,6 +6703,19 @@ public abstract class IgniteUtils {
}
/**
+ * Swaps two objects in array.
+ *
+ * @param arr Array.
+ * @param a Index of the first object.
+ * @param b Index of the second object.
+ */
+ public static void swap(Object[] arr, int a, int b) {
+ Object tmp = arr[a];
+ arr[a] = arr[b];
+ arr[b] = tmp;
+ }
+
+ /**
* Returns array which is the union of two arrays
* (array of elements contained in any of provided arrays).
* <p/>
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
index ab31625..5eb27d3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/lang/GridFunc.java
@@ -2313,6 +2313,26 @@ public class GridFunc {
}
/**
+ * Converts collection of numbers to primitive {@code int[]} array.
+ *
+ * @param col Collection of numbers.
+ * @return Array of integers.
+ */
+ public static int[] toIntArray(Collection<? extends Number> col) {
+ if (col == null)
+ return null;
+
+ int[] res = new int[col.size()];
+
+ Iterator<? extends Number> iter = col.iterator();
+
+ for (int i = 0; i < res.length; i++)
+ res[i] = iter.next().intValue();
+
+ return res;
+ }
+
+ /**
* Utility map getter. This method analogous to {@link #addIfAbsent(Map, Object, Callable)}
* method but this one doesn't put the default value into the map when key is not found.
*
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java b/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
index 04ea56c..7bde651 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/offheap/unsafe/GridOffHeapSnapTreeMap.java
@@ -35,7 +35,6 @@
package org.apache.ignite.internal.util.offheap.unsafe;
-import java.io.Closeable;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
@@ -51,10 +50,11 @@ import java.util.SortedSet;
import java.util.concurrent.ConcurrentNavigableMap;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable;
import org.apache.ignite.internal.util.typedef.internal.SB;
import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
@@ -107,7 +107,7 @@ import org.jsr166.ConcurrentHashMap8;
*/
@SuppressWarnings("ALL")
public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer,V extends GridOffHeapSmartPointer>
- extends AbstractMap<K,V> implements ConcurrentNavigableMap<K, V>, Cloneable, Closeable {
+ extends AbstractMap<K,V> implements ConcurrentNavigableMap<K, V>, Cloneable, AutoCloseable, GridReservable {
/** This is a special value that indicates that an optimistic read failed. */
private static final GridOffHeapSmartPointer SpecialRetry = new GridOffHeapSmartPointer() {
@Override public long pointer() {
@@ -937,17 +937,17 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer,V extends
protected final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
/** */
- private final AtomicBoolean stopped = new AtomicBoolean(false);
+ private boolean stopped;
/** {@inheritDoc} */
@Override public boolean add(long node) {
- ReentrantReadWriteLock.ReadLock l = lock.readLock();
+ Lock l = lock.readLock();
if (!l.tryLock())
return false;
try {
- return super.add(node);
+ return !stopped && super.add(node);
}
finally {
l.unlock();
@@ -956,13 +956,13 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer,V extends
/** {@inheritDoc} */
@Override public boolean add(RecycleQueue que) {
- ReentrantReadWriteLock.ReadLock l = lock.readLock();
+ Lock l = lock.readLock();
if (!l.tryLock())
return false;
try {
- return super.add(que);
+ return !stopped && super.add(que);
}
finally {
l.unlock();
@@ -980,20 +980,21 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer,V extends
* @return {@code true} If we stopped this queue.
*/
public boolean stop() {
- if (stopped.compareAndSet(false, true)) {
- lock.writeLock().lock();
+ Lock l = lock.writeLock();
- return true;
- }
+ l.lock();
- return false;
- }
+ try {
+ if (stopped)
+ return false;
- /**
- * @return {@code true} If this queue is stopped..
- */
- public boolean isStopped() {
- return stopped.get();
+ stopped = true;
+
+ return true;
+ }
+ finally {
+ l.unlock();
+ }
}
}
@@ -1046,6 +1047,12 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer,V extends
/** Recycle queue for this snapshot. */
private volatile StoppableRecycleQueue recycleBin;
+ /** */
+ private AtomicInteger reservations;
+
+ /** */
+ private volatile boolean closing;
+
/**
* @param keyFactory Key factory.
* @param valFactory Value factory.
@@ -1079,10 +1086,53 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer,V extends
this.holderRef = rootHolder();
}
+ /** {@inheritDoc} */
+ @Override public boolean reserve() {
+ for (;;) {
+ int r = reservations.get();
+
+ if (r == -1)
+ return false;
+
+ assert r >= 0 : r;
+
+ if (reservations.compareAndSet(r, r + 1))
+ return true;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public void release() {
+ for (;;) {
+ int r = reservations.get();
+
+ assert r > 0 : r;
+
+ int z = r == 1 && closing ? -1 : r - 1;
+
+ if (reservations.compareAndSet(r, z)) {
+ if (z == -1)
+ doClose();
+
+ return;
+ }
+ }
+ }
+
/**
* Closes tree map and reclaims memory.
*/
- public void close() {
+ @Override public void close() {
+ closing = true;
+
+ if (reservations == null || reservations.compareAndSet(0, -1))
+ doClose();
+ }
+
+ /**
+ *
+ */
+ private void doClose() {
RecycleQueue q;
if (snapshotId.longValue() == 0) {
@@ -1142,6 +1192,7 @@ public class GridOffHeapSnapTreeMap<K extends GridOffHeapSmartPointer,V extends
copy.holderRef = rootHolder(holderRef);
markShared(root());
+ copy.reservations = new AtomicInteger();
copy.size = new AtomicInteger(size());
copy.recycleBin = new StoppableRecycleQueue();
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java
index 9392cc1..37352e1 100644
--- a/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/spi/discovery/tcp/ipfinder/jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java
@@ -51,7 +51,7 @@ public class TcpDiscoveryJdbcIpFinderSelfTest extends
dataSrc.setDriverClass("org.h2.Driver");
if (initSchema)
- dataSrc.setJdbcUrl("jdbc:h2:mem");
+ dataSrc.setJdbcUrl("jdbc:h2:mem:./test");
else {
dataSrc.setJdbcUrl("jdbc:h2:mem:jdbc_ipfinder_not_initialized_schema");
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
index 87509a4..e475754 100644
--- a/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/testframework/junits/common/GridCommonAbstractTest.java
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.cache.Cache;
import javax.cache.CacheException;
@@ -47,6 +48,7 @@ import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CachePeekMode;
import org.apache.ignite.cache.affinity.Affinity;
import org.apache.ignite.cache.affinity.AffinityFunction;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cluster.ClusterGroup;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.cluster.ClusterTopologyException;
@@ -529,7 +531,7 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest {
", locNode=" + g.cluster().localNode() + ']');
}
- Thread.sleep(200); // Busy wait.
+ Thread.sleep(20); // Busy wait.
continue;
}
@@ -1177,4 +1179,39 @@ public abstract class GridCommonAbstractTest extends GridAbstractTest {
}
}
}
+
+ /**
+ * @param aff Affinity.
+ * @param key Counter.
+ * @param node Target node.
+ * @return Key.
+ */
+ protected final Integer keyForNode(Affinity<Object> aff, AtomicInteger key, ClusterNode node) {
+ for (int i = 0; i < 100_000; i++) {
+ Integer next = key.getAndIncrement();
+
+ if (aff.mapKeyToNode(next).equals(node))
+ return next;
+ }
+
+ fail("Failed to find key for node: " + node);
+
+ return null;
+ }
+
+ /**
+ * @param cache Cache.
+ * @param qry Query.
+ * @return Query plan.
+ */
+ protected final String queryPlan(IgniteCache<?, ?> cache, SqlFieldsQuery qry) {
+ return (String)cache.query(new SqlFieldsQuery("explain " + qry.getSql())
+ .setArgs(qry.getArgs())
+ .setLocal(qry.isLocal())
+ .setCollocated(qry.isCollocated())
+ .setPageSize(qry.getPageSize())
+ .setDistributedJoins(qry.isDistributedJoins())
+ .setEnforceJoinOrder(qry.isEnforceJoinOrder()))
+ .getAll().get(0).get(0);
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
----------------------------------------------------------------------
diff --git a/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java b/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
index 29b7dd4..3062d13 100644
--- a/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
+++ b/modules/geospatial/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2SpatialIndex.java
@@ -28,29 +28,31 @@ import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
-import org.h2.engine.Constants;
import org.h2.engine.Session;
import org.h2.index.Cursor;
-import org.h2.index.IndexCondition;
import org.h2.index.IndexType;
import org.h2.index.SingleRowCursor;
import org.h2.index.SpatialIndex;
+import org.h2.index.SpatialTreeIndex;
import org.h2.message.DbException;
import org.h2.mvstore.MVStore;
import org.h2.mvstore.rtree.MVRTreeMap;
import org.h2.mvstore.rtree.SpatialKey;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
-import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.Table;
import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueGeometry;
+import org.jetbrains.annotations.Nullable;
+
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.KEY_COL;
/**
* Spatial index.
*/
+@SuppressWarnings("unused"/*reflection*/)
public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex {
/** */
private final ReadWriteLock lock = new ReentrantReadWriteLock();
@@ -80,12 +82,8 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
* @param tbl Table.
* @param idxName Index name.
* @param cols Columns.
- * @param keyCol Key column.
- * @param valCol Value column.
*/
- public GridH2SpatialIndex(Table tbl, String idxName, IndexColumn[] cols, int keyCol, int valCol) {
- super(keyCol, valCol);
-
+ public GridH2SpatialIndex(Table tbl, String idxName, IndexColumn... cols) {
if (cols.length > 1)
throw DbException.getUnsupportedException("can only do one column");
@@ -121,7 +119,14 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
}
/** {@inheritDoc} */
+ @Nullable @Override protected Object doTakeSnapshot() {
+ return null; // TODO We do not support snapshots, but probably this is possible.
+ }
+
+ /** {@inheritDoc} */
@Override public GridH2Row put(GridH2Row row) {
+ assert row instanceof GridH2AbstractKeyValueRow : "requires key to be at 0";
+
Lock l = lock.writeLock();
l.lock();
@@ -129,7 +134,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
try {
checkClosed();
- Value key = row.getValue(keyCol);
+ Value key = row.getValue(KEY_COL);
assert key != null;
@@ -183,7 +188,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
try {
checkClosed();
- Value key = row.getValue(keyCol);
+ Value key = row.getValue(KEY_COL);
assert key != null;
@@ -208,7 +213,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
}
/** {@inheritDoc} */
- @Override public void close(Session ses) {
+ @Override public void destroy() {
Lock l = lock.writeLock();
l.lock();
@@ -221,37 +226,31 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
finally {
l.unlock();
}
+
+ super.destroy();
}
/** {@inheritDoc} */
- @Override protected long getCostRangeIndex(int[] masks, long rowCnt, TableFilter filter, SortOrder sortOrder) {
- rowCnt += Constants.COST_ROW_OFFSET;
- long cost = rowCnt;
- long rows = rowCnt;
-
- if (masks == null)
- return cost;
-
- for (Column column : columns) {
- int idx = column.getColumnId();
- int mask = masks[idx];
- if ((mask & IndexCondition.SPATIAL_INTERSECTS) != 0) {
- cost = 3 + rows / 4;
-
- break;
- }
- }
-
- return cost;
+ @Override public double getCost(Session ses, int[] masks, TableFilter[] filters, int filter, SortOrder sortOrder) {
+ return SpatialTreeIndex.getCostRangeIndex(masks,
+ table.getRowCountApproximation(), columns) / 10;
}
/** {@inheritDoc} */
- @Override public double getCost(Session ses, int[] masks, TableFilter filter, SortOrder sortOrder) {
- return getCostRangeIndex(masks, rowCnt, filter, sortOrder);
+ @Override public Cursor find(TableFilter filter, SearchRow first, SearchRow last) {
+ return find0(filter);
}
/** {@inheritDoc} */
@Override public Cursor find(Session ses, SearchRow first, SearchRow last) {
+ return find0(null);
+ }
+
+ /**
+ * @param filter Table filter.
+ * @return Cursor.
+ */
+ private Cursor find0(TableFilter filter) {
Lock l = lock.readLock();
l.lock();
@@ -259,7 +258,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
try {
checkClosed();
- return new GridH2Cursor(rowIterator(treeMap.keySet().iterator()));
+ return new GridH2Cursor(rowIterator(treeMap.keySet().iterator(), filter));
}
finally {
l.unlock();
@@ -273,9 +272,10 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
/**
* @param i Spatial key iterator.
+ * @param filter Table filter.
* @return Iterator over rows.
*/
- private Iterator<GridH2Row> rowIterator(Iterator<SpatialKey> i) {
+ private Iterator<GridH2Row> rowIterator(Iterator<SpatialKey> i, TableFilter filter) {
if (!i.hasNext())
return Collections.emptyIterator();
@@ -290,7 +290,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
}
while (i.hasNext());
- return filter(rows.iterator());
+ return filter(rows.iterator(), threadLocalFilter());
}
/** {@inheritDoc} */
@@ -305,7 +305,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
if (!first)
throw DbException.throwInternalError("Spatial Index can only be fetch by ascending order");
- Iterator<GridH2Row> iter = rowIterator(treeMap.keySet().iterator());
+ Iterator<GridH2Row> iter = rowIterator(treeMap.keySet().iterator(), null);
return new SingleRowCursor(iter.hasNext() ? iter.next() : null);
}
@@ -334,7 +334,7 @@ public class GridH2SpatialIndex extends GridH2IndexBase implements SpatialIndex
if (intersection == null)
return find(filter.getSession(), null, null);
- return new GridH2Cursor(rowIterator(treeMap.findIntersectingKeys(getEnvelope(intersection, 0))));
+ return new GridH2Cursor(rowIterator(treeMap.findIntersectingKeys(getEnvelope(intersection, 0)), filter));
}
finally {
l.unlock();
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 0b0fe85..535881e 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
@@ -64,6 +64,7 @@ import org.apache.ignite.cache.query.annotations.QuerySqlFunction;
import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.GridTopic;
import org.apache.ignite.internal.IgniteInternalFuture;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
@@ -74,6 +75,7 @@ import org.apache.ignite.internal.processors.cache.GridCacheAffinityManager;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
+import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
import org.apache.ignite.internal.processors.query.GridQueryFieldsResult;
@@ -82,14 +84,15 @@ 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.GridH2DefaultTableEngine;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOffheap;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2KeyValueRowOnheap;
+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.GridH2RowFactory;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2TreeIndex;
-import org.apache.ignite.internal.processors.query.h2.opt.GridH2Utils;
import org.apache.ignite.internal.processors.query.h2.opt.GridH2ValueCacheObject;
import org.apache.ignite.internal.processors.query.h2.opt.GridLuceneIndex;
import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter;
@@ -100,37 +103,44 @@ 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.lang.GridPlainRunnable;
+import org.apache.ignite.internal.util.lang.IgniteInClosure2X;
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.CU;
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;
import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiClosure;
import org.apache.ignite.lang.IgniteBiPredicate;
import org.apache.ignite.lang.IgniteBiTuple;
import org.apache.ignite.lang.IgniteFuture;
+import org.apache.ignite.lang.IgniteInClosure;
import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.marshaller.jdk.JdkMarshaller;
+import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.resources.LoggerResource;
-import org.apache.ignite.spi.IgniteSpiCloseableIterator;
import org.apache.ignite.spi.indexing.IndexingQueryFilter;
+import org.h2.api.ErrorCode;
import org.h2.api.JavaObjectSerializer;
import org.h2.command.CommandInterface;
-import org.h2.constant.ErrorCode;
-import org.h2.constant.SysProperties;
+import org.h2.engine.Session;
+import org.h2.engine.SysProperties;
import org.h2.index.Index;
import org.h2.index.SpatialIndex;
+import org.h2.jdbc.JdbcConnection;
import org.h2.jdbc.JdbcPreparedStatement;
import org.h2.message.DbException;
import org.h2.mvstore.cache.CacheLongKeyLIRS;
+import org.h2.result.SortOrder;
import org.h2.server.web.WebServer;
import org.h2.table.Column;
import org.h2.table.IndexColumn;
import org.h2.table.Table;
import org.h2.tools.Server;
-import org.h2.util.Utils;
+import org.h2.util.JdbcUtils;
import org.h2.value.DataType;
import org.h2.value.Value;
import org.h2.value.ValueArray;
@@ -149,6 +159,7 @@ import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
import org.h2.value.ValueString;
import org.h2.value.ValueTime;
+import org.h2.value.ValueTimestamp;
import org.h2.value.ValueUuid;
import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
@@ -161,9 +172,8 @@ import static org.apache.ignite.internal.processors.query.GridQueryIndexType.FUL
import static org.apache.ignite.internal.processors.query.GridQueryIndexType.GEO_SPATIAL;
import static org.apache.ignite.internal.processors.query.GridQueryIndexType.SORTED;
import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.KEY_COL;
-import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.VAL_COL;
-import static org.h2.result.SortOrder.ASCENDING;
-import static org.h2.result.SortOrder.DESCENDING;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.LOCAL;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.PREPARE;
/**
* Indexing implementation based on H2 database engine. In this implementation main query language is SQL,
@@ -181,8 +191,10 @@ import static org.h2.result.SortOrder.DESCENDING;
public class IgniteH2Indexing implements GridQueryIndexing {
/** Default DB options. */
private static final String DB_OPTIONS = ";LOCK_MODE=3;MULTI_THREADED=1;DB_CLOSE_ON_EXIT=FALSE" +
- ";DEFAULT_LOCK_TIMEOUT=10000;FUNCTIONS_IN_SCHEMA=true;OPTIMIZE_REUSE_RESULTS=0;QUERY_CACHE_SIZE=0;" +
- "RECOMPILE_ALWAYS=1;MAX_OPERATION_MEMORY=0";
+ ";DEFAULT_LOCK_TIMEOUT=10000;FUNCTIONS_IN_SCHEMA=true;OPTIMIZE_REUSE_RESULTS=0;QUERY_CACHE_SIZE=0" +
+ ";RECOMPILE_ALWAYS=1;MAX_OPERATION_MEMORY=0;NESTED_JOINS=0;BATCH_JOINS=1" +
+ ";ROW_FACTORY=\"" + GridH2RowFactory.class.getName() + "\"" +
+ ";DEFAULT_TABLE_ENGINE=" + GridH2DefaultTableEngine.class.getName();
/** */
private static final int PREPARED_STMT_CACHE_SIZE = 256;
@@ -219,9 +231,12 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* Command in H2 prepared statement.
*/
static {
- try {
- System.setProperty("h2.objectCache", "false");
+ // Initialize system properties for H2.
+ System.setProperty("h2.objectCache", "false");
+ System.setProperty("h2.serializeJavaObject", "false");
+ System.setProperty("h2.objectCacheMaxPerElementSize", "0"); // Avoid ValueJavaObject caching.
+ try {
COMMAND_FIELD = JdbcPreparedStatement.class.getDeclaredField("command");
COMMAND_FIELD.setAccessible(true);
@@ -260,6 +275,9 @@ public class IgniteH2Indexing implements GridQueryIndexing {
private final Map<String, String> space2schema = new ConcurrentHashMap8<>();
/** */
+ private GridSpinBusyLock busyLock;
+
+ /** */
private final ThreadLocal<ConnectionWrapper> connCache = new ThreadLocal<ConnectionWrapper>() {
@Nullable @Override public ConnectionWrapper get() {
ConnectionWrapper c = super.get();
@@ -304,13 +322,35 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** */
private volatile GridKernalContext ctx;
+ /** */
+ private final ConcurrentMap<String, GridH2Table> dataTables = new ConcurrentHashMap8<>();
+
/** Statement cache. */
private final ConcurrentHashMap<Thread, StatementCache> stmtCache = new ConcurrentHashMap<>();
/** */
- private final GridBoundedConcurrentLinkedHashMap<T3<String, String, Boolean>, TwoStepCachedQuery> twoStepCache =
+ private final GridBoundedConcurrentLinkedHashMap<TwoStepCachedQueryKey, TwoStepCachedQuery> twoStepCache =
new GridBoundedConcurrentLinkedHashMap<>(TWO_STEP_QRY_CACHE_SIZE);
+ /** */
+ private final IgniteInClosure<? super IgniteInternalFuture<?>> logger = new IgniteInClosure<IgniteInternalFuture<?>>() {
+ @Override public void apply(IgniteInternalFuture<?> fut) {
+ try {
+ fut.get();
+ }
+ catch (IgniteCheckedException e) {
+ U.error(log, e.getMessage(), e);
+ }
+ }
+ };
+
+ /**
+ * @return Kernal context.
+ */
+ public GridKernalContext kernalContext() {
+ return ctx;
+ }
+
/**
* @param space Space.
* @return Connection.
@@ -695,8 +735,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
U.close(stmt, log);
}
- tbl.tbl.close();
-
if (tbl.luceneIdx != null)
U.closeQuiet(tbl.luceneIdx);
@@ -705,7 +743,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
- @Override public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryText(
+ @Override public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryLocalText(
@Nullable String spaceName, String qry, GridQueryTypeDescriptor type,
IndexingQueryFilter filters) throws IgniteCheckedException {
TableDescriptor tbl = tableDescriptor(spaceName, type);
@@ -727,14 +765,14 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** {@inheritDoc} */
@SuppressWarnings("unchecked")
- @Override public GridQueryFieldsResult queryFields(@Nullable final String spaceName, final String qry,
- @Nullable final Collection<Object> params, final IndexingQueryFilter filters)
+ @Override public GridQueryFieldsResult queryLocalSqlFields(@Nullable final String spaceName, final String qry,
+ @Nullable final Collection<Object> params, final IndexingQueryFilter filters, boolean enforceJoinOrder)
throws IgniteCheckedException {
- setFilters(filters);
+ Connection conn = connectionForSpace(spaceName);
- try {
- Connection conn = connectionForThread(schema(spaceName));
+ initLocalQueryContext(conn, enforceJoinOrder, filters);
+ try {
ResultSet rs = executeSqlQueryWithTimer(spaceName, conn, qry, params, true);
List<GridQueryFieldMetadata> meta = null;
@@ -751,7 +789,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
return new GridQueryFieldsResultAdapter(meta, new FieldsIterator(rs));
}
finally {
- setFilters(null);
+ GridH2QueryContext.clearThreadLocal();
}
}
@@ -897,25 +935,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
- * Executes query.
- *
- * @param space Space.
- * @param qry Query.
- * @param params Query parameters.
- * @param tbl Target table of query to generate select.
- * @return Result set.
- * @throws IgniteCheckedException If failed.
- */
- private ResultSet executeQuery(String space, String qry, @Nullable Collection<Object> params, TableDescriptor tbl)
- throws IgniteCheckedException {
- Connection conn = connectionForThread(tbl.schemaName());
-
- String sql = generateQuery(qry, tbl);
-
- return executeSqlQueryWithTimer(space, conn, sql, params, true);
- }
-
- /**
* Binds parameters to prepared statement.
*
* @param stmt Prepared statement.
@@ -932,43 +951,66 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
- * Executes regular query.
- *
- * @param spaceName Space name.
- * @param qry Query.
- * @param params Query parameters.
- * @param type Query return type.
- * @param filters Space name and key filters.
- * @return Queried rows.
- * @throws IgniteCheckedException If failed.
+ * @param conn Connection.
+ * @param enforceJoinOrder Enforce join order of tables.
+ * @param filter Filter.
*/
+ private void initLocalQueryContext(Connection conn, boolean enforceJoinOrder, IndexingQueryFilter filter) {
+ setupConnection(conn, false, enforceJoinOrder);
+
+ GridH2QueryContext.set(new GridH2QueryContext(nodeId, nodeId, 0, LOCAL).filter(filter).distributedJoins(false));
+ }
+
+ /**
+ * @param conn Connection to use.
+ * @param distributedJoins If distributed joins are enabled.
+ * @param enforceJoinOrder Enforce join order of tables.
+ */
+ public void setupConnection(Connection conn, boolean distributedJoins, boolean enforceJoinOrder) {
+ Session s = session(conn);
+
+ s.setForceJoinOrder(enforceJoinOrder);
+ s.setJoinBatchEnabled(distributedJoins);
+ }
+
+ /** {@inheritDoc} */
@SuppressWarnings("unchecked")
- @Override public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> query(@Nullable String spaceName,
+ @Override public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryLocalSql(@Nullable String spaceName,
final String qry, @Nullable final Collection<Object> params, GridQueryTypeDescriptor type,
- final IndexingQueryFilter filters) throws IgniteCheckedException {
+ final IndexingQueryFilter filter) throws IgniteCheckedException {
final TableDescriptor tbl = tableDescriptor(spaceName, type);
if (tbl == null)
throw new CacheException("Failed to find SQL table for type: " + type.name());
- setFilters(filters);
+ String sql = generateQuery(qry, tbl);
+
+ Connection conn = connectionForThread(tbl.schemaName());
+
+ initLocalQueryContext(conn, false, filter);
try {
- ResultSet rs = executeQuery(spaceName, qry, params, tbl);
+ ResultSet rs = executeSqlQueryWithTimer(spaceName, conn, sql, params, true);
return new KeyValIterator(rs);
}
finally {
- setFilters(null);
+ GridH2QueryContext.clearThreadLocal();
}
}
- /** {@inheritDoc} */
- @Override public Iterable<List<?>> queryTwoStep(final GridCacheContext<?,?> cctx, final GridCacheTwoStepQuery qry,
- final boolean keepCacheObj) {
+ /**
+ * @param cctx Cache context.
+ * @param qry Query.
+ * @param keepCacheObj Flag to keep cache object.
+ * @param enforceJoinOrder Enforce join order of tables.
+ * @return Iterable result.
+ */
+ private Iterable<List<?>> runQueryTwoStep(final GridCacheContext<?,?> cctx, final GridCacheTwoStepQuery qry,
+ final boolean keepCacheObj, final boolean enforceJoinOrder) {
return new Iterable<List<?>>() {
@Override public Iterator<List<?>> iterator() {
- return rdcQryExec.query(cctx, qry, keepCacheObj);
+ return rdcQryExec.query(cctx, qry, keepCacheObj, enforceJoinOrder);
}
};
}
@@ -997,6 +1039,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
fqry.setArgs(qry.getArgs());
fqry.setPageSize(qry.getPageSize());
+ fqry.setDistributedJoins(qry.isDistributedJoins());
final QueryCursor<List<?>> res = queryTwoStep(cctx, fqry);
@@ -1030,6 +1073,14 @@ public class IgniteH2Indexing implements GridQueryIndexing {
};
}
+ /**
+ * @param c Connection.
+ * @return Session.
+ */
+ public static Session session(Connection c) {
+ return (Session)((JdbcConnection)c).getSession();
+ }
+
/** {@inheritDoc} */
@Override public QueryCursor<List<?>> queryTwoStep(GridCacheContext<?,?> cctx, SqlFieldsQuery qry) {
final String space = cctx.name();
@@ -1037,10 +1088,15 @@ public class IgniteH2Indexing implements GridQueryIndexing {
Connection c = connectionForSpace(space);
+ final boolean enforceJoinOrder = qry.isEnforceJoinOrder();
+ final boolean distributedJoins = qry.isDistributedJoins() && cctx.isPartitioned();
+ final boolean grpByCollocated = qry.isCollocated();
+
GridCacheTwoStepQuery twoStepQry;
List<GridQueryFieldMetadata> meta;
- final T3<String, String, Boolean> cachedQryKey = new T3<>(space, sqlQry, qry.isCollocated());
+ final TwoStepCachedQueryKey cachedQryKey = new TwoStepCachedQueryKey(space, sqlQry, grpByCollocated,
+ distributedJoins, enforceJoinOrder);
TwoStepCachedQuery cachedQry = twoStepCache.get(cachedQryKey);
if (cachedQry != null) {
@@ -1048,51 +1104,95 @@ public class IgniteH2Indexing implements GridQueryIndexing {
meta = cachedQry.meta;
}
else {
+ final UUID locNodeId = ctx.localNodeId();
+
+ setupConnection(c, distributedJoins, enforceJoinOrder);
+
+ GridH2QueryContext.set(new GridH2QueryContext(locNodeId, locNodeId, 0, PREPARE)
+ .distributedJoins(distributedJoins));
+
PreparedStatement stmt;
boolean cachesCreated = false;
- while (true) {
- try {
- // Do not cache this statement because the whole two step query object will be cached later on.
- stmt = prepareStatement(c, sqlQry, false);
+ try {
+ while (true) {
+ try {
+ // Do not cache this statement because the whole two step query object will be cached later on.
+ stmt = prepareStatement(c, sqlQry, false);
- break;
- }
- catch (SQLException e) {
- if (!cachesCreated && e.getErrorCode() == ErrorCode.SCHEMA_NOT_FOUND_1) {
- try {
- ctx.cache().createMissingCaches();
- }
- catch (IgniteCheckedException e1) {
- throw new CacheException("Failed to create missing caches.", e);
- }
+ break;
+ }
+ catch (SQLException e) {
+ if (!cachesCreated && e.getErrorCode() == ErrorCode.SCHEMA_NOT_FOUND_1) {
+ try {
+ ctx.cache().createMissingCaches();
+ }
+ catch (IgniteCheckedException e1) {
+ throw new CacheException("Failed to create missing caches.", e);
+ }
- cachesCreated = true;
+ cachesCreated = true;
+ }
+ else
+ throw new CacheException("Failed to parse query: " + sqlQry, e);
}
- else
- throw new CacheException("Failed to parse query: " + sqlQry, e);
}
}
+ finally {
+ GridH2QueryContext.clearThreadLocal();
+ }
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);
- }
+ bindParameters(stmt, F.asList(qry.getArgs()));
- try {
- twoStepQry = GridSqlQuerySplitter.split(
- (JdbcPreparedStatement)stmt, qry.getArgs(), qry.isCollocated(), this);
+ twoStepQry = GridSqlQuerySplitter.split((JdbcPreparedStatement)stmt, qry.getArgs(), grpByCollocated,
+ distributedJoins);
- meta = meta(stmt.getMetaData());
+ List<Integer> caches;
+ List<Integer> extraCaches = null;
+
+ // Setup spaces from schemas.
+ if (!twoStepQry.schemas().isEmpty()) {
+ Collection<String> spaces = new ArrayList<>(twoStepQry.schemas().size());
+ caches = new ArrayList<>(twoStepQry.schemas().size() + 1);
+ caches.add(cctx.cacheId());
+
+ for (String schema : twoStepQry.schemas()) {
+ String space0 = space(schema);
+
+ spaces.add(space0);
+
+ if (!F.eq(space0, space)) {
+ int cacheId = CU.cacheId(space0);
+
+ caches.add(cacheId);
+
+ if (extraCaches == null)
+ extraCaches = new ArrayList<>();
+
+ extraCaches.add(cacheId);
+ }
+ }
+
+ twoStepQry.spaces(spaces);
}
- catch (SQLException e) {
- throw new CacheException(e);
+ else {
+ caches = Collections.singletonList(cctx.cacheId());
+ extraCaches = null;
}
+
+ twoStepQry.caches(caches);
+ twoStepQry.extraCaches(extraCaches);
+
+ meta = meta(stmt.getMetaData());
+ }
+ catch (IgniteCheckedException e) {
+ throw new CacheException("Failed to bind parameters: [qry=" + sqlQry + ", params=" +
+ Arrays.deepToString(qry.getArgs()) + "]", e);
+ }
+ catch (SQLException e) {
+ throw new CacheException(e);
}
finally {
U.close(stmt, log);
@@ -1104,7 +1204,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
twoStepQry.pageSize(qry.getPageSize());
- QueryCursorImpl<List<?>> cursor = new QueryCursorImpl<>(queryTwoStep(cctx, twoStepQry, cctx.keepBinary()));
+ QueryCursorImpl<List<?>> cursor = new QueryCursorImpl<>(
+ runQueryTwoStep(cctx, twoStepQry, cctx.keepBinary(), enforceJoinOrder));
cursor.fieldsMeta(meta);
@@ -1117,17 +1218,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
- * Sets filters for current thread. Must be set to not null value
- * before executeQuery and reset to null after in finally block since it signals
- * to table that it should return content without expired values.
- *
- * @param filters Filters.
- */
- public void setFilters(@Nullable IndexingQueryFilter filters) {
- GridH2IndexBase.setFiltersForThread(filters);
- }
-
- /**
* Prepares statement for query.
*
* @param qry Query string.
@@ -1331,7 +1421,18 @@ public class IgniteH2Indexing implements GridQueryIndexing {
GridH2RowDescriptor desc = new RowDescriptor(tbl.type(), schema);
- GridH2Table.Engine.createTable(conn, sql.toString(), desc, tbl, tbl.schema.spaceName);
+ GridH2Table res = GridH2Table.Engine.createTable(conn, sql.toString(), desc, tbl, tbl.schema.spaceName);
+
+ if (dataTables.putIfAbsent(res.identifier(), res) != null)
+ throw new IllegalStateException("Table already exists: " + res.identifier());
+ }
+
+ /**
+ * @param identifier Table identifier.
+ * @return Data table.
+ */
+ public GridH2Table dataTable(String identifier) {
+ return dataTables.get(identifier);
}
/**
@@ -1447,18 +1548,43 @@ public class IgniteH2Indexing implements GridQueryIndexing {
tbl.tbl.rebuildIndexes();
}
- /** {@inheritDoc} */
- @Override public long size(@Nullable String spaceName, GridQueryTypeDescriptor type,
- IndexingQueryFilter filters) throws IgniteCheckedException {
+ /**
+ * Gets size (for tests only).
+ *
+ * @param spaceName Space name.
+ * @param type Type descriptor.
+ * @return Size.
+ * @throws IgniteCheckedException If failed or {@code -1} if the type is unknown.
+ */
+ long size(@Nullable String spaceName, GridQueryTypeDescriptor type) throws IgniteCheckedException {
TableDescriptor tbl = tableDescriptor(spaceName, type);
if (tbl == null)
return -1;
- IgniteSpiCloseableIterator<List<?>> iter = queryFields(spaceName,
- "SELECT COUNT(*) FROM " + tbl.fullTableName(), null, null).iterator();
+ Connection conn = connectionForSpace(spaceName);
+
+ setupConnection(conn, false, false);
+
+ ResultSet rs = executeSqlQuery(conn,
+ "SELECT COUNT(*) FROM " + tbl.fullTableName(), null, false);
+
+ try {
+ if (!rs.next())
+ throw new IllegalStateException();
- return ((Number)iter.next().get(0)).longValue();
+ return rs.getLong(1);
+ }
+ catch (SQLException e) {
+ throw new IgniteCheckedException(e);
+ }
+ }
+
+ /**
+ * @return Busy lock.
+ */
+ public GridSpinBusyLock busyLock() {
+ return busyLock;
}
/**
@@ -1481,8 +1607,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
if (log.isDebugEnabled())
log.debug("Starting cache query index...");
- System.setProperty("h2.serializeJavaObject", "false");
- System.setProperty("h2.objectCacheMaxPerElementSize", "0"); // Avoid ValueJavaObject caching.
+ this.busyLock = busyLock;
if (SysProperties.serializeJavaObject) {
U.warn(log, "Serialization of Java objects in H2 was enabled.");
@@ -1490,10 +1615,10 @@ public class IgniteH2Indexing implements GridQueryIndexing {
SysProperties.serializeJavaObject = false;
}
- if (Utils.serializer != null)
+ if (JdbcUtils.serializer != null)
U.warn(log, "Custom H2 serialization is already configured, will override.");
- Utils.serializer = h2Serializer();
+ JdbcUtils.serializer = h2Serializer();
String dbName = (ctx != null ? ctx.localNodeId() : UUID.randomUUID()).toString();
@@ -1522,8 +1647,11 @@ public class IgniteH2Indexing implements GridQueryIndexing {
throw new IgniteCheckedException(e);
}
- if (ctx == null) // This is allowed in some tests.
+ if (ctx == null) {
+ // This is allowed in some tests.
+ nodeId = UUID.randomUUID();
marshaller = new JdkMarshaller();
+ }
else {
this.ctx = ctx;
@@ -1548,9 +1676,92 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
+ * @param topic Topic.
+ * @param topicOrd Topic ordinal for {@link GridTopic}.
+ * @param nodes Nodes.
+ * @param msg Message.
+ * @param specialize Optional closure to specialize message for each node.
+ * @param locNodeHnd Handler for local node.
+ * @param plc Policy identifying the executor service which will process message.
+ * @param runLocParallel Run local handler in parallel thread.
+ * @return {@code true} If all messages sent successfully.
+ */
+ public boolean send(
+ Object topic,
+ int topicOrd,
+ Collection<ClusterNode> nodes,
+ Message msg,
+ @Nullable IgniteBiClosure<ClusterNode, Message, Message> specialize,
+ @Nullable final IgniteInClosure2X<ClusterNode, Message> locNodeHnd,
+ byte plc,
+ boolean runLocParallel
+ ) {
+ boolean ok = true;
+
+ if (specialize == null && msg instanceof GridCacheQueryMarshallable)
+ ((GridCacheQueryMarshallable)msg).marshall(marshaller);
+
+ ClusterNode locNode = null;
+
+ for (ClusterNode node : nodes) {
+ if (node.isLocal()) {
+ locNode = node;
+
+ continue;
+ }
+
+ try {
+ if (specialize != null) {
+ msg = specialize.apply(node, msg);
+
+ if (msg instanceof GridCacheQueryMarshallable)
+ ((GridCacheQueryMarshallable)msg).marshall(marshaller);
+ }
+
+ ctx.io().send(node, topic, topicOrd, msg, plc);
+ }
+ catch (IgniteCheckedException e) {
+ ok = false;
+
+ U.warn(log, "Failed to send message [node=" + node + ", msg=" + msg +
+ ", errMsg=" + e.getMessage() + "]");
+ }
+ }
+
+ // Local node goes the last to allow parallel execution.
+ if (locNode != null) {
+ if (specialize != null)
+ msg = specialize.apply(locNode, msg);
+
+ if (runLocParallel) {
+ final ClusterNode finalLocNode = locNode;
+ final Message finalMsg = msg;
+
+ try {
+ // We prefer runLocal to runLocalSafe, because the latter can produce deadlock here.
+ ctx.closure().runLocal(new GridPlainRunnable() {
+ @Override public void run() {
+ locNodeHnd.apply(finalLocNode, finalMsg);
+ }
+ }, plc).listen(logger);
+ }
+ catch (IgniteCheckedException e) {
+ ok = false;
+
+ U.error(log, "Failed to execute query locally.", e);
+ }
+ }
+ else
+ locNodeHnd.apply(locNode, msg);
+ }
+
+ return ok;
+ }
+
+ /**
* @return Serializer.
*/
- protected JavaObjectSerializer h2Serializer() {
+ private JavaObjectSerializer h2Serializer() {
return new JavaObjectSerializer() {
@Override public byte[] serialize(Object obj) throws Exception {
return marshaller.marshal(obj);
@@ -1607,8 +1818,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
for (Schema schema : schemas.values()) {
for (TableDescriptor desc : schema.tbls.values()) {
- desc.tbl.close();
-
if (desc.luceneIdx != null)
U.closeQuiet(desc.luceneIdx);
}
@@ -1632,18 +1841,19 @@ public class IgniteH2Indexing implements GridQueryIndexing {
if (stmtCacheCleanupTask != null)
stmtCacheCleanupTask.close();
+ GridH2QueryContext.clearLocalNodeStop(nodeId);
+
if (log.isDebugEnabled())
log.debug("Cache query index stopped.");
}
/** {@inheritDoc} */
- @Override public void registerCache(CacheConfiguration<?,?> ccfg) throws IgniteCheckedException {
+ @Override public void registerCache(GridCacheContext<?, ?> cctx, CacheConfiguration<?,?> ccfg)
+ throws IgniteCheckedException {
String schema = schemaNameFromCacheConf(ccfg);
- if (schemas.putIfAbsent(schema, new Schema(ccfg.getName(), schema,
- ccfg.getOffHeapMaxMemory() >= 0 || ccfg.getMemoryMode() == CacheMemoryMode.OFFHEAP_TIERED ?
- new GridUnsafeMemory(0) : null, ccfg)) != null)
- throw new IgniteCheckedException("Schema for cache already registered: " + U.maskName(ccfg.getName()));
+ if (schemas.putIfAbsent(schema, new Schema(ccfg.getName(), schema, cctx, ccfg)) != null)
+ throw new IgniteCheckedException("Cache already registered: " + U.maskName(ccfg.getName()));
space2schema.put(emptyIfNull(ccfg.getName()), schema);
@@ -1661,6 +1871,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
space2schema.remove(emptyIfNull(rmv.spaceName));
mapQryExec.onCacheStop(ccfg.getName());
+ rmv.onDrop();
+
try {
dropSchema(schema);
}
@@ -1668,11 +1880,11 @@ public class IgniteH2Indexing implements GridQueryIndexing {
U.error(log, "Failed to drop schema on cache stop (will ignore): " + U.maskName(ccfg.getName()), e);
}
- for (Iterator<Map.Entry<T3<String, String, Boolean>, TwoStepCachedQuery>> it = twoStepCache.entrySet().iterator();
+ for (Iterator<Map.Entry<TwoStepCachedQueryKey, TwoStepCachedQuery>> it = twoStepCache.entrySet().iterator();
it.hasNext();) {
- Map.Entry<T3<String, String, Boolean>, TwoStepCachedQuery> e = it.next();
+ Map.Entry<TwoStepCachedQueryKey, TwoStepCachedQuery> e = it.next();
- if (F.eq(e.getKey().get1(), ccfg.getName()))
+ if (F.eq(e.getKey().space, ccfg.getName()))
it.remove();
}
}
@@ -1680,7 +1892,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/** {@inheritDoc} */
@Override public IndexingQueryFilter backupFilter(
- @Nullable final List<String> caches,
@Nullable final AffinityTopologyVersion topVer,
@Nullable final int[] parts
) {
@@ -1735,6 +1946,10 @@ public class IgniteH2Indexing implements GridQueryIndexing {
@Override public boolean isValueRequired() {
return false;
}
+
+ @Override public String toString() {
+ return "IndexingQueryFilter [ver=" + topVer + ']';
+ }
};
}
@@ -1762,6 +1977,81 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
+ * Key for cached two-step query.
+ */
+ private static final class TwoStepCachedQueryKey {
+ /** */
+ private final String space;
+
+ /** */
+ private final String sql;
+
+ /** */
+ private final boolean grpByCollocated;
+
+ /** */
+ private final boolean distributedJoins;
+
+ /** */
+ private final boolean enforceJoinOrder;
+
+ /**
+ * @param space Space.
+ * @param sql Sql.
+ * @param grpByCollocated Collocated GROUP BY.
+ * @param distributedJoins Distributed joins enabled.
+ * @param enforceJoinOrder Enforce join order of tables.
+ */
+ private TwoStepCachedQueryKey(String space,
+ String sql,
+ boolean grpByCollocated,
+ boolean distributedJoins,
+ boolean enforceJoinOrder) {
+ this.space = space;
+ this.sql = sql;
+ this.grpByCollocated = grpByCollocated;
+ this.distributedJoins = distributedJoins;
+ this.enforceJoinOrder = enforceJoinOrder;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TwoStepCachedQueryKey that = (TwoStepCachedQueryKey)o;
+
+ if (grpByCollocated != that.grpByCollocated)
+ return false;
+
+ if (distributedJoins != that.distributedJoins)
+ return false;
+
+ if (enforceJoinOrder != that.enforceJoinOrder)
+ return false;
+
+ if (space != null ? !space.equals(that.space) : that.space != null)
+ return false;
+
+ return sql.equals(that.sql);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int res = space != null ? space.hashCode() : 0;
+ res = 31 * res + sql.hashCode();
+ res = 31 * res + (grpByCollocated ? 1 : 0);
+ res = 31 * res + (distributedJoins ? 1 : 0);
+ res = 31 * res + (enforceJoinOrder ? 1 : 0);
+
+ return res;
+ }
+ }
+
+ /**
* Cached two-step query.
*/
private static final class TwoStepCachedQuery {
@@ -1787,6 +2077,47 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
+ * @param c1 First column.
+ * @param c2 Second column.
+ * @return {@code true} If they are the same.
+ */
+ private static boolean equal(IndexColumn c1, IndexColumn c2) {
+ return c1.column.getColumnId() == c2.column.getColumnId();
+ }
+
+ /**
+ * @param cols Columns list.
+ * @param col Column to find.
+ * @return {@code true} If found.
+ */
+ private static boolean containsColumn(List<IndexColumn> cols, IndexColumn col) {
+ for (int i = cols.size() - 1; i >= 0; i--) {
+ if (equal(cols.get(i), col))
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param cols Columns list.
+ * @param keyCol Primary key column.
+ * @param affCol Affinity key column.
+ * @return The same list back.
+ */
+ private static List<IndexColumn> treeIndexColumns(List<IndexColumn> cols, IndexColumn keyCol, IndexColumn affCol) {
+ assert keyCol != null;
+
+ if (!containsColumn(cols, keyCol))
+ cols.add(keyCol);
+
+ if (affCol != null && !containsColumn(cols, affCol))
+ cols.add(affCol);
+
+ return cols;
+ }
+
+ /**
* Wrapper to store connection and flag is schema set or not.
*/
private static class ConnectionWrapper {
@@ -2033,7 +2364,15 @@ public class IgniteH2Indexing implements GridQueryIndexing {
ArrayList<Index> idxs = new ArrayList<>();
- idxs.add(new GridH2TreeIndex("_key_PK", tbl, true, KEY_COL, VAL_COL, tbl.indexColumn(0, ASCENDING)));
+ IndexColumn keyCol = tbl.indexColumn(KEY_COL, SortOrder.ASCENDING);
+ IndexColumn affCol = tbl.getAffinityKeyColumn();
+
+ if (affCol != null && equal(affCol, keyCol))
+ affCol = null;
+
+ // Add primary key index.
+ idxs.add(new GridH2TreeIndex("_key_PK", tbl, true,
+ treeIndexColumns(new ArrayList<IndexColumn>(2), keyCol, affCol)));
if (type().valueClass() == String.class) {
try {
@@ -2044,6 +2383,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
}
+ boolean affIdxFound = false;
+
for (Map.Entry<String, GridQueryIndexDescriptor> e : type.indexes().entrySet()) {
String name = e.getKey();
GridQueryIndexDescriptor idx = e.getValue();
@@ -2057,30 +2398,40 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
}
else {
- IndexColumn[] cols = new IndexColumn[idx.fields().size()];
-
- int i = 0;
+ List<IndexColumn> cols = new ArrayList<>(idx.fields().size() + 2);
boolean escapeAll = schema.escapeAll();
for (String field : idx.fields()) {
- // H2 reserved keywords used as column name is case sensitive.
String fieldName = escapeAll ? field : escapeName(field, false).toUpperCase();
Column col = tbl.getColumn(fieldName);
- cols[i++] = tbl.indexColumn(col.getColumnId(), idx.descending(field) ? DESCENDING : ASCENDING);
+ cols.add(tbl.indexColumn(col.getColumnId(),
+ idx.descending(field) ? SortOrder.DESCENDING : SortOrder.ASCENDING));
}
- if (idx.type() == SORTED)
- idxs.add(new GridH2TreeIndex(name, tbl, false, KEY_COL, VAL_COL, cols));
+ if (idx.type() == SORTED) {
+ // We don't care about number of fields in affinity index, just affinity key must be the first.
+ affIdxFound |= affCol != null && equal(cols.get(0), affCol);
+
+ cols = treeIndexColumns(cols, keyCol, affCol);
+
+ idxs.add(new GridH2TreeIndex(name, tbl, false, cols));
+ }
else if (idx.type() == GEO_SPATIAL)
- idxs.add(createH2SpatialIndex(tbl, name, cols, KEY_COL, VAL_COL));
+ idxs.add(createH2SpatialIndex(tbl, name, cols.toArray(new IndexColumn[cols.size()])));
else
- throw new IllegalStateException();
+ throw new IllegalStateException("Index type: " + idx.type());
}
}
+ // Add explicit affinity key index if nothing alike was found.
+ if (affCol != null && !affIdxFound) {
+ idxs.add(new GridH2TreeIndex("AFFINITY_KEY", tbl, false,
+ treeIndexColumns(new ArrayList<IndexColumn>(2), affCol, keyCol)));
+ }
+
return idxs;
}
@@ -2088,15 +2439,11 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* @param tbl Table.
* @param idxName Index name.
* @param cols Columns.
- * @param keyCol Key column.
- * @param valCol Value column.
*/
private SpatialIndex createH2SpatialIndex(
Table tbl,
String idxName,
- IndexColumn[] cols,
- int keyCol,
- int valCol
+ IndexColumn[] cols
) {
String className = "org.apache.ignite.internal.processors.query.h2.opt.GridH2SpatialIndex";
@@ -2106,14 +2453,12 @@ public class IgniteH2Indexing implements GridQueryIndexing {
Constructor<?> ctor = cls.getConstructor(
Table.class,
String.class,
- IndexColumn[].class,
- int.class,
- int.class);
+ IndexColumn[].class);
if (!ctor.isAccessible())
ctor.setAccessible(true);
- return (SpatialIndex)ctor.newInstance(tbl, idxName, cols, keyCol, valCol);
+ return (SpatialIndex)ctor.newInstance(tbl, idxName, cols);
}
catch (Exception e) {
throw new IgniteException("Failed to instantiate: " + className, e);
@@ -2162,6 +2507,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/** {@inheritDoc} */
+ @SuppressWarnings("unchecked")
@Override protected IgniteBiTuple<K, V> createRow() {
K key = (K)row[0];
V val = (V)row[1];
@@ -2256,10 +2602,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
/**
* Database schema object.
*/
- private static class Schema {
- /** */
- private static final long serialVersionUID = 0L;
-
+ private class Schema {
/** */
private final String spaceName;
@@ -2276,23 +2619,33 @@ public class IgniteH2Indexing implements GridQueryIndexing {
private final CacheLongKeyLIRS<GridH2KeyValueRowOffheap> rowCache;
/** */
+ private final GridCacheContext<?,?> cctx;
+
+ /** */
private final CacheConfiguration<?,?> ccfg;
/**
* @param spaceName Space name.
* @param schemaName Schema name.
- * @param offheap Offheap memory.
+ * @param cctx Cache context.
* @param ccfg Cache configuration.
*/
- private Schema(@Nullable String spaceName, String schemaName, GridUnsafeMemory offheap, CacheConfiguration<?,?> ccfg) {
+ private Schema(String spaceName, String schemaName, GridCacheContext<?,?> cctx, CacheConfiguration<?,?> ccfg) {
this.spaceName = spaceName;
+ this.cctx = cctx;
this.schemaName = schemaName;
- this.offheap = offheap;
this.ccfg = ccfg;
- if (offheap != null)
- rowCache = new CacheLongKeyLIRS<>(ccfg.getSqlOnheapRowCacheSize(), 1, 128, 256);
- else
+ offheap = ccfg.getOffHeapMaxMemory() >= 0 || ccfg.getMemoryMode() == CacheMemoryMode.OFFHEAP_TIERED ?
+ new GridUnsafeMemory(0) : null;
+
+ if (offheap != null) {
+ CacheLongKeyLIRS.Config lirsCfg = new CacheLongKeyLIRS.Config();
+
+ lirsCfg.maxMemory = ccfg.getSqlOnheapRowCacheSize();
+
+ rowCache = new CacheLongKeyLIRS<>(lirsCfg);
+ } else
rowCache = null;
}
@@ -2310,6 +2663,19 @@ public class IgniteH2Indexing implements GridQueryIndexing {
public boolean escapeAll() {
return ccfg.isSqlEscapeAll();
}
+
+ /**
+ * Called after the schema was dropped.
+ */
+ public void onDrop() {
+ for (TableDescriptor tblDesc : tbls.values()) {
+ GridH2Table tbl = tblDesc.tbl;
+
+ dataTables.remove(tbl.identifier(), tbl);
+
+ tbl.destroy();
+ }
+ }
}
/**
@@ -2390,6 +2756,26 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/** {@inheritDoc} */
+ @Override public IgniteH2Indexing indexing() {
+ return IgniteH2Indexing.this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridQueryTypeDescriptor type() {
+ return type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridCacheContext<?,?> context() {
+ return schema.cctx;
+ }
+
+ /** {@inheritDoc} */
+ @Override public CacheConfiguration configuration() {
+ return schema.ccfg;
+ }
+
+ /** {@inheritDoc} */
@Override public GridUnsafeGuard guard() {
return guard;
}
@@ -2414,11 +2800,6 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/** {@inheritDoc} */
- @Override public IgniteH2Indexing owner() {
- return IgniteH2Indexing.this;
- }
-
- /** {@inheritDoc} */
@Override public Value wrap(Object obj, int type) throws IgniteCheckedException {
assert obj != null;
@@ -2457,7 +2838,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
if (obj instanceof java.util.Date && !(obj instanceof Timestamp))
obj = new Timestamp(((java.util.Date) obj).getTime());
- return GridH2Utils.toValueTimestamp((Timestamp)obj);
+ return ValueTimestamp.get((Timestamp)obj);
case Value.DECIMAL:
return ValueDecimal.get((BigDecimal)obj);
case Value.STRING:
@@ -2491,7 +2872,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
throws IgniteCheckedException {
try {
if (val == null) // Only can happen for remove operation, can create simple search row.
- return new GridH2Row(wrap(key, keyType), null);
+ return GridH2RowFactory.create(wrap(key, keyType));
return schema.offheap == null ?
new GridH2KeyValueRowOnheap(this, key, keyType, val, valType, expirationTime) :
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java
index fe6851d..284f8c5 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2AbstractKeyValueRow.java
@@ -55,6 +55,15 @@ public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
protected long expirationTime;
+ /** */
+ private Value key;
+
+ /** */
+ private volatile Value val;
+
+ /** */
+ private Value[] valCache;
+
/**
* Constructor.
*
@@ -68,8 +77,6 @@ public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
*/
protected GridH2AbstractKeyValueRow(GridH2RowDescriptor desc, Object key, int keyType, @Nullable Object val,
int valType, long expirationTime) throws IgniteCheckedException {
- super(null, null);
-
setValue(KEY_COL, desc.wrap(key, keyType));
if (val != null) // We remove by key only, so value can be null here.
@@ -79,14 +86,17 @@ public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
this.expirationTime = expirationTime;
}
+ /** {@inheritDoc} */
+ @Override public Value[] getValueList() {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Protected constructor for {@link GridH2KeyValueRowOffheap}
*
* @param desc Row descriptor.
*/
protected GridH2AbstractKeyValueRow(GridH2RowDescriptor desc) {
- super(new Value[DEFAULT_COLUMNS_COUNT]);
-
this.desc = desc;
}
@@ -184,11 +194,20 @@ public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
* @return Value if exists.
*/
protected final Value peekValue(int col) {
- return getValueList()[col];
+ return col == KEY_COL ? key : val;
}
/** {@inheritDoc} */
@Override public Value getValue(int col) {
+ Value[] vCache = valCache;
+
+ if (vCache != null) {
+ Value v = vCache[col];
+
+ if (v != null)
+ return v;
+ }
+
if (col < DEFAULT_COLUMNS_COUNT) {
Value v;
@@ -288,15 +307,35 @@ public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
Object res = desc.columnValue(key.getObject(), val.getObject(), col);
- if (res == null)
- return ValueNull.INSTANCE;
+ Value v;
- try {
- return desc.wrap(res, desc.fieldType(col));
+ if (res == null)
+ v = ValueNull.INSTANCE;
+ else {
+ try {
+ v = desc.wrap(res, desc.fieldType(col));
+ }
+ catch (IgniteCheckedException e) {
+ throw DbException.convert(e);
+ }
}
- catch (IgniteCheckedException e) {
- throw DbException.convert(e);
+
+ if (vCache != null)
+ vCache[col + DEFAULT_COLUMNS_COUNT] = v;
+
+ return v;
+ }
+
+ /**
+ * @param valCache Value cache.
+ */
+ public void valuesCache(Value[] valCache) {
+ if (valCache != null) {
+ valCache[KEY_COL] = key;
+ valCache[VAL_COL] = val;
}
+
+ this.valCache = valCache;
}
/**
@@ -467,6 +506,17 @@ public abstract class GridH2AbstractKeyValueRow extends GridH2Row {
}
/** {@inheritDoc} */
+ @Override public void setValue(int idx, Value v) {
+ if (idx == VAL_COL)
+ val = v;
+ else {
+ assert idx == KEY_COL : idx + " " + v;
+
+ key = v;
+ }
+ }
+
+ /** {@inheritDoc} */
@Override public final int hashCode() {
throw new IllegalStateException();
}
[13/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java
index 38e3839..8d31651 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java
@@ -119,7 +119,7 @@ public enum GridSqlOperationType {
/** {@inheritDoc} */
@Override public String getSql(GridSqlOperation operation) {
- assert operation.opType().childrenCnt == 2;
+ assert operation.operationType().childrenCnt == 2;
return '(' + operation.child(0).getSQL() + " " + delim + " " + operation.child(1).getSQL() + ')';
}
@@ -132,7 +132,7 @@ public enum GridSqlOperationType {
/** {@inheritDoc} */
@Override public String getSql(GridSqlOperation operation) {
- assert operation.opType().childrenCnt == 2;
+ assert operation.operationType().childrenCnt == 2;
return "(INTERSECTS(" + operation.child(0).getSQL() + ", " + operation.child(1).getSQL() + "))";
}
@@ -154,7 +154,7 @@ public enum GridSqlOperationType {
/** {@inheritDoc} */
@Override public String getSql(GridSqlOperation operation) {
- assert operation.opType().childrenCnt == 1;
+ assert operation.operationType().childrenCnt == 1;
return '(' + text + ' ' + operation.child().getSQL() + ')';
}
@@ -176,7 +176,7 @@ public enum GridSqlOperationType {
/** {@inheritDoc} */
@Override public String getSql(GridSqlOperation operation) {
- assert operation.opType().childrenCnt == 1;
+ assert operation.operationType().childrenCnt == 1;
return '(' + operation.child().getSQL() + ' ' + text + ')';
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 7001717..a7451c1 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
@@ -21,8 +21,10 @@ import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.IdentityHashMap;
import java.util.List;
+import javax.cache.CacheException;
import org.apache.ignite.IgniteException;
import org.h2.command.Command;
+import org.h2.command.CommandContainer;
import org.h2.command.Prepared;
import org.h2.command.dml.Explain;
import org.h2.command.dml.Query;
@@ -48,6 +50,8 @@ import org.h2.expression.Parameter;
import org.h2.expression.Subquery;
import org.h2.expression.TableFunction;
import org.h2.expression.ValueExpression;
+import org.h2.index.Index;
+import org.h2.index.ViewIndex;
import org.h2.jdbc.JdbcPreparedStatement;
import org.h2.result.SortOrder;
import org.h2.table.Column;
@@ -91,14 +95,16 @@ import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlType.fro
@SuppressWarnings("TypeMayBeWeakened")
public class GridSqlQueryParser {
/** */
- private static final GridSqlOperationType[] OPERATION_OP_TYPES = new GridSqlOperationType[] {CONCAT, PLUS, MINUS, MULTIPLY, DIVIDE, null, MODULUS};
+ private static final GridSqlOperationType[] OPERATION_OP_TYPES =
+ {CONCAT, PLUS, MINUS, MULTIPLY, DIVIDE, null, MODULUS};
/** */
- private static final GridSqlOperationType[] COMPARISON_TYPES = new GridSqlOperationType[] {
- EQUAL, BIGGER_EQUAL, BIGGER, SMALLER_EQUAL,
+ private static final GridSqlOperationType[] COMPARISON_TYPES =
+ {EQUAL, BIGGER_EQUAL, BIGGER, SMALLER_EQUAL,
SMALLER, NOT_EQUAL, IS_NULL, IS_NOT_NULL,
- null, null, null, SPATIAL_INTERSECTS /* 11 */, null, null, null, null, EQUAL_NULL_SAFE /* 16 */, null, null, null, null,
- NOT_EQUAL_NULL_SAFE /* 21 */};
+ null, null, null, SPATIAL_INTERSECTS /* 11 */,
+ null, null, null, null, EQUAL_NULL_SAFE /* 16 */,
+ null, null, null, null, NOT_EQUAL_NULL_SAFE /* 21 */};
/** */
private static final Getter<Select, Expression> CONDITION = getter(Select.class, "condition");
@@ -134,7 +140,7 @@ public class GridSqlQueryParser {
private static final Getter<ConditionAndOr, Expression> ANDOR_RIGHT = getter(ConditionAndOr.class, "right");
/** */
- private static final Getter<TableView, Query> VIEW_QUERY = getter(TableView.class, "viewQuery");
+ public static final Getter<TableView, Query> VIEW_QUERY = getter(TableView.class, "viewQuery");
/** */
private static final Getter<TableFilter, String> ALIAS = getter(TableFilter.class, "alias");
@@ -218,7 +224,8 @@ public class GridSqlQueryParser {
private static final Getter<Explain, Prepared> EXPLAIN_COMMAND = getter(Explain.class, "command");
/** */
- private static volatile Getter<Command, Prepared> prepared;
+ private static final Getter<Command, Prepared> PREPARED =
+ GridSqlQueryParser.<Command, Prepared>getter(CommandContainer.class, "prepared");
/** */
private final IdentityHashMap<Object, Object> h2ObjToGridObj = new IdentityHashMap<>();
@@ -227,22 +234,12 @@ public class GridSqlQueryParser {
* @param stmt Prepared statement.
* @return Parsed select.
*/
- public static GridSqlQuery parse(JdbcPreparedStatement stmt) {
+ public static Prepared prepared(JdbcPreparedStatement stmt) {
Command cmd = COMMAND.get(stmt);
- Getter<Command, Prepared> p = prepared;
+ assert cmd instanceof CommandContainer;
- if (p == null) {
- Class<? extends Command> cls = cmd.getClass();
-
- assert "CommandContainer".equals(cls.getSimpleName());
-
- prepared = p = getter(cls, "prepared");
- }
-
- Prepared statement = p.get(cmd);
-
- return new GridSqlQueryParser().parse(statement);
+ return PREPARED.get(cmd);
}
/**
@@ -255,11 +252,15 @@ public class GridSqlQueryParser {
Table tbl = filter.getTable();
if (tbl instanceof TableBase)
- res = new GridSqlTable(tbl.getSchema().getName(), tbl.getName());
+ res = new GridSqlTable(tbl);
else if (tbl instanceof TableView) {
Query qry = VIEW_QUERY.get((TableView)tbl);
- res = new GridSqlSubquery(parse(qry));
+ Index idx = filter.getIndex();
+
+ Query idxQry = idx instanceof ViewIndex ? ((ViewIndex)idx).getQuery() : null;
+
+ res = new GridSqlSubquery(parse(qry, idxQry));
}
else if (tbl instanceof FunctionTable)
res = parseExpression(FUNC_EXPR.get((FunctionTable)tbl), false);
@@ -286,7 +287,7 @@ public class GridSqlQueryParser {
/**
* @param select Select.
*/
- public GridSqlSelect parse(Select select) {
+ public GridSqlSelect parse(Select select, @Nullable Query idxQry) {
GridSqlSelect res = (GridSqlSelect)h2ObjToGridObj.get(select);
if (res != null)
@@ -305,6 +306,9 @@ public class GridSqlQueryParser {
TableFilter filter = select.getTopTableFilter();
+ if (idxQry instanceof Select)
+ filter = ((Select)idxQry).getTopTableFilter();
+
do {
assert0(filter != null, select);
assert0(filter.getNestedJoin() == null, select);
@@ -366,11 +370,35 @@ public class GridSqlQueryParser {
}
/**
- * @param qry Select.
+ * @param qry Prepared.
+ * @return Query.
+ */
+ public static Query query(Prepared qry) {
+ if (qry instanceof Query)
+ return (Query)qry;
+
+ if (qry instanceof Explain)
+ return query(EXPLAIN_COMMAND.get((Explain)qry));
+
+ throw new CacheException("Unsupported query: " + qry);
+ }
+
+ /**
+ * @param qry Prepared.
+ * @return Query.
*/
public GridSqlQuery parse(Prepared qry) {
+ return parse(qry, null);
+ }
+
+ /**
+ * @param qry Select.
+ */
+ public GridSqlQuery parse(Prepared qry, @Nullable Query idxQry) {
+ assert qry != null;
+
if (qry instanceof Select)
- return parse((Select)qry);
+ return parse((Select)qry, idxQry);
if (qry instanceof SelectUnion)
return parse((SelectUnion)qry);
@@ -378,7 +406,7 @@ public class GridSqlQueryParser {
if (qry instanceof Explain)
return parse(EXPLAIN_COMMAND.get((Explain)qry)).explain(true);
- throw new UnsupportedOperationException("Unknown query type: " + qry);
+ throw new CacheException("Unsupported query: " + qry);
}
/**
@@ -437,11 +465,12 @@ public class GridSqlQueryParser {
*/
private GridSqlElement parseExpression0(Expression expression, boolean calcTypes) {
if (expression instanceof ExpressionColumn) {
- TableFilter tblFilter = ((ExpressionColumn)expression).getTableFilter();
-
- GridSqlElement gridTblFilter = parseTable(tblFilter);
+ ExpressionColumn expCol = (ExpressionColumn)expression;
- return new GridSqlColumn(gridTblFilter, expression.getColumnName(), expression.getSQL());
+ return new GridSqlColumn(expCol.getColumn(),
+ parseTable(expCol.getTableFilter()),
+ expression.getColumnName(),
+ expression.getSQL());
}
if (expression instanceof Alias)
@@ -475,12 +504,14 @@ public class GridSqlQueryParser {
assert opType != null : COMPARISON_TYPE.get(cmp);
- GridSqlElement left = parseExpression(COMPARISON_LEFT.get(cmp), calcTypes);
+ Expression leftExp = COMPARISON_LEFT.get(cmp);
+ GridSqlElement left = parseExpression(leftExp, calcTypes);
if (opType.childrenCount() == 1)
return new GridSqlOperation(opType, left);
- GridSqlElement right = parseExpression(COMPARISON_RIGHT.get(cmp), calcTypes);
+ Expression rightExp = COMPARISON_RIGHT.get(cmp);
+ GridSqlElement right = parseExpression(rightExp, calcTypes);
return new GridSqlOperation(opType, left, right);
}
@@ -685,7 +716,7 @@ public class GridSqlQueryParser {
* Field getter.
*/
@SuppressWarnings("unchecked")
- private static class Getter<T, R> {
+ public static class Getter<T, R> {
/** */
private final Field fld;
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 4d34ce8..7205a18 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
@@ -23,18 +23,27 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
-import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
+import org.apache.ignite.lang.IgnitePredicate;
+import org.h2.command.Prepared;
import org.h2.jdbc.JdbcPreparedStatement;
+import org.h2.table.Column;
+import org.h2.table.IndexColumn;
import org.h2.util.IntArray;
import org.jetbrains.annotations.Nullable;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2CollocationModel.isCollocated;
import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.AVG;
import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.CAST;
import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.COUNT;
import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.SUM;
import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlPlaceholder.EMPTY;
+import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser.prepared;
+import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser.query;
+import static org.apache.ignite.internal.processors.query.h2.twostep.GridReduceQueryExecutor.toArray;
/**
* Splits a single SQL query into two step map-reduce query.
@@ -136,26 +145,146 @@ public class GridSqlQuerySplitter {
/**
* @param stmt Prepared statement.
* @param params Parameters.
- * @param collocated Collocated query.
- * @param igniteH2Indexing Indexing implementation.
+ * @param collocatedGrpBy Whether the query has collocated GROUP BY keys.
+ * @param distributedJoins If distributed joins enabled.
* @return Two step query.
*/
- public static GridCacheTwoStepQuery split(JdbcPreparedStatement stmt, Object[] params, boolean collocated, IgniteH2Indexing igniteH2Indexing) {
+ public static GridCacheTwoStepQuery split(
+ JdbcPreparedStatement stmt,
+ Object[] params,
+ final boolean collocatedGrpBy,
+ final boolean distributedJoins
+ ) {
if (params == null)
params = GridCacheSqlQuery.EMPTY_PARAMS;
+ Set<String> tbls = new HashSet<>();
Set<String> schemas = new HashSet<>();
+ final Prepared prepared = prepared(stmt);
+
+ GridSqlQuery qry = new GridSqlQueryParser().parse(prepared);
+
+ qry = collectAllTables(qry, schemas, tbls);
+
+ // Build resulting two step query.
+ GridCacheTwoStepQuery res = new GridCacheTwoStepQuery(schemas, tbls);
+
// Map query will be direct reference to the original query AST.
// Thus all the modifications will be performed on the original AST, so we should be careful when
// nullifying or updating things, have to make sure that we will not need them in the original form later.
- final GridSqlSelect mapQry = wrapUnion(collectAllSpaces(GridSqlQueryParser.parse(stmt), schemas));
+ final GridSqlSelect mapQry = wrapUnion(qry);
+
+ GridCacheSqlQuery rdc = split(res, 0, mapQry, params, collocatedGrpBy);
+
+ res.reduceQuery(rdc);
+
+ // We do not have to look at each map query separately here, because if
+ // the whole initial query is collocated, then all the map sub-queries
+ // will be collocated as well.
+ res.distributedJoins(distributedJoins && !isCollocated(query(prepared)));
+
+ return res;
+ }
+
+ /**
+ * @param el Either {@link GridSqlSelect#from()} or {@link GridSqlSelect#where()} elements.
+ */
+ private static void findAffinityColumnConditions(GridSqlElement el) {
+ if (el == null)
+ return;
+
+ el = GridSqlAlias.unwrap(el);
+
+ if (el instanceof GridSqlJoin) {
+ GridSqlJoin join = (GridSqlJoin)el;
+
+ findAffinityColumnConditions(join.leftTable());
+ findAffinityColumnConditions(join.rightTable());
+ findAffinityColumnConditions(join.on());
+ }
+ else if (el instanceof GridSqlOperation) {
+ GridSqlOperationType type = ((GridSqlOperation)el).operationType();
+
+ switch(type) {
+ case AND:
+ findAffinityColumnConditions(el.child(0));
+ findAffinityColumnConditions(el.child(1));
+
+ break;
+
+ case EQUAL:
+ findAffinityColumn(el.child(0));
+ findAffinityColumn(el.child(1));
+ }
+ }
+ }
+
+ /**
+ * @param exp Possible affinity column expression.
+ */
+ private static void findAffinityColumn(GridSqlElement exp) {
+ if (exp instanceof GridSqlColumn) {
+ GridSqlColumn col = (GridSqlColumn)exp;
+
+ GridSqlElement from = col.expressionInFrom();
+
+ if (from instanceof GridSqlTable) {
+ GridSqlTable fromTbl = (GridSqlTable)from;
+
+ GridH2Table tbl = fromTbl.dataTable();
+
+ if (tbl != null) {
+ IndexColumn affKeyCol = tbl.getAffinityKeyColumn();
+ Column expCol = col.column();
+
+ if (affKeyCol != null && expCol != null &&
+ affKeyCol.column.getColumnId() == expCol.getColumnId()) {
+ // Mark that table lookup will use affinity key.
+ fromTbl.affinityKeyCondition(true);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param qry Select.
+ * @return {@code true} If there is at least one partitioned table in FROM clause.
+ */
+ private static boolean hasPartitionedTableInFrom(GridSqlSelect qry) {
+ return findTablesInFrom(qry.from(), new IgnitePredicate<GridSqlElement>() {
+ @Override public boolean apply(GridSqlElement el) {
+ if (el instanceof GridSqlTable) {
+ GridH2Table tbl = ((GridSqlTable)el).dataTable();
+
+ assert tbl != null : el;
+
+ GridCacheContext<?,?> cctx = tbl.rowDescriptor().context();
+ return !cctx.isLocal() && !cctx.isReplicated();
+ }
+
+ return false;
+ }
+ });
+ }
+
+ /**
+ * @param res Resulting two step query.
+ * @param splitIdx Split index.
+ * @param mapQry Map query to be split.
+ * @param params Query parameters.
+ * @param collocatedGroupBy Whether the query has collocated GROUP BY keys.
+ * @return Reduce query for the given map query.
+ */
+ private static GridCacheSqlQuery split(GridCacheTwoStepQuery res, int splitIdx, final GridSqlSelect mapQry,
+ Object[] params, boolean collocatedGroupBy) {
final boolean explain = mapQry.explain();
mapQry.explain(false);
- GridSqlSelect rdcQry = new GridSqlSelect().from(table(0));
+ GridSqlSelect rdcQry = new GridSqlSelect().from(table(splitIdx));
// Split all select expressions into map-reduce parts.
List<GridSqlElement> mapExps = new ArrayList<>(mapQry.allColumns());
@@ -172,9 +301,9 @@ public class GridSqlQuerySplitter {
boolean aggregateFound = false;
for (int i = 0, len = mapExps.size(); i < len; i++) // Remember len because mapExps list can grow.
- aggregateFound |= splitSelectExpression(mapExps, rdcExps, colNames, i, collocated, i == havingCol);
+ aggregateFound |= splitSelectExpression(mapExps, rdcExps, colNames, i, collocatedGroupBy, i == havingCol);
- // Fill select expressions.
+ // -- SELECT
mapQry.clearColumns();
for (GridSqlElement exp : mapExps) // Add all map expressions as visible.
@@ -189,12 +318,18 @@ public class GridSqlQuerySplitter {
for (int i = rdcExps.size(); i < mapExps.size(); i++) // Add all extra map columns as invisible reduce columns.
rdcQry.addColumn(column(((GridSqlAlias)mapExps.get(i)).alias()), false);
+ // -- FROM
+ findAffinityColumnConditions(mapQry.from());
+
+ // -- WHERE
+ findAffinityColumnConditions(mapQry.where());
+
// -- GROUP BY
- if (mapQry.groupColumns() != null && !collocated)
+ if (mapQry.groupColumns() != null && !collocatedGroupBy)
rdcQry.groupColumns(mapQry.groupColumns());
// -- HAVING
- if (havingCol >= 0 && !collocated) {
+ if (havingCol >= 0 && !collocatedGroupBy) {
// TODO IGNITE-1140 - Find aggregate functions in HAVING clause or rewrite query to put all aggregates to SELECT clause.
// We need to find HAVING column in reduce query.
for (int i = visibleCols; i < rdcQry.allColumns(); i++) {
@@ -246,40 +381,25 @@ public class GridSqlQuerySplitter {
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);
-
GridCacheSqlQuery map = new GridCacheSqlQuery(mapQry.getSQL(),
- findParams(mapQry, params, new ArrayList<>(params.length), paramIdxs).toArray())
- .columns(collectColumns(mapExps));
+ findParams(mapQry, params, new ArrayList<>(params.length), paramIdxs).toArray());
- map.parameterIndexes(toIntArray(paramIdxs));
+ map.columns(collectColumns(mapExps));
+ map.parameterIndexes(toArray(paramIdxs));
- Set<String> spaces = new HashSet<>(schemas.size());
+ res.addMapQuery(map);
- for (String schema : schemas)
- spaces.add(igniteH2Indexing.space(schema));
+ res.explain(explain);
- // Build resulting two step query.
- GridCacheTwoStepQuery res = new GridCacheTwoStepQuery(spaces, rdc, rdcQry.simpleQuery()).addMapQuery(map);
+ paramIdxs = new IntArray(params.length);
- res.explain(explain);
+ GridCacheSqlQuery rdc = new GridCacheSqlQuery(rdcQry.getSQL(),
+ findParams(rdcQry, params, new ArrayList<>(), paramIdxs).toArray());
- return res;
- }
+ rdc.parameterIndexes(toArray(paramIdxs));
+ res.skipMergeTable(rdcQry.simpleQuery());
- /**
- * @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;
+ return rdc;
}
/**
@@ -315,25 +435,26 @@ public class GridSqlQuerySplitter {
/**
* @param qry Query.
- * @param schemas Shemas' names.
+ * @param schemas Schema names.
+ * @param tbls Tables.
* @return Query.
*/
- private static GridSqlQuery collectAllSpaces(GridSqlQuery qry, Set<String> schemas) {
+ private static GridSqlQuery collectAllTables(GridSqlQuery qry, Set<String> schemas, Set<String> tbls) {
if (qry instanceof GridSqlUnion) {
GridSqlUnion union = (GridSqlUnion)qry;
- collectAllSpaces(union.left(), schemas);
- collectAllSpaces(union.right(), schemas);
+ collectAllTables(union.left(), schemas, tbls);
+ collectAllTables(union.right(), schemas, tbls);
}
else {
GridSqlSelect select = (GridSqlSelect)qry;
- collectAllSpacesInFrom(select.from(), schemas);
+ collectAllTablesInFrom(select.from(), schemas, tbls);
for (GridSqlElement el : select.columns(false))
- collectAllSpacesInSubqueries(el, schemas);
+ collectAllTablesInSubqueries(el, schemas, tbls);
- collectAllSpacesInSubqueries(select.where(), schemas);
+ collectAllTablesInSubqueries(select.where(), schemas, tbls);
}
return qry;
@@ -341,45 +462,85 @@ public class GridSqlQuerySplitter {
/**
* @param from From element.
- * @param schemas Shemas' names.
+ * @param schemas Schema names.
+ * @param tbls Tables.
*/
- private static void collectAllSpacesInFrom(GridSqlElement from, Set<String> schemas) {
- assert from != null;
+ private static void collectAllTablesInFrom(GridSqlElement from, final Set<String> schemas, final Set<String> tbls) {
+ findTablesInFrom(from, new IgnitePredicate<GridSqlElement>() {
+ @Override public boolean apply(GridSqlElement el) {
+ if (el instanceof GridSqlTable) {
+ GridSqlTable tbl = (GridSqlTable)el;
+
+ String schema = tbl.schema();
+
+ boolean addSchema = tbls == null;
+
+ if (tbls != null)
+ addSchema = tbls.add(tbl.dataTable().identifier());
+
+ if (addSchema && schema != null && schemas != null)
+ schemas.add(schema);
+ }
+ else if (el instanceof GridSqlSubquery)
+ collectAllTables(((GridSqlSubquery)el).select(), schemas, tbls);
+
+ return false;
+ }
+ });
+ }
+
+ /**
+ * Processes all the tables and subqueries using the given closure.
+ *
+ * @param from FROM element.
+ * @param c Closure each found table and subquery will be passed to. If returns {@code true} the we need to stop.
+ * @return {@code true} If we have found.
+ */
+ private static boolean findTablesInFrom(GridSqlElement from, IgnitePredicate<GridSqlElement> c) {
+ if (from == null)
+ return false;
+
+ if (from instanceof GridSqlTable || from instanceof GridSqlSubquery)
+ return c.apply(from);
if (from instanceof GridSqlJoin) {
// Left and right.
- collectAllSpacesInFrom(from.child(0), schemas);
- collectAllSpacesInFrom(from.child(1), schemas);
- }
- else if (from instanceof GridSqlTable) {
- String schema = ((GridSqlTable)from).schema();
+ if (findTablesInFrom(from.child(0), c))
+ return true;
- if (schema != null)
- schemas.add(schema);
+ if (findTablesInFrom(from.child(1), c))
+ return true;
+
+ // We don't process ON condition because it is not a joining part of from here.
+ return false;
}
- else if (from instanceof GridSqlSubquery)
- collectAllSpaces(((GridSqlSubquery)from).select(), schemas);
else if (from instanceof GridSqlAlias)
- collectAllSpacesInFrom(from.child(), schemas);
- else if (!(from instanceof GridSqlFunction))
- throw new IllegalStateException(from.getClass().getName() + " : " + from.getSQL());
+ return findTablesInFrom(from.child(), c);
+ else if (from instanceof GridSqlFunction)
+ return false;
+
+ throw new IllegalStateException(from.getClass().getName() + " : " + from.getSQL());
}
/**
- * Searches spaces in subqueries in SELECT and WHERE clauses.
+ * Searches schema names and tables in subqueries in SELECT and WHERE clauses.
+ *
* @param el Element.
- * @param schemas Schemas' names.
+ * @param schemas Schema names.
+ * @param tbls Tables.
*/
- private static void collectAllSpacesInSubqueries(GridSqlElement el, Set<String> schemas) {
- if (el instanceof GridSqlAlias)
- el = el.child();
+ private static void collectAllTablesInSubqueries(GridSqlElement el, Set<String> schemas, Set<String> tbls) {
+ if (el == null)
+ return;
+
+ el = GridSqlAlias.unwrap(el);
if (el instanceof GridSqlOperation || el instanceof GridSqlFunction) {
for (GridSqlElement child : el)
- collectAllSpacesInSubqueries(child, schemas);
+ collectAllTablesInSubqueries(child, schemas, tbls);
}
else if (el instanceof GridSqlSubquery)
- collectAllSpaces(((GridSqlSubquery)el).select(), schemas);
+ collectAllTables(((GridSqlSubquery)el).select(), schemas, tbls);
}
/**
@@ -691,7 +852,7 @@ public class GridSqlQuerySplitter {
* @return Column.
*/
private static GridSqlColumn column(String name) {
- return new GridSqlColumn(null, name, name);
+ return new GridSqlColumn(null, null, name, name);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 07ef1fa..a38ae68 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
@@ -131,13 +131,12 @@ public class GridSqlSelect extends GridSqlQuery {
/**
* @param buff Statement builder.
- * @param expression Alias expression.
+ * @param exp Alias expression.
*/
- private static void addAlias(StatementBuilder buff, GridSqlElement expression) {
- if (expression instanceof GridSqlAlias)
- expression = expression.child();
+ private static void addAlias(StatementBuilder buff, GridSqlElement exp) {
+ exp = GridSqlAlias.unwrap(exp);
- buff.append(StringUtils.unEnclose(expression.getSQL()));
+ buff.append(StringUtils.unEnclose(exp.getSQL()));
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java
index 0bcdf1c..49c679d 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java
@@ -18,7 +18,9 @@
package org.apache.ignite.internal.processors.query.h2.sql;
import java.util.Collections;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
import org.h2.command.Parser;
+import org.h2.table.Table;
import org.jetbrains.annotations.Nullable;
/**
@@ -31,15 +33,56 @@ public class GridSqlTable extends GridSqlElement {
/** */
private final String tblName;
+ /** */
+ private final GridH2Table tbl;
+
+ /** */
+ private boolean affKeyCond;
+
/**
* @param schema Schema.
* @param tblName Table name.
*/
public GridSqlTable(@Nullable String schema, String tblName) {
+ this(schema, tblName, null);
+ }
+
+ /**
+ * @param tbl Table.
+ */
+ public GridSqlTable(Table tbl) {
+ this(tbl.getSchema().getName(), tbl.getName(), tbl);
+ }
+
+ /**
+ * @param schema Schema.
+ * @param tblName Table name.
+ * @param tbl H2 Table.
+ */
+ private GridSqlTable(@Nullable String schema, String tblName, @Nullable Table tbl) {
super(Collections.<GridSqlElement>emptyList());
+ assert schema != null : "schema";
+ assert tblName != null : "tblName";
+
this.schema = schema;
this.tblName = tblName;
+
+ this.tbl = tbl instanceof GridH2Table ? (GridH2Table)tbl : null;
+ }
+
+ /**
+ * @param affKeyCond If affinity key condition is found.
+ */
+ public void affinityKeyCondition(boolean affKeyCond) {
+ this.affKeyCond = affKeyCond;
+ }
+
+ /**
+ * @return {@code true} If affinity key condition is found.
+ */
+ public boolean affinityKeyCondition() {
+ return affKeyCond;
}
/** {@inheritDoc} */
@@ -63,4 +106,31 @@ public class GridSqlTable extends GridSqlElement {
public String tableName() {
return tblName;
}
+
+ /**
+ * @return Referenced data table.
+ */
+ public GridH2Table dataTable() {
+ return tbl;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (!super.equals(o))
+ return false;
+
+ GridSqlTable that = (GridSqlTable)o;
+
+ return schema.equals(that.schema) && tblName.equals(that.tblName);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ int result = 1;
+
+ result = 31 * result + schema.hashCode();
+ result = 31 * result + tblName.hashCode();
+
+ return result;
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 580058c..bb5e419 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
@@ -18,15 +18,16 @@
package org.apache.ignite.internal.processors.query.h2.twostep;
import java.lang.reflect.Field;
+import java.sql.Connection;
import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceArray;
@@ -45,38 +46,46 @@ import org.apache.ignite.internal.GridTopic;
import org.apache.ignite.internal.managers.communication.GridMessageListener;
import org.apache.ignite.internal.managers.eventstorage.GridLocalEventListener;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
-import org.apache.ignite.internal.processors.cache.GridCacheAdapter;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtLocalPartition;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionsReservation;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable;
import org.apache.ignite.internal.processors.cache.query.CacheQueryType;
+import org.apache.ignite.internal.processors.cache.query.GridCacheQueryMarshallable;
import org.apache.ignite.internal.processors.cache.query.GridCacheSqlQuery;
import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryContext;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2RetryException;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryCancelRequest;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryFailResponse;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryNextPageRequest;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryNextPageResponse;
import org.apache.ignite.internal.processors.query.h2.twostep.messages.GridQueryRequest;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2QueryRequest;
+import org.apache.ignite.internal.util.GridBoundedConcurrentLinkedHashMap;
import org.apache.ignite.internal.util.GridSpinBusyLock;
import org.apache.ignite.internal.util.typedef.CI1;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.T2;
+import org.apache.ignite.internal.util.typedef.X;
+import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.U;
-import org.apache.ignite.marshaller.Marshaller;
import org.apache.ignite.plugin.extensions.communication.Message;
import org.h2.jdbc.JdbcResultSet;
import org.h2.result.ResultInterface;
import org.h2.value.Value;
-import org.jetbrains.annotations.Nullable;
import org.jsr166.ConcurrentHashMap8;
import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_EXECUTED;
import static org.apache.ignite.events.EventType.EVT_CACHE_QUERY_OBJECT_READ;
import static org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion.NONE;
import static org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtPartitionState.OWNING;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.MAP;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.REPLICATED;
import static org.apache.ignite.internal.processors.query.h2.twostep.GridReduceQueryExecutor.QUERY_POOL;
import static org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2ValueMessageFactory.toMessages;
+import static org.jsr166.ConcurrentLinkedHashMap.QueuePolicy.PER_SEGMENT_Q;
/**
* Map query executor.
@@ -109,7 +118,7 @@ public class GridMapQueryExecutor {
private IgniteH2Indexing h2;
/** */
- private ConcurrentMap<UUID, ConcurrentMap<Long, QueryResults>> qryRess = new ConcurrentHashMap8<>();
+ private ConcurrentMap<UUID, NodeResults> qryRess = new ConcurrentHashMap8<>();
/** */
private final GridSpinBusyLock busyLock;
@@ -136,16 +145,20 @@ public class GridMapQueryExecutor {
log = ctx.log(GridMapQueryExecutor.class);
+ final UUID locNodeId = ctx.localNodeId();
+
ctx.event().addLocalEventListener(new GridLocalEventListener() {
@Override public void onEvent(final Event evt) {
UUID nodeId = ((DiscoveryEvent)evt).eventNode().id();
- ConcurrentMap<Long,QueryResults> nodeRess = qryRess.remove(nodeId);
+ GridH2QueryContext.clearAfterDeadNode(locNodeId, nodeId);
+
+ NodeResults nodeRess = qryRess.remove(nodeId);
if (nodeRess == null)
return;
- for (QueryResults ress : nodeRess.values())
+ for (QueryResults ress : nodeRess.results().values())
ress.cancel();
}
}, EventType.EVT_NODE_FAILED, EventType.EVT_NODE_LEFT);
@@ -156,6 +169,9 @@ public class GridMapQueryExecutor {
return;
try {
+ if (msg instanceof GridCacheQueryMarshallable)
+ ((GridCacheQueryMarshallable)msg).unmarshall(ctx.config().getMarshaller(), ctx);
+
GridMapQueryExecutor.this.onMessage(nodeId, msg);
}
finally {
@@ -180,12 +196,14 @@ public class GridMapQueryExecutor {
boolean processed = true;
- if (msg instanceof GridQueryRequest)
- onQueryRequest(node, (GridQueryRequest)msg);
+ if (msg instanceof GridH2QueryRequest)
+ onQueryRequest(node, (GridH2QueryRequest)msg);
else if (msg instanceof GridQueryNextPageRequest)
onNextPageRequest(node, (GridQueryNextPageRequest)msg);
else if (msg instanceof GridQueryCancelRequest)
onCancel(node, (GridQueryCancelRequest)msg);
+ else if (msg instanceof GridQueryRequest)
+ onQueryRequest(node, (GridQueryRequest)msg);
else
processed = false;
@@ -202,9 +220,19 @@ public class GridMapQueryExecutor {
* @param msg Message.
*/
private void onCancel(ClusterNode node, GridQueryCancelRequest msg) {
- ConcurrentMap<Long,QueryResults> nodeRess = resultsForNode(node.id());
+ long qryReqId = msg.queryRequestId();
+
+ NodeResults nodeRess = resultsForNode(node.id());
+
+ boolean clear = GridH2QueryContext.clear(ctx.localNodeId(), node.id(), qryReqId, MAP);
- QueryResults results = nodeRess.remove(msg.queryRequestId());
+ if (!clear) {
+ nodeRess.onCancel(qryReqId);
+
+ GridH2QueryContext.clear(ctx.localNodeId(), node.id(), qryReqId, MAP);
+ }
+
+ QueryResults results = nodeRess.results().remove(qryReqId);
if (results == null)
return;
@@ -216,13 +244,13 @@ public class GridMapQueryExecutor {
* @param nodeId Node ID.
* @return Results for node.
*/
- private ConcurrentMap<Long, QueryResults> resultsForNode(UUID nodeId) {
- ConcurrentMap<Long, QueryResults> nodeRess = qryRess.get(nodeId);
+ private NodeResults resultsForNode(UUID nodeId) {
+ NodeResults nodeRess = qryRess.get(nodeId);
if (nodeRess == null) {
- nodeRess = new ConcurrentHashMap8<>();
+ nodeRess = new NodeResults();
- ConcurrentMap<Long, QueryResults> old = qryRess.putIfAbsent(nodeId, nodeRess);
+ NodeResults old = qryRess.putIfAbsent(nodeId, nodeRess);
if (old != null)
nodeRess = old;
@@ -232,19 +260,6 @@ public class GridMapQueryExecutor {
}
/**
- * @param cacheName Cache name.
- * @return Cache context or {@code null} if none.
- */
- @Nullable private GridCacheContext<?,?> cacheContext(String cacheName) {
- GridCacheAdapter<?,?> cache = ctx.cache().internalCache(cacheName);
-
- if (cache == null)
- return null;
-
- return cache.context();
- }
-
- /**
* @param cctx Cache context.
* @param p Partition ID.
* @return Partition.
@@ -254,7 +269,7 @@ public class GridMapQueryExecutor {
}
/**
- * @param cacheNames Cache names.
+ * @param cacheIds Cache IDs.
* @param topVer Topology version.
* @param explicitParts Explicit partitions list.
* @param reserved Reserved list.
@@ -262,7 +277,7 @@ public class GridMapQueryExecutor {
* @throws IgniteCheckedException If failed.
*/
private boolean reservePartitions(
- Collection<String> cacheNames,
+ List<Integer> cacheIds,
AffinityTopologyVersion topVer,
final int[] explicitParts,
List<GridReservable> reserved
@@ -271,8 +286,8 @@ public class GridMapQueryExecutor {
Collection<Integer> partIds = wrap(explicitParts);
- for (String cacheName : cacheNames) {
- GridCacheContext<?, ?> cctx = cacheContext(cacheName);
+ for (int i = 0; i < cacheIds.size(); i++) {
+ GridCacheContext<?, ?> cctx = ctx.cache().context().cacheContext(cacheIds.get(i));
if (cctx == null) // Cache was not found, probably was not deployed yet.
return false;
@@ -394,121 +409,226 @@ public class GridMapQueryExecutor {
* @param req Query request.
*/
private void onQueryRequest(ClusterNode node, GridQueryRequest req) {
- ConcurrentMap<Long,QueryResults> nodeRess = resultsForNode(node.id());
+ List<Integer> cacheIds;
- QueryResults qr = null;
+ if (req.extraSpaces() != null) {
+ cacheIds = new ArrayList<>(req.extraSpaces().size() + 1);
- List<GridReservable> reserved = new ArrayList<>();
+ cacheIds.add(CU.cacheId(req.space()));
- try {
- // Unmarshall query params.
- Collection<GridCacheSqlQuery> qrys;
+ for (String extraSpace : req.extraSpaces())
+ cacheIds.add(CU.cacheId(extraSpace));
+ }
+ else
+ cacheIds = Collections.singletonList(CU.cacheId(req.space()));
+
+ onQueryRequest0(node,
+ req.requestId(),
+ req.queries(),
+ cacheIds,
+ req.topologyVersion(),
+ null,
+ req.partitions(),
+ null,
+ req.pageSize(),
+ false);
+ }
- try {
- qrys = req.queries();
+ /**
+ * @param node Node.
+ * @param req Query request.
+ */
+ private void onQueryRequest(ClusterNode node, GridH2QueryRequest req) {
+ Map<UUID,int[]> partsMap = req.partitions();
+ int[] parts = partsMap == null ? null : partsMap.get(ctx.localNodeId());
+
+ onQueryRequest0(node,
+ req.requestId(),
+ req.queries(),
+ req.caches(),
+ req.topologyVersion(),
+ partsMap,
+ parts,
+ req.tables(),
+ req.pageSize(),
+ req.isFlagSet(GridH2QueryRequest.FLAG_DISTRIBUTED_JOINS));
+ }
+
+ /**
+ * @param node Node authored request.
+ * @param reqId Request ID.
+ * @param qrys Queries to execute.
+ * @param cacheIds Caches which will be affected by these queries.
+ * @param topVer Topology version.
+ * @param partsMap Partitions map for unstable topology.
+ * @param parts Explicit partitions for current node.
+ * @param tbls Tables.
+ * @param pageSize Page size.
+ * @param distributedJoins Can we expect distributed joins to be ran.
+ */
+ private void onQueryRequest0(
+ ClusterNode node,
+ long reqId,
+ Collection<GridCacheSqlQuery> qrys,
+ List<Integer> cacheIds,
+ AffinityTopologyVersion topVer,
+ Map<UUID, int[]> partsMap,
+ int[] parts,
+ Collection<String> tbls,
+ int pageSize,
+ boolean distributedJoins
+ ) {
+ // Prepare to run queries.
+ GridCacheContext<?, ?> mainCctx = ctx.cache().context().cacheContext(cacheIds.get(0));
- if (!node.isLocal()) {
- Marshaller m = ctx.config().getMarshaller();
+ if (mainCctx == null)
+ throw new CacheException("Failed to find cache.");
- for (GridCacheSqlQuery qry : qrys)
- qry.unmarshallParams(m, ctx);
- }
- }
- catch (IgniteCheckedException e) {
- throw new CacheException("Failed to unmarshall parameters.", e);
- }
+ NodeResults nodeRess = resultsForNode(node.id());
- List<String> caches = (List<String>)F.concat(true, req.space(), req.extraSpaces());
+ QueryResults qr = null;
- // Topology version can be null in rolling restart with previous version!
- final AffinityTopologyVersion topVer = req.topologyVersion();
+ List<GridReservable> reserved = new ArrayList<>();
+ try {
if (topVer != null) {
// Reserve primary for topology version or explicit partitions.
- if (!reservePartitions(caches, topVer, req.partitions(), reserved)) {
- sendRetry(node, req.requestId());
+ if (!reservePartitions(cacheIds, topVer, parts, reserved)) {
+ sendRetry(node, reqId);
return;
}
}
- // Prepare to run queries.
- GridCacheContext<?,?> mainCctx = cacheContext(req.space());
+ qr = new QueryResults(reqId, qrys.size(), mainCctx);
- if (mainCctx == null)
- throw new CacheException("Failed to find cache: " + req.space());
+ if (nodeRess.results().put(reqId, qr) != null)
+ throw new IllegalStateException();
- qr = new QueryResults(req.requestId(), qrys.size(), mainCctx);
+ // Prepare query context.
+ GridH2QueryContext qctx = new GridH2QueryContext(ctx.localNodeId(),
+ node.id(),
+ reqId,
+ mainCctx.isReplicated() ? REPLICATED : MAP)
+ .filter(h2.backupFilter(topVer, parts))
+ .partitionsMap(partsMap)
+ .distributedJoins(distributedJoins)
+ .pageSize(pageSize)
+ .topologyVersion(topVer)
+ .reservations(reserved);
- if (nodeRess.put(req.requestId(), qr) != null)
- throw new IllegalStateException();
+ List<GridH2Table> snapshotedTbls = null;
- h2.setFilters(h2.backupFilter(caches, topVer, req.partitions()));
+ if (!F.isEmpty(tbls)) {
+ snapshotedTbls = new ArrayList<>(tbls.size());
- // TODO Prepare snapshots for all the needed tables before the run.
+ for (String identifier : tbls) {
+ GridH2Table tbl = h2.dataTable(identifier);
- // Run queries.
- int i = 0;
+ Objects.requireNonNull(tbl, identifier);
- for (GridCacheSqlQuery qry : qrys) {
- ResultSet rs = h2.executeSqlQueryWithTimer(req.space(),
- h2.connectionForSpace(req.space()),
- qry.query(),
- F.asList(qry.parameters()),
- true);
+ tbl.snapshotIndexes(qctx);
- if (ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
- ctx.event().record(new CacheQueryExecutedEvent<>(
- node,
- "SQL query executed.",
- EVT_CACHE_QUERY_EXECUTED,
- CacheQueryType.SQL.name(),
- mainCctx.namex(),
- null,
- qry.query(),
- null,
- null,
- qry.parameters(),
- node.id(),
- null));
+ snapshotedTbls.add(tbl);
}
+ }
+
+ Connection conn = h2.connectionForSpace(mainCctx.name());
+
+ // Here we enforce join order to have the same behavior on all the nodes.
+ h2.setupConnection(conn, distributedJoins, true);
+
+ GridH2QueryContext.set(qctx);
- assert rs instanceof JdbcResultSet : rs.getClass();
+ // qctx is set, we have to release reservations inside of it.
+ reserved = null;
- qr.addResult(i, qry, node.id(), rs);
+ try {
+ if (nodeRess.cancelled(reqId)) {
+ GridH2QueryContext.clear(ctx.localNodeId(), node.id(), reqId, qctx.type());
- if (qr.canceled) {
- qr.result(i).close();
+ nodeRess.results().remove(reqId);
return;
}
- // Send the first page.
- sendNextPage(nodeRess, node, qr, i, req.pageSize());
+ // Run queries.
+ int i = 0;
+
+ boolean evt = ctx.event().isRecordable(EVT_CACHE_QUERY_EXECUTED);
+
+ for (GridCacheSqlQuery qry : qrys) {
+ ResultSet rs = h2.executeSqlQueryWithTimer(mainCctx.name(), conn, qry.query(),
+ F.asList(qry.parameters()), true);
+
+ if (evt) {
+ ctx.event().record(new CacheQueryExecutedEvent<>(
+ node,
+ "SQL query executed.",
+ EVT_CACHE_QUERY_EXECUTED,
+ CacheQueryType.SQL.name(),
+ mainCctx.namex(),
+ null,
+ qry.query(),
+ null,
+ null,
+ qry.parameters(),
+ node.id(),
+ null));
+ }
+
+ assert rs instanceof JdbcResultSet : rs.getClass();
+
+ qr.addResult(i, qry, node.id(), rs);
+
+ if (qr.canceled) {
+ qr.result(i).close();
+
+ return;
+ }
+
+ // Send the first page.
+ sendNextPage(nodeRess, node, qr, i, pageSize);
+
+ i++;
+ }
+ }
+ finally {
+ GridH2QueryContext.clearThreadLocal();
+
+ if (!distributedJoins)
+ qctx.clearContext(false);
- i++;
+ if (!F.isEmpty(snapshotedTbls)) {
+ for (GridH2Table dataTbl : snapshotedTbls)
+ dataTbl.releaseSnapshots();
+ }
}
}
catch (Throwable e) {
if (qr != null) {
- nodeRess.remove(req.requestId(), qr);
+ nodeRess.results().remove(reqId, qr);
qr.cancel();
}
- U.error(log, "Failed to execute local query: " + req, e);
+ if (X.hasCause(e, GridH2RetryException.class))
+ sendRetry(node, reqId);
+ else {
+ U.error(log, "Failed to execute local query.", e);
- sendError(node, req.requestId(), e);
+ sendError(node, reqId, e);
- if (e instanceof Error)
- throw (Error)e;
+ if (e instanceof Error)
+ throw (Error)e;
+ }
}
finally {
- h2.setFilters(null);
-
- // Release reserved partitions.
- for (GridReservable r : reserved)
- r.release();
+ if (reserved != null) {
+ // Release reserved partitions.
+ for (int i = 0; i < reserved.size(); i++)
+ reserved.get(i).release();
+ }
}
}
@@ -521,8 +641,11 @@ public class GridMapQueryExecutor {
try {
GridQueryFailResponse msg = new GridQueryFailResponse(qryReqId, err);
- if (node.isLocal())
+ if (node.isLocal()) {
+ U.error(log, "Failed to run map query on local node.", err);
+
h2.reduceQueryExecutor().onMessage(ctx.localNodeId(), msg);
+ }
else
ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, QUERY_POOL);
}
@@ -538,9 +661,9 @@ public class GridMapQueryExecutor {
* @param req Request.
*/
private void onNextPageRequest(ClusterNode node, GridQueryNextPageRequest req) {
- ConcurrentMap<Long, QueryResults> nodeRess = qryRess.get(node.id());
+ NodeResults nodeRess = qryRess.get(node.id());
- QueryResults qr = nodeRess == null ? null : nodeRess.get(req.queryRequestId());
+ QueryResults qr = nodeRess == null ? null : nodeRess.results().get(req.queryRequestId());
if (qr == null || qr.canceled)
sendError(node, req.queryRequestId(), new CacheException("No query result found for request: " + req));
@@ -549,12 +672,13 @@ public class GridMapQueryExecutor {
}
/**
+ * @param nodeRess Results.
* @param node Node.
* @param qr Query results.
* @param qry Query.
* @param pageSize Page size.
*/
- private void sendNextPage(ConcurrentMap<Long, QueryResults> nodeRess, ClusterNode node, QueryResults qr, int qry,
+ private void sendNextPage(NodeResults nodeRess, ClusterNode node, QueryResults qr, int qry,
int pageSize) {
QueryResult res = qr.result(qry);
@@ -570,14 +694,14 @@ public class GridMapQueryExecutor {
res.close();
if (qr.isAllClosed())
- nodeRess.remove(qr.qryReqId, qr);
+ nodeRess.results().remove(qr.qryReqId, qr);
}
try {
boolean loc = node.isLocal();
GridQueryNextPageResponse msg = new GridQueryNextPageResponse(qr.qryReqId, qry, page,
- page == 0 ? res.rowCount : -1 ,
+ page == 0 ? res.rowCnt : -1 ,
res.cols,
loc ? null : toMessages(rows, new ArrayList<Message>(res.cols)),
loc ? rows : null);
@@ -597,22 +721,26 @@ public class GridMapQueryExecutor {
/**
* @param node Node.
* @param reqId Request ID.
- * @throws IgniteCheckedException If failed.
*/
- private void sendRetry(ClusterNode node, long reqId) throws IgniteCheckedException {
- boolean loc = node.isLocal();
+ private void sendRetry(ClusterNode node, long reqId) {
+ try {
+ boolean loc = node.isLocal();
- GridQueryNextPageResponse msg = new GridQueryNextPageResponse(reqId,
+ GridQueryNextPageResponse msg = new GridQueryNextPageResponse(reqId,
/*qry*/0, /*page*/0, /*allRows*/0, /*cols*/1,
- loc ? null : Collections.<Message>emptyList(),
- loc ? Collections.<Value[]>emptyList() : null);
+ loc ? null : Collections.<Message>emptyList(),
+ loc ? Collections.<Value[]>emptyList() : null);
- msg.retry(h2.readyTopologyVersion());
+ msg.retry(h2.readyTopologyVersion());
- if (loc)
- h2.reduceQueryExecutor().onMessage(ctx.localNodeId(), msg);
- else
- ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, QUERY_POOL);
+ if (loc)
+ h2.reduceQueryExecutor().onMessage(ctx.localNodeId(), msg);
+ else
+ ctx.io().send(node, GridTopic.TOPIC_QUERY, msg, QUERY_POOL);
+ }
+ catch (Exception e) {
+ U.warn(log, "Failed to send retry message: " + e.getMessage());
+ }
}
/**
@@ -626,6 +754,44 @@ public class GridMapQueryExecutor {
}
}
+
+ /**
+ *
+ */
+ private static class NodeResults {
+ /** */
+ private final ConcurrentMap<Long, QueryResults> res = new ConcurrentHashMap8<>();
+
+ /** */
+ private final GridBoundedConcurrentLinkedHashMap<Long, Boolean> qryHist =
+ new GridBoundedConcurrentLinkedHashMap<>(1024, 1024, 0.75f, 64, PER_SEGMENT_Q);
+
+ /**
+ * @return All results.
+ */
+ ConcurrentMap<Long, QueryResults> results() {
+ return res;
+ }
+
+ /**
+ * @param qryId Query ID.
+ * @return {@code False} if query was already cancelled.
+ */
+ boolean cancelled(long qryId) {
+ return qryHist.get(qryId) != null;
+ }
+
+ /**
+ * @param qryId Query ID.
+ * @return {@code True} if cancelled.
+ */
+ boolean onCancel(long qryId) {
+ Boolean old = qryHist.putIfAbsent(qryId, Boolean.FALSE);
+
+ return old == null;
+ }
+ }
+
/**
*
*/
@@ -637,7 +803,7 @@ public class GridMapQueryExecutor {
private final AtomicReferenceArray<QueryResult> results;
/** */
- private final GridCacheContext<?,?> cctx;
+ private final GridCacheContext<?, ?> cctx;
/** */
private volatile boolean canceled;
@@ -687,6 +853,9 @@ public class GridMapQueryExecutor {
return true;
}
+ /**
+ *
+ */
void cancel() {
if (canceled)
return;
@@ -728,7 +897,7 @@ public class GridMapQueryExecutor {
private int page;
/** */
- private final int rowCount;
+ private final int rowCnt;
/** */
private volatile boolean closed;
@@ -752,7 +921,7 @@ public class GridMapQueryExecutor {
throw new IllegalStateException(e); // Must not happen.
}
- rowCount = res.getRowCount();
+ rowCnt = res.getRowCount();
cols = res.getVisibleColumnCount();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 3914bd7..796ea66 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
@@ -18,18 +18,22 @@
package org.apache.ignite.internal.processors.query.h2.twostep;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.ConcurrentModificationException;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import javax.cache.CacheException;
import org.apache.ignite.IgniteException;
+import org.apache.ignite.cluster.ClusterNode;
import org.apache.ignite.internal.GridKernalContext;
-import org.h2.engine.Constants;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Cursor;
+import org.apache.ignite.internal.util.typedef.internal.U;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
import org.h2.index.Cursor;
@@ -41,7 +45,6 @@ import org.h2.result.SortOrder;
import org.h2.table.IndexColumn;
import org.h2.table.TableFilter;
import org.jetbrains.annotations.Nullable;
-import org.jsr166.ConcurrentHashMap8;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_SQL_MERGE_TABLE_MAX_SIZE;
import static org.apache.ignite.IgniteSystemProperties.getInteger;
@@ -57,7 +60,7 @@ public abstract class GridMergeIndex extends BaseIndex {
private final AtomicInteger expRowsCnt = new AtomicInteger(0);
/** Remaining rows per source node ID. */
- private final ConcurrentMap<UUID, Counter> remainingRows = new ConcurrentHashMap8<>();
+ private Map<UUID, Counter> remainingRows;
/** */
private final AtomicBoolean lastSubmitted = new AtomicBoolean();
@@ -136,11 +139,19 @@ public abstract class GridMergeIndex extends BaseIndex {
}
/**
- * @param nodeId Node ID.
+ * Set source nodes.
+ *
+ * @param nodes Nodes.
*/
- public void addSource(UUID nodeId) {
- if (remainingRows.put(nodeId, new Counter()) != null)
- throw new IllegalStateException();
+ public void setSources(Collection<ClusterNode> nodes) {
+ assert remainingRows == null;
+
+ remainingRows = U.newHashMap(nodes.size());
+
+ for (ClusterNode node : nodes) {
+ if (remainingRows.put(node.id(), new Counter()) != null)
+ throw new IllegalStateException("Duplicate node id: " + node.id());
+ }
}
/**
@@ -283,8 +294,8 @@ public abstract class GridMergeIndex extends BaseIndex {
}
/** {@inheritDoc} */
- @Override public double getCost(Session ses, int[] masks, TableFilter filter, SortOrder sortOrder) {
- return getRowCountApproximation() + Constants.COST_ROW_OFFSET;
+ @Override public double getCost(Session ses, int[] masks, TableFilter[] filters, int filter, SortOrder sortOrder) {
+ return getCostRangeIndex(masks, getRowCountApproximation(), filters, filter, sortOrder, true);
}
/** {@inheritDoc} */
@@ -318,51 +329,9 @@ public abstract class GridMergeIndex extends BaseIndex {
}
/**
- * Cursor over iterator.
- */
- protected class IteratorCursor implements Cursor {
- /** */
- protected Iterator<Row> iter;
-
- /** */
- protected Row cur;
-
- /**
- * @param iter Iterator.
- */
- public IteratorCursor(Iterator<Row> iter) {
- assert iter != null;
-
- this.iter = iter;
- }
-
- /** {@inheritDoc} */
- @Override public Row get() {
- return cur;
- }
-
- /** {@inheritDoc} */
- @Override public SearchRow getSearchRow() {
- return get();
- }
-
- /** {@inheritDoc} */
- @Override public boolean next() {
- cur = iter.hasNext() ? iter.next() : null;
-
- return cur != null;
- }
-
- /** {@inheritDoc} */
- @Override public boolean previous() {
- throw DbException.getUnsupportedException("previous");
- }
- }
-
- /**
* Fetching cursor.
*/
- protected class FetchingCursor extends IteratorCursor {
+ protected class FetchingCursor extends GridH2Cursor {
/** */
private Iterator<Row> stream;
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 5639340..8a8577f 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
@@ -25,6 +25,8 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import javax.cache.CacheException;
import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2Cursor;
+import org.apache.ignite.internal.processors.query.h2.opt.GridH2RowFactory;
import org.h2.index.Cursor;
import org.h2.index.IndexType;
import org.h2.result.Row;
@@ -73,7 +75,7 @@ public class GridMergeIndexUnsorted extends GridMergeIndex {
/** {@inheritDoc} */
@Override protected Cursor findAllFetched(List<Row> fetched, @Nullable SearchRow first, @Nullable SearchRow last) {
- return new IteratorCursor(fetched.iterator());
+ return new GridH2Cursor(fetched.iterator());
}
/** {@inheritDoc} */
@@ -112,7 +114,7 @@ public class GridMergeIndexUnsorted extends GridMergeIndex {
}
@Override public Row next() {
- return new Row(iter.next(), 0);
+ return GridH2RowFactory.create(iter.next());
}
@Override public void remove() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeTable.java
index a86cbcd..1489021 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeTable.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMergeTable.java
@@ -50,8 +50,8 @@ public class GridMergeTable extends TableBase {
}
/** {@inheritDoc} */
- @Override public void lock(Session session, boolean exclusive, boolean force) {
- // No-op.
+ @Override public boolean lock(Session session, boolean exclusive, boolean force) {
+ return false;
}
/** {@inheritDoc} */
[05/50] [abbrv] ignite git commit: ignite-3300 Fixed potential race.
Posted by vo...@apache.org.
ignite-3300 Fixed potential race.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/d88f7787
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d88f7787
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d88f7787
Branch: refs/heads/ignite-3553
Commit: d88f7787dfcd7cc6207a3a8f7416130f8c2fe757
Parents: 2007cf8
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jul 22 16:32:26 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 22 16:32:53 2016 +0300
----------------------------------------------------------------------
.../processors/cache/GridCacheAffinityManager.java | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/d88f7787/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
index 5e843dc..d182bb4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
@@ -197,15 +197,21 @@ public class GridCacheAffinityManager extends GridCacheManagerAdapter {
public int partition(Object key) {
GridAffinityAssignmentCache aff0 = aff;
- if (key instanceof KeyCacheObject && ((KeyCacheObject)key).partition() != -1)
- return ((KeyCacheObject)key).partition();
+ boolean keyObj = key instanceof KeyCacheObject;
+
+ if (key instanceof KeyCacheObject) {
+ int part = ((KeyCacheObject)key).partition();
+
+ if (part != -1)
+ return part;
+ }
if (aff0 == null)
throw new IgniteException(FAILED_TO_FIND_CACHE_ERR_MSG + cctx.name());
int p = affFunction.partition(affinityKey(key));
- if (key instanceof KeyCacheObject)
+ if (keyObj)
((KeyCacheObject)key).partition(p);
return p;
[33/50] [abbrv] ignite git commit: IGNITE-3349 .NET: Ignition.Start
overload with a custom config file
Posted by vo...@apache.org.
IGNITE-3349 .NET: Ignition.Start overload with a custom config file
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e7547248
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e7547248
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e7547248
Branch: refs/heads/ignite-3553
Commit: e7547248b077275ea2d7eb4bbd8382b054e95f2b
Parents: 3af756d
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Jul 26 15:33:39 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Jul 26 15:33:39 2016 +0300
----------------------------------------------------------------------
.../Apache.Ignite.Core.Tests.csproj | 3 ++
.../IgniteConfigurationSectionTest.cs | 32 ++++++++++++++++
.../IgniteStartStopTest.cs | 3 +-
.../Apache.Ignite.Core.Tests/custom_app.config | 34 +++++++++++++++++
.../dotnet/Apache.Ignite.Core/Ignition.cs | 40 +++++++++++++++++++-
.../dotnet/Apache.Ignite/Config/Configurator.cs | 11 +++---
6 files changed, 116 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e7547248/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
index 5c10612..4e33a91 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj
@@ -291,6 +291,9 @@
<ItemGroup>
<None Include="Apache.Ignite.Core.Tests.nunit" />
<None Include="Apache.Ignite.Core.Tests.snk" />
+ <None Include="custom_app.config">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
<None Include="app.config" />
<Content Include="Config\ignite-dotnet-cfg.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
http://git-wip-us.apache.org/repos/asf/ignite/blob/e7547248/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
index 29aea90..4e10a2b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteConfigurationSectionTest.cs
@@ -64,6 +64,38 @@ namespace Apache.Ignite.Core.Tests
{
Assert.IsTrue(ignite.Name.StartsWith("myGrid"));
}
+
+ using (var ignite = Ignition.StartFromApplicationConfiguration(
+ "igniteConfiguration3", "custom_app.config"))
+ {
+ Assert.AreEqual("myGrid3", ignite.Name);
+ }
+ }
+
+ /// <summary>
+ /// Tests the ignite start error.
+ /// </summary>
+ [Test]
+ public void TestIgniteStartError()
+ {
+ var ex = Assert.Throws<ConfigurationErrorsException>(() =>
+ Ignition.StartFromApplicationConfiguration("igniteConfiguration111"));
+
+ Assert.AreEqual("Could not find IgniteConfigurationSection with name 'igniteConfiguration111'",
+ ex.Message);
+
+
+ ex = Assert.Throws<ConfigurationErrorsException>(() =>
+ Ignition.StartFromApplicationConfiguration("igniteConfiguration", "somefile"));
+
+ Assert.AreEqual("Specified config file does not exist: somefile", ex.Message);
+
+
+ ex = Assert.Throws<ConfigurationErrorsException>(() =>
+ Ignition.StartFromApplicationConfiguration("igniteConfiguration", "custom_app.config"));
+
+ Assert.AreEqual("Could not find IgniteConfigurationSection with name 'igniteConfiguration' " +
+ "in file 'custom_app.config'", ex.Message);
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e7547248/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
index 47212fc..b863308 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/IgniteStartStopTest.cs
@@ -125,6 +125,7 @@ namespace Apache.Ignite.Core.Tests
Assert.AreSame(grid3, Ignition.GetIgnite(null));
Assert.AreSame(grid3, Ignition.TryGetIgnite(null));
+ Assert.AreSame(grid3, Ignition.TryGetIgnite());
Assert.Throws<IgniteException>(() => Ignition.GetIgnite("invalid_name"));
Assert.IsNull(Ignition.TryGetIgnite("invalid_name"));
@@ -365,7 +366,7 @@ namespace Apache.Ignite.Core.Tests
});
// Wait for remote node to join
- Assert.IsTrue(grid.WaitTopology(2, 30000));
+ Assert.IsTrue(grid.WaitTopology(2));
// Wait some more for initialization
Thread.Sleep(1000);
http://git-wip-us.apache.org/repos/asf/ignite/blob/e7547248/modules/platforms/dotnet/Apache.Ignite.Core.Tests/custom_app.config
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/custom_app.config b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/custom_app.config
new file mode 100644
index 0000000..41ea39e
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/custom_app.config
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ 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.
+-->
+
+<configuration>
+ <configSections>
+ <section name="igniteConfiguration3" type="Apache.Ignite.Core.IgniteConfigurationSection, Apache.Ignite.Core" />
+ </configSections>
+
+ <igniteConfiguration3 gridName="myGrid3" localhost="127.0.0.1">
+ <discoverySpi type="TcpDiscoverySpi">
+ <ipFinder type="TcpDiscoveryStaticIpFinder">
+ <endpoints>
+ <string>127.0.0.1:47500</string>
+ </endpoints>
+ </ipFinder>
+ </discoverySpi>
+ </igniteConfiguration3>
+</configuration>
http://git-wip-us.apache.org/repos/asf/ignite/blob/e7547248/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
index 7fbd100..c9ff3ff 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Ignition.cs
@@ -157,10 +157,48 @@ namespace Apache.Ignite.Core
}
/// <summary>
+ /// Reads <see cref="IgniteConfiguration" /> from application configuration
+ /// <see cref="IgniteConfigurationSection" /> with specified name and starts Ignite.
+ /// </summary>
+ /// <param name="sectionName">Name of the section.</param>
+ /// <param name="configPath">Path to the configuration file.</param>
+ /// <returns>Started Ignite.</returns>
+ public static IIgnite StartFromApplicationConfiguration(string sectionName, string configPath)
+ {
+ IgniteArgumentCheck.NotNullOrEmpty(sectionName, "sectionName");
+ IgniteArgumentCheck.NotNullOrEmpty(configPath, "configPath");
+
+ var fileMap = GetConfigMap(configPath);
+ var config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
+
+ var section = config.GetSection(sectionName) as IgniteConfigurationSection;
+
+ if (section == null)
+ throw new ConfigurationErrorsException(
+ string.Format("Could not find {0} with name '{1}' in file '{2}'",
+ typeof(IgniteConfigurationSection).Name, sectionName, configPath));
+
+ return Start(section.IgniteConfiguration);
+ }
+
+ /// <summary>
+ /// Gets the configuration file map.
+ /// </summary>
+ private static ExeConfigurationFileMap GetConfigMap(string fileName)
+ {
+ var fullFileName = Path.GetFullPath(fileName);
+
+ if (!File.Exists(fullFileName))
+ throw new ConfigurationErrorsException("Specified config file does not exist: " + fileName);
+
+ return new ExeConfigurationFileMap { ExeConfigFilename = fullFileName };
+ }
+
+ /// <summary>
/// Starts Ignite with given configuration.
/// </summary>
/// <returns>Started Ignite.</returns>
- public unsafe static IIgnite Start(IgniteConfiguration cfg)
+ public static unsafe IIgnite Start(IgniteConfiguration cfg)
{
IgniteArgumentCheck.NotNull(cfg, "cfg");
http://git-wip-us.apache.org/repos/asf/ignite/blob/e7547248/modules/platforms/dotnet/Apache.Ignite/Config/Configurator.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite/Config/Configurator.cs b/modules/platforms/dotnet/Apache.Ignite/Config/Configurator.cs
index c595de1..5f73a6d 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Config/Configurator.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Config/Configurator.cs
@@ -75,7 +75,8 @@ namespace Apache.Ignite.Config
foreach (var arg in args)
{
- Func<string, bool> argIs = x => arg.Item1.Equals(x, StringComparison.OrdinalIgnoreCase);
+ var arg0 = arg; // copy captured variable
+ Func<string, bool> argIs = x => arg0.Item1.Equals(x, StringComparison.OrdinalIgnoreCase);
if (argIs(CmdIgniteHome))
cfg.IgniteHome = arg.Item2;
@@ -152,12 +153,12 @@ namespace Apache.Ignite.Config
/// </summary>
private static ExeConfigurationFileMap GetConfigMap(string fileName)
{
- fileName = Path.GetFullPath(fileName);
+ var fullFileName = Path.GetFullPath(fileName);
- if (!File.Exists(fileName))
- throw new InvalidOperationException("Specified config file does not exist: " + fileName);
+ if (!File.Exists(fullFileName))
+ throw new ConfigurationErrorsException("Specified config file does not exist: " + fileName);
- return new ExeConfigurationFileMap {ExeConfigFilename = fileName};
+ return new ExeConfigurationFileMap {ExeConfigFilename = fullFileName};
}
/// <summary>
[43/50] [abbrv] ignite git commit: Merge remote-tracking branch
'apache/ignite-1.7' into ignite-1.7
Posted by vo...@apache.org.
Merge remote-tracking branch 'apache/ignite-1.7' into ignite-1.7
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/77781e97
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/77781e97
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/77781e97
Branch: refs/heads/ignite-3553
Commit: 77781e97b2736d74217f08daa8e82c419456a26a
Parents: 87a7c79 db99bec
Author: Andrey Novikov <an...@apache.org>
Authored: Wed Jul 27 17:57:13 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Jul 27 17:57:13 2016 +0700
----------------------------------------------------------------------
----------------------------------------------------------------------
[27/50] [abbrv] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.6.3' into UPSTREAM_master
Posted by vo...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.6.3' into UPSTREAM_master
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/37195a02
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/37195a02
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/37195a02
Branch: refs/heads/ignite-3553
Commit: 37195a024abf16de152dc06914cb88dfbffb1397
Parents: f245c38 332c8c2
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Mon Jul 25 16:13:39 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Mon Jul 25 16:13:39 2016 +0300
----------------------------------------------------------------------
.../internal/processors/igfs/IgfsImpl.java | 12 +-
.../processors/igfs/IgfsMetaManager.java | 115 ++++---
.../igfs/IgfsSecondaryFileSystemImpl.java | 15 +-
.../igfs/IgfsSecondaryFileSystemV2.java | 40 +++
.../processors/igfs/IgfsAbstractSelfTest.java | 111 ++++++-
.../igfs/IgfsDualAbstractSelfTest.java | 34 ++
.../igfs/IgfsExUniversalFileSystemAdapter.java | 15 +
.../igfs/UniversalFileSystemAdapter.java | 11 +
.../fs/IgniteHadoopIgfsSecondaryFileSystem.java | 16 +-
...oopFileSystemUniversalFileSystemAdapter.java | 8 +
.../Binary/BinaryBuilderSelfTest.cs | 325 +++++++++++++++----
.../Binary/IBinaryObjectBuilder.cs | 2 +-
.../Impl/Binary/BinaryObjectBuilder.cs | 16 +-
.../Impl/Binary/BinaryWriter.cs | 133 +++++---
.../commands/cache/VisorCacheStopCommand.scala | 5 +-
15 files changed, 664 insertions(+), 194 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/37195a02/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/37195a02/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
----------------------------------------------------------------------
[45/50] [abbrv] ignite git commit: IGNITE-3591 .NET: Fix self-joins
in LINQ
Posted by vo...@apache.org.
IGNITE-3591 .NET: Fix self-joins in LINQ
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f96b568e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f96b568e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f96b568e
Branch: refs/heads/ignite-3553
Commit: f96b568e662758a915309fe631c5bec4fd0ccdfe
Parents: 2f36ae5
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Wed Jul 27 15:25:59 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Wed Jul 27 15:25:59 2016 +0300
----------------------------------------------------------------------
.../Cache/Query/CacheLinqTest.cs | 18 +++++
.../Apache.Ignite.Linq/Impl/AliasDictionary.cs | 74 ++++++++++++++++----
.../Impl/CacheQueryExpressionVisitor.cs | 4 +-
.../Impl/CacheQueryModelVisitor.cs | 6 +-
.../Apache.Ignite.Linq/Impl/ExpressionWalker.cs | 34 ++++-----
5 files changed, 96 insertions(+), 40 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/f96b568e/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
index 679f03a..70c5fb5 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Cache/Query/CacheLinqTest.cs
@@ -537,6 +537,24 @@ namespace Apache.Ignite.Core.Tests.Cache.Query
}
/// <summary>
+ /// Tests the join of a table to itself.
+ /// </summary>
+ [Test]
+ public void TestSelfJoin()
+ {
+ // Different queryables
+ var p1 = GetPersonCache().AsCacheQueryable();
+ var p2 = GetPersonCache().AsCacheQueryable();
+
+ var qry = p1.Join(p2, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+ Assert.AreEqual(PersonCount, qry.ToArray().Distinct().Count());
+
+ // Same queryables
+ var qry2 = p1.Join(p1, x => x.Value.Age, x => x.Key, (x, y) => x.Key);
+ Assert.AreEqual(PersonCount, qry2.ToArray().Distinct().Count());
+ }
+
+ /// <summary>
/// Tests the group by.
/// </summary>
[Test]
http://git-wip-us.apache.org/repos/asf/ignite/blob/f96b568e/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/AliasDictionary.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/AliasDictionary.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/AliasDictionary.cs
index 10a414c..5fd890d 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/AliasDictionary.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/AliasDictionary.cs
@@ -17,10 +17,13 @@
namespace Apache.Ignite.Linq.Impl
{
+ using System;
using System.Collections.Generic;
using System.Diagnostics;
+ using System.Linq.Expressions;
using System.Text;
using Remotion.Linq.Clauses;
+ using Remotion.Linq.Clauses.Expressions;
/// <summary>
/// Alias dictionary.
@@ -31,10 +34,10 @@ namespace Apache.Ignite.Linq.Impl
private int _aliasIndex;
/** */
- private Dictionary<string, string> _aliases = new Dictionary<string, string>();
+ private Dictionary<IQuerySource, string> _aliases = new Dictionary<IQuerySource, string>();
/** */
- private readonly Stack<Dictionary<string, string>> _stack = new Stack<Dictionary<string, string>>();
+ private readonly Stack<Dictionary<IQuerySource, string>> _stack = new Stack<Dictionary<IQuerySource, string>>();
/// <summary>
/// Pushes current aliases to stack.
@@ -43,7 +46,7 @@ namespace Apache.Ignite.Linq.Impl
{
_stack.Push(_aliases);
- _aliases = new Dictionary<string, string>();
+ _aliases = new Dictionary<IQuerySource, string>();
}
/// <summary>
@@ -57,27 +60,34 @@ namespace Apache.Ignite.Linq.Impl
/// <summary>
/// Gets the table alias.
/// </summary>
- public string GetTableAlias(ICacheQueryableInternal queryable)
+ public string GetTableAlias(Expression expression)
{
- Debug.Assert(queryable != null);
+ Debug.Assert(expression != null);
- return GetTableAlias(ExpressionWalker.GetTableNameWithSchema(queryable));
+ return GetTableAlias(GetQuerySource(expression));
}
- /// <summary>
- /// Gets the table alias.
- /// </summary>
- public string GetTableAlias(string fullName)
+ public string GetTableAlias(IFromClause fromClause)
{
- Debug.Assert(!string.IsNullOrEmpty(fullName));
+ return GetTableAlias(GetQuerySource(fromClause.FromExpression) ?? fromClause);
+ }
+
+ public string GetTableAlias(JoinClause joinClause)
+ {
+ return GetTableAlias(GetQuerySource(joinClause.InnerSequence) ?? joinClause);
+ }
+
+ private string GetTableAlias(IQuerySource querySource)
+ {
+ Debug.Assert(querySource != null);
string alias;
- if (!_aliases.TryGetValue(fullName, out alias))
+ if (!_aliases.TryGetValue(querySource, out alias))
{
alias = "_T" + _aliasIndex++;
- _aliases[fullName] = alias;
+ _aliases[querySource] = alias;
}
return alias;
@@ -94,9 +104,45 @@ namespace Apache.Ignite.Linq.Impl
var queryable = ExpressionWalker.GetCacheQueryable(clause);
var tableName = ExpressionWalker.GetTableNameWithSchema(queryable);
- builder.AppendFormat("{0} as {1}", tableName, GetTableAlias(tableName));
+ builder.AppendFormat("{0} as {1}", tableName, GetTableAlias(clause));
return builder;
}
+
+ /// <summary>
+ /// Gets the query source.
+ /// </summary>
+ private static IQuerySource GetQuerySource(Expression expression)
+ {
+ var subQueryExp = expression as SubQueryExpression;
+
+ if (subQueryExp != null)
+ return GetQuerySource(subQueryExp.QueryModel.MainFromClause.FromExpression)
+ ?? subQueryExp.QueryModel.MainFromClause;
+
+ var srcRefExp = expression as QuerySourceReferenceExpression;
+
+ if (srcRefExp != null)
+ {
+ var fromSource = srcRefExp.ReferencedQuerySource as IFromClause;
+
+ if (fromSource != null)
+ return GetQuerySource(fromSource.FromExpression) ?? fromSource;
+
+ var joinSource = srcRefExp.ReferencedQuerySource as JoinClause;
+
+ if (joinSource != null)
+ return GetQuerySource(joinSource.InnerSequence) ?? joinSource;
+
+ throw new NotSupportedException("Unexpected query source: " + srcRefExp.ReferencedQuerySource);
+ }
+
+ var memberExpr = expression as MemberExpression;
+
+ if (memberExpr != null)
+ return GetQuerySource(memberExpr.Expression);
+
+ return null;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/f96b568e/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
index eaca07a..2362137 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryExpressionVisitor.cs
@@ -248,7 +248,7 @@ namespace Apache.Ignite.Linq.Impl
// In other cases we need both parts of cache entry
var format = _useStar ? "{0}.*" : "{0}._key, {0}._val";
- var tableName = Aliases.GetTableAlias(ExpressionWalker.GetCacheQueryable(expression));
+ var tableName = Aliases.GetTableAlias(expression);
ResultBuilder.AppendFormat(format, tableName);
@@ -283,7 +283,7 @@ namespace Apache.Ignite.Linq.Impl
{
var fieldName = GetFieldName(expression, queryable);
- ResultBuilder.AppendFormat("{0}.{1}", Aliases.GetTableAlias(queryable), fieldName);
+ ResultBuilder.AppendFormat("{0}.{1}", Aliases.GetTableAlias(expression), fieldName);
}
else
AppendParameter(RegisterEvaluatedParameter(expression));
http://git-wip-us.apache.org/repos/asf/ignite/blob/f96b568e/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
index 1888414..a8c4c67 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/CacheQueryModelVisitor.cs
@@ -418,8 +418,7 @@ namespace Apache.Ignite.Linq.Impl
VisitQueryModel(subQuery.QueryModel, true);
- var queryable = ExpressionWalker.GetCacheQueryable(subQuery.QueryModel.MainFromClause);
- var alias = _aliases.GetTableAlias(queryable);
+ var alias = _aliases.GetTableAlias(subQuery.QueryModel.MainFromClause);
_builder.AppendFormat(") as {0} on (", alias);
}
else
@@ -437,7 +436,8 @@ namespace Apache.Ignite.Linq.Impl
var queryable = ExpressionWalker.GetCacheQueryable(joinClause);
var tableName = ExpressionWalker.GetTableNameWithSchema(queryable);
- _builder.AppendFormat("inner join {0} as {1} on (", tableName, _aliases.GetTableAlias(tableName));
+ var alias = _aliases.GetTableAlias(joinClause);
+ _builder.AppendFormat("inner join {0} as {1} on (", tableName, alias);
}
BuildJoinCondition(joinClause.InnerKeySelector, joinClause.OuterKeySelector);
http://git-wip-us.apache.org/repos/asf/ignite/blob/f96b568e/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
index 96371cc..bd57e3f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Impl/ExpressionWalker.cs
@@ -38,26 +38,6 @@ namespace Apache.Ignite.Linq.Impl
/// <summary>
/// Gets the cache queryable.
/// </summary>
- public static ICacheQueryableInternal GetCacheQueryable(QuerySourceReferenceExpression expression)
- {
- Debug.Assert(expression != null);
-
- var fromSource = expression.ReferencedQuerySource as IFromClause;
-
- if (fromSource != null)
- return GetCacheQueryable(fromSource);
-
- var joinSource = expression.ReferencedQuerySource as JoinClause;
-
- if (joinSource != null)
- return GetCacheQueryable(joinSource);
-
- throw new NotSupportedException("Unexpected query source: " + expression.ReferencedQuerySource);
- }
-
- /// <summary>
- /// Gets the cache queryable.
- /// </summary>
public static ICacheQueryableInternal GetCacheQueryable(IFromClause fromClause)
{
return GetCacheQueryable(fromClause.FromExpression);
@@ -84,7 +64,19 @@ namespace Apache.Ignite.Linq.Impl
var srcRefExp = expression as QuerySourceReferenceExpression;
if (srcRefExp != null)
- return GetCacheQueryable(srcRefExp);
+ {
+ var fromSource = srcRefExp.ReferencedQuerySource as IFromClause;
+
+ if (fromSource != null)
+ return GetCacheQueryable(fromSource);
+
+ var joinSource = srcRefExp.ReferencedQuerySource as JoinClause;
+
+ if (joinSource != null)
+ return GetCacheQueryable(joinSource);
+
+ throw new NotSupportedException("Unexpected query source: " + srcRefExp.ReferencedQuerySource);
+ }
var memberExpr = expression as MemberExpression;
[21/50] [abbrv] ignite git commit: IGNITE-2344 WebSessionFilter
doesn't support session ID renewal
Posted by vo...@apache.org.
IGNITE-2344 WebSessionFilter doesn't support session ID renewal
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/58d05444
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/58d05444
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/58d05444
Branch: refs/heads/ignite-3553
Commit: 58d054443d48f2ef48e935bd4e5ce24b5bb352ed
Parents: df1490e
Author: samaitra <sa...@gmail.com>
Authored: Mon Jul 25 10:54:35 2016 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Mon Jul 25 10:54:35 2016 +0300
----------------------------------------------------------------------
.../ignite/internal/websession/WebSessionSelfTest.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/58d05444/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java b/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
index 0ab1130..1a8c328 100644
--- a/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
+++ b/modules/web/src/test/java/org/apache/ignite/internal/websession/WebSessionSelfTest.java
@@ -854,7 +854,7 @@ public class WebSessionSelfTest extends GridCommonAbstractTest {
HashLoginService hashLoginService = new HashLoginService();
hashLoginService.setName("Test Realm");
createRealm();
- hashLoginService.setConfig("realm.properties");
+ hashLoginService.setConfig("/tmp/realm.properties");
ctx.getSecurityHandler().setLoginService(hashLoginService);
srv.setHandler(ctx);
@@ -884,14 +884,14 @@ public class WebSessionSelfTest extends GridCommonAbstractTest {
private void stopServerWithLoginService(@Nullable Server srv) throws Exception{
if (srv != null){
srv.stop();
- File realmFile = new File("realm.properties");
+ File realmFile = new File("/tmp/realm.properties");
realmFile.delete();
}
}
/** Creates a realm file to store test user credentials */
private void createRealm() throws Exception{
- File realmFile = new File("realm.properties");
+ File realmFile = new File("/tmp/realm.properties");
FileWriter fileWriter = new FileWriter(realmFile);
fileWriter.append("admin:admin");
fileWriter.flush();
@@ -1128,7 +1128,7 @@ public class WebSessionSelfTest extends GridCommonAbstractTest {
try {
req.login("admin", "admin");
} catch (Exception e) {
- X.printerrln("Login failed.");
+ X.printerrln("Login failed due to exception.", e);
}
HttpSession session = req.getSession();
[41/50] [abbrv] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.6.3'
Posted by vo...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.6.3'
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/87a7c79b
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/87a7c79b
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/87a7c79b
Branch: refs/heads/ignite-3553
Commit: 87a7c79b5a59470ae7ec59867b765b5e6c586140
Parents: 34d553a 4979c87
Author: Andrey Novikov <an...@apache.org>
Authored: Wed Jul 27 17:51:26 2016 +0700
Committer: Andrey Novikov <an...@apache.org>
Committed: Wed Jul 27 17:51:26 2016 +0700
----------------------------------------------------------------------
.../visor/node/VisorNodeDataCollectorJob.java | 25 +++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
[30/50] [abbrv] ignite git commit: IGNITE-3509 .NET: Add missing
package-info, include LINQ and AspNet in doxygen
Posted by vo...@apache.org.
IGNITE-3509 .NET: Add missing package-info, include LINQ and AspNet in doxygen
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/e70adde7
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/e70adde7
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/e70adde7
Branch: refs/heads/ignite-3553
Commit: e70adde719009e99e56bb4398c6fa3e43cf6b2ca
Parents: 44cabd8
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Tue Jul 26 10:47:49 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Tue Jul 26 10:47:49 2016 +0300
----------------------------------------------------------------------
.../Apache.Ignite.AspNet.csproj | 1 +
.../dotnet/Apache.Ignite.AspNet/Package-Info.cs | 26 ++++
.../Apache.Ignite.Core.csproj | 6 +
.../Cache/Affinity/AffinityFunctionBase.cs | 139 -------------------
.../Configuration/Package-Info.cs | 26 ++++
.../Discovery/Package-Info.cs | 26 ++++
.../Discovery/Tcp/Multicast/Package-Info.cs | 26 ++++
.../Discovery/Tcp/Package-Info.cs | 26 ++++
.../Discovery/Tcp/Static/Package-Info.cs | 26 ++++
.../Apache.Ignite.Core/Interop/Package-Info.cs | 26 ++++
.../Apache.Ignite.Linq.csproj | 1 +
.../dotnet/Apache.Ignite.Linq/Package-Info.cs | 26 ++++
modules/platforms/dotnet/Apache.Ignite.dxg | 4 +-
13 files changed, 218 insertions(+), 141 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj b/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
index b18119e..0c273e0 100644
--- a/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.AspNet/Apache.Ignite.AspNet.csproj
@@ -48,6 +48,7 @@
<ItemGroup>
<Compile Include="IgniteOutputCacheProvider.cs" />
<Compile Include="IgniteWebUtils.cs" />
+ <Compile Include="Package-Info.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.AspNet/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.AspNet/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.AspNet/Package-Info.cs
new file mode 100644
index 0000000..5e74d3c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.AspNet/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Ignite ASP.NET integration.
+/// </summary>
+namespace Apache.Ignite.AspNet
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
index 2e374e5..59bf090 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj
@@ -85,6 +85,11 @@
<ItemGroup>
<Compile Include="Binary\BinaryReflectiveSerializer.cs" />
<Compile Include="Common\JavaException.cs" />
+ <Compile Include="DataStructures\Configuration\Package-Info.cs" />
+ <Compile Include="Discovery\Package-Info.cs" />
+ <Compile Include="Discovery\Tcp\Multicast\Package-Info.cs" />
+ <Compile Include="Discovery\Tcp\Package-Info.cs" />
+ <Compile Include="Discovery\Tcp\Static\Package-Info.cs" />
<Compile Include="Impl\Binary\BinaryReflectiveSerializerInternal.cs" />
<Compile Include="Impl\Binary\IBinarySerializerInternal.cs" />
<Compile Include="Binary\Package-Info.cs" />
@@ -427,6 +432,7 @@
<Compile Include="Impl\Unmanaged\UnmanagedTarget.cs" />
<Compile Include="Impl\Unmanaged\UnmanagedUtils.cs" />
<Compile Include="Interop\JavaObject.cs" />
+ <Compile Include="Interop\Package-Info.cs" />
<Compile Include="Lifecycle\ClientReconnectEventArgs.cs" />
<Compile Include="Lifecycle\Package-Info.cs" />
<Compile Include="Messaging\Package-Info.cs" />
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs
deleted file mode 100644
index ce2e5e1..0000000
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Cache/Affinity/AffinityFunctionBase.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-\ufeff/*
- * 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.
- */
-
-namespace Apache.Ignite.Core.Cache.Affinity
-{
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using Apache.Ignite.Core.Cluster;
- using Apache.Ignite.Core.Common;
-
- /// <summary>
- /// Base class for predefined affinity functions.
- /// </summary>
- [Serializable]
- public abstract class AffinityFunctionBase : IAffinityFunction
- {
- /// <summary> The default value for <see cref="Partitions"/> property. </summary>
- public const int DefaultPartitions = 1024;
-
- /** */
- private int _partitions = DefaultPartitions;
-
- /** */
- private IAffinityFunction _baseFunction;
-
-
- /// <summary>
- /// Gets or sets the total number of partitions.
- /// </summary>
- [DefaultValue(DefaultPartitions)]
- public virtual int Partitions
- {
- get { return _partitions; }
- set { _partitions = value; }
- }
-
- /// <summary>
- /// Gets partition number for a given key starting from 0. Partitioned caches
- /// should make sure that keys are about evenly distributed across all partitions
- /// from 0 to <see cref="Partitions" /> for best performance.
- /// <para />
- /// Note that for fully replicated caches it is possible to segment key sets among different
- /// grid node groups. In that case each node group should return a unique partition
- /// number. However, unlike partitioned cache, mappings of keys to nodes in
- /// replicated caches are constant and a node cannot migrate from one partition
- /// to another.
- /// </summary>
- /// <param name="key">Key to get partition for.</param>
- /// <returns>
- /// Partition number for a given key.
- /// </returns>
- public virtual int GetPartition(object key)
- {
- ThrowIfUninitialized();
-
- return _baseFunction.GetPartition(key);
- }
-
- /// <summary>
- /// Removes node from affinity. This method is called when it is safe to remove
- /// disconnected node from affinity mapping.
- /// </summary>
- /// <param name="nodeId">The node identifier.</param>
- public virtual void RemoveNode(Guid nodeId)
- {
- ThrowIfUninitialized();
-
- _baseFunction.RemoveNode(nodeId);
- }
-
- /// <summary>
- /// Gets affinity nodes for a partition. In case of replicated cache, all returned
- /// nodes are updated in the same manner. In case of partitioned cache, the returned
- /// list should contain only the primary and back up nodes with primary node being
- /// always first.
- /// <pare />
- /// Note that partitioned affinity must obey the following contract: given that node
- /// <code>N</code> is primary for some key <code>K</code>, if any other node(s) leave
- /// grid and no node joins grid, node <code>N</code> will remain primary for key <code>K</code>.
- /// </summary>
- /// <param name="context">The affinity function context.</param>
- /// <returns>
- /// A collection of partitions, where each partition is a collection of nodes,
- /// where first node is a primary node, and other nodes are backup nodes.
- /// </returns>
- public virtual IEnumerable<IEnumerable<IClusterNode>> AssignPartitions(AffinityFunctionContext context)
- {
- ThrowIfUninitialized();
-
- return _baseFunction.AssignPartitions(context);
- }
-
- /// <summary>
- /// Gets or sets a value indicating whether to exclude same-host-neighbors from being backups of each other.
- /// </summary>
- public virtual bool ExcludeNeighbors { get; set; }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AffinityFunctionBase"/> class.
- /// </summary>
- internal AffinityFunctionBase()
- {
- // No-op.
- }
-
- /// <summary>
- /// Sets the base function.
- /// </summary>
- /// <param name="baseFunc">The base function.</param>
- internal void SetBaseFunction(IAffinityFunction baseFunc)
- {
- _baseFunction = baseFunc;
- }
-
- /// <summary>
- /// Gets the direct usage error.
- /// </summary>
- private void ThrowIfUninitialized()
- {
- if (_baseFunction == null)
- throw new IgniteException(GetType() + " has not yet been initialized.");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/DataStructures/Configuration/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/DataStructures/Configuration/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/DataStructures/Configuration/Package-Info.cs
new file mode 100644
index 0000000..aa6cdfd
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/DataStructures/Configuration/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Distributed data structures configuration.
+/// </summary>
+namespace Apache.Ignite.Core.DataStructures.Configuration
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Package-Info.cs
new file mode 100644
index 0000000..c6fadec
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Node discovery API.
+/// </summary>
+namespace Apache.Ignite.Core.Discovery
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/Package-Info.cs
new file mode 100644
index 0000000..0a1c751
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Multicast/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Multicast TCP discovery.
+/// </summary>
+namespace Apache.Ignite.Core.Discovery.Tcp.Multicast
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Package-Info.cs
new file mode 100644
index 0000000..dc94d48
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// TCP node discovery API.
+/// </summary>
+namespace Apache.Ignite.Core.Discovery.Tcp
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Static/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Static/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Static/Package-Info.cs
new file mode 100644
index 0000000..bf3fa5c
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Discovery/Tcp/Static/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Static TCP discovery.
+/// </summary>
+namespace Apache.Ignite.Core.Discovery.Tcp.Static
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Core/Interop/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Interop/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Interop/Package-Info.cs
new file mode 100644
index 0000000..51f26df
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Interop/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Platform interoperability.
+/// </summary>
+namespace Apache.Ignite.Core.Interop
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj b/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
index d1dad16..3abfa56 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Apache.Ignite.Linq.csproj
@@ -69,6 +69,7 @@
<Compile Include="Impl\QueryData.cs" />
<Compile Include="Impl\SqlTypes.cs" />
<Compile Include="Impl\ExpressionWalker.cs" />
+ <Compile Include="Package-Info.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.Linq/Package-Info.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Linq/Package-Info.cs b/modules/platforms/dotnet/Apache.Ignite.Linq/Package-Info.cs
new file mode 100644
index 0000000..1c1e370
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.Linq/Package-Info.cs
@@ -0,0 +1,26 @@
+\ufeff/*
+* 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.
+*/
+
+#pragma warning disable 1587 // invalid XML comment
+
+/// <summary>
+/// Ignite cache LINQ provider.
+/// </summary>
+namespace Apache.Ignite.Linq
+{
+ // No-op.
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/e70adde7/modules/platforms/dotnet/Apache.Ignite.dxg
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.dxg b/modules/platforms/dotnet/Apache.Ignite.dxg
index 6337d83..012a1eb 100644
--- a/modules/platforms/dotnet/Apache.Ignite.dxg
+++ b/modules/platforms/dotnet/Apache.Ignite.dxg
@@ -2381,7 +2381,7 @@ GENERATE_LEGEND = YES
DOT_CLEANUP = YES
-;INPUT=Apache.Ignite.Core
-;EXCLUDE=Apache.Ignite.Core/Impl
+;INPUT=Apache.Ignite.Core Apache.Ignite.Linq Apache.Ignite.AspNet
+;EXCLUDE=Apache.Ignite.Core/Impl Apache.Ignite.Linq/Impl
;OUTPUT_DIRECTORY=../../clients/target/dotnetdoc
;PROJECT_LOGO=../../../assembly/docfiles/ignite_logo.png
[32/50] [abbrv] ignite git commit: IGNITE-3323 Get rid of copypasted
JB annotations, use dependency instead.
Posted by vo...@apache.org.
IGNITE-3323 Get rid of copypasted JB annotations, use dependency instead.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3af756d7
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3af756d7
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3af756d7
Branch: refs/heads/ignite-3553
Commit: 3af756d71a68ad195d48bcced50ea92ba3078fad
Parents: fb884ec
Author: Jens Hoffmann <jc...@gmail.com>
Authored: Tue Jul 26 13:04:38 2016 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Tue Jul 26 13:04:38 2016 +0300
----------------------------------------------------------------------
modules/core/pom.xml | 6 ++++
.../java/org/jetbrains/annotations/NotNull.java | 38 --------------------
.../org/jetbrains/annotations/Nullable.java | 33 -----------------
.../org/jetbrains/annotations/package-info.java | 27 --------------
parent/pom.xml | 1 +
5 files changed, 7 insertions(+), 98 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/3af756d7/modules/core/pom.xml
----------------------------------------------------------------------
diff --git a/modules/core/pom.xml b/modules/core/pom.xml
index 5e32caf..7eefa4a 100644
--- a/modules/core/pom.xml
+++ b/modules/core/pom.xml
@@ -69,6 +69,12 @@
</dependency>
<dependency>
+ <groupId>org.jetbrains</groupId>
+ <artifactId>annotations</artifactId>
+ <version>${jetbrains.annotations.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>mx4j</groupId>
<artifactId>mx4j-tools</artifactId>
<version>3.0.1</version>
http://git-wip-us.apache.org/repos/asf/ignite/blob/3af756d7/modules/core/src/main/java/org/jetbrains/annotations/NotNull.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/jetbrains/annotations/NotNull.java b/modules/core/src/main/java/org/jetbrains/annotations/NotNull.java
deleted file mode 100644
index 66c66f3..0000000
--- a/modules/core/src/main/java/org/jetbrains/annotations/NotNull.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2000-2012 JetBrains s.r.o.
- *
- * Licensed 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.jetbrains.annotations;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * An element annotated with NotNull claims <code>null</code> value is <em>forbidden</em>
- * to return (for methods), pass to (parameters) and hold (local variables and fields).
- * Apart from documentation purposes this annotation is intended to be used by static analysis tools
- * to validate against probable runtime errors and element contract violations.
- *
- * @author max
- */
-@Documented
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
-public @interface NotNull {
- String value() default "";
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/3af756d7/modules/core/src/main/java/org/jetbrains/annotations/Nullable.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/jetbrains/annotations/Nullable.java b/modules/core/src/main/java/org/jetbrains/annotations/Nullable.java
deleted file mode 100644
index defd5d8..0000000
--- a/modules/core/src/main/java/org/jetbrains/annotations/Nullable.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed 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.jetbrains.annotations;
-
-import java.lang.annotation.*;
-
-/**
- * An element annotated with Nullable claims <code>null</code> value is perfectly <em>valid</em>
- * to return (for methods), pass to (parameters) and hold (local variables and fields).
- * Apart from documentation purposes this annotation is intended to be used by static analysis tools
- * to validate against probable runtime errors and element contract violations.
- * @author max
- */
-@Documented
-@Retention(RetentionPolicy.CLASS)
-@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE})
-public @interface Nullable {
- String value() default "";
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/3af756d7/modules/core/src/main/java/org/jetbrains/annotations/package-info.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/jetbrains/annotations/package-info.java b/modules/core/src/main/java/org/jetbrains/annotations/package-info.java
deleted file mode 100644
index 02e3be1..0000000
--- a/modules/core/src/main/java/org/jetbrains/annotations/package-info.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * This software includes code from IntelliJ IDEA Community Edition
- * Copyright (C) JetBrains s.r.o.
- * https://www.jetbrains.com/idea/
- */
-
-/**
- * {@code Nullable} and {@code NotNull} annotations.
- */
-package org.jetbrains.annotations;
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/3af756d7/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index ebd6bf0..17f66c9 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -78,6 +78,7 @@
<jackson2.version>2.7.5</jackson2.version>
<javax.cache.bundle.version>1.0.0_1</javax.cache.bundle.version>
<javax.cache.version>1.0.0</javax.cache.version>
+ <jetbrains.annotations.version>15.0</jetbrains.annotations.version>
<jetty.version>9.2.11.v20150529</jetty.version>
<jms.spec.version>1.1.1</jms.spec.version>
<jsch.bundle.version>0.1.53_1</jsch.bundle.version>
[26/50] [abbrv] ignite git commit: IGNITE-3504 .NET: Fix
IBinaryObjectBuilder setter methods
Posted by vo...@apache.org.
IGNITE-3504 .NET: Fix IBinaryObjectBuilder setter methods
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/332c8c2f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/332c8c2f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/332c8c2f
Branch: refs/heads/ignite-3553
Commit: 332c8c2f118226f3cd3c4dc1fa5564dd1d41d19c
Parents: 855281e
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Mon Jul 25 16:12:51 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Mon Jul 25 16:12:51 2016 +0300
----------------------------------------------------------------------
.../Binary/BinaryBuilderSelfTest.cs | 325 +++++++++++++++----
.../Binary/IBinaryObjectBuilder.cs | 2 +-
.../Impl/Binary/BinaryObjectBuilder.cs | 16 +-
.../Impl/Binary/BinaryWriter.cs | 133 +++++---
4 files changed, 345 insertions(+), 131 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/332c8c2f/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
index 40ecc1e..80788a6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs
@@ -595,7 +595,8 @@ namespace Apache.Ignite.Core.Tests.Binary
[Test]
public void TestPrimitiveFields()
{
- IBinaryObject binObj = _grid.GetBinary().GetBuilder(typeof(Primitives))
+ // Generic SetField method.
+ var binObj = _grid.GetBinary().GetBuilder(typeof(Primitives))
.SetField<byte>("fByte", 1)
.SetField("fBool", true)
.SetField<short>("fShort", 2)
@@ -604,16 +605,73 @@ namespace Apache.Ignite.Core.Tests.Binary
.SetField<long>("fLong", 4)
.SetField<float>("fFloat", 5)
.SetField<double>("fDouble", 6)
+ .SetField("fDecimal", 7.7m)
.SetHashCode(100)
.Build();
+ CheckPrimitiveFields1(binObj);
+
+ // Specific setter methods.
+ binObj = _grid.GetBinary().GetBuilder(typeof(Primitives))
+ .SetByteField("fByte", 1)
+ .SetBooleanField("fBool", true)
+ .SetShortField("fShort", 2)
+ .SetCharField("fChar", 'a')
+ .SetIntField("fInt", 3)
+ .SetLongField("fLong", 4)
+ .SetFloatField("fFloat", 5)
+ .SetDoubleField("fDouble", 6)
+ .SetDecimalField("fDecimal", 7.7m)
+ .SetHashCode(100)
+ .Build();
+
+ CheckPrimitiveFields1(binObj);
+
+ // Overwrite with generic methods.
+ binObj = binObj.ToBuilder()
+ .SetField<byte>("fByte", 7)
+ .SetField("fBool", false)
+ .SetField<short>("fShort", 8)
+ .SetField("fChar", 'b')
+ .SetField("fInt", 9)
+ .SetField<long>("fLong", 10)
+ .SetField<float>("fFloat", 11)
+ .SetField<double>("fDouble", 12)
+ .SetField("fDecimal", 13.13m)
+ .SetHashCode(200)
+ .Build();
+
+ CheckPrimitiveFields2(binObj);
+
+ // Overwrite with specific methods.
+ binObj = binObj.ToBuilder()
+ .SetByteField("fByte", 7)
+ .SetBooleanField("fBool", false)
+ .SetShortField("fShort", 8)
+ .SetCharField("fChar", 'b')
+ .SetIntField("fInt", 9)
+ .SetLongField("fLong", 10)
+ .SetFloatField("fFloat", 11)
+ .SetDoubleField("fDouble", 12)
+ .SetDecimalField("fDecimal", 13.13m)
+ .SetHashCode(200)
+ .Build();
+
+ CheckPrimitiveFields2(binObj);
+ }
+
+ /// <summary>
+ /// Checks the primitive fields values.
+ /// </summary>
+ private static void CheckPrimitiveFields1(IBinaryObject binObj)
+ {
Assert.AreEqual(100, binObj.GetHashCode());
IBinaryType meta = binObj.GetBinaryType();
Assert.AreEqual(typeof(Primitives).Name, meta.TypeName);
- Assert.AreEqual(8, meta.Fields.Count);
+ Assert.AreEqual(9, meta.Fields.Count);
Assert.AreEqual(BinaryTypeNames.TypeNameByte, meta.GetFieldTypeName("fByte"));
Assert.AreEqual(BinaryTypeNames.TypeNameBool, meta.GetFieldTypeName("fBool"));
@@ -623,6 +681,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(BinaryTypeNames.TypeNameLong, meta.GetFieldTypeName("fLong"));
Assert.AreEqual(BinaryTypeNames.TypeNameFloat, meta.GetFieldTypeName("fFloat"));
Assert.AreEqual(BinaryTypeNames.TypeNameDouble, meta.GetFieldTypeName("fDouble"));
+ Assert.AreEqual(BinaryTypeNames.TypeNameDecimal, meta.GetFieldTypeName("fDecimal"));
Assert.AreEqual(1, binObj.GetField<byte>("fByte"));
Assert.AreEqual(true, binObj.GetField<bool>("fBool"));
@@ -632,6 +691,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(4, binObj.GetField<long>("fLong"));
Assert.AreEqual(5, binObj.GetField<float>("fFloat"));
Assert.AreEqual(6, binObj.GetField<double>("fDouble"));
+ Assert.AreEqual(7.7m, binObj.GetField<decimal>("fDecimal"));
Primitives obj = binObj.Deserialize<Primitives>();
@@ -643,20 +703,14 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(4, obj.FLong);
Assert.AreEqual(5, obj.FFloat);
Assert.AreEqual(6, obj.FDouble);
+ Assert.AreEqual(7.7m, obj.FDecimal);
+ }
- // Overwrite.
- binObj = binObj.ToBuilder()
- .SetField<byte>("fByte", 7)
- .SetField("fBool", false)
- .SetField<short>("fShort", 8)
- .SetField("fChar", 'b')
- .SetField("fInt", 9)
- .SetField<long>("fLong", 10)
- .SetField<float>("fFloat", 11)
- .SetField<double>("fDouble", 12)
- .SetHashCode(200)
- .Build();
-
+ /// <summary>
+ /// Checks the primitive fields values.
+ /// </summary>
+ private static void CheckPrimitiveFields2(IBinaryObject binObj)
+ {
Assert.AreEqual(200, binObj.GetHashCode());
Assert.AreEqual(7, binObj.GetField<byte>("fByte"));
@@ -667,8 +721,9 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(10, binObj.GetField<long>("fLong"));
Assert.AreEqual(11, binObj.GetField<float>("fFloat"));
Assert.AreEqual(12, binObj.GetField<double>("fDouble"));
+ Assert.AreEqual(13.13m, binObj.GetField<decimal>("fDecimal"));
- obj = binObj.Deserialize<Primitives>();
+ var obj = binObj.Deserialize<Primitives>();
Assert.AreEqual(7, obj.FByte);
Assert.AreEqual(false, obj.FBool);
@@ -678,6 +733,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(10, obj.FLong);
Assert.AreEqual(11, obj.FFloat);
Assert.AreEqual(12, obj.FDouble);
+ Assert.AreEqual(13.13m, obj.FDecimal);
}
/// <summary>
@@ -686,7 +742,8 @@ namespace Apache.Ignite.Core.Tests.Binary
[Test]
public void TestPrimitiveArrayFields()
{
- IBinaryObject binObj = _grid.GetBinary().GetBuilder(typeof(PrimitiveArrays))
+ // Generic SetField method.
+ var binObj = _grid.GetBinary().GetBuilder(typeof(PrimitiveArrays))
.SetField("fByte", new byte[] { 1 })
.SetField("fBool", new[] { true })
.SetField("fShort", new short[] { 2 })
@@ -695,16 +752,71 @@ namespace Apache.Ignite.Core.Tests.Binary
.SetField("fLong", new long[] { 4 })
.SetField("fFloat", new float[] { 5 })
.SetField("fDouble", new double[] { 6 })
+ .SetField("fDecimal", new decimal?[] { 7.7m })
.SetHashCode(100)
.Build();
+ CheckPrimitiveArrayFields1(binObj);
+
+ // Specific setters.
+ binObj = _grid.GetBinary().GetBuilder(typeof(PrimitiveArrays))
+ .SetByteArrayField("fByte", new byte[] {1})
+ .SetBooleanArrayField("fBool", new[] {true})
+ .SetShortArrayField("fShort", new short[] {2})
+ .SetCharArrayField("fChar", new[] {'a'})
+ .SetIntArrayField("fInt", new[] {3})
+ .SetLongArrayField("fLong", new long[] {4})
+ .SetFloatArrayField("fFloat", new float[] {5})
+ .SetDoubleArrayField("fDouble", new double[] {6})
+ .SetDecimalArrayField("fDecimal", new decimal?[] {7.7m})
+ .SetHashCode(100)
+ .Build();
+
+ // Overwrite with generic setter.
+ binObj = _grid.GetBinary().GetBuilder(binObj)
+ .SetField("fByte", new byte[] { 7 })
+ .SetField("fBool", new[] { false })
+ .SetField("fShort", new short[] { 8 })
+ .SetField("fChar", new[] { 'b' })
+ .SetField("fInt", new[] { 9 })
+ .SetField("fLong", new long[] { 10 })
+ .SetField("fFloat", new float[] { 11 })
+ .SetField("fDouble", new double[] { 12 })
+ .SetField("fDecimal", new decimal?[] { 13.13m })
+ .SetHashCode(200)
+ .Build();
+
+ CheckPrimitiveArrayFields2(binObj);
+
+ // Overwrite with specific setters.
+ binObj = _grid.GetBinary().GetBuilder(binObj)
+ .SetByteArrayField("fByte", new byte[] { 7 })
+ .SetBooleanArrayField("fBool", new[] { false })
+ .SetShortArrayField("fShort", new short[] { 8 })
+ .SetCharArrayField("fChar", new[] { 'b' })
+ .SetIntArrayField("fInt", new[] { 9 })
+ .SetLongArrayField("fLong", new long[] { 10 })
+ .SetFloatArrayField("fFloat", new float[] { 11 })
+ .SetDoubleArrayField("fDouble", new double[] { 12 })
+ .SetDecimalArrayField("fDecimal", new decimal?[] { 13.13m })
+ .SetHashCode(200)
+ .Build();
+
+ CheckPrimitiveArrayFields2(binObj);
+ }
+
+ /// <summary>
+ /// Checks the primitive array fields.
+ /// </summary>
+ private static void CheckPrimitiveArrayFields1(IBinaryObject binObj)
+ {
Assert.AreEqual(100, binObj.GetHashCode());
IBinaryType meta = binObj.GetBinaryType();
Assert.AreEqual(typeof(PrimitiveArrays).Name, meta.TypeName);
- Assert.AreEqual(8, meta.Fields.Count);
+ Assert.AreEqual(9, meta.Fields.Count);
Assert.AreEqual(BinaryTypeNames.TypeNameArrayByte, meta.GetFieldTypeName("fByte"));
Assert.AreEqual(BinaryTypeNames.TypeNameArrayBool, meta.GetFieldTypeName("fBool"));
@@ -714,6 +826,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(BinaryTypeNames.TypeNameArrayLong, meta.GetFieldTypeName("fLong"));
Assert.AreEqual(BinaryTypeNames.TypeNameArrayFloat, meta.GetFieldTypeName("fFloat"));
Assert.AreEqual(BinaryTypeNames.TypeNameArrayDouble, meta.GetFieldTypeName("fDouble"));
+ Assert.AreEqual(BinaryTypeNames.TypeNameArrayDecimal, meta.GetFieldTypeName("fDecimal"));
Assert.AreEqual(new byte[] { 1 }, binObj.GetField<byte[]>("fByte"));
Assert.AreEqual(new[] { true }, binObj.GetField<bool[]>("fBool"));
@@ -723,6 +836,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(new long[] { 4 }, binObj.GetField<long[]>("fLong"));
Assert.AreEqual(new float[] { 5 }, binObj.GetField<float[]>("fFloat"));
Assert.AreEqual(new double[] { 6 }, binObj.GetField<double[]>("fDouble"));
+ Assert.AreEqual(new decimal?[] { 7.7m }, binObj.GetField<decimal?[]>("fDecimal"));
PrimitiveArrays obj = binObj.Deserialize<PrimitiveArrays>();
@@ -734,20 +848,14 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(new long[] { 4 }, obj.FLong);
Assert.AreEqual(new float[] { 5 }, obj.FFloat);
Assert.AreEqual(new double[] { 6 }, obj.FDouble);
+ Assert.AreEqual(new decimal?[] { 7.7m }, obj.FDecimal);
+ }
- // Overwrite.
- binObj = _grid.GetBinary().GetBuilder(binObj)
- .SetField("fByte", new byte[] { 7 })
- .SetField("fBool", new[] { false })
- .SetField("fShort", new short[] { 8 })
- .SetField("fChar", new[] { 'b' })
- .SetField("fInt", new[] { 9 })
- .SetField("fLong", new long[] { 10 })
- .SetField("fFloat", new float[] { 11 })
- .SetField("fDouble", new double[] { 12 })
- .SetHashCode(200)
- .Build();
-
+ /// <summary>
+ /// Checks the primitive array fields.
+ /// </summary>
+ private static void CheckPrimitiveArrayFields2(IBinaryObject binObj)
+ {
Assert.AreEqual(200, binObj.GetHashCode());
Assert.AreEqual(new byte[] { 7 }, binObj.GetField<byte[]>("fByte"));
@@ -758,8 +866,9 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(new long[] { 10 }, binObj.GetField<long[]>("fLong"));
Assert.AreEqual(new float[] { 11 }, binObj.GetField<float[]>("fFloat"));
Assert.AreEqual(new double[] { 12 }, binObj.GetField<double[]>("fDouble"));
+ Assert.AreEqual(new decimal?[] { 13.13m }, binObj.GetField<decimal?[]>("fDecimal"));
- obj = binObj.Deserialize<PrimitiveArrays>();
+ var obj = binObj.Deserialize<PrimitiveArrays>();
Assert.AreEqual(new byte[] { 7 }, obj.FByte);
Assert.AreEqual(new[] { false }, obj.FBool);
@@ -769,6 +878,7 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(new long[] { 10 }, obj.FLong);
Assert.AreEqual(new float[] { 11 }, obj.FFloat);
Assert.AreEqual(new double[] { 12 }, obj.FDouble);
+ Assert.AreEqual(new decimal?[] { 13.13m }, obj.FDecimal);
}
/// <summary>
@@ -777,69 +887,141 @@ namespace Apache.Ignite.Core.Tests.Binary
[Test]
public void TestStringDateGuidEnum()
{
- DateTime? nDate = DateTime.Now;
+ DateTime? nDate = DateTime.Now.ToUniversalTime();
Guid? nGuid = Guid.NewGuid();
+ // Generic setters.
IBinaryObject binObj = _grid.GetBinary().GetBuilder(typeof(StringDateGuidEnum))
.SetField("fStr", "str")
.SetField("fNDate", nDate)
- .SetGuidField("fNGuid", nGuid)
+ .SetTimestampField("fNTimestamp", nDate)
+ .SetField("fNGuid", nGuid)
.SetField("fEnum", TestEnum.One)
- .SetField("fStrArr", new[] { "str" })
+ .SetStringArrayField("fStrArr", new[] { "str" })
+ .SetArrayField("fDateArr", new[] { nDate })
+ .SetTimestampArrayField("fTimestampArr", new[] { nDate })
+ .SetGuidArrayField("fGuidArr", new[] { nGuid })
+ .SetEnumArrayField("fEnumArr", new[] { TestEnum.One })
+ .SetHashCode(100)
+ .Build();
+
+ CheckStringDateGuidEnum1(binObj, nDate, nGuid);
+
+ // Specific setters.
+ binObj = _grid.GetBinary().GetBuilder(typeof(StringDateGuidEnum))
+ .SetStringField("fStr", "str")
+ .SetField("fNDate", nDate)
+ .SetTimestampField("fNTimestamp", nDate)
+ .SetGuidField("fNGuid", nGuid)
+ .SetEnumField("fEnum", TestEnum.One)
+ .SetStringArrayField("fStrArr", new[] { "str" })
.SetArrayField("fDateArr", new[] { nDate })
+ .SetTimestampArrayField("fTimestampArr", new[] { nDate })
.SetGuidArrayField("fGuidArr", new[] { nGuid })
- .SetField("fEnumArr", new[] { TestEnum.One })
+ .SetEnumArrayField("fEnumArr", new[] { TestEnum.One })
.SetHashCode(100)
.Build();
+ CheckStringDateGuidEnum1(binObj, nDate, nGuid);
+
+ // Overwrite.
+ nDate = DateTime.Now.ToUniversalTime();
+ nGuid = Guid.NewGuid();
+
+ binObj = _grid.GetBinary().GetBuilder(typeof(StringDateGuidEnum))
+ .SetField("fStr", "str2")
+ .SetField("fNDate", nDate)
+ .SetTimestampField("fNTimestamp", nDate)
+ .SetField("fNGuid", nGuid)
+ .SetField("fEnum", TestEnum.Two)
+ .SetField("fStrArr", new[] { "str2" })
+ .SetArrayField("fDateArr", new[] { nDate })
+ .SetTimestampArrayField("fTimestampArr", new[] { nDate })
+ .SetField("fGuidArr", new[] { nGuid })
+ .SetField("fEnumArr", new[] { TestEnum.Two })
+ .SetHashCode(200)
+ .Build();
+
+ CheckStringDateGuidEnum2(binObj, nDate, nGuid);
+
+ // Overwrite with specific setters
+ binObj = _grid.GetBinary().GetBuilder(typeof(StringDateGuidEnum))
+ .SetStringField("fStr", "str2")
+ .SetField("fNDate", nDate)
+ .SetTimestampField("fNTimestamp", nDate)
+ .SetGuidField("fNGuid", nGuid)
+ .SetEnumField("fEnum", TestEnum.Two)
+ .SetStringArrayField("fStrArr", new[] { "str2" })
+ .SetArrayField("fDateArr", new[] { nDate })
+ .SetTimestampArrayField("fTimestampArr", new[] { nDate })
+ .SetGuidArrayField("fGuidArr", new[] { nGuid })
+ .SetEnumArrayField("fEnumArr", new[] { TestEnum.Two })
+ .SetHashCode(200)
+ .Build();
+
+ CheckStringDateGuidEnum2(binObj, nDate, nGuid);
+ }
+
+ /// <summary>
+ /// Checks the string date guid enum values.
+ /// </summary>
+ private void CheckStringDateGuidEnum1(IBinaryObject binObj, DateTime? nDate, Guid? nGuid)
+ {
Assert.AreEqual(100, binObj.GetHashCode());
IBinaryType meta = binObj.GetBinaryType();
Assert.AreEqual(typeof(StringDateGuidEnum).Name, meta.TypeName);
- Assert.AreEqual(8, meta.Fields.Count);
+ Assert.AreEqual(10, meta.Fields.Count);
Assert.AreEqual(BinaryTypeNames.TypeNameString, meta.GetFieldTypeName("fStr"));
Assert.AreEqual(BinaryTypeNames.TypeNameObject, meta.GetFieldTypeName("fNDate"));
+ Assert.AreEqual(BinaryTypeNames.TypeNameTimestamp, meta.GetFieldTypeName("fNTimestamp"));
Assert.AreEqual(BinaryTypeNames.TypeNameGuid, meta.GetFieldTypeName("fNGuid"));
Assert.AreEqual(BinaryTypeNames.TypeNameEnum, meta.GetFieldTypeName("fEnum"));
Assert.AreEqual(BinaryTypeNames.TypeNameArrayString, meta.GetFieldTypeName("fStrArr"));
Assert.AreEqual(BinaryTypeNames.TypeNameArrayObject, meta.GetFieldTypeName("fDateArr"));
+ Assert.AreEqual(BinaryTypeNames.TypeNameArrayTimestamp, meta.GetFieldTypeName("fTimestampArr"));
Assert.AreEqual(BinaryTypeNames.TypeNameArrayGuid, meta.GetFieldTypeName("fGuidArr"));
Assert.AreEqual(BinaryTypeNames.TypeNameArrayEnum, meta.GetFieldTypeName("fEnumArr"));
Assert.AreEqual("str", binObj.GetField<string>("fStr"));
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, binObj.GetField<TestEnum>("fEnum"));
- Assert.AreEqual(new[] { "str" }, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fDateArr"));
- Assert.AreEqual(new[] { nGuid }, binObj.GetField<Guid?[]>("fGuidArr"));
+ Assert.AreEqual(new[] {"str"}, binObj.GetField<string[]>("fStrArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fTimestampArr"));
+ Assert.AreEqual(new[] {nGuid}, binObj.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] {TestEnum.One}, binObj.GetField<TestEnum[]>("fEnumArr"));
StringDateGuidEnum obj = binObj.Deserialize<StringDateGuidEnum>();
Assert.AreEqual("str", obj.FStr);
Assert.AreEqual(nDate, obj.FnDate);
+ Assert.AreEqual(nDate, obj.FnTimestamp);
Assert.AreEqual(nGuid, obj.FnGuid);
Assert.AreEqual(TestEnum.One, obj.FEnum);
- Assert.AreEqual(new[] { "str" }, obj.FStrArr);
- Assert.AreEqual(new[] { nDate }, obj.FDateArr);
- Assert.AreEqual(new[] { nGuid }, obj.FGuidArr);
- Assert.AreEqual(new[] { TestEnum.One }, obj.FEnumArr);
+ Assert.AreEqual(new[] {"str"}, obj.FStrArr);
+ Assert.AreEqual(new[] {nDate}, obj.FDateArr);
+ Assert.AreEqual(new[] {nGuid}, obj.FGuidArr);
+ Assert.AreEqual(new[] {TestEnum.One}, obj.FEnumArr);
// Check builder field caching.
var builder = _grid.GetBinary().GetBuilder(binObj);
Assert.AreEqual("str", builder.GetField<string>("fStr"));
Assert.AreEqual(nDate, builder.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, builder.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, builder.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, builder.GetField<TestEnum>("fEnum"));
- Assert.AreEqual(new[] { "str" }, builder.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] { nDate }, builder.GetField<DateTime?[]>("fDateArr"));
- Assert.AreEqual(new[] { nGuid }, builder.GetField<Guid?[]>("fGuidArr"));
+ Assert.AreEqual(new[] {"str"}, builder.GetField<string[]>("fStrArr"));
+ Assert.AreEqual(new[] {nDate}, builder.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, builder.GetField<DateTime?[]>("fTimestampArr"));
+ Assert.AreEqual(new[] {nGuid}, builder.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] {TestEnum.One}, builder.GetField<TestEnum[]>("fEnumArr"));
// Check reassemble.
@@ -847,55 +1029,51 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual("str", binObj.GetField<string>("fStr"));
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, binObj.GetField<TestEnum>("fEnum"));
- Assert.AreEqual(new[] { "str" }, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fDateArr"));
- Assert.AreEqual(new[] { nGuid }, binObj.GetField<Guid?[]>("fGuidArr"));
+ Assert.AreEqual(new[] {"str"}, binObj.GetField<string[]>("fStrArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fTimestampArr"));
+ Assert.AreEqual(new[] {nGuid}, binObj.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] {TestEnum.One}, binObj.GetField<TestEnum[]>("fEnumArr"));
obj = binObj.Deserialize<StringDateGuidEnum>();
Assert.AreEqual("str", obj.FStr);
Assert.AreEqual(nDate, obj.FnDate);
+ Assert.AreEqual(nDate, obj.FnTimestamp);
Assert.AreEqual(nGuid, obj.FnGuid);
Assert.AreEqual(TestEnum.One, obj.FEnum);
- Assert.AreEqual(new[] { "str" }, obj.FStrArr);
- Assert.AreEqual(new[] { nDate }, obj.FDateArr);
- Assert.AreEqual(new[] { nGuid }, obj.FGuidArr);
- Assert.AreEqual(new[] { TestEnum.One }, obj.FEnumArr);
-
- // Overwrite.
- nDate = DateTime.Now.ToUniversalTime();
- nGuid = Guid.NewGuid();
-
- binObj = builder
- .SetField("fStr", "str2")
- .SetTimestampField("fNDate", nDate)
- .SetField("fNGuid", nGuid)
- .SetField("fEnum", TestEnum.Two)
- .SetField("fStrArr", new[] { "str2" })
- .SetArrayField("fDateArr", new[] { nDate })
- .SetField("fGuidArr", new[] { nGuid })
- .SetField("fEnumArr", new[] { TestEnum.Two })
- .SetHashCode(200)
- .Build();
+ Assert.AreEqual(new[] {"str"}, obj.FStrArr);
+ Assert.AreEqual(new[] {nDate}, obj.FDateArr);
+ Assert.AreEqual(new[] {nGuid}, obj.FGuidArr);
+ Assert.AreEqual(new[] {TestEnum.One}, obj.FEnumArr);
+ }
+ /// <summary>
+ /// Checks the string date guid enum values.
+ /// </summary>
+ private static void CheckStringDateGuidEnum2(IBinaryObject binObj, DateTime? nDate, Guid? nGuid)
+ {
Assert.AreEqual(200, binObj.GetHashCode());
Assert.AreEqual("str2", binObj.GetField<string>("fStr"));
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.Two, binObj.GetField<TestEnum>("fEnum"));
Assert.AreEqual(new[] { "str2" }, binObj.GetField<string[]>("fStrArr"));
Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] { nGuid }, binObj.GetField<Guid?[]>("fGuidArr"));
- Assert.AreEqual(new[] {TestEnum.Two}, binObj.GetField<TestEnum[]>("fEnumArr"));
+ Assert.AreEqual(new[] { TestEnum.Two }, binObj.GetField<TestEnum[]>("fEnumArr"));
- obj = binObj.Deserialize<StringDateGuidEnum>();
+ var obj = binObj.Deserialize<StringDateGuidEnum>();
Assert.AreEqual("str2", obj.FStr);
Assert.AreEqual(nDate, obj.FnDate);
+ Assert.AreEqual(nDate, obj.FnTimestamp);
Assert.AreEqual(nGuid, obj.FnGuid);
Assert.AreEqual(TestEnum.Two, obj.FEnum);
Assert.AreEqual(new[] { "str2" }, obj.FStrArr);
@@ -1524,6 +1702,7 @@ namespace Apache.Ignite.Core.Tests.Binary
public long FLong;
public float FFloat;
public double FDouble;
+ public decimal FDecimal;
}
/// <summary>
@@ -1539,6 +1718,7 @@ namespace Apache.Ignite.Core.Tests.Binary
public long[] FLong;
public float[] FFloat;
public double[] FDouble;
+ public decimal?[] FDecimal;
}
/// <summary>
@@ -1548,6 +1728,7 @@ namespace Apache.Ignite.Core.Tests.Binary
{
public string FStr;
public DateTime? FnDate;
+ public DateTime? FnTimestamp;
public Guid? FnGuid;
public TestEnum FEnum;
http://git-wip-us.apache.org/repos/asf/ignite/blob/332c8c2f/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObjectBuilder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObjectBuilder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObjectBuilder.cs
index abb9149..740706a 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObjectBuilder.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Binary/IBinaryObjectBuilder.cs
@@ -62,7 +62,7 @@ namespace Apache.Ignite.Core.Binary
/// <summary>
/// Set explicit hash code. If builder creating object from scratch,
/// then hash code initially set to 0. If builder is created from
- /// exising binary object, then hash code of that object is used
+ /// existing binary object, then hash code of that object is used
/// as initial value.
/// </summary>
/// <param name="hashCode">Hash code.</param>
http://git-wip-us.apache.org/repos/asf/ignite/blob/332c8c2f/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
index 083f557..646d563 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryObjectBuilder.cs
@@ -151,7 +151,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetBooleanField(string fieldName, bool val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (bool), val, BinaryUtils.TypeBool,
- (w, o) => w.WriteBoolean((bool) o)));
+ (w, o) => w.WriteBooleanField((bool) o)));
}
/** <inheritDoc /> */
@@ -165,7 +165,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetByteField(string fieldName, byte val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (byte), val, BinaryUtils.TypeByte,
- (w, o) => w.WriteByte((byte) o)));
+ (w, o) => w.WriteByteField((byte) o)));
}
/** <inheritDoc /> */
@@ -179,7 +179,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetCharField(string fieldName, char val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (char), val, BinaryUtils.TypeChar,
- (w, o) => w.WriteChar((char) o)));
+ (w, o) => w.WriteCharField((char) o)));
}
/** <inheritDoc /> */
@@ -221,7 +221,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetDoubleField(string fieldName, double val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (double), val, BinaryUtils.TypeDouble,
- (w, o) => w.WriteDouble((double) o)));
+ (w, o) => w.WriteDoubleField((double) o)));
}
/** <inheritDoc /> */
@@ -249,7 +249,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetFloatField(string fieldName, float val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (float), val, BinaryUtils.TypeFloat,
- (w, o) => w.WriteFloat((float) o)));
+ (w, o) => w.WriteFloatField((float) o)));
}
/** <inheritDoc /> */
@@ -277,7 +277,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetIntField(string fieldName, int val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (int), val, BinaryUtils.TypeInt,
- (w, o) => w.WriteInt((int) o)));
+ (w, o) => w.WriteIntField((int) o)));
}
/** <inheritDoc /> */
@@ -291,7 +291,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetLongField(string fieldName, long val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (long), val, BinaryUtils.TypeLong,
- (w, o) => w.WriteLong((long) o)));
+ (w, o) => w.WriteLongField((long) o)));
}
/** <inheritDoc /> */
@@ -305,7 +305,7 @@ namespace Apache.Ignite.Core.Impl.Binary
public IBinaryObjectBuilder SetShortField(string fieldName, short val)
{
return SetField0(fieldName, new BinaryBuilderField(typeof (short), val, BinaryUtils.TypeShort,
- (w, o) => w.WriteShort((short) o)));
+ (w, o) => w.WriteShortField((short) o)));
}
/** <inheritDoc /> */
http://git-wip-us.apache.org/repos/asf/ignite/blob/332c8c2f/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
----------------------------------------------------------------------
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
index 1ac98c4..a0b50ac 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryWriter.cs
@@ -26,6 +26,7 @@ namespace Apache.Ignite.Core.Impl.Binary
using Apache.Ignite.Core.Impl.Binary.IO;
using Apache.Ignite.Core.Impl.Binary.Metadata;
using Apache.Ignite.Core.Impl.Binary.Structure;
+ using Apache.Ignite.Core.Impl.Common;
/// <summary>
/// Binary writer implementation.
@@ -87,11 +88,19 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteBoolean(string fieldName, bool val)
{
WriteFieldId(fieldName, BinaryUtils.TypeBool);
+ WriteBooleanField(val);
+ }
+ /// <summary>
+ /// Writes the boolean field.
+ /// </summary>
+ /// <param name="val">if set to <c>true</c> [value].</param>
+ internal void WriteBooleanField(bool val)
+ {
_stream.WriteByte(BinaryUtils.TypeBool);
_stream.WriteBool(val);
}
-
+
/// <summary>
/// Write boolean value.
/// </summary>
@@ -142,7 +151,15 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteByte(string fieldName, byte val)
{
WriteFieldId(fieldName, BinaryUtils.TypeBool);
+ WriteByteField(val);
+ }
+ /// <summary>
+ /// Write byte field value.
+ /// </summary>
+ /// <param name="val">Byte value.</param>
+ internal void WriteByteField(byte val)
+ {
_stream.WriteByte(BinaryUtils.TypeByte);
_stream.WriteByte(val);
}
@@ -197,7 +214,15 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteShort(string fieldName, short val)
{
WriteFieldId(fieldName, BinaryUtils.TypeShort);
+ WriteShortField(val);
+ }
+ /// <summary>
+ /// Write short field value.
+ /// </summary>
+ /// <param name="val">Short value.</param>
+ internal void WriteShortField(short val)
+ {
_stream.WriteByte(BinaryUtils.TypeShort);
_stream.WriteShort(val);
}
@@ -252,7 +277,15 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteChar(string fieldName, char val)
{
WriteFieldId(fieldName, BinaryUtils.TypeChar);
+ WriteCharField(val);
+ }
+ /// <summary>
+ /// Write char field value.
+ /// </summary>
+ /// <param name="val">Char value.</param>
+ internal void WriteCharField(char val)
+ {
_stream.WriteByte(BinaryUtils.TypeChar);
_stream.WriteChar(val);
}
@@ -307,7 +340,15 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteInt(string fieldName, int val)
{
WriteFieldId(fieldName, BinaryUtils.TypeInt);
+ WriteIntField(val);
+ }
+ /// <summary>
+ /// Writes the int field.
+ /// </summary>
+ /// <param name="val">The value.</param>
+ internal void WriteIntField(int val)
+ {
_stream.WriteByte(BinaryUtils.TypeInt);
_stream.WriteInt(val);
}
@@ -362,7 +403,15 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteLong(string fieldName, long val)
{
WriteFieldId(fieldName, BinaryUtils.TypeLong);
+ WriteLongField(val);
+ }
+ /// <summary>
+ /// Writes the long field.
+ /// </summary>
+ /// <param name="val">The value.</param>
+ internal void WriteLongField(long val)
+ {
_stream.WriteByte(BinaryUtils.TypeLong);
_stream.WriteLong(val);
}
@@ -417,7 +466,15 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteFloat(string fieldName, float val)
{
WriteFieldId(fieldName, BinaryUtils.TypeFloat);
+ WriteFloatField(val);
+ }
+ /// <summary>
+ /// Writes the float field.
+ /// </summary>
+ /// <param name="val">The value.</param>
+ internal void WriteFloatField(float val)
+ {
_stream.WriteByte(BinaryUtils.TypeFloat);
_stream.WriteFloat(val);
}
@@ -472,7 +529,15 @@ namespace Apache.Ignite.Core.Impl.Binary
public void WriteDouble(string fieldName, double val)
{
WriteFieldId(fieldName, BinaryUtils.TypeDouble);
+ WriteDoubleField(val);
+ }
+ /// <summary>
+ /// Writes the double field.
+ /// </summary>
+ /// <param name="val">The value.</param>
+ internal void WriteDoubleField(double val)
+ {
_stream.WriteByte(BinaryUtils.TypeDouble);
_stream.WriteDouble(val);
}
@@ -1215,72 +1280,40 @@ namespace Apache.Ignite.Core.Impl.Binary
// Types check sequence is designed to minimize comparisons for the most frequent types.
if (type == typeof(int))
- {
- _stream.WriteByte(BinaryUtils.TypeInt);
- _stream.WriteInt((int)(object)val);
- }
+ WriteIntField(TypeCaster<int>.Cast(val));
else if (type == typeof(long))
- {
- _stream.WriteByte(BinaryUtils.TypeLong);
- _stream.WriteLong((long)(object)val);
- }
+ WriteLongField(TypeCaster<long>.Cast(val));
else if (type == typeof(bool))
- {
- _stream.WriteByte(BinaryUtils.TypeBool);
- _stream.WriteBool((bool)(object)val);
- }
+ WriteBooleanField(TypeCaster<bool>.Cast(val));
else if (type == typeof(byte))
- {
- _stream.WriteByte(BinaryUtils.TypeByte);
- _stream.WriteByte((byte)(object)val);
- }
+ WriteByteField(TypeCaster<byte>.Cast(val));
else if (type == typeof(short))
- {
- _stream.WriteByte(BinaryUtils.TypeShort);
- _stream.WriteShort((short)(object)val);
- }
- else if (type == typeof (char))
- {
- _stream.WriteByte(BinaryUtils.TypeChar);
- _stream.WriteChar((char)(object)val);
- }
+ WriteShortField(TypeCaster<short>.Cast(val));
+ else if (type == typeof(char))
+ WriteCharField(TypeCaster<char>.Cast(val));
else if (type == typeof(float))
- {
- _stream.WriteByte(BinaryUtils.TypeFloat);
- _stream.WriteFloat((float)(object)val);
- }
+ WriteFloatField(TypeCaster<float>.Cast(val));
else if (type == typeof(double))
- {
- _stream.WriteByte(BinaryUtils.TypeDouble);
- _stream.WriteDouble((double)(object)val);
- }
+ WriteDoubleField(TypeCaster<double>.Cast(val));
else if (type == typeof(sbyte))
{
- sbyte val0 = (sbyte)(object)val;
-
- _stream.WriteByte(BinaryUtils.TypeByte);
- _stream.WriteByte(*(byte*)&val0);
+ var val0 = TypeCaster<sbyte>.Cast(val);
+ WriteByteField(*(byte*)&val0);
}
else if (type == typeof(ushort))
{
- ushort val0 = (ushort)(object)val;
-
- _stream.WriteByte(BinaryUtils.TypeShort);
- _stream.WriteShort(*(short*)&val0);
+ var val0 = TypeCaster<ushort>.Cast(val);
+ WriteShortField(*(short*) &val0);
}
else if (type == typeof(uint))
{
- uint val0 = (uint)(object)val;
-
- _stream.WriteByte(BinaryUtils.TypeInt);
- _stream.WriteInt(*(int*)&val0);
+ var val0 = TypeCaster<uint>.Cast(val);
+ WriteIntField(*(int*)&val0);
}
else if (type == typeof(ulong))
{
- ulong val0 = (ulong)(object)val;
-
- _stream.WriteByte(BinaryUtils.TypeLong);
- _stream.WriteLong(*(long*)&val0);
+ var val0 = TypeCaster<ulong>.Cast(val);
+ WriteLongField(*(long*)&val0);
}
else
throw new BinaryObjectException("Unsupported object type [type=" + type.FullName + ", object=" + val + ']');
[06/50] [abbrv] ignite git commit: ignite-3300 Fixed potential race.
Posted by vo...@apache.org.
ignite-3300 Fixed potential race.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/eddd0a98
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/eddd0a98
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/eddd0a98
Branch: refs/heads/ignite-3553
Commit: eddd0a981ead389bed5608444a811b1c90f4098f
Parents: d88f778
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jul 22 16:43:59 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 22 16:43:59 2016 +0300
----------------------------------------------------------------------
.../internal/processors/cache/GridCacheAffinityManager.java | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/eddd0a98/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
index d182bb4..8633333 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
@@ -197,18 +197,18 @@ public class GridCacheAffinityManager extends GridCacheManagerAdapter {
public int partition(Object key) {
GridAffinityAssignmentCache aff0 = aff;
+ if (aff0 == null)
+ throw new IgniteException(FAILED_TO_FIND_CACHE_ERR_MSG + cctx.name());
+
boolean keyObj = key instanceof KeyCacheObject;
- if (key instanceof KeyCacheObject) {
+ if (keyObj) {
int part = ((KeyCacheObject)key).partition();
if (part != -1)
return part;
}
- if (aff0 == null)
- throw new IgniteException(FAILED_TO_FIND_CACHE_ERR_MSG + cctx.name());
-
int p = affFunction.partition(affinityKey(key));
if (keyObj)
[04/50] [abbrv] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.6.3'
Posted by vo...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.6.3'
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2007cf85
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2007cf85
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2007cf85
Branch: refs/heads/ignite-3553
Commit: 2007cf859c6f761d9258f2cb10ef1f695e67d9da
Parents: ab4963a ce53491
Author: Pavel Tupitsyn <pt...@apache.org>
Authored: Fri Jul 22 15:44:09 2016 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
Committed: Fri Jul 22 15:44:09 2016 +0300
----------------------------------------------------------------------
.../Binary/BinaryBuilderSelfTest.cs | 57 +++++++++++++++++---
.../Binary/BinarySelfTest.cs | 3 +-
.../Impl/Binary/BinaryReader.cs | 18 +++----
.../Impl/Binary/Marshaller.cs | 44 ++++++++++-----
.../Binary/Structure/BinaryStructureTracker.cs | 7 +--
5 files changed, 93 insertions(+), 36 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/2007cf85/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/2007cf85/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/2007cf85/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/Marshaller.cs
----------------------------------------------------------------------
[50/50] [abbrv] ignite git commit: Merge branch 'ignite-1.7' into
ignite-3553
Posted by vo...@apache.org.
Merge branch 'ignite-1.7' into ignite-3553
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/7d05b650
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/7d05b650
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/7d05b650
Branch: refs/heads/ignite-3553
Commit: 7d05b6500c2310a54d589429911a2c1756746a12
Parents: b77bee0 8386dd8
Author: vozerov-gridgain <vo...@gridgain.com>
Authored: Thu Jul 28 14:06:00 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Thu Jul 28 14:06:00 2016 +0300
----------------------------------------------------------------------
.gitignore | 1 +
RELEASE_NOTES.txt | 17 +
assembly/libs/README.txt | 39 +-
.../examples/datagrid/CacheQueryExample.java | 78 +-
.../jdbc2/JdbcDistributedJoinsQueryTest.java | 319 ++++
.../JettyRestProcessorAbstractSelfTest.java | 178 +-
.../jdbc/suite/IgniteJdbcDriverTestSuite.java | 2 +
.../ignite/codegen/MessageCodeGenerator.java | 6 +
modules/core/pom.xml | 6 +
.../src/main/java/org/apache/ignite/Ignite.java | 4 +-
.../org/apache/ignite/IgniteFileSystem.java | 9 +
.../org/apache/ignite/IgniteJdbcDriver.java | 14 +-
.../org/apache/ignite/cache/QueryEntity.java | 18 +
.../ignite/cache/query/SqlFieldsQuery.java | 53 +
.../org/apache/ignite/cache/query/SqlQuery.java | 28 +
.../store/jdbc/CacheAbstractJdbcStore.java | 101 +-
.../cache/store/jdbc/CacheJdbcPojoStore.java | 7 +-
.../store/jdbc/CacheJdbcPojoStoreFactory.java | 26 +
.../store/jdbc/JdbcTypesDefaultTransformer.java | 117 ++
.../cache/store/jdbc/JdbcTypesTransformer.java | 39 +
.../configuration/IgniteConfiguration.java | 42 +-
.../internal/cluster/ClusterGroupAdapter.java | 18 +-
.../ignite/internal/jdbc2/JdbcConnection.java | 12 +
.../ignite/internal/jdbc2/JdbcQueryTask.java | 9 +-
.../ignite/internal/jdbc2/JdbcResultSet.java | 4 +-
.../ignite/internal/jdbc2/JdbcStatement.java | 2 +-
.../managers/communication/GridIoManager.java | 34 +-
.../communication/GridIoMessageFactory.java | 2 +-
.../managers/communication/GridIoPolicy.java | 5 +-
.../GridAffinityFunctionContextImpl.java | 2 +-
.../cache/GridCacheAffinityManager.java | 2 +-
.../processors/cache/GridCacheContext.java | 19 +
.../GridCacheDefaultAffinityKeyMapper.java | 19 +
.../processors/cache/GridCacheIoManager.java | 21 +-
.../processors/cache/IgniteCacheProxy.java | 8 +
.../binary/CacheObjectBinaryProcessorImpl.java | 8 +
.../distributed/GridCacheTxRecoveryFuture.java | 7 +
.../distributed/GridCacheTxRecoveryRequest.java | 1 -
.../GridCacheTxRecoveryResponse.java | 23 +-
.../GridDistributedTxFinishRequest.java | 19 +-
.../GridDistributedTxFinishResponse.java | 1 -
.../GridDistributedTxPrepareRequest.java | 26 +-
.../GridDistributedTxPrepareResponse.java | 20 +-
.../dht/GridCachePartitionedConcurrentMap.java | 142 +-
.../dht/GridDhtPartitionTopology.java | 2 +-
.../dht/GridDhtPartitionTopologyImpl.java | 176 +-
.../dht/GridDhtPartitionsReservation.java | 3 +-
.../near/GridNearTxPrepareFutureAdapter.java | 7 +
.../cache/query/GridCacheQueryManager.java | 110 +-
.../cache/query/GridCacheQueryMarshallable.java | 37 +
.../cache/query/GridCacheSqlQuery.java | 33 +-
.../cache/query/GridCacheTwoStepQuery.java | 123 +-
.../cache/transactions/IgniteTxHandler.java | 55 +-
.../IgniteTxImplicitSingleStateImpl.java | 13 +
.../IgniteTxRemoteSingleStateImpl.java | 13 +
.../transactions/IgniteTxRemoteStateImpl.java | 38 +-
.../cache/transactions/IgniteTxState.java | 6 +
.../cache/transactions/IgniteTxStateAware.java | 34 +
.../cache/transactions/IgniteTxStateImpl.java | 12 +
.../cacheobject/IgniteCacheObjectProcessor.java | 6 +
.../IgniteCacheObjectProcessorImpl.java | 5 +
.../processors/closure/GridClosurePolicy.java | 51 -
.../closure/GridClosureProcessor.java | 52 +-
.../datastructures/GridCacheSemaphoreImpl.java | 108 +-
.../internal/processors/igfs/IgfsAsyncImpl.java | 6 +
.../internal/processors/igfs/IgfsImpl.java | 7 +
.../platform/PlatformAbstractBootstrap.java | 5 +
.../processors/platform/PlatformBootstrap.java | 6 +
.../processors/platform/PlatformIgnition.java | 7 +-
.../platform/PlatformProcessorImpl.java | 35 +-
.../platform/cache/PlatformCache.java | 12 +-
.../affinity/PlatformAffinityFunction.java | 27 +
.../cache/affinity/PlatformAffinityUtils.java | 2 +
.../callback/PlatformCallbackGateway.java | 13 +-
.../callback/PlatformCallbackUtils.java | 8 +
.../platform/cluster/PlatformClusterGroup.java | 7 +
.../platform/compute/PlatformAbstractTask.java | 1 +
.../dotnet/PlatformDotNetBootstrap.java | 12 +
.../dotnet/PlatformDotNetCacheStore.java | 27 +-
.../PlatformDotNetConfigurationClosure.java | 58 +-
.../dotnet/PlatformDotNetConsoleStream.java | 54 +
.../services/PlatformAbstractService.java | 3 +-
.../utils/PlatformConfigurationUtils.java | 106 +-
.../platform/utils/PlatformFutureUtils.java | 2 +
.../platform/utils/PlatformUtils.java | 12 +
.../processors/query/GridQueryIndexing.java | 51 +-
.../processors/query/GridQueryProcessor.java | 194 +--
.../query/GridQueryTypeDescriptor.java | 7 +
.../messages/GridQueryCancelRequest.java | 2 +-
.../twostep/messages/GridQueryFailResponse.java | 2 +-
.../messages/GridQueryNextPageRequest.java | 2 +-
.../messages/GridQueryNextPageResponse.java | 12 +-
.../h2/twostep/messages/GridQueryRequest.java | 28 +-
.../handlers/cache/GridCacheCommandHandler.java | 100 +-
.../handlers/query/QueryCommandHandler.java | 4 +
.../rest/request/RestQueryRequest.java | 17 +
.../ignite/internal/util/IgniteUtils.java | 47 +-
.../internal/util/PartitionedReadOnlySet.java | 71 -
.../ignite/internal/util/lang/GridFunc.java | 20 +
.../offheap/unsafe/GridOffHeapSnapTreeMap.java | 91 +-
.../internal/visor/query/VisorQueryArgV2.java | 49 +
.../internal/visor/query/VisorQueryJob.java | 1 +
.../dotnet/PlatformDotNetAffinityFunction.java | 15 +
.../SpringApplicationContextResource.java | 4 +-
.../apache/ignite/resources/SpringResource.java | 15 +-
.../ignite/scheduler/SchedulerFuture.java | 5 +-
.../java/org/jetbrains/annotations/NotNull.java | 38 -
.../org/jetbrains/annotations/Nullable.java | 33 -
.../org/jetbrains/annotations/package-info.java | 27 -
.../ignite/internal/ClusterGroupSelfTest.java | 30 +-
.../cache/GridCacheAbstractFullApiSelfTest.java | 127 +-
.../IgniteTxExceptionAbstractSelfTest.java | 45 +-
.../IgniteSemaphoreAbstractSelfTest.java | 25 +-
.../dht/IgniteCacheConcurrentPutGetRemove.java | 201 +++
.../IgniteCacheSyncRebalanceModeSelfTest.java | 2 +
.../internal/processors/igfs/IgfsMock.java | 8 +
.../processors/igfs/IgfsStreamsSelfTest.java | 5 +-
...niteMessagingConfigVariationFullApiTest.java | 484 ++++++
.../GridCacheAtomicCommandHandlerSelfTest.java | 39 +
.../cache/GridCacheCommandHandlerSelfTest.java | 20 +-
.../ignite/platform/PlatformStringTestTask.java | 67 +
.../jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java | 2 +-
.../junits/common/GridCommonAbstractTest.java | 39 +-
...essagingConfigVariationFullApiTestSuite.java | 72 +
.../testsuites/IgniteRestHandlerTestSuite.java | 2 +
modules/docker/1.6.0/Dockerfile | 44 +
modules/docker/1.6.0/run.sh | 51 +
modules/docker/Dockerfile | 24 +-
.../query/h2/opt/GridH2SpatialIndex.java | 74 +-
.../collections/HadoopHashMapSelfTest.java | 68 +-
.../processors/query/h2/IgniteH2Indexing.java | 726 ++++++--
.../query/h2/opt/GridH2AbstractKeyValueRow.java | 72 +-
.../query/h2/opt/GridH2CollocationModel.java | 783 +++++++++
.../processors/query/h2/opt/GridH2Cursor.java | 36 +-
.../query/h2/opt/GridH2DefaultTableEngine.java | 38 +
.../query/h2/opt/GridH2IndexBase.java | 1392 ++++++++++++++-
.../query/h2/opt/GridH2MetaTable.java | 383 ++++
.../query/h2/opt/GridH2QueryContext.java | 612 +++++++
.../query/h2/opt/GridH2QueryType.java | 49 +
.../query/h2/opt/GridH2RetryException.java | 32 +
.../processors/query/h2/opt/GridH2Row.java | 86 +-
.../query/h2/opt/GridH2RowDescriptor.java | 28 +-
.../query/h2/opt/GridH2RowFactory.java | 179 ++
.../processors/query/h2/opt/GridH2Table.java | 372 ++--
.../query/h2/opt/GridH2TreeIndex.java | 142 +-
.../processors/query/h2/opt/GridH2Utils.java | 133 --
.../query/h2/opt/GridH2ValueCacheObject.java | 3 +-
.../query/h2/opt/GridLuceneIndex.java | 7 +-
.../processors/query/h2/sql/GridSqlAlias.java | 12 +
.../processors/query/h2/sql/GridSqlColumn.java | 22 +-
.../processors/query/h2/sql/GridSqlElement.java | 11 +
.../query/h2/sql/GridSqlOperation.java | 2 +-
.../query/h2/sql/GridSqlOperationType.java | 8 +-
.../query/h2/sql/GridSqlQueryParser.java | 97 +-
.../query/h2/sql/GridSqlQuerySplitter.java | 293 +++-
.../processors/query/h2/sql/GridSqlSelect.java | 9 +-
.../processors/query/h2/sql/GridSqlTable.java | 70 +
.../query/h2/twostep/GridMapQueryExecutor.java | 415 +++--
.../query/h2/twostep/GridMergeIndex.java | 75 +-
.../h2/twostep/GridMergeIndexUnsorted.java | 6 +-
.../query/h2/twostep/GridMergeTable.java | 4 +-
.../h2/twostep/GridReduceQueryExecutor.java | 338 ++--
.../query/h2/twostep/GridThreadLocalTable.java | 68 +-
.../query/h2/twostep/msg/GridH2Array.java | 9 +-
.../query/h2/twostep/msg/GridH2Boolean.java | 10 +-
.../query/h2/twostep/msg/GridH2Byte.java | 9 +-
.../query/h2/twostep/msg/GridH2Bytes.java | 11 +-
.../query/h2/twostep/msg/GridH2CacheObject.java | 9 +-
.../query/h2/twostep/msg/GridH2Date.java | 9 +-
.../query/h2/twostep/msg/GridH2Decimal.java | 11 +-
.../query/h2/twostep/msg/GridH2Double.java | 9 +-
.../query/h2/twostep/msg/GridH2Float.java | 9 +-
.../query/h2/twostep/msg/GridH2Geometry.java | 11 +-
.../h2/twostep/msg/GridH2IndexRangeRequest.java | 208 +++
.../twostep/msg/GridH2IndexRangeResponse.java | 279 +++
.../query/h2/twostep/msg/GridH2Integer.java | 20 +-
.../query/h2/twostep/msg/GridH2JavaObject.java | 11 +-
.../query/h2/twostep/msg/GridH2Long.java | 9 +-
.../query/h2/twostep/msg/GridH2Null.java | 15 +-
.../h2/twostep/msg/GridH2QueryRequest.java | 401 +++++
.../query/h2/twostep/msg/GridH2RowMessage.java | 116 ++
.../query/h2/twostep/msg/GridH2RowRange.java | 181 ++
.../h2/twostep/msg/GridH2RowRangeBounds.java | 188 ++
.../query/h2/twostep/msg/GridH2Short.java | 9 +-
.../query/h2/twostep/msg/GridH2String.java | 9 +-
.../query/h2/twostep/msg/GridH2Time.java | 9 +-
.../query/h2/twostep/msg/GridH2Timestamp.java | 11 +-
.../query/h2/twostep/msg/GridH2Uuid.java | 9 +-
.../h2/twostep/msg/GridH2ValueMessage.java | 2 +-
.../twostep/msg/GridH2ValueMessageFactory.java | 22 +-
.../cache/CacheIndexingOffheapCleanupTest.java | 178 ++
...idCacheReduceQueryMultithreadedSelfTest.java | 168 --
.../cache/IgniteCacheAbstractQuerySelfTest.java | 30 +-
.../IgniteCacheCrossCacheJoinRandomTest.java | 442 +++++
...acheDistributedJoinCollocatedAndNotTest.java | 365 ++++
...acheDistributedJoinCustomAffinityMapper.java | 262 +++
.../IgniteCacheDistributedJoinNoIndexTest.java | 299 ++++
...ributedJoinPartitionedAndReplicatedTest.java | 487 ++++++
...CacheDistributedJoinQueryConditionsTest.java | 624 +++++++
.../cache/IgniteCacheDistributedJoinTest.java | 316 ++++
...PartitionedAndReplicatedCollocationTest.java | 399 +++++
...teCacheJoinPartitionedAndReplicatedTest.java | 316 ++++
...IgniteCacheJoinQueryWithAffinityKeyTest.java | 646 +++++++
...IgniteCachePrimitiveFieldsQuerySelfTest.java | 134 ++
.../cache/IgniteCacheQueryLoadSelfTest.java | 12 +-
.../cache/IgniteCacheUnionDuplicatesTest.java | 151 ++
.../cache/IgniteCrossCachesJoinsQueryTest.java | 1641 ++++++++++++++++++
...QueryNodeRestartDistributedJoinSelfTest.java | 476 +++++
...dCacheAbstractReduceFieldsQuerySelfTest.java | 420 -----
...ridCacheReduceFieldsQueryAtomicSelfTest.java | 38 -
...GridCacheReduceFieldsQueryLocalSelfTest.java | 37 -
...cheReduceFieldsQueryPartitionedSelfTest.java | 59 -
...acheReduceFieldsQueryReplicatedSelfTest.java | 37 -
.../query/IgniteSqlSchemaIndexingTest.java | 5 +-
.../query/IgniteSqlSplitterSelfTest.java | 833 ++++++++-
.../h2/GridIndexingSpiAbstractSelfTest.java | 145 +-
.../query/h2/opt/GridH2TableSelfTest.java | 10 +-
.../h2/sql/AbstractH2CompareQueryTest.java | 165 +-
.../query/h2/sql/GridQueryParsingTest.java | 28 +-
.../H2CompareBigQueryDistributedJoinsTest.java | 28 +
.../query/h2/sql/H2CompareBigQueryTest.java | 119 +-
.../IgniteCacheQuerySelfTestSuite.java | 27 +-
.../IgniteCacheQuerySelfTestSuite2.java | 10 -
.../IgniteCacheWithIndexingTestSuite.java | 2 +
.../ignite/stream/kafka/KafkaStreamer.java | 4 +-
.../connect/IgniteSourceConnectorTest.java | 58 +-
.../cpp/common/include/ignite/common/utils.h | 18 +
modules/platforms/cpp/core-test/Makefile.am | 1 +
.../cpp/core-test/config/cache-query.xml | 42 +-
.../cpp/core-test/project/vs/core-test.vcxproj | 3 +-
.../project/vs/core-test.vcxproj.filters | 5 +-
.../cpp/core-test/src/cache_query_test.cpp | 443 ++++-
.../cpp/core-test/src/interop_test.cpp | 148 ++
.../core/include/ignite/cache/query/query_sql.h | 61 +-
.../ignite/cache/query/query_sql_fields.h | 111 +-
modules/platforms/cpp/examples/README.txt | 1 +
.../cpp/jni/include/ignite/jni/exports.h | 4 +
.../platforms/cpp/jni/include/ignite/jni/java.h | 17 +-
modules/platforms/cpp/jni/project/vs/module.def | 4 +
modules/platforms/cpp/jni/src/exports.cpp | 12 +
modules/platforms/cpp/jni/src/java.cpp | 120 +-
.../cpp/odbc-test/config/queries-test.xml | 9 +-
.../cpp/odbc-test/src/configuration_test.cpp | 110 +-
.../cpp/odbc-test/src/queries_test.cpp | 91 +-
.../include/ignite/odbc/config/configuration.h | 121 +-
.../cpp/odbc/include/ignite/odbc/connection.h | 38 +-
.../cpp/odbc/src/config/configuration.cpp | 227 ++-
modules/platforms/cpp/odbc/src/connection.cpp | 47 +-
modules/platforms/cpp/odbc/src/odbc.cpp | 27 +-
.../Apache.Ignite.AspNet.csproj | 73 +
.../Apache.Ignite.AspNet.nuspec | 57 +
.../Apache.Ignite.AspNet.ruleset | 9 +
.../Apache.Ignite.AspNet.snk | Bin 0 -> 596 bytes
.../IgniteOutputCacheProvider.cs | 220 +++
.../Apache.Ignite.AspNet/IgniteWebUtils.cs | 44 +
.../dotnet/Apache.Ignite.AspNet/Package-Info.cs | 26 +
.../Properties/AssemblyInfo.cs | 39 +
.../Properties/AssemblyInfo.cs | 2 +-
.../Apache.Ignite.Core.Tests.NuGet.csproj | 14 +
.../AspNetTest.cs | 73 +
.../Properties/AssemblyInfo.cs | 2 +-
.../SchemaTest.cs | 62 +
.../install-package.ps1 | 21 +-
.../packages.config | 2 +
.../Properties/AssemblyInfo.cs | 2 +-
.../Apache.Ignite.Core.Tests.csproj | 18 +-
.../AspNet/IgniteOutputCacheProviderTest.cs | 172 ++
.../Binary/BinarySelfTest.cs | 164 +-
.../Binary/BinaryStringTest.cs | 120 ++
.../Cache/Affinity/AffinityFieldTest.cs | 199 +++
.../Affinity/AffinityFunctionSpringTest.cs | 2 +-
.../Cache/Affinity/AffinityFunctionTest.cs | 485 ++++++
.../Cache/Affinity/AffinityTest.cs | 138 ++
.../Cache/CacheAffinityFieldTest.cs | 199 ---
.../Cache/CacheAffinityTest.cs | 139 --
.../Cache/CacheConfigurationTest.cs | 134 +-
.../Cache/Query/CacheLinqTest.cs | 84 +-
.../Cache/Query/CacheQueriesTest.cs | 257 +--
.../Continuous/ContinuousQueryAbstractTest.cs | 18 +-
.../Cache/Store/CacheStoreTest.cs | 11 +-
.../Compute/AbstractTaskTest.cs | 9 +
.../Compute/BinarizableTaskTest.cs | 13 +-
.../Compute/ComputeApiTest.cs | 110 +-
.../Compute/FailoverTaskSelfTest.cs | 2 +-
.../Compute/IgniteExceptionTaskSelfTest.cs | 18 +-
.../Compute/ResourceTaskTest.cs | 8 +-
.../Compute/TaskAdapterTest.cs | 16 +-
.../Compute/TaskResultTest.cs | 10 +-
.../Config/Cache/Affinity/affinity-function.xml | 4 +-
.../Config/cache-query-continuous.xml | 1 +
.../native-client-test-cache-affinity.xml | 2 +-
.../ConsoleRedirectTest.cs | 177 ++
.../Apache.Ignite.Core.Tests/EventsTest.cs | 4 +-
.../Apache.Ignite.Core.Tests/ExceptionsTest.cs | 81 +-
.../IgniteConfigurationSectionTest.cs | 32 +
.../IgniteConfigurationSerializerTest.cs | 21 +
.../IgniteConfigurationTest.cs | 12 +-
.../IgniteStartStopTest.cs | 3 +-
.../Apache.Ignite.Core.Tests/LifecycleTest.cs | 9 +
.../Properties/AssemblyInfo.cs | 2 +-
.../Apache.Ignite.Core.Tests/ReconnectTest.cs | 13 +
.../Services/ServiceProxyTest.cs | 6 +-
.../Services/ServicesTest.cs | 26 +-
.../Apache.Ignite.Core.Tests/TestRunner.cs | 46 +-
.../Apache.Ignite.Core.Tests/TestUtils.cs | 15 +-
.../dotnet/Apache.Ignite.Core.Tests/app.config | 2 +-
.../Apache.Ignite.Core.Tests/custom_app.config | 34 +
.../Apache.Ignite.Core.Schema.nuspec | 53 +
.../Apache.Ignite.Core.csproj | 19 +-
.../Apache.Ignite.Core.nuspec | 2 +-
.../Binary/BinaryReflectiveSerializer.cs | 193 +-
.../Cache/Configuration/CacheConfiguration.cs | 18 +-
.../Cache/Query/SqlFieldsQuery.cs | 27 +-
.../Apache.Ignite.Core/Cache/Query/SqlQuery.cs | 13 +
.../Apache.Ignite.Core/Cluster/IClusterGroup.cs | 6 +
.../Apache.Ignite.Core/Common/JavaException.cs | 65 +
.../Configuration/AtomicConfiguration.cs | 9 +
.../Configuration/Package-Info.cs | 26 +
.../Discovery/Package-Info.cs | 26 +
.../Discovery/Tcp/Multicast/Package-Info.cs | 26 +
.../Discovery/Tcp/Package-Info.cs | 26 +
.../Discovery/Tcp/Static/Package-Info.cs | 26 +
.../Apache.Ignite.Core/Events/EventBase.cs | 2 +-
.../dotnet/Apache.Ignite.Core/IIgnite.cs | 25 +
.../Apache.Ignite.Core/IgniteConfiguration.cs | 2 +
.../IgniteConfigurationSection.xsd | 9 +-
.../dotnet/Apache.Ignite.Core/Ignition.cs | 82 +-
.../Impl/Binary/BinarizableSerializer.cs | 22 +-
.../Impl/Binary/BinaryFullTypeDescriptor.cs | 8 +-
.../Impl/Binary/BinaryReader.cs | 38 +-
.../Impl/Binary/BinaryReaderExtensions.cs | 2 +-
.../Impl/Binary/BinaryReflectiveActions.cs | 10 +-
.../BinaryReflectiveSerializerInternal.cs | 169 ++
.../Binary/BinarySurrogateTypeDescriptor.cs | 4 +-
.../Impl/Binary/BinarySystemTypeSerializer.cs | 20 +-
.../Impl/Binary/BinaryUtils.cs | 180 +-
.../Impl/Binary/BinaryWriter.cs | 2 +-
.../Impl/Binary/DateTimeSerializer.cs | 48 +
.../Impl/Binary/IBinarySerializerInternal.cs | 42 +
.../Impl/Binary/IBinarySystemTypeSerializer.cs | 34 -
.../Impl/Binary/IBinaryTypeDescriptor.cs | 2 +-
.../Impl/Binary/Io/BinaryHeapStream.cs | 2 +-
.../Impl/Binary/Io/BinaryStreamBase.cs | 14 -
.../Impl/Binary/Marshaller.cs | 77 +-
.../Impl/Binary/SerializableSerializer.cs | 48 +
.../Impl/Binary/UserSerializerProxy.cs | 68 +
.../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs | 6 +-
.../Impl/Cache/Store/CacheStore.cs | 4 +-
.../Impl/Cluster/ClusterGroupImpl.cs | 6 +
.../Impl/Common/DelegateConverter.cs | 44 +
.../Impl/Compute/ComputeTaskHolder.cs | 3 +-
.../Apache.Ignite.Core/Impl/ExceptionUtils.cs | 31 +-
.../dotnet/Apache.Ignite.Core/Impl/Ignite.cs | 48 +-
.../Apache.Ignite.Core/Impl/IgniteProxy.cs | 43 +-
.../Apache.Ignite.Core/Impl/IgniteUtils.cs | 47 +-
.../Impl/LifecycleBeanHolder.cs | 2 +-
.../Impl/Memory/PlatformMemoryStream.cs | 3 +-
.../Apache.Ignite.Core/Impl/NativeMethods.cs | 6 +
.../Impl/Services/ServiceProxyInvoker.cs | 14 +-
.../Impl/Services/Services.cs | 17 +-
.../Impl/Unmanaged/IgniteJniNativeMethods.cs | 9 +
.../Impl/Unmanaged/UnmanagedCallbacks.cs | 94 +-
.../Impl/Unmanaged/UnmanagedUtils.cs | 23 +
.../Apache.Ignite.Core/Interop/Package-Info.cs | 26 +
.../Lifecycle/ClientReconnectEventArgs.cs | 47 +
.../Properties/AssemblyInfo.cs | 4 +-
.../Transactions/TransactionConfiguration.cs | 12 +
.../Apache.Ignite.Linq.csproj | 2 +
.../Apache.Ignite.Linq.nuspec | 6 +-
.../Apache.Ignite.Linq/CacheExtensions.cs | 24 +-
.../Apache.Ignite.Linq/Impl/AliasDictionary.cs | 74 +-
.../Impl/CacheFieldsQueryExecutor.cs | 63 +-
.../Impl/CacheQueryExpressionVisitor.cs | 4 +-
.../Impl/CacheQueryModelVisitor.cs | 6 +-
.../Apache.Ignite.Linq/Impl/CacheQueryable.cs | 10 +-
.../Impl/CacheQueryableBase.cs | 7 +-
.../Apache.Ignite.Linq/Impl/ExpressionWalker.cs | 34 +-
.../dotnet/Apache.Ignite.Linq/Package-Info.cs | 26 +
.../Properties/AssemblyInfo.cs | 2 +-
.../dotnet/Apache.Ignite.Linq/QueryOptions.cs | 91 +
modules/platforms/dotnet/Apache.Ignite.dxg | 4 +-
modules/platforms/dotnet/Apache.Ignite.sln | 14 +
.../dotnet/Apache.Ignite.sln.DotSettings | 7 +-
.../dotnet/Apache.Ignite/Config/Configurator.cs | 11 +-
.../Apache.Ignite/Properties/AssemblyInfo.cs | 2 +-
.../Properties/AssemblyInfo.cs | 2 +-
.../Properties/AssemblyInfo.cs | 2 +-
.../http/jetty/GridJettyRestHandler.java | 5 +
.../processors/schedule/ScheduleFutureImpl.java | 7 +-
.../schedule/GridScheduleSelfTest.java | 33 +-
.../apache/ignite/logger/slf4j/Slf4jLogger.java | 2 +-
.../org/apache/ignite/spark/IgniteContext.scala | 8 +-
.../org/apache/ignite/spark/IgniteRDD.scala | 10 +-
.../apache/ignite/spark/JavaIgniteContext.scala | 2 +-
.../org/apache/ignite/spark/JavaIgniteRDD.scala | 12 +-
.../ignite/spark/impl/IgniteAbstractRDD.scala | 2 +-
.../apache/ignite/spark/impl/IgniteSqlRDD.scala | 2 +-
.../spark/JavaEmbeddedIgniteRDDSelfTest.java | 19 +-
.../org/apache/ignite/spark/IgniteRDDSpec.scala | 38 +-
modules/spring/pom.xml | 7 -
.../org/apache/ignite/IgniteSpringBean.java | 143 +-
.../GridResourceSpringBeanInjector.java | 39 +-
.../ignite/internal/IgniteSpringBeanTest.java | 55 +
.../GridSpringResourceInjectionSelfTest.java | 311 +++-
.../spring-resource-with-duplicate-beans.xml | 30 +
.../processors/resource/spring-resource.xml | 2 +-
.../org/apache/ignite/spring-injection-test.xml | 2 +-
.../testsuites/IgniteSpringTestSuite.java | 2 +
.../cache/websession/WebSessionFilter.java | 11 +-
.../ignite/cache/websession/WebSessionV2.java | 10 +-
.../internal/websession/WebSessionSelfTest.java | 8 +-
modules/yardstick/config/queries.sql | 1 +
.../ignite/yardstick/IgniteBenchmarkUtils.java | 45 +
.../IgniteSqlQueryDistributedJoinBenchmark.java | 184 ++
...lQueryDistributedJoinBroadcastBenchmark.java | 28 +
.../IgniteCacheRandomOperationBenchmark.java | 71 +-
parent/pom.xml | 25 +-
417 files changed, 25610 insertions(+), 5087 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/7d05b650/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
[17/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
ignite-1232 Distributed SQL joins implementation
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/68891e89
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/68891e89
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/68891e89
Branch: refs/heads/ignite-3553
Commit: 68891e89dd0e0f19321d6a4d45ae7372279b8b08
Parents: eddd0a9
Author: sboikov <sb...@gridgain.com>
Authored: Fri Jul 22 17:07:58 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Fri Jul 22 17:08:03 2016 +0300
----------------------------------------------------------------------
.../examples/datagrid/CacheQueryExample.java | 78 +-
.../ignite/codegen/MessageCodeGenerator.java | 6 +
.../ignite/cache/query/SqlFieldsQuery.java | 53 +
.../org/apache/ignite/cache/query/SqlQuery.java | 25 +
.../managers/communication/GridIoManager.java | 32 +-
.../communication/GridIoMessageFactory.java | 2 +-
.../managers/communication/GridIoPolicy.java | 5 +-
.../cache/GridCacheAffinityManager.java | 2 +-
.../processors/cache/GridCacheContext.java | 19 +
.../GridCacheDefaultAffinityKeyMapper.java | 19 +
.../processors/cache/IgniteCacheProxy.java | 8 +
.../binary/CacheObjectBinaryProcessorImpl.java | 8 +
.../dht/GridDhtPartitionsReservation.java | 3 +-
.../cache/query/GridCacheQueryManager.java | 47 +-
.../cache/query/GridCacheQueryMarshallable.java | 37 +
.../cache/query/GridCacheSqlQuery.java | 33 +-
.../cache/query/GridCacheTwoStepQuery.java | 123 +-
.../cacheobject/IgniteCacheObjectProcessor.java | 6 +
.../IgniteCacheObjectProcessorImpl.java | 5 +
.../processors/closure/GridClosurePolicy.java | 51 -
.../closure/GridClosureProcessor.java | 52 +-
.../processors/query/GridQueryIndexing.java | 51 +-
.../processors/query/GridQueryProcessor.java | 192 +-
.../query/GridQueryTypeDescriptor.java | 7 +
.../messages/GridQueryCancelRequest.java | 2 +-
.../twostep/messages/GridQueryFailResponse.java | 2 +-
.../messages/GridQueryNextPageRequest.java | 2 +-
.../messages/GridQueryNextPageResponse.java | 12 +-
.../h2/twostep/messages/GridQueryRequest.java | 28 +-
.../ignite/internal/util/IgniteUtils.java | 13 +
.../ignite/internal/util/lang/GridFunc.java | 20 +
.../offheap/unsafe/GridOffHeapSnapTreeMap.java | 91 +-
.../jdbc/TcpDiscoveryJdbcIpFinderSelfTest.java | 2 +-
.../junits/common/GridCommonAbstractTest.java | 39 +-
.../query/h2/opt/GridH2SpatialIndex.java | 74 +-
.../processors/query/h2/IgniteH2Indexing.java | 709 ++++++--
.../query/h2/opt/GridH2AbstractKeyValueRow.java | 72 +-
.../query/h2/opt/GridH2CollocationModel.java | 783 +++++++++
.../processors/query/h2/opt/GridH2Cursor.java | 36 +-
.../query/h2/opt/GridH2DefaultTableEngine.java | 38 +
.../query/h2/opt/GridH2IndexBase.java | 1392 ++++++++++++++-
.../query/h2/opt/GridH2MetaTable.java | 383 ++++
.../query/h2/opt/GridH2QueryContext.java | 612 +++++++
.../query/h2/opt/GridH2QueryType.java | 49 +
.../query/h2/opt/GridH2RetryException.java | 32 +
.../processors/query/h2/opt/GridH2Row.java | 86 +-
.../query/h2/opt/GridH2RowDescriptor.java | 28 +-
.../query/h2/opt/GridH2RowFactory.java | 179 ++
.../processors/query/h2/opt/GridH2Table.java | 372 ++--
.../query/h2/opt/GridH2TreeIndex.java | 142 +-
.../processors/query/h2/opt/GridH2Utils.java | 133 --
.../query/h2/opt/GridH2ValueCacheObject.java | 3 +-
.../query/h2/opt/GridLuceneIndex.java | 7 +-
.../processors/query/h2/sql/GridSqlAlias.java | 12 +
.../processors/query/h2/sql/GridSqlColumn.java | 22 +-
.../processors/query/h2/sql/GridSqlElement.java | 11 +
.../query/h2/sql/GridSqlOperation.java | 2 +-
.../query/h2/sql/GridSqlOperationType.java | 8 +-
.../query/h2/sql/GridSqlQueryParser.java | 97 +-
.../query/h2/sql/GridSqlQuerySplitter.java | 293 +++-
.../processors/query/h2/sql/GridSqlSelect.java | 9 +-
.../processors/query/h2/sql/GridSqlTable.java | 70 +
.../query/h2/twostep/GridMapQueryExecutor.java | 415 +++--
.../query/h2/twostep/GridMergeIndex.java | 75 +-
.../h2/twostep/GridMergeIndexUnsorted.java | 6 +-
.../query/h2/twostep/GridMergeTable.java | 4 +-
.../h2/twostep/GridReduceQueryExecutor.java | 338 ++--
.../query/h2/twostep/GridThreadLocalTable.java | 68 +-
.../query/h2/twostep/msg/GridH2Array.java | 9 +-
.../query/h2/twostep/msg/GridH2Boolean.java | 10 +-
.../query/h2/twostep/msg/GridH2Byte.java | 9 +-
.../query/h2/twostep/msg/GridH2Bytes.java | 11 +-
.../query/h2/twostep/msg/GridH2CacheObject.java | 9 +-
.../query/h2/twostep/msg/GridH2Date.java | 9 +-
.../query/h2/twostep/msg/GridH2Decimal.java | 11 +-
.../query/h2/twostep/msg/GridH2Double.java | 9 +-
.../query/h2/twostep/msg/GridH2Float.java | 9 +-
.../query/h2/twostep/msg/GridH2Geometry.java | 11 +-
.../h2/twostep/msg/GridH2IndexRangeRequest.java | 208 +++
.../twostep/msg/GridH2IndexRangeResponse.java | 279 +++
.../query/h2/twostep/msg/GridH2Integer.java | 20 +-
.../query/h2/twostep/msg/GridH2JavaObject.java | 11 +-
.../query/h2/twostep/msg/GridH2Long.java | 9 +-
.../query/h2/twostep/msg/GridH2Null.java | 15 +-
.../h2/twostep/msg/GridH2QueryRequest.java | 401 +++++
.../query/h2/twostep/msg/GridH2RowMessage.java | 116 ++
.../query/h2/twostep/msg/GridH2RowRange.java | 181 ++
.../h2/twostep/msg/GridH2RowRangeBounds.java | 188 ++
.../query/h2/twostep/msg/GridH2Short.java | 9 +-
.../query/h2/twostep/msg/GridH2String.java | 9 +-
.../query/h2/twostep/msg/GridH2Time.java | 9 +-
.../query/h2/twostep/msg/GridH2Timestamp.java | 11 +-
.../query/h2/twostep/msg/GridH2Uuid.java | 9 +-
.../h2/twostep/msg/GridH2ValueMessage.java | 2 +-
.../twostep/msg/GridH2ValueMessageFactory.java | 22 +-
...idCacheReduceQueryMultithreadedSelfTest.java | 168 --
.../cache/IgniteCacheAbstractQuerySelfTest.java | 30 +-
.../IgniteCacheCrossCacheJoinRandomTest.java | 442 +++++
...acheDistributedJoinCollocatedAndNotTest.java | 365 ++++
...acheDistributedJoinCustomAffinityMapper.java | 262 +++
.../IgniteCacheDistributedJoinNoIndexTest.java | 299 ++++
...ributedJoinPartitionedAndReplicatedTest.java | 487 ++++++
...CacheDistributedJoinQueryConditionsTest.java | 624 +++++++
.../cache/IgniteCacheDistributedJoinTest.java | 316 ++++
...PartitionedAndReplicatedCollocationTest.java | 399 +++++
...teCacheJoinPartitionedAndReplicatedTest.java | 78 +-
...IgniteCacheJoinQueryWithAffinityKeyTest.java | 646 +++++++
.../cache/IgniteCacheQueryLoadSelfTest.java | 12 +-
.../cache/IgniteCrossCachesJoinsQueryTest.java | 1641 ++++++++++++++++++
...QueryNodeRestartDistributedJoinSelfTest.java | 476 +++++
...dCacheAbstractReduceFieldsQuerySelfTest.java | 420 -----
...ridCacheReduceFieldsQueryAtomicSelfTest.java | 38 -
...GridCacheReduceFieldsQueryLocalSelfTest.java | 37 -
...cheReduceFieldsQueryPartitionedSelfTest.java | 59 -
...acheReduceFieldsQueryReplicatedSelfTest.java | 37 -
.../query/IgniteSqlSchemaIndexingTest.java | 5 +-
.../query/IgniteSqlSplitterSelfTest.java | 833 ++++++++-
.../h2/GridIndexingSpiAbstractSelfTest.java | 145 +-
.../query/h2/opt/GridH2TableSelfTest.java | 10 +-
.../h2/sql/AbstractH2CompareQueryTest.java | 163 +-
.../query/h2/sql/GridQueryParsingTest.java | 17 +-
.../H2CompareBigQueryDistributedJoinsTest.java | 28 +
.../query/h2/sql/H2CompareBigQueryTest.java | 119 +-
.../IgniteCacheQuerySelfTestSuite.java | 25 +-
.../IgniteCacheQuerySelfTestSuite2.java | 10 -
.../ignite/yardstick/IgniteBenchmarkUtils.java | 45 +
.../IgniteSqlQueryDistributedJoinBenchmark.java | 184 ++
...lQueryDistributedJoinBroadcastBenchmark.java | 28 +
parent/pom.xml | 24 +-
129 files changed, 15201 insertions(+), 2502 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryExample.java
----------------------------------------------------------------------
diff --git a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryExample.java b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryExample.java
index 9200489..85d74e0 100644
--- a/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryExample.java
+++ b/examples/src/main/java/org/apache/ignite/examples/datagrid/CacheQueryExample.java
@@ -46,8 +46,11 @@ import org.apache.ignite.lang.IgniteBiPredicate;
* limitations (not applied if data is queried from one node only):
* <ul>
* <li>
- * Joins will work correctly only if joined objects are stored in
+ * Non-distributed joins will work correctly only if joined objects are stored in
* collocated mode. Refer to {@link AffinityKey} javadoc for more details.
+ * <p>
+ * To use distributed joins it is necessary to set query 'distributedJoin' flag using
+ * {@link SqlFieldsQuery#setDistributedJoins(boolean)} or {@link SqlQuery#setDistributedJoins(boolean)}.
* </li>
* <li>
* Note that if you created query on to replicated cache, all data will
@@ -65,6 +68,9 @@ public class CacheQueryExample {
/** Organizations cache name. */
private static final String ORG_CACHE = CacheQueryExample.class.getSimpleName() + "Organizations";
+ /** Persons collocated with Organizations cache name. */
+ private static final String COLLOCATED_PERSON_CACHE = CacheQueryExample.class.getSimpleName() + "CollocatedPersons";
+
/** Persons cache name. */
private static final String PERSON_CACHE = CacheQueryExample.class.getSimpleName() + "Persons";
@@ -84,14 +90,20 @@ public class CacheQueryExample {
orgCacheCfg.setCacheMode(CacheMode.PARTITIONED); // Default.
orgCacheCfg.setIndexedTypes(Long.class, Organization.class);
+ CacheConfiguration<AffinityKey<Long>, Person> colPersonCacheCfg = new CacheConfiguration<>(COLLOCATED_PERSON_CACHE);
+
+ colPersonCacheCfg.setCacheMode(CacheMode.PARTITIONED); // Default.
+ colPersonCacheCfg.setIndexedTypes(AffinityKey.class, Person.class);
+
CacheConfiguration<AffinityKey<Long>, Person> personCacheCfg = new CacheConfiguration<>(PERSON_CACHE);
personCacheCfg.setCacheMode(CacheMode.PARTITIONED); // Default.
- personCacheCfg.setIndexedTypes(AffinityKey.class, Person.class);
+ personCacheCfg.setIndexedTypes(Long.class, Person.class);
// Auto-close cache at the end of the example.
try (
IgniteCache<Long, Organization> orgCache = ignite.getOrCreateCache(orgCacheCfg);
+ IgniteCache<AffinityKey<Long>, Person> colPersonCache = ignite.getOrCreateCache(colPersonCacheCfg);
IgniteCache<AffinityKey<Long>, Person> personCache = ignite.getOrCreateCache(personCacheCfg)
) {
// Populate cache.
@@ -103,9 +115,12 @@ public class CacheQueryExample {
// Example for SQL-based querying employees based on salary ranges.
sqlQuery();
- // Example for SQL-based querying employees for a given organization (includes SQL join).
+ // Example for SQL-based querying employees for a given organization (includes SQL join for collocated objects).
sqlQueryWithJoin();
+ // Example for SQL-based querying employees for a given organization (includes distributed SQL join).
+ sqlQueryWithDistributedJoin();
+
// Example for TEXT-based querying for a given string in peoples resumes.
textQuery();
@@ -121,6 +136,7 @@ public class CacheQueryExample {
}
finally {
// Distributed cache could be removed from cluster only by #destroyCache() call.
+ ignite.destroyCache(COLLOCATED_PERSON_CACHE);
ignite.destroyCache(PERSON_CACHE);
ignite.destroyCache(ORG_CACHE);
}
@@ -133,7 +149,7 @@ public class CacheQueryExample {
* Example for scan query based on a predicate.
*/
private static void scanQuery() {
- IgniteCache<BinaryObject, BinaryObject> cache = Ignition.ignite().cache(PERSON_CACHE).withKeepBinary();
+ IgniteCache<BinaryObject, BinaryObject> cache = Ignition.ignite().cache(COLLOCATED_PERSON_CACHE).withKeepBinary();
ScanQuery<BinaryObject, BinaryObject> scan = new ScanQuery<>(
new IgniteBiPredicate<BinaryObject, BinaryObject>() {
@@ -170,7 +186,7 @@ public class CacheQueryExample {
* Example for SQL queries based on all employees working for a specific organization.
*/
private static void sqlQueryWithJoin() {
- IgniteCache<AffinityKey<Long>, Person> cache = Ignition.ignite().cache(PERSON_CACHE);
+ IgniteCache<AffinityKey<Long>, Person> cache = Ignition.ignite().cache(COLLOCATED_PERSON_CACHE);
// SQL clause query which joins on 2 types to select people for a specific organization.
String joinSql =
@@ -189,6 +205,32 @@ public class CacheQueryExample {
}
/**
+ * Example for SQL queries based on all employees working for a specific organization (query uses distributed join).
+ */
+ private static void sqlQueryWithDistributedJoin() {
+ IgniteCache<AffinityKey<Long>, Person> cache = Ignition.ignite().cache(PERSON_CACHE);
+
+ // SQL clause query which joins on 2 types to select people for a specific organization.
+ String joinSql =
+ "from Person, \"" + ORG_CACHE + "\".Organization as org " +
+ "where Person.orgId = org.id " +
+ "and lower(org.name) = lower(?)";
+
+ SqlQuery qry = new SqlQuery<AffinityKey<Long>, Person>(Person.class, joinSql).
+ setArgs("ApacheIgnite");
+
+ // Enable distributed joins for query.
+ qry.setDistributedJoins(true);
+
+ // Execute queries for find employees for different organizations.
+ print("Following people are 'ApacheIgnite' employees (distributed join): ", cache.query(qry).getAll());
+
+ qry.setArgs("Other");
+
+ print("Following people are 'Other' employees (distributed join): ", cache.query(qry).getAll());
+ }
+
+ /**
* Example for TEXT queries using LUCENE-based indexing of people's resumes.
*/
private static void textQuery() {
@@ -210,7 +252,7 @@ public class CacheQueryExample {
* Example for SQL queries to calculate average salary for a specific organization.
*/
private static void sqlQueryWithAggregation() {
- IgniteCache<AffinityKey<Long>, Person> cache = Ignition.ignite().cache(PERSON_CACHE);
+ IgniteCache<AffinityKey<Long>, Person> cache = Ignition.ignite().cache(COLLOCATED_PERSON_CACHE);
// Calculate average of salary of all persons in ApacheIgnite.
// Note that we also join on Organization cache as well.
@@ -249,7 +291,7 @@ public class CacheQueryExample {
* fields instead of whole key-value pairs.
*/
private static void sqlFieldsQueryWithJoin() {
- IgniteCache<AffinityKey<Long>, Person> cache = Ignition.ignite().cache(PERSON_CACHE);
+ IgniteCache<AffinityKey<Long>, Person> cache = Ignition.ignite().cache(COLLOCATED_PERSON_CACHE);
// Execute query to get names of all employees.
String sql =
@@ -263,7 +305,7 @@ public class CacheQueryExample {
List<List<?>> res = cursor.getAll();
// Print persons' names and organizations' names.
- print("Names of all employees and organizations they belong to:", res);
+ print("Names of all employees and organizations they belong to: ", res);
}
/**
@@ -282,9 +324,11 @@ public class CacheQueryExample {
orgCache.put(org1.id(), org1);
orgCache.put(org2.id(), org2);
- IgniteCache<AffinityKey<Long>, Person> personCache = Ignition.ignite().cache(PERSON_CACHE);
+ IgniteCache<AffinityKey<Long>, Person> colPersonCache = Ignition.ignite().cache(COLLOCATED_PERSON_CACHE);
+ IgniteCache<Long, Person> personCache = Ignition.ignite().cache(PERSON_CACHE);
- // Clear cache before running the example.
+ // Clear caches before running the example.
+ colPersonCache.clear();
personCache.clear();
// People.
@@ -295,10 +339,16 @@ public class CacheQueryExample {
// Note that in this example we use custom affinity key for Person objects
// to ensure that all persons are collocated with their organizations.
- personCache.put(p1.key(), p1);
- personCache.put(p2.key(), p2);
- personCache.put(p3.key(), p3);
- personCache.put(p4.key(), p4);
+ colPersonCache.put(p1.key(), p1);
+ colPersonCache.put(p2.key(), p2);
+ colPersonCache.put(p3.key(), p3);
+ colPersonCache.put(p4.key(), p4);
+
+ // These Person objects are not collocated with their organizations.
+ personCache.put(p1.id, p1);
+ personCache.put(p2.id, p2);
+ personCache.put(p3.id, p3);
+ personCache.put(p4.id, p4);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
----------------------------------------------------------------------
diff --git a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
index a6ae0da..f0ba5ce 100644
--- a/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
+++ b/modules/codegen/src/main/java/org/apache/ignite/codegen/MessageCodeGenerator.java
@@ -223,6 +223,12 @@ public class MessageCodeGenerator {
// gen.generateAndWrite(GridH2Uuid.class);
// gen.generateAndWrite(GridH2Geometry.class);
// gen.generateAndWrite(GridH2CacheObject.class);
+// gen.generateAndWrite(GridH2IndexRangeRequest.class);
+// gen.generateAndWrite(GridH2IndexRangeResponse.class);
+// gen.generateAndWrite(GridH2RowRange.class);
+// gen.generateAndWrite(GridH2RowRangeBounds.class);
+// gen.generateAndWrite(GridH2QueryRequest.class);
+// gen.generateAndWrite(GridH2RowMessage.class);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
index b2dd181..48dab6b 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlFieldsQuery.java
@@ -56,6 +56,12 @@ public final class SqlFieldsQuery extends Query<List<?>> {
/** Collocation flag. */
private boolean collocated;
+ /** */
+ private boolean enforceJoinOrder;
+
+ /** */
+ private boolean distributedJoins;
+
/**
* Constructs SQL fields query.
*
@@ -141,6 +147,53 @@ public final class SqlFieldsQuery extends Query<List<?>> {
return this;
}
+ /**
+ * Checks if join order of tables if enforced.
+ *
+ * @return Flag value.
+ */
+ public boolean isEnforceJoinOrder() {
+ return enforceJoinOrder;
+ }
+
+ /**
+ * Sets flag to enforce join order of tables in the query. If set to {@code true}
+ * query optimizer will not reorder tables in join. By default is {@code false}.
+ * <p>
+ * It is not recommended to enable this property until you are sure that
+ * your indexes and the query itself are correct and tuned as much as possible but
+ * query optimizer still produces wrong join order.
+ *
+ * @param enforceJoinOrder Flag value.
+ * @return {@code this} For chaining.
+ */
+ public SqlFieldsQuery setEnforceJoinOrder(boolean enforceJoinOrder) {
+ this.enforceJoinOrder = enforceJoinOrder;
+
+ return this;
+ }
+
+ /**
+ * Specify if distributed joins are enabled for this query.
+ *
+ * @param distributedJoins Distributed joins enabled.
+ * @return {@code this} For chaining.
+ */
+ public SqlFieldsQuery setDistributedJoins(boolean distributedJoins) {
+ this.distributedJoins = distributedJoins;
+
+ return this;
+ }
+
+ /**
+ * Check if distributed joins are enabled for this query.
+ *
+ * @return {@code true} If distributed joind enabled.
+ */
+ public boolean isDistributedJoins() {
+ return distributedJoins;
+ }
+
/** {@inheritDoc} */
@Override public SqlFieldsQuery setPageSize(int pageSize) {
return (SqlFieldsQuery)super.setPageSize(pageSize);
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
index be3b390..e05ff13 100644
--- a/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
+++ b/modules/core/src/main/java/org/apache/ignite/cache/query/SqlQuery.java
@@ -43,6 +43,9 @@ public final class SqlQuery<K, V> extends Query<Cache.Entry<K, V>> {
@GridToStringInclude
private Object[] args;
+ /** */
+ private boolean distributedJoins;
+
/**
* Constructs query for the given type name and SQL query.
*
@@ -142,11 +145,33 @@ public final class SqlQuery<K, V> extends Query<Cache.Entry<K, V>> {
/**
* @param type Type.
+ * @return {@code this} For chaining.
*/
public SqlQuery setType(Class<?> type) {
return setType(GridQueryProcessor.typeName(type));
}
+ /**
+ * Specify if distributed joins are enabled for this query.
+ *
+ * @param distributedJoins Distributed joins enabled.
+ * @return {@code this} For chaining.
+ */
+ public SqlQuery setDistributedJoins(boolean distributedJoins) {
+ this.distributedJoins = distributedJoins;
+
+ return this;
+ }
+
+ /**
+ * Check if distributed joins are enabled for this query.
+ *
+ * @return {@code true} If distributed joind enabled.
+ */
+ public boolean isDistributedJoins() {
+ return distributedJoins;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(SqlQuery.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
index 4bc2eea..99cb7f4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoManager.java
@@ -88,6 +88,7 @@ import static org.apache.ignite.events.EventType.EVT_NODE_JOINED;
import static org.apache.ignite.events.EventType.EVT_NODE_LEFT;
import static org.apache.ignite.internal.GridTopic.TOPIC_COMM_USER;
import static org.apache.ignite.internal.managers.communication.GridIoPolicy.AFFINITY_POOL;
+import static org.apache.ignite.internal.managers.communication.GridIoPolicy.IDX_POOL;
import static org.apache.ignite.internal.managers.communication.GridIoPolicy.IGFS_POOL;
import static org.apache.ignite.internal.managers.communication.GridIoPolicy.MANAGEMENT_POOL;
import static org.apache.ignite.internal.managers.communication.GridIoPolicy.MARSH_CACHE_POOL;
@@ -157,6 +158,9 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
/** IGFS pool. */
private ExecutorService igfsPool;
+ /** Index pool. */
+ private ExecutorService idxPool;
+
/** Discovery listener. */
private GridLocalEventListener discoLsnr;
@@ -268,6 +272,13 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
0,
new LinkedBlockingQueue<Runnable>());
+ if (IgniteComponentType.INDEXING.inClassPath()) {
+ int cpus = Runtime.getRuntime().availableProcessors();
+
+ idxPool = new IgniteThreadPoolExecutor("idx", ctx.gridName(),
+ cpus, cpus * 2, 3000L, new LinkedBlockingQueue<Runnable>(1000));
+ }
+
getSpi().setListener(commLsnr = new CommunicationListener<Serializable>() {
@Override public void onMessage(UUID nodeId, Serializable msg, IgniteRunnable msgC) {
try {
@@ -651,6 +662,7 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
case AFFINITY_POOL:
case UTILITY_CACHE_POOL:
case MARSH_CACHE_POOL:
+ case IDX_POOL:
case IGFS_POOL:
{
if (msg.isOrdered())
@@ -689,7 +701,7 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
* @return Execution pool.
* @throws IgniteCheckedException If failed.
*/
- private Executor pool(byte plc) throws IgniteCheckedException {
+ public Executor pool(byte plc) throws IgniteCheckedException {
switch (plc) {
case P2P_POOL:
return p2pPool;
@@ -717,6 +729,11 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
return igfsPool;
+ case IDX_POOL:
+ assert idxPool != null : "Indexing pool is not configured.";
+
+ return idxPool;
+
default: {
assert plc >= 0 : "Negative policy: " + plc;
@@ -1357,6 +1374,19 @@ public class GridIoManager extends GridManagerAdapter<CommunicationSpi<Serializa
/**
* @param node Destination node.
* @param topic Topic to send the message to.
+ * @param topicOrd GridTopic enumeration ordinal.
+ * @param msg Message to send.
+ * @param plc Type of processing.
+ * @throws IgniteCheckedException Thrown in case of any errors.
+ */
+ public void send(ClusterNode node, Object topic, int topicOrd, Message msg, byte plc)
+ throws IgniteCheckedException {
+ send(node, topic, topicOrd, msg, plc, false, 0, false, null);
+ }
+
+ /**
+ * @param node Destination node.
+ * @param topic Topic to send the message to.
* @param msg Message to send.
* @param plc Type of processing.
* @param timeout Timeout to keep a message on receiving queue.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
index 5f60215..1eebfd4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoMessageFactory.java
@@ -752,7 +752,7 @@ public class GridIoMessageFactory implements MessageFactory {
// [-3..119] [124] - this
// [120..123] - DR
- // [-4..-22] - SQL
+ // [-4..-22, -30..-35] - SQL
default:
if (ext != null) {
for (MessageFactory factory : ext) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoPolicy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoPolicy.java b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoPolicy.java
index 00590ba..70a7354 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoPolicy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/managers/communication/GridIoPolicy.java
@@ -43,9 +43,12 @@ public class GridIoPolicy {
/** Marshaller cache execution pool. */
public static final byte MARSH_CACHE_POOL = 6;
- /** Marshaller cache execution pool. */
+ /** IGFS pool. */
public static final byte IGFS_POOL = 7;
+ /** Pool for handling distributed index range requests. */
+ public static final byte IDX_POOL = 8;
+
/**
* Defines the range of reserved pools that are not available for plugins.
* @param key The key.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
index 8633333..e0e8031 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheAffinityManager.java
@@ -224,7 +224,7 @@ public class GridCacheAffinityManager extends GridCacheManagerAdapter {
* @param key Key.
* @return Affinity key.
*/
- private Object affinityKey(Object key) {
+ public Object affinityKey(Object key) {
if (key instanceof CacheObject && !(key instanceof BinaryObject))
key = ((CacheObject)key).value(cctx.cacheObjectContext(), false);
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
index 36d9104..fec43d0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheContext.java
@@ -245,6 +245,9 @@ public class GridCacheContext<K, V> implements Externalizable {
/** */
private boolean deferredDel;
+ /** */
+ private boolean customAffMapper;
+
/**
* Empty constructor required for {@link Externalizable}.
*/
@@ -365,6 +368,13 @@ public class GridCacheContext<K, V> implements Externalizable {
}
/**
+ * @return {@code True} if custom {@link AffinityKeyMapper} is configured for cache.
+ */
+ public boolean customAffinityMapper() {
+ return customAffMapper;
+ }
+
+ /**
* @param dynamicDeploymentId Dynamic deployment ID.
*/
void dynamicDeploymentId(IgniteUuid dynamicDeploymentId) {
@@ -567,6 +577,13 @@ public class GridCacheContext<K, V> implements Externalizable {
}
/**
+ * @return {@code True} if cache is partitioned cache.
+ */
+ public boolean isPartitioned() {
+ return cacheCfg.getCacheMode() == CacheMode.PARTITIONED;
+ }
+
+ /**
* @return {@code True} in case replication is enabled.
*/
public boolean isDrEnabled() {
@@ -1132,6 +1149,8 @@ public class GridCacheContext<K, V> implements Externalizable {
*/
public void cacheObjectContext(CacheObjectContext cacheObjCtx) {
this.cacheObjCtx = cacheObjCtx;
+
+ customAffMapper = cacheCfg.getAffinityMapper().getClass() != cacheObjCtx.defaultAffMapper().getClass();
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDefaultAffinityKeyMapper.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDefaultAffinityKeyMapper.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDefaultAffinityKeyMapper.java
index 5422bbd..4a2f039 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDefaultAffinityKeyMapper.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheDefaultAffinityKeyMapper.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.util.typedef.P1;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.resources.IgniteInstanceResource;
import org.apache.ignite.resources.LoggerResource;
+import org.jetbrains.annotations.Nullable;
/**
* Default key affinity mapper. If key class has annotation {@link AffinityKeyMapped},
@@ -120,6 +121,24 @@ public class GridCacheDefaultAffinityKeyMapper implements AffinityKeyMapper {
}
/**
+ * @param cls Key class.
+ * @return Name of
+ */
+ @Nullable public String affinityKeyPropertyName(Class<?> cls) {
+ Field field = reflectCache.firstField(cls);
+
+ if (field != null)
+ return field.getName();
+
+ Method mtd = reflectCache.firstMethod(cls);
+
+ if (mtd != null)
+ return mtd.getName();
+
+ return null;
+ }
+
+ /**
* @param ignite Ignite.
*/
@IgniteInstanceResource
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
index 0d7bc6a..0005530 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/IgniteCacheProxy.java
@@ -670,6 +670,10 @@ public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V
opCtxCall != null && opCtxCall.isKeepBinary());
if (qry instanceof SqlQuery) {
+ if (isReplicatedDataNode() && ((SqlQuery)qry).isDistributedJoins())
+ throw new CacheException("Queries using distributed JOINs have to be run on partitioned cache, " +
+ "not on replicated.");
+
final SqlQuery p = (SqlQuery)qry;
if (isReplicatedDataNode() || ctx.isLocal() || qry.isLocal())
@@ -684,6 +688,10 @@ public class IgniteCacheProxy<K, V> extends AsyncSupportAdapter<IgniteCache<K, V
}
if (qry instanceof SqlFieldsQuery) {
+ if (isReplicatedDataNode() && ((SqlFieldsQuery)qry).isDistributedJoins())
+ throw new CacheException("Queries using distributed JOINs have to be run on partitioned cache, " +
+ "not on replicated.");
+
SqlFieldsQuery p = (SqlFieldsQuery)qry;
if (isReplicatedDataNode() || ctx.isLocal() || qry.isLocal())
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
index 8400594..f4d1d6e 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/binary/CacheObjectBinaryProcessorImpl.java
@@ -516,6 +516,14 @@ public class CacheObjectBinaryProcessorImpl extends IgniteCacheObjectProcessorIm
}
/** {@inheritDoc} */
+ @Override public String affinityField(String keyType) {
+ if (binaryCtx == null)
+ return null;
+
+ return binaryCtx.affinityKeyFieldName(typeId(keyType));
+ }
+
+ /** {@inheritDoc} */
@Override public BinaryObjectBuilder builder(String clsName) {
return new BinaryObjectBuilderImpl(binaryCtx, clsName);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionsReservation.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionsReservation.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionsReservation.java
index d12247e..2f51c5a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionsReservation.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/distributed/dht/GridDhtPartitionsReservation.java
@@ -204,7 +204,8 @@ public class GridDhtPartitionsReservation implements GridReservable {
if (reservations.compareAndSet(r, r - 1)) {
// If it was the last reservation and topology version changed -> attempt to evict partitions.
- if (r == 1 && !topVer.equals(cctx.topology().topologyVersion()))
+ if (r == 1 && !cctx.kernalContext().isStopping() &&
+ !topVer.equals(cctx.topology().topologyVersion()))
tryEvict(parts.get());
return;
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
index 4367ee9..60e81e2 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryManager.java
@@ -75,7 +75,6 @@ import org.apache.ignite.internal.processors.datastructures.GridSetQueryPredicat
import org.apache.ignite.internal.processors.datastructures.SetItemKey;
import org.apache.ignite.internal.processors.platform.cache.PlatformCacheEntryFilter;
import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata;
-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.GridQueryProcessor;
@@ -270,25 +269,6 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
}
/**
- * Gets number of objects of given type in index.
- *
- * @param valType Value type.
- * @return Number of objects or -1 if type was not indexed at all.
- * @throws IgniteCheckedException If failed.
- */
- public long size(Class<?> valType) throws IgniteCheckedException {
- if (!enterBusy())
- throw new IllegalStateException("Failed to get size (grid is stopping).");
-
- try {
- return qryProc.size(space, valType);
- }
- finally {
- leaveBusy();
- }
- }
-
- /**
* Rebuilds all search indexes of given value type.
*
* @param typeName Value type name.
@@ -586,26 +566,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
try {
switch (qry.type()) {
case SQL:
- if (cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
- cctx.gridEvents().record(new CacheQueryExecutedEvent<>(
- cctx.localNode(),
- "SQL query executed.",
- EVT_CACHE_QUERY_EXECUTED,
- CacheQueryType.SQL.name(),
- cctx.namex(),
- qry.queryClassName(),
- qry.clause(),
- null,
- null,
- args,
- subjId,
- taskName));
- }
-
- iter = qryProc.query(space, qry.clause(), F.asList(args),
- qry.queryClassName(), filter(qry));
-
- break;
+ throw new IllegalStateException("Should never be called.");
case SCAN:
if (cctx.gridEvents().isRecordable(EVT_CACHE_QUERY_EXECUTED)) {
@@ -764,11 +725,7 @@ public abstract class GridCacheQueryManager<K, V> extends GridCacheManagerAdapte
else {
assert qry.type() == SQL_FIELDS;
- GridQueryFieldsResult qryRes = qryProc.queryFields(space, qry.clause(), F.asList(args), filter(qry));
-
- res.metaData(qryRes.metaData());
-
- res.onDone(qryRes.iterator());
+ throw new IllegalStateException("Should never be called.");
}
}
catch (Exception e) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryMarshallable.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryMarshallable.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryMarshallable.java
new file mode 100644
index 0000000..d87936a
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/GridCacheQueryMarshallable.java
@@ -0,0 +1,37 @@
+/*
+ * 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.query;
+
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.marshaller.Marshaller;
+
+/**
+ * Message which needs to be marshalled and unmarshalled before sending or processing it.
+ */
+public interface GridCacheQueryMarshallable {
+ /**
+ * @param m Marshaller.
+ */
+ public void marshall(Marshaller m);
+
+ /**
+ * @param m Marshaller.
+ * @param ctx Context.
+ */
+ public void unmarshall(Marshaller m, GridKernalContext ctx);
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 0733827..6b81ed1 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
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.processors.cache.query;
import java.nio.ByteBuffer;
import java.util.LinkedHashMap;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.GridDirectTransient;
import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
@@ -35,7 +36,7 @@ import org.apache.ignite.plugin.extensions.communication.MessageWriter;
/**
* Query.
*/
-public class GridCacheSqlQuery implements Message {
+public class GridCacheSqlQuery implements Message, GridCacheQueryMarshallable {
/** */
private static final long serialVersionUID = 0L;
@@ -130,30 +131,34 @@ public class GridCacheSqlQuery implements Message {
return params;
}
- /**
- * @param m Marshaller.
- * @throws IgniteCheckedException If failed.
- */
- public void marshallParams(Marshaller m) throws IgniteCheckedException {
+ /** {@inheritDoc} */
+ @Override public void marshall(Marshaller m) {
if (paramsBytes != null)
return;
assert params != null;
- paramsBytes = m.marshal(params);
+ try {
+ paramsBytes = m.marshal(params);
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException(e);
+ }
}
- /**
- * @param m Marshaller.
- * @throws IgniteCheckedException If failed.
- */
- public void unmarshallParams(Marshaller m, GridKernalContext ctx) throws IgniteCheckedException {
+ /** {@inheritDoc} */
+ @Override public void unmarshall(Marshaller m, GridKernalContext ctx) {
if (params != null)
return;
assert paramsBytes != null;
- params = m.unmarshal(paramsBytes, U.resolveClassLoader(ctx.config()));
+ try {
+ params = m.unmarshal(paramsBytes, U.resolveClassLoader(ctx.config()));
+ }
+ catch (IgniteCheckedException e) {
+ throw new IgniteException(e);
+ }
}
/** {@inheritDoc} */
@@ -271,4 +276,4 @@ public class GridCacheSqlQuery implements Message {
return cp;
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 da59c18..8dcba2f 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
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.processors.cache.query;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Set;
import org.apache.ignite.internal.util.tostring.GridToStringInclude;
@@ -45,24 +46,54 @@ public class GridCacheTwoStepQuery {
private boolean explain;
/** */
- private Set<String> spaces;
+ private Collection<String> spaces;
/** */
- private final boolean skipMergeTbl;
+ private Set<String> schemas;
+
+ /** */
+ private Set<String> tbls;
+
+ /** */
+ private boolean distributedJoins;
+
+ /** */
+ private boolean skipMergeTbl;
+
+ /** */
+ private List<Integer> caches;
+
+ /** */
+ private List<Integer> extraCaches;
/**
- * @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.
+ * @param schemas Schema names in query.
+ * @param tbls Tables in query.
*/
- public GridCacheTwoStepQuery(Set<String> spaces, GridCacheSqlQuery rdc, boolean skipMergeTbl) {
- assert rdc != null;
+ public GridCacheTwoStepQuery(Set<String> schemas, Set<String> tbls) {
+ this.schemas = schemas;
+ this.tbls = tbls;
+ }
- this.spaces = spaces;
- this.rdc = rdc;
- this.skipMergeTbl = skipMergeTbl;
+ /**
+ * Specify if distributed joins are enabled for this query.
+ *
+ * @param distributedJoins Distributed joins enabled.
+ */
+ public void distributedJoins(boolean distributedJoins) {
+ this.distributedJoins = distributedJoins;
+ }
+
+ /**
+ * Check if distributed joins are enabled for this query.
+ *
+ * @return {@code true} If distributed joind enabled.
+ */
+ public boolean distributedJoins() {
+ return distributedJoins;
}
+
+
/**
* @return {@code True} if reduce query can skip merge table creation and get data directly from merge index.
*/
@@ -71,6 +102,13 @@ public class GridCacheTwoStepQuery {
}
/**
+ * @param skipMergeTbl Skip merge table.
+ */
+ public void skipMergeTable(boolean skipMergeTbl) {
+ this.skipMergeTbl = skipMergeTbl;
+ }
+
+ /**
* @return If this is explain query.
*/
public boolean explain() {
@@ -116,6 +154,13 @@ public class GridCacheTwoStepQuery {
}
/**
+ * @param rdc Reduce query.
+ */
+ public void reduceQuery(GridCacheSqlQuery rdc) {
+ this.rdc = rdc;
+ }
+
+ /**
* @return Map queries.
*/
public List<GridCacheSqlQuery> mapQueries() {
@@ -123,34 +168,84 @@ public class GridCacheTwoStepQuery {
}
/**
+ * @return Caches.
+ */
+ public List<Integer> caches() {
+ return caches;
+ }
+
+ /**
+ * @param caches Caches.
+ */
+ public void caches(List<Integer> caches) {
+ this.caches = caches;
+ }
+
+ /**
+ * @return Caches.
+ */
+ public List<Integer> extraCaches() {
+ return extraCaches;
+ }
+
+ /**
+ * @param extraCaches Caches.
+ */
+ public void extraCaches(List<Integer> extraCaches) {
+ this.extraCaches = extraCaches;
+ }
+
+ /**
* @return Spaces.
*/
- public Set<String> spaces() {
+ public Collection<String> spaces() {
return spaces;
}
/**
* @param spaces Spaces.
*/
- public void spaces(Set<String> spaces) {
+ public void spaces(Collection<String> spaces) {
this.spaces = spaces;
}
/**
+ * @return Schemas.
+ */
+ public Set<String> schemas() {
+ return schemas;
+ }
+
+ /**
* @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);
+ GridCacheTwoStepQuery cp = new GridCacheTwoStepQuery(schemas, tbls);
+
+ cp.caches = caches;
+ cp.extraCaches = extraCaches;
+ cp.spaces = spaces;
+ cp.rdc = rdc.copy(args);
+ cp.skipMergeTbl = skipMergeTbl;
cp.pageSize = pageSize;
+ cp.distributedJoins = distributedJoins;
+
for (int i = 0; i < mapQrys.size(); i++)
cp.mapQrys.add(mapQrys.get(i).copy(args));
return cp;
}
+ /**
+ * @return Tables.
+ */
+ public Set<String> tables() {
+ return tbls;
+ }
+
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(GridCacheTwoStepQuery.class, this);
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
index b8ac301..c488b3f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessor.java
@@ -187,4 +187,10 @@ public interface IgniteCacheObjectProcessor extends GridProcessor {
* @return Ignite binary interface.
*/
public IgniteBinary binary();
+
+ /**
+ * @param keyType Key type name.
+ * @return Affinity filed name or {@code null}.
+ */
+ public String affinityField(String keyType);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
index 3203548..f62ce36 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cacheobject/IgniteCacheObjectProcessorImpl.java
@@ -83,6 +83,11 @@ public class IgniteCacheObjectProcessorImpl extends GridProcessorAdapter impleme
}
/** {@inheritDoc} */
+ @Override public String affinityField(String keyType) {
+ return null;
+ }
+
+ /** {@inheritDoc} */
@Override public IgniteBinary binary() {
return noOpBinary;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosurePolicy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosurePolicy.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosurePolicy.java
deleted file mode 100644
index c17cedd..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosurePolicy.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.closure;
-
-import org.jetbrains.annotations.Nullable;
-
-/**
- * This enumeration defines different types of closure
- * processing by the closure processor.
- */
-public enum GridClosurePolicy {
- /** Public execution pool. */
- PUBLIC_POOL,
-
- /** P2P execution pool. */
- P2P_POOL,
-
- /** System execution pool. */
- SYSTEM_POOL,
-
- /** IGFS pool. */
- IGFS_POOL;
-
- /** Enum values. */
- private static final GridClosurePolicy[] VALS = values();
-
- /**
- * Efficiently gets enumerated value from its ordinal.
- *
- * @param ord Ordinal value.
- * @return Enumerated value.
- */
- @Nullable public static GridClosurePolicy fromOrdinal(int ord) {
- return ord >= 0 && ord < VALS.length ? VALS[ord] : null;
- }
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java
index f9b74c4..a4559c8 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/closure/GridClosureProcessor.java
@@ -77,6 +77,9 @@ import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.compute.ComputeJobResultPolicy.FAILOVER;
import static org.apache.ignite.compute.ComputeJobResultPolicy.REDUCE;
+import static org.apache.ignite.internal.managers.communication.GridIoPolicy.IGFS_POOL;
+import static org.apache.ignite.internal.managers.communication.GridIoPolicy.PUBLIC_POOL;
+import static org.apache.ignite.internal.managers.communication.GridIoPolicy.SYSTEM_POOL;
import static org.apache.ignite.internal.processors.task.GridTaskThreadContextKey.TC_NO_FAILOVER;
import static org.apache.ignite.internal.processors.task.GridTaskThreadContextKey.TC_SUBGRID;
@@ -87,15 +90,6 @@ public class GridClosureProcessor extends GridProcessorAdapter {
/** Ignite version in which binarylizable versions of closures were introduced. */
public static final IgniteProductVersion BINARYLIZABLE_CLOSURES_SINCE = IgniteProductVersion.fromString("1.6.0");
- /** */
- private final Executor sysPool;
-
- /** */
- private final Executor pubPool;
-
- /** */
- private final Executor igfsPool;
-
/** Lock to control execution after stop. */
private final GridSpinReadWriteLock busyLock = new GridSpinReadWriteLock();
@@ -107,10 +101,6 @@ public class GridClosureProcessor extends GridProcessorAdapter {
*/
public GridClosureProcessor(GridKernalContext ctx) {
super(ctx);
-
- sysPool = ctx.getSystemExecutorService();
- pubPool = ctx.getExecutorService();
- igfsPool = ctx.getIgfsExecutorService();
}
/** {@inheritDoc} */
@@ -727,20 +717,8 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @param plc Whether to get system or public pool.
* @return Requested worker pool.
*/
- private Executor pool(GridClosurePolicy plc) {
- switch (plc) {
- case PUBLIC_POOL:
- return pubPool;
-
- case SYSTEM_POOL:
- return sysPool;
-
- case IGFS_POOL:
- return igfsPool;
-
- default:
- throw new IllegalArgumentException("Invalid closure execution policy: " + plc);
- }
+ private Executor pool(byte plc) throws IgniteCheckedException {
+ return ctx.io().pool(plc);
}
/**
@@ -749,7 +727,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @param plc Policy to choose executor pool.
* @return Pool name.
*/
- private String poolName(GridClosurePolicy plc) {
+ private String poolName(byte plc) {
switch (plc) {
case PUBLIC_POOL:
return "public";
@@ -761,7 +739,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
return "igfs";
default:
- throw new IllegalArgumentException("Invalid closure execution policy: " + plc);
+ return "unknown";
}
}
@@ -772,7 +750,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @throws IgniteCheckedException Thrown in case of any errors.
*/
private IgniteInternalFuture<?> runLocal(@Nullable final Runnable c, boolean sys) throws IgniteCheckedException {
- return runLocal(c, sys ? GridClosurePolicy.SYSTEM_POOL : GridClosurePolicy.PUBLIC_POOL);
+ return runLocal(c, sys ? SYSTEM_POOL : PUBLIC_POOL);
}
/**
@@ -781,7 +759,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @return Future.
* @throws IgniteCheckedException Thrown in case of any errors.
*/
- private IgniteInternalFuture<?> runLocal(@Nullable final Runnable c, GridClosurePolicy plc) throws IgniteCheckedException {
+ public IgniteInternalFuture<?> runLocal(@Nullable final Runnable c, byte plc) throws IgniteCheckedException {
if (c == null)
return new GridFinishedFuture();
@@ -857,7 +835,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @return Future.
*/
public IgniteInternalFuture<?> runLocalSafe(Runnable c, boolean sys) {
- return runLocalSafe(c, sys ? GridClosurePolicy.SYSTEM_POOL : GridClosurePolicy.PUBLIC_POOL);
+ return runLocalSafe(c, sys ? SYSTEM_POOL : PUBLIC_POOL);
}
/**
@@ -868,7 +846,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @param plc Policy to choose executor pool.
* @return Future.
*/
- public IgniteInternalFuture<?> runLocalSafe(Runnable c, GridClosurePolicy plc) {
+ public IgniteInternalFuture<?> runLocalSafe(Runnable c, byte plc) {
try {
return runLocal(c, plc);
}
@@ -912,7 +890,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @throws IgniteCheckedException Thrown in case of any errors.
*/
private <R> IgniteInternalFuture<R> callLocal(@Nullable final Callable<R> c, boolean sys) throws IgniteCheckedException {
- return callLocal(c, sys ? GridClosurePolicy.SYSTEM_POOL : GridClosurePolicy.PUBLIC_POOL);
+ return callLocal(c, sys ? SYSTEM_POOL : PUBLIC_POOL);
}
/**
@@ -922,7 +900,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @return Future.
* @throws IgniteCheckedException Thrown in case of any errors.
*/
- private <R> IgniteInternalFuture<R> callLocal(@Nullable final Callable<R> c, GridClosurePolicy plc) throws IgniteCheckedException {
+ private <R> IgniteInternalFuture<R> callLocal(@Nullable final Callable<R> c, byte plc) throws IgniteCheckedException {
if (c == null)
return new GridFinishedFuture<>();
@@ -996,7 +974,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @return Future.
*/
public <R> IgniteInternalFuture<R> callLocalSafe(Callable<R> c, boolean sys) {
- return callLocalSafe(c, sys ? GridClosurePolicy.SYSTEM_POOL : GridClosurePolicy.PUBLIC_POOL);
+ return callLocalSafe(c, sys ? SYSTEM_POOL : PUBLIC_POOL);
}
/**
@@ -1007,7 +985,7 @@ public class GridClosureProcessor extends GridProcessorAdapter {
* @param plc Policy to choose executor pool.
* @return Future.
*/
- public <R> IgniteInternalFuture<R> callLocalSafe(Callable<R> c, GridClosurePolicy plc) {
+ public <R> IgniteInternalFuture<R> callLocalSafe(Callable<R> c, byte plc) {
try {
return callLocal(c, plc);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
index 7697a12..643cb8c 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
@@ -29,7 +29,6 @@ import org.apache.ignite.internal.GridKernalContext;
import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion;
import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
-import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
import org.apache.ignite.internal.util.GridSpinBusyLock;
import org.apache.ignite.internal.util.lang.GridCloseableIterator;
import org.apache.ignite.lang.IgniteBiTuple;
@@ -58,17 +57,6 @@ public interface GridQueryIndexing {
public void stop() throws IgniteCheckedException;
/**
- * Runs two step query.
- *
- * @param cctx Cache context.
- * @param qry Query.
- * @param keepCacheObjects If {@code true}, cache objects representation will be preserved.
- * @return Cursor.
- */
- public Iterable<List<?>> queryTwoStep(GridCacheContext<?,?> cctx, GridCacheTwoStepQuery qry,
- boolean keepCacheObjects);
-
- /**
* Parses SQL query into two step query and executes it.
*
* @param cctx Cache context.
@@ -92,12 +80,13 @@ public interface GridQueryIndexing {
* @param spaceName Space name.
* @param qry Query.
* @param params Query parameters.
- * @param filters Space name and key filters.
+ * @param filter Space name and key filter.
+ * @param enforceJoinOrder Enforce join order of tables in the query.
* @return Query result.
* @throws IgniteCheckedException If failed.
*/
- public GridQueryFieldsResult queryFields(@Nullable String spaceName, String qry,
- Collection<Object> params, IndexingQueryFilter filters) throws IgniteCheckedException;
+ public GridQueryFieldsResult queryLocalSqlFields(@Nullable String spaceName, String qry,
+ Collection<Object> params, IndexingQueryFilter filter, boolean enforceJoinOrder) throws IgniteCheckedException;
/**
* Executes regular query.
@@ -106,12 +95,12 @@ public interface GridQueryIndexing {
* @param qry Query.
* @param params Query parameters.
* @param type Query return type.
- * @param filters Space name and key filters.
+ * @param filter Space name and key filter.
* @return Queried rows.
* @throws IgniteCheckedException If failed.
*/
- public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> query(@Nullable String spaceName, String qry,
- Collection<Object> params, GridQueryTypeDescriptor type, IndexingQueryFilter filters) throws IgniteCheckedException;
+ public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryLocalSql(@Nullable String spaceName, String qry,
+ Collection<Object> params, GridQueryTypeDescriptor type, IndexingQueryFilter filter) throws IgniteCheckedException;
/**
* Executes text query.
@@ -119,35 +108,24 @@ public interface GridQueryIndexing {
* @param spaceName Space name.
* @param qry Text query.
* @param type Query return type.
- * @param filters Space name and key filter.
+ * @param filter Space name and key filter.
* @return Queried rows.
* @throws IgniteCheckedException If failed.
*/
- public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryText(@Nullable String spaceName, String qry,
- GridQueryTypeDescriptor type, IndexingQueryFilter filters) throws IgniteCheckedException;
-
- /**
- * Gets size of index for given type or -1 if it is a unknown type.
- *
- * @param spaceName Space name.
- * @param desc Type descriptor.
- * @param filters Filters.
- * @return Objects number.
- * @throws IgniteCheckedException If failed.
- */
- public long size(@Nullable String spaceName, GridQueryTypeDescriptor desc, IndexingQueryFilter filters)
- throws IgniteCheckedException;
+ public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> queryLocalText(@Nullable String spaceName, String qry,
+ GridQueryTypeDescriptor type, IndexingQueryFilter filter) throws IgniteCheckedException;
/**
* Registers cache.
*
+ * @param cctx Cache context.
* @param ccfg Cache configuration.
* @throws IgniteCheckedException If failed.
*/
- public void registerCache(CacheConfiguration<?,?> ccfg) throws IgniteCheckedException;
+ public void registerCache(GridCacheContext<?,?> cctx, CacheConfiguration<?,?> ccfg) throws IgniteCheckedException;
/**
- * Deregisters cache.
+ * Unregisters cache.
*
* @param ccfg Cache configuration.
* @throws IgniteCheckedException If failed to drop cache schema.
@@ -228,12 +206,11 @@ public interface GridQueryIndexing {
/**
* Returns backup filter.
*
- * @param caches List of caches.
* @param topVer Topology version.
* @param parts Partitions.
* @return Backup filter.
*/
- public IndexingQueryFilter backupFilter(List<String> caches, AffinityTopologyVersion topVer, int[] parts);
+ public IndexingQueryFilter backupFilter(AffinityTopologyVersion topVer, int[] parts);
/**
* Client disconnected callback.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 a42eb98..04c6cb0 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
@@ -28,6 +28,7 @@ import org.apache.ignite.cache.CacheTypeMetadata;
import org.apache.ignite.cache.QueryEntity;
import org.apache.ignite.cache.QueryIndex;
import org.apache.ignite.cache.QueryIndexType;
+import org.apache.ignite.cache.affinity.AffinityKeyMapper;
import org.apache.ignite.cache.query.QueryCursor;
import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.SqlQuery;
@@ -42,11 +43,11 @@ import org.apache.ignite.internal.processors.cache.CacheEntryImpl;
import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.CacheObjectContext;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.GridCacheDefaultAffinityKeyMapper;
import org.apache.ignite.internal.processors.cache.QueryCursorImpl;
import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl;
import org.apache.ignite.internal.processors.cache.query.CacheQueryFuture;
import org.apache.ignite.internal.processors.cache.query.CacheQueryType;
-import org.apache.ignite.internal.processors.cache.query.GridCacheTwoStepQuery;
import org.apache.ignite.internal.util.GridSpinBusyLock;
import org.apache.ignite.internal.util.future.GridCompoundFuture;
import org.apache.ignite.internal.util.future.GridFinishedFuture;
@@ -191,11 +192,13 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/**
- * @param ccfg Cache configuration.
+ * @param cctx Cache context.
* @throws IgniteCheckedException If failed.
*/
- public void initializeCache(CacheConfiguration<?, ?> ccfg) throws IgniteCheckedException {
- idx.registerCache(ccfg);
+ private void initializeCache(GridCacheContext<?, ?> cctx) throws IgniteCheckedException {
+ CacheConfiguration<?,?> ccfg = cctx.config();
+
+ idx.registerCache(cctx, cctx.config());
try {
List<Class<?>> mustDeserializeClss = null;
@@ -275,10 +278,28 @@ public class GridQueryProcessor extends GridProcessorAdapter {
if (valCls != null)
altTypeId = new TypeId(ccfg.getName(), valCls);
+
+ if (!cctx.customAffinityMapper() && qryEntity.getKeyType() != null) {
+ // Need to setup affinity key for distributed joins.
+ String affField = ctx.cacheObjects().affinityField(qryEntity.getKeyType());
+
+ if (affField != null)
+ desc.affinityKey(affField);
+ }
}
else {
processClassMeta(qryEntity, desc, coCtx);
+ AffinityKeyMapper keyMapper = cctx.config().getAffinityMapper();
+
+ if (keyMapper instanceof GridCacheDefaultAffinityKeyMapper) {
+ String affField =
+ ((GridCacheDefaultAffinityKeyMapper)keyMapper).affinityKeyPropertyName(desc.keyCls);
+
+ if (affField != null)
+ desc.affinityKey(affField);
+ }
+
typeId = new TypeId(ccfg.getName(), valCls);
altTypeId = new TypeId(ccfg.getName(), ctx.cacheObjects().typeId(qryEntity.getValueType()));
}
@@ -290,7 +311,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
types.put(altTypeId, desc);
desc.registered(idx.registerType(ccfg.getName(), desc));
-
}
}
@@ -460,7 +480,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
return;
try {
- initializeCache(cctx.config());
+ initializeCache(cctx);
}
finally {
busyLock.leaveBusy();
@@ -501,33 +521,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/**
- * Returns number of objects of given type for given space of spi.
- *
- * @param space Space.
- * @param valType Value type.
- * @return Objects number or -1 if this type is unknown for given SPI and space.
- * @throws IgniteCheckedException If failed.
- */
- public long size(@Nullable String space, Class<?> valType) throws IgniteCheckedException {
- checkEnabled();
-
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to get space size (grid is stopping).");
-
- try {
- TypeDescriptor desc = types.get(new TypeId(space, valType));
-
- if (desc == null || !desc.registered())
- return -1;
-
- return idx.size(space, desc, null);
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
* Rebuilds all search indexes of given value type for given space of spi.
*
* @param space Space.
@@ -657,7 +650,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
return;
if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to write to index (grid is stopping).");
+ return;
try {
if (coctx == null)
@@ -723,74 +716,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/**
- * @param space Space.
- * @param clause Clause.
- * @param params Parameters collection.
- * @param resType Result type.
- * @param filters Filters.
- * @return Key/value rows.
- * @throws IgniteCheckedException If failed.
- */
- @SuppressWarnings("unchecked")
- public <K, V> GridCloseableIterator<IgniteBiTuple<K, V>> query(final String space, final String clause,
- final Collection<Object> params, final String resType, final IndexingQueryFilter filters)
- throws IgniteCheckedException {
- checkEnabled();
-
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to execute query (grid is stopping).");
-
- try {
- final GridCacheContext<?, ?> cctx = ctx.cache().internalCache(space).context();
-
- return executeQuery(cctx, new IgniteOutClosureX<GridCloseableIterator<IgniteBiTuple<K, V>>>() {
- @Override public GridCloseableIterator<IgniteBiTuple<K, V>> applyx() throws IgniteCheckedException {
- TypeDescriptor type = typesByName.get(new TypeName(space, resType));
-
- if (type == null || !type.registered())
- throw new CacheException("Failed to find SQL table for type: " + resType);
-
- return idx.query(space, clause, params, type, filters);
- }
- }, false);
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
- * @param space Space name.
- * @param qry Query.
- * @return Cursor.
- */
- public Iterable<List<?>> queryTwoStep(String space, final GridCacheTwoStepQuery qry) {
- checkxEnabled();
-
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to execute query (grid is stopping).");
-
- try {
- final GridCacheContext<Object, Object> cctx = ctx.cache().internalCache(space).context();
-
- return executeQuery(cctx, new IgniteOutClosureX<Iterable<List<?>>>() {
- @Override public Iterable<List<?>> applyx() throws IgniteCheckedException {
- return idx.queryTwoStep(
- cctx,
- qry,
- cctx.keepBinary());
- }
- }, false);
- }
- catch (IgniteCheckedException e) {
- throw new IgniteException(e);
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
* @param cctx Cache context.
* @param qry Query.
* @return Cursor.
@@ -845,6 +770,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
/**
* @param cctx Cache context.
* @param qry Query.
+ * @param keepBinary Keep binary flag.
* @return Cursor.
*/
public <K, V> Iterator<Cache.Entry<K, V>> queryLocal(
@@ -873,12 +799,12 @@ public class GridQueryProcessor extends GridProcessorAdapter {
if (typeDesc == null || !typeDesc.registered())
throw new CacheException("Failed to find SQL table for type: " + type);
- final GridCloseableIterator<IgniteBiTuple<K, V>> i = idx.query(
+ final GridCloseableIterator<IgniteBiTuple<K, V>> i = idx.queryLocalSql(
space,
sqlQry,
F.asList(params),
typeDesc,
- idx.backupFilter(null, null, null));
+ idx.backupFilter(null, null));
sendQueryExecutedEvent(
sqlQry,
@@ -963,8 +889,8 @@ public class GridQueryProcessor extends GridProcessorAdapter {
String sql = qry.getSql();
Object[] args = qry.getArgs();
- final GridQueryFieldsResult res = idx.queryFields(space, sql, F.asList(args),
- idx.backupFilter(null, null, null));
+ final GridQueryFieldsResult res = idx.queryLocalSqlFields(space, sql, F.asList(args),
+ idx.backupFilter(null, null), qry.isEnforceJoinOrder());
sendQueryExecutedEvent(sql, args);
@@ -1118,7 +1044,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
if (type == null || !type.registered())
throw new CacheException("Failed to find SQL table for type: " + resType);
- return idx.queryText(
+ return idx.queryLocalText(
space,
clause,
type,
@@ -1132,35 +1058,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/**
- * @param space Space name.
- * @param clause Clause.
- * @param params Parameters collection.
- * @param filters Key and value filters.
- * @return Field rows.
- * @throws IgniteCheckedException If failed.
- */
- public GridQueryFieldsResult queryFields(@Nullable final String space, final String clause,
- final Collection<Object> params, final IndexingQueryFilter filters) throws IgniteCheckedException {
- checkEnabled();
-
- if (!busyLock.enterBusy())
- throw new IllegalStateException("Failed to execute query (grid is stopping).");
-
- try {
- final GridCacheContext<?, ?> cctx = ctx.cache().internalCache(space).context();
-
- return executeQuery(cctx, new IgniteOutClosureX<GridQueryFieldsResult>() {
- @Override public GridQueryFieldsResult applyx() throws IgniteCheckedException {
- return idx.queryFields(space, clause, params, filters);
- }
- }, false);
- }
- finally {
- busyLock.leaveBusy();
- }
- }
-
- /**
* Will be called when entry for key will be swapped.
*
* @param spaceName Space name.
@@ -1523,7 +1420,6 @@ public class GridQueryProcessor extends GridProcessorAdapter {
aliases,
coCtx);
-
d.addProperty(prop, false);
}
@@ -1770,7 +1666,7 @@ public class GridQueryProcessor extends GridProcessorAdapter {
res = clo.apply();
if (res instanceof CacheQueryFuture) {
- CacheQueryFuture fut = (CacheQueryFuture) res;
+ CacheQueryFuture fut = (CacheQueryFuture)res;
err = fut.error();
}
@@ -1782,6 +1678,11 @@ public class GridQueryProcessor extends GridProcessorAdapter {
throw (IgniteCheckedException)err;
}
+ catch (CacheException e) {
+ err = e;
+
+ throw e;
+ }
catch (Exception e) {
err = e;
@@ -2096,6 +1997,9 @@ public class GridQueryProcessor extends GridProcessorAdapter {
/** */
private boolean valTextIdx;
+ /** */
+ private String affKey;
+
/** SPI can decide not to register this type. */
private boolean registered;
@@ -2265,6 +2169,18 @@ public class GridQueryProcessor extends GridProcessorAdapter {
}
/** {@inheritDoc} */
+ @Override public String affinityKey() {
+ return affKey;
+ }
+
+ /**
+ * @param affKey Affinity key field.
+ */
+ void affinityKey(String affKey) {
+ this.affKey = affKey;
+ }
+
+ /** {@inheritDoc} */
@Override public String toString() {
return S.toString(TypeDescriptor.class, this);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 45919ef..b636841 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
@@ -82,4 +82,11 @@ public interface GridQueryTypeDescriptor {
* @return If string representation of value should be full-text indexed.
*/
public boolean valueTextIndex();
+
+ /**
+ * Returns affinity key field name or {@code null} for default.
+ *
+ * @return Affinity key.
+ */
+ public String affinityKey();
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryCancelRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryCancelRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryCancelRequest.java
index ecc0abd..6706ab9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryCancelRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryCancelRequest.java
@@ -117,4 +117,4 @@ public class GridQueryCancelRequest implements Message {
@Override public byte fieldsCount() {
return 1;
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryFailResponse.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryFailResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryFailResponse.java
index 499438d..bd9f7d1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryFailResponse.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryFailResponse.java
@@ -143,4 +143,4 @@ public class GridQueryFailResponse implements Message {
@Override public byte fieldsCount() {
return 2;
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageRequest.java
index 84cb57e..1feff5a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/messages/GridQueryNextPageRequest.java
@@ -170,4 +170,4 @@ public class GridQueryNextPageRequest implements Message {
@Override public byte fieldsCount() {
return 3;
}
-}
\ No newline at end of file
+}
[20/50] [abbrv] ignite git commit: ignite-3399 - minor improvements
Posted by vo...@apache.org.
ignite-3399 - minor improvements
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/df1490e1
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/df1490e1
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/df1490e1
Branch: refs/heads/ignite-3553
Commit: df1490e18e2271969ef6857d40e77427958e28ac
Parents: df5a842
Author: Sergi Vladykin <se...@gmail.com>
Authored: Mon Jul 25 09:08:00 2016 +0300
Committer: Sergi Vladykin <se...@gmail.com>
Committed: Mon Jul 25 09:08:00 2016 +0300
----------------------------------------------------------------------
.../org/apache/ignite/internal/util/IgniteUtils.java | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/df1490e1/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
index 31128ca..b58e3b3 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/util/IgniteUtils.java
@@ -1373,17 +1373,19 @@ public abstract class IgniteUtils {
* @param includePrimitiveTypes Whether class resolution should include primitive types (i.e. "int" will resolve to int.class if flag is set)
* @return Class or default given class if it can't be found.
*/
- @Nullable
- public static Class<?> classForName(@Nullable String cls, @Nullable Class<?> dflt, boolean includePrimitiveTypes) {
+ @Nullable public static Class<?> classForName(
+ @Nullable String cls,
+ @Nullable Class<?> dflt,
+ boolean includePrimitiveTypes
+ ) {
Class<?> clazz;
if (cls == null)
clazz = dflt;
- else if (includePrimitiveTypes && primitiveMap.containsKey(cls))
- clazz = primitiveMap.get(cls);
- else {
+ else if (!includePrimitiveTypes || cls.length() > 7 || (clazz = primitiveMap.get(cls)) == null) {
try {
clazz = Class.forName(cls);
- } catch (ClassNotFoundException ignore) {
+ }
+ catch (ClassNotFoundException ignore) {
clazz = dflt;
}
}
[29/50] [abbrv] ignite git commit: ignite-3560 Offheap resources
cleanup on H2 table destroy.
Posted by vo...@apache.org.
ignite-3560 Offheap resources cleanup on H2 table destroy.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/44cabd84
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/44cabd84
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/44cabd84
Branch: refs/heads/ignite-3553
Commit: 44cabd84152b5d956666b6c906eb43763ab7d72f
Parents: 856b536
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jul 26 10:41:50 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jul 26 10:41:50 2016 +0300
----------------------------------------------------------------------
.../processors/query/h2/IgniteH2Indexing.java | 31 ++--
.../cache/CacheIndexingOffheapCleanupTest.java | 178 +++++++++++++++++++
.../IgniteCacheWithIndexingTestSuite.java | 2 +
3 files changed, 196 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/44cabd84/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 535881e..e1b21e2 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
@@ -735,8 +735,7 @@ public class IgniteH2Indexing implements GridQueryIndexing {
U.close(stmt, log);
}
- if (tbl.luceneIdx != null)
- U.closeQuiet(tbl.luceneIdx);
+ tbl.onDrop();
tbl.schema.tbls.remove(tbl.name());
}
@@ -1816,12 +1815,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
// unregisterMBean(); TODO https://issues.apache.org/jira/browse/IGNITE-2139
- for (Schema schema : schemas.values()) {
- for (TableDescriptor desc : schema.tbls.values()) {
- if (desc.luceneIdx != null)
- U.closeQuiet(desc.luceneIdx);
- }
- }
+ for (Schema schema : schemas.values())
+ schema.onDrop();
for (Connection c : conns)
U.close(c, log);
@@ -2436,6 +2431,17 @@ public class IgniteH2Indexing implements GridQueryIndexing {
}
/**
+ *
+ */
+ void onDrop() {
+ dataTables.remove(tbl.identifier(), tbl);
+
+ tbl.destroy();
+
+ U.closeQuiet(luceneIdx);
+ }
+
+ /**
* @param tbl Table.
* @param idxName Index name.
* @param cols Columns.
@@ -2668,13 +2674,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
* Called after the schema was dropped.
*/
public void onDrop() {
- for (TableDescriptor tblDesc : tbls.values()) {
- GridH2Table tbl = tblDesc.tbl;
-
- dataTables.remove(tbl.identifier(), tbl);
-
- tbl.destroy();
- }
+ for (TableDescriptor tblDesc : tbls.values())
+ tblDesc.onDrop();
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/44cabd84/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheIndexingOffheapCleanupTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheIndexingOffheapCleanupTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheIndexingOffheapCleanupTest.java
new file mode 100644
index 0000000..3d7e30a
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/CacheIndexingOffheapCleanupTest.java
@@ -0,0 +1,178 @@
+/*
+ * 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;
+
+import java.util.Map;
+import java.util.concurrent.ThreadLocalRandom;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.cache.query.annotations.QueryTextField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.util.offheap.unsafe.GridUnsafeMemory;
+import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+
+/**
+ *
+ */
+public class CacheIndexingOffheapCleanupTest extends GridCommonAbstractTest {
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ startGrid(0);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+
+ super.afterTest();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCacheDestroy() throws Exception {
+ Ignite ignite = ignite(0);
+
+ for (int i = 0; i < 5; i++) {
+ log.info("Iteration: " + i);
+
+ IgniteCache cache = ignite.createCache(cacheConfiguration());
+
+ for (int k = 0; k < 100; k++)
+ cache.put(k, new TestType());
+
+ GridUnsafeMemory mem = schemaMemory(ignite, cache.getName());
+
+ assertTrue(mem.allocatedSize() > 0);
+
+ ignite.destroyCache(cache.getName());
+
+ assertEquals(0, mem.allocatedSize());
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testStopNode() throws Exception {
+ Ignite ignite = ignite(0);
+
+ IgniteCache cache = ignite.createCache(cacheConfiguration());
+
+ for (int k = 0; k < 100; k++)
+ cache.put(k, new TestType());
+
+ GridUnsafeMemory mem = schemaMemory(ignite, cache.getName());
+
+ assertTrue(mem.allocatedSize() > 0);
+
+ stopGrid(0);
+
+ assertEquals(0, mem.allocatedSize());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testUndeploy() throws Exception {
+ Ignite ignite = ignite(0);
+
+ IgniteCache cache = ignite.createCache(cacheConfiguration());
+
+ for (int k = 0; k < 100; k++)
+ cache.put(k, new TestType());
+
+ GridUnsafeMemory mem = schemaMemory(ignite, cache.getName());
+
+ assertTrue(mem.allocatedSize() > 0);
+
+ ((IgniteKernal)ignite).context().query().onUndeploy("cache", U.detectClassLoader(TestType.class));
+
+ assertEquals(0, mem.allocatedSize());
+ }
+
+ /**
+ * @param ignite Node.
+ * @param cacheName Cache name.
+ * @return Memory.
+ */
+ private GridUnsafeMemory schemaMemory(Ignite ignite, String cacheName) {
+ Map<String, Object> schemas = GridTestUtils.getFieldValue(((IgniteKernal)ignite).context().query(),
+ "idx",
+ "schemas");
+
+ assertNotNull(schemas);
+
+ Object schema = schemas.get("\"" + cacheName + "\"");
+
+ assertNotNull(schema);
+
+ GridUnsafeMemory mem = GridTestUtils.getFieldValue(schema, "offheap");
+
+ assertNotNull(mem);
+
+ return mem;
+ }
+
+ /**
+ * @return Cache configuration.
+ */
+ private CacheConfiguration cacheConfiguration() {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName("cache");
+ ccfg.setMemoryMode(OFFHEAP_TIERED);
+ ccfg.setIndexedTypes(Integer.class, TestType.class);
+
+ return ccfg;
+ }
+
+ /**
+ *
+ */
+ static class TestType {
+ /** */
+ @QuerySqlField(index = true)
+ private int v1;
+
+ /** */
+ @QuerySqlField(index = true)
+ private String v2;
+
+ /** */
+ @QueryTextField
+ private String v3;
+
+ /**
+ *
+ */
+ public TestType() {
+ int v = ThreadLocalRandom.current().nextInt();
+
+ v1 = v;
+ v2 = String.valueOf(v);
+ v3 = v2;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/44cabd84/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
index a85b7a6..5cdd744 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheWithIndexingTestSuite.java
@@ -20,6 +20,7 @@ package org.apache.ignite.testsuites;
import junit.framework.TestSuite;
import org.apache.ignite.internal.processors.cache.CacheConfigurationP2PTest;
import org.apache.ignite.internal.processors.cache.CacheIndexStreamerTest;
+import org.apache.ignite.internal.processors.cache.CacheIndexingOffheapCleanupTest;
import org.apache.ignite.internal.processors.cache.CacheOperationsWithExpirationTest;
import org.apache.ignite.internal.processors.cache.CacheRandomOperationsMultithreadedTest;
import org.apache.ignite.internal.processors.cache.GridCacheOffHeapAndSwapSelfTest;
@@ -76,6 +77,7 @@ public class IgniteCacheWithIndexingTestSuite extends TestSuite {
suite.addTestSuite(CacheRandomOperationsMultithreadedTest.class);
suite.addTestSuite(IgniteCacheStarvationOnRebalanceTest.class);
suite.addTestSuite(CacheOperationsWithExpirationTest.class);
+ suite.addTestSuite(CacheIndexingOffheapCleanupTest.class);
return suite;
}
[07/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 0da71c8..fae3188 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
@@ -44,7 +44,7 @@ import org.apache.ignite.spi.IgniteSpiException;
import org.apache.ignite.testframework.GridStringLogger;
import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.h2.util.Utils;
+import org.h2.util.JdbcUtils;
import org.jetbrains.annotations.Nullable;
/**
@@ -101,8 +101,8 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
protected void startIndexing(IgniteH2Indexing spi) throws Exception {
spi.start(null, null);
- spi.registerCache(cacheCfg("A"));
- spi.registerCache(cacheCfg("B"));
+ spi.registerCache(null, cacheCfg("A"));
+ spi.registerCache(null, cacheCfg("B"));
}
private CacheConfiguration cacheCfg(String name) {
@@ -199,38 +199,38 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
public void testSpi() throws Exception {
IgniteH2Indexing spi = getIndexing();
- assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(-1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(-1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(-1, spi.size(typeAA.space(), typeAA));
+ assertEquals(-1, spi.size(typeAB.space(), typeAB));
+ assertEquals(-1, spi.size(typeBA.space(), typeBA));
spi.registerType(typeAA.space(), typeAA);
- assertEquals(0, spi.size(typeAA.space(), typeAA, null));
- assertEquals(-1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(-1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(0, spi.size(typeAA.space(), typeAA));
+ assertEquals(-1, spi.size(typeAB.space(), typeAB));
+ assertEquals(-1, spi.size(typeBA.space(), typeBA));
spi.registerType(typeAB.space(), typeAB);
- assertEquals(0, spi.size(typeAA.space(), typeAA, null));
- assertEquals(0, spi.size(typeAB.space(), typeAB, null));
- assertEquals(-1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(0, spi.size(typeAA.space(), typeAA));
+ assertEquals(0, spi.size(typeAB.space(), typeAB));
+ assertEquals(-1, spi.size(typeBA.space(), typeBA));
spi.registerType(typeBA.space(), typeBA);
// Initially all is empty.
- assertEquals(0, spi.size(typeAA.space(), typeAA, null));
- assertEquals(0, spi.size(typeAB.space(), typeAB, null));
- assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(0, spi.size(typeAA.space(), typeAA));
+ assertEquals(0, spi.size(typeAB.space(), typeAB));
+ assertEquals(0, spi.size(typeBA.space(), typeBA));
- assertFalse(spi.query(typeAA.space(), "select * from A.A", Collections.emptySet(), typeAA, null).hasNext());
- assertFalse(spi.query(typeAB.space(), "select * from A.B", Collections.emptySet(), typeAB, null).hasNext());
- assertFalse(spi.query(typeBA.space(), "select * from B.A", Collections.emptySet(), typeBA, null).hasNext());
+ assertFalse(spi.queryLocalSql(typeAA.space(), "select * from A.A", Collections.emptySet(), typeAA, null).hasNext());
+ assertFalse(spi.queryLocalSql(typeAB.space(), "select * from A.B", Collections.emptySet(), typeAB, null).hasNext());
+ assertFalse(spi.queryLocalSql(typeBA.space(), "select * from B.A", Collections.emptySet(), typeBA, null).hasNext());
- assertFalse(spi.query(typeBA.space(), "select * from B.A, A.B, A.A",
+ assertFalse(spi.queryLocalSql(typeBA.space(), "select * from B.A, A.B, A.A",
Collections.emptySet(), typeBA, null).hasNext());
try {
- spi.query(typeBA.space(), "select aa.*, ab.*, ba.* from A.A aa, A.B ab, B.A ba",
+ spi.queryLocalSql(typeBA.space(), "select aa.*, ab.*, ba.* from A.A aa, A.B ab, B.A ba",
Collections.emptySet(), typeBA, null).hasNext();
fail("Enumerations of aliases in select block must be prohibited");
@@ -239,10 +239,10 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
// all fine
}
- assertFalse(spi.query(typeAB.space(), "select ab.* from A.B ab",
+ assertFalse(spi.queryLocalSql(typeAB.space(), "select ab.* from A.B ab",
Collections.emptySet(), typeAB, null).hasNext());
- assertFalse(spi.query(typeBA.space(), "select ba.* from B.A as ba",
+ assertFalse(spi.queryLocalSql(typeBA.space(), "select ba.* from B.A as ba",
Collections.emptySet(), typeBA, null).hasNext());
// Nothing to remove.
@@ -251,53 +251,53 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
spi.store(typeAA.space(), typeAA, key(1), aa(1, "Vasya", 10), "v1".getBytes(), 0);
- assertEquals(1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(0, spi.size(typeAB.space(), typeAB, null));
- assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(1, spi.size(typeAA.space(), typeAA));
+ assertEquals(0, spi.size(typeAB.space(), typeAB));
+ assertEquals(0, spi.size(typeBA.space(), typeBA));
spi.store(typeAB.space(), typeAB, key(1), ab(1, "Vasya", 20, "Some text about Vasya goes here."),
"v2".getBytes(), 0);
// In one space all keys must be unique.
- assertEquals(0, spi.size(typeAA.space(), typeAA, null));
- assertEquals(1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(0, spi.size(typeAA.space(), typeAA));
+ assertEquals(1, spi.size(typeAB.space(), typeAB));
+ assertEquals(0, spi.size(typeBA.space(), typeBA));
spi.store(typeBA.space(), typeBA, key(1), ba(2, "Petya", 25, true), "v3".getBytes(), 0);
// No replacement because of different space.
- assertEquals(0, spi.size(typeAA.space(), typeAA, null));
- assertEquals(1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(0, spi.size(typeAA.space(), typeAA));
+ assertEquals(1, spi.size(typeAB.space(), typeAB));
+ assertEquals(1, spi.size(typeBA.space(), typeBA));
spi.store(typeBA.space(), typeBA, key(1), ba(2, "Kolya", 25, true), "v4".getBytes(), 0);
// Replacement in the same table.
- assertEquals(0, spi.size(typeAA.space(), typeAA, null));
- assertEquals(1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(0, spi.size(typeAA.space(), typeAA));
+ assertEquals(1, spi.size(typeAB.space(), typeAB));
+ assertEquals(1, spi.size(typeBA.space(), typeBA));
spi.store(typeAA.space(), typeAA, key(2), aa(2, "Valera", 19), "v5".getBytes(), 0);
- assertEquals(1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(1, spi.size(typeAA.space(), typeAA));
+ assertEquals(1, spi.size(typeAB.space(), typeAB));
+ assertEquals(1, spi.size(typeBA.space(), typeBA));
spi.store(typeAA.space(), typeAA, key(3), aa(3, "Borya", 18), "v6".getBytes(), 0);
- assertEquals(2, spi.size(typeAA.space(), typeAA, null));
- assertEquals(1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(2, spi.size(typeAA.space(), typeAA));
+ assertEquals(1, spi.size(typeAB.space(), typeAB));
+ assertEquals(1, spi.size(typeBA.space(), typeBA));
spi.store(typeAB.space(), typeAB, key(4), ab(4, "Vitalya", 20, "Very Good guy"), "v7".getBytes(), 0);
- assertEquals(2, spi.size(typeAA.space(), typeAA, null));
- assertEquals(2, spi.size(typeAB.space(), typeAB, null));
- assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(2, spi.size(typeAA.space(), typeAA));
+ assertEquals(2, spi.size(typeAB.space(), typeAB));
+ assertEquals(1, spi.size(typeBA.space(), typeBA));
// Query data.
Iterator<IgniteBiTuple<Integer, Map<String, Object>>> res =
- spi.query(typeAA.space(), "from a order by age", Collections.emptySet(), typeAA, null);
+ spi.queryLocalSql(typeAA.space(), "from a order by age", Collections.emptySet(), typeAA, null);
assertTrue(res.hasNext());
assertEquals(aa(3, "Borya", 18).value(null, false), value(res.next()));
@@ -305,7 +305,7 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
assertEquals(aa(2, "Valera", 19).value(null, false), value(res.next()));
assertFalse(res.hasNext());
- res = spi.query(typeAA.space(), "select aa.* from a aa order by aa.age",
+ res = spi.queryLocalSql(typeAA.space(), "select aa.* from a aa order by aa.age",
Collections.emptySet(), typeAA, null);
assertTrue(res.hasNext());
@@ -314,7 +314,7 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
assertEquals(aa(2, "Valera", 19).value(null, false), value(res.next()));
assertFalse(res.hasNext());
- res = spi.query(typeAB.space(), "from b order by name", Collections.emptySet(), typeAB, null);
+ res = spi.queryLocalSql(typeAB.space(), "from b order by name", Collections.emptySet(), typeAB, null);
assertTrue(res.hasNext());
assertEquals(ab(1, "Vasya", 20, "Some text about Vasya goes here.").value(null, false), value(res.next()));
@@ -322,7 +322,7 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
assertEquals(ab(4, "Vitalya", 20, "Very Good guy").value(null, false), value(res.next()));
assertFalse(res.hasNext());
- res = spi.query(typeAB.space(), "select bb.* from b as bb order by bb.name",
+ res = spi.queryLocalSql(typeAB.space(), "select bb.* from b as bb order by bb.name",
Collections.emptySet(), typeAB, null);
assertTrue(res.hasNext());
@@ -331,14 +331,15 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
assertEquals(ab(4, "Vitalya", 20, "Very Good guy").value(null, false), value(res.next()));
assertFalse(res.hasNext());
- res = spi.query(typeBA.space(), "from a", Collections.emptySet(), typeBA, null);
+
+ res = spi.queryLocalSql(typeBA.space(), "from a", Collections.emptySet(), typeBA, null);
assertTrue(res.hasNext());
assertEquals(ba(2, "Kolya", 25, true).value(null, false), value(res.next()));
assertFalse(res.hasNext());
// Text queries
- Iterator<IgniteBiTuple<Integer, Map<String, Object>>> txtRes = spi.queryText(typeAB.space(), "good",
+ Iterator<IgniteBiTuple<Integer, Map<String, Object>>> txtRes = spi.queryLocalText(typeAB.space(), "good",
typeAB, null);
assertTrue(txtRes.hasNext());
@@ -347,8 +348,8 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
// Fields query
GridQueryFieldsResult fieldsRes =
- spi.queryFields("A", "select a.a.name n1, a.a.age a1, b.a.name n2, " +
- "b.a.age a2 from a.a, b.a where a.a.id = b.a.id ", Collections.emptySet(), null);
+ spi.queryLocalSqlFields("A", "select a.a.name n1, a.a.age a1, b.a.name n2, " +
+ "b.a.age a2 from a.a, b.a where a.a.id = b.a.id ", Collections.emptySet(), null, false);
String[] aliases = {"N1", "A1", "N2", "A2"};
Object[] vals = { "Valera", 19, "Kolya", 25};
@@ -371,15 +372,15 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
// Remove
spi.remove(typeAA.space(), key(2), aa(2, "Valera", 19));
- assertEquals(1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(2, spi.size(typeAB.space(), typeAB, null));
- assertEquals(1, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(1, spi.size(typeAA.space(), typeAA));
+ assertEquals(2, spi.size(typeAB.space(), typeAB));
+ assertEquals(1, spi.size(typeBA.space(), typeBA));
spi.remove(typeBA.space(), key(1), ba(2, "Kolya", 25, true));
- assertEquals(1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(2, spi.size(typeAB.space(), typeAB, null));
- assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(1, spi.size(typeAA.space(), typeAA));
+ assertEquals(2, spi.size(typeAB.space(), typeAB));
+ assertEquals(0, spi.size(typeBA.space(), typeBA));
boolean h2IdxOffheap = offheap();
@@ -389,9 +390,9 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
spi.rebuildIndexes(typeAB.space(), typeAB);
- assertEquals(1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(2, spi.size(typeAB.space(), typeAB, null));
- assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(1, spi.size(typeAA.space(), typeAA));
+ assertEquals(2, spi.size(typeAB.space(), typeAB));
+ assertEquals(0, spi.size(typeBA.space(), typeBA));
// For invalid space name/type should not fail.
spi.rebuildIndexes("not_existing_space", typeAA);
@@ -401,22 +402,22 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
// Unregister.
spi.unregisterType(typeAA.space(), typeAA);
- assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(2, spi.size(typeAB.space(), typeAB, null));
- assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(-1, spi.size(typeAA.space(), typeAA));
+ assertEquals(2, spi.size(typeAB.space(), typeAB));
+ assertEquals(0, spi.size(typeBA.space(), typeBA));
spi.unregisterType(typeAB.space(), typeAB);
- assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
- assertEquals(-1, spi.size(typeAB.space(), typeAB, null));
- assertEquals(0, spi.size(typeBA.space(), typeBA, null));
+ assertEquals(-1, spi.size(typeAA.space(), typeAA));
+ assertEquals(-1, spi.size(typeAB.space(), typeAB));
+ assertEquals(0, spi.size(typeBA.space(), typeBA));
spi.unregisterType(typeBA.space(), typeBA);
// Should not store but should not fail as well.
spi.store(typeAA.space(), typeAA, key(10), aa(1, "Fail", 100500), "v220".getBytes(), 0);
- assertEquals(-1, spi.size(typeAA.space(), typeAA, null));
+ assertEquals(-1, spi.size(typeAA.space(), typeAA));
}
/**
@@ -447,7 +448,8 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
time = now;
range *= 3;
- GridQueryFieldsResult res = spi.queryFields("A", sql, Arrays.<Object>asList(1, range), null);
+ GridQueryFieldsResult res = spi.queryLocalSqlFields("A", sql, Arrays.<Object>asList(1, range), null,
+ false);
assert res.iterator().hasNext();
@@ -525,6 +527,11 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
}
/** {@inheritDoc} */
+ @Override public String affinityKey() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
@Override public String name() {
return name;
}
@@ -621,7 +628,7 @@ public abstract class GridIndexingSpiAbstractSelfTest extends GridCommonAbstract
/** {@inheritDoc} */
@Override public byte[] valueBytes(CacheObjectContext ctx) throws IgniteCheckedException {
- return Utils.serialize(val, null);
+ return JdbcUtils.serialize(val, null);
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
index e70ee8d..8408ba0 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2TableSelfTest.java
@@ -33,6 +33,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.h2.Driver;
import org.h2.index.Index;
@@ -95,9 +96,9 @@ public class GridH2TableSelfTest extends GridCommonAbstractTest {
IndexColumn str = tbl.indexColumn(2, SortOrder.DESCENDING);
IndexColumn x = tbl.indexColumn(3, SortOrder.DESCENDING);
- idxs.add(new GridH2TreeIndex(PK_NAME, tbl, true, 0, 1, id));
- idxs.add(new GridH2TreeIndex(NON_UNIQUE_IDX_NAME, tbl, false, 0, 1, x, t));
- idxs.add(new GridH2TreeIndex(STR_IDX_NAME, tbl, false, 0, 1, str));
+ idxs.add(new GridH2TreeIndex(PK_NAME, tbl, true, F.asList(id)));
+ idxs.add(new GridH2TreeIndex(NON_UNIQUE_IDX_NAME, tbl, false, F.asList(x, t, id)));
+ idxs.add(new GridH2TreeIndex(STR_IDX_NAME, tbl, false, F.asList(str, id)));
return idxs;
}
@@ -120,7 +121,8 @@ public class GridH2TableSelfTest extends GridCommonAbstractTest {
* @return New row.
*/
private GridH2Row row(UUID id, long t, String str, long x) {
- return new GridH2Row(ValueUuid.get(id.getMostSignificantBits(), id.getLeastSignificantBits()),
+ return GridH2RowFactory.create(
+ ValueUuid.get(id.getMostSignificantBits(), id.getLeastSignificantBits()),
ValueTimestamp.get(new Timestamp(t)),
ValueString.get(str),
ValueLong.get(x));
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/AbstractH2CompareQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/AbstractH2CompareQueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/AbstractH2CompareQueryTest.java
index ffe137f..f0ab123 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/AbstractH2CompareQueryTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/AbstractH2CompareQueryTest.java
@@ -30,6 +30,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
+import junit.framework.AssertionFailedError;
import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.cache.CacheAtomicityMode;
@@ -49,18 +50,21 @@ import org.jetbrains.annotations.Nullable;
/**
* Abstract test framework to compare query results from h2 database instance and mixed ignite caches (replicated and partitioned)
- * which have the same data models and data content.
+ * which have the same data models and data content.
*/
public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest {
/** */
private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+ /** */
+ protected static final int SRVS = 4;
+
/** Partitioned cache. */
protected static IgniteCache pCache;
/** Replicated cache. */
protected static IgniteCache rCache;
-
+
/** H2 db connection. */
protected static Connection conn;
@@ -77,14 +81,21 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
c.setMarshaller(new OptimizedMarshaller(true));
- c.setCacheConfiguration(createCache("part", CacheMode.PARTITIONED),
- createCache("repl", CacheMode.REPLICATED)
- );
+ c.setCacheConfiguration(cacheConfigurations());
return c;
}
/**
+ * @return Cache configurations.
+ */
+ protected CacheConfiguration[] cacheConfigurations() {
+ return new CacheConfiguration[] {
+ createCache("part", CacheMode.PARTITIONED),
+ createCache("repl", CacheMode.REPLICATED)};
+ }
+
+ /**
* Creates new cache configuration.
*
* @param name Cache name.
@@ -114,14 +125,14 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
@Override protected void beforeTestsStarted() throws Exception {
super.beforeTestsStarted();
- Ignite ignite = startGrids(4);
+ Ignite ignite = startGrids(SRVS);
pCache = ignite.cache("part");
-
+
rCache = ignite.cache("repl");
awaitPartitionMapExchange();
-
+
conn = openH2Connection(false);
initializeH2Schema();
@@ -130,22 +141,23 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
checkAllDataEquals();
}
-
+
/** {@inheritDoc} */
@Override protected void afterTestsStopped() throws Exception {
super.afterTestsStopped();
Statement st = conn.createStatement();
-
+
st.execute("DROP ALL OBJECTS");
conn.close();
-
+
stopAllGrids();
}
/**
* Populate cache and h2 database with test data.
+ * @throws SQLException If failed.
*/
protected abstract void initCacheAndDbData() throws Exception;
@@ -158,6 +170,7 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
* Initialize h2 database schema.
*
* @throws SQLException If exception.
+ * @return Statement.
*/
protected Statement initializeH2Schema() throws SQLException {
Statement st = conn.createStatement();
@@ -175,11 +188,11 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
* @return Pooled connection.
* @throws SQLException In case of error.
*/
- private Connection openH2Connection(boolean autocommit) throws SQLException {
+ protected Connection openH2Connection(boolean autocommit) throws SQLException {
System.setProperty("h2.serializeJavaObject", "false");
-
+
String dbName = "test";
-
+
Connection conn = DriverManager.getConnection("jdbc:h2:mem:" + dbName + ";DB_CLOSE_DELAY=-1");
conn.setAutoCommit(autocommit);
@@ -193,7 +206,7 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
* @param sql SQL query.
* @param args SQL arguments.
* then results will compare as ordered queries.
- * @return Result set after SQL query execution.
+ * @return Result set after SQL query execution.
* @throws SQLException If exception.
*/
protected final List<List<?>> compareQueryRes0(String sql, @Nullable Object... args) throws SQLException {
@@ -201,14 +214,14 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
}
/**
- * Execute given sql query on h2 database and on ignite cache and compare results.
+ * Execute given sql query on h2 database and on ignite cache and compare results.
* Expected that results are not ordered.
*
* @param cache Ignite cache.
* @param sql SQL query.
* @param args SQL arguments.
* then results will compare as ordered queries.
- * @return Result set after SQL query execution.
+ * @return Result set after SQL query execution.
* @throws SQLException If exception.
*/
protected final List<List<?>> compareQueryRes0(IgniteCache cache, String sql, @Nullable Object... args) throws SQLException {
@@ -239,20 +252,80 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
* then results will compare as ordered queries.
* @return Result set after SQL query execution.
* @throws SQLException If exception.
- */
+ */
+ @SuppressWarnings("unchecked")
+ protected static List<List<?>> compareQueryRes0(IgniteCache cache, String sql, @Nullable Object[] args,
+ Ordering ordering) throws SQLException {
+ return compareQueryRes0(cache, sql, false, args, ordering);
+ }
+
+ /**
+ * Execute given sql query on h2 database and on ignite cache and compare results.
+ *
+ * @param cache Ignite cache.
+ * @param sql SQL query.
+ * @param distrib Distributed SQL Join flag.
+ * @param args SQL arguments.
+ * @param ordering Expected ordering of SQL results. If {@link Ordering#ORDERED}
+ * then results will compare as ordered queries.
+ * @return Result set after SQL query execution.
+ * @throws SQLException If exception.
+ */
+ protected static List<List<?>> compareQueryRes0(IgniteCache cache,
+ String sql,
+ boolean distrib,
+ @Nullable Object[] args,
+ Ordering ordering) throws SQLException {
+ return compareQueryRes0(cache, sql, distrib, false, args, ordering);
+ }
+
+ /**
+ * Execute given sql query on h2 database and on ignite cache and compare results.
+ *
+ * @param cache Ignite cache.
+ * @param sql SQL query.
+ * @param distrib Distributed SQL Join flag.
+ * @param enforceJoinOrder Enforce join order flag.
+ * @param args SQL arguments.
+ * @param ordering Expected ordering of SQL results. If {@link Ordering#ORDERED}
+ * then results will compare as ordered queries.
+ * @return Result set after SQL query execution.
+ * @throws SQLException If exception.
+ */
@SuppressWarnings("unchecked")
- protected final List<List<?>> compareQueryRes0(IgniteCache cache, String sql, @Nullable Object[] args, Ordering ordering) throws SQLException {
+ protected static List<List<?>> compareQueryRes0(IgniteCache cache,
+ String sql,
+ boolean distrib,
+ boolean enforceJoinOrder,
+ @Nullable Object[] args,
+ Ordering ordering) throws SQLException {
if (args == null)
args = new Object[] {null};
-
- info("Sql query:\n" + sql + "\nargs=" + Arrays.toString(args));
List<List<?>> h2Res = executeH2Query(sql, args);
- List<List<?>> cacheRes = cache.query(new SqlFieldsQuery(sql).setArgs(args)).getAll();
+// String plan = (String)((IgniteCache<Object, Object>)cache).query(new SqlFieldsQuery("explain " + sql)
+// .setArgs(args)
+// .setDistributedJoins(distrib))
+// .getAll().get(0).get(0);
+//
+// X.println("Plan : " + plan);
+
+ List<List<?>> cacheRes = cache.query(new SqlFieldsQuery(sql).
+ setArgs(args).
+ setDistributedJoins(distrib).
+ setEnforceJoinOrder(enforceJoinOrder)).getAll();
+
+ try {
+ assertRsEquals(h2Res, cacheRes, ordering);
+ }
+ catch (AssertionFailedError e) {
+ X.println("Sql query:\n" + sql + "\nargs=" + Arrays.toString(args));
+ X.println("[h2Res=" + h2Res + ", cacheRes=" + cacheRes + "]");
+
+ throw e;
+ }
- assertRsEquals(h2Res, cacheRes, ordering);
-
return h2Res;
}
@@ -264,11 +337,11 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
* @return Result of SQL query on h2 database.
* @throws SQLException If exception.
*/
- private List<List<?>> executeH2Query(String sql, Object[] args) throws SQLException {
+ private static List<List<?>> executeH2Query(String sql, Object[] args) throws SQLException {
List<List<?>> res = new ArrayList<>();
ResultSet rs = null;
- try(PreparedStatement st = conn.prepareStatement(sql)) {
+ try (PreparedStatement st = conn.prepareStatement(sql)) {
for (int idx = 0; idx < args.length; idx++)
st.setObject(idx + 1, args[idx]);
@@ -278,17 +351,17 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
int colCnt = meta.getColumnCount();
- for (int i = 1; i <= colCnt; i++)
- X.print(meta.getColumnLabel(i) + " ");
-
- X.println();
+// for (int i = 1; i <= colCnt; i++)
+// X.print(meta.getColumnLabel(i) + " ");
+//
+// X.println();
while (rs.next()) {
List<Object> row = new ArrayList<>(colCnt);
-
+
for (int i = 1; i <= colCnt; i++)
row.add(rs.getObject(i));
-
+
res.add(row);
}
}
@@ -307,9 +380,9 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
* @param ordering Expected ordering of SQL results. If {@link Ordering#ORDERED}
* then results will compare as ordered queries.
*/
- private void assertRsEquals(List<List<?>> rs1, List<List<?>> rs2, Ordering ordering) {
+ private static void assertRsEquals(List<List<?>> rs1, List<List<?>> rs2, Ordering ordering) {
assertEquals("Rows count has to be equal.", rs1.size(), rs2.size());
-
+
switch (ordering){
case ORDERED:
for (int rowNum = 0; rowNum < rs1.size(); rowNum++) {
@@ -329,7 +402,7 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
assertEquals("Unique rows count has to be equal.", rowsWithCnt1.size(), rowsWithCnt2.size());
- X.println("Result size: " + rowsWithCnt1.size());
+ // X.println("Result size: " + rowsWithCnt1.size());
Iterator<Map.Entry<String,Integer>> iter1 = rowsWithCnt1.entrySet().iterator();
Iterator<Map.Entry<String,Integer>> iter2 = rowsWithCnt2.entrySet().iterator();
@@ -343,15 +416,15 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
assertTrue(iter2.hasNext());
- Map.Entry<String,Integer> e1 = iter1.next();
- Map.Entry<String,Integer> e2 = iter2.next();
+ Map.Entry<String, Integer> e1 = iter1.next();
+ Map.Entry<String, Integer> e2 = iter2.next();
assertEquals(e1.getKey(), e2.getKey());
assertEquals(e1.getValue(), e2.getValue());
}
-
+
break;
- default:
+ default:
throw new IllegalStateException();
}
}
@@ -360,30 +433,30 @@ public abstract class AbstractH2CompareQueryTest extends GridCommonAbstractTest
* @param rs Result set.
* @return Map of unique rows at the result set to number of occuriances at the result set.
*/
- private TreeMap<String, Integer> extractUniqueRowsWithCounts(Iterable<List<?>> rs) {
+ private static TreeMap<String, Integer> extractUniqueRowsWithCounts(Iterable<List<?>> rs) {
TreeMap<String, Integer> res = new TreeMap<>();
for (List<?> row : rs) {
String rowStr = row.toString();
Integer cnt = res.get(rowStr);
-
+
if (cnt == null)
cnt = 0;
-
+
res.put(rowStr, cnt + 1);
}
return res;
}
-
+
/**
* Ordering type.
*/
protected enum Ordering {
/** Random. */
- RANDOM,
+ RANDOM,
/** Ordered. */
ORDERED
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
index 9fb5765..d6ee511 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java
@@ -147,6 +147,8 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
checkQuery("select avg(old) from Person left join Address where Person.addrId = Address.id " +
"and lower(Address.street) = lower(?)");
+ checkQuery("select avg(old) from Person right join Address where Person.addrId = Address.id " +
+ "and lower(Address.street) = lower(?)");
checkQuery("select avg(old) from Person, Address where Person.addrId = Address.id " +
"and lower(Address.street) = lower(?)");
@@ -164,6 +166,7 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
checkQuery("select person.* from Person, Address a");
checkQuery("select p.*, street from Person p, Address a");
checkQuery("select p.name, a.street from Person p, Address a");
+ checkQuery("select p.name, a.street from Address a, Person p");
checkQuery("select distinct p.name, a.street from Person p, Address a");
checkQuery("select distinct name, street from Person, Address group by old");
checkQuery("select distinct name, street from Person, Address");
@@ -254,20 +257,6 @@ public class GridQueryParsingTest extends GridCommonAbstractTest {
/**
*
*/
- public void testExample1() throws Exception {
- Query select = parse("select p.name n, max(p.old) maxOld, min(p.old) minOld from Person p group by p.name having maxOld > 10 and min(p.old) < 1");
-
- GridSqlQueryParser ses = new GridSqlQueryParser();
-
- GridSqlQuery gridSelect = ses.parse(select);
-
- //System.out.println(select.getPlanSQL());
- System.out.println(gridSelect.getSQL());
- }
-
- /**
- *
- */
private JdbcConnection connection() throws Exception {
GridKernalContext ctx = ((IgniteEx)ignite).context();
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryDistributedJoinsTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryDistributedJoinsTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryDistributedJoinsTest.java
new file mode 100644
index 0000000..267778f
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryDistributedJoinsTest.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.query.h2.sql;
+
+/**
+ * Executes SQL big query test using distributed joins mode.
+ */
+public class H2CompareBigQueryDistributedJoinsTest extends H2CompareBigQueryTest {
+ /** {@inheritDoc} */
+ @Override protected boolean distributedJoins() {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryTest.java
index 255ac44..dc73e96 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/H2CompareBigQueryTest.java
@@ -35,11 +35,11 @@ import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.configuration.CacheConfiguration;
/**
- * Executes one big query (and subqueries of the big query) to compare query results from h2 database instance and
+ * Executes one big query (and subqueries of the big query) to compare query results from h2 database instance and
* mixed ignite caches (replicated and partitioned) which have the same data models and data content.
- *
- *
- * <pre>
+ *
+ *
+ * <pre>
*
* -------------------------------------> rootOrderId (virtual) <--------------------------
* | | |
@@ -75,20 +75,20 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
/** Dates count. */
private static final int DATES_CNT = 5;
-
+
/** Full the big query. */
private String bigQry = getBigQry();
/**
* Extracts the big query from file.
- *
+ *
* @return Big query.
*/
private String getBigQry() {
String res = "";
Reader isr = new InputStreamReader(getClass().getResourceAsStream("bigQuery.sql"));
-
+
try(BufferedReader reader = new BufferedReader(isr)) {
for(String line; (line = reader.readLine()) != null; )
if (!line.startsWith("--")) // Skip commented lines.
@@ -96,21 +96,35 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
}
catch (Throwable e) {
e.printStackTrace();
-
+
fail();
}
return res;
}
+ /**
+ * @return Use colocated data.
+ */
+ private boolean useColocatedData() {
+ return !distributedJoins();
+ }
+
+ /**
+ * @return Whehter to use distrubutedJoins or not.
+ */
+ protected boolean distributedJoins() {
+ return false;
+ }
+
/** {@inheritDoc} */
@Override protected void setIndexedTypes(CacheConfiguration<?, ?> cc, CacheMode mode) {
if (mode == CacheMode.PARTITIONED)
cc.setIndexedTypes(
Integer.class, CustOrder.class,
- AffinityKey.class, ReplaceOrder.class,
- AffinityKey.class, OrderParams.class,
- AffinityKey.class, Cancel.class
+ useColocatedData() ? AffinityKey.class : Integer.class, ReplaceOrder.class,
+ useColocatedData() ? AffinityKey.class : Integer.class, OrderParams.class,
+ useColocatedData() ? AffinityKey.class : Integer.class, Cancel.class
);
else if (mode == CacheMode.REPLICATED)
cc.setIndexedTypes(
@@ -142,8 +156,8 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
// Generate 1 - 5 orders for 1 root order.
for (int i = 0; i < rootOrderId % 5; i++) {
int orderId = idGen.incrementAndGet();
-
- CustOrder order = new CustOrder(orderId, rootOrderId, dates.get(orderId % dates.size()) ,
+
+ CustOrder order = new CustOrder(orderId, rootOrderId, dates.get(orderId % dates.size()) ,
orderId % 2 == 0 ? "CUSTOM" : "OTHER", orderId);
add(order);
@@ -151,23 +165,23 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
pCache.put(order.orderId, order);
insertInDb(order);
- }
+ }
}
}};
final Collection<OrderParams> params = new ArrayList<OrderParams>(){{
for (CustOrder o : orders) {
- OrderParams op = new OrderParams(idGen.incrementAndGet(), o.orderId, o.date,
+ OrderParams op = new OrderParams(idGen.incrementAndGet(), o.orderId, o.date,
o.orderId % 2 == 0 ? "Algo 1" : "Algo 2");
add(op);
- pCache.put(op.key(), op);
+ pCache.put(op.key(useColocatedData()), op);
insertInDb(op);
}
}};
-
+
final Collection<ReplaceOrder> replaces = new ArrayList<ReplaceOrder>(){{
for (CustOrder o : orders) {
if (o.orderId % 7 == 0) {
@@ -176,7 +190,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
add(replace);
- pCache.put(replace.key(), replace);
+ pCache.put(replace.key(useColocatedData()), replace);
insertInDb(replace);
}
@@ -186,12 +200,12 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
final Collection<Cancel> cancels = new ArrayList<Cancel>(){{
for (CustOrder o : orders) {
if (o.orderId % 9 == 0) {
- Cancel c = new Cancel(idGen.incrementAndGet(), o.orderId,
+ Cancel c = new Cancel(idGen.incrementAndGet(), o.orderId,
new Date(o.date.getTime() + 12 * 60 * 60 * 1000));// Plus a half of day.
add(c);
- pCache.put(c.key(), c);
+ pCache.put(c.key(useColocatedData()), c);
insertInDb(c);
}
@@ -203,7 +217,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
int execShares = 10000 + rootOrderId;
int price = 1000 + rootOrderId;
int latsMkt = 3000 + rootOrderId;
-
+
Exec exec = new Exec(rootOrderId, dates.get(rootOrderId % dates.size()), execShares, price, latsMkt);
add(exec);
@@ -232,8 +246,8 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
* @throws Exception If failed.
*/
public void testBigQuery() throws Exception {
- List<List<?>> res = compareQueryRes0(bigQry);
-
+ List<List<?>> res = compareQueryRes0(pCache, bigQry, distributedJoins(), new Object[0], Ordering.RANDOM);
+
assertTrue(!res.isEmpty()); // Ensure we set good testing data at database.
}
@@ -241,6 +255,8 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
@Override protected Statement initializeH2Schema() throws SQLException {
Statement st = super.initializeH2Schema();
+ final String keyType = useColocatedData() ? "other" : "int";
+
st.execute("create table \"part\".CustOrder" +
" (" +
" _key int not null," +
@@ -255,7 +271,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
st.execute("create table \"part\".ReplaceOrder" +
" (" +
- " _key other not null," +
+ " _key " + keyType + " not null," +
" _val other not null," +
" id int unique," +
" orderId int ," +
@@ -268,7 +284,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
st.execute("create table \"part\".OrderParams" +
" (" +
- " _key other not null," +
+ " _key " + keyType + " not null," +
" _val other not null," +
" id int unique," +
" orderId int ," +
@@ -278,7 +294,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
st.execute("create table \"part\".Cancel" +
" (" +
- " _key other not null," +
+ " _key " + keyType + " not null," +
" _val other not null," +
" id int unique," +
" date Date, " +
@@ -295,15 +311,15 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
" price int," +
" lastMkt int" +
" )");
-
+
conn.commit();
-
+
return st;
}
/**
* Insert {@link CustOrder} at h2 database.
- *
+ *
* @param o CustOrder.
*/
private void insertInDb(CustOrder o) throws SQLException {
@@ -311,7 +327,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
"insert into \"part\".CustOrder (_key, _val, orderId, rootOrderId, date, alias, archSeq, origOrderId) " +
"values(?, ?, ?, ?, ?, ?, ?, ?)")) {
int i = 0;
-
+
st.setObject(++i, o.orderId);
st.setObject(++i, o);
st.setObject(++i, o.orderId);
@@ -335,8 +351,8 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
"insert into \"part\".ReplaceOrder (_key, _val, id, orderId, rootOrderId, date, alias, archSeq, refOrderId) " +
"values(?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
int i = 0;
-
- st.setObject(++i, o.key());
+
+ st.setObject(++i, o.key(useColocatedData()));
st.setObject(++i, o);
st.setObject(++i, o.id);
st.setObject(++i, o.orderId);
@@ -359,15 +375,15 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
try(PreparedStatement st = conn.prepareStatement(
"insert into \"part\".OrderParams (_key, _val, id, date, orderId, parentAlgo) values(?, ?, ?, ?, ?, ?)")) {
int i = 0;
-
- st.setObject(++i, o.key());
+
+ st.setObject(++i, o.key(useColocatedData()));
st.setObject(++i, o);
st.setObject(++i, o.id);
st.setObject(++i, o.date);
st.setObject(++i, o.orderId);
st.setObject(++i, o.parentAlgo);
- st.executeUpdate();
+ st.executeUpdate();
}
}
@@ -380,8 +396,8 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
try(PreparedStatement st = conn.prepareStatement(
"insert into \"part\".Cancel (_key, _val, id, date, refOrderId) values(?, ?, ?, ?, ?)")) {
int i = 0;
-
- st.setObject(++i, o.key());
+
+ st.setObject(++i, o.key(useColocatedData()));
st.setObject(++i, o);
st.setObject(++i, o.id);
st.setObject(++i, o.date);
@@ -401,7 +417,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
"insert into \"repl\".Exec (_key, _val, date, rootOrderId, execShares, price, lastMkt) " +
"values(?, ?, ?, ?, ?, ?, ?)")) {
int i = 0;
-
+
st.setObject(++i, o.rootOrderId);
st.setObject(++i, o);
st.setObject(++i, o.date);
@@ -475,7 +491,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
/** Primary key. */
@QuerySqlField(index = true)
private int id;
-
+
/** Order id. */
@QuerySqlField(index = true)
private int orderId;
@@ -518,10 +534,11 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
}
/**
- * @return Afinity key.
+ * @param useColocatedData Use colocated data.
+ * @return Key.
*/
- public AffinityKey<Integer> key() {
- return new AffinityKey<>(id, orderId);
+ public Object key(boolean useColocatedData) {
+ return useColocatedData ? new AffinityKey<>(id, orderId) : id;
}
/** {@inheritDoc} */
@@ -569,10 +586,11 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
}
/**
- * @return Afinity key.
+ * @param useColocatedData Use colocated data.*
+ * @return Key.
*/
- public AffinityKey<Integer> key() {
- return new AffinityKey<>(id, orderId);
+ public Object key(boolean useColocatedData) {
+ return useColocatedData ? new AffinityKey<>(id, orderId) : id;
}
/** {@inheritDoc} */
@@ -603,7 +621,7 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
private Date date;
/**
- * @param id
+ * @param id ID.
* @param refOrderId Reference order id.
* @param date Date.
*/
@@ -614,10 +632,11 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
}
/**
- * @return Afinity key.
+ * @param useColocatedData Use colocated data.
+ * @return Key.
*/
- public AffinityKey<Integer> key() {
- return new AffinityKey<>(id, refOrderId);
+ public Object key(boolean useColocatedData) {
+ return useColocatedData ? new AffinityKey<>(id, refOrderId) : id;
}
/** {@inheritDoc} */
@@ -680,4 +699,4 @@ public class H2CompareBigQueryTest extends AbstractH2CompareQueryTest {
return rootOrderId;
}
}
-}
\ No newline at end of file
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/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 1b1908d..65a94dd 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
@@ -22,11 +22,19 @@ import org.apache.ignite.internal.processors.cache.GridCacheCrossCacheQuerySelfT
import org.apache.ignite.internal.processors.cache.GridCacheQueryIndexDisabledSelfTest;
import org.apache.ignite.internal.processors.cache.GridCacheQueryInternalKeysSelfTest;
import org.apache.ignite.internal.processors.cache.GridCacheQuerySerializationSelfTest;
-import org.apache.ignite.internal.processors.cache.GridCacheReduceQueryMultithreadedSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteBinaryObjectFieldsQuerySelfTest;
import org.apache.ignite.internal.processors.cache.IgniteBinaryWrappedObjectFieldsQuerySelfTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheCollocatedQuerySelfTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheCrossCacheJoinRandomTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheDistributedJoinCollocatedAndNotTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheDistributedJoinCustomAffinityMapper;
+import org.apache.ignite.internal.processors.cache.IgniteCacheDistributedJoinPartitionedAndReplicatedTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheDistributedJoinQueryConditionsTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheDistributedJoinTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheDuplicateEntityConfigurationSelfTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheDistributedJoinNoIndexTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheJoinPartitionedAndReplicatedTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheJoinQueryWithAffinityKeyTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheLargeResultSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapEvictQueryTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheOffheapIndexScanTest;
@@ -41,6 +49,7 @@ import org.apache.ignite.internal.processors.cache.IgniteCacheQueryMultiThreaded
import org.apache.ignite.internal.processors.cache.IgniteCacheQueryOffheapEvictsMultiThreadedSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheQueryOffheapMultiThreadedSelfTest;
import org.apache.ignite.internal.processors.cache.IgniteCacheSqlQueryMultiThreadedSelfTest;
+import org.apache.ignite.internal.processors.cache.IgniteCrossCachesJoinsQueryTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheAtomicNearEnabledQuerySelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheAtomicQuerySelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheClientQueryReplicatedNodeRestartSelfTest;
@@ -49,6 +58,7 @@ import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheP
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCachePartitionedSnapshotEnabledQuerySelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNoRebalanceSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeFailTest;
+import org.apache.ignite.internal.processors.cache.distributed.near.IgniteCacheQueryNodeRestartDistributedJoinSelfTest;
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.IgniteCacheReplicatedQueryP2PDisabledSelfTest;
@@ -106,9 +116,9 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
suite.addTestSuite(IgniteCacheOffheapIndexScanTest.class);
suite.addTestSuite(IgniteCacheQueryNodeRestartSelfTest.class);
suite.addTestSuite(IgniteCacheQueryNodeRestartSelfTest2.class);
+ suite.addTestSuite(IgniteCacheQueryNodeRestartDistributedJoinSelfTest.class);
suite.addTestSuite(IgniteCacheQueryNodeFailTest.class);
suite.addTestSuite(IgniteCacheClientQueryReplicatedNodeRestartSelfTest.class);
- suite.addTestSuite(GridCacheReduceQueryMultithreadedSelfTest.class);
suite.addTestSuite(GridCacheCrossCacheQuerySelfTest.class);
suite.addTestSuite(GridCacheQuerySerializationSelfTest.class);
suite.addTestSuite(IgniteBinaryObjectFieldsQuerySelfTest.class);
@@ -116,6 +126,17 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
suite.addTestSuite(IgniteCacheQueryH2IndexingLeakTest.class);
suite.addTestSuite(IgniteCacheQueryNoRebalanceSelfTest.class);
+ suite.addTestSuite(IgniteCacheJoinQueryWithAffinityKeyTest.class);
+ suite.addTestSuite(IgniteCacheDistributedJoinCollocatedAndNotTest.class);
+ suite.addTestSuite(IgniteCacheDistributedJoinPartitionedAndReplicatedTest.class);
+ suite.addTestSuite(IgniteCacheDistributedJoinQueryConditionsTest.class);
+ suite.addTestSuite(IgniteCacheDistributedJoinTest.class);
+ suite.addTestSuite(IgniteCacheJoinPartitionedAndReplicatedTest.class);
+ suite.addTestSuite(IgniteCacheDistributedJoinNoIndexTest.class);
+ suite.addTestSuite(IgniteCrossCachesJoinsQueryTest.class);
+ suite.addTestSuite(IgniteCacheCrossCacheJoinRandomTest.class);
+ suite.addTestSuite(IgniteCacheDistributedJoinCustomAffinityMapper.class);
+
return suite;
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
index e5f4027..7cb1adb 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteCacheQuerySelfTestSuite2.java
@@ -40,10 +40,6 @@ import org.apache.ignite.internal.processors.cache.distributed.replicated.Ignite
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedFieldsQuerySelfTest;
import org.apache.ignite.internal.processors.cache.local.IgniteCacheLocalFieldsQuerySelfTest;
import org.apache.ignite.internal.processors.cache.query.GridCacheSwapScanQuerySelfTest;
-import org.apache.ignite.internal.processors.cache.reducefields.GridCacheReduceFieldsQueryAtomicSelfTest;
-import org.apache.ignite.internal.processors.cache.reducefields.GridCacheReduceFieldsQueryLocalSelfTest;
-import org.apache.ignite.internal.processors.cache.reducefields.GridCacheReduceFieldsQueryPartitionedSelfTest;
-import org.apache.ignite.internal.processors.cache.reducefields.GridCacheReduceFieldsQueryReplicatedSelfTest;
import org.apache.ignite.internal.processors.query.h2.sql.BaseH2CompareQueryTest;
import org.apache.ignite.internal.processors.query.h2.sql.H2CompareBigQueryTest;
import org.apache.ignite.spi.communication.tcp.GridOrderedMessageCancelSelfTest;
@@ -73,12 +69,6 @@ public class IgniteCacheQuerySelfTestSuite2 extends TestSuite {
suite.addTestSuite(IgniteCachePartitionedFieldsQueryP2PEnabledSelfTest.class);
suite.addTestSuite(IgniteCacheFieldsQueryNoDataSelfTest.class);
- // Reduce fields queries.
- suite.addTestSuite(GridCacheReduceFieldsQueryLocalSelfTest.class);
- suite.addTestSuite(GridCacheReduceFieldsQueryPartitionedSelfTest.class);
- suite.addTestSuite(GridCacheReduceFieldsQueryAtomicSelfTest.class);
- suite.addTestSuite(GridCacheReduceFieldsQueryReplicatedSelfTest.class);
-
suite.addTestSuite(GridCacheQueryIndexingDisabledSelfTest.class);
suite.addTestSuite(GridCacheSwapScanQuerySelfTest.class);
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/yardstick/src/main/java/org/apache/ignite/yardstick/IgniteBenchmarkUtils.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/IgniteBenchmarkUtils.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/IgniteBenchmarkUtils.java
index 0b7568b..af060d4 100644
--- a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/IgniteBenchmarkUtils.java
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/IgniteBenchmarkUtils.java
@@ -26,6 +26,10 @@ import org.apache.ignite.transactions.TransactionConcurrency;
import org.apache.ignite.transactions.TransactionIsolation;
import org.apache.ignite.transactions.TransactionOptimisticException;
import org.apache.ignite.transactions.TransactionRollbackException;
+import org.apache.ignite.yardstick.cache.IgniteSqlQueryBenchmark;
+import org.apache.ignite.yardstick.cache.IgniteSqlQueryDistributedJoinBenchmark;
+import org.yardstickframework.BenchmarkDriverStartUp;
+import org.yardstickframework.BenchmarkServerStartUp;
/**
* Utils.
@@ -72,4 +76,45 @@ public class IgniteBenchmarkUtils {
}
}
}
+
+// /**
+// * Starts driver for quick benchmarks testing.
+// *
+// * @param args Command line arguments.
+// * @throws Exception If failed.
+// */
+// public static void main(String[] args) throws Exception {
+// String[] args0 = {
+// "-t", "1",
+// "-w", "5",
+// "-d", "5",
+// "-dn", IgniteSqlQueryDistributedJoinBenchmark.class.getSimpleName(),
+// "-r", "100",
+// "-sn", "IgniteNode",
+// "-bcj",
+// "-cfg", "modules/yardstick/config/ignite-localhost-config.xml"};
+//
+// BenchmarkDriverStartUp.main(args0);
+// }
+
+ /**
+ * Starts driver for quick benchmarks testing.
+ *
+ * @param args Command line arguments.
+ * @throws Exception If failed.
+ */
+ public static void main(String[] args) throws Exception {
+ String[] args0 = {
+ "-t", "15",
+ "-w", "30",
+ "-d", "60",
+ "-cl",
+ "-pr", "ThroughputLatencyProbe",
+ "-dn", IgniteSqlQueryBenchmark.class.getSimpleName(),
+ "-r", "100000",
+ "-sn", "IgniteNode",
+ "-cfg", "modules/yardstick/config/ignite-localhost-config.xml"};
+
+ BenchmarkDriverStartUp.main(args0);
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBenchmark.java
new file mode 100644
index 0000000..1f009e6
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBenchmark.java
@@ -0,0 +1,184 @@
+/*
+ * 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.yardstick.cache;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteDataStreamer;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.yardstick.cache.model.Organization;
+import org.apache.ignite.yardstick.cache.model.Person;
+import org.yardstickframework.BenchmarkConfiguration;
+
+import static org.yardstickframework.BenchmarkUtils.println;
+
+/**
+ * Ignite benchmark that performs query operations with joins.
+ */
+public class IgniteSqlQueryDistributedJoinBenchmark extends IgniteCacheAbstractBenchmark<Integer, Object> {
+ /** */
+ private int orgRange;
+
+ /** */
+ private boolean broadcast;
+
+ /** {@inheritDoc} */
+ @Override public void setUp(BenchmarkConfiguration cfg) throws Exception {
+ super.setUp(cfg);
+
+ broadcast = broadcastJoin();
+
+ println(cfg, "Populating query data...");
+
+ long start = System.nanoTime();
+
+ int personCnt = 0;
+
+ try (IgniteDataStreamer<Object, Object> dataLdr = ignite().dataStreamer(cache.getName())) {
+ orgRange = args.range() / 10;
+
+ if (orgRange <= 0)
+ throw new IllegalArgumentException();
+
+ // Populate organizations.
+ for (int orgId = 0; orgId < orgRange; orgId++) {
+ dataLdr.addData(orgId, new Organization(orgId, "org" + orgId));
+
+ if (orgId % 1000 == 0 && Thread.currentThread().isInterrupted())
+ return;
+ }
+
+ dataLdr.flush();
+
+ // Populate persons.
+ for (int orgId = 0; orgId < orgRange; orgId++) {
+ int persons = orgId % 10 + 1;
+
+ for (int j = 0; j < persons; j++) {
+ int personId = orgRange + personCnt++;
+
+ Person p = new Person(personId,
+ orgId,
+ "firstName" + personId,
+ "lastName" + personId, 1000);
+
+ dataLdr.addData(personId, p);
+ }
+
+ if (personCnt % 100000 == 0)
+ println(cfg, "Populated persons: " + personCnt);
+
+ if (orgId % 1000 == 0 && Thread.currentThread().isInterrupted())
+ return;
+ }
+
+ dataLdr.close();
+ }
+
+ println(cfg, "Finished populating join query [orgCnt=" + orgRange +
+ ", personCnt=" + personCnt +
+ ", broadcastJoin=" + broadcast +
+ ", time=" + ((System.nanoTime() - start) / 1_000_000) + "ms]");
+
+ executeQueryJoin(0, broadcast, true);
+ }
+
+ /**
+ * @return Broadcast join flag.
+ */
+ protected boolean broadcastJoin() {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean test(Map<Object, Object> ctx) throws Exception {
+ int orgId = nextRandom(orgRange);
+
+ Collection<List<?>> res = executeQueryJoin(orgId, broadcast, false);
+
+ int persons = orgId % 10 + 1;
+
+ if (res.size() != persons)
+ throw new Exception("Invalid join result [orgId=" + orgId + ", resSize=" + res.size() + ']');
+
+ for (List<?> l : res) {
+ int orgId0 = (Integer)l.get(1);
+
+ if (orgId != orgId0)
+ throw new Exception("Invalid join result [orgId=" + orgId + ", res=" + l + ']');
+ }
+
+ return true;
+ }
+
+ /**
+ * @param orgId Organization ID.
+ * @param broadcast Broadcast join flag.
+ * @param planOnly If {@code true} just prints query plan.
+ * @return Query results.
+ * @throws Exception If failed.
+ */
+ private Collection<List<?>> executeQueryJoin(int orgId, boolean broadcast, boolean planOnly) throws Exception {
+ SqlFieldsQuery qry;
+
+ String sql;
+
+ if (broadcast) {
+ sql = "select p.id, p.orgId, p.firstName, p.lastName, o.name " +
+ "from Person p " +
+ "join Organization o " +
+ "on p.orgId = o.id " +
+ "where o.id=?";
+ }
+ else {
+ sql = "select p.id, p.orgId, p.firstName, p.lastName, o.name " +
+ "from Organization o " +
+ "join Person p " +
+ "on p.orgId = o._key " +
+ "where o._key=?";
+ }
+
+ qry = new SqlFieldsQuery(planOnly ? ("explain " + sql) : sql);
+ qry.setDistributedJoins(true);
+ qry.setArgs(orgId);
+
+ if (planOnly) {
+ String plan = (String)cache.query(qry).getAll().get(0).get(0);
+
+ println("Query execution plan:\n" + plan);
+
+ if (broadcast) {
+ if (plan.contains("batched:unicast") || !plan.contains("batched:broadcast"))
+ throw new Exception("Unexpected query plan: " + plan);
+ }
+ else if (!plan.contains("batched:unicast") || plan.contains("batched:broadcast"))
+ throw new Exception("Unexpected query plan: " + plan);
+
+ return null;
+ }
+ else
+ return cache.query(qry).getAll();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteCache<Integer, Object> cache() {
+ return ignite().cache("query");
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBroadcastBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBroadcastBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBroadcastBenchmark.java
new file mode 100644
index 0000000..8b03e3e
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteSqlQueryDistributedJoinBroadcastBenchmark.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.yardstick.cache;
+
+/**
+ *
+ */
+public class IgniteSqlQueryDistributedJoinBroadcastBenchmark extends IgniteSqlQueryDistributedJoinBenchmark {
+ /** {@inheritDoc} */
+ @Override protected boolean broadcastJoin() {
+ return true;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 3e9a71c..ebd6bf0 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -35,8 +35,9 @@
<properties>
<ignite.edition>fabric</ignite.edition>
-
- <!-- Build parameters. -->
+ <hadoop.version>2.4.1</hadoop.version>
+ <spark.version>1.5.2</spark.version>
+ <spring.version>4.1.0.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.build.timestamp.format>MMMM d yyyy</maven.build.timestamp.format>
<doxygen.exec>doxygen</doxygen.exec>
@@ -69,7 +70,7 @@
<guava.version>18.0</guava.version>
<guava14.version>14.0.1</guava14.version>
<guava16.version>16.0.1</guava16.version>
- <h2.version>1.3.175</h2.version>
+ <h2.version>1.4.191</h2.version>
<hadoop.version>2.4.1</hadoop.version>
<httpclient.version>4.5.1</httpclient.version>
<httpcore.version>4.4.3</httpcore.version>
@@ -188,6 +189,23 @@
</developer>
</developers>
+ <repositories>
+ <repository>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>always</updatePolicy>
+ <checksumPolicy>ignore</checksumPolicy>
+ </snapshots>
+ <id>h2database.com</id>
+ <name>Snapshot repository on h2database.com</name>
+ <url>http://h2database.com/m2-repo</url>
+ <layout>default</layout>
+ </repository>
+ </repositories>
+
<dependencyManagement>
<dependencies>
<dependency>
[38/50] [abbrv] ignite git commit: JB Annotations versions hotfix
(cherry picked from commit bbdf145)
Posted by vo...@apache.org.
JB Annotations versions hotfix
(cherry picked from commit bbdf145)
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a32eb87d
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a32eb87d
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a32eb87d
Branch: refs/heads/ignite-3553
Commit: a32eb87da4f07f327c92f788a0169507e3b125d9
Parents: 42f42ea
Author: Anton Vinogradov <av...@apache.org>
Authored: Wed Jul 27 11:00:22 2016 +0300
Committer: Anton Vinogradov <av...@apache.org>
Committed: Wed Jul 27 13:36:33 2016 +0300
----------------------------------------------------------------------
parent/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a32eb87d/parent/pom.xml
----------------------------------------------------------------------
diff --git a/parent/pom.xml b/parent/pom.xml
index 17f66c9..246c36b 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -78,7 +78,7 @@
<jackson2.version>2.7.5</jackson2.version>
<javax.cache.bundle.version>1.0.0_1</javax.cache.bundle.version>
<javax.cache.version>1.0.0</javax.cache.version>
- <jetbrains.annotations.version>15.0</jetbrains.annotations.version>
+ <jetbrains.annotations.version>13.0</jetbrains.annotations.version>
<jetty.version>9.2.11.v20150529</jetty.version>
<jms.spec.version>1.1.1</jms.spec.version>
<jsch.bundle.version>0.1.53_1</jsch.bundle.version>
[15/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java
new file mode 100644
index 0000000..0f76316
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2CollocationModel.java
@@ -0,0 +1,783 @@
+/*
+ * 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.opt;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.cache.CacheException;
+import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQueryParser;
+import org.apache.ignite.internal.util.typedef.F;
+import org.h2.command.dml.Query;
+import org.h2.command.dml.Select;
+import org.h2.command.dml.SelectUnion;
+import org.h2.expression.Comparison;
+import org.h2.expression.Expression;
+import org.h2.expression.ExpressionColumn;
+import org.h2.index.IndexCondition;
+import org.h2.index.ViewIndex;
+import org.h2.table.Column;
+import org.h2.table.IndexColumn;
+import org.h2.table.SubQueryInfo;
+import org.h2.table.Table;
+import org.h2.table.TableFilter;
+import org.h2.table.TableView;
+
+/**
+ * Collocation model for a query.
+ */
+public final class GridH2CollocationModel {
+ /** */
+ public static final int MULTIPLIER_COLLOCATED = 1;
+
+ /** */
+ private static final int MULTIPLIER_UNICAST = 50;
+
+ /** */
+ private static final int MULTIPLIER_BROADCAST = 200;
+
+ /** */
+ private static final int MULTIPLIER_REPLICATED_NOT_LAST = 10_000;
+
+ /** */
+ private final GridH2CollocationModel upper;
+
+ /** */
+ private final int filter;
+
+ /** */
+ private final boolean view;
+
+ /** */
+ private int multiplier;
+
+ /** */
+ private Type type;
+
+ /** */
+ private GridH2CollocationModel[] children;
+
+ /** */
+ private TableFilter[] childFilters;
+
+ /** */
+ private List<GridH2CollocationModel> unions;
+
+ /** */
+ private Select select;
+
+ /** */
+ private final boolean validate;
+
+ /**
+ * @param upper Upper.
+ * @param filter Filter.
+ * @param view This model will be a subquery (or top level query) and must contain child filters.
+ * @param validate Query validation flag.
+ */
+ private GridH2CollocationModel(GridH2CollocationModel upper, int filter, boolean view, boolean validate) {
+ this.upper = upper;
+ this.filter = filter;
+ this.view = view;
+ this.validate = validate;
+ }
+
+ /**
+ * @param upper Upper.
+ * @param filter Filter.
+ * @param unions Unions.
+ * @param view This model will be a subquery (or top level query) and must contain child filters.
+ * @param validate Query validation flag.
+ * @return Created child collocation model.
+ */
+ private static GridH2CollocationModel createChildModel(GridH2CollocationModel upper,
+ int filter,
+ List<GridH2CollocationModel> unions,
+ boolean view,
+ boolean validate) {
+ GridH2CollocationModel child = new GridH2CollocationModel(upper, filter, view, validate);
+
+ if (unions != null) {
+ // Bind created child to unions.
+ assert upper == null || upper.child(filter, false) != null || unions.isEmpty();
+
+ if (upper != null && unions.isEmpty()) {
+ assert upper.child(filter, false) == null;
+
+ upper.children[filter] = child;
+ }
+
+ unions.add(child);
+
+ child.unions = unions;
+ }
+ else if (upper != null) {
+ // Bind created child to upper model.
+ assert upper.child(filter, false) == null;
+
+ upper.children[filter] = child;
+ }
+
+ return child;
+ }
+
+ /**
+ * @param childFilters New child filters.
+ * @return {@code true} If child filters were updated.
+ */
+ private boolean childFilters(TableFilter[] childFilters) {
+ assert childFilters != null;
+ assert view;
+
+ Select select = childFilters[0].getSelect();
+
+ assert this.select == null || this.select == select;
+
+ if (this.select == null) {
+ this.select = select;
+
+ assert this.childFilters == null;
+ }
+ else if (Arrays.equals(this.childFilters, childFilters))
+ return false;
+
+ if (this.childFilters == null) {
+ // We have to clone because H2 reuses array and reorders elements.
+ this.childFilters = childFilters.clone();
+
+ children = new GridH2CollocationModel[childFilters.length];
+ }
+ else {
+ assert this.childFilters.length == childFilters.length;
+
+ // We have to copy because H2 reuses array and reorders elements.
+ System.arraycopy(childFilters, 0, this.childFilters, 0, childFilters.length);
+
+ Arrays.fill(children, null);
+ }
+
+ // Reset results.
+ type = null;
+ multiplier = 0;
+
+ return true;
+ }
+
+ /**
+ * @param i Index.
+ * @param f Table filter.
+ * @return {@code true} If the child is not a table or view.
+ */
+ private boolean isChildTableOrView(int i, TableFilter f) {
+ if (f == null)
+ f = childFilters[i];
+
+ Table t = f.getTable();
+
+ return t.isView() || t instanceof GridH2Table;
+ }
+
+ /**
+ * Do the needed calculations.
+ */
+ private void calculate() {
+ if (type != null)
+ return;
+
+ if (view) { // We are at (sub-)query model.
+ assert childFilters != null;
+
+ boolean collocated = true;
+ boolean partitioned = false;
+ int maxMultiplier = MULTIPLIER_COLLOCATED;
+
+ for (int i = 0; i < childFilters.length; i++) {
+ GridH2CollocationModel child = child(i, true);
+
+ Type t = child.type(true);
+
+ if (child.multiplier == MULTIPLIER_REPLICATED_NOT_LAST)
+ maxMultiplier = child.multiplier;
+
+ if (t.isPartitioned()) {
+ partitioned = true;
+
+ if (!t.isCollocated()) {
+ collocated = false;
+
+ int m = child.multiplier(true);
+
+ if (m > maxMultiplier) {
+ maxMultiplier = m;
+
+ if (maxMultiplier == MULTIPLIER_REPLICATED_NOT_LAST)
+ break;
+ }
+ }
+ }
+ }
+
+ type = Type.of(partitioned, collocated);
+ multiplier = maxMultiplier;
+ }
+ else {
+ assert upper != null;
+ assert childFilters == null;
+
+ // We are at table instance.
+ GridH2Table tbl = (GridH2Table)upper.childFilters[filter].getTable();
+
+ // Only partitioned tables will do distributed joins.
+ if (!tbl.isPartitioned()) {
+ type = Type.REPLICATED;
+ multiplier = MULTIPLIER_COLLOCATED;
+
+ return;
+ }
+
+ // If we are the first partitioned table in a join, then we are "base" for all the rest partitioned tables
+ // which will need to get remote result (if there is no affinity condition). Since this query is broadcasted
+ // to all the affinity nodes the "base" does not need to get remote results.
+ if (!upper.findPartitionedTableBefore(filter)) {
+ type = Type.PARTITIONED_COLLOCATED;
+ multiplier = MULTIPLIER_COLLOCATED;
+ }
+ else {
+ // It is enough to make sure that our previous join by affinity key is collocated, then we are
+ // collocated. If we at least have affinity key condition, then we do unicast which is cheaper.
+ switch (upper.joinedWithCollocated(filter)) {
+ case JOINED_WITH_COLLOCATED:
+ type = Type.PARTITIONED_COLLOCATED;
+ multiplier = MULTIPLIER_COLLOCATED;
+
+ break;
+
+ case HAS_AFFINITY_CONDITION:
+ type = Type.PARTITIONED_NOT_COLLOCATED;
+ multiplier = MULTIPLIER_UNICAST;
+
+ break;
+
+ case NONE:
+ type = Type.PARTITIONED_NOT_COLLOCATED;
+ multiplier = MULTIPLIER_BROADCAST;
+
+ break;
+
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ if (upper.previousReplicated(filter))
+ multiplier = MULTIPLIER_REPLICATED_NOT_LAST;
+ }
+ }
+
+ /**
+ * @param f Current filter.
+ * @return {@code true} If partitioned table was found.
+ */
+ private boolean findPartitionedTableBefore(int f) {
+ for (int i = 0; i < f; i++) {
+ GridH2CollocationModel child = child(i, true);
+
+ // The c can be null if it is not a GridH2Table and not a sub-query,
+ // it is a some kind of function table or anything else that considered replicated.
+ if (child != null && child.type(true).isPartitioned())
+ return true;
+ }
+
+ // We have to search globally in upper queries as well.
+ return upper != null && upper.findPartitionedTableBefore(filter);
+ }
+
+ /**
+ * @param f Current filter.
+ * @return {@code true} If previous table is REPLICATED.
+ */
+ private boolean previousReplicated(int f) {
+ if (f > 0 && child(f - 1, true).type(true) == Type.REPLICATED)
+ return true;
+
+ return upper != null && upper.previousReplicated(filter);
+ }
+
+ /**
+ * @param f Filter.
+ * @return Affinity join type.
+ */
+ private Affinity joinedWithCollocated(int f) {
+ TableFilter tf = childFilters[f];
+
+ GridH2Table tbl = (GridH2Table)tf.getTable();
+
+ if (validate) {
+ if (tbl.rowDescriptor().context().customAffinityMapper())
+ throw customAffinityError(tbl.spaceName());
+
+ if (F.isEmpty(tf.getIndexConditions())) {
+ throw new CacheException("Failed to prepare distributed join query: " +
+ "join condition does not use index [joinedCache=" + tbl.spaceName() +
+ ", plan=" + tf.getSelect().getPlanSQL() + ']');
+ }
+ }
+
+ IndexColumn affCol = tbl.getAffinityKeyColumn();
+
+ boolean affKeyCondFound = false;
+
+ if (affCol != null) {
+ ArrayList<IndexCondition> idxConditions = tf.getIndexConditions();
+
+ int affColId = affCol.column.getColumnId();
+
+ for (int i = 0; i < idxConditions.size(); i++) {
+ IndexCondition c = idxConditions.get(i);
+
+ int cmpType = c.getCompareType();
+
+ if ((cmpType == Comparison.EQUAL || cmpType == Comparison.EQUAL_NULL_SAFE) &&
+ c.getColumn().getColumnId() == affColId && c.isEvaluatable()) {
+ affKeyCondFound = true;
+
+ Expression exp = c.getExpression();
+
+ exp = exp.getNonAliasExpression();
+
+ if (exp instanceof ExpressionColumn) {
+ ExpressionColumn expCol = (ExpressionColumn)exp;
+
+ // This is one of our previous joins.
+ TableFilter prevJoin = expCol.getTableFilter();
+
+ if (prevJoin != null) {
+ GridH2CollocationModel cm = child(indexOf(prevJoin), true);
+
+ if (cm != null) {
+ Type t = cm.type(true);
+
+ if (t.isPartitioned() && t.isCollocated() && isAffinityColumn(prevJoin, expCol, validate))
+ return Affinity.JOINED_WITH_COLLOCATED;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return affKeyCondFound ? Affinity.HAS_AFFINITY_CONDITION : Affinity.NONE;
+ }
+
+ /**
+ * @param f Table filter.
+ * @return Index.
+ */
+ private int indexOf(TableFilter f) {
+ for (int i = 0; i < childFilters.length; i++) {
+ if (childFilters[i] == f)
+ return i;
+ }
+
+ throw new IllegalStateException();
+ }
+
+ /**
+ * @param f Table filter.
+ * @param expCol Expression column.
+ * @param validate Query validation flag.
+ * @return {@code true} It it is an affinity column.
+ */
+ private static boolean isAffinityColumn(TableFilter f, ExpressionColumn expCol, boolean validate) {
+ Column col = expCol.getColumn();
+
+ if (col == null)
+ return false;
+
+ Table t = col.getTable();
+
+ if (t.isView()) {
+ Query qry;
+
+ if (f.getIndex() != null)
+ qry = getSubQuery(f);
+ else
+ qry = GridSqlQueryParser.VIEW_QUERY.get((TableView)t);
+
+ return isAffinityColumn(qry, expCol, validate);
+ }
+
+ if (t instanceof GridH2Table) {
+ if (validate && ((GridH2Table)t).rowDescriptor().context().customAffinityMapper())
+ throw customAffinityError(((GridH2Table)t).spaceName());
+
+ IndexColumn affCol = ((GridH2Table)t).getAffinityKeyColumn();
+
+ return affCol != null && col.getColumnId() == affCol.column.getColumnId();
+ }
+
+ return false;
+ }
+
+ /**
+ * @param qry Query.
+ * @param expCol Expression column.
+ * @param validate Query validation flag.
+ * @return {@code true} It it is an affinity column.
+ */
+ private static boolean isAffinityColumn(Query qry, ExpressionColumn expCol, boolean validate) {
+ if (qry.isUnion()) {
+ SelectUnion union = (SelectUnion)qry;
+
+ return isAffinityColumn(union.getLeft(), expCol, validate) && isAffinityColumn(union.getRight(), expCol, validate);
+ }
+
+ Expression exp = qry.getExpressions().get(expCol.getColumn().getColumnId()).getNonAliasExpression();
+
+ if (exp instanceof ExpressionColumn) {
+ expCol = (ExpressionColumn)exp;
+
+ return isAffinityColumn(expCol.getTableFilter(), expCol, validate);
+ }
+
+ return false;
+ }
+
+ /**
+ * @return Multiplier.
+ */
+ public int calculateMultiplier() {
+ // We don't need multiplier for union here because it will be summarized in H2.
+ return multiplier(false);
+ }
+
+ /**
+ * @param withUnion With respect to union.
+ * @return Multiplier.
+ */
+ private int multiplier(boolean withUnion) {
+ calculate();
+
+ assert multiplier != 0;
+
+ if (withUnion && unions != null) {
+ int maxMultiplier = 0;
+
+ for (int i = 0; i < unions.size(); i++) {
+ int m = unions.get(i).multiplier(false);
+
+ if (m > maxMultiplier)
+ maxMultiplier = m;
+ }
+
+ return maxMultiplier;
+ }
+
+ return multiplier;
+ }
+
+ /**
+ * @param withUnion With respect to union.
+ * @return Type.
+ */
+ private Type type(boolean withUnion) {
+ calculate();
+
+ assert type != null;
+
+ if (withUnion && unions != null) {
+ Type left = unions.get(0).type(false);
+
+ for (int i = 1; i < unions.size(); i++) {
+ Type right = unions.get(i).type(false);
+
+ if (!left.isCollocated() || !right.isCollocated()) {
+ left = Type.PARTITIONED_NOT_COLLOCATED;
+
+ break;
+ }
+ else if (!left.isPartitioned() && !right.isPartitioned())
+ left = Type.REPLICATED;
+ else
+ left = Type.PARTITIONED_COLLOCATED;
+ }
+
+ return left;
+ }
+
+ return type;
+ }
+
+ /**
+ * @param i Index.
+ * @param create Create child if needed.
+ * @return Child collocation.
+ */
+ private GridH2CollocationModel child(int i, boolean create) {
+ GridH2CollocationModel child = children[i];
+
+ if (child == null && create && isChildTableOrView(i, null)) {
+ TableFilter f = childFilters[i];
+
+ if (f.getTable().isView()) {
+ if (f.getIndex() == null) {
+ // If we don't have view index yet, then we just creating empty model and it must be filled later.
+ child = createChildModel(this, i, null, true, validate);
+ }
+ else
+ child = buildCollocationModel(this, i, getSubQuery(f), null, validate);
+ }
+ else
+ child = createChildModel(this, i, null, false, validate);
+
+ assert child != null;
+ assert children[i] == child;
+ }
+
+ return child;
+ }
+
+ /**
+ * @param f Table filter.
+ * @return Sub-query.
+ */
+ private static Query getSubQuery(TableFilter f) {
+ return ((ViewIndex)f.getIndex()).getQuery();
+ }
+
+ /**
+ * @return Unions list.
+ */
+ private List<GridH2CollocationModel> getOrCreateUnions() {
+ if (unions == null) {
+ unions = new ArrayList<>(4);
+
+ unions.add(this);
+ }
+
+ return unions;
+ }
+
+ /**
+ * @param qctx Query context.
+ * @param info Sub-query info.
+ * @param filters Filters.
+ * @param filter Filter.
+ * @param validate Query validation flag.
+ * @return Collocation.
+ */
+ public static GridH2CollocationModel buildCollocationModel(GridH2QueryContext qctx, SubQueryInfo info,
+ TableFilter[] filters, int filter, boolean validate) {
+ GridH2CollocationModel cm;
+
+ if (info != null) {
+ // Go up until we reach the root query.
+ cm = buildCollocationModel(qctx, info.getUpper(), info.getFilters(), info.getFilter(), validate);
+ }
+ else {
+ // We are at the root query.
+ cm = qctx.queryCollocationModel();
+
+ if (cm == null) {
+ cm = createChildModel(null, -1, null, true, validate);
+
+ qctx.queryCollocationModel(cm);
+ }
+ }
+
+ assert cm.view;
+
+ Select select = filters[0].getSelect();
+
+ // Handle union. We have to rely on fact that select will be the same on uppermost select.
+ // For sub-queries we will drop collocation models, so that they will be recalculated anyways.
+ if (cm.select != null && cm.select != select) {
+ List<GridH2CollocationModel> unions = cm.getOrCreateUnions();
+
+ // Try to find this select in existing unions.
+ // Start with 1 because at 0 it always will be c.
+ for (int i = 1; i < unions.size(); i++) {
+ GridH2CollocationModel u = unions.get(i);
+
+ if (u.select == select) {
+ cm = u;
+
+ break;
+ }
+ }
+
+ // Nothing was found, need to create new child in union.
+ if (cm.select != select)
+ cm = createChildModel(cm.upper, cm.filter, unions, true, validate);
+ }
+
+ cm.childFilters(filters);
+
+ return cm.child(filter, true);
+ }
+
+ /**
+ * @param qry Query.
+ * @return {@code true} If the query is collocated.
+ */
+ public static boolean isCollocated(Query qry) {
+ GridH2CollocationModel mdl = buildCollocationModel(null, -1, qry, null, true);
+
+ Type type = mdl.type(true);
+
+ if (!type.isCollocated() && mdl.multiplier == MULTIPLIER_REPLICATED_NOT_LAST)
+ throw new CacheException("Failed to execute query: for distributed join " +
+ "all REPLICATED caches must be at the end of the joined tables list.");
+
+ return type.isCollocated();
+ }
+
+ /**
+ * @param upper Upper.
+ * @param filter Filter.
+ * @param qry Query.
+ * @param unions Unions.
+ * @param validate Query validation flag.
+ * @return Built model.
+ */
+ private static GridH2CollocationModel buildCollocationModel(GridH2CollocationModel upper,
+ int filter,
+ Query qry,
+ List<GridH2CollocationModel> unions,
+ boolean validate) {
+ if (qry.isUnion()) {
+ if (unions == null)
+ unions = new ArrayList<>();
+
+ SelectUnion union = (SelectUnion)qry;
+
+ GridH2CollocationModel left = buildCollocationModel(upper, filter, union.getLeft(), unions, validate);
+ GridH2CollocationModel right = buildCollocationModel(upper, filter, union.getRight(), unions, validate);
+
+ assert left != null;
+ assert right != null;
+
+ return upper != null ? upper : left;
+ }
+
+ Select select = (Select)qry;
+
+ List<TableFilter> list = new ArrayList<>();
+
+ for (TableFilter f = select.getTopTableFilter(); f != null; f = f.getJoin())
+ list.add(f);
+
+ TableFilter[] filters = list.toArray(new TableFilter[list.size()]);
+
+ GridH2CollocationModel cm = createChildModel(upper, filter, unions, true, validate);
+
+ cm.childFilters(filters);
+
+ for (int i = 0; i < filters.length; i++) {
+ TableFilter f = filters[i];
+
+ if (f.getTable().isView())
+ buildCollocationModel(cm, i, getSubQuery(f), null, validate);
+ else if (f.getTable() instanceof GridH2Table)
+ createChildModel(cm, i, null, false, validate);
+ }
+
+ return upper != null ? upper : cm;
+ }
+
+ /**
+ * @param cacheName Cache name.
+ * @return Error.
+ */
+ private static CacheException customAffinityError(String cacheName) {
+ return new CacheException("Failed to prepare distributed join query: can not use distributed joins for cache " +
+ "with custom AffinityKeyMapper configured. " +
+ "Please use AffinityKeyMapped annotation instead [cache=" + cacheName + ']');
+ }
+
+ /**
+ * Collocation type.
+ */
+ private enum Type {
+ /** */
+ PARTITIONED_COLLOCATED(true, true),
+
+ /** */
+ PARTITIONED_NOT_COLLOCATED(true, false),
+
+ /** */
+ REPLICATED(false, true);
+
+ /** */
+ private final boolean partitioned;
+
+ /** */
+ private final boolean collocated;
+
+ /**
+ * @param partitioned Partitioned.
+ * @param collocated Collocated.
+ */
+ Type(boolean partitioned, boolean collocated) {
+ this.partitioned = partitioned;
+ this.collocated = collocated;
+ }
+
+ /**
+ * @return {@code true} If partitioned.
+ */
+ public boolean isPartitioned() {
+ return partitioned;
+ }
+
+ /**
+ * @return {@code true} If collocated.
+ */
+ public boolean isCollocated() {
+ return collocated;
+ }
+
+ /**
+ * @param partitioned Partitioned.
+ * @param collocated Collocated.
+ * @return Type.
+ */
+ static Type of(boolean partitioned, boolean collocated) {
+ if (collocated)
+ return partitioned ? Type.PARTITIONED_COLLOCATED : Type.REPLICATED;
+
+ assert partitioned;
+
+ return Type.PARTITIONED_NOT_COLLOCATED;
+ }
+ }
+
+ /**
+ * Affinity of a table relative to previous joined tables.
+ */
+ private enum Affinity {
+ /** */
+ NONE,
+
+ /** */
+ HAS_AFFINITY_CONDITION,
+
+ /** */
+ JOINED_WITH_COLLOCATED
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Cursor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Cursor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Cursor.java
index a2f60c4..66d5736 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Cursor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2Cursor.java
@@ -28,23 +28,44 @@ import org.h2.result.SearchRow;
*/
public class GridH2Cursor implements Cursor {
/** */
- private Iterator<GridH2Row> iter;
+ public static final Cursor EMPTY = new Cursor() {
+ @Override public Row get() {
+ return null;
+ }
+
+ @Override public SearchRow getSearchRow() {
+ return null;
+ }
+
+ @Override public boolean next() {
+ return false;
+ }
+
+ @Override public boolean previous() {
+ return false;
+ }
+ };
/** */
- private Row row;
+ protected Iterator<? extends Row> iter;
+
+ /** */
+ protected Row cur;
/**
* Constructor.
*
* @param iter Rows iterator.
*/
- public GridH2Cursor(Iterator<GridH2Row> iter) {
+ public GridH2Cursor(Iterator<? extends Row> iter) {
+ assert iter != null;
+
this.iter = iter;
}
/** {@inheritDoc} */
@Override public Row get() {
- return row;
+ return cur;
}
/** {@inheritDoc} */
@@ -54,12 +75,9 @@ public class GridH2Cursor implements Cursor {
/** {@inheritDoc} */
@Override public boolean next() {
- row = null;
-
- if (iter.hasNext())
- row = iter.next();
+ cur = iter.hasNext() ? iter.next() : null;
- return row != null;
+ return cur != null;
}
/** {@inheritDoc} */
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2DefaultTableEngine.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2DefaultTableEngine.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2DefaultTableEngine.java
new file mode 100644
index 0000000..f53f1b3
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2DefaultTableEngine.java
@@ -0,0 +1,38 @@
+/*
+ * 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.opt;
+
+import org.h2.api.TableEngine;
+import org.h2.command.ddl.CreateTableData;
+import org.h2.table.RegularTable;
+import org.h2.table.Table;
+
+/**
+ * Default table engine.
+ */
+public class GridH2DefaultTableEngine implements TableEngine {
+ /** {@inheritDoc} */
+ @Override public Table createTable(CreateTableData data) {
+ assert !data.persistData && !data.persistIndexes;
+
+ if (data.isHidden && data.id == 0 && "SYS".equals(data.tableName))
+ return new GridH2MetaTable(data);
+
+ return new RegularTable(data);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
index fbf7c7c..c29239f 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/opt/GridH2IndexBase.java
@@ -17,49 +17,164 @@
package org.apache.ignite.internal.processors.query.h2.opt;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentNavigableMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import javax.cache.CacheException;
+import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteInterruptedException;
+import org.apache.ignite.IgniteLogger;
+import org.apache.ignite.cluster.ClusterNode;
+import org.apache.ignite.internal.GridKernalContext;
+import org.apache.ignite.internal.GridTopic;
+import org.apache.ignite.internal.IgniteInterruptedCheckedException;
+import org.apache.ignite.internal.managers.communication.GridIoPolicy;
+import org.apache.ignite.internal.managers.communication.GridMessageListener;
+import org.apache.ignite.internal.processors.cache.GridCacheContext;
+import org.apache.ignite.internal.processors.cache.distributed.dht.GridReservable;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2IndexRangeRequest;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2IndexRangeResponse;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2RowMessage;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2RowRange;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2RowRangeBounds;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2ValueMessage;
+import org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2ValueMessageFactory;
+import org.apache.ignite.internal.util.GridSpinBusyLock;
import org.apache.ignite.internal.util.lang.GridFilteredIterator;
+import org.apache.ignite.internal.util.typedef.CIX2;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteBiPredicate;
+import org.apache.ignite.lang.IgniteBiTuple;
+import org.apache.ignite.logger.NullLogger;
+import org.apache.ignite.plugin.extensions.communication.Message;
import org.apache.ignite.spi.indexing.IndexingQueryFilter;
import org.h2.engine.Session;
import org.h2.index.BaseIndex;
+import org.h2.index.Cursor;
+import org.h2.index.IndexCondition;
+import org.h2.index.IndexLookupBatch;
+import org.h2.index.ViewIndex;
import org.h2.message.DbException;
import org.h2.result.Row;
import org.h2.result.SearchRow;
-import org.h2.result.SortOrder;
+import org.h2.table.IndexColumn;
+import org.h2.table.TableFilter;
+import org.h2.util.DoneFuture;
import org.h2.value.Value;
+import org.h2.value.ValueNull;
import org.jetbrains.annotations.Nullable;
+import static java.util.Collections.emptyIterator;
+import static java.util.Collections.singletonList;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.KEY_COL;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2AbstractKeyValueRow.VAL_COL;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2CollocationModel.buildCollocationModel;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.MAP;
+import static org.apache.ignite.internal.processors.query.h2.opt.GridH2QueryType.PREPARE;
+import static org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2IndexRangeResponse.STATUS_ERROR;
+import static org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2IndexRangeResponse.STATUS_NOT_FOUND;
+import static org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2IndexRangeResponse.STATUS_OK;
+import static org.apache.ignite.internal.processors.query.h2.twostep.msg.GridH2RowRangeBounds.rangeBounds;
+import static org.h2.result.Row.MEMORY_CALCULATE;
+
/**
* Index base.
*/
public abstract class GridH2IndexBase extends BaseIndex {
/** */
- protected static final ThreadLocal<IndexingQueryFilter> filters = new ThreadLocal<>();
+ private static final Object EXPLICIT_NULL = new Object();
+
+ /** */
+ private static final AtomicLong idxIdGen = new AtomicLong();
+
+ /** */
+ protected final long idxId = idxIdGen.incrementAndGet();
+
+ /** */
+ private final ThreadLocal<Object> snapshot = new ThreadLocal<>();
+
+ /** */
+ private Object msgTopic;
+
+ /** */
+ private GridMessageListener msgLsnr;
/** */
- protected final int keyCol;
+ private IgniteLogger log;
/** */
- protected final int valCol;
+ private final CIX2<ClusterNode,Message> locNodeHnd = new CIX2<ClusterNode,Message>() {
+ @Override public void applyx(ClusterNode clusterNode, Message msg) throws IgniteCheckedException {
+ onMessage0(clusterNode.id(), msg);
+ }
+ };
/**
- * @param keyCol Key column.
- * @param valCol Value column.
+ * @param tbl Table.
*/
- protected GridH2IndexBase(int keyCol, int valCol) {
- this.keyCol = keyCol;
- this.valCol = valCol;
+ protected final void initDistributedJoinMessaging(GridH2Table tbl) {
+ final GridH2RowDescriptor desc = tbl.rowDescriptor();
+
+ if (desc != null && desc.context() != null) {
+ GridKernalContext ctx = desc.context().kernalContext();
+
+ log = ctx.log(getClass());
+
+ msgTopic = new IgniteBiTuple<>(GridTopic.TOPIC_QUERY, tbl.identifier() + '.' + getName());
+
+ msgLsnr = new GridMessageListener() {
+ @Override public void onMessage(UUID nodeId, Object msg) {
+ GridSpinBusyLock l = desc.indexing().busyLock();
+
+ if (!l.enterBusy())
+ return;
+
+ try {
+ onMessage0(nodeId, msg);
+ }
+ finally {
+ l.leaveBusy();
+ }
+ }
+ };
+
+ ctx.io().addMessageListener(msgTopic, msgLsnr);
+ }
+ else {
+ msgTopic = null;
+ msgLsnr = null;
+ log = new NullLogger();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public final void close(Session ses) {
+ // No-op. Actual index destruction must happen in method destroy.
}
/**
- * Sets key filters for current thread.
- *
- * @param fs Filters.
+ * Attempts to destroys index and release all the resources.
+ * We use this method instead of {@link #close(Session)} because that method
+ * is used by H2 internally.
*/
- public static void setFiltersForThread(IndexingQueryFilter fs) {
- filters.set(fs);
+ public void destroy() {
+ if (msgLsnr != null)
+ kernalContext().io().removeMessageListener(msgTopic, msgLsnr);
}
/**
@@ -92,71 +207,121 @@ public abstract class GridH2IndexBase extends BaseIndex {
* Takes or sets existing snapshot to be used in current thread.
*
* @param s Optional existing snapshot to use.
+ * @param qctx Query context.
* @return Snapshot.
*/
- public Object takeSnapshot(@Nullable Object s) {
+ public final Object takeSnapshot(@Nullable Object s, GridH2QueryContext qctx) {
+ assert snapshot.get() == null;
+
+ if (s == null)
+ s = doTakeSnapshot();
+
+ if (s != null) {
+ if (s instanceof GridReservable && !((GridReservable)s).reserve())
+ return null;
+
+ snapshot.set(s);
+
+ if (qctx != null)
+ qctx.putSnapshot(idxId, s);
+ }
+
return s;
}
/**
- * Releases snapshot for current thread.
+ * @param ses Session.
*/
- public void releaseSnapshot() {
- // No-op.
+ private static void clearViewIndexCache(Session ses) {
+ Map<Object,ViewIndex> viewIdxCache = ses.getViewIndexCache(true);
+
+ if (!viewIdxCache.isEmpty())
+ viewIdxCache.clear();
}
- /** {@inheritDoc} */
- @Override public int compareRows(SearchRow rowData, SearchRow compare) {
- if (rowData == compare)
- return 0;
+ /**
+ * @param ses Session.
+ * @param filters All joined table filters.
+ * @param filter Current filter.
+ * @return Multiplier.
+ */
+ public int getDistributedMultiplier(Session ses, TableFilter[] filters, int filter) {
+ GridH2QueryContext qctx = GridH2QueryContext.get();
- for (int i = 0, len = indexColumns.length; i < len; i++) {
- int index = columnIds[i];
+ // We do complex optimizations with respect to distributed joins only on prepare stage
+ // because on run stage reordering of joined tables by Optimizer is explicitly disabled
+ // and thus multiplier will be always the same, so it will not affect choice of index.
+ // Query expressions can not be distributed as well.
+ if (qctx == null || qctx.type() != PREPARE || !qctx.distributedJoins() || ses.isPreparingQueryExpression())
+ return GridH2CollocationModel.MULTIPLIER_COLLOCATED;
- Value v1 = rowData.getValue(index);
- Value v2 = compare.getValue(index);
+ // We have to clear this cache because normally sub-query plan cost does not depend on anything
+ // other than index condition masks and sort order, but in our case it can depend on order
+ // of previous table filters.
+ clearViewIndexCache(ses);
- if (v1 == null || v2 == null)
- return 0;
+ assert filters != null;
- int c = compareValues(v1, v2, indexColumns[i].sortType);
+ GridH2CollocationModel c = buildCollocationModel(qctx, ses.getSubQueryInfo(), filters, filter, false);
- if (c != 0)
- return c;
- }
- return 0;
+ return c.calculateMultiplier();
+ }
+
+ /** {@inheritDoc} */
+ @Override public GridH2Table getTable() {
+ return (GridH2Table)super.getTable();
+ }
+
+ /**
+ * Takes and returns actual snapshot or {@code null} if snapshots are not supported.
+ *
+ * @return Snapshot or {@code null}.
+ */
+ @Nullable protected abstract Object doTakeSnapshot();
+
+ /**
+ * @return Thread local snapshot.
+ */
+ @SuppressWarnings("unchecked")
+ protected <T> T threadLocalSnapshot() {
+ return (T)snapshot.get();
}
/**
- * @param a First value.
- * @param b Second value.
- * @param sortType Sort type.
- * @return Comparison result.
+ * Releases snapshot for current thread.
*/
- private int compareValues(Value a, Value b, int sortType) {
- if (a == b)
- return 0;
+ public void releaseSnapshot() {
+ Object s = snapshot.get();
+
+ assert s != null;
- int comp = table.compareTypeSave(a, b);
+ snapshot.remove();
- if ((sortType & SortOrder.DESCENDING) != 0)
- comp = -comp;
+ if (s instanceof GridReservable)
+ ((GridReservable)s).release();
- return comp;
+ if (s instanceof AutoCloseable)
+ U.closeQuiet((AutoCloseable)s);
}
/**
* Filters rows from expired ones and using predicate.
*
* @param iter Iterator over rows.
+ * @param filter Optional filter.
* @return Filtered iterator.
*/
- protected Iterator<GridH2Row> filter(Iterator<GridH2Row> iter) {
- IgniteBiPredicate<Object, Object> p = null;
+ protected Iterator<GridH2Row> filter(Iterator<GridH2Row> iter, IndexingQueryFilter filter) {
+ return new FilteringIterator(iter, U.currentTimeMillis(), filter, getTable().spaceName());
+ }
- IndexingQueryFilter f = filters.get();
+ /**
+ * @return Filter for currently running query or {@code null} if none.
+ */
+ protected static IndexingQueryFilter threadLocalFilter() {
+ GridH2QueryContext qctx = GridH2QueryContext.get();
- return new FilteringIterator(iter, U.currentTimeMillis(), f);
+ return qctx != null ? qctx.filter() : null;
}
/** {@inheritDoc} */
@@ -194,10 +359,1125 @@ public abstract class GridH2IndexBase extends BaseIndex {
return false;
}
+ /** {@inheritDoc} */
+ @Override public IndexLookupBatch createLookupBatch(TableFilter filter) {
+ GridH2QueryContext qctx = GridH2QueryContext.get();
+
+ if (qctx == null || !qctx.distributedJoins() || !getTable().isPartitioned())
+ return null;
+
+ IndexColumn affCol = getTable().getAffinityKeyColumn();
+
+ int affColId;
+ boolean ucast;
+
+ if (affCol != null) {
+ affColId = affCol.column.getColumnId();
+ int[] masks = filter.getMasks();
+ ucast = masks != null && masks[affColId] == IndexCondition.EQUALITY;
+ }
+ else {
+ affColId = -1;
+ ucast = false;
+ }
+
+ GridCacheContext<?,?> cctx = getTable().rowDescriptor().context();
+
+ return new DistributedLookupBatch(cctx, ucast, affColId);
+ }
+
+ /**
+ * @param nodes Nodes.
+ * @param msg Message.
+ */
+ private void send(Collection<ClusterNode> nodes, Message msg) {
+ if (!getTable().rowDescriptor().indexing().send(msgTopic,
+ -1,
+ nodes,
+ msg,
+ null,
+ locNodeHnd,
+ GridIoPolicy.IDX_POOL,
+ false))
+ throw new GridH2RetryException("Failed to send message to nodes: " + nodes + ".");
+ }
+
+ /**
+ * @param nodeId Source node ID.
+ * @param msg Message.
+ */
+ private void onMessage0(UUID nodeId, Object msg) {
+ ClusterNode node = kernalContext().discovery().node(nodeId);
+
+ if (node == null)
+ return;
+
+ try {
+ if (msg instanceof GridH2IndexRangeRequest)
+ onIndexRangeRequest(node, (GridH2IndexRangeRequest)msg);
+ else if (msg instanceof GridH2IndexRangeResponse)
+ onIndexRangeResponse(node, (GridH2IndexRangeResponse)msg);
+ }
+ catch (Throwable th) {
+ U.error(log, "Failed to handle message[nodeId=" + nodeId + ", msg=" + msg + "]", th);
+
+ if (th instanceof Error)
+ throw th;
+ }
+ }
+
+ /**
+ * @return Kernal context.
+ */
+ private GridKernalContext kernalContext() {
+ return getTable().rowDescriptor().context().kernalContext();
+ }
+
+ /**
+ * @param node Requesting node.
+ * @param msg Request message.
+ */
+ private void onIndexRangeRequest(ClusterNode node, GridH2IndexRangeRequest msg) {
+ GridH2QueryContext qctx = GridH2QueryContext.get(kernalContext().localNodeId(),
+ msg.originNodeId(),
+ msg.queryId(),
+ MAP);
+
+ GridH2IndexRangeResponse res = new GridH2IndexRangeResponse();
+
+ res.originNodeId(msg.originNodeId());
+ res.queryId(msg.queryId());
+ res.batchLookupId(msg.batchLookupId());
+
+ if (qctx == null)
+ res.status(STATUS_NOT_FOUND);
+ else {
+ try {
+ RangeSource src;
+
+ if (msg.bounds() != null) {
+ // This is the first request containing all the search rows.
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> snapshot0 = qctx.getSnapshot(idxId);
+
+ assert !msg.bounds().isEmpty() : "empty bounds";
+
+ src = new RangeSource(msg.bounds(), snapshot0, qctx.filter());
+ }
+ else {
+ // This is request to fetch next portion of data.
+ src = qctx.getSource(node.id(), msg.batchLookupId());
+
+ assert src != null;
+ }
+
+ List<GridH2RowRange> ranges = new ArrayList<>();
+
+ int maxRows = qctx.pageSize();
+
+ assert maxRows > 0 : maxRows;
+
+ while (maxRows > 0) {
+ GridH2RowRange range = src.next(maxRows);
+
+ if (range == null)
+ break;
+
+ ranges.add(range);
+
+ if (range.rows() != null)
+ maxRows -= range.rows().size();
+ }
+
+ if (src.hasMoreRows()) {
+ // Save source for future fetches.
+ if (msg.bounds() != null)
+ qctx.putSource(node.id(), msg.batchLookupId(), src);
+ }
+ else if (msg.bounds() == null) {
+ // Drop saved source.
+ qctx.putSource(node.id(), msg.batchLookupId(), null);
+ }
+
+ assert !ranges.isEmpty();
+
+ res.ranges(ranges);
+ res.status(STATUS_OK);
+ }
+ catch (Throwable th) {
+ U.error(log, "Failed to process request: " + msg, th);
+
+ res.error(th.getClass() + ": " + th.getMessage());
+ res.status(STATUS_ERROR);
+ }
+ }
+
+ send(singletonList(node), res);
+ }
+
+ /**
+ * @param node Responded node.
+ * @param msg Response message.
+ */
+ private void onIndexRangeResponse(ClusterNode node, GridH2IndexRangeResponse msg) {
+ GridH2QueryContext qctx = GridH2QueryContext.get(kernalContext().localNodeId(),
+ msg.originNodeId(), msg.queryId(), MAP);
+
+ if (qctx == null)
+ return;
+
+ Map<ClusterNode, RangeStream> streams = qctx.getStreams(msg.batchLookupId());
+
+ if (streams == null)
+ return;
+
+ RangeStream stream = streams.get(node);
+
+ assert stream != null;
+
+ stream.onResponse(msg);
+ }
+
+ /**
+ * @param v1 First value.
+ * @param v2 Second value.
+ * @return {@code true} If they equal.
+ */
+ private boolean equal(Value v1, Value v2) {
+ return v1 == v2 || (v1 != null && v2 != null && v1.compareTypeSafe(v2, getDatabase().getCompareMode()) == 0);
+ }
+
+ /**
+ * @param qctx Query context.
+ * @param batchLookupId Batch lookup ID.
+ * @return Index range request.
+ */
+ private static GridH2IndexRangeRequest createRequest(GridH2QueryContext qctx, int batchLookupId) {
+ GridH2IndexRangeRequest req = new GridH2IndexRangeRequest();
+
+ req.originNodeId(qctx.originNodeId());
+ req.queryId(qctx.queryId());
+ req.batchLookupId(batchLookupId);
+
+ return req;
+ }
+
+ /**
+ * @param qctx Query context.
+ * @param cctx Cache context.
+ * @return Collection of nodes for broadcasting.
+ */
+ private List<ClusterNode> broadcastNodes(GridH2QueryContext qctx, GridCacheContext<?,?> cctx) {
+ Map<UUID, int[]> partMap = qctx.partitionsMap();
+
+ List<ClusterNode> res;
+
+ if (partMap == null)
+ res = new ArrayList<>(CU.affinityNodes(cctx, qctx.topologyVersion()));
+ else {
+ res = new ArrayList<>(partMap.size());
+
+ GridKernalContext ctx = kernalContext();
+
+ for (UUID nodeId : partMap.keySet()) {
+ ClusterNode node = ctx.discovery().node(nodeId);
+
+ if (node == null)
+ throw new GridH2RetryException("Failed to find node.");
+
+ res.add(node);
+ }
+ }
+
+ if (F.isEmpty(res))
+ throw new GridH2RetryException("Failed to collect affinity nodes.");
+
+ return res;
+ }
+
+ /**
+ * @param cctx Cache context.
+ * @param qctx Query context.
+ * @param affKeyObj Affinity key.
+ * @return Cluster nodes or {@code null} if affinity key is a null value.
+ */
+ private ClusterNode rangeNode(GridCacheContext<?,?> cctx, GridH2QueryContext qctx, Object affKeyObj) {
+ assert affKeyObj != null && affKeyObj != EXPLICIT_NULL : affKeyObj;
+
+ ClusterNode node;
+
+ if (qctx.partitionsMap() != null) {
+ // If we have explicit partitions map, we have to use it to calculate affinity node.
+ UUID nodeId = qctx.nodeForPartition(cctx.affinity().partition(affKeyObj), cctx);
+
+ node = cctx.discovery().node(nodeId);
+ }
+ else // Get primary node for current topology version.
+ node = cctx.affinity().primary(affKeyObj, qctx.topologyVersion());
+
+ if (node == null) // Node was not found, probably topology changed and we need to retry the whole query.
+ throw new GridH2RetryException("Failed to find node.");
+
+ return node;
+ }
+
+ /**
+ * @param row Row.
+ * @return Row message.
+ */
+ private GridH2RowMessage toRowMessage(Row row) {
+ if (row == null)
+ return null;
+
+ int cols = row.getColumnCount();
+
+ assert cols > 0 : cols;
+
+ List<GridH2ValueMessage> vals = new ArrayList<>(cols);
+
+ for (int i = 0; i < cols; i++) {
+ try {
+ vals.add(GridH2ValueMessageFactory.toMessage(row.getValue(i)));
+ }
+ catch (IgniteCheckedException e) {
+ throw new CacheException(e);
+ }
+ }
+
+ GridH2RowMessage res = new GridH2RowMessage();
+
+ res.values(vals);
+
+ return res;
+ }
+
+ /**
+ * @param msg Row message.
+ * @return Search row.
+ */
+ private SearchRow toSearchRow(GridH2RowMessage msg) {
+ if (msg == null)
+ return null;
+
+ GridKernalContext ctx = kernalContext();
+
+ Value[] vals = new Value[getTable().getColumns().length];
+
+ assert vals.length > 0;
+
+ List<GridH2ValueMessage> msgVals = msg.values();
+
+ for (int i = 0; i < indexColumns.length; i++) {
+ if (i >= msgVals.size())
+ continue;
+
+ try {
+ vals[indexColumns[i].column.getColumnId()] = msgVals.get(i).value(ctx);
+ }
+ catch (IgniteCheckedException e) {
+ throw new CacheException(e);
+ }
+ }
+
+ return database.createRow(vals, MEMORY_CALCULATE);
+ }
+
+ /**
+ * @param row Search row.
+ * @return Row message.
+ */
+ private GridH2RowMessage toSearchRowMessage(SearchRow row) {
+ if (row == null)
+ return null;
+
+ List<GridH2ValueMessage> vals = new ArrayList<>(indexColumns.length);
+
+ for (IndexColumn idxCol : indexColumns) {
+ Value val = row.getValue(idxCol.column.getColumnId());
+
+ if (val == null)
+ break;
+
+ try {
+ vals.add(GridH2ValueMessageFactory.toMessage(val));
+ }
+ catch (IgniteCheckedException e) {
+ throw new CacheException(e);
+ }
+ }
+
+ GridH2RowMessage res = new GridH2RowMessage();
+
+ res.values(vals);
+
+ return res;
+ }
+
+ /**
+ * @param msg Message.
+ * @return Row.
+ */
+ private Row toRow(GridH2RowMessage msg) {
+ if (msg == null)
+ return null;
+
+ GridKernalContext ctx = kernalContext();
+
+ List<GridH2ValueMessage> vals = msg.values();
+
+ assert !F.isEmpty(vals) : vals;
+
+ Value[] vals0 = new Value[vals.size()];
+
+ for (int i = 0; i < vals0.length; i++) {
+ try {
+ vals0[i] = vals.get(i).value(ctx);
+ }
+ catch (IgniteCheckedException e) {
+ throw new CacheException(e);
+ }
+ }
+
+ return database.createRow(vals0, MEMORY_CALCULATE);
+ }
+
+ /**
+ * Simple cursor from a single node.
+ */
+ private static class UnicastCursor implements Cursor {
+ /** */
+ final int rangeId;
+
+ /** */
+ RangeStream stream;
+
+ /**
+ * @param rangeId Range ID.
+ * @param nodes Remote nodes.
+ * @param rangeStreams Range streams.
+ */
+ private UnicastCursor(int rangeId, Collection<ClusterNode> nodes, Map<ClusterNode,RangeStream> rangeStreams) {
+ assert nodes.size() == 1;
+
+ this.rangeId = rangeId;
+ this.stream = rangeStreams.get(F.first(nodes));
+
+ assert stream != null;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean next() {
+ return stream.next(rangeId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public Row get() {
+ return stream.get(rangeId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public SearchRow getSearchRow() {
+ return get();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean previous() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Merge cursor from multiple nodes.
+ */
+ private class BroadcastCursor implements Cursor, Comparator<RangeStream> {
+ /** */
+ final int rangeId;
+
+ /** */
+ final RangeStream[] streams;
+
+ /** */
+ boolean first = true;
+
+ /** */
+ int off;
+
+ /**
+ * @param rangeId Range ID.
+ * @param nodes Remote nodes.
+ * @param rangeStreams Range streams.
+ */
+ private BroadcastCursor(int rangeId, Collection<ClusterNode> nodes, Map<ClusterNode,RangeStream> rangeStreams) {
+ assert nodes.size() > 1;
+
+ this.rangeId = rangeId;
+
+ streams = new RangeStream[nodes.size()];
+
+ int i = 0;
+
+ for (ClusterNode node : nodes) {
+ RangeStream stream = rangeStreams.get(node);
+
+ assert stream != null;
+
+ streams[i++] = stream;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override public int compare(RangeStream o1, RangeStream o2) {
+ if (o1 == o2)
+ return 0;
+
+ // Nulls are at the beginning of array.
+ if (o1 == null)
+ return -1;
+
+ if (o2 == null)
+ return 1;
+
+ return compareRows(o1.get(rangeId), o2.get(rangeId));
+ }
+
+ /**
+ * Try to fetch the first row.
+ *
+ * @return {@code true} If we were able to find at least one row.
+ */
+ private boolean goFirst() {
+ // Fetch first row from all the streams and sort them.
+ for (int i = 0; i < streams.length; i++) {
+ if (!streams[i].next(rangeId)) {
+ streams[i] = null;
+ off++; // After sorting this offset will cut off all null elements at the beginning of array.
+ }
+ }
+
+ if (off == streams.length)
+ return false;
+
+ Arrays.sort(streams, this);
+
+ return true;
+ }
+
+ /**
+ * Fetch next row.
+ *
+ * @return {@code true} If we were able to find at least one row.
+ */
+ private boolean goNext() {
+ assert off != streams.length;
+
+ if (!streams[off].next(rangeId)) {
+ // Next row from current min stream was not found -> nullify that stream and bump offset forward.
+ streams[off] = null;
+
+ return ++off != streams.length;
+ }
+
+ // Bubble up current min stream with respect to fetched row to achieve correct sort order of streams.
+ for (int i = off, last = streams.length - 1; i < last; i++) {
+ if (compareRows(streams[i].get(rangeId), streams[i + 1].get(rangeId)) <= 0)
+ break;
+
+ U.swap(streams, i, i + 1);
+ }
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean next() {
+ if (first) {
+ first = false;
+
+ return goFirst();
+ }
+
+ return goNext();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Row get() {
+ return streams[off].get(rangeId);
+ }
+
+ /** {@inheritDoc} */
+ @Override public SearchRow getSearchRow() {
+ return get();
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean previous() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Index lookup batch.
+ */
+ private class DistributedLookupBatch implements IndexLookupBatch {
+ /** */
+ final GridCacheContext<?,?> cctx;
+
+ /** */
+ final boolean ucast;
+
+ /** */
+ final int affColId;
+
+ /** */
+ GridH2QueryContext qctx;
+
+ /** */
+ int batchLookupId;
+
+ /** */
+ Map<ClusterNode, RangeStream> rangeStreams = Collections.emptyMap();
+
+ /** */
+ List<ClusterNode> broadcastNodes;
+
+ /** */
+ List<Future<Cursor>> res = Collections.emptyList();
+
+ /** */
+ boolean batchFull;
+
+ /** */
+ boolean findCalled;
+
+ /**
+ * @param cctx Cache Cache context.
+ * @param ucast Unicast or broadcast query.
+ * @param affColId Affinity column ID.
+ */
+ private DistributedLookupBatch(GridCacheContext<?,?> cctx, boolean ucast, int affColId) {
+ this.cctx = cctx;
+ this.ucast = ucast;
+ this.affColId = affColId;
+ }
+
+ /**
+ * @param firstRow First row.
+ * @param lastRow Last row.
+ * @return Affinity key or {@code null}.
+ */
+ private Object getAffinityKey(SearchRow firstRow, SearchRow lastRow) {
+ if (firstRow == null || lastRow == null)
+ return null;
+
+ Value affKeyFirst = firstRow.getValue(affColId);
+ Value affKeyLast = lastRow.getValue(affColId);
+
+ if (affKeyFirst != null && equal(affKeyFirst, affKeyLast))
+ return affKeyFirst == ValueNull.INSTANCE ? EXPLICIT_NULL : affKeyFirst.getObject();
+
+ if (affColId == KEY_COL)
+ return null;
+
+ // Try to extract affinity key from primary key.
+ Value pkFirst = firstRow.getValue(KEY_COL);
+ Value pkLast = lastRow.getValue(KEY_COL);
+
+ if (pkFirst == ValueNull.INSTANCE || pkLast == ValueNull.INSTANCE)
+ return EXPLICIT_NULL;
+
+ if (pkFirst == null || pkLast == null || !equal(pkFirst, pkLast))
+ return null;
+
+ Object pkAffKeyFirst = cctx.affinity().affinityKey(pkFirst.getObject());
+ Object pkAffKeyLast = cctx.affinity().affinityKey(pkLast.getObject());
+
+ if (pkAffKeyFirst == null || pkAffKeyLast == null)
+ throw new CacheException("Cache key without affinity key.");
+
+ if (pkAffKeyFirst.equals(pkAffKeyLast))
+ return pkAffKeyFirst;
+
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @SuppressWarnings("ForLoopReplaceableByForEach")
+ @Override public boolean addSearchRows(SearchRow firstRow, SearchRow lastRow) {
+ if (qctx == null || findCalled) {
+ if (qctx == null) {
+ // It is the first call after query begin (may be after reuse),
+ // reinitialize query context and result.
+ qctx = GridH2QueryContext.get();
+ res = new ArrayList<>();
+
+ assert qctx != null;
+ assert !findCalled;
+ }
+ else {
+ // Cleanup after the previous lookup phase.
+ assert batchLookupId != 0;
+
+ findCalled = false;
+ qctx.putStreams(batchLookupId, null);
+ res.clear();
+ }
+
+ // Reinitialize for the next lookup phase.
+ batchLookupId = qctx.nextBatchLookupId();
+ rangeStreams = new HashMap<>();
+ }
+
+ Object affKey = affColId == -1 ? null : getAffinityKey(firstRow, lastRow);
+
+ List<ClusterNode> nodes;
+ Future<Cursor> fut;
+
+ if (affKey != null) {
+ // Affinity key is provided.
+ if (affKey == EXPLICIT_NULL) // Affinity key is explicit null, we will not find anything.
+ return false;
+
+ nodes = F.asList(rangeNode(cctx, qctx, affKey));
+ }
+ else {
+ // Affinity key is not provided or is not the same in upper and lower bounds, we have to broadcast.
+ if (broadcastNodes == null)
+ broadcastNodes = broadcastNodes(qctx, cctx);
+
+ nodes = broadcastNodes;
+ }
+
+ assert !F.isEmpty(nodes) : nodes;
+
+ final int rangeId = res.size();
+
+ // Create messages.
+ GridH2RowMessage first = toSearchRowMessage(firstRow);
+ GridH2RowMessage last = toSearchRowMessage(lastRow);
+
+ // Range containing upper and lower bounds.
+ GridH2RowRangeBounds rangeBounds = rangeBounds(rangeId, first, last);
+
+ // Add range to every message of every participating node.
+ for (int i = 0; i < nodes.size(); i++) {
+ ClusterNode node = nodes.get(i);
+ assert node != null;
+
+ RangeStream stream = rangeStreams.get(node);
+
+ List<GridH2RowRangeBounds> bounds;
+
+ if (stream == null) {
+ stream = new RangeStream(qctx, node);
+
+ stream.req = createRequest(qctx, batchLookupId);
+ stream.req.bounds(bounds = new ArrayList<>());
+
+ rangeStreams.put(node, stream);
+ }
+ else
+ bounds = stream.req.bounds();
+
+ bounds.add(rangeBounds);
+
+ // If at least one node will have a full batch then we are ok.
+ if (bounds.size() >= qctx.pageSize())
+ batchFull = true;
+ }
+
+ fut = new DoneFuture<>(nodes.size() == 1 ?
+ new UnicastCursor(rangeId, nodes, rangeStreams) :
+ new BroadcastCursor(rangeId, nodes, rangeStreams));
+
+ res.add(fut);
+
+ return true;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isBatchFull() {
+ return batchFull;
+ }
+
+ /**
+ *
+ */
+ private void startStreams() {
+ if (rangeStreams.isEmpty()) {
+ assert res.isEmpty();
+
+ return;
+ }
+
+ qctx.putStreams(batchLookupId, rangeStreams);
+
+ // Start streaming.
+ for (RangeStream stream : rangeStreams.values())
+ stream.start();
+ }
+
+ /** {@inheritDoc} */
+ @Override public List<Future<Cursor>> find() {
+ batchFull = false;
+ findCalled = true;
+
+ startStreams();
+
+ return res;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void reset(boolean beforeQry) {
+ if (beforeQry || qctx == null) // Query context can be null if addSearchRows was never called.
+ return;
+
+ assert batchLookupId != 0;
+
+ // Do cleanup after the query run.
+ qctx.putStreams(batchLookupId, null);
+ qctx = null; // The same query can be reused multiple times for different query contexts.
+ batchLookupId = 0;
+
+ rangeStreams = Collections.emptyMap();
+ broadcastNodes = null;
+ batchFull = false;
+ findCalled = false;
+ res = Collections.emptyList();
+ }
+
+ /** {@inheritDoc} */
+ @Override public String getPlanSQL() {
+ return ucast ? "unicast" : "broadcast";
+ }
+ }
+
+ /**
+ * Per node range stream.
+ */
+ private class RangeStream {
+ /** */
+ final GridH2QueryContext qctx;
+
+ /** */
+ final ClusterNode node;
+
+ /** */
+ GridH2IndexRangeRequest req;
+
+ /** */
+ int remainingRanges;
+
+ /** */
+ final BlockingQueue<GridH2IndexRangeResponse> respQueue = new LinkedBlockingQueue<>();
+
+ /** */
+ Iterator<GridH2RowRange> ranges = emptyIterator();
+
+ /** */
+ Cursor cursor = GridH2Cursor.EMPTY;
+
+ /** */
+ int cursorRangeId = -1;
+
+ /**
+ * @param qctx Query context.
+ * @param node Node.
+ */
+ RangeStream(GridH2QueryContext qctx, ClusterNode node) {
+ this.node = node;
+ this.qctx = qctx;
+ }
+
+ /**
+ * Start streaming.
+ */
+ private void start() {
+ remainingRanges = req.bounds().size();
+
+ assert remainingRanges > 0;
+
+ if (log.isDebugEnabled())
+ log.debug("Starting stream: [node=" + node + ", req=" + req + "]");
+
+ send(singletonList(node), req);
+ }
+
+ /**
+ * @param msg Response.
+ */
+ public void onResponse(GridH2IndexRangeResponse msg) {
+ respQueue.add(msg);
+ }
+
+ /**
+ * @return Response.
+ */
+ private GridH2IndexRangeResponse awaitForResponse() {
+ assert remainingRanges > 0;
+
+ final long start = U.currentTimeMillis();
+
+ for (int attempt = 0;; attempt++) {
+ if (qctx.isCleared())
+ throw new GridH2RetryException("Query is cancelled.");
+
+ if (kernalContext().isStopping())
+ throw new GridH2RetryException("Stopping node.");
+
+ GridH2IndexRangeResponse res;
+
+ try {
+ res = respQueue.poll(500, TimeUnit.MILLISECONDS);
+ }
+ catch (InterruptedException e) {
+ throw new GridH2RetryException("Interrupted.");
+ }
+
+ if (res != null) {
+ switch (res.status()) {
+ case STATUS_OK:
+ List<GridH2RowRange> ranges0 = res.ranges();
+
+ remainingRanges -= ranges0.size();
+
+ if (ranges0.get(ranges0.size() - 1).isPartial())
+ remainingRanges++;
+
+ if (remainingRanges > 0) {
+ if (req.bounds() != null)
+ req = createRequest(qctx, req.batchLookupId());
+
+ // Prefetch next page.
+ send(singletonList(node), req);
+ }
+ else
+ req = null;
+
+ return res;
+
+ case STATUS_NOT_FOUND:
+ if (req == null || req.bounds() == null) // We have already received the first response.
+ throw new GridH2RetryException("Failure on remote node.");
+
+ if (U.currentTimeMillis() - start > 30_000)
+ throw new GridH2RetryException("Timeout.");
+
+ try {
+ U.sleep(20 * attempt);
+ }
+ catch (IgniteInterruptedCheckedException e) {
+ throw new IgniteInterruptedException(e.getMessage());
+ }
+
+ // Retry to send the request once more after some time.
+ send(singletonList(node), req);
+
+ break;
+
+ case STATUS_ERROR:
+ throw new CacheException(res.error());
+
+ default:
+ throw new IllegalStateException();
+ }
+ }
+
+ if (!kernalContext().discovery().alive(node))
+ throw new GridH2RetryException("Node left: " + node);
+ }
+ }
+
+ /**
+ * @param rangeId Requested range ID.
+ * @return {@code true} If next row for the requested range was found.
+ */
+ private boolean next(final int rangeId) {
+ for (;;) {
+ if (rangeId == cursorRangeId) {
+ if (cursor.next())
+ return true;
+ }
+ else if (rangeId < cursorRangeId)
+ return false;
+
+ cursor = GridH2Cursor.EMPTY;
+
+ while (!ranges.hasNext()) {
+ if (remainingRanges == 0) {
+ ranges = emptyIterator();
+
+ return false;
+ }
+
+ ranges = awaitForResponse().ranges().iterator();
+ }
+
+ GridH2RowRange range = ranges.next();
+
+ cursorRangeId = range.rangeId();
+
+ if (!F.isEmpty(range.rows())) {
+ final Iterator<GridH2RowMessage> it = range.rows().iterator();
+
+ if (it.hasNext()) {
+ cursor = new GridH2Cursor(new Iterator<Row>() {
+ @Override public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ @Override public Row next() {
+ // Lazily convert messages into real rows.
+ return toRow(it.next());
+ }
+
+ @Override public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ });
+ }
+ }
+ }
+ }
+
+ /**
+ * @param rangeId Requested range ID.
+ * @return Current row.
+ */
+ private Row get(int rangeId) {
+ assert rangeId == cursorRangeId;
+
+ return cursor.get();
+ }
+ }
+
+ /**
+ * Bounds iterator.
+ */
+ private class RangeSource {
+ /** */
+ Iterator<GridH2RowRangeBounds> boundsIter;
+
+ /** */
+ int curRangeId = -1;
+
+ /** */
+ Iterator<GridH2Row> curRange = emptyIterator();
+
+ /** */
+ final ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree;
+
+ /** */
+ final IndexingQueryFilter filter;
+
+ /**
+ * @param bounds Bounds.
+ * @param tree Snapshot.
+ * @param filter Filter.
+ */
+ RangeSource(
+ Iterable<GridH2RowRangeBounds> bounds,
+ ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> tree,
+ IndexingQueryFilter filter
+ ) {
+ this.filter = filter;
+ this.tree = tree;
+ boundsIter = bounds.iterator();
+ }
+
+ /**
+ * @return {@code true} If there are more rows in this source.
+ */
+ public boolean hasMoreRows() {
+ return boundsIter.hasNext() || curRange.hasNext();
+ }
+
+ /**
+ * @param maxRows Max allowed rows.
+ * @return Range.
+ */
+ public GridH2RowRange next(int maxRows) {
+ assert maxRows > 0 : maxRows;
+
+ for (;;) {
+ if (curRange.hasNext()) {
+ // Here we are getting last rows from previously partially fetched range.
+ List<GridH2RowMessage> rows = new ArrayList<>();
+
+ GridH2RowRange nextRange = new GridH2RowRange();
+
+ nextRange.rangeId(curRangeId);
+ nextRange.rows(rows);
+
+ do {
+ rows.add(toRowMessage(curRange.next()));
+ }
+ while (rows.size() < maxRows && curRange.hasNext());
+
+ if (curRange.hasNext())
+ nextRange.setPartial();
+ else
+ curRange = emptyIterator();
+
+ return nextRange;
+ }
+
+ curRange = emptyIterator();
+
+ if (!boundsIter.hasNext()) {
+ boundsIter = emptyIterator();
+
+ return null;
+ }
+
+ GridH2RowRangeBounds bounds = boundsIter.next();
+
+ curRangeId = bounds.rangeId();
+
+ SearchRow first = toSearchRow(bounds.first());
+ SearchRow last = toSearchRow(bounds.last());
+
+ ConcurrentNavigableMap<GridSearchRowPointer,GridH2Row> t = tree != null ? tree : treeForRead();
+
+ curRange = doFind0(t, first, true, last, filter);
+
+ if (!curRange.hasNext()) {
+ // We have to return empty range here.
+ GridH2RowRange emptyRange = new GridH2RowRange();
+
+ emptyRange.rangeId(curRangeId);
+
+ return emptyRange;
+ }
+ }
+ }
+ }
+
+ /**
+ * @return Snapshot for current thread if there is one.
+ */
+ protected ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> treeForRead() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @param t Tree.
+ * @param first Lower bound.
+ * @param includeFirst Whether lower bound should be inclusive.
+ * @param last Upper bound always inclusive.
+ * @param filter Filter.
+ * @return Iterator over rows in given range.
+ */
+ protected Iterator<GridH2Row> doFind0(ConcurrentNavigableMap<GridSearchRowPointer, GridH2Row> t,
+ @Nullable SearchRow first,
+ boolean includeFirst,
+ @Nullable SearchRow last,
+ IndexingQueryFilter filter) {
+ throw new UnsupportedOperationException();
+ }
+
/**
* Iterator which filters by expiration time and predicate.
*/
- protected class FilteringIterator extends GridFilteredIterator<GridH2Row> {
+ protected static class FilteringIterator extends GridFilteredIterator<GridH2Row> {
/** */
private final IgniteBiPredicate<Object, Object> fltr;
@@ -210,15 +1490,19 @@ public abstract class GridH2IndexBase extends BaseIndex {
/**
* @param iter Iterator.
* @param time Time for expired rows filtering.
+ * @param qryFilter Filter.
+ * @param spaceName Space name.
*/
- protected FilteringIterator(Iterator<GridH2Row> iter, long time,
- IndexingQueryFilter qryFilter) {
+ protected FilteringIterator(Iterator<GridH2Row> iter,
+ long time,
+ IndexingQueryFilter qryFilter,
+ String spaceName) {
super(iter);
this.time = time;
if (qryFilter != null) {
- this.fltr = qryFilter.forSpace(((GridH2Table)getTable()).spaceName());
+ this.fltr = qryFilter.forSpace(spaceName);
this.isValRequired = qryFilter.isValueRequired();
} else {
@@ -242,8 +1526,8 @@ public abstract class GridH2IndexBase extends BaseIndex {
if (fltr == null)
return true;
- Object key = row.getValue(keyCol).getObject();
- Object val = isValRequired ? row.getValue(valCol).getObject() : null;
+ Object key = row.getValue(KEY_COL).getObject();
+ Object val = isValRequired ? row.getValue(VAL_COL).getObject() : null;
assert key != null;
assert !isValRequired || val != null;
[09/50] [abbrv] ignite git commit: ignite-1232 Distributed SQL joins
implementation
Posted by vo...@apache.org.
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinQueryWithAffinityKeyTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinQueryWithAffinityKeyTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinQueryWithAffinityKeyTest.java
new file mode 100644
index 0000000..44bca5e
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheJoinQueryWithAffinityKeyTest.java
@@ -0,0 +1,646 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ThreadLocalRandom;
+import javax.cache.CacheException;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheKeyConfiguration;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.AffinityKeyMapped;
+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.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.binary.BinaryMarshaller;
+import org.apache.ignite.internal.util.typedef.F;
+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 org.apache.ignite.testframework.GridTestUtils;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+@SuppressWarnings("unchecked")
+public class IgniteCacheJoinQueryWithAffinityKeyTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final int NODES = 5;
+
+ /** */
+ private boolean client;
+
+ /** */
+ private boolean escape;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+ CacheKeyConfiguration keyCfg = new CacheKeyConfiguration();
+
+ keyCfg.setTypeName(TestKeyWithAffinity.class.getName());
+ keyCfg.setAffinityKeyFieldName("affKey");
+
+ cfg.setCacheKeyConfiguration(keyCfg);
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ super.beforeTestsStarted();
+
+ startGridsMultiThreaded(NODES - 1);
+
+ client = true;
+
+ startGrid(NODES - 1);
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTestsStopped() throws Exception {
+ stopAllGrids();
+
+ super.afterTestsStopped();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQuery() throws Exception {
+ testJoinQuery(PARTITIONED, 0, false, true);
+
+ testJoinQuery(PARTITIONED, 1, false, true);
+
+ testJoinQuery(REPLICATED, 0, false, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQueryEscapeAll() throws Exception {
+ escape = true;
+
+ testJoinQuery();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQueryWithAffinityKey() throws Exception {
+ testJoinQuery(PARTITIONED, 0, true, true);
+
+ testJoinQuery(PARTITIONED, 1, true, true);
+
+ testJoinQuery(REPLICATED, 0, true, true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQueryWithAffinityKeyEscapeAll() throws Exception {
+ escape = true;
+
+ testJoinQueryWithAffinityKey();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQueryWithAffinityKeyNotQueryField() throws Exception {
+ testJoinQuery(PARTITIONED, 0, true, false);
+
+ testJoinQuery(PARTITIONED, 1, true, false);
+
+ testJoinQuery(REPLICATED, 0, true, false);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testJoinQueryWithAffinityKeyNotQueryFieldEscapeAll() throws Exception {
+ escape = true;
+
+ testJoinQueryWithAffinityKeyNotQueryField();
+ }
+
+ /**
+ * @param cacheMode Cache mode.
+ * @param backups Number of backups.
+ * @param affKey If {@code true} uses key with affinity key field.
+ * @param includeAffKey If {@code true} includes affinity key field in query fields.
+ */
+ private void testJoinQuery(CacheMode cacheMode, int backups, final boolean affKey, boolean includeAffKey) {
+ CacheConfiguration ccfg = cacheConfiguration(cacheMode, backups, affKey, includeAffKey);
+
+ log.info("Test cache [mode=" + cacheMode + ", backups=" + backups + ']');
+
+ IgniteCache cache = ignite(0).createCache(ccfg);
+
+ try {
+ final PutData putData = putData(cache, affKey);
+
+ for (int i = 0; i < NODES; i++) {
+ log.info("Test node: " + i);
+
+ final IgniteCache cache0 = ignite(i).cache(ccfg.getName());
+
+ if (cacheMode == REPLICATED && !ignite(i).configuration().isClientMode()) {
+ GridTestUtils.assertThrows(log, new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ checkPersonAccountsJoin(cache0, putData.personAccounts, affKey);
+
+ return null;
+ }
+ }, CacheException.class, "Queries using distributed JOINs have to be run on partitioned cache");
+ }
+ else {
+ checkPersonAccountsJoin(cache0, putData.personAccounts, affKey);
+
+ checkOrganizationPersonsJoin(cache0, putData.orgPersons);
+ }
+ }
+ }
+ finally {
+ ignite(0).destroyCache(ccfg.getName());
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @param cnts Organizations per person counts.
+ */
+ private void checkOrganizationPersonsJoin(IgniteCache cache, Map<Integer, Integer> cnts) {
+ SqlFieldsQuery qry;
+
+ if (escape) {
+ qry = new SqlFieldsQuery("select o.\"name\", p.\"name\" " +
+ "from \"Organization\" o, \"Person\" p " +
+ "where p.\"orgId\" = o._key and o._key=?");
+ }
+ else {
+ qry = new SqlFieldsQuery("select o.name, p.name " +
+ "from Organization o, Person p " +
+ "where p.orgId = o._key and o._key=?");
+ }
+
+ qry.setDistributedJoins(true);
+
+ long total = 0;
+
+ for (int i = 0; i < cnts.size(); i++) {
+ qry.setArgs(i);
+
+ List<List<Object>> res = cache.query(qry).getAll();
+
+ assertEquals((int)cnts.get(i), res.size());
+
+ total += res.size();
+ }
+
+ SqlFieldsQuery qry2;
+
+ if (escape) {
+ qry2 = new SqlFieldsQuery("select count(*) " +
+ "from \"Organization\" o, \"Person\" p where p.\"orgId\" = o._key");
+ }
+ else {
+ qry2 = new SqlFieldsQuery("select count(*) " +
+ "from Organization o, Person p where p.orgId = o._key");
+ }
+
+ qry2.setDistributedJoins(true);
+
+ List<List<Object>> res = cache.query(qry2).getAll();
+
+ assertEquals(1, res.size());
+ assertEquals(total, res.get(0).get(0));
+ }
+
+ /**
+ * @param cache Cache.
+ * @param cnts Accounts per person counts.
+ * @param affKey If {@code true} uses key with affinity key field.
+ */
+ private void checkPersonAccountsJoin(IgniteCache cache, Map<Object, Integer> cnts, boolean affKey) {
+ String sql1;
+
+ if (escape) {
+ sql1 = "select p.\"name\" from \"Person\" p, \"" + (affKey ? "AccountKeyWithAffinity" : "Account") + "\" a " +
+ "where p._key = a.\"personKey\" and p._key=?";
+ }
+ else {
+ sql1 = "select p.name from Person p, " + (affKey ? "AccountKeyWithAffinity" : "Account") + " a " +
+ "where p._key = a.personKey and p._key=?";
+ }
+
+ SqlFieldsQuery qry1 = new SqlFieldsQuery(sql1);
+
+ qry1.setDistributedJoins(true);
+
+ String sql2;
+
+ if (escape) {
+ sql2 = "select p.\"name\" from \"Person\" p, \"" + (affKey ? "AccountKeyWithAffinity" : "Account") + "\" a " +
+ "where p.\"id\" = a.\"personId\" and p.\"id\"=?";
+ }
+ else {
+ sql2 = "select p.name from Person p, " + (affKey ? "AccountKeyWithAffinity" : "Account") + " a " +
+ "where p.id = a.personId and p.id=?";
+ }
+
+ SqlFieldsQuery qry2 = new SqlFieldsQuery(sql2);
+
+ qry2.setDistributedJoins(true);
+
+ Ignite ignite = (Ignite)cache.unwrap(Ignite.class);
+
+ boolean binary = ignite.configuration().getMarshaller() instanceof BinaryMarshaller;
+
+ long total = 0;
+
+ for (Map.Entry<Object, Integer> e : cnts.entrySet()) {
+ Object arg = binary ? ignite.binary().toBinary(e.getKey()) : e.getKey();
+
+ qry1.setArgs(arg);
+
+ List<List<Object>> res = cache.query(qry1).getAll();
+
+ assertEquals((int)e.getValue(), res.size());
+
+ total += res.size();
+
+ qry2.setArgs(((Id)e.getKey()).id());
+
+ res = cache.query(qry2).getAll();
+
+ assertEquals((int)e.getValue(), res.size());
+ }
+
+ SqlFieldsQuery[] qrys = new SqlFieldsQuery[2];
+
+
+ if (escape) {
+ qrys[0] = new SqlFieldsQuery("select count(*) " +
+ "from \"Person\" p, \"" + (affKey ? "AccountKeyWithAffinity" : "Account") + "\" a " +
+ "where p.\"id\" = a.\"personId\"");
+
+ qrys[1] = new SqlFieldsQuery("select count(*) " +
+ "from \"Person\" p, \"" + (affKey ? "AccountKeyWithAffinity" : "Account") + "\" a " +
+ "where p._key = a.\"personKey\"");
+ }
+ else {
+ qrys[0] = new SqlFieldsQuery("select count(*) " +
+ "from Person p, " + (affKey ? "AccountKeyWithAffinity" : "Account") + " a " +
+ "where p.id = a.personId");
+
+ qrys[1] = new SqlFieldsQuery("select count(*) " +
+ "from Person p, " + (affKey ? "AccountKeyWithAffinity" : "Account") + " a " +
+ "where p._key = a.personKey");
+ }
+
+ for (SqlFieldsQuery qry : qrys) {
+ qry.setDistributedJoins(true);
+
+ List<List<Object>> res = cache.query(qry).getAll();
+
+ assertEquals(1, res.size());
+ assertEquals(total, res.get(0).get(0));
+ }
+ }
+
+ /**
+ * @param cacheMode Cache mode.
+ * @param backups Number of backups.
+ * @param affKey If {@code true} uses key with affinity key field.
+ * @param includeAffKey If {@code true} includes affinity key field in query fields.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration cacheConfiguration(CacheMode cacheMode,
+ int backups,
+ boolean affKey,
+ boolean includeAffKey) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setCacheMode(cacheMode);
+
+ if (cacheMode == PARTITIONED)
+ ccfg.setBackups(backups);
+
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+
+ String personKeyType = affKey ? TestKeyWithAffinity.class.getName() : TestKey.class.getName();
+
+ QueryEntity account = new QueryEntity();
+ account.setKeyType(Integer.class.getName());
+ account.setValueType(affKey ? AccountKeyWithAffinity.class.getName() : Account.class.getName());
+ account.addQueryField("personKey", personKeyType, null);
+ account.addQueryField("personId", Integer.class.getName(), null);
+ account.setIndexes(F.asList(new QueryIndex("personKey"), new QueryIndex("personId")));
+
+ QueryEntity person = new QueryEntity();
+ person.setKeyType(personKeyType);
+ person.setValueType(Person.class.getName());
+ person.addQueryField("orgId", Integer.class.getName(), null);
+ person.addQueryField("id", Integer.class.getName(), null);
+ person.addQueryField("name", String.class.getName(), null);
+ person.setIndexes(F.asList(new QueryIndex("orgId"), new QueryIndex("id"), new QueryIndex("name")));
+
+ if (affKey && includeAffKey)
+ person.addQueryField("affKey", Integer.class.getName(), null);
+
+ QueryEntity org = new QueryEntity();
+ org.setKeyType(Integer.class.getName());
+ org.setValueType(Organization.class.getName());
+ org.addQueryField("name", String.class.getName(), null);
+ org.setIndexes(F.asList(new QueryIndex("name")));
+
+ ccfg.setQueryEntities(F.asList(account, person, org));
+
+ ccfg.setSqlEscapeAll(escape);
+
+ return ccfg;
+ }
+
+ /**
+ * @param cache Cache.
+ * @param affKey If {@code true} uses key with affinity key field.
+ * @return Put data counts.
+ */
+ private PutData putData(IgniteCache cache, boolean affKey) {
+ Map<Integer, Integer> orgPersons = new HashMap<>();
+ Map<Object, Integer> personAccounts = new HashMap<>();
+
+ final int ORG_CNT = 10;
+
+ for (int i = 0; i < ORG_CNT; i++)
+ cache.put(i, new Organization("org-" + i));
+
+ Set<Integer> personIds = new HashSet<>();
+ Set<Integer> accountIds = new HashSet<>();
+
+ for (int i = 0; i < ORG_CNT; i++) {
+ int persons = ThreadLocalRandom.current().nextInt(100);
+
+ for (int p = 0; p < persons; p++) {
+ int personId = ThreadLocalRandom.current().nextInt();
+
+ while (!personIds.add(personId))
+ personId = ThreadLocalRandom.current().nextInt();
+
+ Object personKey = affKey ? new TestKeyWithAffinity(personId) : new TestKey(personId);
+
+ String name = "person-" + personId;
+
+ cache.put(personKey, new Person(i, name));
+
+ int accounts = ThreadLocalRandom.current().nextInt(10);
+
+ for (int a = 0; a < accounts; a++) {
+ int accountId = ThreadLocalRandom.current().nextInt();
+
+ while (!accountIds.add(accountId))
+ accountId = ThreadLocalRandom.current().nextInt();
+
+ cache.put(accountId, affKey ? new AccountKeyWithAffinity(personKey) : new Account(personKey));
+ }
+
+ personAccounts.put(personKey, accounts);
+ }
+
+ orgPersons.put(i, persons);
+ }
+
+ return new PutData(orgPersons, personAccounts);
+ }
+
+ /**
+ *
+ */
+ private static class PutData {
+ /** */
+ final Map<Integer, Integer> orgPersons;
+
+ /** */
+ final Map<Object, Integer> personAccounts;
+
+ /**
+ * @param orgPersons Organizations per person counts.
+ * @param personAccounts Accounts per person counts.
+ */
+ public PutData(Map<Integer, Integer> orgPersons, Map<Object, Integer> personAccounts) {
+ this.orgPersons = orgPersons;
+ this.personAccounts = personAccounts;
+ }
+ }
+
+ /**
+ *
+ */
+ public interface Id {
+ /**
+ * @return ID.
+ */
+ public int id();
+ }
+
+ /**
+ *
+ */
+ public static class TestKey implements Id {
+ /** */
+ private int id;
+
+ /**
+ * @param id Key.
+ */
+ public TestKey(int id) {
+ this.id = id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int id() {
+ return id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TestKey other = (TestKey)o;
+
+ return id == other.id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return id;
+ }
+ }
+
+ /**
+ *
+ */
+ public static class TestKeyWithAffinity implements Id {
+ /** */
+ private int id;
+
+ /** */
+ @AffinityKeyMapped
+ private int affKey;
+
+ /**
+ * @param id Key.
+ */
+ public TestKeyWithAffinity(int id) {
+ this.id = id;
+
+ affKey = id + 1;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int id() {
+ return id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ TestKeyWithAffinity other = (TestKeyWithAffinity)o;
+
+ return id == other.id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return id;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Account implements Serializable {
+ /** */
+ @QuerySqlField
+ private TestKey personKey;
+
+ /** */
+ @QuerySqlField
+ private int personId;
+
+ /**
+ * @param personKey Person key.
+ */
+ public Account(Object personKey) {
+ this.personKey = (TestKey)personKey;
+ personId = this.personKey.id;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class AccountKeyWithAffinity implements Serializable {
+ /** */
+ @QuerySqlField
+ private TestKeyWithAffinity personKey;
+
+ /** */
+ @QuerySqlField
+ private int personId;
+
+ /**
+ * @param personKey Person key.
+ */
+ public AccountKeyWithAffinity(Object personKey) {
+ this.personKey = (TestKeyWithAffinity)personKey;
+ personId = this.personKey.id;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ @QuerySqlField
+ int orgId;
+
+ /** */
+ @QuerySqlField
+ String name;
+
+ /**
+ * @param orgId Organization ID.
+ * @param name Name.
+ */
+ public Person(int orgId, String name) {
+ this.orgId = orgId;
+ this.name = name;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ /** */
+ @QuerySqlField
+ String name;
+
+ /**
+ * @param name Name.
+ */
+ public Organization(String name) {
+ this.name = name;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryLoadSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryLoadSelfTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryLoadSelfTest.java
index f55a833..ca612a8 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryLoadSelfTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCacheQueryLoadSelfTest.java
@@ -25,13 +25,13 @@ import javax.cache.Cache;
import javax.cache.integration.CompletionListenerFuture;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
import org.apache.ignite.cache.query.SqlQuery;
import org.apache.ignite.cache.query.annotations.QuerySqlField;
import org.apache.ignite.cache.store.CacheStoreAdapter;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
-import org.apache.ignite.internal.IgniteKernal;
-import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager;
+import org.apache.ignite.internal.processors.query.GridQueryProcessor;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.P2;
import org.apache.ignite.internal.util.typedef.internal.S;
@@ -109,11 +109,9 @@ public class IgniteCacheQueryLoadSelfTest extends GridCommonAbstractTest {
* @throws IgniteCheckedException If failed.
*/
private long size(Class<?> cls) throws IgniteCheckedException {
- GridCacheQueryManager<Object, Object> qryMgr = ((IgniteKernal)grid()).internalCache().context().queries();
-
- assert qryMgr != null;
-
- return qryMgr.size(cls);
+ return (Long)grid().cache(null).query(
+ new SqlFieldsQuery("select count(*) from " + GridQueryProcessor.typeName(cls)).setLocal(true))
+ .getAll().get(0).get(0);
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/68891e89/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java
new file mode 100644
index 0000000..0dd9281
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/IgniteCrossCachesJoinsQueryTest.java
@@ -0,0 +1,1641 @@
+/*
+ * 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;
+
+import java.io.Serializable;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import javax.cache.CacheException;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheMemoryMode;
+import org.apache.ignite.cache.CacheMode;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.cache.QueryIndex;
+import org.apache.ignite.cache.affinity.AffinityKey;
+import org.apache.ignite.cache.query.Query;
+import org.apache.ignite.cache.query.SqlFieldsQuery;
+import org.apache.ignite.cache.query.SqlQuery;
+import org.apache.ignite.cache.query.annotations.QuerySqlField;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.query.h2.sql.AbstractH2CompareQueryTest;
+import org.apache.ignite.internal.util.tostring.GridToStringInclude;
+import org.apache.ignite.internal.util.typedef.F;
+import org.apache.ignite.internal.util.typedef.internal.S;
+import org.apache.ignite.internal.util.typedef.internal.SB;
+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 org.apache.ignite.testframework.GridTestUtils;
+
+import static org.apache.ignite.cache.CacheMemoryMode.OFFHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMemoryMode.ONHEAP_TIERED;
+import static org.apache.ignite.cache.CacheMode.PARTITIONED;
+import static org.apache.ignite.cache.CacheMode.REPLICATED;
+import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_SYNC;
+
+/**
+ *
+ */
+@SuppressWarnings({"unchecked", "PackageVisibleField", "serial"})
+public class IgniteCrossCachesJoinsQueryTest extends AbstractH2CompareQueryTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private static final String PERSON_CACHE_NAME = "person";
+
+ /** */
+ private static final String ORG_CACHE_NAME = "org";
+
+ /** */
+ private static final String ACC_CACHE_NAME = "acc";
+
+ /** */
+ private static final int NODES = 5;
+
+ /** */
+ private boolean client;
+
+ /** */
+ private Data data;
+
+ /** Tested qry. */
+ private String qry;
+
+ /** Tested cache. */
+ private IgniteCache cache;
+
+ /** */
+ private boolean distributedJoins;
+
+ /** */
+ private static Random rnd;
+
+ /** */
+ private CacheMemoryMode memMode = ONHEAP_TIERED;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(gridName);
+
+ ((TcpDiscoverySpi)cfg.getDiscoverySpi()).setIpFinder(IP_FINDER);
+
+ cfg.setClientMode(client);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected CacheConfiguration[] cacheConfigurations() {
+ return null;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void setIndexedTypes(CacheConfiguration<?, ?> cc, CacheMode mode) {
+ throw new UnsupportedOperationException();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTestsStarted() throws Exception {
+ long seed = System.currentTimeMillis();
+
+ rnd = new Random(seed);
+
+ log.info("Random seed: " + seed);
+
+ startGridsMultiThreaded(NODES - 1);
+
+ client = true;
+
+ startGrid(NODES - 1);
+
+ awaitPartitionMapExchange();
+
+ conn = openH2Connection(false);
+
+ initializeH2Schema();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void initCacheAndDbData() throws SQLException {
+ Statement st = conn.createStatement();
+
+ final String keyType = useCollocatedData() ? "other" : "int";
+
+ st.execute("create table \"" + ACC_CACHE_NAME + "\".Account" +
+ " (" +
+ " _key " + keyType + " not null," +
+ " _val other not null," +
+ " id int unique," +
+ " personId int," +
+ " personDateId TIMESTAMP," +
+ " personStrId varchar(255)" +
+ " )");
+
+ st.execute("create table \"" + PERSON_CACHE_NAME + "\".Person" +
+ " (" +
+ " _key " + keyType + " not null," +
+ " _val other not null," +
+ " id int unique," +
+ " strId varchar(255) ," +
+ " dateId TIMESTAMP ," +
+ " orgId int," +
+ " orgDateId TIMESTAMP," +
+ " orgStrId varchar(255), " +
+ " name varchar(255), " +
+ " salary int" +
+ " )");
+
+ st.execute("create table \"" + ORG_CACHE_NAME + "\".Organization" +
+ " (" +
+ " _key int not null," +
+ " _val other not null," +
+ " id int unique," +
+ " strId varchar(255) ," +
+ " dateId TIMESTAMP ," +
+ " name varchar(255) " +
+ " )");
+
+ conn.commit();
+
+ st.close();
+
+ for (Account account : data.accounts)
+ insertInDb(account);
+
+ for (Person person : data.persons)
+ insertInDb(person);
+
+ for (Organization org : data.orgs)
+ insertInDb(org);
+ }
+
+ /**
+ *
+ */
+ private void initCachesData() {
+ IgniteCache accCache = ignite(0).cache(ACC_CACHE_NAME);
+
+ for (Account account : data.accounts)
+ accCache.put(account.key(useCollocatedData()), account);
+
+ IgniteCache personCache = ignite(0).cache(PERSON_CACHE_NAME);
+
+ for (Person person : data.persons)
+ personCache.put(person.key(useCollocatedData()), person);
+
+ IgniteCache orgCache = ignite(0).cache(ORG_CACHE_NAME);
+
+ for (Organization org : data.orgs)
+ orgCache.put(org.id, org);
+ }
+
+ /**
+ * @param acc Account.
+ * @throws SQLException If failed.
+ */
+ private void insertInDb(Account acc) throws SQLException {
+ try (PreparedStatement st = conn.prepareStatement(
+ "insert into \"" + ACC_CACHE_NAME + "\".Account (_key, _val, id, personId, personDateId, personStrId) " +
+ "values(?, ?, ?, ?, ?, ?)")) {
+ int i = 0;
+
+ st.setObject(++i, acc.key(useCollocatedData()));
+ st.setObject(++i, acc);
+ st.setObject(++i, acc.id);
+ st.setObject(++i, acc.personId);
+ st.setObject(++i, acc.personDateId);
+ st.setObject(++i, acc.personStrId);
+
+ st.executeUpdate();
+ }
+ }
+
+ /**
+ * @param p Person.
+ * @throws SQLException If failed.
+ */
+ private void insertInDb(Person p) throws SQLException {
+ try (PreparedStatement st = conn.prepareStatement(
+ "insert into \"" + PERSON_CACHE_NAME + "\".Person (_key, _val, id, strId, dateId, name, orgId, orgDateId, " +
+ "orgStrId, salary) " +
+ "values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) {
+ int i = 0;
+
+ st.setObject(++i, p.key(useCollocatedData()));
+ st.setObject(++i, p);
+ st.setObject(++i, p.id);
+ st.setObject(++i, p.strId);
+ st.setObject(++i, p.dateId);
+ st.setObject(++i, p.name);
+ st.setObject(++i, p.orgId);
+ st.setObject(++i, p.orgDateId);
+ st.setObject(++i, p.orgStrId);
+ st.setObject(++i, p.salary);
+
+ st.executeUpdate();
+ }
+ }
+
+ /**
+ * @param o Organization.
+ * @throws SQLException If failed.
+ */
+ private void insertInDb(Organization o) throws SQLException {
+ try (PreparedStatement st = conn.prepareStatement(
+ "insert into \"" + ORG_CACHE_NAME + "\".Organization (_key, _val, id, strId, dateId, name) " +
+ "values(?, ?, ?, ?, ?, ?)")) {
+ int i = 0;
+
+ st.setObject(++i, o.id);
+ st.setObject(++i, o);
+ st.setObject(++i, o.id);
+ st.setObject(++i, o.strId);
+ st.setObject(++i, o.dateId);
+ st.setObject(++i, o.name);
+
+ st.executeUpdate();
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void checkAllDataEquals() throws Exception {
+ compareQueryRes0(ignite(0).cache(ACC_CACHE_NAME), "select _key, _val, id, personId, personDateId, personStrId " +
+ "from \"" + ACC_CACHE_NAME + "\".Account");
+
+ compareQueryRes0(ignite(0).cache(PERSON_CACHE_NAME), "select _key, _val, id, strId, dateId, name, orgId, " +
+ "orgDateId, orgStrId, salary from \"" + PERSON_CACHE_NAME + "\".Person");
+
+ compareQueryRes0(ignite(0).cache(ORG_CACHE_NAME), "select _key, _val, id, strId, dateId, name " +
+ "from \"" + ORG_CACHE_NAME + "\".Organization");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected Statement initializeH2Schema() throws SQLException {
+ Statement st = conn.createStatement();
+
+ for (String cacheName : new String[]{"person", "acc", "org"})
+ st.execute("CREATE SCHEMA \"" + cacheName + "\"");
+
+ return st;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected long getTestTimeout() {
+ return 30 * 60_000;
+ }
+
+ /**
+ * @return Distributed joins flag.
+ */
+ protected boolean distributedJoins() {
+ return distributedJoins;
+ }
+
+ /**
+ * @return Use collocated data.
+ */
+ private boolean useCollocatedData() {
+ return !distributedJoins();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoins1() throws Exception {
+ distributedJoins = true;
+
+ checkAllCacheCombinationsSet1(true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoins1Offheap() throws Exception {
+ memMode = OFFHEAP_TIERED;
+
+ testDistributedJoins1();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoins2() throws Exception {
+ distributedJoins = true;
+
+ checkAllCacheCombinationsSet2(true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testDistributedJoins3() throws Exception {
+ distributedJoins = true;
+
+ checkAllCacheCombinationsSet3(true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCollocatedJoins1() throws Exception {
+ distributedJoins = false;
+
+ checkAllCacheCombinationsSet1(true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCollocatedJoins2() throws Exception {
+ distributedJoins = false;
+
+ checkAllCacheCombinationsSet2(true);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testCollocatedJoins3() throws Exception {
+ distributedJoins = false;
+
+ checkAllCacheCombinationsSet3(true);
+ }
+
+ /**
+ * @param idx Index flag.
+ * @throws Exception If failed.
+ */
+ private void checkAllCacheCombinationsSet1(boolean idx) throws Exception {
+ List<List<TestCache>> types = cacheCombinations(TestCacheType.REPLICATED);
+
+ checkAllCacheCombinations(idx, types);
+ }
+
+ /**
+ * @param idx Index flag.
+ * @throws Exception If failed.
+ */
+ private void checkAllCacheCombinationsSet2(boolean idx) throws Exception {
+ List<List<TestCache>> types = cacheCombinations(TestCacheType.PARTITIONED_b0);
+
+ checkAllCacheCombinations(idx, types);
+ }
+
+ /**
+ * @param idx Index flag.
+ * @throws Exception If failed.
+ */
+ private void checkAllCacheCombinationsSet3(boolean idx) throws Exception {
+ List<List<TestCache>> types = cacheCombinations(TestCacheType.PARTITIONED_b1);
+
+ checkAllCacheCombinations(idx, types);
+ }
+
+ /**
+ * @param personType Person cache type.
+ * @return Cache combinations.
+ */
+ private List<List<TestCache>> cacheCombinations(TestCacheType personType) {
+ List<List<TestCache>> res = new ArrayList<>();
+
+ for (TestCacheType accCacheType : TestCacheType.values()) {
+ for (TestCacheType orgCacheType : TestCacheType.values()) {
+ List<TestCache> cacheTypes = new ArrayList<>(3);
+
+ cacheTypes.add(new TestCache("person", personType));
+ cacheTypes.add(new TestCache("acc", accCacheType));
+ cacheTypes.add(new TestCache("org", orgCacheType));
+
+ res.add(cacheTypes);
+ }
+ }
+
+ return res;
+ }
+
+ /**
+ * @param idx Index flag.
+ * @param cacheList Caches.
+ * @throws Exception If failed.
+ */
+ private void checkAllCacheCombinations(
+ boolean idx,
+ List<List<TestCache>> cacheList) throws Exception {
+ data = prepareData();
+
+ initCacheAndDbData();
+
+ try {
+ Map<TestConfig, Throwable> errors = new LinkedHashMap<>();
+ List<TestConfig> success = new ArrayList<>();
+
+ int cfgIdx = 0;
+
+ for (List<TestCache> caches : cacheList) {
+ assert caches.size() == 3 : caches;
+
+ TestCache personCache = caches.get(0);
+ TestCache accCache = caches.get(1);
+ TestCache orgCache = caches.get(2);
+
+ try {
+ check(idx, personCache, accCache, orgCache);
+
+ success.add(new TestConfig(cfgIdx, cache, personCache, accCache, orgCache, ""));
+ }
+ catch (Throwable e) {
+ error("", e);
+
+ errors.put(new TestConfig(cfgIdx, cache, personCache, accCache, orgCache, qry), e);
+ }
+
+ cfgIdx++;
+ }
+
+ if (!errors.isEmpty()) {
+ int total = cacheList.size();
+
+ SB sb = new SB("Test failed for the following " + errors.size() + " combination(s) (" + total + " total):\n");
+
+ for (Map.Entry<TestConfig, Throwable> e : errors.entrySet())
+ sb.a(e.getKey()).a(", error=").a(e.getValue()).a("\n");
+
+ sb.a("Successfully finished combinations:\n");
+
+ for (TestConfig t : success)
+ sb.a(t).a("\n");
+
+ sb.a("The following data has beed used for test:\n " + data);
+
+ fail(sb.toString());
+ }
+ }
+ finally {
+ for (String cacheName : new String[]{PERSON_CACHE_NAME, ACC_CACHE_NAME, ORG_CACHE_NAME})
+ ignite(0).destroyCache(cacheName);
+
+ Statement st = conn.createStatement();
+
+ st.execute("drop table \"" + ACC_CACHE_NAME + "\".Account");
+ st.execute("drop table \"" + PERSON_CACHE_NAME + "\".Person");
+ st.execute("drop table \"" + ORG_CACHE_NAME + "\".Organization");
+
+ conn.commit();
+
+ st.close();
+ }
+ }
+
+ /**
+ * @param idx Index flag.
+ * @param personCacheType Person cache personCacheType.
+ * @param accCacheType Account cache personCacheType.
+ * @param orgCacheType Organization cache personCacheType.
+ * @throws Exception If failed.
+ */
+ private void check(
+ boolean idx,
+ final TestCache personCacheType,
+ final TestCache accCacheType,
+ final TestCache orgCacheType) throws Exception {
+ info("Checking cross cache joins [accCache=" + accCacheType +
+ ", personCache=" + personCacheType +
+ ", orgCache=" + orgCacheType + "]");
+
+ Collection<TestCache> cacheTypes = F.asList(personCacheType, accCacheType, orgCacheType);
+
+ for (TestCache cache : cacheTypes) {
+ CacheConfiguration cc = cacheConfiguration(cache.cacheName,
+ cache.type.cacheMode,
+ cache.type.backups,
+ idx,
+ cache == accCacheType,
+ cache == personCacheType,
+ cache == orgCacheType
+ );
+
+ ignite(0).getOrCreateCache(cc);
+
+ info("Created cache [name=" + cache.cacheName + ", mode=" + cache.type + "]");
+ }
+
+ initCachesData();
+
+ // checkAllDataEquals();
+
+ List<String> cacheNames = new ArrayList<>();
+
+ cacheNames.add(personCacheType.cacheName);
+ cacheNames.add(orgCacheType.cacheName);
+ cacheNames.add(accCacheType.cacheName);
+
+ for (int i = 0; i < NODES; i++) {
+ Ignite testNode = ignite(i);
+
+ log.info("Test node [idx=" + i + ", isClient=" + testNode.configuration().isClientMode() + "]");
+
+ for (String cacheName : cacheNames) {
+ cache = testNode.cache(cacheName);
+
+ log.info("Use cache: " + cache.getName());
+
+ boolean distributeJoins0 = distributedJoins;
+
+ if (replicated(cache)) {
+ if (!testNode.configuration().isClientMode())
+ assertProperException(cache);
+
+ boolean all3CachesAreReplicated =
+ replicated(ignite(0).cache(ACC_CACHE_NAME)) &&
+ replicated(ignite(0).cache(PERSON_CACHE_NAME)) &&
+ replicated(ignite(0).cache(ORG_CACHE_NAME));
+
+ // Queries running on replicated cache should not contain JOINs with partitioned tables.
+ if (distributeJoins0 && !all3CachesAreReplicated)
+ continue;
+ else
+ distributedJoins = false;
+ }
+
+ if (!cache.getName().equals(orgCacheType.cacheName))
+ checkPersonAccountsJoin(cache, data.accountsPerPerson);
+
+ if (!cache.getName().equals(accCacheType.cacheName))
+ checkOrganizationPersonsJoin(cache);
+
+ checkOrganizationPersonAccountJoin(cache);
+
+ checkUnion();
+ checkUnionAll();
+
+ if (!cache.getName().equals(orgCacheType.cacheName))
+ checkPersonAccountCrossJoin(cache);
+
+ if (!cache.getName().equals(accCacheType.cacheName))
+ checkPersonOrganizationGroupBy(cache);
+
+ if (!cache.getName().equals(orgCacheType.cacheName))
+ checkPersonAccountGroupBy(cache);
+
+ checkGroupBy();
+
+ distributedJoins = distributeJoins0;
+ }
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @return {@code True} if cache is replicated.
+ */
+ private boolean replicated(IgniteCache<?, ?> cache) {
+ return cache.getConfiguration(CacheConfiguration.class).getCacheMode() == REPLICATED;
+ }
+
+ /**
+ * @param cache Cache.
+ */
+ private void assertProperException(final IgniteCache cache) {
+ qry = "assertProperException";
+
+ GridTestUtils.assertThrows(log, new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ cache.query(new SqlFieldsQuery("select p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p._key = a.personId").setDistributedJoins(true));
+
+ return null;
+ }
+ }, CacheException.class, "Queries using distributed JOINs have to be run on partitioned cache");
+
+ GridTestUtils.assertThrows(log, new Callable<Object>() {
+ @Override public Object call() throws Exception {
+ cache.query(new SqlQuery(Person.class,
+ "from \"" + PERSON_CACHE_NAME + "\".Person , " +
+ "\"" + ACC_CACHE_NAME + "\".Account " +
+ "where Person._key = Account.personId")
+ .setDistributedJoins(true));
+
+ return null;
+ }
+ }, CacheException.class, "Queries using distributed JOINs have to be run on partitioned cache");
+ }
+
+ /**
+ * Organization ids: [0, 9]. Person ids: randoms at [10, 9999]. Accounts ids: randoms at [10000, 999_999]
+ *
+ * @return Data.
+ */
+ private Data prepareData() {
+ Map<Integer, Integer> personsPerOrg = new HashMap<>();
+ Map<Integer, Integer> accountsPerPerson = new HashMap<>();
+ Map<Integer, Integer> accountsPerOrg = new HashMap<>();
+ Map<Integer, Integer> maxSalaryPerOrg = new HashMap<>();
+
+ List<Organization> orgs = new ArrayList<>();
+ List<Person> persons = new ArrayList<>();
+ List<Account> accounts = new ArrayList<>();
+
+ final int ORG_CNT = 10;
+ final int MAX_PERSONS_PER_ORG = 20;
+ final int MAX_ACCOUNTS_PER_PERSON = 10;
+
+ for (int id = 0; id < ORG_CNT; id++)
+ orgs.add(new Organization(id, "org-" + id));
+
+ Set<Integer> personIds = new HashSet<>();
+ Set<Integer> accountIds = new HashSet<>();
+
+ for (int orgId = 0; orgId < ORG_CNT; orgId++) {
+ int personsCnt = rnd.nextInt(MAX_PERSONS_PER_ORG);
+
+ int accsPerOrg = 0;
+ int maxSalary = -1;
+
+ for (int p = 0; p < personsCnt; p++) {
+ int personId = rnd.nextInt(10_000) + 10;
+
+ while (!personIds.add(personId))
+ personId = rnd.nextInt(10_000) + 10;
+
+ String name = "person-" + personId;
+
+ int salary = (rnd.nextInt(10) + 1) * 1000;
+
+ if (salary > maxSalary)
+ maxSalary = salary;
+
+ persons.add(new Person(personId, orgId, name, salary));
+
+ int accountsCnt = rnd.nextInt(MAX_ACCOUNTS_PER_PERSON);
+
+ for (int a = 0; a < accountsCnt; a++) {
+ int accountId = rnd.nextInt(100_000) + 10_000;
+
+ while (!accountIds.add(accountId))
+ accountId = rnd.nextInt(100_000) + 10_000;
+
+ accounts.add(new Account(accountId, personId, orgId));
+ }
+
+ accountsPerPerson.put(personId, accountsCnt);
+
+ accsPerOrg += accountsCnt;
+ }
+
+ personsPerOrg.put(orgId, personsCnt);
+ accountsPerOrg.put(orgId, accsPerOrg);
+ maxSalaryPerOrg.put(orgId, maxSalary);
+ }
+
+ return new Data(orgs, persons, accounts, personsPerOrg, accountsPerPerson, accountsPerOrg, maxSalaryPerOrg);
+ }
+
+ /**
+ * @param cacheName Cache name.
+ * @param cacheMode Cache mode.
+ * @param backups Number of backups.
+ * @param idx Index flag.
+ * @param accountCache Account cache flag.
+ * @param personCache Person cache flag.
+ * @param orgCache Organization cache flag.
+ * @return Cache configuration.
+ */
+ private CacheConfiguration cacheConfiguration(String cacheName,
+ CacheMode cacheMode,
+ int backups,
+ boolean idx,
+ boolean accountCache,
+ boolean personCache,
+ boolean orgCache) {
+ CacheConfiguration ccfg = new CacheConfiguration();
+
+ ccfg.setName(cacheName);
+ ccfg.setMemoryMode(memMode);
+ ccfg.setCacheMode(cacheMode);
+
+ if (cacheMode == PARTITIONED)
+ ccfg.setBackups(backups);
+
+ ccfg.setWriteSynchronizationMode(FULL_SYNC);
+
+ List<QueryEntity> entities = new ArrayList<>();
+
+ if (accountCache) {
+ QueryEntity account = new QueryEntity();
+ account.setKeyType(useCollocatedData() ? AffinityKey.class.getName() : Integer.class.getName());
+ account.setValueType(Account.class.getName());
+ account.addQueryField("id", Integer.class.getName(), null);
+ account.addQueryField("personId", Integer.class.getName(), null);
+ account.addQueryField("personDateId", Date.class.getName(), null);
+ account.addQueryField("personStrId", String.class.getName(), null);
+
+ if (idx) {
+ account.setIndexes(F.asList(new QueryIndex("id"),
+ new QueryIndex("personId"),
+ new QueryIndex("personDateId"),
+ new QueryIndex("personStrId")));
+ }
+
+ entities.add(account);
+ }
+
+ if (personCache) {
+ QueryEntity person = new QueryEntity();
+ person.setKeyType(useCollocatedData() ? AffinityKey.class.getName() : Integer.class.getName());
+ person.setValueType(Person.class.getName());
+ person.addQueryField("id", Integer.class.getName(), null);
+ person.addQueryField("dateId", Date.class.getName(), null);
+ person.addQueryField("strId", String.class.getName(), null);
+ person.addQueryField("orgId", Integer.class.getName(), null);
+ person.addQueryField("orgDateId", Date.class.getName(), null);
+ person.addQueryField("orgStrId", String.class.getName(), null);
+ person.addQueryField("name", String.class.getName(), null);
+ person.addQueryField("salary", Integer.class.getName(), null);
+
+ if (idx) {
+ person.setIndexes(F.asList(new QueryIndex("id"),
+ new QueryIndex("dateId"),
+ new QueryIndex("strId"),
+ new QueryIndex("orgId"),
+ new QueryIndex("orgDateId"),
+ new QueryIndex("orgStrId"),
+ new QueryIndex("name"),
+ new QueryIndex("salary")));
+ }
+
+ entities.add(person);
+ }
+
+ if (orgCache) {
+ QueryEntity org = new QueryEntity();
+ org.setKeyType(Integer.class.getName());
+ org.setValueType(Organization.class.getName());
+ org.addQueryField("id", Integer.class.getName(), null);
+ org.addQueryField("dateId", Date.class.getName(), null);
+ org.addQueryField("strId", String.class.getName(), null);
+ org.addQueryField("name", String.class.getName(), null);
+
+ if (idx) {
+ org.setIndexes(F.asList(new QueryIndex("id"),
+ new QueryIndex("dateId"),
+ new QueryIndex("strId"),
+ new QueryIndex("name")));
+ }
+
+ entities.add(org);
+ }
+
+ ccfg.setQueryEntities(entities);
+
+ return ccfg;
+ }
+
+ /**
+ * @param cache Cache.
+ */
+ private void checkOrganizationPersonsJoin(IgniteCache cache) {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ORG_CACHE_NAME))
+ return;
+
+ qry = "checkOrganizationPersonsJoin";
+
+ SqlFieldsQuery qry = new SqlFieldsQuery("select o.name, p.name " +
+ "from \"" + ORG_CACHE_NAME + "\".Organization o, \"" + PERSON_CACHE_NAME + "\".Person p " +
+ "where p.orgId = o._key and o._key=?");
+
+ qry.setDistributedJoins(distributedJoins());
+
+ SqlQuery qry2 = null;
+
+ if (PERSON_CACHE_NAME.equals(cache.getName())) {
+ qry2 = new SqlQuery(Person.class,
+ "from \"" + ORG_CACHE_NAME + "\".Organization, \"" + PERSON_CACHE_NAME + "\".Person " +
+ "where Person.orgId = Organization._key and Organization._key=?"
+ );
+
+ qry2.setDistributedJoins(distributedJoins());
+ }
+
+ long total = 0;
+
+ for (int i = 0; i < data.personsPerOrg.size(); i++) {
+ qry.setArgs(i);
+
+ if (qry2 != null)
+ qry2.setArgs(i);
+
+ List<List<Object>> res = cache.query(qry).getAll();
+
+ assertEquals((int)data.personsPerOrg.get(i), res.size());
+
+ if (qry2 != null) {
+ List<List<Object>> res2 = cache.query(qry2).getAll();
+
+ assertEquals((int)data.personsPerOrg.get(i), res2.size());
+ }
+
+ total += res.size();
+ }
+
+ SqlFieldsQuery qry3 = new SqlFieldsQuery("select count(*) " +
+ "from \"" + ORG_CACHE_NAME + "\".Organization o, \"" + PERSON_CACHE_NAME + "\".Person p where p.orgId = o._key");
+
+ qry3.setDistributedJoins(distributedJoins());
+
+ List<List<Object>> res = cache.query(qry3).getAll();
+
+ assertEquals(1, res.size());
+ assertEquals(total, res.get(0).get(0));
+ }
+
+ /**
+ * @param cache Cache.
+ * @param cnts Accounts per person counts.
+ */
+ private void checkPersonAccountsJoin(IgniteCache cache, Map<Integer, Integer> cnts) {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ACC_CACHE_NAME))
+ return;
+
+ qry = "checkPersonAccountsJoin";
+
+ List<Query> qrys = new ArrayList<>();
+
+ qrys.add(new SqlFieldsQuery("select p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.id = a.personId and p.id=?")
+ );
+
+ qrys.add(new SqlFieldsQuery("select p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.dateId = a.personDateId and p.id=?")
+ );
+
+ qrys.add(new SqlFieldsQuery("select p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.strId = a.personStrId and p.id=?")
+ );
+
+ qrys.add(new SqlFieldsQuery("select p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.id = a.personId and p.id=?")
+ );
+
+ qrys.add(new SqlFieldsQuery("select p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.dateId = a.personDateId and p.id=?")
+ );
+
+ qrys.add(new SqlFieldsQuery("select p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.strId = a.personStrId and p.id=?")
+ );
+
+ if (PERSON_CACHE_NAME.equals(cache.getName())) {
+ qrys.add(new SqlQuery(Person.class,
+ "from \"" + PERSON_CACHE_NAME + "\".Person , \"" + ACC_CACHE_NAME + "\".Account " +
+ "where Person.id = Account.personId and Person.id=?")
+ );
+
+ qrys.add(new SqlQuery(Person.class,
+ "from \"" + PERSON_CACHE_NAME + "\".Person , \"" + ACC_CACHE_NAME + "\".Account " +
+ "where Person.id = Account.personId and Person.id=?")
+ );
+ }
+
+ List<Integer> keys = new ArrayList<>(cnts.keySet());
+
+ for (int i = 0; i < 10; i++) {
+ Integer key = keys.get(rnd.nextInt(keys.size()));
+
+ List<List<Object>> res;
+
+ for (Query q : qrys) {
+ if (q instanceof SqlFieldsQuery) {
+ ((SqlFieldsQuery)q).setDistributedJoins(distributedJoins());
+
+ ((SqlFieldsQuery)q).setArgs(key);
+ }
+ else {
+ ((SqlQuery)q).setDistributedJoins(distributedJoins());
+
+ ((SqlQuery)q).setArgs(key);
+ }
+
+ res = cache.query(q).getAll();
+
+ assertEquals((int)cnts.get(key), res.size());
+ }
+ }
+
+ qrys.clear();
+
+ qrys.add(new SqlFieldsQuery("select count(*) " +
+ "from \"" + PERSON_CACHE_NAME + "\".Person p, \"" + ACC_CACHE_NAME + "\".Account" + " a " +
+ "where p.id = a.personId"));
+
+ qrys.add(new SqlFieldsQuery("select count(*) " +
+ "from \"" + PERSON_CACHE_NAME + "\".Person p, \"" + ACC_CACHE_NAME + "\".Account" + " a " +
+ "where p.Dateid = a.personDateId"));
+
+ qrys.add(new SqlFieldsQuery("select count(*) " +
+ "from \"" + PERSON_CACHE_NAME + "\".Person p, \"" + ACC_CACHE_NAME + "\".Account" + " a " +
+ "where p.strId = a.personStrId"));
+
+ qrys.add(new SqlFieldsQuery("select count(*) " +
+ "from \"" + PERSON_CACHE_NAME + "\".Person p, \"" + ACC_CACHE_NAME + "\".Account" + " a " +
+ "where p.id = a.personId"));
+
+ long total = 0;
+
+ for (Integer cnt : data.accountsPerPerson.values())
+ total += cnt;
+
+ for (Query q : qrys) {
+ ((SqlFieldsQuery)q).setDistributedJoins(distributedJoins());
+
+ List<List<Object>> res = cache.query(q).getAll();
+
+ assertEquals(1, res.size());
+ assertEquals(total, res.get(0).get(0));
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @throws Exception If failed.
+ */
+ private void checkOrganizationPersonAccountJoin(IgniteCache cache) throws Exception {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ORG_CACHE_NAME, ACC_CACHE_NAME))
+ return;
+
+ qry = "checkOrganizationPersonAccountJoin";
+
+ List<String> sqlFields = new ArrayList<>();
+
+ sqlFields.add("select o.name, p.name, a._key " +
+ "from " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o, " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.orgId = o.id and p.id = a.personId and o.id = ?");
+
+ sqlFields.add("select o.name, p.name, a._key " +
+ "from " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o, " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.orgDateId = o.dateId and p.strId = a.personStrId and o.id = ?");
+
+ sqlFields.add("select o.name, p.name, a._key " +
+ "from " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o, " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.orgStrId = o.strId and p.id = a.personId and o.id = ?");
+
+ for (Organization org : data.orgs) {
+ for (String sql : sqlFields)
+ compareQueryRes0(cache, sql, distributedJoins(), new Object[] {org.id}, Ordering.RANDOM);
+ }
+
+ if (ACC_CACHE_NAME.equals(cache.getName())) {
+ for (int orgId = 0; orgId < data.accountsPerOrg.size(); orgId++) {
+ SqlQuery q = new SqlQuery(Account.class, "from " +
+ "\"" + ORG_CACHE_NAME + "\".Organization , " +
+ "\"" + PERSON_CACHE_NAME + "\".Person , " +
+ "\"" + ACC_CACHE_NAME + "\".Account " +
+ "where Person.orgId = Organization.id and Person.id = Account.personId and Organization.id = ?");
+
+ q.setDistributedJoins(distributedJoins());
+
+ q.setArgs(orgId);
+
+ List<List<Object>> res = cache.query(q).getAll();
+
+ assertEquals((int)data.accountsPerOrg.get(orgId), res.size());
+ }
+ }
+
+ String sql = "select count(*) " +
+ "from " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o, " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.orgId = o.id and p.id = a.personId";
+
+ compareQueryRes0(cache, sql, distributedJoins(), new Object[0], Ordering.RANDOM);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ private void checkUnionAll() throws Exception {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ACC_CACHE_NAME, ORG_CACHE_NAME))
+ return;
+
+ qry = "checkUnionAll";
+
+ String sql = "select a.id, p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.id = a.personId and p.id = ? " +
+ "union all " +
+ "select p.id, o.name from " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o, " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p " +
+ "where p.orgStrId = o.strId and o.id = ?";
+
+ for (int i = 0; i < 10; i++) {
+ Person person = data.persons.get(rnd.nextInt(data.persons.size()));
+
+ for (Organization org : data.orgs)
+ compareQueryRes0(cache, sql, distributedJoins(), new Object[] {person.id, org.id}, Ordering.RANDOM);
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ private void checkUnion() throws Exception {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ACC_CACHE_NAME, ORG_CACHE_NAME))
+ return;
+
+ qry = "checkUnion";
+
+ String sql = "select a.id, p.name from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.id = a.personId and p.id = ? " +
+ "union " +
+ "select p.id, o.name from " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o, " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p " +
+ "where p.orgStrId = o.strId and o.id = ?";
+
+ for (int i = 0; i < 10; i++) {
+ Person person = data.persons.get(rnd.nextInt(data.persons.size()));
+
+ for (Organization org : data.orgs)
+ compareQueryRes0(cache, sql, distributedJoins(), new Object[] {person.id, org.id}, Ordering.RANDOM);
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ * @throws Exception If failed.
+ */
+ private void checkPersonAccountCrossJoin(IgniteCache cache) throws Exception {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ACC_CACHE_NAME))
+ return;
+
+ qry = "checkPersonAccountCrossJoin";
+
+ String sql = "select p.name " +
+ "from \"" + PERSON_CACHE_NAME + "\".Person p " +
+ "cross join \"" + ACC_CACHE_NAME + "\".Account a";
+
+ compareQueryRes0(cache, sql, distributedJoins(), new Object[0], Ordering.RANDOM);
+ }
+
+ /**
+ * @param cache Cache.
+ */
+ private void checkPersonOrganizationGroupBy(IgniteCache cache) {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ORG_CACHE_NAME))
+ return;
+
+ qry = "checkPersonOrganizationGroupBy";
+
+ // Max salary per organization.
+ SqlFieldsQuery q = new SqlFieldsQuery("select max(p.salary) " +
+ "from \"" + PERSON_CACHE_NAME + "\".Person p join \"" + ORG_CACHE_NAME + "\".Organization o " +
+ "on p.orgId = o.id " +
+ "group by o.name " +
+ "having o.id = ?");
+
+ q.setDistributedJoins(distributedJoins());
+
+ for (Map.Entry<Integer, Integer> e : data.maxSalaryPerOrg.entrySet()) {
+ Integer orgId = e.getKey();
+ Integer maxSalary = e.getValue();
+
+ q.setArgs(orgId);
+
+ List<List<?>> res = cache.query(q).getAll();
+
+ String errMsg = "Expected data [orgId=" + orgId + ", maxSalary=" + maxSalary + ", data=" + data + "]";
+
+ // MaxSalary == -1 means that there are no persons at organization.
+ if (maxSalary > 0) {
+ assertEquals(errMsg, 1, res.size());
+ assertEquals(errMsg, 1, res.get(0).size());
+ assertEquals(errMsg, maxSalary, res.get(0).get(0));
+ }
+ else
+ assertEquals(errMsg, 0, res.size());
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ */
+ private void checkPersonAccountGroupBy(IgniteCache cache) {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ACC_CACHE_NAME))
+ return;
+
+ qry = "checkPersonAccountGroupBy";
+
+ // Count accounts per person.
+ SqlFieldsQuery q = new SqlFieldsQuery("select count(a.id) " +
+ "from \"" + PERSON_CACHE_NAME + "\".Person p join \"" + ACC_CACHE_NAME + "\".Account a " +
+ "on p.strId = a.personStrId " +
+ "group by p.name " +
+ "having p.id = ?");
+
+ q.setDistributedJoins(distributedJoins());
+
+ List<Integer> keys = new ArrayList<>(data.accountsPerPerson.keySet());
+
+ for (int i = 0; i < 10; i++) {
+ Integer personId = keys.get(rnd.nextInt(keys.size()));
+ Integer cnt = data.accountsPerPerson.get(personId);
+
+ q.setArgs(personId);
+
+ List<List<?>> res = cache.query(q).getAll();
+
+ String errMsg = "Expected data [personId=" + personId + ", cnt=" + cnt + ", data=" + data + "]";
+
+ // Cnt == 0 means that there are no accounts for the person.
+ if (cnt > 0) {
+ assertEquals(errMsg, 1, res.size());
+ assertEquals(errMsg, 1, res.get(0).size());
+ assertEquals(errMsg, (long)cnt, res.get(0).get(0));
+ }
+ else
+ assertEquals(errMsg, 0, res.size());
+ }
+ }
+
+ /**
+ * @param cache Cache.
+ */
+ private void checkPersonAccountOrganizationGroupBy(IgniteCache cache) {
+ qry = "checkPersonAccountOrganizationGroupBy";
+
+ // Max count of accounts at org.
+ SqlFieldsQuery q = new SqlFieldsQuery("select max(count(a.id)) " +
+ "from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.id = a.personId and p.orgStrId = o.strId " +
+ "group by org.id " +
+ "having o.id = ?");
+
+ q.setDistributedJoins(distributedJoins());
+
+ for (Map.Entry<Integer, Integer> e : data.accountsPerPerson.entrySet()) {
+ Integer personId = e.getKey();
+ Integer cnt = e.getValue();
+
+ q.setArgs(personId);
+
+ List<List<?>> res = cache.query(q).getAll();
+
+ String errMsg = "Expected data [personId=" + personId + ", cnt=" + cnt + ", data=" + data + "]";
+
+ // Cnt == 0 means that there are no accounts for the person.
+ if (cnt > 0) {
+ assertEquals(errMsg, 1, res.size());
+ assertEquals(errMsg, 1, res.get(0).size());
+ assertEquals(errMsg, (long)cnt, res.get(0).get(0));
+ }
+ else
+ assertEquals(errMsg, 0, res.size());
+ }
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ private void checkGroupBy() throws Exception {
+ if (skipQuery(cache, PERSON_CACHE_NAME, ACC_CACHE_NAME, ORG_CACHE_NAME))
+ return;
+
+ qry = "checkGroupBy";
+
+ // Select persons with count of accounts of person at organization.
+ String sql = "select p.id, count(a.id) " +
+ "from " +
+ "\"" + PERSON_CACHE_NAME + "\".Person p, " +
+ "\"" + ORG_CACHE_NAME + "\".Organization o, " +
+ "\"" + ACC_CACHE_NAME + "\".Account a " +
+ "where p.id = a.personId and p.orgStrId = o.strId " +
+ "group by p.id " +
+ "having o.id = ?";
+
+ for (Organization org : data.orgs)
+ compareQueryRes0(cache, sql, distributedJoins(), new Object[] {org.id}, Ordering.RANDOM);
+ }
+
+ /**
+ * @param cache Cache used to run query.
+ * @param caches Cache names.
+ * @return {@code True} if skip query execution.
+ */
+ private boolean skipQuery(IgniteCache cache, String... caches) {
+ // Skip join replicated/partitioned caches executed on replicated cache.
+ Ignite node = (Ignite)cache.unwrap(Ignite.class);
+
+ if (!distributedJoins() && replicated(cache)) {
+ for (String cacheName : caches) {
+ if (!replicated(node.cache(cacheName)))
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ *
+ */
+ private enum TestCacheType {
+ /** */
+ REPLICATED(CacheMode.REPLICATED, 0),
+
+ /** */
+ PARTITIONED_b0(CacheMode.PARTITIONED, 0),
+
+ /** */
+ PARTITIONED_b1(CacheMode.PARTITIONED, 1);
+
+ /** */
+ final CacheMode cacheMode;
+
+ /** */
+ final int backups;
+
+ /**
+ * @param mode Cache mode.
+ * @param backups Backups.
+ */
+ TestCacheType(CacheMode mode, int backups) {
+ cacheMode = mode;
+ this.backups = backups;
+ }
+ }
+
+ /**
+ *
+ */
+ private static class TestCache {
+ /** */
+ @GridToStringInclude
+ final String cacheName;
+
+ /** */
+ @GridToStringInclude
+ final TestCacheType type;
+
+ /**
+ * @param cacheName Cache name.
+ * @param type Cache type.
+ */
+ public TestCache(String cacheName, TestCacheType type) {
+ this.cacheName = cacheName;
+ this.type = type;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(TestCache.class, this);
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Data {
+ /** */
+ final List<Organization> orgs;
+
+ /** */
+ final List<Person> persons;
+
+ /** */
+ final List<Account> accounts;
+
+ /** */
+ final Map<Integer, Integer> personsPerOrg;
+
+ /** PersonId to count of accounts that person has. */
+ final Map<Integer, Integer> accountsPerPerson;
+
+ /** */
+ final Map<Integer, Integer> accountsPerOrg;
+
+ /** */
+ final Map<Integer, Integer> maxSalaryPerOrg;
+
+ /**
+ * @param orgs Organizations.
+ * @param persons Persons.
+ * @param accounts Accounts.
+ * @param personsPerOrg Count of persons per organization.
+ * @param accountsPerPerson Count of accounts per person.
+ * @param accountsPerOrg Count of accounts per organization.
+ * @param maxSalaryPerOrg Maximum salary per organization.
+ */
+ Data(List<Organization> orgs,
+ List<Person> persons,
+ List<Account> accounts,
+ Map<Integer, Integer> personsPerOrg,
+ Map<Integer, Integer> accountsPerPerson,
+ Map<Integer, Integer> accountsPerOrg,
+ Map<Integer, Integer> maxSalaryPerOrg) {
+ this.orgs = orgs;
+ this.persons = persons;
+ this.accounts = accounts;
+ this.personsPerOrg = personsPerOrg;
+ this.accountsPerPerson = accountsPerPerson;
+ this.accountsPerOrg = accountsPerOrg;
+ this.maxSalaryPerOrg = maxSalaryPerOrg;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "Data [" +
+ "orgs=" + orgs +
+ ", persons=" + persons +
+ ", accounts=" + accounts +
+ ", personsPerOrg=" + personsPerOrg +
+ ", accountsPerPerson=" + accountsPerPerson +
+ ", accountsPerOrg=" + accountsPerOrg +
+ ", maxSalaryPerOrg=" + maxSalaryPerOrg +
+ ']';
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Account implements Serializable {
+ /** */
+ @QuerySqlField
+ private int id;
+
+ /** */
+ @QuerySqlField
+ private int personId;
+
+ /** */
+ @QuerySqlField
+ private Date personDateId;
+
+ /** */
+ @QuerySqlField
+ private String personStrId;
+
+ /** */
+ @QuerySqlField
+ private int orgId;
+
+ /**
+ * @param id ID.
+ * @param personId Person ID.
+ * @param orgId Organization ID.
+ */
+ Account(int id, int personId, int orgId) {
+ this.id = id;
+ this.personId = personId;
+ this.orgId = orgId;
+ personDateId = new Date(personId);
+ personStrId = "personId" + personId;
+ }
+
+ /**
+ * @param useCollocatedData Use colocated data.
+ * @return Key.
+ */
+ public Object key(boolean useCollocatedData) {
+ return useCollocatedData ? new AffinityKey<>(id, orgId) : id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "Account [" +
+ "id=" + id +
+ ", personId=" + personId +
+ ']';
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Person implements Serializable {
+ /** */
+ @QuerySqlField
+ int id;
+
+ /** Date as ID. */
+ @QuerySqlField
+ Date dateId;
+
+ /** String as ID */
+ @QuerySqlField
+ String strId;
+
+ /** */
+ @QuerySqlField
+ int orgId;
+
+ /** */
+ @QuerySqlField
+ Date orgDateId;
+
+ /** */
+ @QuerySqlField
+ String orgStrId;
+
+ /** */
+ @QuerySqlField
+ String name;
+
+ /** */
+ @QuerySqlField
+ int salary;
+
+ /**
+ * @param id ID.
+ * @param orgId Organization ID.
+ * @param name Name.
+ * @param salary Salary.
+ */
+ Person(int id, int orgId, String name, int salary) {
+ this.id = id;
+ dateId = new Date(id);
+ strId = "personId" + id;
+ this.orgId = orgId;
+ orgDateId = new Date(orgId);
+ orgStrId = "orgId" + orgId;
+ this.name = name;
+ this.salary = salary;
+ }
+
+ /**
+ * @param useCollocatedData Use collocated data.
+ * @return Key.
+ */
+ public Object key(boolean useCollocatedData) {
+ return useCollocatedData ? new AffinityKey<>(id, orgId) : id;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "Person [" +
+ "id=" + id +
+ ", orgId=" + orgId +
+ ", name='" + name + '\'' +
+ ", salary=" + salary +
+ ']';
+ }
+ }
+
+ /**
+ *
+ */
+ private static class Organization implements Serializable {
+ /** */
+ @QuerySqlField
+ int id;
+
+ /** */
+ @QuerySqlField
+ Date dateId;
+
+ /** */
+ @QuerySqlField
+ String strId;
+
+ /** */
+ @QuerySqlField
+ String name;
+
+ /**
+ * @param id ID.
+ * @param name Name.
+ */
+ Organization(int id, String name) {
+ this.id = id;
+ dateId = new Date(id);
+ strId = "orgId" + id;
+ this.name = name;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "Organization [" +
+ "name='" + name + '\'' +
+ ", id=" + id +
+ ']';
+ }
+ }
+
+ /**
+ *
+ */
+ private static class TestConfig {
+ /** */
+ private final int idx;
+
+ /** */
+ private final IgniteCache testedCache;
+
+ /** */
+ private final TestCache personCache;
+
+ /** */
+ private final TestCache accCache;
+
+ /** */
+ private final TestCache orgCache;
+
+ /** */
+ private final String qry;
+
+ /**
+ * @param cfgIdx Tested configuration index.
+ * @param testedCache Tested testedCache.
+ * @param personCacheType Person testedCache personCacheType.
+ * @param accCacheType Account testedCache personCacheType.
+ * @param orgCacheType Organization testedCache personCacheType.
+ * @param testedQry Query.
+ */
+ TestConfig(int cfgIdx,
+ IgniteCache testedCache,
+ TestCache personCacheType,
+ TestCache accCacheType,
+ TestCache orgCacheType,
+ String testedQry) {
+ idx = cfgIdx;
+ this.testedCache = testedCache;
+ this.personCache = personCacheType;
+ this.accCache = accCacheType;
+ this.orgCache = orgCacheType;
+ qry = testedQry;
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return "TestConfig [" +
+ "idx=" + idx +
+ ", testedCache=" + testedCache.getName() +
+ ", personCache=" + personCache +
+ ", accCache=" + accCache +
+ ", orgCache=" + orgCache +
+ ", qry=" + qry +
+ ']';
+ }
+ }
+}
[02/50] [abbrv] ignite git commit: Merge remote-tracking branch
'remotes/community/ignite-1.6.3'
Posted by vo...@apache.org.
Merge remote-tracking branch 'remotes/community/ignite-1.6.3'
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a989f04e
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a989f04e
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a989f04e
Branch: refs/heads/ignite-3553
Commit: a989f04ec08638855f13ef4195ce7d9d1efee083
Parents: f7e8a6d 0f1a0cc
Author: Denis Magda <dm...@gridgain.com>
Authored: Fri Jul 22 14:20:16 2016 +0300
Committer: Denis Magda <dm...@gridgain.com>
Committed: Fri Jul 22 14:20:16 2016 +0300
----------------------------------------------------------------------
.../binary/CacheObjectBinaryProcessorImpl.java | 6 +
.../internal/processors/igfs/IgfsImpl.java | 77 ++---
.../processors/igfs/IgfsModeResolver.java | 94 +-----
.../internal/processors/igfs/IgfsUtils.java | 83 +++++
.../BinaryObjectBuilderAdditionalSelfTest.java | 38 ++-
...sCachePerBlockLruEvictionPolicySelfTest.java | 7 +-
.../processors/igfs/IgfsMetricsSelfTest.java | 54 +--
.../igfs/IgfsModeResolverSelfTest.java | 124 +++++--
.../processors/igfs/IgfsModesSelfTest.java | 61 ++--
.../hadoop/fs/v2/IgniteHadoopFileSystem.java | 22 +-
.../igfs/HadoopFIleSystemFactorySelfTest.java | 2 +-
...teHadoopFileSystemSecondaryModeSelfTest.java | 327 -------------------
.../testsuites/IgniteHadoopTestSuite.java | 2 -
.../stream/kafka/connect/package-info.java | 21 ++
.../connect/serialization/package-info.java | 21 ++
15 files changed, 360 insertions(+), 579 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a989f04e/modules/core/src/main/java/org/apache/ignite/internal/processors/igfs/IgfsImpl.java
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a989f04e/modules/core/src/test/java/org/apache/ignite/internal/processors/igfs/IgfsModesSelfTest.java
----------------------------------------------------------------------
[24/50] [abbrv] ignite git commit: ignite-3573 Support of Distributed
joins queries in REST API
Posted by vo...@apache.org.
ignite-3573 Support of Distributed joins queries in REST API
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/f245c383
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/f245c383
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/f245c383
Branch: refs/heads/ignite-3553
Commit: f245c3838bd2eda4aa11b0bd0d07223b9cb2f237
Parents: 0e15cf1
Author: agura <ag...@gridgain.com>
Authored: Mon Jul 25 14:31:10 2016 +0300
Committer: agura <ag...@gridgain.com>
Committed: Mon Jul 25 15:22:47 2016 +0300
----------------------------------------------------------------------
.../JettyRestProcessorAbstractSelfTest.java | 121 ++++++++++++++++++-
.../handlers/query/QueryCommandHandler.java | 4 +
.../rest/request/RestQueryRequest.java | 17 +++
.../http/jetty/GridJettyRestHandler.java | 5 +
4 files changed, 142 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/f245c383/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
index 0dd12ac..8d3ab74 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
@@ -1687,6 +1687,32 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
/**
* @throws Exception If failed.
*/
+ public void testDistributedJoinsQuery() throws Exception {
+ String qry = "select * from Person, \"organization\".Organization " +
+ "where \"organization\".Organization.id = Person.orgId " +
+ "and \"organization\".Organization.name = ?";
+
+ Map<String, String> params = new HashMap<>();
+ params.put("cmd", GridRestCommand.EXECUTE_SQL_QUERY.key());
+ params.put("type", "Person");
+ params.put("distributedJoins", "true");
+ params.put("pageSize", "10");
+ params.put("cacheName", "person");
+ params.put("qry", URLEncoder.encode(qry, CHARSET));
+ params.put("arg1", "o1");
+
+ String ret = content(params);
+
+ JsonNode items = jsonResponse(ret).get("items");
+
+ assertEquals(2, items.size());
+
+ assertFalse(queryCursorFound());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
public void testSqlFieldsQuery() throws Exception {
String qry = "select concat(firstName, ' ', lastName) from Person";
@@ -1708,6 +1734,28 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
/**
* @throws Exception If failed.
*/
+ public void testDistributedJoinsSqlFieldsQuery() throws Exception {
+ String qry = "select * from \"person\".Person p, \"organization\".Organization o where o.id = p.orgId";
+
+ Map<String, String> params = new HashMap<>();
+ params.put("cmd", GridRestCommand.EXECUTE_SQL_FIELDS_QUERY.key());
+ params.put("distributedJoins", "true");
+ params.put("pageSize", "10");
+ params.put("cacheName", "person");
+ params.put("qry", URLEncoder.encode(qry, CHARSET));
+
+ String ret = content(params);
+
+ JsonNode items = jsonResponse(ret).get("items");
+
+ assertEquals(4, items.size());
+
+ assertFalse(queryCursorFound());
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
public void testSqlFieldsMetadataQuery() throws Exception {
String qry = "select firstName, lastName from Person";
@@ -1831,6 +1879,20 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
* Init cache.
*/
private void initCache() {
+ CacheConfiguration<Integer, Organization> orgCacheCfg = new CacheConfiguration<>("organization");
+
+ orgCacheCfg.setIndexedTypes(Integer.class, Organization.class);
+
+ IgniteCache<Integer, Organization> orgCache = ignite(0).getOrCreateCache(orgCacheCfg);
+
+ orgCache.clear();
+
+ Organization o1 = new Organization(1, "o1");
+ Organization o2 = new Organization(2, "o2");
+
+ orgCache.put(1, o1);
+ orgCache.put(2, o2);
+
CacheConfiguration<Integer, Person> personCacheCfg = new CacheConfiguration<>("person");
personCacheCfg.setIndexedTypes(Integer.class, Person.class);
@@ -1839,10 +1901,10 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
personCache.clear();
- Person p1 = new Person("John", "Doe", 2000);
- Person p2 = new Person("Jane", "Doe", 1000);
- Person p3 = new Person("John", "Smith", 1000);
- Person p4 = new Person("Jane", "Smith", 2000);
+ Person p1 = new Person(1, "John", "Doe", 2000);
+ Person p2 = new Person(1, "Jane", "Doe", 1000);
+ Person p3 = new Person(2, "John", "Smith", 1000);
+ Person p4 = new Person(2, "Jane", "Smith", 2000);
personCache.put(p1.getId(), p1);
personCache.put(p2.getId(), p2);
@@ -1856,6 +1918,43 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
assertEquals(2, personCache.query(qry).getAll().size());
}
+
+ /**
+ * Organization class.
+ */
+ public static class Organization implements Serializable {
+ /** Organization ID (indexed). */
+ @QuerySqlField(index = true)
+ private Integer id;
+
+ /** First name (not-indexed). */
+ @QuerySqlField(index = true)
+ private String name;
+
+ /**
+ * @param id Id.
+ * @param name Name.
+ */
+ Organization(Integer id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ /**
+ * @return Id.
+ */
+ public Integer getId() {
+ return id;
+ }
+
+ /**
+ * @return Name.
+ */
+ public String getName() {
+ return name;
+ }
+ }
+
/**
* Person class.
*/
@@ -1867,6 +1966,10 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
@QuerySqlField(index = true)
private Integer id;
+ /** Organization id. */
+ @QuerySqlField(index = true)
+ private Integer orgId;
+
/** First name (not-indexed). */
@QuerySqlField
private String firstName;
@@ -1884,15 +1987,23 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
* @param lastName Last name.
* @param salary Salary.
*/
- Person(String firstName, String lastName, double salary) {
+ Person(Integer orgId, String firstName, String lastName, double salary) {
id = PERSON_ID++;
+ this.orgId = orgId;
this.firstName = firstName;
this.lastName = lastName;
this.salary = salary;
}
/**
+ * @return Organization ID.
+ */
+ public Integer getOrganizationId() {
+ return orgId;
+ }
+
+ /**
* @return First name.
*/
public String getFirstName() {
http://git-wip-us.apache.org/repos/asf/ignite/blob/f245c383/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
index 67e146b..4317dd9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
@@ -278,6 +278,8 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
((SqlQuery)qry).setArgs(req.arguments());
+ ((SqlQuery)qry).setDistributedJoins(req.distributedJoins());
+
break;
case SQL_FIELDS:
@@ -285,6 +287,8 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
((SqlFieldsQuery)qry).setArgs(req.arguments());
+ ((SqlFieldsQuery)qry).setDistributedJoins(req.distributedJoins());
+
break;
case SCAN:
http://git-wip-us.apache.org/repos/asf/ignite/blob/f245c383/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
index a719776..7159c83 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
@@ -32,6 +32,9 @@ public class RestQueryRequest extends GridRestRequest {
/** Page size. */
private Integer pageSize;
+ /** Distributed joins. */
+ private boolean distributedJoins;
+
/** Cache name. */
private String cacheName;
@@ -90,6 +93,20 @@ public class RestQueryRequest extends GridRestRequest {
}
/**
+ * @param distributedJoins New distributed joins.
+ */
+ public void distributedJoins(boolean distributedJoins) {
+ this.distributedJoins = distributedJoins;
+ }
+
+ /**
+ * @return Distributed joins.
+ */
+ public boolean distributedJoins() {
+ return distributedJoins;
+ }
+
+ /**
* @param cacheName Cache name.
*/
public void cacheName(String cacheName) {
http://git-wip-us.apache.org/repos/asf/ignite/blob/f245c383/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
----------------------------------------------------------------------
diff --git a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
index c2679df..c864a10 100644
--- a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
+++ b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
@@ -566,6 +566,11 @@ public class GridJettyRestHandler extends AbstractHandler {
if (pageSize != null)
restReq0.pageSize(Integer.parseInt(pageSize));
+ String distributedJoins = (String)params.get("distributedJoins");
+
+ if (distributedJoins != null)
+ restReq0.distributedJoins(Boolean.parseBoolean(distributedJoins));
+
restReq0.cacheName((String)params.get("cacheName"));
if (cmd == EXECUTE_SQL_QUERY)
[34/50] [abbrv] ignite git commit:
IgniteCacheRandomOperationBenchmark: removed unnecessary output.
Posted by vo...@apache.org.
IgniteCacheRandomOperationBenchmark: removed unnecessary output.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/422c9a83
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/422c9a83
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/422c9a83
Branch: refs/heads/ignite-3553
Commit: 422c9a8320b4a11c64ab95311a9897fdb48e6ed6
Parents: e754724
Author: sboikov <sb...@gridgain.com>
Authored: Tue Jul 26 16:25:50 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Tue Jul 26 16:25:50 2016 +0300
----------------------------------------------------------------------
.../yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java | 2 --
1 file changed, 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/422c9a83/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
index c2947ba..e62df45 100644
--- a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/load/IgniteCacheRandomOperationBenchmark.java
@@ -885,8 +885,6 @@ public class IgniteCacheRandomOperationBenchmark extends IgniteAbstractBenchmark
else {
String sql = rendomizeSql();
- BenchmarkUtils.println(sql);
-
sq = new SqlFieldsQuery(sql);
}