Files
migrate/dialect.go
T
jchenry 9b998b7904 Refactor and improve code quality, fix security issues and documentation
Security Fixes:
- Add SQL injection protection in dialect.go using proper identifier quoting
- Implement quoteIdentifier() method to escape SQL identifiers safely
- Fix resource leak in dbVersion() by adding deferred rows.Close()
- Fix incorrect error handling in dbVersion() to properly propagate errors

Code Quality Improvements:
- Replace custom Error struct with idiomatic fmt.Errorf with %w verb
- Simplify error handling by replacing nested if-err-nil with early returns
- Remove named return values with implicit returns for clarity
- Update interface{} to any (Go 1.18+ style)
- Fix variable shadowing in Apply loop (use m.Description instead of migrations[i])

Test Improvements:
- Fix variable shadowing bug in createTestDB() that caused nil pointer panics
- Update SQL driver from github.com/mattn/go-sqlite3 to modernc.org/sqlite
- Fix driver name from "sqlite3" to "sqlite" for modernc.org/sqlite
- Add missing error check for r.Scan() in TestApply
- Make test error handling consistent by using t.Fatal() throughout
- Simplify test helper functions with early returns

Documentation Fixes:
- Fix README example to use 'Apply' field instead of incorrect 'F' field
- Update README example to match actual test code (sex instead of gender)
- Fix typos: "datbase" → "database", "datbases" → "databases"
- Improve README clarity with proper punctuation and formatting
- Update doc.go with correct spelling

Dependencies:
- Update go.mod to Go 1.25
- Switch to modernc.org/sqlite v1.44.0 (pure Go SQLite driver)
- Add all required indirect dependencies

All changes maintain backward compatibility and pass existing tests.
2026-01-18 01:34:09 -08:00

46 lines
1.2 KiB
Go
Executable File

package migrate
import (
"fmt"
"strings"
)
type Dialect interface {
CreateTable(table string) string
TableExists(table string) string
CheckVersion(table string) string
InsertVersion(table string) string
}
func Sqlite3() Dialect {
return sqlite3{}
}
type sqlite3 struct{}
// quoteIdentifier safely quotes a SQL identifier to prevent SQL injection
func (s sqlite3) quoteIdentifier(identifier string) string {
// Replace any existing quotes with double quotes (SQL escape mechanism)
escaped := strings.ReplaceAll(identifier, `"`, `""`)
return fmt.Sprintf(`"%s"`, escaped)
}
func (s sqlite3) CreateTable(table string) string {
return fmt.Sprintf(`CREATE TABLE %s (
id INTEGER PRIMARY KEY AUTOINCREMENT,
description VARCHAR,
applied TIMESTAMP);`, s.quoteIdentifier(table))
}
func (s sqlite3) TableExists(table string) string {
return fmt.Sprintf("SELECT * FROM %s;", s.quoteIdentifier(table))
}
func (s sqlite3) CheckVersion(table string) string {
return fmt.Sprintf("SELECT id FROM %s ORDER BY id DESC LIMIT 0, 1;", s.quoteIdentifier(table))
}
func (s sqlite3) InsertVersion(table string) string {
return fmt.Sprintf("INSERT INTO %s(description, applied) VALUES (?,?);", s.quoteIdentifier(table))
}