69 lines
1.4 KiB
Go
69 lines
1.4 KiB
Go
package databaseHelpers
|
|
|
|
import (
|
|
"bufio"
|
|
"database/sql"
|
|
"strings"
|
|
)
|
|
|
|
// ExecScript executes a multi-statement SQL script.
|
|
// It only requires that statements end with ';' and ignores '--' comments.
|
|
// (Good for simple DDL/DML. If you add routines/triggers, upgrade later.)
|
|
func ExecScript(tx *sql.Tx, script string) error {
|
|
sc := bufio.NewScanner(strings.NewReader(script))
|
|
sc.Split(splitStatements)
|
|
|
|
for sc.Scan() {
|
|
stmt := strings.TrimSpace(sc.Text())
|
|
if stmt == "" {
|
|
continue
|
|
}
|
|
if _, err := tx.Exec(stmt); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return sc.Err()
|
|
}
|
|
|
|
// splitStatements separates statements at ';'
|
|
// and strips whitespace and '--' comments.
|
|
func splitStatements(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
|
// skip whitespace and comments
|
|
start := 0
|
|
for {
|
|
// whitespace
|
|
for start < len(data) {
|
|
switch data[start] {
|
|
case ' ', '\t', '\n', '\r':
|
|
start++
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
// '-- comment'
|
|
if start+1 < len(data) && data[start] == '-' && data[start+1] == '-' {
|
|
i := start + 2
|
|
for i < len(data) && data[i] != '\n' {
|
|
i++
|
|
}
|
|
if i >= len(data) {
|
|
return len(data), nil, nil
|
|
}
|
|
start = i + 1
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
|
|
// detect semicolon termination
|
|
for i := start; i < len(data); i++ {
|
|
if data[i] == ';' {
|
|
return i + 1, data[start:i], nil
|
|
}
|
|
}
|
|
if atEOF && start < len(data) {
|
|
return len(data), data[start:], nil
|
|
}
|
|
return 0, nil, nil
|
|
}
|