tidb parser RestoreWithDefaultDB SubqueryExpr 加括号后,tidb低版本不兼容问题

问题描述

当使用RestoreWithDefaultDB方法还原SQL时,子查询自动添加上括号,导致TiDB执行SQL时报语法错误。目前受影响的版本为:TiDB V5.04以下

TiDB Parser版本

github.com/pingcap/tidb/parser v0.0.0-20230530104642-635a4362235e

表结构

CREATE TABLE `a` (
    `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    PRIMARY KEY (`ID`)
) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

CREATE TABLE `b` (
    `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    PRIMARY KEY (`ID`)
) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

CREATE TABLE `c` (
    `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
    PRIMARY KEY (`ID`)
) ENGINE = InnoDB AUTO_INCREMENT = 3 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

原SQL语句

SELECT
    *
FROM
    (
        SELECT
            prov.id
        FROM
            (
                SELECT
                    id
                FROM
                    `a`
            ) AS `prov`
            JOIN (
                SELECT
                    id
                FROM
                    `b`
            ) AS `mon`
            LEFT JOIN (
                SELECT
                    id
                FROM
                    `c` AS `d`
            ) AS `amt` ON `prov`.`id` = `amt`.`id`
            AND `mon`.`id` = `amt`.`id`
    ) AS `r`;

将原始SQL解析成stmt,然后使用utilparser.RestoreWithDefaultDB还原SQL

SELECT
    *
FROM
    (
        SELECT
            prov.id
        FROM
            (
                (
                    SELECT
                        id
                    FROM
                        a
                ) AS prov
                JOIN (
                    SELECT
                        id
                    FROM
                        b
                ) AS mon
            )
            LEFT JOIN (
                SELECT
                    id
                FROM
                    c AS d
            ) AS amt ON prov.id = amt.id
            AND mon.id = amt.id
    ) AS r

可以发现还原后的SQL,自动添加了括号,导致低版本的TiDB支持报错

由于目前公司有多套TiDB集群,且版本不统一,请问如何解决?
在使用utilparser.RestoreWithDefaultDB方法时,如何对SubqueryExpr部分进行处理?

这个也算正常吧。官方文档明确说了不支持降级和版本回退。一般是向上兼容,向下不兼容。

感觉只能在程序上检测数据库版本然后做分支处理了。我们现在兼容mysql和tidb,就是在程序里判断兼容的。

建议修改查询语句