use of com.shulie.druid.sql.dialect.mysql.ast.statement.MySqlRenameTableStatement in project LinkAgent by shulieTech.
the class SqlParser method parseAndReplaceTableNames.
public static String parseAndReplaceTableNames(String sql, String key, String dbTypeName, String midType) throws SQLException {
sql = sql.replaceAll("< >", "<>");
DbType dbType = DbType.of(dbTypeName);
Map<String, String> mappingTable = getMappingTables(key);
if (SqlParser.lowerCase != null && "Y".equals(SqlParser.lowerCase)) {
Map<String, String> mappingTableLower = new ConcurrentHashMap<String, String>();
Set<String> keys = mappingTable.keySet();
for (String tableName : keys) {
String value = mappingTable.get(tableName);
mappingTableLower.put(tableName.toLowerCase(), value.toLowerCase());
}
mappingTable = mappingTableLower;
resetMappingTables(key, mappingTableLower);
}
// new MySQL Parser
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbTypeName);
if (parser == null) {
if (GlobalConfig.getInstance().getWrongSqlDetail().size() < 10) {
GlobalConfig.getInstance().addWrongSqlDetail(StringUtils.substring("dbType not support" + key + " dbType" + dbTypeName + " sql" + sql, 0, 1995));
}
throw new SQLException("dbType not support" + key + " dbType" + dbTypeName + " sql" + sql);
}
// 使用Parser解析生成AST,这里SQLStatement就是AST
final StringWriter val = new StringWriter();
try {
final List<SQLStatement> sqlStatements = parser.parseStatementList();
for (final SQLStatement sqlStatement : sqlStatements) {
SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(val, dbType);
SchemaStatVisitor visitor2 = SQLUtils.createSchemaStatVisitor(dbType);
sqlStatement.accept(visitor2);
final Map<TableStat.Name, TableStat> map2 = visitor2.getTables();
// Set<String> tablesName = visitor.getTables();
final Map<String, String> additionalTableNames = new HashMap();
for (final TableStat.Name name : map2.keySet()) {
/**
* 过滤掉函数
*/
String tableName = name.getName();
if (StringUtils.indexOf(tableName, '(') != -1 && StringUtils.indexOf(tableName, ')') != -1) {
continue;
}
for (String mappingName : mappingTable.keySet()) {
mappingName = StringUtils.replace(mappingName, "\"", "");
String nameTemp = name.getName();
String schema = "";
String fullTableName = StringUtils.replace(nameTemp, "\"", "");
if (nameTemp != null && StringUtils.contains(nameTemp, ".")) {
schema = StringUtils.substringBefore(nameTemp, ".");
nameTemp = StringUtils.substringAfter(nameTemp, ".");
}
if (StringUtils.indexOf(schema, "\"") != -1) {
schema = StringUtils.replace(schema, "\"", "");
}
if (StringUtils.indexOf(nameTemp, "\"") != -1) {
nameTemp = StringUtils.replace(nameTemp, "\"", "");
}
/**
* 如果配置的表名与获取到的表名相等,则如果 sql 中有 schema,则将映射表名也添加 schema
* 如sql 中的表名为 user或者是 test.user,但是配置的表名为 user
*
* 如果sql中的表名(带 schema)与映射表名相等,则直接添加映射表名
*
* 如 sql 中的表名为 test.user,配置的表名也为 test.user
*/
if (StringUtils.equalsIgnoreCase(nameTemp, mappingName)) {
String value = mappingTable.get(mappingName);
if (StringUtils.isNotBlank(schema)) {
additionalTableNames.put(schema + "." + nameTemp, schema + "." + value);
} else {
additionalTableNames.put(nameTemp, value);
}
} else if (StringUtils.equalsIgnoreCase(fullTableName, mappingName)) {
additionalTableNames.put(fullTableName, mappingName);
}
}
}
if (additionalTableNames.size() > 0) {
mappingTable.putAll(additionalTableNames);
}
visitor.setTableMapping(mappingTable);
sqlStatement.accept(visitor);
}
} catch (Throwable e) {
if (GlobalConfig.getInstance().getWrongSqlDetail().size() < 10) {
GlobalConfig.getInstance().addWrongSqlDetail(StringUtils.substring(("Exception:" + e + " sql" + sql), 0, 1995));
}
throw new SQLException("Wrong sql:" + sql, e);
}
SQLStatementParser parser2 = SQLParserUtils.createSQLStatementParser(val.toString(), dbTypeName);
final List<SQLStatement> sqlStatements2 = parser2.parseStatementList();
for (final SQLStatement sqlStatement : sqlStatements2) {
if (sqlStatement instanceof SQLInsertStatement || sqlStatement instanceof SQLUpdateStatement || sqlStatement instanceof SQLDeleteStatement || sqlStatement instanceof SQLAlterTableStatement || sqlStatement instanceof SQLDropTableStatement || sqlStatement instanceof SQLCreateTableStatement || sqlStatement instanceof MySqlRenameTableStatement) {
SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(dbType);
sqlStatement.accept(visitor);
final Map<TableStat.Name, TableStat> map = visitor.getTables();
for (final TableStat.Name name : map.keySet()) {
boolean passThisTable = false;
String nameTemp = SQLUtils.normalize(name.getName(), dbType);
if (nameTemp != null && StringUtils.contains(nameTemp, ".")) {
nameTemp = StringUtils.substringAfter(nameTemp, ".");
}
if ("DUAL".equalsIgnoreCase(nameTemp)) {
// dual table no need pt table
passThisTable = true;
} else {
for (final String mappingname : mappingTable.values()) {
if (StringUtils.equalsIgnoreCase(nameTemp, mappingname)) {
passThisTable = true;
}
}
}
if (!passThisTable) {
if (GlobalConfig.getInstance().getWrongSqlDetail().size() < 10) {
GlobalConfig.getInstance().addWrongSqlDetail(StringUtils.substring(sql, 0, 1995));
}
String url = key;
if (url.indexOf('|') != -1) {
url = url.substring(0, url.indexOf('|'));
}
int idx = key.lastIndexOf('|');
String userName = idx > 0 ? key.substring(idx + 1) : "未知";
ErrorReporter.buildError().setErrorType(ErrorTypeEnum.DataSource).setErrorCode("datasource-0004").setMessage(String.format("没有配置对应的影子表! url:%s, table:%s, driverClassName:%s, dbType:%s, userName:%s, 中间件类型:%s", url, name.getName(), getDriverClassName(url), dbType, userName, midType)).setDetail(String.format("The business table [%s] doesn't has shadow mapping table! url:%s, table:%s, " + "driverClassName:%s, dbType:%s, [sql] %s [new sql] %s", name.getName(), url, name.getName(), getDriverClassName(url), dbType, sql, val)).closePradar(ConfigNames.SHADOW_DATABASE_CONFIGS).report();
throw new SQLException(String.format("The business table [%s] doesn't has shadow mapping table! url:%s, table:%s, " + "driverClassName:%s, dbType:%s, username:%s, 中间件类型:%s, [sql] %s [new sql] %s", name.getName(), url, name.getName(), getDriverClassName(url), dbType, userName, midType, sql, val));
}
}
}
}
return val.toString();
}
Aggregations