// helper method to asynchronously diff a schema func (wr *Wrangler) diffSchema(ctx context.Context, masterSchema *myproto.SchemaDefinition, masterTabletAlias, alias *pb.TabletAlias, excludeTables []string, includeViews bool, wg *sync.WaitGroup, er concurrency.ErrorRecorder) { defer wg.Done() log.Infof("Gathering schema for %v", alias) slaveSchema, err := wr.GetSchema(ctx, alias, nil, excludeTables, includeViews) if err != nil { er.RecordError(err) return } log.Infof("Diffing schema for %v", alias) myproto.DiffSchema(topo.TabletAliasString(masterTabletAlias), masterSchema, topo.TabletAliasString(alias), slaveSchema, er) }
// diffPermissions is a helper method to asynchronously diff a permissions func (wr *Wrangler) diffPermissions(ctx context.Context, masterPermissions *tabletmanagerdatapb.Permissions, masterAlias *pb.TabletAlias, alias *pb.TabletAlias, wg *sync.WaitGroup, er concurrency.ErrorRecorder) { defer wg.Done() log.Infof("Gathering permissions for %v", topoproto.TabletAliasString(alias)) slavePermissions, err := wr.GetPermissions(ctx, alias) if err != nil { er.RecordError(err) return } log.Infof("Diffing permissions for %v", topoproto.TabletAliasString(alias)) tmutils.DiffPermissions(topoproto.TabletAliasString(masterAlias), masterPermissions, topoproto.TabletAliasString(alias), slavePermissions, er) }
// helper method to asynchronously diff a schema func (wr *Wrangler) diffSchema(masterSchema *mysqlctl.SchemaDefinition, masterTabletAlias, alias topo.TabletAlias, includeViews bool, wg *sync.WaitGroup, er concurrency.ErrorRecorder) { defer wg.Done() relog.Info("Gathering schema for %v", alias) slaveSchema, err := wr.GetSchema(alias, nil, includeViews) if err != nil { er.RecordError(err) return } relog.Info("Diffing schema for %v", alias) mysqlctl.DiffSchema(masterTabletAlias.String(), masterSchema, alias.String(), slaveSchema, er) }
// diffPermissions is a helper method to asynchronously diff a permissions func (wr *Wrangler) diffPermissions(ctx context.Context, masterPermissions *myproto.Permissions, masterAlias topo.TabletAlias, alias topo.TabletAlias, wg *sync.WaitGroup, er concurrency.ErrorRecorder) { defer wg.Done() log.Infof("Gathering permissions for %v", alias) slavePermissions, err := wr.GetPermissions(ctx, alias) if err != nil { er.RecordError(err) return } log.Infof("Diffing permissions for %v", alias) myproto.DiffPermissions(masterAlias.String(), masterPermissions, alias.String(), slavePermissions, er) }
// helper method to asynchronously get and diff a version func (wr *Wrangler) diffVersion(ctx context.Context, masterVersion string, masterAlias *pb.TabletAlias, alias *pb.TabletAlias, wg *sync.WaitGroup, er concurrency.ErrorRecorder) { defer wg.Done() log.Infof("Gathering version for %v", topo.TabletAliasString(alias)) slaveVersion, err := wr.GetVersion(ctx, alias) if err != nil { er.RecordError(err) return } if masterVersion != slaveVersion { er.RecordError(fmt.Errorf("Master %v version %v is different than slave %v version %v", topo.TabletAliasString(masterAlias), masterVersion, topo.TabletAliasString(alias), slaveVersion)) } }
func diffPermissions(name, leftName string, left permissionList, rightName string, right permissionList, er concurrency.ErrorRecorder) { leftIndex := 0 rightIndex := 0 for leftIndex < left.Len() && rightIndex < right.Len() { lpk, lval := left.Get(leftIndex) rpk, rval := right.Get(rightIndex) // extra value on the left side if lpk < rpk { er.RecordError(fmt.Errorf("%v has an extra %v %v", leftName, name, lpk)) leftIndex++ continue } // extra value on the right side if lpk > rpk { er.RecordError(fmt.Errorf("%v has an extra %v %v", rightName, name, rpk)) rightIndex++ continue } // same name, let's see content if lval != rval { er.RecordError(fmt.Errorf("%v and %v disagree on %v %v:\n%v\n differs from:\n%v", leftName, rightName, name, lpk, lval, rval)) } leftIndex++ rightIndex++ } for leftIndex < left.Len() { lpk, _ := left.Get(leftIndex) er.RecordError(fmt.Errorf("%v has an extra %v %v", leftName, name, lpk)) leftIndex++ } for rightIndex < right.Len() { rpk, _ := right.Get(rightIndex) er.RecordError(fmt.Errorf("%v has an extra %v %v", rightName, name, rpk)) rightIndex++ } }
func diffPermissions(name, leftName string, left PermissionList, rightName string, right PermissionList, er concurrency.ErrorRecorder) { leftIndex := 0 rightIndex := 0 for leftIndex < left.Len() && rightIndex < right.Len() { l := left.Get(leftIndex) r := right.Get(rightIndex) // extra value on the left side if l.PrimaryKey() < r.PrimaryKey() { er.RecordError(fmt.Errorf("%v has an extra %v %v", leftName, name, l.PrimaryKey())) leftIndex++ continue } // extra value on the right side if l.PrimaryKey() > r.PrimaryKey() { er.RecordError(fmt.Errorf("%v has an extra %v %v", rightName, name, r.PrimaryKey())) rightIndex++ continue } // same name, let's see content if l.String() != r.String() { er.RecordError(fmt.Errorf("%v and %v disagree on %v %v:\n%v\n differs from:\n%v", leftName, rightName, name, l.PrimaryKey(), l.String(), r.String())) } leftIndex++ rightIndex++ } for leftIndex < left.Len() { er.RecordError(fmt.Errorf("%v has an extra %v %v", leftName, name, left.Get(leftIndex).PrimaryKey())) leftIndex++ } for rightIndex < right.Len() { er.RecordError(fmt.Errorf("%v has an extra %v %v", rightName, name, right.Get(rightIndex).PrimaryKey())) rightIndex++ } }
// generates a report on what's different between two SchemaDefinition // for now, we skip the VIEW entirely. func DiffSchema(leftName string, left *SchemaDefinition, rightName string, right *SchemaDefinition, er concurrency.ErrorRecorder) { if left.DatabaseSchema != right.DatabaseSchema { er.RecordError(fmt.Errorf("%v and %v don't agree on database creation command:\n%v\n differs from:\n%v", leftName, rightName, left.DatabaseSchema, right.DatabaseSchema)) } leftIndex := 0 rightIndex := 0 for leftIndex < len(left.TableDefinitions) && rightIndex < len(right.TableDefinitions) { // skip views if left.TableDefinitions[leftIndex].Type == TABLE_VIEW { leftIndex++ continue } if right.TableDefinitions[rightIndex].Type == TABLE_VIEW { rightIndex++ continue } // extra table on the left side if left.TableDefinitions[leftIndex].Name < right.TableDefinitions[rightIndex].Name { er.RecordError(fmt.Errorf("%v has an extra table named %v", leftName, left.TableDefinitions[leftIndex].Name)) leftIndex++ continue } // extra table on the right side if left.TableDefinitions[leftIndex].Name > right.TableDefinitions[rightIndex].Name { er.RecordError(fmt.Errorf("%v has an extra table named %v", rightName, right.TableDefinitions[rightIndex].Name)) rightIndex++ continue } // same name, let's see content if left.TableDefinitions[leftIndex].Schema != right.TableDefinitions[rightIndex].Schema { er.RecordError(fmt.Errorf("%v and %v disagree on schema for table %v:\n%v\n differs from:\n%v", leftName, rightName, left.TableDefinitions[leftIndex].Name, left.TableDefinitions[leftIndex].Schema, right.TableDefinitions[rightIndex].Schema)) } leftIndex++ rightIndex++ } for leftIndex < len(left.TableDefinitions) { if left.TableDefinitions[leftIndex].Type == TABLE_BASE_TABLE { er.RecordError(fmt.Errorf("%v has an extra table named %v", leftName, left.TableDefinitions[leftIndex].Name)) } leftIndex++ } for rightIndex < len(right.TableDefinitions) { if right.TableDefinitions[rightIndex].Type == TABLE_BASE_TABLE { er.RecordError(fmt.Errorf("%v has an extra table named %v", rightName, right.TableDefinitions[rightIndex].Name)) } rightIndex++ } }
// DiffSchema generates a report on what's different between two SchemaDefinitions // including views. func DiffSchema(leftName string, left *SchemaDefinition, rightName string, right *SchemaDefinition, er concurrency.ErrorRecorder) { if left == nil && right == nil { return } if left == nil || right == nil { er.RecordError(fmt.Errorf("%v and %v are different, %s: %v, %s: %v", leftName, rightName, leftName, left, rightName, right)) return } if left.DatabaseSchema != right.DatabaseSchema { er.RecordError(fmt.Errorf("%v and %v don't agree on database creation command:\n%v\n differs from:\n%v", leftName, rightName, left.DatabaseSchema, right.DatabaseSchema)) } leftIndex := 0 rightIndex := 0 for leftIndex < len(left.TableDefinitions) && rightIndex < len(right.TableDefinitions) { // extra table on the left side if left.TableDefinitions[leftIndex].Name < right.TableDefinitions[rightIndex].Name { er.RecordError(fmt.Errorf("%v has an extra table named %v", leftName, left.TableDefinitions[leftIndex].Name)) leftIndex++ continue } // extra table on the right side if left.TableDefinitions[leftIndex].Name > right.TableDefinitions[rightIndex].Name { er.RecordError(fmt.Errorf("%v has an extra table named %v", rightName, right.TableDefinitions[rightIndex].Name)) rightIndex++ continue } // same name, let's see content if left.TableDefinitions[leftIndex].Schema != right.TableDefinitions[rightIndex].Schema { er.RecordError(fmt.Errorf("%v and %v disagree on schema for table %v:\n%v\n differs from:\n%v", leftName, rightName, left.TableDefinitions[leftIndex].Name, left.TableDefinitions[leftIndex].Schema, right.TableDefinitions[rightIndex].Schema)) } if left.TableDefinitions[leftIndex].Type != right.TableDefinitions[rightIndex].Type { er.RecordError(fmt.Errorf("%v and %v disagree on table type for table %v:\n%v\n differs from:\n%v", leftName, rightName, left.TableDefinitions[leftIndex].Name, left.TableDefinitions[leftIndex].Type, right.TableDefinitions[rightIndex].Type)) } leftIndex++ rightIndex++ } for leftIndex < len(left.TableDefinitions) { if left.TableDefinitions[leftIndex].Type == TableBaseTable { er.RecordError(fmt.Errorf("%v has an extra table named %v", leftName, left.TableDefinitions[leftIndex].Name)) } if left.TableDefinitions[leftIndex].Type == TableView { er.RecordError(fmt.Errorf("%v has an extra view named %v", leftName, left.TableDefinitions[leftIndex].Name)) } leftIndex++ } for rightIndex < len(right.TableDefinitions) { if right.TableDefinitions[rightIndex].Type == TableBaseTable { er.RecordError(fmt.Errorf("%v has an extra table named %v", rightName, right.TableDefinitions[rightIndex].Name)) } if right.TableDefinitions[rightIndex].Type == TableView { er.RecordError(fmt.Errorf("%v has an extra view named %v", rightName, right.TableDefinitions[rightIndex].Name)) } rightIndex++ } }