|
@@ -70,18 +70,21 @@ public class SqlIllegalInterceptor implements Interceptor {
|
|
|
/**
|
|
|
* cache the legal sql result.
|
|
|
*/
|
|
|
- private final Set<String> legalSqlCacheSet = new HashSet<>();
|
|
|
+ private final Set<String> legalSqlCacheSet = new HashSet<>();
|
|
|
/**
|
|
|
* cache the index info exist on the column.
|
|
|
*/
|
|
|
- private final Set<String> indexInfoCacheSet = new CopyOnWriteArraySet<>();
|
|
|
+ private static final Set<String> indexInfoCacheSet = new CopyOnWriteArraySet<>();
|
|
|
/**
|
|
|
* cache the table had load index info from the connection.
|
|
|
*/
|
|
|
- private final Set<String> tableCacheSet = new HashSet<>();
|
|
|
+ private static final Set<String> tableCacheSet = new HashSet<>();
|
|
|
@Getter
|
|
|
@Setter
|
|
|
- private boolean devMode = true;
|
|
|
+ private boolean devMode = true;
|
|
|
+ @Getter
|
|
|
+ @Setter
|
|
|
+ private boolean sqlWrite = false;
|
|
|
@Override
|
|
|
public Object intercept(Invocation invocation) throws Throwable {
|
|
|
StatementHandler statementHandler = SqlUtils.realTarget(invocation.getTarget());
|
|
@@ -93,7 +96,7 @@ public class SqlIllegalInterceptor implements Interceptor {
|
|
|
}
|
|
|
String originalSql = statementHandler.getBoundSql().getSql();
|
|
|
log.info("Verifying SQL ID: {}", mappedStatement.getId());
|
|
|
- if (!devMode) {
|
|
|
+ if (sqlWrite) {
|
|
|
log.info("Verifying SQL:");
|
|
|
log.info(originalSql);
|
|
|
}
|
|
@@ -142,15 +145,19 @@ public class SqlIllegalInterceptor implements Interceptor {
|
|
|
@Override
|
|
|
public void setProperties(Properties prop) {
|
|
|
String devMode = prop.getProperty("devMode");
|
|
|
+ String sqlWrite = prop.getProperty("sqlWrite");
|
|
|
if (SqlUtils.isBoolean(devMode)) {
|
|
|
this.devMode = Boolean.valueOf(devMode);
|
|
|
}
|
|
|
+ if (SqlUtils.isBoolean(devMode)) {
|
|
|
+ this.sqlWrite = Boolean.valueOf(sqlWrite);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* the rules of illegal sql.
|
|
|
*/
|
|
|
- private class IllegalRule {
|
|
|
+ private static class IllegalRule {
|
|
|
// the list of where exp parse from the sql to verify.
|
|
|
private List<Expression> wheres = new ArrayList<>();
|
|
|
// the list of index info parse from the sql to verify.
|
|
@@ -294,51 +301,52 @@ public class SqlIllegalInterceptor implements Interceptor {
|
|
|
* @param indexInfo include catalog & schema & tableName & columnName to Specify a unique index.
|
|
|
*/
|
|
|
private int columnNoUseIndex(IndexInfo indexInfo) {
|
|
|
- String indexCache = indexInfo.fullyQualifiedColumn();
|
|
|
+ String fullyQualifiedColumn = indexInfo.fullyQualifiedColumn();
|
|
|
//if the column has set. and the cache contains the column.
|
|
|
- if (indexInfo.fullyColumn() && indexInfoCacheSet.contains(indexCache)) {
|
|
|
+ if (indexInfo.fullyColumn() && indexInfoCacheSet.contains(fullyQualifiedColumn)) {
|
|
|
return 1;
|
|
|
}
|
|
|
//if the table has set. and the cache do not contains the table.
|
|
|
- String tableCache = indexInfo.fullyQualifiedTable();
|
|
|
+ String fullyQualifiedTable = indexInfo.fullyQualifiedTable();
|
|
|
// if new create index on the column. must to reload index,
|
|
|
- if (indexInfo.fullyTable() && !tableCacheSet.contains(tableCache)) {
|
|
|
- //get index info from the connection.
|
|
|
- try (ResultSet resultSet = databaseMetaData.getIndexInfo(indexInfo.catalog, indexInfo.schema, indexInfo.tableName, false, true)){
|
|
|
- int indexCount = 0;
|
|
|
- while (resultSet.next()) {
|
|
|
- //索引中的列序列号等于1,才有效, index: 8, label: ORDINAL_POSITION
|
|
|
- if (resultSet.getShort("ORDINAL_POSITION") == 1) {
|
|
|
- //在索引中的列名列 index:9, label: COLUMN_NAME
|
|
|
- IndexInfo index = IndexInfo.newInstance();
|
|
|
- //TABLE_CAT
|
|
|
- index.setCatalog(indexInfo.catalog);
|
|
|
- //TABLE_SCHEM
|
|
|
- index.setSchema(indexInfo.schema);
|
|
|
- //TABLE_NAME
|
|
|
- index.setTableName(indexInfo.tableName);
|
|
|
- //COLUMN_NAME
|
|
|
- index.setColumnName(resultSet.getString("COLUMN_NAME"));
|
|
|
- indexInfoCacheSet.add(index.fullyQualifiedColumn());
|
|
|
- indexCount++;
|
|
|
- //cache table, no reload index every time.
|
|
|
- tableCacheSet.add(index.fullyQualifiedTable());
|
|
|
- }
|
|
|
- }
|
|
|
- if (indexCount > 6) {
|
|
|
- addMessage("Too many indexes (%s > 6) use on table (%s).", indexCount, tableCache);
|
|
|
+ if (indexInfo.fullyTable() && tableCacheSet.contains(fullyQualifiedTable)) {
|
|
|
+ addMessage("Index not use on %s. Example sql: CREATE [UNIQUE|CLUSTERED] INDEX idx_%s ON %s(%s)", fullyQualifiedColumn, indexInfo.columnName, indexInfo.tableName, indexInfo.columnName);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ //get index info from the connection.
|
|
|
+ try (ResultSet resultSet = databaseMetaData.getIndexInfo(indexInfo.catalog, indexInfo.schema, indexInfo.tableName, false, true)) {
|
|
|
+ int indexCount = 0;
|
|
|
+ while (resultSet.next()) {
|
|
|
+ //索引中的列序列号等于1,才有效, index: 8, label: ORDINAL_POSITION
|
|
|
+ if (resultSet.getShort("ORDINAL_POSITION") == 1) {
|
|
|
+ //在索引中的列名列 index:9, label: COLUMN_NAME
|
|
|
+ IndexInfo index = IndexInfo.newInstance();
|
|
|
+ //TABLE_CAT
|
|
|
+ index.setCatalog(indexInfo.catalog);
|
|
|
+ //TABLE_SCHEM
|
|
|
+ index.setSchema(indexInfo.schema);
|
|
|
+ //TABLE_NAME
|
|
|
+ index.setTableName(indexInfo.tableName);
|
|
|
+ //COLUMN_NAME
|
|
|
+ index.setColumnName(resultSet.getString("COLUMN_NAME"));
|
|
|
+ indexInfoCacheSet.add(index.fullyQualifiedColumn());
|
|
|
+ indexCount++;
|
|
|
+ //cache table, no reload index every time.
|
|
|
+ tableCacheSet.add(index.fullyQualifiedTable());
|
|
|
}
|
|
|
- log.info("Cache index: {}, table: {}", indexInfoCacheSet.size(), tableCacheSet.size());
|
|
|
- } catch (SQLException e) {
|
|
|
- log.error("get index info from DatabaseMetaData fail.");
|
|
|
}
|
|
|
+ if (indexCount > 6) {
|
|
|
+ addMessage("Too many indexes (%s > 6) use on table (%s).", indexCount, fullyQualifiedTable);
|
|
|
+ }
|
|
|
+ log.info("Cache index: {}, table: {}", indexInfoCacheSet.size(), tableCacheSet.size());
|
|
|
+ } catch (SQLException e) {
|
|
|
+ log.error("get index info from DatabaseMetaData fail.");
|
|
|
}
|
|
|
- boolean useIndex = indexInfoCacheSet.contains(indexCache);
|
|
|
- if (!useIndex) {
|
|
|
- addMessage("Index not use on %s. Example sql: CREATE [UNIQUE|CLUSTERED] INDEX idx_%s ON %s(%s)", indexCache, indexInfo.columnName, indexInfo.tableName, indexInfo.columnName);
|
|
|
- return 0;
|
|
|
+ if (indexInfo.fullyColumn() && indexInfoCacheSet.contains(fullyQualifiedColumn)) {
|
|
|
+ return 1;
|
|
|
}
|
|
|
- return 1;
|
|
|
+ addMessage("Index not use on %s. Example sql: CREATE [UNIQUE|CLUSTERED] INDEX idx_%s ON %s(%s)", fullyQualifiedColumn, indexInfo.columnName, indexInfo.tableName, indexInfo.columnName);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -647,6 +655,33 @@ public class SqlIllegalInterceptor implements Interceptor {
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
+ private boolean isSelect(Statement statement) {
|
|
|
+ return (statement instanceof Select);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isUpdate(Statement statement) {
|
|
|
+ return (statement instanceof Update);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isDelete(Statement statement) {
|
|
|
+ return (statement instanceof Delete);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isPlainSelect(Object object) {
|
|
|
+ return (object instanceof PlainSelect);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isSubSelect(Object object) {
|
|
|
+ return (object instanceof SubSelect);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isBinary(Expression expression) {
|
|
|
+ return (expression instanceof BinaryExpression);
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isColumn(Expression expression) {
|
|
|
+ return (expression instanceof Column);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Data
|
|
@@ -736,23 +771,23 @@ public class SqlIllegalInterceptor implements Interceptor {
|
|
|
private String tableName;
|
|
|
private String columnName;
|
|
|
|
|
|
- public static IndexInfo newInstance(){
|
|
|
+ private static IndexInfo newInstance() {
|
|
|
return new IndexInfo();
|
|
|
}
|
|
|
|
|
|
- public boolean fullyColumn() {
|
|
|
+ private boolean fullyColumn() {
|
|
|
return SqlUtils.notNull(getTableName(), getColumnName());
|
|
|
}
|
|
|
|
|
|
- public boolean fullyTable() {
|
|
|
+ private boolean fullyTable() {
|
|
|
return SqlUtils.notNull(getTableName());
|
|
|
}
|
|
|
|
|
|
- public String fullyQualifiedColumn() {
|
|
|
+ private String fullyQualifiedColumn() {
|
|
|
return fullyColumn() ? String.format("%s.%s.%s.%s", fixCatalog(), fixSchema(), getTableName(), getColumnName()) : null;
|
|
|
}
|
|
|
|
|
|
- public String fullyQualifiedTable() {
|
|
|
+ private String fullyQualifiedTable() {
|
|
|
return fullyTable() ? String.format("%s.%s.%s", fixCatalog(), fixSchema(), getTableName()) : null;
|
|
|
}
|
|
|
|
|
@@ -764,32 +799,4 @@ public class SqlIllegalInterceptor implements Interceptor {
|
|
|
return null == this.schema ? "<schema>" : this.schema;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- private boolean isSelect(Statement statement) {
|
|
|
- return (statement instanceof Select);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isUpdate(Statement statement) {
|
|
|
- return (statement instanceof Update);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isDelete(Statement statement) {
|
|
|
- return (statement instanceof Delete);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isPlainSelect(Object object) {
|
|
|
- return (object instanceof PlainSelect);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isSubSelect(Object object) {
|
|
|
- return (object instanceof SubSelect);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isBinary(Expression expression) {
|
|
|
- return (expression instanceof BinaryExpression);
|
|
|
- }
|
|
|
-
|
|
|
- private boolean isColumn(Expression expression) {
|
|
|
- return (expression instanceof Column);
|
|
|
- }
|
|
|
}
|