feat(dbml): support case-insensitive table note parsing
Release / test (push) Successful in 4m15s
Release / release (push) Successful in 5m29s
Release / pkg-rpm (push) Successful in 2m10s
Release / pkg-deb (push) Successful in 2m27s
Release / pkg-aur (push) Successful in 5m52s

This commit is contained in:
2026-09-09 22:31:00 +02:00
parent 161ac317f0
commit 58e46e5b59
2 changed files with 68 additions and 8 deletions
+59 -6
View File
@@ -454,7 +454,7 @@ func (r *Reader) parseDBML(content string) (*models.Database, error) {
// for a column declaration.
if inTableNote {
if line == "'''" {
currentTable.Description = strings.TrimSpace(strings.Join(tableNoteLines, "\n"))
setTableNote(currentTable, strings.TrimSpace(strings.Join(tableNoteLines, "\n")))
inTableNote = false
tableNoteLines = nil
continue
@@ -557,9 +557,10 @@ func (r *Reader) parseDBML(content string) (*models.Database, error) {
continue
}
// Parse table note
if inTable && currentTable != nil && strings.HasPrefix(line, "Note:") {
note := strings.TrimPrefix(line, "Note:")
// Parse table note. DBML files in the wild use both `Note:` and
// `note:`, so accept either spelling.
if inTable && currentTable != nil && strings.HasPrefix(strings.ToLower(line), "note:") {
note := strings.TrimSpace(line[len("note:"):])
if strings.TrimSpace(note) == "'''" {
inTableNote = true
tableNoteLines = nil
@@ -567,7 +568,7 @@ func (r *Reader) parseDBML(content string) (*models.Database, error) {
continue
}
note = strings.Trim(note, " '\"")
currentTable.Description = note
setTableNote(currentTable, note)
continue
}
@@ -654,6 +655,20 @@ func (r *Reader) parseDBML(content string) (*models.Database, error) {
return db, nil
}
// setTableNote preserves multiple table notes. The first maps to Description
// and the second to Comment, matching the model fields used by code writers.
func setTableNote(table *models.Table, note string) {
if table.Description == "" {
table.Description = note
return
}
if table.Comment == "" {
table.Comment = note
return
}
table.Comment += "\n" + note
}
// parseColumn parses a DBML column definition
func (r *Reader) parseColumn(line, tableName, schemaName string) (*models.Column, *models.Constraint) {
// Format: column_name type [attributes] // comment
@@ -671,7 +686,7 @@ func (r *Reader) parseColumn(line, tableName, schemaName string) (*models.Column
// Parse attributes in brackets
if attrs != "" {
attrList := strings.Split(attrs, ",")
attrList := splitColumnAttrs(attrs)
for _, attr := range attrList {
attr = strings.TrimSpace(attr)
@@ -754,6 +769,44 @@ func (r *Reader) parseColumn(line, tableName, schemaName string) (*models.Column
return column, constraint
}
// splitColumnAttrs splits a DBML attribute list on top-level commas. Notes and
// quoted defaults may contain commas of their own, which are part of the value
// rather than attribute separators.
func splitColumnAttrs(attrs string) []string {
var result []string
start := 0
var quote byte
escaped := false
for i := 0; i < len(attrs); i++ {
ch := attrs[i]
if quote != 0 {
if escaped {
escaped = false
continue
}
if ch == '\\' {
escaped = true
continue
}
if ch == quote {
quote = 0
}
continue
}
switch ch {
case '\'', '"', '`':
quote = ch
case ',':
result = append(result, attrs[start:i])
start = i + 1
}
}
return append(result, attrs[start:])
}
func splitInlineComment(line string) (content, inlineComment string) {
commentStart := strings.Index(line, "//")
if commentStart == -1 {