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 2019/02/07 13:46:35 UTC

[ignite] branch master updated: IGNITE-11118: SQL: Type conversions for thin client partition pruning. This closes #6016.

This is an automated email from the ASF dual-hosted git repository.

vozerov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 3524eb9  IGNITE-11118: SQL: Type conversions for thin client partition pruning. This closes #6016.
3524eb9 is described below

commit 3524eb9d42bd865d28326c4f82070928c5e5fd75
Author: sanpwc <la...@gmail.com>
AuthorDate: Thu Feb 7 16:46:27 2019 +0300

    IGNITE-11118: SQL: Type conversions for thin client partition pruning. This closes #6016.
---
 .../sql/optimizer/affinity/PartitionAllNode.java   |   2 +-
 ...onResolver.java => PartitionClientContext.java} |  19 +-
 .../optimizer/affinity/PartitionCompositeNode.java |  27 +-
 .../optimizer/affinity/PartitionConstantNode.java  |   2 +-
 .../optimizer/affinity/PartitionDataTypeUtils.java | 528 +++++++++++++++++++++
 .../sql/optimizer/affinity/PartitionGroupNode.java |  13 +-
 .../sql/optimizer/affinity/PartitionNode.java      |   4 +-
 .../sql/optimizer/affinity/PartitionNoneNode.java  |   2 +-
 .../optimizer/affinity/PartitionParameterNode.java |  36 +-
 ...onResolver.java => PartitionParameterType.java} |  45 +-
 .../sql/optimizer/affinity/PartitionResolver.java  |   1 +
 .../optimizer/affinity/PartitionSingleNode.java    |  14 +-
 .../processors/query/h2/IgniteH2Indexing.java      |   6 +-
 .../query/h2/affinity/PartitionExtractor.java      |  69 ++-
 .../h2/twostep/SqlDataTypeConversionTest.java      | 372 +++++++++++++++
 .../IgniteBinaryCacheQueryTestSuite.java           |   5 +-
 16 files changed, 1079 insertions(+), 66 deletions(-)

diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionAllNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionAllNode.java
index c625089..cb9500d 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionAllNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionAllNode.java
@@ -36,7 +36,7 @@ public class PartitionAllNode implements PartitionNode {
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<Integer> apply(Object... args) {
+    @Override public Collection<Integer> apply(PartitionClientContext cliCtx, Object... args) {
         return null;
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionClientContext.java
similarity index 66%
copy from modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java
copy to modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionClientContext.java
index e606200..1d7594f 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionClientContext.java
@@ -14,23 +14,26 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package org.apache.ignite.internal.sql.optimizer.affinity;
 
-import org.apache.ignite.IgniteCheckedException;
+import org.jetbrains.annotations.Nullable;
 
 /**
- * Partition resolver interface. Takes argument, data type and cache name, returns partition.
+ * Client context. Passed to partition resolver on thin clients.
  */
-public interface PartitionResolver {
+public class PartitionClientContext {
     /**
      * Resolve partition.
      *
      * @param arg Argument.
-     * @param dataType Data type.
+     * @param typ Type.
      * @param cacheName Cache name.
-     * @return Partition.
-     * @throws IgniteCheckedException If failed.
+     * @return Partition or {@code null} if cannot be resolved.
      */
-    int partition(Object arg, int dataType, String cacheName) throws IgniteCheckedException;
+    @Nullable public Integer partition(Object arg, @Nullable PartitionParameterType typ, String cacheName) {
+        PartitionDataTypeUtils.convert(arg, typ);
+
+        // TODO: IGNITE-10308: Implement partition resolution logic.
+        return null;
+    }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionCompositeNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionCompositeNode.java
index d724cf8..1235e6a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionCompositeNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionCompositeNode.java
@@ -56,14 +56,21 @@ public class PartitionCompositeNode implements PartitionNode {
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<Integer> apply(Object... args) throws IgniteCheckedException {
-        Collection<Integer> leftParts = left.apply(args);
-        Collection<Integer> rightParts = right.apply(args);
+    @Override public Collection<Integer> apply(PartitionClientContext cliCtx, Object... args)
+        throws IgniteCheckedException {
+        Collection<Integer> leftParts = left.apply(cliCtx, args);
+        Collection<Integer> rightParts = right.apply(cliCtx, args);
+
+        // Failed to resolve partitions on both sides, return.
+        if (leftParts == null && rightParts == null)
+            return null;
 
         if (op == PartitionCompositeNodeOperator.AND) {
-            // () and (...) -> ()
-            if (leftParts == null || rightParts == null)
-                return null;
+            // (ALL) and (...) -> (...)
+            if (leftParts == null)
+                return rightParts;
+            else if (rightParts == null)
+                return leftParts;
 
             // (A, B) and (B, C) -> (B)
             leftParts = new HashSet<>(leftParts);
@@ -73,11 +80,9 @@ public class PartitionCompositeNode implements PartitionNode {
         else {
             assert op == PartitionCompositeNodeOperator.OR;
 
-            // () or (...) -> (...)
-            if (leftParts == null)
-                return rightParts;
-            else if (rightParts == null)
-                return leftParts;
+            // (ALL) or (...) -> (ALL)
+            if (leftParts == null || rightParts == null)
+                return null;
 
             // (A, B) or (B, C) -> (A, B, C)
             leftParts = new HashSet<>(leftParts);
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionConstantNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionConstantNode.java
index da9dca2..24037bd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionConstantNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionConstantNode.java
@@ -39,7 +39,7 @@ public class PartitionConstantNode extends PartitionSingleNode {
     }
 
     /** {@inheritDoc} */
-    @Override public int applySingle(Object... args) {
+    @Override public Integer applySingle(PartitionClientContext cliCtx, Object... args) {
         return part;
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionDataTypeUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionDataTypeUtils.java
new file mode 100644
index 0000000..cbb9810
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionDataTypeUtils.java
@@ -0,0 +1,528 @@
+/*
+ * 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.sql.optimizer.affinity;
+
+import java.math.BigDecimal;
+import java.util.UUID;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Utility methods for partition extractor.
+ */
+public class PartitionDataTypeUtils {
+    /** Decimal representation of maximum long value. */
+    private static final BigDecimal MAX_LONG_DECIMAL = BigDecimal.valueOf(Long.MAX_VALUE);
+
+    /** Decimal representation of minimum long value. */
+    private static final BigDecimal MIN_LONG_DECIMAL = BigDecimal.valueOf(Long.MIN_VALUE);
+
+    /** Decimal representation of maximum int value. */
+    private static final BigDecimal MAX_INTEGER_DECIMAL = new BigDecimal(Integer.MAX_VALUE);
+
+    /** Decimal representation of minimum int value. */
+    private static final BigDecimal MIN_INTEGER_DECIMAL = new BigDecimal(Integer.MIN_VALUE);
+
+    /** Decimal representation of maximum short value. */
+    private static final BigDecimal MAX_SHORT_DECIMAL = new BigDecimal(Short.MAX_VALUE);
+
+    /** Decimal representation of minimum short value. */
+    private static final BigDecimal MIN_SHORT_DECIMAL = new BigDecimal(Short.MIN_VALUE);
+
+    /** Decimal representation of maximum byte value. */
+    private static final BigDecimal MAX_BYTE_DECIMAL = new BigDecimal(Byte.MAX_VALUE);
+
+    /** Decimal representation of minimum byte value. */
+    private static final BigDecimal MIN_BYTE_DECIMAL = new BigDecimal(Byte.MIN_VALUE);
+
+    /** Convertation failure marker. */
+    public static final Object CONVERTATION_FAILURE = new Object();
+
+    /**
+     * Convert argument to the given type.
+     *
+     * @param arg Argument.
+     * @param targetType Type.
+     * @return Converted argument or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    public static Object convert(Object arg, PartitionParameterType targetType) {
+        assert targetType != null;
+
+        if (arg == null)
+            return null;
+
+        PartitionParameterType argType = typeFromClass(arg.getClass());
+
+        if (argType == null)
+            return CONVERTATION_FAILURE;
+
+        if (argType == targetType)
+            return arg;
+
+        try {
+            switch (targetType) {
+                case BOOLEAN:
+                    return getBoolean(arg, argType);
+
+                case BYTE:
+                    return getIntegerNumeric(
+                        arg,
+                        argType,
+                        Byte.MIN_VALUE,
+                        Byte.MAX_VALUE,
+                        MIN_BYTE_DECIMAL,
+                        MAX_BYTE_DECIMAL,
+                        PartitionParameterType.BYTE
+                    );
+
+                case SHORT:
+                    return getIntegerNumeric(
+                        arg,
+                        argType,
+                        Short.MIN_VALUE,
+                        Short.MAX_VALUE,
+                        MIN_SHORT_DECIMAL,
+                        MAX_SHORT_DECIMAL,
+                        PartitionParameterType.SHORT
+                    );
+
+                case INT:
+                    return getIntegerNumeric(
+                        arg,
+                        argType,
+                        Integer.MIN_VALUE,
+                        Integer.MAX_VALUE,
+                        MIN_INTEGER_DECIMAL,
+                        MAX_INTEGER_DECIMAL,
+                        PartitionParameterType.INT
+                    );
+
+                case LONG:
+                    return getIntegerNumeric(
+                        arg,
+                        argType,
+                        Long.MIN_VALUE,
+                        Long.MAX_VALUE, MIN_LONG_DECIMAL,
+                        MAX_LONG_DECIMAL,
+                        PartitionParameterType.LONG
+                    );
+
+                case FLOAT:
+                    return getFloat(arg, argType);
+
+                case DOUBLE:
+                    return getDouble(arg, argType);
+
+                case DECIMAL:
+                    return getDecimal(arg, argType);
+
+                case STRING:
+                    return getString(arg, argType);
+
+                case UUID:
+                    return getUUID(arg, argType);
+
+                default:
+                    return CONVERTATION_FAILURE;
+            }
+        }
+        catch (NumberFormatException e) {
+            return CONVERTATION_FAILURE;
+        }
+    }
+
+    /**
+     * Convert argument to <code>UUID</code>.
+     *
+     * @param arg Argument to convert.
+     * @param argType Argument type.
+     * @return Converted value or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    @NotNull private static Object getUUID(Object arg, PartitionParameterType argType) {
+        switch (argType) {
+            case STRING:
+                return stringToUUID((String)arg);
+
+            default:
+                return CONVERTATION_FAILURE;
+        }
+    }
+
+    /**
+     * Convert argument to <code>String</code>.
+     *
+     * @param arg Argument to convert.
+     * @param argType Argument type.
+     * @return Converted value or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    private static Object getString(Object arg, PartitionParameterType argType) {
+        switch (argType) {
+            case BOOLEAN:
+                return (Boolean)arg ? "TRUE" : "FALSE";
+
+            case BYTE:
+            case SHORT:
+            case INT:
+            case LONG:
+            case DOUBLE:
+            case FLOAT:
+                return String.valueOf(arg);
+
+            case DECIMAL: {
+                // We had to use such kind of convertation instead of common arg.toString() in order to match
+                // H2 convertation results. In case of using arg.toString() we will have inconsistant convertation
+                // results for values similar to BigDecimal.valueOf(12334535345456700.12345634534534578901).
+                // Main difference between toPlainString() and toString() is that toPlainString()
+                // returns a string representation of a {@code BigDecimal}  without an exponent field.
+                String p = ((BigDecimal)arg).toPlainString();
+
+                return p.length() < 40 ? p : arg.toString();
+            }
+
+            case UUID:
+                return arg.toString();
+
+            default:
+                return CONVERTATION_FAILURE;
+        }
+    }
+
+    /**
+     * Convert argument to <code>Float</code>.
+     *
+     * @param arg Argument to convert.
+     * @param argType Argument type.
+     * @return Converted value or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    @NotNull private static Object getFloat(Object arg, PartitionParameterType argType) {
+        switch (argType) {
+            case BOOLEAN:
+                return arg.equals(Boolean.TRUE) ? (float)1 : (float)0;
+
+            case BYTE:
+            case SHORT:
+            case INT:
+            case LONG:
+            case DECIMAL:
+            case DOUBLE:
+                return ((Number)arg).floatValue();
+
+            case STRING:
+                return Float.parseFloat(((String)arg).trim());
+
+            default:
+                return CONVERTATION_FAILURE;
+        }
+    }
+
+    /**
+     * Convert argument to <code>Double</code>.
+     *
+     * @param arg Argument to convert.
+     * @param argType Argument type.
+     * @return Converted value or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    @NotNull private static Object getDouble(Object arg, PartitionParameterType argType) {
+        switch (argType) {
+            case BOOLEAN:
+                return arg.equals(Boolean.TRUE) ? (double)1 : (double)0;
+
+            case BYTE:
+            case SHORT:
+            case INT:
+            case LONG:
+            case DECIMAL:
+            case FLOAT:
+                return ((Number)arg).doubleValue();
+
+            case STRING:
+                return Double.parseDouble(((String)arg).trim());
+
+            default:
+                return CONVERTATION_FAILURE;
+        }
+    }
+
+    /**
+     * Convert argument to <code>Decimal</code>.
+     *
+     * @param arg Argument to convert.
+     * @param argType Argument type.
+     * @return Converted value or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    @NotNull private static Object getDecimal(Object arg, PartitionParameterType argType) {
+        switch (argType) {
+            case BOOLEAN:
+                return arg.equals(Boolean.TRUE) ? BigDecimal.ONE : BigDecimal.ZERO;
+
+            case BYTE:
+            case SHORT:
+            case INT:
+            case LONG:
+                return BigDecimal.valueOf(((Number)arg).longValue());
+
+            case DOUBLE: {
+                double d = (double)arg;
+
+                if (Double.isInfinite(d) || Double.isNaN(d))
+                    return CONVERTATION_FAILURE;
+
+                return BigDecimal.valueOf(d);
+            }
+            case FLOAT: {
+                float f = (float)arg;
+
+                if (Float.isInfinite(f) || Float.isNaN(f))
+                    return CONVERTATION_FAILURE;
+
+                return new BigDecimal(Float.toString(f));
+            }
+
+            case STRING:
+                return new BigDecimal(((String)arg).trim());
+
+            default:
+                return CONVERTATION_FAILURE;
+        }
+    }
+
+    /**
+     * Convert argument to integer numeric: byte, short, int, long.
+     *
+     * @param arg Argument to convert.
+     * @param argType Argument type.
+     * @return Converted value or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    @SuppressWarnings("EnumSwitchStatementWhichMissesCases")
+    @NotNull private static Object getIntegerNumeric(
+        Object arg,
+        PartitionParameterType argType,
+        long minVal,
+        long maxVal,
+        BigDecimal minValDecimal,
+        BigDecimal maxValDecimal,
+        PartitionParameterType targetType
+    ) {
+        assert targetType == PartitionParameterType.BYTE || targetType == PartitionParameterType.SHORT ||
+            targetType == PartitionParameterType.INT || targetType == PartitionParameterType.LONG;
+
+        long res;
+
+        switch (argType) {
+            case BOOLEAN:
+                res = arg.equals(Boolean.TRUE) ? 1L : 0L;
+
+                break;
+
+            case BYTE:
+            case SHORT:
+            case INT:
+            case LONG: {
+                res = ((Number)arg).longValue();
+
+                if (res > maxVal || res < minVal)
+                    return CONVERTATION_FAILURE;
+
+                break;
+            }
+            case DECIMAL: {
+                BigDecimal d = (BigDecimal)arg;
+
+                if (d.compareTo(maxValDecimal) > 0 || d.compareTo(minValDecimal) < 0)
+                    return CONVERTATION_FAILURE;
+                else
+                    res = d.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
+
+                break;
+            }
+
+            case DOUBLE: {
+                Double d = (Double)arg;
+
+                if (d > maxVal || d < minVal)
+                    return CONVERTATION_FAILURE;
+                else
+                    res = Math.round(d);
+
+                break;
+            }
+
+            case FLOAT: {
+                Float f = (Float)arg;
+
+                if (f > maxVal || f < minVal)
+                    return CONVERTATION_FAILURE;
+                else
+                    res = Math.round(f);
+
+                break;
+            }
+
+            case STRING: {
+                res = Long.parseLong(((String)arg).trim());
+
+                if (res > maxVal || res < minVal)
+                    return CONVERTATION_FAILURE;
+
+                break;
+            }
+
+            default:
+                return CONVERTATION_FAILURE;
+        }
+
+        switch (targetType) {
+            case BYTE:
+                return (byte)res;
+            case SHORT:
+                return (short)res;
+            case INT:
+                return (int)res;
+            case LONG:
+                return res;
+        }
+
+        return CONVERTATION_FAILURE;
+    }
+
+    /**
+     * Convert argument to <code>Boolean</code>.
+     *
+     * @param arg Argument to convert.
+     * @param argType Argument type.
+     * @return Converted value or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    @NotNull private static Object getBoolean(Object arg, PartitionParameterType argType) {
+        switch (argType) {
+            case BYTE:
+                return (Byte)arg != 0;
+
+            case SHORT:
+                return (Short)arg != 0;
+
+            case INT:
+                return (Integer)arg != 0;
+
+            case LONG:
+                return (Long)arg != 0;
+
+            case DECIMAL:
+                return !arg.equals(BigDecimal.ZERO);
+
+            case DOUBLE:
+                return Math.signum((Double)arg) != 0;
+
+            case FLOAT:
+                return Math.signum((Float)arg) != 0;
+
+            case STRING: {
+                String sVal = (String)arg;
+
+                if ("true".equalsIgnoreCase(sVal) ||
+                    "t".equalsIgnoreCase(sVal) ||
+                    "yes".equalsIgnoreCase(sVal) ||
+                    "y".equalsIgnoreCase(sVal) ||
+                    "1".equals(sVal))
+                    return Boolean.TRUE;
+                else if ("false".equalsIgnoreCase(sVal) ||
+                    "f".equalsIgnoreCase(sVal) ||
+                    "no".equalsIgnoreCase(sVal) ||
+                    "n".equalsIgnoreCase(sVal) ||
+                    "0".equals(sVal))
+                    return Boolean.FALSE;
+            }
+            default:
+                return CONVERTATION_FAILURE;
+        }
+    }
+
+    /**
+     * Get the <code>PartitionParameterType</code> type for the given Java class.
+     *
+     * @param c The Java class.
+     * @return The <code>PartitionParameterType</code> type.
+     */
+    private static PartitionParameterType typeFromClass(Class<?> c) {
+        assert c != null;
+
+        if (String.class == c)
+            return PartitionParameterType.STRING;
+        else if (Integer.class == c)
+            return PartitionParameterType.INT;
+        else if (Long.class == c)
+            return PartitionParameterType.LONG;
+        else if (Boolean.class == c)
+            return PartitionParameterType.BOOLEAN;
+        else if (Double.class == c)
+            return PartitionParameterType.DOUBLE;
+        else if (Byte.class == c)
+            return PartitionParameterType.BYTE;
+        else if (Short.class == c)
+            return PartitionParameterType.SHORT;
+        else if (Float.class == c)
+            return PartitionParameterType.FLOAT;
+        else if (UUID.class == c)
+            return PartitionParameterType.UUID;
+        else if (BigDecimal.class == c)
+            return PartitionParameterType.DECIMAL;
+        else
+            return null;
+    }
+
+    /**
+     * Utility method that helps to convert String to UUID. Given method is more fault tolerant than more common
+     * <code>UUID.fromString()</code>. For example it supports String represendation of UUID-without-hyphens
+     * conversion, that is not supported by mentioned above <code>UUID.fromString()</code>.
+     *
+     * @param s String to
+     * @return UUID or <code>CONVERTATION_FAILURE</code> if convertation failed.
+     */
+    public static Object stringToUUID(String s) {
+        long low = 0, high = 0;
+        for (int i = 0, j = 0, len = s.length(); i < len; i++) {
+            char c = s.charAt(i);
+
+            if (c >= '0' && c <= '9')
+                low = (low << 4) | (c - '0');
+            else if (c >= 'a' && c <= 'f')
+                low = (low << 4) | (c - 'a' + 0xa);
+            else if (c == '-')
+                continue;
+            else if (c >= 'A' && c <= 'F')
+                low = (low << 4) | (c - 'A' + 0xa);
+            else if (c <= ' ')
+                continue;
+            else
+                return CONVERTATION_FAILURE;
+
+            if (j++ == 15) {
+                high = low;
+
+                low = 0;
+            }
+        }
+
+        return new UUID(high, low);
+    }
+
+    /**
+     * Private constructor.
+     */
+    private PartitionDataTypeUtils() {
+        // No-op.
+    }
+}
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionGroupNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionGroupNode.java
index b7106a7..8a3c5d1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionGroupNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionGroupNode.java
@@ -46,12 +46,19 @@ public class PartitionGroupNode implements PartitionNode {
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<Integer> apply(Object... args) throws IgniteCheckedException {
+    @Override public Collection<Integer> apply(PartitionClientContext ctx, Object... args)
+        throws IgniteCheckedException {
         // Deduplicate same partitions which may appear during resolution.
         HashSet<Integer> res = new HashSet<>(siblings.size());
 
-        for (PartitionSingleNode sibling : siblings)
-            res.add(sibling.applySingle(args));
+        for (PartitionSingleNode sibling : siblings) {
+            Integer part = sibling.applySingle(ctx, args);
+
+            if (part == null)
+                return null;
+
+            res.add(part);
+        }
 
         return res;
     }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNode.java
index c8c354c..57936b1 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNode.java
@@ -18,6 +18,7 @@
 package org.apache.ignite.internal.sql.optimizer.affinity;
 
 import org.apache.ignite.IgniteCheckedException;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
 
@@ -28,11 +29,12 @@ public interface PartitionNode {
     /**
      * Get partitions.
      *
+     * @param cliCtx Thin client context (optional).
      * @param args Query arguments.
      * @return Partitions.
      * @throws IgniteCheckedException If failed.
      */
-    Collection<Integer> apply(Object... args) throws IgniteCheckedException;
+    Collection<Integer> apply(@Nullable PartitionClientContext cliCtx, Object... args) throws IgniteCheckedException;
 
     /**
      * @return Join group for the given node.
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNoneNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNoneNode.java
index f136fc9..361b3e0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNoneNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionNoneNode.java
@@ -37,7 +37,7 @@ public class PartitionNoneNode implements PartitionNode {
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<Integer> apply(Object... args) {
+    @Override public Collection<Integer> apply(PartitionClientContext cliCtx, Object... args) {
         return Collections.emptySet();
     }
 
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionParameterNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionParameterNode.java
index 6219c30..c909a23 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionParameterNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionParameterNode.java
@@ -32,8 +32,11 @@ public class PartitionParameterNode extends PartitionSingleNode {
     /** Index. */
     private final int idx;
 
-    /** Data type. */
-    private final int dataType;
+    /** Parameter data type. */
+    private final int type;
+
+    /** Mapped parameter type. */
+    private final PartitionParameterType mappedType;
 
     /**
      * Constructor.
@@ -41,26 +44,37 @@ public class PartitionParameterNode extends PartitionSingleNode {
      * @param tbl Table descriptor.
      * @param partResolver Partition resolver.
      * @param idx Parameter index.
-     * @param dataType Parameter data type.
+     * @param type Parameter data type.
+     * @param mappedType Mapped parameter type to be used by thin clients.
      */
-    public PartitionParameterNode(PartitionTable tbl, PartitionResolver partResolver, int idx, int dataType) {
+    public PartitionParameterNode(PartitionTable tbl, PartitionResolver partResolver, int idx, int type,
+        PartitionParameterType mappedType) {
         super(tbl);
 
         this.partResolver = partResolver;
         this.idx = idx;
-        this.dataType = dataType;
+        this.type = type;
+        this.mappedType = mappedType;
     }
 
     /** {@inheritDoc} */
-    @Override public int applySingle(Object... args) throws IgniteCheckedException {
+    @Override public Integer applySingle(PartitionClientContext cliCtx, Object... args) throws IgniteCheckedException {
         assert args != null;
         assert idx < args.length;
 
-        return partResolver.partition(
-            args[idx],
-            dataType,
-            tbl.cacheName()
-        );
+        Object arg = args[idx];
+
+        if (cliCtx != null)
+            return cliCtx.partition(arg, mappedType, tbl.cacheName());
+        else {
+            assert partResolver != null;
+
+            return partResolver.partition(
+                arg,
+                type,
+                tbl.cacheName()
+            );
+        }
     }
 
     /** {@inheritDoc} */
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionParameterType.java
similarity index 63%
copy from modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java
copy to modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionParameterType.java
index e606200..ff0943b 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionParameterType.java
@@ -17,20 +17,37 @@
 
 package org.apache.ignite.internal.sql.optimizer.affinity;
 
-import org.apache.ignite.IgniteCheckedException;
-
 /**
- * Partition resolver interface. Takes argument, data type and cache name, returns partition.
+ * Partition argument type.
  */
-public interface PartitionResolver {
-    /**
-     * Resolve partition.
-     *
-     * @param arg Argument.
-     * @param dataType Data type.
-     * @param cacheName Cache name.
-     * @return Partition.
-     * @throws IgniteCheckedException If failed.
-     */
-    int partition(Object arg, int dataType, String cacheName) throws IgniteCheckedException;
+public enum PartitionParameterType {
+    /** Boolean. */
+    BOOLEAN,
+
+    /** Byte. */
+    BYTE,
+
+    /** Short. */
+    SHORT,
+
+    /** Int. */
+    INT,
+
+    /** Long. */
+    LONG,
+
+    /** Float. */
+    FLOAT,
+
+    /** Double. */
+    DOUBLE,
+
+    /** String. */
+    STRING,
+
+    /** Decimal. */
+    DECIMAL,
+
+    /** UUID. */
+    UUID
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java
index e606200..4d25bef 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionResolver.java
@@ -21,6 +21,7 @@ import org.apache.ignite.IgniteCheckedException;
 
 /**
  * Partition resolver interface. Takes argument, data type and cache name, returns partition.
+ * The only purpose of this methods is to allow partition pruning classes to be located in core module.
  */
 public interface PartitionResolver {
     /**
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionSingleNode.java b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionSingleNode.java
index 466e1c6..33f61d0 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionSingleNode.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/sql/optimizer/affinity/PartitionSingleNode.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.sql.optimizer.affinity;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.F;
+import org.jetbrains.annotations.Nullable;
 
 import java.util.Collection;
 import java.util.Collections;
@@ -42,17 +43,22 @@ public abstract class PartitionSingleNode implements PartitionNode {
     }
 
     /** {@inheritDoc} */
-    @Override public Collection<Integer> apply(Object... args) throws IgniteCheckedException {
-        return Collections.singletonList(applySingle(args));
+    @Override public Collection<Integer> apply(PartitionClientContext cliCtx, Object... args)
+        throws IgniteCheckedException {
+        Integer part = applySingle(cliCtx, args);
+
+        return part != null ? Collections.singletonList(part) : null;
     }
 
     /**
      * Apply arguments and get single partition.
      *
+     * @param cliCtx Client context.
      * @param args Arguments.
-     * @return Partition.
+     * @return Partition or {@code null} if failed.
      */
-    public abstract int applySingle(Object... args) throws IgniteCheckedException;
+    public abstract Integer applySingle(@Nullable PartitionClientContext cliCtx, Object... args)
+        throws IgniteCheckedException;
 
     /**
      * @return {@code True} if constant, {@code false} if argument.
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 9ee056f..f5b013f 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
@@ -2103,9 +2103,11 @@ public class IgniteH2Indexing implements GridQueryIndexing {
             return explicitParts;
         else if (derivedParts != null) {
             try {
-                Collection<Integer> realParts = derivedParts.tree().apply(args);
+                Collection<Integer> realParts = derivedParts.tree().apply(null, args);
 
-                if (F.isEmpty(realParts))
+                if (realParts == null)
+                    return null;
+                else if (realParts.isEmpty())
                     return IgniteUtils.EMPTY_INTS;
                 else {
                     int[] realParts0 = new int[realParts.size()];
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/affinity/PartitionExtractor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/affinity/PartitionExtractor.java
index f82be53..996a3b2 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/affinity/PartitionExtractor.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/affinity/PartitionExtractor.java
@@ -17,6 +17,11 @@
 
 package org.apache.ignite.internal.processors.query.h2.affinity;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import org.apache.ignite.IgniteCheckedException;
 import org.apache.ignite.IgniteSystemProperties;
 import org.apache.ignite.cache.CacheMode;
@@ -46,6 +51,7 @@ import org.apache.ignite.internal.sql.optimizer.affinity.PartitionJoinCondition;
 import org.apache.ignite.internal.sql.optimizer.affinity.PartitionNode;
 import org.apache.ignite.internal.sql.optimizer.affinity.PartitionNoneNode;
 import org.apache.ignite.internal.sql.optimizer.affinity.PartitionParameterNode;
+import org.apache.ignite.internal.sql.optimizer.affinity.PartitionParameterType;
 import org.apache.ignite.internal.sql.optimizer.affinity.PartitionResult;
 import org.apache.ignite.internal.sql.optimizer.affinity.PartitionSingleNode;
 import org.apache.ignite.internal.sql.optimizer.affinity.PartitionTable;
@@ -56,12 +62,6 @@ import org.h2.table.Column;
 import org.h2.value.Value;
 import org.jetbrains.annotations.Nullable;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 /**
  * Partition tree extractor.
  */
@@ -623,13 +623,66 @@ public class PartitionExtractor {
 
             return new PartitionConstantNode(tbl0, part);
         }
-        else if (rightParam != null)
-            return new PartitionParameterNode(tbl0, partResolver, rightParam.index(), leftCol0.getType());
+        else if (rightParam != null) {
+            int colType = leftCol0.getType();
+
+            return new PartitionParameterNode(
+                tbl0,
+                partResolver,
+                rightParam.index(),
+                leftCol0.getType(),
+                mappedType(colType)
+            );
+        }
         else
             return null;
     }
 
     /**
+     * Mapped Ignite type for H2 type.
+     *
+     * @param type H2 type.
+     * @return ignite type.
+     */
+    @Nullable private static PartitionParameterType mappedType(int type) {
+        // Try map if possible.
+        switch (type) {
+            case Value.BOOLEAN:
+                return PartitionParameterType.BOOLEAN;
+
+            case Value.BYTE:
+                return PartitionParameterType.BYTE;
+
+            case Value.SHORT:
+                return PartitionParameterType.SHORT;
+
+            case Value.INT:
+                return PartitionParameterType.INT;
+
+            case Value.LONG:
+                return PartitionParameterType.LONG;
+
+            case Value.FLOAT:
+                return PartitionParameterType.FLOAT;
+
+            case Value.DOUBLE:
+                return PartitionParameterType.DOUBLE;
+
+            case Value.STRING:
+                return PartitionParameterType.STRING;
+
+            case Value.DECIMAL:
+                return PartitionParameterType.DECIMAL;
+
+            case Value.UUID:
+                return PartitionParameterType.UUID;
+        }
+
+        // Otherwise we do not support it.
+        return null;
+    }
+
+    /**
      * Unwrap constant if possible.
      *
      * @param ast AST.
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/twostep/SqlDataTypeConversionTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/twostep/SqlDataTypeConversionTest.java
new file mode 100644
index 0000000..3e62d5d
--- /dev/null
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/twostep/SqlDataTypeConversionTest.java
@@ -0,0 +1,372 @@
+/*
+ * 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;
+
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.UUID;
+import org.apache.ignite.internal.processors.query.h2.H2Utils;
+import org.apache.ignite.internal.processors.query.h2.IgniteH2Indexing;
+import org.apache.ignite.internal.sql.optimizer.affinity.PartitionDataTypeUtils;
+import org.apache.ignite.internal.sql.optimizer.affinity.PartitionParameterType;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.h2.value.Value;
+import org.junit.Test;
+
+/**
+ * Data conversion tests.
+ */
+public class SqlDataTypeConversionTest extends GridCommonAbstractTest {
+    /** Map to convert <code>PartitionParameterType</code> instances to correspondig java classes. */
+    private static final Map<PartitionParameterType, Class<?>> PARAMETER_TYPE_TO_JAVA_CLASS;
+
+    /** Map to convert <code>PartitionParameterType</code> instances to correspondig H2 data types. */
+    private static final Map<PartitionParameterType, Integer> IGNITE_PARAMETER_TYPE_TO_H2_PARAMETER_TYPE;
+
+    /** Ignite H2 Indexing. */
+    private static IgniteH2Indexing idx;
+
+    static {
+        Map<PartitionParameterType, Class<?>> paramTypeToJavaCls = new EnumMap<>(PartitionParameterType.class);
+
+        paramTypeToJavaCls.put(PartitionParameterType.BOOLEAN, Boolean.class);
+        paramTypeToJavaCls.put(PartitionParameterType.BYTE, Byte.class);
+        paramTypeToJavaCls.put(PartitionParameterType.SHORT, Short.class);
+        paramTypeToJavaCls.put(PartitionParameterType.INT, Integer.class);
+        paramTypeToJavaCls.put(PartitionParameterType.LONG, Long.class);
+        paramTypeToJavaCls.put(PartitionParameterType.FLOAT, Float.class);
+        paramTypeToJavaCls.put(PartitionParameterType.DOUBLE, Double.class);
+        paramTypeToJavaCls.put(PartitionParameterType.STRING, String.class);
+        paramTypeToJavaCls.put(PartitionParameterType.DECIMAL, BigDecimal.class);
+        paramTypeToJavaCls.put(PartitionParameterType.UUID, UUID.class);
+
+        PARAMETER_TYPE_TO_JAVA_CLASS = Collections.unmodifiableMap(paramTypeToJavaCls);
+
+        Map<PartitionParameterType, Integer> igniteParamTypeToH2ParamType = new EnumMap<>(PartitionParameterType.class);
+
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.BOOLEAN, Value.BOOLEAN);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.BYTE, Value.BYTE);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.SHORT, Value.SHORT);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.INT, Value.INT);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.LONG, Value.LONG);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.FLOAT, Value.FLOAT);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.DOUBLE, Value.DOUBLE);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.STRING, Value.STRING);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.DECIMAL, Value.DECIMAL);
+        igniteParamTypeToH2ParamType.put(PartitionParameterType.UUID, Value.UUID);
+
+        IGNITE_PARAMETER_TYPE_TO_H2_PARAMETER_TYPE = Collections.unmodifiableMap(igniteParamTypeToH2ParamType);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        idx = (IgniteH2Indexing)startGrid(0).context().query().getIndexing();
+    }
+
+    /**
+     * Test null value conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertNull() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(null);
+    }
+
+    /**
+     * Test boolean conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertBoolean() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Boolean.TRUE);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Boolean.FALSE);
+    }
+
+    /**
+     * Test byte conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertByte() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2((byte)42, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2((byte)0, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Byte.MIN_VALUE, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Byte.MAX_VALUE, PartitionParameterType.UUID);
+
+        assertEquals(PartitionDataTypeUtils.CONVERTATION_FAILURE,
+            PartitionDataTypeUtils.convert((byte)42, PartitionParameterType.UUID));
+    }
+
+    /**
+     * Test short conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertShort() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2((short)42, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2((short)0, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Short.MIN_VALUE, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Short.MAX_VALUE, PartitionParameterType.UUID);
+
+        assertEquals(PartitionDataTypeUtils.CONVERTATION_FAILURE,
+            PartitionDataTypeUtils.convert((short)42, PartitionParameterType.UUID));
+    }
+
+    /**
+     * Test int conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertInteger() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(42, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(0, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Integer.MIN_VALUE, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Integer.MAX_VALUE, PartitionParameterType.UUID);
+
+        assertEquals(PartitionDataTypeUtils.CONVERTATION_FAILURE,
+            PartitionDataTypeUtils.convert(42, PartitionParameterType.UUID));
+    }
+
+    /**
+     * Test long conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertLong() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(42L, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(0L, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Long.MIN_VALUE, PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Long.MAX_VALUE, PartitionParameterType.UUID);
+
+        assertEquals(PartitionDataTypeUtils.CONVERTATION_FAILURE,
+            PartitionDataTypeUtils.convert(42L, PartitionParameterType.UUID));
+    }
+
+    /**
+     * Test float conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertFloat() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(42.1f);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(0.1f);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(0f);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(1.2345678E7f);
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Float.POSITIVE_INFINITY);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Float.NEGATIVE_INFINITY);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Float.NaN);
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Float.MIN_VALUE);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Float.MAX_VALUE);
+    }
+
+    /**
+     * Test double conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertDouble() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(42.2d);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(0.2d);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(0d);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(1.2345678E7d);
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Double.POSITIVE_INFINITY);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Double.NEGATIVE_INFINITY);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Double.NaN);
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Double.MIN_VALUE);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(Double.MAX_VALUE);
+    }
+
+    /**
+     * Test string conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertString() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("42", PartitionParameterType.BOOLEAN);
+
+        assertEquals(PartitionDataTypeUtils.CONVERTATION_FAILURE,
+            PartitionDataTypeUtils.convert("42", PartitionParameterType.BOOLEAN));
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("0");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("1");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("42.3", PartitionParameterType.BOOLEAN);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("0.3", PartitionParameterType.BOOLEAN);
+
+        assertEquals(PartitionDataTypeUtils.CONVERTATION_FAILURE,
+            PartitionDataTypeUtils.convert("0.3", PartitionParameterType.BOOLEAN));
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("42.4f");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("0.4d");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("12345678901234567890.123456789012345678901d");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("04d17cf3-bc20-4e3d-9ff7-72437cdae227");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("04d17cf3bc204e3d9ff772437cdae227");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("a");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("aaa",
+            PartitionParameterType.BOOLEAN);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(" aaa ");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("true");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("t");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("yes");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("y");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("false");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("f");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("no");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("n");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(" true ");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("null");
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("NULL");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("2000-01-02");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("10:00:00");
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2("2001-01-01 23:59:59.123456");
+    }
+
+    /**
+     * Test decimal conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertDecimal() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(new BigDecimal(42.5d), PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(new BigDecimal(0.5d), PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(new BigDecimal(0), PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(new BigDecimal(1.2345678E7),
+            PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(BigDecimal.valueOf(12334535345456700.12345634534534578901),
+            PartitionParameterType.UUID);
+
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(new BigDecimal(Double.MIN_VALUE),
+            PartitionParameterType.UUID);
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(new BigDecimal(Double.MAX_VALUE),
+            PartitionParameterType.UUID);
+
+        assertEquals(PartitionDataTypeUtils.CONVERTATION_FAILURE,
+            PartitionDataTypeUtils.convert(new BigDecimal(42.5d), PartitionParameterType.UUID));
+    }
+
+    /**
+     * Test uuid conversion.
+     *
+     * @throws Exception If failed.
+     */
+    @Test
+    public void convertUUID() throws Exception {
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(UUID.randomUUID());
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(UUID.fromString("00000000-0000-0000-0000-00000000000a"));
+        makeSureThatConvertationResultsExactTheSameAsWithinH2(new UUID(0L, 1L));
+    }
+
+    /**
+     * Test string to uuid conversion with different combinations of upper and lower case letters and with/without
+     * hyphens.
+     */
+    @Test
+    public void stringToUUIDConvertation() {
+        UUID expUuid = UUID.fromString("273ded0d-86de-432e-b252-54c06ec22927");
+
+        // Lower case and hyphens.
+        assertEquals(expUuid, PartitionDataTypeUtils.stringToUUID("273ded0d-86de-432e-b252-54c06ec22927"));
+
+        // Lower case without hyphens.
+        assertEquals(expUuid, PartitionDataTypeUtils.stringToUUID("273ded0d86de432eb25254c06ec22927"));
+
+        // Lower case without few hyphens.
+        assertEquals(expUuid, PartitionDataTypeUtils.stringToUUID("273ded0d86de432e-b25254c06ec22927"));
+
+        // Upper case and hyphens.
+        assertEquals(expUuid, PartitionDataTypeUtils.stringToUUID("273dED0D-86DE-432E-B25254C06EC22927"));
+
+        // Upper case without few hyphens.
+        assertEquals(expUuid, PartitionDataTypeUtils.stringToUUID("273dED0D86DE432Eb252-54c06ec22927"));
+    }
+
+    /**
+     * Actual conversial check logic.
+     *
+     * @param arg Argument to convert.
+     * @param excludedTargetTypesFromCheck <@code>PartitionParameterType</code> instances to exclude from check.
+     * @throws Exception If failed.
+     */
+    private void makeSureThatConvertationResultsExactTheSameAsWithinH2(Object arg,
+        PartitionParameterType ... excludedTargetTypesFromCheck) throws Exception {
+
+        Iterable<PartitionParameterType> targetTypes = excludedTargetTypesFromCheck.length > 0 ?
+            EnumSet.complementOf(EnumSet.of(excludedTargetTypesFromCheck[0], excludedTargetTypesFromCheck)):
+            EnumSet.allOf(PartitionParameterType.class);
+
+        for (PartitionParameterType targetType : targetTypes) {
+            Object convertationRes = PartitionDataTypeUtils.convert(arg, targetType);
+
+            if (PartitionDataTypeUtils.CONVERTATION_FAILURE == convertationRes) {
+                try {
+                    H2Utils.convert(arg, idx, IGNITE_PARAMETER_TYPE_TO_H2_PARAMETER_TYPE.get(targetType));
+
+                    fail("Data conversion failed in Ignite but not in H2.");
+                }
+                catch (org.h2.message.DbException h2Exception) {
+                    assertTrue(h2Exception.getMessage().contains("Numeric value out of range") ||
+                        h2Exception.getMessage().contains("Data conversion error"));
+                }
+            }
+            else {
+                Object convertationH2Res = H2Utils.convert(arg, idx,
+                    IGNITE_PARAMETER_TYPE_TO_H2_PARAMETER_TYPE.get(targetType));
+
+                if (convertationRes == null)
+                    assertNull(convertationH2Res);
+                else {
+                    assertEquals(PARAMETER_TYPE_TO_JAVA_CLASS.get(targetType), convertationRes.getClass());
+                    assertEquals(convertationH2Res.getClass(), convertationRes.getClass());
+                    assertEquals(convertationH2Res, convertationRes);
+                }
+            }
+        }
+    }
+}
diff --git a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
index 4482b612c..a275ac6 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite.java
@@ -82,8 +82,8 @@ import org.apache.ignite.internal.processors.cache.IgniteCachePrimitiveFieldsQue
 import org.apache.ignite.internal.processors.cache.IgniteCacheQueryH2IndexingLeakTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheQueryIndexSelfTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheQueryLoadSelfTest;
-import org.apache.ignite.internal.processors.cache.IgniteCacheSqlInsertValidationSelfTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheSqlDmlErrorSelfTest;
+import org.apache.ignite.internal.processors.cache.IgniteCacheSqlInsertValidationSelfTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheSqlQueryErrorSelfTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheUnionDuplicatesTest;
 import org.apache.ignite.internal.processors.cache.IgniteCacheUpdateSqlQuerySelfTest;
@@ -223,6 +223,7 @@ import org.apache.ignite.internal.processors.query.h2.twostep.BetweenOperationEx
 import org.apache.ignite.internal.processors.query.h2.twostep.DmlSelectPartitionPruningSelfTest;
 import org.apache.ignite.internal.processors.query.h2.twostep.InOperationExtractPartitionSelfTest;
 import org.apache.ignite.internal.processors.query.h2.twostep.JoinPartitionPruningSelfTest;
+import org.apache.ignite.internal.processors.query.h2.twostep.SqlDataTypeConversionTest;
 import org.apache.ignite.internal.processors.sql.IgniteCachePartitionedAtomicColumnConstraintsTest;
 import org.apache.ignite.internal.processors.sql.IgniteCachePartitionedTransactionalColumnConstraintsTest;
 import org.apache.ignite.internal.processors.sql.IgniteCachePartitionedTransactionalSnapshotColumnConstraintTest;
@@ -545,6 +546,8 @@ import org.junit.runners.Suite;
     GridCacheDynamicLoadOnClientTest.class,
     GridCacheDynamicLoadOnClientPersistentTest.class,
 
+    SqlDataTypeConversionTest.class,
+
         //Query history.
     SqlQueryHistorySelfTest.class,
     SqlQueryHistoryFromClientSelfTest.class,