vitess.io/vitess@v0.16.2/go/vt/vtgate/engine/insert_test.go (about) 1 /* 2 Copyright 2019 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 engine 18 19 import ( 20 "context" 21 "errors" 22 "testing" 23 24 topodatapb "vitess.io/vitess/go/vt/proto/topodata" 25 26 "vitess.io/vitess/go/vt/vtgate/evalengine" 27 28 "github.com/stretchr/testify/require" 29 30 "vitess.io/vitess/go/sqltypes" 31 "vitess.io/vitess/go/vt/vtgate/vindexes" 32 33 querypb "vitess.io/vitess/go/vt/proto/query" 34 vschemapb "vitess.io/vitess/go/vt/proto/vschema" 35 ) 36 37 func TestInsertUnsharded(t *testing.T) { 38 ins := NewQueryInsert( 39 InsertUnsharded, 40 &vindexes.Keyspace{ 41 Name: "ks", 42 Sharded: false, 43 }, 44 "dummy_insert", 45 ) 46 47 vc := newDMLTestVCursor("0") 48 vc.results = []*sqltypes.Result{{ 49 InsertID: 4, 50 }} 51 52 result, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 53 if err != nil { 54 t.Fatal(err) 55 } 56 vc.ExpectLog(t, []string{ 57 `ResolveDestinations ks [] Destinations:DestinationAllShards()`, 58 `ExecuteMultiShard ks.0: dummy_insert {} true true`, 59 }) 60 expectResult(t, "Execute", result, &sqltypes.Result{InsertID: 4}) 61 62 // Failure cases 63 vc = &loggingVCursor{shardErr: errors.New("shard_error")} 64 _, err = ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 65 require.EqualError(t, err, `shard_error`) 66 67 vc = &loggingVCursor{} 68 _, err = ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 69 require.EqualError(t, err, `Keyspace does not have exactly one shard: []`) 70 } 71 72 func TestInsertUnshardedGenerate(t *testing.T) { 73 ins := NewQueryInsert( 74 InsertUnsharded, 75 &vindexes.Keyspace{ 76 Name: "ks", 77 Sharded: false, 78 }, 79 "dummy_insert", 80 ) 81 ins.Generate = &Generate{ 82 Keyspace: &vindexes.Keyspace{ 83 Name: "ks2", 84 Sharded: false, 85 }, 86 Query: "dummy_generate", 87 Values: evalengine.NewTupleExpr( 88 evalengine.NewLiteralInt(1), 89 evalengine.NullExpr, 90 evalengine.NewLiteralInt(2), 91 evalengine.NullExpr, 92 evalengine.NewLiteralInt(3), 93 ), 94 } 95 96 vc := newDMLTestVCursor("0") 97 vc.results = []*sqltypes.Result{ 98 sqltypes.MakeTestResult( 99 sqltypes.MakeTestFields( 100 "nextval", 101 "int64", 102 ), 103 "4", 104 ), 105 {InsertID: 1}, 106 } 107 108 result, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 109 if err != nil { 110 t.Fatal(err) 111 } 112 vc.ExpectLog(t, []string{ 113 // Fetch two sequence value. 114 `ResolveDestinations ks2 [] Destinations:DestinationAnyShard()`, 115 `ExecuteStandalone dummy_generate n: type:INT64 value:"2" ks2 0`, 116 // Fill those values into the insert. 117 `ResolveDestinations ks [] Destinations:DestinationAllShards()`, 118 `ExecuteMultiShard ks.0: dummy_insert {__seq0: type:INT64 value:"1" __seq1: type:INT64 value:"4" __seq2: type:INT64 value:"2" __seq3: type:INT64 value:"5" __seq4: type:INT64 value:"3"} true true`, 119 }) 120 121 // The insert id returned by ExecuteMultiShard should be overwritten by processGenerateFromValues. 122 expectResult(t, "Execute", result, &sqltypes.Result{InsertID: 4}) 123 } 124 125 func TestInsertUnshardedGenerate_Zeros(t *testing.T) { 126 ins := NewQueryInsert( 127 InsertUnsharded, 128 &vindexes.Keyspace{ 129 Name: "ks", 130 Sharded: false, 131 }, 132 "dummy_insert", 133 ) 134 ins.Generate = &Generate{ 135 Keyspace: &vindexes.Keyspace{ 136 Name: "ks2", 137 Sharded: false, 138 }, 139 Query: "dummy_generate", 140 Values: evalengine.NewTupleExpr( 141 evalengine.NewLiteralInt(1), 142 evalengine.NewLiteralInt(0), 143 evalengine.NewLiteralInt(2), 144 evalengine.NewLiteralInt(0), 145 evalengine.NewLiteralInt(3), 146 ), 147 } 148 149 vc := newDMLTestVCursor("0") 150 vc.results = []*sqltypes.Result{ 151 sqltypes.MakeTestResult( 152 sqltypes.MakeTestFields( 153 "nextval", 154 "int64", 155 ), 156 "4", 157 ), 158 {InsertID: 1}, 159 } 160 161 result, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 162 if err != nil { 163 t.Fatal(err) 164 } 165 vc.ExpectLog(t, []string{ 166 // Fetch two sequence value. 167 `ResolveDestinations ks2 [] Destinations:DestinationAnyShard()`, 168 `ExecuteStandalone dummy_generate n: type:INT64 value:"2" ks2 0`, 169 // Fill those values into the insert. 170 `ResolveDestinations ks [] Destinations:DestinationAllShards()`, 171 `ExecuteMultiShard ks.0: dummy_insert {__seq0: type:INT64 value:"1" __seq1: type:INT64 value:"4" __seq2: type:INT64 value:"2" __seq3: type:INT64 value:"5" __seq4: type:INT64 value:"3"} true true`, 172 }) 173 174 // The insert id returned by ExecuteMultiShard should be overwritten by processGenerateFromValues. 175 expectResult(t, "Execute", result, &sqltypes.Result{InsertID: 4}) 176 } 177 178 func TestInsertShardedSimple(t *testing.T) { 179 invschema := &vschemapb.SrvVSchema{ 180 Keyspaces: map[string]*vschemapb.Keyspace{ 181 "sharded": { 182 Sharded: true, 183 Vindexes: map[string]*vschemapb.Vindex{ 184 "hash": { 185 Type: "hash", 186 }, 187 }, 188 Tables: map[string]*vschemapb.Table{ 189 "t1": { 190 ColumnVindexes: []*vschemapb.ColumnVindex{{ 191 Name: "hash", 192 Columns: []string{"id"}, 193 }}, 194 }, 195 }, 196 }, 197 }, 198 } 199 vs := vindexes.BuildVSchema(invschema) 200 ks := vs.Keyspaces["sharded"] 201 202 // A single row insert should be autocommitted 203 ins := NewInsert( 204 InsertSharded, 205 false, 206 ks.Keyspace, 207 [][][]evalengine.Expr{{ 208 // colVindex columns: id 209 { 210 evalengine.NewLiteralInt(1), 211 }, 212 }}, 213 ks.Tables["t1"], 214 "prefix", 215 []string{" mid1"}, 216 " suffix", 217 ) 218 vc := newDMLTestVCursor("-20", "20-") 219 vc.shardForKsid = []string{"20-", "-20", "20-"} 220 221 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 222 if err != nil { 223 t.Fatal(err) 224 } 225 vc.ExpectLog(t, []string{ 226 // Based on shardForKsid, values returned will be 20-. 227 `ResolveDestinations sharded [value:"0"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, 228 // Row 2 will go to -20, rows 1 & 3 will go to 20- 229 `ExecuteMultiShard ` + 230 `sharded.20-: prefix mid1 suffix {_id_0: type:INT64 value:"1"} ` + 231 `true true`, 232 }) 233 234 // Multiple rows are not autocommitted by default 235 ins = NewInsert( 236 InsertSharded, 237 false, 238 ks.Keyspace, 239 [][][]evalengine.Expr{{ 240 // colVindex columns: id 241 // 3 rows. 242 { 243 evalengine.NewLiteralInt(1), 244 evalengine.NewLiteralInt(2), 245 evalengine.NewLiteralInt(3), 246 }, 247 }}, 248 ks.Tables["t1"], 249 "prefix", 250 []string{" mid1", " mid2", " mid3"}, 251 " suffix", 252 ) 253 vc = newDMLTestVCursor("-20", "20-") 254 vc.shardForKsid = []string{"20-", "-20", "20-"} 255 256 _, err = ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 257 if err != nil { 258 t.Fatal(err) 259 } 260 vc.ExpectLog(t, []string{ 261 // Based on shardForKsid, values returned will be 20-, -20, 20-. 262 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 263 // Row 2 will go to -20, rows 1 & 3 will go to 20- 264 `ExecuteMultiShard ` + 265 `sharded.20-: prefix mid1, mid3 suffix {_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 266 `sharded.-20: prefix mid2 suffix {_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 267 `true false`, 268 }) 269 270 // Optional flag overrides autocommit 271 ins = NewInsert( 272 InsertSharded, 273 false, 274 ks.Keyspace, 275 [][][]evalengine.Expr{{ 276 // colVindex columns: id 277 // 3 rows. 278 { 279 evalengine.NewLiteralInt(1), 280 evalengine.NewLiteralInt(2), 281 evalengine.NewLiteralInt(3), 282 }, 283 }}, 284 285 ks.Tables["t1"], 286 "prefix", 287 []string{" mid1", " mid2", " mid3"}, 288 " suffix", 289 ) 290 ins.MultiShardAutocommit = true 291 292 vc = newDMLTestVCursor("-20", "20-") 293 vc.shardForKsid = []string{"20-", "-20", "20-"} 294 295 _, err = ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 296 if err != nil { 297 t.Fatal(err) 298 } 299 vc.ExpectLog(t, []string{ 300 // Based on shardForKsid, values returned will be 20-, -20, 20-. 301 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 302 // Row 2 will go to -20, rows 1 & 3 will go to 20- 303 `ExecuteMultiShard ` + 304 `sharded.20-: prefix mid1, mid3 suffix {_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 305 `sharded.-20: prefix mid2 suffix {_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 306 `true true`, 307 }) 308 } 309 310 func TestInsertShardedFail(t *testing.T) { 311 invschema := &vschemapb.SrvVSchema{ 312 Keyspaces: map[string]*vschemapb.Keyspace{ 313 "sharded": { 314 Sharded: true, 315 Vindexes: map[string]*vschemapb.Vindex{ 316 "primary": { 317 Type: "lookup_unique", 318 Params: map[string]string{ 319 "table": "prim", 320 "from": "from1", 321 "to": "toc", 322 }, 323 }, 324 }, 325 Tables: map[string]*vschemapb.Table{ 326 "t1": { 327 ColumnVindexes: []*vschemapb.ColumnVindex{{ 328 Name: "primary", 329 Columns: []string{"id"}, 330 }}, 331 }, 332 }, 333 }, 334 }, 335 } 336 vs := vindexes.BuildVSchema(invschema) 337 ks := vs.Keyspaces["sharded"] 338 339 ins := NewInsert( 340 InsertSharded, 341 false, 342 ks.Keyspace, 343 [][][]evalengine.Expr{{ 344 // colVindex columns: id 345 { 346 evalengine.NewLiteralInt(1), 347 }, 348 }}, 349 350 ks.Tables["t1"], 351 "prefix", 352 []string{" mid1", " mid2", " mid3"}, 353 " suffix", 354 ) 355 356 vc := &loggingVCursor{} 357 358 // The lookup will fail to map to a keyspace id. 359 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 360 require.EqualError(t, err, `could not map [INT64(1)] to a keyspace id`) 361 } 362 363 func TestInsertShardedGenerate(t *testing.T) { 364 invschema := &vschemapb.SrvVSchema{ 365 Keyspaces: map[string]*vschemapb.Keyspace{ 366 "sharded": { 367 Sharded: true, 368 Vindexes: map[string]*vschemapb.Vindex{ 369 "hash": { 370 Type: "hash", 371 }, 372 }, 373 Tables: map[string]*vschemapb.Table{ 374 "t1": { 375 ColumnVindexes: []*vschemapb.ColumnVindex{{ 376 Name: "hash", 377 Columns: []string{"id"}, 378 }}, 379 }, 380 }, 381 }, 382 }, 383 } 384 vs := vindexes.BuildVSchema(invschema) 385 ks := vs.Keyspaces["sharded"] 386 387 ins := NewInsert( 388 InsertSharded, 389 false, 390 ks.Keyspace, 391 [][][]evalengine.Expr{{ 392 // colVindex columns: id 393 { 394 // 3 rows. 395 evalengine.NewLiteralInt(1), 396 evalengine.NewLiteralInt(2), 397 evalengine.NewLiteralInt(3), 398 }, 399 }}, 400 ks.Tables["t1"], 401 "prefix", 402 []string{" mid1", " mid2", " mid3"}, 403 " suffix", 404 ) 405 406 ins.Generate = &Generate{ 407 Keyspace: &vindexes.Keyspace{ 408 Name: "ks2", 409 Sharded: false, 410 }, 411 Query: "dummy_generate", 412 Values: evalengine.NewTupleExpr( 413 evalengine.NewLiteralInt(1), 414 evalengine.NullExpr, 415 evalengine.NewLiteralInt(2), 416 ), 417 } 418 419 vc := newDMLTestVCursor("-20", "20-") 420 vc.shardForKsid = []string{"20-", "-20", "20-"} 421 vc.results = []*sqltypes.Result{ 422 sqltypes.MakeTestResult( 423 sqltypes.MakeTestFields( 424 "nextval", 425 "int64", 426 ), 427 "2", 428 ), 429 {InsertID: 1}, 430 } 431 432 result, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 433 if err != nil { 434 t.Fatal(err) 435 } 436 vc.ExpectLog(t, []string{ 437 `ResolveDestinations ks2 [] Destinations:DestinationAnyShard()`, 438 `ExecuteStandalone dummy_generate n: type:INT64 value:"1" ks2 -20`, 439 // Based on shardForKsid, values returned will be 20-, -20, 20-. 440 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 441 // Row 2 will go to -20, rows 1 & 3 will go to 20- 442 `ExecuteMultiShard ` + 443 `sharded.20-: prefix mid1, mid3 suffix ` + 444 `{__seq0: type:INT64 value:"1" __seq1: type:INT64 value:"2" __seq2: type:INT64 value:"2" ` + 445 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 446 `sharded.-20: prefix mid2 suffix ` + 447 `{__seq0: type:INT64 value:"1" __seq1: type:INT64 value:"2" __seq2: type:INT64 value:"2" ` + 448 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 449 `true false`, 450 }) 451 452 // The insert id returned by ExecuteMultiShard should be overwritten by processGenerateFromValues. 453 expectResult(t, "Execute", result, &sqltypes.Result{InsertID: 2}) 454 } 455 456 func TestInsertShardedOwned(t *testing.T) { 457 invschema := &vschemapb.SrvVSchema{ 458 Keyspaces: map[string]*vschemapb.Keyspace{ 459 "sharded": { 460 Sharded: true, 461 Vindexes: map[string]*vschemapb.Vindex{ 462 "hash": { 463 Type: "hash", 464 }, 465 "twocol": { 466 Type: "lookup", 467 Params: map[string]string{ 468 "table": "lkp2", 469 "from": "from1,from2", 470 "to": "toc", 471 }, 472 Owner: "t1", 473 }, 474 "onecol": { 475 Type: "lookup", 476 Params: map[string]string{ 477 "table": "lkp1", 478 "from": "from", 479 "to": "toc", 480 }, 481 Owner: "t1", 482 }, 483 }, 484 Tables: map[string]*vschemapb.Table{ 485 "t1": { 486 ColumnVindexes: []*vschemapb.ColumnVindex{{ 487 Name: "hash", 488 Columns: []string{"id"}, 489 }, { 490 Name: "twocol", 491 Columns: []string{"c1", "c2"}, 492 }, { 493 Name: "onecol", 494 Columns: []string{"c3"}, 495 }}, 496 }, 497 }, 498 }, 499 }, 500 } 501 vs := vindexes.BuildVSchema(invschema) 502 ks := vs.Keyspaces["sharded"] 503 504 ins := NewInsert( 505 InsertSharded, 506 false, 507 ks.Keyspace, 508 [][][]evalengine.Expr{{ 509 // colVindex columns: id 510 { 511 // rows for id 512 evalengine.NewLiteralInt(1), 513 evalengine.NewLiteralInt(2), 514 evalengine.NewLiteralInt(3), 515 }, 516 }, { 517 // colVindex columns: c1, c2 518 { 519 evalengine.NewLiteralInt(4), 520 evalengine.NewLiteralInt(5), 521 evalengine.NewLiteralInt(6), 522 }, 523 { 524 evalengine.NewLiteralInt(7), 525 evalengine.NewLiteralInt(8), 526 evalengine.NewLiteralInt(9), 527 }, 528 }, { 529 // colVindex columns: c3 530 { 531 evalengine.NewLiteralInt(10), 532 evalengine.NewLiteralInt(11), 533 evalengine.NewLiteralInt(12), 534 }, 535 }}, 536 ks.Tables["t1"], 537 "prefix", 538 []string{" mid1", " mid2", " mid3"}, 539 " suffix", 540 ) 541 542 vc := newDMLTestVCursor("-20", "20-") 543 vc.shardForKsid = []string{"20-", "-20", "20-"} 544 545 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 546 if err != nil { 547 t.Fatal(err) 548 } 549 vc.ExpectLog(t, []string{ 550 `Execute insert into lkp2(from1, from2, toc) values(:from1_0, :from2_0, :toc_0), (:from1_1, :from2_1, :toc_1), (:from1_2, :from2_2, :toc_2) ` + 551 `from1_0: type:INT64 value:"4" from1_1: type:INT64 value:"5" from1_2: type:INT64 value:"6" ` + 552 `from2_0: type:INT64 value:"7" from2_1: type:INT64 value:"8" from2_2: type:INT64 value:"9" ` + 553 `toc_0: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" toc_1: type:VARBINARY value:"\x06\xe7\xea\"Βp\x8f" toc_2: type:VARBINARY value:"N\xb1\x90ɢ\xfa\x16\x9c" true`, 554 `Execute insert into lkp1(from, toc) values(:from_0, :toc_0), (:from_1, :toc_1), (:from_2, :toc_2) ` + 555 `from_0: type:INT64 value:"10" from_1: type:INT64 value:"11" from_2: type:INT64 value:"12" ` + 556 `toc_0: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" toc_1: type:VARBINARY value:"\x06\xe7\xea\"Βp\x8f" toc_2: type:VARBINARY value:"N\xb1\x90ɢ\xfa\x16\x9c" true`, 557 // Based on shardForKsid, values returned will be 20-, -20, 20-. 558 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 559 `ExecuteMultiShard ` + 560 `sharded.20-: prefix mid1, mid3 suffix ` + 561 `{_c1_0: type:INT64 value:"4" _c1_1: type:INT64 value:"5" _c1_2: type:INT64 value:"6" ` + 562 `_c2_0: type:INT64 value:"7" _c2_1: type:INT64 value:"8" _c2_2: type:INT64 value:"9" ` + 563 `_c3_0: type:INT64 value:"10" _c3_1: type:INT64 value:"11" _c3_2: type:INT64 value:"12" ` + 564 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 565 `sharded.-20: prefix mid2 suffix ` + 566 `{_c1_0: type:INT64 value:"4" _c1_1: type:INT64 value:"5" _c1_2: type:INT64 value:"6" ` + 567 `_c2_0: type:INT64 value:"7" _c2_1: type:INT64 value:"8" _c2_2: type:INT64 value:"9" ` + 568 `_c3_0: type:INT64 value:"10" _c3_1: type:INT64 value:"11" _c3_2: type:INT64 value:"12" ` + 569 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 570 `true false`, 571 }) 572 } 573 574 func TestInsertShardedOwnedWithNull(t *testing.T) { 575 invschema := &vschemapb.SrvVSchema{ 576 Keyspaces: map[string]*vschemapb.Keyspace{ 577 "sharded": { 578 Sharded: true, 579 Vindexes: map[string]*vschemapb.Vindex{ 580 "hash": { 581 Type: "hash", 582 }, 583 "onecol": { 584 Type: "lookup", 585 Params: map[string]string{ 586 "table": "lkp1", 587 "from": "from", 588 "to": "toc", 589 "ignore_nulls": "true", 590 }, 591 Owner: "t1", 592 }, 593 }, 594 Tables: map[string]*vschemapb.Table{ 595 "t1": { 596 ColumnVindexes: []*vschemapb.ColumnVindex{{ 597 Name: "hash", 598 Columns: []string{"id"}, 599 }, { 600 Name: "onecol", 601 Columns: []string{"c3"}, 602 }}, 603 }, 604 }, 605 }, 606 }, 607 } 608 vs := vindexes.BuildVSchema(invschema) 609 ks := vs.Keyspaces["sharded"] 610 611 ins := NewInsert( 612 InsertSharded, 613 false, 614 ks.Keyspace, 615 [][][]evalengine.Expr{{ 616 // colVindex columns: id 617 { 618 // rows for id 619 evalengine.NewLiteralInt(1), 620 }, 621 }, { 622 // colVindex columns: c3 623 { 624 evalengine.NullExpr, 625 }, 626 }}, 627 ks.Tables["t1"], 628 "prefix", 629 []string{" mid1", " mid2", " mid3"}, 630 " suffix", 631 ) 632 633 vc := newDMLTestVCursor("-20", "20-") 634 vc.shardForKsid = []string{"20-", "-20", "20-"} 635 636 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 637 if err != nil { 638 t.Fatal(err) 639 } 640 vc.ExpectLog(t, []string{ 641 `ResolveDestinations sharded [value:"0"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, 642 `ExecuteMultiShard sharded.20-: prefix mid1 suffix ` + 643 `{_c3_0: _id_0: type:INT64 value:"1"} true true`, 644 }) 645 } 646 647 func TestInsertShardedGeo(t *testing.T) { 648 invschema := &vschemapb.SrvVSchema{ 649 Keyspaces: map[string]*vschemapb.Keyspace{ 650 "sharded": { 651 Sharded: true, 652 Vindexes: map[string]*vschemapb.Vindex{ 653 "geo": { 654 Type: "region_experimental", 655 Params: map[string]string{ 656 "region_bytes": "1", 657 }, 658 }, 659 "lookup": { 660 Type: "lookup_unique", 661 Params: map[string]string{ 662 "table": "id_idx", 663 "from": "id", 664 "to": "keyspace_id", 665 }, 666 Owner: "t1", 667 }, 668 }, 669 Tables: map[string]*vschemapb.Table{ 670 "t1": { 671 ColumnVindexes: []*vschemapb.ColumnVindex{{ 672 Name: "geo", 673 Columns: []string{"region", "id"}, 674 }, { 675 Name: "lookup", 676 Columns: []string{"id"}, 677 }}, 678 }, 679 }, 680 }, 681 }, 682 } 683 vs := vindexes.BuildVSchema(invschema) 684 ks := vs.Keyspaces["sharded"] 685 686 ins := NewInsert( 687 InsertSharded, 688 false, 689 ks.Keyspace, 690 [][][]evalengine.Expr{{ 691 // colVindex columns: region, id 692 { 693 // rows for region 694 evalengine.NewLiteralInt(1), 695 evalengine.NewLiteralInt(255), 696 }, 697 { 698 // rows for id 699 evalengine.NewLiteralInt(1), 700 evalengine.NewLiteralInt(1), 701 }, 702 }, { 703 // colVindex columns: id 704 { 705 // rows for id 706 evalengine.NewLiteralInt(1), 707 evalengine.NewLiteralInt(1), 708 }, 709 }}, 710 ks.Tables["t1"], 711 "prefix", 712 []string{" mid1", " mid2"}, 713 " suffix", 714 ) 715 for _, colVindex := range ks.Tables["t1"].ColumnVindexes { 716 if colVindex.IsPartialVindex() { 717 continue 718 } 719 ins.ColVindexes = append(ins.ColVindexes, colVindex) 720 } 721 722 vc := newDMLTestVCursor("-20", "20-") 723 vc.shardForKsid = []string{"20-", "-20"} 724 725 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 726 if err != nil { 727 t.Fatal(err) 728 } 729 vc.ExpectLog(t, []string{ 730 `Execute insert into id_idx(id, keyspace_id) values(:id_0, :keyspace_id_0), (:id_1, :keyspace_id_1) ` + 731 `id_0: type:INT64 value:"1" id_1: type:INT64 value:"1" ` + 732 `keyspace_id_0: type:VARBINARY value:"\x01\x16k@\xb4J\xbaK\xd6" keyspace_id_1: type:VARBINARY value:"\xff\x16k@\xb4J\xbaK\xd6" true`, 733 `ResolveDestinations sharded [value:"0" value:"1"] Destinations:DestinationKeyspaceID(01166b40b44aba4bd6),DestinationKeyspaceID(ff166b40b44aba4bd6)`, 734 `ExecuteMultiShard sharded.20-: prefix mid1 suffix ` + 735 `{_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"1" ` + 736 `_region_0: type:INT64 value:"1" _region_1: type:INT64 value:"255"} ` + 737 `sharded.-20: prefix mid2 suffix ` + 738 `{_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"1" ` + 739 `_region_0: type:INT64 value:"1" _region_1: type:INT64 value:"255"} ` + 740 `true false`, 741 }) 742 } 743 744 func TestInsertShardedIgnoreOwned(t *testing.T) { 745 invschema := &vschemapb.SrvVSchema{ 746 Keyspaces: map[string]*vschemapb.Keyspace{ 747 "sharded": { 748 Sharded: true, 749 Vindexes: map[string]*vschemapb.Vindex{ 750 "primary": { 751 Type: "lookup_unique", 752 Params: map[string]string{ 753 "table": "prim", 754 "from": "from1", 755 "to": "toc", 756 }, 757 }, 758 "twocol": { 759 Type: "lookup", 760 Params: map[string]string{ 761 "table": "lkp2", 762 "from": "from1,from2", 763 "to": "toc", 764 }, 765 Owner: "t1", 766 }, 767 "onecol": { 768 Type: "lookup", 769 Params: map[string]string{ 770 "table": "lkp1", 771 "from": "from", 772 "to": "toc", 773 }, 774 Owner: "t1", 775 }, 776 }, 777 Tables: map[string]*vschemapb.Table{ 778 "t1": { 779 ColumnVindexes: []*vschemapb.ColumnVindex{{ 780 Name: "primary", 781 Columns: []string{"id"}, 782 }, { 783 Name: "twocol", 784 Columns: []string{"c1", "c2"}, 785 }, { 786 Name: "onecol", 787 Columns: []string{"c3"}, 788 }}, 789 }, 790 }, 791 }, 792 }, 793 } 794 vs := vindexes.BuildVSchema(invschema) 795 ks := vs.Keyspaces["sharded"] 796 797 ins := NewInsert( 798 InsertSharded, 799 true, 800 ks.Keyspace, 801 [][][]evalengine.Expr{{ 802 // colVindex columns: id 803 { 804 // rows for id 805 806 evalengine.NewLiteralInt(1), 807 evalengine.NewLiteralInt(2), 808 evalengine.NewLiteralInt(3), 809 evalengine.NewLiteralInt(4), 810 }, 811 }, { 812 // colVindex columns: c1, c2 813 { 814 // rows for c1 815 evalengine.NewLiteralInt(5), 816 evalengine.NewLiteralInt(6), 817 evalengine.NewLiteralInt(7), 818 evalengine.NewLiteralInt(8), 819 }, 820 { 821 // rows for c2 822 evalengine.NewLiteralInt(9), 823 evalengine.NewLiteralInt(10), 824 evalengine.NewLiteralInt(11), 825 evalengine.NewLiteralInt(12), 826 }, 827 }, { 828 // colVindex columns: c3 829 { 830 // rows for c3 831 evalengine.NewLiteralInt(13), 832 evalengine.NewLiteralInt(14), 833 evalengine.NewLiteralInt(15), 834 evalengine.NewLiteralInt(16), 835 }, 836 }}, 837 ks.Tables["t1"], 838 "prefix", 839 []string{" mid1", " mid2", " mid3", " mid4"}, 840 " suffix", 841 ) 842 843 ksid0Lookup := sqltypes.MakeTestResult( 844 sqltypes.MakeTestFields( 845 "from|to", 846 "int64|varbinary", 847 ), 848 "1|\x00", 849 "3|\x00", 850 "4|\x00", 851 ) 852 ksid0 := sqltypes.MakeTestResult( 853 sqltypes.MakeTestFields( 854 "to", 855 "varbinary", 856 ), 857 "\x00", 858 ) 859 noresult := &sqltypes.Result{} 860 vc := newDMLTestVCursor("-20", "20-") 861 vc.shardForKsid = []string{"20-", "-20"} 862 vc.results = []*sqltypes.Result{ 863 // primary vindex lookups: fail row 2. 864 ksid0Lookup, 865 // insert lkp2 866 noresult, 867 // fail one verification (row 3) 868 ksid0, 869 noresult, 870 ksid0, 871 // insert lkp1 872 noresult, 873 // verify lkp1 (only two rows to verify) 874 ksid0, 875 ksid0, 876 } 877 878 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 879 if err != nil { 880 t.Fatal(err) 881 } 882 vc.ExpectLog(t, []string{ 883 `Execute select from1, toc from prim where from1 in ::from1 from1: type:TUPLE values:{type:INT64 value:"1"} values:{type:INT64 value:"2"} values:{type:INT64 value:"3"} values:{type:INT64 value:"4"} false`, 884 `Execute insert ignore into lkp2(from1, from2, toc) values(:from1_0, :from2_0, :toc_0), (:from1_1, :from2_1, :toc_1), (:from1_2, :from2_2, :toc_2) ` + 885 `from1_0: type:INT64 value:"5" from1_1: type:INT64 value:"7" from1_2: type:INT64 value:"8" ` + 886 `from2_0: type:INT64 value:"9" from2_1: type:INT64 value:"11" from2_2: type:INT64 value:"12" ` + 887 `toc_0: type:VARBINARY value:"\x00" toc_1: type:VARBINARY value:"\x00" toc_2: type:VARBINARY value:"\x00" ` + 888 `true`, 889 // row 2 is out because it didn't map to a ksid. 890 `Execute select from1 from lkp2 where from1 = :from1 and toc = :toc from1: type:INT64 value:"5" toc: type:VARBINARY value:"\x00" false`, 891 `Execute select from1 from lkp2 where from1 = :from1 and toc = :toc from1: type:INT64 value:"7" toc: type:VARBINARY value:"\x00" false`, 892 `Execute select from1 from lkp2 where from1 = :from1 and toc = :toc from1: type:INT64 value:"8" toc: type:VARBINARY value:"\x00" false`, 893 `Execute insert ignore into lkp1(from, toc) values(:from_0, :toc_0), (:from_1, :toc_1) ` + 894 `from_0: type:INT64 value:"13" from_1: type:INT64 value:"16" ` + 895 `toc_0: type:VARBINARY value:"\x00" toc_1: type:VARBINARY value:"\x00" ` + 896 `true`, 897 // row 3 is out because it failed Verify. Only two verifications from lkp1. 898 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"13" toc: type:VARBINARY value:"\x00" false`, 899 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"16" toc: type:VARBINARY value:"\x00" false`, 900 `ResolveDestinations sharded [value:"0" value:"3"] Destinations:DestinationKeyspaceID(00),DestinationKeyspaceID(00)`, 901 // Bind vars for rows 2 & 3 may be missing because they were not sent. 902 `ExecuteMultiShard ` + 903 `sharded.20-: prefix mid1 suffix ` + 904 `{_c1_0: type:INT64 value:"5" _c1_3: type:INT64 value:"8" ` + 905 `_c2_0: type:INT64 value:"9" _c2_3: type:INT64 value:"12" ` + 906 `_c3_0: type:INT64 value:"13" _c3_3: type:INT64 value:"16" ` + 907 `_id_0: type:INT64 value:"1" _id_3: type:INT64 value:"4"} ` + 908 `sharded.-20: prefix mid4 suffix ` + 909 `{_c1_0: type:INT64 value:"5" _c1_3: type:INT64 value:"8" ` + 910 `_c2_0: type:INT64 value:"9" _c2_3: type:INT64 value:"12" ` + 911 `_c3_0: type:INT64 value:"13" _c3_3: type:INT64 value:"16" ` + 912 `_id_0: type:INT64 value:"1" _id_3: type:INT64 value:"4"} ` + 913 `true false`, 914 }) 915 } 916 917 func TestInsertShardedIgnoreOwnedWithNull(t *testing.T) { 918 invschema := &vschemapb.SrvVSchema{ 919 Keyspaces: map[string]*vschemapb.Keyspace{ 920 "sharded": { 921 Sharded: true, 922 Vindexes: map[string]*vschemapb.Vindex{ 923 "primary": { 924 Type: "hash", 925 }, 926 "onecol": { 927 Type: "lookup", 928 Params: map[string]string{ 929 "table": "lkp1", 930 "from": "from", 931 "to": "toc", 932 "ignore_nulls": "true", 933 }, 934 Owner: "t1", 935 }, 936 }, 937 Tables: map[string]*vschemapb.Table{ 938 "t1": { 939 ColumnVindexes: []*vschemapb.ColumnVindex{{ 940 Name: "primary", 941 Columns: []string{"id"}, 942 }, { 943 Name: "onecol", 944 Columns: []string{"c3"}, 945 }}, 946 }, 947 }, 948 }, 949 }, 950 } 951 vs := vindexes.BuildVSchema(invschema) 952 ks := vs.Keyspaces["sharded"] 953 954 ins := NewInsert( 955 InsertSharded, 956 true, 957 ks.Keyspace, 958 [][][]evalengine.Expr{{ 959 // colVindex columns: id 960 { 961 // rows for id 962 evalengine.NewLiteralInt(1), 963 }, 964 }, { 965 // colVindex columns: c3 966 { 967 // rows for c3 968 evalengine.NullExpr, 969 }, 970 }}, 971 ks.Tables["t1"], 972 "prefix", 973 []string{" mid1", " mid2", " mid3", " mid4"}, 974 " suffix", 975 ) 976 977 ksid0 := sqltypes.MakeTestResult( 978 sqltypes.MakeTestFields( 979 "to", 980 "varbinary", 981 ), 982 "\x00", 983 ) 984 vc := newDMLTestVCursor("-20", "20-") 985 vc.shardForKsid = []string{"-20", "20-"} 986 vc.results = []*sqltypes.Result{ 987 ksid0, 988 ksid0, 989 ksid0, 990 } 991 992 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 993 if err != nil { 994 t.Fatal(err) 995 } 996 vc.ExpectLog(t, []string{ 997 `Execute select from from lkp1 where from = :from and toc = :toc from: toc: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" false`, 998 `ResolveDestinations sharded [value:"0"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, 999 `ExecuteMultiShard sharded.-20: prefix mid1 suffix ` + 1000 `{_c3_0: _id_0: type:INT64 value:"1"} true true`, 1001 }) 1002 } 1003 1004 func TestInsertShardedUnownedVerify(t *testing.T) { 1005 invschema := &vschemapb.SrvVSchema{ 1006 Keyspaces: map[string]*vschemapb.Keyspace{ 1007 "sharded": { 1008 Sharded: true, 1009 Vindexes: map[string]*vschemapb.Vindex{ 1010 "hash": { 1011 Type: "hash", 1012 }, 1013 "twocol": { 1014 Type: "lookup", 1015 Params: map[string]string{ 1016 "table": "lkp2", 1017 "from": "from1,from2", 1018 "to": "toc", 1019 }, 1020 }, 1021 "onecol": { 1022 Type: "lookup", 1023 Params: map[string]string{ 1024 "table": "lkp1", 1025 "from": "from", 1026 "to": "toc", 1027 }, 1028 }, 1029 }, 1030 Tables: map[string]*vschemapb.Table{ 1031 "t1": { 1032 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1033 Name: "hash", 1034 Columns: []string{"id"}, 1035 }, { 1036 Name: "twocol", 1037 Columns: []string{"c1", "c2"}, 1038 }, { 1039 Name: "onecol", 1040 Columns: []string{"c3"}, 1041 }}, 1042 }, 1043 }, 1044 }, 1045 }, 1046 } 1047 vs := vindexes.BuildVSchema(invschema) 1048 ks := vs.Keyspaces["sharded"] 1049 1050 ins := NewInsert( 1051 InsertSharded, 1052 false, 1053 ks.Keyspace, 1054 [][][]evalengine.Expr{{ 1055 // colVindex columns: id 1056 { 1057 // rows for id 1058 evalengine.NewLiteralInt(1), 1059 evalengine.NewLiteralInt(2), 1060 evalengine.NewLiteralInt(3), 1061 }, 1062 }, { 1063 // colVindex columns: c1, c2 1064 { 1065 // rows for c1 1066 evalengine.NewLiteralInt(4), 1067 evalengine.NewLiteralInt(5), 1068 evalengine.NewLiteralInt(6), 1069 }, 1070 { 1071 // rows for c2 1072 evalengine.NewLiteralInt(7), 1073 evalengine.NewLiteralInt(8), 1074 evalengine.NewLiteralInt(9), 1075 }, 1076 }, { 1077 // colVindex columns: c3 1078 { 1079 // rows for c3 1080 evalengine.NewLiteralInt(10), 1081 evalengine.NewLiteralInt(11), 1082 evalengine.NewLiteralInt(12), 1083 }, 1084 }}, 1085 ks.Tables["t1"], 1086 "prefix", 1087 []string{" mid1", " mid2", " mid3"}, 1088 " suffix", 1089 ) 1090 1091 // nonemptyResult will cause the lookup verify queries to succeed. 1092 nonemptyResult := sqltypes.MakeTestResult( 1093 sqltypes.MakeTestFields( 1094 "c1", 1095 "int64", 1096 ), 1097 "1", 1098 ) 1099 1100 vc := newDMLTestVCursor("-20", "20-") 1101 vc.shardForKsid = []string{"20-", "-20", "20-"} 1102 vc.results = []*sqltypes.Result{ 1103 nonemptyResult, 1104 nonemptyResult, 1105 nonemptyResult, 1106 nonemptyResult, 1107 nonemptyResult, 1108 nonemptyResult, 1109 } 1110 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1111 if err != nil { 1112 t.Fatal(err) 1113 } 1114 vc.ExpectLog(t, []string{ 1115 // Perform verification for each colvindex. 1116 // Note that only first column of each colvindex is used. 1117 `Execute select from1 from lkp2 where from1 = :from1 and toc = :toc from1: type:INT64 value:"4" toc: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" false`, 1118 `Execute select from1 from lkp2 where from1 = :from1 and toc = :toc from1: type:INT64 value:"5" toc: type:VARBINARY value:"\x06\xe7\xea\"Βp\x8f" false`, 1119 `Execute select from1 from lkp2 where from1 = :from1 and toc = :toc from1: type:INT64 value:"6" toc: type:VARBINARY value:"N\xb1\x90ɢ\xfa\x16\x9c" false`, 1120 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"10" toc: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" false`, 1121 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"11" toc: type:VARBINARY value:"\x06\xe7\xea\"Βp\x8f" false`, 1122 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"12" toc: type:VARBINARY value:"N\xb1\x90ɢ\xfa\x16\x9c" false`, 1123 // Based on shardForKsid, values returned will be 20-, -20, 20-. 1124 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 1125 `ExecuteMultiShard ` + 1126 `sharded.20-: prefix mid1, mid3 suffix ` + 1127 `{_c1_0: type:INT64 value:"4" _c1_1: type:INT64 value:"5" _c1_2: type:INT64 value:"6" ` + 1128 `_c2_0: type:INT64 value:"7" _c2_1: type:INT64 value:"8" _c2_2: type:INT64 value:"9" ` + 1129 `_c3_0: type:INT64 value:"10" _c3_1: type:INT64 value:"11" _c3_2: type:INT64 value:"12" ` + 1130 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 1131 `sharded.-20: prefix mid2 suffix ` + 1132 `{_c1_0: type:INT64 value:"4" _c1_1: type:INT64 value:"5" _c1_2: type:INT64 value:"6" ` + 1133 `_c2_0: type:INT64 value:"7" _c2_1: type:INT64 value:"8" _c2_2: type:INT64 value:"9" ` + 1134 `_c3_0: type:INT64 value:"10" _c3_1: type:INT64 value:"11" _c3_2: type:INT64 value:"12" ` + 1135 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 1136 `true false`, 1137 }) 1138 } 1139 1140 func TestInsertShardedIgnoreUnownedVerify(t *testing.T) { 1141 invschema := &vschemapb.SrvVSchema{ 1142 Keyspaces: map[string]*vschemapb.Keyspace{ 1143 "sharded": { 1144 Sharded: true, 1145 Vindexes: map[string]*vschemapb.Vindex{ 1146 "hash": { 1147 Type: "hash", 1148 }, 1149 "onecol": { 1150 Type: "lookup", 1151 Params: map[string]string{ 1152 "table": "lkp1", 1153 "from": "from", 1154 "to": "toc", 1155 }, 1156 }, 1157 }, 1158 Tables: map[string]*vschemapb.Table{ 1159 "t1": { 1160 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1161 Name: "hash", 1162 Columns: []string{"id"}, 1163 }, { 1164 Name: "onecol", 1165 Columns: []string{"c3"}, 1166 }}, 1167 }, 1168 }, 1169 }, 1170 }, 1171 } 1172 vs := vindexes.BuildVSchema(invschema) 1173 ks := vs.Keyspaces["sharded"] 1174 1175 ins := NewInsert( 1176 InsertSharded, 1177 true, 1178 ks.Keyspace, 1179 [][][]evalengine.Expr{{ 1180 // colVindex columns: id 1181 { 1182 // rows for id 1183 evalengine.NewLiteralInt(1), 1184 evalengine.NewLiteralInt(2), 1185 evalengine.NewLiteralInt(3), 1186 }, 1187 }, { 1188 // colVindex columns: c3 1189 { 1190 // rows for c3 1191 evalengine.NewLiteralInt(10), 1192 evalengine.NewLiteralInt(11), 1193 evalengine.NewLiteralInt(12), 1194 }, 1195 }}, 1196 ks.Tables["t1"], 1197 "prefix", 1198 []string{" mid1", " mid2", " mid3"}, 1199 " suffix", 1200 ) 1201 1202 // nonemptyResult will cause the lookup verify queries to succeed. 1203 nonemptyResult := sqltypes.MakeTestResult( 1204 sqltypes.MakeTestFields( 1205 "c1", 1206 "int64", 1207 ), 1208 "1", 1209 ) 1210 1211 vc := newDMLTestVCursor("-20", "20-") 1212 vc.shardForKsid = []string{"20-", "-20"} 1213 vc.results = []*sqltypes.Result{ 1214 nonemptyResult, 1215 // fail verification of second row. 1216 {}, 1217 nonemptyResult, 1218 } 1219 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1220 if err != nil { 1221 t.Fatal(err) 1222 } 1223 vc.ExpectLog(t, []string{ 1224 // Perform verification for each colvindex. 1225 // Note that only first column of each colvindex is used. 1226 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"10" toc: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" false`, 1227 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"11" toc: type:VARBINARY value:"\x06\xe7\xea\"Βp\x8f" false`, 1228 `Execute select from from lkp1 where from = :from and toc = :toc from: type:INT64 value:"12" toc: type:VARBINARY value:"N\xb1\x90ɢ\xfa\x16\x9c" false`, 1229 // Based on shardForKsid, values returned will be 20-, -20. 1230 `ResolveDestinations sharded [value:"0" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(4eb190c9a2fa169c)`, 1231 `ExecuteMultiShard ` + 1232 `sharded.20-: prefix mid1 suffix ` + 1233 `{_c3_0: type:INT64 value:"10" _c3_2: type:INT64 value:"12" ` + 1234 `_id_0: type:INT64 value:"1" _id_2: type:INT64 value:"3"} ` + 1235 `sharded.-20: prefix mid3 suffix ` + 1236 `{_c3_0: type:INT64 value:"10" _c3_2: type:INT64 value:"12" ` + 1237 `_id_0: type:INT64 value:"1" _id_2: type:INT64 value:"3"} ` + 1238 `true false`, 1239 }) 1240 } 1241 1242 func TestInsertShardedIgnoreUnownedVerifyFail(t *testing.T) { 1243 invschema := &vschemapb.SrvVSchema{ 1244 Keyspaces: map[string]*vschemapb.Keyspace{ 1245 "sharded": { 1246 Sharded: true, 1247 Vindexes: map[string]*vschemapb.Vindex{ 1248 "hash": { 1249 Type: "hash", 1250 }, 1251 "onecol": { 1252 Type: "lookup", 1253 Params: map[string]string{ 1254 "table": "lkp1", 1255 "from": "from", 1256 "to": "toc", 1257 }, 1258 }, 1259 }, 1260 Tables: map[string]*vschemapb.Table{ 1261 "t1": { 1262 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1263 Name: "hash", 1264 Columns: []string{"id"}, 1265 }, { 1266 Name: "onecol", 1267 Columns: []string{"c3"}, 1268 }}, 1269 }, 1270 }, 1271 }, 1272 }, 1273 } 1274 vs := vindexes.BuildVSchema(invschema) 1275 ks := vs.Keyspaces["sharded"] 1276 1277 ins := NewInsert( 1278 InsertSharded, 1279 false, 1280 ks.Keyspace, 1281 [][][]evalengine.Expr{{ 1282 // colVindex columns: id 1283 { 1284 // rows for id 1285 evalengine.NewLiteralInt(1), 1286 }, 1287 }, { 1288 // colVindex columns: c3 1289 { 1290 // rows for c3 1291 evalengine.NewLiteralInt(2), 1292 }, 1293 }}, 1294 ks.Tables["t1"], 1295 "prefix", 1296 []string{" mid1", " mid2", " mid3"}, 1297 " suffix", 1298 ) 1299 1300 vc := newDMLTestVCursor("-20", "20-") 1301 1302 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1303 require.EqualError(t, err, `values [[INT64(2)]] for column [c3] does not map to keyspace ids`) 1304 } 1305 1306 func TestInsertShardedUnownedReverseMap(t *testing.T) { 1307 invschema := &vschemapb.SrvVSchema{ 1308 Keyspaces: map[string]*vschemapb.Keyspace{ 1309 "sharded": { 1310 Sharded: true, 1311 Vindexes: map[string]*vschemapb.Vindex{ 1312 "hash": { 1313 Type: "hash", 1314 }, 1315 "twocol": { 1316 Type: "lookup", 1317 Params: map[string]string{ 1318 "table": "lkp2", 1319 "from": "from1,from2", 1320 "to": "toc", 1321 }, 1322 }, 1323 "onecol": { 1324 Type: "lookup", 1325 Params: map[string]string{ 1326 "table": "lkp1", 1327 "from": "from", 1328 "to": "toc", 1329 }, 1330 }, 1331 }, 1332 Tables: map[string]*vschemapb.Table{ 1333 "t1": { 1334 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1335 Name: "hash", 1336 Columns: []string{"id"}, 1337 }, { 1338 Name: "hash", 1339 Columns: []string{"c1", "c2"}, 1340 }, { 1341 Name: "hash", 1342 Columns: []string{"c3"}, 1343 }}, 1344 }, 1345 }, 1346 }, 1347 }, 1348 } 1349 vs := vindexes.BuildVSchema(invschema) 1350 ks := vs.Keyspaces["sharded"] 1351 1352 ins := NewInsert( 1353 InsertSharded, 1354 false, 1355 ks.Keyspace, 1356 [][][]evalengine.Expr{{ 1357 // colVindex columns: id 1358 { 1359 // rows for id 1360 evalengine.NewLiteralInt(1), 1361 evalengine.NewLiteralInt(2), 1362 evalengine.NewLiteralInt(3), 1363 }, 1364 }, { 1365 // colVindex columns: c1, c2 1366 { 1367 // rows for c1 1368 evalengine.NullExpr, 1369 evalengine.NullExpr, 1370 evalengine.NullExpr, 1371 }, 1372 { 1373 // rows for c2 1374 evalengine.NullExpr, 1375 evalengine.NullExpr, 1376 evalengine.NullExpr, 1377 }, 1378 }, { 1379 // colVindex columns: c3 1380 { 1381 // rows for c3 1382 evalengine.NullExpr, 1383 evalengine.NullExpr, 1384 evalengine.NullExpr, 1385 }, 1386 }}, 1387 ks.Tables["t1"], 1388 "prefix", 1389 []string{" mid1", " mid2", " mid3"}, 1390 " suffix", 1391 ) 1392 1393 // nonemptyResult will cause the lookup verify queries to succeed. 1394 nonemptyResult := sqltypes.MakeTestResult( 1395 sqltypes.MakeTestFields( 1396 "c1", 1397 "int64", 1398 ), 1399 "1", 1400 ) 1401 1402 vc := newDMLTestVCursor("-20", "20-") 1403 vc.shardForKsid = []string{"20-", "-20", "20-"} 1404 vc.results = []*sqltypes.Result{ 1405 nonemptyResult, 1406 } 1407 1408 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1409 if err != nil { 1410 t.Fatal(err) 1411 } 1412 vc.ExpectLog(t, []string{ 1413 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 1414 `ExecuteMultiShard ` + 1415 `sharded.20-: prefix mid1, mid3 suffix ` + 1416 `{_c1_0: type:UINT64 value:"1" _c1_1: type:UINT64 value:"2" _c1_2: type:UINT64 value:"3" ` + 1417 `_c2_0: _c2_1: _c2_2: ` + 1418 `_c3_0: type:UINT64 value:"1" _c3_1: type:UINT64 value:"2" _c3_2: type:UINT64 value:"3" ` + 1419 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 1420 `sharded.-20: prefix mid2 suffix ` + 1421 `{_c1_0: type:UINT64 value:"1" _c1_1: type:UINT64 value:"2" _c1_2: type:UINT64 value:"3" ` + 1422 `_c2_0: _c2_1: _c2_2: ` + 1423 `_c3_0: type:UINT64 value:"1" _c3_1: type:UINT64 value:"2" _c3_2: type:UINT64 value:"3" ` + 1424 `_id_0: type:INT64 value:"1" _id_1: type:INT64 value:"2" _id_2: type:INT64 value:"3"} ` + 1425 `true false`, 1426 }) 1427 } 1428 1429 func TestInsertShardedUnownedReverseMapSuccess(t *testing.T) { 1430 invschema := &vschemapb.SrvVSchema{ 1431 Keyspaces: map[string]*vschemapb.Keyspace{ 1432 "sharded": { 1433 Sharded: true, 1434 Vindexes: map[string]*vschemapb.Vindex{ 1435 "hash": { 1436 Type: "hash", 1437 }, 1438 "onecol": { 1439 Type: "lookup", 1440 Params: map[string]string{ 1441 "table": "lkp1", 1442 "from": "from", 1443 "to": "toc", 1444 }, 1445 }, 1446 }, 1447 Tables: map[string]*vschemapb.Table{ 1448 "t1": { 1449 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1450 Name: "hash", 1451 Columns: []string{"id"}, 1452 }, { 1453 Name: "onecol", 1454 Columns: []string{"c3"}, 1455 }}, 1456 }, 1457 }, 1458 }, 1459 }, 1460 } 1461 vs := vindexes.BuildVSchema(invschema) 1462 ks := vs.Keyspaces["sharded"] 1463 1464 ins := NewInsert( 1465 InsertSharded, 1466 false, 1467 ks.Keyspace, 1468 [][][]evalengine.Expr{{ 1469 // colVindex columns: id 1470 { 1471 // rows for id 1472 evalengine.NewLiteralInt(1), 1473 }, 1474 }, { 1475 // colVindex columns: c3 1476 { 1477 // rows for c3 1478 evalengine.NullExpr, 1479 }, 1480 }}, 1481 ks.Tables["t1"], 1482 "prefix", 1483 []string{" mid1", " mid2", " mid3"}, 1484 " suffix", 1485 ) 1486 1487 vc := newDMLTestVCursor("-20", "20-") 1488 1489 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1490 require.NoError(t, err) 1491 } 1492 1493 func TestInsertSelectSimple(t *testing.T) { 1494 invschema := &vschemapb.SrvVSchema{ 1495 Keyspaces: map[string]*vschemapb.Keyspace{ 1496 "sharded": { 1497 Sharded: true, 1498 Vindexes: map[string]*vschemapb.Vindex{ 1499 "hash": {Type: "hash"}}, 1500 Tables: map[string]*vschemapb.Table{ 1501 "t1": { 1502 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1503 Name: "hash", 1504 Columns: []string{"id"}}}}}}}} 1505 1506 vs := vindexes.BuildVSchema(invschema) 1507 ks := vs.Keyspaces["sharded"] 1508 1509 // A single row insert should be autocommitted 1510 ins := &Insert{ 1511 Opcode: InsertSelect, 1512 Keyspace: ks.Keyspace, 1513 Query: "dummy_insert", 1514 Table: ks.Tables["t1"], 1515 VindexValueOffset: [][]int{{1}}, 1516 Input: &Route{ 1517 Query: "dummy_select", 1518 FieldQuery: "dummy_field_query", 1519 RoutingParameters: &RoutingParameters{ 1520 Opcode: Scatter, 1521 Keyspace: ks.Keyspace}}} 1522 1523 ins.ColVindexes = append(ins.ColVindexes, ks.Tables["t1"].ColumnVindexes...) 1524 ins.Prefix = "prefix " 1525 ins.Suffix = " suffix" 1526 1527 vc := newDMLTestVCursor("-20", "20-") 1528 vc.shardForKsid = []string{"20-", "-20", "20-"} 1529 vc.results = []*sqltypes.Result{ 1530 sqltypes.MakeTestResult( 1531 sqltypes.MakeTestFields( 1532 "name|id", 1533 "varchar|int64"), 1534 "a|1", 1535 "a|3", 1536 "b|2")} 1537 1538 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1539 require.NoError(t, err) 1540 vc.ExpectLog(t, []string{ 1541 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 1542 1543 // the select query 1544 `ExecuteMultiShard sharded.-20: dummy_select {} sharded.20-: dummy_select {} false false`, 1545 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(4eb190c9a2fa169c),DestinationKeyspaceID(06e7ea22ce92708f)`, 1546 1547 // two rows go to the 20- shard, and one row go to the -20 shard 1548 `ExecuteMultiShard ` + 1549 `sharded.20-: prefix values (:_c0_0, :_c0_1), (:_c2_0, :_c2_1) suffix ` + 1550 `{_c0_0: type:VARCHAR value:"a" _c0_1: type:INT64 value:"1"` + 1551 ` _c2_0: type:VARCHAR value:"b" _c2_1: type:INT64 value:"2"} ` + 1552 `sharded.-20: prefix values (:_c1_0, :_c1_1) suffix` + 1553 ` {_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"3"} true false`}) 1554 1555 vc.Rewind() 1556 err = ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 1557 return nil 1558 }) 1559 require.NoError(t, err) 1560 vc.ExpectLog(t, []string{ 1561 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 1562 1563 // the select query 1564 `StreamExecuteMulti dummy_select sharded.-20: {} sharded.20-: {} `, 1565 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(4eb190c9a2fa169c),DestinationKeyspaceID(06e7ea22ce92708f)`, 1566 1567 // two rows go to the 20- shard, and one row go to the -20 shard 1568 `ExecuteMultiShard ` + 1569 `sharded.20-: prefix values (:_c0_0, :_c0_1), (:_c2_0, :_c2_1) suffix ` + 1570 `{_c0_0: type:VARCHAR value:"a" _c0_1: type:INT64 value:"1"` + 1571 ` _c2_0: type:VARCHAR value:"b" _c2_1: type:INT64 value:"2"} ` + 1572 `sharded.-20: prefix values (:_c1_0, :_c1_1) suffix` + 1573 ` {_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"3"} true false`}) 1574 } 1575 1576 func TestInsertSelectOwned(t *testing.T) { 1577 invschema := &vschemapb.SrvVSchema{ 1578 Keyspaces: map[string]*vschemapb.Keyspace{ 1579 "sharded": { 1580 Sharded: true, 1581 Vindexes: map[string]*vschemapb.Vindex{ 1582 "hash": {Type: "hash"}, 1583 "onecol": { 1584 Type: "lookup", 1585 Params: map[string]string{ 1586 "table": "lkp1", 1587 "from": "from", 1588 "to": "toc"}, 1589 Owner: "t1"}}, 1590 Tables: map[string]*vschemapb.Table{ 1591 "t1": { 1592 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1593 Name: "hash", 1594 Columns: []string{"id"}}, { 1595 Name: "onecol", 1596 Columns: []string{"c3"}}}}}}}} 1597 1598 vs := vindexes.BuildVSchema(invschema) 1599 ks := vs.Keyspaces["sharded"] 1600 1601 ins := &Insert{ 1602 Opcode: InsertSelect, 1603 Keyspace: ks.Keyspace, 1604 Query: "dummy_insert", 1605 Table: ks.Tables["t1"], 1606 VindexValueOffset: [][]int{ 1607 {1}, // The primary vindex has a single column as sharding key 1608 {0}}, // the onecol vindex uses the 'name' column 1609 Input: &Route{ 1610 Query: "dummy_select", 1611 FieldQuery: "dummy_field_query", 1612 RoutingParameters: &RoutingParameters{ 1613 Opcode: Scatter, 1614 Keyspace: ks.Keyspace}}} 1615 1616 ins.ColVindexes = append(ins.ColVindexes, ks.Tables["t1"].ColumnVindexes...) 1617 ins.Prefix = "prefix " 1618 ins.Suffix = " suffix" 1619 1620 vc := newDMLTestVCursor("-20", "20-") 1621 vc.shardForKsid = []string{"20-", "-20", "20-"} 1622 vc.results = []*sqltypes.Result{ 1623 sqltypes.MakeTestResult( 1624 sqltypes.MakeTestFields( 1625 "name|id", 1626 "varchar|int64"), 1627 "a|1", 1628 "a|3", 1629 "b|2")} 1630 1631 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1632 require.NoError(t, err) 1633 vc.ExpectLog(t, []string{ 1634 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 1635 1636 // the select query 1637 `ExecuteMultiShard sharded.-20: dummy_select {} sharded.20-: dummy_select {} false false`, 1638 1639 // insert values into the owned lookup vindex 1640 `Execute insert into lkp1(from, toc) values(:from_0, :toc_0), (:from_1, :toc_1), (:from_2, :toc_2) from_0: type:VARCHAR value:"a" from_1: type:VARCHAR value:"a" from_2: type:VARCHAR value:"b" toc_0: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" toc_1: type:VARBINARY value:"N\xb1\x90ɢ\xfa\x16\x9c" toc_2: type:VARBINARY value:"\x06\xe7\xea\"Βp\x8f" true`, 1641 1642 // Values 0 1 2 come from the id column 1643 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(4eb190c9a2fa169c),DestinationKeyspaceID(06e7ea22ce92708f)`, 1644 1645 // insert values into the main table 1646 `ExecuteMultiShard ` + 1647 // first we insert two rows on the 20- shard 1648 `sharded.20-: prefix values (:_c0_0, :_c0_1), (:_c2_0, :_c2_1) suffix ` + 1649 `{_c0_0: type:VARCHAR value:"a" _c0_1: type:INT64 value:"1" _c2_0: type:VARCHAR value:"b" _c2_1: type:INT64 value:"2"} ` + 1650 1651 // next we insert one row on the -20 shard 1652 `sharded.-20: prefix values (:_c1_0, :_c1_1) suffix ` + 1653 `{_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"3"} ` + 1654 `true false`}) 1655 1656 vc.Rewind() 1657 err = ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 1658 return nil 1659 }) 1660 require.NoError(t, err) 1661 vc.ExpectLog(t, []string{ 1662 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 1663 1664 // the select query 1665 `StreamExecuteMulti dummy_select sharded.-20: {} sharded.20-: {} `, 1666 1667 // insert values into the owned lookup vindex 1668 `Execute insert into lkp1(from, toc) values(:from_0, :toc_0), (:from_1, :toc_1), (:from_2, :toc_2) from_0: type:VARCHAR value:"a" from_1: type:VARCHAR value:"a" from_2: type:VARCHAR value:"b" toc_0: type:VARBINARY value:"\x16k@\xb4J\xbaK\xd6" toc_1: type:VARBINARY value:"N\xb1\x90ɢ\xfa\x16\x9c" toc_2: type:VARBINARY value:"\x06\xe7\xea\"Βp\x8f" true`, 1669 1670 // Values 0 1 2 come from the id column 1671 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(4eb190c9a2fa169c),DestinationKeyspaceID(06e7ea22ce92708f)`, 1672 1673 // insert values into the main table 1674 `ExecuteMultiShard ` + 1675 // first we insert two rows on the 20- shard 1676 `sharded.20-: prefix values (:_c0_0, :_c0_1), (:_c2_0, :_c2_1) suffix ` + 1677 `{_c0_0: type:VARCHAR value:"a" _c0_1: type:INT64 value:"1" _c2_0: type:VARCHAR value:"b" _c2_1: type:INT64 value:"2"} ` + 1678 1679 // next we insert one row on the -20 shard 1680 `sharded.-20: prefix values (:_c1_0, :_c1_1) suffix ` + 1681 `{_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"3"} ` + 1682 `true false`}) 1683 } 1684 1685 func TestInsertSelectGenerate(t *testing.T) { 1686 invschema := &vschemapb.SrvVSchema{ 1687 Keyspaces: map[string]*vschemapb.Keyspace{ 1688 "sharded": { 1689 Sharded: true, 1690 Vindexes: map[string]*vschemapb.Vindex{ 1691 "hash": { 1692 Type: "hash"}}, 1693 Tables: map[string]*vschemapb.Table{ 1694 "t1": { 1695 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1696 Name: "hash", 1697 Columns: []string{"id"}}}}}}}} 1698 1699 vs := vindexes.BuildVSchema(invschema) 1700 ks := vs.Keyspaces["sharded"] 1701 1702 ins := &Insert{ 1703 Opcode: InsertSelect, 1704 Keyspace: ks.Keyspace, 1705 Query: "dummy_insert", 1706 Table: ks.Tables["t1"], 1707 VindexValueOffset: [][]int{ 1708 {1}}, // The primary vindex has a single column as sharding key 1709 Input: &Route{ 1710 Query: "dummy_select", 1711 FieldQuery: "dummy_field_query", 1712 RoutingParameters: &RoutingParameters{ 1713 Opcode: Scatter, 1714 Keyspace: ks.Keyspace}}} 1715 1716 ins.Generate = &Generate{ 1717 Keyspace: &vindexes.Keyspace{ 1718 Name: "ks2", 1719 Sharded: false, 1720 }, 1721 Query: "dummy_generate", 1722 Offset: 1, 1723 } 1724 ins.Prefix = "prefix " 1725 ins.Suffix = " suffix" 1726 1727 vc := newDMLTestVCursor("-20", "20-") 1728 vc.shardForKsid = []string{"20-", "-20", "20-"} 1729 vc.results = []*sqltypes.Result{ 1730 // This is the result from the input SELECT 1731 sqltypes.MakeTestResult( 1732 sqltypes.MakeTestFields( 1733 "name|id", 1734 "varchar|int64"), 1735 "a|1", 1736 "a|null", 1737 "b|null"), 1738 // This is the result for the sequence query 1739 sqltypes.MakeTestResult( 1740 sqltypes.MakeTestFields( 1741 "nextval", 1742 "int64", 1743 ), 1744 "2", 1745 ), 1746 {InsertID: 1}, 1747 } 1748 1749 result, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1750 require.NoError(t, err) 1751 vc.ExpectLog(t, []string{ 1752 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 1753 // this is the input query 1754 `ExecuteMultiShard sharded.-20: dummy_select {} sharded.20-: dummy_select {} false false`, 1755 `ResolveDestinations ks2 [] Destinations:DestinationAnyShard()`, 1756 1757 // this is the sequence table query 1758 `ExecuteStandalone dummy_generate n: type:INT64 value:"2" ks2 -20`, 1759 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 1760 `ExecuteMultiShard ` + 1761 // first we send the insert to the 20- shard 1762 `sharded.20-: prefix values (:_c0_0, :_c0_1), (:_c2_0, :_c2_1) suffix ` + 1763 `{_c0_0: type:VARCHAR value:"a" ` + 1764 `_c0_1: type:INT64 value:"1" ` + 1765 `_c2_0: type:VARCHAR value:"b" ` + 1766 `_c2_1: type:INT64 value:"3"} ` + 1767 // next we send the insert to the -20 shard 1768 `sharded.-20: prefix values (:_c1_0, :_c1_1) suffix ` + 1769 `{_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"2"} ` + 1770 `true false`, 1771 }) 1772 1773 // The insert id returned by ExecuteMultiShard should be overwritten by processGenerateFromValues. 1774 expectResult(t, "Execute", result, &sqltypes.Result{InsertID: 2}) 1775 } 1776 1777 func TestStreamingInsertSelectGenerate(t *testing.T) { 1778 invschema := &vschemapb.SrvVSchema{ 1779 Keyspaces: map[string]*vschemapb.Keyspace{ 1780 "sharded": { 1781 Sharded: true, 1782 Vindexes: map[string]*vschemapb.Vindex{ 1783 "hash": { 1784 Type: "hash"}}, 1785 Tables: map[string]*vschemapb.Table{ 1786 "t1": { 1787 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1788 Name: "hash", 1789 Columns: []string{"id"}}}}}}}} 1790 1791 vs := vindexes.BuildVSchema(invschema) 1792 ks := vs.Keyspaces["sharded"] 1793 1794 ins := &Insert{ 1795 Opcode: InsertSelect, 1796 Keyspace: ks.Keyspace, 1797 Query: "dummy_insert", 1798 Table: ks.Tables["t1"], 1799 VindexValueOffset: [][]int{ 1800 {1}}, // The primary vindex has a single column as sharding key 1801 Input: &Route{ 1802 Query: "dummy_select", 1803 FieldQuery: "dummy_field_query", 1804 RoutingParameters: &RoutingParameters{ 1805 Opcode: Scatter, 1806 Keyspace: ks.Keyspace}}} 1807 1808 ins.Generate = &Generate{ 1809 Keyspace: &vindexes.Keyspace{ 1810 Name: "ks2", 1811 Sharded: false, 1812 }, 1813 Query: "dummy_generate", 1814 Offset: 1, 1815 } 1816 ins.Prefix = "prefix " 1817 ins.Suffix = " suffix" 1818 1819 vc := newDMLTestVCursor("-20", "20-") 1820 vc.shardForKsid = []string{"20-", "-20", "20-"} 1821 vc.results = []*sqltypes.Result{ 1822 // This is the result from the input SELECT 1823 sqltypes.MakeTestResult( 1824 sqltypes.MakeTestFields( 1825 "name|id", 1826 "varchar|int64"), 1827 "a|1", 1828 "a|null", 1829 "b|null"), 1830 // This is the result for the sequence query 1831 sqltypes.MakeTestResult( 1832 sqltypes.MakeTestFields( 1833 "nextval", 1834 "int64", 1835 ), 1836 "2", 1837 ), 1838 {InsertID: 1}, 1839 } 1840 1841 var output *sqltypes.Result 1842 err := ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 1843 output = result 1844 return nil 1845 }) 1846 require.NoError(t, err) 1847 vc.ExpectLog(t, []string{ 1848 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 1849 // this is the input query 1850 `StreamExecuteMulti dummy_select sharded.-20: {} sharded.20-: {} `, 1851 `ResolveDestinations ks2 [] Destinations:DestinationAnyShard()`, 1852 1853 // this is the sequence table query 1854 `ExecuteStandalone dummy_generate n: type:INT64 value:"2" ks2 -20`, 1855 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 1856 `ExecuteMultiShard ` + 1857 // first we send the insert to the 20- shard 1858 `sharded.20-: prefix values (:_c0_0, :_c0_1), (:_c2_0, :_c2_1) suffix ` + 1859 `{_c0_0: type:VARCHAR value:"a" ` + 1860 `_c0_1: type:INT64 value:"1" ` + 1861 `_c2_0: type:VARCHAR value:"b" ` + 1862 `_c2_1: type:INT64 value:"3"} ` + 1863 // next we send the insert to the -20 shard 1864 `sharded.-20: prefix values (:_c1_0, :_c1_1) suffix ` + 1865 `{_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"2"} ` + 1866 `true false`, 1867 }) 1868 1869 // The insert id returned by ExecuteMultiShard should be overwritten by processGenerateFromValues. 1870 expectResult(t, "Execute", output, &sqltypes.Result{InsertID: 2}) 1871 } 1872 1873 func TestInsertSelectGenerateNotProvided(t *testing.T) { 1874 invschema := &vschemapb.SrvVSchema{ 1875 Keyspaces: map[string]*vschemapb.Keyspace{ 1876 "sharded": { 1877 Sharded: true, 1878 Vindexes: map[string]*vschemapb.Vindex{ 1879 "hash": { 1880 Type: "hash"}}, 1881 Tables: map[string]*vschemapb.Table{ 1882 "t1": { 1883 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1884 Name: "hash", 1885 Columns: []string{"id"}}}}}}}} 1886 1887 vs := vindexes.BuildVSchema(invschema) 1888 ks := vs.Keyspaces["sharded"] 1889 1890 ins := &Insert{ 1891 Opcode: InsertSelect, 1892 Keyspace: ks.Keyspace, 1893 Query: "dummy_insert", 1894 Table: ks.Tables["t1"], 1895 VindexValueOffset: [][]int{ 1896 {1}}, // The primary vindex has a single column as sharding key 1897 Input: &Route{ 1898 Query: "dummy_select", 1899 FieldQuery: "dummy_field_query", 1900 RoutingParameters: &RoutingParameters{ 1901 Opcode: Scatter, 1902 Keyspace: ks.Keyspace}}} 1903 1904 ins.Generate = &Generate{ 1905 Keyspace: &vindexes.Keyspace{ 1906 Name: "ks2", 1907 Sharded: false, 1908 }, 1909 Query: "dummy_generate", 1910 Offset: 2, 1911 } 1912 ins.Prefix = "prefix " 1913 ins.Suffix = " suffix" 1914 1915 vc := newDMLTestVCursor("-20", "20-") 1916 vc.shardForKsid = []string{"20-", "-20", "20-"} 1917 vc.results = []*sqltypes.Result{ 1918 // This is the result from the input SELECT 1919 sqltypes.MakeTestResult( 1920 sqltypes.MakeTestFields( 1921 "name|id", 1922 "varchar|int64"), 1923 "a|1", 1924 "a|2", 1925 "b|3"), 1926 // This is the result for the sequence query 1927 sqltypes.MakeTestResult( 1928 sqltypes.MakeTestFields( 1929 "nextval", 1930 "int64", 1931 ), 1932 "10", 1933 ), 1934 {InsertID: 1}, 1935 } 1936 1937 result, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 1938 require.NoError(t, err) 1939 vc.ExpectLog(t, []string{ 1940 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 1941 // this is the input query 1942 `ExecuteMultiShard sharded.-20: dummy_select {} sharded.20-: dummy_select {} false false`, 1943 `ResolveDestinations ks2 [] Destinations:DestinationAnyShard()`, 1944 1945 // this is the sequence table query 1946 `ExecuteStandalone dummy_generate n: type:INT64 value:"3" ks2 -20`, 1947 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 1948 `ExecuteMultiShard ` + 1949 `sharded.20-: prefix values (:_c0_0, :_c0_1, :_c0_2), (:_c2_0, :_c2_1, :_c2_2) suffix ` + 1950 `{_c0_0: type:VARCHAR value:"a" _c0_1: type:INT64 value:"1" _c0_2: type:INT64 value:"10" ` + 1951 `_c2_0: type:VARCHAR value:"b" _c2_1: type:INT64 value:"3" _c2_2: type:INT64 value:"12"} ` + 1952 `sharded.-20: prefix values (:_c1_0, :_c1_1, :_c1_2) suffix ` + 1953 `{_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"2" _c1_2: type:INT64 value:"11"} ` + 1954 `true false`, 1955 }) 1956 1957 // The insert id returned by ExecuteMultiShard should be overwritten by processGenerateFromValues. 1958 expectResult(t, "Execute", result, &sqltypes.Result{InsertID: 10}) 1959 } 1960 1961 func TestStreamingInsertSelectGenerateNotProvided(t *testing.T) { 1962 invschema := &vschemapb.SrvVSchema{ 1963 Keyspaces: map[string]*vschemapb.Keyspace{ 1964 "sharded": { 1965 Sharded: true, 1966 Vindexes: map[string]*vschemapb.Vindex{ 1967 "hash": { 1968 Type: "hash"}}, 1969 Tables: map[string]*vschemapb.Table{ 1970 "t1": { 1971 ColumnVindexes: []*vschemapb.ColumnVindex{{ 1972 Name: "hash", 1973 Columns: []string{"id"}}}}}}}} 1974 1975 vs := vindexes.BuildVSchema(invschema) 1976 ks := vs.Keyspaces["sharded"] 1977 1978 ins := &Insert{ 1979 Opcode: InsertSelect, 1980 Keyspace: ks.Keyspace, 1981 Query: "dummy_insert", 1982 Table: ks.Tables["t1"], 1983 VindexValueOffset: [][]int{ 1984 {1}}, // The primary vindex has a single column as sharding key 1985 Input: &Route{ 1986 Query: "dummy_select", 1987 FieldQuery: "dummy_field_query", 1988 RoutingParameters: &RoutingParameters{ 1989 Opcode: Scatter, 1990 Keyspace: ks.Keyspace}}} 1991 1992 ins.Generate = &Generate{ 1993 Keyspace: &vindexes.Keyspace{ 1994 Name: "ks2", 1995 Sharded: false, 1996 }, 1997 Query: "dummy_generate", 1998 Offset: 2, 1999 } 2000 ins.Prefix = "prefix " 2001 ins.Suffix = " suffix" 2002 2003 vc := newDMLTestVCursor("-20", "20-") 2004 vc.shardForKsid = []string{"20-", "-20", "20-"} 2005 vc.results = []*sqltypes.Result{ 2006 // This is the result from the input SELECT 2007 sqltypes.MakeTestResult( 2008 sqltypes.MakeTestFields( 2009 "name|id", 2010 "varchar|int64"), 2011 "a|1", 2012 "a|2", 2013 "b|3"), 2014 // This is the result for the sequence query 2015 sqltypes.MakeTestResult( 2016 sqltypes.MakeTestFields( 2017 "nextval", 2018 "int64", 2019 ), 2020 "10", 2021 ), 2022 {InsertID: 1}, 2023 } 2024 2025 var output *sqltypes.Result 2026 err := ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 2027 output = result 2028 return nil 2029 }) 2030 require.NoError(t, err) 2031 vc.ExpectLog(t, []string{ 2032 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 2033 // this is the input query 2034 `StreamExecuteMulti dummy_select sharded.-20: {} sharded.20-: {} `, 2035 `ResolveDestinations ks2 [] Destinations:DestinationAnyShard()`, 2036 2037 // this is the sequence table query 2038 `ExecuteStandalone dummy_generate n: type:INT64 value:"3" ks2 -20`, 2039 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6),DestinationKeyspaceID(06e7ea22ce92708f),DestinationKeyspaceID(4eb190c9a2fa169c)`, 2040 `ExecuteMultiShard ` + 2041 `sharded.20-: prefix values (:_c0_0, :_c0_1, :_c0_2), (:_c2_0, :_c2_1, :_c2_2) suffix ` + 2042 `{_c0_0: type:VARCHAR value:"a" _c0_1: type:INT64 value:"1" _c0_2: type:INT64 value:"10" ` + 2043 `_c2_0: type:VARCHAR value:"b" _c2_1: type:INT64 value:"3" _c2_2: type:INT64 value:"12"} ` + 2044 `sharded.-20: prefix values (:_c1_0, :_c1_1, :_c1_2) suffix ` + 2045 `{_c1_0: type:VARCHAR value:"a" _c1_1: type:INT64 value:"2" _c1_2: type:INT64 value:"11"} ` + 2046 `true false`, 2047 }) 2048 2049 // The insert id returned by ExecuteMultiShard should be overwritten by processGenerateFromValues. 2050 expectResult(t, "Execute", output, &sqltypes.Result{InsertID: 10}) 2051 } 2052 2053 func TestInsertSelectUnowned(t *testing.T) { 2054 invschema := &vschemapb.SrvVSchema{ 2055 Keyspaces: map[string]*vschemapb.Keyspace{ 2056 "sharded": { 2057 Sharded: true, 2058 Vindexes: map[string]*vschemapb.Vindex{ 2059 "hash": {Type: "hash"}, 2060 "onecol": { 2061 Type: "lookup_unique", 2062 Params: map[string]string{ 2063 "table": "lkp1", 2064 "from": "from", 2065 "to": "toc"}, 2066 Owner: "t1"}}, 2067 Tables: map[string]*vschemapb.Table{ 2068 "t2": { 2069 ColumnVindexes: []*vschemapb.ColumnVindex{{ 2070 Name: "onecol", 2071 Columns: []string{"id"}}}}}}}} 2072 2073 vs := vindexes.BuildVSchema(invschema) 2074 ks := vs.Keyspaces["sharded"] 2075 2076 ins := &Insert{ 2077 Opcode: InsertSelect, 2078 Keyspace: ks.Keyspace, 2079 Query: "dummy_insert", 2080 Table: ks.Tables["t2"], 2081 VindexValueOffset: [][]int{ 2082 {0}}, // the onecol vindex as unowned lookup sharding column 2083 Input: &Route{ 2084 Query: "dummy_select", 2085 FieldQuery: "dummy_field_query", 2086 RoutingParameters: &RoutingParameters{ 2087 Opcode: Scatter, 2088 Keyspace: ks.Keyspace}}} 2089 2090 ins.ColVindexes = append(ins.ColVindexes, ks.Tables["t2"].ColumnVindexes...) 2091 ins.Prefix = "prefix " 2092 ins.Suffix = " suffix" 2093 2094 vc := newDMLTestVCursor("-20", "20-") 2095 vc.shardForKsid = []string{"20-", "-20", "20-"} 2096 vc.results = []*sqltypes.Result{ 2097 sqltypes.MakeTestResult(sqltypes.MakeTestFields("id", "int64"), "1", "3", "2"), 2098 sqltypes.MakeTestResult(sqltypes.MakeTestFields("id|tocol", "int64|int64"), "1|1", "3|2", "2|3"), 2099 } 2100 2101 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 2102 require.NoError(t, err) 2103 2104 vc.ExpectLog(t, []string{ 2105 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 2106 2107 // the select query 2108 `ExecuteMultiShard sharded.-20: dummy_select {} sharded.20-: dummy_select {} false false`, 2109 2110 // select values into the unowned lookup vindex for routing 2111 `Execute select from, toc from lkp1 where from in ::from from: type:TUPLE values:{type:INT64 value:"1"} values:{type:INT64 value:"3"} values:{type:INT64 value:"2"} false`, 2112 2113 // values from lookup vindex resolved to destination 2114 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(31),DestinationKeyspaceID(32),DestinationKeyspaceID(33)`, 2115 2116 // insert values into the main table 2117 `ExecuteMultiShard ` + 2118 // first we insert two rows on the 20- shard 2119 `sharded.20-: prefix values (:_c0_0), (:_c2_0) suffix ` + 2120 `{_c0_0: type:INT64 value:"1" _c2_0: type:INT64 value:"2"} ` + 2121 2122 // next we insert one row on the -20 shard 2123 `sharded.-20: prefix values (:_c1_0) suffix ` + 2124 `{_c1_0: type:INT64 value:"3"} ` + 2125 `true false`}) 2126 2127 vc.Rewind() 2128 err = ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 2129 return nil 2130 }) 2131 require.NoError(t, err) 2132 vc.ExpectLog(t, []string{ 2133 `ResolveDestinations sharded [] Destinations:DestinationAllShards()`, 2134 2135 // the select query 2136 `StreamExecuteMulti dummy_select sharded.-20: {} sharded.20-: {} `, 2137 2138 // select values into the unowned lookup vindex for routing 2139 `Execute select from, toc from lkp1 where from in ::from from: type:TUPLE values:{type:INT64 value:"1"} values:{type:INT64 value:"3"} values:{type:INT64 value:"2"} false`, 2140 2141 // values from lookup vindex resolved to destination 2142 `ResolveDestinations sharded [value:"0" value:"1" value:"2"] Destinations:DestinationKeyspaceID(31),DestinationKeyspaceID(32),DestinationKeyspaceID(33)`, 2143 2144 // insert values into the main table 2145 `ExecuteMultiShard ` + 2146 // first we insert two rows on the 20- shard 2147 `sharded.20-: prefix values (:_c0_0), (:_c2_0) suffix ` + 2148 `{_c0_0: type:INT64 value:"1" _c2_0: type:INT64 value:"2"} ` + 2149 2150 // next we insert one row on the -20 shard 2151 `sharded.-20: prefix values (:_c1_0) suffix ` + 2152 `{_c1_0: type:INT64 value:"3"} ` + 2153 `true false`}) 2154 } 2155 2156 func TestInsertSelectShardingCases(t *testing.T) { 2157 invschema := &vschemapb.SrvVSchema{ 2158 Keyspaces: map[string]*vschemapb.Keyspace{ 2159 "sks1": { 2160 Sharded: true, 2161 Vindexes: map[string]*vschemapb.Vindex{"hash": {Type: "hash"}}, 2162 Tables: map[string]*vschemapb.Table{ 2163 "s1": { 2164 ColumnVindexes: []*vschemapb.ColumnVindex{{ 2165 Name: "hash", 2166 Columns: []string{"id"}}}}}}, 2167 "sks2": { 2168 Sharded: true, 2169 Vindexes: map[string]*vschemapb.Vindex{"hash": {Type: "hash"}}, 2170 Tables: map[string]*vschemapb.Table{ 2171 "s2": { 2172 ColumnVindexes: []*vschemapb.ColumnVindex{{ 2173 Name: "hash", 2174 Columns: []string{"id"}}}}}}, 2175 "uks1": {Tables: map[string]*vschemapb.Table{"u1": {}}}, 2176 "uks2": {Tables: map[string]*vschemapb.Table{"u2": {}}}, 2177 }} 2178 2179 vs := vindexes.BuildVSchema(invschema) 2180 sks1 := vs.Keyspaces["sks1"] 2181 sks2 := vs.Keyspaces["sks2"] 2182 uks1 := vs.Keyspaces["uks1"] 2183 uks2 := vs.Keyspaces["uks2"] 2184 2185 // sharded input route. 2186 sRoute := &Route{ 2187 Query: "dummy_select", 2188 FieldQuery: "dummy_field_query", 2189 RoutingParameters: &RoutingParameters{Opcode: Scatter, Keyspace: sks2.Keyspace}} 2190 2191 // unsharded input route. 2192 uRoute := &Route{ 2193 Query: "dummy_select", 2194 FieldQuery: "dummy_field_query", 2195 RoutingParameters: &RoutingParameters{Opcode: Unsharded, Keyspace: uks2.Keyspace}} 2196 2197 // sks1 and sks2 2198 ins := &Insert{ 2199 Opcode: InsertSelect, 2200 Keyspace: sks1.Keyspace, 2201 Query: "dummy_insert", 2202 Table: sks1.Tables["s1"], 2203 Prefix: "prefix ", 2204 Suffix: " suffix", 2205 ColVindexes: sks1.Tables["s1"].ColumnVindexes, 2206 VindexValueOffset: [][]int{{0}}, 2207 Input: sRoute, 2208 } 2209 2210 vc := &loggingVCursor{ 2211 resolvedTargetTabletType: topodatapb.TabletType_PRIMARY, 2212 ksShardMap: map[string][]string{ 2213 "sks1": {"-20", "20-"}, 2214 "sks2": {"-20", "20-"}, 2215 "uks1": {"0"}, 2216 "uks2": {"0"}, 2217 }, 2218 } 2219 vc.results = []*sqltypes.Result{ 2220 sqltypes.MakeTestResult(sqltypes.MakeTestFields("id", "int64"), "1")} 2221 2222 _, err := ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 2223 require.NoError(t, err) 2224 vc.ExpectLog(t, []string{ 2225 // the select query 2226 `ResolveDestinations sks2 [] Destinations:DestinationAllShards()`, 2227 `ExecuteMultiShard sks2.-20: dummy_select {} sks2.20-: dummy_select {} false false`, 2228 2229 // the query exec 2230 `ResolveDestinations sks1 [value:"0"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, 2231 `ExecuteMultiShard sks1.-20: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2232 2233 vc.Rewind() 2234 err = ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 2235 return nil 2236 }) 2237 require.NoError(t, err) 2238 vc.ExpectLog(t, []string{ 2239 // the select query 2240 `ResolveDestinations sks2 [] Destinations:DestinationAllShards()`, 2241 `StreamExecuteMulti dummy_select sks2.-20: {} sks2.20-: {} `, 2242 2243 // the query exec 2244 `ResolveDestinations sks1 [value:"0"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, 2245 `ExecuteMultiShard sks1.-20: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2246 2247 // sks1 and uks2 2248 ins.Input = uRoute 2249 2250 vc.Rewind() 2251 _, err = ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 2252 require.NoError(t, err) 2253 vc.ExpectLog(t, []string{ 2254 // the select query 2255 `ResolveDestinations uks2 [] Destinations:DestinationAllShards()`, 2256 `ExecuteMultiShard uks2.0: dummy_select {} false false`, 2257 2258 // the query exec 2259 `ResolveDestinations sks1 [value:"0"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, 2260 `ExecuteMultiShard sks1.-20: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2261 2262 vc.Rewind() 2263 err = ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 2264 return nil 2265 }) 2266 require.NoError(t, err) 2267 vc.ExpectLog(t, []string{ 2268 // the select query 2269 `ResolveDestinations uks2 [] Destinations:DestinationAllShards()`, 2270 `StreamExecuteMulti dummy_select uks2.0: {} `, 2271 2272 // the query exec 2273 `ResolveDestinations sks1 [value:"0"] Destinations:DestinationKeyspaceID(166b40b44aba4bd6)`, 2274 `ExecuteMultiShard sks1.-20: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2275 2276 // uks1 and sks2 2277 ins = &Insert{ 2278 Opcode: InsertUnsharded, 2279 Keyspace: uks1.Keyspace, 2280 Query: "dummy_insert", 2281 Table: uks1.Tables["s1"], 2282 Prefix: "prefix ", 2283 Suffix: " suffix", 2284 Input: sRoute, 2285 } 2286 2287 vc.Rewind() 2288 _, err = ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 2289 require.NoError(t, err) 2290 vc.ExpectLog(t, []string{ 2291 // the select query 2292 `ResolveDestinations sks2 [] Destinations:DestinationAllShards()`, 2293 `ExecuteMultiShard sks2.-20: dummy_select {} sks2.20-: dummy_select {} false false`, 2294 2295 // the query exec 2296 `ResolveDestinations uks1 [] Destinations:DestinationAllShards()`, 2297 `ExecuteMultiShard uks1.0: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2298 2299 vc.Rewind() 2300 err = ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 2301 return nil 2302 }) 2303 require.NoError(t, err) 2304 vc.ExpectLog(t, []string{ 2305 // the select query 2306 `ResolveDestinations sks2 [] Destinations:DestinationAllShards()`, 2307 `StreamExecuteMulti dummy_select sks2.-20: {} sks2.20-: {} `, 2308 2309 // the query exec 2310 `ResolveDestinations uks1 [] Destinations:DestinationAllShards()`, 2311 `ExecuteMultiShard uks1.0: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2312 2313 // uks1 and uks2 2314 ins.Input = uRoute 2315 2316 vc.Rewind() 2317 _, err = ins.TryExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false) 2318 require.NoError(t, err) 2319 vc.ExpectLog(t, []string{ 2320 // the select query 2321 `ResolveDestinations uks2 [] Destinations:DestinationAllShards()`, 2322 `ExecuteMultiShard uks2.0: dummy_select {} false false`, 2323 2324 // the query exec 2325 `ResolveDestinations uks1 [] Destinations:DestinationAllShards()`, 2326 `ExecuteMultiShard uks1.0: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2327 2328 vc.Rewind() 2329 err = ins.TryStreamExecute(context.Background(), vc, map[string]*querypb.BindVariable{}, false, func(result *sqltypes.Result) error { 2330 return nil 2331 }) 2332 require.NoError(t, err) 2333 vc.ExpectLog(t, []string{ 2334 // the select query 2335 `ResolveDestinations uks2 [] Destinations:DestinationAllShards()`, 2336 `StreamExecuteMulti dummy_select uks2.0: {} `, 2337 2338 // the query exec 2339 `ResolveDestinations uks1 [] Destinations:DestinationAllShards()`, 2340 `ExecuteMultiShard uks1.0: prefix values (:_c0_0) suffix {_c0_0: type:INT64 value:"1"} true true`}) 2341 }