mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
InfluxDB SQL: Use double quotes instead of backticks (#75443)
Use double quotes instead of backticks
This commit is contained in:
@@ -8,10 +8,9 @@ import { SQLQuery } from '../../../../../../../features/plugins/sql';
|
||||
import { SqlQueryEditor } from '../../../../../../../features/plugins/sql/components/QueryEditor';
|
||||
import { applyQueryDefaults } from '../../../../../../../features/plugins/sql/defaults';
|
||||
import InfluxDatasource from '../../../../datasource';
|
||||
import { FlightSQLDatasource } from '../../../../fsql/datasource.flightsql';
|
||||
import { InfluxQuery } from '../../../../types';
|
||||
|
||||
import { FlightSQLDatasource } from './FlightSQLDatasource';
|
||||
|
||||
interface Props extends Themeable2 {
|
||||
onChange: (query: InfluxQuery) => void;
|
||||
onRunQuery: () => void;
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
import { DataSourceInstanceSettings, TimeRange } from '@grafana/data';
|
||||
import { DataSourceInstanceSettings, TimeRange } from '@grafana/data/src';
|
||||
import { CompletionItemKind, LanguageDefinition, TableIdentifier } from '@grafana/experimental';
|
||||
import { SqlDatasource } from 'app/features/plugins/sql/datasource/SqlDatasource';
|
||||
import { DB, SQLQuery } from 'app/features/plugins/sql/types';
|
||||
import { formatSQL } from 'app/features/plugins/sql/utils/formatSQL';
|
||||
|
||||
// @todo These are being imported for PoC, but should probably be reimplemented within the influx datasource?
|
||||
import { mapFieldsToTypes } from '../../../../../mysql/fields';
|
||||
import { buildColumnQuery, buildTableQuery, showDatabases } from '../../../../../mysql/mySqlMetaQuery';
|
||||
import { getSqlCompletionProvider } from '../../../../../mysql/sqlCompletionProvider';
|
||||
import { quoteIdentifierIfNecessary, quoteLiteral, toRawSql } from '../../../../../mysql/sqlUtil';
|
||||
import { MySQLOptions } from '../../../../../mysql/types';
|
||||
import { mapFieldsToTypes } from './fields';
|
||||
import { buildColumnQuery, buildTableQuery, showDatabases } from './flightsqlMetaQuery';
|
||||
import { getSqlCompletionProvider } from './sqlCompletionProvider';
|
||||
import { quoteLiteral, quoteIdentifierIfNecessary, toRawSql } from './sqlUtil';
|
||||
import { FlightSQLOptions } from './types';
|
||||
|
||||
export class FlightSQLDatasource extends SqlDatasource {
|
||||
sqlLanguageDefinition: LanguageDefinition | undefined;
|
||||
|
||||
constructor(private instanceSettings: DataSourceInstanceSettings<MySQLOptions>) {
|
||||
constructor(private instanceSettings: DataSourceInstanceSettings<FlightSQLOptions>) {
|
||||
super(instanceSettings);
|
||||
}
|
||||
|
||||
@@ -31,7 +30,7 @@ export class FlightSQLDatasource extends SqlDatasource {
|
||||
getMeta: (identifier?: TableIdentifier) => this.fetchMeta(identifier),
|
||||
};
|
||||
this.sqlLanguageDefinition = {
|
||||
id: 'mysql',
|
||||
id: 'flightsql',
|
||||
completionProvider: getSqlCompletionProvider(args),
|
||||
formatter: formatSQL,
|
||||
};
|
||||
91
public/app/plugins/datasource/influxdb/fsql/fields.ts
Normal file
91
public/app/plugins/datasource/influxdb/fsql/fields.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { RAQBFieldTypes, SQLSelectableValue } from 'app/features/plugins/sql/types';
|
||||
|
||||
export function mapFieldsToTypes(columns: SQLSelectableValue[]) {
|
||||
const fields: SQLSelectableValue[] = [];
|
||||
for (const col of columns) {
|
||||
let type: RAQBFieldTypes = 'text';
|
||||
switch (col.type?.toUpperCase()) {
|
||||
case 'BOOLEAN':
|
||||
case 'BOOL': {
|
||||
type = 'boolean';
|
||||
break;
|
||||
}
|
||||
case 'BYTES':
|
||||
case 'VARCHAR': {
|
||||
type = 'text';
|
||||
break;
|
||||
}
|
||||
case 'FLOAT':
|
||||
case 'FLOAT64':
|
||||
case 'INT':
|
||||
case 'INTEGER':
|
||||
case 'INT64':
|
||||
case 'NUMERIC':
|
||||
case 'BIGNUMERIC': {
|
||||
type = 'number';
|
||||
break;
|
||||
}
|
||||
case 'DATE': {
|
||||
type = 'date';
|
||||
break;
|
||||
}
|
||||
case 'DATETIME': {
|
||||
type = 'datetime';
|
||||
break;
|
||||
}
|
||||
case 'TIME': {
|
||||
type = 'time';
|
||||
break;
|
||||
}
|
||||
case 'TIMESTAMP': {
|
||||
type = 'datetime';
|
||||
break;
|
||||
}
|
||||
case 'GEOGRAPHY': {
|
||||
type = 'text';
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fields.push({ ...col, raqbFieldType: type, icon: mapColumnTypeToIcon(col.type!.toUpperCase()) });
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
export function mapColumnTypeToIcon(type: string) {
|
||||
switch (type) {
|
||||
case 'TIME':
|
||||
case 'DATETIME':
|
||||
case 'TIMESTAMP':
|
||||
return 'clock-nine';
|
||||
case 'BOOLEAN':
|
||||
return 'toggle-off';
|
||||
case 'INTEGER':
|
||||
case 'FLOAT':
|
||||
case 'FLOAT64':
|
||||
case 'INT':
|
||||
case 'SMALLINT':
|
||||
case 'BIGINT':
|
||||
case 'TINYINT':
|
||||
case 'BYTEINT':
|
||||
case 'INT64':
|
||||
case 'NUMERIC':
|
||||
case 'DECIMAL':
|
||||
return 'calculator-alt';
|
||||
case 'CHAR':
|
||||
case 'VARCHAR':
|
||||
case 'STRING':
|
||||
case 'BYTES':
|
||||
case 'TEXT':
|
||||
case 'TINYTEXT':
|
||||
case 'MEDIUMTEXT':
|
||||
case 'LONGTEXT':
|
||||
return 'text';
|
||||
case 'GEOGRAPHY':
|
||||
return 'map';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import { quoteLiteral, unquoteIdentifier } from './sqlUtil';
|
||||
|
||||
export function buildTableQuery(dataset?: string) {
|
||||
const database = dataset !== undefined ? quoteIdentAsLiteral(dataset) : 'database()';
|
||||
return `SELECT table_name FROM information_schema.tables WHERE table_schema = ${database} ORDER BY table_name`;
|
||||
}
|
||||
|
||||
export function showDatabases() {
|
||||
return `SELECT DISTINCT TABLE_SCHEMA from information_schema.TABLES where TABLE_TYPE != 'SYSTEM VIEW' ORDER BY TABLE_SCHEMA`;
|
||||
}
|
||||
|
||||
export function buildColumnQuery(table: string, dbName?: string) {
|
||||
let query = 'SELECT column_name, data_type FROM information_schema.columns WHERE ';
|
||||
query += buildTableConstraint(table, dbName);
|
||||
|
||||
query += ' ORDER BY column_name';
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
export function buildTableConstraint(table: string, dbName?: string) {
|
||||
let query = '';
|
||||
|
||||
// check for schema qualified table
|
||||
if (table.includes('.')) {
|
||||
const parts = table.split('.');
|
||||
query = 'table_schema = ' + quoteIdentAsLiteral(parts[0]);
|
||||
query += ' AND table_name = ' + quoteIdentAsLiteral(parts[1]);
|
||||
return query;
|
||||
} else {
|
||||
const database = dbName !== undefined ? quoteIdentAsLiteral(dbName) : 'database()';
|
||||
query = `table_schema = ${database} AND table_name = ` + quoteIdentAsLiteral(table);
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
export function quoteIdentAsLiteral(value: string) {
|
||||
return quoteLiteral(unquoteIdentifier(value));
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
import {
|
||||
CompletionItemKind,
|
||||
CompletionItemPriority,
|
||||
getStandardSQLCompletionProvider,
|
||||
LanguageCompletionProvider,
|
||||
LinkedToken,
|
||||
PositionContext,
|
||||
StatementPlacementProvider,
|
||||
SuggestionKind,
|
||||
SuggestionKindProvider,
|
||||
TableDefinition,
|
||||
TableIdentifier,
|
||||
TokenType,
|
||||
} from '@grafana/experimental';
|
||||
|
||||
interface CompletionProviderGetterArgs {
|
||||
getMeta: (t?: TableIdentifier) => Promise<TableDefinition[]>;
|
||||
}
|
||||
|
||||
export const getSqlCompletionProvider: (args: CompletionProviderGetterArgs) => LanguageCompletionProvider =
|
||||
({ getMeta }) =>
|
||||
(monaco, language) => ({
|
||||
...(language && getStandardSQLCompletionProvider(monaco, language)),
|
||||
customStatementPlacement: customStatementPlacementProvider,
|
||||
customSuggestionKinds: customSuggestionKinds(getMeta),
|
||||
});
|
||||
|
||||
const customStatementPlacement = {
|
||||
afterDatabase: 'afterDatabase',
|
||||
};
|
||||
|
||||
const customSuggestionKind = {
|
||||
tablesWithinDatabase: 'tablesWithinDatabase',
|
||||
};
|
||||
|
||||
const FROMKEYWORD = 'FROM';
|
||||
|
||||
export const customStatementPlacementProvider: StatementPlacementProvider = () => [
|
||||
{
|
||||
id: customStatementPlacement.afterDatabase,
|
||||
resolve: (currentToken, previousKeyword, previousNonWhiteSpace) => {
|
||||
return Boolean(
|
||||
currentToken?.is(TokenType.Delimiter, '.') &&
|
||||
previousKeyword?.value === FROMKEYWORD &&
|
||||
(previousNonWhiteSpace?.is(TokenType.IdentifierQuote) || previousNonWhiteSpace?.isIdentifier()) &&
|
||||
// don't match after table name
|
||||
currentToken
|
||||
?.getPreviousUntil(TokenType.Keyword, [TokenType.IdentifierQuote], FROMKEYWORD)
|
||||
?.filter((t) => t.isIdentifier()).length === 1
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const customSuggestionKinds: (getMeta: CompletionProviderGetterArgs['getMeta']) => SuggestionKindProvider =
|
||||
(getMeta) => () => [
|
||||
{
|
||||
id: SuggestionKind.Tables,
|
||||
overrideDefault: true,
|
||||
suggestionsResolver: async (ctx) => {
|
||||
const databaseName = getDatabaseName(ctx.currentToken);
|
||||
|
||||
const suggestions = await getMeta({ schema: databaseName });
|
||||
|
||||
return suggestions.map(mapToSuggestion(ctx));
|
||||
},
|
||||
},
|
||||
{
|
||||
id: SuggestionKind.Columns,
|
||||
overrideDefault: true,
|
||||
suggestionsResolver: async (ctx) => {
|
||||
const databaseToken = getDatabaseToken(ctx.currentToken);
|
||||
const databaseName = getDatabaseName(databaseToken);
|
||||
const tableName = getTableName(databaseToken);
|
||||
|
||||
if (!databaseName || !tableName) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const suggestions = await getMeta({ schema: databaseName, table: tableName });
|
||||
|
||||
return suggestions.map(mapToSuggestion(ctx));
|
||||
},
|
||||
},
|
||||
{
|
||||
id: customSuggestionKind.tablesWithinDatabase,
|
||||
applyTo: [customStatementPlacement.afterDatabase],
|
||||
suggestionsResolver: async (ctx) => {
|
||||
const databaseName = getDatabaseName(ctx.currentToken);
|
||||
|
||||
const suggestions = await getMeta({ schema: databaseName });
|
||||
|
||||
return suggestions.map(mapToSuggestion(ctx));
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
function mapToSuggestion(ctx: PositionContext) {
|
||||
return function (tableDefinition: TableDefinition) {
|
||||
return {
|
||||
label: tableDefinition.name,
|
||||
insertText: tableDefinition.completion ?? tableDefinition.name,
|
||||
command: { id: 'editor.action.triggerSuggest', title: '' },
|
||||
kind: CompletionItemKind.Field,
|
||||
sortText: CompletionItemPriority.High,
|
||||
range: {
|
||||
...ctx.range,
|
||||
startColumn: ctx.range.endColumn,
|
||||
endColumn: ctx.range.endColumn,
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function getDatabaseName(token: LinkedToken | null | undefined) {
|
||||
if (token?.isIdentifier() && token.value[token.value.length - 1] !== '.') {
|
||||
return token.value;
|
||||
}
|
||||
|
||||
if (token?.is(TokenType.Delimiter, '.')) {
|
||||
return token.getPreviousOfType(TokenType.Identifier)?.value;
|
||||
}
|
||||
|
||||
if (token?.is(TokenType.IdentifierQuote)) {
|
||||
return token.getPreviousOfType(TokenType.Identifier)?.value || token.getNextOfType(TokenType.Identifier)?.value;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
function getTableName(token: LinkedToken | null | undefined) {
|
||||
const identifier = token?.getNextOfType(TokenType.Identifier);
|
||||
return identifier?.value;
|
||||
}
|
||||
|
||||
const getFromKeywordToken = (currentToken: LinkedToken | null) => {
|
||||
const selectToken = currentToken?.getPreviousOfType(TokenType.Keyword, 'SELECT') ?? null;
|
||||
return selectToken?.getNextOfType(TokenType.Keyword, FROMKEYWORD);
|
||||
};
|
||||
|
||||
const getDatabaseToken = (currentToken: LinkedToken | null) => {
|
||||
const fromToken = getFromKeywordToken(currentToken);
|
||||
const nextIdentifier = fromToken?.getNextOfType(TokenType.Identifier);
|
||||
if (nextIdentifier?.isKeyword() && nextIdentifier.next?.is(TokenType.Parenthesis, '(')) {
|
||||
return null;
|
||||
} else {
|
||||
return nextIdentifier;
|
||||
}
|
||||
};
|
||||
@@ -3,6 +3,21 @@ import { isEmpty } from 'lodash';
|
||||
import { SQLQuery } from 'app/features/plugins/sql/types';
|
||||
import { createSelectClause, haveColumns } from 'app/features/plugins/sql/utils/sql.utils';
|
||||
|
||||
// remove identifier quoting from identifier to use in metadata queries
|
||||
export function unquoteIdentifier(value: string) {
|
||||
if (value[0] === '"' && value[value.length - 1] === '"') {
|
||||
return value.substring(1, value.length - 1).replace(/""/g, '"');
|
||||
} else if (value[0] === '`' && value[value.length - 1] === '`') {
|
||||
return value.substring(1, value.length - 1);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
export function quoteLiteral(value: string) {
|
||||
return "'" + value.replace(/'/g, "''") + "'";
|
||||
}
|
||||
|
||||
export function toRawSql({ sql, dataset, table }: SQLQuery): string {
|
||||
let rawQuery = '';
|
||||
|
||||
@@ -43,3 +58,283 @@ export function toRawSql({ sql, dataset, table }: SQLQuery): string {
|
||||
}
|
||||
|
||||
const isLimit = (limit: number | undefined): boolean => limit !== undefined && limit >= 0;
|
||||
|
||||
// Puts double quotes (") around the identifier if it is necessary.
|
||||
export function quoteIdentifierIfNecessary(value: string) {
|
||||
return isValidIdentifier(value) ? value : `\"${value}\"`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the identifier from MySql and returns true if it
|
||||
* doesn't need to be escaped.
|
||||
*/
|
||||
export function isValidIdentifier(identifier: string): boolean {
|
||||
const isValidName = /^[a-zA-Z_][a-zA-Z0-9_$]*$/g.test(identifier);
|
||||
const isReservedWord = RESERVED_WORDS.includes(identifier.toUpperCase());
|
||||
return !isReservedWord && isValidName;
|
||||
}
|
||||
|
||||
const RESERVED_WORDS = [
|
||||
'ACCESSIBLE',
|
||||
'ADD',
|
||||
'ALL',
|
||||
'ALTER',
|
||||
'ANALYZE',
|
||||
'AND',
|
||||
'AS',
|
||||
'ASC',
|
||||
'ASENSITIVE',
|
||||
'BEFORE',
|
||||
'BETWEEN',
|
||||
'BIGINT',
|
||||
'BINARY',
|
||||
'BLOB',
|
||||
'BOTH',
|
||||
'BY',
|
||||
'CALL',
|
||||
'CASCADE',
|
||||
'CASE',
|
||||
'CHANGE',
|
||||
'CHAR',
|
||||
'CHARACTER',
|
||||
'CHECK',
|
||||
'COLLATE',
|
||||
'COLUMN',
|
||||
'CONDITION',
|
||||
'CONSTRAINT',
|
||||
'CONTINUE',
|
||||
'CONVERT',
|
||||
'CREATE',
|
||||
'CROSS',
|
||||
'CUBE',
|
||||
'CUME_DIST',
|
||||
'CURRENT_DATE',
|
||||
'CURRENT_TIME',
|
||||
'CURRENT_TIMESTAMP',
|
||||
'CURRENT_USER',
|
||||
'CURSOR',
|
||||
'DATABASE',
|
||||
'DATABASES',
|
||||
'DAY_HOUR',
|
||||
'DAY_MICROSECOND',
|
||||
'DAY_MINUTE',
|
||||
'DAY_SECOND',
|
||||
'DEC',
|
||||
'DECIMAL',
|
||||
'DECLARE',
|
||||
'DEFAULT',
|
||||
'DELAYED',
|
||||
'DELETE',
|
||||
'DENSE_RANK',
|
||||
'DESC',
|
||||
'DESCRIBE',
|
||||
'DETERMINISTIC',
|
||||
'DISTINCT',
|
||||
'DISTINCTROW',
|
||||
'DIV',
|
||||
'DOUBLE',
|
||||
'DROP',
|
||||
'DUAL',
|
||||
'EACH',
|
||||
'ELSE',
|
||||
'ELSEIF',
|
||||
'EMPTY',
|
||||
'ENCLOSED',
|
||||
'ESCAPED',
|
||||
'EXCEPT',
|
||||
'EXISTS',
|
||||
'EXIT',
|
||||
'EXPLAIN',
|
||||
'FALSE',
|
||||
'FETCH',
|
||||
'FIRST_VALUE',
|
||||
'FLOAT',
|
||||
'FLOAT4',
|
||||
'FLOAT8',
|
||||
'FOR',
|
||||
'FORCE',
|
||||
'FOREIGN',
|
||||
'FROM',
|
||||
'FULLTEXT',
|
||||
'FUNCTION',
|
||||
'GENERATED',
|
||||
'GET',
|
||||
'GRANT',
|
||||
'GROUP',
|
||||
'GROUPING',
|
||||
'GROUPS',
|
||||
'HAVING',
|
||||
'HIGH_PRIORITY',
|
||||
'HOUR_MICROSECOND',
|
||||
'HOUR_MINUTE',
|
||||
'HOUR_SECOND',
|
||||
'IF',
|
||||
'IGNORE',
|
||||
'IN',
|
||||
'INDEX',
|
||||
'INFILE',
|
||||
'INNER',
|
||||
'INOUT',
|
||||
'INSENSITIVE',
|
||||
'INSERT',
|
||||
'INT',
|
||||
'INT1',
|
||||
'INT2',
|
||||
'INT3',
|
||||
'INT4',
|
||||
'INT8',
|
||||
'INTEGER',
|
||||
'INTERSECT',
|
||||
'INTERVAL',
|
||||
'INTO',
|
||||
'IO_AFTER_GTIDS',
|
||||
'IO_BEFORE_GTIDS',
|
||||
'IS',
|
||||
'ITERATE',
|
||||
'JOIN',
|
||||
'JSON_TABLE',
|
||||
'KEY',
|
||||
'KEYS',
|
||||
'KILL',
|
||||
'LAG',
|
||||
'LAST_VALUE',
|
||||
'LATERAL',
|
||||
'LEAD',
|
||||
'LEADING',
|
||||
'LEAVE',
|
||||
'LEFT',
|
||||
'LIKE',
|
||||
'LIMIT',
|
||||
'LINEAR',
|
||||
'LINES',
|
||||
'LOAD',
|
||||
'LOCALTIME',
|
||||
'LOCALTIMESTAMP',
|
||||
'LOCK',
|
||||
'LONG',
|
||||
'LONGBLOB',
|
||||
'LONGTEXT',
|
||||
'LOOP',
|
||||
'LOW_PRIORITY',
|
||||
'MASTER_BIND',
|
||||
'MASTER_SSL_VERIFY_SERVER_CERT',
|
||||
'MATCH',
|
||||
'MAXVALUE',
|
||||
'MEDIUMBLOB',
|
||||
'MEDIUMINT',
|
||||
'MEDIUMTEXT',
|
||||
'MIDDLEINT',
|
||||
'MINUTE_MICROSECOND',
|
||||
'MINUTE_SECOND',
|
||||
'MOD',
|
||||
'MODIFIES',
|
||||
'NATURAL',
|
||||
'NOT',
|
||||
'NO_WRITE_TO_BINLOG',
|
||||
'NTH_VALUE',
|
||||
'NTILE',
|
||||
'NULL',
|
||||
'NUMERIC',
|
||||
'OF',
|
||||
'ON',
|
||||
'OPTIMIZE',
|
||||
'OPTIMIZER_COSTS',
|
||||
'OPTION',
|
||||
'OPTIONALLY',
|
||||
'OR',
|
||||
'ORDER',
|
||||
'OUT',
|
||||
'OUTER',
|
||||
'OUTFILE',
|
||||
'OVER',
|
||||
'PARTITION',
|
||||
'PERCENT_RANK',
|
||||
'PRECISION',
|
||||
'PRIMARY',
|
||||
'PROCEDURE',
|
||||
'PURGE',
|
||||
'RANGE',
|
||||
'RANK',
|
||||
'READ',
|
||||
'READS',
|
||||
'READ_WRITE',
|
||||
'REAL',
|
||||
'RECURSIVE',
|
||||
'REFERENCES',
|
||||
'REGEXP',
|
||||
'RELEASE',
|
||||
'RENAME',
|
||||
'REPEAT',
|
||||
'REPLACE',
|
||||
'REQUIRE',
|
||||
'RESIGNAL',
|
||||
'RESTRICT',
|
||||
'RETURN',
|
||||
'REVOKE',
|
||||
'RIGHT',
|
||||
'RLIKE',
|
||||
'ROW',
|
||||
'ROWS',
|
||||
'ROW_NUMBER',
|
||||
'SCHEMA',
|
||||
'SCHEMAS',
|
||||
'SECOND_MICROSECOND',
|
||||
'SELECT',
|
||||
'SENSITIVE',
|
||||
'SEPARATOR',
|
||||
'SET',
|
||||
'SHOW',
|
||||
'SIGNAL',
|
||||
'SMALLINT',
|
||||
'SPATIAL',
|
||||
'SPECIFIC',
|
||||
'SQL',
|
||||
'SQLEXCEPTION',
|
||||
'SQLSTATE',
|
||||
'SQLWARNING',
|
||||
'SQL_BIG_RESULT',
|
||||
'SQL_CALC_FOUND_ROWS',
|
||||
'SQL_SMALL_RESULT',
|
||||
'SSL',
|
||||
'STARTING',
|
||||
'STORED',
|
||||
'STRAIGHT_JOIN',
|
||||
'SYSTEM',
|
||||
'TABLE',
|
||||
'TERMINATED',
|
||||
'THEN',
|
||||
'TINYBLOB',
|
||||
'TINYINT',
|
||||
'TINYTEXT',
|
||||
'TO',
|
||||
'TRAILING',
|
||||
'TRIGGER',
|
||||
'TRUE',
|
||||
'UNDO',
|
||||
'UNION',
|
||||
'UNIQUE',
|
||||
'UNLOCK',
|
||||
'UNSIGNED',
|
||||
'UPDATE',
|
||||
'USAGE',
|
||||
'USE',
|
||||
'USING',
|
||||
'UTC_DATE',
|
||||
'UTC_TIME',
|
||||
'UTC_TIMESTAMP',
|
||||
'VALUES',
|
||||
'VARBINARY',
|
||||
'VARCHAR',
|
||||
'VARCHARACTER',
|
||||
'VARYING',
|
||||
'VIRTUAL',
|
||||
'WHEN',
|
||||
'WHERE',
|
||||
'WHILE',
|
||||
'WINDOW',
|
||||
'WITH',
|
||||
'WRITE',
|
||||
'XOR',
|
||||
'YEAR_MONTH',
|
||||
'ZEROFILL',
|
||||
];
|
||||
|
||||
7
public/app/plugins/datasource/influxdb/fsql/types.ts
Normal file
7
public/app/plugins/datasource/influxdb/fsql/types.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { SQLOptions, SQLQuery } from 'app/features/plugins/sql/types';
|
||||
|
||||
export interface FlightSQLOptions extends SQLOptions {
|
||||
allowCleartextPasswords?: boolean;
|
||||
}
|
||||
|
||||
export interface FlightSQLQuery extends SQLQuery {}
|
||||
Reference in New Issue
Block a user