From 279aa4863bfefb802b53bb4d1c44574a8e7281d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Farkas?= Date: Mon, 22 Jan 2024 15:36:45 +0100 Subject: [PATCH] Postgres: Handle single quotes in table names in the query editor (#80951) postgres: handle single quotes in table names --- .../grafana-postgresql-datasource/datasource.ts | 7 ++++++- .../postgresMetaQuery.test.ts | 14 ++++++++++++++ .../postgresMetaQuery.ts | 9 +++++++-- 3 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.test.ts diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts b/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts index 173c17fd7d8..eca17ba04c5 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/datasource.ts @@ -67,7 +67,12 @@ export class PostgresDatasource extends SqlDatasource { } async fetchFields(query: SQLQuery): Promise { - const schema = await this.runSql<{ column: string; type: string }>(getSchema(query.table), { refId: 'columns' }); + const { table } = query; + if (table === undefined) { + // if no table-name, we are not able to query for fields + return []; + } + const schema = await this.runSql<{ column: string; type: string }>(getSchema(table), { refId: 'columns' }); const result: SQLSelectableValue[] = []; for (let i = 0; i < schema.length; i++) { const column = schema.fields.column.values[i]; diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.test.ts b/public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.test.ts new file mode 100644 index 00000000000..1ba58784c71 --- /dev/null +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.test.ts @@ -0,0 +1,14 @@ +import { getSchema } from './postgresMetaQuery'; + +describe('postgredsMetaQuery.getSchema', () => { + it('should handle table-names with single quote', () => { + // testing multi-line with single-quote, double-quote, backtick + const tableName = `'a''bcd'efg'h' "a""b" ` + '`x``y`z' + `\n a'b''c`; + const escapedName = `''a''''bcd''efg''h'' "a""b" ` + '`x``y`z' + `\n a''b''''c`; + + const schemaQuery = getSchema(tableName); + + expect(schemaQuery.includes(escapedName)).toBeTruthy(); + expect(schemaQuery.includes(tableName)).toBeFalsy(); + }); +}); diff --git a/public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.ts b/public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.ts index 80b0466f91c..664a8e9c4dc 100644 --- a/public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.ts +++ b/public/app/plugins/datasource/grafana-postgresql-datasource/postgresMetaQuery.ts @@ -19,10 +19,15 @@ export function showTables() { and ${buildSchemaConstraint()}`; } -export function getSchema(table?: string) { +export function getSchema(table: string) { + // we will put table-name between single-quotes, so we need to escape single-quotes + // in the table-name + const tableNamePart = "'" + table.replace(/'/g, "''") + "'"; + return `select quote_ident(column_name) as "column", data_type as "type" from information_schema.columns - where quote_ident(table_name) = '${table}'`; + where quote_ident(table_name) = ${tableNamePart}; + `; } function buildSchemaConstraint() {