types

package
v0.20.0 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2025 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package types contains the core database interface definitions for go-bricks. These interfaces are separate from the main database package to avoid import cycles and to make them easily accessible for mocking and testing.

Package types contains the core database interface definitions for go-bricks.

Package types contains the core database interface definitions for go-bricks.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrEmptyTableName is returned when Table() is called with an empty name.
	ErrEmptyTableName = errors.New("table name cannot be empty")

	// ErrEmptyTableAlias is returned when TableRef.As() is called with an empty alias.
	ErrEmptyTableAlias = errors.New("table alias cannot be empty")

	ErrNilTableRef = errors.New("table reference cannot be nil")

	// ErrEmptyExpressionSQL is returned when Expr() is called with empty SQL.
	ErrEmptyExpressionSQL = errors.New("expression SQL cannot be empty")

	// ErrTooManyAliases is returned when Expr() is called with more than 1 alias.
	ErrTooManyAliases = errors.New("expression accepts maximum 1 alias")

	// ErrDangerousAlias is returned when an alias contains SQL injection patterns.
	ErrDangerousAlias = errors.New("alias contains dangerous characters")

	// ErrNilSubquery is returned when ValidateSubquery() is called with nil subquery.
	ErrNilSubquery = errors.New("subquery cannot be nil")

	// ErrInvalidSubquery is returned when subquery validation fails.
	ErrInvalidSubquery = errors.New("invalid subquery")

	// ErrEmptySubquerySQL is returned when subquery produces empty SQL.
	ErrEmptySubquerySQL = errors.New("subquery produced empty SQL")
)

Sentinel errors for validation failures in type constructors. These can be used with errors.Is() for programmatic error checking.

Functions

func MustValidateSubquery added in v0.19.0

func MustValidateSubquery(subquery SelectQueryBuilder)

MustValidateSubquery is like ValidateSubquery but panics on error. Use this only when errors indicate programming bugs that should crash immediately.

func ValidateSubquery added in v0.14.2

func ValidateSubquery(subquery SelectQueryBuilder) error

ValidateSubquery checks if a subquery is valid for use in filter expressions. Returns an error if subquery is nil or produces invalid SQL.

Returns:

  • ErrNilSubquery if subquery is nil
  • ErrInvalidSubquery if subquery validation fails
  • ErrEmptySubquerySQL if subquery produces empty SQL

This function is called internally by filter implementations to ensure subqueries are constructed correctly before query execution.

Types

type Columns added in v0.15.0

type Columns interface {
	// Col retrieves the vendor-quoted column name for the given struct field name.
	// If aliased via As(), returns qualified column (e.g., "u.id").
	// Panics if the field name is not found (fail-fast for development-time typos).
	//
	// Example (unaliased):
	//   cols.Col("ID")    // Returns: "id" (PostgreSQL) or "ID" (Oracle)
	//   cols.Col("Level") // Returns: "level" (PostgreSQL) or "LEVEL" (Oracle, quoted)
	//
	// Example (aliased):
	//   u := cols.As("u")
	//   u.Col("ID")       // Returns: "u.id" (PostgreSQL) or "u.\"ID\"" (Oracle)
	Col(fieldName string) string

	// As returns a new Columns instance bound to the specified table alias.
	// The returned instance shares the underlying column metadata (zero-copy).
	// This method is immutable - the original Columns instance remains unchanged.
	//
	// Example:
	//   cols := qb.Columns(&User{})
	//   u := cols.As("u")
	//   p := cols.As("p")
	//   u.Col("ID")  // "u.id"
	//   p.Col("ID")  // "p.id"
	//   cols.Col("ID") // "id" (original unaffected)
	As(alias string) Columns

	// Alias returns the current table alias, or empty string if unaliased.
	//
	// Example:
	//   cols.Alias()        // ""
	//   cols.As("u").Alias() // "u"
	Alias() string

	// Cols retrieves vendor-quoted column names for multiple struct field names.
	// If aliased, returns qualified columns.
	// Panics if any field name is not found.
	//
	// Example:
	//   cols.Cols("ID", "Name", "Email") // ["id", "name", "email"]
	//   cols.As("u").Cols("ID", "Name")  // ["u.id", "u.name"]
	Cols(fieldNames ...string) []string

	// All returns vendor-quoted column names for all columns in the struct,
	// in the order they were declared in the struct definition.
	//
	// Example:
	//   cols.All()        // ["id", "name", "email"] (unaliased)
	//   cols.As("u").All() // ["u.id", "u.name", "u.email"] (aliased)
	All() []string

	// FieldMap extracts field values from a struct instance into a map.
	// The map keys are vendor-quoted column names (respecting alias if set).
	// Only fields with `db` tags are included. Zero values are included.
	//
	// Example:
	//   user := User{ID: 123, Name: "Alice", Email: "alice@example.com"}
	//   cols.FieldMap(&user)
	//   // Returns: {"id": 123, "name": "Alice", "email": "alice@example.com"}
	//
	//   cols.As("u").FieldMap(&user)
	//   // Returns: {"u.id": 123, "u.name": "Alice", "u.email": "alice@example.com"}
	//
	// Panics if instance is not a struct or pointer to struct.
	FieldMap(instance any) map[string]any

	// AllFields extracts all field values from a struct instance as separate slices.
	// Returns (columns, values) suitable for bulk INSERT/UPDATE operations.
	// Only fields with `db` tags are included. Zero values are included.
	//
	// Example:
	//   user := User{ID: 123, Name: "Alice", Email: "alice@example.com"}
	//   cols, vals := cols.AllFields(&user)
	//   // cols: ["id", "name", "email"]
	//   // vals: [123, "Alice", "alice@example.com"]
	//
	// Panics if instance is not a struct or pointer to struct.
	AllFields(instance any) ([]string, []any)
}

Columns represents cached metadata for a struct type with `db:"column_name"` tags. It provides methods to retrieve vendor-quoted column names with optional table aliasing.

This interface is implemented by the internal columns package and returned by QueryBuilder.Columns(). The metadata is lazily parsed on first use and cached forever.

v2.4 Breaking Changes:

  • Renamed Get() → Col() for consistency with database terminology
  • Renamed Fields() → Cols() with []string return type (was []any)
  • All() now returns []string instead of []any
  • Added As() for immutable aliasing: cols.As("u").Col("ID") → "u.id"
  • Added FieldMap() and AllFields() for struct-to-query conversion

type DeleteQueryBuilder added in v0.13.0

type DeleteQueryBuilder interface {
	// Filtering
	Where(filter Filter) DeleteQueryBuilder

	// Batch operations
	Limit(limit uint64) DeleteQueryBuilder
	OrderBy(orderBys ...string) DeleteQueryBuilder

	// SQL generation
	ToSQL() (sql string, args []any, err error)
}

DeleteQueryBuilder defines the interface for DELETE query building with type-safe filtering. This interface wraps squirrel.DeleteBuilder with Filter API support.

type Filter added in v0.13.0

type Filter interface {
	squirrel.Sqlizer

	// ToSQL is a convenience method with idiomatic Go naming.
	// It should delegate to ToSql() in implementations.
	ToSQL() (sql string, args []any, err error)
}

Filter represents a composable WHERE clause filter that can be combined with AND/OR/NOT operators. Filters are created through FilterFactory methods obtained from QueryBuilder.Filter().

Filter embeds squirrel.Sqlizer for compatibility with Squirrel's query builder, and adds ToSQL() as a convenience method with idiomatic Go naming (uppercase SQL).

This is an interface to support mocking and testing. The concrete implementation is in database/internal/builder package.

type FilterFactory added in v0.13.0

type FilterFactory interface {
	// Comparison operators
	Eq(column string, value any) Filter
	NotEq(column string, value any) Filter
	Lt(column string, value any) Filter
	Lte(column string, value any) Filter
	Gt(column string, value any) Filter
	Gte(column string, value any) Filter
	In(column string, values any) Filter
	NotIn(column string, values any) Filter
	Like(column, pattern string) Filter
	Null(column string) Filter
	NotNull(column string) Filter
	Between(column string, lowerBound, upperBound any) Filter

	// Logical operators
	And(filters ...Filter) Filter
	Or(filters ...Filter) Filter
	Not(filter Filter) Filter

	// Raw escape hatch
	Raw(condition string, args ...any) Filter

	// Subquery support (v2.1+)
	Exists(subquery SelectQueryBuilder) Filter
	NotExists(subquery SelectQueryBuilder) Filter
	InSubquery(column string, subquery SelectQueryBuilder) Filter
}

FilterFactory provides methods for creating composable, type-safe query filters. Filters maintain vendor-specific quoting rules and can be combined with AND/OR/NOT logic.

type Interface

type Interface interface {
	// Querier provides core query execution operations
	Querier

	// Transactor provides transaction management operations
	Transactor

	// Prepared statements
	Prepare(ctx context.Context, query string) (Statement, error)

	// Health and diagnostics
	Health(ctx context.Context) error
	Stats() (map[string]any, error)

	// Connection management
	Close() error

	// Migration support
	MigrationTable() string
	CreateMigrationTable(ctx context.Context) error
}

Interface defines the common database operations supported by the framework. This is the main interface that applications and modules should depend on for database operations, allowing for easy mocking and testing.

Interface is composed of focused sub-interfaces following the Single Responsibility Principle:

  • Querier: Core query execution (Query, QueryRow, Exec, DatabaseType)
  • Transactor: Transaction management (Begin, BeginTx)

For easier testing, consider using the smaller interfaces (Querier or Transactor) when your code doesn't need all Interface capabilities. The database/testing package provides utilities for mocking these interfaces with minimal boilerplate.

Backward compatibility: All existing code using Interface continues to work unchanged.

type JoinFilter added in v0.13.0

type JoinFilter interface {
	squirrel.Sqlizer

	// ToSQL is a convenience method with idiomatic Go naming.
	// It should delegate to ToSql() in implementations.
	ToSQL() (sql string, args []any, err error)
}

JoinFilter represents a filter specifically for JOIN ON conditions where columns are compared to other columns (not to values). This follows Single Responsibility Principle by separating column-to-column comparisons (JOIN) from column-to-value comparisons (WHERE).

JoinFilters are created through JoinFilterFactory methods obtained from QueryBuilder.JoinFilter().

Example:

jf := qb.JoinFilter()
query := qb.Select("*").From("users").JoinOn("profiles", jf.EqColumn("users.id", "profiles.user_id"))

This is an interface to support mocking and testing. The concrete implementation is in database/internal/builder package.

type JoinFilterFactory added in v0.13.0

type JoinFilterFactory interface {
	// Column-to-column comparison operators
	EqColumn(leftColumn, rightColumn string) JoinFilter
	NotEqColumn(leftColumn, rightColumn string) JoinFilter
	LtColumn(leftColumn, rightColumn string) JoinFilter
	LteColumn(leftColumn, rightColumn string) JoinFilter
	GtColumn(leftColumn, rightColumn string) JoinFilter
	GteColumn(leftColumn, rightColumn string) JoinFilter

	// Column-to-value comparison operators (v2.2+)
	// These methods accept any value type, including RawExpression for complex SQL.
	// Regular values generate placeholders; RawExpression values are inserted verbatim.
	Eq(column string, value any) JoinFilter
	NotEq(column string, value any) JoinFilter
	Lt(column string, value any) JoinFilter
	Lte(column string, value any) JoinFilter
	Gt(column string, value any) JoinFilter
	Gte(column string, value any) JoinFilter
	In(column string, values any) JoinFilter
	NotIn(column string, values any) JoinFilter
	Like(column, pattern string) JoinFilter
	Null(column string) JoinFilter
	NotNull(column string) JoinFilter
	Between(column string, lowerBound, upperBound any) JoinFilter

	// Logical operators for complex JOIN conditions
	And(filters ...JoinFilter) JoinFilter
	Or(filters ...JoinFilter) JoinFilter

	// Raw escape hatch for complex JOIN conditions
	Raw(condition string, args ...any) JoinFilter
}

JoinFilterFactory provides methods for creating type-safe JOIN ON filters. JoinFilters support both column-to-column comparisons and column-to-value comparisons, enabling mixed JOIN conditions without requiring Raw() for common cases.

Column-to-value methods accept RawExpression for complex SQL expressions:

jf.Eq("amount", qb.Expr("TO_NUMBER(?)"), 100)  // Expression support
jf.Eq("status", "active")                      // Simple value with placeholder

type Querier added in v0.16.0

type Querier interface {
	// Query executes a SQL query that returns rows, typically a SELECT statement.
	// The caller is responsible for closing the returned rows.
	//
	// The query should use vendor-specific placeholders:
	//   - PostgreSQL: $1, $2, $3
	//   - Oracle: :1, :2, :3
	//   - MongoDB: N/A (query builder handles translation)
	//
	// For vendor-agnostic query construction, use the QueryBuilder.
	Query(ctx context.Context, query string, args ...any) (*sql.Rows, error)

	// QueryRow executes a SQL query that is expected to return at most one row.
	// QueryRow always returns a non-nil value. Errors are deferred until Row's Scan method is called.
	//
	// For vendor-agnostic query construction, use the QueryBuilder.
	QueryRow(ctx context.Context, query string, args ...any) Row

	// Exec executes a SQL statement that doesn't return rows, typically INSERT, UPDATE, or DELETE.
	// The returned sql.Result provides RowsAffected and LastInsertId (if supported by the vendor).
	//
	// For vendor-agnostic query construction, use the QueryBuilder.
	Exec(ctx context.Context, query string, args ...any) (sql.Result, error)

	// DatabaseType returns the vendor identifier for this database connection.
	// Valid values are defined as constants: PostgreSQL, Oracle, MongoDB.
	//
	// This is included in Querier (despite being metadata) because the query builder
	// requires vendor information for placeholder generation and identifier quoting.
	// Including it here prevents forcing all test mocks to implement additional interfaces.
	DatabaseType() string
}

Querier defines the core query execution operations that represent 80% of typical database usage. This interface follows the Single Responsibility Principle by focusing solely on query execution, separate from transaction management, health checks, and migration support.

Querier is designed for easy mocking in unit tests, requiring only 4 methods instead of the full 13 methods in the Interface type. Most business logic only needs query execution capabilities.

The database.Interface type embeds Querier, so all existing code continues to work unchanged.

Usage in tests:

// Simple mock implementation
type mockQuerier struct {
    queryFunc    func(ctx context.Context, query string, args ...any) (*sql.Rows, error)
    queryRowFunc func(ctx context.Context, query string, args ...any) Row
    execFunc     func(ctx context.Context, query string, args ...any) (sql.Result, error)
}

// Inject via ModuleDeps.GetDB
deps := &app.ModuleDeps{
    GetDB: func(ctx context.Context) (database.Interface, error) {
        return mockQuerier, nil
    },
}

For comprehensive testing utilities, see the database/testing package which provides TestDB with fluent API for setting up query expectations and assertions.

type QueryBuilderInterface added in v0.8.1

type QueryBuilderInterface interface {
	// Vendor information
	Vendor() string

	// Filter factories
	Filter() FilterFactory
	JoinFilter() JoinFilterFactory

	// Expression builder (v2.1+)
	// Returns error if SQL is empty, too many aliases provided, or alias contains dangerous characters.
	Expr(sql string, alias ...string) (RawExpression, error)

	// MustExpr is like Expr but panics on error.
	// Use this only in static initialization or tests where errors indicate programming bugs.
	MustExpr(sql string, alias ...string) RawExpression

	// Column metadata extraction (v2.4+)
	// Extracts column metadata from structs with `db:"column_name"` tags.
	// Lazily parses struct on first use, caches forever.
	// Returns vendor-specific quoted column names (e.g., Oracle reserved words).
	//
	// Example:
	//   type User struct {
	//       ID    int64  `db:"id"`
	//       Level string `db:"level"` // Oracle reserved word
	//   }
	//   cols := qb.Columns(&User{})
	//   qb.Select(cols.Col("ID"), cols.Col("Level")).From("users")
	//
	//   // With aliasing:
	//   u := cols.As("u")
	//   qb.Select(u.Col("ID"), u.Col("Level")).From(Table("users").As("u"))
	//
	// Panics if structPtr is not a pointer to a struct with db tags.
	Columns(structPtr any) Columns

	// Query builders
	Select(columns ...any) SelectQueryBuilder
	Insert(table string) squirrel.InsertBuilder
	InsertWithColumns(table string, columns ...string) squirrel.InsertBuilder

	// Struct-based INSERT (v2.4+)
	// InsertStruct extracts all fields from a struct instance and creates an INSERT query.
	// Zero-value ID fields (int64/string) are automatically excluded to support auto-increment.
	InsertStruct(table string, instance any) squirrel.InsertBuilder

	// InsertFields extracts only specified fields from a struct instance for INSERT.
	// Useful for partial inserts or when you need explicit control over included fields.
	InsertFields(table string, instance any, fields ...string) squirrel.InsertBuilder

	Update(table string) UpdateQueryBuilder
	Delete(table string) DeleteQueryBuilder

	// Vendor-specific helpers
	BuildCaseInsensitiveLike(column, value string) squirrel.Sqlizer
	BuildUpsert(table string, conflictColumns []string, insertColumns, updateColumns map[string]any) (query string, args []any, err error)

	// Database function builders
	BuildCurrentTimestamp() string
	BuildUUIDGeneration() string
	BuildBooleanValue(value bool) any

	// Identifier escaping
	EscapeIdentifier(identifier string) string
}

QueryBuilderInterface defines the interface for vendor-specific SQL query building. This interface allows for dependency injection and mocking of query builders, enabling unit testing of business logic that constructs queries without actually generating SQL strings.

type RawExpression added in v0.14.2

type RawExpression struct {
	SQL   string // The raw SQL expression
	Alias string // Optional alias (AS clause)
}

RawExpression represents a raw SQL expression that can be used in SELECT, GROUP BY, and ORDER BY clauses. It allows using SQL functions, aggregations, calculations, and other expressions that go beyond simple column names.

SECURITY WARNING: Raw SQL expressions are NOT escaped or sanitized by the framework. Never interpolate user input directly into expressions - this creates SQL injection vulnerabilities. Only use static SQL or carefully validated values in expressions.

Safe usage:

qb.Select(qb.Expr("COUNT(*)", "total"))           // Aggregation with alias
qb.Select(qb.Expr("UPPER(name)"))                  // Function without alias
qb.Select(qb.Expr("price * quantity", "total"))    // Calculation with alias

Unsafe usage (NEVER do this):

userInput := req.Query("column")
qb.Select(qb.Expr(fmt.Sprintf("UPPER(%s)", userInput))) // SQL INJECTION RISK!

func Expr added in v0.14.2

func Expr(sql string, alias ...string) (RawExpression, error)

Expr creates a raw SQL expression with optional alias for use in SELECT, GROUP BY, and ORDER BY clauses.

Parameters:

  • sql: The raw SQL expression (e.g., "COUNT(*)", "UPPER(name)", "price * quantity")
  • alias: Optional alias for the expression (e.g., "total", "upper_name"). Max 1 alias allowed.

Returns:

  • RawExpression: The constructed expression
  • error: ErrEmptyExpressionSQL, ErrTooManyAliases, or ErrDangerousAlias on validation failure

Examples:

// Aggregation with alias
expr, err := qb.Expr("COUNT(*)", "total")
if err != nil { return err }

// Function without alias
expr, err := qb.Expr("UPPER(name)")

// Calculation with alias
expr, err := qb.Expr("price * quantity", "line_total")

SECURITY WARNING: Never interpolate user input directly into the sql parameter. This function does NOT sanitize SQL - you are responsible for ensuring safety.

func MustExpr added in v0.19.0

func MustExpr(sql string, alias ...string) RawExpression

MustExpr is like Expr but panics on error. Use this only in static initialization or tests where errors indicate programming bugs.

type Row added in v0.9.0

type Row interface {
	Scan(dest ...any) error
	Err() error
}

Row represents a single result set row with basic scanning behaviour.

func NewRowFromSQL added in v0.9.0

func NewRowFromSQL(row *sql.Row) Row

NewRowFromSQL wraps the provided *sql.Row in a Row. If row is nil, NewRowFromSQL returns nil.

type SelectQueryBuilder added in v0.11.0

type SelectQueryBuilder interface {
	// Core SELECT builder methods
	// From accepts either string table names or *TableRef instances with optional aliases
	From(from ...any) SelectQueryBuilder

	// Type-safe JOIN methods with JoinFilter (v2.0+)
	// Each accepts either string table name or *TableRef instance with optional alias
	JoinOn(table any, filter JoinFilter) SelectQueryBuilder
	LeftJoinOn(table any, filter JoinFilter) SelectQueryBuilder
	RightJoinOn(table any, filter JoinFilter) SelectQueryBuilder
	InnerJoinOn(table any, filter JoinFilter) SelectQueryBuilder
	CrossJoinOn(table any) SelectQueryBuilder

	GroupBy(groupBys ...any) SelectQueryBuilder
	Having(pred any, rest ...any) SelectQueryBuilder
	OrderBy(orderBys ...any) SelectQueryBuilder
	Limit(limit uint64) SelectQueryBuilder
	Offset(offset uint64) SelectQueryBuilder
	Paginate(limit, offset uint64) SelectQueryBuilder

	// Composable WHERE clause
	Where(filter Filter) SelectQueryBuilder

	// SQL generation
	ToSQL() (sql string, args []any, err error)
}

SelectQueryBuilder defines the interface for enhanced SELECT query building with type safety. This interface extends basic squirrel.SelectBuilder functionality with additional methods for composable filters, JOIN operations, and vendor-specific query features.

type Statement

type Statement interface {
	// Query execution
	Query(ctx context.Context, args ...any) (*sql.Rows, error)
	QueryRow(ctx context.Context, args ...any) Row
	Exec(ctx context.Context, args ...any) (sql.Result, error)

	// Statement management
	Close() error
}

Statement defines the interface for prepared statements

type TableRef added in v0.14.2

type TableRef struct {
	// contains filtered or unexported fields
}

TableRef represents a table reference with optional alias for SQL queries. Use the Table() function to create instances.

Example:

table, _ := Table("customers")
aliased, _ := table.As("c")

func MustTable added in v0.19.0

func MustTable(name string) *TableRef

MustTable is like Table but panics on error. Use this only in static initialization or tests where errors indicate programming bugs.

func Table added in v0.14.2

func Table(name string) (*TableRef, error)

Table creates a new table reference. Returns ErrEmptyTableName if name is empty. Call As() to add an alias, or use directly for tables without aliases.

Example:

table, err := Table("users")
if err != nil { return err }
aliased, err := table.As("u")

func (*TableRef) Alias added in v0.14.2

func (t *TableRef) Alias() string

Alias returns the table alias, or empty string if no alias.

func (*TableRef) As added in v0.14.2

func (t *TableRef) As(alias string) (*TableRef, error)

As creates a new TableRef with the given alias. Returns ErrEmptyTableAlias if alias is empty. Returns a new TableRef instance (immutable pattern).

Example:

table, _ := Table("customers")
aliased, err := table.As("c")

func (*TableRef) HasAlias added in v0.14.2

func (t *TableRef) HasAlias() bool

HasAlias returns true if this table has an alias.

func (*TableRef) MustAs added in v0.19.0

func (t *TableRef) MustAs(alias string) *TableRef

MustAs is like As but panics on error. Use this only in static initialization or tests where errors indicate programming bugs.

func (*TableRef) Name added in v0.14.2

func (t *TableRef) Name() string

Name returns the table name (unquoted).

type Transactor added in v0.16.0

type Transactor interface {
	// Begin starts a new transaction with default isolation level.
	// The returned Tx must be committed or rolled back to release resources.
	//
	// Common usage pattern:
	//   tx, err := db.Begin(ctx)
	//   if err != nil { return err }
	//   defer tx.Rollback(ctx)  // No-op if already committed
	//   // ... execute operations on tx ...
	//   return tx.Commit(ctx)
	Begin(ctx context.Context) (Tx, error)

	// BeginTx starts a new transaction with explicit isolation level and read-only settings.
	// Use this when you need precise control over transaction behavior.
	//
	// Common isolation levels (from database/sql):
	//   - sql.LevelDefault: Use database's default isolation
	//   - sql.LevelReadUncommitted: Lowest isolation, allows dirty reads
	//   - sql.LevelReadCommitted: Prevents dirty reads (PostgreSQL default)
	//   - sql.LevelRepeatableRead: Prevents dirty and non-repeatable reads
	//   - sql.LevelSerializable: Highest isolation, full transaction isolation
	//
	// Example (read-only transaction for complex reporting):
	//   tx, err := db.BeginTx(ctx, &sql.TxOptions{
	//       Isolation: sql.LevelRepeatableRead,
	//       ReadOnly:  true,
	//   })
	//
	// Note: Not all databases support all isolation levels. Consult vendor documentation.
	BeginTx(ctx context.Context, opts *sql.TxOptions) (Tx, error)
}

Transactor defines transaction management operations. This interface follows the Single Responsibility Principle by focusing solely on transaction lifecycle, separate from query execution, health checks, and migration support.

Transactor is typically used by business logic that needs to execute multiple operations atomically (all succeed or all fail). For query-only operations, use the Querier interface.

The database.Interface type embeds Transactor, so all existing code continues to work unchanged.

Usage in services:

func (s *OrderService) CreateWithPayment(ctx context.Context, order Order, payment Payment) error {
    db, err := s.deps.GetDB(ctx)
    if err != nil {
        return err
    }

    tx, err := db.Begin(ctx)
    if err != nil {
        return err
    }
    defer tx.Rollback(ctx)  // No-op if already committed

    if err := s.insertOrder(ctx, tx, order); err != nil {
        return err
    }
    if err := s.insertPayment(ctx, tx, payment); err != nil {
        return err
    }

    return tx.Commit(ctx)
}

For testing transaction logic, see the database/testing package which provides TestTx for tracking commit/rollback behavior and query execution within transactions.

type Tx

type Tx interface {
	// Query execution within transaction
	Query(ctx context.Context, query string, args ...any) (*sql.Rows, error)
	QueryRow(ctx context.Context, query string, args ...any) Row
	Exec(ctx context.Context, query string, args ...any) (sql.Result, error)

	// Prepared statements within transaction
	Prepare(ctx context.Context, query string) (Statement, error)

	// Transaction control
	// Note: Context is passed to support proper cancellation and tracing.
	// The context should be the same one used to begin the transaction.
	Commit(ctx context.Context) error
	Rollback(ctx context.Context) error
}

Tx defines the interface for database transactions

type UpdateQueryBuilder added in v0.13.0

type UpdateQueryBuilder interface {
	// Data modification
	Set(column string, value any) UpdateQueryBuilder
	SetMap(clauses map[string]any) UpdateQueryBuilder

	// Struct-based UPDATE (v2.4+)
	// SetStruct extracts field values from a struct instance for UPDATE.
	// If fields are specified, only those fields are updated.
	// If no fields specified, all struct fields are updated.
	SetStruct(instance any, fields ...string) UpdateQueryBuilder

	// Filtering
	Where(filter Filter) UpdateQueryBuilder

	// SQL generation
	ToSQL() (sql string, args []any, err error)
}

UpdateQueryBuilder defines the interface for UPDATE query building with type-safe filtering. This interface wraps squirrel.UpdateBuilder with Filter API support and vendor-specific quoting.

type Vendor added in v0.9.0

type Vendor = string

Database vendor identifiers shared across the database packages.

const (
	PostgreSQL Vendor = "postgresql"
	Oracle     Vendor = "oracle"
	MongoDB    Vendor = "mongodb"
)

Jump to

Keyboard shortcuts

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