Repository: apache/incubator-seata-go
Pull request #719 (2024-11-29 08:24:10)

only inserted fields
What this PR does:
optimize: only the inserted fields are checked

Which issue(s) this PR fixes:
https://github.com/apache/incubator-seata-go/issues/697

Fixes #

Special notes for your reviewer:

Does this PR introduce a user-facing change?:

sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=apache_incubator-seata-go&pullRequest=719) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [20.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=apache_incubator-seata-go&pullRequest=719&metric=new_duplicated_lines_density&view=list) (required ≤ 3%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=apache_incubator-seata-go&pullRequest=719)


sonarcloud[bot]: ## [![Quality Gate Failed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-failed-20px.png 'Quality Gate Failed')](https://sonarcloud.io/dashboard?id=apache_incubator-seata-go&pullRequest=719) **Quality Gate failed**  
Failed conditions  
![](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/common/failed-16px.png '') [20.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=apache_incubator-seata-go&pullRequest=719&metric=new_duplicated_lines_density&view=list) (required ≤ 3%)  
  
[See analysis details on SonarQube Cloud](https://sonarcloud.io/dashboard?id=apache_incubator-seata-go&pullRequest=719)



Patch:
diff --git a/.golangci.yml b/.golangci.yml
index 1180b70..e558827 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -17,7 +17,7 @@
 
 linters-settings:
   govet:
-    check-shadowing: false
+    shadow: true
   golint:
     min-confidence: 0
   gocyclo:
@@ -56,13 +56,19 @@ linters:
     - staticcheck
     - ineffassign
     - misspell
+    - asciicheck
+    - bodyclose
+    - rowserrcheck
+    - gofmt
+    - durationcheck
+    - sqlclosecheck
 
 run:
-  skip-dirs:
-    - test/testdata_etc
-    - pkg/golinters/goanalysis/(checker|passes)
 
 issues:
+  exclude-dirs:
+    - test/testdata_etc
+    - pkg/golinters/goanalysis/(checker|passes)
   exclude-rules:
     - text: "weak cryptographic primitive"
       linters:
@@ -70,11 +76,17 @@ issues:
     - linters:
         - staticcheck
       text: "SA1019:"
+    - path: _test\.go
+      linters:
+        - errcheck
+        - gosec
+        - rowserrcheck
+        - govet
 
 # golangci.com configuration
 # https://github.com/golangci/golangci/wiki/Configuration
 service:
-  golangci-lint-version: 1.49.x # use the fixed version to not introduce new linters unexpectedly
+  golangci-lint-version: 1.57.x # use the fixed version to not introduce new linters unexpectedly
   prepare:
     - echo "here I can run custom commands, but no preparation needed for this repo"
 
diff --git a/README.md b/README.md
index e95785e..e2f2bd0 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ The principle of seata-go is consistent with that of Seata-java, which is compos
 ## TODO list
 
 - [x] TCC
-- [ ] XA
+- [x] XA
 - [x] AT
   - [x] Insert SQL
   - [x] Delete SQL
@@ -33,9 +33,9 @@ The principle of seata-go is consistent with that of Seata-java, which is compos
   - [x] Manually way
   - [x] Proxy datasource way 
 - [x] Null compensation
-- [ ] Configuration center
+- [x] Configuration center
   - [x] Configuration file
-- [ ] Registration Center
+- [x] Registration Center
 - [ ] Metric monitoring
 - [x] Compressor algorithm
 - [x] Examples
diff --git a/README_ZH.md b/README_ZH.md
index cea4ec1..3cc5814 100644
--- a/README_ZH.md
+++ b/README_ZH.md
@@ -17,7 +17,7 @@ Seata-go 的原理和 Seata-java 保持一致，都是由 TM、RM 和 TC 组成
 ## 待办事项
 
 - [x] TCC
-- [ ] XA
+- [x] XA
 - [x] AT
   - [x] Insert SQL
   - [x] Delete SQL
@@ -35,9 +35,9 @@ Seata-go 的原理和 Seata-java 保持一致，都是由 TM、RM 和 TC 组成
 - [x] 空补偿
   - [x] 手动方式
   - [x] 代理数据源方式
-- [ ] 配置中心
+- [x] 配置中心
   - [x] 配置文件
-- [ ] 注册中心
+- [x] 注册中心
 - [ ] Metric 监控
 - [x] 压缩算法
 - [x] Sample 例子
diff --git a/go.mod b/go.mod
index eb77d6a..e35e996 100644
--- a/go.mod
+++ b/go.mod
@@ -5,7 +5,7 @@ go 1.20
 require (
 	dubbo.apache.org/dubbo-go/v3 v3.0.4
 	github.com/DATA-DOG/go-sqlmock v1.5.0
-	github.com/apache/dubbo-getty v1.4.10
+	github.com/apache/dubbo-getty v1.5.0
 	github.com/arana-db/parser v0.2.5
 	github.com/bluele/gcache v0.0.2
 	github.com/dsnet/compress v0.0.1
@@ -31,7 +31,6 @@ require (
 )
 
 require (
-	github.com/agiledragon/gomonkey v2.0.2+incompatible
 	github.com/agiledragon/gomonkey/v2 v2.9.0
 	go.etcd.io/etcd/api/v3 v3.5.6
 	go.etcd.io/etcd/client/v3 v3.5.6
diff --git a/go.sum b/go.sum
index ae805fd..461c515 100644
--- a/go.sum
+++ b/go.sum
@@ -54,8 +54,6 @@ github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/
 github.com/Workiva/go-datastructures v1.0.52 h1:PLSK6pwn8mYdaoaCZEMsXBpBotr4HHn9abU0yMQt0NI=
 github.com/Workiva/go-datastructures v1.0.52/go.mod h1:Z+F2Rca0qCsVYDS8z7bAGm8f3UkzuWYS/oBZz5a7VVA=
 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
-github.com/agiledragon/gomonkey v2.0.2+incompatible h1:eXKi9/piiC3cjJD1658mEE2o3NjkJ5vDLgYjCQu0Xlw=
-github.com/agiledragon/gomonkey v2.0.2+incompatible/go.mod h1:2NGfXu1a80LLr2cmWXGBDaHEjb1idR6+FVlX5T3D9hw=
 github.com/agiledragon/gomonkey/v2 v2.9.0 h1:PDiKKybR596O6FHW+RVSG0Z7uGCBNbmbUXh3uCNQ7Hc=
 github.com/agiledragon/gomonkey/v2 v2.9.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY=
 github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
@@ -68,8 +66,8 @@ github.com/alibaba/sentinel-golang v1.0.4/go.mod h1:Lag5rIYyJiPOylK8Kku2P+a23gdK
 github.com/aliyun/alibaba-cloud-sdk-go v1.61.18/go.mod h1:v8ESoHo4SyHmuB4b1tJqDHxfTGEciD+yhvOU/5s1Rfk=
 github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
 github.com/apache/dubbo-getty v1.4.9-0.20221022181821-4dc6252ce98c/go.mod h1:6qmrqBSPGs3B35zwEuGhEYNVsx1nfGT/xzV2yOt2amM=
-github.com/apache/dubbo-getty v1.4.10 h1:ZmkpHJa/qgS0evX2tTNqNCz6rClI/9Wwp7ctyMml82w=
-github.com/apache/dubbo-getty v1.4.10/go.mod h1:V64WqLIxksEgNu5aBJBOxNIvpOZyfUJ7J/DXBlKSUoA=
+github.com/apache/dubbo-getty v1.5.0 h1:40RMjEoSfTuoG5EwKbGgfhjd7m6Zc7qBfOFgQv1jHCI=
+github.com/apache/dubbo-getty v1.5.0/go.mod h1:V64WqLIxksEgNu5aBJBOxNIvpOZyfUJ7J/DXBlKSUoA=
 github.com/apache/dubbo-go-hessian2 v1.9.1/go.mod h1:xQUjE7F8PX49nm80kChFvepA/AvqAZ0oh/UaB6+6pBE=
 github.com/apache/dubbo-go-hessian2 v1.9.3/go.mod h1:xQUjE7F8PX49nm80kChFvepA/AvqAZ0oh/UaB6+6pBE=
 github.com/apache/dubbo-go-hessian2 v1.11.4 h1:u8spEogpaZ82/k3bmv1PLYnha/wiwsIme15FuZZgkiI=
diff --git a/pkg/datasource/sql/datasource/mysql/trigger.go b/pkg/datasource/sql/datasource/mysql/trigger.go
index 5512a41..689ad2c 100644
--- a/pkg/datasource/sql/datasource/mysql/trigger.go
+++ b/pkg/datasource/sql/datasource/mysql/trigger.go
@@ -93,6 +93,7 @@ func (m *mysqlTrigger) getColumnMetas(ctx context.Context, dbName string, table
 	if err != nil {
 		return nil, err
 	}
+	defer stmt.Close()
 
 	rows, err := stmt.Query(dbName, table)
 	if err != nil {
@@ -144,7 +145,9 @@ func (m *mysqlTrigger) getColumnMetas(ctx context.Context, dbName string, table
 		columnMeta.Autoincrement = strings.Contains(strings.ToLower(extra), "auto_increment")
 		columnMetas = append(columnMetas, columnMeta)
 	}
-
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
 	if len(columnMetas) == 0 {
 		return nil, fmt.Errorf("can't find column")
 	}
@@ -162,7 +165,7 @@ func (m *mysqlTrigger) getIndexes(ctx context.Context, dbName string, tableName
 	if err != nil {
 		return nil, err
 	}
-
+	defer stmt.Close()
 	rows, err := stmt.Query(dbName, tableName)
 	if err != nil {
 		return nil, err
@@ -204,6 +207,8 @@ func (m *mysqlTrigger) getIndexes(ctx context.Context, dbName string, tableName
 		result = append(result, index)
 
 	}
-
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
 	return result, nil
 }
diff --git a/pkg/datasource/sql/exec/at/base_executor.go b/pkg/datasource/sql/exec/at/base_executor.go
index 75f0cab..05f4405 100644
--- a/pkg/datasource/sql/exec/at/base_executor.go
+++ b/pkg/datasource/sql/exec/at/base_executor.go
@@ -23,6 +23,7 @@ import (
 	"database/sql"
 	"database/sql/driver"
 	"fmt"
+	"seata.apache.org/seata-go/pkg/datasource/sql/undo"
 	"strings"
 
 	"github.com/arana-db/parser/ast"
@@ -187,6 +188,48 @@ func (b *baseExecutor) buildRecordImages(rowsi driver.Rows, tableMetaData *types
 	return &types.RecordImage{TableName: tableMetaData.TableName, Rows: rowImages, SQLType: sqlType}, nil
 }
 
+func (b *baseExecutor) getNeedColumns(meta *types.TableMeta, columns []string, dbType types.DBType) []string {
+	var needUpdateColumns []string
+	if undo.UndoConfig.OnlyCareUpdateColumns && columns != nil && len(columns) > 0 {
+		needUpdateColumns = columns
+		if !b.containsPKByName(meta, columns) {
+			pkNames := meta.GetPrimaryKeyOnlyName()
+			if pkNames != nil && len(pkNames) > 0 {
+				for _, name := range pkNames {
+					needUpdateColumns = append(needUpdateColumns, name)
+				}
+			}
+		}
+		// todo If it contains onUpdate columns, add onUpdate columns
+	} else {
+		needUpdateColumns = meta.ColumnNames
+	}
+
+	for i := range needUpdateColumns {
+		needUpdateColumns[i] = AddEscape(needUpdateColumns[i], dbType)
+	}
+	return needUpdateColumns
+}
+
+func (b *baseExecutor) containsPKByName(meta *types.TableMeta, columns []string) bool {
+	pkColumnNameList := meta.GetPrimaryKeyOnlyName()
+	if len(pkColumnNameList) == 0 {
+		return false
+	}
+
+	matchCounter := 0
+	for _, column := range columns {
+		for _, pkName := range pkColumnNameList {
+			if strings.EqualFold(pkName, column) ||
+				strings.EqualFold(pkName, strings.ToLower(column)) {
+				matchCounter++
+			}
+		}
+	}
+
+	return matchCounter == len(pkColumnNameList)
+}
+
 func getSqlNullValue(value interface{}) interface{} {
 	if value == nil {
 		return nil
diff --git a/pkg/datasource/sql/exec/at/escape.go b/pkg/datasource/sql/exec/at/escape.go
index 3133b40..bd8d1c6 100644
--- a/pkg/datasource/sql/exec/at/escape.go
+++ b/pkg/datasource/sql/exec/at/escape.go
@@ -142,7 +142,7 @@ func addEscape(colName string, dbType types.DBType, escape string) string {
 	buf := make([]byte, len(colName)+2)
 	buf[0], buf[len(buf)-1] = escape[0], escape[0]
 
-	for key, _ := range colName {
+	for key := range colName {
 		buf[key+1] = colName[key]
 	}
 
diff --git a/pkg/datasource/sql/exec/at/insert_executor.go b/pkg/datasource/sql/exec/at/insert_executor.go
index a05da50..ae7bac7 100644
--- a/pkg/datasource/sql/exec/at/insert_executor.go
+++ b/pkg/datasource/sql/exec/at/insert_executor.go
@@ -184,9 +184,17 @@ func (i *insertExecutor) buildAfterImageSQL(ctx context.Context) (string, []driv
 	}
 	// build check sql
 	sb := strings.Builder{}
-	sb.WriteString("SELECT * FROM " + tableName)
-	whereSQL := i.buildWhereConditionByPKs(pkColumnNameList, len(pkValuesMap[pkColumnNameList[0]]), "mysql", maxInSize)
-	sb.WriteString(" WHERE " + whereSQL + " ")
+	suffix := strings.Builder{}
+	var insertColumns []string
+
+	for _, column := range i.parserCtx.InsertStmt.Columns {
+		insertColumns = append(insertColumns, column.Name.O)
+	}
+	sb.WriteString("SELECT " + strings.Join(i.getNeedColumns(meta, insertColumns, types.DBTypeMySQL), ", "))
+	suffix.WriteString(" FROM " + tableName)
+	whereSQL := i.buildWhereConditionByPKs(pkColumnNameList, rowSize, "mysql", maxInSize)
+	suffix.WriteString(" WHERE " + whereSQL + " ")
+	sb.WriteString(suffix.String())
 	return sb.String(), i.buildPKParams(pkRowImages, pkColumnNameList), nil
 }
 
diff --git a/pkg/datasource/sql/tx.go b/pkg/datasource/sql/tx.go
index a6c5f70..db55e97 100644
--- a/pkg/datasource/sql/tx.go
+++ b/pkg/datasource/sql/tx.go
@@ -166,7 +166,7 @@ func (tx *Tx) register(ctx *types.TransactionContext) error {
 		if !ctx.HasUndoLog() || !ctx.HasLockKey() {
 			return nil
 		}
-		for k, _ := range ctx.LockKeys {
+		for k := range ctx.LockKeys {
 			lockKey += k + ";"
 		}
 		request.LockKeys = lockKey
diff --git a/pkg/datasource/sql/types/image.go b/pkg/datasource/sql/types/image.go
index f755d9c..0290b36 100644
--- a/pkg/datasource/sql/types/image.go
+++ b/pkg/datasource/sql/types/image.go
@@ -146,7 +146,7 @@ func (r *RowImage) GetColumnMap() map[string]*ColumnImage {
 // PrimaryKeys Primary keys list.
 func (r *RowImage) PrimaryKeys(cols []ColumnImage) []ColumnImage {
 	var pkFields []ColumnImage
-	for key, _ := range cols {
+	for key := range cols {
 		if cols[key].KeyType == PrimaryKey.Number() {
 			pkFields = append(pkFields, cols[key])
 		}
@@ -158,7 +158,7 @@ func (r *RowImage) PrimaryKeys(cols []ColumnImage) []ColumnImage {
 // NonPrimaryKeys get non-primary keys
 func (r *RowImage) NonPrimaryKeys(cols []ColumnImage) []ColumnImage {
 	var nonPkFields []ColumnImage
-	for key, _ := range cols {
+	for key := range cols {
 		if cols[key].KeyType != PrimaryKey.Number() {
 			nonPkFields = append(nonPkFields, cols[key])
 		}
diff --git a/pkg/datasource/sql/undo/base/undo.go b/pkg/datasource/sql/undo/base/undo.go
index 5861012..752597f 100644
--- a/pkg/datasource/sql/undo/base/undo.go
+++ b/pkg/datasource/sql/undo/base/undo.go
@@ -106,6 +106,8 @@ func (m *BaseUndoLogManager) InsertUndoLogWithSqlConn(ctx context.Context, recor
 	if err != nil {
 		return err
 	}
+	defer stmt.Close()
+
 	_, err = stmt.Exec(record.BranchID, record.XID, record.Context, record.RollbackInfo, int64(record.LogStatus))
 	if err != nil {
 		return err
@@ -120,7 +122,7 @@ func (m *BaseUndoLogManager) DeleteUndoLog(ctx context.Context, xid string, bran
 		log.Errorf("[DeleteUndoLog] prepare sql fail, err: %v", err)
 		return err
 	}
-
+	defer stmt.Close()
 	if _, err = stmt.Exec(branchID, xid); err != nil {
 		log.Errorf("[DeleteUndoLog] exec delete undo log fail, err: %v", err)
 		return err
@@ -146,6 +148,7 @@ func (m *BaseUndoLogManager) BatchDeleteUndoLog(xid []string, branchID []int64,
 		log.Errorf("prepare sql fail, err: %v", err)
 		return err
 	}
+	defer stmt.Close()
 
 	branchIDStr, err := Int64Slice2Str(branchID, ",")
 	if err != nil {
@@ -222,7 +225,7 @@ func (m *BaseUndoLogManager) FlushUndoLog(tranCtx *types.TransactionContext, con
 	}
 
 	parseContext := make(map[string]string, 0)
-	parseContext[serializerKey] = "json"
+	parseContext[serializerKey] = undo.UndoConfig.LogSerialization
 	parseContext[compressorTypeKey] = undo.UndoConfig.CompressConfig.Type
 	undoLogContent := m.encodeUndoLogCtx(parseContext)
 	rollbackInfo, err := m.serializeBranchUndoLog(&branchUndoLog, parseContext[serializerKey])
@@ -297,7 +300,10 @@ func (m *BaseUndoLogManager) Undo(ctx context.Context, dbType types.DBType, xid
 		}
 		undoLogRecords = append(undoLogRecords, record)
 	}
-
+	if err := rows.Err(); err != nil {
+		log.Errorf("read rows next fail, xid: %s, branchID:%s err:%v", xid, branchID, err)
+		return err
+	}
 	var exists bool
 	for _, record := range undoLogRecords {
 		exists = true
@@ -377,7 +383,7 @@ func (m *BaseUndoLogManager) Undo(ctx context.Context, dbType types.DBType, xid
 func (m *BaseUndoLogManager) insertUndoLogWithGlobalFinished(ctx context.Context, xid string, branchID uint64, conn *sql.Conn) error {
 	// todo use config to replace
 	parseContext := make(map[string]string, 0)
-	parseContext[serializerKey] = "json"
+	parseContext[serializerKey] = undo.UndoConfig.LogSerialization
 	parseContext[compressorTypeKey] = undo.UndoConfig.CompressConfig.Type
 	undoLogContent := m.encodeUndoLogCtx(parseContext)
 
@@ -410,7 +416,7 @@ func (m *BaseUndoLogManager) DBType() types.DBType {
 
 // HasUndoLogTable check undo log table if exist
 func (m *BaseUndoLogManager) HasUndoLogTable(ctx context.Context, conn *sql.Conn) (res bool, err error) {
-	if _, err = conn.QueryContext(ctx, getCheckUndoLogTableExistSql()); err != nil {
+	if _, err = conn.QueryContext(ctx, getCheckUndoLogTableExistSql()); err != nil { //nolint:rowserrcheck,sqlclosecheck
 		// 1146 mysql table not exist fault code
 		if e, ok := err.(*mysql.SQLError); ok && e.Code == mysql.ErrNoSuchTable {
 			return false, nil
diff --git a/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go b/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go
index a619c15..043e7eb 100644
--- a/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go
+++ b/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go
@@ -121,6 +121,10 @@ func (b *BasicUndoLogBuilder) traversalArgs(node ast.Node, argsIndex *[]int32) {
 			b.traversalArgs(exprs[i], argsIndex)
 		}
 		break
+	case *ast.ParenthesesExpr:
+		expr := node.(*ast.ParenthesesExpr)
+		b.traversalArgs(expr.Expr, argsIndex)
+		break
 	case *test_driver.ParamMarkerExpr:
 		*argsIndex = append(*argsIndex, int32(node.(*test_driver.ParamMarkerExpr).Order))
 		break
diff --git a/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder.go b/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder.go
index 4a23ded..6b82d53 100644
--- a/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder.go
+++ b/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder.go
@@ -128,7 +128,7 @@ func (u *MySQLInsertOnDuplicateUndoLogBuilder) buildBeforeImageSQL(insertStmt *a
 			columnIsNull := true
 			uniqueList := make([]string, 0)
 			for _, columnMeta := range index.Columns {
-				columnName := columnMeta.ColumnName
+				columnName := strings.ToLower(columnMeta.ColumnName)
 				imageParameters, ok := paramMap[columnName]
 				if !ok && columnMeta.ColumnDef != nil {
 					if strings.EqualFold("PRIMARY", index.Name) {
@@ -222,7 +222,7 @@ func (u *MySQLInsertOnDuplicateUndoLogBuilder) buildAfterImageSQL(ctx context.Co
 func checkDuplicateKeyUpdate(insert *ast.InsertStmt, metaData types.TableMeta) error {
 	duplicateColsMap := make(map[string]bool)
 	for _, v := range insert.OnDuplicate {
-		duplicateColsMap[v.Column.Name.L] = true
+		duplicateColsMap[strings.ToLower(v.Column.Name.L)] = true
 	}
 	if len(duplicateColsMap) == 0 {
 		return nil
@@ -254,7 +254,7 @@ func (u *MySQLInsertOnDuplicateUndoLogBuilder) buildImageParameters(insert *ast.
 			return nil, fmt.Errorf("insert row's column size not equal to insert column size")
 		}
 		for i, col := range insertColumns {
-			columnName := executor.DelEscape(col, types.DBTypeMySQL)
+			columnName := strings.ToLower(executor.DelEscape(col, types.DBTypeMySQL))
 			val := row[i]
 			rStr, ok := val.(string)
 			if ok && strings.EqualFold(rStr, SqlPlaceholder) {
@@ -279,14 +279,14 @@ func getInsertColumns(insertStmt *ast.InsertStmt) []string {
 	}
 	var list []string
 	for _, col := range colList {
-		list = append(list, col.Name.L)
+		list = append(list, strings.ToLower(col.Name.L))
 	}
 	return list
 }
 
 func isIndexValueNotNull(indexMeta types.IndexMeta, imageParameterMap map[string][]driver.Value, rowIndex int) bool {
 	for _, colMeta := range indexMeta.Columns {
-		columnName := colMeta.ColumnName
+		columnName := strings.ToLower(colMeta.ColumnName)
 		imageParameters := imageParameterMap[columnName]
 		if imageParameters == nil && colMeta.ColumnDef == nil {
 			return false
diff --git a/pkg/datasource/sql/undo/executor/executor.go b/pkg/datasource/sql/undo/executor/executor.go
index f4d9a8b..f5b573a 100644
--- a/pkg/datasource/sql/undo/executor/executor.go
+++ b/pkg/datasource/sql/undo/executor/executor.go
@@ -124,7 +124,7 @@ func (b *BaseExecutor) queryCurrentRecords(ctx context.Context, conn *sql.Conn)
 	if err != nil {
 		return nil, err
 	}
-
+	defer rows.Close()
 	image := types.RecordImage{
 		TableName: b.undoImage.TableName,
 		TableMeta: tableMeta,
@@ -159,7 +159,9 @@ func (b *BaseExecutor) queryCurrentRecords(ctx context.Context, conn *sql.Conn)
 		}
 		rowImages = append(rowImages, types.RowImage{Columns: columns})
 	}
-
+	if err := rows.Err(); err != nil {
+		return nil, err
+	}
 	image.Rows = rowImages
 	return &image, nil
 }
diff --git a/pkg/datasource/sql/undo/executor/mysql_undo_delete_executor.go b/pkg/datasource/sql/undo/executor/mysql_undo_delete_executor.go
index 7a392fc..02045c3 100644
--- a/pkg/datasource/sql/undo/executor/mysql_undo_delete_executor.go
+++ b/pkg/datasource/sql/undo/executor/mysql_undo_delete_executor.go
@@ -48,7 +48,7 @@ func (m *mySQLUndoDeleteExecutor) ExecuteOn(ctx context.Context, dbType types.DB
 	if err != nil {
 		return err
 	}
-
+	defer stmt.Close()
 	beforeImage := m.sqlUndoLog.BeforeImage
 
 	for _, row := range beforeImage.Rows {
@@ -97,7 +97,7 @@ func (m *mySQLUndoDeleteExecutor) buildUndoSQL(dbType types.DBType) (string, err
 		insertColumnSlice, insertValueSlice []string
 	)
 
-	for key, _ := range fields {
+	for key := range fields {
 		insertColumnSlice = append(insertColumnSlice, AddEscape(fields[key].ColumnName, dbType))
 		insertValueSlice = append(insertValueSlice, "?")
 	}
diff --git a/pkg/datasource/sql/undo/executor/mysql_undo_insert_executor.go b/pkg/datasource/sql/undo/executor/mysql_undo_insert_executor.go
index 108a62e..bd80804 100644
--- a/pkg/datasource/sql/undo/executor/mysql_undo_insert_executor.go
+++ b/pkg/datasource/sql/undo/executor/mysql_undo_insert_executor.go
@@ -50,7 +50,7 @@ func (m *mySQLUndoInsertExecutor) ExecuteOn(ctx context.Context, dbType types.DB
 	if err != nil {
 		return err
 	}
-
+	defer stmt.Close()
 	afterImage := m.sqlUndoLog.AfterImage
 	for _, row := range afterImage.Rows {
 		pkValueList := make([]interface{}, 0)
@@ -96,7 +96,7 @@ func (m *mySQLUndoInsertExecutor) generateDeleteSql(
 	}
 
 	var pkList []string
-	for key, _ := range colImages {
+	for key := range colImages {
 		pkList = append(pkList, colImages[key].ColumnName)
 	}
 
diff --git a/pkg/datasource/sql/undo/executor/mysql_undo_update_executor.go b/pkg/datasource/sql/undo/executor/mysql_undo_update_executor.go
index d3561c4..65e1321 100644
--- a/pkg/datasource/sql/undo/executor/mysql_undo_update_executor.go
+++ b/pkg/datasource/sql/undo/executor/mysql_undo_update_executor.go
@@ -54,6 +54,7 @@ func (m *mySQLUndoUpdateExecutor) ExecuteOn(ctx context.Context, dbType types.DB
 	if err != nil {
 		return err
 	}
+	defer stmt.Close()
 
 	beforeImage := m.sqlUndoLog.BeforeImage
 	for _, row := range beforeImage.Rows {
@@ -93,7 +94,7 @@ func (m *mySQLUndoUpdateExecutor) buildUndoSQL(dbType types.DBType) (string, err
 	)
 
 	nonPkFields := row.NonPrimaryKeys(row.Columns)
-	for key, _ := range nonPkFields {
+	for key := range nonPkFields {
 		updateColumnSlice = append(updateColumnSlice, AddEscape(nonPkFields[key].ColumnName, dbType)+" = ? ")
 	}
 
@@ -103,7 +104,7 @@ func (m *mySQLUndoUpdateExecutor) buildUndoSQL(dbType types.DBType) (string, err
 		return "", err
 	}
 
-	for key, _ := range pkList {
+	for key := range pkList {
 		pkNameList = append(pkNameList, pkList[key].ColumnName)
 	}
 
diff --git a/pkg/datasource/sql/undo/executor/sql.go b/pkg/datasource/sql/undo/executor/sql.go
index 104bace..5594a44 100644
--- a/pkg/datasource/sql/undo/executor/sql.go
+++ b/pkg/datasource/sql/undo/executor/sql.go
@@ -142,7 +142,7 @@ func addEscape(colName string, dbType types.DBType, escape string) string {
 	buf := make([]byte, len(colName)+2)
 	buf[0], buf[len(buf)-1] = escape[0], escape[0]
 
-	for key, _ := range colName {
+	for key := range colName {
 		buf[key+1] = colName[key]
 	}
 
diff --git a/pkg/datasource/sql/undo/parser/branch_undo_log.pb.go b/pkg/datasource/sql/undo/parser/branch_undo_log.pb.go
new file mode 100644
index 0000000..4bdce65
--- /dev/null
+++ b/pkg/datasource/sql/undo/parser/branch_undo_log.pb.go
@@ -0,0 +1,1445 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.34.2
+// 	protoc        v5.28.3
+// source: branch_undo_log.proto
+
+package parser
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	anypb "google.golang.org/protobuf/types/known/anypb"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type IndexType int32
+
+const (
+	IndexType_IndexTypeNull       IndexType = 0
+	IndexType_IndexTypePrimaryKey IndexType = 1
+)
+
+// Enum value maps for IndexType.
+var (
+	IndexType_name = map[int32]string{
+		0: "IndexTypeNull",
+		1: "IndexTypePrimaryKey",
+	}
+	IndexType_value = map[string]int32{
+		"IndexTypeNull":       0,
+		"IndexTypePrimaryKey": 1,
+	}
+)
+
+func (x IndexType) Enum() *IndexType {
+	p := new(IndexType)
+	*p = x
+	return p
+}
+
+func (x IndexType) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (IndexType) Descriptor() protoreflect.EnumDescriptor {
+	return file_branch_undo_log_proto_enumTypes[0].Descriptor()
+}
+
+func (IndexType) Type() protoreflect.EnumType {
+	return &file_branch_undo_log_proto_enumTypes[0]
+}
+
+func (x IndexType) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use IndexType.Descriptor instead.
+func (IndexType) EnumDescriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{0}
+}
+
+type JDBCType int32
+
+const (
+	JDBCType_JDBCTypeNull                  JDBCType = 0
+	JDBCType_JDBCTypeBit                   JDBCType = -7
+	JDBCType_JDBCTypeTinyInt               JDBCType = -6
+	JDBCType_JDBCTypeSmallInt              JDBCType = 5
+	JDBCType_JDBCTypeInteger               JDBCType = 4
+	JDBCType_JDBCTypeBigInt                JDBCType = -5
+	JDBCType_JDBCTypeFloat                 JDBCType = 6
+	JDBCType_JDBCTypeReal                  JDBCType = 7
+	JDBCType_JDBCTypeDouble                JDBCType = 8
+	JDBCType_JDBCTypeNumberic              JDBCType = 2
+	JDBCType_JDBCTypeDecimal               JDBCType = 3
+	JDBCType_JDBCTypeChar                  JDBCType = 1
+	JDBCType_JDBCTypeVarchar               JDBCType = 12
+	JDBCType_JDBCTypeLongVarchar           JDBCType = -1
+	JDBCType_JDBCTypeDate                  JDBCType = 91
+	JDBCType_JDBCTypeTime                  JDBCType = 92
+	JDBCType_JDBCTypeTimestamp             JDBCType = 93
+	JDBCType_JDBCTypeBinary                JDBCType = -2
+	JDBCType_JDBCTypeVarBinary             JDBCType = -3
+	JDBCType_JDBCTypeLongVarBinary         JDBCType = -4
+	JDBCType_JDBCTypeOther                 JDBCType = 1111
+	JDBCType_JDBCTypeJavaObject            JDBCType = 2000
+	JDBCType_JDBCTypeDistinct              JDBCType = 2001
+	JDBCType_JDBCTypeStruct                JDBCType = 2002
+	JDBCType_JDBCTypeArray                 JDBCType = 2003
+	JDBCType_JDBCTypeBlob                  JDBCType = 2004
+	JDBCType_JDBCTypeClob                  JDBCType = 2005
+	JDBCType_JDBCTypeRef                   JDBCType = 2006
+	JDBCType_JDBCTypeDateLink              JDBCType = 70
+	JDBCType_JDBCTypeBoolean               JDBCType = 16
+	JDBCType_JDBCTypeRowID                 JDBCType = -8
+	JDBCType_JDBCTypeNchar                 JDBCType = -15
+	JDBCType_JDBCTypeNvarchar              JDBCType = -9
+	JDBCType_JDBCTypeLongNvVarchar         JDBCType = -16
+	JDBCType_JDBCTypeNclob                 JDBCType = 2011
+	JDBCType_JDBCTypeSqlXML                JDBCType = 2009
+	JDBCType_JDBCTypeRefCursor             JDBCType = 2012
+	JDBCType_JDBCTypeTimeWithTimeZone      JDBCType = 2013
+	JDBCType_JDBCTypeTimestampWithTimezone JDBCType = 2014
+)
+
+// Enum value maps for JDBCType.
+var (
+	JDBCType_name = map[int32]string{
+		0:    "JDBCTypeNull",
+		-7:   "JDBCTypeBit",
+		-6:   "JDBCTypeTinyInt",
+		5:    "JDBCTypeSmallInt",
+		4:    "JDBCTypeInteger",
+		-5:   "JDBCTypeBigInt",
+		6:    "JDBCTypeFloat",
+		7:    "JDBCTypeReal",
+		8:    "JDBCTypeDouble",
+		2:    "JDBCTypeNumberic",
+		3:    "JDBCTypeDecimal",
+		1:    "JDBCTypeChar",
+		12:   "JDBCTypeVarchar",
+		-1:   "JDBCTypeLongVarchar",
+		91:   "JDBCTypeDate",
+		92:   "JDBCTypeTime",
+		93:   "JDBCTypeTimestamp",
+		-2:   "JDBCTypeBinary",
+		-3:   "JDBCTypeVarBinary",
+		-4:   "JDBCTypeLongVarBinary",
+		1111: "JDBCTypeOther",
+		2000: "JDBCTypeJavaObject",
+		2001: "JDBCTypeDistinct",
+		2002: "JDBCTypeStruct",
+		2003: "JDBCTypeArray",
+		2004: "JDBCTypeBlob",
+		2005: "JDBCTypeClob",
+		2006: "JDBCTypeRef",
+		70:   "JDBCTypeDateLink",
+		16:   "JDBCTypeBoolean",
+		-8:   "JDBCTypeRowID",
+		-15:  "JDBCTypeNchar",
+		-9:   "JDBCTypeNvarchar",
+		-16:  "JDBCTypeLongNvVarchar",
+		2011: "JDBCTypeNclob",
+		2009: "JDBCTypeSqlXML",
+		2012: "JDBCTypeRefCursor",
+		2013: "JDBCTypeTimeWithTimeZone",
+		2014: "JDBCTypeTimestampWithTimezone",
+	}
+	JDBCType_value = map[string]int32{
+		"JDBCTypeNull":                  0,
+		"JDBCTypeBit":                   -7,
+		"JDBCTypeTinyInt":               -6,
+		"JDBCTypeSmallInt":              5,
+		"JDBCTypeInteger":               4,
+		"JDBCTypeBigInt":                -5,
+		"JDBCTypeFloat":                 6,
+		"JDBCTypeReal":                  7,
+		"JDBCTypeDouble":                8,
+		"JDBCTypeNumberic":              2,
+		"JDBCTypeDecimal":               3,
+		"JDBCTypeChar":                  1,
+		"JDBCTypeVarchar":               12,
+		"JDBCTypeLongVarchar":           -1,
+		"JDBCTypeDate":                  91,
+		"JDBCTypeTime":                  92,
+		"JDBCTypeTimestamp":             93,
+		"JDBCTypeBinary":                -2,
+		"JDBCTypeVarBinary":             -3,
+		"JDBCTypeLongVarBinary":         -4,
+		"JDBCTypeOther":                 1111,
+		"JDBCTypeJavaObject":            2000,
+		"JDBCTypeDistinct":              2001,
+		"JDBCTypeStruct":                2002,
+		"JDBCTypeArray":                 2003,
+		"JDBCTypeBlob":                  2004,
+		"JDBCTypeClob":                  2005,
+		"JDBCTypeRef":                   2006,
+		"JDBCTypeDateLink":              70,
+		"JDBCTypeBoolean":               16,
+		"JDBCTypeRowID":                 -8,
+		"JDBCTypeNchar":                 -15,
+		"JDBCTypeNvarchar":              -9,
+		"JDBCTypeLongNvVarchar":         -16,
+		"JDBCTypeNclob":                 2011,
+		"JDBCTypeSqlXML":                2009,
+		"JDBCTypeRefCursor":             2012,
+		"JDBCTypeTimeWithTimeZone":      2013,
+		"JDBCTypeTimestampWithTimezone": 2014,
+	}
+)
+
+func (x JDBCType) Enum() *JDBCType {
+	p := new(JDBCType)
+	*p = x
+	return p
+}
+
+func (x JDBCType) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (JDBCType) Descriptor() protoreflect.EnumDescriptor {
+	return file_branch_undo_log_proto_enumTypes[1].Descriptor()
+}
+
+func (JDBCType) Type() protoreflect.EnumType {
+	return &file_branch_undo_log_proto_enumTypes[1]
+}
+
+func (x JDBCType) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use JDBCType.Descriptor instead.
+func (JDBCType) EnumDescriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{1}
+}
+
+type SQLType int32
+
+const (
+	SQLType_SQLTypeSelect                  SQLType = 0
+	SQLType_SQLTypeInsert                  SQLType = 1
+	SQLType_SQLTypeUpdate                  SQLType = 2
+	SQLType_SQLTypeDelete                  SQLType = 3
+	SQLType_SQLTypeSelectForUpdate         SQLType = 4
+	SQLType_SQLTypeReplace                 SQLType = 5
+	SQLType_SQLTypeTruncate                SQLType = 6
+	SQLType_SQLTypeCreate                  SQLType = 7
+	SQLType_SQLTypeDrop                    SQLType = 8
+	SQLType_SQLTypeLoad                    SQLType = 9
+	SQLType_SQLTypeMerge                   SQLType = 10
+	SQLType_SQLTypeShow                    SQLType = 11
+	SQLType_SQLTypeAlter                   SQLType = 12
+	SQLType_SQLTypeRename                  SQLType = 13
+	SQLType_SQLTypeDump                    SQLType = 14
+	SQLType_SQLTypeDebug                   SQLType = 15
+	SQLType_SQLTypeExplain                 SQLType = 16
+	SQLType_SQLTypeProcedure               SQLType = 17
+	SQLType_SQLTypeDesc                    SQLType = 18
+	SQLType_SQLLastInsertID                SQLType = 19
+	SQLType_SQLSelectWithoutTable          SQLType = 20
+	SQLType_SQLCreateSequence              SQLType = 21
+	SQLType_SQLShowSequence                SQLType = 22
+	SQLType_SQLGetSequence                 SQLType = 23
+	SQLType_SQLAlterSequence               SQLType = 24
+	SQLType_SQLDropSequence                SQLType = 25
+	SQLType_SQLTddlShow                    SQLType = 26
+	SQLType_SQLTypeSet                     SQLType = 27
+	SQLType_SQLTypeReload                  SQLType = 28
+	SQLType_SQLTypeSelectUnion             SQLType = 29
+	SQLType_SQLTypeCreateTable             SQLType = 30
+	SQLType_SQLTypeDropTable               SQLType = 31
+	SQLType_SQLTypeAlterTable              SQLType = 32
+	SQLType_SQLTypeSavePoint               SQLType = 33
+	SQLType_SQLTypeSelectFromUpdate        SQLType = 34
+	SQLType_SQLTypeMultiDelete             SQLType = 35
+	SQLType_SQLTypeMultiUpdate             SQLType = 36
+	SQLType_SQLTypeCreateIndex             SQLType = 37
+	SQLType_SQLTypeDropIndex               SQLType = 38
+	SQLType_SQLTypeKill                    SQLType = 39
+	SQLType_SQLTypeLockTables              SQLType = 40
+	SQLType_SQLTypeUnLockTables            SQLType = 41
+	SQLType_SQLTypeCheckTable              SQLType = 42
+	SQLType_SQLTypeSelectFoundRows         SQLType = 43
+	SQLType_SQLTypeInsertIgnore            SQLType = 101 // Adjusted the value to match Go's logic
+	SQLType_SQLTypeInsertOnDuplicateUpdate SQLType = 102
+	SQLType_SQLTypeMulti                   SQLType = 1044 // Adjusted the value to match Go's logic
+	SQLType_SQLTypeUnknown                 SQLType = 1045
+)
+
+// Enum value maps for SQLType.
+var (
+	SQLType_name = map[int32]string{
+		0:    "SQLTypeSelect",
+		1:    "SQLTypeInsert",
+		2:    "SQLTypeUpdate",
+		3:    "SQLTypeDelete",
+		4:    "SQLTypeSelectForUpdate",
+		5:    "SQLTypeReplace",
+		6:    "SQLTypeTruncate",
+		7:    "SQLTypeCreate",
+		8:    "SQLTypeDrop",
+		9:    "SQLTypeLoad",
+		10:   "SQLTypeMerge",
+		11:   "SQLTypeShow",
+		12:   "SQLTypeAlter",
+		13:   "SQLTypeRename",
+		14:   "SQLTypeDump",
+		15:   "SQLTypeDebug",
+		16:   "SQLTypeExplain",
+		17:   "SQLTypeProcedure",
+		18:   "SQLTypeDesc",
+		19:   "SQLLastInsertID",
+		20:   "SQLSelectWithoutTable",
+		21:   "SQLCreateSequence",
+		22:   "SQLShowSequence",
+		23:   "SQLGetSequence",
+		24:   "SQLAlterSequence",
+		25:   "SQLDropSequence",
+		26:   "SQLTddlShow",
+		27:   "SQLTypeSet",
+		28:   "SQLTypeReload",
+		29:   "SQLTypeSelectUnion",
+		30:   "SQLTypeCreateTable",
+		31:   "SQLTypeDropTable",
+		32:   "SQLTypeAlterTable",
+		33:   "SQLTypeSavePoint",
+		34:   "SQLTypeSelectFromUpdate",
+		35:   "SQLTypeMultiDelete",
+		36:   "SQLTypeMultiUpdate",
+		37:   "SQLTypeCreateIndex",
+		38:   "SQLTypeDropIndex",
+		39:   "SQLTypeKill",
+		40:   "SQLTypeLockTables",
+		41:   "SQLTypeUnLockTables",
+		42:   "SQLTypeCheckTable",
+		43:   "SQLTypeSelectFoundRows",
+		101:  "SQLTypeInsertIgnore",
+		102:  "SQLTypeInsertOnDuplicateUpdate",
+		1044: "SQLTypeMulti",
+		1045: "SQLTypeUnknown",
+	}
+	SQLType_value = map[string]int32{
+		"SQLTypeSelect":                  0,
+		"SQLTypeInsert":                  1,
+		"SQLTypeUpdate":                  2,
+		"SQLTypeDelete":                  3,
+		"SQLTypeSelectForUpdate":         4,
+		"SQLTypeReplace":                 5,
+		"SQLTypeTruncate":                6,
+		"SQLTypeCreate":                  7,
+		"SQLTypeDrop":                    8,
+		"SQLTypeLoad":                    9,
+		"SQLTypeMerge":                   10,
+		"SQLTypeShow":                    11,
+		"SQLTypeAlter":                   12,
+		"SQLTypeRename":                  13,
+		"SQLTypeDump":                    14,
+		"SQLTypeDebug":                   15,
+		"SQLTypeExplain":                 16,
+		"SQLTypeProcedure":               17,
+		"SQLTypeDesc":                    18,
+		"SQLLastInsertID":                19,
+		"SQLSelectWithoutTable":          20,
+		"SQLCreateSequence":              21,
+		"SQLShowSequence":                22,
+		"SQLGetSequence":                 23,
+		"SQLAlterSequence":               24,
+		"SQLDropSequence":                25,
+		"SQLTddlShow":                    26,
+		"SQLTypeSet":                     27,
+		"SQLTypeReload":                  28,
+		"SQLTypeSelectUnion":             29,
+		"SQLTypeCreateTable":             30,
+		"SQLTypeDropTable":               31,
+		"SQLTypeAlterTable":              32,
+		"SQLTypeSavePoint":               33,
+		"SQLTypeSelectFromUpdate":        34,
+		"SQLTypeMultiDelete":             35,
+		"SQLTypeMultiUpdate":             36,
+		"SQLTypeCreateIndex":             37,
+		"SQLTypeDropIndex":               38,
+		"SQLTypeKill":                    39,
+		"SQLTypeLockTables":              40,
+		"SQLTypeUnLockTables":            41,
+		"SQLTypeCheckTable":              42,
+		"SQLTypeSelectFoundRows":         43,
+		"SQLTypeInsertIgnore":            101,
+		"SQLTypeInsertOnDuplicateUpdate": 102,
+		"SQLTypeMulti":                   1044,
+		"SQLTypeUnknown":                 1045,
+	}
+)
+
+func (x SQLType) Enum() *SQLType {
+	p := new(SQLType)
+	*p = x
+	return p
+}
+
+func (x SQLType) String() string {
+	return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
+}
+
+func (SQLType) Descriptor() protoreflect.EnumDescriptor {
+	return file_branch_undo_log_proto_enumTypes[2].Descriptor()
+}
+
+func (SQLType) Type() protoreflect.EnumType {
+	return &file_branch_undo_log_proto_enumTypes[2]
+}
+
+func (x SQLType) Number() protoreflect.EnumNumber {
+	return protoreflect.EnumNumber(x)
+}
+
+// Deprecated: Use SQLType.Descriptor instead.
+func (SQLType) EnumDescriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{2}
+}
+
+type BranchUndoLog struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Xid      string        `protobuf:"bytes,1,opt,name=Xid,proto3" json:"Xid,omitempty"`
+	BranchID uint64        `protobuf:"varint,2,opt,name=BranchID,proto3" json:"BranchID,omitempty"`
+	Logs     []*SQLUndoLog `protobuf:"bytes,3,rep,name=Logs,proto3" json:"Logs,omitempty"`
+}
+
+func (x *BranchUndoLog) Reset() {
+	*x = BranchUndoLog{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *BranchUndoLog) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*BranchUndoLog) ProtoMessage() {}
+
+func (x *BranchUndoLog) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use BranchUndoLog.ProtoReflect.Descriptor instead.
+func (*BranchUndoLog) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *BranchUndoLog) GetXid() string {
+	if x != nil {
+		return x.Xid
+	}
+	return ""
+}
+
+func (x *BranchUndoLog) GetBranchID() uint64 {
+	if x != nil {
+		return x.BranchID
+	}
+	return 0
+}
+
+func (x *BranchUndoLog) GetLogs() []*SQLUndoLog {
+	if x != nil {
+		return x.Logs
+	}
+	return nil
+}
+
+type SQLUndoLog struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	SQLType     SQLType      `protobuf:"varint,1,opt,name=SQLType,proto3,enum=parser.SQLType" json:"SQLType,omitempty"`
+	TableName   string       `protobuf:"bytes,2,opt,name=TableName,proto3" json:"TableName,omitempty"`
+	BeforeImage *RecordImage `protobuf:"bytes,3,opt,name=BeforeImage,proto3" json:"BeforeImage,omitempty"`
+	AfterImage  *RecordImage `protobuf:"bytes,4,opt,name=AfterImage,proto3" json:"AfterImage,omitempty"`
+}
+
+func (x *SQLUndoLog) Reset() {
+	*x = SQLUndoLog{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *SQLUndoLog) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*SQLUndoLog) ProtoMessage() {}
+
+func (x *SQLUndoLog) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use SQLUndoLog.ProtoReflect.Descriptor instead.
+func (*SQLUndoLog) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *SQLUndoLog) GetSQLType() SQLType {
+	if x != nil {
+		return x.SQLType
+	}
+	return SQLType_SQLTypeSelect
+}
+
+func (x *SQLUndoLog) GetTableName() string {
+	if x != nil {
+		return x.TableName
+	}
+	return ""
+}
+
+func (x *SQLUndoLog) GetBeforeImage() *RecordImage {
+	if x != nil {
+		return x.BeforeImage
+	}
+	return nil
+}
+
+func (x *SQLUndoLog) GetAfterImage() *RecordImage {
+	if x != nil {
+		return x.AfterImage
+	}
+	return nil
+}
+
+type RecordImage struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Index     int32       `protobuf:"varint,1,opt,name=index,proto3" json:"index,omitempty"`
+	TableName string      `protobuf:"bytes,2,opt,name=TableName,proto3" json:"TableName,omitempty"`
+	SQLType   SQLType     `protobuf:"varint,3,opt,name=SQLType,proto3,enum=parser.SQLType" json:"SQLType,omitempty"`
+	Rows      []*RowImage `protobuf:"bytes,4,rep,name=Rows,proto3" json:"Rows,omitempty"`
+	TableMeta *TableMeta  `protobuf:"bytes,5,opt,name=TableMeta,proto3" json:"TableMeta,omitempty"`
+}
+
+func (x *RecordImage) Reset() {
+	*x = RecordImage{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[2]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *RecordImage) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RecordImage) ProtoMessage() {}
+
+func (x *RecordImage) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[2]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use RecordImage.ProtoReflect.Descriptor instead.
+func (*RecordImage) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{2}
+}
+
+func (x *RecordImage) GetIndex() int32 {
+	if x != nil {
+		return x.Index
+	}
+	return 0
+}
+
+func (x *RecordImage) GetTableName() string {
+	if x != nil {
+		return x.TableName
+	}
+	return ""
+}
+
+func (x *RecordImage) GetSQLType() SQLType {
+	if x != nil {
+		return x.SQLType
+	}
+	return SQLType_SQLTypeSelect
+}
+
+func (x *RecordImage) GetRows() []*RowImage {
+	if x != nil {
+		return x.Rows
+	}
+	return nil
+}
+
+func (x *RecordImage) GetTableMeta() *TableMeta {
+	if x != nil {
+		return x.TableMeta
+	}
+	return nil
+}
+
+type RowImage struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Columns []*ColumnImage `protobuf:"bytes,1,rep,name=Columns,proto3" json:"Columns,omitempty"`
+}
+
+func (x *RowImage) Reset() {
+	*x = RowImage{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *RowImage) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*RowImage) ProtoMessage() {}
+
+func (x *RowImage) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use RowImage.ProtoReflect.Descriptor instead.
+func (*RowImage) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *RowImage) GetColumns() []*ColumnImage {
+	if x != nil {
+		return x.Columns
+	}
+	return nil
+}
+
+type ColumnImage struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	KeyType    IndexType  `protobuf:"varint,1,opt,name=KeyType,proto3,enum=parser.IndexType" json:"KeyType,omitempty"`
+	ColumnName string     `protobuf:"bytes,2,opt,name=ColumnName,proto3" json:"ColumnName,omitempty"`
+	ColumnType JDBCType   `protobuf:"varint,3,opt,name=ColumnType,proto3,enum=parser.JDBCType" json:"ColumnType,omitempty"`
+	Value      *anypb.Any `protobuf:"bytes,4,opt,name=Value,proto3" json:"Value,omitempty"`
+}
+
+func (x *ColumnImage) Reset() {
+	*x = ColumnImage{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[4]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ColumnImage) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ColumnImage) ProtoMessage() {}
+
+func (x *ColumnImage) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[4]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ColumnImage.ProtoReflect.Descriptor instead.
+func (*ColumnImage) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *ColumnImage) GetKeyType() IndexType {
+	if x != nil {
+		return x.KeyType
+	}
+	return IndexType_IndexTypeNull
+}
+
+func (x *ColumnImage) GetColumnName() string {
+	if x != nil {
+		return x.ColumnName
+	}
+	return ""
+}
+
+func (x *ColumnImage) GetColumnType() JDBCType {
+	if x != nil {
+		return x.ColumnType
+	}
+	return JDBCType_JDBCTypeNull
+}
+
+func (x *ColumnImage) GetValue() *anypb.Any {
+	if x != nil {
+		return x.Value
+	}
+	return nil
+}
+
+type TableMeta struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	TableName   string                 `protobuf:"bytes,1,opt,name=TableName,proto3" json:"TableName,omitempty"`
+	Columns     map[string]*ColumnMeta `protobuf:"bytes,2,rep,name=Columns,proto3" json:"Columns,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	Indexs      map[string]*IndexMeta  `protobuf:"bytes,3,rep,name=Indexs,proto3" json:"Indexs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+	ColumnNames []string               `protobuf:"bytes,4,rep,name=ColumnNames,proto3" json:"ColumnNames,omitempty"`
+}
+
+func (x *TableMeta) Reset() {
+	*x = TableMeta{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[5]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *TableMeta) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TableMeta) ProtoMessage() {}
+
+func (x *TableMeta) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[5]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use TableMeta.ProtoReflect.Descriptor instead.
+func (*TableMeta) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *TableMeta) GetTableName() string {
+	if x != nil {
+		return x.TableName
+	}
+	return ""
+}
+
+func (x *TableMeta) GetColumns() map[string]*ColumnMeta {
+	if x != nil {
+		return x.Columns
+	}
+	return nil
+}
+
+func (x *TableMeta) GetIndexs() map[string]*IndexMeta {
+	if x != nil {
+		return x.Indexs
+	}
+	return nil
+}
+
+func (x *TableMeta) GetColumnNames() []string {
+	if x != nil {
+		return x.ColumnNames
+	}
+	return nil
+}
+
+type ColumnMeta struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Schema             string `protobuf:"bytes,1,opt,name=Schema,proto3" json:"Schema,omitempty"`
+	Table              string `protobuf:"bytes,2,opt,name=Table,proto3" json:"Table,omitempty"`
+	ColumnDef          []byte `protobuf:"bytes,3,opt,name=ColumnDef,proto3" json:"ColumnDef,omitempty"`
+	Autoincrement      bool   `protobuf:"varint,4,opt,name=Autoincrement,proto3" json:"Autoincrement,omitempty"`
+	ColumnName         string `protobuf:"bytes,5,opt,name=ColumnName,proto3" json:"ColumnName,omitempty"`
+	ColumnType         string `protobuf:"bytes,6,opt,name=ColumnType,proto3" json:"ColumnType,omitempty"`
+	DatabaseType       int32  `protobuf:"varint,7,opt,name=DatabaseType,proto3" json:"DatabaseType,omitempty"`
+	DatabaseTypeString string `protobuf:"bytes,8,opt,name=DatabaseTypeString,proto3" json:"DatabaseTypeString,omitempty"`
+	ColumnKey          string `protobuf:"bytes,9,opt,name=ColumnKey,proto3" json:"ColumnKey,omitempty"`
+	IsNullable         int32  `protobuf:"varint,10,opt,name=IsNullable,proto3" json:"IsNullable,omitempty"`
+	Extra              string `protobuf:"bytes,11,opt,name=Extra,proto3" json:"Extra,omitempty"`
+}
+
+func (x *ColumnMeta) Reset() {
+	*x = ColumnMeta{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[6]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *ColumnMeta) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*ColumnMeta) ProtoMessage() {}
+
+func (x *ColumnMeta) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[6]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use ColumnMeta.ProtoReflect.Descriptor instead.
+func (*ColumnMeta) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *ColumnMeta) GetSchema() string {
+	if x != nil {
+		return x.Schema
+	}
+	return ""
+}
+
+func (x *ColumnMeta) GetTable() string {
+	if x != nil {
+		return x.Table
+	}
+	return ""
+}
+
+func (x *ColumnMeta) GetColumnDef() []byte {
+	if x != nil {
+		return x.ColumnDef
+	}
+	return nil
+}
+
+func (x *ColumnMeta) GetAutoincrement() bool {
+	if x != nil {
+		return x.Autoincrement
+	}
+	return false
+}
+
+func (x *ColumnMeta) GetColumnName() string {
+	if x != nil {
+		return x.ColumnName
+	}
+	return ""
+}
+
+func (x *ColumnMeta) GetColumnType() string {
+	if x != nil {
+		return x.ColumnType
+	}
+	return ""
+}
+
+func (x *ColumnMeta) GetDatabaseType() int32 {
+	if x != nil {
+		return x.DatabaseType
+	}
+	return 0
+}
+
+func (x *ColumnMeta) GetDatabaseTypeString() string {
+	if x != nil {
+		return x.DatabaseTypeString
+	}
+	return ""
+}
+
+func (x *ColumnMeta) GetColumnKey() string {
+	if x != nil {
+		return x.ColumnKey
+	}
+	return ""
+}
+
+func (x *ColumnMeta) GetIsNullable() int32 {
+	if x != nil {
+		return x.IsNullable
+	}
+	return 0
+}
+
+func (x *ColumnMeta) GetExtra() string {
+	if x != nil {
+		return x.Extra
+	}
+	return ""
+}
+
+type IndexMeta struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Schema     string        `protobuf:"bytes,1,opt,name=Schema,proto3" json:"Schema,omitempty"`
+	Table      string        `protobuf:"bytes,2,opt,name=Table,proto3" json:"Table,omitempty"`
+	Name       string        `protobuf:"bytes,3,opt,name=Name,proto3" json:"Name,omitempty"`
+	ColumnName string        `protobuf:"bytes,4,opt,name=ColumnName,proto3" json:"ColumnName,omitempty"`
+	IType      IndexType     `protobuf:"varint,5,opt,name=IType,proto3,enum=parser.IndexType" json:"IType,omitempty"`
+	Columns    []*ColumnMeta `protobuf:"bytes,6,rep,name=Columns,proto3" json:"Columns,omitempty"`
+}
+
+func (x *IndexMeta) Reset() {
+	*x = IndexMeta{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_branch_undo_log_proto_msgTypes[7]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *IndexMeta) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*IndexMeta) ProtoMessage() {}
+
+func (x *IndexMeta) ProtoReflect() protoreflect.Message {
+	mi := &file_branch_undo_log_proto_msgTypes[7]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use IndexMeta.ProtoReflect.Descriptor instead.
+func (*IndexMeta) Descriptor() ([]byte, []int) {
+	return file_branch_undo_log_proto_rawDescGZIP(), []int{7}
+}
+
+func (x *IndexMeta) GetSchema() string {
+	if x != nil {
+		return x.Schema
+	}
+	return ""
+}
+
+func (x *IndexMeta) GetTable() string {
+	if x != nil {
+		return x.Table
+	}
+	return ""
+}
+
+func (x *IndexMeta) GetName() string {
+	if x != nil {
+		return x.Name
+	}
+	return ""
+}
+
+func (x *IndexMeta) GetColumnName() string {
+	if x != nil {
+		return x.ColumnName
+	}
+	return ""
+}
+
+func (x *IndexMeta) GetIType() IndexType {
+	if x != nil {
+		return x.IType
+	}
+	return IndexType_IndexTypeNull
+}
+
+func (x *IndexMeta) GetColumns() []*ColumnMeta {
+	if x != nil {
+		return x.Columns
+	}
+	return nil
+}
+
+var File_branch_undo_log_proto protoreflect.FileDescriptor
+
+var file_branch_undo_log_proto_rawDesc = []byte{
+	0x0a, 0x15, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x5f, 0x75, 0x6e, 0x64, 0x6f, 0x5f, 0x6c, 0x6f,
+	0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x1a,
+	0x19, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
+	0x2f, 0x61, 0x6e, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x65, 0x0a, 0x0d, 0x42, 0x72,
+	0x61, 0x6e, 0x63, 0x68, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x6f, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x58,
+	0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x58, 0x69, 0x64, 0x12, 0x1a, 0x0a,
+	0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52,
+	0x08, 0x42, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x49, 0x44, 0x12, 0x26, 0x0a, 0x04, 0x4c, 0x6f, 0x67,
+	0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72,
+	0x2e, 0x53, 0x51, 0x4c, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x6f, 0x67, 0x52, 0x04, 0x4c, 0x6f, 0x67,
+	0x73, 0x22, 0xc1, 0x01, 0x0a, 0x0a, 0x53, 0x51, 0x4c, 0x55, 0x6e, 0x64, 0x6f, 0x4c, 0x6f, 0x67,
+	0x12, 0x29, 0x0a, 0x07, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
+	0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x53, 0x51, 0x4c, 0x54, 0x79,
+	0x70, 0x65, 0x52, 0x07, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x54,
+	0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x54, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x0b, 0x42, 0x65, 0x66,
+	0x6f, 0x72, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13,
+	0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x49, 0x6d,
+	0x61, 0x67, 0x65, 0x52, 0x0b, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x49, 0x6d, 0x61, 0x67, 0x65,
+	0x12, 0x33, 0x0a, 0x0a, 0x41, 0x66, 0x74, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x52, 0x65,
+	0x63, 0x6f, 0x72, 0x64, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x0a, 0x41, 0x66, 0x74, 0x65, 0x72,
+	0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0xc3, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64,
+	0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01,
+	0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1c, 0x0a, 0x09, 0x54,
+	0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
+	0x54, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x53, 0x51, 0x4c,
+	0x54, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x70, 0x61, 0x72,
+	0x73, 0x65, 0x72, 0x2e, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x53, 0x51, 0x4c,
+	0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x52, 0x6f, 0x77, 0x73, 0x18, 0x04, 0x20, 0x03,
+	0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x52, 0x6f, 0x77, 0x49,
+	0x6d, 0x61, 0x67, 0x65, 0x52, 0x04, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x2f, 0x0a, 0x09, 0x54, 0x61,
+	0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e,
+	0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61,
+	0x52, 0x09, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0x39, 0x0a, 0x08, 0x52,
+	0x6f, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2d, 0x0a, 0x07, 0x43, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65,
+	0x72, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x07, 0x43,
+	0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x22, 0xb8, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x07, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70,
+	0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72,
+	0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 0x07, 0x4b, 0x65, 0x79, 0x54,
+	0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d,
+	0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e,
+	0x61, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x79, 0x70,
+	0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72,
+	0x2e, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x2a, 0x0a, 0x05, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
+	0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x05, 0x56, 0x61, 0x6c, 0x75,
+	0x65, 0x22, 0xda, 0x02, 0x0a, 0x09, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12,
+	0x1c, 0x0a, 0x09, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x09, 0x52, 0x09, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a,
+	0x07, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e,
+	0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74,
+	0x61, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07,
+	0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x06, 0x49, 0x6e, 0x64, 0x65, 0x78,
+	0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72,
+	0x2e, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78,
+	0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x73, 0x12, 0x20,
+	0x0a, 0x0b, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20,
+	0x03, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73,
+	0x1a, 0x4e, 0x0a, 0x0c, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
+	0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b,
+	0x65, 0x79, 0x12, 0x28, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x0b, 0x32, 0x12, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01,
+	0x1a, 0x4c, 0x0a, 0x0b, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
+	0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
+	0x79, 0x12, 0x27, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
+	0x32, 0x11, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x4d,
+	0x65, 0x74, 0x61, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xe6,
+	0x02, 0x0a, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x16, 0x0a,
+	0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53,
+	0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02,
+	0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x43,
+	0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x44, 0x65, 0x66, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09,
+	0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x44, 0x65, 0x66, 0x12, 0x24, 0x0a, 0x0d, 0x41, 0x75, 0x74,
+	0x6f, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
+	0x52, 0x0d, 0x41, 0x75, 0x74, 0x6f, 0x69, 0x6e, 0x63, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12,
+	0x1e, 0x0a, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12,
+	0x1e, 0x0a, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12,
+	0x22, 0x0a, 0x0c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x54,
+	0x79, 0x70, 0x65, 0x12, 0x2e, 0x0a, 0x12, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x54,
+	0x79, 0x70, 0x65, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52,
+	0x12, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x53, 0x74, 0x72,
+	0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4b, 0x65, 0x79,
+	0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x4b, 0x65,
+	0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x49, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18,
+	0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x49, 0x73, 0x4e, 0x75, 0x6c, 0x6c, 0x61, 0x62, 0x6c,
+	0x65, 0x12, 0x14, 0x0a, 0x05, 0x45, 0x78, 0x74, 0x72, 0x61, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09,
+	0x52, 0x05, 0x45, 0x78, 0x74, 0x72, 0x61, 0x22, 0xc4, 0x01, 0x0a, 0x09, 0x49, 0x6e, 0x64, 0x65,
+	0x78, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18,
+	0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x14, 0x0a,
+	0x05, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x61,
+	0x62, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
+	0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x43, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x43, 0x6f, 0x6c,
+	0x75, 0x6d, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x05, 0x49, 0x54, 0x79, 0x70, 0x65,
+	0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x11, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e,
+	0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x52, 0x05, 0x49, 0x54, 0x79, 0x70, 0x65,
+	0x12, 0x2c, 0x0a, 0x07, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
+	0x0b, 0x32, 0x12, 0x2e, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d,
+	0x6e, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x07, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x73, 0x2a, 0x37,
+	0x0a, 0x09, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x49,
+	0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x17,
+	0x0a, 0x13, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x54, 0x79, 0x70, 0x65, 0x50, 0x72, 0x69, 0x6d, 0x61,
+	0x72, 0x79, 0x4b, 0x65, 0x79, 0x10, 0x01, 0x2a, 0xb4, 0x07, 0x0a, 0x08, 0x4a, 0x44, 0x42, 0x43,
+	0x54, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65,
+	0x4e, 0x75, 0x6c, 0x6c, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x0b, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79,
+	0x70, 0x65, 0x42, 0x69, 0x74, 0x10, 0xf9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+	0x12, 0x1c, 0x0a, 0x0f, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x54, 0x69, 0x6e, 0x79,
+	0x49, 0x6e, 0x74, 0x10, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x14,
+	0x0a, 0x10, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x53, 0x6d, 0x61, 0x6c, 0x6c, 0x49,
+	0x6e, 0x74, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65,
+	0x49, 0x6e, 0x74, 0x65, 0x67, 0x65, 0x72, 0x10, 0x04, 0x12, 0x1b, 0x0a, 0x0e, 0x4a, 0x44, 0x42,
+	0x43, 0x54, 0x79, 0x70, 0x65, 0x42, 0x69, 0x67, 0x49, 0x6e, 0x74, 0x10, 0xfb, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79,
+	0x70, 0x65, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x44, 0x42,
+	0x43, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x61, 0x6c, 0x10, 0x07, 0x12, 0x12, 0x0a, 0x0e, 0x4a,
+	0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x10, 0x08, 0x12,
+	0x14, 0x0a, 0x10, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65,
+	0x72, 0x69, 0x63, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70,
+	0x65, 0x44, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x6c, 0x10, 0x03, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x44,
+	0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x43, 0x68, 0x61, 0x72, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f,
+	0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x56, 0x61, 0x72, 0x63, 0x68, 0x61, 0x72, 0x10,
+	0x0c, 0x12, 0x20, 0x0a, 0x13, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x4c, 0x6f, 0x6e,
+	0x67, 0x56, 0x61, 0x72, 0x63, 0x68, 0x61, 0x72, 0x10, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x44,
+	0x61, 0x74, 0x65, 0x10, 0x5b, 0x12, 0x10, 0x0a, 0x0c, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70,
+	0x65, 0x54, 0x69, 0x6d, 0x65, 0x10, 0x5c, 0x12, 0x15, 0x0a, 0x11, 0x4a, 0x44, 0x42, 0x43, 0x54,
+	0x79, 0x70, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x10, 0x5d, 0x12, 0x1b,
+	0x0a, 0x0e, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79,
+	0x10, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x1e, 0x0a, 0x11, 0x4a,
+	0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x56, 0x61, 0x72, 0x42, 0x69, 0x6e, 0x61, 0x72, 0x79,
+	0x10, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x22, 0x0a, 0x15, 0x4a,
+	0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x4c, 0x6f, 0x6e, 0x67, 0x56, 0x61, 0x72, 0x42, 0x69,
+	0x6e, 0x61, 0x72, 0x79, 0x10, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12,
+	0x12, 0x0a, 0x0d, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x4f, 0x74, 0x68, 0x65, 0x72,
+	0x10, 0xd7, 0x08, 0x12, 0x17, 0x0a, 0x12, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x4a,
+	0x61, 0x76, 0x61, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x10, 0xd0, 0x0f, 0x12, 0x15, 0x0a, 0x10,
+	0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x44, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x63, 0x74,
+	0x10, 0xd1, 0x0f, 0x12, 0x13, 0x0a, 0x0e, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x53,
+	0x74, 0x72, 0x75, 0x63, 0x74, 0x10, 0xd2, 0x0f, 0x12, 0x12, 0x0a, 0x0d, 0x4a, 0x44, 0x42, 0x43,
+	0x54, 0x79, 0x70, 0x65, 0x41, 0x72, 0x72, 0x61, 0x79, 0x10, 0xd3, 0x0f, 0x12, 0x11, 0x0a, 0x0c,
+	0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x42, 0x6c, 0x6f, 0x62, 0x10, 0xd4, 0x0f, 0x12,
+	0x11, 0x0a, 0x0c, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x43, 0x6c, 0x6f, 0x62, 0x10,
+	0xd5, 0x0f, 0x12, 0x10, 0x0a, 0x0b, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65,
+	0x66, 0x10, 0xd6, 0x0f, 0x12, 0x14, 0x0a, 0x10, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65,
+	0x44, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x10, 0x46, 0x12, 0x13, 0x0a, 0x0f, 0x4a, 0x44,
+	0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x42, 0x6f, 0x6f, 0x6c, 0x65, 0x61, 0x6e, 0x10, 0x10, 0x12,
+	0x1a, 0x0a, 0x0d, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x52, 0x6f, 0x77, 0x49, 0x44,
+	0x10, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x1a, 0x0a, 0x0d, 0x4a,
+	0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x63, 0x68, 0x61, 0x72, 0x10, 0xf1, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x1d, 0x0a, 0x10, 0x4a, 0x44, 0x42, 0x43, 0x54,
+	0x79, 0x70, 0x65, 0x4e, 0x76, 0x61, 0x72, 0x63, 0x68, 0x61, 0x72, 0x10, 0xf7, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x22, 0x0a, 0x15, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79,
+	0x70, 0x65, 0x4c, 0x6f, 0x6e, 0x67, 0x4e, 0x76, 0x56, 0x61, 0x72, 0x63, 0x68, 0x61, 0x72, 0x10,
+	0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x12, 0x12, 0x0a, 0x0d, 0x4a, 0x44,
+	0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x4e, 0x63, 0x6c, 0x6f, 0x62, 0x10, 0xdb, 0x0f, 0x12, 0x13,
+	0x0a, 0x0e, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x53, 0x71, 0x6c, 0x58, 0x4d, 0x4c,
+	0x10, 0xd9, 0x0f, 0x12, 0x16, 0x0a, 0x11, 0x4a, 0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x52,
+	0x65, 0x66, 0x43, 0x75, 0x72, 0x73, 0x6f, 0x72, 0x10, 0xdc, 0x0f, 0x12, 0x1d, 0x0a, 0x18, 0x4a,
+	0x44, 0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x57, 0x69, 0x74, 0x68, 0x54,
+	0x69, 0x6d, 0x65, 0x5a, 0x6f, 0x6e, 0x65, 0x10, 0xdd, 0x0f, 0x12, 0x22, 0x0a, 0x1d, 0x4a, 0x44,
+	0x42, 0x43, 0x54, 0x79, 0x70, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x57,
+	0x69, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x10, 0xde, 0x0f, 0x2a, 0x8b,
+	0x08, 0x0a, 0x07, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x51,
+	0x4c, 0x54, 0x79, 0x70, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x10, 0x00, 0x12, 0x11, 0x0a,
+	0x0d, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x10, 0x01,
+	0x12, 0x11, 0x0a, 0x0d, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x55, 0x70, 0x64, 0x61, 0x74,
+	0x65, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x44, 0x65,
+	0x6c, 0x65, 0x74, 0x65, 0x10, 0x03, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70,
+	0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x46, 0x6f, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
+	0x10, 0x04, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x70,
+	0x6c, 0x61, 0x63, 0x65, 0x10, 0x05, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70,
+	0x65, 0x54, 0x72, 0x75, 0x6e, 0x63, 0x61, 0x74, 0x65, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x53,
+	0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x10, 0x07, 0x12, 0x0f,
+	0x0a, 0x0b, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x10, 0x08, 0x12,
+	0x0f, 0x0a, 0x0b, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x4c, 0x6f, 0x61, 0x64, 0x10, 0x09,
+	0x12, 0x10, 0x0a, 0x0c, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x4d, 0x65, 0x72, 0x67, 0x65,
+	0x10, 0x0a, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x53, 0x68, 0x6f,
+	0x77, 0x10, 0x0b, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6c,
+	0x74, 0x65, 0x72, 0x10, 0x0c, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65,
+	0x52, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x10, 0x0d, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x51, 0x4c, 0x54,
+	0x79, 0x70, 0x65, 0x44, 0x75, 0x6d, 0x70, 0x10, 0x0e, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x51, 0x4c,
+	0x54, 0x79, 0x70, 0x65, 0x44, 0x65, 0x62, 0x75, 0x67, 0x10, 0x0f, 0x12, 0x12, 0x0a, 0x0e, 0x53,
+	0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x45, 0x78, 0x70, 0x6c, 0x61, 0x69, 0x6e, 0x10, 0x10, 0x12,
+	0x14, 0x0a, 0x10, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x64,
+	0x75, 0x72, 0x65, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65,
+	0x44, 0x65, 0x73, 0x63, 0x10, 0x12, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x51, 0x4c, 0x4c, 0x61, 0x73,
+	0x74, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x49, 0x44, 0x10, 0x13, 0x12, 0x19, 0x0a, 0x15, 0x53,
+	0x51, 0x4c, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x57, 0x69, 0x74, 0x68, 0x6f, 0x75, 0x74, 0x54,
+	0x61, 0x62, 0x6c, 0x65, 0x10, 0x14, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x51, 0x4c, 0x43, 0x72, 0x65,
+	0x61, 0x74, 0x65, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x10, 0x15, 0x12, 0x13, 0x0a,
+	0x0f, 0x53, 0x51, 0x4c, 0x53, 0x68, 0x6f, 0x77, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65,
+	0x10, 0x16, 0x12, 0x12, 0x0a, 0x0e, 0x53, 0x51, 0x4c, 0x47, 0x65, 0x74, 0x53, 0x65, 0x71, 0x75,
+	0x65, 0x6e, 0x63, 0x65, 0x10, 0x17, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x51, 0x4c, 0x41, 0x6c, 0x74,
+	0x65, 0x72, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x10, 0x18, 0x12, 0x13, 0x0a, 0x0f,
+	0x53, 0x51, 0x4c, 0x44, 0x72, 0x6f, 0x70, 0x53, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x63, 0x65, 0x10,
+	0x19, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x51, 0x4c, 0x54, 0x64, 0x64, 0x6c, 0x53, 0x68, 0x6f, 0x77,
+	0x10, 0x1a, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x53, 0x65, 0x74,
+	0x10, 0x1b, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x52, 0x65, 0x6c,
+	0x6f, 0x61, 0x64, 0x10, 0x1c, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65,
+	0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x55, 0x6e, 0x69, 0x6f, 0x6e, 0x10, 0x1d, 0x12, 0x16, 0x0a,
+	0x12, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x61,
+	0x62, 0x6c, 0x65, 0x10, 0x1e, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65,
+	0x44, 0x72, 0x6f, 0x70, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x1f, 0x12, 0x15, 0x0a, 0x11, 0x53,
+	0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x54, 0x61, 0x62, 0x6c, 0x65,
+	0x10, 0x20, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x53, 0x61, 0x76,
+	0x65, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x10, 0x21, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x51, 0x4c, 0x54,
+	0x79, 0x70, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x46, 0x72, 0x6f, 0x6d, 0x55, 0x70, 0x64,
+	0x61, 0x74, 0x65, 0x10, 0x22, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65,
+	0x4d, 0x75, 0x6c, 0x74, 0x69, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x10, 0x23, 0x12, 0x16, 0x0a,
+	0x12, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x55, 0x70, 0x64,
+	0x61, 0x74, 0x65, 0x10, 0x24, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65,
+	0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x10, 0x25, 0x12, 0x14, 0x0a,
+	0x10, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x44, 0x72, 0x6f, 0x70, 0x49, 0x6e, 0x64, 0x65,
+	0x78, 0x10, 0x26, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x4b, 0x69,
+	0x6c, 0x6c, 0x10, 0x27, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x4c,
+	0x6f, 0x63, 0x6b, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x10, 0x28, 0x12, 0x17, 0x0a, 0x13, 0x53,
+	0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x55, 0x6e, 0x4c, 0x6f, 0x63, 0x6b, 0x54, 0x61, 0x62, 0x6c,
+	0x65, 0x73, 0x10, 0x29, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x43,
+	0x68, 0x65, 0x63, 0x6b, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x10, 0x2a, 0x12, 0x1a, 0x0a, 0x16, 0x53,
+	0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x46, 0x6f, 0x75, 0x6e,
+	0x64, 0x52, 0x6f, 0x77, 0x73, 0x10, 0x2b, 0x12, 0x17, 0x0a, 0x13, 0x53, 0x51, 0x4c, 0x54, 0x79,
+	0x70, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x49, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x10, 0x65,
+	0x12, 0x22, 0x0a, 0x1e, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x73, 0x65, 0x72,
+	0x74, 0x4f, 0x6e, 0x44, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x55, 0x70, 0x64, 0x61,
+	0x74, 0x65, 0x10, 0x66, 0x12, 0x11, 0x0a, 0x0c, 0x53, 0x51, 0x4c, 0x54, 0x79, 0x70, 0x65, 0x4d,
+	0x75, 0x6c, 0x74, 0x69, 0x10, 0x94, 0x08, 0x12, 0x13, 0x0a, 0x0e, 0x53, 0x51, 0x4c, 0x54, 0x79,
+	0x70, 0x65, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x95, 0x08, 0x42, 0x0a, 0x5a, 0x08,
+	0x2e, 0x3b, 0x70, 0x61, 0x72, 0x73, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_branch_undo_log_proto_rawDescOnce sync.Once
+	file_branch_undo_log_proto_rawDescData = file_branch_undo_log_proto_rawDesc
+)
+
+func file_branch_undo_log_proto_rawDescGZIP() []byte {
+	file_branch_undo_log_proto_rawDescOnce.Do(func() {
+		file_branch_undo_log_proto_rawDescData = protoimpl.X.CompressGZIP(file_branch_undo_log_proto_rawDescData)
+	})
+	return file_branch_undo_log_proto_rawDescData
+}
+
+var file_branch_undo_log_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
+var file_branch_undo_log_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
+var file_branch_undo_log_proto_goTypes = []any{
+	(IndexType)(0),        // 0: parser.IndexType
+	(JDBCType)(0),         // 1: parser.JDBCType
+	(SQLType)(0),          // 2: parser.SQLType
+	(*BranchUndoLog)(nil), // 3: parser.BranchUndoLog
+	(*SQLUndoLog)(nil),    // 4: parser.SQLUndoLog
+	(*RecordImage)(nil),   // 5: parser.RecordImage
+	(*RowImage)(nil),      // 6: parser.RowImage
+	(*ColumnImage)(nil),   // 7: parser.ColumnImage
+	(*TableMeta)(nil),     // 8: parser.TableMeta
+	(*ColumnMeta)(nil),    // 9: parser.ColumnMeta
+	(*IndexMeta)(nil),     // 10: parser.IndexMeta
+	nil,                   // 11: parser.TableMeta.ColumnsEntry
+	nil,                   // 12: parser.TableMeta.IndexsEntry
+	(*anypb.Any)(nil),     // 13: google.protobuf.Any
+}
+var file_branch_undo_log_proto_depIdxs = []int32{
+	4,  // 0: parser.BranchUndoLog.Logs:type_name -> parser.SQLUndoLog
+	2,  // 1: parser.SQLUndoLog.SQLType:type_name -> parser.SQLType
+	5,  // 2: parser.SQLUndoLog.BeforeImage:type_name -> parser.RecordImage
+	5,  // 3: parser.SQLUndoLog.AfterImage:type_name -> parser.RecordImage
+	2,  // 4: parser.RecordImage.SQLType:type_name -> parser.SQLType
+	6,  // 5: parser.RecordImage.Rows:type_name -> parser.RowImage
+	8,  // 6: parser.RecordImage.TableMeta:type_name -> parser.TableMeta
+	7,  // 7: parser.RowImage.Columns:type_name -> parser.ColumnImage
+	0,  // 8: parser.ColumnImage.KeyType:type_name -> parser.IndexType
+	1,  // 9: parser.ColumnImage.ColumnType:type_name -> parser.JDBCType
+	13, // 10: parser.ColumnImage.Value:type_name -> google.protobuf.Any
+	11, // 11: parser.TableMeta.Columns:type_name -> parser.TableMeta.ColumnsEntry
+	12, // 12: parser.TableMeta.Indexs:type_name -> parser.TableMeta.IndexsEntry
+	0,  // 13: parser.IndexMeta.IType:type_name -> parser.IndexType
+	9,  // 14: parser.IndexMeta.Columns:type_name -> parser.ColumnMeta
+	9,  // 15: parser.TableMeta.ColumnsEntry.value:type_name -> parser.ColumnMeta
+	10, // 16: parser.TableMeta.IndexsEntry.value:type_name -> parser.IndexMeta
+	17, // [17:17] is the sub-list for method output_type
+	17, // [17:17] is the sub-list for method input_type
+	17, // [17:17] is the sub-list for extension type_name
+	17, // [17:17] is the sub-list for extension extendee
+	0,  // [0:17] is the sub-list for field type_name
+}
+
+func init() { file_branch_undo_log_proto_init() }
+func file_branch_undo_log_proto_init() {
+	if File_branch_undo_log_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_branch_undo_log_proto_msgTypes[0].Exporter = func(v any, i int) any {
+			switch v := v.(*BranchUndoLog); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_branch_undo_log_proto_msgTypes[1].Exporter = func(v any, i int) any {
+			switch v := v.(*SQLUndoLog); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_branch_undo_log_proto_msgTypes[2].Exporter = func(v any, i int) any {
+			switch v := v.(*RecordImage); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_branch_undo_log_proto_msgTypes[3].Exporter = func(v any, i int) any {
+			switch v := v.(*RowImage); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_branch_undo_log_proto_msgTypes[4].Exporter = func(v any, i int) any {
+			switch v := v.(*ColumnImage); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_branch_undo_log_proto_msgTypes[5].Exporter = func(v any, i int) any {
+			switch v := v.(*TableMeta); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_branch_undo_log_proto_msgTypes[6].Exporter = func(v any, i int) any {
+			switch v := v.(*ColumnMeta); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_branch_undo_log_proto_msgTypes[7].Exporter = func(v any, i int) any {
+			switch v := v.(*IndexMeta); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_branch_undo_log_proto_rawDesc,
+			NumEnums:      3,
+			NumMessages:   10,
+			NumExtensions: 0,
+			NumServices:   0,
+		},
+		GoTypes:           file_branch_undo_log_proto_goTypes,
+		DependencyIndexes: file_branch_undo_log_proto_depIdxs,
+		EnumInfos:         file_branch_undo_log_proto_enumTypes,
+		MessageInfos:      file_branch_undo_log_proto_msgTypes,
+	}.Build()
+	File_branch_undo_log_proto = out.File
+	file_branch_undo_log_proto_rawDesc = nil
+	file_branch_undo_log_proto_goTypes = nil
+	file_branch_undo_log_proto_depIdxs = nil
+}
diff --git a/pkg/datasource/sql/undo/parser/branch_undo_log.proto b/pkg/datasource/sql/undo/parser/branch_undo_log.proto
new file mode 100644
index 0000000..9055ea1
--- /dev/null
+++ b/pkg/datasource/sql/undo/parser/branch_undo_log.proto
@@ -0,0 +1,165 @@
+syntax = "proto3";
+package parser;
+import "google/protobuf/any.proto";
+
+option go_package=".;parser";
+
+message BranchUndoLog {
+	string Xid = 1;
+	uint64 BranchID = 2;
+	repeated SQLUndoLog Logs = 3;
+}
+
+message SQLUndoLog {
+	SQLType SQLType = 1;
+	string TableName = 2;
+	RecordImage BeforeImage = 3;
+	RecordImage AfterImage = 4;
+}
+
+message RecordImage {
+	int32 index = 1;
+	string TableName = 2;
+	SQLType SQLType = 3;
+	repeated RowImage Rows = 4;
+	TableMeta TableMeta = 5;
+}
+
+message RowImage {
+	repeated ColumnImage Columns = 1;
+}
+
+message ColumnImage {
+	IndexType KeyType = 1;
+	string ColumnName = 2;
+	JDBCType ColumnType = 3;
+	google.protobuf.Any Value = 4;
+}
+
+message TableMeta {
+	string TableName = 1;
+	map<string, ColumnMeta> Columns = 2;
+	map<string, IndexMeta> Indexs = 3;
+	repeated string ColumnNames = 4;
+}
+
+message ColumnMeta {
+	string Schema = 1;
+	string Table = 2;
+	bytes ColumnDef = 3;
+	bool Autoincrement = 4;
+	string ColumnName = 5;
+	string ColumnType = 6;
+	int32 DatabaseType = 7;
+	string DatabaseTypeString = 8;
+	string ColumnKey = 9;
+	int32 IsNullable = 10;
+	string Extra = 11;
+}
+
+message IndexMeta {
+	string Schema = 1;
+	string Table = 2;
+	string Name = 3;
+	string ColumnName = 4;
+	IndexType IType = 5;
+	repeated ColumnMeta Columns = 6;
+}
+
+enum IndexType {
+	IndexTypeNull = 0;
+	IndexTypePrimaryKey = 1;
+}
+
+enum JDBCType {
+	JDBCTypeNull = 0;
+	JDBCTypeBit = -7;
+	JDBCTypeTinyInt = -6;
+	JDBCTypeSmallInt = 5;
+	JDBCTypeInteger = 4;
+	JDBCTypeBigInt = -5;
+	JDBCTypeFloat = 6;
+	JDBCTypeReal = 7;
+	JDBCTypeDouble = 8;
+	JDBCTypeNumberic = 2;
+	JDBCTypeDecimal = 3;
+	JDBCTypeChar = 1;
+	JDBCTypeVarchar = 12;
+	JDBCTypeLongVarchar = -1;
+	JDBCTypeDate = 91;
+	JDBCTypeTime = 92;
+	JDBCTypeTimestamp = 93;
+	JDBCTypeBinary = -2;
+	JDBCTypeVarBinary = -3;
+	JDBCTypeLongVarBinary = -4;
+	JDBCTypeOther = 1111;
+	JDBCTypeJavaObject = 2000;
+	JDBCTypeDistinct = 2001;
+	JDBCTypeStruct = 2002;
+	JDBCTypeArray = 2003;
+	JDBCTypeBlob = 2004;
+	JDBCTypeClob = 2005;
+	JDBCTypeRef = 2006;
+	JDBCTypeDateLink = 70;
+	JDBCTypeBoolean = 16;
+	JDBCTypeRowID = -8;
+	JDBCTypeNchar = -15;
+	JDBCTypeNvarchar = -9;
+	JDBCTypeLongNvVarchar = -16;
+	JDBCTypeNclob = 2011;
+	JDBCTypeSqlXML = 2009;
+	JDBCTypeRefCursor = 2012;
+	JDBCTypeTimeWithTimeZone = 2013;
+	JDBCTypeTimestampWithTimezone = 2014;
+}
+
+enum SQLType {
+	SQLTypeSelect = 0;
+	SQLTypeInsert = 1;
+	SQLTypeUpdate = 2;
+	SQLTypeDelete = 3;
+	SQLTypeSelectForUpdate = 4;
+	SQLTypeReplace = 5;
+	SQLTypeTruncate = 6;
+	SQLTypeCreate = 7;
+	SQLTypeDrop = 8;
+	SQLTypeLoad = 9;
+	SQLTypeMerge = 10;
+	SQLTypeShow = 11;
+	SQLTypeAlter = 12;
+	SQLTypeRename = 13;
+	SQLTypeDump = 14;
+	SQLTypeDebug = 15;
+	SQLTypeExplain = 16;
+	SQLTypeProcedure = 17;
+	SQLTypeDesc = 18;
+	SQLLastInsertID = 19;
+	SQLSelectWithoutTable = 20;
+	SQLCreateSequence = 21;
+	SQLShowSequence = 22;
+	SQLGetSequence = 23;
+	SQLAlterSequence = 24;
+	SQLDropSequence = 25;
+	SQLTddlShow = 26;
+	SQLTypeSet = 27;
+	SQLTypeReload = 28;
+	SQLTypeSelectUnion = 29;
+	SQLTypeCreateTable = 30;
+	SQLTypeDropTable = 31;
+	SQLTypeAlterTable = 32;
+	SQLTypeSavePoint = 33;
+	SQLTypeSelectFromUpdate = 34;
+	SQLTypeMultiDelete = 35;
+	SQLTypeMultiUpdate = 36;
+	SQLTypeCreateIndex = 37;
+	SQLTypeDropIndex = 38;
+	SQLTypeKill = 39;
+	SQLTypeLockTables = 40;
+	SQLTypeUnLockTables = 41;
+	SQLTypeCheckTable = 42;
+	SQLTypeSelectFoundRows = 43;
+	SQLTypeInsertIgnore = 101; // Adjusted the value to match Go's logic
+	SQLTypeInsertOnDuplicateUpdate = 102;
+	SQLTypeMulti = 1044; // Adjusted the value to match Go's logic
+	SQLTypeUnknown = 1045;
+}
diff --git a/pkg/datasource/sql/undo/parser/parser_cache.go b/pkg/datasource/sql/undo/parser/parser_cache.go
index 511fd09..59c703f 100644
--- a/pkg/datasource/sql/undo/parser/parser_cache.go
+++ b/pkg/datasource/sql/undo/parser/parser_cache.go
@@ -39,6 +39,7 @@ func initCache() {
 	}
 
 	cache.store(&JsonParser{})
+	cache.store(&ProtobufParser{})
 }
 
 func GetCache() *UndoLogParserCache {
diff --git a/pkg/datasource/sql/undo/parser/parser_protobuf.go b/pkg/datasource/sql/undo/parser/parser_protobuf.go
new file mode 100644
index 0000000..7fd5608
--- /dev/null
+++ b/pkg/datasource/sql/undo/parser/parser_protobuf.go
@@ -0,0 +1,248 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package parser
+
+import (
+	"encoding/json"
+
+	"github.com/golang/protobuf/ptypes/any"
+	"github.com/golang/protobuf/ptypes/wrappers"
+	"google.golang.org/protobuf/proto"
+	"google.golang.org/protobuf/types/known/anypb"
+
+	"seata.apache.org/seata-go/pkg/datasource/sql/types"
+	"seata.apache.org/seata-go/pkg/datasource/sql/undo"
+)
+
+type ProtobufParser struct {
+}
+
+// GetName get the name of parser
+func (p *ProtobufParser) GetName() string {
+	return "protobuf"
+}
+
+// GetDefaultContent get default content of this parser
+func (p *ProtobufParser) GetDefaultContent() []byte {
+	return []byte{}
+}
+
+// Encode branch undo log to byte array
+func (p *ProtobufParser) Encode(branchUndoLog *undo.BranchUndoLog) ([]byte, error) {
+	protoLog := ConvertToProto(branchUndoLog)
+	return proto.Marshal(protoLog)
+}
+
+// Decode byte array to branch undo log
+func (p *ProtobufParser) Decode(data []byte) (*undo.BranchUndoLog, error) {
+	branchUndoLog := &BranchUndoLog{}
+	err := proto.Unmarshal(data, branchUndoLog)
+	if err != nil {
+		return nil, err
+	}
+
+	return ConvertToIntree(branchUndoLog), nil
+}
+
+func ConvertToProto(intreeLog *undo.BranchUndoLog) *BranchUndoLog {
+	protoLog := &BranchUndoLog{
+		Xid:      intreeLog.Xid,
+		BranchID: intreeLog.BranchID,
+		Logs:     []*SQLUndoLog{},
+	}
+	for _, undolog := range intreeLog.Logs {
+		protolog := &SQLUndoLog{
+			SQLType:   SQLType(undolog.SQLType),
+			TableName: undolog.TableName,
+		}
+
+		if undolog.BeforeImage != nil {
+			protolog.BeforeImage = &RecordImage{
+				TableName: undolog.BeforeImage.TableName,
+				SQLType:   SQLType(undolog.BeforeImage.SQLType),
+				Rows:      []*RowImage{},
+			}
+
+			for _, row := range undolog.BeforeImage.Rows {
+				protoRow := &RowImage{
+					Columns: []*ColumnImage{},
+				}
+
+				for _, col := range row.Columns {
+					anyValue, err := convertInterfaceToAny(col.GetActualValue())
+					if err != nil {
+						continue
+					}
+
+					protoCol := &ColumnImage{
+						KeyType:    IndexType(col.KeyType),
+						ColumnName: col.ColumnName,
+						ColumnType: JDBCType(col.ColumnType),
+						Value:      anyValue,
+					}
+
+					protoRow.Columns = append(protoRow.Columns, protoCol)
+				}
+
+				protolog.BeforeImage.Rows = append(protolog.BeforeImage.Rows, protoRow)
+			}
+		}
+
+		if undolog.AfterImage != nil {
+			protolog.AfterImage = &RecordImage{
+				TableName: undolog.AfterImage.TableName,
+				SQLType:   SQLType(undolog.AfterImage.SQLType),
+				Rows:      []*RowImage{},
+			}
+
+			for _, row := range undolog.AfterImage.Rows {
+				protoRow := &RowImage{
+					Columns: []*ColumnImage{},
+				}
+
+				for _, col := range row.Columns {
+					anyValue, err := convertInterfaceToAny(col.Value)
+					if err != nil {
+						continue
+					}
+
+					protoCol := &ColumnImage{
+						KeyType:    IndexType(col.KeyType),
+						ColumnName: col.ColumnName,
+						ColumnType: JDBCType(col.ColumnType),
+						Value:      anyValue,
+					}
+
+					protoRow.Columns = append(protoRow.Columns, protoCol)
+				}
+
+				protolog.AfterImage.Rows = append(protolog.AfterImage.Rows, protoRow)
+			}
+		}
+
+		protoLog.Logs = append(protoLog.Logs, protolog)
+	}
+	return protoLog
+}
+
+func ConvertToIntree(protoLog *BranchUndoLog) *undo.BranchUndoLog {
+	intreeLog := &undo.BranchUndoLog{
+		Xid:      protoLog.Xid,
+		BranchID: protoLog.BranchID,
+		Logs:     []undo.SQLUndoLog{},
+	}
+
+	for _, pbSqlLog := range protoLog.Logs {
+		undoSqlLog := undo.SQLUndoLog{
+			SQLType:   types.SQLType(pbSqlLog.SQLType),
+			TableName: pbSqlLog.TableName,
+		}
+
+		if pbSqlLog.BeforeImage != nil {
+			undoSqlLog.BeforeImage = &types.RecordImage{
+				TableName: pbSqlLog.BeforeImage.TableName,
+				SQLType:   types.SQLType(pbSqlLog.BeforeImage.SQLType),
+				Rows:      []types.RowImage{},
+			}
+
+			for _, pbRow := range pbSqlLog.BeforeImage.Rows {
+				undoRow := types.RowImage{
+					Columns: []types.ColumnImage{},
+				}
+
+				for _, pbCol := range pbRow.Columns {
+					anyValue, err := convertAnyToInterface(pbCol.Value)
+					if err != nil {
+						continue
+					}
+
+					undoCol := types.ColumnImage{
+						KeyType:    types.IndexType(pbCol.KeyType),
+						ColumnName: pbCol.ColumnName,
+						ColumnType: types.JDBCType(pbCol.ColumnType),
+						Value:      anyValue,
+					}
+
+					undoRow.Columns = append(undoRow.Columns, undoCol)
+				}
+
+				undoSqlLog.BeforeImage.Rows = append(undoSqlLog.BeforeImage.Rows, undoRow)
+			}
+		}
+
+		if pbSqlLog.AfterImage != nil {
+			undoSqlLog.AfterImage = &types.RecordImage{
+				TableName: pbSqlLog.AfterImage.TableName,
+				SQLType:   types.SQLType(pbSqlLog.AfterImage.SQLType),
+				Rows:      []types.RowImage{},
+			}
+
+			for _, pbRow := range pbSqlLog.AfterImage.Rows {
+				undoRow := types.RowImage{
+					Columns: []types.ColumnImage{},
+				}
+
+				for _, pbCol := range pbRow.Columns {
+					anyValue, err := convertAnyToInterface(pbCol.Value)
+					if err != nil {
+						continue
+					}
+
+					undoCol := types.ColumnImage{
+						KeyType:    types.IndexType(pbCol.KeyType),
+						ColumnName: pbCol.ColumnName,
+						ColumnType: types.JDBCType(pbCol.ColumnType),
+						Value:      anyValue,
+					}
+
+					undoRow.Columns = append(undoRow.Columns, undoCol)
+				}
+
+				undoSqlLog.AfterImage.Rows = append(undoSqlLog.AfterImage.Rows, undoRow)
+			}
+		}
+
+		intreeLog.Logs = append(intreeLog.Logs, undoSqlLog)
+	}
+
+	return intreeLog
+}
+
+func convertAnyToInterface(anyValue *any.Any) (interface{}, error) {
+	var value interface{}
+	bytesValue := &wrappers.BytesValue{}
+	err := anypb.UnmarshalTo(anyValue, bytesValue, proto.UnmarshalOptions{})
+	if err != nil {
+		return value, err
+	}
+	uErr := json.Unmarshal(bytesValue.Value, &value)
+	if uErr != nil {
+		return value, uErr
+	}
+	return value, nil
+}
+
+func convertInterfaceToAny(v interface{}) (*any.Any, error) {
+	anyValue := &any.Any{}
+	bytes, _ := json.Marshal(v)
+	bytesValue := &wrappers.BytesValue{
+		Value: bytes,
+	}
+	err := anypb.MarshalFrom(anyValue, bytesValue, proto.MarshalOptions{})
+	return anyValue, err
+}
diff --git a/pkg/remoting/getty/listener.go b/pkg/remoting/getty/listener.go
index f5ba96f..2f2e974 100644
--- a/pkg/remoting/getty/listener.go
+++ b/pkg/remoting/getty/listener.go
@@ -115,10 +115,14 @@ func (g *gettyClientHandler) OnMessage(session getty.Session, pkg interface{}) {
 
 func (g *gettyClientHandler) OnCron(session getty.Session) {
 	log.Debug("session{%s} Oncron executing", session.Stat())
-	g.transferBeatHeart(session, message.HeartBeatMessagePing)
+	err := g.transferHeartBeat(session, message.HeartBeatMessagePing)
+	if err != nil {
+		log.Errorf("failed to send heart beat: {%#v}", err.Error())
+		g.sessionManager.releaseSession(session)
+	}
 }
 
-func (g *gettyClientHandler) transferBeatHeart(session getty.Session, msg message.HeartBeatMessage) {
+func (g *gettyClientHandler) transferHeartBeat(session getty.Session, msg message.HeartBeatMessage) error {
 	rpcMessage := message.RpcMessage{
 		ID:         int32(g.idGenerator.Inc()),
 		Type:       message.GettyRequestTypeHeartbeatRequest,
@@ -126,7 +130,7 @@ func (g *gettyClientHandler) transferBeatHeart(session getty.Session, msg messag
 		Compressor: 0,
 		Body:       msg,
 	}
-	GetGettyRemotingInstance().SendASync(rpcMessage, session, nil)
+	return GetGettyRemotingInstance().SendASync(rpcMessage, session, nil)
 }
 
 func (g *gettyClientHandler) RegisterProcessor(msgType message.MessageType, processor processor.RemotingProcessor) {
diff --git a/pkg/remoting/getty/readwriter.go b/pkg/remoting/getty/readwriter.go
index 5232315..3216489 100644
--- a/pkg/remoting/getty/readwriter.go
+++ b/pkg/remoting/getty/readwriter.go
@@ -58,9 +58,9 @@ var (
 
 var (
 	ErrNotEnoughStream = errors.New("packet stream is not enough")
-	ErrTooLargePackage = errors.New("package length is exceed the getty package's legal maximum length.")
+	ErrTooLargePackage = errors.New("package length is exceed the getty package's legal maximum length")
 	ErrInvalidPackage  = errors.New("invalid rpc package")
-	ErrIllegalMagic    = errors.New("package magic is not right.")
+	ErrIllegalMagic    = errors.New("package magic is not right")
 )
 
 type RpcPackageHandler struct{}
@@ -141,7 +141,7 @@ func (p *RpcPackageHandler) Write(ss getty.Session, pkg interface{}) ([]byte, er
 	headLength := message.V1HeadLength
 
 	var headMapBytes []byte
-	if msg.HeadMap != nil && len(msg.HeadMap) > 0 {
+	if len(msg.HeadMap) > 0 {
 		hb, headMapLength := encodeHeapMap(msg.HeadMap)
 		headMapBytes = hb
 		headLength += headMapLength
diff --git a/pkg/remoting/loadbalance/loadbalance.go b/pkg/remoting/loadbalance/loadbalance.go
index 5704eb3..abfb6b6 100644
--- a/pkg/remoting/loadbalance/loadbalance.go
+++ b/pkg/remoting/loadbalance/loadbalance.go
@@ -40,7 +40,7 @@ func Select(loadBalanceType string, sessions *sync.Map, xid string) getty.Sessio
 	case consistentHashLoadBalance:
 		return ConsistentHashLoadBalance(sessions, xid)
 	case leastActiveLoadBalance:
-		return LeastActiveLoadBalance(sessions, xid)	
+		return LeastActiveLoadBalance(sessions, xid)
 	case roundRobinLoadBalance:
 		return RoundRobinLoadBalance(sessions, xid)
 	default:
diff --git a/pkg/rm/rm_remoting.go b/pkg/rm/rm_remoting.go
index 6752250..563ebc8 100644
--- a/pkg/rm/rm_remoting.go
+++ b/pkg/rm/rm_remoting.go
@@ -156,7 +156,7 @@ func isRegisterSuccess(response interface{}) bool {
 func isReportSuccess(response interface{}) error {
 	if res, ok := response.(message.BranchReportResponse); ok {
 		if res.ResultCode == message.ResultCodeFailed {
-			return fmt.Errorf(res.Msg)
+			return errors.New(res.Msg)
 		}
 	} else {
 		return ErrBranchReportResponseFault
diff --git a/pkg/rm/tcc/tcc_service.go b/pkg/rm/tcc/tcc_service.go
index ffedff1..87335c6 100644
--- a/pkg/rm/tcc/tcc_service.go
+++ b/pkg/rm/tcc/tcc_service.go
@@ -20,7 +20,7 @@ package tcc
 import (
 	"context"
 	"encoding/json"
-	"fmt"
+	"errors"
 	"reflect"
 	"sync"
 	"time"
@@ -94,7 +94,7 @@ func (t *TCCServiceProxy) registeBranch(ctx context.Context, params interface{})
 	if !tm.IsGlobalTx(ctx) {
 		errStr := "BranchRegister error, transaction should be opened"
 		log.Errorf(errStr)
-		return fmt.Errorf(errStr)
+		return errors.New(errStr)
 	}
 
 	tccContext := t.initBusinessActionContext(ctx, params)


Test patch:
diff --git a/pkg/datasource/sql/exec/at/insert_executor_test.go b/pkg/datasource/sql/exec/at/insert_executor_test.go
index fa899df..742249b 100644
--- a/pkg/datasource/sql/exec/at/insert_executor_test.go
+++ b/pkg/datasource/sql/exec/at/insert_executor_test.go
@@ -78,7 +78,7 @@ func TestBuildSelectSQLByInsert(t *testing.T) {
 				},
 			},
 
-			expectQuery:     "SELECT * FROM user WHERE (`id`) IN ((?),(?)) ",
+			expectQuery:     "SELECT id, name FROM user WHERE (`id`) IN ((?),(?)) ",
 			expectQueryArgs: []driver.Value{int64(19), int64(21)},
 		},
 		{
@@ -107,7 +107,7 @@ func TestBuildSelectSQLByInsert(t *testing.T) {
 					},
 				},
 			},
-			expectQuery:     "SELECT * FROM user WHERE (`user_id`) IN ((?)) ",
+			expectQuery:     "SELECT user_id, name FROM user WHERE (`user_id`) IN ((?)) ",
 			expectQueryArgs: []driver.Value{int64(20)},
 		},
 	}
diff --git a/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder_test.go b/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder_test.go
index 03e028f..59e673f 100644
--- a/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder_test.go
+++ b/pkg/datasource/sql/undo/builder/mysql_insertonduplicate_update_undo_log_builder_test.go
@@ -46,7 +46,7 @@ func TestInsertOnDuplicateBuildBeforeImageSQL(t *testing.T) {
 	)
 	columnId := types.ColumnMeta{
 		ColumnDef:  nil,
-		ColumnName: "id",
+		ColumnName: "ID",
 	}
 	columnName := types.ColumnMeta{
 		ColumnDef:  nil,
@@ -56,12 +56,12 @@ func TestInsertOnDuplicateBuildBeforeImageSQL(t *testing.T) {
 		ColumnDef:  nil,
 		ColumnName: "age",
 	}
-	columns["id"] = columnId
+	columns["ID"] = columnId
 	columns["name"] = columnName
 	columns["age"] = columnAge
 	columnMeta1 = append(columnMeta1, columnId)
 	columnMeta2 = append(columnMeta2, columnName, columnAge)
-	index["id"] = types.IndexMeta{
+	index["ID"] = types.IndexMeta{
 		Name:    "PRIMARY",
 		IType:   types.IndexTypePrimaryKey,
 		Columns: columnMeta1,
@@ -72,7 +72,7 @@ func TestInsertOnDuplicateBuildBeforeImageSQL(t *testing.T) {
 		Columns: columnMeta2,
 	}
 
-	ColumnNames = []string{"id", "name", "age"}
+	ColumnNames = []string{"ID", "name", "age"}
 	tableMeta1 = types.TableMeta{
 		TableName:   "t_user",
 		Columns:     columns,
diff --git a/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder_test.go b/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder_test.go
index f5b07a4..f65a2e9 100644
--- a/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder_test.go
+++ b/pkg/datasource/sql/undo/builder/mysql_update_undo_log_builder_test.go
@@ -39,12 +39,14 @@ import (
 )
 
 func TestBuildSelectSQLByUpdate(t *testing.T) {
-	t.SkipNow()
+	//t.SkipNow()
 	var (
 		builder = MySQLUpdateUndoLogBuilder{}
 	)
 
-	stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta", func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string, conn driver.Conn) (*types.TableMeta, error) {
+	datasource.RegisterTableCache(types.DBTypeMySQL, &mysql.TableMetaCache{})
+
+	stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta", func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) {
 		return &types.TableMeta{
 			Indexs: map[string]types.IndexMeta{
 				"id": {
@@ -77,6 +79,12 @@ func TestBuildSelectSQLByUpdate(t *testing.T) {
 			expectQuery:     "SELECT SQL_NO_CACHE name,age,id FROM t_user WHERE id=? AND name=_UTF8MB4Jack AND age BETWEEN ? AND ? FOR UPDATE",
 			expectQueryArgs: []driver.Value{100, 18, 28},
 		},
+		{
+			sourceQuery:     "update t_user set name = ?, age = ? where (id = ? or name = 'Jack') and age between ? and ?",
+			sourceQueryArgs: []driver.Value{"Jack", 1, 100, 18, 28},
+			expectQuery:     "SELECT SQL_NO_CACHE name,age,id FROM t_user WHERE (id=? OR name=_UTF8MB4Jack) AND age BETWEEN ? AND ? FOR UPDATE",
+			expectQueryArgs: []driver.Value{100, 18, 28},
+		},
 		{
 			sourceQuery:     "update t_user set name = ?, age = ? where id = ? and name = 'Jack' and age in (?,?)",
 			sourceQueryArgs: []driver.Value{"Jack", 1, 100, 18, 28},
diff --git a/pkg/datasource/sql/undo/parser/parser_json_test.go b/pkg/datasource/sql/undo/parser/parser_json_test.go
index 4f73c32..2123f08 100644
--- a/pkg/datasource/sql/undo/parser/parser_json_test.go
+++ b/pkg/datasource/sql/undo/parser/parser_json_test.go
@@ -25,15 +25,15 @@ import (
 	"seata.apache.org/seata-go/pkg/datasource/sql/undo"
 )
 
-func TestGetName(t *testing.T) {
+func TestJsonGetName(t *testing.T) {
 	assert.Equal(t, "json", (&JsonParser{}).GetName())
 }
 
-func TestGetDefaultContext(t *testing.T) {
+func TestJsonGetDefaultContext(t *testing.T) {
 	assert.Equal(t, []byte("{}"), (&JsonParser{}).GetDefaultContent())
 }
 
-func TestEncode(t *testing.T) {
+func TestJsonEncode(t *testing.T) {
 	TestCases := []struct {
 		CaseName    string
 		UndoLog     *undo.BranchUndoLog
@@ -67,7 +67,7 @@ func TestEncode(t *testing.T) {
 	}
 }
 
-func TestDecode(t *testing.T) {
+func TestJsonDecode(t *testing.T) {
 	TestCases := []struct {
 		CaseName      string
 		ExpectUndoLog undo.BranchUndoLog
diff --git a/pkg/datasource/sql/undo/parser/parser_protobuf_test.go b/pkg/datasource/sql/undo/parser/parser_protobuf_test.go
new file mode 100644
index 0000000..e8cb0d5
--- /dev/null
+++ b/pkg/datasource/sql/undo/parser/parser_protobuf_test.go
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package parser
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"seata.apache.org/seata-go/pkg/datasource/sql/undo"
+)
+
+func TestProtobufGetName(t *testing.T) {
+	assert.Equal(t, "protobuf", (&ProtobufParser{}).GetName())
+}
+
+func TestProtobufDefaultContext(t *testing.T) {
+	assert.Equal(t, []byte{}, (&ProtobufParser{}).GetDefaultContent())
+}
+
+func TestProtobufEncodeDecode(t *testing.T) {
+	TestCases := []struct {
+		CaseName  string
+		UndoLog   *undo.BranchUndoLog
+		ExpectErr bool
+	}{
+		{
+			CaseName: "pass",
+			UndoLog: &undo.BranchUndoLog{
+				Xid:      "123456",
+				BranchID: 123456,
+				Logs:     []undo.SQLUndoLog{},
+			},
+			ExpectErr: false,
+		},
+	}
+
+	for _, Case := range TestCases {
+		t.Run(Case.CaseName, func(t *testing.T) {
+			parser := &ProtobufParser{}
+
+			encodedBytes, err := parser.Encode(Case.UndoLog)
+			if Case.ExpectErr {
+				assert.NotNil(t, err)
+				return
+			}
+			assert.Nil(t, err)
+
+			decodedUndoLog, err := parser.Decode(encodedBytes)
+			if Case.ExpectErr {
+				assert.NotNil(t, err)
+				return
+			}
+			assert.Nil(t, err)
+
+			assert.Equal(t, Case.UndoLog.Xid, decodedUndoLog.Xid)
+			assert.Equal(t, Case.UndoLog.BranchID, decodedUndoLog.BranchID)
+			assert.Equal(t, len(Case.UndoLog.Logs), len(decodedUndoLog.Logs))
+		})
+	}
+}
+
+func TestConvertInterfaceToAnyAndBack(t *testing.T) {
+	originalValue := map[string]interface{}{
+		"key1": "value1",
+		"key2": float64(123), // Use float64 to match JSON default behavior
+		"key3": true,
+	}
+
+	anyValue, err := convertInterfaceToAny(originalValue)
+	assert.NoError(t, err, "convertInterfaceToAny should not return an error")
+
+	convertedValue, err := convertAnyToInterface(anyValue)
+	assert.NoError(t, err, "convertAnyToInterface should not return an error")
+
+	assert.Equal(t, originalValue, convertedValue, "The converted value should match the original")
+}
diff --git a/pkg/rm/tcc/fence/fennce_driver_test.go b/pkg/rm/tcc/fence/fennce_driver_test.go
index cfaddd2..c0e804e 100644
--- a/pkg/rm/tcc/fence/fennce_driver_test.go
+++ b/pkg/rm/tcc/fence/fennce_driver_test.go
@@ -24,7 +24,7 @@ import (
 	"reflect"
 	"testing"
 
-	"github.com/agiledragon/gomonkey"
+	gomonkey "github.com/agiledragon/gomonkey/v2"
 	"github.com/go-sql-driver/mysql"
 	"github.com/stretchr/testify/assert"
 )