Repository: ariga/atlas
Pull request #1080 (2022-08-21 15:30:50)

schemahcl: correctly set qualifier scoped vars


Patch:
diff --git a/schemahcl/context.go b/schemahcl/context.go
index 32c9f346..864abacb 100644
--- a/schemahcl/context.go
+++ b/schemahcl/context.go
@@ -25,10 +25,10 @@ type varDef struct {
 // setInputVals sets the input values into the evaluation context. HCL documents can define
 // input variables in the document body by defining "variable" blocks:
 //
-// 	variable "name" {
-// 	  type = string // also supported: int, bool
-// 	  default = "rotemtam"
-// 	}
+//	variable "name" {
+//	  type = string // also supported: int, bool
+//	  default = "rotemtam"
+//	}
 func (s *State) setInputVals(ctx *hcl.EvalContext, body hcl.Body, input map[string]string) error {
 	var c struct {
 		Vars   []*varDef `hcl:"variable,block"`
@@ -125,9 +125,11 @@ func blockVars(blocks hclsyntax.Blocks, parentAddr string, defs *blockDef) (map[
 	vars := make(map[string]cty.Value)
 	for name, def := range defs.children {
 		v := make(map[string]cty.Value)
+		qv := make(map[string]map[string]cty.Value)
 		blocks := blocksOfType(blocks, name)
 		if len(blocks) == 0 {
-			v[name] = cty.NullVal(def.asCty())
+			vars[name] = cty.NullVal(def.asCty())
+			continue
 		}
 		var unlabeled int
 		for _, blk := range blocks {
@@ -153,16 +155,18 @@ func blockVars(blocks hclsyntax.Blocks, parentAddr string, defs *blockDef) (map[
 			for k, v := range varMap {
 				attrs[k] = v
 			}
-			key, obj := blkName, cty.ObjectVal(attrs)
-			if qualifier != "" {
-				obj = cty.ObjectVal(
-					map[string]cty.Value{
-						blkName: obj,
-					},
-				)
-				key = qualifier
+			switch {
+			case qualifier != "":
+				obj := cty.ObjectVal(attrs)
+				if _, ok := qv[qualifier]; !ok {
+					qv[qualifier] = make(map[string]cty.Value)
+				}
+				qv[qualifier][blkName] = obj
+				obj = cty.ObjectVal(qv[qualifier])
+				v[qualifier] = obj
+			default:
+				v[blkName] = cty.ObjectVal(attrs)
 			}
-			v[key] = obj
 		}
 		if len(v) > 0 {
 			vars[name] = cty.ObjectVal(v)
diff --git a/schemahcl/hcl.go b/schemahcl/hcl.go
index 3fd3d04c..42285dbd 100644
--- a/schemahcl/hcl.go
+++ b/schemahcl/hcl.go
@@ -19,10 +19,8 @@ import (
 	"github.com/zclconf/go-cty/cty"
 )
 
-var (
-	// Marshal returns the Atlas HCL encoding of v.
-	Marshal = MarshalerFunc(New().MarshalSpec)
-)
+// Marshal returns the Atlas HCL encoding of v.
+var Marshal = MarshalerFunc(New().MarshalSpec)
 
 type (
 	// State is used to evaluate and marshal Atlas HCL documents and stores a configuration for these operations.
@@ -174,7 +172,7 @@ func (r addrRef) copy() addrRef {
 	return n
 }
 
-// load loads the references from the children of the resource.
+// load the references from the children of the resource.
 func (r addrRef) load(res *Resource, track string) addrRef {
 	unlabeled := 0
 	for _, ch := range res.Children {


Test patch:
diff --git a/sql/mysql/sqlspec_test.go b/sql/mysql/sqlspec_test.go
index e9901f20..b24a30b4 100644
--- a/sql/mysql/sqlspec_test.go
+++ b/sql/mysql/sqlspec_test.go
@@ -1271,3 +1271,49 @@ func lineIfSet(s string) string {
 	}
 	return s
 }
+
+func TestUnmarshalSpec(t *testing.T) {
+	s := []byte(`
+schema "s1" {}
+schema "s2" {}
+
+table "s1" "t1" {
+ schema  = schema.s1
+ column "id" {
+   type = int
+ }
+}
+
+table "s2" "t1" {
+  schema  = schema.s2
+  column "id" {
+    type = int
+  }
+}
+table "s2" "t2" {
+  schema  = schema.s2
+  column "oid" {
+    type = int
+  }
+  foreign_key "fk" {
+    columns = [column.oid]
+    ref_columns = [table.s2.t1.column.id]
+  }
+}
+`)
+	var (
+		r        schema.Realm
+		expected = schema.NewRealm(
+			schema.New("s1").AddTables(schema.NewTable("t1").AddColumns(schema.NewIntColumn("id", "int"))),
+			schema.New("s2").AddTables(
+				schema.NewTable("t1").AddColumns(schema.NewIntColumn("id", "int")),
+				schema.NewTable("t2").AddColumns(schema.NewIntColumn("oid", "int")),
+			),
+		)
+	)
+	expected.Schemas[1].Tables[1].AddForeignKeys(schema.NewForeignKey("fk").
+		AddColumns(expected.Schemas[1].Tables[1].Columns[0]).
+		SetRefTable(expected.Schemas[1].Tables[0]).
+		AddRefColumns(expected.Schemas[1].Tables[0].Columns[0]))
+	require.NoError(t, EvalHCLBytes(s, &r, nil))
+}