vitess.io/vitess@v0.16.2/go/test/endtoend/vtgate/queries/dml/insert_test.go (about) 1 /* 2 Copyright 2022 The Vitess Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package dml 18 19 import ( 20 "fmt" 21 "testing" 22 23 "github.com/stretchr/testify/assert" 24 25 "vitess.io/vitess/go/test/endtoend/utils" 26 ) 27 28 func TestSimpleInsertSelect(t *testing.T) { 29 if clusterInstance.HasPartialKeyspaces { 30 t.Skip("test uses multiple keyspaces, test framework only supports partial keyspace testing for a single keyspace") 31 } 32 mcmp, closer := start(t) 33 defer closer() 34 35 mcmp.Exec("insert into s_tbl(id, num) values (1,2),(3,4)") 36 mcmp.Exec("insert into u_tbl(id, num) values (1,2),(3,4)") 37 38 for i, mode := range []string{"oltp", "olap"} { 39 t.Run(mode, func(t *testing.T) { 40 utils.Exec(t, mcmp.VtConn, fmt.Sprintf("set workload = %s", mode)) 41 42 qr := mcmp.Exec(fmt.Sprintf("insert into s_tbl(id, num) select id*%d, num*%d from s_tbl where id < 10", 10+i, 20+i)) 43 assert.EqualValues(t, 2, qr.RowsAffected) 44 qr = mcmp.Exec(fmt.Sprintf("insert into u_tbl(id, num) select id*%d, num*%d from u_tbl where id < 10", 10+i, 20+i)) 45 assert.EqualValues(t, 2, qr.RowsAffected) 46 }) 47 } 48 49 mcmp.AssertMatches(`select id, num from s_tbl order by id`, `[[INT64(1) INT64(2)] [INT64(3) INT64(4)] [INT64(10) INT64(40)] [INT64(11) INT64(42)] [INT64(30) INT64(80)] [INT64(33) INT64(84)]]`) 50 mcmp.AssertMatches(`select id, num from u_tbl order by id`, `[[INT64(1) INT64(2)] [INT64(3) INT64(4)] [INT64(10) INT64(40)] [INT64(11) INT64(42)] [INT64(30) INT64(80)] [INT64(33) INT64(84)]]`) 51 52 utils.AssertMatches(t, mcmp.VtConn, `select num from num_vdx_tbl order by num`, `[[INT64(2)] [INT64(4)] [INT64(40)] [INT64(42)] [INT64(80)] [INT64(84)]]`) 53 } 54 55 func TestFailureInsertSelect(t *testing.T) { 56 if clusterInstance.HasPartialKeyspaces { 57 t.Skip("don't run on partial keyspaces") 58 } 59 mcmp, closer := start(t) 60 defer closer() 61 62 mcmp.Exec("insert into s_tbl(id, num) values (1,2),(3,4)") 63 mcmp.Exec("insert into u_tbl(id, num) values (1,2),(3,4)") 64 65 for _, mode := range []string{"oltp", "olap"} { 66 t.Run(mode, func(t *testing.T) { 67 utils.Exec(t, mcmp.VtConn, fmt.Sprintf("set workload = %s", mode)) 68 69 // primary key same 70 mcmp.AssertContainsError("insert into s_tbl(id, num) select id, num*20 from s_tbl where id = 1", `AlreadyExists desc = Duplicate entry '1' for key`) 71 // lookup key same (does not fail on MySQL as there is no lookup, and we have not put unique contrains on num column) 72 utils.AssertContainsError(t, mcmp.VtConn, "insert into s_tbl(id, num) select id*20, num from s_tbl where id = 1", `lookup.Create: Code: ALREADY_EXISTS`) 73 // mismatch column count 74 mcmp.AssertContainsError("insert into s_tbl(id, num) select 100,200,300", `column count does not match value count at row 1`) 75 mcmp.AssertContainsError("insert into s_tbl(id, num) select 100", `column count does not match value count at row 1`) 76 }) 77 } 78 } 79 80 func TestAutoIncInsertSelect(t *testing.T) { 81 if clusterInstance.HasPartialKeyspaces { 82 t.Skip("test uses multiple keyspaces, test framework only supports partial keyspace testing for a single keyspace") 83 } 84 mcmp, closer := start(t) 85 defer closer() 86 87 // comparison with MySQL ignored in this test as it tests auto increment 88 utils.Exec(t, mcmp.VtConn, "insert into user_tbl(region_id, name) values (1,'A'),(3,'C')") 89 90 tcases := []struct { 91 query string 92 expRowsAffected uint64 93 expInsertID uint64 94 }{{ 95 query: "insert into user_tbl(region_id, name) select region_id, name from user_tbl", 96 expRowsAffected: 2, 97 expInsertID: 3, 98 }, { 99 query: "insert into user_tbl(id, region_id, name) select null, region_id, name from user_tbl where id = 1", 100 expRowsAffected: 1, 101 expInsertID: 5, 102 }, { 103 query: "insert into user_tbl(id, region_id, name) select 100, region_id, name from user_tbl where id = 1", 104 expRowsAffected: 1, 105 expInsertID: 0, 106 }, { 107 // auto-inc column as sharding column 108 query: "insert into auto_tbl(id) select 10 union select null", 109 expRowsAffected: 2, 110 expInsertID: 666, 111 }, { 112 // auto-inc column as sharding column 113 query: "insert into auto_tbl(unq_col) select null", 114 expRowsAffected: 1, 115 expInsertID: 667, 116 }} 117 118 for _, tcase := range tcases { 119 t.Run(tcase.query, func(t *testing.T) { 120 qr := utils.Exec(t, mcmp.VtConn, tcase.query) 121 assert.EqualValues(t, tcase.expRowsAffected, qr.RowsAffected) 122 assert.EqualValues(t, tcase.expInsertID, qr.InsertID) 123 }) 124 } 125 126 utils.AssertMatches(t, mcmp.VtConn, `select id from user_tbl order by id`, `[[INT64(1)] [INT64(2)] [INT64(3)] [INT64(4)] [INT64(5)] [INT64(100)]]`) 127 } 128 129 func TestAutoIncInsertSelectOlapMode(t *testing.T) { 130 if clusterInstance.HasPartialKeyspaces { 131 t.Skip("don't run on partial keyspaces") 132 } 133 mcmp, closer := start(t) 134 defer closer() 135 136 utils.Exec(t, mcmp.VtConn, "set workload = olap") 137 138 // comparison with MySQL ignored in this test as it tests auto increment 139 utils.Exec(t, mcmp.VtConn, "insert into user_tbl(region_id, name) values (1,'A'),(3,'C')") 140 141 tcases := []struct { 142 query string 143 expRowsAffected uint64 144 expInsertID uint64 145 }{{ 146 query: "insert into user_tbl(region_id, name) select region_id, name from user_tbl", 147 expRowsAffected: 2, 148 expInsertID: 8, 149 }, { 150 query: "insert into user_tbl(id, region_id, name) select null, region_id, name from user_tbl where id = 8", 151 expRowsAffected: 1, 152 expInsertID: 10, 153 }, { 154 query: "insert into user_tbl(id, region_id, name) select 100, region_id, name from user_tbl where id = 8", 155 expRowsAffected: 1, 156 expInsertID: 0, 157 }, { 158 // auto-inc column as sharding column 159 query: "insert into auto_tbl(id) select 10 union select null", 160 expRowsAffected: 2, 161 expInsertID: 668, 162 }, { 163 // auto-inc column as sharding column 164 query: "insert into auto_tbl(unq_col) select null", 165 expRowsAffected: 1, 166 expInsertID: 669, 167 }} 168 169 for _, tcase := range tcases { 170 t.Run(tcase.query, func(t *testing.T) { 171 qr := utils.Exec(t, mcmp.VtConn, tcase.query) 172 assert.EqualValues(t, tcase.expRowsAffected, qr.RowsAffected) 173 assert.EqualValues(t, tcase.expInsertID, qr.InsertID) 174 }) 175 } 176 177 utils.AssertMatches(t, mcmp.VtConn, `select id from user_tbl order by id`, `[[INT64(6)] [INT64(7)] [INT64(8)] [INT64(9)] [INT64(10)] [INT64(100)]]`) 178 } 179 180 func TestUnownedVindexInsertSelect(t *testing.T) { 181 if clusterInstance.HasPartialKeyspaces { 182 t.Skip("test uses multiple keyspaces, test framework only supports partial keyspace testing for a single keyspace") 183 } 184 mcmp, closer := start(t) 185 defer closer() 186 187 utils.Exec(t, mcmp.VtConn, "insert into order_tbl(oid, region_id) values (100,1),(300,2),(600,3),(700,4)") 188 189 qr := utils.Exec(t, mcmp.VtConn, "insert into oevent_tbl(oid, ename) select oid, 'dispatched' from order_tbl") 190 assert.EqualValues(t, 4, qr.RowsAffected) 191 192 utils.Exec(t, mcmp.VtConn, "use `sks/-80`") 193 qr = utils.Exec(t, mcmp.VtConn, `select count(*) from order_tbl o join oevent_tbl oe on o.oid = oe.oid`) 194 assert.Equal(t, `[[INT64(3)]]`, fmt.Sprintf("%v", qr.Rows)) 195 utils.Exec(t, mcmp.VtConn, "use `sks/80-`") 196 qr = utils.Exec(t, mcmp.VtConn, `select count(*) from order_tbl o join oevent_tbl oe on o.oid = oe.oid`) 197 assert.Equal(t, `[[INT64(1)]]`, fmt.Sprintf("%v", qr.Rows)) 198 199 // resetting the target 200 utils.Exec(t, mcmp.VtConn, "use `sks`") 201 202 // inserting non-existing record in oevent_tbl. 203 utils.AssertContainsError(t, mcmp.VtConn, "insert into oevent_tbl(oid, ename) select 1000, 'dispatched'", `could not map [INT64(1000)] to a keyspace id`) 204 205 // id is the sharding column, oid is unknowned lookup which points to region_id, 206 // the verify step should pass as we are inserting the same region_id to id 207 qr = utils.Exec(t, mcmp.VtConn, "insert into oextra_tbl(id, oid) select region_id, oid from order_tbl") 208 assert.EqualValues(t, 4, qr.RowsAffected) 209 210 // mismatch value, verify step will fail. oid 100 is mapped to region_id 1, in this test trying to insert 100 with 2. 211 utils.AssertContainsError(t, mcmp.VtConn, "insert into oextra_tbl(id, oid) select 2, 100", `values [[INT64(100)]] for column [oid] does not map to keyspace ids`) 212 213 // null to oid is allowed so verify ksids will ignore it. 214 utils.Exec(t, mcmp.VtConn, "insert into oextra_tbl(id, oid) select 5, null") 215 } 216 217 func TestUnownedVindexInsertSelectOlapMode(t *testing.T) { 218 if clusterInstance.HasPartialKeyspaces { 219 t.Skip("don't run on partial keyspaces") 220 } 221 mcmp, closer := start(t) 222 defer closer() 223 224 utils.Exec(t, mcmp.VtConn, "set workload = olap") 225 226 utils.Exec(t, mcmp.VtConn, "insert into order_tbl(oid, region_id) values (100,1),(300,2),(600,3),(700,4)") 227 228 qr := utils.Exec(t, mcmp.VtConn, "insert into oevent_tbl(oid, ename) select oid, 'dispatched' from order_tbl") 229 assert.EqualValues(t, 4, qr.RowsAffected) 230 231 utils.Exec(t, mcmp.VtConn, "use `sks/-80`") 232 utils.AssertMatches(t, mcmp.VtConn, `select count(*) from order_tbl o join oevent_tbl oe on o.oid = oe.oid`, `[[INT64(3)]]`) 233 utils.Exec(t, mcmp.VtConn, "use `sks/80-`") 234 utils.AssertMatches(t, mcmp.VtConn, `select count(*) from order_tbl o join oevent_tbl oe on o.oid = oe.oid`, `[[INT64(1)]]`) 235 236 // resetting the target 237 utils.Exec(t, mcmp.VtConn, "use `sks`") 238 239 // inserting non-existing record in oevent_tbl. 240 utils.AssertContainsError(t, mcmp.VtConn, "insert into oevent_tbl(oid, ename) select 1000, 'dispatched'", `could not map [INT64(1000)] to a keyspace id`) 241 242 // id is the sharding column, oid is unknowned lookup which points to region_id, 243 // the verify step should pass as we are inserting the same region_id to id 244 qr = utils.Exec(t, mcmp.VtConn, "insert into oextra_tbl(id, oid) select region_id, oid from order_tbl") 245 assert.EqualValues(t, 4, qr.RowsAffected) 246 247 // mismatch value, verify step will fail. oid 100 is mapped to region_id 1, in this test trying to insert 100 with 2. 248 utils.AssertContainsError(t, mcmp.VtConn, "insert into oextra_tbl(id, oid) select 2, 100", `values [[INT64(100)]] for column [oid] does not map to keyspace ids`) 249 250 // null to oid is allowed so verify ksids will ignore it. 251 utils.Exec(t, mcmp.VtConn, "insert into oextra_tbl(id, oid) select 5, null") 252 } 253 254 func TestLookupCasesIncInsertSelect(t *testing.T) { 255 mcmp, closer := start(t) 256 defer closer() 257 258 // all lookup vdx cols present 259 mcmp.Exec("insert into auto_tbl(id, unq_col, nonunq_col) select 1,2,3") 260 // unique lookup vdx cols present 261 mcmp.Exec("insert into auto_tbl(id, nonunq_col) select 2,3") 262 // non-unique lookup vdx cols present 263 mcmp.Exec("insert into auto_tbl(id, unq_col) select 3,3") 264 265 mcmp.AssertMatches(`select id, unq_col, nonunq_col from auto_tbl order by id`, 266 `[[INT64(1) INT64(2) INT64(3)] [INT64(2) NULL INT64(3)] [INT64(3) INT64(3) NULL]]`) 267 utils.AssertMatches(t, mcmp.VtConn, `select unq_col from unq_idx order by unq_col`, 268 `[[INT64(2)] [INT64(3)]]`) 269 utils.AssertMatches(t, mcmp.VtConn, `select nonunq_col, id from nonunq_idx order by nonunq_col, id`, 270 `[[INT64(3) INT64(1)] [INT64(3) INT64(2)]]`) 271 } 272 273 func TestLookupCasesIncInsertSelectOlapMode(t *testing.T) { 274 mcmp, closer := start(t) 275 defer closer() 276 277 utils.Exec(t, mcmp.VtConn, "set workload = olap") 278 279 // all lookup vdx cols present 280 mcmp.Exec("insert into auto_tbl(id, unq_col, nonunq_col) select 1,2,3") 281 // unique lookup vdx cols present 282 mcmp.Exec("insert into auto_tbl(id, nonunq_col) select 2,3") 283 // non-unique lookup vdx cols present 284 mcmp.Exec("insert into auto_tbl(id, unq_col) select 3,3") 285 286 mcmp.AssertMatches(`select id, unq_col, nonunq_col from auto_tbl order by id`, 287 `[[INT64(1) INT64(2) INT64(3)] [INT64(2) NULL INT64(3)] [INT64(3) INT64(3) NULL]]`) 288 utils.AssertMatches(t, mcmp.VtConn, `select unq_col from unq_idx order by unq_col`, 289 `[[INT64(2)] [INT64(3)]]`) 290 utils.AssertMatches(t, mcmp.VtConn, `select nonunq_col, id from nonunq_idx order by nonunq_col, id`, 291 `[[INT64(3) INT64(1)] [INT64(3) INT64(2)]]`) 292 } 293 294 func TestIgnoreInsertSelect(t *testing.T) { 295 mcmp, closer := start(t) 296 defer closer() 297 298 mcmp.Exec("insert into order_tbl(region_id, oid, cust_no) values (1,1,100),(1,2,200),(1,3,300)") 299 300 // inserting same rows, throws error. 301 mcmp.AssertContainsError("insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl", `lookup.Create: Code: ALREADY_EXISTS`) 302 // inserting same rows with ignore 303 qr := mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl") 304 assert.EqualValues(t, 0, qr.RowsAffected) 305 mcmp.AssertMatches("select count(*) from order_tbl", `[[INT64(3)]]`) 306 307 // inserting row with ignore with cust_no non-unique 308 qr = mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select 1, 4, 100 from order_tbl") 309 assert.EqualValues(t, 0, qr.RowsAffected) 310 311 // inserting row with ignore with cust_no unique 312 qr = mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select 1, 4, 400 from order_tbl") 313 assert.EqualValues(t, 1, qr.RowsAffected) 314 mcmp.AssertMatches("select count(*) from order_tbl", `[[INT64(4)]]`) 315 316 mcmp.AssertMatches("select oid, cust_no from order_tbl where region_id = 1 order by oid", `[[INT64(1) INT64(100)] [INT64(2) INT64(200)] [INT64(3) INT64(300)] [INT64(4) INT64(400)]]`) 317 318 // inserting row with on dup with cust_no non-unique 319 qr = utils.Exec(t, mcmp.VtConn, "insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl where oid = 4 on duplicate key update cust_no = cust_no + 1") 320 assert.EqualValues(t, 2, qr.RowsAffected) 321 utils.AssertMatches(t, mcmp.VtConn, "select count(*) from order_tbl", `[[INT64(4)]]`) 322 323 utils.AssertMatches(t, mcmp.VtConn, "select oid, cust_no from order_tbl order by oid", `[[INT64(1) INT64(100)] [INT64(2) INT64(200)] [INT64(3) INT64(300)] [INT64(4) INT64(401)]]`) 324 325 // inserting on dup trying to update vindex throws error. 326 utils.AssertContainsError(t, mcmp.VtConn, "insert into order_tbl(region_id, oid, cust_no) select 1, 10, 1000 on duplicate key update region_id = region_id + 1", `unsupported: DML cannot update vindex column`) 327 utils.AssertContainsError(t, mcmp.VtConn, "insert into order_tbl(region_id, oid, cust_no) select 1, 10, 1000 on duplicate key update oid = oid + 100", `unsupported: DML cannot update vindex column`) 328 } 329 330 func TestIgnoreInsertSelectOlapMode(t *testing.T) { 331 mcmp, closer := start(t) 332 defer closer() 333 334 utils.Exec(t, mcmp.VtConn, "set workload = olap") 335 336 mcmp.Exec("insert into order_tbl(region_id, oid, cust_no) values (1,1,100),(1,2,200),(1,3,300)") 337 338 // inserting same rows, throws error. 339 mcmp.AssertContainsError("insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl", `lookup.Create: Code: ALREADY_EXISTS`) 340 // inserting same rows with ignore 341 qr := mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl") 342 assert.EqualValues(t, 0, qr.RowsAffected) 343 mcmp.AssertMatches("select count(*) from order_tbl", `[[INT64(3)]]`) 344 345 // inserting row with ignore with cust_no non-unique 346 qr = mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select 1, 4, 100 from order_tbl") 347 assert.EqualValues(t, 0, qr.RowsAffected) 348 349 // inserting row with ignore with cust_no unique 350 qr = mcmp.Exec("insert ignore into order_tbl(region_id, oid, cust_no) select 1, 4, 400 from order_tbl") 351 assert.EqualValues(t, 1, qr.RowsAffected) 352 mcmp.AssertMatches("select count(*) from order_tbl", `[[INT64(4)]]`) 353 354 mcmp.AssertMatches("select oid, cust_no from order_tbl where region_id = 1 order by oid", `[[INT64(1) INT64(100)] [INT64(2) INT64(200)] [INT64(3) INT64(300)] [INT64(4) INT64(400)]]`) 355 356 // inserting row with on dup with cust_no non-unique 357 qr = utils.Exec(t, mcmp.VtConn, "insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl where oid = 4 on duplicate key update cust_no = cust_no + 1") 358 assert.EqualValues(t, 2, qr.RowsAffected) 359 utils.AssertMatches(t, mcmp.VtConn, "select count(*) from order_tbl", `[[INT64(4)]]`) 360 361 utils.AssertMatches(t, mcmp.VtConn, "select oid, cust_no from order_tbl order by oid", `[[INT64(1) INT64(100)] [INT64(2) INT64(200)] [INT64(3) INT64(300)] [INT64(4) INT64(401)]]`) 362 363 // inserting on dup trying to update vindex throws error. 364 utils.AssertContainsError(t, mcmp.VtConn, "insert into order_tbl(region_id, oid, cust_no) select 1, 10, 1000 on duplicate key update region_id = region_id + 1", `unsupported: DML cannot update vindex column`) 365 utils.AssertContainsError(t, mcmp.VtConn, "insert into order_tbl(region_id, oid, cust_no) select 1, 10, 1000 on duplicate key update oid = oid + 100", `unsupported: DML cannot update vindex column`) 366 } 367 368 func TestInsertSelectUnshardedUsingSharded(t *testing.T) { 369 if clusterInstance.HasPartialKeyspaces { 370 t.Skip("test uses multiple keyspaces, test framework only supports partial keyspace testing for a single keyspace") 371 } 372 mcmp, closer := start(t) 373 defer closer() 374 375 mcmp.Exec("insert into s_tbl(id, num) values (1,2),(3,4)") 376 377 for _, mode := range []string{"oltp", "olap"} { 378 t.Run(mode, func(t *testing.T) { 379 utils.Exec(t, mcmp.VtConn, fmt.Sprintf("set workload = %s", mode)) 380 qr := mcmp.Exec("insert into u_tbl(id, num) select id, num from s_tbl where s_tbl.id in (1,3)") 381 assert.EqualValues(t, 2, qr.RowsAffected) 382 mcmp.AssertMatches(`select id, num from u_tbl order by id`, `[[INT64(1) INT64(2)] [INT64(3) INT64(4)]]`) 383 mcmp.Exec(`delete from u_tbl`) 384 }) 385 } 386 } 387 388 func TestRedactDupError(t *testing.T) { 389 mcmp, closer := start(t) 390 defer closer() 391 392 mcmp.Exec("insert into order_tbl(region_id, oid, cust_no) values (1,1,100),(1,2,200),(1,3,300)") 393 394 // inserting same rows, throws error. 395 mcmp.AssertContainsError("insert into order_tbl(region_id, oid, cust_no) select region_id, oid, cust_no from order_tbl", `BindVars: {REDACTED}`) 396 }