diff --git a/sqldb/v2/interfaces.go b/sqldb/v2/interfaces.go index caec453ea..adce4e53b 100644 --- a/sqldb/v2/interfaces.go +++ b/sqldb/v2/interfaces.go @@ -84,20 +84,12 @@ func ReadTxOpt() TxOptions { } } -// BaseQuerier is a generic interface that represents the base methods that any -// database backend implementation which uses a Querier for its operations must -// implement. -type BaseQuerier interface { - // Backend returns the type of the database backend used. - Backend() BackendType -} - // BatchedTx is a generic interface that represents the ability to execute // several operations to a given storage interface in a single atomic // transaction. Typically, Q here will be some subset of the main sqlc.Querier // interface allowing it to only depend on the routines it needs to implement // any additional business logic. -type BatchedTx[Q BaseQuerier] interface { +type BatchedTx[Q any] interface { // ExecTx will execute the passed txBody, operating upon generic // parameter Q (usually a storage interface) in a single transaction. // @@ -137,6 +129,9 @@ type BatchedQuerier interface { // BeginTx creates a new database transaction given the set of // transaction options. BeginTx(ctx context.Context, options TxOptions) (*sql.Tx, error) + + // Backend returns the type of the database backend used. + Backend() BackendType } // txExecutorOptions is a struct that holds the options for the transaction @@ -188,7 +183,7 @@ func WithTxRetryDelay(delay time.Duration) TxExecutorOption { // query a type needs to run under a database transaction, and also the set of // options for that transaction. The QueryCreator is used to create a query // given a database transaction created by the BatchedQuerier. -type TransactionExecutor[Query BaseQuerier] struct { +type TransactionExecutor[Query any] struct { BatchedQuerier createQuery QueryCreator[Query] @@ -196,10 +191,14 @@ type TransactionExecutor[Query BaseQuerier] struct { opts *txExecutorOptions } +// A compile-time assertion to ensure TransactionExecutor satisfies the +// batched transaction interface. +var _ BatchedTx[any] = (*TransactionExecutor[any])(nil) + // NewTransactionExecutor creates a new instance of a TransactionExecutor given // a Querier query object and a concrete type for the type of transactions the // Querier understands. -func NewTransactionExecutor[Querier BaseQuerier](db BatchedQuerier, +func NewTransactionExecutor[Querier any](db BatchedQuerier, createQuery QueryCreator[Querier], opts ...TxExecutorOption) *TransactionExecutor[Querier] { @@ -215,6 +214,11 @@ func NewTransactionExecutor[Querier BaseQuerier](db BatchedQuerier, } } +// Backend returns the type of database backend used by the executor. +func (t *TransactionExecutor[Q]) Backend() BackendType { + return t.BatchedQuerier.Backend() +} + // randRetryDelay returns a random retry delay between -50% and +50% of the // configured delay that is doubled for each attempt and capped at a max value. func randRetryDelay(initialRetryDelay, maxRetryDelay time.Duration, diff --git a/sqldb/v2/interfaces_test.go b/sqldb/v2/interfaces_test.go new file mode 100644 index 000000000..024b36746 --- /dev/null +++ b/sqldb/v2/interfaces_test.go @@ -0,0 +1,48 @@ +package sqldb + +import ( + "context" + "database/sql" + "testing" + + "github.com/stretchr/testify/require" +) + +// testQuerier is a minimal query wrapper used to instantiate the generic +// transaction executor in tests. +type testQuerier struct { +} + +// testBatchedQuerier is a minimal BatchedQuerier implementation used to verify +// that TransactionExecutor forwards backend identity. +type testBatchedQuerier struct { + backend BackendType +} + +// BeginTx is a stub implementation used to satisfy the BatchedQuerier +// interface in tests. +func (t testBatchedQuerier) BeginTx(context.Context, + TxOptions) (*sql.Tx, error) { + + return nil, nil +} + +// Backend returns the backend type used by the test batched querier. +func (t testBatchedQuerier) Backend() BackendType { + return t.backend +} + +// TestTransactionExecutorBackend verifies that the executor forwards the +// backend type from its batched querier. +func TestTransactionExecutorBackend(t *testing.T) { + t.Parallel() + + executor := NewTransactionExecutor[testQuerier]( + testBatchedQuerier{backend: BackendTypePostgres}, + func(*sql.Tx) testQuerier { + return testQuerier{} + }, + ) + + require.Equal(t, BackendTypePostgres, executor.Backend()) +}