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"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -124,5 +125,80 @@ func (h *AdminSettingsHandler) runSeedFile(filename string) error {
|
|||||||
return err
|
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