Java ,druid 解析sql,并通过 feign接口查询到的表元数据,替换包含left join 的select sql语句中的*,支持mysql、hive、postgresql、oracle、sqlserver等多种数据库。需要写出代码
时间: 2023-07-16 22:14:00 浏览: 94
提取Druid的SQL解析器
下面是使用Java和Druid实现解析SQL语句,并通过Feign接口查询表元数据,替换包含left join的select语句中的*的示例代码:
```java
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLJoinTableSource;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.alibaba.druid.util.JdbcConstants;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SqlParser {
private static final String DB_TYPE_MYSQL = "mysql";
private static final String DB_TYPE_ORACLE = "oracle";
private static final String DB_TYPE_POSTGRESQL = "postgresql";
private static final String DB_TYPE_SQLSERVER = "sqlserver";
private static final String DB_TYPE_HIVE = "hive";
private static final Pattern LEFT_JOIN_PATTERN = Pattern.compile("(?i)\\b(left join)\\b");
private FeignClient feignClient; // Feign接口
public void parseAndReplaceSql(String sql, String dbType) {
// 解析SQL语句
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, dbType);
for (SQLStatement statement : sqlStatements) {
// 只处理SELECT语句
if (statement instanceof SQLSelect) {
SQLSelect select = (SQLSelect) statement;
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) select.getQuery();
// 获取所有SELECT项
List<SQLSelectItem> selectItems = queryBlock.getSelectList();
// 判断是否包含LEFT JOIN
boolean hasLeftJoin = false;
SQLTableSource from = queryBlock.getFrom();
if (from instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) from;
if (join.getJoinType().getName().equalsIgnoreCase("left join")) {
hasLeftJoin = true;
}
}
// 如果包含LEFT JOIN,则替换SELECT项中的*
if (hasLeftJoin) {
for (int i = 0; i < selectItems.size(); i++) {
SQLSelectItem item = selectItems.get(i);
SQLExpr expr = item.getExpr();
if (expr instanceof SQLIdentifierExpr && ((SQLIdentifierExpr) expr).getName().equals("*")) {
// 调用Feign接口查询表元数据,替换SELECT项中的*
String tableName = ((SQLIdentifierExpr) from).getName(); // 获取表名
List<TableColumn> columns = feignClient.getTableColumns(tableName);
StringBuilder sb = new StringBuilder();
for (TableColumn column : columns) {
sb.append(column.getColumnName()).append(",");
}
sb.deleteCharAt(sb.length() - 1);
item.setExpr(SQLUtils.toSQLExpr(sb.toString(), dbType));
selectItems.set(i, item);
}
}
}
}
}
// 生成替换后的SQL语句
String resultSql = SQLUtils.toSQLString(sqlStatements, dbType, new MySqlOutputVisitor());
System.out.println(resultSql);
}
}
// 表元数据
class TableColumn {
private String columnName;
private String columnType;
// getter/setter
}
// Feign接口
@FeignClient(name = "metadata-service")
public interface FeignClient {
@GetMapping("/tableColumns")
List<TableColumn> getTableColumns(@RequestParam("tableName") String tableName);
}
```
需要注意的是,上述代码中的`FeignClient`是使用Spring Cloud Feign实现的,需要在项目中引入相应的依赖。同时,`getTableColumns`方法需要根据实际情况进行修改,具体实现可以参考Feign的使用文档。
阅读全文