Skip to content
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.github.wz2cool</groupId>
<artifactId>canal-utils</artifactId>
<version>0.2.16</version>
<version>0.2.17</version>
<packaging>jar</packaging>

<organization>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,16 @@ protected Optional<String> convertToDropColumnSql(AlterColumnExpression alterCol
protected List<String> convertToOtherColumnActionSqlList(List<AlterColumnExpression> alterColumnExpressions) {
return new ArrayList<>();
}

@Override
protected Optional<String> convertToDropIndexSql(AlterColumnExpression alterColumnExpression) {
// Hive 不支持索引操作,返回空
return Optional.empty();
}

@Override
protected Optional<String> convertToAddIndexSql(AlterColumnExpression alterColumnExpression) {
// Hive 不支持索引操作,返回空
return Optional.empty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,12 @@ protected Optional<String> convertToDropColumnSql(AlterColumnExpression alterCol
protected List<String> convertToOtherColumnActionSqlList(List<AlterColumnExpression> alterColumnExpressions) {
return new ArrayList<>();
}

@Override
protected Optional<String> convertToDropIndexSql(AlterColumnExpression alterColumnExpression) {
String tableName = alterColumnExpression.getTableName();
String indexName = alterColumnExpression.getColumnName();
String sql = String.format("DROP INDEX %s ON %s;", indexName, tableName);
return Optional.of(sql);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ protected Optional<String> convertToDropColumnSql(AlterColumnExpression alterCol
return generateDropColumnSql(alterColumnExpression);
}

@Override
protected List<String> convertToOtherColumnActionSqlList(List<AlterColumnExpression> alterColumnExpressions) {
return new ArrayList<>();
}

@Override
protected Optional<String> convertToDropIndexSql(AlterColumnExpression alterColumnExpression) {
return generateDropIndexSql(alterColumnExpression);
}

@Override
protected Optional<String> convertToAddIndexSql(AlterColumnExpression alterColumnExpression) {
return generateAddIndexSql(alterColumnExpression);
}

@Override
protected Optional<String> convertToCreateIndexSql(AlterColumnExpression alterColumnExpression) {
return generateCreateIndexSql(alterColumnExpression);
}

private Optional<String> generateSql(String action, AlterColumnExpression alterColumnExpression) {
SqlContext sqlContext = new SqlContext(
action,
Expand Down Expand Up @@ -111,9 +131,80 @@ private Optional<String> generateDropColumnSql(AlterColumnExpression alterColumn
return Optional.of(sql);
}

@Override
protected List<String> convertToOtherColumnActionSqlList(List<AlterColumnExpression> alterColumnExpressions) {
return new ArrayList<>();
private Optional<String> generateDropIndexSql(AlterColumnExpression alterColumnExpression) {
SqlContext sqlContext = new SqlContext(
"DROP INDEX",
"",
alterColumnExpression.getTableName(),
alterColumnExpression.getColumnName(),
null,
null,
null,
"",
""
);

for (AlterSqlConverterDecorator decorator : decorators) {
sqlContext = decorator.apply(this, alterColumnExpression, sqlContext);
}

String qualifiedTableName = getQualifiedTableName(sqlContext.schemaName, sqlContext.tableName);
String formattedIndexName = getFormattedColumnNameOrEmpty(sqlContext.oldColumnName);
String sql = String.format("ALTER TABLE %s DROP INDEX %s;", qualifiedTableName, formattedIndexName).trim();
return Optional.of(sql);
}

private Optional<String> generateAddIndexSql(AlterColumnExpression alterColumnExpression) {
SqlContext sqlContext = new SqlContext(
"ADD CONSTRAINT",
"",
alterColumnExpression.getTableName(),
alterColumnExpression.getColumnName(),
alterColumnExpression.getColOldName(),
null,
null,
"",
alterColumnExpression.getCommentText()
);

for (AlterSqlConverterDecorator decorator : decorators) {
sqlContext = decorator.apply(this, alterColumnExpression, sqlContext);
}

String qualifiedTableName = getQualifiedTableName(sqlContext.schemaName, sqlContext.tableName);
String formattedConstraintName = getFormattedColumnNameOrEmpty(sqlContext.oldColumnName);
String constraintType = sqlContext.newColumnName;
String columns = sqlContext.commentText;

String sql = String.format("ALTER TABLE %s ADD CONSTRAINT %s %s (%s);",
qualifiedTableName, formattedConstraintName, constraintType, columns).trim();
return Optional.of(sql);
}

private Optional<String> generateCreateIndexSql(AlterColumnExpression alterColumnExpression) {
SqlContext sqlContext = new SqlContext(
"CREATE INDEX",
"",
alterColumnExpression.getTableName(),
alterColumnExpression.getColumnName(),
null,
null,
null,
"",
alterColumnExpression.getCommentText()
);

for (AlterSqlConverterDecorator decorator : decorators) {
sqlContext = decorator.apply(this, alterColumnExpression, sqlContext);
}

String qualifiedTableName = getQualifiedTableName(sqlContext.schemaName, sqlContext.tableName);
String formattedIndexName = getFormattedColumnNameOrEmpty(sqlContext.oldColumnName);
String columns = sqlContext.commentText;

String sql = String.format("CREATE INDEX %s ON %s (%s);",
formattedIndexName, qualifiedTableName, columns).trim();
return Optional.of(sql);
}

protected String generateColumnSql(String action, String schemaName, String tableName, String oldColumnName, String newColumnName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,17 @@ public enum EnhancedAlterOperation {
/**
* The operation of drop column.
*/
DROP_COLUMN
DROP_COLUMN,
/**
* The operation of drop index.
*/
DROP_INDEX,
/**
* The operation of add index.
*/
ADD_INDEX,
/**
* The operation of create index.
*/
CREATE_INDEX
}
117 changes: 117 additions & 0 deletions src/main/java/com/github/wz2cool/canal/utils/regex/SqlCleaner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package com.github.wz2cool.canal.utils.regex;

/**
* SQL 清理工具类
* 提供 SQL 语句的清理和格式化功能
*
* @author YinPengHai
*/
public class SqlCleaner {

// 私有构造函数,防止实例化
private SqlCleaner() {
throw new UnsupportedOperationException("Utility class cannot be instantiated");
}

/**
* 清理 SQL 中的逗号问题
* 处理移除索引操作后可能出现的各种逗号问题
*
* @param sql 需要清理的 SQL 语句
* @return 清理后的 SQL 语句
*/
public static String cleanCommas(String sql) {
String result = sql;

// 1. 清理连续的逗号 (,, -> ,)
result = cleanConsecutiveCommas(result);

// 2. 清理表名后直接跟逗号的情况 (alter table xxx, -> alter table xxx )
result = cleanCommaAfterTableName(result);

// 3. 清理逗号后直接跟分号的情况 (, ; -> ;)
result = cleanCommaBeforeSemicolon(result);

// 4. 清理开头的逗号 (, xxx -> xxx)
result = cleanLeadingComma(result);

// 5. 清理结尾的逗号 (xxx, -> xxx)
result = cleanTrailingComma(result);

// 6. 规范化空格
result = normalizeWhitespace(result);

return result;
}

/**
* 清理连续的逗号
* 例如: "a,, b" -> "a, b"
*/
private static String cleanConsecutiveCommas(String sql) {
return sql.replaceAll(",\\s*,", ",");
}

/**
* 清理表名后直接跟逗号的情况
* 例如: "alter table test, drop column col" -> "alter table test drop column col"
*/
private static String cleanCommaAfterTableName(String sql) {
return sql.replaceAll("(?i)(alter\\s+table\\s+\\S+)\\s*,\\s*", "$1 ");
}

/**
* 清理逗号后直接跟分号的情况
* 例如: "alter table test add column col1 int, ;" -> "alter table test add column col1 int;"
*/
private static String cleanCommaBeforeSemicolon(String sql) {
return sql.replaceAll(",\\s*;", ";");
}

/**
* 清理开头的逗号
* 例如: ", drop column col" -> "drop column col"
*/
private static String cleanLeadingComma(String sql) {
return sql.replaceAll("^\\s*,\\s*", "");
}

/**
* 清理结尾的逗号
* 例如: "alter table test add column col1 int," -> "alter table test add column col1 int"
*/
private static String cleanTrailingComma(String sql) {
return sql.replaceAll(",\\s*$", "");
}

/**
* 规范化空格
* 将多个连续空格替换为单个空格,并去除首尾空格
*/
private static String normalizeWhitespace(String sql) {
return sql.replaceAll("\\s+", " ").trim();
}

/**
* 清理 MySQL ALTER 语句中的特殊关键字
* 移除一些可能导致解析问题的关键字
*
* @param sql 原始 SQL 语句
* @return 清理后的 SQL 语句
*/
public static String cleanMysqlAlterSql(String sql) {
return sql.replace("COLLATE", "")
.replace("collate", "");
}

/**
* 清理文本中的反引号
* MySQL 中的表名和列名可能包含反引号,需要清理
*
* @param text 包含反引号的文本
* @return 清理后的文本
*/
public static String cleanBackticks(String text) {
return text.replace("`", "");
}
}
Loading