sqlize

package module
v0.8.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 7, 2024 License: AGPL-3.0 Imports: 13 Imported by: 3

README

sqlize

Go Reference

Experimental tools to help with the use of Go sql. It strives not to be a framework but a toolbox that makes it easy to pick only the tools you want.

This module is somewhat chaotic. It is primarily published as a dependency off another FOSS app project. However the sqlize has matured. And, by the way, it should combine quite well with sqlx.

Key features are:

  • Easily handle transactions with a "begin at most once" semantic. See sqlize.Xaction and stmt.Xaction.

  • Query building that hepls to keep queries in line with the DB model. See package bsq.

  • Log DB calls to Go's standard logger or tests. Can easily extended for other loggers.

  • Entities and repositories

  • Supports using the above concepts with prepared statements.

Documentation

Overview

Package sqlize helps with on-demand transactions, SQL logging and running scripts with Go's standard database/sql package.

Moular DB Code with Transactions

In Go the object to perform DB operations is explicitly passed around – for good reasons. These objects are either of type *sql.DB and *sql.Tx. If one wants to perfom a single atomic DB operation its fast and simple to use sql.DB.Exec et al. If one needs to combine more than one operation into a tarnsaction, then sql.Tx.Exed et al must be used. Now consider a DB function

func simpleDBOp(db *sql.DB) error {
    … a single DB operation …
}

Nice and smooth! Now we want to use it in a complex DB transaction:

func complexDBOp(tx *sql.Tx) error { // complex ⇒ need a Tx
    …
    simpleDBOp(tx) // compile error
    …
}

One would have to rewrite simpleDBOp(tx *sql.Tx)… which imposes the costs of explicit transactions to all users of simpleDBOp. That's why sqlize uses the Querier interface that has the common methods of sql.DB and sql.Tx. This makes the sqlize API reusable and allows to implement application code in a more modular way:

// Now, complexDBOp(tx *sql.Tx) will compile
func simpleDBOp(db sqlize.Querier) error {
    … a single DB operation …
}
Example (SplitPara)
rd := strings.NewReader(`1 one line
1 next line
	
2 another line
   

3 third 1
3 third 2`)
scn := bufio.NewScanner(rd)
scn.Split(splitPara)
for scn.Scan() {
	fmt.Print(scn.Text())
	fmt.Println("¶")
}
Output:

1 one line
1 next line¶
2 another line¶
3 third 1
3 third 2¶

Index

Examples

Constants

View Source
const NoID = 0

NoID is an ID that no DB record must have as an ID.

Variables

This section is empty.

Functions

func Begin added in v0.7.2

func Begin(q Querier) (tx *sql.Tx, ok bool, err error)

Begin starts a new transaction tx if q is a DB and returns tx, true. If q is altrady a transaction tx then tx, false is returned. If an error occurs it will be returned as err.

func BeginTx added in v0.7.2

func BeginTx(q Querier, ctx context.Context, opts *sql.TxOptions) (*sql.Tx, bool, error)

func CommitOrRollbackOn added in v0.7.2

func CommitOrRollbackOn(err *error, tx *sql.Tx)
Example
sql.Register("CommitOrRollbackOn", sqlmw.Driver(&sqlite3.SQLiteDriver{}, new(printCommitNRollbackstruct)))
db, _ := sql.Open("CommitOrRollbackOn", ":memory:")
defer db.Close()

tx, ok, err := Begin(db)
if err != nil {
	fmt.Println(err)
	return
}
if ok {
	defer CommitOrRollbackOn(&err, tx)
}
// An non-nil err will rool back
err = errors.New("Just an error")
Output:

TxRollback

func LogDriver added in v0.7.2

func LogDriver(name string, drv driver.Driver, logTo Logger, flags LogFlag)

LogDriver registers a new sql driver that wraps the real driver drv with calls to the Logger logTo. With flags one can select which driver methods are logged. If logTo is nil the driver will log to the standard logger from Go's log package.

Example
const loggingDriverName = "log-sqlite3"
LogDriver(
	loggingDriverName, &sqlite3.SQLiteDriver{},
	NewStdLogger(log.New(os.Stdout, "DB: #", 0)),
	LogAll,
)
db, err := sql.Open(loggingDriverName, ":memory:")
if err != nil {
	fmt.Println(err)
	return
}
defer db.Close()
db.QueryRow("SELECT * FROM sqlize")
Output:

DB: #1     Connect
DB: #1 OK  Connect
DB: #2     Query [SELECT * FROM sqlize []]
DB: #2 ERR Query no such table: sqlize

func MustBegin added in v0.7.2

func MustBegin(q Querier) (tx *sql.Tx, ok bool)

func MustBeginTx added in v0.7.2

func MustBeginTx(q Querier, ctx context.Context, opts *sql.TxOptions) (*sql.Tx, bool)

func NotNoRows

func NotNoRows(err error) error

func RunScript

func RunScript(db Querier, rd io.Reader, ignoreErr bool) error

func RunScriptFile

func RunScriptFile(db Querier, file string, ignoreErr bool) error

func Xaction added in v0.2.0

func Xaction(q Querier, do func(*sql.Tx) error) (err error)
Example
sql.Register("ExampleXaction", sqlmw.Driver(&sqlite3.SQLiteDriver{}, new(printCommitNRollbackstruct)))
db, _ := sql.Open("ExampleXaction", ":memory:")
defer db.Close()

Xaction(db, func(tx *sql.Tx) error {
	return errors.New("Just an error")
})
Output:

TxRollback

func XactionTx added in v0.7.2

func XactionTx(q Querier, ctx context.Context, opts *sql.TxOptions, do func(*sql.Tx) error) (err error)

Types

type CallRef added in v0.7.2

type CallRef struct {
	Name string
	ID   any
}

type LogFlag added in v0.7.2

type LogFlag uint
const (
	LogBeginTx LogFlag = (1 << iota)
	LogPrepare
	LogPing
	LogExec
	LogQuery
	LogConnect
	LogInsertId
	LogRowsAffected
	LogRowsNext
	LogRowsClose
	LogStmtExec
	LogStmtQuery
	LogStmtClose
	LogTxCommit
	LogTxRollback

	LogDefault = LogExec | LogQuery | LogStmtExec | LogStmtQuery | LogInsertId

	LogAll = ^LogFlag(0)
)

type Logger added in v0.7.2

type Logger interface {
	Call(name string, args ...any) CallRef
	Result(ref CallRef, err error, args ...any)
}

func NewStdLogger added in v0.7.2

func NewStdLogger(l *log.Logger) Logger

NewStdLogger creates a new SQL logger that logs with Go's standard log package. If l is nil the log.Default() logger is used.

type Querier added in v0.2.0

type Querier interface {
	Exec(query string, args ...interface{}) (sql.Result, error)
	ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
	Query(query string, args ...interface{}) (*sql.Rows, error)
	QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
	QueryRow(query string, args ...interface{}) *sql.Row
	QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
	Prepare(query string) (*sql.Stmt, error)
	PrepareContext(ctx context.Context, query string) (*sql.Stmt, error)
}

Querier allows to run or execute queries against a database or to prepare statements. It is used to drop the distinction between sql.DB and sql.Tx in application code. See also Xaction and XactionContext.

type RollbackError

type RollbackError struct {
	Cause    error
	Rollback error
}

func (RollbackError) Error

func (ce RollbackError) Error() string

func (RollbackError) Unwrap

func (ce RollbackError) Unwrap() error

Directories

Path Synopsis
bsq
Package bsq helps to Build Structured Queries for SQL in a maintainable manner.
Package bsq helps to Build Structured Queries for SQL in a maintainable manner.
keywords
Package keywords defines some handy SQL keywords as const strings for use with the bsq query builder.
Package keywords defines some handy SQL keywords as const strings for use with the bsq query builder.
Package dbtest has utilities to help with writing DB related tests in conjunction with sqlize.
Package dbtest has utilities to help with writing DB related tests in conjunction with sqlize.
Package null implements typed adapters for Go values to nullable DB columns.
Package null implements typed adapters for Go values to nullable DB columns.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL