feat(dbml/reader): 🎉 Implement splitIdentifier function for parsing
All checks were successful
CI / Test (1.24) (push) Successful in -26m24s
CI / Test (1.25) (push) Successful in -26m17s
CI / Build (push) Successful in -26m44s
CI / Lint (push) Successful in -26m33s
Integration Tests / Integration Tests (push) Successful in -26m11s
Release / Build and Release (push) Successful in -26m36s
All checks were successful
CI / Test (1.24) (push) Successful in -26m24s
CI / Test (1.25) (push) Successful in -26m17s
CI / Build (push) Successful in -26m44s
CI / Lint (push) Successful in -26m33s
Integration Tests / Integration Tests (push) Successful in -26m11s
Release / Build and Release (push) Successful in -26m36s
This commit is contained in:
@@ -128,6 +128,46 @@ func (r *Reader) readDirectoryDBML(dirPath string) (*models.Database, error) {
|
|||||||
return db, nil
|
return db, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// splitIdentifier splits a dotted identifier while respecting quotes
|
||||||
|
// Handles cases like: "schema.with.dots"."table"."column"
|
||||||
|
func splitIdentifier(s string) []string {
|
||||||
|
var parts []string
|
||||||
|
var current strings.Builder
|
||||||
|
inQuote := false
|
||||||
|
quoteChar := byte(0)
|
||||||
|
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
ch := s[i]
|
||||||
|
|
||||||
|
if !inQuote {
|
||||||
|
switch ch {
|
||||||
|
case '"', '\'':
|
||||||
|
inQuote = true
|
||||||
|
quoteChar = ch
|
||||||
|
current.WriteByte(ch)
|
||||||
|
case '.':
|
||||||
|
if current.Len() > 0 {
|
||||||
|
parts = append(parts, current.String())
|
||||||
|
current.Reset()
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
current.WriteByte(ch)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
current.WriteByte(ch)
|
||||||
|
if ch == quoteChar {
|
||||||
|
inQuote = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if current.Len() > 0 {
|
||||||
|
parts = append(parts, current.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts
|
||||||
|
}
|
||||||
|
|
||||||
// stripQuotes removes surrounding quotes and comments from an identifier
|
// stripQuotes removes surrounding quotes and comments from an identifier
|
||||||
func stripQuotes(s string) string {
|
func stripQuotes(s string) string {
|
||||||
s = strings.TrimSpace(s)
|
s = strings.TrimSpace(s)
|
||||||
@@ -409,7 +449,9 @@ func (r *Reader) parseDBML(content string) (*models.Database, error) {
|
|||||||
// Parse Table definition
|
// Parse Table definition
|
||||||
if matches := tableRegex.FindStringSubmatch(line); matches != nil {
|
if matches := tableRegex.FindStringSubmatch(line); matches != nil {
|
||||||
tableName := matches[1]
|
tableName := matches[1]
|
||||||
parts := strings.Split(tableName, ".")
|
// Strip comments/notes before parsing to avoid dots in notes
|
||||||
|
tableName = strings.TrimSpace(regexp.MustCompile(`\s*\[.*?\]\s*`).ReplaceAllString(tableName, ""))
|
||||||
|
parts := splitIdentifier(tableName)
|
||||||
|
|
||||||
if len(parts) == 2 {
|
if len(parts) == 2 {
|
||||||
currentSchema = stripQuotes(parts[0])
|
currentSchema = stripQuotes(parts[0])
|
||||||
@@ -814,7 +856,7 @@ func (r *Reader) parseTableRef(ref string) (schema, table string, columns []stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse schema, table, and optionally column
|
// Parse schema, table, and optionally column
|
||||||
parts := strings.Split(strings.TrimSpace(ref), ".")
|
parts := splitIdentifier(strings.TrimSpace(ref))
|
||||||
if len(parts) == 3 {
|
if len(parts) == 3 {
|
||||||
// Format: "schema"."table"."column"
|
// Format: "schema"."table"."column"
|
||||||
schema = stripQuotes(parts[0])
|
schema = stripQuotes(parts[0])
|
||||||
|
|||||||
Reference in New Issue
Block a user