Repository: ariga/atlas
Pull request #486 (2022-01-25 10:06:37)

sql/mysql: support marshal on update expressions in HCL
This PR adds support for marshalling inspected `ON UPDATE` clauses in MySQL / Maria to HCL. The marshaled HCL has the following form: 

```hcl
column "tTimestamp" {
  null      = false
  type      = timestamp(3)
  default   = sql("current_timestamp(3)")
  on_update = sql("current_timestamp(3)")
}
```

Adresses #471 


Patch:
diff --git a/sql/internal/specutil/spec.go b/sql/internal/specutil/spec.go
index 1f936938..9845b891 100644
--- a/sql/internal/specutil/spec.go
+++ b/sql/internal/specutil/spec.go
@@ -33,6 +33,14 @@ func LitAttr(k, v string) *schemaspec.Attr {
 	}
 }
 
+// RawAttr is a helper method for constructing *schemaspec.Attr instances that contain sql expressions.
+func RawAttr(k, v string) *schemaspec.Attr {
+	return &schemaspec.Attr{
+		K: k,
+		V: &schemaspec.RawExpr{X: v},
+	}
+}
+
 // ListAttr is a helper method for constructing *schemaspec.Attr instances that contain list values.
 func ListAttr(k string, litValues ...string) *schemaspec.Attr {
 	lv := &schemaspec.ListValue{}
diff --git a/sql/mysql/sqlspec.go b/sql/mysql/sqlspec.go
index 9b55be71..f89eaf3b 100644
--- a/sql/mysql/sqlspec.go
+++ b/sql/mysql/sqlspec.go
@@ -113,6 +113,13 @@ func convertColumn(spec *sqlspec.Column, _ *schema.Table) (*schema.Column, error
 	if err := convertCharset(spec, &c.Attrs); err != nil {
 		return nil, err
 	}
+	if attr, ok := spec.Attr("on_update"); ok {
+		s, err := attr.String()
+		if err != nil {
+			return nil, err
+		}
+		c.AddAttrs(&OnUpdate{A: s})
+	}
 	return c, err
 }
 
@@ -170,6 +177,9 @@ func columnSpec(c *schema.Column, t *schema.Table) (*sqlspec.Column, error) {
 	if c, ok := hasCollate(c.Attrs, t.Attrs); ok {
 		col.Extra.Attrs = append(col.Extra.Attrs, specutil.StrAttr("collation", c))
 	}
+	if o := (OnUpdate{}); sqlx.Has(c.Attrs, &o) {
+		col.Extra.Attrs = append(col.Extra.Attrs, specutil.RawAttr("on_update", o.A))
+	}
 	return col, nil
 }
 


Test patch:
diff --git a/sql/mysql/sqlspec_test.go b/sql/mysql/sqlspec_test.go
index 45c39566..e886283a 100644
--- a/sql/mysql/sqlspec_test.go
+++ b/sql/mysql/sqlspec_test.go
@@ -449,7 +449,9 @@ func TestMarshalSpec_TimePrecision(t *testing.T) {
 					schema.NewTimeColumn("tTimeDef", TypeTime),
 					schema.NewTimeColumn("tTime", TypeTime, schema.TimePrecision(1)),
 					schema.NewTimeColumn("tDatetime", TypeDateTime, schema.TimePrecision(2)),
-					schema.NewTimeColumn("tTimestamp", TypeTimestamp, schema.TimePrecision(3)),
+					schema.NewTimeColumn("tTimestamp", TypeTimestamp, schema.TimePrecision(3)).
+						SetDefault(&schema.RawExpr{X: "current_timestamp(3)"}).
+						AddAttrs(&OnUpdate{A: "current_timestamp(3)"}),
 					schema.NewTimeColumn("tDate", TypeDate, schema.TimePrecision(2)),
 					schema.NewTimeColumn("tYear", TypeYear, schema.TimePrecision(2)),
 				),
@@ -471,8 +473,10 @@ func TestMarshalSpec_TimePrecision(t *testing.T) {
     type = datetime(2)
   }
   column "tTimestamp" {
-    null = false
-    type = timestamp(3)
+    null      = false
+    type      = timestamp(3)
+    default   = sql("current_timestamp(3)")
+    on_update = sql("current_timestamp(3)")
   }
   column "tDate" {
     null = false