diff --git a/go/vt/vttablet/onlineddl/executor.go b/go/vt/vttablet/onlineddl/executor.go index 048b4e7ce62..a55f690f581 100644 --- a/go/vt/vttablet/onlineddl/executor.go +++ b/go/vt/vttablet/onlineddl/executor.go @@ -1989,7 +1989,7 @@ func (e *Executor) terminateMigration(ctx context.Context, onlineDDL *schema.Onl // CancelMigration attempts to abort a scheduled or a running migration func (e *Executor) CancelMigration(ctx context.Context, uuid string, message string, issuedByUser bool) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } log.Infof("CancelMigration: request to cancel %s with message: %v", uuid, message) @@ -2060,7 +2060,7 @@ func (e *Executor) cancelMigrations(ctx context.Context, cancellable []*cancella // for this keyspace func (e *Executor) CancelPendingMigrations(ctx context.Context, message string, issuedByUser bool) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } uuids, err := e.readPendingMigrationsUUIDs(ctx) @@ -4335,7 +4335,7 @@ func (e *Executor) retryMigrationWhere(ctx context.Context, whereExpr string) (r // RetryMigration marks given migration for retry func (e *Executor) RetryMigration(ctx context.Context, uuid string) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } if !schema.IsOnlineDDLUUID(uuid) { return nil, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "Not a valid migration ID in RETRY: %s", uuid) @@ -4359,7 +4359,7 @@ func (e *Executor) RetryMigration(ctx context.Context, uuid string) (result *sql // next iteration of gcArtifacts() picks up the migration's artifacts and schedules them for deletion func (e *Executor) CleanupMigration(ctx context.Context, uuid string) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } if !schema.IsOnlineDDLUUID(uuid) { return nil, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "Not a valid migration ID in CLEANUP: %s", uuid) @@ -4385,7 +4385,7 @@ func (e *Executor) CleanupMigration(ctx context.Context, uuid string) (result *s // CompleteMigration clears the postpone_completion flag for a given migration, assuming it was set in the first place func (e *Executor) CompleteMigration(ctx context.Context, uuid string) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } if !schema.IsOnlineDDLUUID(uuid) { return nil, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "Not a valid migration ID in COMPLETE: %s", uuid) @@ -4419,7 +4419,7 @@ func (e *Executor) CompleteMigration(ctx context.Context, uuid string) (result * // for this keyspace func (e *Executor) CompletePendingMigrations(ctx context.Context) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } uuids, err := e.readPendingMigrationsUUIDs(ctx) @@ -4444,7 +4444,7 @@ func (e *Executor) CompletePendingMigrations(ctx context.Context) (result *sqlty // LaunchMigration clears the postpone_launch flag for a given migration, assuming it was set in the first place func (e *Executor) LaunchMigration(ctx context.Context, uuid string, shardsArg string) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } if !schema.IsOnlineDDLUUID(uuid) { return nil, vterrors.Errorf(vtrpcpb.Code_UNKNOWN, "Not a valid migration ID in EXECUTE: %s", uuid) @@ -4476,7 +4476,7 @@ func (e *Executor) LaunchMigration(ctx context.Context, uuid string, shardsArg s // LaunchMigrations launches all launch-postponed queued migrations for this keyspace func (e *Executor) LaunchMigrations(ctx context.Context) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } uuids, err := e.readPendingMigrationsUUIDs(ctx) @@ -4598,7 +4598,7 @@ func (e *Executor) SubmitMigration( stmt sqlparser.Statement, ) (*sqltypes.Result, error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } log.Infof("SubmitMigration: request to submit migration with statement: %0.50s...", sqlparser.CanonicalString(stmt)) @@ -4693,10 +4693,35 @@ func (e *Executor) SubmitMigration( return result, nil } +// ShowMigrations shows migrations, optionally filtered by a condition +func (e *Executor) ShowMigrations(ctx context.Context, show *sqlparser.Show) (result *sqltypes.Result, err error) { + if atomic.LoadInt64(&e.isOpen) == 0 { + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) + } + showBasic, ok := show.Internal.(*sqlparser.ShowBasic) + if !ok { + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] ShowMigrations expects a ShowBasic statement. Got: %s", sqlparser.String(show)) + } + if showBasic.Command != sqlparser.VitessMigrations { + return nil, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "[BUG] ShowMigrations expects a VitessMigrations command, got %+v. Statement: %s", showBasic.Command, sqlparser.String(show)) + } + whereExpr := "" + if showBasic.Filter != nil { + if showBasic.Filter.Filter != nil { + whereExpr = fmt.Sprintf(" where %s", sqlparser.String(showBasic.Filter.Filter)) + } else if showBasic.Filter.Like != "" { + lit := sqlparser.String(sqlparser.NewStrLiteral(showBasic.Filter.Like)) + whereExpr = fmt.Sprintf(" where migration_uuid LIKE %s OR migration_context LIKE %s OR migration_status LIKE %s", lit, lit, lit) + } + } + query := sqlparser.BuildParsedQuery(sqlShowMigrationsWhere, whereExpr).Query + return e.execQuery(ctx, query) +} + // ShowMigrationLogs reads the migration log for a given migration func (e *Executor) ShowMigrationLogs(ctx context.Context, stmt *sqlparser.ShowMigrationLogs) (result *sqltypes.Result, err error) { if atomic.LoadInt64(&e.isOpen) == 0 { - return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, "online ddl is disabled") + return nil, vterrors.New(vtrpcpb.Code_FAILED_PRECONDITION, schema.ErrOnlineDDLDisabled.Error()) } _, row, err := e.readMigration(ctx, stmt.UUID) if err != nil { diff --git a/go/vt/vttablet/onlineddl/schema.go b/go/vt/vttablet/onlineddl/schema.go index 90babe05b20..c35591fd5a9 100644 --- a/go/vt/vttablet/onlineddl/schema.go +++ b/go/vt/vttablet/onlineddl/schema.go @@ -359,6 +359,10 @@ const ( AND cleanup_timestamp IS NULL AND completed_timestamp IS NULL ` + sqlShowMigrationsWhere = `SELECT * + FROM _vt.schema_migrations + %s + ` sqlSelectMigration = `SELECT id, migration_uuid, diff --git a/go/vt/vttablet/tabletserver/planbuilder/builder.go b/go/vt/vttablet/tabletserver/planbuilder/builder.go index 980adf3efb5..89388812d70 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/builder.go +++ b/go/vt/vttablet/tabletserver/planbuilder/builder.go @@ -135,7 +135,10 @@ func analyzeInsert(ins *sqlparser.Insert, tables map[string]*schema.Table) (plan func analyzeShow(show *sqlparser.Show, dbName string) (plan *Plan, err error) { switch showInternal := show.Internal.(type) { case *sqlparser.ShowBasic: - if showInternal.Command == sqlparser.Table { + switch showInternal.Command { + case sqlparser.VitessMigrations: + return &Plan{PlanID: PlanShowMigrations, FullStmt: show}, nil + case sqlparser.Table: // rewrite WHERE clause if it exists // `where Tables_in_Keyspace` => `where Tables_in_DbName` if showInternal.Filter != nil { diff --git a/go/vt/vttablet/tabletserver/planbuilder/plan.go b/go/vt/vttablet/tabletserver/planbuilder/plan.go index 603ea455ac7..842f6349665 100644 --- a/go/vt/vttablet/tabletserver/planbuilder/plan.go +++ b/go/vt/vttablet/tabletserver/planbuilder/plan.go @@ -76,6 +76,7 @@ const ( PlanCallProc PlanAlterMigration PlanRevertMigration + PlanShowMigrations PlanShowMigrationLogs PlanShowThrottledApps PlanShowThrottlerStatus @@ -112,6 +113,7 @@ var planName = []string{ "CallProcedure", "AlterMigration", "RevertMigration", + "ShowMigrations", "ShowMigrationLogs", "ShowThrottledApps", "ShowThrottlerStatus", diff --git a/go/vt/vttablet/tabletserver/query_executor.go b/go/vt/vttablet/tabletserver/query_executor.go index e342b2b6b18..eb8ef76dcd0 100644 --- a/go/vt/vttablet/tabletserver/query_executor.go +++ b/go/vt/vttablet/tabletserver/query_executor.go @@ -204,6 +204,8 @@ func (qre *QueryExecutor) Execute() (reply *sqltypes.Result, err error) { return qre.execAlterMigration() case p.PlanRevertMigration: return qre.execRevertMigration() + case p.PlanShowMigrations: + return qre.execShowMigrations() case p.PlanShowMigrationLogs: return qre.execShowMigrationLogs() case p.PlanShowThrottledApps: @@ -1057,6 +1059,13 @@ func (qre *QueryExecutor) execRevertMigration() (*sqltypes.Result, error) { return qre.tsv.onlineDDLExecutor.SubmitMigration(qre.ctx, qre.plan.FullStmt) } +func (qre *QueryExecutor) execShowMigrations() (*sqltypes.Result, error) { + if showStmt, ok := qre.plan.FullStmt.(*sqlparser.Show); ok { + return qre.tsv.onlineDDLExecutor.ShowMigrations(qre.ctx, showStmt) + } + return nil, vterrors.New(vtrpcpb.Code_INTERNAL, "Expecting SHOW VITESS_MIGRATIONS plan") +} + func (qre *QueryExecutor) execShowMigrationLogs() (*sqltypes.Result, error) { if showMigrationLogsStmt, ok := qre.plan.FullStmt.(*sqlparser.ShowMigrationLogs); ok { return qre.tsv.onlineDDLExecutor.ShowMigrationLogs(qre.ctx, showMigrationLogsStmt) diff --git a/go/vt/vttablet/tabletserver/query_executor_test.go b/go/vt/vttablet/tabletserver/query_executor_test.go index 10dd261f975..fd824c48940 100644 --- a/go/vt/vttablet/tabletserver/query_executor_test.go +++ b/go/vt/vttablet/tabletserver/query_executor_test.go @@ -489,7 +489,7 @@ func TestDisableOnlineDDL(t *testing.T) { qre = newTestQueryExecutor(ctx, tsv, query, 0) _, err = qre.Execute() - require.EqualError(t, err, "online ddl is disabled") + require.EqualError(t, err, "online DDL is disabled") } func TestQueryExecutorLimitFailure(t *testing.T) {