From f139939e29ed976d1025380dc151e156b2686f36 Mon Sep 17 00:00:00 2001 From: Alain Jobart Date: Mon, 14 Mar 2016 08:19:31 -0700 Subject: [PATCH] Fixing a bug in table blacklisting. If a tablet has blacklisted table rules that don't match any existing tables, don't blacklist exverything. In the process, allowing schema changes on databases with views, as the integration test needs it, and it's a good fix anyway. --- go/vt/mysqlctl/schema.go | 12 ++++++++++-- go/vt/tabletmanager/state_change.go | 16 +++++++++++----- test/vertical_split.py | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/go/vt/mysqlctl/schema.go b/go/vt/mysqlctl/schema.go index 301105c053..5be5a7b03c 100644 --- a/go/vt/mysqlctl/schema.go +++ b/go/vt/mysqlctl/schema.go @@ -218,6 +218,14 @@ func (mysqld *Mysqld) PreflightSchemaChange(dbName string, change string) (*tmut sql += td.Schema + ";\n" } } + for _, td := range beforeSchema.TableDefinitions { + if td.Type == tmutils.TableView { + // Views will have {{.DatabaseName}} in there, replace + // it with _vt_preflight + s := strings.Replace(td.Schema, "`{{.DatabaseName}}`", "`_vt_preflight`", -1) + sql += s + ";\n" + } + } if err = mysqld.executeMysqlCommands(mysqld.dba.Uname, sql); err != nil { return nil, err } @@ -249,7 +257,7 @@ func (mysqld *Mysqld) PreflightSchemaChange(dbName string, change string) (*tmut // ApplySchemaChange will apply the schema change to the given database. func (mysqld *Mysqld) ApplySchemaChange(dbName string, change *tmutils.SchemaChange) (*tmutils.SchemaChangeResult, error) { // check current schema matches - beforeSchema, err := mysqld.GetSchema(dbName, nil, nil, false) + beforeSchema, err := mysqld.GetSchema(dbName, nil, nil, true) if err != nil { return nil, err } @@ -296,7 +304,7 @@ func (mysqld *Mysqld) ApplySchemaChange(dbName string, change *tmutils.SchemaCha } // get AfterSchema - afterSchema, err := mysqld.GetSchema(dbName, nil, nil, false) + afterSchema, err := mysqld.GetSchema(dbName, nil, nil, true) if err != nil { return nil, err } diff --git a/go/vt/tabletmanager/state_change.go b/go/vt/tabletmanager/state_change.go index 36a7d662ea..4bed616a36 100644 --- a/go/vt/tabletmanager/state_change.go +++ b/go/vt/tabletmanager/state_change.go @@ -51,12 +51,18 @@ func (agent *ActionAgent) loadBlacklistRules(tablet *topodatapb.Tablet, blacklis if err != nil { return err } - log.Infof("Blacklisting tables %v", strings.Join(tables, ", ")) - qr := tabletserver.NewQueryRule("enforce blacklisted tables", "blacklisted_table", tabletserver.QRFailRetry) - for _, t := range tables { - qr.AddTableCond(t) + + // if the wildcards resolve into real tables, blacklist them. + // (if there are no tables here, the rule would blacklist + // all queries, oops). + if len(tables) > 0 { + log.Infof("Blacklisting tables %v", strings.Join(tables, ", ")) + qr := tabletserver.NewQueryRule("enforce blacklisted tables", "blacklisted_table", tabletserver.QRFailRetry) + for _, t := range tables { + qr.AddTableCond(t) + } + blacklistRules.Add(qr) } - blacklistRules.Add(qr) } loadRuleErr := agent.QueryServiceControl.SetQueryRules(blacklistQueryRules, blacklistRules) diff --git a/test/vertical_split.py b/test/vertical_split.py index 3bc9a84765..af06a27c09 100755 --- a/test/vertical_split.py +++ b/test/vertical_split.py @@ -536,6 +536,24 @@ index by_msg (msg) # check the stats are correct self._check_stats() + # now remove the tables on the source shard. The blacklisted tables + # in the source shard won't match any table, make sure that works. + utils.run_vtctl(['ApplySchema', + '-sql=drop view view1', + 'source_keyspace'], + auto_log=True) + for t in ['moving1', 'moving2']: + utils.run_vtctl(['ApplySchema', + '-sql=drop table %s' % (t), + 'source_keyspace'], + auto_log=True) + for t in [source_master, source_replica, source_rdonly1, source_rdonly2]: + utils.run_vtctl(['ReloadSchema', t.tablet_alias]) + qr = source_master.execute('select count(1) from staying1') + self.assertEqual(len(qr['rows']), 1, + 'cannot read staying1: got %s' % str(qr)) + + # test SetShardTabletControl self._verify_vtctl_set_shard_tablet_control() def _verify_vtctl_set_shard_tablet_control(self):