sql

package
v1.25.13 Latest Latest
Warning

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

Go to latest
Published: Jan 28, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package sql provides a set of utilities for mapping database query results to Go data structures.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNilDestination is an error that is returned when the destination is nil.
	ErrNilDestination = errors.New("destination can not be nil")

	// ErrNilRows is an error that is returned when the rows is nil.
	ErrNilRows = errors.New("rows can not be nil")

	// ErrResultMapNotSet is an error that is returned when the result map is not set.
	ErrResultMapNotSet = errors.New("resultMap not set")

	// ErrPointerRequired is an error that is returned when the destination is not a pointer.
	ErrPointerRequired = errors.New("destination must be a pointer")
)
View Source
var (
	// ErrTooManyRows is returned when the result set has too many rows but excepted only one row.
	ErrTooManyRows = errors.New("juice: too many rows in result set")
)

Functions

func Bind

func Bind[T any](rows Rows) (result T, err error)

Bind Rows to given entity with default mapper Example usage of the binder package

Example_bind shows how to use the Bind function:

type User struct {
    ID   int    `column:"id"`
    Name string `column:"name"`
}

rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

user, err := Bind[[]User](rows)
if err != nil {
    log.Fatal(err)
}

func BindWithResultMap

func BindWithResultMap[T any](rows Rows, resultMap ResultMap) (result T, err error)

BindWithResultMap bind Rows to given entity with given ResultMap bind cover Rows to given entity dest can be a pointer to a struct, a pointer to a slice of struct, or a pointer to a slice of any type. rows won't be closed when the function returns.

func ColumnTagName

func ColumnTagName() string

func List

func List[T any](rows Rows) (result []T, err error)

List converts Rows to a slice of the given entity type. If there are no rows, it will return an empty slice.

Differences between List and Bind: - List always returns a slice, even if there is only one row. - Bind always returns the entity of the given type.

Bind is more flexible; you can use it to bind a single row to a struct, a slice of structs, or a slice of any type. However, if you are sure that the result will be a slice, you can use List. It could be faster than Bind.

Example_list shows how to use the List function:

type User struct {
    ID   int    `column:"id"`
    Name string `column:"name"`
}

rows, err := db.Query("SELECT id, name FROM users")
if err != nil {
    log.Fatal(err)
}
defer rows.Close()

users, err := List[User](rows)
if err != nil {
    log.Fatal(err)
}

func List2

func List2[T any](rows Rows) ([]*T, error)

List2 converts database query results into a slice of pointers. Unlike List function, List2 returns a slice of pointers []*T instead of a slice of values []T. This is particularly useful when you need to modify slice elements or handle large structs.

Types

type Action

type Action string

Action defines a sql Action.

const (
	// Select is an Action for query
	Select Action = "select"

	// Insert is an Action for insert
	Insert Action = "insert"

	// Update is an Action for update
	Update Action = "update"

	// Delete is an Action for delete
	Delete Action = "delete"
)

func (Action) ForRead

func (a Action) ForRead() bool

func (Action) ForWrite

func (a Action) ForWrite() bool

func (Action) String

func (a Action) String() string

type BatchResult

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

BatchResult is a custom implementation of sql.Result that aggregates results from multiple batch operations. It provides methods to accumulate results from individual batch executions and maintains cumulative statistics.

This implementation ensures that RowsAffected() returns the cumulative count of all affected rows across batches, while LastInsertId() returns the ID from the last successful insert operation.

func (*BatchResult) AccumulateResult

func (r *BatchResult) AccumulateResult(result sql.Result)

AccumulateResult processes a sql.Result from a batch operation and updates the internal statistics. It extracts RowsAffected and LastInsertId from the provided result and adds them to the cumulative totals.

Parameters:

  • result: The sql.Result from a single batch operation

This method safely handles errors from RowsAffected() and LastInsertId() calls, only updating values when they can be successfully retrieved.

func (*BatchResult) LastInsertId

func (r *BatchResult) LastInsertId() (int64, error)

LastInsertId returns the insert ID from the last successful batch operation. For batch insert operations, this represents the ID of the last inserted record, which is consistent with the behavior expected by middleware components.

func (*BatchResult) RowsAffected

func (r *BatchResult) RowsAffected() (int64, error)

RowsAffected returns the total number of rows affected across all batch operations. This provides an accurate count of the cumulative impact of the entire batch processing, rather than just the count from the final batch.

type ColumnDestination

type ColumnDestination interface {
	// Destination returns the destination for the given reflect value and column.
	Destination(rv reflect.Value, column []string) ([]any, error)
}

ColumnDestination is a column destination which can be used to scan a row.

type Iterator added in v1.25.9

type Iterator[T any] iter.Seq2[T, error]

Iterator is a type alias for iter.Seq2[T, error]. It represents an iterator that yields values of type T and may return an error.

This type is specifically designed for juicecli to use as a type annotation during code generation, allowing the tool to recognize and generate proper iterator-based query methods.

func Iter

func Iter[T any](rows Rows) (Iterator[T], error)

Iter creates an iterator from the given Rows. It scans each row into a new instance of type T and yields it. If an error occurs during scanning, it yields the error.

type MultiRowsResultMap

type MultiRowsResultMap struct {
	New func() reflect.Value
}

MultiRowsResultMap is a ResultMap that maps a rowDestination to a slice type.

func (MultiRowsResultMap) MapTo

func (m MultiRowsResultMap) MapTo(rv reflect.Value, rows Rows) error

MapTo implements ResultMapper interface. It maps the data from the SQL rows to the provided reflect.Value. The reflect.Value must be a pointer to a slice. Each row will be mapped to a new element in the slice.

type Result added in v1.25.8

type Result = sql.Result

Result is an alias for sql.Result to maintain compatibility

type ResultMap

type ResultMap interface {
	// MapTo maps the data from the SQL row to the provided reflect.Value.
	MapTo(rv reflect.Value, row Rows) error
}

ResultMap is an interface that defines a method for mapping database query results to Go data structures.

type RowScanner

type RowScanner interface {
	ScanRows(rows Rows) error
}

RowScanner is an interface that provides a custom mechanism for mapping database rows to Go structures. It serves as an extension point in the data binding system, allowing implementers to override the default reflection-based mapping behavior.

When a type implements this interface, the binding system will detect it during the mapping process and delegate the row scanning responsibility to the implementation. This gives complete control over how database values are mapped to the target structure.

Use cases: - Custom mapping logic for complex database schemas or legacy systems - Performance optimization by eliminating reflection overhead - Special data type handling (e.g., JSON, XML, custom database types) - Complex data transformations during the mapping process - Implementation of caching or lazy loading strategies

Example implementation:

func (u *User) ScanRows(rows *sql.Rows) error {
    return rows.Scan(&u.ID, &u.Name, &u.Email)
}

The implementation must ensure proper handling of NULL values and return appropriate errors if the scanning process fails.

type Rows

type Rows interface {
	// Next prepares the next result row for reading with the Scan method. It
	// returns true on success, or false if there is no next result row or an error
	// happened while preparing it. Err should be consulted to distinguish between
	// the two cases.
	//
	// Every call to Scan, even the first one, must be preceded by a call to Next.
	Next() bool

	// Scan copies the columns in the current row into the values pointed at by dest.
	// The number of values in dest must be the same as the number of columns
	// in Rows.
	//
	// Scan converts columns read from the database into the following common
	// Go types and nil if the column value is NULL:
	//
	//    *string
	//    *[]byte
	//    *int, *int8, *int16, *int32, *int64
	//    *uint, *uint8, *uint16, *uint32, *uint64
	//    *bool
	//    *float32, *float64
	//    *interface{}
	//    *time.Time
	//
	// If a dest argument has type *[]byte, Scan saves in that argument a copy
	// of the corresponding data. The copy is owned by the caller and can be
	// modified and held indefinitely. The copy can be avoided by using an argument
	// of type *sql.RawBytes instead; see the documentation for sql.RawBytes for
	// details.
	//
	// If an error occurs during conversion, Scan returns the error.
	Scan(dest ...any) error

	// Close closes the Rows, preventing further enumeration. If Next is called
	// and returns false and there are no further result sets, the Rows are closed
	// automatically and it will suffice to check the result of Err. Close is
	// idempotent and does not affect the result of Err.
	Close() error

	// Err returns the error, if any, that was encountered during iteration.
	// Err may be called after an explicit or implicit Close.
	Err() error

	// Columns returns the column names.
	// Columns returns an error if the rows are closed.
	Columns() ([]string, error)
}

Rows is the result of a query. Its cursor starts before the first row of the result set. Use Next to advance from row to row.

type RowsBuffer added in v1.25.8

type RowsBuffer struct {
	ColumnsLine []string
	Data        [][]any
	// contains filtered or unexported fields
}

RowsBuffer is a memory-based implementation of the Rows interface. It can be used to store query results in memory or for testing purposes.

func NewRowsBuffer added in v1.25.8

func NewRowsBuffer(columns []string, data [][]any) *RowsBuffer

NewRowsBuffer creates a new RowsBuffer with the given columns and data.

func (*RowsBuffer) Close added in v1.25.8

func (rb *RowsBuffer) Close() error

Close marks the RowsBuffer as closed, preventing further operations.

func (*RowsBuffer) Columns added in v1.25.8

func (rb *RowsBuffer) Columns() ([]string, error)

Columns returns the column names of the result set. It returns an error if the RowsBuffer is closed.

func (*RowsBuffer) Err added in v1.25.8

func (rb *RowsBuffer) Err() error

Err returns the error encountered during iteration, if any. In this implementation, it always returns nil as the data is pre-buffered.

func (*RowsBuffer) Next added in v1.25.8

func (rb *RowsBuffer) Next() bool

Next advances the cursor to the next row of the result set. It returns false if there are no more rows or if the RowsBuffer is closed.

func (*RowsBuffer) Scan added in v1.25.8

func (rb *RowsBuffer) Scan(dest ...any) error

Scan copies the columns in the current row into the values pointed at by dest. The number of values in dest must be the same as the number of columns in the row. It returns an error if the RowsBuffer is closed, if there are no rows at the current index, or if the number of destination arguments does not match the number of columns.

type SingleRowResultMap

type SingleRowResultMap struct{}

SingleRowResultMap is a ResultMap that maps a rowDestination to a non-slice type.

func (SingleRowResultMap) MapTo

func (SingleRowResultMap) MapTo(rv reflect.Value, rows Rows) error

MapTo implements ResultMapper interface. It maps the data from the SQL row to the provided reflect.Value. If more than one row is returned from the query, it returns an ErrTooManyRows error.

Jump to

Keyboard shortcuts

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