Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for issue with information_schema queries with both table name and schema name predicates #8087

Merged
merged 4 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go/test/endtoend/vtgate/system_schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ func TestInformationSchemaQuery(t *testing.T) {
assertResultIsEmpty(t, conn, "table_schema = 'PERFORMANCE_SCHEMA'")
assertSingleRowIsReturned(t, conn, "table_schema = 'performance_schema' and table_name = 'users'", "performance_schema")
assertResultIsEmpty(t, conn, "table_schema = 'performance_schema' and table_name = 'foo'")
assertSingleRowIsReturned(t, conn, "table_schema = 'vt_ks' and table_name = 't1'", "vt_ks")
assertSingleRowIsReturned(t, conn, "table_schema = 'ks' and table_name = 't1'", "vt_ks")
}

func assertResultIsEmpty(t *testing.T, conn *mysql.Conn, pre string) {
Expand Down
5 changes: 5 additions & 0 deletions go/vt/vtgate/engine/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,11 @@ func (route *Route) routeInfoSchemaQuery(vcursor VCursor, bindVars map[string]*q
if tableName != "" {
rss, err := route.paramsRoutedTable(vcursor, bindVars, specifiedKS, tableName)
if err != nil {
// Only if keyspace is not found in vschema, we try with default keyspace.
// As the in the table_schema predicates for a keyspace 'ks' it can contain 'vt_ks'.
if vterrors.ErrState(err) == vterrors.BadDb {
return defaultRoute()
}
return nil, err
}
if rss != nil {
Expand Down
29 changes: 28 additions & 1 deletion go/vt/vtgate/executor_select_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ func TestSelectDBA(t *testing.T) {
require.NoError(t, err)
wantQueries := []*querypb.BoundQuery{{Sql: query, BindVariables: map[string]*querypb.BindVariable{}}}
utils.MustMatch(t, wantQueries, sbc1.Queries)
sbc1.Queries = nil

sbc1.Queries = nil
query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema = 'performance_schema' AND table_name = 'foo'"
_, err = executor.Execute(context.Background(), "TestSelectDBA",
NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}),
Expand All @@ -85,6 +85,33 @@ func TestSelectDBA(t *testing.T) {
}}}
utils.MustMatch(t, wantQueries, sbc1.Queries)

sbc1.Queries = nil
query = "select 1 from information_schema.table_constraints where constraint_schema = 'vt_ks' and table_name = 'user'"
_, err = executor.Execute(context.Background(), "TestSelectDBA",
NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}),
query, map[string]*querypb.BindVariable{},
)
require.NoError(t, err)
wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname and table_name = :__vttablename",
BindVariables: map[string]*querypb.BindVariable{
"__vtschemaname": sqltypes.StringBindVariable("vt_ks"),
"__vttablename": sqltypes.StringBindVariable("user"),
}}}
utils.MustMatch(t, wantQueries, sbc1.Queries)

sbc1.Queries = nil
query = "select 1 from information_schema.table_constraints where constraint_schema = 'vt_ks'"
_, err = executor.Execute(context.Background(), "TestSelectDBA",
NewSafeSession(&vtgatepb.Session{TargetString: "TestExecutor"}),
query, map[string]*querypb.BindVariable{},
)
require.NoError(t, err)
wantQueries = []*querypb.BoundQuery{{Sql: "select 1 from information_schema.table_constraints where constraint_schema = :__vtschemaname",
BindVariables: map[string]*querypb.BindVariable{
"__vtschemaname": sqltypes.StringBindVariable("vt_ks"),
}}}
utils.MustMatch(t, wantQueries, sbc1.Queries)

}

func TestUnsharded(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/planbuilder/testdata/ddl_cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@

#Alter table with unknown qualifier
"alter table a.b ADD id int"
"keyspace a not found in vschema"
"Unknown database 'a' in vschema"

# create db foo
"create database foo"
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/planbuilder/testdata/from_cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ Gen4 plan same as above

# routing rules bad table
"select * from bad_table"
"keyspace noks not found in vschema"
"Unknown database 'noks' in vschema"
Gen4 plan same as above

# routing rules disabled table
Expand Down
7 changes: 5 additions & 2 deletions go/vt/vtgate/vindexes/vschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
"io/ioutil"
"sort"

vtrpcpb "vitess.io/vitess/go/vt/proto/vtrpc"
"vitess.io/vitess/go/vt/vterrors"

"vitess.io/vitess/go/json2"
"vitess.io/vitess/go/sqltypes"
"vitess.io/vitess/go/vt/sqlparser"
Expand Down Expand Up @@ -481,7 +484,7 @@ func (vschema *VSchema) findTable(keyspace, tablename string) (*Table, error) {
}
ks, ok := vschema.Keyspaces[keyspace]
if !ok {
return nil, fmt.Errorf("keyspace %s not found in vschema", keyspace)
return nil, vterrors.NewErrorf(vtrpcpb.Code_NOT_FOUND, vterrors.BadDb, "Unknown database '%s' in vschema", keyspace)
}
table := ks.Tables[tablename]
if table == nil {
Expand Down Expand Up @@ -559,7 +562,7 @@ func (vschema *VSchema) FindVindex(keyspace, name string) (Vindex, error) {
}
ks, ok := vschema.Keyspaces[keyspace]
if !ok {
return nil, fmt.Errorf("keyspace %s not found in vschema", keyspace)
return nil, vterrors.NewErrorf(vtrpcpb.Code_NOT_FOUND, vterrors.BadDb, "Unknown database '%s' in vschema", keyspace)
}
return ks.Vindexes[name], nil
}
Expand Down
47 changes: 16 additions & 31 deletions go/vt/vtgate/vindexes/vschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ func TestVSchemaRoutingRules(t *testing.T) {
Error: errors.New("table t1 must be qualified"),
},
"badkeyspace": {
Error: errors.New("keyspace ks3 not found in vschema"),
Error: errors.New("Unknown database 'ks3' in vschema"),
},
"notfound": {
Error: errors.New("table t2 not found"),
Expand Down Expand Up @@ -2156,53 +2156,38 @@ func TestFindTable(t *testing.T) {
}
vschema, _ := BuildVSchema(&input)
_, err := vschema.FindTable("", "t1")
wantErr := "ambiguous table reference: t1"
if err == nil || err.Error() != wantErr {
t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr)
}
require.EqualError(t, err, "ambiguous table reference: t1")

_, err = vschema.FindTable("", "none")
wantErr = "table none not found"
if err == nil || err.Error() != wantErr {
t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr)
}
got, err := vschema.FindTable("", "ta")
if err != nil {
t.Error(err)
return
}
require.EqualError(t, err, "table none not found")

ta := &Table{
Name: sqlparser.NewTableIdent("ta"),
Keyspace: &Keyspace{
Name: "ksa",
},
}
if !reflect.DeepEqual(got, ta) {
t.Errorf("FindTable(\"t1a\"): %+v, want %+v", got, ta)
}
got, err := vschema.FindTable("", "ta")
require.NoError(t, err)
require.Equal(t, ta, got)

got, _ = vschema.FindTable("ksa", "ta")
if !reflect.DeepEqual(got, ta) {
t.Errorf("FindTable(\"t1a\"): %+v, want %+v", got, ta)
}
require.Equal(t, ta, got)

none := &Table{
Name: sqlparser.NewTableIdent("none"),
Keyspace: &Keyspace{
Name: "ksa",
},
}
got, _ = vschema.FindTable("ksa", "none")
if !reflect.DeepEqual(got, none) {
t.Errorf("FindTable(\"t1a\"): %+v, want %+v", got, none)
}
require.Equal(t, none, got)

_, err = vschema.FindTable("ksb", "none")
wantErr = "table none not found"
if err == nil || err.Error() != wantErr {
t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr)
}
require.EqualError(t, err, "table none not found")

_, err = vschema.FindTable("none", "aa")
wantErr = "keyspace none not found in vschema"
if err == nil || err.Error() != wantErr {
t.Errorf("FindTable(\"\"): %v, want %s", err, wantErr)
}
require.EqualError(t, err, "Unknown database 'none' in vschema")
}

func TestFindTableOrVindex(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion go/vt/vtgate/vtgate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ func TestVTGateExecuteWithKeyspaceShard(t *testing.T) {
"select id from none",
nil,
)
want := "keyspace invalid_keyspace not found in vschema"
want := "Unknown database 'invalid_keyspace' in vschema"
assert.EqualError(t, err, want)

// Valid keyspace/shard.
Expand Down