信创MySQL到达梦数据库的SQL语法转换技术解析

发布于:2025-09-05 ⋅ 阅读:(16) ⋅ 点赞:(0)

信创背景下MySQL到达梦数据库的SQL语法转换技术解析

一、背景介绍

在信创(信息技术应用创新)产业快速发展的背景下,国产数据库的替代已成为必然趋势。达梦数据库作为国产数据库的重要代表,在企业级应用中逐渐取代MySQL等国外数据库产品。然而,由于SQL语法在不同数据库间存在差异,如何实现平滑迁移成为亟需解决的技术难题。

本文基于实际的SQL语法转换器实现,深入解析MySQL到达梦数据库的SQL转换技术方案。

二、整体架构设计

2.1 核心转换流程

SQL转换器的核心架构采用抽象语法树(AST)解析+策略模式的设计:

// 基类定义通用转换框架
public abstract class BaseConverter {
    // 存储各类SQL语句的转换结果
    public List<String> creatTableList = new ArrayList<>();
    public List<String> commentList = new ArrayList<>();
    // ...其他语句列表
    
    // 策略映射表:语句类型→处理函数
    private final Map<Class<?>, Consumer<Object>> conversionStrategies = new HashMap<>();
    
    // 初始化策略映射
    public BaseConverter() {
        conversionStrategies.put(MySqlCreateTableStatement.class, stmt -> convertCreateTabletStatement((MySqlCreateTableStatement) stmt));
        conversionStrategies.put(MySqlInsertStatement.class, stmt -> convertInsertStatement((MySqlInsertStatement) stmt));
        // ...其他语句类型映射
    }
}

2.2 转换执行流程

  1. SQL解析:使用Druid解析器将原始SQL转换为AST
  2. 语句分发:根据语句类型选择对应的处理策略
  3. 语法转换:针对特定数据库进行语法适配
  4. 结果收集:将转换后的SQL语句分类存储

三、关键技术实现

3.1 函数映射转换

不同数据库的函数差异是转换的重点难点,我们采用函数映射表的方式解决:

// MySQL与达梦函数映射表
private static final Map<String, String> FUNCTION_MAPPING = new HashMap<>();
static {
    FUNCTION_MAPPING.put("CONCAT", "||");
    FUNCTION_MAPPING.put("NOW()", "SYSDATE");
    FUNCTION_MAPPING.put("DATE_FORMAT", "TO_CHAR");
    FUNCTION_MAPPING.put("SUBSTRING", "SUBSTR");
    FUNCTION_MAPPING.put("IFNULL", "NVL");
    FUNCTION_MAPPING.put("UUID", "SYS_GUID");
    // ...更多函数映射
}

3.2 分页语法转换

MySQL的LIMIT语法与达梦的ROWNUM语法存在显著差异:

private static String convertPagination(String query) {
    // 转换 LIMIT offset, size 语法
    Pattern pattern1 = Pattern.compile("LIMIT\\s+(\\d+)\\s*,\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
    Matcher matcher1 = pattern1.matcher(query);
    if (matcher1.find()) {
        String offset = matcher1.group(1);
        String limit = matcher1.group(2);
        return matcher1.replaceFirst("OFFSET " + offset + " FETCH FIRST " + limit + " ROWS ONLY");
    }
    // 其他分页模式处理...
}

3.3 数据类型映射

数据类型在不同数据库间存在差异,需要特殊处理:

// 数据类型转换示例
if ("VARCHAR".equals(dataTypeName)) {
    builder.append("\"").append(columnName).append("\" ").append(dataTypeName)
          .append("(").append(sqlIntegerExpr.getNumber()).append(")");
} else if ("TIMESTAMP".equals(dataTypeName) || "DATETIME".equals(dataTypeName)) {
    builder.append("\"").append(columnName).append("\" ").append("TIMESTAMP(0)");
} else if ("BIT".equals(dataTypeName)) {
    builder.append("\"").append(columnName).append("\" ").append("TINYINT");
}
// ...更多类型处理

四、复杂语句处理

4.1 CREATE TABLE语句解析

建表语句涉及表结构、约束、索引等多方面内容:

@Override
public void convertCreateTabletStatement(MySqlCreateTableStatement statement) {
    String tableName = statement.getTableName().replace("`", "").toUpperCase();
    
    // 处理表注释
    if (Objects.nonNull(statement.getComment())) {
        commentList.add("COMMENT ON TABLE \"" + tableName + "\"" + " IS '" + comment + "';");
    }
    
    // 处理表元素(列、约束等)
    statement.getTableElementList().forEach(column -> {
        if (column instanceof SQLColumnDefinition) {
            // 列定义处理
            processColumnDefinition((SQLColumnDefinition) column, tableName);
        } else if (column instanceof MySqlPrimaryKey) {
            // 主键约束处理
            processPrimaryKey((MySqlPrimaryKey) column, tableName);
        }
        // ...其他元素类型
    });
}

4.2 SELECT查询处理

查询语句需要处理函数、别名、关联查询等复杂场景:

private String processSelectQuery(SQLSelectQuery query) {
    if (query instanceof SQLSelectQueryBlock) {
        SQLSelectQueryBlock block = (SQLSelectQueryBlock) query;
        
        // 处理SELECT子句
        processSelectItems(block.getSelectList());
        
        // 处理FROM子句
        processTableSource(block.getFrom());
        
        // 处理WHERE条件
        processWhereCondition(block.getWhere());
        
        // 处理GROUP BY和HAVING
        processGroupBy(block.getGroupBy());
        
        // 处理分页
        processLimit(block.getLimit());
    }
    // ...联合查询处理
}

五、特殊场景处理

5.1 自增字段处理

达梦使用IDENTITY语法替代MySQL的AUTO_INCREMENT:

if (autoIncrement) {
    if (StringUtils.isNotBlank(increment)) {
        builder.append(" IDENTITY(").append(increment).append(",1)");
    } else {
        builder.append(" IDENTITY(1,1)");
    }
}

5.2 索引和约束处理

不同数据库的索引创建语法需要适配:

// 唯一索引转换
if ("UNIQUE".equals(type)) {
    String indexName = "UNIQUE_" + tableName + "_" + StringUtils.join(keys, "_");
    indexList.add("ALTER TABLE \"" + tableName + "\" ADD CONSTRAINT \"" + indexName 
                 + "\" UNIQUE(" + StringUtils.join(keys, ",") + ");");
} else {
    // 普通索引
    String indexName = "IDX_" + tableName + "_" + StringUtils.join(keys, "_");
    indexList.add("CREATE INDEX \"" + indexName + "\" ON \"" + tableName 
                 + "\"(" + StringUtils.join(keys, ",") + ");");
}

六、转换效果示例

MySQL原始SQL:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL,
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';

SELECT * FROM `user` WHERE DATE_FORMAT(create_time, '%Y-%m-%d') = '2023-01-01' LIMIT 10;

转换后的达梦SQL:

CREATE TABLE "USER" (
  "ID" INT IDENTITY(1,1) NOT NULL,
  "NAME" VARCHAR(50) NULL,
  "CREATE_TIME" TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP NULL
);
COMMENT ON TABLE "USER" IS '用户表';
COMMENT ON COLUMN "USER"."ID" IS '';

SELECT * FROM "USER" WHERE TO_CHAR(CREATE_TIME, 'YYYY-MM-DD') = '2023-01-01' FETCH FIRST 10 ROWS ONLY;

七、原始代码

基础代码

import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
import com.alibaba.druid.util.JdbcConstants;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;


public abstract class BaseConverter {

    /**
     * createTable sql语句
     */
    public List<String> creatTableList = new ArrayList<>();

    /**
     * comment sql语句
     */
    public List<String> commentList = new ArrayList<>();

    /**
     * index sql语句
     */
    public List<String> indexList = new ArrayList<>();

    /**
     * alter sql语句
     */
    public List<String> alterList = new ArrayList<>();

    /**
     * insert sql语句
     */
    public List<String> insertList = new ArrayList<>();

    /**
     * update sql语句
     */
    public List<String> updateList = new ArrayList<>();

    /**
     * select sql语句
     */
    public List<String> selectList = new ArrayList<>();

    /**
     * sequence sql语句
     */
    public List<String> sequenceList = new ArrayList<>();

    /**
     * alterSequence sql语句
     */
    public List<String> alterSequenceList = new ArrayList<>();

    /**
     * sql别名及函数
     */
    public final Map<String, SQLExpr> selectAliasMap = new HashMap<>();

    /**
     * SQL语法树映射
     */
    private final Map<Class<?>, Consumer<Object>> conversionStrategies = new HashMap<>();

    /**
     * 初始化策略映射
     */
    public BaseConverter() {
        conversionStrategies.put(MySqlCreateTableStatement.class, stmt -> convertCreateTabletStatement((MySqlCreateTableStatement) stmt));
        conversionStrategies.put(MySqlInsertStatement.class, stmt -> convertInsertStatement((MySqlInsertStatement) stmt));
        conversionStrategies.put(SQLCreateIndexStatement.class, stmt -> convertCreateIndexStatement((SQLCreateIndexStatement) stmt));
        conversionStrategies.put(MySqlUpdateStatement.class, stmt -> convertUpdateStatement((MySqlUpdateStatement) stmt));
        conversionStrategies.put(MySqlDeleteStatement.class, stmt -> convertDeleteStatement((MySqlDeleteStatement) stmt));
        conversionStrategies.put(SQLAlterTableStatement.class, stmt -> convertAlterTableStatement((SQLAlterTableStatement) stmt));
        conversionStrategies.put(MySqlRenameTableStatement.class, stmt -> convertRenameTableStatement((MySqlRenameTableStatement) stmt));
        conversionStrategies.put(SQLDropTableStatement.class, stmt -> convertDropTableStatement((SQLDropTableStatement) stmt));
        conversionStrategies.put(SQLTruncateStatement.class, stmt -> convertTruncateStatement((SQLTruncateStatement) stmt));
        conversionStrategies.put(SQLSelectStatement.class, stmt -> convertQueryStatement((SQLSelectStatement) stmt));
    }


    /**
     * 转换器适配
     *
     * @param dbType 数据库类型
     * @return 是否适配
     */
    abstract boolean support(String dbType);


    /**
     * 翻译转换
     *
     * @return 结果集
     */
    public List<String> convert(String schemaName, String originalSql) {
        List<SQLStatement> stmtList = SQLUtils.parseStatements(originalSql, JdbcConstants.MYSQL);
        List<String> result = new ArrayList<>();
        stmtList.forEach(statement -> {
            // 语法树翻译转化
            processConvertStatement(statement);
            List<String> collect = Stream.of(creatTableList, alterSequenceList, sequenceList, commentList, indexList, alterList, insertList, updateList, selectList).
                    flatMap(Collection::stream).
                    filter(Objects::nonNull).
                    collect(Collectors.toList());
            if (collect.isEmpty()) {
                collect.add(statement.toString());
            }
            result.addAll(collect);
        });

        return result;
    }

    /**
     * 语法树翻译转化
     *
     * @param statement 抽象语法树
     */
    private void processConvertStatement(SQLStatement statement) {
        Consumer<Object> consumer = conversionStrategies.get(statement.getClass());
        if (Objects.isNull(consumer)) {
            log.error("Unsupported statement type: " + statement.getClass());
            return;
        }
        consumer.accept(statement);
    }


    /**
     * DDL-CREATE 语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertCreateTabletStatement(MySqlCreateTableStatement statement);

    /**
     * DML-INSERT 语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertInsertStatement(MySqlInsertStatement statement);

    /**
     * DDL-INDEX 语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertCreateIndexStatement(SQLCreateIndexStatement statement);

    /**
     * DML-UPDATE 语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertUpdateStatement(MySqlUpdateStatement statement);

    /**
     * DML-DELETE 语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertDeleteStatement(MySqlDeleteStatement statement);

    /**
     * DLL-ALTER TABLE 语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertAlterTableStatement(SQLAlterTableStatement statement);

    /**
     * DDL-RENAME 语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertRenameTableStatement(MySqlRenameTableStatement statement);

    /**
     * DDL-Drop语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertDropTableStatement(SQLDropTableStatement statement);

    /**
     * 截断操作语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertTruncateStatement(SQLTruncateStatement statement);

    /**
     * 查询语法树转换
     *
     * @param statement 语法树
     */
    abstract void convertQueryStatement(SQLSelectStatement statement);

}

达梦代码

import com.alibaba.druid.sql.ast.SQLCurrentTimeExpr;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLIndexDefinition;
import com.alibaba.druid.sql.ast.SQLLimit;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddColumn;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddConstraint;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableAddIndex;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLConstraint;
import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
import com.alibaba.druid.sql.ast.statement.SQLNotNullConstraint;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey;
import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableChangeColumn;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableModifyColumn;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
import com.alibaba.druid.util.JdbcConstants;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class DamengConverter extends BaseConverter {

    /**
     * 初始化策略映射
     */
    public DamengConverter() {
        super();
    }


    /**
     * 定义MySQL和达梦数据库的函数映射
     */
    private static final Map<String, String> FUNCTION_MAPPING = new HashMap<>();

    static {
        FUNCTION_MAPPING.put("CONCAT", "||");
        FUNCTION_MAPPING.put("NOW()", "SYSDATE");
        FUNCTION_MAPPING.put("CURRENT_TIMESTAMP", "CURRENT_TIMESTAMP");
        FUNCTION_MAPPING.put("DATE_FORMAT", "TO_CHAR");
        FUNCTION_MAPPING.put("SUBSTRING", "SUBSTR");
        FUNCTION_MAPPING.put("DATEDIFF", "-");
        FUNCTION_MAPPING.put("IFNULL", "NVL");
        FUNCTION_MAPPING.put("UUID", "SYS_GUID");
        FUNCTION_MAPPING.put("GROUP_CONCAT", "WM_CONCAT");
        FUNCTION_MAPPING.put("FIND_IN_SET", "INSTR");
        FUNCTION_MAPPING.put("UNIX_TIMESTAMP", "EXTRACT(EPOCH FROM SYSDATE)");
        FUNCTION_MAPPING.put("LOCATE", "INSTR");
        FUNCTION_MAPPING.put("COALESCE", "COALESCE");
        FUNCTION_MAPPING.put("REPLACE", "REPLACE");
    }


    /**
     * 转换器适配
     *
     * @param dbType 数据库类型
     * @return 是否适配
     */
    @Override
    public boolean support(String dbType) {
        return JdbcConstants.DM.name().equals(dbType);
    }

    private static String convertPagination(String query) {
        // 匹配 LIMIT offset, size
        Pattern pattern1 = Pattern.compile("LIMIT\\s+(\\d+)\\s*,\\s*(\\d+)", Pattern.CASE_INSENSITIVE);
        Matcher matcher1 = pattern1.matcher(query);
        if (matcher1.find()) {
            String offset = matcher1.group(1);
            String limit = matcher1.group(2);
            return matcher1.replaceFirst("OFFSET " + offset + " FETCH FIRST " + limit + " ROWS ONLY");
        }

        // 匹配 LIMIT size OFFSET offset
        Pattern pattern2 = Pattern.compile("LIMIT\\s+(\\d+)\\s+OFFSET\\s+(\\d+)", Pattern.CASE_INSENSITIVE);
        Matcher matcher2 = pattern2.matcher(query);
        if (matcher2.find()) {
            String limit = matcher2.group(1);
            String offset = matcher2.group(2);
            return matcher2.replaceFirst("OFFSET " + offset + " FETCH FIRST " + limit + " ROWS ONLY");
        }

        return query;
    }


    @Override
    public void convertQueryStatement(SQLSelectStatement statement) {
        SQLSelect select = statement.getSelect();
        if (select != null) {
            SQLSelectQuery query = select.getQuery();
            if (query != null) {
                String convertedSql = processSelectQuery(query);
                if (StringUtils.isNotBlank(convertedSql)) {
                    selectList.add(convertedSql);
                }
            }
        }
    }

    private String processSelectQuery(SQLSelectQuery query) {
        StringBuilder sb = new StringBuilder();
        if (query instanceof SQLSelectQueryBlock) {
            SQLSelectQueryBlock block = (SQLSelectQueryBlock) query;
            // SELECT 列
            sb.append("SELECT ");
            List<SQLSelectItem> selectItems = block.getSelectList();
            for (int i = 0; i < selectItems.size(); i++) {
                if (i > 0) {
                    sb.append(", ");
                }
                sb.append(processSelectItem(selectItems.get(i)));
            }
            // FROM 子句
            SQLTableSource from = block.getFrom();
            if (from != null) {
                sb.append(" FROM ").append(processTableSource(from));
            }

            // WHERE 条件
            SQLExpr where = block.getWhere();
            if (where != null) {
                sb.append(" WHERE ").append(processWhereCondition(where));
            }
            collectSelectAliases(block);
            // GROUP BY
            List<SQLExpr> groupBy = block.getGroupBy() != null ? block.getGroupBy().getItems() : Collections.emptyList();
            if (!groupBy.isEmpty()) {
                sb.append(" GROUP BY ");
                for (int i = 0; i < groupBy.size(); i++) {
                    if (i > 0) {
                        sb.append(", ");
                    }
                    sb.append(groupBy.get(i).toString());
                }
                SQLExpr having = block.getGroupBy().getHaving();
                if (having != null) {
                    SQLExpr replacedHaving = replaceAliasWithExpr(having);
                    sb.append(" HAVING ").append(replacedHaving.toString());
                }
            }

            // ORDER BY
            SQLOrderBy orderBy = block.getOrderBy();
            if (orderBy != null) {
                List<SQLSelectOrderByItem> orderByItems = orderBy.getItems();
                if (orderByItems != null && !orderByItems.isEmpty()) {
                    sb.append(" ORDER BY ");
                    for (int i = 0; i < orderByItems.size(); i++) {
                        SQLSelectOrderByItem item = orderByItems.get(i);
                        if (i > 0) {
                            sb.append(", ");
                        }
                        sb.append(item.getExpr().toString());
                        if (item.getType() == SQLOrderingSpecification.DESC) {
                            sb.append(" DESC");
                        } else {
                            sb.append(" ASC");
                        }
                    }
                }
            }

            // LIMIT / OFFSET 分页
            SQLLimit limit = block.getLimit();
            if (limit != null) {
                sb.append(" ").append(convertPagination(limit.toString()));
            }

        } else if (query instanceof SQLUnionQuery) {
            SQLUnionQuery unionQuery = (SQLUnionQuery) query;
            sb.append("(").append(processSelectQuery(unionQuery.getLeft())).append(")");
            sb.append(" ").append(unionQuery.getOperator()).append(" ");
            sb.append("(").append(processSelectQuery(unionQuery.getRight())).append(")");
        }

        return sb.toString();
    }

    private void collectSelectAliases(SQLSelectQueryBlock block) {
        selectAliasMap.clear();
        for (SQLSelectItem item : block.getSelectList()) {
            if (Objects.isNull(item.getAlias())) {
                continue;
            }
            selectAliasMap.put(item.getAlias(), item.getExpr());
        }
    }

    private SQLExpr replaceAliasWithExpr(SQLExpr expr) {
        if (expr instanceof SQLIdentifierExpr) {
            String aliasName = ((SQLIdentifierExpr) expr).getName();
            return selectAliasMap.getOrDefault(aliasName, expr);
        } else if (expr instanceof SQLBinaryOpExpr) {
            SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) expr;
            SQLExpr left = replaceAliasWithExpr(binaryExpr.getLeft());
            SQLExpr right = replaceAliasWithExpr(binaryExpr.getRight());
            return new SQLBinaryOpExpr(left, binaryExpr.getOperator(), right);
        }
        // 可继续扩展其他类型...
        return expr;
    }

    private String processSelectItem(SQLSelectItem item) {
        item.getExpr().accept(createFunctionReplaceVisitor());
        String expr = item.getExpr().toString();
        if (item.getAlias() != null) {
            return expr + " AS " + item.getAlias();
        }
        return expr;
    }

    private String processTableSource(SQLTableSource source) {
        if (source instanceof SQLExprTableSource) {
            SQLIdentifierExpr expr = (SQLIdentifierExpr) ((SQLExprTableSource) source).getExpr();
            return expr.getName().replace("`", "");
        } else if (source instanceof SQLJoinTableSource) {
            SQLJoinTableSource join = (SQLJoinTableSource) source;
            String left = processTableSource(join.getLeft());
            String right = processTableSource(join.getRight());
            String on = join.getCondition() != null ? " ON " + join.getCondition().toString() : "";
            return left + " " + join.getJoinType().nameLCase + " " + right + on;
        } else if (source instanceof SQLSubqueryTableSource) {
            SQLSelect subQuery = ((SQLSubqueryTableSource) source).getSelect();
            String alias = ((SQLSubqueryTableSource) source).getAlias();
            return "(" + processSelectQuery(subQuery.getQuery()) + ") AS  " + alias;
        }
        return source.toString();
    }

    private String processWhereCondition(SQLExpr where) {
        where.accept(createFunctionReplaceVisitor());
        return ((SQLSelectQueryBlock) where.getParent()).getWhere().toString();
    }

    private SQLASTVisitor createFunctionReplaceVisitor() {
        return new SQLASTVisitorAdapter() {
            @Override
            public boolean visit(SQLMethodInvokeExpr expr) {
                handleFunction(expr);
                return true;
            }

            @Override
            public boolean visit(SQLAggregateExpr expr) {
                handleFunction(expr);
                return true;
            }

            private void handleFunction(SQLMethodInvokeExpr expr) {
                String funcName = expr.getMethodName();
                System.out.println("funcName: " + funcName);
                String gbaseFunc = FUNCTION_MAPPING.get(funcName.toUpperCase());
                String gbaseFunc2 = gbaseFunc == null ? FUNCTION_MAPPING.get(funcName.toUpperCase() + "()") : gbaseFunc;
                if (gbaseFunc2 != null) {
                    // 特殊处理 GROUP_CONCAT -> STRING_AGG 需要加参数
                    if ("GROUP_CONCAT".equalsIgnoreCase(funcName)) {
                        handleGroupConcat(expr, gbaseFunc2);
                    } else if ("FIND_IN_SET".equalsIgnoreCase(funcName)) {
                        // FIND_IN_SET(a, b) => STRPOS(b, a) > 0
                        List<SQLExpr> parameters = expr.getParameters();
                        if (parameters.size() >= 2) {
                            SQLExpr a = parameters.get(0);  // 'apple'
                            SQLExpr b = parameters.get(1);  // fruits
                            // 构建 STRPOS(b, a)
                            SQLMethodInvokeExpr strpos = new SQLMethodInvokeExpr("INSTR");
                            strpos.addParameter(b);
                            strpos.addParameter(a);
                            // 构建 STRPOS(...) > 0
                            SQLBinaryOpExpr gtZero = new SQLBinaryOpExpr(strpos, SQLBinaryOperator.GreaterThan, new SQLIntegerExpr(0));
                            SQLObject parent = expr.getParent();
                            if (parent instanceof SQLBinaryOpExpr) {
                                ((SQLBinaryOpExpr) parent).replace(expr, gtZero);
                            } else if (parent instanceof SQLSelectItem) {
                                ((SQLSelectItem) parent).setExpr(gtZero);
                            } else if (parent instanceof SQLExprStatement) {
                                ((SQLExprStatement) parent).setExpr(gtZero);
                            } else if (parent instanceof SQLSelectQueryBlock) {
                                //  expr.setUsing(gtZero);
                                //expr.replace(expr, gtZero);
                                ((SQLSelectQueryBlock) parent).replace(expr, gtZero);
                            } else if (parent instanceof SQLInListExpr) {
                                // 处理 FIND_IN_SET 在 IN 子句中的情况
                                SQLInListExpr inListExpr = (SQLInListExpr) parent;
                                inListExpr.addTarget(gtZero);
                            } else {
                                // 其他复杂结构需要单独处理
                                System.err.println("Unsupported parent type: " + parent.getClass());
                            }
                        }
                    } else {
                        expr.setMethodName(gbaseFunc2.replace("()", ""));
                    }
                }
            }

            private void handleGroupConcat(SQLMethodInvokeExpr expr, String gbaseFunc2) {
                if (expr instanceof SQLAggregateExpr) {
                    SQLAggregateExpr aggExpr = (SQLAggregateExpr) expr;
                    List<SQLExpr> parameters = aggExpr.getArguments();

                    if (parameters.size() >= 1) {
                        SQLExpr col = parameters.get(0);
                        SQLCharExpr defaultSep = new SQLCharExpr(",");
                        SQLMethodInvokeExpr stringAgg = new SQLMethodInvokeExpr("WM_CONCAT"); // STRING_AGG
                        stringAgg.addParameter(col);
                        stringAgg.addParameter(defaultSep);

                        SQLObject parent = expr.getParent();
                        if (parent instanceof SQLBinaryOpExpr) {
                            ((SQLBinaryOpExpr) parent).replace(expr, stringAgg);
                        } else if (parent instanceof SQLSelectItem) {
                            ((SQLSelectItem) parent).setExpr(stringAgg);
                        }
                    }
                } else if (expr instanceof SQLMethodInvokeExpr) {
                    // 处理 GROUP_CONCAT 作为普通函数的情况(如果有的话)
                    SQLMethodInvokeExpr methodExpr = (SQLMethodInvokeExpr) expr;
                    List<SQLExpr> parameters = methodExpr.getParameters();
                    if (parameters.size() == 1) {
                        SQLExpr col = parameters.get(0);
                        SQLCharExpr defaultSep = new SQLCharExpr(",");
                        SQLMethodInvokeExpr stringAgg = new SQLMethodInvokeExpr("STRING_AGG");
                        stringAgg.addParameter(col);
                        stringAgg.addParameter(defaultSep);
                        SQLObject parent = expr.getParent();
                        if (parent instanceof SQLBinaryOpExpr) {
                            ((SQLBinaryOpExpr) parent).replace(expr, stringAgg);
                        } else if (parent instanceof SQLSelectItem) {
                            ((SQLSelectItem) parent).setExpr(stringAgg);
                        }
                    }
                }
            }
        };
    }


    @Override
    public void convertCreateTabletStatement(MySqlCreateTableStatement statement) {
        String tableName = statement.getTableName()
                .replace("`", "").replace("\"", "").toUpperCase();
        String comment = null;
        if (Objects.nonNull(statement.getComment())) {
            comment = statement.getComment().toString().replace("'", "").replace("\"", "");
        }
        List<SQLTableElement> tableElementList = statement.getTableElementList();
        List<SQLAssignItem> tableOptions = statement.getTableOptions();
        Map<String, Object> sqlAssignMap = new HashMap<>();
        tableOptions.forEach(option -> {
            sqlAssignMap.put(option.getTarget().toString(), option.getValue());
        });
        if (StringUtils.isNotBlank(comment)) {
            commentList.add("COMMENT ON TABLE \"" + tableName + "\"" + " IS '" + comment + "';");
        }
        StringBuilder builder = new StringBuilder("CREATE TABLE ");
        builder.append("\"").append(tableName).append("\"").append("\n(");
        tableElementList.forEach(column -> {
            if (column instanceof SQLColumnDefinition) {
                SQLCharExpr commentSqlExpr = (SQLCharExpr) ((SQLColumnDefinition) column).getComment();
                String columnName = ((SQLColumnDefinition) column).getColumnName().replace("`", "").replace("\"", "").toUpperCase();
                String columnComment = null;
                if (Objects.nonNull(commentSqlExpr)) {
                    columnComment = commentSqlExpr.getText();
                }
                String autoIncrement = null;
                if (sqlAssignMap.containsKey("AUTO_INCREMENT")) {
                    autoIncrement = sqlAssignMap.get("AUTO_INCREMENT").toString();
                }
                builder.append(buildColumn((SQLColumnDefinition) column, autoIncrement));
                builder.append(",\n");
                if (StringUtils.isNotBlank(columnComment)) {
                    commentList.add("COMMENT ON COLUMN \"" + tableName + "\".\"" + columnName + "\" IS '" + columnComment + "';");
                }
            } else if (column instanceof MySqlPrimaryKey) {
                MySqlPrimaryKey mySqlPrimaryKey = (MySqlPrimaryKey) column;
                List<SQLSelectOrderByItem> sqlSelectOrderByItems = mySqlPrimaryKey.getIndexDefinition().getColumns();
                SQLIdentifierExpr expr = (SQLIdentifierExpr) sqlSelectOrderByItems.get(0).getExpr();
                alterList.add("ALTER TABLE \"" + tableName + "\" ADD CONSTRAINT PRIMARY KEY(\"" + expr.getName().replace("`", "").toUpperCase() + "\");");
            } else if (column instanceof MySqlUnique) {
                MySqlUnique mySqlKey = (MySqlUnique) column;
                SQLIndexDefinition sqlIndexDefinition = mySqlKey.getIndexDefinition();
                List<SQLSelectOrderByItem> sqlSelectOrderByItems = sqlIndexDefinition.getColumns();
                List<String> keys = new ArrayList<>();
                sqlSelectOrderByItems.forEach(keyItem -> {
                    if (keyItem.getExpr() instanceof SQLIdentifierExpr) {
                        SQLIdentifierExpr expr = (SQLIdentifierExpr) keyItem.getExpr();
                        keys.add("\"" + expr.getName().replace("`", "").toUpperCase() + "\"");
                    } else if (keyItem.getExpr() instanceof SQLMethodInvokeExpr) {
                        SQLMethodInvokeExpr invokeExpr = (SQLMethodInvokeExpr) keyItem.getExpr();
                        keys.add("\"" + invokeExpr.getMethodName().replace("`", "").toUpperCase() + "\"");
                    }
                });
                String indexName = "UNIQUE_" + tableName + "_" + StringUtils.join(keys, "_").replace("\"", "");
                alterList.add("ALTER TABLE \"" + tableName + "\" ADD CONSTRAINT \"" + indexName + "\" UNIQUE(" + StringUtils.join(keys, ",") + ");");
            } else if (column instanceof MySqlKey) {
                MySqlKey mySqlKey = (MySqlKey) column;
                SQLIndexDefinition sqlIndexDefinition = mySqlKey.getIndexDefinition();
                List<SQLSelectOrderByItem> sqlSelectOrderByItems = sqlIndexDefinition.getColumns();
                List<String> keys = new ArrayList<>();
                sqlSelectOrderByItems.forEach(keyItem -> {
                    SQLIdentifierExpr expr = (SQLIdentifierExpr) keyItem.getExpr();
                    keys.add("\"" + expr.getName().replace("`", "").toUpperCase() + "\"");
                });
                String indexName = "IDX_" + tableName + "_" + StringUtils.join(keys, "_").replace("\"", "");
                indexList.add("CREATE INDEX \"" + indexName + "\" ON \"" + tableName + "\"(" + StringUtils.join(keys, ",") + ");");
            }
        });
        builder.replace(builder.length() - 2, builder.length() - 1, "");
        builder.append(");\n");
        creatTableList.add(builder.toString());
    }

    @Override
    public void convertInsertStatement(MySqlInsertStatement statement) {
        String tableName = statement.getTableName().toString().replace("`", "").toUpperCase();
        StringBuilder builder = new StringBuilder("SET IDENTITY_INSERT \"");
        builder.append(tableName).append("\" ON;");
        insertList.add(builder.toString());
        String sql = statement.toString().replace("`", "").replace("CURRENT_TIMESTAMP()", "CURRENT_TIMESTAMP").replace("current_timestamp()", "CURRENT_TIMESTAMP").replace("b'0'", "0").replace("b'1'", "1");
        insertList.add(sql);

        StringBuilder builder1 = new StringBuilder("SET IDENTITY_INSERT \"");
        builder1.append(tableName).append("\" OFF;");
        insertList.add(builder1.toString());
    }

    @Override
    public void convertCreateIndexStatement(SQLCreateIndexStatement statement) {
        String tableName = statement.getTableName().replace("`", "").toUpperCase();
        SQLIndexDefinition sqlIndexDefinition = statement.getIndexDefinition();
        List<SQLSelectOrderByItem> sqlSelectOrderByItems = sqlIndexDefinition.getColumns();
        String type = null;
        if (StringUtils.isNotBlank(sqlIndexDefinition.getType())) {
            type = sqlIndexDefinition.getType().toUpperCase();
        }
        List<String> keys = new ArrayList<>();
        sqlSelectOrderByItems.forEach(keyItem -> {
            if (keyItem.getExpr() instanceof SQLIdentifierExpr) {
                SQLIdentifierExpr expr = (SQLIdentifierExpr) keyItem.getExpr();
                keys.add("\"" + expr.getName().replace("`", "").toUpperCase() + "\"");
            } else if (keyItem.getExpr() instanceof SQLMethodInvokeExpr) {
                SQLMethodInvokeExpr invokeExpr = (SQLMethodInvokeExpr) keyItem.getExpr();
                keys.add("\"" + invokeExpr.getMethodName().replace("`", "").toUpperCase() + "\"");
            }
        });
        if (StringUtils.isNotBlank(type) && "UNIQUE".equals(type)) {
            String indexName = "UNIQUE_" + tableName + "_" + StringUtils.join(keys, "_").replace("\"", "");
            indexList.add("ALTER TABLE \"" + tableName + "\" ADD CONSTRAINT \"" + indexName + "\" UNIQUE(" + StringUtils.join(keys, ",") + ");");
        } else {
            String indexName = "IDX_" + tableName + "_" + StringUtils.join(keys, "_").replace("\"", "");
            indexList.add("CREATE INDEX \"" + indexName + "\" ON \"" + tableName + "\"(" + StringUtils.join(keys, ",") + ");");
        }

    }

    @Override
    public void convertUpdateStatement(MySqlUpdateStatement statement) {
        String sql = statement.toString().replace("`", "").replace("CURRENT_TIMESTAMP()", "CURRENT_TIMESTAMP").replace("current_timestamp()", "CURRENT_TIMESTAMP").replace("b'0'", "0").replace("b'1'", "1");
        updateList.add(sql);
    }

    @Override
    public void convertDeleteStatement(MySqlDeleteStatement statement) {
        String sql = statement.toString().replace("`", "").replace("b'0'", "0").replace("b'1'", "1");
        updateList.add(sql);
    }

    @Override
    public void convertAlterTableStatement(SQLAlterTableStatement statement) {
        String tableName = statement.getTableName().toString().replace("`", "").toUpperCase();
        statement.getItems().forEach(sqlAlterTableItem -> {
            if (sqlAlterTableItem instanceof SQLAlterTableAddColumn) {
                SQLAlterTableAddColumn addColumn = (SQLAlterTableAddColumn) sqlAlterTableItem;
                addColumn.getColumns().forEach(addColumnItem -> {
                    StringBuilder builder = new StringBuilder("ALTER TABLE \"");
                    builder.append(tableName).append("\"");
                    builder.append(" ADD ").append(buildColumn(addColumnItem, null)).append(";\n");
                    SQLCharExpr commentSqlExpr = (SQLCharExpr) addColumnItem.getComment();
                    String columnName = addColumnItem.getColumnName().replace("`", "").replace("\"", "").toUpperCase();
                    String columnComment = null;
                    if (Objects.nonNull(commentSqlExpr)) {
                        columnComment = commentSqlExpr.getText();
                    }
                    if (StringUtils.isNotBlank(columnComment)) {
                        commentList.add("COMMENT ON COLUMN \"" + tableName + "\".\"" + columnName + "\" IS '" + columnComment + "';");
                    }
                    alterList.add(builder.toString());
                });
            } else if (sqlAlterTableItem instanceof MySqlAlterTableModifyColumn) {
                MySqlAlterTableModifyColumn alterColumn = (MySqlAlterTableModifyColumn) sqlAlterTableItem;
                SQLColumnDefinition definition = alterColumn.getNewColumnDefinition();
                StringBuilder builder = new StringBuilder("ALTER TABLE \"");
                builder.append(tableName).append("\"");
                builder.append(" MODIFY ").append(buildColumn(definition, null)).append(";\n");
                SQLCharExpr commentSqlExpr = (SQLCharExpr) definition.getComment();
                String columnName = definition.getColumnName().replace("`", "").replace("\"", "").toUpperCase();
                String columnComment = null;
                if (Objects.nonNull(commentSqlExpr)) {
                    columnComment = commentSqlExpr.getText();
                }
                if (StringUtils.isNotBlank(columnComment)) {
                    commentList.add("COMMENT ON COLUMN \"" + tableName + "\".\"" + columnName + "\" IS '" + columnComment + "';");
                }
                alterList.add(builder.toString());
            } else if (sqlAlterTableItem instanceof SQLAlterTableAddIndex) {
                SQLAlterTableAddIndex addIndex = (SQLAlterTableAddIndex) sqlAlterTableItem;
                SQLIndexDefinition sqlIndexDefinition = addIndex.getIndexDefinition();
                List<SQLSelectOrderByItem> sqlSelectOrderByItems = sqlIndexDefinition.getColumns();
                List<String> keys = new ArrayList<>();
                sqlSelectOrderByItems.forEach(keyItem -> {
                    if (keyItem.getExpr() instanceof SQLIdentifierExpr) {
                        SQLIdentifierExpr expr = (SQLIdentifierExpr) keyItem.getExpr();
                        keys.add("\"" + expr.getName().replace("`", "").toUpperCase() + "\"");
                    } else if (keyItem.getExpr() instanceof SQLMethodInvokeExpr) {
                        SQLMethodInvokeExpr invokeExpr = (SQLMethodInvokeExpr) keyItem.getExpr();
                        keys.add("\"" + invokeExpr.getMethodName().replace("`", "").toUpperCase() + "\"");
                    }
                });
                String indexName = "IDX_" + tableName + "_" + StringUtils.join(keys, "_").replace("\"", "");
                alterList.add("CREATE INDEX \"" + indexName + "\" ON \"" + tableName + "\"(" + StringUtils.join(keys, ",") + ");");
            } else if (sqlAlterTableItem instanceof SQLAlterTableAddConstraint) {
                SQLAlterTableAddConstraint addIndex = (SQLAlterTableAddConstraint) sqlAlterTableItem;
                SQLConstraint sqlConstraint = addIndex.getConstraint();
                if (sqlConstraint instanceof MySqlPrimaryKey) {
                    MySqlPrimaryKey mySqlPrimaryKey = (MySqlPrimaryKey) sqlConstraint;
                    List<SQLSelectOrderByItem> sqlSelectOrderByItems = mySqlPrimaryKey.getIndexDefinition().getColumns();
                    SQLIdentifierExpr expr = (SQLIdentifierExpr) sqlSelectOrderByItems.get(0).getExpr();
                    alterList.add("ALTER TABLE \"" + tableName + "\" ADD CONSTRAINT  PRIMARY KEY(\"" + expr.getName().replace("`", "").toUpperCase() + "\");");
                } else if (sqlConstraint instanceof MySqlUnique) {
                    MySqlUnique mySqlKey = (MySqlUnique) sqlConstraint;
                    SQLIndexDefinition sqlIndexDefinition = mySqlKey.getIndexDefinition();
                    List<SQLSelectOrderByItem> sqlSelectOrderByItems = sqlIndexDefinition.getColumns();
                    List<String> keys = new ArrayList<>();
                    sqlSelectOrderByItems.forEach(keyItem -> {
                        if (keyItem.getExpr() instanceof SQLIdentifierExpr) {
                            SQLIdentifierExpr expr = (SQLIdentifierExpr) keyItem.getExpr();
                            keys.add("\"" + expr.getName().replace("`", "").toUpperCase() + "\"");
                        } else if (keyItem.getExpr() instanceof SQLMethodInvokeExpr) {
                            SQLMethodInvokeExpr invokeExpr = (SQLMethodInvokeExpr) keyItem.getExpr();
                            keys.add("\"" + invokeExpr.getMethodName().replace("`", "").toUpperCase() + "\"");
                        }
                    });
                    String indexName = "UNIQUE_" + tableName + "_" + StringUtils.join(keys, "_").replace("\"", "");
                    alterList.add("ALTER TABLE \"" + tableName + "\" ADD CONSTRAINT \"" + indexName + "\" UNIQUE(\"" + StringUtils.join(keys, ",") + "\");");
                } else if (sqlConstraint instanceof MySqlKey) {
                    MySqlKey mySqlKey = (MySqlKey) sqlConstraint;
                    SQLIndexDefinition sqlIndexDefinition = mySqlKey.getIndexDefinition();
                    List<SQLSelectOrderByItem> sqlSelectOrderByItems = sqlIndexDefinition.getColumns();
                    List<String> keys = new ArrayList<>();
                    sqlSelectOrderByItems.forEach(keyItem -> {
                        if (keyItem.getExpr() instanceof SQLIdentifierExpr) {
                            SQLIdentifierExpr expr = (SQLIdentifierExpr) keyItem.getExpr();
                            keys.add("\"" + expr.getName().replace("`", "").toUpperCase() + "\"");
                        } else if (keyItem.getExpr() instanceof SQLMethodInvokeExpr) {
                            SQLMethodInvokeExpr invokeExpr = (SQLMethodInvokeExpr) keyItem.getExpr();
                            keys.add("\"" + invokeExpr.getMethodName().replace("`", "").toUpperCase() + "\"");
                        }
                    });
                    String indexName = "IDX_" + tableName + "_" + StringUtils.join(keys, "_").replace("\"", "");
                    alterList.add("CREATE INDEX \"" + indexName + "\" ON \"" + tableName + "\"(" + StringUtils.join(keys, ",") + ");");
                }
            } else if (sqlAlterTableItem instanceof MySqlAlterTableChangeColumn) {
                String columnName = ((MySqlAlterTableChangeColumn) sqlAlterTableItem).getColumnName().getSimpleName().replace("`", "").replace("\"", "").toUpperCase();
                SQLColumnDefinition newColumn = ((MySqlAlterTableChangeColumn) sqlAlterTableItem).getNewColumnDefinition();
                String newColumnName = newColumn.getColumnName().replace("`", "").replace("\"", "").toUpperCase();
                alterList.add("ALTER TABLE \"" + tableName + "\" ALTER \"" + columnName + "\" RENAME TO \"" + newColumnName + "\";");
                String builder = "ALTER TABLE \"" + tableName + "\"" +
                        " MODIFY " + buildColumn(newColumn, null) + ";\n";
                SQLCharExpr commentSqlExpr = (SQLCharExpr) newColumn.getComment();
                String columnComment = null;
                if (Objects.nonNull(commentSqlExpr)) {
                    columnComment = commentSqlExpr.getText();
                }
                if (StringUtils.isNotBlank(columnComment)) {
                    commentList.add("COMMENT ON COLUMN \"" + tableName + "\".\"" + newColumnName + "\" IS '" + columnComment + "';");
                }
                alterList.add(builder);
            }
        });
    }

    @Override
    public void convertRenameTableStatement(MySqlRenameTableStatement statement) {
        MySqlRenameTableStatement.Item item = (MySqlRenameTableStatement.Item) statement.getItems().get(0);
        String name = item.getName().getSimpleName().replace("`", "").toUpperCase();
        String toName = item.getTo().getSimpleName().replace("`", "").toUpperCase();
        alterList.add("ALTER TABLE \"" + name + "\" RENAME TO \"" + toName + "\";");
    }

    @Override
    public void convertDropTableStatement(SQLDropTableStatement statement) {
        String table = ((SQLIdentifierExpr) statement.getTableSources().get(0).getExpr()).getName().replace("`", "").toUpperCase();
        alterList.add("DROP TABLE IF EXISTS \"" + table + "\";");
    }

    @Override
    public void convertTruncateStatement(SQLTruncateStatement statement) {
        String table = ((SQLIdentifierExpr) statement.getTableSources().get(0).getExpr()).getName().replace("`", "").toUpperCase();
        alterList.add("TRUNCATE TABLE \"" + table + "\";");
    }

    private String buildColumn(SQLColumnDefinition definition, String increment) {
        StringBuilder builder = new StringBuilder("");
        String columnName = definition.getColumnName().replace("`", "").replace("\"", "").toUpperCase();
        Boolean autoIncrement = definition.isAutoIncrement();
        SQLDataTypeImpl dataType = (SQLDataTypeImpl) definition.getDataType();
        String dataTypeName = dataType.getName().toUpperCase();
        List<SQLExpr> sqlExprs = dataType.getArguments();
        List<SQLColumnConstraint> constraints = definition.getConstraints();
        if ("VARCHAR".equals(dataTypeName)) {
            SQLIntegerExpr sqlIntegerExpr = (SQLIntegerExpr) sqlExprs.get(0);
            builder.append("\"").append(columnName).append("\" ").append(dataTypeName).append("(").append(sqlIntegerExpr.getNumber()).append(")");
        } else if ("TIMESTAMP".equals(dataTypeName) || "DATETIME".equals(dataTypeName)) {
            builder.append("\"").append(columnName).append("\" ").append("TIMESTAMP(0)");
        } else if ("BIT".equals(dataTypeName)) {
            builder.append("\"").append(columnName).append("\" ").append("TINYINT");
        } else if ("LONGTEXT".equals(dataTypeName)) {
            builder.append("\"").append(columnName).append("\" ").append("TEXT");
        } else if ("MEDIUMTEXT".equals(dataTypeName)) {
            builder.append("\"").append(columnName).append("\" TEXT");
        } else if ("DECIMAL".equals(dataTypeName)) {
            SQLIntegerExpr precision = (SQLIntegerExpr) sqlExprs.get(0);
            SQLIntegerExpr scale = (SQLIntegerExpr) sqlExprs.get(1);
            builder.append("\"").append(columnName).append("\" ").append(" DECIMAL(").append(precision.getNumber()).append(", ").append(scale.getNumber()).append(")");
        } else {
            builder.append("\"").append(columnName).append("\" ").append(dataTypeName);
        }
        if (autoIncrement) {
            if (StringUtils.isNotBlank(increment)) {
                builder.append(" IDENTITY(").append(increment).append(",1)");
            } else {
                builder.append(" IDENTITY(1,1)");
            }
        }
        SQLExpr sqlExpr = definition.getDefaultExpr();
        if (Objects.nonNull(sqlExpr)) {
            builder.append(" DEFAULT ");
            if (sqlExpr instanceof SQLIntegerExpr) {
                SQLIntegerExpr sqlIntegerExpr = (SQLIntegerExpr) sqlExpr;
                builder.append(sqlIntegerExpr.getValue());
            } else if (sqlExpr instanceof SQLBinaryExpr) {
                SQLBinaryExpr sqlBinaryExpr = (SQLBinaryExpr) sqlExpr;
                builder.append(sqlBinaryExpr.getValue());
            } else if (sqlExpr instanceof SQLCurrentTimeExpr) {
                builder.append("CURRENT_TIMESTAMP()");
            } else if (sqlExpr instanceof SQLCharExpr) {
                SQLCharExpr sqlCharExpr = (SQLCharExpr) sqlExpr;
                builder.append("'").append(sqlCharExpr.getText()).append("'");
            }
        }
        if (Objects.nonNull(constraints) && !constraints.isEmpty() && constraints.get(0) instanceof SQLNotNullConstraint) {
            builder.append(" NOT NULL");
        } else {
            if (Objects.isNull(sqlExpr) || sqlExpr instanceof SQLNullExpr) {
                builder.append(" NULL");
            }
        }
        return builder.toString();
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到