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/02/20 10:16:53 UTC

[11/12] ignite git commit: IGNITE-2598 - Fixes enum arguments processing in SQL queries with BinaryMarshaller. This closes #480.

IGNITE-2598 - Fixes enum arguments processing in SQL queries with BinaryMarshaller. This closes #480.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/be454612
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/be454612
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/be454612

Branch: refs/heads/ignite-1786
Commit: be4546128aa4a507335f1db8d3e88451cc06cefe
Parents: b99714d
Author: dkarachentsev <dk...@gridgain.com>
Authored: Sat Feb 20 12:01:53 2016 +0300
Committer: vozerov-gridgain <vo...@gridgain.com>
Committed: Sat Feb 20 12:01:53 2016 +0300

----------------------------------------------------------------------
 .../internal/binary/BinaryEnumObjectImpl.java   |   9 +
 .../query/h2/opt/GridH2ValueCacheObject.java    |   9 +
 .../cache/IgniteCacheAbstractQuerySelfTest.java | 187 ++++++++++++++++++-
 3 files changed, 204 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/be454612/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
index 33c62e9..0486db9 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryEnumObjectImpl.java
@@ -316,4 +316,13 @@ public class BinaryEnumObjectImpl implements BinaryObjectEx, Externalizable, Cac
 
         return reader.afterMessageRead(BinaryEnumObjectImpl.class);
     }
+
+    /**
+     * @param cls type to examine.
+     * @return true if typeId equals for passed type and current
+     * binary enum.
+     */
+    public boolean isTypeEquals(final Class<?> cls) {
+        return ctx.descriptorForClass(cls, false).typeId() == typeId();
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/be454612/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 fd0e6ed..29f9675 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,8 @@ import java.sql.PreparedStatement;
 import java.sql.SQLException;
 import java.sql.Types;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.binary.BinaryObject;
+import org.apache.ignite.internal.binary.BinaryEnumObjectImpl;
 import org.apache.ignite.internal.processors.cache.CacheObject;
 import org.apache.ignite.internal.processors.cache.CacheObjectContext;
 import org.apache.ignite.internal.processors.cache.GridCacheContext;
@@ -144,6 +146,13 @@ public class GridH2ValueCacheObject extends Value {
             return c1.compareTo(o2);
         }
 
+        if (o1 instanceof BinaryEnumObjectImpl && o2 instanceof Enum) {
+            final BinaryEnumObjectImpl bo1 = (BinaryEnumObjectImpl)o1;
+
+            if (bo1.isTypeEquals(o2.getClass()))
+                return Integer.compare(bo1.enumOrdinal(), ((Enum)o2).ordinal());
+        }
+
         // Group by types.
         if (o1.getClass() != o2.getClass()) {
             if (o1Comparable != o2Comparable)

http://git-wip-us.apache.org/repos/asf/ignite/blob/be454612/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 8ef3f9b..2b2020d 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
@@ -42,6 +42,7 @@ import javax.cache.configuration.Factory;
 import javax.cache.expiry.Duration;
 import javax.cache.expiry.TouchedExpiryPolicy;
 import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteBinary;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.binary.BinaryObject;
@@ -176,7 +177,8 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
                     Integer.class, ArrayObject.class,
                     Key.class, GridCacheQueryTestValue.class,
                     UUID.class, Person.class,
-                    IgniteCacheReplicatedQuerySelfTest.CacheKey.class, IgniteCacheReplicatedQuerySelfTest.CacheValue.class
+                    IgniteCacheReplicatedQuerySelfTest.CacheKey.class, IgniteCacheReplicatedQuerySelfTest.CacheValue.class,
+                    Long.class, EnumObject.class
                 );
 
                 if (cacheMode() != CacheMode.LOCAL)
@@ -585,6 +587,143 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
      *
      * @throws Exception In case of error.
      */
+    public void testEnumObjectQuery() throws Exception {
+        final IgniteCache<Long, EnumObject> cache = ignite().cache(null);
+
+        for (long i = 0; i < 50; i++)
+            cache.put(i, new EnumObject(i, i % 2 == 0 ? EnumType.TYPE_A : EnumType.TYPE_B));
+
+
+        assertEnumQry("type = ?", EnumType.TYPE_A, EnumType.TYPE_A, cache, 25);
+        assertEnumQry("type > ?", EnumType.TYPE_A, EnumType.TYPE_B, cache, 25);
+        assertEnumQry("type < ?", EnumType.TYPE_B, EnumType.TYPE_A, cache, 25);
+        assertEnumQry("type != ?", EnumType.TYPE_B, EnumType.TYPE_A, cache, 25);
+
+        assertEmptyEnumQry("type = ?", null, cache);
+        assertEmptyEnumQry("type > ?", EnumType.TYPE_B, cache);
+        assertEmptyEnumQry("type < ?", EnumType.TYPE_A, cache);
+
+        cache.put(50L, new EnumObject(50, null));
+
+        assertNoArgEnumQry("type is null", null, cache, 1);
+        assertAnyResTypeEnumQry("type is not null", cache, 50);
+
+        // Additional tests for binary enums.
+        IgniteBinary binary = ignite().binary();
+
+        if (binary != null) {
+            assertEnumQry("type = ?", binaryEnum(binary, EnumType.TYPE_A), EnumType.TYPE_A, cache, 25);
+            assertEnumQry("type > ?", binaryEnum(binary, EnumType.TYPE_A), EnumType.TYPE_B, cache, 25);
+            assertEnumQry("type < ?", binaryEnum(binary, EnumType.TYPE_B), EnumType.TYPE_A, cache, 25);
+            assertEnumQry("type != ?", binaryEnum(binary, EnumType.TYPE_B), EnumType.TYPE_A, cache, 25);
+
+            assertEmptyEnumQry("type > ?", binaryEnum(binary, EnumType.TYPE_B), cache);
+            assertEmptyEnumQry("type < ?", binaryEnum(binary, EnumType.TYPE_A), cache);
+        }
+    }
+
+    /**
+     * Create binary enum.
+     *
+     * @param binary Binary facade.
+     * @param val Enum value.
+     * @return Binary enum.
+     */
+    private static BinaryObject binaryEnum(IgniteBinary binary, EnumType val) {
+        return binary.buildEnum(EnumType.class.getName(), val.ordinal());
+    }
+
+    /**
+     * Fails if result size not equals to resSize.
+     *
+     * @param qryStr to execute.
+     * @param cache cache.
+     * @param resSize size of the result.
+     */
+    private void assertAnyResTypeEnumQry(String qryStr, IgniteCache<Long, EnumObject> cache, int resSize) {
+        final SqlQuery<Long, EnumObject> qry = new SqlQuery<>(EnumObject.class, qryStr);
+
+        final List<Cache.Entry<Long, EnumObject>> res = cache.query(qry).getAll();
+
+        assert resSize == res.size();
+    }
+
+    /**
+     * Fails if result size not equals to resSize or
+     * at least one entry has different of resType type.
+     *
+     * @param qryStr to execute.
+     * @param resType to compare with.
+     * @param cache cache.
+     * @param resSize size of the result.
+     */
+    private void assertNoArgEnumQry(String qryStr, EnumType resType, IgniteCache<Long, EnumObject> cache, int resSize) {
+        final SqlQuery<Long, EnumObject> qry = new SqlQuery<>(EnumObject.class, qryStr);
+
+        final List<Cache.Entry<Long, EnumObject>> res = cache.query(qry).getAll();
+
+        assert resSize == res.size();
+
+        assertEnumType(res, resType);
+    }
+
+    /**
+     * Fails if result size not equals to resSize or
+     * at least one entry has different of resType type.
+     *
+     * @param qryStr to execute.
+     * @param arg to be passed to query.
+     * @param resType to compare with.
+     * @param cache cache.
+     * @param resSize size of the result.
+     */
+    private void assertEnumQry(String qryStr, Object arg, EnumType resType, IgniteCache<Long, EnumObject> cache,
+        int resSize) {
+        final SqlQuery<Long, EnumObject> qry = new SqlQuery<>(EnumObject.class, qryStr);
+
+        qry.setArgs(arg);
+
+        final List<Cache.Entry<Long, EnumObject>> res = cache.query(qry).getAll();
+
+        assert resSize == res.size();
+
+        assertEnumType(res, resType);
+    }
+
+    /**
+     * Fails if result has entries.
+     *
+     * @param qryStr to execute.
+     * @param arg argument that will be passed to query.
+     * @param cache cache on which query will be executed.
+     */
+    private void assertEmptyEnumQry(String qryStr, Object arg, IgniteCache<Long, EnumObject> cache) {
+        final SqlQuery<Long, EnumObject> qry = new SqlQuery<>(EnumObject.class, qryStr);
+
+        qry.setArgs(arg);
+
+        final List<Cache.Entry<Long, EnumObject>> res = cache.query(qry).getAll();
+
+        assert res.isEmpty();
+    }
+
+    /**
+     * Fails if at least one object in result has type field that doesn't
+     * equal to passed enumType.
+     *
+     * @param enumObjects query execution result.
+     * @param enumType compare to.
+     */
+    private void assertEnumType(final List<Cache.Entry<Long, EnumObject>> enumObjects, final EnumType enumType) {
+        for (final Cache.Entry<Long, EnumObject> entry : enumObjects)
+            assert entry.getValue().type == enumType;
+    }
+
+    /**
+     * JUnit.
+     *
+     * @throws Exception In case of error.
+     */
     public void testObjectQueryWithSwap() throws Exception {
         IgniteCache<Integer, ObjectValue> cache = ignite().cache(null);
 
@@ -1795,4 +1934,50 @@ public abstract class IgniteCacheAbstractQuerySelfTest extends GridCommonAbstrac
             return store;
         }
     }
+
+    /**
+     * Test enum class.
+     */
+    private static class EnumObject {
+        /**
+         * Test id.
+         */
+        @QuerySqlField(index = true)
+        private long id;
+
+        /**
+         * Test enum.
+         */
+        @QuerySqlField
+        private EnumType type;
+
+        /**
+         * @param id id.
+         * @param type enum.
+         */
+        public EnumObject(long id, EnumType type) {
+            this.id = id;
+            this.type = type;
+        }
+
+        /**
+         * @return string representation of object.
+         */
+        @Override public String toString() {
+            return "EnumObject{" +
+                    "id=" + id +
+                    ", type=" + type +
+                    '}';
+        }
+    }
+
+    /**
+     * Test enum.
+     */
+    private enum EnumType {
+        /** */
+        TYPE_A,
+        /** */
+        TYPE_B
+    }
 }
\ No newline at end of file