ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject [14/16] incubator-ignite git commit: ignite-sql - moved packages
Date Mon, 26 Jan 2015 19:11:28 GMT
ignite-sql - moved packages


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

Branch: refs/heads/ignite-sql
Commit: 2851b52b9921988980051130129e5c043898e724
Parents: 0b1f629
Author: S.Vladykin <svladykin@gridgain.com>
Authored: Mon Jan 26 21:43:49 2015 +0300
Committer: S.Vladykin <svladykin@gridgain.com>
Committed: Mon Jan 26 21:43:49 2015 +0300

----------------------------------------------------------------------
 .../processors/query/h2/IgniteH2Indexing.java   |   6 +-
 .../query/h2/sql/GridSqlAggregateFunction.java  |  76 +++
 .../processors/query/h2/sql/GridSqlAlias.java   |  55 +++
 .../processors/query/h2/sql/GridSqlColumn.java  |  57 +++
 .../processors/query/h2/sql/GridSqlConst.java   |  39 ++
 .../processors/query/h2/sql/GridSqlElement.java |  73 +++
 .../query/h2/sql/GridSqlFunction.java           | 142 ++++++
 .../query/h2/sql/GridSqlFunctionType.java       |  78 +++
 .../processors/query/h2/sql/GridSqlJoin.java    |  68 +++
 .../query/h2/sql/GridSqlOperation.java          |  73 +++
 .../query/h2/sql/GridSqlOperationType.java      | 202 ++++++++
 .../query/h2/sql/GridSqlParameter.java          |  44 ++
 .../query/h2/sql/GridSqlQueryParser.java        | 495 +++++++++++++++++++
 .../query/h2/sql/GridSqlQuerySplitter.java      | 252 ++++++++++
 .../processors/query/h2/sql/GridSqlSelect.java  | 287 +++++++++++
 .../query/h2/sql/GridSqlSubquery.java           |  44 ++
 .../processors/query/h2/sql/GridSqlTable.java   |  55 +++
 .../processors/query/h2/sql/GridSqlValue.java   |  17 +
 .../query/h2/twostep/GridMapQueryExecutor.java  | 270 ++++++++++
 .../query/h2/twostep/GridMergeIndex.java        | 290 +++++++++++
 .../h2/twostep/GridMergeIndexUnsorted.java      |  85 ++++
 .../query/h2/twostep/GridMergeTable.java        | 178 +++++++
 .../h2/twostep/GridReduceQueryExecutor.java     | 242 +++++++++
 .../query/h2/twostep/GridResultPage.java        |  59 +++
 .../twostep/messages/GridNextPageRequest.java   |  59 +++
 .../twostep/messages/GridNextPageResponse.java  | 180 +++++++
 .../query/h2/twostep/messages/GridQueryAck.java |  34 ++
 .../twostep/messages/GridQueryFailResponse.java |  46 ++
 .../h2/twostep/messages/GridQueryRequest.java   |  61 +++
 .../query/h2/sql/GridSqlAggregateFunction.java  |  76 ---
 .../processors/query/h2/sql/GridSqlAlias.java   |  55 ---
 .../processors/query/h2/sql/GridSqlColumn.java  |  57 ---
 .../processors/query/h2/sql/GridSqlConst.java   |  39 --
 .../processors/query/h2/sql/GridSqlElement.java |  73 ---
 .../query/h2/sql/GridSqlFunction.java           | 142 ------
 .../query/h2/sql/GridSqlFunctionType.java       |  78 ---
 .../processors/query/h2/sql/GridSqlJoin.java    |  68 ---
 .../query/h2/sql/GridSqlOperation.java          |  73 ---
 .../query/h2/sql/GridSqlOperationType.java      | 202 --------
 .../query/h2/sql/GridSqlParameter.java          |  44 --
 .../query/h2/sql/GridSqlQueryParser.java        | 495 -------------------
 .../query/h2/sql/GridSqlQuerySplitter.java      | 252 ----------
 .../processors/query/h2/sql/GridSqlSelect.java  | 287 -----------
 .../query/h2/sql/GridSqlSubquery.java           |  44 --
 .../processors/query/h2/sql/GridSqlTable.java   |  55 ---
 .../processors/query/h2/sql/GridSqlValue.java   |  17 -
 .../query/h2/twostep/GridMapQueryExecutor.java  | 270 ----------
 .../query/h2/twostep/GridMergeIndex.java        | 290 -----------
 .../h2/twostep/GridMergeIndexUnsorted.java      |  85 ----
 .../query/h2/twostep/GridMergeTable.java        | 178 -------
 .../h2/twostep/GridReduceQueryExecutor.java     | 242 ---------
 .../query/h2/twostep/GridResultPage.java        |  59 ---
 .../twostep/messages/GridNextPageRequest.java   |  59 ---
 .../twostep/messages/GridNextPageResponse.java  | 180 -------
 .../query/h2/twostep/messages/GridQueryAck.java |  34 --
 .../twostep/messages/GridQueryFailResponse.java |  46 --
 .../h2/twostep/messages/GridQueryRequest.java   |  61 ---
 .../query/h2/sql/GridQueryParsingTest.java      |   1 -
 58 files changed, 3564 insertions(+), 3565 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/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 53721b1..baa4382 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
@@ -39,9 +39,9 @@ import org.apache.ignite.internal.util.typedef.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
 import org.gridgain.grid.kernal.processors.cache.query.GridCacheSqlResult;
 import org.gridgain.grid.kernal.processors.cache.query.GridCacheTwoStepQuery;
-import org.gridgain.grid.kernal.processors.query.h2.sql.GridSqlQuerySplitter;
-import org.gridgain.grid.kernal.processors.query.h2.twostep.GridMapQueryExecutor;
-import org.gridgain.grid.kernal.processors.query.h2.twostep.GridReduceQueryExecutor;
+import org.apache.ignite.internal.processors.query.h2.sql.GridSqlQuerySplitter;
+import org.apache.ignite.internal.processors.query.h2.twostep.GridMapQueryExecutor;
+import org.apache.ignite.internal.processors.query.h2.twostep.GridReduceQueryExecutor;
 import org.h2.api.*;
 import org.h2.command.*;
 import org.h2.constant.*;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java
new file mode 100644
index 0000000..376d1e1
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAggregateFunction.java
@@ -0,0 +1,76 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.util.*;
+
+import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.*;
+
+/**
+ * Aggregate function.
+ */
+public class GridSqlAggregateFunction extends GridSqlFunction {
+    /** */
+    private static final GridSqlFunctionType[] TYPE_INDEX = new GridSqlFunctionType[]{
+        COUNT_ALL, COUNT, GROUP_CONCAT, SUM, MIN, MAX, AVG,
+//        STDDEV_POP, STDDEV_SAMP, VAR_POP, VAR_SAMP, BOOL_OR, BOOL_AND, SELECTIVITY, HISTOGRAM,
+    };
+
+    /** */
+    private final boolean distinct;
+
+    /**
+     * @param distinct Distinct.
+     * @param type Type.
+     */
+    public GridSqlAggregateFunction(boolean distinct, GridSqlFunctionType type) {
+        super(type);
+
+        this.distinct = distinct;
+    }
+
+    /**
+     * @param distinct Distinct.
+     * @param typeId Type.
+     */
+    public GridSqlAggregateFunction(boolean distinct, int typeId) {
+        this(distinct, TYPE_INDEX[typeId]);
+    }
+
+    /**
+     * @return Distinct.
+     */
+    public boolean distinct() {
+        return distinct;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        String text;
+
+        switch (type) {
+            case GROUP_CONCAT:
+                throw new UnsupportedOperationException();
+
+            case COUNT_ALL:
+                return "COUNT(*)";
+
+            default:
+                text = type.name();
+
+                break;
+        }
+
+        if (distinct)
+            return text + "(DISTINCT " + child().getSQL() + ")";
+
+        return text + StringUtils.enclose(child().getSQL());
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java
new file mode 100644
index 0000000..f1a87d1
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlAlias.java
@@ -0,0 +1,55 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.command.*;
+
+/**
+ * Alias for column or table.
+ */
+public class GridSqlAlias extends GridSqlElement {
+    /** */
+    private final String alias;
+
+    /** */
+    private final boolean useAs;
+
+    /**
+     * @param alias Alias.
+     * @param expr Expr.
+     */
+    public GridSqlAlias(String alias, GridSqlElement expr) {
+        this(alias, expr, false);
+    }
+
+    /**
+     * @param alias Alias.
+     * @param expr Expr.
+     * @param useAs Use 'AS' keyword.
+     */
+    public GridSqlAlias(String alias, GridSqlElement expr, boolean useAs) {
+        addChild(expr);
+
+        this.useAs = useAs;
+        this.alias = alias;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        return child().getSQL() + (useAs ? " AS " : " ") + Parser.quoteIdentifier(alias);
+    }
+
+    /**
+     * @return Alias.
+     */
+    public String alias() {
+        return alias;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
new file mode 100644
index 0000000..31acbe0
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlColumn.java
@@ -0,0 +1,57 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+/**
+ * Column.
+ */
+public class GridSqlColumn extends GridSqlElement implements GridSqlValue {
+    /** */
+    private final GridSqlElement expressionInFrom;
+
+    /** */
+    private final String colName;
+
+    /** SQL from original query. May be qualified or unqualified column name. */
+    private final String sqlText;
+
+    /**
+     * @param from From.
+     * @param name Name.
+     * @param sqlText Text.
+     */
+    public GridSqlColumn(GridSqlElement from, String name, String sqlText) {
+        assert sqlText != null;
+
+        expressionInFrom = from;
+        colName = name;
+        this.sqlText = sqlText;
+    }
+
+
+    /**
+     * @return Column name.
+     */
+    public String columnName() {
+        return colName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        return sqlText;
+    }
+
+    /**
+     * @return Expression in from.
+     */
+    public GridSqlElement expressionInFrom() {
+        return expressionInFrom;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlConst.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlConst.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlConst.java
new file mode 100644
index 0000000..fd0e7d0
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlConst.java
@@ -0,0 +1,39 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.value.*;
+
+/**
+ * Constant value.
+ */
+public class GridSqlConst extends GridSqlElement implements GridSqlValue {
+    /** */
+    private final Value val;
+
+    /**
+     * @param val Value.
+     */
+    public GridSqlConst(Value val) {
+        this.val = val;
+    }
+
+    /**
+     * @return Value.
+     */
+    public Value value() {
+        return val;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        return val.getSQL();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java
new file mode 100644
index 0000000..35140b5
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlElement.java
@@ -0,0 +1,73 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import java.util.*;
+
+/**
+ * Abstract SQL element.
+ */
+public abstract class GridSqlElement implements Cloneable {
+    /** */
+    protected List<GridSqlElement> children = new ArrayList<>();
+
+    /** {@inheritDoc} */
+    public abstract String getSQL();
+
+    /**
+     * @return Children.
+     */
+    public List<GridSqlElement> children() {
+        return children;
+    }
+
+    /**
+     * @param expr Expr.
+     * @return {@code this}.
+     */
+    public GridSqlElement addChild(GridSqlElement expr) {
+        if (expr == null)
+            throw new NullPointerException();
+
+        children.add(expr);
+
+        return this;
+    }
+
+    /**
+     * @return First child.
+     */
+    public GridSqlElement child() {
+        return children.get(0);
+    }
+
+    /**
+     * @param idx Index.
+     * @return Child.
+     */
+    public GridSqlElement child(int idx) {
+        return children.get(idx);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"CloneCallsConstructors", "CloneDoesntDeclareCloneNotSupportedException"})
+    @Override protected GridSqlElement clone() {
+        try {
+            GridSqlElement res = (GridSqlElement)super.clone();
+
+            res.children = new ArrayList<>(children);
+
+            return res;
+        }
+        catch (CloneNotSupportedException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunction.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunction.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunction.java
new file mode 100644
index 0000000..06b4235
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunction.java
@@ -0,0 +1,142 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.apache.ignite.internal.util.typedef.*;
+import org.h2.util.*;
+import org.h2.value.*;
+
+import java.util.*;
+
+import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.*;
+
+/**
+ * Function.
+ */
+public class GridSqlFunction extends GridSqlElement {
+    /** */
+    private static final Map<String, GridSqlFunctionType> TYPE_MAP = new HashMap<>();
+
+    /**
+     *
+     */
+    static {
+        for (GridSqlFunctionType type : GridSqlFunctionType.values())
+            TYPE_MAP.put(type.name(), type);
+    }
+
+    /** */
+    private final String name;
+
+    /** */
+    protected final GridSqlFunctionType type;
+
+    /**  */
+    private String castType;
+
+    /**
+     * @param type Function type.
+     */
+    public GridSqlFunction(GridSqlFunctionType type) {
+        this(type, type.functionName());
+    }
+
+    /**
+     * @param type Type.
+     * @param name Name.
+     */
+    private GridSqlFunction(GridSqlFunctionType type, String name) {
+        if (name == null)
+            throw new NullPointerException();
+
+        if (type == null)
+            type = UNKNOWN_FUNCTION;
+
+        this.name = name;
+        this.type = type;
+    }
+
+    /**
+     * @param name Name.
+     */
+    public GridSqlFunction(String name) {
+        this(TYPE_MAP.get(name), name);
+    }
+
+    /**
+     * @param castType Type for {@link GridSqlFunctionType#CAST} function.
+     * @return {@code this}.
+     */
+    public GridSqlFunction setCastType(String castType) {
+        this.castType = castType;
+
+        return this;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        StatementBuilder buff = new StatementBuilder(name);
+
+        if (type == CASE) {
+            if (!children.isEmpty())
+                buff.append(" ").append(child().getSQL());
+
+            for (int i = 1, len = children.size() - 1; i < len; i += 2) {
+                buff.append(" WHEN ").append(child(i).getSQL());
+                buff.append(" THEN ").append(child(i + 1).getSQL());
+            }
+            if (children.size() % 2 == 0)
+                buff.append(" ELSE ").append(child(children.size() - 1).getSQL());
+
+            return buff.append(" END").toString();
+        }
+
+        buff.append('(');
+
+        if (type == CAST) {
+            assert !F.isEmpty(castType) : castType;
+            assert children().size() == 1;
+
+            buff.append(child().getSQL()).append(" AS ").append(castType);
+        }
+        else if (type == CONVERT) {
+            assert !F.isEmpty(castType) : castType;
+            assert children().size() == 1;
+
+            buff.append(child().getSQL()).append(',').append(castType);
+        }
+        else if (type == GridSqlFunctionType.EXTRACT) {
+            ValueString v = (ValueString)((GridSqlConst)child(0)).value();
+            buff.append(v.getString()).append(" FROM ").append(child(1).getSQL());
+        }
+        else {
+            for (GridSqlElement e : children) {
+                buff.appendExceptFirst(", ");
+                buff.append(e.getSQL());
+            }
+        }
+
+        return buff.append(')').toString();
+    }
+
+    /**
+     * @return Name.
+     */
+    public String name() {
+        return name;
+    }
+
+    /**
+     * @return Type.
+     */
+    public GridSqlFunctionType type() {
+        return type;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunctionType.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunctionType.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunctionType.java
new file mode 100644
index 0000000..ffad44e
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlFunctionType.java
@@ -0,0 +1,78 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.expression.*;
+
+/**
+ * Full list of available functions see at {@link Function}
+ */
+public enum GridSqlFunctionType {
+    // Aggregate functions.
+    /** */
+    COUNT_ALL("COUNT(*)"),
+
+    /** */
+    COUNT,
+
+    /** */
+    SUM,
+
+    /** */
+    MIN,
+
+    /** */
+    MAX,
+
+    /** */
+    AVG,
+
+    /** */
+    GROUP_CONCAT,
+
+    // Functions with special handling.
+    /** */
+    CASE,
+
+    /** */
+    CAST,
+
+    /** */
+    CONVERT,
+
+    /** */
+    EXTRACT,
+
+    /** Constant for all other functions. */
+    UNKNOWN_FUNCTION;
+
+    /** */
+    private final String name;
+
+    /**
+     */
+    GridSqlFunctionType() {
+        name = name();
+    }
+
+    /**
+     * @param name Name.
+     */
+    GridSqlFunctionType(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return Function name.
+     */
+    public String functionName() {
+        return name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlJoin.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlJoin.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlJoin.java
new file mode 100644
index 0000000..400fc68
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlJoin.java
@@ -0,0 +1,68 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.util.*;
+import org.jetbrains.annotations.*;
+
+/**
+ * Join of two tables or subqueries.
+ */
+public class GridSqlJoin extends GridSqlElement {
+    /**
+     * @param leftTbl Left table.
+     * @param rightTbl Right table.
+     */
+    public GridSqlJoin(GridSqlElement leftTbl, GridSqlElement rightTbl) {
+        addChild(leftTbl);
+        addChild(rightTbl);
+    }
+
+    /**
+     * @return Table 1.
+     */
+    public GridSqlElement leftTable() {
+        return child(0);
+    }
+
+    /**
+     * @return Table 2.
+     */
+    public GridSqlElement rightTable() {
+        return child(1);
+    }
+
+    /**
+     * @return {@code ON} Condition.
+     */
+    @Nullable public GridSqlElement on() {
+        return child(2);
+    }
+
+    /**
+     * @return {@code true} If it is a {@code LEFT JOIN}.
+     */
+    public boolean leftJoin() {
+        return false; // TODO
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        StatementBuilder buff = new StatementBuilder();
+
+        buff.append(leftTable().getSQL());
+
+        buff.append(leftJoin() ? " \n LEFT JOIN " : " \n INNER JOIN ");
+
+        buff.append(rightTable().getSQL());
+
+        return buff.toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java
new file mode 100644
index 0000000..ea8abd1
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperation.java
@@ -0,0 +1,73 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+/**
+ * Unary or binary operation.
+ */
+public class GridSqlOperation extends GridSqlElement {
+    /** */
+    private final GridSqlOperationType opType;
+
+    /**
+     * @param opType Operation type.
+     */
+    public GridSqlOperation(GridSqlOperationType opType) {
+        this.opType = opType;
+    }
+
+    /**
+     * @param opType Op type.
+     * @param arg argument.
+     */
+    public GridSqlOperation(GridSqlOperationType opType, GridSqlElement arg) {
+        this(opType);
+
+        addChild(arg);
+    }
+
+    /**
+     * @param opType Op type.
+     * @param left Left.
+     * @param right Right.
+     */
+    public GridSqlOperation(GridSqlOperationType opType, GridSqlElement left, GridSqlElement right) {
+        this(opType);
+
+        addChild(left);
+        addChild(right);
+    }
+
+    /**
+     * @return Left.
+     */
+    public GridSqlElement left() {
+        return child(0);
+    }
+
+    /**
+     * @return Right.
+     */
+    public GridSqlElement right() {
+        return child(1);
+    }
+
+    /**
+     * @return Operation type.
+     */
+    public GridSqlOperationType opType() {
+        return opType;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        return opType.toSql(this);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java
new file mode 100644
index 0000000..8d7c611
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlOperationType.java
@@ -0,0 +1,202 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.util.*;
+
+/**
+ * Operation type.
+ */
+public enum GridSqlOperationType {
+    // from org.h2.expression.Operation
+    CONCAT(2, new BiExpressionSqlGenerator("||")),
+    PLUS(2, new BiExpressionSqlGenerator("+")),
+    MINUS(2, new BiExpressionSqlGenerator("-")),
+    MULTIPLY(2, new BiExpressionSqlGenerator("*")),
+    DIVIDE(2, new BiExpressionSqlGenerator("/")),
+    MODULUS(2, new BiExpressionSqlGenerator("%")),
+    NEGATE(1, new PrefixSqlGenerator("-")),
+
+    // from org.h2.expression.Comparison
+    EQUAL(2, new BiExpressionSqlGenerator("=")),
+    EQUAL_NULL_SAFE(2, new BiExpressionSqlGenerator("IS")),
+    BIGGER_EQUAL(2, new BiExpressionSqlGenerator(">=")),
+    BIGGER(2, new BiExpressionSqlGenerator(">")),
+    SMALLER_EQUAL(2, new BiExpressionSqlGenerator("<=")),
+    SMALLER(2, new BiExpressionSqlGenerator("<")),
+    NOT_EQUAL(2, new BiExpressionSqlGenerator("<>")),
+    NOT_EQUAL_NULL_SAFE(2, new BiExpressionSqlGenerator("IS NOT")),
+
+    SPATIAL_INTERSECTS(2, new IntersectsSqlGenerator()),
+    IS_NULL(1, new SuffixSqlGenerator("IS NULL")),
+    IS_NOT_NULL(1, new SuffixSqlGenerator("IS NOT NULL")),
+
+    NOT(1, new PrefixSqlGenerator("NOT")),
+
+    // from org.h2.expression.ConditionAndOr
+    AND(2, new BiExpressionSqlGenerator("AND")),
+    OR(2, new BiExpressionSqlGenerator("OR")),
+
+    // from
+    REGEXP(2, new BiExpressionSqlGenerator("REGEXP")),
+    LIKE(2, new BiExpressionSqlGenerator("LIKE")),
+
+    IN(-1, new ConditionInSqlGenerator()),
+
+    ;
+    /** */
+    private final SqlGenerator sqlGenerator;
+
+    /** */
+    private final int childrenCnt;
+
+    /**
+     * @param childrenCnt Children count.
+     * @param sqlGenerator sqlGenerator.
+     */
+    GridSqlOperationType(int childrenCnt, SqlGenerator sqlGenerator) {
+        this.childrenCnt = childrenCnt;
+        this.sqlGenerator = sqlGenerator;
+    }
+
+    /**
+     * @param operation Operation.
+     */
+    public String toSql(GridSqlOperation operation) {
+        return sqlGenerator.getSql(operation);
+    }
+
+    /**
+     * @return Children count.
+     */
+    public int childrenCount() {
+        return childrenCnt;
+    }
+
+    /**
+     *
+     */
+    private static interface SqlGenerator {
+
+        /**
+         * @param operation Operation expression.
+         */
+        public String getSql(GridSqlOperation operation);
+    }
+
+    /**
+     *
+     */
+    private static class BiExpressionSqlGenerator implements SqlGenerator {
+
+        /** */
+        private final String delim;
+
+        /**
+         * @param delim Delimiter.
+         */
+        private BiExpressionSqlGenerator(String delim) {
+            this.delim = delim;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String getSql(GridSqlOperation operation) {
+            assert operation.opType().childrenCnt == 2;
+
+            return '(' + operation.child(0).getSQL() + " " + delim + " " + operation.child(1).getSQL() + ')';
+        }
+    }
+
+    /**
+     *
+     */
+    private static class IntersectsSqlGenerator implements SqlGenerator {
+
+        /** {@inheritDoc} */
+        @Override public String getSql(GridSqlOperation operation) {
+            assert operation.opType().childrenCnt == 2;
+
+            return "(INTERSECTS(" + operation.child(0) + ", " + operation.child(1) + "))";
+        }
+    }
+
+    /**
+     *
+     */
+    private static class PrefixSqlGenerator implements SqlGenerator {
+        /** */
+        private final String text;
+
+        /**
+         * @param text Text.
+         */
+        private PrefixSqlGenerator(String text) {
+            this.text = text;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String getSql(GridSqlOperation operation) {
+            assert operation.opType().childrenCnt == 1;
+
+            return '(' + text + ' ' + operation.child().getSQL() + ')';
+        }
+    }
+
+    /**
+     *
+     */
+    private static class SuffixSqlGenerator implements SqlGenerator {
+        /** */
+        private final String text;
+
+        /**
+         * @param text Text.
+         */
+        private SuffixSqlGenerator(String text) {
+            this.text = text;
+        }
+
+        /** {@inheritDoc} */
+        @Override public String getSql(GridSqlOperation operation) {
+            assert operation.opType().childrenCnt == 1;
+
+            return '(' + operation.child().getSQL() + ' ' + text + ')';
+        }
+    }
+
+    /**
+     *
+     */
+    private static class ConditionInSqlGenerator implements SqlGenerator {
+
+        /** {@inheritDoc} */
+        @Override public String getSql(GridSqlOperation operation) {
+            StatementBuilder buff = new StatementBuilder("(");
+
+            buff.append(operation.child(0).getSQL()).append(" IN(");
+
+            assert operation.children().size() > 1;
+
+            if (operation.children().size() == 2) {
+                String child = operation.child(1).getSQL();
+
+                buff.append(' ').append(StringUtils.unEnclose(child)).append(' ');
+            }
+            else {
+                for (int i = 1; i < operation.children().size(); i++) {
+                    buff.appendExceptFirst(", ");
+                    buff.append(operation.child(i).getSQL());
+                }
+            }
+
+            return buff.append("))").toString();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlParameter.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlParameter.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlParameter.java
new file mode 100644
index 0000000..3e11aab
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlParameter.java
@@ -0,0 +1,44 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+/**
+ * Query parameter.
+ */
+public class GridSqlParameter extends GridSqlElement implements GridSqlValue {
+    /** Index. */
+    private int idx;
+
+    /**
+     * @param idx Index.
+     */
+    public GridSqlParameter(int idx) {
+        this.idx = idx;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        return "?" + (idx + 1);
+    }
+
+    /**
+     * @return Index.
+     */
+    public int index() {
+        return idx;
+    }
+
+    /**
+     * @param idx New index.
+     */
+    public void index(int idx) {
+        this.idx = idx;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
new file mode 100644
index 0000000..7a7c0e6
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java
@@ -0,0 +1,495 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.apache.ignite.*;
+import org.h2.command.dml.*;
+import org.h2.engine.*;
+import org.h2.expression.*;
+import org.h2.jdbc.*;
+import org.h2.result.*;
+import org.h2.table.*;
+import org.jetbrains.annotations.*;
+
+import java.lang.reflect.*;
+import java.sql.*;
+import java.util.*;
+import java.util.Set;
+
+import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlOperationType.*;
+
+/**
+ * H2 Query parser.
+ */
+@SuppressWarnings("TypeMayBeWeakened")
+public class GridSqlQueryParser {
+    /** */
+    private static final GridSqlOperationType[] OPERATION_OP_TYPES = new GridSqlOperationType[]{CONCAT, PLUS, MINUS, MULTIPLY, DIVIDE, null, MODULUS};
+
+    /** */
+    private static final GridSqlOperationType[] COMPARISON_TYPES = new GridSqlOperationType[]{EQUAL, BIGGER_EQUAL, BIGGER, SMALLER_EQUAL,
+        SMALLER, NOT_EQUAL, IS_NULL, IS_NOT_NULL,
+        null, null, null, SPATIAL_INTERSECTS /* 11 */, null, null, null, null, EQUAL_NULL_SAFE /* 16 */, null, null, null, null,
+        NOT_EQUAL_NULL_SAFE /* 21 */};
+
+    /** */
+    private static final Getter<Select, Expression> CONDITION = getter(Select.class, "condition");
+
+    /** */
+    private static final Getter<Select, int[]> GROUP_INDEXES = getter(Select.class, "groupIndex");
+
+    /** */
+    private static final Getter<Operation, Integer> OPERATION_TYPE = getter(Operation.class, "opType");
+
+    /** */
+    private static final Getter<Operation, Expression> OPERATION_LEFT = getter(Operation.class, "left");
+
+    /** */
+    private static final Getter<Operation, Expression> OPERATION_RIGHT = getter(Operation.class, "right");
+
+    /** */
+    private static final Getter<Comparison, Integer> COMPARISON_TYPE = getter(Comparison.class, "compareType");
+
+    /** */
+    private static final Getter<Comparison, Expression> COMPARISON_LEFT = getter(Comparison.class, "left");
+
+    /** */
+    private static final Getter<Comparison, Expression> COMPARISON_RIGHT = getter(Comparison.class, "right");
+
+    /** */
+    private static final Getter<ConditionAndOr, Integer> ANDOR_TYPE = getter(ConditionAndOr.class, "andOrType");
+
+    /** */
+    private static final Getter<ConditionAndOr, Expression> ANDOR_LEFT = getter(ConditionAndOr.class, "left");
+
+    /** */
+    private static final Getter<ConditionAndOr, Expression> ANDOR_RIGHT = getter(ConditionAndOr.class, "right");
+
+    /** */
+    private static final Getter<TableView, Query> VIEW_QUERY = getter(TableView.class, "viewQuery");
+
+    /** */
+    private static final Getter<TableFilter, String> ALIAS = getter(TableFilter.class, "alias");
+
+    /** */
+    private static final Getter<Select, Integer> HAVING_INDEX = getter(Select.class, "havingIndex");
+
+    /** */
+    private static final Getter<ConditionIn, Expression> LEFT_CI = getter(ConditionIn.class, "left");
+
+    /** */
+    private static final Getter<ConditionIn, List<Expression>> VALUE_LIST_CI = getter(ConditionIn.class, "valueList");
+
+    /** */
+    private static final Getter<ConditionInConstantSet, Expression> LEFT_CICS =
+        getter(ConditionInConstantSet.class, "left");
+
+    /** */
+    private static final Getter<ConditionInConstantSet, List<Expression>> VALUE_LIST_CICS =
+        getter(ConditionInConstantSet.class, "valueList");
+
+    /** */
+    private static final Getter<ConditionInSelect, Expression> LEFT_CIS = getter(ConditionInSelect.class, "left");
+
+    /** */
+    private static final Getter<ConditionInSelect, Boolean> ALL = getter(ConditionInSelect.class, "all");
+
+    /** */
+    private static final Getter<ConditionInSelect, Integer> COMPARE_TYPE = getter(ConditionInSelect.class,
+        "compareType");
+
+    /** */
+    private static final Getter<ConditionInSelect, Query> QUERY = getter(ConditionInSelect.class, "query");
+
+    /** */
+    private static final Getter<CompareLike, Expression> LEFT = getter(CompareLike.class, "left");
+
+    /** */
+    private static final Getter<CompareLike, Expression> RIGHT = getter(CompareLike.class, "right");
+
+    /** */
+    private static final Getter<CompareLike, Expression> ESCAPE = getter(CompareLike.class, "escape");
+
+    /** */
+    private static final Getter<CompareLike, Boolean> REGEXP_CL = getter(CompareLike.class, "regexp");
+
+    /** */
+    private static final Getter<Aggregate, Boolean> DISTINCT = getter(Aggregate.class, "distinct");
+
+    /** */
+    private static final Getter<Aggregate, Integer> TYPE = getter(Aggregate.class, "type");
+
+    /** */
+    private static final Getter<Aggregate, Expression> ON = getter(Aggregate.class, "on");
+
+    /** */
+    private final IdentityHashMap<Object, Object> h2ObjToGridObj = new IdentityHashMap<>();
+
+    /**
+     * @param conn Connection.
+     * @param select Select query.
+     * @return Parsed select query.
+     */
+    public static GridSqlSelect parse(Connection conn, String select) {
+        Session ses = (Session)((JdbcConnection)conn).getSession();
+
+        return new GridSqlQueryParser().parse((Select)ses.prepare(select));
+    }
+
+    /**
+     * @param filter Filter.
+     */
+    private GridSqlElement parse(TableFilter filter) {
+        GridSqlElement res = (GridSqlElement)h2ObjToGridObj.get(filter);
+
+        if (res == null) {
+            Table tbl = filter.getTable();
+
+            if (tbl instanceof TableBase)
+                res = new GridSqlTable(tbl.getSchema().getName(), tbl.getName());
+            else if (tbl instanceof TableView) {
+                Query qry = VIEW_QUERY.get((TableView)tbl);
+
+                assert0(qry instanceof Select, qry);
+
+                res = new GridSqlSubquery(parse((Select)qry));
+            }
+            else
+                throw new IgniteException("Unsupported query: " + filter);
+
+            String alias = ALIAS.get(filter);
+
+            if (alias != null)
+                res = new GridSqlAlias(alias, res, false);
+
+            h2ObjToGridObj.put(filter, res);
+        }
+
+        return res;
+    }
+
+    /**
+     * @param select Select.
+     */
+    public GridSqlSelect parse(Select select) {
+        GridSqlSelect res = (GridSqlSelect)h2ObjToGridObj.get(select);
+
+        if (res != null)
+            return res;
+
+        res = new GridSqlSelect();
+
+        h2ObjToGridObj.put(select, res);
+
+        res.distinct(select.isDistinct());
+
+        Expression where = CONDITION.get(select);
+        res.where(parseExpression(where));
+
+        Set<TableFilter> allFilers = new HashSet<>(select.getTopFilters());
+
+        GridSqlElement from = null;
+
+        TableFilter filter = select.getTopTableFilter();
+        do {
+            assert0(filter != null, select);
+            assert0(!filter.isJoinOuter(), select);
+            assert0(filter.getNestedJoin() == null, select);
+            assert0(filter.getJoinCondition() == null, select);
+            assert0(filter.getFilterCondition() == null, select);
+
+            GridSqlElement gridFilter = parse(filter);
+
+            from = from == null ? gridFilter : new GridSqlJoin(from, gridFilter);
+
+            allFilers.remove(filter);
+
+            filter = filter.getJoin();
+        }
+        while (filter != null);
+
+        res.from(from);
+
+        assert allFilers.isEmpty();
+
+        ArrayList<Expression> expressions = select.getExpressions();
+
+        for (Expression exp : expressions)
+            res.addExpression(parseExpression(exp));
+
+        int[] grpIdx = GROUP_INDEXES.get(select);
+
+        if (grpIdx != null) {
+            res.groupColumns(grpIdx);
+
+            for (int idx : grpIdx)
+                res.addGroupExpression(parseExpression(expressions.get(idx)));
+        }
+
+        assert0(select.getHaving() == null, select);
+
+        int havingIdx = HAVING_INDEX.get(select);
+
+        if (havingIdx >= 0)
+            res.having(parseExpression(expressions.get(havingIdx)));
+
+        for (int i = 0; i < select.getColumnCount(); i++)
+            res.addSelectExpression(parseExpression(expressions.get(i)));
+
+        SortOrder sortOrder = select.getSortOrder();
+
+        if (sortOrder != null) {
+            int[] indexes = sortOrder.getQueryColumnIndexes();
+            int[] sortTypes = sortOrder.getSortTypes();
+
+            for (int i = 0; i < indexes.length; i++)
+                res.addSort(parseExpression(expressions.get(indexes[i])), sortTypes[i]);
+        }
+
+        return res;
+    }
+
+    /**
+     * @param expression Expression.
+     */
+    private GridSqlElement parseExpression(@Nullable Expression expression) {
+        if (expression == null)
+            return null;
+
+        GridSqlElement res = (GridSqlElement)h2ObjToGridObj.get(expression);
+
+        if (res == null) {
+            res = parseExpression0(expression);
+
+            h2ObjToGridObj.put(expression, res);
+        }
+
+        return res;
+    }
+
+    /**
+     * @param expression Expression.
+     */
+    private GridSqlElement parseExpression0(Expression expression) {
+        if (expression instanceof ExpressionColumn) {
+            TableFilter tblFilter = ((ExpressionColumn)expression).getTableFilter();
+
+            GridSqlElement gridTblFilter = parse(tblFilter);
+
+            return new GridSqlColumn(gridTblFilter, expression.getColumnName(), expression.getSQL());
+        }
+
+        if (expression instanceof Alias)
+            return new GridSqlAlias(expression.getAlias(), parseExpression(expression.getNonAliasExpression()), true);
+
+        if (expression instanceof ValueExpression)
+            return new GridSqlConst(expression.getValue(null));
+
+        if (expression instanceof Operation) {
+            Operation operation = (Operation)expression;
+
+            Integer type = OPERATION_TYPE.get(operation);
+
+            if (type == Operation.NEGATE) {
+                assert OPERATION_RIGHT.get(operation) == null;
+
+                return new GridSqlOperation(GridSqlOperationType.NEGATE, parseExpression(OPERATION_LEFT.get(operation)));
+            }
+
+            return new GridSqlOperation(OPERATION_OP_TYPES[type],
+                parseExpression(OPERATION_LEFT.get(operation)),
+                parseExpression(OPERATION_RIGHT.get(operation)));
+        }
+
+        if (expression instanceof Comparison) {
+            Comparison cmp = (Comparison)expression;
+
+            GridSqlOperationType opType = COMPARISON_TYPES[COMPARISON_TYPE.get(cmp)];
+
+            assert opType != null : COMPARISON_TYPE.get(cmp);
+
+            GridSqlElement left = parseExpression(COMPARISON_LEFT.get(cmp));
+
+            if (opType.childrenCount() == 1)
+                return new GridSqlOperation(opType, left);
+
+            GridSqlElement right = parseExpression(COMPARISON_RIGHT.get(cmp));
+
+            return new GridSqlOperation(opType, left, right);
+        }
+
+        if (expression instanceof ConditionNot)
+            return new GridSqlOperation(NOT, parseExpression(expression.getNotIfPossible(null)));
+
+        if (expression instanceof ConditionAndOr) {
+            ConditionAndOr andOr = (ConditionAndOr)expression;
+
+            int type = ANDOR_TYPE.get(andOr);
+
+            assert type == ConditionAndOr.AND || type == ConditionAndOr.OR;
+
+            return new GridSqlOperation(type == ConditionAndOr.AND ? AND : OR,
+                parseExpression(ANDOR_LEFT.get(andOr)), parseExpression(ANDOR_RIGHT.get(andOr)));
+        }
+
+        if (expression instanceof Subquery) {
+            Query qry = ((Subquery)expression).getQuery();
+
+            assert0(qry instanceof Select, expression);
+
+            return new GridSqlSubquery(parse((Select) qry));
+        }
+
+        if (expression instanceof ConditionIn) {
+            GridSqlOperation res = new GridSqlOperation(IN);
+
+            res.addChild(parseExpression(LEFT_CI.get((ConditionIn) expression)));
+
+            List<Expression> vals = VALUE_LIST_CI.get((ConditionIn)expression);
+
+            for (Expression val : vals)
+                res.addChild(parseExpression(val));
+
+            return res;
+        }
+
+        if (expression instanceof ConditionInConstantSet) {
+            GridSqlOperation res = new GridSqlOperation(IN);
+
+            res.addChild(parseExpression(LEFT_CICS.get((ConditionInConstantSet) expression)));
+
+            List<Expression> vals = VALUE_LIST_CICS.get((ConditionInConstantSet)expression);
+
+            for (Expression val : vals)
+                res.addChild(parseExpression(val));
+
+            return res;
+        }
+
+        if (expression instanceof ConditionInSelect) {
+            GridSqlOperation res = new GridSqlOperation(IN);
+
+            boolean all = ALL.get((ConditionInSelect)expression);
+            int compareType = COMPARE_TYPE.get((ConditionInSelect)expression);
+
+            assert0(!all, expression);
+            assert0(compareType == Comparison.EQUAL, expression);
+
+            res.addChild(parseExpression(LEFT_CIS.get((ConditionInSelect) expression)));
+
+            Query qry = QUERY.get((ConditionInSelect)expression);
+
+            assert0(qry instanceof Select, qry);
+
+            res.addChild(new GridSqlSubquery(parse((Select) qry)));
+
+            return res;
+        }
+
+        if (expression instanceof CompareLike) {
+            assert0(ESCAPE.get((CompareLike)expression) == null, expression);
+
+            boolean regexp = REGEXP_CL.get((CompareLike)expression);
+
+            return new GridSqlOperation(regexp ? REGEXP : LIKE, parseExpression(LEFT.get((CompareLike) expression)),
+                parseExpression(RIGHT.get((CompareLike) expression)));
+        }
+
+        if (expression instanceof Function) {
+            Function f = (Function)expression;
+
+            GridSqlFunction res = new GridSqlFunction(f.getName());
+
+            for (Expression arg : f.getArgs())
+                res.addChild(parseExpression(arg));
+
+            if (f.getFunctionType() == Function.CAST || f.getFunctionType() == Function.CONVERT)
+                res.setCastType(new Column(null, f.getType(), f.getPrecision(), f.getScale(), f.getDisplaySize())
+                    .getCreateSQL());
+
+            return res;
+        }
+
+        if (expression instanceof Parameter)
+            return new GridSqlParameter(((Parameter)expression).getIndex());
+
+        if (expression instanceof Aggregate) {
+            GridSqlAggregateFunction res = new GridSqlAggregateFunction(DISTINCT.get((Aggregate)expression),
+                TYPE.get((Aggregate)expression));
+
+            Expression on = ON.get((Aggregate)expression);
+
+            if (on != null)
+                res.addChild(parseExpression(on));
+
+            return res;
+        }
+
+        throw new IgniteException("Unsupported expression: " + expression + " [type=" +
+            expression.getClass().getSimpleName() + ']');
+    }
+
+    /**
+     * @param cond Condition.
+     * @param o Object.
+     */
+    private static void assert0(boolean cond, Object o) {
+        if (!cond)
+            throw new IgniteException("Unsupported query: " + o);
+    }
+
+    /**
+     * @param cls Class.
+     * @param fldName Fld name.
+     */
+    private static <T, R> Getter<T, R> getter(Class<T> cls, String fldName) {
+        Field field;
+
+        try {
+            field = cls.getDeclaredField(fldName);
+        }
+        catch (NoSuchFieldException e) {
+            throw new RuntimeException(e);
+        }
+
+        field.setAccessible(true);
+
+        return new Getter<>(field);
+    }
+
+    /**
+     * Field getter.
+     */
+    @SuppressWarnings("unchecked")
+    private static class Getter<T, R> {
+        /** */
+        private final Field fld;
+
+        /**
+         * @param fld Fld.
+         */
+        private Getter(Field fld) {
+            this.fld = fld;
+        }
+
+        /**
+         * @param obj Object.
+         * @return Result.
+         */
+        public R get(T obj) {
+            try {
+                return (R)fld.get(obj);
+            }
+            catch (IllegalAccessException e) {
+                throw new IgniteException(e);
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
new file mode 100644
index 0000000..db67ee7
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQuerySplitter.java
@@ -0,0 +1,252 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.apache.ignite.*;
+import org.gridgain.grid.kernal.processors.cache.query.*;
+
+import java.sql.*;
+import java.util.*;
+
+import static org.apache.ignite.internal.processors.query.h2.sql.GridSqlFunctionType.*;
+
+/**
+ * Splits a single SQL query into two step map-reduce query.
+ */
+public class GridSqlQuerySplitter {
+    /** */
+    private static final String TABLE_PREFIX = "__T";
+
+    /** */
+    private static final String COLUMN_PREFIX = "__C";
+
+    /**
+     * @param idx Index of table.
+     * @return Table name.
+     */
+    private static String table(int idx) {
+        return TABLE_PREFIX + idx;
+    }
+
+    /**
+     * @param idx Index of column.
+     * @return Generated by index column alias.
+     */
+    private static String columnName(int idx) {
+        return COLUMN_PREFIX + idx;
+    }
+
+    /**
+     * @param conn Connection.
+     * @param query Query.
+     * @param params Parameters.
+     * @return Two step query.
+     */
+    public static GridCacheTwoStepQuery split(Connection conn, String query, Object[] params) {
+        // TODO possibly get column types from query.
+        GridSqlSelect srcQry = GridSqlQueryParser.parse(conn, query);
+
+        if (srcQry.groups().isEmpty()) { // Simple case.
+            String tbl0 = table(0);
+
+            GridCacheTwoStepQuery res = new GridCacheTwoStepQuery("select * from " + tbl0);
+
+            res.addMapQuery(tbl0, srcQry.getSQL(), params);
+
+            return res;
+        }
+
+        // Split all select expressions into map-reduce parts.
+        List<GridSqlElement> mapExps = new ArrayList<>(srcQry.allExpressions());
+
+        GridSqlElement[] rdcExps = new GridSqlElement[srcQry.select().size()];
+
+        for (int i = 0, len = mapExps.size(); i < len; i++)
+            splitSelectExpression(mapExps, rdcExps, i);
+
+        // Build map query.
+        GridSqlSelect mapQry = srcQry.clone();
+
+        mapQry.clearSelect();
+
+        for (GridSqlElement exp : mapExps)
+            mapQry.addSelectExpression(exp);
+
+        mapQry.clearGroups();
+
+        for (int col : srcQry.groupColumns())
+            mapQry.addGroupExpression(column(((GridSqlAlias)mapExps.get(col)).alias()));
+
+        // TODO sort support
+
+        // Reduce query.
+        GridSqlSelect rdcQry = new GridSqlSelect();
+
+        for (GridSqlElement rdcExp : rdcExps)
+            rdcQry.addSelectExpression(rdcExp);
+
+        rdcQry.from(new GridSqlTable(null, table(0)));
+
+        for (int col : srcQry.groupColumns())
+            rdcQry.addGroupExpression(column(((GridSqlAlias)mapExps.get(col)).alias()));
+
+        GridCacheTwoStepQuery res = new GridCacheTwoStepQuery(rdcQry.getSQL());
+
+        res.addMapQuery(table(0), mapQry.getSQL(), params);
+
+        return res;
+    }
+
+    /**
+     * @param mapSelect Selects for map query.
+     * @param rdcSelect Selects for reduce query.
+     * @param idx Index.
+     */
+    private static void splitSelectExpression(List<GridSqlElement> mapSelect, GridSqlElement[] rdcSelect, int idx) {
+        GridSqlElement el = mapSelect.get(idx);
+
+        GridSqlAlias alias = null;
+
+        if (el instanceof GridSqlAlias) { // Unwrap from alias.
+            alias = (GridSqlAlias)el;
+            el = alias.child();
+        }
+
+        if (el instanceof GridSqlAggregateFunction) {
+            GridSqlAggregateFunction agg = (GridSqlAggregateFunction)el;
+
+            GridSqlElement mapAgg, rdcAgg;
+
+            String mapAggAlias = columnName(idx);
+
+            switch (agg.type()) {
+                case AVG: // SUM( AVG(CAST(x AS DECIMAL))*COUNT(x) )/SUM( COUNT(x) ).
+                    //-- COUNT(x) map
+                    GridSqlElement cntMapAgg = aggregate(agg.distinct(), COUNT).addChild(agg.child());
+
+                    // Add generated alias to COUNT(x).
+                    // Using size as index since COUNT will be added as the last select element to the map query.
+                    String cntMapAggAlias = columnName(mapSelect.size());
+
+                    cntMapAgg = alias(cntMapAggAlias, cntMapAgg);
+
+                    mapSelect.add(cntMapAgg);
+
+                    //-- AVG(CAST(x AS DECIMAL)) map
+                    mapAgg = aggregate(agg.distinct(), AVG).addChild( // Add function argument.
+                        function(CAST).setCastType("DECIMAL").addChild(agg.child()));
+
+                    //-- SUM( AVG(x)*COUNT(x) )/SUM( COUNT(x) ) reduce
+                    GridSqlElement sumUpRdc = aggregate(false, SUM).addChild(
+                        op(GridSqlOperationType.MULTIPLY,
+                                column(mapAggAlias),
+                                column(cntMapAggAlias)));
+
+                    GridSqlElement sumDownRdc = aggregate(false, SUM).addChild(column(cntMapAggAlias));
+
+                    rdcAgg = op(GridSqlOperationType.DIVIDE, sumUpRdc, sumDownRdc);
+
+                    break;
+
+                case SUM: // SUM( SUM(x) )
+                case MAX: // MAX( MAX(x) )
+                case MIN: // MIN( MIN(x) )
+                    mapAgg = aggregate(agg.distinct(), agg.type()).addChild(agg.child());
+
+                    rdcAgg = aggregate(agg.distinct(), agg.type()).addChild(column(mapAggAlias));
+
+                    break;
+
+                case COUNT_ALL: // CAST(SUM( COUNT(*) ) AS BIGINT)
+                case COUNT: // CAST(SUM( COUNT(x) ) AS BIGINT)
+                    mapAgg = aggregate(agg.distinct(), agg.type());
+
+                    if (agg.type() == COUNT)
+                        mapAgg.addChild(agg.child());
+
+                    rdcAgg = aggregate(false, SUM).addChild(column(mapAggAlias));
+
+                    rdcAgg = function(CAST).setCastType("BIGINT").addChild(rdcAgg);
+
+                    break;
+
+                default:
+                    throw new IgniteException("Unsupported aggregate: " + agg.type());
+            }
+
+            assert !(mapAgg instanceof GridSqlAlias);
+
+            // Add generated alias to map aggregate.
+            mapAgg = alias(mapAggAlias, mapAgg);
+
+            if (alias != null) // Add initial alias if it was set.
+                rdcAgg = alias(alias.alias(), rdcAgg);
+
+            // Set map and reduce aggregates to their places in selects.
+            mapSelect.set(idx, mapAgg);
+
+            rdcSelect[idx] = rdcAgg;
+        }
+        else {
+            if (alias == null) { // Generate alias if none.
+                alias = alias(columnName(idx), mapSelect.get(idx));
+
+                mapSelect.set(idx, alias);
+            }
+
+            if (idx < rdcSelect.length)
+                rdcSelect[idx] = column(alias.alias());
+        }
+    }
+
+    /**
+     * @param distinct Distinct.
+     * @param type Type.
+     * @return Aggregate function.
+     */
+    private static GridSqlAggregateFunction aggregate(boolean distinct, GridSqlFunctionType type) {
+        return new GridSqlAggregateFunction(distinct, type);
+    }
+
+    /**
+     * @param name Column name.
+     * @return Column.
+     */
+    private static GridSqlColumn column(String name) {
+        return new GridSqlColumn(null, name, name);
+    }
+
+    /**
+     * @param alias Alias.
+     * @param child Child.
+     * @return Alias.
+     */
+    private static GridSqlAlias alias(String alias, GridSqlElement child) {
+        return new GridSqlAlias(alias, child);
+    }
+
+    /**
+     * @param type Type.
+     * @param left Left expression.
+     * @param right Right expression.
+     * @return Binary operator.
+     */
+    private static GridSqlOperation op(GridSqlOperationType type, GridSqlElement left, GridSqlElement right) {
+        return new GridSqlOperation(type, left, right);
+    }
+
+    /**
+     * @param type Type.
+     * @return Function.
+     */
+    private static GridSqlFunction function(GridSqlFunctionType type) {
+        return new GridSqlFunction(type);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java
new file mode 100644
index 0000000..ee4d6c8
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSelect.java
@@ -0,0 +1,287 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.result.*;
+import org.h2.util.*;
+
+import java.util.*;
+
+/**
+ * Select query.
+ */
+public class GridSqlSelect implements Cloneable {
+    /** */
+    private boolean distinct;
+
+    /** */
+    private List<GridSqlElement> allExprs;
+
+    /** */
+    private List<GridSqlElement> select = new ArrayList<>();
+
+    /** */
+    private List<GridSqlElement> groups = new ArrayList<>();
+
+    /** */
+    private int[] grpCols;
+
+    /** */
+    private GridSqlElement from;
+
+    /** */
+    private GridSqlElement where;
+
+    /** */
+    private GridSqlElement having;
+
+    /** */
+    private Map<GridSqlElement, Integer> sort = new LinkedHashMap<>();
+
+    /**
+     * @return Distinct.
+     */
+    public boolean distinct() {
+        return distinct;
+    }
+
+    /**
+     * @param distinct New distinct.
+     */
+    public void distinct(boolean distinct) {
+        this.distinct = distinct;
+    }
+
+    /**
+     * @return Generate sql.
+     */
+    public String getSQL() {
+        StatementBuilder buff = new StatementBuilder("SELECT");
+
+        if (distinct)
+            buff.append(" DISTINCT");
+
+        for (GridSqlElement expression : select) {
+            buff.appendExceptFirst(",");
+            buff.append('\n');
+            buff.append(StringUtils.indent(expression.getSQL(), 4, false));
+        }
+
+        buff.append("\nFROM ").append(from.getSQL());
+
+        if (where != null)
+            buff.append("\nWHERE ").append(StringUtils.unEnclose(where.getSQL()));
+
+        if (!groups.isEmpty()) {
+            buff.append("\nGROUP BY ");
+
+            buff.resetCount();
+
+            for (GridSqlElement expression : groups) {
+                buff.appendExceptFirst(", ");
+
+                if (expression instanceof GridSqlAlias)
+                    buff.append(StringUtils.unEnclose((expression.child().getSQL())));
+                else
+                    buff.append(StringUtils.unEnclose(expression.getSQL()));
+            }
+        }
+
+        if (having != null)
+            buff.append("\nHAVING ").append(StringUtils.unEnclose(having.getSQL()));
+
+        if (!sort.isEmpty()) {
+            buff.append("\nORDER BY ");
+
+            buff.resetCount();
+
+            for (Map.Entry<GridSqlElement, Integer> entry : sort.entrySet()) {
+                buff.appendExceptFirst(", ");
+
+                GridSqlElement expression = entry.getKey();
+
+                int idx = select.indexOf(expression);
+
+                if (idx >= 0)
+                    buff.append(idx + 1);
+                else
+                    buff.append('=').append(StringUtils.unEnclose(expression.getSQL()));
+
+                int type = entry.getValue();
+
+                if ((type & SortOrder.DESCENDING) != 0)
+                    buff.append(" DESC");
+
+                if ((type & SortOrder.NULLS_FIRST) != 0)
+                    buff.append(" NULLS FIRST");
+                else if ((type & SortOrder.NULLS_LAST) != 0)
+                    buff.append(" NULLS LAST");
+            }
+        }
+
+        return buff.toString();
+    }
+
+    /**
+     * @param expression Expression.
+     */
+    public void addExpression(GridSqlElement expression) {
+        if (allExprs == null)
+            allExprs = new ArrayList<>();
+
+        allExprs.add(expression);
+    }
+
+    /**
+     * @return All expressions in select, group by, order by.
+     */
+    public List<GridSqlElement> allExpressions() {
+        return allExprs;
+    }
+
+    /**
+     * @return Expressions.
+     */
+    public List<GridSqlElement> select() {
+        return select;
+    }
+
+    /**
+     * Clears select list.
+     */
+    public void clearSelect() {
+        select = new ArrayList<>();
+    }
+
+    /**
+     * @param expression Expression.
+     */
+    public void addSelectExpression(GridSqlElement expression) {
+        select.add(expression);
+    }
+
+    /**
+     * @return Expressions.
+     */
+    public List<GridSqlElement> groups() {
+        return groups;
+    }
+
+    /**
+     *
+     */
+    public void clearGroups() {
+        groups = new ArrayList<>();
+        grpCols = null;
+    }
+
+    /**
+     * @param expression Expression.
+     */
+    public void addGroupExpression(GridSqlElement expression) {
+        groups.add(expression);
+    }
+
+    /**
+     * @return Group columns.
+     */
+    public int[] groupColumns() {
+        return grpCols;
+    }
+
+    /**
+     * @param grpCols Group columns.
+     */
+    public void groupColumns(int[] grpCols) {
+        this.grpCols = grpCols;
+    }
+
+    /**
+     * @return Tables.
+     */
+    public GridSqlElement from() {
+        return from;
+    }
+
+    /**
+     * @param from From element.
+     */
+    public void from(GridSqlElement from) {
+        this.from = from;
+    }
+
+    /**
+     * @return Where.
+     */
+    public GridSqlElement where() {
+        return where;
+    }
+
+    /**
+     * @param where New where.
+     */
+    public void where(GridSqlElement where) {
+        this.where = where;
+    }
+
+    /**
+     * @return Having.
+     */
+    public GridSqlElement having() {
+        return having;
+    }
+
+    /**
+     * @param having New having.
+     */
+    public void having(GridSqlElement having) {
+        this.having = having;
+    }
+
+    /**
+     * @return Sort.
+     */
+    public Map<GridSqlElement, Integer> sort() {
+        return sort;
+    }
+
+    /**
+     *
+     */
+    public void clearSort() {
+        sort = new LinkedHashMap<>();
+    }
+
+    /**
+     * @param expression Expression.
+     * @param sortType The sort type bit mask (SortOrder.DESCENDING, SortOrder.NULLS_FIRST, SortOrder.NULLS_LAST).
+     */
+    public void addSort(GridSqlElement expression, int sortType) {
+        sort.put(expression, sortType);
+    }
+
+    /** {@inheritDoc} */
+    @SuppressWarnings({"CloneCallsConstructors", "CloneDoesntDeclareCloneNotSupportedException"})
+    @Override public GridSqlSelect clone() {
+        try {
+            GridSqlSelect res = (GridSqlSelect)super.clone();
+
+            res.select = new ArrayList<>(select);
+            res.groups = new ArrayList<>(groups);
+            res.sort = new LinkedHashMap<>(sort);
+            res.allExprs = null;
+
+            return res;
+        }
+        catch (CloneNotSupportedException e) {
+            throw new RuntimeException(e); // Never thrown.
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSubquery.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSubquery.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSubquery.java
new file mode 100644
index 0000000..7a558f0
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlSubquery.java
@@ -0,0 +1,44 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+/**
+ * Subquery.
+ */
+public class GridSqlSubquery extends GridSqlElement {
+    /** */
+    private GridSqlSelect select;
+
+    /**
+     * @param select Select.
+     */
+    public GridSqlSubquery(GridSqlSelect select) {
+        this.select = select;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        return "(" + select.getSQL() + ")";
+    }
+
+    /**
+     * @return Select.
+     */
+    public GridSqlSelect select() {
+        return select;
+    }
+
+    /**
+     * @param select New select.
+     */
+    public void select(GridSqlSelect select) {
+        this.select = select;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java
new file mode 100644
index 0000000..c9c551f
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlTable.java
@@ -0,0 +1,55 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+import org.h2.command.*;
+import org.jetbrains.annotations.*;
+
+/**
+ * Table with optional schema.
+ */
+public class GridSqlTable extends GridSqlElement {
+    /** */
+    private final String schema;
+
+    /** */
+    private final String tblName;
+
+    /**
+     * @param schema Schema.
+     * @param tblName Table name.
+     */
+    public GridSqlTable(@Nullable String schema, String tblName) {
+        this.schema = schema;
+        this.tblName = tblName;
+    }
+
+    /** {@inheritDoc} */
+    @Override public String getSQL() {
+        if (schema == null)
+            return Parser.quoteIdentifier(tblName);
+
+        return Parser.quoteIdentifier(schema) + '.' + Parser.quoteIdentifier(tblName);
+    }
+
+    /**
+     * @return Schema.
+     */
+    public String schema() {
+        return schema;
+    }
+
+    /**
+     * @return Table name.
+     */
+    public String tableName() {
+        return tblName;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlValue.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlValue.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlValue.java
new file mode 100644
index 0000000..41c8275
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlValue.java
@@ -0,0 +1,17 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.sql;
+
+/**
+ * Marker interface for a simple value.
+ */
+public interface GridSqlValue {
+    // No-op.
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/2851b52b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
new file mode 100644
index 0000000..c572d5d
--- /dev/null
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/twostep/GridMapQueryExecutor.java
@@ -0,0 +1,270 @@
+/* @java.file.header */
+
+/*  _________        _____ __________________        _____
+ *  __  ____/___________(_)______  /__  ____/______ ____(_)_______
+ *  _  / __  __  ___/__  / _  __  / _  / __  _  __ `/__  / __  __ \
+ *  / /_/ /  _  /    _  /  / /_/ /  / /_/ /  / /_/ / _  /  _  / / /
+ *  \____/   /_/     /_/   \_,__/   \____/   \__,_/  /_/   /_/ /_/
+ */
+
+package org.apache.ignite.internal.processors.query.h2.twostep;
+
+import org.apache.ignite.*;
+import org.apache.ignite.cluster.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.processors.cache.*;
+import org.apache.ignite.internal.processors.query.h2.*;
+import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.lang.*;
+import org.apache.ignite.spi.indexing.*;
+import org.gridgain.grid.kernal.processors.cache.query.*;
+import org.apache.ignite.internal.processors.query.h2.twostep.messages.*;
+import org.h2.jdbc.*;
+import org.h2.result.*;
+import org.h2.value.*;
+import org.jdk8.backport.*;
+import org.jetbrains.annotations.*;
+
+import java.lang.reflect.*;
+import java.sql.*;
+import java.util.*;
+import java.util.concurrent.*;
+
+/**
+ * Map query executor.
+ */
+public class GridMapQueryExecutor {
+    /** */
+    private static final Field RESULT_FIELD;
+
+    /**
+     * Initialize.
+     */
+    static {
+        try {
+            RESULT_FIELD = JdbcResultSet.class.getDeclaredField("result");
+
+            RESULT_FIELD.setAccessible(true);
+        }
+        catch (NoSuchFieldException e) {
+            throw new IllegalStateException("Check H2 version in classpath.", e);
+        }
+    }
+
+    /** */
+    private IgniteLogger log;
+
+    /** */
+    private GridKernalContext ctx;
+
+    /** */
+    private IgniteH2Indexing h2;
+
+    /** */
+    private ConcurrentMap<UUID, ConcurrentMap<Long, QueryResults>> qryRess = new ConcurrentHashMap8<>();
+
+    /**
+     * @param ctx Context.
+     * @param h2 H2 Indexing.
+     * @throws IgniteCheckedException If failed.
+     */
+    public void start(final GridKernalContext ctx, IgniteH2Indexing h2) throws IgniteCheckedException {
+        this.ctx = ctx;
+        this.h2 = h2;
+
+        log = ctx.log(GridMapQueryExecutor.class);
+
+        // TODO handle node failures.
+
+        ctx.io().addUserMessageListener(GridTopic.TOPIC_QUERY, new IgniteBiPredicate<UUID, Object>() {
+            @Override public boolean apply(UUID nodeId, Object msg) {
+                assert msg != null;
+
+                ClusterNode node = ctx.discovery().node(nodeId);
+
+                if (msg instanceof GridQueryRequest)
+                    executeLocalQuery(node, (GridQueryRequest)msg);
+                else if (msg instanceof GridNextPageRequest)
+                    sendNextPage(node, (GridNextPageRequest)msg);
+
+                return true;
+            }
+        });
+    }
+
+    /**
+     * @param node Node.
+     * @param req Query request.
+     */
+    private void executeLocalQuery(ClusterNode node, GridQueryRequest req) {
+        h2.setFilters(new GridIndexingQueryFilter() {
+            @Nullable @Override public <K, V> IgniteBiPredicate<K, V> forSpace(String spaceName) {
+                final GridCacheAdapter<Object, Object> cache = ctx.cache().internalCache(spaceName);
+
+                if (cache.context().isReplicated() || cache.configuration().getBackups() == 0)
+                    return null;
+
+                return new IgniteBiPredicate<K, V>() {
+                    @Override public boolean apply(K k, V v) {
+                        return cache.context().affinity().primary(ctx.discovery().localNode(), k, -1);
+                    }
+                };
+            }
+        });
+
+        try {
+            QueryResults qr = new QueryResults(req.requestId(), req.queries().size());
+
+            ConcurrentMap<Long, QueryResults> nodeRess = qryRess.get(node.id());
+
+            if (nodeRess == null) {
+                nodeRess = new ConcurrentHashMap8<>();
+
+                ConcurrentMap<Long, QueryResults> old = qryRess.putIfAbsent(node.id(), nodeRess);
+
+                if (old != null)
+                    nodeRess = old;
+            }
+
+            QueryResults old = nodeRess.putIfAbsent(req.requestId(), qr);
+
+            assert old == null;
+
+            // Prepare snapshots for all the needed tables before actual run.
+            for (GridCacheSqlQuery qry : req.queries()) {
+                // TODO
+            }
+
+            // Run queries.
+            int i = 0;
+
+            for (GridCacheSqlQuery qry : req.queries()) {
+                ResultSet rs = h2.executeSqlQueryWithTimer(h2.connectionForSpace(null), qry.query(),
+                    F.asList(qry.parameters()));
+
+                assert rs instanceof JdbcResultSet : rs.getClass();
+
+                ResultInterface res = (ResultInterface)RESULT_FIELD.get(rs);
+
+                qr.results[i] = res;
+                qr.resultSets[i] = rs;
+
+                // Send the first page.
+                sendNextPage(node, qr, i, req.pageSize(), res.getRowCount());
+
+                i++;
+            }
+        }
+        catch (Throwable e) {
+            sendError(node, req.requestId(), e);
+        }
+        finally {
+            h2.setFilters(null);
+        }
+    }
+
+    /**
+     * @param node Node.
+     * @param qryReqId Query request ID.
+     * @param err Error.
+     */
+    private void sendError(ClusterNode node, long qryReqId, Throwable err) {
+        try {
+            ctx.io().sendUserMessage(F.asList(node), new GridQueryFailResponse(qryReqId, err));
+        }
+        catch (IgniteCheckedException e) {
+            e.addSuppressed(err);
+
+            log.error("Failed to send error message.", e);
+        }
+    }
+
+    /**
+     * @param node Node.
+     * @param req Request.
+     */
+    private void sendNextPage(ClusterNode node, GridNextPageRequest req) {
+        ConcurrentMap<Long, QueryResults> nodeRess = qryRess.get(node.id());
+
+        QueryResults qr = nodeRess == null ? null : nodeRess.get(req.queryRequestId());
+
+        if (qr == null)
+            sendError(node, req.queryRequestId(),
+                new IllegalStateException("No query result found for request: " + req));
+        else
+            sendNextPage(node, qr, req.query(), req.pageSize(), -1);
+    }
+
+    /**
+     * @param node Node.
+     * @param qr Query results.
+     * @param qry Query.
+     * @param pageSize Page size.
+     * @param allRows All rows count.
+     */
+    private void sendNextPage(ClusterNode node, QueryResults qr, int qry, int pageSize, int allRows) {
+        int page;
+
+        List<Value[]> rows = new ArrayList<>(Math.min(64, pageSize));
+
+        ResultInterface res = qr.results[qry];
+
+        assert res != null;
+
+        boolean last = false;
+
+        synchronized (res) {
+            page = qr.pages[qry]++;
+
+            for (int i = 0 ; i < pageSize; i++) {
+                if (!res.next()) {
+                    last = true;
+
+                    break;
+                }
+
+                rows.add(res.currentRow());
+            }
+        }
+
+        try {
+            ctx.io().sendUserMessage(F.asList(node),
+                new GridNextPageResponse(qr.qryReqId, qry, page, allRows, last, rows),
+                GridTopic.TOPIC_QUERY, false, 0);
+        }
+        catch (IgniteCheckedException e) {
+            log.error("Failed to send message.", e);
+
+            throw new IgniteException(e);
+        }
+    }
+
+    /**
+     *
+     */
+    private static class QueryResults {
+        /** */
+        private long qryReqId;
+
+        /** */
+        private ResultInterface[] results;
+
+        /** */
+        private ResultSet[] resultSets;
+
+        /** */
+        private int[] pages;
+
+        /**
+         * @param qryReqId Query request ID.
+         * @param qrys Queries.
+         */
+        private QueryResults(long qryReqId, int qrys) {
+            this.qryReqId = qryReqId;
+
+            results = new ResultInterface[qrys];
+            resultSets = new ResultSet[qrys];
+            pages = new int[qrys];
+        }
+    }
+}


Mime
View raw message