github.com/kaydxh/golang@v0.0.131/pkg/database/mysql/mysql_operate_test.go (about) 1 /* 2 *Copyright (c) 2023, kaydxh 3 * 4 *Permission is hereby granted, free of charge, to any person obtaining a copy 5 *of this software and associated documentation files (the "Software"), to deal 6 *in the Software without restriction, including without limitation the rights 7 *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 *copies of the Software, and to permit persons to whom the Software is 9 *furnished to do so, subject to the following conditions: 10 * 11 *The above copyright notice and this permission notice shall be included in all 12 *copies or substantial portions of the Software. 13 * 14 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 *SOFTWARE. 21 */ 22 package mysql_test 23 24 import ( 25 "context" 26 "database/sql" 27 "fmt" 28 "strings" 29 "testing" 30 31 "github.com/google/uuid" 32 mysql_ "github.com/kaydxh/golang/pkg/database/mysql" 33 viper_ "github.com/kaydxh/golang/pkg/viper" 34 ) 35 36 type TaskTable struct { 37 // Id sql.NullInt64 `db:"id"` // primary key ID 38 39 // NullTime represents a time.Time that may be null. 40 // NullTime implements the Scanner interface so 41 // it can be used as a scan destination, similar to NullString. 42 CreateTime sql.NullTime `db:"create_time"` 43 UpdateTime sql.NullTime `db:"update_time"` 44 45 GroupId string `db:"group_id"` 46 PageId string `db:"page_id"` 47 FeaId string `db:"fea_id"` 48 EntityId string `db:"entity_id"` 49 Feature0 []byte `db:"feature0"` 50 Feature1 []byte `db:"feature1"` 51 ExtendInfo []byte `db:"extend_info"` 52 } 53 54 type Tasks []*TaskTable 55 56 func (t Tasks) String() string { 57 s := "[" 58 for _, task := range t { 59 s += fmt.Sprintf("%v,", task) 60 } 61 if len(t) > 0 { 62 s = strings.TrimRight(s, ",") 63 } 64 65 return s + "]" 66 } 67 func TestInsert(t *testing.T) { 68 69 cfgFile := "./mysql.dev.yaml" 70 config := mysql_.NewConfig(mysql_.WithViper(viper_.GetViper(cfgFile, "database.mysql"))) 71 72 db, err := config.Complete().New(context.Background()) 73 if err != nil { 74 t.Errorf("failed to new config err: %v", err) 75 } 76 77 t.Logf("db: %#v", db) 78 ctx := context.Background() 79 80 testCases := []struct { 81 TableName string 82 GroupId string 83 Number int64 84 }{ 85 { 86 TableName: "hetu_zeus_0", 87 GroupId: "hetu_image_copyright_prod", 88 Number: 100, 89 }, 90 } 91 92 for _, testCase := range testCases { 93 t.Run(fmt.Sprintf("table[%v]-fieldKey[%v]", testCase.TableName, testCase.GroupId), func(t *testing.T) { 94 95 count := testCase.Number 96 97 for count > 0 { 98 arg := &TaskTable{ 99 GroupId: testCase.GroupId, 100 PageId: "100", 101 FeaId: uuid.NewString(), 102 Feature0: []byte("Feature0"), 103 Feature1: []byte("Feature1"), 104 ExtendInfo: []byte("ExtendInfo"), 105 } 106 query := fmt.Sprintf(`INSERT INTO %s 107 ( 108 group_id, 109 page_id, 110 fea_id, 111 entity_id, 112 feature0, 113 feature1, 114 extend_info 115 ) 116 VALUES ( 117 :group_id, 118 :page_id, 119 :fea_id, 120 :entity_id, 121 :feature0, 122 :feature1, 123 :extend_info 124 ) 125 `, testCase.TableName) 126 127 _, err = mysql_.ExecContext(ctx, query, arg, nil, db) 128 if err != nil { 129 t.Errorf("faild to insert %v, err: %v", arg, err) 130 } 131 count-- 132 } 133 134 }) 135 } 136 } 137 138 func TestInsertNewBatch(t *testing.T) { 139 140 cfgFile := "./mysql.dev.yaml" 141 config := mysql_.NewConfig(mysql_.WithViper(viper_.GetViper(cfgFile, "database.mysql"))) 142 143 db, err := config.Complete().New(context.Background()) 144 if err != nil { 145 t.Errorf("failed to new config err: %v", err) 146 } 147 148 t.Logf("db: %#v", db) 149 ctx := context.Background() 150 151 batch := 512 152 tableName := "hetu_zeus_0" 153 154 cols := []string{"group_id", "page_id", "fea_id", "entity_id", "feature0", "feature1", "extend_info"} 155 query := fmt.Sprintf(`INSERT INTO %s 156 ( 157 group_id, 158 page_id, 159 fea_id, 160 entity_id, 161 feature0, 162 feature1, 163 extend_info 164 ) 165 VALUES %s 166 `, tableName, 167 mysql_.JoinNamedColumnsValuesBatch(cols, batch)) 168 169 testCases := []struct { 170 TableName string 171 GroupId string 172 Number int64 173 }{ 174 { 175 TableName: "hetu_zeus_0", 176 GroupId: "hetu_image_copyright_prod", 177 }, 178 } 179 180 for _, testCase := range testCases { 181 t.Run(fmt.Sprintf("table[%v]-fieldKey[%v]", testCase.TableName, testCase.GroupId), func(t *testing.T) { 182 183 count := batch 184 var args []*TaskTable 185 for count > 0 { 186 arg := &TaskTable{ 187 GroupId: testCase.GroupId, 188 PageId: "100", 189 FeaId: uuid.NewString(), 190 EntityId: "200", 191 Feature0: []byte("Feature0"), 192 Feature1: []byte("Feature1"), 193 ExtendInfo: []byte("ExtendInfo"), 194 } 195 args = append(args, arg) 196 count-- 197 } 198 _, err = mysql_.ExecContext(ctx, query, mysql_.BuildNamedColumnsValuesBatch(args), nil, db) 199 if err != nil { 200 t.Errorf("faild to insert %v, err: %v", args, err) 201 } 202 203 }) 204 } 205 } 206 207 func TestInsertBatch(t *testing.T) { 208 209 cfgFile := "./mysql.dev.yaml" 210 config := mysql_.NewConfig(mysql_.WithViper(viper_.GetViper(cfgFile, "database.mysql"))) 211 212 db, err := config.Complete().New(context.Background()) 213 if err != nil { 214 t.Errorf("failed to new config err: %v", err) 215 } 216 217 t.Logf("db: %#v", db) 218 ctx := context.Background() 219 220 tableName := "hetu_zeus_0" 221 query := fmt.Sprintf(`INSERT INTO %s 222 ( 223 group_id, 224 page_id, 225 fea_id, 226 entity_id, 227 feature0, 228 feature1, 229 extend_info 230 ) 231 VALUES ( 232 :group_id_1, 233 :page_id_1, 234 :fea_id_1, 235 :entity_id_1, 236 :feature0_1, 237 :feature1_1, 238 :extend_info_1 239 ), 240 ( 241 :group_id_2, 242 :page_id_2, 243 :fea_id_2, 244 :entity_id_2, 245 :feature0_2, 246 :feature1_2, 247 :extend_info_2 248 ) 249 `, tableName) 250 251 testCases := []struct { 252 TableName string 253 GroupId string 254 Number int64 255 }{ 256 { 257 TableName: "hetu_zeus_0", 258 GroupId: "hetu_image_copyright_prod", 259 Number: 2, 260 }, 261 } 262 263 for _, testCase := range testCases { 264 t.Run(fmt.Sprintf("table[%v]-fieldKey[%v]", testCase.TableName, testCase.GroupId), func(t *testing.T) { 265 266 count := testCase.Number 267 var args []TaskTable 268 269 for count > 0 { 270 arg := TaskTable{ 271 GroupId: testCase.GroupId, 272 PageId: "100", 273 FeaId: uuid.NewString(), 274 EntityId: "200", 275 Feature0: []byte("Feature0"), 276 Feature1: []byte("Feature1"), 277 ExtendInfo: []byte("ExtendInfo"), 278 } 279 args = append(args, arg) 280 count-- 281 } 282 283 tagsValues := map[string]interface{}{ 284 "group_id_1": "group_id_1", 285 "page_id_1": uuid.NewString(), 286 "fea_id_1": uuid.NewString(), 287 "entity_id_1": uuid.NewString(), 288 "feature0_1": "feature0_1", 289 "feature1_1": "feature1_1", 290 "extend_info_1": "extend_info_1", 291 "group_id_2": "group_id_2", 292 "page_id_2": uuid.NewString(), 293 "fea_id_2": uuid.NewString(), 294 "entity_id_2": uuid.NewString(), 295 "feature0_2": "feature0_2", 296 "feature1_2": "feature1_2", 297 "extend_info_2": "extend_info_2", 298 } 299 t.Logf("batch insert %v", tagsValues) 300 301 //_, err = mysql_.ExecContext(ctx, query, tagsValues, nil, db) 302 //_, err = mysql_.ExecContext(ctx, query, []interface{}{tagsValues[0], tagsValues[1]}, nil, db) 303 _, err = mysql_.ExecContext(ctx, query, tagsValues, nil, db) 304 if err != nil { 305 t.Errorf("faild to insert %v, err: %v", tagsValues, err) 306 } 307 308 }) 309 } 310 } 311 312 func TestDeleteBatch(t *testing.T) { 313 314 cfgFile := "./mysql.yaml" 315 config := mysql_.NewConfig(mysql_.WithViper(viper_.GetViper(cfgFile, "database.mysql"))) 316 317 db, err := config.Complete().New(context.Background()) 318 if err != nil { 319 t.Errorf("failed to new config err: %v", err) 320 } 321 322 t.Logf("db: %#v", db) 323 ctx := context.Background() 324 325 testCases := []struct { 326 TableName string 327 GroupId string 328 DeleteField string 329 Batch int64 330 }{ 331 { 332 TableName: "hetu_zeus_0", 333 DeleteField: "group_id", 334 GroupId: "hetu_image_copyright_prod", 335 Batch: 5, 336 }, 337 } 338 339 for _, testCase := range testCases { 340 t.Run(fmt.Sprintf("table[%v]-fieldKey[%v]", testCase.TableName, testCase.GroupId), func(t *testing.T) { 341 342 var count int64 343 arg := &TaskTable{ 344 GroupId: testCase.GroupId, 345 } 346 347 for { 348 query := fmt.Sprintf( 349 `DELETE FROM %s 350 WHERE %s limit %v`, 351 testCase.TableName, 352 mysql_.ConditionWithEqualAnd(testCase.DeleteField), 353 testCase.Batch, 354 ) 355 rows, err := mysql_.ExecContext(ctx, query, arg, nil, db) 356 if err != nil { 357 t.Fatalf("failed to delete %v, current deleted total number: %v, err: %v", arg.GroupId, count, err) 358 } 359 360 count += rows 361 if rows == 0 { 362 t.Logf("finished to delete %v, total number: %v", arg.GroupId, count) 363 break 364 } 365 366 if count%testCase.Batch == 0 { 367 t.Logf("delete number: %v ...", count) 368 } 369 } 370 371 }) 372 } 373 374 }