github.com/XiaoMi/Gaea@v1.2.5/proxy/plan/plan_update_test.go (about)

     1  // Copyright 2019 The Gaea Authors. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plan
    16  
    17  import "testing"
    18  
    19  func TestMycatShardSimpleUpdate(t *testing.T) {
    20  	ns, err := preparePlanInfo()
    21  	if err != nil {
    22  		t.Fatalf("prepare namespace error: %v", err)
    23  	}
    24  
    25  	tests := []SQLTestcase{
    26  		{
    27  			db:  "db_mycat",
    28  			sql: "update tbl_mycat set a = 'hi'",
    29  			sqls: map[string]map[string][]string{
    30  				"slice-0": {
    31  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi'"},
    32  					"db_mycat_1": {"UPDATE `tbl_mycat` SET `a`='hi'"},
    33  				},
    34  				"slice-1": {
    35  					"db_mycat_2": {"UPDATE `tbl_mycat` SET `a`='hi'"},
    36  					"db_mycat_3": {"UPDATE `tbl_mycat` SET `a`='hi'"},
    37  				},
    38  			},
    39  		},
    40  		{
    41  			db:     "db_mycat",
    42  			sql:    "update tbl_mycat set id = 5",
    43  			hasErr: true, // cannot update shard column value
    44  		},
    45  		{
    46  			db:     "db_mycat",
    47  			sql:    "update tbl_mycat set ID = 5",
    48  			hasErr: true, // cannot update shard column value
    49  		},
    50  		{
    51  			db:  "db_mycat",
    52  			sql: "update tbl_mycat set a = 'hi' where ID = 5",
    53  			sqls: map[string]map[string][]string{
    54  				"slice-0": {
    55  					"db_mycat_1": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `ID`=5"},
    56  				},
    57  			},
    58  		},
    59  		{
    60  			db:     "db_mycat",
    61  			sql:    "update tbl_mycat, tbl_mycat_child set id = 5",
    62  			hasErr: true, // does not support update multiple tables in sharding
    63  		},
    64  	}
    65  	for _, test := range tests {
    66  		t.Run(test.sql, getTestFunc(ns, test))
    67  	}
    68  }
    69  
    70  func TestMycatShardUpdateColumnCaseInsensitive(t *testing.T) {
    71  	ns, err := preparePlanInfo()
    72  	if err != nil {
    73  		t.Fatalf("prepare namespace error: %v", err)
    74  	}
    75  
    76  	tests := []SQLTestcase{
    77  		{
    78  			db:     "db_mycat",
    79  			sql:    "update tbl_mycat set ID = 5",
    80  			hasErr: true, // cannot update shard column value
    81  		},
    82  		{
    83  			db:  "db_mycat",
    84  			sql: "update tbl_mycat set a = 'hi' where ID = 5",
    85  			sqls: map[string]map[string][]string{
    86  				"slice-0": {
    87  					"db_mycat_1": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `ID`=5"},
    88  				},
    89  			},
    90  		},
    91  	}
    92  	for _, test := range tests {
    93  		t.Run(test.sql, getTestFunc(ns, test))
    94  	}
    95  }
    96  
    97  func TestMycatShardUpdateWithWhere(t *testing.T) {
    98  	ns, err := preparePlanInfo()
    99  	if err != nil {
   100  		t.Fatalf("prepare namespace error: %v", err)
   101  	}
   102  
   103  	tests := []SQLTestcase{
   104  		{
   105  			db:  "db_mycat",
   106  			sql: "update tbl_mycat set a = 'hi' where id = 0",
   107  			sqls: map[string]map[string][]string{
   108  				"slice-0": {
   109  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=0"},
   110  				},
   111  			},
   112  		},
   113  		{
   114  			db:  "db_mycat",
   115  			sql: "update tbl_mycat set a = 'hi' where id = 1",
   116  			sqls: map[string]map[string][]string{
   117  				"slice-0": {
   118  					"db_mycat_1": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=1"},
   119  				},
   120  			},
   121  		},
   122  		{
   123  			db:  "db_mycat",
   124  			sql: "update tbl_mycat set a = 'hi' where id = 2",
   125  			sqls: map[string]map[string][]string{
   126  				"slice-1": {
   127  					"db_mycat_2": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=2"},
   128  				},
   129  			},
   130  		},
   131  		{
   132  			db:  "db_mycat",
   133  			sql: "update tbl_mycat set a = 'hi' where id = 3",
   134  			sqls: map[string]map[string][]string{
   135  				"slice-1": {
   136  					"db_mycat_3": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=3"},
   137  				},
   138  			},
   139  		},
   140  		{
   141  			db:  "db_mycat",
   142  			sql: "update tbl_mycat set a = 'hi' where id = 4",
   143  			sqls: map[string]map[string][]string{
   144  				"slice-0": {
   145  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=4"},
   146  				},
   147  			},
   148  		},
   149  		{
   150  			db:  "db_mycat",
   151  			sql: "update tbl_mycat set a = 'hi' where id = 6",
   152  			sqls: map[string]map[string][]string{
   153  				"slice-1": {
   154  					"db_mycat_2": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=6"},
   155  				},
   156  			},
   157  		},
   158  		{
   159  			db:  "db_mycat",
   160  			sql: "update tbl_mycat set tbl_mycat.a = 'hi' where tbl_mycat.id = 6",
   161  			sqls: map[string]map[string][]string{
   162  				"slice-1": {
   163  					"db_mycat_2": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `tbl_mycat`.`id`=6"}, // table name in assignment is removed
   164  				},
   165  			},
   166  		},
   167  		{
   168  			db:  "db_mycat",
   169  			sql: "update tbl_mycat set db_mycat.tbl_mycat.a = 'hi' where db_mycat.tbl_mycat.id = 6",
   170  			sqls: map[string]map[string][]string{
   171  				"slice-1": {
   172  					"db_mycat_2": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `db_mycat_2`.`tbl_mycat`.`id`=6"}, // db name in assignment is removed
   173  				},
   174  			},
   175  		},
   176  		{
   177  			db:  "db_mycat",
   178  			sql: "update tbl_mycat set a = 'hi' where id in (1,3,5)",
   179  			sqls: map[string]map[string][]string{
   180  				"slice-0": {
   181  					"db_mycat_1": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id` IN (1,5)"},
   182  				},
   183  				"slice-1": {
   184  					"db_mycat_3": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id` IN (3)"},
   185  				},
   186  			},
   187  		},
   188  		{
   189  			db:     "db_mycat",
   190  			sql:    "update tbl_mycat set id = 5 where id = 6",
   191  			hasErr: true,
   192  		},
   193  	}
   194  	for _, test := range tests {
   195  		t.Run(test.sql, getTestFunc(ns, test))
   196  	}
   197  }
   198  
   199  func TestMycatShardUpdateWithOrderBy(t *testing.T) {
   200  	ns, err := preparePlanInfo()
   201  	if err != nil {
   202  		t.Fatalf("prepare namespace error: %v", err)
   203  	}
   204  
   205  	tests := []SQLTestcase{
   206  		{
   207  			db:  "db_mycat",
   208  			sql: "update tbl_mycat set a = 'hi' order by id",
   209  			sqls: map[string]map[string][]string{
   210  				"slice-0": {
   211  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' ORDER BY `id`"},
   212  					"db_mycat_1": {"UPDATE `tbl_mycat` SET `a`='hi' ORDER BY `id`"},
   213  				},
   214  				"slice-1": {
   215  					"db_mycat_2": {"UPDATE `tbl_mycat` SET `a`='hi' ORDER BY `id`"},
   216  					"db_mycat_3": {"UPDATE `tbl_mycat` SET `a`='hi' ORDER BY `id`"},
   217  				},
   218  			},
   219  		},
   220  		{
   221  			db:  "db_mycat",
   222  			sql: "update tbl_mycat set a = 'hi' where id = 0 order by id",
   223  			sqls: map[string]map[string][]string{
   224  				"slice-0": {
   225  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=0 ORDER BY `id`"},
   226  				},
   227  			},
   228  		},
   229  		{
   230  			db:  "db_mycat",
   231  			sql: "update tbl_mycat set a = 'hi' where id = 0 order by db_mycat.tbl_mycat.id",
   232  			sqls: map[string]map[string][]string{
   233  				"slice-0": {
   234  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=0 ORDER BY `db_mycat_0`.`tbl_mycat`.`id`"},
   235  				},
   236  			},
   237  		},
   238  		{
   239  			db:  "db_mycat",
   240  			sql: "update tbl_mycat set a = 'hi' where id = 0 order by a",
   241  			sqls: map[string]map[string][]string{
   242  				"slice-0": {
   243  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=0 ORDER BY `a`"},
   244  				},
   245  			},
   246  		},
   247  		{
   248  			db:  "db_mycat",
   249  			sql: "update tbl_mycat set a = 'hi' where id = 0 order by id desc",
   250  			sqls: map[string]map[string][]string{
   251  				"slice-0": {
   252  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' WHERE `id`=0 ORDER BY `id` DESC"},
   253  				},
   254  			},
   255  		},
   256  	}
   257  	for _, test := range tests {
   258  		t.Run(test.sql, getTestFunc(ns, test))
   259  	}
   260  }
   261  
   262  func TestMycatShardUpdateWithLimit(t *testing.T) {
   263  	ns, err := preparePlanInfo()
   264  	if err != nil {
   265  		t.Fatalf("prepare namespace error: %v", err)
   266  	}
   267  
   268  	tests := []SQLTestcase{
   269  		{
   270  			db:  "db_mycat",
   271  			sql: "update tbl_mycat set a = 'hi' limit 10",
   272  			sqls: map[string]map[string][]string{
   273  				"slice-0": {
   274  					"db_mycat_0": {"UPDATE `tbl_mycat` SET `a`='hi' LIMIT 10"},
   275  					"db_mycat_1": {"UPDATE `tbl_mycat` SET `a`='hi' LIMIT 10"},
   276  				},
   277  				"slice-1": {
   278  					"db_mycat_2": {"UPDATE `tbl_mycat` SET `a`='hi' LIMIT 10"},
   279  					"db_mycat_3": {"UPDATE `tbl_mycat` SET `a`='hi' LIMIT 10"},
   280  				},
   281  			},
   282  		},
   283  		{
   284  			db:     "db_mycat",
   285  			sql:    "update tbl_mycat set a = 'hi' limit 0, 10",
   286  			hasErr: true, // parse sql error: line 1 column 45 near "offset 0"
   287  		},
   288  		{
   289  			db:     "db_mycat",
   290  			sql:    "update tbl_mycat set a = 'hi' limit 10 offset 20",
   291  			hasErr: true, // parse sql error: line 1 column 45 near "offset 20"
   292  		},
   293  	}
   294  	for _, test := range tests {
   295  		t.Run(test.sql, getTestFunc(ns, test))
   296  	}
   297  }
   298  
   299  func TestGlobalTableUpdate(t *testing.T) {
   300  	ns, err := preparePlanInfo()
   301  	if err != nil {
   302  		t.Fatalf("prepare namespace error: %v", err)
   303  	}
   304  
   305  	tests := []SQLTestcase{
   306  		{
   307  			db:  "db_mycat",
   308  			sql: "update tbl_mycat_global_one set a = 'hi' limit 10",
   309  			sqls: map[string]map[string][]string{
   310  				"slice-0": {
   311  					"db_mycat_0": {"UPDATE `tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   312  					"db_mycat_1": {"UPDATE `tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   313  				},
   314  				"slice-1": {
   315  					"db_mycat_2": {"UPDATE `tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   316  					"db_mycat_3": {"UPDATE `tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   317  				},
   318  			},
   319  		},
   320  		{
   321  			db:  "db_mycat",
   322  			sql: "update db_mycat.tbl_mycat_global_one set db_mycat.tbl_mycat_global_one.a = 'hi' limit 10",
   323  			sqls: map[string]map[string][]string{
   324  				"slice-0": {
   325  					"db_mycat_0": {"UPDATE `db_mycat_0`.`tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   326  					"db_mycat_1": {"UPDATE `db_mycat_1`.`tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   327  				},
   328  				"slice-1": {
   329  					"db_mycat_2": {"UPDATE `db_mycat_2`.`tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   330  					"db_mycat_3": {"UPDATE `db_mycat_3`.`tbl_mycat_global_one` SET `a`='hi' LIMIT 10"},
   331  				},
   332  			},
   333  		},
   334  		{
   335  			db:     "db_mycat",
   336  			sql:    "update tbl_mycat_global_one set a = 'hi' limit 0, 10",
   337  			hasErr: true, // parse sql error: line 1 column 45 near "offset 0"
   338  		},
   339  		{
   340  			db:     "db_mycat",
   341  			sql:    "update tbl_mycat_global_one set a = 'hi' limit 10 offset 20",
   342  			hasErr: true, // parse sql error: line 1 column 45 near "offset 20"
   343  		},
   344  	}
   345  	for _, test := range tests {
   346  		t.Run(test.sql, getTestFunc(ns, test))
   347  	}
   348  }