157 lines
3.9 KiB
Go
157 lines
3.9 KiB
Go
|
|
package stardb
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"database/sql"
|
||
|
|
"errors"
|
||
|
|
)
|
||
|
|
|
||
|
|
// StarTx represents a database transaction
|
||
|
|
type StarTx struct {
|
||
|
|
tx *sql.Tx
|
||
|
|
db *StarDB
|
||
|
|
}
|
||
|
|
|
||
|
|
// Query executes a query within the transaction
|
||
|
|
func (t *StarTx) Query(query string, args ...interface{}) (*StarRows, error) {
|
||
|
|
return t.query(nil, query, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// QueryContext executes a query with context within the transaction
|
||
|
|
func (t *StarTx) QueryContext(ctx context.Context, query string, args ...interface{}) (*StarRows, error) {
|
||
|
|
return t.query(ctx, query, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// query is the internal query implementation
|
||
|
|
func (t *StarTx) query(ctx context.Context, query string, args ...interface{}) (*StarRows, error) {
|
||
|
|
if err := t.db.Ping(); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
var rows *sql.Rows
|
||
|
|
var err error
|
||
|
|
|
||
|
|
if ctx == nil {
|
||
|
|
rows, err = t.tx.Query(query, args...)
|
||
|
|
} else {
|
||
|
|
rows, err = t.tx.QueryContext(ctx, query, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
starRows := &StarRows{
|
||
|
|
rows: rows,
|
||
|
|
db: t.db,
|
||
|
|
}
|
||
|
|
|
||
|
|
if !t.db.ManualScan {
|
||
|
|
err = starRows.parse()
|
||
|
|
}
|
||
|
|
|
||
|
|
return starRows, err
|
||
|
|
}
|
||
|
|
|
||
|
|
// Exec executes a query within the transaction
|
||
|
|
func (t *StarTx) Exec(query string, args ...interface{}) (sql.Result, error) {
|
||
|
|
return t.exec(nil, query, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ExecContext executes a query with context within the transaction
|
||
|
|
func (t *StarTx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
||
|
|
return t.exec(ctx, query, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// exec is the internal exec implementation
|
||
|
|
func (t *StarTx) exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
||
|
|
if err := t.db.Ping(); err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
|
||
|
|
if ctx == nil {
|
||
|
|
return t.tx.Exec(query, args...)
|
||
|
|
}
|
||
|
|
return t.tx.ExecContext(ctx, query, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Prepare creates a prepared statement within the transaction
|
||
|
|
func (t *StarTx) Prepare(query string) (*StarStmt, error) {
|
||
|
|
stmt, err := t.tx.Prepare(query)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return &StarStmt{stmt: stmt, db: t.db}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// PrepareContext creates a prepared statement with context
|
||
|
|
func (t *StarTx) PrepareContext(ctx context.Context, query string) (*StarStmt, error) {
|
||
|
|
stmt, err := t.tx.PrepareContext(ctx, query)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
return &StarStmt{stmt: stmt, db: t.db}, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
// QueryStmt executes a prepared statement query within the transaction
|
||
|
|
func (t *StarTx) QueryStmt(query string, args ...interface{}) (*StarRows, error) {
|
||
|
|
if query == "" {
|
||
|
|
return nil, errors.New("query string cannot be empty")
|
||
|
|
}
|
||
|
|
stmt, err := t.Prepare(query)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
defer stmt.Close()
|
||
|
|
return stmt.Query(args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// QueryStmtContext executes a prepared statement query with context
|
||
|
|
func (t *StarTx) QueryStmtContext(ctx context.Context, query string, args ...interface{}) (*StarRows, error) {
|
||
|
|
if query == "" {
|
||
|
|
return nil, errors.New("query string cannot be empty")
|
||
|
|
}
|
||
|
|
stmt, err := t.PrepareContext(ctx, query)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
defer stmt.Close()
|
||
|
|
return stmt.QueryContext(ctx, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ExecStmt executes a prepared statement within the transaction
|
||
|
|
func (t *StarTx) ExecStmt(query string, args ...interface{}) (sql.Result, error) {
|
||
|
|
if query == "" {
|
||
|
|
return nil, errors.New("query string cannot be empty")
|
||
|
|
}
|
||
|
|
stmt, err := t.Prepare(query)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
defer stmt.Close()
|
||
|
|
return stmt.Exec(args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// ExecStmtContext executes a prepared statement with context
|
||
|
|
func (t *StarTx) ExecStmtContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
|
||
|
|
if query == "" {
|
||
|
|
return nil, errors.New("query string cannot be empty")
|
||
|
|
}
|
||
|
|
stmt, err := t.PrepareContext(ctx, query)
|
||
|
|
if err != nil {
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
defer stmt.Close()
|
||
|
|
return stmt.ExecContext(ctx, args...)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Commit commits the transaction
|
||
|
|
func (t *StarTx) Commit() error {
|
||
|
|
return t.tx.Commit()
|
||
|
|
}
|
||
|
|
|
||
|
|
// Rollback rolls back the transaction
|
||
|
|
func (t *StarTx) Rollback() error {
|
||
|
|
return t.tx.Rollback()
|
||
|
|
}
|