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:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user