Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-959-x [created] 7df4f8cb0


ignite-959-x - wip


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

Branch: refs/heads/ignite-959-x
Commit: 781f0d5ff32ea034d67260469a595cdb64048655
Parents: 285d790
Author: S.Vladykin <svlady...@gridgain.com>
Authored: Thu Jun 25 12:46:25 2015 +0300
Committer: S.Vladykin <svlady...@gridgain.com>
Committed: Thu Jun 25 12:46:25 2015 +0300

----------------------------------------------------------------------
 .../configuration/CacheConfiguration.java       | 602 ++++++++++++++++++-
 .../processors/query/GridQueryProcessor.java    |  44 ++
 .../processors/query/h2/IgniteH2Indexing.java   |   2 -
 3 files changed, 632 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/781f0d5f/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
----------------------------------------------------------------------
diff --git 
a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
 
b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
index 7af4974..50ba040 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/configuration/CacheConfiguration.java
@@ -25,6 +25,9 @@ import org.apache.ignite.cache.eviction.*;
 import org.apache.ignite.cache.query.annotations.*;
 import org.apache.ignite.cache.store.*;
 import org.apache.ignite.cluster.*;
+import org.apache.ignite.internal.processors.query.*;
+import org.apache.ignite.internal.util.tostring.*;
+import org.apache.ignite.internal.util.typedef.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
 import org.apache.ignite.lang.*;
 import org.apache.ignite.plugin.*;
@@ -33,8 +36,11 @@ import org.jetbrains.annotations.*;
 import javax.cache.*;
 import javax.cache.configuration.*;
 import javax.cache.expiry.*;
+import java.lang.reflect.*;
 import java.util.*;
 
+import static org.apache.ignite.internal.processors.query.GridQueryIndexType.*;
+
 /**
  * This class defines grid cache configuration. This configuration is passed to
  * grid via {@link IgniteConfiguration#getCacheConfiguration()} method. It 
defines all configuration
@@ -298,7 +304,7 @@ public class CacheConfiguration<K, V> extends 
MutableConfiguration<K, V> {
     private boolean sqlEscapeAll;
 
     /** */
-    private Class<?>[] indexedTypes;
+    private transient Class<?>[] indexedTypes;
 
     /** */
     private int sqlOnheapRowCacheSize = DFLT_SQL_ONHEAP_ROW_CACHE_SIZE;
@@ -1506,7 +1512,12 @@ public class CacheConfiguration<K, V> extends 
MutableConfiguration<K, V> {
      * @return {@code this} for chaining.
      */
     public CacheConfiguration setTypeMetadata(Collection<CacheTypeMetadata> 
typeMeta) {
-        this.typeMeta = typeMeta;
+        if (this.typeMeta == null)
+            this.typeMeta = new ArrayList<>(typeMeta);
+        else if (indexedTypes != null)
+            this.typeMeta.addAll(typeMeta);
+        else
+            throw new CacheException("Type metadata can be set only once.");
 
         return this;
     }
@@ -1661,21 +1672,31 @@ public class CacheConfiguration<K, V> extends 
MutableConfiguration<K, V> {
      * @return {@code this} for chaining.
      */
     public CacheConfiguration setIndexedTypes(Class<?>... indexedTypes) {
-        A.ensure(indexedTypes == null || (indexedTypes.length & 1) == 0,
+        int len = indexedTypes.length;
+
+        A.ensure(len > 0, "Array of indexed types can not be empty.");
+        A.ensure((len & 1) == 0,
             "Number of indexed types is expected to be even. Refer to method 
javadoc for details.");
 
-        if (indexedTypes != null) {
-            int len = indexedTypes.length;
+        if (this.indexedTypes != null)
+            throw new CacheException("Indexed types can be set only once.");
+
+        Class<?>[] newIndexedTypes = new Class<?>[len];
 
-            Class<?>[] newIndexedTypes = new Class<?>[len];
+        for (int i = 0; i < len; i++)
+            newIndexedTypes[i] = U.box(indexedTypes[i]);
 
-            for (int i = 0; i < len; i++)
-                newIndexedTypes[i] = U.box(indexedTypes[i]);
+        if (typeMeta == null)
+            typeMeta = new ArrayList<>();
 
-            this.indexedTypes = newIndexedTypes;
+        for (int i = 0; i < len; i += 2) {
+            Class<?> keyCls = newIndexedTypes[i];
+            Class<?> valCls = newIndexedTypes[i + 1];
+
+            TypeDescriptor desc = processKeyAndValueClasses(keyCls, valCls);
+
+            typeMeta.add(convert(desc));
         }
-        else
-            this.indexedTypes = null;
 
         return this;
     }
@@ -1773,6 +1794,165 @@ public class CacheConfiguration<K, V> extends 
MutableConfiguration<K, V> {
         return this;
     }
 
+    /**
+     * @param desc Type descriptor.
+     * @return Type metadata.
+     */
+    private CacheTypeMetadata convert(TypeDescriptor desc) {
+        CacheTypeMetadata meta = new CacheTypeMetadata();
+
+        // TODO
+
+        return meta;
+    }
+
+    /**
+     * @param keyCls Key class.
+     * @param valCls Value class.
+     * @return Type descriptor.
+     */
+    private static TypeDescriptor processKeyAndValueClasses(
+        Class<?> keyCls,
+        Class<?> valCls
+    ) {
+        TypeDescriptor d = new TypeDescriptor();
+
+        d.keyClass(keyCls);
+        d.valueClass(valCls);
+
+        processAnnotationsInClass(true, d.keyCls, d, null);
+
+        String valTypeName = GridQueryProcessor.typeName(valCls);
+
+        d.name(valTypeName);
+
+        processAnnotationsInClass(false, d.valCls, d, null);
+
+        return d;
+    }
+
+    /**
+     * Process annotations for class.
+     *
+     * @param key If given class relates to key.
+     * @param cls Class.
+     * @param type Type descriptor.
+     * @param parent Parent in case of embeddable.
+     */
+    private static void processAnnotationsInClass(boolean key, Class<?> cls, 
TypeDescriptor type,
+        @Nullable ClassProperty parent) {
+        if (U.isJdk(cls) || GridQueryProcessor.isGeometryClass(cls)) {
+            if (parent == null && !key && GridQueryProcessor.isSqlType(cls) ) 
{ // We have to index primitive _val.
+                String idxName = "_val_idx";
+
+                type.addIndex(idxName, GridQueryProcessor.isGeometryClass(cls) 
? GEO_SPATIAL : SORTED);
+
+                type.addFieldToIndex(idxName, "_VAL", 0, false);
+            }
+
+            return;
+        }
+
+        if (parent != null && parent.knowsClass(cls))
+            throw new CacheException("Recursive reference found in type: " + 
cls.getName());
+
+        if (parent == null) { // Check class annotation at top level only.
+            QueryTextField txtAnnCls = cls.getAnnotation(QueryTextField.class);
+
+            if (txtAnnCls != null)
+                type.valueTextIndex(true);
+
+            QueryGroupIndex grpIdx = cls.getAnnotation(QueryGroupIndex.class);
+
+            if (grpIdx != null)
+                type.addIndex(grpIdx.name(), SORTED);
+
+            QueryGroupIndex.List grpIdxList = 
cls.getAnnotation(QueryGroupIndex.List.class);
+
+            if (grpIdxList != null && !F.isEmpty(grpIdxList.value())) {
+                for (QueryGroupIndex idx : grpIdxList.value())
+                    type.addIndex(idx.name(), SORTED);
+            }
+        }
+
+        for (Class<?> c = cls; c != null && !c.equals(Object.class); c = 
c.getSuperclass()) {
+            for (Field field : c.getDeclaredFields()) {
+                QuerySqlField sqlAnn = 
field.getAnnotation(QuerySqlField.class);
+                QueryTextField txtAnn = 
field.getAnnotation(QueryTextField.class);
+
+                if (sqlAnn != null || txtAnn != null) {
+                    ClassProperty prop = new ClassProperty(field, key);
+
+                    prop.parent(parent);
+
+                    processAnnotation(key, sqlAnn, txtAnn, field.getType(), 
prop, type);
+
+                    type.addProperty(prop, true);
+                }
+            }
+
+            for (Method mtd : c.getDeclaredMethods()) {
+                QuerySqlField sqlAnn = mtd.getAnnotation(QuerySqlField.class);
+                QueryTextField txtAnn = 
mtd.getAnnotation(QueryTextField.class);
+
+                if (sqlAnn != null || txtAnn != null) {
+                    if (mtd.getParameterTypes().length != 0)
+                        throw new CacheException("Getter with QuerySqlField " +
+                            "annotation cannot have parameters: " + mtd);
+
+                    ClassProperty prop = new ClassProperty(mtd, key);
+
+                    prop.parent(parent);
+
+                    processAnnotation(key, sqlAnn, txtAnn, 
mtd.getReturnType(), prop, type);
+
+                    type.addProperty(prop, true);
+                }
+            }
+        }
+    }
+
+    /**
+     * Processes annotation at field or method.
+     *
+     * @param key If given class relates to key.
+     * @param sqlAnn SQL annotation, can be {@code null}.
+     * @param txtAnn H2 text annotation, can be {@code null}.
+     * @param cls Class of field or return type for method.
+     * @param prop Current property.
+     * @param desc Class description.
+     */
+    private static void processAnnotation(boolean key, QuerySqlField sqlAnn, 
QueryTextField txtAnn,
+        Class<?> cls, ClassProperty prop, TypeDescriptor desc) {
+        if (sqlAnn != null) {
+            processAnnotationsInClass(key, cls, desc, prop);
+
+            if (!sqlAnn.name().isEmpty())
+                prop.name(sqlAnn.name());
+
+            if (sqlAnn.index()) {
+                String idxName = prop.name() + "_idx";
+
+                desc.addIndex(idxName, 
GridQueryProcessor.isGeometryClass(prop.type()) ? GEO_SPATIAL : SORTED);
+
+                desc.addFieldToIndex(idxName, prop.name(), 0, 
sqlAnn.descending());
+            }
+
+            if (!F.isEmpty(sqlAnn.groups())) {
+                for (String group : sqlAnn.groups())
+                    desc.addFieldToIndex(group, prop.name(), 0, false);
+            }
+
+            if (!F.isEmpty(sqlAnn.orderedGroups())) {
+                for (QuerySqlField.Group idx : sqlAnn.orderedGroups())
+                    desc.addFieldToIndex(idx.name(), prop.name(), idx.order(), 
idx.descending());
+            }
+        }
+
+        if (txtAnn != null)
+            desc.addFieldToTextIndex(prop.name());
+    }
+
     /** {@inheritDoc} */
     @Override public String toString() {
         return S.toString(CacheConfiguration.class, this);
@@ -1792,10 +1972,404 @@ public class CacheConfiguration<K, V> extends 
MutableConfiguration<K, V> {
 
         /** {@inheritDoc} */
         @Override public boolean equals(Object obj) {
-            if (obj == null)
-                return false;
+            return obj != null && obj.getClass().equals(this.getClass());
+        }
+    }
+
+    /**
+     * Descriptor of type.
+     */
+    private static class TypeDescriptor implements GridQueryTypeDescriptor {
+        /** */
+        private String name;
+
+        /** Value field names and types with preserved order. */
+        @GridToStringInclude
+        private final Map<String, Class<?>> fields = new LinkedHashMap<>();
+
+        /** */
+        @GridToStringExclude
+        private final Map<String, Property> props = new HashMap<>();
+
+        /** */
+        @GridToStringInclude
+        private final Map<String, IndexDescriptor> indexes = new HashMap<>();
+
+        /** */
+        private IndexDescriptor fullTextIdx;
+
+        /** */
+        private Class<?> keyCls;
+
+        /** */
+        private Class<?> valCls;
+
+        /** */
+        private boolean valTextIdx;
+
+        /** SPI can decide not to register this type. */
+        private boolean registered;
+
+        /**
+         * @return {@code True} if type registration in SPI was finished and 
type was not rejected.
+         */
+        boolean registered() {
+            return registered;
+        }
+
+        /**
+         * @param registered Sets registered flag.
+         */
+        void registered(boolean registered) {
+            this.registered = registered;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String name() {
+            return name;
+        }
+
+        /**
+         * Sets type name.
+         *
+         * @param name Name.
+         */
+        void name(String name) {
+            this.name = name;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Map<String, Class<?>> fields() {
+            return fields;
+        }
+
+        /** {@inheritDoc} */
+        @SuppressWarnings("unchecked")
+        @Override public <T> T value(String field, Object key, Object val) 
throws IgniteCheckedException {
+            assert field != null;
+
+            Property prop = props.get(field);
+
+            if (prop == null)
+                throw new IgniteCheckedException("Failed to find field '" + 
field + "' in type '" + name + "'.");
+
+            return (T)prop.value(key, val);
+        }
+
+        /** {@inheritDoc} */
+        @Override public Map<String, GridQueryIndexDescriptor> indexes() {
+            return Collections.<String, 
GridQueryIndexDescriptor>unmodifiableMap(indexes);
+        }
+
+        /**
+         * Adds index.
+         *
+         * @param idxName Index name.
+         * @param type Index type.
+         * @return Index descriptor.
+         */
+        public IndexDescriptor addIndex(String idxName, GridQueryIndexType 
type) {
+            IndexDescriptor idx = new IndexDescriptor(type);
+
+            if (indexes.put(idxName, idx) != null)
+                throw new CacheException("Index with name '" + idxName + "' 
already exists.");
+
+            return idx;
+        }
 
-            return obj.getClass().equals(this.getClass());
+        /**
+         * Adds field to index.
+         *
+         * @param idxName Index name.
+         * @param field Field name.
+         * @param orderNum Fields order number in index.
+         * @param descending Sorting order.
+         */
+        public void addFieldToIndex(String idxName, String field, int orderNum,
+            boolean descending) {
+            IndexDescriptor desc = indexes.get(idxName);
+
+            if (desc == null)
+                desc = addIndex(idxName, SORTED);
+
+            desc.addField(field, orderNum, descending);
+        }
+
+        /**
+         * Adds field to text index.
+         *
+         * @param field Field name.
+         */
+        public void addFieldToTextIndex(String field) {
+            if (fullTextIdx == null) {
+                fullTextIdx = new IndexDescriptor(FULLTEXT);
+
+                indexes.put(null, fullTextIdx);
+            }
+
+            fullTextIdx.addField(field, 0, false);
+        }
+
+        /** {@inheritDoc} */
+        @Override public Class<?> valueClass() {
+            return valCls;
+        }
+
+        /**
+         * Sets value class.
+         *
+         * @param valCls Value class.
+         */
+        void valueClass(Class<?> valCls) {
+            this.valCls = valCls;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Class<?> keyClass() {
+            return keyCls;
+        }
+
+        /**
+         * Set key class.
+         *
+         * @param keyCls Key class.
+         */
+        void keyClass(Class<?> keyCls) {
+            this.keyCls = keyCls;
+        }
+
+        /**
+         * Adds property to the type descriptor.
+         *
+         * @param prop Property.
+         * @param failOnDuplicate Fail on duplicate flag.
+         */
+        public void addProperty(Property prop, boolean failOnDuplicate) {
+            String name = prop.name();
+
+            if (props.put(name, prop) != null && failOnDuplicate)
+                throw new CacheException("Property with name '" + name + "' 
already exists.");
+
+            fields.put(name, prop.type());
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean valueTextIndex() {
+            return valTextIdx;
+        }
+
+        /**
+         * Sets if this value should be text indexed.
+         *
+         * @param valTextIdx Flag value.
+         */
+        public void valueTextIndex(boolean valTextIdx) {
+            this.valTextIdx = valTextIdx;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(TypeDescriptor.class, this);
+        }
+    }
+
+    /**
+     * Index descriptor.
+     */
+    private static class IndexDescriptor implements GridQueryIndexDescriptor {
+        /** Fields sorted by order number. */
+        private final Collection<T2<String, Integer>> fields = new TreeSet<>(
+            new Comparator<T2<String, Integer>>() {
+                @Override public int compare(T2<String, Integer> o1, 
T2<String, Integer> o2) {
+                    if (o1.get2().equals(o2.get2())) // Order is equal, 
compare field names to avoid replace in Set.
+                        return o1.get1().compareTo(o2.get1());
+
+                    return o1.get2() < o2.get2() ? -1 : 1;
+                }
+            });
+
+        /** Fields which should be indexed in descending order. */
+        private Collection<String> descendings;
+
+        /** */
+        private final GridQueryIndexType type;
+
+        /**
+         * @param type Type.
+         */
+        private IndexDescriptor(GridQueryIndexType type) {
+            assert type != null;
+
+            this.type = type;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Collection<String> fields() {
+            Collection<String> res = new ArrayList<>(fields.size());
+
+            for (T2<String, Integer> t : fields)
+                res.add(t.get1());
+
+            return res;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean descending(String field) {
+            return descendings != null && descendings.contains(field);
+        }
+
+        /**
+         * Adds field to this index.
+         *
+         * @param field Field name.
+         * @param orderNum Field order number in this index.
+         * @param descending Sort order.
+         */
+        public void addField(String field, int orderNum, boolean descending) {
+            fields.add(new T2<>(field, orderNum));
+
+            if (descending) {
+                if (descendings == null)
+                    descendings  = new HashSet<>();
+
+                descendings.add(field);
+            }
+        }
+
+        /** {@inheritDoc} */
+        @Override public GridQueryIndexType type() {
+            return type;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(IndexDescriptor.class, this);
+        }
+    }
+
+    /**
+     *
+     */
+    private abstract static class Property {
+        /**
+         * Gets this property value from the given object.
+         *
+         * @param key Key.
+         * @param val Value.
+         * @return Property value.
+         * @throws IgniteCheckedException If failed.
+         */
+        public abstract Object value(Object key, Object val) throws 
IgniteCheckedException;
+
+        /**
+         * @return Property name.
+         */
+        public abstract String name();
+
+        /**
+         * @return Class member type.
+         */
+        public abstract Class<?> type();
+    }
+
+    /**
+     * Description of type property.
+     */
+    private static class ClassProperty extends Property {
+        /** */
+        private final Member member;
+
+        /** */
+        private ClassProperty parent;
+
+        /** */
+        private String name;
+
+        /** */
+        private boolean field;
+
+        /** */
+        private boolean key;
+
+        /**
+         * Constructor.
+         *
+         * @param member Element.
+         */
+        ClassProperty(Member member, boolean key) {
+            this.member = member;
+            this.key = key;
+
+            name = member instanceof Method && 
member.getName().startsWith("get") && member.getName().length() > 3 ?
+                member.getName().substring(3) : member.getName();
+
+            ((AccessibleObject) member).setAccessible(true);
+
+            field = member instanceof Field;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object value(Object key, Object val) throws 
IgniteCheckedException {
+            Object x = this.key ? key : val;
+
+            if (parent != null)
+                x = parent.value(key, val);
+
+            if (x == null)
+                return null;
+
+            try {
+                if (field) {
+                    Field field = (Field)member;
+
+                    return field.get(x);
+                }
+                else {
+                    Method mtd = (Method)member;
+
+                    return mtd.invoke(x);
+                }
+            }
+            catch (Exception e) {
+                throw new IgniteCheckedException(e);
+            }
+        }
+
+        /**
+         * @param name Property name.
+         */
+        public void name(String name) {
+            this.name = name;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String name() {
+            return name;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Class<?> type() {
+            return member instanceof Field ? ((Field)member).getType() : 
((Method)member).getReturnType();
+        }
+
+        /**
+         * @param parent Parent property if this is embeddable element.
+         */
+        public void parent(ClassProperty parent) {
+            this.parent = parent;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String toString() {
+            return S.toString(ClassProperty.class, this);
+        }
+
+        /**
+         * @param cls Class.
+         * @return {@code true} If this property or some parent relates to 
member of the given class.
+         */
+        public boolean knowsClass(Class<?> cls) {
+            return member.getDeclaringClass() == cls || (parent != null && 
parent.knowsClass(cls));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/781f0d5f/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 e080c6d..f6cff33 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
@@ -41,6 +41,8 @@ import org.jsr166.*;
 
 import javax.cache.*;
 import java.lang.reflect.*;
+import java.math.*;
+import java.sql.*;
 import java.util.*;
 import java.util.concurrent.*;
 
@@ -52,6 +54,28 @@ import static 
org.apache.ignite.internal.processors.query.GridQueryIndexType.*;
  * Indexing processor.
  */
 public class GridQueryProcessor extends GridProcessorAdapter {
+    /** */
+    private static final Class<?> GEOMETRY_CLASS = 
U.classForName("com.vividsolutions.jts.geom.Geometry", null);
+
+    /** */
+    private static Set<Class<?>> SQL_TYPES = new HashSet<>(F.<Class<?>>asList(
+        Integer.class,
+        Boolean.class,
+        Byte.class,
+        Short.class,
+        Long.class,
+        BigDecimal.class,
+        Double.class,
+        Float.class,
+        Time.class,
+        Timestamp.class,
+        java.util.Date.class,
+        java.sql.Date.class,
+        String.class,
+        UUID.class,
+        byte[].class
+    ));
+
     /** For tests. */
     public static Class<? extends GridQueryIndexing> idxCls;
 
@@ -801,6 +825,26 @@ public class GridQueryProcessor extends 
GridProcessorAdapter {
     }
 
     /**
+     * Checks if the given class can be mapped to a simple SQL type.
+     *
+     * @param cls Class.
+     * @return {@code true} If can.
+     */
+    public static boolean isSqlType(Class<?> cls) {
+        return SQL_TYPES.contains(cls);
+    }
+
+    /**
+     * Checks if the given class is GEOMETRY.
+     *
+     * @param cls Class.
+     * @return {@code true} If this is geometry.
+     */
+    public static boolean isGeometryClass(Class<?> cls) {
+        return GEOMETRY_CLASS != null && GEOMETRY_CLASS.isAssignableFrom(cls);
+    }
+
+    /**
      * Gets type name by class.
      *
      * @param cls Class.

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/781f0d5f/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 06c0961..359341a 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
@@ -1584,8 +1584,6 @@ public class IgniteH2Indexing implements 
GridQueryIndexing {
             map.put(Timestamp.class, TIMESTAMP);
             map.put(java.util.Date.class, TIMESTAMP);
             map.put(java.sql.Date.class, DATE);
-            map.put(char.class, CHAR);
-            map.put(Character.class, CHAR);
             map.put(String.class, VARCHAR);
             map.put(UUID.class, UUID);
             map.put(byte[].class, BINARY);

Reply via email to