使用Druid SQL Parser解析SQL 获取多个来源表和对应的目标表

<dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.6</version>
    </dependency>





    String sql = "";

    String[] split = sql.split(";\n");
    for (String s : split) {
        SQLStatement stmt = SQLUtils.parseSingleStatement(s, DbType.mysql); // 将 SQL 语句解析为 SQLStatement 对象
        if (stmt instanceof SQLInsertStatement) {
            SQLInsertStatement insert = (SQLInsertStatement) stmt;
//                String targetTable = insert.getTableName().getSimpleName(); // 获取目标表(不带库名称和catalog)
            String targetTable = insert.getTableSource().toString(); // 获取目标表(带库名称和catalog)

            SQLSelect source = insert.getQuery(); // 找出来源表查询

            List<SQLTableSource> sourceTables = new ArrayList<>(); // 存储来源表的列表
            Set<String> sourceTableAliases = new HashSet<>(); // 存储来源表别名的集合
            getSources(source.getQueryBlock().getFrom(), sourceTables, sourceTableAliases); // 获取主表及其关联的所有来源表
            Map<SQLTableSource, String> sourceTableMap = new HashMap<>(); // 存储来源表与对应别名或表名的映射关系
            for (SQLTableSource sourceTable : sourceTables) {
                if (sourceTable instanceof SQLExprTableSource) { // 如果是基本表,则直接获取表名
                    SQLExprTableSource exprTableSource = (SQLExprTableSource) sourceTable;
                    String sourceTableName = exprTableSource.getName().toString();
//                        String sourceTableName = exprTableSource.getName().getSimpleName();  //只有表名称
                    sourceTableMap.put(sourceTable, sourceTableName);
                } else if (sourceTable instanceof SQLSubqueryTableSource) { // 如果是子查询,则递归解析
                    SQLSubqueryTableSource subqueryTableSource = (SQLSubqueryTableSource) sourceTable;
                    SQLSelect subquery = subqueryTableSource.getSelect();
                    List<SQLTableSource> subquerySources = new ArrayList<>();
                    Set<String> subqueryAliases = new HashSet<>();
                    getSources(subquery.getQueryBlock().getFrom(), subquerySources, subqueryAliases);
                    for (SQLTableSource subquerySource : subquerySources) {
                        if (!sourceTables.contains(subquerySource)) {
                            sourceTables.add(subquerySource); // 将子查询中的来源表加入列表中
                        }
                        String alias = subqueryAliases.contains(subquerySource.getAlias()) ? subquerySource.getAlias() : null; // 子查询中的来源表可能存在别名,进行处理
                        if (alias == null && subquerySource instanceof SQLExprTableSource) { // 如果没有别名,则使用表名作为键
                            SQLExprTableSource exprTableSource = (SQLExprTableSource) subquerySource;
                            alias = exprTableSource.getName().toString();
//                                alias = exprTableSource.getName().getSimpleName(); //只有表名称
                        }
                        sourceTableMap.put(subquerySource, alias);
                    }
                } else {
                    throw new UnsupportedOperationException("Unsupported table type: " + sourceTable.getClass());
                }
            }

            String table = getTable(targetTable);
            System.out.println("目标表: " + table);


            ArrayList<String> sourceTabless = new ArrayList<>();
            for (SQLTableSource sourceTable : sourceTables) {
                String sourceTableName = sourceTableMap.get(sourceTable);
                if (targetTable.equalsIgnoreCase(sourceTableName)) {
                    System.out.println("来源表和目标表在同一个sql中一致,过滤掉来源表");
                } else {
                    if (!sourceTabless.contains(sourceTableName)) {
                        sourceTabless.add(sourceTableName);
                    }
                }
            }

            for (int i = 0; i < sourceTabless.size(); i++) {
                String table1 = getTable(sourceTabless.get(i));
                System.out.println("来源表: " + table1);
            }

        }
    }

}

private static String getTable(String tables){
    String targetTable = "";
    String[] split1 = tables.split("\\.");
    if (split1.length == 2) {
        targetTable = tables;
    } else if (split1.length == 3) {
        int startIndex = tables.indexOf(".") + 1; // 获取.后的索引位置,并加上1来跳过.
        targetTable = tables.substring(startIndex);
    }
    return targetTable;
}

/**
 * @param tableSource 存储来源表的列表
 * @param sources     存储来源表别名的集合
 * @param aliases     存储来源表和对应别名或者表名的映射关系
 */
private static void getSources(SQLTableSource tableSource, List<SQLTableSource> sources, Set<String> aliases) {
    if (tableSource == null) {
        return;
    }
    if (tableSource instanceof SQLJoinTableSource) {
        SQLJoinTableSource join = (SQLJoinTableSource) tableSource;

        getSources(join.getLeft(), sources, aliases);
        getSources(join.getRight(), sources, aliases);
    } else {
        if (!sources.contains(tableSource)) {
            sources.add(tableSource);
            String alias = tableSource.getAlias();
            if (alias != null) {
                aliases.add(alias);
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值