Fix seed SQL execution to handle multiple statements

PostgreSQL prepared statements don't support multiple commands.
Split SQL file into individual statements and execute each one,
handling string literals and comment-only blocks properly.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-28 08:54:30 -06:00
parent b38a1f547b
commit 9db1b41708

View File

@@ -4,6 +4,7 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
@@ -124,5 +125,80 @@ func (h *AdminSettingsHandler) runSeedFile(filename string) error {
return err
}
return h.db.Exec(string(sqlContent)).Error
// Split SQL into individual statements and execute each one
// This is needed because GORM/PostgreSQL prepared statements don't support multiple commands
statements := splitSQLStatements(string(sqlContent))
for _, stmt := range statements {
stmt = strings.TrimSpace(stmt)
if stmt == "" {
continue
}
if err := h.db.Exec(stmt).Error; err != nil {
return err
}
}
return nil
}
// splitSQLStatements splits SQL content into individual statements
func splitSQLStatements(sql string) []string {
var statements []string
var current strings.Builder
inString := false
stringChar := byte(0)
for i := 0; i < len(sql); i++ {
c := sql[i]
// Handle string literals (don't split on semicolons inside strings)
if (c == '\'' || c == '"') && (i == 0 || sql[i-1] != '\\') {
if !inString {
inString = true
stringChar = c
} else if c == stringChar {
// Check for escaped quote ('')
if c == '\'' && i+1 < len(sql) && sql[i+1] == '\'' {
current.WriteByte(c)
i++
current.WriteByte(sql[i])
continue
}
inString = false
}
}
// Split on semicolon if not in string
if c == ';' && !inString {
current.WriteByte(c)
stmt := strings.TrimSpace(current.String())
if stmt != "" && !isCommentOnly(stmt) {
statements = append(statements, stmt)
}
current.Reset()
continue
}
current.WriteByte(c)
}
// Don't forget the last statement if it doesn't end with semicolon
if stmt := strings.TrimSpace(current.String()); stmt != "" && !isCommentOnly(stmt) {
statements = append(statements, stmt)
}
return statements
}
// isCommentOnly checks if the statement is only comments
func isCommentOnly(stmt string) bool {
lines := strings.Split(stmt, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line != "" && !strings.HasPrefix(line, "--") {
return false
}
}
return true
}