diff --git a/go/vt/topo/topoproto/shard.go b/go/vt/topo/topoproto/shard.go index 00d5115c23e..282b9ec02c3 100644 --- a/go/vt/topo/topoproto/shard.go +++ b/go/vt/topo/topoproto/shard.go @@ -30,17 +30,6 @@ func ParseKeyspaceShard(param string) (string, string, error) { return keySpaceShard[0], keySpaceShard[1], nil } -// ParseKeyspaceOptionalShard parses a "keyspace/shard" string -// and extracts the parts. If a shard is not specified, it's -// returned as empty string. -func ParseKeyspaceOptionalShard(keyspaceShard string) (string, string) { - last := strings.LastIndex(keyspaceShard, "/") - if last == -1 { - return keyspaceShard, "" - } - return keyspaceShard[:last], keyspaceShard[last+1:] -} - // SourceShardString returns a printable view of a SourceShard. func SourceShardString(source *topodatapb.Shard_SourceShard) string { return fmt.Sprintf("SourceShard(%v,%v/%v)", source.Uid, source.Keyspace, source.Shard) diff --git a/go/vt/topo/topoproto/shard_test.go b/go/vt/topo/topoproto/shard_test.go index 22bc0d73810..ea8eb3313f4 100644 --- a/go/vt/topo/topoproto/shard_test.go +++ b/go/vt/topo/topoproto/shard_test.go @@ -31,36 +31,6 @@ func TestParseKeyspaceShard(t *testing.T) { } } -func TestParseKeyspaceOptionalShard(t *testing.T) { - testcases := []struct { - keyspaceShard string - keyspace string - shard string - }{{ - keyspaceShard: "ks", - keyspace: "ks", - shard: "", - }, { - keyspaceShard: "/-80", - keyspace: "", - shard: "-80", - }, { - keyspaceShard: "ks/-80", - keyspace: "ks", - shard: "-80", - }, { - keyspaceShard: "ks/", - keyspace: "ks", - shard: "", - }} - - for _, tcase := range testcases { - if keyspace, shard := ParseKeyspaceOptionalShard(tcase.keyspaceShard); keyspace != tcase.keyspace || shard != tcase.shard { - t.Errorf("parseKeyspaceShard(%s): %s:%s, want %s:%s", tcase.keyspaceShard, keyspace, shard, tcase.keyspace, tcase.shard) - } - } -} - func TestSourceShardAsHTML(t *testing.T) { s := &topodatapb.Shard_SourceShard{ Uid: 123, diff --git a/go/vt/vtgate/vtgate.go b/go/vt/vtgate/vtgate.go index bc493ff04f9..79d11e4f176 100644 --- a/go/vt/vtgate/vtgate.go +++ b/go/vt/vtgate/vtgate.go @@ -34,6 +34,8 @@ import ( "github.com/youtube/vitess/go/vt/vtgate/gateway" "github.com/youtube/vitess/go/vt/vtgate/vtgateservice" + "strings" + querypb "github.com/youtube/vitess/go/vt/proto/query" topodatapb "github.com/youtube/vitess/go/vt/proto/topodata" vtgatepb "github.com/youtube/vitess/go/vt/proto/vtgate" @@ -248,7 +250,7 @@ func (vtg *VTGate) Execute(ctx context.Context, sql string, bindVariables map[st vtg.localBegin(session) } - keyspace, shard := topoproto.ParseKeyspaceOptionalShard(keyspaceShard) + keyspace, shard := parseKeyspaceOptionalShard(keyspaceShard) if shard != "" { sql = sqlannotation.AnnotateIfDML(sql, nil) f := func(keyspace string) (string, []string, error) { @@ -578,7 +580,7 @@ func (vtg *VTGate) StreamExecute(ctx context.Context, sql string, bindVariables statsKey := []string{"StreamExecute", "Any", ltt} defer vtg.timings.Record(statsKey, startTime) - keyspace, shard := topoproto.ParseKeyspaceOptionalShard(keyspaceShard) + keyspace, shard := parseKeyspaceOptionalShard(keyspaceShard) var err error if shard != "" { err = vtg.resolver.streamExecute( @@ -1043,3 +1045,15 @@ func annotateBoundShardQueriesAsUnfriendly(queries []*vtgatepb.BoundShardQuery) queries[i].Query.Sql = sqlannotation.AnnotateIfDML(q.Query.Sql, nil) } } + +// parseKeyspaceOptionalShard parses a "keyspace/shard" or "keyspace:shard" string +// and extracts the parts. If a shard is not specified, it's +// returned as empty string. We need to support : and / in vtgate because some clients +// can't support our default of /. Everywhere else we only support /. +func parseKeyspaceOptionalShard(keyspaceShard string) (string, string) { + last := strings.LastIndexAny(keyspaceShard, "/:") + if last == -1 { + return keyspaceShard, "" + } + return keyspaceShard[:last], keyspaceShard[last+1:] +} diff --git a/go/vt/vtgate/vtgate_test.go b/go/vt/vtgate/vtgate_test.go index 0cdf336ca96..600c5e25fdc 100644 --- a/go/vt/vtgate/vtgate_test.go +++ b/go/vt/vtgate/vtgate_test.go @@ -2683,3 +2683,29 @@ func TestVTGateShowMetadataTwoShards(t *testing.T) { t.Errorf("shard %s not found in Values \n%+v", shard1, qr.Rows) } } + +func TestParseKeyspaceOptionalShard(t *testing.T) { + testcases := []struct { + keyspaceShard string + keyspace string + shard string + }{{ + keyspaceShard: "ks", + keyspace: "ks", + shard: "", + }, { + keyspaceShard: "ks/-80", + keyspace: "ks", + shard: "-80", + }, { + keyspaceShard: "ks:-80", + keyspace: "ks", + shard: "-80", + }} + + for _, tcase := range testcases { + if keyspace, shard := parseKeyspaceOptionalShard(tcase.keyspaceShard); keyspace != tcase.keyspace || shard != tcase.shard { + t.Errorf("parseKeyspaceShard(%s): %s:%s, want %s:%s", tcase.keyspaceShard, keyspace, shard, tcase.keyspace, tcase.shard) + } + } +}