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  }