diff --git a/conformance_test.go b/conformance_test.go new file mode 100644 index 0000000..e5c1211 --- /dev/null +++ b/conformance_test.go @@ -0,0 +1,37 @@ +package dalgo2sql + +import ( + "fmt" + "testing" + + "github.com/dal-go/dalgo/dal" + "github.com/dal-go/dalgo/dalgotest" +) + +// TestConformance runs the shared dalgotest suite against a real (in-memory) +// SQLite database, via the same modernc.org/sqlite driver already used by +// sql_map_get_test.go — no external database or env-gate is needed. +// +// dalgo2sql itself validates nothing (there is no Validate call anywhere in +// this adapter). Every check here passes because dal.NewDB's write pipeline +// runs BeforeSave validation and hooks before this adapter's code is ever +// entered — see database.go's NewDatabase. +func TestConformance(t *testing.T) { + createSQL := fmt.Sprintf(`CREATE TABLE %s ( + ID TEXT PRIMARY KEY, + Name TEXT + )`, dalgotest.DefaultCollection) + + opts := DbOptions{ + Recordsets: map[string]*Recordset{ + dalgotest.DefaultCollection: NewRecordset( + dalgotest.DefaultCollection, Table, []dal.FieldRef{dal.Field("ID")}, + ), + }, + } + + dalgotest.RunConformance(t, func(t *testing.T) (dal.DB, func()) { + sqlDB := openTestSQLiteDB(t, createSQL) + return NewDatabase(sqlDB, newSchema(), opts), nil + }) +} diff --git a/coverage_additions_test.go b/coverage_additions_test.go index 1d12498..bf412a7 100644 --- a/coverage_additions_test.go +++ b/coverage_additions_test.go @@ -750,7 +750,7 @@ func TestUpdater_Errors(t *testing.T) { t.Fatal(err) } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) // no recordsets and no top-level PrimaryKey -> PrimaryKeyFieldNames returns nil key := record.NewKeyWithID("users", "u1") // update without primary key -> error @@ -766,11 +766,11 @@ func TestUpdater_Errors(t *testing.T) { t.Fatal(err) } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("a"), dal.Field("b")}), }, - }).(*database) + })).(*database) key := record.NewKeyWithID("users", "u1") err = db.Update(ctx, key, nil) if !errors.Is(err, dal.ErrNotImplementedYet) { @@ -784,11 +784,11 @@ func TestUpdater_Errors(t *testing.T) { t.Fatal(err) } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) mock.ExpectExec("UPDATE users SET").WillReturnError(errors.New("exec fail")) err = db.Update(ctx, record.NewKeyWithID("users", "u1"), nil) if err == nil { @@ -802,11 +802,11 @@ func TestUpdater_Errors(t *testing.T) { t.Fatal(err) } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) mock.ExpectExec("UPDATE users SET").WillReturnError(errors.New("nope")) err = db.UpdateMulti(ctx, []*record.Key{record.NewKeyWithID("users", "u1")}, nil) if err == nil { @@ -826,11 +826,11 @@ func TestInserter_Errors(t *testing.T) { t.Fatal(err) } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) mock.ExpectExec("INSERT INTO users").WillReturnError(errors.New("insert fail")) rec := record.NewRecordWithData(record.NewKeyWithID("users", "u1"), &user{Name: "J"}) err = db.Insert(ctx, rec) @@ -873,11 +873,11 @@ func TestDeleter_MultiInSingleTable_CustomPK(t *testing.T) { } defer closeDatabase(t, sqlDB) ctx := context.Background() - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("uid")}), }, - }).(*database) + })).(*database) keys := []*record.Key{ record.NewKeyWithID("users", "u1"), record.NewKeyWithID("users", "u2"), @@ -897,7 +897,7 @@ func TestDeleter_MultiInSingleTable_ExecError(t *testing.T) { } defer closeDatabase(t, sqlDB) ctx := context.Background() - db := NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) keys := []*record.Key{ record.NewKeyWithID("users", "u1"), record.NewKeyWithID("users", "u2"), @@ -919,11 +919,11 @@ func TestSetter_SetMulti_Error(t *testing.T) { } defer closeDatabase(t, sqlDB) ctx := context.Background() - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) mock.ExpectBegin() mock.ExpectQuery("SELECT ID FROM users WHERE ID = ?"). WithArgs("u1"). diff --git a/database.go b/database.go index 34c4f3e..4b495ef 100644 --- a/database.go +++ b/database.go @@ -9,7 +9,7 @@ import ( "github.com/dal-go/dalgo/recordset" ) -var _ dal.DB = (*database)(nil) +var _ dal.Backend = (*database)(nil) type database struct { dal.ConcurrencyAvailable // SupportsConcurrentConnections() = true (standard SQL pool) @@ -103,9 +103,11 @@ func (dtb *database) ExecuteQueryToRecordsReader(ctx context.Context, query dal. return getRecordsReader(ctx, query, dtb.db.QueryContext) } -var _ dal.DB = (*database)(nil) - -// NewDatabase creates a new instance of DALgo adapter to SQL database +// NewDatabase creates a new instance of DALgo adapter to SQL database. +// +// The returned dal.DB is sealed by dal.NewDB: every read-write transaction it +// starts hands the worker a transaction whose writes run the framework's +// BeforeSave validation and hooks before reaching this adapter's code. func NewDatabase(db *sql.DB, schema dal.Schema, options DbOptions) dal.DB { if db == nil { panic("db is a required parameter, got nil") @@ -113,7 +115,7 @@ func NewDatabase(db *sql.DB, schema dal.Schema, options DbOptions) dal.DB { if schema == nil { panic("schema is a required parameter, got nil") } - return &database{ + return dal.NewDB(&database{ recordsReaderProvider: recordsReaderProvider{ executeQuery: db.QueryContext, }, @@ -121,5 +123,5 @@ func NewDatabase(db *sql.DB, schema dal.Schema, options DbOptions) dal.DB { db: db, schema: schema, options: options, - } + }) } diff --git a/database_test.go b/database_test.go index 5ace1ba..5e46a1f 100644 --- a/database_test.go +++ b/database_test.go @@ -99,7 +99,7 @@ func TestOptions_PrimaryKeyFieldNames(t *testing.T) { func newDatabase(t *testing.T) (sqlDB *sql.DB, mock sqlmock.Sqlmock, db *database, closer func(), err error) { sqlDB, mock, err = sqlmock.New() - db = NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db = dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) closer = func() { closeDatabase(t, sqlDB) } diff --git a/deleter_test.go b/deleter_test.go index e39279f..909b97f 100644 --- a/deleter_test.go +++ b/deleter_test.go @@ -20,7 +20,7 @@ func TestDeleter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) key := record.NewKeyWithID("users", "u1") mock.ExpectExec("DELETE FROM users WHERE ID = ?"). @@ -41,11 +41,11 @@ func TestDeleter(t *testing.T) { defer closeDatabase(t, sqlDB) rs := NewRecordset("users", Table, []dal.FieldRef{dal.Field("uid")}) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": rs, }, - }).(*database) + })).(*database) key := record.NewKeyWithID("users", "u1") mock.ExpectExec("DELETE FROM users WHERE uid = ?"). @@ -65,7 +65,7 @@ func TestDeleter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) keys := []*record.Key{ record.NewKeyWithID("users", "u1"), record.NewKeyWithID("users", "u2"), @@ -90,7 +90,7 @@ func TestDeleter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) keys := []*record.Key{ record.NewKeyWithID("users", "u1"), record.NewKeyWithID("posts", "p1"), @@ -112,7 +112,7 @@ func TestDeleter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) key := record.NewKeyWithID("users", "u1") mock.ExpectExec("DELETE FROM users WHERE ID = ?"). @@ -132,7 +132,7 @@ func TestDeleter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{}).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{})).(*database) keys := []*record.Key{ record.NewKeyWithID("users", "u1"), record.NewKeyWithID("users", "u2"), diff --git a/end2end/go.mod b/end2end/go.mod index 83455d1..52a3def 100644 --- a/end2end/go.mod +++ b/end2end/go.mod @@ -5,7 +5,7 @@ go 1.25.0 toolchain go1.26.5 require ( - github.com/dal-go/dalgo v0.63.2 + github.com/dal-go/dalgo v0.64.2 github.com/dal-go/dalgo2sql v0.9.6 // No version as we alway replace it with local version github.com/mattn/go-sqlite3 v1.14.48 ) @@ -13,9 +13,9 @@ require ( replace github.com/dal-go/dalgo2sql => ./../ require ( - github.com/RoaringBitmap/roaring/v2 v2.22.0 // indirect + github.com/RoaringBitmap/roaring/v2 v2.24.0 // indirect github.com/bits-and-blooms/bitset v1.24.6 // indirect - github.com/dal-go/record v0.1.0 // indirect + github.com/dal-go/record v0.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/georgysavva/scany/v2 v2.1.4 // indirect github.com/jackc/pgx/v5 v5.7.6 // indirect diff --git a/end2end/go.sum b/end2end/go.sum index 5c82b46..022e028 100644 --- a/end2end/go.sum +++ b/end2end/go.sum @@ -1,17 +1,15 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= -github.com/RoaringBitmap/roaring/v2 v2.22.0 h1:aGqjvTSkJSTP7W6q518EHiK9RRRb5gJbCaaciCFr/Lg= -github.com/RoaringBitmap/roaring/v2 v2.22.0/go.mod h1:SfT3of9nYh3vis1dIbCj4Yw6KQGujTN+f345nrN/0JA= +github.com/RoaringBitmap/roaring/v2 v2.24.0 h1:zQkkBZtG3WRP4j+P3A5DO221SvL1Br88TJkhyqEQRZo= +github.com/RoaringBitmap/roaring/v2 v2.24.0/go.mod h1:SfT3of9nYh3vis1dIbCj4Yw6KQGujTN+f345nrN/0JA= github.com/bits-and-blooms/bitset v1.24.6 h1:qcrftZUVBIwfs+m+nhoCBAPT+ZPZZjti8SbHbDQQkZ4= github.com/bits-and-blooms/bitset v1.24.6/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs= github.com/cockroachdb/cockroach-go/v2 v2.2.0/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI= -github.com/dal-go/dalgo v0.63.1 h1:GEJAGlNH5xGLdFasSIRrYdqGfd0+4A9DGQ843qJQbyA= -github.com/dal-go/dalgo v0.63.1/go.mod h1:LtD5XVzb1kAdXaRcWVNy4F2ROC4fqR4jqD3q/GD4fJQ= -github.com/dal-go/dalgo v0.63.2 h1:L3hDte5QaorZngNK619V1zKach4qfeb9jOQQUsn4vrc= -github.com/dal-go/dalgo v0.63.2/go.mod h1:LtD5XVzb1kAdXaRcWVNy4F2ROC4fqR4jqD3q/GD4fJQ= -github.com/dal-go/record v0.1.0 h1:hA4143oZwIgtBH/1BRTUEZMCpDfXQr3ONlVXX8USCNg= -github.com/dal-go/record v0.1.0/go.mod h1:quwsVJTT0f6y3Mhx+yHpTobY7luX1M6kyO6fdJ/AFYE= +github.com/dal-go/dalgo v0.64.2 h1:uWCRISCMTpuwjq+VKlymq3kBtdr0c09gcsr75zmeqrw= +github.com/dal-go/dalgo v0.64.2/go.mod h1:PZGzE0AqnaJgPEDTSo7ayfKZaoglhFQ9FxHecF3aQAc= +github.com/dal-go/record v0.1.1 h1:N2WVDBnm2tOb83h5DJqFyINB5kH0vLjKlYFAgCJWv2g= +github.com/dal-go/record v0.1.1/go.mod h1:quwsVJTT0f6y3Mhx+yHpTobY7luX1M6kyO6fdJ/AFYE= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= diff --git a/getter_map_coverage_test.go b/getter_map_coverage_test.go index 5482504..5bd7ca0 100644 --- a/getter_map_coverage_test.go +++ b/getter_map_coverage_test.go @@ -46,7 +46,7 @@ func TestMapDataGetIntoNilMapPointer(t *testing.T) { name TEXT NOT NULL )` sqlDB := openTestSQLiteDB(t, createSQL) - db := NewDatabase(sqlDB, newSchema(), opts).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), opts)).(*database) rec := record.NewRecordWithData( record.NewKeyWithID("widgets", "w1"), @@ -85,7 +85,7 @@ func TestMapDataGetBlobAsString(t *testing.T) { payload BLOB NOT NULL )` sqlDB := openTestSQLiteDB(t, createSQL) - db := NewDatabase(sqlDB, newSchema(), opts).(*database) + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), opts)).(*database) // Insert a genuine BLOB value directly so the driver returns []byte on read. if _, err := sqlDB.Exec(`INSERT INTO blobs (id, payload) VALUES (?, ?)`, "b1", []byte("hello-blob")); err != nil { diff --git a/go.mod b/go.mod index 56a7750..5a8748c 100644 --- a/go.mod +++ b/go.mod @@ -8,14 +8,14 @@ toolchain go1.26.5 require ( github.com/DATA-DOG/go-sqlmock v1.5.2 - github.com/dal-go/dalgo v0.63.2 - github.com/dal-go/record v0.1.0 + github.com/dal-go/dalgo v0.64.2 + github.com/dal-go/record v0.1.1 github.com/georgysavva/scany/v2 v2.1.4 modernc.org/sqlite v1.54.0 ) require ( - github.com/RoaringBitmap/roaring/v2 v2.22.0 // indirect + github.com/RoaringBitmap/roaring/v2 v2.24.0 // indirect github.com/bits-and-blooms/bitset v1.24.6 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/google/uuid v1.6.0 // indirect diff --git a/go.sum b/go.sum index 3a5fe06..41dd4c7 100644 --- a/go.sum +++ b/go.sum @@ -1,17 +1,15 @@ github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= -github.com/RoaringBitmap/roaring/v2 v2.22.0 h1:aGqjvTSkJSTP7W6q518EHiK9RRRb5gJbCaaciCFr/Lg= -github.com/RoaringBitmap/roaring/v2 v2.22.0/go.mod h1:SfT3of9nYh3vis1dIbCj4Yw6KQGujTN+f345nrN/0JA= +github.com/RoaringBitmap/roaring/v2 v2.24.0 h1:zQkkBZtG3WRP4j+P3A5DO221SvL1Br88TJkhyqEQRZo= +github.com/RoaringBitmap/roaring/v2 v2.24.0/go.mod h1:SfT3of9nYh3vis1dIbCj4Yw6KQGujTN+f345nrN/0JA= github.com/bits-and-blooms/bitset v1.24.6 h1:qcrftZUVBIwfs+m+nhoCBAPT+ZPZZjti8SbHbDQQkZ4= github.com/bits-and-blooms/bitset v1.24.6/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= github.com/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs= github.com/cockroachdb/cockroach-go/v2 v2.2.0/go.mod h1:u3MiKYGupPPjkn3ozknpMUpxPaNLTFWAya419/zv6eI= -github.com/dal-go/dalgo v0.63.1 h1:GEJAGlNH5xGLdFasSIRrYdqGfd0+4A9DGQ843qJQbyA= -github.com/dal-go/dalgo v0.63.1/go.mod h1:LtD5XVzb1kAdXaRcWVNy4F2ROC4fqR4jqD3q/GD4fJQ= -github.com/dal-go/dalgo v0.63.2 h1:L3hDte5QaorZngNK619V1zKach4qfeb9jOQQUsn4vrc= -github.com/dal-go/dalgo v0.63.2/go.mod h1:LtD5XVzb1kAdXaRcWVNy4F2ROC4fqR4jqD3q/GD4fJQ= -github.com/dal-go/record v0.1.0 h1:hA4143oZwIgtBH/1BRTUEZMCpDfXQr3ONlVXX8USCNg= -github.com/dal-go/record v0.1.0/go.mod h1:quwsVJTT0f6y3Mhx+yHpTobY7luX1M6kyO6fdJ/AFYE= +github.com/dal-go/dalgo v0.64.2 h1:uWCRISCMTpuwjq+VKlymq3kBtdr0c09gcsr75zmeqrw= +github.com/dal-go/dalgo v0.64.2/go.mod h1:PZGzE0AqnaJgPEDTSo7ayfKZaoglhFQ9FxHecF3aQAc= +github.com/dal-go/record v0.1.1 h1:N2WVDBnm2tOb83h5DJqFyINB5kH0vLjKlYFAgCJWv2g= +github.com/dal-go/record v0.1.1/go.mod h1:quwsVJTT0f6y3Mhx+yHpTobY7luX1M6kyO6fdJ/AFYE= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= diff --git a/inserter_options_test.go b/inserter_options_test.go index d894e17..feadfee 100644 --- a/inserter_options_test.go +++ b/inserter_options_test.go @@ -17,11 +17,11 @@ func newUsersDatabaseWithMock(t *testing.T) (*database, sqlmock.Sqlmock, func()) if err != nil { t.Fatal(err) } - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) return db, mock, func() { closeDatabase(t, sqlDB) } } diff --git a/inserter_test.go b/inserter_test.go index 2b35e83..16f2d3b 100644 --- a/inserter_test.go +++ b/inserter_test.go @@ -23,11 +23,11 @@ func TestInserter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) u := user{Name: "u1"} record := dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), &u) @@ -49,11 +49,11 @@ func TestInserter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) records := []dalrecord.Record{ dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), &user{Name: "u1"}), diff --git a/setter_test.go b/setter_test.go index eb33f86..ea4f057 100644 --- a/setter_test.go +++ b/setter_test.go @@ -20,11 +20,11 @@ func TestSetter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) u := user{Name: "u1"} record := dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), &u) @@ -45,11 +45,11 @@ func TestSetter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) u := user{Name: "u1"} record := dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), &u) @@ -70,11 +70,11 @@ func TestSetter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) records := []dalrecord.Record{ dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), &user{Name: "u1"}), @@ -98,11 +98,11 @@ func TestSetter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) u := user{Name: "u1"} record := dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), &u) diff --git a/sql_map_get_test.go b/sql_map_get_test.go index 6e342d4..ba4c5d3 100644 --- a/sql_map_get_test.go +++ b/sql_map_get_test.go @@ -47,7 +47,7 @@ func TestMapDataGetRoundTrip(t *testing.T) { newDB := func(t *testing.T) *database { t.Helper() sqlDB := openTestSQLiteDB(t, createSQL) - return NewDatabase(sqlDB, newSchema(), opts).(*database) + return dal.BackendOf(NewDatabase(sqlDB, newSchema(), opts)).(*database) } t.Run("Insert_then_Get_map", func(t *testing.T) { diff --git a/sql_map_test.go b/sql_map_test.go index cef2cc1..9e20dfe 100644 --- a/sql_map_test.go +++ b/sql_map_test.go @@ -120,11 +120,11 @@ func TestInserter_MapData(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) data := map[string]any{"col_b": 42, "col_a": "x"} record := dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), data) diff --git a/transaction_test.go b/transaction_test.go index 4ca3f43..d64187c 100644 --- a/transaction_test.go +++ b/transaction_test.go @@ -171,11 +171,17 @@ func TestTransaction(t *testing.T) { t.Run("Upsert", func(t *testing.T) { sqlDB, mock, _ := sqlmock.New() defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + // Upsert is an adapter-specific convenience method, not part of any + // dal package interface, so the framework's validated transaction + // wrapper (dal.validatedTx) does not promote it. dal.BackendOf + // recovers the adapter's own Backend so RunReadwriteTransaction + // hands the worker the concrete *transaction the type assertion + // below expects, exactly as it did before dal.DB was sealed. + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }) + })) mock.ExpectBegin() mock.ExpectQuery("SELECT ID FROM users WHERE ID = ?").WillReturnRows(sqlmock.NewRows([]string{"ID"})) // not exists mock.ExpectExec("INSERT INTO users").WillReturnResult(sqlmock.NewResult(1, 1)) diff --git a/updater_test.go b/updater_test.go index e8ee839..f317bb0 100644 --- a/updater_test.go +++ b/updater_test.go @@ -20,11 +20,11 @@ func TestUpdater(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) key := dalrecord.NewKeyWithID("users", "id1") updates := []update.Update{ @@ -48,11 +48,11 @@ func TestUpdater(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) keys := []*dalrecord.Key{ dalrecord.NewKeyWithID("users", "id1"), @@ -82,11 +82,11 @@ func TestUpserter(t *testing.T) { } defer closeDatabase(t, sqlDB) - db := NewDatabase(sqlDB, newSchema(), DbOptions{ + db := dal.BackendOf(NewDatabase(sqlDB, newSchema(), DbOptions{ Recordsets: map[string]*Recordset{ "users": NewRecordset("users", Table, []dal.FieldRef{dal.Field("ID")}), }, - }).(*database) + })).(*database) u := user{Name: "u1"} record := dalrecord.NewRecordWithData(dalrecord.NewKeyWithID("users", "id1"), &u)