You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by an...@apache.org on 2015/08/21 13:05:42 UTC

[1/7] incubator-ignite git commit: Merge branches 'ignite-843' and 'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-843

Repository: incubator-ignite
Updated Branches:
  refs/heads/ignite-843 41c2abaad -> 4e007c7eb


Merge branches 'ignite-843' and 'master' of https://git-wip-us.apache.org/repos/asf/incubator-ignite into ignite-843


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

Branch: refs/heads/ignite-843
Commit: fc09db16df0d00ead103e1c455a3844b9b1ffd68
Parents: ca73da1 7a96a4b
Author: Andrey <an...@gridgain.com>
Authored: Thu Aug 20 17:58:07 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Thu Aug 20 17:58:07 2015 +0700

----------------------------------------------------------------------
 .../internal/interop/InteropIgnition.java       | 55 --------------------
 .../internal/interop/InteropProcessor.java      | 12 -----
 2 files changed, 67 deletions(-)
----------------------------------------------------------------------



[4/7] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-843' into ignite-843

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-843' into ignite-843


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

Branch: refs/heads/ignite-843
Commit: d686f12e1e2c6a597d827aa1b763a1e7fe662f1b
Parents: eae81c0 bc9c860
Author: Andrey <an...@gridgain.com>
Authored: Fri Aug 21 15:33:26 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Fri Aug 21 15:33:26 2015 +0700

----------------------------------------------------------------------
 modules/control-center-agent/pom.xml            |  6 ++
 .../apache/ignite/agent/AgentConfiguration.java | 38 +++++++++-
 .../org/apache/ignite/agent/AgentLauncher.java  |  7 ++
 .../agent/testdrive/AgentMetadataTestDrive.java | 75 ++++++++++++++++++++
 .../agent/testdrive/AgentSqlTestDrive.java      | 15 ++++
 .../main/js/controllers/metadata-controller.js  |  4 +-
 .../src/main/js/public/stylesheets/style.scss   |  2 +-
 .../src/main/js/routes/agent.js                 |  2 +-
 .../js/views/configuration/metadata-load.jade   | 12 ++--
 .../src/main/js/views/includes/controls.jade    | 12 ++--
 10 files changed, 154 insertions(+), 19 deletions(-)
----------------------------------------------------------------------



[2/7] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-843' into ignite-843

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-843' into ignite-843


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

Branch: refs/heads/ignite-843
Commit: 1234196ae9d435ea50d965157cc85364f45ff6c6
Parents: fc09db1 de8dcc6
Author: Andrey <an...@gridgain.com>
Authored: Fri Aug 21 10:48:48 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Fri Aug 21 10:48:48 2015 +0700

----------------------------------------------------------------------
 .../main/js/controllers/metadata-controller.js  | 86 ++++++++++++++------
 1 file changed, 62 insertions(+), 24 deletions(-)
----------------------------------------------------------------------



[6/7] incubator-ignite git commit: # GG-843 Merged with ignite-961.

Posted by an...@apache.org.
# GG-843 Merged with ignite-961.


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

Branch: refs/heads/ignite-843
Commit: 17a681c78d87101c328ce2a139662600beb204ae
Parents: 494f978
Author: Andrey <an...@gridgain.com>
Authored: Fri Aug 21 18:03:04 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Fri Aug 21 18:03:04 2015 +0700

----------------------------------------------------------------------
 examples/pom.xml                                |   8 +
 .../ignite/examples/NodeJsExamplesSelfTest.java |  94 ++++++++++
 .../JettyRestProcessorAbstractSelfTest.java     |  59 ++++++-
 .../src/main/js/controllers/sql-controller.js   | 141 ++++++++-------
 .../src/main/js/public/stylesheets/style.scss   |  69 +++++++-
 .../src/main/js/routes/agent.js                 |  21 +++
 .../src/main/js/views/sql/sql.jade              | 149 ++++++----------
 .../processors/rest/GridRestCommand.java        |   3 +
 .../processors/rest/GridRestProcessor.java      |   3 +-
 .../handlers/query/QueryCommandHandler.java     | 100 +++++++++--
 .../rest/request/RestQueryRequest.java          | 175 +++++++++++++++++++
 .../rest/request/RestSqlQueryRequest.java       | 125 -------------
 modules/nodejs/src/main/js/apache-ignite.js     |   5 +-
 modules/nodejs/src/main/js/cache.js             |  32 +++-
 modules/nodejs/src/main/js/query.js             |  52 ++++++
 modules/nodejs/src/main/js/scan-query.js        |  52 ++++++
 modules/nodejs/src/main/js/server.js            |   4 +-
 modules/nodejs/src/main/js/sql-fields-query.js  |  70 +-------
 modules/nodejs/src/test/js/test-query.js        |  51 +++++-
 modules/nodejs/src/test/js/test-runner.js       |   4 +-
 .../nodejs/src/test/js/test-script-runner.js    |  39 +++++
 .../http/jetty/GridJettyRestHandler.java        |  35 +++-
 22 files changed, 888 insertions(+), 403 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/examples/pom.xml
----------------------------------------------------------------------
diff --git a/examples/pom.xml b/examples/pom.xml
index 8204a36..54dc2ea 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -63,6 +63,14 @@
 
         <dependency>
             <groupId>org.apache.ignite</groupId>
+            <artifactId>ignite-nodejs</artifactId>
+            <version>${project.version}</version>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.ignite</groupId>
             <artifactId>ignite-spring</artifactId>
             <version>${project.version}</version>
         </dependency>

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/examples/src/test/java/org/apache/ignite/examples/NodeJsExamplesSelfTest.java
----------------------------------------------------------------------
diff --git a/examples/src/test/java/org/apache/ignite/examples/NodeJsExamplesSelfTest.java b/examples/src/test/java/org/apache/ignite/examples/NodeJsExamplesSelfTest.java
new file mode 100644
index 0000000..53f194f
--- /dev/null
+++ b/examples/src/test/java/org/apache/ignite/examples/NodeJsExamplesSelfTest.java
@@ -0,0 +1,94 @@
+/*
+ *
+ *  * 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.examples;
+
+import org.apache.ignite.configuration.*;
+import org.apache.ignite.internal.*;
+import org.apache.ignite.internal.util.typedef.internal.*;
+
+/**
+ * Test for nodejs examples.
+ */
+public class NodeJsExamplesSelfTest extends NodeJsAbstractTest {
+    /** {@inheritDoc} */
+    @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
+        return loadConfiguration("examples/config/js/example-query.xml");
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void beforeTestsStarted() throws Exception {
+        startGrid(0);
+    }
+
+    /** {@inheritDoc} */
+    @Override protected void afterTestsStopped() throws Exception {
+        stopAllGrids();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCacheApiExample() throws Exception {
+        run("cache-api-example.js");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testCachePutGetExample() throws Exception {
+        run("cache-put-get-example.js");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testQueryExample() throws Exception {
+        run("cache-query-example.js");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testFieldsQueryExample() throws Exception {
+        run("cache-sql-fields-query-example.js");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testComputeRunExample() throws Exception {
+        run("compute-run-example.js");
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testComputeMapReduceExample() throws Exception {
+        run("map-reduce-example.js");
+    }
+
+    /**
+     * @param fileName Example file name.
+     * @throws Exception If failed.
+     */
+    private void run(String fileName) throws Exception {
+        runJsScript(null, U.getIgniteHome() + "/examples/src/main/js/" + fileName, ">>> end");
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
index 26c22af..4dc3bdc 100644
--- a/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/internal/processors/rest/JettyRestProcessorAbstractSelfTest.java
@@ -27,6 +27,7 @@ import org.apache.ignite.configuration.*;
 import org.apache.ignite.internal.processors.json.*;
 import org.apache.ignite.internal.processors.rest.handlers.*;
 import org.apache.ignite.internal.util.typedef.*;
+import org.apache.ignite.lang.*;
 import org.apache.ignite.testframework.*;
 
 import java.io.*;
@@ -1333,6 +1334,52 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
     /**
      * @throws Exception If failed.
      */
+    public void testQueryScan() throws Exception {
+        Map<String, String> params = new HashMap<>();
+        params.put("cmd", GridRestCommand.EXECUTE_SCAN_QUERY.key());
+        params.put("pageSize", "10");
+        params.put("cacheName", "person");
+        params.put("classname", ScanFilter.class.getName());
+
+        String ret = content(params);
+
+        assertNotNull(ret);
+        assertTrue(!ret.isEmpty());
+
+        JSONObject json = JSONObject.fromObject(ret);
+
+        List items = (List)((Map)json.get("response")).get("items");
+
+        assertEquals(2, items.size());
+
+        assertFalse(queryCursorFound());
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testIncorrectQueryScan() throws Exception {
+        Map<String, String> params = new HashMap<>();
+        params.put("cmd", GridRestCommand.EXECUTE_SCAN_QUERY.key());
+        params.put("pageSize", "10");
+        params.put("cacheName", "person");
+        params.put("classname", ScanFilter.class.getName() + 1);
+
+        String ret = content(params);
+
+        assertNotNull(ret);
+        assertTrue(!ret.isEmpty());
+
+        JSONObject json = JSONObject.fromObject(ret);
+
+        String err = (String)json.get("error");
+
+        assertTrue(err.contains("Failed to find target class"));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
     public void testQuery() throws Exception {
         grid(0).cache(null).put("1", "1");
         grid(0).cache(null).put("2", "2");
@@ -1648,7 +1695,7 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
         String qry = "salary > ? and salary <= ?";
 
         String ret = makePostRequest(F.asMap("cmd", GridRestCommand.EXECUTE_SQL_QUERY.key(),
-                "type", "Person", "psz", "10", "cacheName", "person",
+                "type", "Person", "pageSize", "10", "cacheName", "person",
                 "qry", URLEncoder.encode(qry)), "{\"arg\": [1000, 2000]}");
 
         assertNotNull(ret);
@@ -1775,4 +1822,14 @@ public abstract class JettyRestProcessorAbstractSelfTest extends AbstractRestPro
             return id;
         }
     }
+
+    /**
+     * Test filter for scan query.
+     */
+    public static class ScanFilter implements IgniteBiPredicate<Integer, Person> {
+        /** {@inheritDoc} */
+        @Override public boolean apply(Integer integer, Person person) {
+            return person.salary > 1000;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/control-center-web/src/main/js/controllers/sql-controller.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/controllers/sql-controller.js b/modules/control-center-web/src/main/js/controllers/sql-controller.js
index d02dec0..7a1eb49 100644
--- a/modules/control-center-web/src/main/js/controllers/sql-controller.js
+++ b/modules/control-center-web/src/main/js/controllers/sql-controller.js
@@ -38,9 +38,6 @@ controlCenterModule.controller('sqlController', ['$scope', '$controller', '$http
                 $scope.notebook = notebook;
 
                 $scope.notebook_name = notebook.name;
-
-                if (notebook.paragraphs)
-                    notebook.paragraphs = [{name: 'Query'}];
             })
             .error(function (errMsg) {
                 $common.showError(errMsg);
@@ -50,50 +47,63 @@ controlCenterModule.controller('sqlController', ['$scope', '$controller', '$http
     loadNotebook();
 
     $scope.renameNotebook = function(name) {
-        $scope.notebook_edit = false;
+        if ($scope.notebook.name != name) {
+            $scope.notebook.name = name;
 
-        $scope.notebook.name = name;
+            $http.post('/notebooks/save', $scope.notebook)
+                .success(function () {
+                    var idx = _.findIndex($scope.$root.notebooks, function (item) {
+                        return item._id == $scope.notebook._id;
+                    });
 
-        $http.post('/notebooks/save', $scope.notebook)
-            .success(function () {
-                var idx = _.findIndex($scope.$root.notebooks, function (item) {
-                    return item._id == $scope.notebook._id;
-                });
+                    if (idx >= 0) {
+                        $scope.$root.notebooks[idx].name = name;
 
-                if (idx >= 0) {
-                    $scope.$root.notebooks[idx].name = name;
+                        $scope.$root.rebuildDropdown();
+                    }
 
-                    $scope.$root.rebuildDropdown();
-                }
-            })
-            .error(function (errMsg) {
-                $common.showError(errMsg);
-            });
+                    $scope.notebook.edit = false;
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
+        }
+        else
+            $scope.notebook.edit = false
     };
 
-    $scope.resetNotebookName = function() {
-        $scope.notebook_edit = false;
+    $scope.renameParagraph = function(paragraph, newName) {
+        if (paragraph.name != newName) {
+            paragraph.name = newName;
 
-        $scope.notebook_name = $scope.notebook.name;
+            $http.post('/notebooks/save', $scope.notebook)
+                .success(function () {
+                    paragraph.edit = false;
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                });
+        }
+        else
+            paragraph.edit = false
     };
 
-    $scope.addParagraph = function(notebook) {
-        notebook.paragraphs.push({});
-    };
+    $scope.addParagraph = function() {
+        if (!$scope.notebook.paragraphs)
+            $scope.notebook.paragraphs = [];
 
-    $scope.tabs = [];
+        var sz = $scope.notebook.paragraphs.length;
 
-    $scope.addTab = function() {
-        var tab = {query: "", pageSize: $scope.pageSizes[0]};
+        var paragraph = {name: 'Query' + (sz ==0 ? '' : sz), editor: true, query: '', pageSize: $scope.pageSizes[0]};
 
         if ($scope.caches.length > 0)
-            tab.selectedItem = $scope.caches[0];
+            paragraph.cache = $scope.caches[0];
 
-        $scope.tabs.push(tab);
+        $scope.notebook.paragraphs.push(paragraph);
     };
 
-    $scope.removeTab = function(idx) {
-        $scope.tabs.splice(idx, 1);
+    $scope.removeParagraph = function(idx) {
+        $scope.notebook.splice(idx, 1);
     };
 
     $http.get('/models/sql.json')
@@ -113,8 +123,8 @@ controlCenterModule.controller('sqlController', ['$scope', '$controller', '$http
 
             $scope.caches = node.caches;
 
-            if ($scope.tabs.length == 0)
-                $scope.addTab();
+            $scope.addParagraph();
+            $scope.addParagraph();
         })
         .error(function (err, status) {
             $scope.caches = undefined;
@@ -125,59 +135,60 @@ controlCenterModule.controller('sqlController', ['$scope', '$controller', '$http
                 $common.showError('Receive agent error: ' + err);
         });
 
-    $scope.execute = function(tab) {
-        $http.post('/agent/query', {query: tab.query, pageSize: tab.pageSize, cacheName: tab.selectedItem.name})
-            .success(function (res) {
-                tab.meta = [];
+    var _processQueryResult = function(item) {
+        return function(res) {
+            item.meta = [];
 
-                if (res.meta)
-                    tab.meta = res.meta;
+            if (res.meta)
+                item.meta = res.meta;
 
-                tab.page = 1;
+            item.page = 1;
 
-                tab.total = 0;
+            item.total = 0;
 
-                tab.queryId = res.queryId;
+            item.queryId = res.queryId;
 
-                tab.rows = res.rows;
-            })
+            item.rows = res.rows;
+
+            item.result = 'table';
+        }
+    };
+
+    $scope.execute = function(item) {
+        $http.post('/agent/query', {query: item.query, pageSize: item.pageSize, cacheName: item.cache.name})
+            .success(_processQueryResult(item))
             .error(function (errMsg) {
                 $common.showError(errMsg);
             });
     };
 
-    $scope.explain = function(tab) {
-        $http.post('/agent/query', {query: 'EXPLAIN ' + tab.query, pageSize: tab.pageSize, cacheName: tab.selectedItem.name})
-            .success(function (res) {
-                tab.meta = [];
-
-                if (res.meta)
-                    tab.meta = res.meta;
-
-                tab.page = 1;
-
-                tab.total = 0;
-
-                tab.queryId = res.queryId;
+    $scope.explain = function(item) {
+        $http.post('/agent/query', {query: 'EXPLAIN ' + item.query, pageSize: item.pageSize, cacheName: item.cache.name})
+            .success(_processQueryResult)
+            .error(function (errMsg) {
+                $common.showError(errMsg);
+            });
+    };
 
-                tab.rows = res.rows;
-            })
+    $scope.scan = function(item) {
+        $http.post('/agent/scan', {pageSize: item.pageSize, cacheName: item.cache.name})
+            .success(_processQueryResult(item))
             .error(function (errMsg) {
                 $common.showError(errMsg);
             });
     };
 
-    $scope.nextPage = function(tab) {
-        $http.post('/agent/query/fetch', {queryId: tab.queryId, pageSize: tab.pageSize, cacheName: tab.selectedItem.name})
+    $scope.nextPage = function(item) {
+        $http.post('/agent/query/fetch', {queryId: item.queryId, pageSize: item.pageSize, cacheName: item.cache.name})
             .success(function (res) {
-                tab.page++;
+                item.page++;
 
-                tab.total += tab.rows.length;
+                item.total += item.rows.length;
 
-                tab.rows = res.rows;
+                item.rows = res.rows;
 
                 if (res.last)
-                    delete tab.queryId;
+                    delete item.queryId;
             })
             .error(function (errMsg) {
                 $common.showError(errMsg);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/control-center-web/src/main/js/public/stylesheets/style.scss
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/public/stylesheets/style.scss b/modules/control-center-web/src/main/js/public/stylesheets/style.scss
index e42e91f..1ebb373 100644
--- a/modules/control-center-web/src/main/js/public/stylesheets/style.scss
+++ b/modules/control-center-web/src/main/js/public/stylesheets/style.scss
@@ -15,6 +15,8 @@
  * limitations under the License.
  */
 
+@import "../../node_modules/bootstrap-sass/assets/stylesheets/bootstrap";
+
 $logo-path: "https://www.filepicker.io/api/file/QagunjDGRFul2JgNCAli";
 $input-height: 28px;
 $ignite-red: #ec1c24;
@@ -675,6 +677,12 @@ button .caret, .btn .caret {
     height: $input-height;
 }
 
+.sql-name-input {
+    @extend .form-control;
+
+    width: auto;
+}
+
 .form-control {
     @extend .base-control;
 
@@ -685,12 +693,36 @@ button .caret, .btn .caret {
     }
 }
 
-.form-control-h1 {
-    @extend .form-control;
+.theme-line .notebook-header {
+    color: black;
+    border-color: #eee;
 
-    width: auto;
     font-size: 22px;
+    line-height: 44px;
     height: 44px;
+
+    h1 {
+        padding: 0;
+        line-height: 44px;
+        height: 44px;
+        margin: 0;
+    }
+
+    i {
+        line-height: 44px;
+        height: 44px;
+        font-size: 14px;
+    }
+
+    input {
+        font-size: 22px;
+        line-height: 44px;
+        height: 44px;
+    }
+}
+
+.theme-line .paragraph-header {
+
 }
 
 .line-control {
@@ -703,11 +735,25 @@ button .caret, .btn .caret {
 
     h3 {
         margin-bottom: 0;
+
+        .result {
+            float: right;
+            i {
+                font-size: 14px;
+                line-height: 14px;
+            }
+        }
     }
 
     h3 > a {
         color: black;
     }
+
+    i {
+        font-size: 14px;
+    }
+
+
 }
 
 .theme-line .panel-body {
@@ -859,6 +905,23 @@ button .caret, .btn .caret {
 
         line-height: $input-height;
     }
+
+    tfoot > tr > td {
+        padding: 0;
+
+        .pagination {
+            margin: 10px 0 0 0;
+
+            > .active > a {
+                color: $ignite-red;
+                font-weight: bold;
+                border-color: #ddd;
+                background-color: #eee;
+            }
+        }
+    }
+
+    margin: 0;
 }
 
 .panel-title a {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/control-center-web/src/main/js/routes/agent.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/routes/agent.js b/modules/control-center-web/src/main/js/routes/agent.js
index d0fba45..4b23b2e 100644
--- a/modules/control-center-web/src/main/js/routes/agent.js
+++ b/modules/control-center-web/src/main/js/routes/agent.js
@@ -20,6 +20,7 @@ var agentManager = require('../agents/agent-manager');
 
 var apacheIgnite = require('apache-ignite');
 var SqlFieldsQuery = apacheIgnite.SqlFieldsQuery;
+var ScanQuery = apacheIgnite.ScanQuery;
 
 function _client(req, res) {
     var client = agentManager.getAgentManager().findClient(req.currentUserId());
@@ -77,6 +78,26 @@ router.post('/query', function (req, res) {
     }
 });
 
+/* Execute query. */
+router.post('/scan', function (req, res) {
+    var client = _client(req, res);
+
+    if (client) {
+        // Create sql query.
+        var qry = new ScanQuery();
+
+        // Set page size for query.
+        qry.setPageSize(req.body.pageSize);
+
+        // Get query cursor.
+        client.ignite().cache(req.body.cacheName).query(qry).nextPage().then(function (cursor) {
+            res.json({meta: cursor.fieldsMetadata(), rows: cursor.page(), queryId: cursor.queryId()});
+        }, function (err) {
+            res.status(500).send(err);
+        });
+    }
+});
+
 /* Get next query page. */
 router.post('/query/fetch', function (req, res) {
     var client = _client(req, res);

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/control-center-web/src/main/js/views/sql/sql.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/sql/sql.jade b/modules/control-center-web/src/main/js/views/sql/sql.jade
index aa770ae..e49e3ad 100644
--- a/modules/control-center-web/src/main/js/views/sql/sql.jade
+++ b/modules/control-center-web/src/main/js/views/sql/sql.jade
@@ -25,34 +25,46 @@ block container
     .row
         .col-sm-12(ng-init='noteId = "#{noteId}";')
             .docs-content(ng-controller='sqlController' )
-                .docs-header
-                    h1
-                        a(ng-hide='notebook_edit' ng-click='notebook_edit = true;' style='line-height: 44px;') {{notebook.name}}
-                    div(ng-show='notebook_edit')
-                        input.form-control-h1(ng-model='notebook_name' on-enter='renameNotebook(notebook_name)' on-escape='resetNotebookName()')
+                .docs-header.notebook-header
+                    h1.col-sm-6(ng-hide='notebook.edit')
+                        a {{notebook.name}}
+                        i.fa.fa-pencil.tipLabel(ng-click='notebook.edit = true;notebook.edit_name = notebook.name' bs-tooltip data-title='Rename notebook' data-trigger='hover')
+                    h1.col-sm-6(ng-show='notebook.edit')
+                        input.sql-name-input(ng-model='notebook.edit_name' on-enter='renameNotebook(notebook.edit_name)' on-escape='notebook.edit = false;')
+                        i.tipLabel.fa.fa-floppy-o(ng-click='renameNotebook(notebook.edit_name)' bs-tooltip data-title='Save notebook name' data-trigger='hover')
+                    h1.col-sm-6
+                        i.tipField.fa.fa-plus(ng-click='addParagraph()' bs-tooltip data-title='Add new paragraph' data-trigger='hover')
+                .docs-body(style='margin-top: 20px;')
                     hr
-                .docs-body
-                    .panel-group(bs-collapse ng-model='notebook.activeIdx')
+                    .panel-group(bs-collapse ng-model='notebook.activeIdx' data-allow-multiple='true' data-start-collapsed='false')
                         .panel.panel-default(ng-repeat='paragraph in notebook.paragraphs')
                             .panel-heading
-                                h3
+                                h3(ng-hide='paragraph.edit')
                                     a(bs-collapse-toggle ng-click='hidePopover()') {{paragraph.name}}
+                                    i.fa.fa-pencil.tipLabel(ng-click='paragraph.edit = true; paragraph.edit_name = paragraph.name;' bs-tooltip data-title='Rename paragraph' data-trigger='hover')
+                                    .result.btn-group(ng-model='paragraph.result')
+                                        i.btn.btn-default.fa.fa-table(ng-click='paragraph.result="table"' bs-tooltip data-title='Show table' data-trigger='hover')
+                                        i.btn.btn-default.fa.fa-bar-chart(ng-click='paragraph.result="bar"' bs-tooltip data-title='Show bar chart' data-trigger='hover')
+                                h3(ng-show='paragraph.edit')
+                                    input.sql-name-input(ng-model='paragraph.edit_name' on-enter='renameParagraph(paragraph, paragraph.edit_name)' on-escape='paragraph.edit = false;')
+                                    i.tipLabel.fa.fa-floppy-o(ng-click='renameParagraph(paragraph, paragraph.edit_name)' bs-tooltip data-title='Save paragraph name' data-trigger='hover')
                             .panel-collapse(role='tabpanel' bs-collapse-target)
-                                .panel-body
+                                .panel-body(ng-show='paragraph.editor')
                                     .row
                                         .col-xs-8.col-sm-9(style='border-right: 1px solid #eee')
                                             div(style='height: 200px' ui-ace='{ theme: "chrome", mode: "sql",' +
                                             'require: ["ace/ext/language_tools"],' +
                                             'rendererOptions: {showPrintMargin: false, highlightGutterLine: false, fontSize: 14},' +
-                                            'advanced: {enableSnippets: false, enableBasicAutocompletion: true, enableLiveAutocompletion: true}}' ng-model='paragraph.query')
+                                            'advanced: {enableSnippets: false, enableBasicAutocompletion: true, enableLiveAutocompletion: true}}' ng-model='paragraph.query'
+                                            ng-class='{"disable": paragraph.status == "RUNNING" || paragraph.status == "PENDING" }')
                                         .col-xs-4.col-sm-3
                                             div(ng-hide='caches.length == 0' style='margin-top: 0.65em')
                                                 lable.labelHeader Caches:
                                                 table.links(st-table='caches')
                                                     tbody
                                                         tr(ng-repeat='cache in caches track by cache.name')
-                                                            td.col-sm-6(ng-class='{active: cache.name == paragraph.activeCache.name}')
-                                                                a(ng-click='paragraph.activeCache = row') {{$index + 1}}) {{::cache.name}}, {{::cache.mode}}
+                                                            td.col-sm-6(ng-class='{active: cache.name == paragraph.cache.name}')
+                                                                a(ng-click='paragraph.cache = cache') {{$index + 1}}) {{::cache.name}}, {{::cache.mode}}
                                     hr(style='margin: 0')
                                     .settings-row
                                         label Page Size:&nbsp;
@@ -61,90 +73,29 @@ block container
                                         button.btn.btn-primary(ng-click='explain(paragraph)') Explain
                                         button.btn.btn-primary(ng-click='execute(paragraph)') Execute
                                         button.btn.btn-primary(ng-click='scan(paragraph)') Scan
-
-                    //    div(ng-show='#{tab}.rows.length > 0' style='margin-top: 0.65em')
-                    //        hr
-                    //        div
-                    //            table.table.table-striped.col-sm-12.sql-results(st-table='displayedCollection' st-safe-src='#{tab}.rows')
-                    //                thead
-                    //                    tr(style='border-size: 0')
-                    //                        td(colspan='{{#{tab}.meta.length}}')
-                    //                            .col-sm-8
-                    //                                lable Page #:&nbsp;
-                    //                                b {{#{tab}.page}}&nbsp;&nbsp;&nbsp;
-                    //                                | Results:&nbsp;
-                    //                                b {{#{tab}.rows.length + #{tab}.total}}
-                    //                            .col-sm-4
-                    //                                button.btn.btn-primary.fieldButton(ng-click='nextPage(#{tab})' ng-disabled='!#{tab}.queryId') Next page
-                    //                                //.input-tip
-                    //                                //    input.form-control(st-search placeholder='Filter...' type='search')
-                    //                    tr
-                    //                        th(ng-repeat='col in #{tab}.meta track by $index' st-sort='getter' data-ng-bind='::col.fieldName' bs-tooltip='col.schemaName + "." + col.typeName + "." + col.fieldName')
-                    //                tbody
-                    //                    //tr
-                    //                    //    td(colspan='{{#{tab}.cols.length}}')
-                    //                    //        .loading-indicator
-                    //                    tr(ng-repeat='row in displayedCollection track by $index')
-                    //                        td(ng-repeat='val in row track by $index') {{ val }}
-                    //
-                    //
-                    //
-                    //div(ng-if='!caches')
-                    //    .block-callout-right.margin-bottom-dflt(style='width: 100%')
-                    //        p(ng-bind-html='joinTip(missingClientTip)')
-                    //div(ng-if='caches')
-                    //    .block-callout-parent.block-callout-border.margin-bottom-dflt
-                    //        .block-callout
-                    //            p(ng-bind-html='joinTip(screenTip)')
-                    //
-                    //    - var tab = 'tabs[tabs.activeIdx]'
-                    //
-                    //    .tabs-below(bs-tabs bs-active-pane='tabs.activeIdx' data-template='/tab')
-                    //        div(ng-repeat='tab in tabs' title='Query' bs-pane)
-                    //    .row
-                    //        .col-xs-8.col-sm-9(style='border-right: 1px solid #eee')
-                    //            div(style='height: 200px' ui-ace='{ theme: "chrome", mode: "sql",' +
-                    //                'require: ["ace/ext/language_tools"],' +
-                    //                'rendererOptions: {showPrintMargin: false, highlightGutterLine: false, fontSize: 14},' +
-                    //                'advanced: {enableSnippets: false, enableBasicAutocompletion: true, enableLiveAutocompletion: true}}' ng-model='#{tab}.query')
-                    //        .col-xs-4.col-sm-3
-                    //            div(ng-hide='caches.length == 0' style='margin-top: 0.65em')
-                    //                lable.labelHeader Caches:
-                    //                table.links(st-table='caches')
-                    //                    tbody
-                    //                        tr(ng-repeat='row in caches track by row.name')
-                    //                            td.col-sm-6(ng-class='{active: row.name == #{tab}.selectedItem.name}')
-                    //                                a(ng-click='#{tab}.selectedItem = row') {{$index + 1}}) {{::row.name}}, {{::row.mode}}
-                    //    hr(style='margin: 0')
-                    //    .settings-row
-                    //        label Page Size:&nbsp;
-                    //        button.btn.btn-default.base-control(ng-model='#{tab}.pageSize' bs-options='item for item in pageSizes' bs-select)
-                    //    .settings-row
-                    //        button.btn.btn-primary(ng-click='explain(#{tab})') Explain
-                    //        button.btn.btn-primary(ng-click='execute(#{tab})') Execute
-                    //        button.btn.btn-primary(ng-click='scan(#{tab})' disabled) Scan
-                    //
-                    //    div(ng-show='#{tab}.rows.length > 0' style='margin-top: 0.65em')
-                    //        hr
-                    //        div
-                    //            table.table.table-striped.col-sm-12.sql-results(st-table='displayedCollection' st-safe-src='#{tab}.rows')
-                    //                thead
-                    //                    tr(style='border-size: 0')
-                    //                        td(colspan='{{#{tab}.meta.length}}')
-                    //                            .col-sm-8
-                    //                                lable Page #:&nbsp;
-                    //                                b {{#{tab}.page}}&nbsp;&nbsp;&nbsp;
-                    //                                | Results:&nbsp;
-                    //                                b {{#{tab}.rows.length + #{tab}.total}}
-                    //                            .col-sm-4
-                    //                                button.btn.btn-primary.fieldButton(ng-click='nextPage(#{tab})' ng-disabled='!#{tab}.queryId') Next page
-                    //                                //.input-tip
-                    //                                //    input.form-control(st-search placeholder='Filter...' type='search')
-                    //                    tr
-                    //                        th(ng-repeat='col in #{tab}.meta track by $index' st-sort='getter' data-ng-bind='::col.fieldName' bs-tooltip='col.schemaName + "." + col.typeName + "." + col.fieldName')
-                    //                tbody
-                    //                    //tr
-                    //                    //    td(colspan='{{#{tab}.cols.length}}')
-                    //                    //        .loading-indicator
-                    //                    tr(ng-repeat='row in displayedCollection track by $index')
-                    //                        td(ng-repeat='val in row track by $index') {{ val }}
+                                .panel-body(ng-show='paragraph.result == "table')
+                                    table.table.table-striped.col-sm-12.sql-results(st-table='displayedCollection' st-safe-src='paragraph.rows')
+                                        thead
+                                            tr(style='border-size: 0')
+                                                td(colspan='{{paragraph.meta.length}}')
+                                                    .col-sm-8
+                                                        lable Page #:&nbsp;
+                                                        b {{paragraph.page}}&nbsp;&nbsp;&nbsp;
+                                                        | Results:&nbsp;
+                                                        b {{paragraph.rows.length + paragraph.total}}
+                                                    .col-sm-4
+                                                        button.btn.btn-primary.fieldButton(ng-click='nextPage(paragraph)' ng-disabled='!paragraph.queryId') Next page
+                                                        //.input-tip
+                                                        //    input.form-control(st-search placeholder='Filter...' type='search')
+                                            tr
+                                                th(ng-repeat='col in paragraph.meta track by $index' st-sort='getter' data-ng-bind='::col.fieldName' bs-tooltip='col.schemaName + "." + col.typeName + "." + col.fieldName')
+                                        tbody
+                                            //tr
+                                            //    td(colspan='{{#{tab}.cols.length}}')
+                                            //        .loading-indicator
+                                            tr(ng-repeat='row in displayedCollection track by $index')
+                                                td(ng-repeat='val in row track by $index') {{ val }}
+                                        tfoot
+                                            tr
+                                                td.text-right(colspan='{{paragraph.meta.length}}')
+                                                    div(st-pagination st-items-by-page='10' st-displayed-pages='5')

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
index d28119a..cabe5fd 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestCommand.java
@@ -153,6 +153,9 @@ public enum GridRestCommand {
     /** Execute sql fields query. */
     EXECUTE_SQL_FIELDS_QUERY("qryfldexe"),
 
+    /** Execute scan query. */
+    EXECUTE_SCAN_QUERY("qryscanexe"),
+
     /** Fetch query results. */
     FETCH_SQL_QUERY("qryfetch"),
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
index 5937c14..ccf4d47 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/GridRestProcessor.java
@@ -540,10 +540,11 @@ public class GridRestProcessor extends GridProcessorAdapter {
 
             case EXECUTE_SQL_QUERY:
             case EXECUTE_SQL_FIELDS_QUERY:
+            case EXECUTE_SCAN_QUERY:
             case CLOSE_SQL_QUERY:
             case FETCH_SQL_QUERY:
                 perm = SecurityPermission.CACHE_READ;
-                name = ((RestSqlQueryRequest)req).cacheName();
+                name = ((RestQueryRequest)req).cacheName();
 
                 break;
 

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
index 43ecc0c..e121b23 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/handlers/query/QueryCommandHandler.java
@@ -29,6 +29,7 @@ import org.apache.ignite.internal.util.future.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
 import org.apache.ignite.lang.*;
 
+import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
@@ -42,6 +43,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
     /** Supported commands. */
     private static final Collection<GridRestCommand> SUPPORTED_COMMANDS = U.sealList(EXECUTE_SQL_QUERY,
         EXECUTE_SQL_FIELDS_QUERY,
+        EXECUTE_SCAN_QUERY,
         FETCH_SQL_QUERY,
         CLOSE_SQL_QUERY);
 
@@ -68,23 +70,24 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
         assert req != null;
 
         assert SUPPORTED_COMMANDS.contains(req.command());
-        assert req instanceof RestSqlQueryRequest : "Invalid type of query request.";
+        assert req instanceof RestQueryRequest : "Invalid type of query request.";
 
         switch (req.command()) {
             case EXECUTE_SQL_QUERY:
-            case EXECUTE_SQL_FIELDS_QUERY: {
+            case EXECUTE_SQL_FIELDS_QUERY:
+            case EXECUTE_SCAN_QUERY: {
                 return ctx.closure().callLocalSafe(
-                    new ExecuteQueryCallable(ctx, (RestSqlQueryRequest)req, qryCurs), false);
+                    new ExecuteQueryCallable(ctx, (RestQueryRequest)req, qryCurs), false);
             }
 
             case FETCH_SQL_QUERY: {
                 return ctx.closure().callLocalSafe(
-                    new FetchQueryCallable(ctx, (RestSqlQueryRequest)req, qryCurs), false);
+                    new FetchQueryCallable(ctx, (RestQueryRequest)req, qryCurs), false);
             }
 
             case CLOSE_SQL_QUERY: {
                 return ctx.closure().callLocalSafe(
-                    new CloseQueryCallable((RestSqlQueryRequest)req, qryCurs), false);
+                    new CloseQueryCallable((RestQueryRequest)req, qryCurs), false);
             }
         }
 
@@ -99,7 +102,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
         private GridKernalContext ctx;
 
         /** Execute query request. */
-        private RestSqlQueryRequest req;
+        private RestQueryRequest req;
 
         /** Queries cursors. */
         private ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCurs;
@@ -109,7 +112,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
          * @param req Execute query request.
          * @param qryCurs Queries cursors.
          */
-        public ExecuteQueryCallable(GridKernalContext ctx, RestSqlQueryRequest req,
+        public ExecuteQueryCallable(GridKernalContext ctx, RestQueryRequest req,
             ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCurs) {
             this.ctx = ctx;
             this.req = req;
@@ -123,15 +126,33 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
             try {
                 Query qry;
 
-                if (req.typeName() != null) {
-                    qry = new SqlQuery(req.typeName(), req.sqlQuery());
+                switch (req.queryType()) {
+                    case SQL:
+                        qry = new SqlQuery(req.typeName(), req.sqlQuery());
 
-                    ((SqlQuery)qry).setArgs(req.arguments());
-                }
-                else {
-                    qry = new SqlFieldsQuery(req.sqlQuery());
+                        ((SqlQuery)qry).setArgs(req.arguments());
+
+                        break;
+
+                    case SQL_FIELDS:
+                        qry = new SqlFieldsQuery(req.sqlQuery());
+
+                        ((SqlFieldsQuery)qry).setArgs(req.arguments());
+
+                        break;
+
+                    case SCAN:
+                        IgniteBiPredicate pred = null;
 
-                    ((SqlFieldsQuery)qry).setArgs(req.arguments());
+                        if (req.className() != null)
+                            pred = instance(IgniteBiPredicate.class, req.className());
+
+                        qry = new ScanQuery(pred);
+
+                        break;
+
+                    default:
+                        throw new IgniteException("Incorrect query type [type=" + req.queryType() + "]");
                 }
 
                 IgniteCache<Object, Object> cache = ctx.grid().cache(req.cacheName());
@@ -182,7 +203,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
      */
     private static class CloseQueryCallable implements Callable<GridRestResponse> {
         /** Execute query request. */
-        private RestSqlQueryRequest req;
+        private RestQueryRequest req;
 
         /** Queries cursors. */
         private final ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCurs;
@@ -191,7 +212,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
          * @param req Execute query request.
          * @param qryCurs Queries cursors.
          */
-        public CloseQueryCallable(RestSqlQueryRequest req,
+        public CloseQueryCallable(RestQueryRequest req,
             ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCurs) {
             this.req = req;
             this.qryCurs = qryCurs;
@@ -225,7 +246,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
      */
     private static class FetchQueryCallable implements Callable<GridRestResponse> {
         /** Execute query request. */
-        private RestSqlQueryRequest req;
+        private RestQueryRequest req;
 
         /** Queries cursors. */
         private final ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCurs;
@@ -238,7 +259,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
          * @param req Execute query request.
          * @param qryCurs Queries cursors.
          */
-        public FetchQueryCallable(GridKernalContext ctx, RestSqlQueryRequest req,
+        public FetchQueryCallable(GridKernalContext ctx, RestQueryRequest req,
             ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCurs) {
             this.ctx = ctx;
             this.req = req;
@@ -276,7 +297,7 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
      */
     private static CacheQueryResult createQueryResult(
         ConcurrentHashMap<Long, IgniteBiTuple<QueryCursor, Iterator>> qryCurs,
-        Iterator cur, RestSqlQueryRequest req, Long qryId, GridKernalContext ctx) {
+        Iterator cur, RestQueryRequest req, Long qryId, GridKernalContext ctx) {
         CacheQueryResult res = new CacheQueryResult();
 
         List<Object> items = new ArrayList<>();
@@ -295,4 +316,45 @@ public class QueryCommandHandler extends GridRestCommandHandlerAdapter {
 
         return res;
     }
+
+    /**
+     * Creates class instance.
+     *
+     * @param cls Target class.
+     * @param clsName Implementing class name.
+     * @return Class instance.
+     * @throws IgniteException If failed.
+     */
+    private static <T> T instance(Class<? extends T> cls, String clsName) throws IgniteException {
+        try {
+            Class<?> implCls = Class.forName(clsName);
+
+            if (!cls.isAssignableFrom(implCls))
+                throw new IgniteException("Failed to create instance (target class does not extend or implement " +
+                    "required class or interface) [cls=" + cls.getName() + ", clsName=" + clsName + ']');
+
+            Constructor<?> ctor = implCls.getConstructor();
+
+            return (T)ctor.newInstance();
+        }
+        catch (ClassNotFoundException e) {
+            throw new IgniteException("Failed to find target class: " + clsName, e);
+        }
+        catch (NoSuchMethodException e) {
+            throw new IgniteException("Failed to find constructor for provided arguments " +
+                "[clsName=" + clsName + ']', e);
+        }
+        catch (InstantiationException e) {
+            throw new IgniteException("Failed to instantiate target class " +
+                "[clsName=" + clsName + ']', e);
+        }
+        catch (IllegalAccessException e) {
+            throw new IgniteException("Failed to instantiate class (constructor is not available) " +
+                "[clsName=" + clsName + ']', e);
+        }
+        catch (InvocationTargetException e) {
+            throw new IgniteException("Failed to instantiate class (constructor threw an exception) " +
+                "[clsName=" + clsName + ']', e.getCause());
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
new file mode 100644
index 0000000..a719776
--- /dev/null
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestQueryRequest.java
@@ -0,0 +1,175 @@
+/*
+ *
+ *  * 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.rest.request;
+
+/**
+ * Sql query request.
+ */
+public class RestQueryRequest extends GridRestRequest {
+    /** Sql query. */
+    private String sqlQry;
+
+    /** Sql query arguments. */
+    private Object[] args;
+
+    /** Page size. */
+    private Integer pageSize;
+
+    /** Cache name. */
+    private String cacheName;
+
+    /** Query id. */
+    private Long qryId;
+
+    /** Query type name. */
+    private String typeName;
+
+    /** Predicate class name for scan query. */
+    private String className;
+
+    /** Query type. */
+    private QueryType type;
+
+    /**
+     * @param sqlQry Sql query.
+     */
+    public void sqlQuery(String sqlQry) {
+        this.sqlQry = sqlQry;
+    }
+
+    /**
+     * @return Sql query.
+     */
+    public String sqlQuery() {
+        return sqlQry;
+    }
+
+    /**
+     * @param args Sql query arguments.
+     */
+    public void arguments(Object[] args) {
+        this.args = args;
+    }
+
+    /**
+     * @return Sql query arguments.
+     */
+    public Object[] arguments() {
+        return args;
+    }
+
+    /**
+     * @param pageSize Page size.
+     */
+    public void pageSize(Integer pageSize) {
+        this.pageSize = pageSize;
+    }
+
+    /**
+     * @return Page size.
+     */
+    public int pageSize() {
+        return pageSize;
+    }
+
+    /**
+     * @param cacheName Cache name.
+     */
+    public void cacheName(String cacheName) {
+        this.cacheName = cacheName;
+    }
+
+    /**
+     * @return Cache name.
+     */
+    public String cacheName() {
+        return cacheName;
+    }
+
+    /**
+     * @param id Query id.
+     */
+    public void queryId(Long id) {
+        this.qryId = id;
+    }
+
+    /**
+     * @return Query id.
+     */
+    public Long queryId() {
+        return qryId;
+    }
+
+    /**
+     * @param typeName Query type name.
+     */
+    public void typeName(String typeName) {
+        this.typeName = typeName;
+    }
+
+    /**
+     * @return Query type name.
+     */
+    public String typeName() {
+        return typeName;
+    }
+
+    /**
+     * @return Predicate class name for scan query.
+     */
+    public String className() {
+        return className;
+    }
+
+    /**
+     * @param className Predicate class name for scan query.
+     */
+    public void className(String className) {
+        this.className = className;
+    }
+
+    /**
+     * @param type Query type.
+     */
+    public void queryType(QueryType type) {
+        this.type = type;
+    }
+
+    /**
+     * @return Query type.
+     */
+    public QueryType queryType() {
+        return type;
+    }
+
+    /**
+     * Supported query types.
+     */
+    public enum QueryType {
+        /** Sql query. */
+        SQL,
+
+        /** Sql fields query. */
+        SQL_FIELDS,
+
+        /** Scan query. */
+        SCAN
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestSqlQueryRequest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestSqlQueryRequest.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestSqlQueryRequest.java
deleted file mode 100644
index 5ba3a50..0000000
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/rest/request/RestSqlQueryRequest.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * 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.rest.request;
-
-/**
- * Sql query request.
- */
-public class RestSqlQueryRequest extends GridRestRequest {
-    /** Sql query. */
-    private String sqlQry;
-
-    /** Sql query arguments. */
-    private Object[] args;
-
-    /** Page size. */
-    private Integer pageSize;
-
-    /** Cache name. */
-    private String cacheName;
-
-    /** Query id. */
-    private Long qryId;
-
-    /** Query type name. */
-    private String typeName;
-
-    /**
-     * @param sqlQry Sql query.
-     */
-    public void sqlQuery(String sqlQry) {
-        this.sqlQry = sqlQry;
-    }
-
-    /**
-     * @return Sql query.
-     */
-    public String sqlQuery() {
-        return sqlQry;
-    }
-
-    /**
-     * @param args Sql query arguments.
-     */
-    public void arguments(Object[] args) {
-        this.args = args;
-    }
-
-    /**
-     * @return Sql query arguments.
-     */
-    public Object[] arguments() {
-        return args;
-    }
-
-    /**
-     * @param pageSize Page size.
-     */
-    public void pageSize(Integer pageSize) {
-        this.pageSize = pageSize;
-    }
-
-    /**
-     * @return Page size.
-     */
-    public int pageSize() {
-        return pageSize;
-    }
-
-    /**
-     * @param cacheName Cache name.
-     */
-    public void cacheName(String cacheName) {
-        this.cacheName = cacheName;
-    }
-
-    /**
-     * @return Cache name.
-     */
-    public String cacheName() {
-        return cacheName;
-    }
-
-    /**
-     * @param id Query id.
-     */
-    public void queryId(Long id) {
-        this.qryId = id;
-    }
-
-    /**
-     * @return Query id.
-     */
-    public Long queryId() {
-        return qryId;
-    }
-
-    /**
-     * @param typeName Query type name.
-     */
-    public void typeName(String typeName) {
-        this.typeName = typeName;
-    }
-
-    /**
-     * @return Query type name.
-     */
-    public String typeName() {
-        return typeName;
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/main/js/apache-ignite.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/apache-ignite.js b/modules/nodejs/src/main/js/apache-ignite.js
index 053b88a..5c54c33 100644
--- a/modules/nodejs/src/main/js/apache-ignite.js
+++ b/modules/nodejs/src/main/js/apache-ignite.js
@@ -22,5 +22,6 @@ module.exports = {
     Ignite : require('./ignite.js').Ignite,
     Compute : require('./compute.js').Compute,
     SqlQuery : require('./sql-query.js').SqlQuery,
-    SqlFieldsQuery : require('./sql-fields-query.js').SqlFieldsQuery
-}
\ No newline at end of file
+    SqlFieldsQuery : require('./sql-fields-query.js').SqlFieldsQuery,
+    ScanQuery : require('./scan-query.js').ScanQuery
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/main/js/cache.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/cache.js b/modules/nodejs/src/main/js/cache.js
index 7c04843..0a6dae2 100644
--- a/modules/nodejs/src/main/js/cache.js
+++ b/modules/nodejs/src/main/js/cache.js
@@ -274,7 +274,7 @@ Cache.prototype.metadata = function(callback) {
 /**
  * Execute sql query
  *
- * @param {SqlQuery|SqlFieldsQuery} qry Query
+ * @param {SqlQuery|SqlFieldsQuery|ScanQuery} qry Query
  * @returns {QueryCursor} Cursor for current query.
  */
 Cache.prototype.query = function(qry) {
@@ -308,7 +308,7 @@ Cache.prototype._createCommand = function(name) {
  * @constructor
  * @this {QueryCursor}
  * @param {Cache} cache Cache that runs query
- * @param {SqlQuery|SqlFieldsQuery} qry Sql query
+ * @param {SqlQuery|SqlFieldsQuery|ScanQuery} qry Sql query
  * @param {boolean} init True if query is not started
  * @param {Object[]} res Current page result
  * @param fieldsMeta Fields metadata.
@@ -485,17 +485,23 @@ QueryCursor.prototype.isFinished = function() {
 
 QueryCursor.prototype._getQueryCommand = function() {
     if (this._init) {
+        this._init = false;
+
         if (this._qry.type() === "Sql") {
             return this._sqlQuery(this._qry);
         }
+        else if (this._qry.type() == "SqlFields") {
+            return this._sqlFieldsQuery(this._qry);
+        }
+        else if (this._qry.type() == "Scan") {
+            return this._scanQuery(this._qry);
+        }
 
-        this._init = false;
-
-        return this._sqlFieldsQuery(this._qry);
+        return null;
     }
 
     return this._cache._createCommand("qryfetch").addParam("qryId", this._res.queryId).
-        addParam("psz", this._qry.pageSize());
+        addParam("pageSize", this._qry.pageSize());
 }
 
 QueryCursor.prototype._sqlFieldsQuery = function(qry) {
@@ -508,9 +514,19 @@ QueryCursor.prototype._sqlQuery = function(qry) {
         setPostData(JSON.stringify({"arg" : qry.arguments()}));
 }
 
+QueryCursor.prototype._scanQuery = function(qry) {
+    var cmd = new Command("qryscanexe").addParam("cacheName", this._cache._cacheName).
+        addParam("pageSize", qry.pageSize());
+
+    if (qry.filterClassName() != null)
+        cmd.addParam("classname", qry.filterClassName());
+
+    return cmd;
+}
+
 QueryCursor.prototype._createQueryCommand = function(name, qry) {
     return new Command(name).addParam("cacheName", this._cache._cacheName).
-        addParam("qry", qry.query()).addParam("psz", qry.pageSize());
+        addParam("qry", qry.query()).addParam("pageSize", qry.pageSize());
 }
 
 /**
@@ -524,4 +540,4 @@ function CacheEntry(key0, val0) {
 }
 
 exports.Cache = Cache
-exports.CacheEntry = CacheEntry
\ No newline at end of file
+exports.CacheEntry = CacheEntry

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/main/js/query.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/query.js b/modules/nodejs/src/main/js/query.js
new file mode 100644
index 0000000..221dd76
--- /dev/null
+++ b/modules/nodejs/src/main/js/query.js
@@ -0,0 +1,52 @@
+/*
+ *
+ *  * 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.
+ *
+ */
+
+/**
+ * @this {Query}
+ */
+function Query() {
+    this._qryType = "";
+    this._pageSz = 1;
+}
+
+/**
+ * @this {Query}
+ * @param {int} pageSz Page size.
+ */
+Query.prototype.setPageSize = function(pageSz) {
+    this._pageSz = pageSz;
+}
+
+/**
+ * @this {Query}
+ * @returns pageSize
+ */
+Query.prototype.pageSize = function() {
+    return this._pageSz;
+}
+
+/**
+ * @this {Query}
+ * @returns "SqlFields"
+ */
+Query.prototype.type = function() {
+    return this._qryType;
+}
+
+exports.Query = Query;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/main/js/scan-query.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/scan-query.js b/modules/nodejs/src/main/js/scan-query.js
new file mode 100644
index 0000000..1e211c2
--- /dev/null
+++ b/modules/nodejs/src/main/js/scan-query.js
@@ -0,0 +1,52 @@
+/*
+ *
+ *  * 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.
+ *
+ */
+
+var Query = require("./query").Query
+
+/**
+ * @this {ScanQuery}
+ */
+function ScanQuery() {
+    Query.apply(this, arguments);
+    this._className = null;
+    this._qryType = "Scan";
+}
+
+ScanQuery.prototype = Query.prototype;
+
+ScanQuery.prototype.constructor = ScanQuery;
+
+
+/**
+ * @this {ScanQuery}
+ * @param type Filter class name
+ */
+ScanQuery.prototype.setFilterClassName = function(className) {
+    this._className = className;
+}
+
+/**
+ * @this {ScanQuery}
+ * @returns Filter class name
+ */
+ScanQuery.prototype.filterClassName = function() {
+    return this._className;
+}
+
+exports.ScanQuery = ScanQuery;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/main/js/server.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/server.js b/modules/nodejs/src/main/js/server.js
index 7fa22b1..b81073c 100644
--- a/modules/nodejs/src/main/js/server.js
+++ b/modules/nodejs/src/main/js/server.js
@@ -86,8 +86,6 @@ Server.prototype.runCommand = function(cmd, callback) {
         });
 
         response.on('end', function () {
-            //console.log("Full response:" + fullResponseString);
-
             if (response.statusCode !== 200) {
                 if (response.statusCode === 401) {
                     callback.call(null, "Authentication failed. Status code 401.");
@@ -250,4 +248,4 @@ Command.prototype._isPost = function() {
 }
 
 exports.Server = Server;
-exports.Command = Command;
\ No newline at end of file
+exports.Command = Command;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/main/js/sql-fields-query.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/main/js/sql-fields-query.js b/modules/nodejs/src/main/js/sql-fields-query.js
index edc9f4c..36615a1 100644
--- a/modules/nodejs/src/main/js/sql-fields-query.js
+++ b/modules/nodejs/src/main/js/sql-fields-query.js
@@ -15,65 +15,23 @@
  * limitations under the License.
  */
 
+var Query = require("./query").Query
+
 /**
  * @this {SqlFieldsQuery}
  * @param {string} Sql query
  */
 function SqlFieldsQuery(sql) {
+    Query.apply(this, arguments);
     this._qryType = "SqlFields";
     this._sql = sql;
     this._arg = [];
     this._pageSz = 1;
-    this._type = null;
-    this._endFunc = function(err) {console.log("Empty end function is called [err=" + err + "]")};
-    this._pageFunc = function(res) {console.log("Empty page function is called [res=" + res + "]")}
-}
-
-/**
- * Set the callbacks for query events.
- *
- * @this {SqlFieldsQuery}
- * @param {string} code Function code could be "end", "page"
- * @param function Functions "end" and "page" are one argument functions.
- */
-SqlFieldsQuery.prototype.on = function(code, f) {
-    switch(code) {
-        case "end":
-            this._endFunc = f;
-
-            break;
-        case "page":
-            this._pageFunc = f;
-
-            break;
-        default :
-            throw "Sql do not have method " + code;
-    }
-}
-
-/**
- * @this {SqlFieldsQuery}
- * @param res Query result
- */
-SqlFieldsQuery.prototype.end = function(err) {
-    this._endFunc(err);
 }
 
-/**
- * @this {SqlFieldsQuery}
- * @param res Query data
- */
-SqlFieldsQuery.prototype.page = function(res) {
-    this._pageFunc(res);
-}
+SqlFieldsQuery.prototype = Query.prototype;
 
-/**
- * @this {SqlFieldsQuery}
- * @param {int} pageSz Page size.
- */
-SqlFieldsQuery.prototype.setPageSize = function(pageSz) {
-    this._pageSz = pageSz;
-}
+SqlFieldsQuery.prototype.constructor = SqlFieldsQuery;
 
 /**
  * @this {SqlFieldsQuery}
@@ -99,20 +57,4 @@ SqlFieldsQuery.prototype.arguments = function() {
     return this._arg;
 }
 
-/**
- * @this {SqlFieldsQuery}
- * @returns pageSize
- */
-SqlFieldsQuery.prototype.pageSize = function() {
-    return this._pageSz;
-}
-
-/**
- * @this {SqlFieldsQuery}
- * @returns "SqlFields"
- */
-SqlFieldsQuery.prototype.type = function() {
-    return this._qryType;
-}
-
-exports.SqlFieldsQuery = SqlFieldsQuery;
\ No newline at end of file
+exports.SqlFieldsQuery = SqlFieldsQuery;

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/test/js/test-query.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/js/test-query.js b/modules/nodejs/src/test/js/test-query.js
index 3d55886..293b2ea 100644
--- a/modules/nodejs/src/test/js/test-query.js
+++ b/modules/nodejs/src/test/js/test-query.js
@@ -22,6 +22,7 @@ var assert = require("assert");
 var Ignite = require(TestUtils.scriptPath());
 var SqlQuery = Ignite.SqlQuery;
 var SqlFieldsQuery = Ignite.SqlFieldsQuery;
+var ScanQuery = Ignite.ScanQuery;
 
 testSqlQuery = function() {
     TestUtils.startIgniteNode().then(function(ignite) {
@@ -59,10 +60,46 @@ testSqlQuery = function() {
 
             cursor.nextPage().then(onQuery);
         }).catch(function(err) {
-            assert(err === null, err);
+            TestUtils.testFails(err);
         })
     }).catch(function(err) {
-        assert(err === null, err);
+        TestUtils.testFails(err);
+    });
+}
+
+testScanQuery = function() {
+    TestUtils.startIgniteNode().then(function(ignite) {
+        var qry = new ScanQuery();
+
+        var fullRes = [];
+
+        function onQuery(cursor) {
+            var page = cursor.page();
+
+            fullRes = fullRes.concat(page);
+
+            if (cursor.isFinished()) {
+                console.log("Full result=" + JSON.stringify(fullRes));
+
+                assert(fullRes.length === 4, "Result length is not correct" +
+                    "[expected=1, val = " + fullRes.length + "]");
+
+                fullRes.sort();
+
+                assert(fullRes[0]["key"] >= 0,
+                    "Result has incorrect index [res=" + fullRes[0]["key"] + "]");
+
+                return ignite.cache("person").get("key");
+            }
+
+            return cursor.nextPage().then(onQuery);
+        }
+
+        ignite.cache("person").query(qry).nextPage().then(onQuery).then(function(){
+            TestUtils.testDone();
+        })
+    }).catch(function(err) {
+        TestUtils.testFails(err);
     });
 }
 
@@ -98,7 +135,7 @@ testSqlFieldsQuery = function() {
             TestUtils.testDone();
         })
     }).catch(function(err) {
-        assert(err === null, err);
+        TestUtils.testFails(err);
     });
 }
 
@@ -148,7 +185,7 @@ testSqlFieldsGetAllQuery = function() {
             TestUtils.testDone();
         })
     }).catch(function(err) {
-        assert(err === null, err);
+        TestUtils.testFails(err);
     });
 }
 
@@ -193,7 +230,7 @@ testSqlFieldsMeta = function() {
 
         ignite.cache("person").query(qry).nextPage().then(onQuery);
     }).catch(function(err) {
-        assert(err === null, err);
+        TestUtils.testFails(err);
     });
 }
 
@@ -232,6 +269,6 @@ testSqlQueryWithParams = function() {
 
         ignite.cache("person").query(qry).nextPage().then(onQuery);
     }).catch(function(err) {
-        assert(err === null, err);
+        TestUtils.testFails(err);
     });
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/test/js/test-runner.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/js/test-runner.js b/modules/nodejs/src/test/js/test-runner.js
index 9ee1092..adbad85 100644
--- a/modules/nodejs/src/test/js/test-runner.js
+++ b/modules/nodejs/src/test/js/test-runner.js
@@ -31,7 +31,7 @@ TestRunner.runTest = function() {
 
     console.log("FileName " + fileName);
 
-    require("./" + fileName);
+    require(fileName);
 
     var functionName = process.argv[3].toString().trim();
 
@@ -43,4 +43,4 @@ TestRunner.runTest = function() {
     global[functionName]();
 }
 
-TestRunner.runTest();
\ No newline at end of file
+TestRunner.runTest();

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/nodejs/src/test/js/test-script-runner.js
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/js/test-script-runner.js b/modules/nodejs/src/test/js/test-script-runner.js
new file mode 100644
index 0000000..7223d51
--- /dev/null
+++ b/modules/nodejs/src/test/js/test-script-runner.js
@@ -0,0 +1,39 @@
+/*
+ *
+ *  * 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.
+ *
+ */
+
+/**
+ * Create instance of ScriptTestRunner
+ *
+ * @constructor
+ */
+function ScriptTestRunner() {
+}
+
+/**
+ * Test routine
+ */
+ScriptTestRunner.runTest = function() {
+    var fileName = process.argv[2].toString().trim();
+
+    console.log("FileName " + fileName);
+
+    require(fileName);
+}
+
+ScriptTestRunner.runTest();

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/17a681c7/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
----------------------------------------------------------------------
diff --git a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
index edd1745..59b22d4 100644
--- a/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
+++ b/modules/rest-http/src/main/java/org/apache/ignite/internal/processors/rest/protocols/http/jetty/GridJettyRestHandler.java
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.*;
 import org.apache.ignite.internal.processors.rest.*;
 import org.apache.ignite.internal.processors.rest.client.message.*;
 import org.apache.ignite.internal.processors.rest.request.*;
+import org.apache.ignite.internal.processors.rest.request.RestQueryRequest.*;
 import org.apache.ignite.internal.util.typedef.*;
 import org.apache.ignite.internal.util.typedef.internal.*;
 import org.apache.ignite.lang.*;
@@ -640,7 +641,7 @@ public class GridJettyRestHandler extends AbstractHandler {
 
             case EXECUTE_SQL_QUERY:
             case EXECUTE_SQL_FIELDS_QUERY: {
-                RestSqlQueryRequest restReq0 = new RestSqlQueryRequest();
+                RestQueryRequest restReq0 = new RestQueryRequest();
 
                 restReq0.sqlQuery((String) params.get("qry"));
 
@@ -661,20 +662,46 @@ public class GridJettyRestHandler extends AbstractHandler {
 
                 restReq0.cacheName((String)params.get("cacheName"));
 
+                if (cmd.equals(EXECUTE_SQL_QUERY))
+                    restReq0.queryType(QueryType.SQL);
+                else
+                    restReq0.queryType(QueryType.SQL_FIELDS);
+
+                restReq = restReq0;
+
+                break;
+            }
+
+            case EXECUTE_SCAN_QUERY: {
+                RestQueryRequest restReq0 = new RestQueryRequest();
+
+                restReq0.sqlQuery((String)params.get("qry"));
+
+                String pageSize = (String)params.get("pageSize");
+
+                if (pageSize != null)
+                    restReq0.pageSize(Integer.parseInt(pageSize));
+
+                restReq0.cacheName((String)params.get("cacheName"));
+
+                restReq0.className((String)params.get("classname"));
+
+                restReq0.queryType(QueryType.SCAN);
+
                 restReq = restReq0;
 
                 break;
             }
 
             case FETCH_SQL_QUERY: {
-                RestSqlQueryRequest restReq0 = new RestSqlQueryRequest();
+                RestQueryRequest restReq0 = new RestQueryRequest();
 
                 String qryId = (String) params.get("qryId");
 
                 if (qryId != null)
                     restReq0.queryId(Long.parseLong(qryId));
 
-                String pageSize = (String) params.get("pageSize");
+                String pageSize = (String)params.get("pageSize");
 
                 if (pageSize != null)
                     restReq0.pageSize(Integer.parseInt(pageSize));
@@ -687,7 +714,7 @@ public class GridJettyRestHandler extends AbstractHandler {
             }
 
             case CLOSE_SQL_QUERY: {
-                RestSqlQueryRequest restReq0 = new RestSqlQueryRequest();
+                RestQueryRequest restReq0 = new RestQueryRequest();
 
                 String qryId = (String) params.get("qryId");
 


[3/7] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-843' into ignite-843

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-843' into ignite-843


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

Branch: refs/heads/ignite-843
Commit: eae81c0510eabee6e75664367ab31601a7ab727a
Parents: 1234196 885a022
Author: Andrey <an...@gridgain.com>
Authored: Fri Aug 21 10:54:19 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Fri Aug 21 10:54:19 2015 +0700

----------------------------------------------------------------------
 .../main/js/controllers/models/metadata.json    |   2 +-
 .../src/main/js/public/stylesheets/style.scss   |  11 +-
 .../src/main/js/views/includes/controls.jade    |  93 +++--
 .../util/nio/ssl/BlockingSslHandler.java        |   2 +-
 .../ignite/testframework/GridTestUtils.java     |   2 +-
 .../query/IgniteSqlSplitterSelfTest.java        | 123 ++++--
 modules/zookeeper/pom.xml                       |  89 +++++
 .../zk/TcpDiscoveryZookeeperIpFinder.java       | 350 +++++++++++++++++
 .../tcp/ipfinder/zk/ZookeeperIpFinderTest.java  | 390 +++++++++++++++++++
 pom.xml                                         |   1 +
 10 files changed, 982 insertions(+), 81 deletions(-)
----------------------------------------------------------------------



[7/7] incubator-ignite git commit: Merge remote-tracking branch 'origin/ignite-843' into ignite-843

Posted by an...@apache.org.
Merge remote-tracking branch 'origin/ignite-843' into ignite-843


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

Branch: refs/heads/ignite-843
Commit: 4e007c7ebe36944edbff938ba21401350d16e2ed
Parents: 17a681c 41c2aba
Author: Andrey <an...@gridgain.com>
Authored: Fri Aug 21 18:04:49 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Fri Aug 21 18:04:49 2015 +0700

----------------------------------------------------------------------
 modules/control-center-agent/README.txt         |   5 +-
 .../assembly/release-control-center-agent.xml   |   4 +-
 .../apache/ignite/agent/AgentConfiguration.java | 110 +++++++++----------
 .../org/apache/ignite/agent/AgentLauncher.java  |  20 ++--
 .../org/apache/ignite/agent/AgentSocket.java    |   4 +-
 .../org/apache/ignite/agent/AgentUtils.java     |   4 +-
 .../handlers/DatabaseMetadataExtractor.java     |   2 +-
 .../ignite/agent/handlers/RestExecutor.java     |   4 +-
 .../agent/testdrive/AgentMetadataTestDrive.java |  44 +++-----
 .../test-drive/test-drive.sql                   |  40 +++++++
 .../src/main/js/public/stylesheets/style.scss   |  21 ++++
 .../src/main/js/views/configuration/caches.jade |   2 +-
 .../main/js/views/configuration/clusters.jade   |   2 +-
 .../js/views/configuration/metadata-load.jade   |   2 +-
 .../main/js/views/configuration/metadata.jade   |   2 +-
 .../src/main/js/views/includes/controls.jade    |  11 +-
 .../src/main/js/views/templates/copy.jade       |   4 +-
 .../src/main/js/views/templates/select.jade     |   8 +-
 18 files changed, 167 insertions(+), 122 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/4e007c7e/modules/control-center-web/src/main/js/public/stylesheets/style.scss
----------------------------------------------------------------------


[5/7] incubator-ignite git commit: # GG-843 Minor fix.

Posted by an...@apache.org.
# GG-843 Minor fix.


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

Branch: refs/heads/ignite-843
Commit: 494f978e82e25a6100be5a99b9b0768b3da18d10
Parents: d686f12
Author: Andrey <an...@gridgain.com>
Authored: Fri Aug 21 15:39:14 2015 +0700
Committer: Andrey <an...@gridgain.com>
Committed: Fri Aug 21 15:39:14 2015 +0700

----------------------------------------------------------------------
 .../main/js/views/templates/agent-download.jade | 16 ++++++---
 .../ignite/internal/NodeJsAbstractTest.java     | 34 +++++++++++++++++---
 .../ignite/internal/NodeJsSqlQuerySelfTest.java |  9 ++++++
 3 files changed, 51 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/494f978e/modules/control-center-web/src/main/js/views/templates/agent-download.jade
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/views/templates/agent-download.jade b/modules/control-center-web/src/main/js/views/templates/agent-download.jade
index c619a45..a9312d6 100644
--- a/modules/control-center-web/src/main/js/views/templates/agent-download.jade
+++ b/modules/control-center-web/src/main/js/views/templates/agent-download.jade
@@ -24,9 +24,17 @@
                     | &nbsp;in order to {{::agentGoal}}.
                 p For installation:
                 ul
-                    li Download and unzip ignite-web-agent.
-                    li For list of options, run ignite-web-agent.[sh|bat] --help.
-                    li To test drive, run ignite-web-agent.[sh|bat] {{::agentTestDriveOption}}.
-                    li Refer to README.txt for more information.
+                    li Download and unzip&nbsp;
+                        b ignite-web-agent
+                        | .
+                    li For list of options, run&nbsp;
+                        b ignite-web-agent.{sh|bat} --help
+                        | .
+                    li To test drive, run&nbsp;
+                        b ignite-web-agent.{sh|bat} {{::agentTestDriveOption}}
+                        | .
+                    li Refer to&nbsp;
+                        b README.txt
+                        | &nbsp;for more information.
             .modal-footer
                 button.btn.btn-primary(ng-click='downloadAgent()') Download zip

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/494f978e/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsAbstractTest.java b/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsAbstractTest.java
index 47152e9..011d727 100644
--- a/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsAbstractTest.java
+++ b/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsAbstractTest.java
@@ -58,6 +58,13 @@ public class NodeJsAbstractTest extends GridCommonAbstractTest {
         this.fileName = fileName;
     }
 
+    /**
+     * Empty constructor.
+     */
+    protected NodeJsAbstractTest() {
+        // No-op.
+    }
+
     /** {@inheritDoc} */
     @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception {
         IgniteConfiguration cfg = super.getConfiguration(gridName);
@@ -111,6 +118,16 @@ public class NodeJsAbstractTest extends GridCommonAbstractTest {
      * @throws Exception If script failed.
      */
     protected void runJsScript(String functionName) throws Exception {
+        runJsScript(functionName, getNodeJsTestDir() + fileName, null);
+    }
+
+    /**
+     * @param functionName Function name.
+     * @param fileName File name.
+     * @param scriptFinished Script finished string.
+     * @throws Exception If script failed.
+     */
+    protected void runJsScript(String functionName, String fileName, String scriptFinished) throws Exception {
         final CountDownLatch readyLatch = new CountDownLatch(1);
 
         GridJavaProcess proc = null;
@@ -120,9 +137,18 @@ public class NodeJsAbstractTest extends GridCommonAbstractTest {
         List<String> cmd = new ArrayList<>();
 
         cmd.add("node");
-        cmd.add(getNodeJsTestDir() + "test-runner.js");
-        cmd.add(fileName);
-        cmd.add(functionName);
+
+        if (functionName != null) {
+            cmd.add(getNodeJsTestDir() + "test-runner.js");
+            cmd.add(fileName);
+            cmd.add(functionName);
+        }
+        else {
+            cmd.add(getNodeJsTestDir() + "test-script-runner.js");
+            cmd.add(fileName);
+        }
+
+        final String finishedFlag = scriptFinished != null ? scriptFinished : SCRIPT_FINISHED;
 
         Map<String, String> env = new HashMap<>();
 
@@ -136,7 +162,7 @@ public class NodeJsAbstractTest extends GridCommonAbstractTest {
 
                         s = s.toLowerCase();
 
-                        if (s.contains(SCRIPT_FINISHED))
+                        if (s.contains(finishedFlag))
                             readyLatch.countDown();
 
                         if (s.contains("assert") || s.contains(SCRIPT_FAILED)) {

http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/494f978e/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsSqlQuerySelfTest.java
----------------------------------------------------------------------
diff --git a/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsSqlQuerySelfTest.java b/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsSqlQuerySelfTest.java
index 22d7ad4..f290820 100644
--- a/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsSqlQuerySelfTest.java
+++ b/modules/nodejs/src/test/java/org/apache/ignite/internal/NodeJsSqlQuerySelfTest.java
@@ -99,6 +99,15 @@ public class NodeJsSqlQuerySelfTest extends NodeJsAbstractTest {
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testScanQuery() throws Exception {
+        initCache();
+
+        runJsScript("testScanQuery");
+    }
+
+    /**
      * Init cache.
      */
     private void initCache() {