From 7f22270b6f37f19487421b12761459c470088246 Mon Sep 17 00:00:00 2001 From: taozhi8833998 Date: Tue, 9 Apr 2024 08:53:22 +0800 Subject: [PATCH] fix: support collate after multiple conditions in brackets in mysql --- pegjs/mariadb.pegjs | 11 +++++++---- pegjs/mysql.pegjs | 11 +++++++---- src/binary.js | 15 +++++++++++++-- test/mysql-mariadb.spec.js | 9 ++++++++- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/pegjs/mariadb.pegjs b/pegjs/mariadb.pegjs index 1c5429ae..52ee1584 100644 --- a/pegjs/mariadb.pegjs +++ b/pegjs/mariadb.pegjs @@ -2181,7 +2181,10 @@ on_clause = KW_ON __ e:or_and_expr { return e; } where_clause - = KW_WHERE __ e:(or_and_where_expr) { return e; } + = KW_WHERE __ e:or_and_where_expr __ ca:collate_expr? { + if (ca) e.suffix = [ca] + return e; + } group_by_clause = KW_GROUP __ KW_BY __ e:expr_list { return e.value; } @@ -2742,9 +2745,9 @@ primary / column_ref / param / LPAREN __ list:or_and_where_expr __ RPAREN { - list.parentheses = true; - return list; - } + list.parentheses = true; + return list + } / var_decl / __ prepared_symbol:'?' { return { diff --git a/pegjs/mysql.pegjs b/pegjs/mysql.pegjs index 75bcf25a..2550663b 100644 --- a/pegjs/mysql.pegjs +++ b/pegjs/mysql.pegjs @@ -2450,7 +2450,10 @@ on_clause = KW_ON __ e:or_and_expr { return e; } where_clause - = KW_WHERE __ e:or_and_where_expr { return e; } + = KW_WHERE __ e:or_and_where_expr __ ca:collate_expr? { + if (ca) e.suffix = [ca] + return e; + } group_by_clause = KW_GROUP __ KW_BY __ e:expr_list { return e.value; } @@ -3025,9 +3028,9 @@ primary / column_ref / param / LPAREN __ list:or_and_where_expr __ RPAREN { - list.parentheses = true; - return list; - } + list.parentheses = true + return list + } / var_decl / __ prepared_symbol:'?' { return { diff --git a/src/binary.js b/src/binary.js index a269fada..eb450277 100644 --- a/src/binary.js +++ b/src/binary.js @@ -1,5 +1,5 @@ import { exprToSQL } from './expr' -import { hasVal, toUpper } from './util' +import { commonTypeValue, hasVal, toUpper } from './util' function binaryToSQL(expr) { let operator = expr.operator || expr.op @@ -25,7 +25,18 @@ function binaryToSQL(expr) { } const escape = expr.right.escape || {} const str = [exprToSQL(expr.left), operator, rstr, toUpper(escape.type), exprToSQL(escape.value)].filter(hasVal).join(' ') - return expr.parentheses ? `(${str})` : str + const result = [expr.parentheses ? `(${str})` : str] + const { suffix } = expr + if (!suffix) return result.join(' ') + for (const suffixItem of suffix) { + const { type } = suffixItem + switch (type) { + case 'collate': + result.push(commonTypeValue(suffixItem).join(' ')) + break + } + } + return result.filter(hasVal).join(' ') } export { diff --git a/test/mysql-mariadb.spec.js b/test/mysql-mariadb.spec.js index 7db5fbc0..2e312cbc 100644 --- a/test/mysql-mariadb.spec.js +++ b/test/mysql-mariadb.spec.js @@ -949,7 +949,14 @@ describe('mysql', () => { 'show index from user', 'SHOW INDEX FROM `user`' ] - } + }, + { + title: 'collate in where clause include parentheses', + sql: [ + "SELECT * FROM product WHERE (id = '1' OR id = '2') COLLATE utf8mb4_general_ci;", + "SELECT * FROM `product` WHERE (`id` = '1' OR `id` = '2') COLLATE UTF8MB4_GENERAL_CI" + ] + }, ] SQL_LIST.forEach(sqlInfo => { const { title, sql } = sqlInfo