80 lines
2.3 KiB
Go
80 lines
2.3 KiB
Go
// Package migrations contains the reviewed SQL bundled with the application.
|
|
// SQL execution and database lifecycle remain in internal/data.
|
|
package migrations
|
|
|
|
import (
|
|
_ "embed"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
//go:embed legacy-framework.sql
|
|
var frameworkSQL string
|
|
|
|
//go:embed cleanup-legacy.sql
|
|
var cleanupSQL string
|
|
|
|
func FrameworkSQL() string { return frameworkSQL }
|
|
func CleanupSQL() string { return cleanupSQL }
|
|
|
|
// Statements understands the DELIMITER directives in the bundled, trusted
|
|
// scripts. It does not split stored-procedure bodies on their semicolons.
|
|
func Statements(source string) ([]string, error) {
|
|
delimiter := ";"
|
|
var buffer strings.Builder
|
|
var statements []string
|
|
for _, line := range strings.Split(source, "\n") {
|
|
trimmed := strings.TrimSpace(line)
|
|
if strings.HasPrefix(trimmed, "DELIMITER ") {
|
|
delimiter = strings.TrimSpace(strings.TrimPrefix(trimmed, "DELIMITER "))
|
|
if delimiter == "" {
|
|
return nil, fmt.Errorf("empty SQL delimiter")
|
|
}
|
|
continue
|
|
}
|
|
if buffer.Len() == 0 && (trimmed == "" || strings.HasPrefix(trimmed, "--")) {
|
|
continue
|
|
}
|
|
buffer.WriteString(line)
|
|
buffer.WriteByte('\n')
|
|
if strings.HasSuffix(trimmed, delimiter) {
|
|
statement := strings.TrimSuffix(strings.TrimSpace(buffer.String()), delimiter)
|
|
statements = append(statements, statement)
|
|
buffer.Reset()
|
|
}
|
|
}
|
|
if strings.TrimSpace(buffer.String()) != "" {
|
|
return nil, fmt.Errorf("unterminated SQL script")
|
|
}
|
|
return statements, nil
|
|
}
|
|
|
|
func CleanupTables() []string {
|
|
block := regexp.MustCompile(`(?s)INSERT INTO _sw_cleanup_targets_20261106\([^\n]+\) VALUES\s*(.*?);`).FindStringSubmatch(cleanupSQL)
|
|
if len(block) != 2 {
|
|
panic("cleanup table manifest is missing")
|
|
}
|
|
var names []string
|
|
for _, match := range regexp.MustCompile(`\('([a-z0-9_]+)'`).FindAllStringSubmatch(block[1], -1) {
|
|
names = append(names, match[1])
|
|
}
|
|
return names
|
|
}
|
|
|
|
func LegacyArchives() map[string]string {
|
|
archives := map[string]string{}
|
|
for _, match := range regexp.MustCompile("`([a-z0-9_]+)` TO `(legacy_sw_20261103_[a-z0-9_]+)`").FindAllStringSubmatch(frameworkSQL, -1) {
|
|
archives[match[1]] = match[2]
|
|
}
|
|
return archives
|
|
}
|
|
|
|
func FrameworkCreatedTables() []string {
|
|
var names []string
|
|
for _, match := range regexp.MustCompile("(?m)^CREATE TABLE `?([a-z0-9_]+)`? ").FindAllStringSubmatch(frameworkSQL, -1) {
|
|
names = append(names, match[1])
|
|
}
|
|
return names
|
|
}
|