Commit e4672906 by Torkel Ödegaard Committed by GitHub

SqlDataSources: Fixes the Show Generated SQL button in query editors (#31236)

* SqlDataSources: Fixes the Show Generated SQL button in query editors

* No need to protect against duplicate events now that the event emitter is isolated for each editor
parent 06e6bcf0
...@@ -126,14 +126,16 @@ export class QueryEditorRow extends PureComponent<Props, State> { ...@@ -126,14 +126,16 @@ export class QueryEditorRow extends PureComponent<Props, State> {
const { data, query } = this.props; const { data, query } = this.props;
if (data !== prevProps.data) { if (data !== prevProps.data) {
this.setState({ data: filterPanelDataToQuery(data, query.refId) }); const dataFilteredByRefId = filterPanelDataToQuery(data, query.refId);
this.setState({ data: dataFilteredByRefId });
if (this.angularScope) { if (this.angularScope) {
this.angularScope.range = getTimeSrv().timeRange(); this.angularScope.range = getTimeSrv().timeRange();
} }
if (this.angularQueryEditor) { if (this.angularQueryEditor && dataFilteredByRefId) {
notifyAngularQueryEditorsOfData(this.angularScope!, data, this.angularQueryEditor); notifyAngularQueryEditorsOfData(this.angularScope!, dataFilteredByRefId, this.angularQueryEditor);
} }
} }
...@@ -353,17 +355,7 @@ export class QueryEditorRow extends PureComponent<Props, State> { ...@@ -353,17 +355,7 @@ export class QueryEditorRow extends PureComponent<Props, State> {
} }
} }
// To avoid sending duplicate events for each row we have this global cached object here
// So we can check if we already emitted this legacy data event
let globalLastPanelDataCache: PanelData | null = null;
function notifyAngularQueryEditorsOfData(scope: AngularQueryComponentScope, data: PanelData, editor: AngularComponent) { function notifyAngularQueryEditorsOfData(scope: AngularQueryComponentScope, data: PanelData, editor: AngularComponent) {
if (data === globalLastPanelDataCache) {
return;
}
globalLastPanelDataCache = data;
if (data.state === LoadingState.Done) { if (data.state === LoadingState.Done) {
const legacy = data.series.map((v) => toLegacyResponseData(v)); const legacy = data.series.map((v) => toLegacyResponseData(v));
scope.events.emit(PanelEvents.dataReceived, legacy); scope.events.emit(PanelEvents.dataReceived, legacy);
......
...@@ -20,12 +20,13 @@ ...@@ -20,12 +20,13 @@
<icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon> <icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon>
</label> </label>
</div> </div>
<div class="gf-form"> <div class="gf-form" ng-show="ctrl.lastQueryMeta">
<label class="gf-form-label query-keyword" ng-click="ctrl.showQueryInspector()"> <label class="gf-form-label query-keyword pointer" ng-click="ctrl.showLastQuerySQL = !ctrl.showLastQuerySQL">
Generated SQL Generated SQL
<icon name="'angle-right'" style="margin-top: 3px;"></icon> <icon name="'angle-down'" ng-show="ctrl.showLastQuerySQL" style="margin-top: 3px;"></icon>
<icon name="'angle-right'" ng-hide="ctrl.showLastQuerySQL" style="margin-top: 3px;"></icon>
</label> </label>
</div> </div>
<div class="gf-form gf-form--grow"> <div class="gf-form gf-form--grow">
<div class="gf-form-label gf-form-label--grow"></div> <div class="gf-form-label gf-form-label--grow"></div>
</div> </div>
...@@ -78,6 +79,10 @@ Or build your own conditionals using these macros which just return the values: ...@@ -78,6 +79,10 @@ Or build your own conditionals using these macros which just return the values:
</div> </div>
<div class="gf-form" ng-show="ctrl.showLastQuerySQL">
<pre class="gf-form-pre">{{ctrl.lastQueryMeta.executedQueryString}}</pre>
</div>
<div class="gf-form" ng-show="ctrl.lastQueryError"> <div class="gf-form" ng-show="ctrl.lastQueryError">
<pre class="gf-form-pre alert alert-error">{{ctrl.lastQueryError}}</pre> <pre class="gf-form-pre alert alert-error">{{ctrl.lastQueryError}}</pre>
</div> </div>
......
import _ from 'lodash'; import _ from 'lodash';
import { QueryCtrl } from 'app/plugins/sdk'; import { QueryCtrl } from 'app/plugins/sdk';
import { auto } from 'angular'; import { auto } from 'angular';
import { PanelEvents } from '@grafana/data'; import { PanelEvents, QueryResultMeta } from '@grafana/data';
import { getLocationSrv } from '@grafana/runtime';
export interface MssqlQuery { export interface MssqlQuery {
refId: string; refId: string;
...@@ -11,10 +10,6 @@ export interface MssqlQuery { ...@@ -11,10 +10,6 @@ export interface MssqlQuery {
rawSql: string; rawSql: string;
} }
export interface QueryMeta {
sql: string;
}
const defaultQuery = `SELECT const defaultQuery = `SELECT
$__timeEpoch(<time_column>), $__timeEpoch(<time_column>),
<value column> as value, <value column> as value,
...@@ -31,7 +26,8 @@ export class MssqlQueryCtrl extends QueryCtrl { ...@@ -31,7 +26,8 @@ export class MssqlQueryCtrl extends QueryCtrl {
formats: any[]; formats: any[];
target: MssqlQuery; target: MssqlQuery;
lastQueryError: string | null; lastQueryMeta?: QueryResultMeta;
lastQueryError?: string;
showHelp: boolean; showHelp: boolean;
/** @ngInject */ /** @ngInject */
...@@ -59,15 +55,9 @@ export class MssqlQueryCtrl extends QueryCtrl { ...@@ -59,15 +55,9 @@ export class MssqlQueryCtrl extends QueryCtrl {
this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope); this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope);
} }
showQueryInspector() {
getLocationSrv().update({
query: { inspect: this.panel.id, inspectTab: 'query' },
partial: true,
});
}
onDataReceived(dataList: any) { onDataReceived(dataList: any) {
this.lastQueryError = null; this.lastQueryError = undefined;
this.lastQueryMeta = dataList[0]?.meta;
} }
onDataError(err: any) { onDataError(err: any) {
......
...@@ -120,10 +120,11 @@ ...@@ -120,10 +120,11 @@
<icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon> <icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon>
</label> </label>
</div> </div>
<div class="gf-form"> <div class="gf-form" ng-show="ctrl.lastQueryMeta">
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.showQueryInspector()"> <label class="gf-form-label query-keyword pointer" ng-click="ctrl.showLastQuerySQL = !ctrl.showLastQuerySQL">
Generated SQL Generated SQL
<icon name="'angle-right'" style="margin-top: 3px;"></icon> <icon name="'angle-down'" ng-show="ctrl.showLastQuerySQL" style="margin-top: 3px;"></icon>
<icon name="'angle-right'" ng-hide="ctrl.showLastQuerySQL" style="margin-top: 3px;"></icon>
</label> </label>
</div> </div>
<div class="gf-form gf-form--grow"> <div class="gf-form gf-form--grow">
...@@ -178,6 +179,10 @@ Or build your own conditionals using these macros which just return the values: ...@@ -178,6 +179,10 @@ Or build your own conditionals using these macros which just return the values:
</div> </div>
<div class="gf-form" ng-show="ctrl.showLastQuerySQL">
<pre class="gf-form-pre">{{ctrl.lastQueryMeta.executedQueryString}}</pre>
</div>
<div class="gf-form" ng-show="ctrl.lastQueryError"> <div class="gf-form" ng-show="ctrl.lastQueryError">
<pre class="gf-form-pre alert alert-error">{{ctrl.lastQueryError}}</pre> <pre class="gf-form-pre alert alert-error">{{ctrl.lastQueryError}}</pre>
</div> </div>
......
...@@ -7,13 +7,9 @@ import MysqlQuery from './mysql_query'; ...@@ -7,13 +7,9 @@ import MysqlQuery from './mysql_query';
import sqlPart from './sql_part'; import sqlPart from './sql_part';
import { auto } from 'angular'; import { auto } from 'angular';
import { CoreEvents } from 'app/types'; import { CoreEvents } from 'app/types';
import { PanelEvents } from '@grafana/data'; import { PanelEvents, QueryResultMeta } from '@grafana/data';
import { VariableWithMultiSupport } from 'app/features/variables/types'; import { VariableWithMultiSupport } from 'app/features/variables/types';
import { getLocationSrv, TemplateSrv } from '@grafana/runtime'; import { TemplateSrv } from '@grafana/runtime';
export interface QueryMeta {
sql: string;
}
const defaultQuery = `SELECT const defaultQuery = `SELECT
UNIX_TIMESTAMP(<time_column>) as time_sec, UNIX_TIMESTAMP(<time_column>) as time_sec,
...@@ -28,11 +24,12 @@ export class MysqlQueryCtrl extends QueryCtrl { ...@@ -28,11 +24,12 @@ export class MysqlQueryCtrl extends QueryCtrl {
static templateUrl = 'partials/query.editor.html'; static templateUrl = 'partials/query.editor.html';
formats: any[]; formats: any[];
lastQueryError: string | null; lastQueryError?: string;
showHelp: boolean; showHelp: boolean;
queryModel: MysqlQuery; queryModel: MysqlQuery;
metaBuilder: MysqlMetaQuery; metaBuilder: MysqlMetaQuery;
lastQueryMeta?: QueryResultMeta;
tableSegment: any; tableSegment: any;
whereAdd: any; whereAdd: any;
timeColumnSegment: any; timeColumnSegment: any;
...@@ -108,13 +105,6 @@ export class MysqlQueryCtrl extends QueryCtrl { ...@@ -108,13 +105,6 @@ export class MysqlQueryCtrl extends QueryCtrl {
this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope); this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope);
} }
showQueryInspector() {
getLocationSrv().update({
query: { inspect: this.panel.id, inspectTab: 'query' },
partial: true,
});
}
updateRawSqlAndRefresh() { updateRawSqlAndRefresh() {
if (!this.target.rawQuery) { if (!this.target.rawQuery) {
this.target.rawSql = this.queryModel.buildQuery(); this.target.rawSql = this.queryModel.buildQuery();
...@@ -278,7 +268,8 @@ export class MysqlQueryCtrl extends QueryCtrl { ...@@ -278,7 +268,8 @@ export class MysqlQueryCtrl extends QueryCtrl {
} }
onDataReceived(dataList: any) { onDataReceived(dataList: any) {
this.lastQueryError = null; this.lastQueryError = undefined;
this.lastQueryMeta = dataList[0]?.meta;
} }
onDataError(err: any) { onDataError(err: any) {
......
...@@ -120,10 +120,11 @@ ...@@ -120,10 +120,11 @@
<icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon> <icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon>
</label> </label>
</div> </div>
<div class="gf-form"> <div class="gf-form" ng-show="ctrl.lastQueryMeta">
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.showQueryInspector()"> <label class="gf-form-label query-keyword pointer" ng-click="ctrl.showLastQuerySQL = !ctrl.showLastQuerySQL">
Generated SQL Generated SQL
<icon name="'angle-right'" style="margin-top: 3px;"></icon> <icon name="'angle-down'" ng-show="ctrl.showLastQuerySQL" style="margin-top: 3px;"></icon>
<icon name="'angle-right'" ng-hide="ctrl.showLastQuerySQL" style="margin-top: 3px;"></icon>
</label> </label>
</div> </div>
<div class="gf-form gf-form--grow"> <div class="gf-form gf-form--grow">
...@@ -179,6 +180,10 @@ Or build your own conditionals using these macros which just return the values: ...@@ -179,6 +180,10 @@ Or build your own conditionals using these macros which just return the values:
</div> </div>
<div class="gf-form" ng-show="ctrl.showLastQuerySQL">
<pre class="gf-form-pre">{{ctrl.lastQueryMeta.executedQueryString}}</pre>
</div>
<div class="gf-form" ng-show="ctrl.lastQueryError"> <div class="gf-form" ng-show="ctrl.lastQueryError">
<pre class="gf-form-pre alert alert-error">{{ctrl.lastQueryError}}</pre> <pre class="gf-form-pre alert alert-error">{{ctrl.lastQueryError}}</pre>
</div> </div>
......
...@@ -7,13 +7,9 @@ import PostgresQuery from './postgres_query'; ...@@ -7,13 +7,9 @@ import PostgresQuery from './postgres_query';
import sqlPart from './sql_part'; import sqlPart from './sql_part';
import { auto } from 'angular'; import { auto } from 'angular';
import { CoreEvents } from 'app/types'; import { CoreEvents } from 'app/types';
import { PanelEvents } from '@grafana/data'; import { PanelEvents, QueryResultMeta } from '@grafana/data';
import { VariableWithMultiSupport } from 'app/features/variables/types'; import { VariableWithMultiSupport } from 'app/features/variables/types';
import { getLocationSrv, TemplateSrv } from '@grafana/runtime'; import { TemplateSrv } from '@grafana/runtime';
export interface QueryMeta {
sql: string;
}
const defaultQuery = `SELECT const defaultQuery = `SELECT
$__time(time_column), $__time(time_column),
...@@ -30,7 +26,8 @@ export class PostgresQueryCtrl extends QueryCtrl { ...@@ -30,7 +26,8 @@ export class PostgresQueryCtrl extends QueryCtrl {
formats: any[]; formats: any[];
queryModel: PostgresQuery; queryModel: PostgresQuery;
metaBuilder: PostgresMetaQuery; metaBuilder: PostgresMetaQuery;
lastQueryError: string | null; lastQueryMeta?: QueryResultMeta;
lastQueryError?: string;
showHelp: boolean; showHelp: boolean;
tableSegment: any; tableSegment: any;
whereAdd: any; whereAdd: any;
...@@ -106,13 +103,6 @@ export class PostgresQueryCtrl extends QueryCtrl { ...@@ -106,13 +103,6 @@ export class PostgresQueryCtrl extends QueryCtrl {
this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope); this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope);
} }
showQueryInspector() {
getLocationSrv().update({
query: { inspect: this.panel.id, inspectTab: 'query' },
partial: true,
});
}
updateRawSqlAndRefresh() { updateRawSqlAndRefresh() {
if (!this.target.rawQuery) { if (!this.target.rawQuery) {
this.target.rawSql = this.queryModel.buildQuery(); this.target.rawSql = this.queryModel.buildQuery();
...@@ -311,7 +301,8 @@ export class PostgresQueryCtrl extends QueryCtrl { ...@@ -311,7 +301,8 @@ export class PostgresQueryCtrl extends QueryCtrl {
} }
onDataReceived(dataList: any) { onDataReceived(dataList: any) {
this.lastQueryError = null; this.lastQueryError = undefined;
this.lastQueryMeta = dataList[0]?.meta;
} }
onDataError(err: any) { onDataError(err: any) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment