Skip to content

Commit

Permalink
Add missing tables to globally routed list in schema tracker only if …
Browse files Browse the repository at this point in the history
…they are not already present in a VSchema

Signed-off-by: Rohit Nayak <rohit@planetscale.com>
  • Loading branch information
rohit-nayak-ps committed Dec 11, 2024
1 parent 747a61c commit 5ed2dcb
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 4 deletions.
37 changes: 37 additions & 0 deletions go/test/endtoend/vtgate/gen4/gen4_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,3 +520,40 @@ func TestDualJoinQueries(t *testing.T) {
mcmp.Exec("select t.title, t2.id from t2 left join (select 'ABC' as title) as t on t.title = t2.tcol1")

}

// TestSchemaTrackingGlobalTables tests that schema tracking works as intended with global table routing.
// This test creates a new table in a schema and verifies we can query it without needing to add it to the vschema as long
// as the name of the table is unique. It also creates a table which is already in the vschema to ensure that we
// don't mark it as ambiguous when schema tracking also finds it.
func TestSchemaTrackingGlobalTables(t *testing.T) {
// Create a new vtgate connection.
tables := []string{"uniqueTableName", "t1"}
for _, table := range tables {
t.Run(table, func(t *testing.T) {
vtConn, err := mysql.Connect(context.Background(), &vtParams)
require.NoError(t, err)
defer vtConn.Close()

// Create a new table in the unsharded keyspace such that it has a unique name that allows for global routing.
utils.Exec(t, vtConn, `use `+unshardedKs)
// Use the same schema as t1 from sharded_schema.sql
utils.Exec(t, vtConn, fmt.Sprintf(`create table if not exists %s(id bigint, col bigint, primary key(id))`, table))
defer utils.Exec(t, vtConn, fmt.Sprintf(`drop table %s`, table))

// Wait for schema tracking to see this column.
err = utils.WaitForAuthoritative(t, unshardedKs, table, clusterInstance.VtgateProcess.ReadVSchema)
require.NoError(t, err)

// Create a new vtgate connection.
vtConn2, err := mysql.Connect(context.Background(), &vtParams)
require.NoError(t, err)
defer vtConn2.Close()

// Insert rows into the table and select them to verify we can use them.
utils.Exec(t, vtConn2, fmt.Sprintf(`insert into %s(id, col) values (10, 100),(20, 200)`, table))
require.NoError(t, err)
utils.AssertMatches(t, vtConn2, fmt.Sprintf(`select * from %s order by id`, table),
`[[INT64(10) INT64(100)] [INT64(20) INT64(200)]]`)
})
}
}
12 changes: 8 additions & 4 deletions go/vt/vtgate/vindexes/vschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ func BuildVSchema(source *vschemapb.SrvVSchema, parser *sqlparser.Parser) (vsche
buildKeyspaces(source, vschema, parser)
// buildGlobalTables before buildReferences so that buildReferences can
// resolve sources which reference global tables.
buildGlobalTables(source, vschema)
BuildGlobalTables(source, vschema, true)
buildReferences(source, vschema)
buildRoutingRule(source, vschema, parser)
buildShardRoutingRule(source, vschema)
Expand Down Expand Up @@ -461,23 +461,27 @@ func (vschema *VSchema) AddUDF(ksname, udfName string) error {
return nil
}

func buildGlobalTables(source *vschemapb.SrvVSchema, vschema *VSchema) {
func BuildGlobalTables(source *vschemapb.SrvVSchema, vschema *VSchema, skipIfAlreadyGlobal bool) {
for ksname, ks := range source.Keyspaces {
ksvschema := vschema.Keyspaces[ksname]
// If the keyspace requires explicit routing, don't include any of
// its tables in global tables.
if ks.RequireExplicitRouting {
continue
}
buildKeyspaceGlobalTables(vschema, ksvschema)
buildKeyspaceGlobalTables(vschema, ksvschema, skipIfAlreadyGlobal)
}
}

func buildKeyspaceGlobalTables(vschema *VSchema, ksvschema *KeyspaceSchema) {
func buildKeyspaceGlobalTables(vschema *VSchema, ksvschema *KeyspaceSchema, skipIfAlreadyGlobal bool) {
for tname, t := range ksvschema.Tables {
if gt, ok := vschema.globalTables[tname]; ok {
// There is already an entry table stored in global tables
// with this name.
if !skipIfAlreadyGlobal {
// Called when updating from schema tracking
continue
}
if gt == nil {
// Table name is already marked ambiguous, nothing to do.
continue
Expand Down
4 changes: 4 additions & 0 deletions go/vt/vtgate/vschema_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,10 @@ func (vm *VSchemaManager) buildAndEnhanceVSchema(v *vschemapb.SrvVSchema) *vinde
// We mark the keyspaces that have foreign key management in Vitess and have cyclic foreign keys
// to have an error. This makes all queries against them to fail.
markErrorIfCyclesInFk(vschema)
// Add tables from schema tracking into globally routable tables, if they are not already present.
// We need to skip if already present, to handle the case where MoveTables has switched traffic
// and removed the source vschema but not from the source database because user asked to --keep-data
vindexes.BuildGlobalTables(v, vschema, false)
}
return vschema
}
Expand Down

0 comments on commit 5ed2dcb

Please sign in to comment.