Repository: ariga/atlas
Pull request #1016 (2022-08-04 15:29:40)

sql/migrate: store baseline migrations in history table


Patch:
diff --git a/cmd/atlas/internal/migrate/ent/migrate/schema.go b/cmd/atlas/internal/migrate/ent/migrate/schema.go
index 828dffe3..e2342762 100644
--- a/cmd/atlas/internal/migrate/ent/migrate/schema.go
+++ b/cmd/atlas/internal/migrate/ent/migrate/schema.go
@@ -17,6 +17,7 @@ var (
 	AtlasSchemaRevisionsColumns = []*schema.Column{
 		{Name: "version", Type: field.TypeString},
 		{Name: "description", Type: field.TypeString},
+		{Name: "type", Type: field.TypeUint},
 		{Name: "applied", Type: field.TypeInt},
 		{Name: "total", Type: field.TypeInt},
 		{Name: "executed_at", Type: field.TypeTime},
@@ -25,7 +26,6 @@ var (
 		{Name: "hash", Type: field.TypeString},
 		{Name: "partial_hashes", Type: field.TypeJSON, Nullable: true},
 		{Name: "operator_version", Type: field.TypeString},
-		{Name: "meta", Type: field.TypeJSON},
 	}
 	// AtlasSchemaRevisionsTable holds the schema information for the "atlas_schema_revisions" table.
 	AtlasSchemaRevisionsTable = &schema.Table{
diff --git a/cmd/atlas/internal/migrate/ent/mutation.go b/cmd/atlas/internal/migrate/ent/mutation.go
index 043bbb90..bf67333e 100644
--- a/cmd/atlas/internal/migrate/ent/mutation.go
+++ b/cmd/atlas/internal/migrate/ent/mutation.go
@@ -15,6 +15,7 @@ import (
 
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/predicate"
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/revision"
+	"ariga.io/atlas/sql/migrate"
 
 	"entgo.io/ent"
 )
@@ -38,6 +39,8 @@ type RevisionMutation struct {
 	typ               string
 	id                *string
 	description       *string
+	_type             *migrate.RevisionType
+	add_type          *migrate.RevisionType
 	applied           *int
 	addapplied        *int
 	total             *int
@@ -49,7 +52,6 @@ type RevisionMutation struct {
 	hash              *string
 	partial_hashes    *[]string
 	operator_version  *string
-	meta              *map[string]string
 	clearedFields     map[string]struct{}
 	done              bool
 	oldValue          func(context.Context) (*Revision, error)
@@ -196,6 +198,62 @@ func (m *RevisionMutation) ResetDescription() {
 	m.description = nil
 }
 
+// SetType sets the "type" field.
+func (m *RevisionMutation) SetType(mt migrate.RevisionType) {
+	m._type = &mt
+	m.add_type = nil
+}
+
+// GetType returns the value of the "type" field in the mutation.
+func (m *RevisionMutation) GetType() (r migrate.RevisionType, exists bool) {
+	v := m._type
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// OldType returns the old "type" field's value of the Revision entity.
+// If the Revision object wasn't provided to the builder, the object is fetched from the database.
+// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
+func (m *RevisionMutation) OldType(ctx context.Context) (v migrate.RevisionType, err error) {
+	if !m.op.Is(OpUpdateOne) {
+		return v, errors.New("OldType is only allowed on UpdateOne operations")
+	}
+	if m.id == nil || m.oldValue == nil {
+		return v, errors.New("OldType requires an ID field in the mutation")
+	}
+	oldValue, err := m.oldValue(ctx)
+	if err != nil {
+		return v, fmt.Errorf("querying old value for OldType: %w", err)
+	}
+	return oldValue.Type, nil
+}
+
+// AddType adds mt to the "type" field.
+func (m *RevisionMutation) AddType(mt migrate.RevisionType) {
+	if m.add_type != nil {
+		*m.add_type += mt
+	} else {
+		m.add_type = &mt
+	}
+}
+
+// AddedType returns the value that was added to the "type" field in this mutation.
+func (m *RevisionMutation) AddedType() (r migrate.RevisionType, exists bool) {
+	v := m.add_type
+	if v == nil {
+		return
+	}
+	return *v, true
+}
+
+// ResetType resets all changes to the "type" field.
+func (m *RevisionMutation) ResetType() {
+	m._type = nil
+	m.add_type = nil
+}
+
 // SetApplied sets the "applied" field.
 func (m *RevisionMutation) SetApplied(i int) {
 	m.applied = &i
@@ -570,42 +628,6 @@ func (m *RevisionMutation) ResetOperatorVersion() {
 	m.operator_version = nil
 }
 
-// SetMeta sets the "meta" field.
-func (m *RevisionMutation) SetMeta(value map[string]string) {
-	m.meta = &value
-}
-
-// Meta returns the value of the "meta" field in the mutation.
-func (m *RevisionMutation) Meta() (r map[string]string, exists bool) {
-	v := m.meta
-	if v == nil {
-		return
-	}
-	return *v, true
-}
-
-// OldMeta returns the old "meta" field's value of the Revision entity.
-// If the Revision object wasn't provided to the builder, the object is fetched from the database.
-// An error is returned if the mutation operation is not UpdateOne, or the database query fails.
-func (m *RevisionMutation) OldMeta(ctx context.Context) (v map[string]string, err error) {
-	if !m.op.Is(OpUpdateOne) {
-		return v, errors.New("OldMeta is only allowed on UpdateOne operations")
-	}
-	if m.id == nil || m.oldValue == nil {
-		return v, errors.New("OldMeta requires an ID field in the mutation")
-	}
-	oldValue, err := m.oldValue(ctx)
-	if err != nil {
-		return v, fmt.Errorf("querying old value for OldMeta: %w", err)
-	}
-	return oldValue.Meta, nil
-}
-
-// ResetMeta resets all changes to the "meta" field.
-func (m *RevisionMutation) ResetMeta() {
-	m.meta = nil
-}
-
 // Where appends a list predicates to the RevisionMutation builder.
 func (m *RevisionMutation) Where(ps ...predicate.Revision) {
 	m.predicates = append(m.predicates, ps...)
@@ -629,6 +651,9 @@ func (m *RevisionMutation) Fields() []string {
 	if m.description != nil {
 		fields = append(fields, revision.FieldDescription)
 	}
+	if m._type != nil {
+		fields = append(fields, revision.FieldType)
+	}
 	if m.applied != nil {
 		fields = append(fields, revision.FieldApplied)
 	}
@@ -653,9 +678,6 @@ func (m *RevisionMutation) Fields() []string {
 	if m.operator_version != nil {
 		fields = append(fields, revision.FieldOperatorVersion)
 	}
-	if m.meta != nil {
-		fields = append(fields, revision.FieldMeta)
-	}
 	return fields
 }
 
@@ -666,6 +688,8 @@ func (m *RevisionMutation) Field(name string) (ent.Value, bool) {
 	switch name {
 	case revision.FieldDescription:
 		return m.Description()
+	case revision.FieldType:
+		return m.GetType()
 	case revision.FieldApplied:
 		return m.Applied()
 	case revision.FieldTotal:
@@ -682,8 +706,6 @@ func (m *RevisionMutation) Field(name string) (ent.Value, bool) {
 		return m.PartialHashes()
 	case revision.FieldOperatorVersion:
 		return m.OperatorVersion()
-	case revision.FieldMeta:
-		return m.Meta()
 	}
 	return nil, false
 }
@@ -695,6 +717,8 @@ func (m *RevisionMutation) OldField(ctx context.Context, name string) (ent.Value
 	switch name {
 	case revision.FieldDescription:
 		return m.OldDescription(ctx)
+	case revision.FieldType:
+		return m.OldType(ctx)
 	case revision.FieldApplied:
 		return m.OldApplied(ctx)
 	case revision.FieldTotal:
@@ -711,8 +735,6 @@ func (m *RevisionMutation) OldField(ctx context.Context, name string) (ent.Value
 		return m.OldPartialHashes(ctx)
 	case revision.FieldOperatorVersion:
 		return m.OldOperatorVersion(ctx)
-	case revision.FieldMeta:
-		return m.OldMeta(ctx)
 	}
 	return nil, fmt.Errorf("unknown Revision field %s", name)
 }
@@ -729,6 +751,13 @@ func (m *RevisionMutation) SetField(name string, value ent.Value) error {
 		}
 		m.SetDescription(v)
 		return nil
+	case revision.FieldType:
+		v, ok := value.(migrate.RevisionType)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.SetType(v)
+		return nil
 	case revision.FieldApplied:
 		v, ok := value.(int)
 		if !ok {
@@ -785,13 +814,6 @@ func (m *RevisionMutation) SetField(name string, value ent.Value) error {
 		}
 		m.SetOperatorVersion(v)
 		return nil
-	case revision.FieldMeta:
-		v, ok := value.(map[string]string)
-		if !ok {
-			return fmt.Errorf("unexpected type %T for field %s", value, name)
-		}
-		m.SetMeta(v)
-		return nil
 	}
 	return fmt.Errorf("unknown Revision field %s", name)
 }
@@ -800,6 +822,9 @@ func (m *RevisionMutation) SetField(name string, value ent.Value) error {
 // this mutation.
 func (m *RevisionMutation) AddedFields() []string {
 	var fields []string
+	if m.add_type != nil {
+		fields = append(fields, revision.FieldType)
+	}
 	if m.addapplied != nil {
 		fields = append(fields, revision.FieldApplied)
 	}
@@ -817,6 +842,8 @@ func (m *RevisionMutation) AddedFields() []string {
 // was not set, or was not defined in the schema.
 func (m *RevisionMutation) AddedField(name string) (ent.Value, bool) {
 	switch name {
+	case revision.FieldType:
+		return m.AddedType()
 	case revision.FieldApplied:
 		return m.AddedApplied()
 	case revision.FieldTotal:
@@ -832,6 +859,13 @@ func (m *RevisionMutation) AddedField(name string) (ent.Value, bool) {
 // type.
 func (m *RevisionMutation) AddField(name string, value ent.Value) error {
 	switch name {
+	case revision.FieldType:
+		v, ok := value.(migrate.RevisionType)
+		if !ok {
+			return fmt.Errorf("unexpected type %T for field %s", value, name)
+		}
+		m.AddType(v)
+		return nil
 	case revision.FieldApplied:
 		v, ok := value.(int)
 		if !ok {
@@ -898,6 +932,9 @@ func (m *RevisionMutation) ResetField(name string) error {
 	case revision.FieldDescription:
 		m.ResetDescription()
 		return nil
+	case revision.FieldType:
+		m.ResetType()
+		return nil
 	case revision.FieldApplied:
 		m.ResetApplied()
 		return nil
@@ -922,9 +959,6 @@ func (m *RevisionMutation) ResetField(name string) error {
 	case revision.FieldOperatorVersion:
 		m.ResetOperatorVersion()
 		return nil
-	case revision.FieldMeta:
-		m.ResetMeta()
-		return nil
 	}
 	return fmt.Errorf("unknown Revision field %s", name)
 }
diff --git a/cmd/atlas/internal/migrate/ent/revision.go b/cmd/atlas/internal/migrate/ent/revision.go
index ad1d4064..57269d0d 100644
--- a/cmd/atlas/internal/migrate/ent/revision.go
+++ b/cmd/atlas/internal/migrate/ent/revision.go
@@ -13,6 +13,7 @@ import (
 	"time"
 
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/revision"
+	"ariga.io/atlas/sql/migrate"
 	"entgo.io/ent/dialect/sql"
 )
 
@@ -23,6 +24,8 @@ type Revision struct {
 	ID string `json:"id,omitempty"`
 	// Description holds the value of the "description" field.
 	Description string `json:"description,omitempty"`
+	// Type holds the value of the "type" field.
+	Type migrate.RevisionType `json:"type,omitempty"`
 	// Applied holds the value of the "applied" field.
 	Applied int `json:"applied,omitempty"`
 	// Total holds the value of the "total" field.
@@ -39,8 +42,6 @@ type Revision struct {
 	PartialHashes []string `json:"partial_hashes,omitempty"`
 	// OperatorVersion holds the value of the "operator_version" field.
 	OperatorVersion string `json:"operator_version,omitempty"`
-	// Meta holds the value of the "meta" field.
-	Meta map[string]string `json:"meta,omitempty"`
 }
 
 // scanValues returns the types for scanning values from sql.Rows.
@@ -48,9 +49,9 @@ func (*Revision) scanValues(columns []string) ([]interface{}, error) {
 	values := make([]interface{}, len(columns))
 	for i := range columns {
 		switch columns[i] {
-		case revision.FieldPartialHashes, revision.FieldMeta:
+		case revision.FieldPartialHashes:
 			values[i] = new([]byte)
-		case revision.FieldApplied, revision.FieldTotal, revision.FieldExecutionTime:
+		case revision.FieldType, revision.FieldApplied, revision.FieldTotal, revision.FieldExecutionTime:
 			values[i] = new(sql.NullInt64)
 		case revision.FieldID, revision.FieldDescription, revision.FieldError, revision.FieldHash, revision.FieldOperatorVersion:
 			values[i] = new(sql.NullString)
@@ -83,6 +84,12 @@ func (r *Revision) assignValues(columns []string, values []interface{}) error {
 			} else if value.Valid {
 				r.Description = value.String
 			}
+		case revision.FieldType:
+			if value, ok := values[i].(*sql.NullInt64); !ok {
+				return fmt.Errorf("unexpected type %T for field type", values[i])
+			} else if value.Valid {
+				r.Type = migrate.RevisionType(value.Int64)
+			}
 		case revision.FieldApplied:
 			if value, ok := values[i].(*sql.NullInt64); !ok {
 				return fmt.Errorf("unexpected type %T for field applied", values[i])
@@ -133,14 +140,6 @@ func (r *Revision) assignValues(columns []string, values []interface{}) error {
 			} else if value.Valid {
 				r.OperatorVersion = value.String
 			}
-		case revision.FieldMeta:
-			if value, ok := values[i].(*[]byte); !ok {
-				return fmt.Errorf("unexpected type %T for field meta", values[i])
-			} else if value != nil && len(*value) > 0 {
-				if err := json.Unmarshal(*value, &r.Meta); err != nil {
-					return fmt.Errorf("unmarshal field meta: %w", err)
-				}
-			}
 		}
 	}
 	return nil
@@ -172,6 +171,9 @@ func (r *Revision) String() string {
 	builder.WriteString("description=")
 	builder.WriteString(r.Description)
 	builder.WriteString(", ")
+	builder.WriteString("type=")
+	builder.WriteString(fmt.Sprintf("%v", r.Type))
+	builder.WriteString(", ")
 	builder.WriteString("applied=")
 	builder.WriteString(fmt.Sprintf("%v", r.Applied))
 	builder.WriteString(", ")
@@ -195,9 +197,6 @@ func (r *Revision) String() string {
 	builder.WriteString(", ")
 	builder.WriteString("operator_version=")
 	builder.WriteString(r.OperatorVersion)
-	builder.WriteString(", ")
-	builder.WriteString("meta=")
-	builder.WriteString(fmt.Sprintf("%v", r.Meta))
 	builder.WriteByte(')')
 	return builder.String()
 }
diff --git a/cmd/atlas/internal/migrate/ent/revision/revision.go b/cmd/atlas/internal/migrate/ent/revision/revision.go
index 9afefe1f..ab5a9883 100644
--- a/cmd/atlas/internal/migrate/ent/revision/revision.go
+++ b/cmd/atlas/internal/migrate/ent/revision/revision.go
@@ -13,6 +13,8 @@ const (
 	FieldID = "version"
 	// FieldDescription holds the string denoting the description field in the database.
 	FieldDescription = "description"
+	// FieldType holds the string denoting the type field in the database.
+	FieldType = "type"
 	// FieldApplied holds the string denoting the applied field in the database.
 	FieldApplied = "applied"
 	// FieldTotal holds the string denoting the total field in the database.
@@ -29,8 +31,6 @@ const (
 	FieldPartialHashes = "partial_hashes"
 	// FieldOperatorVersion holds the string denoting the operator_version field in the database.
 	FieldOperatorVersion = "operator_version"
-	// FieldMeta holds the string denoting the meta field in the database.
-	FieldMeta = "meta"
 	// Table holds the table name of the revision in the database.
 	Table = "atlas_schema_revisions"
 )
@@ -39,6 +39,7 @@ const (
 var Columns = []string{
 	FieldID,
 	FieldDescription,
+	FieldType,
 	FieldApplied,
 	FieldTotal,
 	FieldExecutedAt,
@@ -47,7 +48,6 @@ var Columns = []string{
 	FieldHash,
 	FieldPartialHashes,
 	FieldOperatorVersion,
-	FieldMeta,
 }
 
 // ValidColumn reports if the column name is valid (part of the table columns).
diff --git a/cmd/atlas/internal/migrate/ent/revision/where.go b/cmd/atlas/internal/migrate/ent/revision/where.go
index a3858dcc..30b71173 100644
--- a/cmd/atlas/internal/migrate/ent/revision/where.go
+++ b/cmd/atlas/internal/migrate/ent/revision/where.go
@@ -10,6 +10,7 @@ import (
 	"time"
 
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/predicate"
+	"ariga.io/atlas/sql/migrate"
 	"entgo.io/ent/dialect/sql"
 )
 
@@ -91,6 +92,14 @@ func Description(v string) predicate.Revision {
 	})
 }
 
+// Type applies equality check predicate on the "type" field. It's identical to TypeEQ.
+func Type(v migrate.RevisionType) predicate.Revision {
+	vc := uint(v)
+	return predicate.Revision(func(s *sql.Selector) {
+		s.Where(sql.EQ(s.C(FieldType), vc))
+	})
+}
+
 // Applied applies equality check predicate on the "applied" field. It's identical to AppliedEQ.
 func Applied(v int) predicate.Revision {
 	return predicate.Revision(func(s *sql.Selector) {
@@ -252,6 +261,88 @@ func DescriptionContainsFold(v string) predicate.Revision {
 	})
 }
 
+// TypeEQ applies the EQ predicate on the "type" field.
+func TypeEQ(v migrate.RevisionType) predicate.Revision {
+	vc := uint(v)
+	return predicate.Revision(func(s *sql.Selector) {
+		s.Where(sql.EQ(s.C(FieldType), vc))
+	})
+}
+
+// TypeNEQ applies the NEQ predicate on the "type" field.
+func TypeNEQ(v migrate.RevisionType) predicate.Revision {
+	vc := uint(v)
+	return predicate.Revision(func(s *sql.Selector) {
+		s.Where(sql.NEQ(s.C(FieldType), vc))
+	})
+}
+
+// TypeIn applies the In predicate on the "type" field.
+func TypeIn(vs ...migrate.RevisionType) predicate.Revision {
+	v := make([]interface{}, len(vs))
+	for i := range v {
+		v[i] = uint(vs[i])
+	}
+	return predicate.Revision(func(s *sql.Selector) {
+		// if not arguments were provided, append the FALSE constants,
+		// since we can't apply "IN ()". This will make this predicate falsy.
+		if len(v) == 0 {
+			s.Where(sql.False())
+			return
+		}
+		s.Where(sql.In(s.C(FieldType), v...))
+	})
+}
+
+// TypeNotIn applies the NotIn predicate on the "type" field.
+func TypeNotIn(vs ...migrate.RevisionType) predicate.Revision {
+	v := make([]interface{}, len(vs))
+	for i := range v {
+		v[i] = uint(vs[i])
+	}
+	return predicate.Revision(func(s *sql.Selector) {
+		// if not arguments were provided, append the FALSE constants,
+		// since we can't apply "IN ()". This will make this predicate falsy.
+		if len(v) == 0 {
+			s.Where(sql.False())
+			return
+		}
+		s.Where(sql.NotIn(s.C(FieldType), v...))
+	})
+}
+
+// TypeGT applies the GT predicate on the "type" field.
+func TypeGT(v migrate.RevisionType) predicate.Revision {
+	vc := uint(v)
+	return predicate.Revision(func(s *sql.Selector) {
+		s.Where(sql.GT(s.C(FieldType), vc))
+	})
+}
+
+// TypeGTE applies the GTE predicate on the "type" field.
+func TypeGTE(v migrate.RevisionType) predicate.Revision {
+	vc := uint(v)
+	return predicate.Revision(func(s *sql.Selector) {
+		s.Where(sql.GTE(s.C(FieldType), vc))
+	})
+}
+
+// TypeLT applies the LT predicate on the "type" field.
+func TypeLT(v migrate.RevisionType) predicate.Revision {
+	vc := uint(v)
+	return predicate.Revision(func(s *sql.Selector) {
+		s.Where(sql.LT(s.C(FieldType), vc))
+	})
+}
+
+// TypeLTE applies the LTE predicate on the "type" field.
+func TypeLTE(v migrate.RevisionType) predicate.Revision {
+	vc := uint(v)
+	return predicate.Revision(func(s *sql.Selector) {
+		s.Where(sql.LTE(s.C(FieldType), vc))
+	})
+}
+
 // AppliedEQ applies the EQ predicate on the "applied" field.
 func AppliedEQ(v int) predicate.Revision {
 	return predicate.Revision(func(s *sql.Selector) {
diff --git a/cmd/atlas/internal/migrate/ent/revision_create.go b/cmd/atlas/internal/migrate/ent/revision_create.go
index 7ede34b0..e475f93c 100644
--- a/cmd/atlas/internal/migrate/ent/revision_create.go
+++ b/cmd/atlas/internal/migrate/ent/revision_create.go
@@ -13,6 +13,7 @@ import (
 	"time"
 
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/revision"
+	"ariga.io/atlas/sql/migrate"
 	"entgo.io/ent/dialect"
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
@@ -33,6 +34,12 @@ func (rc *RevisionCreate) SetDescription(s string) *RevisionCreate {
 	return rc
 }
 
+// SetType sets the "type" field.
+func (rc *RevisionCreate) SetType(mt migrate.RevisionType) *RevisionCreate {
+	rc.mutation.SetType(mt)
+	return rc
+}
+
 // SetApplied sets the "applied" field.
 func (rc *RevisionCreate) SetApplied(i int) *RevisionCreate {
 	rc.mutation.SetApplied(i)
@@ -89,12 +96,6 @@ func (rc *RevisionCreate) SetOperatorVersion(s string) *RevisionCreate {
 	return rc
 }
 
-// SetMeta sets the "meta" field.
-func (rc *RevisionCreate) SetMeta(m map[string]string) *RevisionCreate {
-	rc.mutation.SetMeta(m)
-	return rc
-}
-
 // SetID sets the "id" field.
 func (rc *RevisionCreate) SetID(s string) *RevisionCreate {
 	rc.mutation.SetID(s)
@@ -180,6 +181,9 @@ func (rc *RevisionCreate) check() error {
 	if _, ok := rc.mutation.Description(); !ok {
 		return &ValidationError{Name: "description", err: errors.New(`ent: missing required field "Revision.description"`)}
 	}
+	if _, ok := rc.mutation.GetType(); !ok {
+		return &ValidationError{Name: "type", err: errors.New(`ent: missing required field "Revision.type"`)}
+	}
 	if _, ok := rc.mutation.Applied(); !ok {
 		return &ValidationError{Name: "applied", err: errors.New(`ent: missing required field "Revision.applied"`)}
 	}
@@ -203,9 +207,6 @@ func (rc *RevisionCreate) check() error {
 	if _, ok := rc.mutation.OperatorVersion(); !ok {
 		return &ValidationError{Name: "operator_version", err: errors.New(`ent: missing required field "Revision.operator_version"`)}
 	}
-	if _, ok := rc.mutation.Meta(); !ok {
-		return &ValidationError{Name: "meta", err: errors.New(`ent: missing required field "Revision.meta"`)}
-	}
 	return nil
 }
 
@@ -252,6 +253,14 @@ func (rc *RevisionCreate) createSpec() (*Revision, *sqlgraph.CreateSpec) {
 		})
 		_node.Description = value
 	}
+	if value, ok := rc.mutation.GetType(); ok {
+		_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
+			Type:   field.TypeUint,
+			Value:  value,
+			Column: revision.FieldType,
+		})
+		_node.Type = value
+	}
 	if value, ok := rc.mutation.Applied(); ok {
 		_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
 			Type:   field.TypeInt,
@@ -316,14 +325,6 @@ func (rc *RevisionCreate) createSpec() (*Revision, *sqlgraph.CreateSpec) {
 		})
 		_node.OperatorVersion = value
 	}
-	if value, ok := rc.mutation.Meta(); ok {
-		_spec.Fields = append(_spec.Fields, &sqlgraph.FieldSpec{
-			Type:   field.TypeJSON,
-			Value:  value,
-			Column: revision.FieldMeta,
-		})
-		_node.Meta = value
-	}
 	return _node, _spec
 }
 
@@ -390,6 +391,24 @@ func (u *RevisionUpsert) UpdateDescription() *RevisionUpsert {
 	return u
 }
 
+// SetType sets the "type" field.
+func (u *RevisionUpsert) SetType(v migrate.RevisionType) *RevisionUpsert {
+	u.Set(revision.FieldType, v)
+	return u
+}
+
+// UpdateType sets the "type" field to the value that was provided on create.
+func (u *RevisionUpsert) UpdateType() *RevisionUpsert {
+	u.SetExcluded(revision.FieldType)
+	return u
+}
+
+// AddType adds v to the "type" field.
+func (u *RevisionUpsert) AddType(v migrate.RevisionType) *RevisionUpsert {
+	u.Add(revision.FieldType, v)
+	return u
+}
+
 // SetApplied sets the "applied" field.
 func (u *RevisionUpsert) SetApplied(v int) *RevisionUpsert {
 	u.Set(revision.FieldApplied, v)
@@ -516,18 +535,6 @@ func (u *RevisionUpsert) UpdateOperatorVersion() *RevisionUpsert {
 	return u
 }
 
-// SetMeta sets the "meta" field.
-func (u *RevisionUpsert) SetMeta(v map[string]string) *RevisionUpsert {
-	u.Set(revision.FieldMeta, v)
-	return u
-}
-
-// UpdateMeta sets the "meta" field to the value that was provided on create.
-func (u *RevisionUpsert) UpdateMeta() *RevisionUpsert {
-	u.SetExcluded(revision.FieldMeta)
-	return u
-}
-
 // UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
 // Using this option is equivalent to using:
 //
@@ -598,6 +605,27 @@ func (u *RevisionUpsertOne) UpdateDescription() *RevisionUpsertOne {
 	})
 }
 
+// SetType sets the "type" field.
+func (u *RevisionUpsertOne) SetType(v migrate.RevisionType) *RevisionUpsertOne {
+	return u.Update(func(s *RevisionUpsert) {
+		s.SetType(v)
+	})
+}
+
+// AddType adds v to the "type" field.
+func (u *RevisionUpsertOne) AddType(v migrate.RevisionType) *RevisionUpsertOne {
+	return u.Update(func(s *RevisionUpsert) {
+		s.AddType(v)
+	})
+}
+
+// UpdateType sets the "type" field to the value that was provided on create.
+func (u *RevisionUpsertOne) UpdateType() *RevisionUpsertOne {
+	return u.Update(func(s *RevisionUpsert) {
+		s.UpdateType()
+	})
+}
+
 // SetApplied sets the "applied" field.
 func (u *RevisionUpsertOne) SetApplied(v int) *RevisionUpsertOne {
 	return u.Update(func(s *RevisionUpsert) {
@@ -745,20 +773,6 @@ func (u *RevisionUpsertOne) UpdateOperatorVersion() *RevisionUpsertOne {
 	})
 }
 
-// SetMeta sets the "meta" field.
-func (u *RevisionUpsertOne) SetMeta(v map[string]string) *RevisionUpsertOne {
-	return u.Update(func(s *RevisionUpsert) {
-		s.SetMeta(v)
-	})
-}
-
-// UpdateMeta sets the "meta" field to the value that was provided on create.
-func (u *RevisionUpsertOne) UpdateMeta() *RevisionUpsertOne {
-	return u.Update(func(s *RevisionUpsert) {
-		s.UpdateMeta()
-	})
-}
-
 // Exec executes the query.
 func (u *RevisionUpsertOne) Exec(ctx context.Context) error {
 	if len(u.create.conflict) == 0 {
@@ -994,6 +1008,27 @@ func (u *RevisionUpsertBulk) UpdateDescription() *RevisionUpsertBulk {
 	})
 }
 
+// SetType sets the "type" field.
+func (u *RevisionUpsertBulk) SetType(v migrate.RevisionType) *RevisionUpsertBulk {
+	return u.Update(func(s *RevisionUpsert) {
+		s.SetType(v)
+	})
+}
+
+// AddType adds v to the "type" field.
+func (u *RevisionUpsertBulk) AddType(v migrate.RevisionType) *RevisionUpsertBulk {
+	return u.Update(func(s *RevisionUpsert) {
+		s.AddType(v)
+	})
+}
+
+// UpdateType sets the "type" field to the value that was provided on create.
+func (u *RevisionUpsertBulk) UpdateType() *RevisionUpsertBulk {
+	return u.Update(func(s *RevisionUpsert) {
+		s.UpdateType()
+	})
+}
+
 // SetApplied sets the "applied" field.
 func (u *RevisionUpsertBulk) SetApplied(v int) *RevisionUpsertBulk {
 	return u.Update(func(s *RevisionUpsert) {
@@ -1141,20 +1176,6 @@ func (u *RevisionUpsertBulk) UpdateOperatorVersion() *RevisionUpsertBulk {
 	})
 }
 
-// SetMeta sets the "meta" field.
-func (u *RevisionUpsertBulk) SetMeta(v map[string]string) *RevisionUpsertBulk {
-	return u.Update(func(s *RevisionUpsert) {
-		s.SetMeta(v)
-	})
-}
-
-// UpdateMeta sets the "meta" field to the value that was provided on create.
-func (u *RevisionUpsertBulk) UpdateMeta() *RevisionUpsertBulk {
-	return u.Update(func(s *RevisionUpsert) {
-		s.UpdateMeta()
-	})
-}
-
 // Exec executes the query.
 func (u *RevisionUpsertBulk) Exec(ctx context.Context) error {
 	for i, b := range u.create.builders {
diff --git a/cmd/atlas/internal/migrate/ent/revision_update.go b/cmd/atlas/internal/migrate/ent/revision_update.go
index a8738986..12383f2e 100644
--- a/cmd/atlas/internal/migrate/ent/revision_update.go
+++ b/cmd/atlas/internal/migrate/ent/revision_update.go
@@ -15,6 +15,7 @@ import (
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/internal"
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/predicate"
 	"ariga.io/atlas/cmd/atlas/internal/migrate/ent/revision"
+	"ariga.io/atlas/sql/migrate"
 	"entgo.io/ent/dialect/sql"
 	"entgo.io/ent/dialect/sql/sqlgraph"
 	"entgo.io/ent/schema/field"
@@ -33,6 +34,19 @@ func (ru *RevisionUpdate) Where(ps ...predicate.Revision) *RevisionUpdate {
 	return ru
 }
 
+// SetType sets the "type" field.
+func (ru *RevisionUpdate) SetType(mt migrate.RevisionType) *RevisionUpdate {
+	ru.mutation.ResetType()
+	ru.mutation.SetType(mt)
+	return ru
+}
+
+// AddType adds mt to the "type" field.
+func (ru *RevisionUpdate) AddType(mt migrate.RevisionType) *RevisionUpdate {
+	ru.mutation.AddType(mt)
+	return ru
+}
+
 // SetApplied sets the "applied" field.
 func (ru *RevisionUpdate) SetApplied(i int) *RevisionUpdate {
 	ru.mutation.ResetApplied()
@@ -116,12 +130,6 @@ func (ru *RevisionUpdate) SetOperatorVersion(s string) *RevisionUpdate {
 	return ru
 }
 
-// SetMeta sets the "meta" field.
-func (ru *RevisionUpdate) SetMeta(m map[string]string) *RevisionUpdate {
-	ru.mutation.SetMeta(m)
-	return ru
-}
-
 // Mutation returns the RevisionMutation object of the builder.
 func (ru *RevisionUpdate) Mutation() *RevisionMutation {
 	return ru.mutation
@@ -215,6 +223,20 @@ func (ru *RevisionUpdate) sqlSave(ctx context.Context) (n int, err error) {
 			}
 		}
 	}
+	if value, ok := ru.mutation.GetType(); ok {
+		_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
+			Type:   field.TypeUint,
+			Value:  value,
+			Column: revision.FieldType,
+		})
+	}
+	if value, ok := ru.mutation.AddedType(); ok {
+		_spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{
+			Type:   field.TypeUint,
+			Value:  value,
+			Column: revision.FieldType,
+		})
+	}
 	if value, ok := ru.mutation.Applied(); ok {
 		_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
 			Type:   field.TypeInt,
@@ -297,13 +319,6 @@ func (ru *RevisionUpdate) sqlSave(ctx context.Context) (n int, err error) {
 			Column: revision.FieldOperatorVersion,
 		})
 	}
-	if value, ok := ru.mutation.Meta(); ok {
-		_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
-			Type:   field.TypeJSON,
-			Value:  value,
-			Column: revision.FieldMeta,
-		})
-	}
 	_spec.Node.Schema = ru.schemaConfig.Revision
 	ctx = internal.NewSchemaConfigContext(ctx, ru.schemaConfig)
 	if n, err = sqlgraph.UpdateNodes(ctx, ru.driver, _spec); err != nil {
@@ -325,6 +340,19 @@ type RevisionUpdateOne struct {
 	mutation *RevisionMutation
 }
 
+// SetType sets the "type" field.
+func (ruo *RevisionUpdateOne) SetType(mt migrate.RevisionType) *RevisionUpdateOne {
+	ruo.mutation.ResetType()
+	ruo.mutation.SetType(mt)
+	return ruo
+}
+
+// AddType adds mt to the "type" field.
+func (ruo *RevisionUpdateOne) AddType(mt migrate.RevisionType) *RevisionUpdateOne {
+	ruo.mutation.AddType(mt)
+	return ruo
+}
+
 // SetApplied sets the "applied" field.
 func (ruo *RevisionUpdateOne) SetApplied(i int) *RevisionUpdateOne {
 	ruo.mutation.ResetApplied()
@@ -408,12 +436,6 @@ func (ruo *RevisionUpdateOne) SetOperatorVersion(s string) *RevisionUpdateOne {
 	return ruo
 }
 
-// SetMeta sets the "meta" field.
-func (ruo *RevisionUpdateOne) SetMeta(m map[string]string) *RevisionUpdateOne {
-	ruo.mutation.SetMeta(m)
-	return ruo
-}
-
 // Mutation returns the RevisionMutation object of the builder.
 func (ruo *RevisionUpdateOne) Mutation() *RevisionMutation {
 	return ruo.mutation
@@ -537,6 +559,20 @@ func (ruo *RevisionUpdateOne) sqlSave(ctx context.Context) (_node *Revision, err
 			}
 		}
 	}
+	if value, ok := ruo.mutation.GetType(); ok {
+		_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
+			Type:   field.TypeUint,
+			Value:  value,
+			Column: revision.FieldType,
+		})
+	}
+	if value, ok := ruo.mutation.AddedType(); ok {
+		_spec.Fields.Add = append(_spec.Fields.Add, &sqlgraph.FieldSpec{
+			Type:   field.TypeUint,
+			Value:  value,
+			Column: revision.FieldType,
+		})
+	}
 	if value, ok := ruo.mutation.Applied(); ok {
 		_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
 			Type:   field.TypeInt,
@@ -619,13 +655,6 @@ func (ruo *RevisionUpdateOne) sqlSave(ctx context.Context) (_node *Revision, err
 			Column: revision.FieldOperatorVersion,
 		})
 	}
-	if value, ok := ruo.mutation.Meta(); ok {
-		_spec.Fields.Set = append(_spec.Fields.Set, &sqlgraph.FieldSpec{
-			Type:   field.TypeJSON,
-			Value:  value,
-			Column: revision.FieldMeta,
-		})
-	}
 	_spec.Node.Schema = ruo.schemaConfig.Revision
 	ctx = internal.NewSchemaConfigContext(ctx, ruo.schemaConfig)
 	_node = &Revision{config: ruo.config}
diff --git a/cmd/atlas/internal/migrate/ent/runtime.go b/cmd/atlas/internal/migrate/ent/runtime.go
index 68fb39fa..c3e1864c 100644
--- a/cmd/atlas/internal/migrate/ent/runtime.go
+++ b/cmd/atlas/internal/migrate/ent/runtime.go
@@ -18,7 +18,7 @@ func init() {
 	revisionFields := schema.Revision{}.Fields()
 	_ = revisionFields
 	// revisionDescTotal is the schema descriptor for total field.
-	revisionDescTotal := revisionFields[3].Descriptor()
+	revisionDescTotal := revisionFields[4].Descriptor()
 	// revision.TotalValidator is a validator for the "total" field. It is called by the builders before save.
 	revision.TotalValidator = revisionDescTotal.Validators[0].(func(int) error)
 }
diff --git a/cmd/atlas/internal/migrate/ent/schema/revision.go b/cmd/atlas/internal/migrate/ent/schema/revision.go
index fe222ba0..68ac9bfb 100644
--- a/cmd/atlas/internal/migrate/ent/schema/revision.go
+++ b/cmd/atlas/internal/migrate/ent/schema/revision.go
@@ -7,6 +7,8 @@ package schema
 import (
 	"time"
 
+	"ariga.io/atlas/sql/migrate"
+
 	"entgo.io/ent"
 	"entgo.io/ent/dialect/entsql"
 	"entgo.io/ent/schema"
@@ -26,6 +28,8 @@ func (Revision) Fields() []ent.Field {
 			Immutable(),
 		field.String("description").
 			Immutable(),
+		field.Uint("type").
+			GoType(migrate.RevisionType(0)),
 		field.Int("applied"),
 		field.Int("total").
 			Positive(),
@@ -39,7 +43,6 @@ func (Revision) Fields() []ent.Field {
 		field.Strings("partial_hashes").
 			Optional(),
 		field.String("operator_version"),
-		field.JSON("meta", make(map[string]string)),
 	}
 }
 
diff --git a/cmd/atlas/internal/migrate/migrate.go b/cmd/atlas/internal/migrate/migrate.go
index 1dbcf087..d5d2ae9e 100644
--- a/cmd/atlas/internal/migrate/migrate.go
+++ b/cmd/atlas/internal/migrate/migrate.go
@@ -154,6 +154,7 @@ func (r *EntRevisions) write(ctx context.Context, rev *migrate.Revision) error {
 	return r.ec.Revision.Create().
 		SetID(rev.Version).
 		SetDescription(rev.Description).
+		SetType(rev.Type).
 		SetApplied(rev.Applied).
 		SetTotal(rev.Total).
 		SetExecutedAt(rev.ExecutedAt).
@@ -162,7 +163,6 @@ func (r *EntRevisions) write(ctx context.Context, rev *migrate.Revision) error {
 		SetHash(rev.Hash).
 		SetPartialHashes(rev.PartialHashes).
 		SetOperatorVersion(rev.OperatorVersion).
-		SetMeta(rev.Meta).
 		OnConflict(sql.ConflictColumns(revision.FieldID)).
 		UpdateNewValues().
 		Exec(ctx)
@@ -172,6 +172,7 @@ func fromEnt(r *ent.Revision) *migrate.Revision {
 	return &migrate.Revision{
 		Version:         r.ID,
 		Description:     r.Description,
+		Type:            r.Type,
 		Applied:         r.Applied,
 		Total:           r.Total,
 		ExecutedAt:      r.ExecutedAt,
@@ -180,7 +181,6 @@ func fromEnt(r *ent.Revision) *migrate.Revision {
 		Hash:            r.Hash,
 		PartialHashes:   r.PartialHashes,
 		OperatorVersion: r.OperatorVersion,
-		Meta:            r.Meta,
 	}
 }
 
diff --git a/sql/migrate/migrate.go b/sql/migrate/migrate.go
index c1433fbd..9cc59cf3 100644
--- a/sql/migrate/migrate.go
+++ b/sql/migrate/migrate.go
@@ -163,6 +163,8 @@ type (
 		Version string
 		// Description of this migration.
 		Description string
+		// Type of the migration.
+		Type RevisionType
 		// Applied denotes the amount of successfully applied statements of the revision.
 		Applied int
 		// Total denotes the total amount of statements of the migration.
@@ -182,10 +184,11 @@ type (
 		PartialHashes []string
 		// OperatorVersion holds a string representation of the Atlas operator managing this database migration.
 		OperatorVersion string
-		// Meta holds additional custom meta-data given for this migration.
-		Meta map[string]string
 	}
 
+	// RevisionType defines the type of the revision record in the history table.
+	RevisionType uint
+
 	// Revisions is an ordered set of Revision structs.
 	Revisions []*Revision
 
@@ -204,6 +207,26 @@ type (
 	ExecutorOption func(*Executor) error
 )
 
+const (
+	// RevisionTypeUnknown represents an unknown revision type.
+	// This is type is unexpected and exists here to only ensure
+	// the type is not set to the zero value.
+	RevisionTypeUnknown RevisionType = 0
+
+	// RevisionTypeBaseline represents a baseline revision. Note that only
+	// the first record can represent a baseline migration and most of its
+	// fields are set to the zero value.
+	RevisionTypeBaseline RevisionType = 1 << (iota - 1)
+
+	// RevisionTypeExecute represents a migration that was executed.
+	RevisionTypeExecute
+
+	// RevisionTypeResolved represents a migration that was resolved. A migration
+	// script that was script executed and then resolved should set its Type to
+	// RevisionTypeExecute | RevisionTypeResolved.
+	RevisionTypeResolved
+)
+
 // NewPlanner creates a new Planner.
 func NewPlanner(drv Driver, dir Dir, opts ...PlannerOption) *Planner {
 	p := &Planner{drv: drv, dir: dir, sum: true}
@@ -424,6 +447,11 @@ func (e *Executor) Pending(ctx context.Context) ([]File, error) {
 			if baseline == -1 {
 				return nil, fmt.Errorf("baseline version %q was not found", e.baselineVer)
 			}
+			f := migrations[baseline]
+			// Mark the revision in the database as baseline revision.
+			if err := writeRevision(ctx, e.rrw, &Revision{Version: f.Version(), Description: f.Desc(), Type: RevisionTypeBaseline}); err != nil {
+				return nil, err
+			}
 			pending = migrations[baseline+1:]
 		}
 	// Not the first time we execute and a
@@ -494,8 +522,8 @@ func (e *Executor) Execute(ctx context.Context, m File) (err error) {
 		r = &Revision{
 			Version:     version,
 			Description: m.Desc(),
+			Type:        RevisionTypeExecute,
 			Total:       len(stmts),
-			ExecutedAt:  time.Now(),
 			Hash:        hash,
 		}
 	}
@@ -539,6 +567,7 @@ func (e *Executor) Execute(ctx context.Context, m File) (err error) {
 }
 
 func writeRevision(ctx context.Context, w RevisionReadWriter, r *Revision) error {
+	r.ExecutedAt = time.Now()
 	if err := w.WriteRevision(ctx, r); err != nil {
 		return fmt.Errorf("sql/migrate: execute: write revision: %w", err)
 	}


Test patch:
diff --git a/cmd/atlas/internal/cmdapi/migrate_test.go b/cmd/atlas/internal/cmdapi/migrate_test.go
index 6ed4dfb8..a7612d0a 100644
--- a/cmd/atlas/internal/cmdapi/migrate_test.go
+++ b/cmd/atlas/internal/cmdapi/migrate_test.go
@@ -246,6 +246,28 @@ func TestMigrate_Apply(t *testing.T) {
 	require.Len(t, revs, 1)
 }
 
+func TestMigrate_ApplyBaseline(t *testing.T) {
+	p := t.TempDir()
+	// Run migration with baseline should store this revision in the database.
+	s, err := runCmd(
+		Root, "migrate", "apply",
+		"--dir", "file://testdata/baseline1",
+		"--baseline", "1",
+		"--url", fmt.Sprintf("sqlite://file:%s?cache=shared&_fk=1", filepath.Join(p, "test.db")),
+	)
+	require.NoError(t, err)
+	require.Contains(t, s, "The migration directory is synced with the database, no migration files to execute")
+
+	// Next run without baseline should run the migration from the baseline.
+	s, err = runCmd(
+		Root, "migrate", "apply",
+		"--dir", "file://testdata/baseline2",
+		"--url", fmt.Sprintf("sqlite://file:%s?cache=shared&_fk=1", filepath.Join(p, "test.db")),
+	)
+	require.NoError(t, err)
+	require.Contains(t, s, "Migrating to version 20220318104615 (2 migrations in total)")
+}
+
 func TestMigrate_Diff(t *testing.T) {
 	p := t.TempDir()
 
diff --git a/cmd/atlas/internal/cmdapi/testdata/baseline1/1_baseline.sql b/cmd/atlas/internal/cmdapi/testdata/baseline1/1_baseline.sql
new file mode 100644
index 00000000..2f762fb4
--- /dev/null
+++ b/cmd/atlas/internal/cmdapi/testdata/baseline1/1_baseline.sql
@@ -0,0 +1,2 @@
+-- create "baseline" table
+CREATE TABLE baseline (`c` int NOT NULL);
diff --git a/cmd/atlas/internal/cmdapi/testdata/baseline1/atlas.sum b/cmd/atlas/internal/cmdapi/testdata/baseline1/atlas.sum
new file mode 100644
index 00000000..9fe13d99
--- /dev/null
+++ b/cmd/atlas/internal/cmdapi/testdata/baseline1/atlas.sum
@@ -0,0 +1,2 @@
+h1:GqOjMVGk2H0qYhhtJ1SPCyyHEBbWP/LD2ueWQTY4e6A=
+1_baseline.sql h1:rZgkRmNcN2UEKgxru1nHCpBRVn/fjFavyQ4xxPxhrD4=
diff --git a/cmd/atlas/internal/cmdapi/testdata/baseline2/1_baseline.sql b/cmd/atlas/internal/cmdapi/testdata/baseline2/1_baseline.sql
new file mode 100644
index 00000000..2f762fb4
--- /dev/null
+++ b/cmd/atlas/internal/cmdapi/testdata/baseline2/1_baseline.sql
@@ -0,0 +1,2 @@
+-- create "baseline" table
+CREATE TABLE baseline (`c` int NOT NULL);
diff --git a/cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104614_initial.sql b/cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104614_initial.sql
new file mode 100644
index 00000000..eaf12fab
--- /dev/null
+++ b/cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104614_initial.sql
@@ -0,0 +1,2 @@
+-- create "tbl" table
+CREATE TABLE tbl (`col` int NOT NULL);
diff --git a/cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104615_second.sql b/cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104615_second.sql
new file mode 100644
index 00000000..1e27bf30
--- /dev/null
+++ b/cmd/atlas/internal/cmdapi/testdata/baseline2/20220318104615_second.sql
@@ -0,0 +1,1 @@
+ALTER TABLE `tbl` ADD `col_2` bigint;
diff --git a/cmd/atlas/internal/cmdapi/testdata/baseline2/atlas.sum b/cmd/atlas/internal/cmdapi/testdata/baseline2/atlas.sum
new file mode 100644
index 00000000..e0669c00
--- /dev/null
+++ b/cmd/atlas/internal/cmdapi/testdata/baseline2/atlas.sum
@@ -0,0 +1,4 @@
+h1:sxNQqhuqhm1fLpr3WN9N/M/niaS81Y7k5RrSaKpmBZE=
+1_baseline.sql h1:rZgkRmNcN2UEKgxru1nHCpBRVn/fjFavyQ4xxPxhrD4=
+20220318104614_initial.sql h1:/B1/+IxzgrRc4tCm1tpcpMhocHgqkdWF+iffxuguYaQ=
+20220318104615_second.sql h1:nUc1cUvm8BzjTZdbavM1IRlNpfhtyY3YyZJ8v23K9j4=
diff --git a/sql/migrate/migrate_test.go b/sql/migrate/migrate_test.go
index 32d8f037..11828f01 100644
--- a/sql/migrate/migrate_test.go
+++ b/sql/migrate/migrate_test.go
@@ -220,6 +220,7 @@ func TestExecutor(t *testing.T) {
 		rev1 = &migrate.Revision{
 			Version:     "1.a",
 			Description: "sub.up",
+			Type:        migrate.RevisionTypeExecute,
 			Applied:     2,
 			Total:       2,
 			Hash:        "nXyZR020M/mH7LxkoTkJr7BcQkipVg90imQ9I4595dw=",
@@ -227,6 +228,7 @@ func TestExecutor(t *testing.T) {
 		rev2 = &migrate.Revision{
 			Version:     "2.10.x-20",
 			Description: "description",
+			Type:        migrate.RevisionTypeExecute,
 			Applied:     1,
 			Total:       1,
 			Hash:        "wQB3Vh3PHVXQg9OD3Gn7TBxbZN3r1Qb7TtAE1g3q9mQ=",
@@ -313,6 +315,7 @@ func TestExecutor(t *testing.T) {
 	requireEqualRevision(t, &migrate.Revision{
 		Version:     "3",
 		Description: "partly",
+		Type:        migrate.RevisionTypeExecute,
 		Applied:     1,
 		Total:       2,
 		Error:       "Statement:\nALTER TABLE t_sub ADD c4 int;\n\nError:\nthis is an error",
@@ -335,13 +338,13 @@ func TestExecutor(t *testing.T) {
 
 func TestExecutor_Baseline(t *testing.T) {
 	var (
+		rrw mockRevisionReadWriter
 		drv = &lockMockDriver{&mockDriver{dirty: true}}
-		rrw = &mockRevisionReadWriter{}
 		log = &mockLogger{}
 	)
 	dir, err := migrate.NewLocalDir(filepath.Join("testdata/migrate", "sub"))
 	require.NoError(t, err)
-	ex, err := migrate.NewExecutor(drv, dir, rrw, migrate.WithLogger(log))
+	ex, err := migrate.NewExecutor(drv, dir, &rrw, migrate.WithLogger(log))
 	require.NoError(t, err)
 
 	// Require baseline-version or explicit flag to work on a dirty workspace.
@@ -349,22 +352,33 @@ func TestExecutor_Baseline(t *testing.T) {
 	require.EqualError(t, err, "sql/migrate: connected database is not clean: found table. baseline version or allow-dirty are required")
 	require.Nil(t, files)
 
-	ex, err = migrate.NewExecutor(drv, dir, rrw, migrate.WithLogger(log), migrate.WithAllowDirty(true))
+	rrw = mockRevisionReadWriter{}
+	ex, err = migrate.NewExecutor(drv, dir, &rrw, migrate.WithLogger(log), migrate.WithAllowDirty(true))
 	require.NoError(t, err)
 	files, err = ex.Pending(context.Background())
 	require.NoError(t, err)
 	require.Len(t, files, 3)
 
-	ex, err = migrate.NewExecutor(drv, dir, rrw, migrate.WithLogger(log), migrate.WithBaselineVersion("2.10.x-20"))
+	rrw = mockRevisionReadWriter{}
+	ex, err = migrate.NewExecutor(drv, dir, &rrw, migrate.WithLogger(log), migrate.WithBaselineVersion("2.10.x-20"))
 	require.NoError(t, err)
 	files, err = ex.Pending(context.Background())
 	require.NoError(t, err)
 	require.Len(t, files, 1)
+	require.Len(t, rrw, 1)
+	require.Equal(t, "2.10.x-20", rrw[0].Version)
+	require.Equal(t, "description", rrw[0].Description)
+	require.Equal(t, migrate.RevisionTypeBaseline, rrw[0].Type)
 
-	ex, err = migrate.NewExecutor(drv, dir, rrw, migrate.WithLogger(log), migrate.WithBaselineVersion("3"))
+	rrw = mockRevisionReadWriter{}
+	ex, err = migrate.NewExecutor(drv, dir, &rrw, migrate.WithLogger(log), migrate.WithBaselineVersion("3"))
 	require.NoError(t, err)
 	files, err = ex.Pending(context.Background())
 	require.ErrorIs(t, err, migrate.ErrNoPendingFiles)
+	require.Len(t, rrw, 1)
+	require.Equal(t, "3", rrw[0].Version)
+	require.Equal(t, "partly", rrw[0].Description)
+	require.Equal(t, migrate.RevisionTypeBaseline, rrw[0].Type)
 }
 
 func TestExecutor_FromVersion(t *testing.T) {
@@ -550,6 +564,7 @@ func requireEqualRevisions(t *testing.T, expected, actual migrate.Revisions) {
 func requireEqualRevision(t *testing.T, expected, actual *migrate.Revision) {
 	require.Equal(t, expected.Version, actual.Version)
 	require.Equal(t, expected.Description, actual.Description)
+	require.Equal(t, expected.Type, actual.Type)
 	require.Equal(t, expected.Applied, actual.Applied)
 	require.Equal(t, expected.Total, actual.Total)
 	require.Equal(t, expected.Error, actual.Error)
@@ -557,7 +572,6 @@ func requireEqualRevision(t *testing.T, expected, actual *migrate.Revision) {
 		require.Equal(t, expected.Hash, actual.Hash)
 	}
 	require.Equal(t, expected.OperatorVersion, actual.OperatorVersion)
-	require.Equal(t, expected.Meta, actual.Meta)
 }
 
 func countFiles(t *testing.T, d migrate.Dir) int {