From 79d4a87cc7f40eea5124573eb55fe75e830964cb Mon Sep 17 00:00:00 2001 From: taozhi8833998 Date: Thu, 11 Jul 2024 09:51:42 +0800 Subject: [PATCH] feat: support explain stmt in mysql --- pegjs/mariadb.pegjs | 13 +++++++++++++ pegjs/mysql.pegjs | 13 +++++++++++++ src/explain.js | 11 +++++++++++ src/sql.js | 2 +- src/union.js | 2 ++ test/mysql-mariadb.spec.js | 9 ++++++++- 6 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 src/explain.js diff --git a/pegjs/mariadb.pegjs b/pegjs/mariadb.pegjs index 69a9a696..1b12321b 100644 --- a/pegjs/mariadb.pegjs +++ b/pegjs/mariadb.pegjs @@ -248,6 +248,7 @@ cmd_stmt / show_stmt / desc_stmt / grant_stmt + / explain_stmt create_stmt = create_table_stmt @@ -1663,6 +1664,18 @@ desc_stmt }; } +explain_stmt + = KW_EXPLAIN __ t:select_stmt_nake { + return { + tableList: Array.from(tableList), + columnList: columnListTableAlias(columnList), + ast: { + type: 'explain', + expr: t + } + } + } + lock_type = "READ"i __ s:("LOCAL"i)? { return { diff --git a/pegjs/mysql.pegjs b/pegjs/mysql.pegjs index 1436784c..94e4f7c1 100644 --- a/pegjs/mysql.pegjs +++ b/pegjs/mysql.pegjs @@ -445,6 +445,7 @@ cmd_stmt / show_stmt / desc_stmt / grant_stmt + / explain_stmt create_stmt = create_table_stmt @@ -1938,6 +1939,18 @@ desc_stmt }; } +explain_stmt + = KW_EXPLAIN __ t:select_stmt_nake { + return { + tableList: Array.from(tableList), + columnList: columnListTableAlias(columnList), + ast: { + type: 'explain', + expr: t + } + } + } + priv_type_table = p:(KW_ALL / KW_ALTER / KW_CREATE __ 'VIEW'i / KW_CREATE / KW_DELETE / KW_DROP / 'GRANT'i __ 'OPTION'i / KW_INDEX / KW_INSERT / KW_REFERENCES / KW_SELECT / KW_SHOW __ KW_VIEW / KW_TRIGGER / KW_UPDATE) { return { diff --git a/src/explain.js b/src/explain.js new file mode 100644 index 00000000..9e12392b --- /dev/null +++ b/src/explain.js @@ -0,0 +1,11 @@ +import { selectToSQL } from './select' +import { toUpper } from './util' + +function explainToSQL(stmt) { + const { type, expr } = stmt + return [toUpper(type), selectToSQL(expr)].join(' ') +} + +export { + explainToSQL, +} diff --git a/src/sql.js b/src/sql.js index b5aa786f..2ac20db7 100644 --- a/src/sql.js +++ b/src/sql.js @@ -1,6 +1,6 @@ import { unionToSQL, multipleToSQL } from './union' -const supportedTypes = ['analyze', 'attach', 'select', 'deallocate', 'delete', 'exec', 'update', 'insert', 'drop', 'rename', 'truncate', 'call', 'desc', 'use', 'alter', 'set', 'create', 'lock', 'unlock', 'declare', 'show', 'replace', 'if', 'grant', 'revoke', 'proc', 'raise', 'execute', 'transaction'] +const supportedTypes = ['analyze', 'attach', 'select', 'deallocate', 'delete', 'exec', 'update', 'insert', 'drop', 'rename', 'truncate', 'call', 'desc', 'use', 'alter', 'set', 'create', 'lock', 'unlock', 'declare', 'show', 'replace', 'if', 'grant', 'revoke', 'proc', 'raise', 'execute', 'transaction', 'explain'] function checkSupported(expr) { const ast = expr && expr.ast ? expr.ast : expr diff --git a/src/union.js b/src/union.js index a286b993..d35ac59d 100644 --- a/src/union.js +++ b/src/union.js @@ -1,6 +1,7 @@ import { alterToSQL } from './alter' import { analyzeToSQL, attachToSQL } from './analyze' import { createToSQL } from './create' +import { explainToSQL } from './explain' import { selectToSQL } from './select' import { deleteToSQL } from './delete' import { updateToSQL } from './update' @@ -39,6 +40,7 @@ const typeToSQLFn = { delete : deleteToSQL, exec : execToSQL, execute : executeToSQL, + explain : explainToSQL, for : forLoopToSQL, update : updateToSQL, if : ifToSQL, diff --git a/test/mysql-mariadb.spec.js b/test/mysql-mariadb.spec.js index f12c8dac..a53f49d5 100644 --- a/test/mysql-mariadb.spec.js +++ b/test/mysql-mariadb.spec.js @@ -1064,12 +1064,19 @@ describe('mysql', () => { ] }, { - title: 'collate2', + title: 'collate with symbol and value', sql: [ 'select * from test where id COLLATE utf8mb4_unicode_ci = abc', 'SELECT * FROM `test` WHERE `id` COLLATE utf8mb4_unicode_ci = abc' ] }, + { + title: 'explain stmt', + sql: [ + 'EXPLAIN SELECT * FROM incidents where id > 10 and is_delete = 0', + 'EXPLAIN SELECT * FROM `incidents` WHERE `id` > 10 AND `is_delete` = 0' + ] + }, ] SQL_LIST.forEach(sqlInfo => { const { title, sql } = sqlInfo