From 863abc63aa283f194be39a53fabc5a84b0a6ae7a Mon Sep 17 00:00:00 2001 From: jinhyuk9714 Date: Sun, 24 May 2026 15:57:48 +0900 Subject: [PATCH] compiler: preserve matching sql table column types Signed-off-by: jinhyuk9714 --- d2compiler/compile.go | 13 +- d2compiler/compile_test.go | 18 + .../sql-column-type-matches-name.exp.json | 355 ++++++++++++++++++ 3 files changed, 385 insertions(+), 1 deletion(-) create mode 100644 testdata/d2compiler/TestCompile/sql-column-type-matches-name.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 66f6497a54..4eca0299af 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -1061,7 +1061,7 @@ func (c *compiler) compileSQLTable(obj *d2graph.Object) { obj.SQLTable = &d2target.SQLTable{} for _, col := range obj.ChildrenArray { typ := col.Label.Value - if typ == col.IDVal { + if typ == col.IDVal && !hasExplicitScalarLabel(col.Label.MapKey) { // Not great, AST should easily allow specifying alternate primary field // as an explicit label should change the name. typ = "" @@ -1086,6 +1086,17 @@ func (c *compiler) compileSQLTable(obj *d2graph.Object) { obj.ChildrenArray = nil } +func hasExplicitScalarLabel(mapKey *d2ast.Key) bool { + if mapKey == nil { + return false + } + if mapKey.Primary.Unbox() != nil { + return true + } + _, ok := mapKey.Value.Unbox().(d2ast.Scalar) + return ok +} + func (c *compiler) validateKeys(obj *d2graph.Object, m *d2ir.Map) { for _, f := range m.Fields { if _, ok := d2ast.BoardKeywords[f.Name.ScalarString()]; ok && f.Name.IsUnquoted() { diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index aacae33711..9c6590b3b1 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -2743,6 +2743,24 @@ ok: { tassert.Equal(t, []string{"primary_key", "foreign_key"}, table.Columns[1].Constraint) }, }, + { + name: "sql-column-type-matches-name", + text: `x: { + shape: sql_table + date: date + id + created {constraint: primary_key} +}`, + assertions: func(t *testing.T, g *d2graph.Graph) { + table := g.Objects[0].SQLTable + tassert.Equal(t, "date", table.Columns[0].Name.Label) + tassert.Equal(t, "date", table.Columns[0].Type.Label) + tassert.Equal(t, "id", table.Columns[1].Name.Label) + tassert.Empty(t, table.Columns[1].Type.Label) + tassert.Equal(t, "created", table.Columns[2].Name.Label) + tassert.Empty(t, table.Columns[2].Type.Label) + }, + }, { name: "sql-null-constraint", text: `x: { diff --git a/testdata/d2compiler/TestCompile/sql-column-type-matches-name.exp.json b/testdata/d2compiler/TestCompile/sql-column-type-matches-name.exp.json new file mode 100644 index 0000000000..679bcc8a04 --- /dev/null +++ b/testdata/d2compiler/TestCompile/sql-column-type-matches-name.exp.json @@ -0,0 +1,355 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,0:0:0-5:1:79", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,0:0:0-5:1:79", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,0:3:3-5:1:79", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,1:2:7-1:18:23", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,1:2:7-1:7:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,1:2:7-1:7:12", + "value": [ + { + "string": "shape", + "raw_string": "shape" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,1:9:14-1:18:23", + "value": [ + { + "string": "sql_table", + "raw_string": "sql_table" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,2:2:26-2:12:36", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,2:2:26-2:6:30", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,2:2:26-2:6:30", + "value": [ + { + "string": "date", + "raw_string": "date" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,2:8:32-2:12:36", + "value": [ + { + "string": "date", + "raw_string": "date" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,3:2:39-3:4:41", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,3:2:39-3:4:41", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,3:2:39-3:4:41", + "value": [ + { + "string": "id", + "raw_string": "id" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:2:44-4:35:77", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:2:44-4:9:51", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:2:44-4:9:51", + "value": [ + { + "string": "created", + "raw_string": "created" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:10:52-4:35:77", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:11:53-4:34:76", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:11:53-4:21:63", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:11:53-4:21:63", + "value": [ + { + "string": "constraint", + "raw_string": "constraint" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,4:23:65-4:34:76", + "value": [ + { + "string": "primary_key", + "raw_string": "primary_key" + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sql-column-type-matches-name.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "sql_table": { + "columns": [ + { + "name": { + "label": "date", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "date", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": null, + "reference": "" + }, + { + "name": { + "label": "id", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": null, + "reference": "" + }, + { + "name": { + "label": "created", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "type": { + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0 + }, + "constraint": [ + "primary_key" + ], + "reference": "" + } + ] + }, + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "sql_table" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}