diff --git a/go/vt/key/destination.go b/go/vt/key/destination.go index 2f3e32c88c5..ca7867fa501 100644 --- a/go/vt/key/destination.go +++ b/go/vt/key/destination.go @@ -19,6 +19,7 @@ package key import ( "bytes" "encoding/hex" + "math/rand" "strings" "vitess.io/vitess/go/vt/vterrors" @@ -27,6 +28,9 @@ import ( vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc" ) +// AnyShardPicker makes a choice on what shard to use when any shard will do. Used for testing. +var AnyShardPicker DestinationAnyShardPicker = DestinationAnyShardPickerRandomShard{} + // Destination is an interface definition for a query destination, // within a given Keyspace / Tablet Type. It is meant to be an internal // data structure, with multiple possible implementations. @@ -369,12 +373,25 @@ func (d DestinationKeyspaceIDs) String() string { return buffer.String() } +// DestinationAnyShardPicker exposes an interface that will pick an index given a number of available shards. +type DestinationAnyShardPicker interface { + // PickShard picks a shard given a number of shards + PickShard(shardCount int) int +} + +// DestinationAnyShardPickerRandomShard picks a random shard. +type DestinationAnyShardPickerRandomShard struct{} + +// PickShard is DestinationAnyShardPickerRandomShard's implmentation. +func (dp DestinationAnyShardPickerRandomShard) PickShard(shardCount int) int { + return rand.Intn(shardCount) +} + // // DestinationAnyShard // -// DestinationAnyShard is the destination for any one shard in the -// keyspace. This usually maps to the first one in the list. +// DestinationAnyShard is the destination for any one shard in the keyspace. // It implements the Destination interface. type DestinationAnyShard struct{} @@ -388,7 +405,7 @@ func (d DestinationAnyShard) Resolve(allShards []*topodatapb.ShardReference, add if len(allShards) == 0 { return vterrors.Errorf(vtrpcpb.Code_UNAVAILABLE, "no shard in keyspace") } - return addShard(allShards[0].Name) + return addShard(allShards[AnyShardPicker.PickShard(len(allShards))].Name) } // String is part of the Destination interface. diff --git a/go/vt/vtgate/engine/insert.go b/go/vt/vtgate/engine/insert.go index 72d5e20da56..a1ead406736 100644 --- a/go/vt/vtgate/engine/insert.go +++ b/go/vt/vtgate/engine/insert.go @@ -78,6 +78,37 @@ type Insert struct { MultiShardAutocommit bool } +// NewQueryInsert creates an Insert with a query string. +func NewQueryInsert(opcode InsertOpcode, keyspace *vindexes.Keyspace, query string) *Insert { + return &Insert{ + Opcode: opcode, + Keyspace: keyspace, + Query: query, + } +} + +// NewSimpleInsert creates an Insert for a Table. +func NewSimpleInsert(opcode InsertOpcode, table *vindexes.Table, keyspace *vindexes.Keyspace) *Insert { + return &Insert{ + Opcode: opcode, + Table: table, + Keyspace: keyspace, + } +} + +// NewInsert creates a new Insert. +func NewInsert(opcode InsertOpcode, keyspace *vindexes.Keyspace, vindexValues []sqltypes.PlanValue, table *vindexes.Table, prefix string, mid []string, suffix string) *Insert { + return &Insert{ + Opcode: opcode, + Keyspace: keyspace, + VindexValues: vindexValues, + Table: table, + Prefix: prefix, + Mid: mid, + Suffix: suffix, + } +} + // MarshalJSON serializes the Insert into a JSON representation. // It's used for testing and diagnostics. func (ins *Insert) MarshalJSON() ([]byte, error) { diff --git a/go/vt/vtgate/engine/insert_test.go b/go/vt/vtgate/engine/insert_test.go index 5353588c73d..70722ad2c18 100644 --- a/go/vt/vtgate/engine/insert_test.go +++ b/go/vt/vtgate/engine/insert_test.go @@ -28,14 +28,14 @@ import ( ) func TestInsertUnsharded(t *testing.T) { - ins := &Insert{ - Opcode: InsertUnsharded, - Keyspace: &vindexes.Keyspace{ + ins := NewQueryInsert( + InsertUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_insert", - } + "dummy_insert", + ) vc := &loggingVCursor{ shards: []string{"0"}, @@ -64,27 +64,27 @@ func TestInsertUnsharded(t *testing.T) { } func TestInsertUnshardedGenerate(t *testing.T) { - ins := &Insert{ - Opcode: InsertUnsharded, - Keyspace: &vindexes.Keyspace{ + ins := NewQueryInsert( + InsertUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_insert", - Generate: &Generate{ - Keyspace: &vindexes.Keyspace{ - Name: "ks2", - Sharded: false, - }, - Query: "dummy_generate", - Values: sqltypes.PlanValue{ - Values: []sqltypes.PlanValue{ - {Value: sqltypes.NewInt64(1)}, - {Value: sqltypes.NULL}, - {Value: sqltypes.NewInt64(2)}, - {Value: sqltypes.NULL}, - {Value: sqltypes.NewInt64(3)}, - }, + "dummy_insert", + ) + ins.Generate = &Generate{ + Keyspace: &vindexes.Keyspace{ + Name: "ks2", + Sharded: false, + }, + Query: "dummy_generate", + Values: sqltypes.PlanValue{ + Values: []sqltypes.PlanValue{ + {Value: sqltypes.NewInt64(1)}, + {Value: sqltypes.NULL}, + {Value: sqltypes.NewInt64(2)}, + {Value: sqltypes.NULL}, + {Value: sqltypes.NewInt64(3)}, }, }, } @@ -147,10 +147,10 @@ func TestInsertShardedSimple(t *testing.T) { ks := vs.Keyspaces["sharded"] // A single row insert should be autocommitted - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // 3 rows. @@ -159,11 +159,11 @@ func TestInsertShardedSimple(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1"}, + " suffix", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, shardForKsid: []string{"20-", "-20", "20-"}, @@ -182,10 +182,10 @@ func TestInsertShardedSimple(t *testing.T) { }) // Multiple rows are not autocommitted by default - ins = &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins = NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // 3 rows. @@ -198,11 +198,11 @@ func TestInsertShardedSimple(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) vc = &loggingVCursor{ shards: []string{"-20", "20-"}, shardForKsid: []string{"20-", "-20", "20-"}, @@ -222,10 +222,10 @@ func TestInsertShardedSimple(t *testing.T) { }) // Optional flag overrides autocommit - ins = &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins = NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // 3 rows. @@ -238,12 +238,13 @@ func TestInsertShardedSimple(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - MultiShardAutocommit: true, - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) + ins.MultiShardAutocommit = true + vc = &loggingVCursor{ shards: []string{"-20", "20-"}, shardForKsid: []string{"20-", "-20", "20-"}, @@ -295,10 +296,10 @@ func TestInsertShardedFail(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // 1 row @@ -307,11 +308,11 @@ func TestInsertShardedFail(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) vc := &loggingVCursor{} @@ -347,10 +348,10 @@ func TestInsertShardedGenerate(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // 3 rows. @@ -363,24 +364,25 @@ func TestInsertShardedGenerate(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Generate: &Generate{ - Keyspace: &vindexes.Keyspace{ - Name: "ks2", - Sharded: false, - }, - Query: "dummy_generate", - Values: sqltypes.PlanValue{ - Values: []sqltypes.PlanValue{ - {Value: sqltypes.NewInt64(1)}, - {Value: sqltypes.NULL}, - {Value: sqltypes.NewInt64(2)}, - }, + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) + + ins.Generate = &Generate{ + Keyspace: &vindexes.Keyspace{ + Name: "ks2", + Sharded: false, + }, + Query: "dummy_generate", + Values: sqltypes.PlanValue{ + Values: []sqltypes.PlanValue{ + {Value: sqltypes.NewInt64(1)}, + {Value: sqltypes.NULL}, + {Value: sqltypes.NewInt64(2)}, }, }, - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", } vc := &loggingVCursor{ @@ -472,10 +474,10 @@ func TestInsertShardedOwned(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -521,11 +523,11 @@ func TestInsertShardedOwned(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -599,10 +601,10 @@ func TestInsertShardedOwnedWithNull(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -619,11 +621,11 @@ func TestInsertShardedOwnedWithNull(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -698,10 +700,10 @@ func TestInsertShardedIgnoreOwned(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertShardedIgnore, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertShardedIgnore, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -755,11 +757,11 @@ func TestInsertShardedIgnoreOwned(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3", " mid4"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3", " mid4"}, + " suffix", + ) ksid0 := sqltypes.MakeTestResult( sqltypes.MakeTestFields( @@ -872,10 +874,10 @@ func TestInsertShardedIgnoreOwnedWithNull(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertShardedIgnore, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertShardedIgnore, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -892,11 +894,11 @@ func TestInsertShardedIgnoreOwnedWithNull(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3", " mid4"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3", " mid4"}, + " suffix", + ) ksid0 := sqltypes.MakeTestResult( sqltypes.MakeTestFields( @@ -978,10 +980,10 @@ func TestInsertShardedUnownedVerify(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -1027,11 +1029,11 @@ func TestInsertShardedUnownedVerify(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) // nonemptyResult will cause the lookup verify queries to succeed. nonemptyResult := sqltypes.MakeTestResult( @@ -1122,10 +1124,10 @@ func TestInsertShardedIgnoreUnownedVerify(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertShardedIgnore, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertShardedIgnore, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -1150,11 +1152,11 @@ func TestInsertShardedIgnoreUnownedVerify(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) // nonemptyResult will cause the lookup verify queries to succeed. nonemptyResult := sqltypes.MakeTestResult( @@ -1236,10 +1238,10 @@ func TestInsertShardedIgnoreUnownedVerifyFail(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -1256,11 +1258,11 @@ func TestInsertShardedIgnoreUnownedVerifyFail(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -1318,10 +1320,10 @@ func TestInsertShardedUnownedReverseMap(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -1367,11 +1369,11 @@ func TestInsertShardedUnownedReverseMap(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) // nonemptyResult will cause the lookup verify queries to succeed. nonemptyResult := sqltypes.MakeTestResult( @@ -1448,10 +1450,10 @@ func TestInsertShardedUnownedReverseMapFail(t *testing.T) { } ks := vs.Keyspaces["sharded"] - ins := &Insert{ - Opcode: InsertSharded, - Keyspace: ks.Keyspace, - VindexValues: []sqltypes.PlanValue{{ + ins := NewInsert( + InsertSharded, + ks.Keyspace, + []sqltypes.PlanValue{{ // colVindex columns: id Values: []sqltypes.PlanValue{{ // rows for id @@ -1468,11 +1470,11 @@ func TestInsertShardedUnownedReverseMapFail(t *testing.T) { }}, }}, }}, - Table: ks.Tables["t1"], - Prefix: "prefix", - Mid: []string{" mid1", " mid2", " mid3"}, - Suffix: " suffix", - } + ks.Tables["t1"], + "prefix", + []string{" mid1", " mid2", " mid3"}, + " suffix", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, diff --git a/go/vt/vtgate/engine/route.go b/go/vt/vtgate/engine/route.go index 470cc8f93c1..fb6678bd23c 100644 --- a/go/vt/vtgate/engine/route.go +++ b/go/vt/vtgate/engine/route.go @@ -83,6 +83,24 @@ type Route struct { ScatterErrorsAsWarnings bool } +// NewSimpleRoute creates a Route with the bare minimum of parameters. +func NewSimpleRoute(opcode RouteOpcode, keyspace *vindexes.Keyspace) *Route { + return &Route{ + Opcode: opcode, + Keyspace: keyspace, + } +} + +// NewRoute creates a Route. +func NewRoute(opcode RouteOpcode, keyspace *vindexes.Keyspace, query, fieldQuery string) *Route { + return &Route{ + Opcode: opcode, + Keyspace: keyspace, + Query: query, + FieldQuery: fieldQuery, + } +} + // OrderbyParams specifies the parameters for ordering. // This is used for merge-sorting scatter queries. type OrderbyParams struct { diff --git a/go/vt/vtgate/engine/route_test.go b/go/vt/vtgate/engine/route_test.go index 7aaf3fb3ce7..682e6f0d788 100644 --- a/go/vt/vtgate/engine/route_test.go +++ b/go/vt/vtgate/engine/route_test.go @@ -35,15 +35,15 @@ var defaultSelectResult = sqltypes.MakeTestResult( ) func TestSelectUnsharded(t *testing.T) { - sel := &Route{ - Opcode: SelectUnsharded, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - } + "dummy_select", + "dummy_select_field", + ) vc := &loggingVCursor{ shards: []string{"0"}, @@ -72,15 +72,15 @@ func TestSelectUnsharded(t *testing.T) { } func TestSelectScatter(t *testing.T) { - sel := &Route{ - Opcode: SelectScatter, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectScatter, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - } + "dummy_select", + "dummy_select_field", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -110,17 +110,17 @@ func TestSelectScatter(t *testing.T) { func TestSelectEqualUnique(t *testing.T) { vindex, _ := vindexes.NewHash("", nil) - sel := &Route{ - Opcode: SelectEqualUnique, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectEqualUnique, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - Vindex: vindex, - Values: []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}, - } + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex + sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}} vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -155,17 +155,17 @@ func TestSelectEqualUniqueScatter(t *testing.T) { "to": "toc", "write_only": "true", }) - sel := &Route{ - Opcode: SelectEqualUnique, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectEqualUnique, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - Vindex: vindex, - Values: []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}, - } + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex + sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}} vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -199,17 +199,17 @@ func TestSelectEqual(t *testing.T) { "from": "from", "to": "toc", }) - sel := &Route{ - Opcode: SelectEqual, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectEqual, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - Vindex: vindex, - Values: []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}, - } + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex + sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}} vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -255,17 +255,17 @@ func TestSelectEqualNoRoute(t *testing.T) { "from": "from", "to": "toc", }) - sel := &Route{ - Opcode: SelectEqual, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectEqual, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - Vindex: vindex, - Values: []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}, - } + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex + sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}} vc := &loggingVCursor{shards: []string{"-20", "20-"}} result, err := sel.Execute(vc, map[string]*querypb.BindVariable{}, false) @@ -292,25 +292,25 @@ func TestSelectEqualNoRoute(t *testing.T) { func TestSelectINUnique(t *testing.T) { vindex, _ := vindexes.NewHash("", nil) - sel := &Route{ - Opcode: SelectIN, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectIN, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - Vindex: vindex, + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex + sel.Values = []sqltypes.PlanValue{{ Values: []sqltypes.PlanValue{{ - Values: []sqltypes.PlanValue{{ - Value: sqltypes.NewInt64(1), - }, { - Value: sqltypes.NewInt64(2), - }, { - Value: sqltypes.NewInt64(4), - }}, + Value: sqltypes.NewInt64(1), + }, { + Value: sqltypes.NewInt64(2), + }, { + Value: sqltypes.NewInt64(4), }}, - } + }} vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -348,25 +348,25 @@ func TestSelectINNonUnique(t *testing.T) { "from": "from", "to": "toc", }) - sel := &Route{ - Opcode: SelectIN, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectIN, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - Vindex: vindex, + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex + sel.Values = []sqltypes.PlanValue{{ Values: []sqltypes.PlanValue{{ - Values: []sqltypes.PlanValue{{ - Value: sqltypes.NewInt64(1), - }, { - Value: sqltypes.NewInt64(2), - }, { - Value: sqltypes.NewInt64(4), - }}, + Value: sqltypes.NewInt64(1), + }, { + Value: sqltypes.NewInt64(2), + }, { + Value: sqltypes.NewInt64(4), }}, - } + }} fields := sqltypes.MakeTestFields( "toc", @@ -426,15 +426,15 @@ func TestSelectINNonUnique(t *testing.T) { } func TestSelectNext(t *testing.T) { - sel := &Route{ - Opcode: SelectNext, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectNext, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - } + "dummy_select", + "dummy_select_field", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -456,15 +456,15 @@ func TestSelectNext(t *testing.T) { } func TestSelectDBA(t *testing.T) { - sel := &Route{ - Opcode: SelectDBA, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectDBA, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - } + "dummy_select", + "dummy_select_field", + ) vc := &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -491,17 +491,17 @@ func TestRouteGetFields(t *testing.T) { "from": "from", "to": "toc", }) - sel := &Route{ - Opcode: SelectEqual, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectEqual, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - Vindex: vindex, - Values: []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}}, - } + "dummy_select", + "dummy_select_field", + ) + sel.Vindex = vindex + sel.Values = []sqltypes.PlanValue{{Value: sqltypes.NewInt64(1)}} vc := &loggingVCursor{shards: []string{"-20", "20-"}} result, err := sel.Execute(vc, map[string]*querypb.BindVariable{}, true) @@ -531,18 +531,18 @@ func TestRouteGetFields(t *testing.T) { } func TestRouteSort(t *testing.T) { - sel := &Route{ - Opcode: SelectUnsharded, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - OrderBy: []OrderbyParams{{ - Col: 0, - }}, - } + "dummy_select", + "dummy_select_field", + ) + sel.OrderBy = []OrderbyParams{{ + Col: 0, + }} vc := &loggingVCursor{ shards: []string{"0"}, @@ -616,19 +616,19 @@ func TestRouteSort(t *testing.T) { } func TestRouteSortTruncate(t *testing.T) { - sel := &Route{ - Opcode: SelectUnsharded, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - OrderBy: []OrderbyParams{{ - Col: 0, - }}, - TruncateColumnCount: 1, - } + "dummy_select", + "dummy_select_field", + ) + sel.OrderBy = []OrderbyParams{{ + Col: 0, + }} + sel.TruncateColumnCount = 1 vc := &loggingVCursor{ shards: []string{"0"}, @@ -667,16 +667,16 @@ func TestRouteSortTruncate(t *testing.T) { } func TestRouteStreamTruncate(t *testing.T) { - sel := &Route{ - Opcode: SelectUnsharded, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - TruncateColumnCount: 1, - } + "dummy_select", + "dummy_select_field", + ) + sel.TruncateColumnCount = 1 vc := &loggingVCursor{ shards: []string{"0"}, @@ -711,19 +711,19 @@ func TestRouteStreamTruncate(t *testing.T) { } func TestRouteStreamSortTruncate(t *testing.T) { - sel := &Route{ - Opcode: SelectUnsharded, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - OrderBy: []OrderbyParams{{ - Col: 0, - }}, - TruncateColumnCount: 1, - } + "dummy_select", + "dummy_select_field", + ) + sel.OrderBy = []OrderbyParams{{ + Col: 0, + }} + sel.TruncateColumnCount = 1 vc := &loggingVCursor{ shards: []string{"0"}, @@ -762,15 +762,15 @@ func TestRouteStreamSortTruncate(t *testing.T) { } func TestParamsFail(t *testing.T) { - sel := &Route{ - Opcode: SelectUnsharded, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - } + "dummy_select", + "dummy_select_field", + ) vc := &loggingVCursor{shardErr: errors.New("shard error")} _, err := sel.Execute(vc, map[string]*querypb.BindVariable{}, false) @@ -783,15 +783,15 @@ func TestParamsFail(t *testing.T) { func TestExecFail(t *testing.T) { // Unsharded error - sel := &Route{ - Opcode: SelectUnsharded, - Keyspace: &vindexes.Keyspace{ + sel := NewRoute( + SelectUnsharded, + &vindexes.Keyspace{ Name: "ks", Sharded: false, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - } + "dummy_select", + "dummy_select_field", + ) vc := &loggingVCursor{shards: []string{"0"}, resultErr: mysql.NewSQLError(mysql.ERQueryInterrupted, "", "query timeout")} _, err := sel.Execute(vc, map[string]*querypb.BindVariable{}, false) @@ -803,15 +803,15 @@ func TestExecFail(t *testing.T) { expectError(t, "sel.StreamExecute err", err, "query timeout (errno 1317) (sqlstate HY000)") // Scatter fails if one of N fails without ScatterErrorsAsWarnings - sel = &Route{ - Opcode: SelectScatter, - Keyspace: &vindexes.Keyspace{ + sel = NewRoute( + SelectScatter, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - } + "dummy_select", + "dummy_select_field", + ) vc = &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -831,16 +831,16 @@ func TestExecFail(t *testing.T) { vc.Rewind() // Scatter succeeds if all shards fail with ScatterErrorsAsWarnings - sel = &Route{ - Opcode: SelectScatter, - Keyspace: &vindexes.Keyspace{ + sel = NewRoute( + SelectScatter, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - ScatterErrorsAsWarnings: true, - } + "dummy_select", + "dummy_select_field", + ) + sel.ScatterErrorsAsWarnings = true vc = &loggingVCursor{ shards: []string{"-20", "20-"}, @@ -869,16 +869,16 @@ func TestExecFail(t *testing.T) { vc.Rewind() // Scatter succeeds if one of N fails with ScatterErrorsAsWarnings - sel = &Route{ - Opcode: SelectScatter, - Keyspace: &vindexes.Keyspace{ + sel = NewRoute( + SelectScatter, + &vindexes.Keyspace{ Name: "ks", Sharded: true, }, - Query: "dummy_select", - FieldQuery: "dummy_select_field", - ScatterErrorsAsWarnings: true, - } + "dummy_select", + "dummy_select_field", + ) + sel.ScatterErrorsAsWarnings = true vc = &loggingVCursor{ shards: []string{"-20", "20-"}, diff --git a/go/vt/vtgate/executor_framework_test.go b/go/vt/vtgate/executor_framework_test.go index 36f4909ee00..26f86cbae6f 100644 --- a/go/vt/vtgate/executor_framework_test.go +++ b/go/vt/vtgate/executor_framework_test.go @@ -267,6 +267,12 @@ var unshardedVSchema = ` } ` +type DestinationAnyShardPickerFirstShard struct{} + +func (dp DestinationAnyShardPickerFirstShard) PickShard(shardCount int) int { + return 0 +} + // keyRangeLookuper is for testing a lookup that returns a keyrange. type keyRangeLookuper struct { } @@ -353,6 +359,7 @@ func createExecutorEnv() (executor *Executor, sbc1, sbc2, sbclookup *sandboxconn getSandbox(KsTestUnsharded).VSchema = unshardedVSchema executor = NewExecutor(context.Background(), serv, cell, "", resolver, false, testBufferSize, testCacheSize, false) + key.AnyShardPicker = DestinationAnyShardPickerFirstShard{} return executor, sbc1, sbc2, sbclookup } diff --git a/go/vt/vtgate/planbuilder/from.go b/go/vt/vtgate/planbuilder/from.go index af0319a3dfe..dd598cc9510 100644 --- a/go/vt/vtgate/planbuilder/from.go +++ b/go/vt/vtgate/planbuilder/from.go @@ -149,10 +149,7 @@ func (pb *primitiveBuilder) buildTablePrimitive(tableExpr *sqlparser.AliasedTabl return err } rb, st := newRoute(sel, nil, nil) - rb.ERoute = &engine.Route{ - Opcode: engine.SelectDBA, - Keyspace: ks, - } + rb.ERoute = engine.NewSimpleRoute(engine.SelectDBA, ks) pb.bldr, pb.st = rb, st return nil } @@ -172,28 +169,20 @@ func (pb *primitiveBuilder) buildTablePrimitive(tableExpr *sqlparser.AliasedTabl _ = st.AddVindexTable(alias, table, rb) if !table.Keyspace.Sharded { - rb.ERoute = &engine.Route{ - Opcode: engine.SelectUnsharded, - Keyspace: table.Keyspace, - } + rb.ERoute = engine.NewSimpleRoute(engine.SelectUnsharded, table.Keyspace) return nil } if table.Pinned == nil { - rb.ERoute = &engine.Route{ - Opcode: engine.SelectScatter, - Keyspace: table.Keyspace, - TargetDestination: destTarget, - TargetTabletType: destTableType, - } + rb.ERoute = engine.NewSimpleRoute(engine.SelectScatter, table.Keyspace) + rb.ERoute.TargetDestination = destTarget + rb.ERoute.TargetTabletType = destTableType + return nil } // Pinned tables have their keyspace ids already assigned. // Use the Binary vindex, which is the identity function // for keyspace id. Currently only dual tables are pinned. - eRoute := &engine.Route{ - Opcode: engine.SelectEqualUnique, - Keyspace: table.Keyspace, - } + eRoute := engine.NewSimpleRoute(engine.SelectEqualUnique, table.Keyspace) eRoute.Vindex, _ = vindexes.NewBinary("binary", nil) eRoute.Values = []sqltypes.PlanValue{{Value: sqltypes.MakeTrusted(sqltypes.VarBinary, table.Pinned)}} rb.ERoute = eRoute diff --git a/go/vt/vtgate/planbuilder/insert.go b/go/vt/vtgate/planbuilder/insert.go index 4ba900513b0..7046dfcdee6 100644 --- a/go/vt/vtgate/planbuilder/insert.go +++ b/go/vt/vtgate/planbuilder/insert.go @@ -59,11 +59,11 @@ func buildInsertPlan(ins *sqlparser.Insert, vschema ContextVSchema) (*engine.Ins } func buildInsertUnshardedPlan(ins *sqlparser.Insert, table *vindexes.Table, vschema ContextVSchema) (*engine.Insert, error) { - eins := &engine.Insert{ - Opcode: engine.InsertUnsharded, - Table: table, - Keyspace: table.Keyspace, - } + eins := engine.NewSimpleInsert( + engine.InsertUnsharded, + table, + table.Keyspace, + ) var rows sqlparser.Values switch insertValues := ins.Rows.(type) { case *sqlparser.Select, *sqlparser.Union: @@ -99,11 +99,11 @@ func buildInsertUnshardedPlan(ins *sqlparser.Insert, table *vindexes.Table, vsch } func buildInsertShardedPlan(ins *sqlparser.Insert, table *vindexes.Table) (*engine.Insert, error) { - eins := &engine.Insert{ - Opcode: engine.InsertSharded, - Table: table, - Keyspace: table.Keyspace, - } + eins := engine.NewSimpleInsert( + engine.InsertSharded, + table, + table.Keyspace, + ) if ins.Ignore != "" { eins.Opcode = engine.InsertShardedIgnore }