This is an automated email from the ASF dual-hosted git repository.

luky116 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-seata-go.git


The following commit(s) were added to refs/heads/master by this push:
     new 1b72cb8c optimize: optimize the speed of buildLockKey (#714)
1b72cb8c is described below

commit 1b72cb8cb8bb5c5019d478558515d6dc5d168073
Author: FinnTew <[email protected]>
AuthorDate: Fri Dec 27 23:46:57 2024 +0800

    optimize: optimize the speed of buildLockKey (#714)
    
    * optimize: optimize the speed of buildLockKey
    
    * improve unit testing of buildLockKey
    
    * fix the situation where primaryKeyValues contains nil value
    
    * update the unit test of buildLockKey
    
    ---------
    
    Co-authored-by: JayLiu <[email protected]>
---
 .../sql/undo/builder/basic_undo_log_builder.go     |  46 ++++---
 .../undo/builder/basic_undo_log_builder_test.go    | 139 +++++++++++++++++++--
 2 files changed, 152 insertions(+), 33 deletions(-)

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 043e7eb4..775cb619 100644
--- a/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go
+++ b/pkg/datasource/sql/undo/builder/basic_undo_log_builder.go
@@ -276,35 +276,41 @@ func (b *BasicUndoLogBuilder) buildLockKey(rows 
driver.Rows, meta types.TableMet
 
 // the string as local key. the local key example(multi pk): "t_user:1_a,2_b"
 func (b *BasicUndoLogBuilder) buildLockKey2(records *types.RecordImage, meta 
types.TableMeta) string {
-       var (
-               lockKeys      bytes.Buffer
-               filedSequence int
-       )
+       var lockKeys bytes.Buffer
        lockKeys.WriteString(meta.TableName)
        lockKeys.WriteString(":")
 
        keys := meta.GetPrimaryKeyOnlyName()
+       keyIndexMap := make(map[string]int, len(keys))
 
-       for _, row := range records.Rows {
-               if filedSequence > 0 {
+       for idx, columnName := range keys {
+               keyIndexMap[columnName] = idx
+       }
+
+       primaryKeyRows := make([][]interface{}, len(records.Rows))
+
+       for i, row := range records.Rows {
+               primaryKeyValues := make([]interface{}, len(keys))
+               for _, column := range row.Columns {
+                       if idx, exist := keyIndexMap[column.ColumnName]; exist {
+                               primaryKeyValues[idx] = column.Value
+                       }
+               }
+               primaryKeyRows[i] = primaryKeyValues
+       }
+
+       for i, primaryKeyValues := range primaryKeyRows {
+               if i > 0 {
                        lockKeys.WriteString(",")
                }
-               pkSplitIndex := 0
-               for _, column := range row.Columns {
-                       var hasKeyColumn bool
-                       for _, key := range keys {
-                               if column.ColumnName == key {
-                                       hasKeyColumn = true
-                                       if pkSplitIndex > 0 {
-                                               lockKeys.WriteString("_")
-                                       }
-                                       lockKeys.WriteString(fmt.Sprintf("%v", 
column.Value))
-                                       pkSplitIndex++
-                               }
+               for j, pkVal := range primaryKeyValues {
+                       if j > 0 {
+                               lockKeys.WriteString("_")
                        }
-                       if hasKeyColumn {
-                               filedSequence++
+                       if pkVal == nil {
+                               continue
                        }
+                       lockKeys.WriteString(fmt.Sprintf("%v", pkVal))
                }
        }
 
diff --git a/pkg/datasource/sql/undo/builder/basic_undo_log_builder_test.go 
b/pkg/datasource/sql/undo/builder/basic_undo_log_builder_test.go
index 152c0a47..465bf516 100644
--- a/pkg/datasource/sql/undo/builder/basic_undo_log_builder_test.go
+++ b/pkg/datasource/sql/undo/builder/basic_undo_log_builder_test.go
@@ -50,22 +50,135 @@ func TestBuildWhereConditionByPKs(t *testing.T) {
 }
 
 func TestBuildLockKey(t *testing.T) {
-       metaData := types.TableMeta{
-               TableName: "test_name",
-               Indexs: map[string]types.IndexMeta{
-                       "PRIMARY_KEY": {IType: types.IndexTypePrimaryKey, 
Columns: []types.ColumnMeta{{ColumnName: "id"}, {ColumnName: "userId"}}},
-               },
+       var builder BasicUndoLogBuilder
+
+       columnID := types.ColumnMeta{
+               ColumnName: "id",
+       }
+       columnUserId := types.ColumnMeta{
+               ColumnName: "userId",
+       }
+       columnName := types.ColumnMeta{
+               ColumnName: "name",
+       }
+       columnAge := types.ColumnMeta{
+               ColumnName: "age",
        }
+       columnNonExistent := types.ColumnMeta{
+               ColumnName: "non_existent",
+       }
+
+       columnsTwoPk := []types.ColumnMeta{columnID, columnUserId}
+       columnsMixPk := []types.ColumnMeta{columnName, columnAge}
 
-       records := types.RecordImage{
-               TableName: "test_name",
-               Rows: []types.RowImage{
-                       {Columns: []types.ColumnImage{{KeyType: 
types.IndexTypePrimaryKey, ColumnName: "id", Value: 1}, {KeyType: 
types.IndexTypePrimaryKey, ColumnName: "userId", Value: "one"}}},
-                       {Columns: []types.ColumnImage{{KeyType: 
types.IndexTypePrimaryKey, ColumnName: "id", Value: 2}, {KeyType: 
types.IndexTypePrimaryKey, ColumnName: "userId", Value: "two"}}},
+       getColumnImage := func(columnName string, value interface{}) 
types.ColumnImage {
+               return types.ColumnImage{KeyType: types.IndexTypePrimaryKey, 
ColumnName: columnName, Value: value}
+       }
+
+       tests := []struct {
+               name     string
+               metaData types.TableMeta
+               records  types.RecordImage
+               expected string
+       }{
+               {
+                       "Two Primary Keys",
+                       types.TableMeta{
+                               TableName: "test_name",
+                               Indexs: map[string]types.IndexMeta{
+                                       "PRIMARY_KEY": {IType: 
types.IndexTypePrimaryKey, Columns: columnsTwoPk},
+                               },
+                       },
+                       types.RecordImage{
+                               TableName: "test_name",
+                               Rows: []types.RowImage{
+                                       
{[]types.ColumnImage{getColumnImage("id", 1), getColumnImage("userId", "one")}},
+                                       
{[]types.ColumnImage{getColumnImage("id", 2), getColumnImage("userId", "two")}},
+                               },
+                       },
+                       "test_name:1_one,2_two",
+               },
+               {
+                       name: "Single Primary Key",
+                       metaData: types.TableMeta{
+                               TableName: "single_key",
+                               Indexs: map[string]types.IndexMeta{
+                                       "PRIMARY_KEY": {IType: 
types.IndexTypePrimaryKey, Columns: []types.ColumnMeta{columnID}},
+                               },
+                       },
+                       records: types.RecordImage{
+                               TableName: "single_key",
+                               Rows: []types.RowImage{
+                                       {Columns: 
[]types.ColumnImage{getColumnImage("id", 100)}},
+                               },
+                       },
+                       expected: "single_key:100",
+               },
+               {
+                       name: "Mixed Type Keys",
+                       metaData: types.TableMeta{
+                               TableName: "mixed_key",
+                               Indexs: map[string]types.IndexMeta{
+                                       "PRIMARY_KEY": {IType: 
types.IndexTypePrimaryKey, Columns: columnsMixPk},
+                               },
+                       },
+                       records: types.RecordImage{
+                               TableName: "mixed_key",
+                               Rows: []types.RowImage{
+                                       {Columns: 
[]types.ColumnImage{getColumnImage("name", "Alice"), getColumnImage("age", 
25)}},
+                               },
+                       },
+                       expected: "mixed_key:Alice_25",
+               },
+               {
+                       name: "Empty Records",
+                       metaData: types.TableMeta{
+                               TableName: "empty",
+                               Indexs: map[string]types.IndexMeta{
+                                       "PRIMARY_KEY": {IType: 
types.IndexTypePrimaryKey, Columns: []types.ColumnMeta{columnID}},
+                               },
+                       },
+                       records:  types.RecordImage{TableName: "empty"},
+                       expected: "empty:",
+               },
+               {
+                       name: "Special Characters",
+                       metaData: types.TableMeta{
+                               TableName: "special",
+                               Indexs: map[string]types.IndexMeta{
+                                       "PRIMARY_KEY": {IType: 
types.IndexTypePrimaryKey, Columns: []types.ColumnMeta{columnID}},
+                               },
+                       },
+                       records: types.RecordImage{
+                               TableName: "special",
+                               Rows: []types.RowImage{
+                                       {Columns: 
[]types.ColumnImage{getColumnImage("id", "a,b_c")}},
+                               },
+                       },
+                       expected: "special:a,b_c",
+               },
+               {
+                       name: "Non-existent Key Name",
+                       metaData: types.TableMeta{
+                               TableName: "error_key",
+                               Indexs: map[string]types.IndexMeta{
+                                       "PRIMARY_KEY": {IType: 
types.IndexTypePrimaryKey, Columns: []types.ColumnMeta{columnNonExistent}},
+                               },
+                       },
+                       records: types.RecordImage{
+                               TableName: "error_key",
+                               Rows: []types.RowImage{
+                                       {Columns: 
[]types.ColumnImage{getColumnImage("id", 1)}},
+                               },
+                       },
+                       expected: "error_key:",
                },
        }
 
-       builder := BasicUndoLogBuilder{}
-       lockKeys := builder.buildLockKey2(&records, metaData)
-       assert.Equal(t, "test_name:1_one,2_two", lockKeys)
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       lockKeys := builder.buildLockKey2(&tt.records, 
tt.metaData)
+                       assert.Equal(t, tt.expected, lockKeys)
+               })
+       }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to