diff --git a/public/app/plugins/datasource/postgres/partials/query.editor.html b/public/app/plugins/datasource/postgres/partials/query.editor.html index 58d2415479a..0c053388034 100644 --- a/public/app/plugins/datasource/postgres/partials/query.editor.html +++ b/public/app/plugins/datasource/postgres/partials/query.editor.html @@ -66,7 +66,7 @@
- +
@@ -83,12 +83,12 @@ + handle-event="ctrl.handleGroupPartEvent(part, $index, $event)">
- +
diff --git a/public/app/plugins/datasource/postgres/postgres_query.ts b/public/app/plugins/datasource/postgres/postgres_query.ts index eb51449dd39..4cd3ddefaa2 100644 --- a/public/app/plugins/datasource/postgres/postgres_query.ts +++ b/public/app/plugins/datasource/postgres/postgres_query.ts @@ -134,14 +134,21 @@ export default class PostgresQuery { let columnName = _.find(column, (g: any) => g.type === 'column'); query = columnName.params[0]; - let aggregate = _.find(column, (g: any) => g.type === 'aggregate'); + let aggregate = _.find(column, (g: any) => g.type === 'aggregate' || g.type === 'percentile'); let special = _.find(column, (g: any) => g.type === 'window'); if (aggregate) { - if (special) { - query = aggregate.params[0] + '(' + query + ' ORDER BY ' + this.target.timeColumn + ')'; - } else { - query = aggregate.params[0] + '(' + query + ')'; + switch (aggregate.type) { + case 'aggregate': + if (special) { + query = aggregate.params[0] + '(' + query + ' ORDER BY ' + this.target.timeColumn + ')'; + } else { + query = aggregate.params[0] + '(' + query + ')'; + } + break; + case 'percentile': + query = aggregate.params[0] + '(' + aggregate.params[1] + ') WITHIN GROUP (ORDER BY ' + query + ')'; + break; } } diff --git a/public/app/plugins/datasource/postgres/query_ctrl.ts b/public/app/plugins/datasource/postgres/query_ctrl.ts index 88ef587037d..0191d46065f 100644 --- a/public/app/plugins/datasource/postgres/query_ctrl.ts +++ b/public/app/plugins/datasource/postgres/query_ctrl.ts @@ -112,6 +112,14 @@ export class PostgresQueryCtrl extends QueryCtrl { { text: 'Variance', value: 'variance' }, ], }, + { + text: 'Ordered-Set Aggregate Functions', + value: 'percentile', + submenu: [ + { text: 'Percentile (continuous)', value: 'percentile_cont' }, + { text: 'Percentile (discrete)', value: 'percentile_disc' }, + ], + }, { text: 'Window Functions', value: 'window', @@ -121,9 +129,9 @@ export class PostgresQueryCtrl extends QueryCtrl { { text: 'Sum', value: 'sum' }, ], }, - { text: 'Alias', value: 'alias' }, - { text: 'Column', value: 'column' }, ]; + this.selectMenu.push({ text: 'Alias', value: 'alias' }); + this.selectMenu.push({ text: 'Column', value: 'column' }); } toggleEditorMode() { @@ -241,15 +249,17 @@ export class PostgresQueryCtrl extends QueryCtrl { }); this.selectParts.push(parts); break; + case 'percentile': + partModel.params.push('0.95'); case 'aggregate': // add group by if no group by yet if (this.target.group.length === 0) { this.addGroup('time', '1m'); } - case 'window': - let index = _.findIndex(selectParts, (p: any) => p.def.type === item.value); - if (index !== -1) { - selectParts[index] = partModel; + let aggIndex = _.findIndex(selectParts, (p: any) => p.def.type === 'aggregate' || p.def.type === 'percentile'); + if (aggIndex !== -1) { + // replace current aggregation + selectParts[aggIndex] = partModel; } else { selectParts.splice(1, 0, partModel); } @@ -257,6 +267,26 @@ export class PostgresQueryCtrl extends QueryCtrl { addAlias = true; } break; + case 'window': + let windowIndex = _.findIndex(selectParts, (p: any) => p.def.type === 'window'); + if (windowIndex !== -1) { + // replace current window function + selectParts[windowIndex] = partModel; + } else { + let aggIndex = _.findIndex( + selectParts, + (p: any) => p.def.type === 'aggregate' || p.def.type === 'percentile' + ); + if (aggIndex !== -1) { + selectParts.splice(aggIndex + 1, 0, partModel); + } else { + selectParts.splice(1, 0, partModel); + } + } + if (!_.find(selectParts, (p: any) => p.def.type === 'alias')) { + addAlias = true; + } + break; case 'alias': addAlias = true; break; @@ -322,7 +352,7 @@ export class PostgresQueryCtrl extends QueryCtrl { } } - onGroupPartEvent(part, index, evt) { + handleGroupPartEvent(part, index, evt) { switch (evt.name) { case 'get-param-options': { return this.datasource @@ -379,7 +409,7 @@ export class PostgresQueryCtrl extends QueryCtrl { // remove aggregations this.selectParts = _.map(this.selectParts, (s: any) => { return _.filter(s, (part: any) => { - if (part.def.type === 'aggregate') { + if (part.def.type === 'aggregate' || part.def.type === 'percentile') { return false; } return true; @@ -436,7 +466,7 @@ export class PostgresQueryCtrl extends QueryCtrl { return this.$q.when(options); } - whereAddAction(part, index) { + addWhereAction(part, index) { switch (this.whereAdd.type) { case 'macro': { this.whereParts.push(sqlPart.create({ type: 'macro', name: this.whereAdd.value, params: [] })); @@ -468,7 +498,7 @@ export class PostgresQueryCtrl extends QueryCtrl { .catch(this.handleQueryError.bind(this)); } - onGroupAction() { + addGroupAction() { switch (this.groupAdd.value) { default: { this.addGroup(this.groupAdd.type, this.groupAdd.value); diff --git a/public/app/plugins/datasource/postgres/sql_part.ts b/public/app/plugins/datasource/postgres/sql_part.ts index 487ddb50276..9cf0bd8f425 100644 --- a/public/app/plugins/datasource/postgres/sql_part.ts +++ b/public/app/plugins/datasource/postgres/sql_part.ts @@ -45,10 +45,35 @@ register({ register({ type: 'aggregate', style: 'label', - params: [{ name: 'name', type: 'string', dynamicLookup: true }], + params: [ + { + name: 'name', + type: 'string', + options: ['avg', 'count', 'min', 'max', 'sum', 'stddev', 'variance'], + }, + ], defaultParams: ['avg'], }); +register({ + type: 'percentile', + label: 'Aggregate:', + style: 'label', + params: [ + { + name: 'name', + type: 'string', + options: ['percentile_cont', 'percentile_disc'], + }, + { + name: 'fraction', + type: 'number', + options: ['0.5', '0.75', '0.9', '0.95', '0.99'], + }, + ], + defaultParams: ['percentile_cont', '0.95'], +}); + register({ type: 'alias', style: 'label',