diff --git a/public/app/plugins/datasource/postgres/partials/query.editor.html b/public/app/plugins/datasource/postgres/partials/query.editor.html
index 400855cf82f..3e921e1c631 100644
--- a/public/app/plugins/datasource/postgres/partials/query.editor.html
+++ b/public/app/plugins/datasource/postgres/partials/query.editor.html
@@ -51,6 +51,27 @@
+
+
diff --git a/public/app/plugins/datasource/postgres/postgres_query.ts b/public/app/plugins/datasource/postgres/postgres_query.ts
index e6d84306a9b..389ce85aae9 100644
--- a/public/app/plugins/datasource/postgres/postgres_query.ts
+++ b/public/app/plugins/datasource/postgres/postgres_query.ts
@@ -22,7 +22,7 @@ export default class PostgresQuery {
target.alias = '';
target.orderByTime = target.orderByTime || 'ASC';
-// target.groupBy = target.groupBy || [{ type: 'time', params: ['$__interval'] }, { type: 'fill', params: ['null'] }];
+ target.groupBy = target.groupBy || [{ type: 'time', params: ['$__interval'] }, { type: 'fill', params: ['null'] }];
target.select = target.select || [[{ type: 'field', params: ['value'] }]];
this.updateProjection();
@@ -92,9 +92,6 @@ export default class PostgresQuery {
if (partModel.def.category === categories.Aggregations) {
return false;
}
- if (partModel.def.category === categories.Selectors) {
- return false;
- }
return true;
});
});
diff --git a/public/app/plugins/datasource/postgres/query_ctrl.ts b/public/app/plugins/datasource/postgres/query_ctrl.ts
index 4e39105370b..020d8007789 100644
--- a/public/app/plugins/datasource/postgres/query_ctrl.ts
+++ b/public/app/plugins/datasource/postgres/query_ctrl.ts
@@ -29,6 +29,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
tableSegment: any;
timeColumnSegment: any;
selectMenu: any;
+ groupBySegment: any;
/** @ngInject **/
constructor($scope, $injector, private templateSrv, private $q, private uiSegmentSrv) {
@@ -59,6 +60,8 @@ export class PostgresQueryCtrl extends QueryCtrl {
this.timeColumnSegment = uiSegmentSrv.newSegment(this.target.timeColumn);
this.buildSelectMenu();
+ this.groupBySegment = this.uiSegmentSrv.newPlusButton();
+
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
}
@@ -224,6 +227,87 @@ export class PostgresQueryCtrl extends QueryCtrl {
}
}
+ handleGroupByPartEvent(part, index, evt) {
+ switch (evt.name) {
+ case 'get-param-options': {
+ var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
+ columnQuery += " table_schema = '" + this.target.schema + "'";
+ columnQuery += " AND table_name = '" + this.target.table + "'";
+
+ return this.datasource
+ .metricFindQuery(columnQuery)
+ .then(this.transformToSegments(true))
+ .catch(this.handleQueryError.bind(this));
+ }
+ case 'part-param-changed': {
+ this.panelCtrl.refresh();
+ break;
+ }
+ case 'action': {
+ this.queryModel.removeGroupByPart(part, index);
+ this.panelCtrl.refresh();
+ break;
+ }
+ case 'get-part-actions': {
+ return this.$q.when([{ text: 'Remove', value: 'remove-part' }]);
+ }
+ }
+ }
+
+ getGroupByOptions() {
+ var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
+ columnQuery += " table_schema = '" + this.target.schema + "'";
+ columnQuery += " AND table_name = '" + this.target.table + "'";
+
+
+ return this.datasource
+ .metricFindQuery(columnQuery)
+ .then(tags => {
+ var options = [];
+ if (!this.queryModel.hasFill()) {
+ options.push(this.uiSegmentSrv.newSegment({ value: 'fill(null)' }));
+ }
+ if (!this.target.limit) {
+ options.push(this.uiSegmentSrv.newSegment({ value: 'LIMIT' }));
+ }
+ if (!this.target.slimit) {
+ options.push(this.uiSegmentSrv.newSegment({ value: 'SLIMIT' }));
+ }
+ if (this.target.orderByTime === 'ASC') {
+ options.push(this.uiSegmentSrv.newSegment({ value: 'ORDER BY time DESC' }));
+ }
+ if (!this.queryModel.hasGroupByTime()) {
+ options.push(this.uiSegmentSrv.newSegment({ value: 'time($interval)' }));
+ }
+ for (let tag of tags) {
+ options.push(this.uiSegmentSrv.newSegment({ value: 'tag(' + tag.text + ')' }));
+ }
+ return options;
+ })
+ .catch(this.handleQueryError.bind(this));
+ }
+
+ groupByAction() {
+ switch (this.groupBySegment.value) {
+ case 'LIMIT': {
+ this.target.limit = 10;
+ break;
+ }
+ case 'ORDER BY time DESC': {
+ this.target.orderByTime = 'DESC';
+ break;
+ }
+ default: {
+ this.queryModel.addGroupBy(this.groupBySegment.value);
+ }
+ }
+
+ var plusButton = this.uiSegmentSrv.newPlusButton();
+ this.groupBySegment.value = plusButton.value;
+ this.groupBySegment.html = plusButton.html;
+ this.panelCtrl.refresh();
+ }
+
handleQueryError(err) {
this.error = err.message || 'Failed to issue metric query';
return [];
diff --git a/public/app/plugins/datasource/postgres/query_part.ts b/public/app/plugins/datasource/postgres/query_part.ts
index dffea15dbd1..5828515ec06 100644
--- a/public/app/plugins/datasource/postgres/query_part.ts
+++ b/public/app/plugins/datasource/postgres/query_part.ts
@@ -4,9 +4,6 @@ import { QueryPartDef, QueryPart, functionRenderer, suffixRenderer } from 'app/c
var index = [];
var categories = {
Aggregations: [],
- Selectors: [],
- Transformations: [],
- Predictors: [],
Math: [],
Aliasing: [],
Fields: [],
@@ -44,10 +41,6 @@ function replaceAggregationAddStrategy(selectParts, partModel) {
selectParts[i] = partModel;
return;
}
- if (part.def.category === categories.Selectors) {
- selectParts[i] = partModel;
- return;
- }
}
selectParts.splice(1, 0, partModel);
@@ -147,34 +140,10 @@ register({
// transformations
-register({
- type: 'derivative',
- addStrategy: addTransformationStrategy,
- category: categories.Transformations,
- params: [
- {
- name: 'duration',
- type: 'interval',
- options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h'],
- },
- ],
- defaultParams: ['10s'],
- renderer: functionRenderer,
-});
-
-register({
- type: 'spread',
- addStrategy: addTransformationStrategy,
- category: categories.Transformations,
- params: [],
- defaultParams: [],
- renderer: functionRenderer,
-});
-
register({
type: 'non_negative_derivative',
addStrategy: addTransformationStrategy,
- category: categories.Transformations,
+ category: categories.Aggregations,
params: [
{
name: 'duration',
@@ -186,46 +155,10 @@ register({
renderer: functionRenderer,
});
-register({
- type: 'difference',
- addStrategy: addTransformationStrategy,
- category: categories.Transformations,
- params: [],
- defaultParams: [],
- renderer: functionRenderer,
-});
-
-register({
- type: 'non_negative_difference',
- addStrategy: addTransformationStrategy,
- category: categories.Transformations,
- params: [],
- defaultParams: [],
- renderer: functionRenderer,
-});
-
-register({
- type: 'moving_average',
- addStrategy: addTransformationStrategy,
- category: categories.Transformations,
- params: [{ name: 'window', type: 'int', options: [5, 10, 20, 30, 40] }],
- defaultParams: [10],
- renderer: functionRenderer,
-});
-
-register({
- type: 'cumulative_sum',
- addStrategy: addTransformationStrategy,
- category: categories.Transformations,
- params: [],
- defaultParams: [],
- renderer: functionRenderer,
-});
-
register({
type: 'stddev',
addStrategy: addTransformationStrategy,
- category: categories.Transformations,
+ category: categories.Aggregations,
params: [],
defaultParams: [],
renderer: functionRenderer,
@@ -259,60 +192,11 @@ register({
renderer: functionRenderer,
});
-register({
- type: 'elapsed',
- addStrategy: addTransformationStrategy,
- category: categories.Transformations,
- params: [
- {
- name: 'duration',
- type: 'interval',
- options: ['1s', '10s', '1m', '5m', '10m', '15m', '1h'],
- },
- ],
- defaultParams: ['10s'],
- renderer: functionRenderer,
-});
-
-// predictions
-register({
- type: 'holt_winters',
- addStrategy: addTransformationStrategy,
- category: categories.Predictors,
- params: [
- { name: 'number', type: 'int', options: [5, 10, 20, 30, 40] },
- { name: 'season', type: 'int', options: [0, 1, 2, 5, 10] },
- ],
- defaultParams: [10, 2],
- renderer: functionRenderer,
-});
-
-register({
- type: 'holt_winters_with_fit',
- addStrategy: addTransformationStrategy,
- category: categories.Predictors,
- params: [
- { name: 'number', type: 'int', options: [5, 10, 20, 30, 40] },
- { name: 'season', type: 'int', options: [0, 1, 2, 5, 10] },
- ],
- defaultParams: [10, 2],
- renderer: functionRenderer,
-});
-
// Selectors
-register({
- type: 'bottom',
- addStrategy: replaceAggregationAddStrategy,
- category: categories.Selectors,
- params: [{ name: 'count', type: 'int' }],
- defaultParams: [3],
- renderer: functionRenderer,
-});
-
register({
type: 'max',
addStrategy: replaceAggregationAddStrategy,
- category: categories.Selectors,
+ category: categories.Aggregations,
params: [],
defaultParams: [],
renderer: functionRenderer,
@@ -321,38 +205,12 @@ register({
register({
type: 'min',
addStrategy: replaceAggregationAddStrategy,
- category: categories.Selectors,
+ category: categories.Aggregations,
params: [],
defaultParams: [],
renderer: functionRenderer,
});
-register({
- type: 'percentile',
- addStrategy: replaceAggregationAddStrategy,
- category: categories.Selectors,
- params: [{ name: 'nth', type: 'int' }],
- defaultParams: [95],
- renderer: functionRenderer,
-});
-
-register({
- type: 'top',
- addStrategy: replaceAggregationAddStrategy,
- category: categories.Selectors,
- params: [{ name: 'count', type: 'int' }],
- defaultParams: [3],
- renderer: functionRenderer,
-});
-
-register({
- type: 'tag',
- category: groupByTimeFunctions,
- params: [{ name: 'tag', type: 'string', dynamicLookup: true }],
- defaultParams: ['tag'],
- renderer: fieldRenderer,
-});
-
register({
type: 'math',
addStrategy: addMathStrategy,