mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
refactor PostgresQueryCtrl and PostgresQuery
This commit is contained in:
parent
2dc9d4e960
commit
d7ed706e12
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form-inline" ng-repeat="selectParts in ctrl.queryModel.selectModels">
|
<div class="gf-form-inline" ng-repeat="selectParts in ctrl.selectModels">
|
||||||
<div class="gf-form">
|
<div class="gf-form">
|
||||||
<label class="gf-form-label query-keyword width-6">
|
<label class="gf-form-label query-keyword width-6">
|
||||||
<span ng-show="$index === 0">SELECT</span>
|
<span ng-show="$index === 0">SELECT</span>
|
||||||
@ -58,8 +58,8 @@
|
|||||||
<label class="gf-form-label query-keyword width-6">WHERE</label>
|
<label class="gf-form-label query-keyword width-6">WHERE</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="gf-form" ng-repeat="part in ctrl.queryModel.whereParts">
|
<div class="gf-form" ng-repeat="part in ctrl.whereParts">
|
||||||
<sql-part-editor class="gf-form-label sql-part" part="part" handle-event="ctrl.handleWherePartEvent(ctrl.queryModel.whereParts, part, $event, $index)">
|
<sql-part-editor class="gf-form-label sql-part" part="part" handle-event="ctrl.handleWherePartEvent(ctrl.whereParts, part, $event, $index)">
|
||||||
</sql-part-editor>
|
</sql-part-editor>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -79,7 +79,7 @@
|
|||||||
<span>GROUP BY</span>
|
<span>GROUP BY</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<sql-part-editor ng-repeat="part in ctrl.queryModel.groupByParts"
|
<sql-part-editor ng-repeat="part in ctrl.groupByParts"
|
||||||
part="part" class="gf-form-label sql-part"
|
part="part" class="gf-form-label sql-part"
|
||||||
handle-event="ctrl.handleGroupByPartEvent(part, $index, $event)">
|
handle-event="ctrl.handleGroupByPartEvent(part, $index, $event)">
|
||||||
</sql-part-editor>
|
</sql-part-editor>
|
||||||
|
@ -1,12 +1,8 @@
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import sqlPart from './sql_part';
|
|
||||||
|
|
||||||
export default class PostgresQuery {
|
export default class PostgresQuery {
|
||||||
target: any;
|
target: any;
|
||||||
selectModels: any[];
|
|
||||||
queryBuilder: any;
|
queryBuilder: any;
|
||||||
groupByParts: any[];
|
|
||||||
whereParts: any[];
|
|
||||||
templateSrv: any;
|
templateSrv: any;
|
||||||
scopedVars: any;
|
scopedVars: any;
|
||||||
|
|
||||||
@ -38,8 +34,6 @@ export default class PostgresQuery {
|
|||||||
|
|
||||||
// give interpolateQueryStr access to this
|
// give interpolateQueryStr access to this
|
||||||
this.interpolateQueryStr = this.interpolateQueryStr.bind(this);
|
this.interpolateQueryStr = this.interpolateQueryStr.bind(this);
|
||||||
|
|
||||||
this.updateProjection();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove identifier quoting from identifier to use in metadata queries
|
// remove identifier quoting from identifier to use in metadata queries
|
||||||
@ -59,100 +53,10 @@ export default class PostgresQuery {
|
|||||||
return "'" + value.replace("'", "''") + "'";
|
return "'" + value.replace("'", "''") + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
updateProjection() {
|
|
||||||
this.selectModels = _.map(this.target.select, function(parts: any) {
|
|
||||||
return _.map(parts, sqlPart.create).filter(n => n);
|
|
||||||
});
|
|
||||||
this.whereParts = _.map(this.target.where, sqlPart.create).filter(n => n);
|
|
||||||
this.groupByParts = _.map(this.target.groupBy, sqlPart.create).filter(n => n);
|
|
||||||
}
|
|
||||||
|
|
||||||
updatePersistedParts() {
|
|
||||||
this.target.select = _.map(this.selectModels, function(selectParts) {
|
|
||||||
return _.map(selectParts, function(part: any) {
|
|
||||||
return { type: part.def.type, params: part.params };
|
|
||||||
});
|
|
||||||
});
|
|
||||||
this.target.where = _.map(this.whereParts, function(part: any) {
|
|
||||||
return { type: part.def.type, name: part.name, params: part.params };
|
|
||||||
});
|
|
||||||
this.target.groupBy = _.map(this.groupByParts, function(part: any) {
|
|
||||||
return { type: part.def.type, params: part.params };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
hasGroupByTime() {
|
hasGroupByTime() {
|
||||||
return _.find(this.target.groupBy, (g: any) => g.type === 'time');
|
return _.find(this.target.groupBy, (g: any) => g.type === 'time');
|
||||||
}
|
}
|
||||||
|
|
||||||
addGroupBy(partType, value) {
|
|
||||||
let params = [value];
|
|
||||||
if (partType === 'time') {
|
|
||||||
params = ['1m', 'none'];
|
|
||||||
}
|
|
||||||
let partModel = sqlPart.create({ type: partType, params: params });
|
|
||||||
|
|
||||||
if (partType === 'time') {
|
|
||||||
// put timeGroup at start
|
|
||||||
this.groupByParts.splice(0, 0, partModel);
|
|
||||||
} else {
|
|
||||||
this.groupByParts(partModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add aggregates when adding group by
|
|
||||||
for (let i = 0; i < this.selectModels.length; i++) {
|
|
||||||
var selectParts = this.selectModels[i];
|
|
||||||
if (!selectParts.some(part => part.def.type === 'aggregate')) {
|
|
||||||
let aggregate = sqlPart.create({ type: 'aggregate', params: ['avg'] });
|
|
||||||
selectParts.splice(1, 0, aggregate);
|
|
||||||
if (!selectParts.some(part => part.def.type === 'alias')) {
|
|
||||||
let alias = sqlPart.create({ type: 'alias', params: [selectParts[0].part.params[0]] });
|
|
||||||
selectParts.push(alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updatePersistedParts();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeGroupByPart(part, index) {
|
|
||||||
if (part.def.type === 'time') {
|
|
||||||
// remove aggregations
|
|
||||||
this.selectModels = _.map(this.selectModels, (s: any) => {
|
|
||||||
return _.filter(s, (part: any) => {
|
|
||||||
if (part.def.type === 'aggregate') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
this.groupByParts.splice(index, 1);
|
|
||||||
this.updatePersistedParts();
|
|
||||||
}
|
|
||||||
|
|
||||||
removeSelectPart(selectParts, part) {
|
|
||||||
// if we remove the field remove the whole statement
|
|
||||||
if (part.def.type === 'column') {
|
|
||||||
if (this.selectModels.length > 1) {
|
|
||||||
let modelsIndex = _.indexOf(this.selectModels, selectParts);
|
|
||||||
this.selectModels.splice(modelsIndex, 1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let partIndex = _.indexOf(selectParts, part);
|
|
||||||
selectParts.splice(partIndex, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.updatePersistedParts();
|
|
||||||
}
|
|
||||||
|
|
||||||
addSelectPart(selectParts, type) {
|
|
||||||
let partModel = sqlPart.create({ type: type });
|
|
||||||
partModel.def.addStrategy(selectParts, partModel, this);
|
|
||||||
this.updatePersistedParts();
|
|
||||||
}
|
|
||||||
|
|
||||||
interpolateQueryStr(value, variable, defaultFormatFn) {
|
interpolateQueryStr(value, variable, defaultFormatFn) {
|
||||||
// if no multi or include all do not regexEscape
|
// if no multi or include all do not regexEscape
|
||||||
if (!variable.multi && !variable.includeAll) {
|
if (!variable.multi && !variable.includeAll) {
|
||||||
|
@ -33,6 +33,9 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
timeColumnSegment: any;
|
timeColumnSegment: any;
|
||||||
metricColumnSegment: any;
|
metricColumnSegment: any;
|
||||||
selectMenu: any;
|
selectMenu: any;
|
||||||
|
selectModels: any[];
|
||||||
|
groupByParts: any[];
|
||||||
|
whereParts: any[];
|
||||||
groupByAdd: any;
|
groupByAdd: any;
|
||||||
|
|
||||||
/** @ngInject **/
|
/** @ngInject **/
|
||||||
@ -41,6 +44,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
this.target = this.target;
|
this.target = this.target;
|
||||||
this.queryModel = new PostgresQuery(this.target, templateSrv, this.panel.scopedVars);
|
this.queryModel = new PostgresQuery(this.target, templateSrv, this.panel.scopedVars);
|
||||||
this.queryBuilder = new PostgresQueryBuilder(this.target, this.queryModel);
|
this.queryBuilder = new PostgresQueryBuilder(this.target, this.queryModel);
|
||||||
|
this.updateProjection();
|
||||||
|
|
||||||
this.formats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
|
this.formats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
|
||||||
|
|
||||||
@ -66,7 +70,6 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
this.metricColumnSegment = uiSegmentSrv.newSegment(this.target.metricColumn);
|
this.metricColumnSegment = uiSegmentSrv.newSegment(this.target.metricColumn);
|
||||||
|
|
||||||
this.buildSelectMenu();
|
this.buildSelectMenu();
|
||||||
this.buildWhereSegments();
|
|
||||||
this.whereAdd = this.uiSegmentSrv.newPlusButton();
|
this.whereAdd = this.uiSegmentSrv.newPlusButton();
|
||||||
this.groupByAdd = this.uiSegmentSrv.newPlusButton();
|
this.groupByAdd = this.uiSegmentSrv.newPlusButton();
|
||||||
|
|
||||||
@ -74,10 +77,31 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
|
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateProjection() {
|
||||||
|
this.selectModels = _.map(this.target.select, function(parts: any) {
|
||||||
|
return _.map(parts, sqlPart.create).filter(n => n);
|
||||||
|
});
|
||||||
|
this.whereParts = _.map(this.target.where, sqlPart.create).filter(n => n);
|
||||||
|
this.groupByParts = _.map(this.target.groupBy, sqlPart.create).filter(n => n);
|
||||||
|
}
|
||||||
|
|
||||||
|
updatePersistedParts() {
|
||||||
|
this.target.select = _.map(this.selectModels, function(selectParts) {
|
||||||
|
return _.map(selectParts, function(part: any) {
|
||||||
|
return { type: part.def.type, params: part.params };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.target.where = _.map(this.whereParts, function(part: any) {
|
||||||
|
return { type: part.def.type, name: part.name, params: part.params };
|
||||||
|
});
|
||||||
|
this.target.groupBy = _.map(this.groupByParts, function(part: any) {
|
||||||
|
return { type: part.def.type, params: part.params };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
buildSelectMenu() {
|
buildSelectMenu() {
|
||||||
this.selectMenu = [
|
this.selectMenu = [
|
||||||
{ text: 'Aggregate', value: 'aggregate' },
|
{ text: 'Aggregate', value: 'aggregate' },
|
||||||
{ text: 'Math', value: 'math' },
|
|
||||||
{ text: 'Special', value: 'special' },
|
{ text: 'Special', value: 'special' },
|
||||||
{ text: 'Alias', value: 'alias' },
|
{ text: 'Alias', value: 'alias' },
|
||||||
{ text: 'Column', value: 'column' },
|
{ text: 'Column', value: 'column' },
|
||||||
@ -88,6 +112,10 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
this.target.rawQuery = !this.target.rawQuery;
|
this.target.rawQuery = !this.target.rawQuery;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetPlusButton(button) {}
|
||||||
|
|
||||||
|
// schema functions
|
||||||
|
|
||||||
getSchemaSegments() {
|
getSchemaSegments() {
|
||||||
return this.datasource
|
return this.datasource
|
||||||
.metricFindQuery(this.queryBuilder.buildSchemaQuery())
|
.metricFindQuery(this.queryBuilder.buildSchemaQuery())
|
||||||
@ -95,6 +123,13 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
.catch(this.handleQueryError.bind(this));
|
.catch(this.handleQueryError.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
schemaChanged() {
|
||||||
|
this.target.schema = this.schemaSegment.value;
|
||||||
|
this.panelCtrl.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// table functions
|
||||||
|
|
||||||
getTableSegments() {
|
getTableSegments() {
|
||||||
return this.datasource
|
return this.datasource
|
||||||
.metricFindQuery(this.queryBuilder.buildTableQuery())
|
.metricFindQuery(this.queryBuilder.buildTableQuery())
|
||||||
@ -121,11 +156,6 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
schemaChanged() {
|
|
||||||
this.target.schema = this.schemaSegment.value;
|
|
||||||
this.panelCtrl.refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
timeColumnChanged() {
|
timeColumnChanged() {
|
||||||
this.target.timeColumn = this.timeColumnSegment.value;
|
this.target.timeColumn = this.timeColumnSegment.value;
|
||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
@ -193,13 +223,34 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
|
|
||||||
addSelectPart(selectParts, cat, subitem) {
|
addSelectPart(selectParts, cat, subitem) {
|
||||||
if ('submenu' in cat) {
|
if ('submenu' in cat) {
|
||||||
this.queryModel.addSelectPart(selectParts, subitem.value);
|
this.addSelectPart2(selectParts, subitem.value);
|
||||||
} else {
|
} else {
|
||||||
this.queryModel.addSelectPart(selectParts, cat.value);
|
this.addSelectPart2(selectParts, cat.value);
|
||||||
}
|
}
|
||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeSelectPart(selectParts, part) {
|
||||||
|
// if we remove the field remove the whole statement
|
||||||
|
if (part.def.type === 'column') {
|
||||||
|
if (this.selectModels.length > 1) {
|
||||||
|
let modelsIndex = _.indexOf(this.selectModels, selectParts);
|
||||||
|
this.selectModels.splice(modelsIndex, 1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let partIndex = _.indexOf(selectParts, part);
|
||||||
|
selectParts.splice(partIndex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updatePersistedParts();
|
||||||
|
}
|
||||||
|
|
||||||
|
addSelectPart2(selectParts, type) {
|
||||||
|
let partModel = sqlPart.create({ type: type });
|
||||||
|
partModel.def.addStrategy(selectParts, partModel, this);
|
||||||
|
this.updatePersistedParts();
|
||||||
|
}
|
||||||
|
|
||||||
handleSelectPartEvent(selectParts, part, evt) {
|
handleSelectPartEvent(selectParts, part, evt) {
|
||||||
switch (evt.name) {
|
switch (evt.name) {
|
||||||
case 'get-param-options': {
|
case 'get-param-options': {
|
||||||
@ -221,7 +272,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'action': {
|
case 'action': {
|
||||||
this.queryModel.removeSelectPart(selectParts, part);
|
this.removeSelectPart(selectParts, part);
|
||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -244,7 +295,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'action': {
|
case 'action': {
|
||||||
this.queryModel.removeGroupByPart(part, index);
|
this.removeGroupBy(part, index);
|
||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -254,6 +305,53 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addGroupBy(partType, value) {
|
||||||
|
let params = [value];
|
||||||
|
if (partType === 'time') {
|
||||||
|
params = ['1m', 'none'];
|
||||||
|
}
|
||||||
|
let partModel = sqlPart.create({ type: partType, params: params });
|
||||||
|
|
||||||
|
if (partType === 'time') {
|
||||||
|
// put timeGroup at start
|
||||||
|
this.groupByParts.splice(0, 0, partModel);
|
||||||
|
} else {
|
||||||
|
this.groupByParts.push(partModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add aggregates when adding group by
|
||||||
|
for (let i = 0; i < this.selectModels.length; i++) {
|
||||||
|
var selectParts = this.selectModels[i];
|
||||||
|
if (!selectParts.some(part => part.def.type === 'aggregate')) {
|
||||||
|
let aggregate = sqlPart.create({ type: 'aggregate', params: ['avg'] });
|
||||||
|
selectParts.splice(1, 0, aggregate);
|
||||||
|
if (!selectParts.some(part => part.def.type === 'alias')) {
|
||||||
|
let alias = sqlPart.create({ type: 'alias', params: [selectParts[0].part.params[0]] });
|
||||||
|
selectParts.push(alias);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updatePersistedParts();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeGroupBy(part, index) {
|
||||||
|
if (part.def.type === 'time') {
|
||||||
|
// remove aggregations
|
||||||
|
this.selectModels = _.map(this.selectModels, (s: any) => {
|
||||||
|
return _.filter(s, (part: any) => {
|
||||||
|
if (part.def.type === 'aggregate') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.groupByParts.splice(index, 1);
|
||||||
|
this.updatePersistedParts();
|
||||||
|
}
|
||||||
|
|
||||||
buildWhereSegments() {
|
buildWhereSegments() {
|
||||||
// this.whereSegments = [];
|
// this.whereSegments = [];
|
||||||
// this.whereSegments.push(sqlPart.create({ type: 'expression', params: ['value', '=', 'value'] }));
|
// this.whereSegments.push(sqlPart.create({ type: 'expression', params: ['value', '=', 'value'] }));
|
||||||
@ -286,7 +384,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
case 'action': {
|
case 'action': {
|
||||||
// remove element
|
// remove element
|
||||||
whereParts.splice(index, 1);
|
whereParts.splice(index, 1);
|
||||||
this.queryModel.updatePersistedParts();
|
this.updatePersistedParts();
|
||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -307,11 +405,11 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
whereAddAction(part, index) {
|
whereAddAction(part, index) {
|
||||||
switch (this.whereAdd.type) {
|
switch (this.whereAdd.type) {
|
||||||
case 'macro': {
|
case 'macro': {
|
||||||
this.queryModel.whereParts.push(sqlPart.create({ type: 'macro', name: this.whereAdd.value, params: [] }));
|
this.whereParts.push(sqlPart.create({ type: 'macro', name: this.whereAdd.value, params: [] }));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
this.queryModel.whereParts.push(sqlPart.create({ type: 'expression', params: ['value', '=', 'value'] }));
|
this.whereParts.push(sqlPart.create({ type: 'expression', params: ['value', '=', 'value'] }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -319,7 +417,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
this.whereAdd.html = plusButton.html;
|
this.whereAdd.html = plusButton.html;
|
||||||
this.whereAdd.value = plusButton.value;
|
this.whereAdd.value = plusButton.value;
|
||||||
|
|
||||||
this.queryModel.updatePersistedParts();
|
this.updatePersistedParts();
|
||||||
this.panelCtrl.refresh();
|
this.panelCtrl.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -342,7 +440,7 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|||||||
groupByAction() {
|
groupByAction() {
|
||||||
switch (this.groupByAdd.value) {
|
switch (this.groupByAdd.value) {
|
||||||
default: {
|
default: {
|
||||||
this.queryModel.addGroupBy(this.groupByAdd.type, this.groupByAdd.value);
|
this.addGroupBy(this.groupByAdd.type, this.groupByAdd.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user