背景:数据源迁移,目标数据源和原始数据源的语法不同,要把建表语句全都改成新的语法。
一个个sql文件去替换实在是麻烦,可以把原始的sql文件放在一个文件夹,然后用程序一跑,改完语法的sql语句就放在新的文件夹里了。
主要用到的File文件操作,一行一行解析;
还有比较巧妙的是用到了String.format()方法,%s作为占位符,会被替换成后面跟着的参数。
package com.test;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
public class SqlTransTest {
public static void main(String[] args) throws Exception {
long start = System.currentTimeMillis();
File srcDir = new File("C:\\Users\\humeng\\Desktop\\ori");
File targetDir = new File("C:\\Users\\humeng\\Desktop\\out");
File[] files = srcDir.listFiles();
if (!ArrayUtils.isEmpty(files)) {
for (File file : files) {
if (file.isHidden()) {
continue;
}
List<String> out = new ArrayList<>();
List<String> append = new ArrayList<>();
AtomicReference<String> tableName = new AtomicReference<>();
List<String> lines = FileUtils.readLines(file, Charset.defaultCharset());
lines.forEach(line -> {
if (StringUtils.isBlank(line) || "(".equals(line) || ")".equals(line)) {
out.add(line);
return;
}
if (line.startsWith("CREATE TABLE ")) {
String tableNameStr = line.replace("CREATE TABLE ", "");
tableNameStr = String.format("dim.%s", tableNameStr.substring(tableNameStr.indexOf(".") + 1));
if (tableNameStr.contains(" COMMENT ")) {
String[] tableInfos = tableNameStr.split(" COMMENT ");
tableNameStr = tableInfos[0];
append.add(String.format("COMMENT ON TABLE %s IS %s;", tableNameStr, tableInfos[1]));
}
tableName.set(tableNameStr);
out.add(String.format("CREATE TABLE %s", tableName.get()));
return;
}
if (line.toUpperCase().startsWith("PARTITIONED BY ")) {
System.out.println("发现分区语句:"+file.getName()+"===>"+line);
// todo 分区转换
return;
}
String endChar = line.endsWith(",") ? "," : "";
String[] columnInfos = line.replace(" ", " ").replace(" ,", ",").split(" ");
out.add(columnInfos[0] + " " + tranType(columnInfos[1], file.getName()) + endChar);
if (columnInfos.length > 2) {
if (!StringUtils.equalsIgnoreCase("comment", columnInfos[2])) {
System.out.println("发现未知语句:"+file.getName()+"===>"+line);
// todo 看下sql是否存在异常,针对性修改sql或补充转换处理
return;
}
String[] columnSections = line.split(String.format(" %s ", columnInfos[2]));
if (columnSections.length > 2) {
System.out.println("sql异常,发现单行多comment语句:"+file.getName()+"===>"+line);
// todo 看下sql是否存在异常,针对性修改sql或补充转换处理
return;
}
String commentStr = columnSections[1];
if (commentStr.endsWith(",")) {
commentStr = commentStr.substring(0, commentStr.length() - 1);
}
append.add(String.format("COMMENT ON COLUMN %s.%s IS %s;", tableName.get(), columnInfos[0], commentStr));
}
});
out.add("");
out.add("TABLESPACE ctg169519944208");
out.add("DISTRIBUTED RANDOMLY");
out.add("");
out.addAll(append);
FileUtils.writeLines(new File(targetDir, file.getName()), out);
System.out.println("文件写入完成====>" + file.getName());
}
}
long end = System.currentTimeMillis();
System.out.println("全部文件写入完成,耗时" + (end - start) + "毫秒");
}
private static String tranType(String typeStr, String fileName) {
if (typeStr.endsWith(",")) {
typeStr = typeStr.substring(0, typeStr.length() - 1);
}
if (typeStr.toUpperCase().startsWith("VARCHAR") || typeStr.toUpperCase().startsWith("INT")) {
return typeStr;
}
if (typeStr.toUpperCase().startsWith("NUMBER")) {
return "NUMERIC(36,18)";
}
if (typeStr.equalsIgnoreCase("LONG")) {
return "BIGINT";
}
if (typeStr.equalsIgnoreCase("DOUBLE")) {
return "DOUBLE PRECISION";
}
System.out.println("发现未知类型:"+ typeStr + "===>" + fileName);
return typeStr;
}
}
append就是后面追加的部分,这里全都是coment语句。
效果如图: