You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2018/09/20 14:19:25 UTC
ignite git commit: IGNITE-9519: SQL: Allow complex object inline into
indexes. This closes #4724.
Repository: ignite
Updated Branches:
refs/heads/master 04f074023 -> a6e97d146
IGNITE-9519: SQL: Allow complex object inline into indexes. This closes #4724.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/a6e97d14
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/a6e97d14
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/a6e97d14
Branch: refs/heads/master
Commit: a6e97d146db68dc510616ef4bd14281d3bba0a8e
Parents: 04f0740
Author: Stanislav Lukyanov <sl...@gridgain.com>
Authored: Thu Sep 20 17:19:17 2018 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Thu Sep 20 17:19:17 2018 +0300
----------------------------------------------------------------------
.../internal/binary/BinaryObjectImpl.java | 2 +-
.../query/h2/database/InlineIndexHelper.java | 32 +-
.../query/h2/opt/GridH2ValueCacheObject.java | 6 +
.../processors/cache/index/BasicIndexTest.java | 820 +++++++++++++++++++
.../h2/database/InlineIndexHelperTest.java | 148 +++-
.../IgniteCacheQuerySelfTestSuite.java | 3 +
6 files changed, 981 insertions(+), 30 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6e97d14/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 7ab8b35..65fb349 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
@@ -205,7 +205,7 @@ public final class BinaryObjectImpl extends BinaryObjectExImpl implements Extern
/**
* @return Detached binary object.
*/
- public BinaryObject detach() {
+ public BinaryObjectImpl detach() {
if (!detachAllowed || detached())
return this;
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6e97d14/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java
index 05d5c46..0299033 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelper.java
@@ -35,6 +35,7 @@ import org.h2.value.ValueDate;
import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
+import org.h2.value.ValueJavaObject;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
@@ -70,7 +71,8 @@ public class InlineIndexHelper {
Value.STRING,
Value.STRING_FIXED,
Value.STRING_IGNORECASE,
- Value.BYTES
+ Value.BYTES,
+ Value.JAVA_OBJECT
);
/** */
@@ -153,6 +155,7 @@ public class InlineIndexHelper {
case Value.STRING_FIXED:
case Value.STRING_IGNORECASE:
case Value.BYTES:
+ case Value.JAVA_OBJECT:
this.size = -1;
break;
@@ -298,6 +301,9 @@ public class InlineIndexHelper {
case Value.BYTES:
return ValueBytes.get(readBytes(pageAddr, off));
+ case Value.JAVA_OBJECT:
+ return ValueJavaObject.getNoCopy(null, readBytes(pageAddr, off), null);
+
default:
throw new UnsupportedOperationException("no get operation for fast index type " + type);
}
@@ -327,6 +333,7 @@ public class InlineIndexHelper {
case Value.STRING_FIXED:
case Value.STRING_IGNORECASE:
case Value.BYTES:
+ case Value.JAVA_OBJECT:
return (PageUtils.getShort(pageAddr, off + 1) & 0x8000) == 0;
default:
@@ -417,6 +424,7 @@ public class InlineIndexHelper {
return compareAsUUID(pageAddr, off, v, type);
case Value.BYTES:
+ case Value.JAVA_OBJECT:
return compareAsBytes(pageAddr, off, v);
}
@@ -900,23 +908,30 @@ public class InlineIndexHelper {
}
}
- case Value.BYTES: {
+ case Value.BYTES:
+ case Value.JAVA_OBJECT:
+ {
short size;
PageUtils.putByte(pageAddr, off, (byte)val.getType());
- if (val.getBytes().length + 3 <= maxSize) {
- size = (short)val.getBytes().length;
+ byte[] bytes = val.getBytes();
+
+ if (bytes.length + 3 <= maxSize) {
+ size = (short)bytes.length;
PageUtils.putShort(pageAddr, off + 1, size);
- PageUtils.putBytes(pageAddr, off + 3, val.getBytes());
+ PageUtils.putBytes(pageAddr, off + 3, bytes);
+
+ return size + 3;
}
else {
size = (short)((maxSize - 3) | 0x8000);
PageUtils.putShort(pageAddr, off + 1, size);
- PageUtils.putBytes(pageAddr, off + 3, Arrays.copyOfRange(val.getBytes(), 0, maxSize - 3));
+ PageUtils.putBytes(pageAddr, off + 3, Arrays.copyOfRange(bytes, 0, maxSize - 3));
+
+ return maxSize;
}
- return size + 3;
}
default:
@@ -959,6 +974,7 @@ public class InlineIndexHelper {
case Value.STRING_FIXED:
case Value.STRING_IGNORECASE:
case Value.BYTES:
+ case Value.JAVA_OBJECT:
if (shortVal.getType() == Value.NULL || v2.getType() == Value.NULL)
return true;
@@ -968,7 +984,7 @@ public class InlineIndexHelper {
int l1;
int l2;
- if (type == Value.BYTES) {
+ if (type == Value.BYTES || type == Value.JAVA_OBJECT) {
l1 = shortVal.getBytes().length;
l2 = v2.getBytes().length;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6e97d14/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 d18668f..9b5f0d5 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
@@ -21,6 +21,7 @@ import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.internal.binary.BinaryObjectImpl;
import org.apache.ignite.internal.processors.cache.CacheObject;
import org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
import org.h2.message.DbException;
@@ -49,6 +50,11 @@ public class GridH2ValueCacheObject extends Value {
public GridH2ValueCacheObject(CacheObject obj, CacheObjectValueContext valCtx) {
assert obj != null;
+ if (obj instanceof BinaryObjectImpl) {
+ ((BinaryObjectImpl)obj).detachAllowed(true);
+ obj = ((BinaryObjectImpl)obj).detach();
+ }
+
this.obj = obj;
this.valCtx = valCtx;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6e97d14/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java
new file mode 100644
index 0000000..feb330b
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/BasicIndexTest.java
@@ -0,0 +1,820 @@
+/*
+ * 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.index;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Objects;
+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.query.SqlFieldsQuery;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.DataRegionConfiguration;
+import org.apache.ignite.configuration.DataStorageConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
+import org.apache.ignite.internal.processors.cache.persistence.file.FilePageStoreManager;
+import org.apache.ignite.internal.util.typedef.internal.S;
+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;
+
+/**
+ * A set of basic tests for caches with indexes.
+ */
+public class BasicIndexTest extends GridCommonAbstractTest {
+ /** */
+ private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true);
+
+ /** */
+ private Collection<QueryIndex> indexes;
+
+ /** */
+ private Integer inlineSize;
+
+ /** */
+ private Boolean isPersistenceEnabled;
+
+ /** */
+ private String affKeyFieldName;
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
+ assertNotNull(indexes);
+
+ assertNotNull(inlineSize);
+
+ assertNotNull(isPersistenceEnabled);
+
+ for (QueryIndex index : indexes) {
+ index.setInlineSize(inlineSize);
+ }
+
+ IgniteConfiguration igniteCfg = super.getConfiguration(igniteInstanceName);
+
+ igniteCfg.setDiscoverySpi(
+ new TcpDiscoverySpi().setIpFinder(IP_FINDER)
+ );
+
+ LinkedHashMap<String, String> fields = new LinkedHashMap<>();
+ fields.put("keyStr", String.class.getName());
+ fields.put("keyLong", Long.class.getName());
+ fields.put("keyPojo", Pojo.class.getName());
+ fields.put("valStr", String.class.getName());
+ fields.put("valLong", Long.class.getName());
+ fields.put("valPojo", Pojo.class.getName());
+
+ CacheConfiguration<Key, Val> ccfg = new CacheConfiguration<Key, Val>(DEFAULT_CACHE_NAME)
+ .setQueryEntities(Collections.singleton(
+ new QueryEntity()
+ .setKeyType(Key.class.getName())
+ .setValueType(Val.class.getName())
+ .setFields(fields)
+ .setIndexes(indexes)
+ ))
+ .setSqlIndexMaxInlineSize(inlineSize);
+
+ if (affKeyFieldName != null) {
+ ccfg.setKeyConfiguration(new CacheKeyConfiguration()
+ .setTypeName(Key.class.getTypeName())
+ .setAffinityKeyFieldName(affKeyFieldName)
+ );
+ }
+
+ igniteCfg.setCacheConfiguration(ccfg);
+
+ if (isPersistenceEnabled) {
+ igniteCfg.setDataStorageConfiguration(new DataStorageConfiguration()
+ .setDefaultDataRegionConfiguration(
+ new DataRegionConfiguration().setPersistenceEnabled(true)
+ )
+ );
+ }
+
+ return igniteCfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ super.beforeTest();
+
+ stopAllGrids();
+
+ cleanPersistenceDir();
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+
+ cleanPersistenceDir();
+
+ indexes = null;
+
+ inlineSize = null;
+
+ isPersistenceEnabled = null;
+
+ affKeyFieldName = null;
+
+ super.afterTest();
+ }
+
+ /** */
+ public void testNoIndexesNoPersistence() throws Exception {
+ indexes = Collections.emptyList();
+
+ isPersistenceEnabled = false;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ populateCache();
+
+ checkAll();
+
+ stopGrid();
+ }
+ }
+
+ /** */
+ public void testAllIndexesNoPersistence() throws Exception {
+ indexes = Arrays.asList(
+ new QueryIndex("keyStr"),
+ new QueryIndex("keyLong"),
+ new QueryIndex("keyPojo"),
+ new QueryIndex("valStr"),
+ new QueryIndex("valLong"),
+ new QueryIndex("valPojo")
+ );
+
+ isPersistenceEnabled = false;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ populateCache();
+
+ checkAll();
+
+ stopGrid();
+ }
+ }
+
+ /** */
+ public void testDynamicIndexesNoPersistence() throws Exception {
+ indexes = Collections.emptyList();
+
+ isPersistenceEnabled = false;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ populateCache();
+
+ createDynamicIndexes(
+ "keyStr",
+ "keyLong",
+ "keyPojo",
+ "valStr",
+ "valLong",
+ "valPojo"
+ );
+
+ checkAll();
+
+ stopGrid();
+ }
+ }
+
+ /** */
+ public void testNoIndexesWithPersistence() throws Exception {
+ indexes = Collections.emptyList();
+
+ isPersistenceEnabled = true;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ populateCache();
+
+ checkAll();
+
+ stopGrid();
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ checkAll();
+
+ stopGrid();
+
+ cleanPersistenceDir();
+ }
+ }
+
+ /** */
+ public void testAllIndexesWithPersistence() throws Exception {
+ indexes = Arrays.asList(
+ new QueryIndex("keyStr"),
+ new QueryIndex("keyLong"),
+ new QueryIndex("keyPojo"),
+ new QueryIndex("valStr"),
+ new QueryIndex("valLong"),
+ new QueryIndex("valPojo")
+ );
+
+ isPersistenceEnabled = true;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ populateCache();
+
+ checkAll();
+
+ stopGrid();
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ checkAll();
+
+ stopGrid();
+
+ cleanPersistenceDir();
+ }
+ }
+
+ /** */
+ public void testDynamicIndexesWithPersistence() throws Exception {
+ indexes = Collections.emptyList();
+
+ isPersistenceEnabled = true;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ populateCache();
+
+ createDynamicIndexes(
+ "keyStr",
+ "keyLong",
+ "keyPojo",
+ "valStr",
+ "valLong",
+ "valPojo"
+ );
+
+ checkAll();
+
+ stopGrid();
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ checkAll();
+
+ stopGrid();
+
+ cleanPersistenceDir();
+ }
+ }
+
+ /** */
+ public void testNoIndexesWithPersistenceIndexRebuild() throws Exception {
+ indexes = Collections.emptyList();
+
+ isPersistenceEnabled = true;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ populateCache();
+
+ checkAll();
+
+ Path idxPath = getIndexBinPath();
+
+ // Shutdown gracefully to ensure there is a checkpoint with index.bin.
+ // Otherwise index.bin rebuilding may not work.
+ grid().cluster().active(false);
+
+ stopGrid();
+
+ assertTrue(U.delete(idxPath));
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ grid().cache(DEFAULT_CACHE_NAME).indexReadyFuture().get();
+
+ checkAll();
+
+ stopGrid();
+
+ cleanPersistenceDir();
+ }
+ }
+
+ /** */
+ public void testAllIndexesWithPersistenceIndexRebuild() throws Exception {
+ indexes = Arrays.asList(
+ new QueryIndex("keyStr"),
+ new QueryIndex("keyLong"),
+ new QueryIndex("keyPojo"),
+ new QueryIndex("valStr"),
+ new QueryIndex("valLong"),
+ new QueryIndex("valPojo")
+ );
+
+ isPersistenceEnabled = true;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ populateCache();
+
+ checkAll();
+
+ Path idxPath = getIndexBinPath();
+
+ // Shutdown gracefully to ensure there is a checkpoint with index.bin.
+ // Otherwise index.bin rebuilding may not work.
+ grid().cluster().active(false);
+
+ stopGrid();
+
+ assertTrue(U.delete(idxPath));
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ grid().cache(DEFAULT_CACHE_NAME).indexReadyFuture().get();
+
+ checkAll();
+
+ stopGrid();
+
+ cleanPersistenceDir();
+ }
+ }
+
+ /** */
+ public void testDynamicIndexesWithPersistenceIndexRebuild() throws Exception {
+ indexes = Collections.emptyList();
+
+ isPersistenceEnabled = true;
+
+ int[] inlineSizes = { 0, 10, 20, 50, 100 };
+
+ for (int i : inlineSizes) {
+ log().info("Checking inlineSize=" + i);
+
+ inlineSize = i;
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ populateCache();
+
+ createDynamicIndexes(
+ "keyStr",
+ "keyLong",
+ "keyPojo",
+ "valStr",
+ "valLong",
+ "valPojo"
+ );
+
+ checkAll();
+
+ Path idxPath = getIndexBinPath();
+
+ // Shutdown gracefully to ensure there is a checkpoint with index.bin.
+ // Otherwise index.bin rebuilding may not work.
+ grid().cluster().active(false);
+
+ stopGrid();
+
+ assertTrue(U.delete(idxPath));
+
+ startGrid();
+
+ grid().cluster().active(true);
+
+ grid().cache(DEFAULT_CACHE_NAME).indexReadyFuture().get();
+
+ checkAll();
+
+ stopGrid();
+
+ cleanPersistenceDir();
+ }
+ }
+
+ /** */
+ private void checkAll() {
+ IgniteCache<Key, Val> cache = grid().cache(DEFAULT_CACHE_NAME);
+
+ checkRemovePut(cache);
+
+ checkSelectAll(cache);
+
+ checkSelectStringEqual(cache);
+
+ checkSelectLongEqual(cache);
+
+ checkSelectStringRange(cache);
+
+ checkSelectLongRange(cache);
+ }
+
+ /** */
+ private void populateCache() {
+ IgniteCache<Key, Val> cache = grid().cache(DEFAULT_CACHE_NAME);
+
+ // Be paranoid and populate first even indexes in ascending order, then odd indexes in descending
+ // to check that inserting in the middle works.
+
+ for (int i = 0; i < 100; i += 2)
+ cache.put(key(i), val(i));
+
+ for (int i = 99; i > 0; i -= 2)
+ cache.put(key(i), val(i));
+
+ for (int i = 99; i > 0; i -= 2)
+ assertEquals(val(i), cache.get(key(i)));
+ }
+
+ /** */
+ private void checkRemovePut(IgniteCache<Key, Val> cache) {
+ final int INT = 24;
+
+ assertEquals(val(INT), cache.get(key(INT)));
+
+ cache.remove(key(INT));
+
+ assertNull(cache.get(key(INT)));
+
+ cache.put(key(INT), val(INT));
+
+ assertEquals(val(INT), cache.get(key(INT)));
+ }
+
+ /** */
+ private void checkSelectAll(IgniteCache<Key, Val> cache) {
+ List<List<?>> data = cache.query(new SqlFieldsQuery("select _key, _val from Val")).getAll();
+
+ assertEquals(100, data.size());
+
+ for (List<?> row : data) {
+ Key key = (Key)row.get(0);
+
+ Val val = (Val)row.get(1);
+
+ long i = key.keyLong;
+
+ assertEquals(key(i), key);
+
+ assertEquals(val(i), val);
+ }
+ }
+
+ /** */
+ private void checkSelectStringEqual(IgniteCache<Key, Val> cache) {
+ final String STR = "foo011";
+
+ final long LONG = 11;
+
+ List<List<?>> data = cache.query(new SqlFieldsQuery("select _key, _val from Val where keyStr = ?")
+ .setArgs(STR))
+ .getAll();
+
+ assertEquals(1, data.size());
+
+ List<?> row = data.get(0);
+
+ assertEquals(key(LONG), row.get(0));
+
+ assertEquals(val(LONG), row.get(1));
+ }
+
+ /** */
+ private void checkSelectLongEqual(IgniteCache<Key, Val> cache) {
+ final long LONG = 42;
+
+ List<List<?>> data = cache.query(new SqlFieldsQuery("select _key, _val from Val where valLong = ?")
+ .setArgs(LONG))
+ .getAll();
+
+ assertEquals(1, data.size());
+
+ List<?> row = data.get(0);
+
+ assertEquals(key(LONG), row.get(0));
+
+ assertEquals(val(LONG), row.get(1));
+ }
+
+ /** */
+ private void checkSelectStringRange(IgniteCache<Key, Val> cache) {
+ final String PREFIX = "foo06";
+
+ List<List<?>> data = cache.query(new SqlFieldsQuery("select _key, _val from Val where keyStr like ?")
+ .setArgs(PREFIX + "%"))
+ .getAll();
+
+ assertEquals(10, data.size());
+
+ for (List<?> row : data) {
+ Key key = (Key)row.get(0);
+
+ Val val = (Val)row.get(1);
+
+ long i = key.keyLong;
+
+ assertEquals(key(i), key);
+
+ assertEquals(val(i), val);
+
+ assertTrue(key.keyStr.startsWith(PREFIX));
+ }
+ }
+
+ /** */
+ private void checkSelectLongRange(IgniteCache<Key, Val> cache) {
+ final long RANGE_START = 70;
+
+ final long RANGE_END = 80;
+
+ List<List<?>> data = cache.query(
+ new SqlFieldsQuery("select _key, _val from Val where valLong >= ? and valLong < ?")
+ .setArgs(RANGE_START, RANGE_END))
+ .getAll();
+
+ assertEquals(10, data.size());
+
+ for (List<?> row : data) {
+ Key key = (Key)row.get(0);
+
+ Val val = (Val)row.get(1);
+
+ long i = key.keyLong;
+
+ assertEquals(key(i), key);
+
+ assertEquals(val(i), val);
+
+ assertTrue(i >= RANGE_START && i < RANGE_END);
+ }
+ }
+
+ /** Must be called when the grid is up. */
+ private Path getIndexBinPath() {
+ IgniteInternalCache<Object, Object> cachex = grid().cachex(DEFAULT_CACHE_NAME);
+
+ assertNotNull(cachex);
+
+ FilePageStoreManager pageStoreMgr = (FilePageStoreManager)cachex.context().shared().pageStore();
+
+ assertNotNull(pageStoreMgr);
+
+ File cacheWorkDir = pageStoreMgr.cacheWorkDir(cachex.configuration());
+
+ return cacheWorkDir.toPath().resolve("index.bin");
+ }
+
+ /** */
+ private void createDynamicIndexes(String... cols) {
+ IgniteCache<Key, Val> cache = grid().cache(DEFAULT_CACHE_NAME);
+
+ for (String col : cols) {
+ cache.query(new SqlFieldsQuery(
+ "create index on Val(" + col + ") INLINE_SIZE " + inlineSize
+ ));
+ }
+
+ cache.indexReadyFuture().get();
+ }
+
+ /** */
+ private static Key key(long i) {
+ return new Key(String.format("foo%03d", i), i, new Pojo(i));
+ }
+
+ /** */
+ private static Val val(long i) {
+ return new Val(String.format("bar%03d", i), i, new Pojo(i));
+ }
+
+ /** */
+ private static class Key {
+ /** */
+ private String keyStr;
+
+ /** */
+ private long keyLong;
+
+ /** */
+ private Pojo keyPojo;
+
+ /** */
+ private Key(String str, long aLong, Pojo pojo) {
+ keyStr = str;
+ keyLong = aLong;
+ keyPojo = pojo;
+ }
+
+ /** {@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 keyLong == key.keyLong &&
+ Objects.equals(keyStr, key.keyStr) &&
+ Objects.equals(keyPojo, key.keyPojo);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return Objects.hash(keyStr, keyLong, keyPojo);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Key.class, this);
+ }
+ }
+
+ /** */
+ private static class Val {
+ /** */
+ private String valStr;
+
+ /** */
+ private long valLong;
+
+ /** */
+ private Pojo valPojo;
+
+ /** */
+ private Val(String str, long aLong, Pojo pojo) {
+ valStr = str;
+ valLong = aLong;
+ valPojo = pojo;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ Val val = (Val)o;
+
+ return valLong == val.valLong &&
+ Objects.equals(valStr, val.valStr) &&
+ Objects.equals(valPojo, val.valPojo);
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return Objects.hash(valStr, valLong, valPojo);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Val.class, this);
+ }
+ }
+
+ /** */
+ private static class Pojo {
+ /** */
+ private long pojoLong;
+
+ /** */
+ private Pojo(long pojoLong) {
+ this.pojoLong = pojoLong;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean equals(Object o) {
+ if (this == o)
+ return true;
+
+ if (o == null || getClass() != o.getClass())
+ return false;
+
+ Pojo pojo = (Pojo)o;
+
+ return pojoLong == pojo.pojoLong;
+ }
+
+ /** {@inheritDoc} */
+ @Override public int hashCode() {
+ return Objects.hash(pojoLong);
+ }
+
+ /** {@inheritDoc} */
+ @Override public String toString() {
+ return S.toString(Pojo.class, this);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6e97d14/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelperTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelperTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelperTest.java
index ea23483..4c64264 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelperTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/database/InlineIndexHelperTest.java
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -42,6 +43,7 @@ import org.h2.value.ValueDate;
import org.h2.value.ValueDouble;
import org.h2.value.ValueFloat;
import org.h2.value.ValueInt;
+import org.h2.value.ValueJavaObject;
import org.h2.value.ValueLong;
import org.h2.value.ValueNull;
import org.h2.value.ValueShort;
@@ -49,6 +51,7 @@ import org.h2.value.ValueString;
import org.h2.value.ValueTime;
import org.h2.value.ValueTimestamp;
import org.h2.value.ValueUuid;
+import org.springframework.util.SerializationUtils;
/**
* Simple tests for {@link InlineIndexHelper}.
@@ -169,7 +172,7 @@ public class InlineIndexHelperTest extends GridCommonAbstractTest {
int i1 = rnd.nextInt(strings.length);
int i2 = rnd.nextInt(strings.length);
- assertEquals(Integer.compare(i1,i2), putAndCompare(strings[i1], strings[i2], inlineSize));
+ assertEquals(Integer.compare(i1, i2), putAndCompare(strings[i1], strings[i2], inlineSize));
}
}
@@ -185,12 +188,12 @@ public class InlineIndexHelperTest extends GridCommonAbstractTest {
.setMaxSize(1024 * MB);
PageMemory pageMem = new PageMemoryNoStoreImpl(log,
- new UnsafeMemoryProvider(log),
- null,
- PAGE_SIZE,
- plcCfg,
- new DataRegionMetricsImpl(plcCfg),
- false);
+ new UnsafeMemoryProvider(log),
+ null,
+ PAGE_SIZE,
+ plcCfg,
+ new DataRegionMetricsImpl(plcCfg),
+ false);
pageMem.start();
@@ -209,7 +212,7 @@ public class InlineIndexHelperTest extends GridCommonAbstractTest {
ih.put(pageAddr, off, v1 == null ? ValueNull.INSTANCE : ValueString.get(v1), maxSize);
- return ih.compare(pageAddr, off, maxSize, v2 == null ? ValueNull.INSTANCE : ValueString.get(v2), ALWAYS_FAILS_COMPARATOR);
+ return ih.compare(pageAddr, off, maxSize, v2 == null ? ValueNull.INSTANCE : ValueString.get(v2), ALWAYS_FAILS_COMPARATOR);
}
finally {
if (page != 0L)
@@ -271,6 +274,30 @@ public class InlineIndexHelperTest extends GridCommonAbstractTest {
assertTrue(getResBytes(ha, null, null));
}
+ /** Test on Bytes values compare */
+ public void testRelyOnCompareJavaObject() {
+ InlineIndexHelper ha = new InlineIndexHelper(Value.JAVA_OBJECT, 0, SortOrder.ASCENDING,
+ CompareMode.getInstance(null, 0));
+
+ // different types
+ assertTrue(getResJavaObjects(ha, new String("1234"), new Integer(10)));
+
+ // the same types, but different values
+ assertTrue(getResJavaObjects(ha, new String("1234"), new String("123")));
+
+ // the same types and values
+ assertFalse(getResJavaObjects(ha, new String("1234"), new String("1234")));
+
+ // the same object
+ String key = "1";
+ assertFalse(getResJavaObjects(ha, key, key));
+
+ // one is null
+ assertTrue(getResJavaObjects(ha, key, null));
+ assertTrue(getResJavaObjects(ha, null, key));
+ assertTrue(getResJavaObjects(ha, null, null));
+ }
+
/** */
public void testStringTruncate() throws Exception {
DataRegionConfiguration plcCfg = new DataRegionConfiguration().setInitialSize(1024 * MB)
@@ -350,17 +377,86 @@ public class InlineIndexHelperTest extends GridCommonAbstractTest {
InlineIndexHelper ih = new InlineIndexHelper(Value.BYTES, 1, 0,
CompareMode.getInstance(null, 0));
- ih.put(pageAddr, off, ValueBytes.get(new byte[] {1, 2, 3, 4, 5}), 3 + 3);
+ int maxSize = 3 + 3;
+ int savedBytesCnt = ih.put(pageAddr, off, ValueBytes.get(new byte[] {1, 2, 3, 4, 5}), maxSize);
+
+ assertTrue(savedBytesCnt > 0);
+
+ assertTrue(savedBytesCnt <= maxSize);
+
+ assertFalse(ih.isValueFull(pageAddr, off));
+
+ maxSize = 3 + 5;
+
+ assertTrue(Arrays.equals(new byte[] {1, 2, 3}, ih.get(pageAddr, off, maxSize).getBytes()));
+
+ savedBytesCnt = ih.put(pageAddr, off, ValueBytes.get(new byte[] {1, 2, 3, 4, 5}), maxSize);
+
+ assertTrue(savedBytesCnt > 0);
+
+ assertTrue(savedBytesCnt <= maxSize);
+
+ assertTrue(ih.isValueFull(pageAddr, off));
+
+ assertTrue(Arrays.equals(new byte[] {1, 2, 3, 4, 5}, ih.get(pageAddr, off, maxSize).getBytes()));
+ }
+ finally {
+ if (page != 0L)
+ pageMem.releasePage(CACHE_ID, pageId, page);
+ pageMem.stop();
+ }
+ }
+
+ /** */
+ public void testJavaObject() throws Exception {
+ DataRegionConfiguration plcCfg = new DataRegionConfiguration().setInitialSize(1024 * MB)
+ .setMaxSize(1024 * MB);
+
+ PageMemory pageMem = new PageMemoryNoStoreImpl(log(),
+ new UnsafeMemoryProvider(log()),
+ null,
+ PAGE_SIZE,
+ plcCfg,
+ new DataRegionMetricsImpl(plcCfg),
+ false);
+
+ pageMem.start();
+
+ long pageId = 0L;
+ long page = 0L;
+
+ try {
+ pageId = pageMem.allocatePage(CACHE_ID, 1, PageIdAllocator.FLAG_DATA);
+ page = pageMem.acquirePage(CACHE_ID, pageId);
+ long pageAddr = pageMem.readLock(CACHE_ID, pageId, page);
+
+ int off = 0;
+
+ InlineIndexHelper ih = new InlineIndexHelper(Value.JAVA_OBJECT, 1, 0,
+ CompareMode.getInstance(null, 0));
+
+ int maxSize = 3 + 3;
+ int savedBytesCnt = ih.put(pageAddr, off, ValueJavaObject.getNoCopy(null, new byte[] {1, 2, 3, 4, 5}, null), maxSize);
+
+ assertTrue(savedBytesCnt > 0);
+
+ assertTrue(savedBytesCnt <= maxSize);
assertFalse(ih.isValueFull(pageAddr, off));
- assertTrue(Arrays.equals(new byte[] {1, 2, 3}, ih.get(pageAddr, off, 3 + 5).getBytes()));
+ maxSize = 3 + 5;
+
+ assertTrue(Arrays.equals(new byte[] {1, 2, 3}, ih.get(pageAddr, off, maxSize).getBytes()));
- ih.put(pageAddr, off, ValueBytes.get(new byte[] {1, 2, 3, 4, 5}), 3 + 5);
+ savedBytesCnt = ih.put(pageAddr, off, ValueJavaObject.getNoCopy(null, new byte[] {1, 2, 3, 4, 5}, null), maxSize);
+
+ assertTrue(savedBytesCnt > 0);
+
+ assertTrue(savedBytesCnt <= maxSize);
assertTrue(ih.isValueFull(pageAddr, off));
- assertTrue(Arrays.equals(new byte[] {1, 2, 3, 4, 5}, ih.get(pageAddr, off, 3 + 5).getBytes()));
+ assertTrue(Arrays.equals(new byte[] {1, 2, 3, 4, 5}, ih.get(pageAddr, off, maxSize).getBytes()));
}
finally {
if (page != 0L)
@@ -510,6 +606,16 @@ public class InlineIndexHelperTest extends GridCommonAbstractTest {
return ha.canRelyOnCompare(c, v1, v2);
}
+ /** */
+ private boolean getResJavaObjects(InlineIndexHelper ha, Object o1, Object o2) {
+ Value v1 = o1 == null ? ValueNull.INSTANCE : ValueJavaObject.getNoCopy(null, SerializationUtils.serialize(o1), null);
+ Value v2 = o2 == null ? ValueNull.INSTANCE : ValueJavaObject.getNoCopy(null, SerializationUtils.serialize(o2), null);
+
+ int c = v1.compareTypeSafe(v2, CompareMode.getInstance(null, 0));
+
+ return ha.canRelyOnCompare(c, v1, v2);
+ }
+
/**
* @param cnt String length.
* @return Random string.
@@ -523,31 +629,31 @@ public class InlineIndexHelperTest extends GridCommonAbstractTest {
char ch;
if (rnd.nextInt(100) > 3)
- ch = (char) (rnd.nextInt(95) + 32); // regular symbols
+ ch = (char)(rnd.nextInt(95) + 32); // regular symbols
else
- ch = (char) (rnd.nextInt(65407) + 127); // others symbols
+ ch = (char)(rnd.nextInt(65407) + 127); // others symbols
- if(ch >= 56320 && ch <= 57343) {
- if(cnt == 0)
+ if (ch >= 56320 && ch <= 57343) {
+ if (cnt == 0)
cnt++;
else {
// low surrogate, insert high surrogate after putting it in
buffer[cnt] = ch;
cnt--;
- buffer[cnt] = (char) (55296 + rnd.nextInt(128));
+ buffer[cnt] = (char)(55296 + rnd.nextInt(128));
}
}
- else if(ch >= 55296 && ch <= 56191) {
- if(cnt == 0)
+ else if (ch >= 55296 && ch <= 56191) {
+ if (cnt == 0)
cnt++;
else {
// high surrogate, insert low surrogate before putting it in
- buffer[cnt] = (char) (56320 + rnd.nextInt(128));
+ buffer[cnt] = (char)(56320 + rnd.nextInt(128));
cnt--;
buffer[cnt] = ch;
}
}
- else if(ch >= 56192 && ch <= 56319)
+ else if (ch >= 56192 && ch <= 56319)
// private high surrogate, no effing clue, so skip it
cnt++;
else
http://git-wip-us.apache.org/repos/asf/ignite/blob/a6e97d14/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 7f67b35..1036eed 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
@@ -104,6 +104,7 @@ import org.apache.ignite.internal.processors.cache.distributed.replicated.Ignite
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQueryEvtsDisabledSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQueryP2PDisabledSelfTest;
import org.apache.ignite.internal.processors.cache.distributed.replicated.IgniteCacheReplicatedQuerySelfTest;
+import org.apache.ignite.internal.processors.cache.index.BasicIndexTest;
import org.apache.ignite.internal.processors.cache.index.DuplicateKeyValueClassesSelfTest;
import org.apache.ignite.internal.processors.cache.index.DynamicIndexClientBasicSelfTest;
import org.apache.ignite.internal.processors.cache.index.DynamicIndexServerBasicSelfTest;
@@ -225,6 +226,8 @@ public class IgniteCacheQuerySelfTestSuite extends TestSuite {
suite.addTestSuite(SqlIllegalSchemaSelfTest.class);
suite.addTestSuite(MultipleStatementsSqlQuerySelfTest.class);
+ suite.addTestSuite(BasicIndexTest.class);
+
// Misc tests.
// TODO: Enable when IGNITE-1094 is fixed.
// suite.addTest(new TestSuite(QueryEntityValidationSelfTest.class));