Documentation
¶
Overview ¶
Package sql provides a set of utilities for mapping database query results to Go data structures.
Index ¶
- Variables
- func Bind[T any](rows Rows) (result T, err error)
- func BindWithResultMap[T any](rows Rows, resultMap ResultMap) (result T, err error)
- func ColumnTagName() string
- func List[T any](rows Rows) (result []T, err error)
- func List2[T any](rows Rows) ([]*T, error)
- type Action
- type BatchResult
- type ColumnDestination
- type Iterator
- type MultiRowsResultMap
- type Result
- type ResultMap
- type RowScanner
- type Rows
- type RowsBuffer
- type SingleRowResultMap
Constants ¶
This section is empty.
Variables ¶
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") )
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 ¶
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 ¶
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 ¶
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)
}
Types ¶
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
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.
type MultiRowsResultMap ¶
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 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 ¶
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.