2024-07-12 21:25:20 +00:00
|
|
|
package querier
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
"sync"
|
|
|
|
"sync/atomic"
|
|
|
|
)
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
type contextKey string
|
|
|
|
|
|
|
|
const QuerierContextKey contextKey = "querier"
|
2024-07-12 21:25:20 +00:00
|
|
|
|
|
|
|
type conn interface {
|
|
|
|
Commit() error
|
|
|
|
Rollback() error
|
|
|
|
Begin() (*sql.Tx, error)
|
|
|
|
BeginTx(ctx context.Context, opts *sql.TxOptions) (*sql.Tx, error)
|
|
|
|
QueryRow(query string, args ...any) *sql.Row
|
|
|
|
QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
|
|
|
|
Exec(query string, args ...any) (sql.Result, error)
|
|
|
|
ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
|
|
|
|
}
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
type Querier struct {
|
2024-07-12 21:25:20 +00:00
|
|
|
txRequested atomic.Bool
|
|
|
|
initOnce sync.Once
|
|
|
|
conn conn
|
|
|
|
}
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
func GetQuerierFromContextOrNew(ctx context.Context) *Querier {
|
|
|
|
q, ok := ctx.Value(QuerierContextKey).(*Querier)
|
2024-07-12 21:25:20 +00:00
|
|
|
if !ok {
|
2024-07-24 23:45:04 +00:00
|
|
|
q = &Querier{
|
2024-07-12 21:25:20 +00:00
|
|
|
txRequested: atomic.Bool{},
|
|
|
|
initOnce: sync.Once{},
|
|
|
|
conn: nil,
|
|
|
|
}
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
|
2024-07-12 21:25:20 +00:00
|
|
|
return q
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
|
|
|
|
func (q *Querier) Begin() *Querier {
|
2024-07-12 21:25:20 +00:00
|
|
|
q.txRequested.Store(true)
|
2024-07-24 23:45:04 +00:00
|
|
|
|
2024-07-12 21:25:20 +00:00
|
|
|
return q
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
|
|
|
|
func (q *Querier) Continue(ctx context.Context, conn *SQLDB) (*Querier, error) {
|
2024-07-12 21:25:20 +00:00
|
|
|
var iErr error
|
|
|
|
q.initOnce.Do(func() {
|
|
|
|
if q.txRequested.Load() {
|
|
|
|
tx, bErr := conn.BeginTx(ctx, nil)
|
|
|
|
if bErr != nil {
|
|
|
|
iErr = bErr
|
2024-07-24 23:45:04 +00:00
|
|
|
|
2024-07-12 21:25:20 +00:00
|
|
|
return
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
q.conn = &SQLTx{tx}
|
2024-07-12 21:25:20 +00:00
|
|
|
} else {
|
2024-07-17 11:04:42 +00:00
|
|
|
q.conn = conn
|
2024-07-12 21:25:20 +00:00
|
|
|
}
|
|
|
|
})
|
2024-07-24 23:45:04 +00:00
|
|
|
|
2024-07-12 21:25:20 +00:00
|
|
|
return q, iErr
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
|
|
|
|
func (q *Querier) Commit() error {
|
2024-07-12 21:25:20 +00:00
|
|
|
return q.conn.Commit()
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
|
|
|
|
func (q *Querier) Rollback() error {
|
2024-07-12 21:25:20 +00:00
|
|
|
return q.conn.Rollback()
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
|
|
|
|
func (q *Querier) Conn() conn {
|
2024-07-12 21:25:20 +00:00
|
|
|
return q.conn
|
|
|
|
}
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
type SQLTx struct {
|
2024-07-12 21:25:20 +00:00
|
|
|
*sql.Tx
|
|
|
|
}
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
func (tx *SQLTx) Begin() (*sql.Tx, error) {
|
2024-07-12 21:25:20 +00:00
|
|
|
return &sql.Tx{}, nil
|
|
|
|
}
|
2024-07-24 23:45:04 +00:00
|
|
|
|
|
|
|
func (tx *SQLTx) BeginTx(_ context.Context, _ *sql.TxOptions) (*sql.Tx, error) {
|
2024-07-12 21:25:20 +00:00
|
|
|
return &sql.Tx{}, nil
|
|
|
|
}
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
type SQLDB struct {
|
2024-07-12 21:25:20 +00:00
|
|
|
*sql.DB
|
|
|
|
}
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
func (db *SQLDB) Commit() error {
|
2024-07-12 21:25:20 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-07-24 23:45:04 +00:00
|
|
|
func (db *SQLDB) Rollback() error {
|
2024-07-12 21:25:20 +00:00
|
|
|
return nil
|
|
|
|
}
|