Repository: ariga/atlas
Pull request #1763 (2023-06-20 06:45:49)

sql/sqlite: sqlspec for table options


Patch:
diff --git a/sql/sqlite/sqlspec.go b/sql/sqlite/sqlspec.go
index 1146820e..3bbcb493 100644
--- a/sql/sqlite/sqlspec.go
+++ b/sql/sqlite/sqlspec.go
@@ -62,7 +62,29 @@ func MarshalSpec(v any, marshaler schemahcl.Marshaler) ([]byte, error) {
 // ForeignKeySpecs into ForeignKeys, as the target tables do not necessarily exist in the schema
 // at this point. Instead, the linking is done by the convertSchema function.
 func convertTable(spec *sqlspec.Table, parent *schema.Schema) (*schema.Table, error) {
-	return specutil.Table(spec, parent, convertColumn, specutil.PrimaryKey, convertIndex, specutil.Check)
+	t, err := specutil.Table(spec, parent, convertColumn, specutil.PrimaryKey, convertIndex, specutil.Check)
+	if err != nil {
+		return nil, err
+	}
+	if attr, ok := spec.Attr("without_rowid"); ok {
+		b, err := attr.Bool()
+		if err != nil {
+			return nil, err
+		}
+		if b {
+			t.AddAttrs(&WithoutRowID{})
+		}
+	}
+	if attr, ok := spec.Attr("strict"); ok {
+		b, err := attr.Bool()
+		if err != nil {
+			return nil, err
+		}
+		if b {
+			t.AddAttrs(&Strict{})
+		}
+	}
+	return t, nil
 }
 
 // convertIndex converts a sqlspec.Index into a schema.Index.
@@ -113,15 +135,29 @@ func schemaSpec(s *schema.Schema) (*specutil.SchemaSpec, error) {
 }
 
 // tableSpec converts from a concrete SQLite sqlspec.Table to a schema.Table.
-func tableSpec(tab *schema.Table) (*sqlspec.Table, error) {
-	return specutil.FromTable(
-		tab,
+func tableSpec(t *schema.Table) (*sqlspec.Table, error) {
+	spec, err := specutil.FromTable(
+		t,
 		columnSpec,
 		specutil.FromPrimaryKey,
 		indexSpec,
 		specutil.FromForeignKey,
 		specutil.FromCheck,
 	)
+	if err != nil {
+		return nil, err
+	}
+	options := &schemahcl.Resource{}
+	if sqlx.Has(t.Attrs, &WithoutRowID{}) {
+		options.SetAttr(schemahcl.BoolAttr("without_rowid", true))
+	}
+	if sqlx.Has(t.Attrs, &Strict{}) {
+		options.SetAttr(schemahcl.BoolAttr("strict", true))
+	}
+	if options != nil {
+		spec.Extra.Children = append(spec.Extra.Children, options)
+	}
+	return spec, nil
 }
 
 // viewSpec converts from a concrete SQLite schema.View to a sqlspec.View.


Test patch:
diff --git a/sql/sqlite/sqlspec_test.go b/sql/sqlite/sqlspec_test.go
index 8c293189..e9f00e06 100644
--- a/sql/sqlite/sqlspec_test.go
+++ b/sql/sqlite/sqlspec_test.go
@@ -56,6 +56,8 @@ table "table" {
 	check "positive price" {
 		expr = "price > 0"
 	}
+	without_rowid = true
+	strict        = false
 }
 
 table "accounts" {
@@ -66,6 +68,7 @@ table "accounts" {
 	primary_key {
 		columns = [table.accounts.column.name]
 	}
+	strict = true
 }
 `
 	exp := &schema.Schema{
@@ -118,6 +121,7 @@ table "accounts" {
 					Name: "positive price",
 					Expr: "price > 0",
 				},
+				&WithoutRowID{},
 			},
 		},
 		{
@@ -134,6 +138,9 @@ table "accounts" {
 					},
 				},
 			},
+			Attrs: []schema.Attr{
+				&Strict{},
+			},
 		},
 	}
 	exp.Tables[0].PrimaryKey = &schema.Index{
@@ -423,6 +430,36 @@ schema "test" {
 	}
 }
 
+func TestMarshalSpec_TableOptions(t *testing.T) {
+	s := schema.New("test").
+		AddTables(
+			schema.NewTable("users").
+				AddColumns(
+					schema.NewIntColumn("id", "int"),
+				).
+				AddAttrs(
+					&WithoutRowID{},
+					&Strict{},
+				),
+		)
+	s.Tables[0].SetSchema(s)
+	buf, err := MarshalSpec(s, hclState)
+	require.NoError(t, err)
+	const expected = `table "users" {
+  schema = schema.test
+  column "id" {
+    null = false
+    type = int
+  }
+  without_rowid = true
+  strict        = true
+}
+schema "test" {
+}
+`
+	require.EqualValues(t, expected, string(buf))
+}
+
 func TestInputVars(t *testing.T) {
 	spectest.TestInputVars(t, EvalHCL)
 }