mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
QueryInspector: add common way to show the raw query (#25204)
This commit is contained in:
parent
c563633870
commit
2a6ac88a73
@ -33,11 +33,16 @@ export interface QueryResultMeta {
|
||||
/** Currently used to show results in Explore only in preferred visualisation option */
|
||||
preferredVisualisationType?: PreferredVisualisationType;
|
||||
|
||||
/**
|
||||
* This is the raw query sent to the underlying system. All macros and templating
|
||||
* as been applied. When metadata contains this value, it will be shown in the query inspector
|
||||
*/
|
||||
executedQueryString?: string;
|
||||
|
||||
/**
|
||||
* Legacy data source specific, should be moved to custom
|
||||
* */
|
||||
gmdMeta?: any[]; // used by cloudwatch
|
||||
rawQuery?: string; // used by stackdriver
|
||||
alignmentPeriod?: string; // used by stackdriver
|
||||
query?: string; // used by azure log
|
||||
searchWords?: string[]; // used by log models and loki
|
||||
|
@ -333,7 +333,7 @@ func TestMSSQL(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
queryResult := resp.Results["A"]
|
||||
So(queryResult.Error, ShouldBeNil)
|
||||
So(queryResult.Meta.Get("sql").MustString(), ShouldEqual, "SELECT FLOOR(DATEDIFF(second, '1970-01-01', time)/60)*60 AS time, avg(value) as value FROM metric GROUP BY FLOOR(DATEDIFF(second, '1970-01-01', time)/60)*60 ORDER BY 1")
|
||||
So(queryResult.Meta.Get(sqleng.MetaKeyExecutedQueryString).MustString(), ShouldEqual, "SELECT FLOOR(DATEDIFF(second, '1970-01-01', time)/60)*60 AS time, avg(value) as value FROM metric GROUP BY FLOOR(DATEDIFF(second, '1970-01-01', time)/60)*60 ORDER BY 1")
|
||||
})
|
||||
})
|
||||
|
||||
@ -698,7 +698,7 @@ func TestMSSQL(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
queryResult := resp.Results["A"]
|
||||
So(queryResult.Error, ShouldBeNil)
|
||||
So(queryResult.Meta.Get("sql").MustString(), ShouldEqual, "SELECT time FROM metric_values WHERE time > '2018-03-15T12:55:00Z' OR time < '2018-03-15T12:55:00Z' OR 1 < 1521118500 OR 1521118800 > 1 ORDER BY 1")
|
||||
So(queryResult.Meta.Get(sqleng.MetaKeyExecutedQueryString).MustString(), ShouldEqual, "SELECT time FROM metric_values WHERE time > '2018-03-15T12:55:00Z' OR time < '2018-03-15T12:55:00Z' OR 1 < 1521118500 OR 1521118800 > 1 ORDER BY 1")
|
||||
|
||||
})
|
||||
|
||||
|
@ -336,7 +336,7 @@ func TestMySQL(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
queryResult := resp.Results["A"]
|
||||
So(queryResult.Error, ShouldBeNil)
|
||||
So(queryResult.Meta.Get("sql").MustString(), ShouldEqual, "SELECT UNIX_TIMESTAMP(time) DIV 60 * 60 AS time, avg(value) as value FROM metric GROUP BY 1 ORDER BY 1")
|
||||
So(queryResult.Meta.Get(sqleng.MetaKeyExecutedQueryString).MustString(), ShouldEqual, "SELECT UNIX_TIMESTAMP(time) DIV 60 * 60 AS time, avg(value) as value FROM metric GROUP BY 1 ORDER BY 1")
|
||||
})
|
||||
})
|
||||
|
||||
@ -778,7 +778,7 @@ func TestMySQL(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
queryResult := resp.Results["A"]
|
||||
So(queryResult.Error, ShouldBeNil)
|
||||
So(queryResult.Meta.Get("sql").MustString(), ShouldEqual, "SELECT time FROM metric_values WHERE time > FROM_UNIXTIME(1521118500) OR time < FROM_UNIXTIME(1521118800) OR 1 < 1521118500 OR 1521118800 > 1 ORDER BY 1")
|
||||
So(queryResult.Meta.Get(sqleng.MetaKeyExecutedQueryString).MustString(), ShouldEqual, "SELECT time FROM metric_values WHERE time > FROM_UNIXTIME(1521118500) OR time < FROM_UNIXTIME(1521118800) OR 1 < 1521118500 OR 1521118800 > 1 ORDER BY 1")
|
||||
|
||||
})
|
||||
|
||||
|
@ -261,7 +261,7 @@ func TestPostgres(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
queryResult := resp.Results["A"]
|
||||
So(queryResult.Error, ShouldBeNil)
|
||||
So(queryResult.Meta.Get("sql").MustString(), ShouldEqual, "SELECT floor(extract(epoch from time)/60)*60 AS time, avg(value) as value FROM metric GROUP BY 1 ORDER BY 1")
|
||||
So(queryResult.Meta.Get(sqleng.MetaKeyExecutedQueryString).MustString(), ShouldEqual, "SELECT floor(extract(epoch from time)/60)*60 AS time, avg(value) as value FROM metric GROUP BY 1 ORDER BY 1")
|
||||
})
|
||||
})
|
||||
|
||||
@ -708,7 +708,7 @@ func TestPostgres(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
queryResult := resp.Results["A"]
|
||||
So(queryResult.Error, ShouldBeNil)
|
||||
So(queryResult.Meta.Get("sql").MustString(), ShouldEqual, "SELECT time FROM metric_values WHERE time > '2018-03-15T12:55:00Z' OR time < '2018-03-15T12:55:00Z' OR 1 < 1521118500 OR 1521118800 > 1 ORDER BY 1")
|
||||
So(queryResult.Meta.Get(sqleng.MetaKeyExecutedQueryString).MustString(), ShouldEqual, "SELECT time FROM metric_values WHERE time > '2018-03-15T12:55:00Z' OR time < '2018-03-15T12:55:00Z' OR 1 < 1521118500 OR 1521118800 > 1 ORDER BY 1")
|
||||
|
||||
})
|
||||
})
|
||||
|
@ -25,6 +25,9 @@ import (
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
// MetaKeyExecutedQueryString is the key where the executed query should get stored
|
||||
const MetaKeyExecutedQueryString = "executedQueryString"
|
||||
|
||||
// SqlMacroEngine interpolates macros into sql. It takes in the Query to have access to query context and
|
||||
// timeRange to be able to generate queries that use from and to.
|
||||
type SqlMacroEngine interface {
|
||||
@ -153,7 +156,7 @@ func (e *sqlQueryEndpoint) Query(ctx context.Context, dsInfo *models.DataSource,
|
||||
continue
|
||||
}
|
||||
|
||||
queryResult.Meta.Set("sql", rawSQL)
|
||||
queryResult.Meta.Set(MetaKeyExecutedQueryString, rawSQL)
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
"github.com/grafana/grafana/pkg/tsdb/sqleng"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"golang.org/x/net/context/ctxhttp"
|
||||
"golang.org/x/oauth2/google"
|
||||
@ -328,7 +329,7 @@ func (e *StackdriverExecutor) executeQuery(ctx context.Context, query *stackdriv
|
||||
}
|
||||
|
||||
req.URL.RawQuery = query.Params.Encode()
|
||||
queryResult.Meta.Set("rawQuery", req.URL.RawQuery)
|
||||
queryResult.Meta.Set(sqleng.MetaKeyExecutedQueryString, req.URL.RawQuery)
|
||||
alignmentPeriod, ok := req.URL.Query()["aggregation.alignmentPeriod"]
|
||||
|
||||
if ok {
|
||||
|
@ -354,7 +354,7 @@ export class PanelInspectorUnconnected extends PureComponent<Props, State> {
|
||||
)}
|
||||
{activeTab === InspectTab.Error && this.renderErrorTab(error)}
|
||||
{activeTab === InspectTab.Stats && this.renderStatsTab()}
|
||||
{activeTab === InspectTab.Query && <QueryInspector panel={panel} />}
|
||||
{activeTab === InspectTab.Query && <QueryInspector panel={panel} data={last.series} />}
|
||||
</TabContent>
|
||||
</CustomScrollbar>
|
||||
</Drawer>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Button, JSONFormatter, LoadingPlaceholder } from '@grafana/ui';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { AppEvents, PanelEvents } from '@grafana/data';
|
||||
import { AppEvents, PanelEvents, DataFrame } from '@grafana/data';
|
||||
|
||||
import appEvents from 'app/core/app_events';
|
||||
import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipboard';
|
||||
@ -9,14 +9,24 @@ import { CoreEvents } from 'app/types';
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { getPanelInspectorStyles } from './styles';
|
||||
import { supportsDataQuery } from '../PanelEditor/utils';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { css } from 'emotion';
|
||||
|
||||
interface DsQuery {
|
||||
isLoading: boolean;
|
||||
response: {};
|
||||
}
|
||||
|
||||
interface ExecutedQueryInfo {
|
||||
refId: string;
|
||||
query: string;
|
||||
frames: number;
|
||||
rows: number;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
panel: PanelModel;
|
||||
data: DataFrame[];
|
||||
}
|
||||
|
||||
interface State {
|
||||
@ -24,6 +34,7 @@ interface State {
|
||||
isMocking: boolean;
|
||||
mockedResponse: string;
|
||||
dsQuery: DsQuery;
|
||||
executedQueries: ExecutedQueryInfo[];
|
||||
}
|
||||
|
||||
export class QueryInspector extends PureComponent<Props, State> {
|
||||
@ -33,6 +44,7 @@ export class QueryInspector extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
executedQueries: [],
|
||||
allNodesExpanded: null,
|
||||
isMocking: false,
|
||||
mockedResponse: '',
|
||||
@ -47,6 +59,43 @@ export class QueryInspector extends PureComponent<Props, State> {
|
||||
appEvents.on(CoreEvents.dsRequestResponse, this.onDataSourceResponse);
|
||||
appEvents.on(CoreEvents.dsRequestError, this.onRequestError);
|
||||
this.props.panel.events.on(PanelEvents.refresh, this.onPanelRefresh);
|
||||
this.updateQueryList();
|
||||
}
|
||||
|
||||
componentDidUpdate(oldProps: Props) {
|
||||
if (this.props.data !== oldProps.data) {
|
||||
this.updateQueryList();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the list of executed queries
|
||||
*/
|
||||
updateQueryList() {
|
||||
const { data } = this.props;
|
||||
const executedQueries: ExecutedQueryInfo[] = [];
|
||||
if (data?.length) {
|
||||
let last: ExecutedQueryInfo | undefined = undefined;
|
||||
data.forEach((frame, idx) => {
|
||||
const query = frame.meta?.executedQueryString;
|
||||
if (query) {
|
||||
const refId = frame.refId || '?';
|
||||
if (last?.refId === refId) {
|
||||
last.frames++;
|
||||
last.rows += frame.length;
|
||||
} else {
|
||||
last = {
|
||||
refId,
|
||||
frames: 0,
|
||||
rows: frame.length,
|
||||
query,
|
||||
};
|
||||
executedQueries.push(last);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
this.setState({ executedQueries });
|
||||
}
|
||||
|
||||
onIssueNewQuery = () => {
|
||||
@ -182,8 +231,39 @@ export class QueryInspector extends PureComponent<Props, State> {
|
||||
}));
|
||||
};
|
||||
|
||||
renderExecutedQueries(executedQueries: ExecutedQueryInfo[]) {
|
||||
if (!executedQueries.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const styles = {
|
||||
refId: css`
|
||||
font-weight: ${config.theme.typography.weight.semibold};
|
||||
color: ${config.theme.colors.textBlue};
|
||||
margin-right: 8px;
|
||||
`,
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{executedQueries.map(info => {
|
||||
return (
|
||||
<div key={info.refId}>
|
||||
<div>
|
||||
<span className={styles.refId}>{info.refId}:</span>
|
||||
{info.frames > 1 && <span>{info.frames} frames, </span>}
|
||||
<span>{info.rows} rows</span>
|
||||
</div>
|
||||
<pre>{info.query}</pre>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { allNodesExpanded } = this.state;
|
||||
const { allNodesExpanded, executedQueries } = this.state;
|
||||
const { response, isLoading } = this.state.dsQuery;
|
||||
const openNodes = this.getNrOfOpenNodes();
|
||||
const styles = getPanelInspectorStyles();
|
||||
@ -202,6 +282,7 @@ export class QueryInspector extends PureComponent<Props, State> {
|
||||
new query. Hit refresh button below to trigger a new query.
|
||||
</p>
|
||||
</div>
|
||||
{this.renderExecutedQueries(executedQueries)}
|
||||
<div className={styles.toolbar}>
|
||||
<Button
|
||||
icon="sync"
|
||||
|
@ -20,11 +20,10 @@
|
||||
<icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="gf-form" ng-show="ctrl.lastQueryMeta">
|
||||
<label class="gf-form-label query-keyword" ng-click="ctrl.showLastQuerySQL = !ctrl.showLastQuerySQL">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword" ng-click="ctrl.showQueryInspector()">
|
||||
Generated SQL
|
||||
<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>
|
||||
<icon name="'angle-right'" style="margin-top: 3px;"></icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="gf-form gf-form--grow">
|
||||
|
@ -2,6 +2,7 @@ import _ from 'lodash';
|
||||
import { QueryCtrl } from 'app/plugins/sdk';
|
||||
import { auto } from 'angular';
|
||||
import { PanelEvents } from '@grafana/data';
|
||||
import { getLocationSrv } from '@grafana/runtime';
|
||||
|
||||
export interface MssqlQuery {
|
||||
refId: string;
|
||||
@ -28,10 +29,8 @@ ORDER BY
|
||||
export class MssqlQueryCtrl extends QueryCtrl {
|
||||
static templateUrl = 'partials/query.editor.html';
|
||||
|
||||
showLastQuerySQL: boolean;
|
||||
formats: any[];
|
||||
target: MssqlQuery;
|
||||
lastQueryMeta: QueryMeta;
|
||||
lastQueryError: string;
|
||||
showHelp: boolean;
|
||||
|
||||
@ -60,21 +59,21 @@ export class MssqlQueryCtrl extends QueryCtrl {
|
||||
this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope);
|
||||
}
|
||||
|
||||
onDataReceived(dataList: any) {
|
||||
this.lastQueryMeta = null;
|
||||
this.lastQueryError = null;
|
||||
|
||||
const anySeriesFromQuery: any = _.find(dataList, { refId: this.target.refId });
|
||||
if (anySeriesFromQuery) {
|
||||
this.lastQueryMeta = anySeriesFromQuery.meta;
|
||||
showQueryInspector() {
|
||||
getLocationSrv().update({
|
||||
query: { inspect: this.panel.id, inspectTab: 'query' },
|
||||
partial: true,
|
||||
});
|
||||
}
|
||||
|
||||
onDataReceived(dataList: any) {
|
||||
this.lastQueryError = null;
|
||||
}
|
||||
|
||||
onDataError(err: any) {
|
||||
if (err.data && err.data.results) {
|
||||
const queryRes = err.data.results[this.target.refId];
|
||||
if (queryRes) {
|
||||
this.lastQueryMeta = queryRes.meta;
|
||||
this.lastQueryError = queryRes.error;
|
||||
}
|
||||
}
|
||||
|
@ -120,11 +120,10 @@
|
||||
<icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="gf-form" ng-show="ctrl.lastQueryMeta">
|
||||
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.showLastQuerySQL = !ctrl.showLastQuerySQL">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.showQueryInspector()">
|
||||
Generated SQL
|
||||
<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>
|
||||
<icon name="'angle-right'" style="margin-top: 3px;"></icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="gf-form gf-form--grow">
|
||||
@ -132,10 +131,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-show="ctrl.showLastQuerySQL">
|
||||
<pre class="gf-form-pre">{{ctrl.lastQueryMeta.sql}}</pre>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-show="ctrl.showHelp">
|
||||
<pre class="gf-form-pre alert alert-info">Time series:
|
||||
- return column named time or time_sec (in UTC), as a unix time stamp or any sql native date data type. You can use the macros below.
|
||||
|
@ -10,6 +10,7 @@ import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { CoreEvents } from 'app/types';
|
||||
import { PanelEvents } from '@grafana/data';
|
||||
import { VariableWithMultiSupport } from 'app/features/templating/types';
|
||||
import { getLocationSrv } from '@grafana/runtime';
|
||||
|
||||
export interface QueryMeta {
|
||||
sql: string;
|
||||
@ -27,9 +28,7 @@ ORDER BY <time_column> ASC
|
||||
export class MysqlQueryCtrl extends QueryCtrl {
|
||||
static templateUrl = 'partials/query.editor.html';
|
||||
|
||||
showLastQuerySQL: boolean;
|
||||
formats: any[];
|
||||
lastQueryMeta: QueryMeta;
|
||||
lastQueryError: string;
|
||||
showHelp: boolean;
|
||||
|
||||
@ -110,6 +109,13 @@ export class MysqlQueryCtrl extends QueryCtrl {
|
||||
this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope);
|
||||
}
|
||||
|
||||
showQueryInspector() {
|
||||
getLocationSrv().update({
|
||||
query: { inspect: this.panel.id, inspectTab: 'query' },
|
||||
partial: true,
|
||||
});
|
||||
}
|
||||
|
||||
updateRawSqlAndRefresh() {
|
||||
if (!this.target.rawQuery) {
|
||||
this.target.rawSql = this.queryModel.buildQuery();
|
||||
@ -273,20 +279,13 @@ export class MysqlQueryCtrl extends QueryCtrl {
|
||||
}
|
||||
|
||||
onDataReceived(dataList: any) {
|
||||
this.lastQueryMeta = null;
|
||||
this.lastQueryError = null;
|
||||
|
||||
const anySeriesFromQuery: any = _.find(dataList, { refId: this.target.refId });
|
||||
if (anySeriesFromQuery) {
|
||||
this.lastQueryMeta = anySeriesFromQuery.meta;
|
||||
}
|
||||
}
|
||||
|
||||
onDataError(err: any) {
|
||||
if (err.data && err.data.results) {
|
||||
const queryRes = err.data.results[this.target.refId];
|
||||
if (queryRes) {
|
||||
this.lastQueryMeta = queryRes.meta;
|
||||
this.lastQueryError = queryRes.error;
|
||||
}
|
||||
}
|
||||
|
@ -120,11 +120,10 @@
|
||||
<icon name="'angle-right'" ng-hide="ctrl.showHelp" style="margin-top: 3px;"></icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="gf-form" ng-show="ctrl.lastQueryMeta">
|
||||
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.showLastQuerySQL = !ctrl.showLastQuerySQL">
|
||||
<div class="gf-form">
|
||||
<label class="gf-form-label query-keyword pointer" ng-click="ctrl.showQueryInspector()">
|
||||
Generated SQL
|
||||
<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>
|
||||
<icon name="'angle-right'" style="margin-top: 3px;"></icon>
|
||||
</label>
|
||||
</div>
|
||||
<div class="gf-form gf-form--grow">
|
||||
@ -132,9 +131,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-show="ctrl.showLastQuerySQL">
|
||||
<pre class="gf-form-pre">{{ctrl.lastQueryMeta.sql}}</pre>
|
||||
</div>
|
||||
|
||||
<div class="gf-form" ng-show="ctrl.showHelp">
|
||||
<pre class="gf-form-pre alert alert-info">Time series:
|
||||
|
@ -10,6 +10,7 @@ import { TemplateSrv } from 'app/features/templating/template_srv';
|
||||
import { CoreEvents } from 'app/types';
|
||||
import { PanelEvents } from '@grafana/data';
|
||||
import { VariableWithMultiSupport } from 'app/features/templating/types';
|
||||
import { getLocationSrv } from '@grafana/runtime';
|
||||
|
||||
export interface QueryMeta {
|
||||
sql: string;
|
||||
@ -31,7 +32,6 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
||||
formats: any[];
|
||||
queryModel: PostgresQuery;
|
||||
metaBuilder: PostgresMetaQuery;
|
||||
lastQueryMeta: QueryMeta;
|
||||
lastQueryError: string;
|
||||
showHelp: boolean;
|
||||
tableSegment: any;
|
||||
@ -108,6 +108,13 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
||||
this.panelCtrl.events.on(PanelEvents.dataError, this.onDataError.bind(this), $scope);
|
||||
}
|
||||
|
||||
showQueryInspector() {
|
||||
getLocationSrv().update({
|
||||
query: { inspect: this.panel.id, inspectTab: 'query' },
|
||||
partial: true,
|
||||
});
|
||||
}
|
||||
|
||||
updateRawSqlAndRefresh() {
|
||||
if (!this.target.rawQuery) {
|
||||
this.target.rawSql = this.queryModel.buildQuery();
|
||||
@ -306,21 +313,13 @@ export class PostgresQueryCtrl extends QueryCtrl {
|
||||
}
|
||||
|
||||
onDataReceived(dataList: any) {
|
||||
this.lastQueryMeta = null;
|
||||
this.lastQueryError = null;
|
||||
console.log('postgres query data received', dataList);
|
||||
|
||||
const anySeriesFromQuery: any = _.find(dataList, { refId: this.target.refId });
|
||||
if (anySeriesFromQuery) {
|
||||
this.lastQueryMeta = anySeriesFromQuery.meta;
|
||||
}
|
||||
}
|
||||
|
||||
onDataError(err: any) {
|
||||
if (err.data && err.data.results) {
|
||||
const queryRes = err.data.results[this.target.refId];
|
||||
if (queryRes) {
|
||||
this.lastQueryMeta = queryRes.meta;
|
||||
this.lastQueryError = queryRes.error;
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,10 @@ export class QueryEditor extends PureComponent<Props, State> {
|
||||
query={sloQuery}
|
||||
></SLOQueryEditor>
|
||||
)}
|
||||
<Help rawQuery={decodeURIComponent(meta?.rawQuery ?? '')} lastQueryError={this.state.lastQueryError} />
|
||||
<Help
|
||||
rawQuery={decodeURIComponent(meta?.executedQueryString ?? '')}
|
||||
lastQueryError={this.state.lastQueryError}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user