Add support to retrieve Rows from statement
Rows statement method executes statements over db connection/transaction and returns Rows.
This commit is contained in:
parent
a5b7769589
commit
3021a6a0fd
7 changed files with 248 additions and 10 deletions
|
|
@ -5,7 +5,8 @@ import (
|
|||
"database/sql"
|
||||
)
|
||||
|
||||
// DB is common database interface used by jet execution
|
||||
// DB is common database interface used by query result mapping
|
||||
// Both *sql.DB and *sql.Tx implements DB interface
|
||||
type DB interface {
|
||||
Exec(query string, args ...interface{}) (sql.Result, error)
|
||||
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
|
||||
|
|
|
|||
50
qrm/qrm.go
50
qrm/qrm.go
|
|
@ -2,9 +2,12 @@ package qrm
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"github.com/go-jet/jet/v2/internal/utils"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/go-jet/jet/v2/internal/utils"
|
||||
)
|
||||
|
||||
// ErrNoRows is returned by Query when query result set is empty
|
||||
|
|
@ -56,6 +59,51 @@ func Query(ctx context.Context, db DB, query string, args []interface{}, destPtr
|
|||
}
|
||||
}
|
||||
|
||||
func ScanOneRowToDest(rows *sql.Rows, destPtr interface{}) error {
|
||||
utils.MustBeInitializedPtr(destPtr, "jet: destination is nil")
|
||||
utils.MustBe(destPtr, reflect.Ptr, "jet: destination has to be a pointer to slice or pointer to struct")
|
||||
|
||||
scanContext, err := newScanContext(rows)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create scan context, %w", err)
|
||||
}
|
||||
|
||||
if len(scanContext.row) == 0 {
|
||||
return errors.New("empty row slice")
|
||||
}
|
||||
|
||||
err = rows.Scan(scanContext.row...)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("rows scan error, %w", err)
|
||||
}
|
||||
|
||||
destinationPtrType := reflect.TypeOf(destPtr)
|
||||
tempSlicePtrValue := reflect.New(reflect.SliceOf(destinationPtrType))
|
||||
tempSliceValue := tempSlicePtrValue.Elem()
|
||||
|
||||
_, err = mapRowToSlice(scanContext, "", tempSlicePtrValue, nil)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to map a row, %w", err)
|
||||
}
|
||||
|
||||
// edge case when row result set contains only NULLs.
|
||||
if tempSliceValue.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
destValue := reflect.ValueOf(destPtr).Elem()
|
||||
firstTempSliceValue := tempSliceValue.Index(0).Elem()
|
||||
|
||||
if destValue.Type().AssignableTo(firstTempSliceValue.Type()) {
|
||||
destValue.Set(tempSliceValue.Index(0).Elem())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func queryToSlice(ctx context.Context, db DB, query string, args []interface{}, slicePtr interface{}) (rowsProcessed int64, err error) {
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue