mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
InfluxDB: Fix sql query generation by adding quotes around the identifiers (#83765)
* Quote the identifiers * wrap where filter with quotes * fix query generation
This commit is contained in:
parent
bc7eacfcbd
commit
dc4c539d46
@ -1,12 +1,12 @@
|
||||
import { DataSourceInstanceSettings, TimeRange } from '@grafana/data';
|
||||
import { CompletionItemKind, LanguageDefinition, TableIdentifier } from '@grafana/experimental';
|
||||
import { getTemplateSrv, TemplateSrv } from '@grafana/runtime';
|
||||
import { DB, SqlDatasource, SQLQuery, formatSQL } from '@grafana/sql';
|
||||
import { DB, formatSQL, SqlDatasource, SQLQuery } from '@grafana/sql';
|
||||
|
||||
import { mapFieldsToTypes } from './fields';
|
||||
import { buildColumnQuery, buildTableQuery } from './flightsqlMetaQuery';
|
||||
import { getSqlCompletionProvider } from './sqlCompletionProvider';
|
||||
import { quoteLiteral, quoteIdentifierIfNecessary, toRawSql } from './sqlUtil';
|
||||
import { quoteIdentifierIfNecessary, quoteLiteral, toRawSql } from './sqlUtil';
|
||||
import { FlightSQLOptions } from './types';
|
||||
|
||||
export class FlightSQLDatasource extends SqlDatasource {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { SQLQuery, QueryEditorExpressionType } from '@grafana/sql';
|
||||
import { QueryEditorExpressionType, SQLQuery } from '@grafana/sql';
|
||||
|
||||
import { toRawSql } from './sqlUtil';
|
||||
|
||||
describe('toRawSql', () => {
|
||||
it('should render sql properly', () => {
|
||||
const expected = 'SELECT host FROM iox.value1 WHERE time >= $__timeFrom AND time <= $__timeTo LIMIT 50';
|
||||
const expected = 'SELECT "host" FROM "value1" WHERE "time" >= $__timeFrom AND "time" <= $__timeTo LIMIT 50';
|
||||
const testQuery: SQLQuery = {
|
||||
refId: 'A',
|
||||
sql: {
|
||||
@ -27,4 +27,55 @@ describe('toRawSql', () => {
|
||||
const result = toRawSql(testQuery);
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should wrap the identifiers with quote', () => {
|
||||
const expected = 'SELECT "host" FROM "TestValue" WHERE "time" >= $__timeFrom AND "time" <= $__timeTo LIMIT 50';
|
||||
const testQuery: SQLQuery = {
|
||||
refId: 'A',
|
||||
sql: {
|
||||
limit: 50,
|
||||
columns: [
|
||||
{
|
||||
parameters: [
|
||||
{
|
||||
name: 'host',
|
||||
type: QueryEditorExpressionType.FunctionParameter,
|
||||
},
|
||||
],
|
||||
type: QueryEditorExpressionType.Function,
|
||||
},
|
||||
],
|
||||
},
|
||||
dataset: 'iox',
|
||||
table: 'TestValue',
|
||||
};
|
||||
const result = toRawSql(testQuery);
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should wrap filters in where', () => {
|
||||
const expected = `SELECT "host" FROM "TestValue" WHERE "time" >= $__timeFrom AND "time" <= $__timeTo AND ("sensor_id" = '12' AND "sensor_id" = '23') LIMIT 50`;
|
||||
const testQuery: SQLQuery = {
|
||||
refId: 'A',
|
||||
sql: {
|
||||
limit: 50,
|
||||
columns: [
|
||||
{
|
||||
parameters: [
|
||||
{
|
||||
name: 'host',
|
||||
type: QueryEditorExpressionType.FunctionParameter,
|
||||
},
|
||||
],
|
||||
type: QueryEditorExpressionType.Function,
|
||||
},
|
||||
],
|
||||
whereString: `(sensor_id = '12' AND sensor_id = '23')`,
|
||||
},
|
||||
dataset: 'iox',
|
||||
table: 'TestValue',
|
||||
};
|
||||
const result = toRawSql(testQuery);
|
||||
expect(result).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { isEmpty } from 'lodash';
|
||||
|
||||
import { SQLQuery, createSelectClause, haveColumns } from '@grafana/sql';
|
||||
import { createSelectClause, haveColumns, SQLQuery } from '@grafana/sql';
|
||||
|
||||
// remove identifier quoting from identifier to use in metadata queries
|
||||
export function unquoteIdentifier(value: string) {
|
||||
@ -17,7 +17,7 @@ export function quoteLiteral(value: string) {
|
||||
return "'" + value.replace(/'/g, "''") + "'";
|
||||
}
|
||||
|
||||
export function toRawSql({ sql, dataset, table }: SQLQuery): string {
|
||||
export function toRawSql({ sql, table }: SQLQuery): string {
|
||||
let rawQuery = '';
|
||||
|
||||
// Return early with empty string if there is no sql column
|
||||
@ -25,25 +25,33 @@ export function toRawSql({ sql, dataset, table }: SQLQuery): string {
|
||||
return rawQuery;
|
||||
}
|
||||
|
||||
rawQuery += createSelectClause(sql.columns);
|
||||
// wrapping the column name with quotes
|
||||
const sc = sql.columns.map((c) => ({ ...c, parameters: c.parameters?.map((p) => ({ ...p, name: `"${p.name}"` })) }));
|
||||
rawQuery += createSelectClause(sc);
|
||||
|
||||
if (dataset && table) {
|
||||
rawQuery += `FROM ${dataset}.${table} `;
|
||||
if (table) {
|
||||
rawQuery += `FROM "${table}" `;
|
||||
}
|
||||
|
||||
// $__timeFrom and $__timeTo will be interpolated on the backend
|
||||
rawQuery += `WHERE time >= $__timeFrom AND time <= $__timeTo `;
|
||||
rawQuery += `WHERE "time" >= $__timeFrom AND "time" <= $__timeTo `;
|
||||
if (sql.whereString) {
|
||||
rawQuery += `AND ${sql.whereString} `;
|
||||
// whereString is generated by the react-awesome-query-builder
|
||||
// we use SQLWhereRow as a common component
|
||||
// in order to not mess with common component here we just modify the string
|
||||
const wherePattern = new RegExp('(\\s?)([^\\(]\\S+)(\\s?=)', 'g');
|
||||
const subst = `$1"$2"$3`;
|
||||
const whereString = sql.whereString.replace(wherePattern, subst);
|
||||
rawQuery += `AND ${whereString} `;
|
||||
}
|
||||
|
||||
if (sql.groupBy?.[0]?.property.name) {
|
||||
const groupBy = sql.groupBy.map((g) => g.property.name).filter((g) => !isEmpty(g));
|
||||
const groupBy = sql.groupBy.map((g) => `"${g.property.name}"`).filter((g) => !isEmpty(g));
|
||||
rawQuery += `GROUP BY ${groupBy.join(', ')} `;
|
||||
}
|
||||
|
||||
if (sql.orderBy?.property.name) {
|
||||
rawQuery += `ORDER BY ${sql.orderBy.property.name} `;
|
||||
rawQuery += `ORDER BY "${sql.orderBy.property.name}" `;
|
||||
}
|
||||
|
||||
if (sql.orderBy?.property.name && sql.orderByDirection) {
|
||||
|
Loading…
Reference in New Issue
Block a user