use of com.shulie.druid.sql.parser.SQLStatementParser in project LinkAgent by shulieTech.
the class SqlParser method parseTables.
private static TableParserResult parseTables(String sql, String dbTypeName) throws SQLException {
DbType dbType = DbType.of(dbTypeName);
boolean isSelect = true;
List<String> tables = new ArrayList<String>();
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbTypeName);
if (parser == null) {
if (GlobalConfig.getInstance().getWrongSqlDetail().size() < 10) {
GlobalConfig.getInstance().addWrongSqlDetail(StringUtils.substring("dbType not support dbType" + dbTypeName + " sql" + sql, 0, 1995));
}
throw new SQLException("dbType not support 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) {
if (!(sqlStatement instanceof SQLSelectStatement)) {
isSelect = false;
}
SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(val, dbType);
SchemaStatVisitor visitor2 = SQLUtils.createSchemaStatVisitor(dbType);
sqlStatement.accept(visitor2);
final Map<TableStat.Name, TableStat> map2 = visitor2.getTables();
for (final TableStat.Name name : map2.keySet()) {
/**
* 过滤掉函数
*/
String tableName = name.getName();
if (StringUtils.indexOf(tableName, '(') != -1 && StringUtils.indexOf(tableName, ')') != -1) {
continue;
}
if ("DUAL".equalsIgnoreCase(tableName)) {
continue;
}
// 这里的表名可能会带 schema,如 test.user
tableName = StringUtils.replace(tableName, "\"", "");
if (!tables.contains(tableName)) {
tables.add(tableName);
}
}
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);
}
return new TableParserResult(tables, isSelect);
}
use of com.shulie.druid.sql.parser.SQLStatementParser in project LinkAgent by shulieTech.
the class SqlParser method parseAndReplaceSchema.
/**
* 替换 schema
*
* @param sql
* @param key
* @param dbTypeName
* @return
* @throws SQLException
*/
public static String parseAndReplaceSchema(String sql, String key, String dbTypeName) throws SQLException {
sql = sql.replaceAll("< >", "<>");
ShadowDatabaseConfig config = GlobalConfig.getInstance().getShadowDatabaseConfig(key);
if (config == null) {
return sql;
}
DbType dbType = DbType.of(dbTypeName);
// 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();
Map<String, String> map = new HashMap<String, String>();
for (Map.Entry<TableStat.Name, TableStat> entry : map2.entrySet()) {
String fullTable = StringUtils.replace(entry.getKey().getName(), "\"", "");
/**
* 过滤掉函数
*/
if (StringUtils.indexOf(fullTable, '(') != -1 && StringUtils.indexOf(fullTable, ')') != -1) {
continue;
}
String table = null, schema = null;
final int indexOfDot = StringUtils.indexOf(fullTable, '.');
if (indexOfDot == -1) {
schema = null;
table = fullTable;
} else {
schema = StringUtils.substring(fullTable, 0, indexOfDot);
table = StringUtils.substring(fullTable, indexOfDot + 1);
}
String shadowSchema = toShadowSchema(schema, config);
String shadowTable = toShadowTable(table, config);
if (StringUtils.isBlank(shadowSchema)) {
map.put(fullTable, shadowTable);
} else {
map.put(fullTable, shadowSchema + '.' + shadowTable);
map.put(schema, shadowSchema);
}
}
visitor.setTableMapping(map);
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);
}
return val.toString();
}
use of com.shulie.druid.sql.parser.SQLStatementParser 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