# ignite-1148 Added sql tab.
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/94bb0d95 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/94bb0d95 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/94bb0d95 Branch: refs/heads/ignite-843 Commit: 94bb0d9587b0479cd64c48496e500c570fa6350a Parents: f621c3e Author: Andrey <anovi...@gridgain.com> Authored: Wed Jul 29 10:27:57 2015 +0700 Committer: Andrey <anovi...@gridgain.com> Committed: Wed Jul 29 10:27:57 2015 +0700 ---------------------------------------------------------------------- modules/nodejs/src/main/js/cache.js | 13 ++ .../src/main/js/agents/agent-manager.js | 4 +- .../src/main/js/controllers/sql-controller.js | 131 +++++++++++++------ .../src/main/js/routes/agent.js | 57 +++++++- .../src/main/js/views/sql.jade | 70 ---------- .../src/main/js/views/sql/sql.jade | 31 +++-- .../src/main/js/views/templates/layout.jade | 2 +- 7 files changed, 171 insertions(+), 137 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94bb0d95/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 1600eaa..e9db1b3 100644 --- a/modules/nodejs/src/main/js/cache.js +++ b/modules/nodejs/src/main/js/cache.js @@ -421,6 +421,19 @@ QueryCursor.prototype.page = function() { } /** + * Gets queryId of the query. + * + * @this{QueryCursor} + * @returns {Object} Query id may be null. + */ +QueryCursor.prototype.queryId = function() { + if (this.isFinished()) + return undefined; + + return this._res.queryId; +} + +/** * Closes all resources related to this cursor. * * @this{QueryCursor} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94bb0d95/modules/web-control-center/src/main/js/agents/agent-manager.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/src/main/js/agents/agent-manager.js b/modules/web-control-center/src/main/js/agents/agent-manager.js index 252b984..10d3a56 100644 --- a/modules/web-control-center/src/main/js/agents/agent-manager.js +++ b/modules/web-control-center/src/main/js/agents/agent-manager.js @@ -17,7 +17,7 @@ var WebSocketServer = require('ws').Server; -var ignite = require('apache-ignite'); +var apacheIgnite = require('apache-ignite'); var db = require('../db'); @@ -216,7 +216,7 @@ Client.prototype._handleMessage = function(msg) { self._manager._addClient(account._id, self); - self._ignite = new ignite.Ignite(new AgentServer(self)); + self._ignite = new apacheIgnite.Ignite(new AgentServer(self)); } }); } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94bb0d95/modules/web-control-center/src/main/js/controllers/sql-controller.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/src/main/js/controllers/sql-controller.js b/modules/web-control-center/src/main/js/controllers/sql-controller.js index 12772c6..b4b4335 100644 --- a/modules/web-control-center/src/main/js/controllers/sql-controller.js +++ b/modules/web-control-center/src/main/js/controllers/sql-controller.js @@ -15,63 +15,32 @@ * limitations under the License. */ -var demoResults = [ - { - id: 256, - firstName: 'Ivan', - lastName: 'Ivanov' - }, - { - id: 384, - firstName: 'Sergey', - lastName: 'Petrov' - }, - { - id: 923, - firstName: 'Andrey', - lastName: 'Sidorov' - } -]; - -var demoCaches = [{_id: '1', name: 'Users', mode: 'LOCAL'}, {_id: '2', name: 'Organizations', mode: 'REPLICATED'}, {_id: '3', name: 'Cities', mode: 'PARTITIONED'}]; - - - controlCenterModule.controller('sqlController', ['$scope', '$http', '$common', function ($scope, $http, $common) { $scope.joinTip = $common.joinTip; $scope.pageSizes = [50, 100, 200, 400, 800, 1000]; - $scope.tabs = [ - { - query: "SELECT u.id, u.firstName, u.lastName FROM User u WHERE u.name LIKE 'aaaa'", - cols: Object.keys(demoResults[0]), - page: 1, - hasMore: true, - total: 0, - rows: demoResults - }, - {query: "SELECT * FROM Organization"} + $scope.modes = [ + {value: 'PARTITIONED', label: 'PARTITIONED'}, + {value: 'REPLICATED', label: 'REPLICATED'}, + {value: 'LOCAL', label: 'LOCAL'} ]; + $scope.tabs = []; + $scope.addTab = function() { - console.log('addTab'); + var tab = {query: "", pageSize: $scope.pageSizes[0]}; + + if ($scope.caches.length > 0) + tab.selectedItem = $scope.caches[0]; - $scope.tabs.push({query: "SELECT "}); + $scope.tabs.push(tab); }; $scope.removeTab = function(idx) { - console.log('removeTab'); - $scope.tabs.splice(idx, 1); }; - $scope.modes = [ - {value: 'PARTITIONED', label: 'PARTITIONED'}, - {value: 'REPLICATED', label: 'REPLICATED'}, - {value: 'LOCAL', label: 'LOCAL'} - ]; - $http.get('/models/sql.json') .success(function (data) { $scope.screenTip = data.screenTip; @@ -80,5 +49,81 @@ controlCenterModule.controller('sqlController', ['$scope', '$http', '$common', f $common.showError(errMsg); }); - $scope.caches = demoCaches; + $scope.caches = []; + + $http.post('/agent/topology') + .success(function (clusters) { + var node = clusters[0]; + + $scope.caches = node.caches; + + if ($scope.tabs.length == 0) + $scope.addTab(); + }) + .error(function (errMsg) { + $common.showError(errMsg); + }); + + $scope.execute = function(tab) { + $http.post('/agent/query', {query: 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; + + tab.rows = res.rows; + }) + .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; + + tab.rows = res.rows; + }) + .error(function (errMsg) { + $common.showError(errMsg); + }); + }; + + $scope.nextPage = function(tab) { + $http.post('/agent/next_page', {queryId: tab.queryId, pageSize: tab.pageSize, cacheName: tab.selectedItem.name}) + .success(function (res) { + tab.page++; + + tab.total += tab.rows.length; + + tab.rows = res.rows; + + if (res.last) + delete tab.queryId; + }) + .error(function (errMsg) { + $common.showError(errMsg); + }); + }; + + $scope.getter = function (value) { + return value; + } }]); http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94bb0d95/modules/web-control-center/src/main/js/routes/agent.js ---------------------------------------------------------------------- diff --git a/modules/web-control-center/src/main/js/routes/agent.js b/modules/web-control-center/src/main/js/routes/agent.js index 19379e2..4646c28 100644 --- a/modules/web-control-center/src/main/js/routes/agent.js +++ b/modules/web-control-center/src/main/js/routes/agent.js @@ -18,20 +18,67 @@ var router = require('express').Router(); var agentManager = require('../agents/agent-manager'); +var apacheIgnite = require('apache-ignite'); +var SqlFieldsQuery = apacheIgnite.SqlFieldsQuery; + /* GET summary page. */ router.post('/topology', function(req, res) { - var c = agentManager.getAgentManager().getOneClient(); + var client = agentManager.getAgentManager().getOneClient(); - if (!c) + if (!client) return res.status(500).send("Client not found"); - var ignite = c.ignite(); + client.ignite().cluster().then(function (clusters) { + res.json(clusters.map(function (cluster) { + var caches = Object.keys(cluster._caches).map(function(key) { + return {"name" : key, "mode" : cluster._caches[key] } + }); - ignite.cluster().then(function (cluster) { - res.json(cluster); + return { nodeId: cluster._nodeId, caches: caches }; + })); }, function (err) { res.send(err); }); }); +/* GET summary page. */ +router.post('/query', function(req, res) { + var client = agentManager.getAgentManager().getOneClient(); + + if (!client) + return res.status(500).send("Client not found"); + + // Create sql query. + var qry = new SqlFieldsQuery(req.body.query); + + // 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 summary page. */ +router.post('/next_page', function(req, res) { + var client = agentManager.getAgentManager().getOneClient(); + + if (!client) + return res.status(500).send("Client not found"); + + var cache = client.ignite().cache(req.body.cacheName); + + var cmd = cache._createCommand("qryfetch").addParam("qryId", req.body.queryId). + addParam("psz", req.body.pageSize); + + cache.__createPromise(cmd).then(function (page) { + res.json({rows: page["items"], last: page === null || page["last"]}); + }, function (err) { + res.status(500).send(err); + }); +}); + module.exports = router; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94bb0d95/modules/web-control-center/src/main/js/views/sql.jade ---------------------------------------------------------------------- diff --git a/modules/web-control-center/src/main/js/views/sql.jade b/modules/web-control-center/src/main/js/views/sql.jade deleted file mode 100644 index 9ba3056..0000000 --- a/modules/web-control-center/src/main/js/views/sql.jade +++ /dev/null @@ -1,70 +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. -extends ../templates/layout - -append scripts - script(src='/sql-controller.js') - - script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/theme-chrome.js') - script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/mode-sql.js') - script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ext-language_tools.js') - -block container - .row - .col-sm-12 - .docs-content - .docs-header - h1 Connect to Ignite and execute SQL queries - hr - .docs-body(ng-controller='sqlController') - .block-callout - p(ng-bind-html='joinTip(screenTip)') - .tabs-below(bs-tabs bs-active-pane='tabs.activeTab') - div(title='Query #1' bs-pane) - .row - .col-sm-9 - 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='query') - .col-sm-3 - .links(ng-hide='caches.length == 0' style='margin-top: 0.65em') - lable.labelHeader Caches: - table(st-table='caches') - tbody - tr(ng-repeat='row in caches track by row._id') - td.col-sm-6(ng-class='{active: row._id == selectedItem._id}') - a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}} - div(title='Query #2' bs-pane) - .row - .settings-row - button.btn.btn-primary(ng-click='') Explain - button.btn.btn-primary(ng-click='') Execute - button.btn.btn-primary(ng-click='' disabled) Scan - //#resultPanel - // strong Results - // - // #queryResult - // div(ng-repeat='r in results') - // .resultRow - // | {{r.id}} -> {{r.s}} - // span.props {{r.fields}} - - div(ng-hide='results.length == 0' style='margin-top: 0.65em') - lable.labelHeader Results: - table.table-bordered(st-table='results') - tbody - tr(ng-repeat='row in results') - td - a(ng-click='selectItem(row)') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94bb0d95/modules/web-control-center/src/main/js/views/sql/sql.jade ---------------------------------------------------------------------- diff --git a/modules/web-control-center/src/main/js/views/sql/sql.jade b/modules/web-control-center/src/main/js/views/sql/sql.jade index 97d34de..2ce6958 100644 --- a/modules/web-control-center/src/main/js/views/sql/sql.jade +++ b/modules/web-control-center/src/main/js/views/sql/sql.jade @@ -46,40 +46,39 @@ block container lable.labelHeader Caches: table.links(st-table='caches') tbody - tr(ng-repeat='row in caches track by row._id') - td.col-sm-6(ng-class='{active: row._id == #{tab}.selectedItem._id}') - a(ng-click='#{tab}.selectedItem = row') {{$index + 1}}) {{row.name}}, {{row.mode | displayValue:modes:'Cache mode not set'}} + 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: - button.btn.btn-default.base-control(ng-init='pageSize = pageSizes[0]' ng-model='pageSize' bs-options='item for item in pageSizes' bs-select) + 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 - button.btn.btn-primary(ng-click='') Execute - button.btn.btn-primary(ng-click='' disabled) Scan + 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='rows' st-safe-src='#{tab}.rows') + 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}.cols.length}}') + td(colspan='{{#{tab}.meta.length}}') .col-sm-8 lable Page #: b {{#{tab}.page}} | Results: b {{#{tab}.rows.length + #{tab}.total}} .col-sm-4 - button.btn.btn-primary.fieldButton(ng-click='') Next page - .input-tip - input.form-control(type='text' st-search='' placeholder='Filter...') - + 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='column in #{tab}.cols' st-sort='{{column}}') {{column}} + 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 rows') - td(ng-repeat='column in #{tab}.cols') {{row[column]}} \ No newline at end of file + tr(ng-repeat='row in displayedCollection track by $index') + td(ng-repeat='val in row track by $index') {{ val }} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/94bb0d95/modules/web-control-center/src/main/js/views/templates/layout.jade ---------------------------------------------------------------------- diff --git a/modules/web-control-center/src/main/js/views/templates/layout.jade b/modules/web-control-center/src/main/js/views/templates/layout.jade index 71d8936..8e92edb 100644 --- a/modules/web-control-center/src/main/js/views/templates/layout.jade +++ b/modules/web-control-center/src/main/js/views/templates/layout.jade @@ -41,7 +41,7 @@ html(ng-app='ignite-web-control-center' ng-init='user = #{JSON.stringify(user)}; script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.js') script(src='//cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.0/angular-strap.tpl.min.js') - script(src='//cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.0.3/smart-table.js') + script(src='//cdnjs.cloudflare.com/ajax/libs/angular-smart-table/2.1.1/smart-table.js') script(src='//cdnjs.cloudflare.com/ajax/libs/ace/1.2.0/ace.js') script(src='//angular-ui.github.io/ui-ace/dist/ui-ace.min.js')