Skip to content
This repository has been archived by the owner on Jun 8, 2024. It is now read-only.

Commit

Permalink
fixed #82 migrate binary and prepare null
Browse files Browse the repository at this point in the history
  • Loading branch information
wentaojin committed Jan 23, 2024
1 parent 4d97e42 commit 8334cb3
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 10 deletions.
58 changes: 58 additions & 0 deletions common/strings.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,3 +535,61 @@ func PathExist(path string) error {
}
return err
}

// EscapeBinaryCSV 转义二进制数据
func EscapeBinaryCSV(s []byte, escapeBackslash bool, delimiterCsv, separatorCsv string) string {
switch {
case escapeBackslash:
return escapeBackslashCSV(s, delimiterCsv, separatorCsv)
case len(delimiterCsv) > 0:
delimiter := []byte(delimiterCsv)
return string(bytes.ReplaceAll(s, delimiter, append(delimiter, delimiter...)))
default:
return string(s)
}
}

func escapeBackslashCSV(s []byte, delimiterCsv, separatorCsv string) string {
bf := bytes.Buffer{}

var (
escape byte
last = 0
specCmt byte = 0
)

delimiter := []byte(delimiterCsv)
separator := []byte(separatorCsv)

if len(delimiter) > 0 {
specCmt = delimiter[0] // if csv has a delimiter, we should use backslash to comment the delimiter in field value
} else if len(separator) > 0 {
specCmt = separator[0] // if csv's delimiter is "", we should escape the separator to avoid error
}

for i := 0; i < len(s); i++ {
escape = 0

switch s[i] {
case 0: /* Must be escaped for 'mysql' */
escape = '0'
case '\r':
escape = 'r'
case '\n': /* escaped for line terminators */
escape = 'n'
case '\\':
escape = '\\'
case specCmt:
escape = specCmt
}

if escape != 0 {
bf.Write(s[last:i])
bf.WriteByte('\\')
bf.WriteByte(escape)
last = i + 1
}
}
bf.Write(s[last:])
return bf.String()
}
15 changes: 6 additions & 9 deletions database/oracle/full.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func (o *Oracle) GetOracleTableRowsDataCSV(querySQL, sourceDBCharset, targetDBCh
rowData[tableColumnNameIndex[columnNames[i]]] = r.String()
case "[]uint8":
// binary data -> raw、long raw、blob
rowData[tableColumnNameIndex[columnNames[i]]] = fmt.Sprintf("%v", raw)
rowData[tableColumnNameIndex[columnNames[i]]] = common.EscapeBinaryCSV(raw, cfg.CSVConfig.EscapeBackslash, cfg.CSVConfig.Delimiter, cfg.CSVConfig.Separator)
default:
var convertTargetRaw []byte

Expand Down Expand Up @@ -416,15 +416,12 @@ func (o *Oracle) GetOracleTableRowsData(querySQL string, insertBatchSize, callTi
}

for i, raw := range rawResult {
// 注意 Oracle/Mysql NULL VS 空字符串区别
// Oracle 空字符串与 NULL 归于一类,统一 NULL 处理 (is null 可以查询 NULL 以及空字符串值,空字符串查询无法查询到空字符串值)
// Mysql 空字符串与 NULL 非一类,NULL 是 NULL,空字符串是空字符串(is null 只查询 NULL 值,空字符串查询只查询到空字符串值)
// 按照 Oracle 特性来,转换同步统一转换成 NULL 即可,但需要注意业务逻辑中空字符串得写入,需要变更
// Oracle/Mysql 对于 'NULL' 统一字符 NULL 处理,查询出来转成 NULL,所以需要判断处理
if raw == nil {
rowsMap[cols[i]] = `NULL`
//rowsMap[cols[i]] = `NULL` -> sql
rowsMap[cols[i]] = nil
} else if string(raw) == "" {
rowsMap[cols[i]] = `NULL`
//rowsMap[cols[i]] = `NULL` -> sql
rowsMap[cols[i]] = nil
} else {
switch columnTypes[i] {
case "int64":
Expand Down Expand Up @@ -465,7 +462,7 @@ func (o *Oracle) GetOracleTableRowsData(querySQL string, insertBatchSize, callTi
rowsMap[cols[i]] = fmt.Sprintf("%v", r)
case "[]uint8":
// binary data -> raw、long raw、blob
rowsMap[cols[i]] = fmt.Sprintf("%v", raw)
rowsMap[cols[i]] = raw
default:
// 特殊字符
convertUtf8Raw, err := common.CharsetConvert(raw, sourceDBCharset, common.CharsetUTF8MB4)
Expand Down
2 changes: 1 addition & 1 deletion example/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ source-schema = "marvin"
# 源端迁移任务表(只用于 prepare/reverse/check/all/full 阶段,assess 阶段不适用,assess 只适用于 schema 级别)
# include-table 和 exclude-table 不能同时配置,两者只能配置一个,如果两个都没配置则 Schema 内表全迁移
# include-table 和 exclude-table 支持正则表达式以及通配符(tab_*/tab*)
source-include-table = ["ganyq0"]
source-include-table = ["kp"]
source-exclude-table = []
# 目标端 schema
target-schema = "marvin"
Expand Down

0 comments on commit 8334cb3

Please sign in to comment.