This commit is contained in:
2026-08-22 02:59:16 +02:00
commit 6a5bb1d699
100 changed files with 17409 additions and 0 deletions
+80
View File
@@ -0,0 +1,80 @@
package db
import (
"context"
"database/sql"
"fmt"
"os"
"path/filepath"
"strings"
_ "github.com/jackc/pgx/v5/stdlib"
_ "modernc.org/sqlite"
)
func New(ctx context.Context, driver, dsn string) (*sql.DB, error) {
driverName, err := normalizeDriver(driver)
if err != nil {
return nil, err
}
if driverName == "sqlite" {
if err := ensureSQLiteDirectory(dsn); err != nil {
return nil, fmt.Errorf("prepare sqlite path: %w", err)
}
}
database, err := sql.Open(driverName, dsn)
if err != nil {
return nil, fmt.Errorf("open %s database: %w", driverName, err)
}
if driverName == "sqlite" {
// In-memory databases are connection-local, so keep SQLite single-connection
// and enable foreign keys for every operation through this handle.
database.SetMaxOpenConns(1)
database.SetMaxIdleConns(1)
if _, err := database.ExecContext(ctx, "PRAGMA foreign_keys = ON"); err != nil {
database.Close()
return nil, fmt.Errorf("configure sqlite: %w", err)
}
} else {
database.SetMaxOpenConns(10)
database.SetMaxIdleConns(1)
}
if err := database.PingContext(ctx); err != nil {
database.Close()
return nil, fmt.Errorf("ping %s database: %w", driverName, err)
}
return database, nil
}
func normalizeDriver(driver string) (string, error) {
switch strings.ToLower(strings.TrimSpace(driver)) {
case "postgres", "postgresql", "pgx":
return "pgx", nil
case "sqlite", "sqlite3":
return "sqlite", nil
default:
return "", fmt.Errorf("unsupported database driver %q (use postgres or sqlite)", driver)
}
}
func ensureSQLiteDirectory(dsn string) error {
if dsn == ":memory:" || strings.HasPrefix(dsn, "file::memory:") {
return nil
}
path := strings.SplitN(dsn, "?", 2)[0]
path = strings.TrimPrefix(path, "file:")
if path == "" || path == ":memory:" {
return nil
}
directory := filepath.Dir(path)
if directory == "." || directory == "" {
return nil
}
return os.MkdirAll(directory, 0o755)
}