From 17fac7f8f8b81fdca1f5b32695436cc4950eb369 Mon Sep 17 00:00:00 2001 From: Andres Taylor Date: Fri, 3 Jun 2022 09:20:48 +0200 Subject: [PATCH] fix V3: only use the special NoRoute handling mode when needed Signed-off-by: Andres Taylor --- go/test/endtoend/vtgate/sec_vind/main_test.go | 113 ++++++++++++++++++ go/test/endtoend/vtgate/sec_vind/schema.sql | 11 ++ go/test/endtoend/vtgate/sec_vind/vschema.json | 39 ++++++ go/vt/vtgate/executor_select_test.go | 4 +- go/vt/vtgate/planbuilder/select.go | 4 +- test/config.json | 9 ++ 6 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 go/test/endtoend/vtgate/sec_vind/main_test.go create mode 100644 go/test/endtoend/vtgate/sec_vind/schema.sql create mode 100644 go/test/endtoend/vtgate/sec_vind/vschema.json diff --git a/go/test/endtoend/vtgate/sec_vind/main_test.go b/go/test/endtoend/vtgate/sec_vind/main_test.go new file mode 100644 index 00000000000..cdcff0b4fa5 --- /dev/null +++ b/go/test/endtoend/vtgate/sec_vind/main_test.go @@ -0,0 +1,113 @@ +/* +Copyright 2022 The Vitess Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package vtgate + +import ( + "context" + _ "embed" + "flag" + "os" + "testing" + + "vitess.io/vitess/go/test/endtoend/utils" + + "github.com/stretchr/testify/require" + + "vitess.io/vitess/go/mysql" + "vitess.io/vitess/go/test/endtoend/cluster" +) + +var ( + clusterInstance *cluster.LocalProcessCluster + vtParams mysql.ConnParams + KeyspaceName = "ks" + Cell = "test" + //go:embed schema.sql + SchemaSQL string + + //go:embed vschema.json + VSchema string +) + +func TestMain(m *testing.M) { + defer cluster.PanicHandler(nil) + flag.Parse() + + exitCode := func() int { + clusterInstance = cluster.NewCluster(Cell, "localhost") + defer clusterInstance.Teardown() + + // Start topo server + err := clusterInstance.StartTopo() + if err != nil { + return 1 + } + + // Start keyspace + keyspace := &cluster.Keyspace{ + Name: KeyspaceName, + SchemaSQL: SchemaSQL, + VSchema: VSchema, + } + err = clusterInstance.StartKeyspace(*keyspace, []string{"-80", "80-"}, 1, true) + if err != nil { + return 1 + } + + // Start vtgate + err = clusterInstance.StartVtgate() + if err != nil { + return 1 + } + vtParams = mysql.ConnParams{ + Host: clusterInstance.Hostname, + Port: clusterInstance.VtgateMySQLPort, + } + return m.Run() + }() + os.Exit(exitCode) +} + +func start(t *testing.T) (*mysql.Conn, func()) { + ctx := context.Background() + conn, err := mysql.Connect(ctx, &vtParams) + require.Nil(t, err) + + deleteAll := func() { + _, _ = utils.ExecAllowError(t, conn, "set workload = oltp") + + tables := []string{"t1", "lookup_t1"} + for _, table := range tables { + _, _ = utils.ExecAllowError(t, conn, "delete from "+table) + } + } + + deleteAll() + + return conn, func() { + deleteAll() + conn.Close() + cluster.PanicHandler(t) + } +} + +func TestInAgainstSecondaryVindex(t *testing.T) { + conn, closer := start(t) + defer closer() + + utils.AssertMatches(t, conn, `select 1 from t1 where c2 in ("abc")`, "[]") +} diff --git a/go/test/endtoend/vtgate/sec_vind/schema.sql b/go/test/endtoend/vtgate/sec_vind/schema.sql new file mode 100644 index 00000000000..cc6413d315e --- /dev/null +++ b/go/test/endtoend/vtgate/sec_vind/schema.sql @@ -0,0 +1,11 @@ +CREATE TABLE t1 ( + c1 bigint unsigned NOT NULL, + c2 varchar(16) NOT NULL, + PRIMARY KEY (c1) +) ENGINE InnoDB; + +CREATE TABLE lookup_t1 ( + c2 varchar(16) NOT NULL, + keyspace_id varbinary(16) NOT NULL, + PRIMARY KEY (c2) +) ENGINE InnoDB; diff --git a/go/test/endtoend/vtgate/sec_vind/vschema.json b/go/test/endtoend/vtgate/sec_vind/vschema.json new file mode 100644 index 00000000000..9809137a508 --- /dev/null +++ b/go/test/endtoend/vtgate/sec_vind/vschema.json @@ -0,0 +1,39 @@ +{ + "sharded": true, + "vindexes": { + "lookup_idx": { + "type": "lookup", + "params": { + "from": "c2", + "to": "keyspace_id", + "table": "lookup_t1" + }, + "owner": "t1" + }, + "xxhash": { + "type": "xxhash" + } + }, + "tables": { + "t1": { + "columnVindexes": [ + { + "column": "c1", + "name": "xxhash" + }, + { + "column": "c2", + "name": "lookup_idx" + } + ] + }, + "lookup_t1": { + "columnVindexes": [ + { + "column": "c2", + "name": "xxhash" + } + ] + } + } +} \ No newline at end of file diff --git a/go/vt/vtgate/executor_select_test.go b/go/vt/vtgate/executor_select_test.go index f49cbffcbfe..d61e23b47ef 100644 --- a/go/vt/vtgate/executor_select_test.go +++ b/go/vt/vtgate/executor_select_test.go @@ -1106,7 +1106,7 @@ func TestSelectBindvars(t *testing.T) { }) require.NoError(t, err) wantQueries = []*querypb.BoundQuery{{ - Sql: "select id from `user` where `name` in ::__vals", + Sql: "select id from `user` where 1 != 1", BindVariables: map[string]*querypb.BindVariable{ "name1": sqltypes.BytesBindVariable([]byte("foo1")), "name2": sqltypes.BytesBindVariable([]byte("foo2")), @@ -1137,7 +1137,7 @@ func TestSelectBindvars(t *testing.T) { // When there are no matching rows in the vindex, vtgate still needs the field info wantQueries = []*querypb.BoundQuery{{ - Sql: "select id from `user` where `name` = :name", + Sql: "select id from `user` where 1 != 1", BindVariables: map[string]*querypb.BindVariable{ "name": sqltypes.StringBindVariable("nonexistent"), }, diff --git a/go/vt/vtgate/planbuilder/select.go b/go/vt/vtgate/planbuilder/select.go index 0145563f5bb..e1007be9381 100644 --- a/go/vt/vtgate/planbuilder/select.go +++ b/go/vt/vtgate/planbuilder/select.go @@ -79,7 +79,9 @@ func buildSelectPlan(query string) stmtPlanner { // if it doesn't find a shard to send the query to. // All other engine primitives can handle this, so we only need it when // Route is the last (and only) instruction before the user sees a result - rb.NoRoutesSpecialHandling = true + if isOnlyDual(sel) || (len(sel.GroupBy) == 0 && sel.SelectExprs.AllAggregation()) { + rb.NoRoutesSpecialHandling = true + } } return primitive, nil diff --git a/test/config.json b/test/config.json index 14c78fa7998..4dff455d9b0 100644 --- a/test/config.json +++ b/test/config.json @@ -1020,6 +1020,15 @@ "RetryMax": 2, "Tags": [] }, + "vindex_secondary": { + "File": "unused.go", + "Args": ["vitess.io/vitess/go/test/endtoend/vtgate/sec_vind"], + "Command": [], + "Manual": false, + "Shard": "vtgate_vindex_heavy", + "RetryMax": 2, + "Tags": [] + }, "web_test": { "File": "unused.go", "Args": ["vitess.io/vitess/go/test/endtoend/vtctldweb"],