mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
pkg/infra blank-imported modernc.org/sqlite, so any binary linking this store
next to another Hanzo store (base/core, orm/db, tasks' shard store — all of
which reach SQLite through github.com/hanzoai/sqlite) registered the "sqlite"
database/sql driver name twice and panicked during init:
panic: sql: Register called twice for driver sqlite
modernc.org/sqlite.init.0() modernc.org/[email protected].0/sqlite.go:57
hanzoai/mpc's mpcd is exactly that binary; `go test ./...` there could not even
start. hanzoai/sqlite is the ecosystem's single registrar of that name (pure-Go
modernc under !cgo, hanzoai/csqlite+SQLCipher under cgo), so this store must go
through it — and so must base and orm, hence base v0.39.1 -> v1.5.8 and orm
v0.5.2 -> v0.6.16, the versions that route through it. mpcd's package graph now
has exactly one importer of a SQLite driver.
The hand-rolled DSN went with it. `?_journal_mode=WAL&_busy_timeout=5000&...`
is mattn syntax and the pure-Go backend this module actually linked dropped it
silently — measured journal_mode=delete, busy_timeout=0, foreign_keys=0, i.e.
no WAL, immediate SQLITE_BUSY under concurrent writers and no FK enforcement.
sqlite.PragmaDSN encodes the pragma set in the ACTIVE backend's syntax, so all
three apply under both backends.
Tests: sqlite_driver_test.go links base/core and orm/db alongside this store, so
a regression to a direct modernc import blows the test binary up in init;
TestSQLiteMeta_PragmasApplied reads the pragmas back off a file-backed WAL
store. Both pass under CGO_ENABLED=0 and CGO_ENABLED=1.
Co-authored-by: Hanzo Dev <[email protected]>
65 lines
2.3 KiB
Go
65 lines
2.3 KiB
Go
package infra
|
|
|
|
import (
|
|
"database/sql"
|
|
"path/filepath"
|
|
"slices"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
// The other Hanzo stores a single binary links alongside SQLiteMeta — mpcd
|
|
// links all three. Each must reach SQLite through github.com/hanzoai/sqlite,
|
|
// the ONE package that registers the "sqlite" driver name. If any of them
|
|
// (including this one) regresses to importing modernc.org/sqlite directly,
|
|
// the second sql.Register panics while this test binary is still running
|
|
// init and the whole package fails to start. That init-time explosion is
|
|
// the teeth of this test; the assertions below are the readable part.
|
|
_ "github.com/hanzoai/base/core"
|
|
_ "github.com/hanzoai/orm/db"
|
|
)
|
|
|
|
// TestSQLiteDriverRegisteredOnce pins the invariant that broke hanzoai/mpc:
|
|
// linking SQLiteMeta next to base/core and orm/db must yield exactly one
|
|
// registration of the "sqlite" driver name.
|
|
func TestSQLiteDriverRegisteredOnce(t *testing.T) {
|
|
drivers := sql.Drivers()
|
|
assert.True(t, slices.Contains(drivers, "sqlite"),
|
|
"no %q driver registered; hanzoai/sqlite must register it: %v", "sqlite", drivers)
|
|
|
|
// sql.Register panics on a duplicate name, so reaching this line already
|
|
// proves single registration. Assert it anyway so the intent is legible.
|
|
var n int
|
|
for _, d := range drivers {
|
|
if d == "sqlite" {
|
|
n++
|
|
}
|
|
}
|
|
assert.Equal(t, 1, n, "driver %q registered %d times", "sqlite", n)
|
|
}
|
|
|
|
// TestSQLiteMeta_PragmasApplied proves the connection DSN is expressed in the
|
|
// ACTIVE backend's syntax. The previous hand-rolled `?_journal_mode=WAL&...`
|
|
// string was mattn-only: the pure-Go backend silently dropped it, leaving
|
|
// journal_mode=delete and busy_timeout=0 — immediate SQLITE_BUSY under
|
|
// concurrent writers. sqlite.PragmaDSN encodes them per backend.
|
|
func TestSQLiteMeta_PragmasApplied(t *testing.T) {
|
|
s, err := NewSQLiteMeta(SQLiteMetaConfig{
|
|
Path: filepath.Join(t.TempDir(), "meta.db"),
|
|
WAL: true,
|
|
})
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { s.Close() })
|
|
|
|
pragma := func(name string) string {
|
|
var v string
|
|
require.NoError(t, s.db.NewQuery("PRAGMA "+name).Row(&v), "read pragma %s", name)
|
|
return v
|
|
}
|
|
|
|
assert.Equal(t, "wal", pragma("journal_mode"))
|
|
assert.Equal(t, "5000", pragma("busy_timeout"))
|
|
assert.Equal(t, "1", pragma("foreign_keys"))
|
|
}
|