|
@@ -1,12 +1,7 @@
|
|
|
import _ from 'lodash';
|
|
import _ from 'lodash';
|
|
|
import { QueryCtrl } from 'app/plugins/sdk';
|
|
import { QueryCtrl } from 'app/plugins/sdk';
|
|
|
-
|
|
|
|
|
-export interface PostgresQuery {
|
|
|
|
|
- refId: string;
|
|
|
|
|
- format: string;
|
|
|
|
|
- alias: string;
|
|
|
|
|
- rawSql: string;
|
|
|
|
|
-}
|
|
|
|
|
|
|
+import queryPart from './query_part';
|
|
|
|
|
+import PostgresQuery from './postgres_query';
|
|
|
|
|
|
|
|
export interface QueryMeta {
|
|
export interface QueryMeta {
|
|
|
sql: string;
|
|
sql: string;
|
|
@@ -26,17 +21,21 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|
|
|
|
|
|
|
showLastQuerySQL: boolean;
|
|
showLastQuerySQL: boolean;
|
|
|
formats: any[];
|
|
formats: any[];
|
|
|
- target: PostgresQuery;
|
|
|
|
|
|
|
+ queryModel: PostgresQuery;
|
|
|
lastQueryMeta: QueryMeta;
|
|
lastQueryMeta: QueryMeta;
|
|
|
lastQueryError: string;
|
|
lastQueryError: string;
|
|
|
showHelp: boolean;
|
|
showHelp: boolean;
|
|
|
|
|
+ schemaSegment: any;
|
|
|
|
|
+ tableSegment: any;
|
|
|
|
|
+ timeColumnSegment: any;
|
|
|
|
|
+ selectMenu: any;
|
|
|
|
|
|
|
|
/** @ngInject **/
|
|
/** @ngInject **/
|
|
|
- constructor($scope, $injector) {
|
|
|
|
|
|
|
+ constructor($scope, $injector, private templateSrv, private $q, private uiSegmentSrv) {
|
|
|
super($scope, $injector);
|
|
super($scope, $injector);
|
|
|
|
|
+ this.target = this.target;
|
|
|
|
|
+ this.queryModel = new PostgresQuery(this.target, templateSrv, this.panel.scopedVars);
|
|
|
|
|
|
|
|
- this.target.format = this.target.format || 'time_series';
|
|
|
|
|
- this.target.alias = '';
|
|
|
|
|
this.formats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
|
|
this.formats = [{ text: 'Time series', value: 'time_series' }, { text: 'Table', value: 'table' }];
|
|
|
|
|
|
|
|
if (!this.target.rawSql) {
|
|
if (!this.target.rawSql) {
|
|
@@ -49,10 +48,104 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ this.schemaSegment= uiSegmentSrv.newSegment(this.target.schema);
|
|
|
|
|
+
|
|
|
|
|
+ if (!this.target.table) {
|
|
|
|
|
+ this.tableSegment = uiSegmentSrv.newSegment({value: 'select table',fake: true});
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.tableSegment= uiSegmentSrv.newSegment(this.target.table);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ this.timeColumnSegment = uiSegmentSrv.newSegment(this.target.timeColumn);
|
|
|
|
|
+
|
|
|
|
|
+ this.buildSelectMenu();
|
|
|
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
|
|
this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
|
|
|
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
|
|
this.panelCtrl.events.on('data-error', this.onDataError.bind(this), $scope);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ buildSelectMenu() {
|
|
|
|
|
+ var categories = queryPart.getCategories();
|
|
|
|
|
+ this.selectMenu = _.reduce(
|
|
|
|
|
+ categories,
|
|
|
|
|
+ function(memo, cat, key) {
|
|
|
|
|
+ var menu = {
|
|
|
|
|
+ text: key,
|
|
|
|
|
+ submenu: cat.map(item => {
|
|
|
|
|
+ return { text: item.type, value: item.type };
|
|
|
|
|
+ }),
|
|
|
|
|
+ };
|
|
|
|
|
+ memo.push(menu);
|
|
|
|
|
+ return memo;
|
|
|
|
|
+ },
|
|
|
|
|
+ []
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ toggleEditorMode() {
|
|
|
|
|
+ try {
|
|
|
|
|
+// this.target.query = this.queryModel.render(false);
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ console.log('query render error');
|
|
|
|
|
+ }
|
|
|
|
|
+ this.target.rawQuery = !this.target.rawQuery;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getSchemaSegments() {
|
|
|
|
|
+ var schemaQuery = "SELECT schema_name FROM information_schema.schemata WHERE";
|
|
|
|
|
+ schemaQuery += " schema_name NOT LIKE 'pg_%' AND schema_name <> 'information_schema';";
|
|
|
|
|
+ return this.datasource
|
|
|
|
|
+ .metricFindQuery(schemaQuery)
|
|
|
|
|
+ .then(this.transformToSegments(true))
|
|
|
|
|
+ .catch(this.handleQueryError.bind(this));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getTableSegments() {
|
|
|
|
|
+ var tableQuery = "SELECT table_name FROM information_schema.tables WHERE table_schema = '" + this.target.schema + "';";
|
|
|
|
|
+ return this.datasource
|
|
|
|
|
+ .metricFindQuery(tableQuery)
|
|
|
|
|
+ .then(this.transformToSegments(true))
|
|
|
|
|
+ .catch(this.handleQueryError.bind(this));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getTimeColumnSegments() {
|
|
|
|
|
+ var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
|
|
|
|
|
+ columnQuery += " table_schema = '" + this.target.schema + "'";
|
|
|
|
|
+ columnQuery += " AND table_name = '" + this.target.table + "'";
|
|
|
|
|
+ columnQuery += " AND data_type IN ('timestamp without time zone','timestamp with time zone','bigint','integer','double precision','real');";
|
|
|
|
|
+
|
|
|
|
|
+ return this.datasource
|
|
|
|
|
+ .metricFindQuery(columnQuery)
|
|
|
|
|
+ .then(this.transformToSegments(true))
|
|
|
|
|
+ .catch(this.handleQueryError.bind(this));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getColumnSegments() {
|
|
|
|
|
+ var columnQuery = "SELECT column_name FROM information_schema.columns WHERE ";
|
|
|
|
|
+ columnQuery += " table_schema = '" + this.target.schema + "'";
|
|
|
|
|
+ columnQuery += " AND table_name = '" + this.target.table + "'";
|
|
|
|
|
+ columnQuery += " AND data_type IN ('bigint','integer','double precision','real');";
|
|
|
|
|
+
|
|
|
|
|
+ return this.datasource
|
|
|
|
|
+ .metricFindQuery(columnQuery)
|
|
|
|
|
+ .then(this.transformToSegments(true))
|
|
|
|
|
+ .catch(this.handleQueryError.bind(this));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ tableChanged() {
|
|
|
|
|
+ this.target.table = this.tableSegment.value;
|
|
|
|
|
+ this.panelCtrl.refresh();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ schemaChanged() {
|
|
|
|
|
+ this.target.schema = this.schemaSegment.value;
|
|
|
|
|
+ this.panelCtrl.refresh();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ timeColumnChanged() {
|
|
|
|
|
+ this.target.time = this.timeColumnSegment.value;
|
|
|
|
|
+ this.panelCtrl.refresh();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
onDataReceived(dataList) {
|
|
onDataReceived(dataList) {
|
|
|
this.lastQueryMeta = null;
|
|
this.lastQueryMeta = null;
|
|
|
this.lastQueryError = null;
|
|
this.lastQueryError = null;
|
|
@@ -72,4 +165,68 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ transformToSegments(addTemplateVars) {
|
|
|
|
|
+ return results => {
|
|
|
|
|
+ var segments = _.map(results, segment => {
|
|
|
|
|
+ return this.uiSegmentSrv.newSegment({
|
|
|
|
|
+ value: segment.text,
|
|
|
|
|
+ expandable: segment.expandable,
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (addTemplateVars) {
|
|
|
|
|
+ for (let variable of this.templateSrv.variables) {
|
|
|
|
|
+ segments.unshift(
|
|
|
|
|
+ this.uiSegmentSrv.newSegment({
|
|
|
|
|
+ type: 'template',
|
|
|
|
|
+ value: '/^$' + variable.name + '$/',
|
|
|
|
|
+ expandable: true,
|
|
|
|
|
+ })
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return segments;
|
|
|
|
|
+ };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ addSelectPart(selectParts, cat, subitem) {
|
|
|
|
|
+ this.queryModel.addSelectPart(selectParts, subitem.value);
|
|
|
|
|
+ this.panelCtrl.refresh();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ handleSelectPartEvent(selectParts, part, 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 + "'";
|
|
|
|
|
+ columnQuery += " AND data_type IN ('bigint','integer','double precision','real');";
|
|
|
|
|
+
|
|
|
|
|
+ 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.removeSelectPart(selectParts, part);
|
|
|
|
|
+ this.panelCtrl.refresh();
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ case 'get-part-actions': {
|
|
|
|
|
+ return this.$q.when([{ text: 'Remove', value: 'remove-part' }]);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ handleQueryError(err) {
|
|
|
|
|
+ this.error = err.message || 'Failed to issue metric query';
|
|
|
|
|
+ return [];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|