Skip to content

Commit 63274db

Browse files
committed
Merge pull request #363 from EverythingMe/feature/query_parameters
Feature: support for query parameters
2 parents 521a32d + 4c73e78 commit 63274db

File tree

7 files changed

+91
-32
lines changed

7 files changed

+91
-32
lines changed

rd_ui/app/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
<script src="/scripts/ui-bootstrap-tpls-0.5.0.min.js"></script>
127127
<script src="/bower_components/bucky/bucky.js"></script>
128128
<script src="/bower_components/pace/pace.js"></script>
129+
<script src="/bower_components/mustache/mustache.js"></script>
129130
<!-- endbuild -->
130131

131132
<!-- build:js({.tmp,app}) /scripts/scripts.js -->

rd_ui/app/scripts/controllers/dashboard.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
var w = new Widget(widget);
1717

1818
if (w.visualization) {
19-
promises.push(w.getQuery().getQueryResultPromise());
19+
promises.push(w.getQuery().getQueryResult().toPromise());
2020
}
2121

2222
return w;
@@ -104,7 +104,7 @@
104104
};
105105
};
106106

107-
var WidgetCtrl = function($scope, Events, Query) {
107+
var WidgetCtrl = function($scope, $location, Events, Query) {
108108
$scope.deleteWidget = function() {
109109
if (!confirm('Are you sure you want to remove "' + $scope.widget.getName() + '" from the dashboard?')) {
110110
return;
@@ -128,7 +128,9 @@
128128
Events.record(currentUser, "view", "visualization", $scope.widget.visualization.id);
129129

130130
$scope.query = $scope.widget.getQuery();
131-
$scope.queryResult = $scope.query.getQueryResult();
131+
var parameters = Query.collectParamsFromQueryString($location, $scope.query);
132+
var maxAge = $location.search()['maxAge'];
133+
$scope.queryResult = $scope.query.getQueryResult(maxAge, parameters);
132134
$scope.nextUpdateTime = moment(new Date(($scope.query.updated_at + $scope.query.ttl + $scope.query.runtime + 300) * 1000)).fromNow();
133135

134136
$scope.type = 'visualization';
@@ -139,6 +141,6 @@
139141

140142
angular.module('redash.controllers')
141143
.controller('DashboardCtrl', ['$scope', 'Events', 'Widget', '$routeParams', '$location', '$http', '$timeout', '$q', 'Dashboard', DashboardCtrl])
142-
.controller('WidgetCtrl', ['$scope', 'Events', 'Query', WidgetCtrl])
144+
.controller('WidgetCtrl', ['$scope', '$location', 'Events', 'Query', WidgetCtrl])
143145

144146
})();

rd_ui/app/scripts/controllers/query_source.js

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,7 @@
1414
var isNewQuery = !$scope.query.id,
1515
queryText = $scope.query.query,
1616
// ref to QueryViewCtrl.saveQuery
17-
saveQuery = $scope.saveQuery,
18-
shortcuts = {
19-
'meta+s': function () {
20-
if ($scope.canEdit) {
21-
$scope.saveQuery();
22-
}
23-
},
24-
'ctrl+s': function () {
25-
if ($scope.canEdit) {
26-
$scope.saveQuery();
27-
}
28-
},
29-
// Cmd+Enter for Mac
30-
'meta+enter': function () {
31-
$scope.executeQuery();
32-
},
33-
// Ctrl+Enter for PC
34-
'ctrl+enter': function () {
35-
$scope.executeQuery();
36-
}
37-
};
17+
saveQuery = $scope.saveQuery;
3818

3919
$scope.sourceMode = true;
4020
$scope.canEdit = currentUser.canEdit($scope.query);
@@ -49,8 +29,22 @@
4929
}
5030
});
5131

52-
53-
KeyboardShortcuts.bind(shortcuts);
32+
KeyboardShortcuts.bind({
33+
'meta+s': function () {
34+
if ($scope.canEdit) {
35+
$scope.saveQuery();
36+
}
37+
},
38+
'ctrl+s': function () {
39+
if ($scope.canEdit) {
40+
$scope.saveQuery();
41+
}
42+
},
43+
// Cmd+Enter for Mac
44+
'meta+enter': $scope.executeQuery,
45+
// Ctrl+Enter for PC
46+
'ctrl+enter': $scope.executeQuery
47+
});
5448

5549
// @override
5650
$scope.saveQuery = function(options, data) {

rd_ui/app/scripts/controllers/query_view.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,18 @@
44
function QueryViewCtrl($scope, Events, $route, $location, notifications, growl, Query, DataSource) {
55
var DEFAULT_TAB = 'table';
66

7+
var getQueryResult = function(ttl) {
8+
// Collect params, and getQueryResult with params; getQueryResult merges it into the query
9+
var parameters = Query.collectParamsFromQueryString($location, $scope.query);
10+
if (ttl == undefined) {
11+
ttl = $location.search()['maxAge'];
12+
}
13+
$scope.queryResult = $scope.query.getQueryResult(ttl, parameters);
14+
}
15+
716
$scope.query = $route.current.locals.query;
817
Events.record(currentUser, 'view', 'query', $scope.query.id);
9-
$scope.queryResult = $scope.query.getQueryResult();
18+
getQueryResult();
1019
$scope.queryExecuting = false;
1120

1221
$scope.isQueryOwner = currentUser.id === $scope.query.user.id;
@@ -57,7 +66,7 @@
5766
};
5867

5968
$scope.executeQuery = function() {
60-
$scope.queryResult = $scope.query.getQueryResult(0);
69+
getQueryResult(0);
6170
$scope.lockButton(true);
6271
$scope.cancelling = false;
6372
Events.record(currentUser, 'execute', 'query', $scope.query.id);

rd_ui/app/scripts/services/resources.js

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,15 +399,54 @@
399399
});
400400
};
401401

402+
Query.collectParamsFromQueryString = function($location, query) {
403+
var parameterNames = query.getParameters();
404+
var parameters = {};
405+
406+
var queryString = $location.search();
407+
_.each(parameterNames, function(param, i) {
408+
var qsName = "p_" + param;
409+
if (qsName in queryString) {
410+
parameters[param] = queryString[qsName];
411+
}
412+
});
413+
414+
return parameters;
415+
};
416+
402417
Query.prototype.getSourceLink = function () {
403418
return '/queries/' + this.id + '/source';
404419
};
405420

406-
Query.prototype.getQueryResult = function (ttl) {
421+
Query.prototype.getQueryResult = function (ttl, parameters) {
407422
if (ttl == undefined) {
408423
ttl = this.ttl;
409424
}
410425

426+
var queryText = this.query;
427+
428+
var queryParameters = this.getParameters();
429+
var paramsRequired = !_.isEmpty(queryParameters);
430+
431+
var missingParams = parameters === undefined ? queryParameters : _.difference(queryParameters, _.keys(parameters));
432+
433+
if (paramsRequired && missingParams.length > 0) {
434+
var paramsWord = "parameter";
435+
if (missingParams.length > 1) {
436+
paramsWord = "parameters";
437+
}
438+
439+
return new QueryResult({job: {error: "Missing values for " + missingParams.join(', ') + " "+paramsWord+".", status: 4}});
440+
}
441+
442+
if (parameters !== undefined) {
443+
queryText = Mustache.render(queryText, parameters);
444+
445+
// Need to clear latest results, to make sure we don't used results for different params.
446+
this.latest_query_data = null;
447+
this.latest_query_data_id = null;
448+
}
449+
411450
if (this.latest_query_data && ttl != 0) {
412451
if (!this.queryResult) {
413452
this.queryResult = new QueryResult({'query_result': this.latest_query_data});
@@ -417,14 +456,26 @@
417456
this.queryResult = QueryResult.getById(this.latest_query_data_id);
418457
}
419458
} else if (this.data_source_id) {
420-
this.queryResult = QueryResult.get(this.data_source_id, this.query, ttl);
459+
this.queryResult = QueryResult.get(this.data_source_id, queryText, ttl);
421460
}
422461

423462
return this.queryResult;
424463
};
425464

426465
Query.prototype.getQueryResultPromise = function() {
427466
return this.getQueryResult().toPromise();
467+
};
468+
469+
Query.prototype.getParameters = function() {
470+
var parts = Mustache.parse(this.query);
471+
var parameters = [];
472+
_.each(parts, function(part) {
473+
if (part[0] == 'name') {
474+
parameters.push(part[1]);
475+
}
476+
});
477+
478+
return parameters;
428479
}
429480

430481
return Query;

rd_ui/bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
"bucky": "~0.2.6",
2828
"pace": "~0.5.1",
2929
"angular-ui-select": "0.8.2",
30-
"font-awesome": "~4.2.0"
30+
"font-awesome": "~4.2.0",
31+
"mustache": "~1.0.0"
3132
},
3233
"devDependencies": {
3334
"angular-mocks": "1.2.18",

rd_ui/test/karma.conf.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ module.exports = function(config) {
5555
'app/scripts/ui-bootstrap-tpls-0.5.0.min.js',
5656
'app/bower_components/bucky/bucky.js',
5757
'app/bower_components/pace/pace.js',
58+
'app/bower_components/mustache/mustache.js',
5859

5960
'app/scripts/app.js',
6061
'app/scripts/services/services.js',

0 commit comments

Comments
 (0)