From 54be8a09d763f6e81eda400d81c77dbe781b80e5 Mon Sep 17 00:00:00 2001 From: taozhi8833998 Date: Sun, 19 May 2024 07:25:21 +0800 Subject: [PATCH 1/2] feat: support multiple set items in mysql --- pegjs/athena.pegjs | 8 +++++++- pegjs/bigquery.pegjs | 8 +++++++- pegjs/db2.pegjs | 8 +++++++- pegjs/flinksql.pegjs | 12 +++++++++--- pegjs/hive.pegjs | 8 +++++++- pegjs/mariadb.pegjs | 8 +++++++- pegjs/mysql.pegjs | 8 +++++++- pegjs/noql.pegjs | 16 +++++++--------- pegjs/postgresql.pegjs | 12 +++++++++--- pegjs/redshift.pegjs | 15 +++++++-------- pegjs/snowflake.pegjs | 15 +++++++-------- pegjs/sqlite.pegjs | 8 +++++++- pegjs/transactsql.pegjs | 13 +++++++++---- pegjs/trino.pegjs | 15 +++++++-------- src/command.js | 8 ++++---- test/mysql-mariadb.spec.js | 7 +++++++ 16 files changed, 115 insertions(+), 54 deletions(-) diff --git a/pegjs/athena.pegjs b/pegjs/athena.pegjs index 7ddfc14c..c81a09bc 100644 --- a/pegjs/athena.pegjs +++ b/pegjs/athena.pegjs @@ -860,13 +860,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -2519,6 +2520,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { return { diff --git a/pegjs/bigquery.pegjs b/pegjs/bigquery.pegjs index 8e2d2790..3f31f91a 100644 --- a/pegjs/bigquery.pegjs +++ b/pegjs/bigquery.pegjs @@ -447,6 +447,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { return { @@ -705,13 +710,14 @@ alter_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } diff --git a/pegjs/db2.pegjs b/pegjs/db2.pegjs index 536fc1de..0857d6bb 100644 --- a/pegjs/db2.pegjs +++ b/pegjs/db2.pegjs @@ -921,13 +921,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -2486,6 +2487,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { return { diff --git a/pegjs/flinksql.pegjs b/pegjs/flinksql.pegjs index 9c32a489..36691a7d 100644 --- a/pegjs/flinksql.pegjs +++ b/pegjs/flinksql.pegjs @@ -1528,20 +1528,21 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { /* export interface set_stmt_node { type: 'set'; - expr: assign_stmt & { keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY'; }; + keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY' | undefined; + expr: assign_stmt; } => AstStatement */ - a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -3621,6 +3622,11 @@ proc_stmt return { type: 'proc', stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { // => { type: 'assign'; left: var_decl | without_prefix_var_decl; symbol: ':=' | '='; right: proc_expr; } diff --git a/pegjs/hive.pegjs b/pegjs/hive.pegjs index e672405e..d116be61 100644 --- a/pegjs/hive.pegjs +++ b/pegjs/hive.pegjs @@ -860,13 +860,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -2487,6 +2488,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { return { diff --git a/pegjs/mariadb.pegjs b/pegjs/mariadb.pegjs index 6dd8cb84..d3e6069e 100644 --- a/pegjs/mariadb.pegjs +++ b/pegjs/mariadb.pegjs @@ -1482,13 +1482,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -3747,6 +3748,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { return { diff --git a/pegjs/mysql.pegjs b/pegjs/mysql.pegjs index cc7ddcf4..7c220b84 100644 --- a/pegjs/mysql.pegjs +++ b/pegjs/mysql.pegjs @@ -1705,13 +1705,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -4068,6 +4069,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { return { diff --git a/pegjs/noql.pegjs b/pegjs/noql.pegjs index 7733dc03..206e29b6 100644 --- a/pegjs/noql.pegjs +++ b/pegjs/noql.pegjs @@ -2135,20 +2135,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { - /* - export interface set_stmt_node { - type: 'set'; - expr: assign_stmt & { keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY'; }; - } - => AstStatement - */ + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -5047,6 +5041,11 @@ proc_stmt return { type: 'proc', stmt: s, vars: varList } } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { // => { type: 'assign'; left: var_decl | without_prefix_var_decl; symbol: ':=' | '='; right: proc_expr; } @@ -5058,7 +5057,6 @@ assign_stmt }; } - return_stmt = KW_RETURN __ e:proc_expr { // => { type: 'return'; expr: proc_expr; } diff --git a/pegjs/postgresql.pegjs b/pegjs/postgresql.pegjs index 95bbb578..cc01de96 100644 --- a/pegjs/postgresql.pegjs +++ b/pegjs/postgresql.pegjs @@ -2267,20 +2267,21 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { /* export interface set_stmt_node { type: 'set'; - expr: assign_stmt & { keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY'; }; + keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY' | undefined; + expr: assign_stmt; } => AstStatement */ - a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -5258,6 +5259,11 @@ proc_stmt return { type: 'proc', stmt: s, vars: varList } } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s:(KW_ASSIGN / KW_ASSIGIN_EQUAL / KW_TO) __ e:proc_expr { // => { type: 'assign'; left: var_decl | without_prefix_var_decl; symbol: ':=' | '='; right: proc_expr; } diff --git a/pegjs/redshift.pegjs b/pegjs/redshift.pegjs index 29d3b6cc..5b9528c5 100644 --- a/pegjs/redshift.pegjs +++ b/pegjs/redshift.pegjs @@ -2152,20 +2152,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { - /* - export interface set_stmt_node { - type: 'set'; - expr: assign_stmt & { keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY'; }; - } - => AstStatement - */ + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -5119,6 +5113,11 @@ proc_stmt return { type: 'proc', stmt: s, vars: varList } } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s:(KW_ASSIGN / KW_ASSIGIN_EQUAL / KW_TO) __ e:proc_expr { // => { type: 'assign'; left: var_decl | without_prefix_var_decl; symbol: ':=' | '='; right: proc_expr; } diff --git a/pegjs/snowflake.pegjs b/pegjs/snowflake.pegjs index e0f52ede..98b224c2 100644 --- a/pegjs/snowflake.pegjs +++ b/pegjs/snowflake.pegjs @@ -1857,20 +1857,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { - /* - export interface set_stmt_node { - type: 'set'; - expr: assign_stmt & { keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY'; }; - } - => AstStatement - */ + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -4529,6 +4523,11 @@ proc_stmt return { type: 'proc', stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { // => { type: 'assign'; left: var_decl | without_prefix_var_decl; symbol: ':=' | '='; right: proc_expr; } diff --git a/pegjs/sqlite.pegjs b/pegjs/sqlite.pegjs index 8d9031cd..1bc1d990 100644 --- a/pegjs/sqlite.pegjs +++ b/pegjs/sqlite.pegjs @@ -986,13 +986,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -2692,6 +2693,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { return { diff --git a/pegjs/transactsql.pegjs b/pegjs/transactsql.pegjs index 51e73830..2aa6e28d 100644 --- a/pegjs/transactsql.pegjs +++ b/pegjs/transactsql.pegjs @@ -1284,14 +1284,14 @@ set_stmt columnList: columnListTableAlias(columnList), ast: { type: 'set', - expr: { + expr: [{ type: 'assign', left: { type: 'origin', value: 'transaction isolation level' }, right: e - } + }] } } } @@ -1301,11 +1301,11 @@ set_stmt columnList: columnListTableAlias(columnList), ast: { type: 'set', - expr: { + expr: [{ type: 'assign', left: va, right: e - } + }] } } } @@ -3176,6 +3176,11 @@ proc_stmt return { stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL)? __ e:proc_expr { return { diff --git a/pegjs/trino.pegjs b/pegjs/trino.pegjs index 630c3643..17954878 100644 --- a/pegjs/trino.pegjs +++ b/pegjs/trino.pegjs @@ -1886,20 +1886,14 @@ rename_stmt set_stmt = KW_SET __ kw: (KW_GLOBAL / KW_SESSION / KW_LOCAL / KW_PERSIST / KW_PERSIST_ONLY)? __ - a: assign_stmt { - /* - export interface set_stmt_node { - type: 'set'; - expr: assign_stmt & { keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY'; }; - } - => AstStatement - */ + a: assign_stmt_list { a.keyword = kw return { tableList: Array.from(tableList), columnList: columnListTableAlias(columnList), ast: { type: 'set', + keyword: kw, expr: a } } @@ -4570,6 +4564,11 @@ proc_stmt return { type: 'proc', stmt: s, vars: varList }; } +assign_stmt_list + = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + return createList(head, tail); + } + assign_stmt = va:(var_decl / without_prefix_var_decl) __ s: (KW_ASSIGN / KW_ASSIGIN_EQUAL) __ e:proc_expr { // => { type: 'assign'; left: var_decl | without_prefix_var_decl; symbol: ':=' | '='; right: proc_expr; } diff --git a/src/command.js b/src/command.js index 171b78b0..cf8bd2f7 100644 --- a/src/command.js +++ b/src/command.js @@ -90,10 +90,10 @@ function useToSQL(stmt) { } function setVarToSQL(stmt) { - const { expr } = stmt - const action = 'SET' - const val = exprToSQL(expr) - return `${action} ${val}` + const { type, expr, keyword } = stmt + const action = toUpper(type) + const setItems = expr.map(exprToSQL).join(', ') + return [action, toUpper(keyword), setItems].filter(hasVal).join(' ') } function pgLock(stmt) { diff --git a/test/mysql-mariadb.spec.js b/test/mysql-mariadb.spec.js index b5a93f82..4e582c01 100644 --- a/test/mysql-mariadb.spec.js +++ b/test/mysql-mariadb.spec.js @@ -1016,6 +1016,13 @@ describe('mysql', () => { "SELECT `d`.`Fdrug_hash_id` FROM `t_xxxx` AS `d` WHERE `d`.`Fapproval_number` LIKE '\tH20190022%'" ] }, + { + title: 'multiple set', + sql: [ + "SET @_mystoredprocedure_0='1',@_mystoredprocedure_1='2'", + "SET @_mystoredprocedure_0 = '1', @_mystoredprocedure_1 = '2'" + ] + }, ] SQL_LIST.forEach(sqlInfo => { const { title, sql } = sqlInfo From a8ea6b96914c0ce995737bdfd6ff27536c2ec88e Mon Sep 17 00:00:00 2001 From: taozhi8833998 Date: Mon, 20 May 2024 08:56:06 +0800 Subject: [PATCH 2/2] fix: pg type generation --- ast/postgresql.ts | 5 ++++- pegjs/postgresql.pegjs | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ast/postgresql.ts b/ast/postgresql.ts index 729d9892..a995798c 100644 --- a/ast/postgresql.ts +++ b/ast/postgresql.ts @@ -618,7 +618,8 @@ export type rename_stmt = AstStatement; export interface set_stmt_node { type: 'set'; - expr: assign_stmt & { keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY'; }; + keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY' | undefined; + expr: assign_stmt_list; } export type set_stmt = AstStatement; @@ -1791,6 +1792,8 @@ export interface proc_stmt_t { type: 'proc'; stmt: assign_stmt | return_stmt; va export type proc_stmt = AstStatement; +export type assign_stmt_list = assign_stmt[]; + export type assign_stmt = { type: 'assign'; left: var_decl | without_prefix_var_decl; symbol: ':=' | '='; right: proc_expr; }; export type return_stmt = { type: 'return'; expr: proc_expr; }; diff --git a/pegjs/postgresql.pegjs b/pegjs/postgresql.pegjs index cc01de96..39729da6 100644 --- a/pegjs/postgresql.pegjs +++ b/pegjs/postgresql.pegjs @@ -2272,7 +2272,7 @@ set_stmt export interface set_stmt_node { type: 'set'; keyword?: 'GLOBAL' | 'SESSION' | 'LOCAL' | 'PERSIST' | 'PERSIST_ONLY' | undefined; - expr: assign_stmt; + expr: assign_stmt_list; } => AstStatement */ @@ -5261,6 +5261,7 @@ proc_stmt assign_stmt_list = head:assign_stmt tail:(__ COMMA __ assign_stmt)* { + // => assign_stmt[] return createList(head, tail); }