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 }