代码拉取完成,页面将自动刷新
package sqlx
import (
"database/sql"
"errors"
"fmt"
"gitee.com/gopher2011/sqlx/reflectx"
"reflect"
)
// Row 是对 sql.Row 的重新实现,以便获得对 StructScan 必需的基础 sql.Rows.Columns() 数据的访问。
type Row struct {
rows *sql.Rows
err error
unsafe bool
Mapper *reflectx.Mapper
}
// ColumnTypes returns the underlying sql.Rows.ColumnTypes(), or the deferred error
func (r *Row) ColumnTypes() ([]*sql.ColumnType, error) {
if r.err != nil {
return []*sql.ColumnType{}, r.err
}
return r.rows.ColumnTypes()
}
// Columns 返回基础的sql.Rows.Columns(),或通常由Row.Scan() 返回的延迟错误
func (r *Row) Columns() ([]string, error) {
if r.err != nil {
return []string{}, r.err
}
return r.rows.Columns()
}
// Err returns the error encountered while scanning.
func (r *Row) Err() error {
return r.err
}
// scan (原Scan) 是sql.Row.Scan的固定实现,它不会从内部行对象中删除基础错误(如果存在)。
func (r *Row) scan(pointer ...interface{}) error {
if r.err != nil {
return r.err
}
defer r.rows.Close()
for _, dp := range pointer {
if _, ok := dp.(*sql.RawBytes); ok {
return errors.New("sql: RawBytes isn't allowed on Row.Scan")
}
}
if !r.rows.Next() {
if err := r.rows.Err(); err != nil {
return err
}
return sql.ErrNoRows
}
err := r.rows.Scan(pointer...)
if err != nil {
return err
}
// Make sure the query can be processed to completion with no errors.
if err1 := r.rows.Close(); err1 != nil {
return err
}
return nil
}
// scanAny 参数<pointer>只能是指针类型。
func (r *Row) scanAny(pointer interface{}, structOnly bool) error {
if r.err != nil {
return r.err
}
if r.rows == nil {
r.err = sql.ErrNoRows
return r.err
}
defer r.rows.Close()
v := reflect.ValueOf(pointer)
// 因为 sql.Row.Scan()只能接收指针类型的参数。所以这里必须限定 pointer 只能是指针类型。
if v.Kind() != reflect.Ptr {
return errors.New("must pass a pointer, not a value, to StructScan destination")
}
if v.IsNil() {
return errors.New("nil pointer passed to StructScan destination")
}
// 获取 pointer 的反射类型(即:包名+类名),例如: main.Student。
base := reflectx.Indirect(v.Type())
// 如果 pointer 是结构体并且实现了 Scan(src interface{})error接口,或者不是结构体。则ok为:true。
ok := isScan(base)
// 如果 pointer 是结构体并且实现了 Scan(src interface{})error接口,或者不是结构体,则直接返回错误。
if structOnly && ok {
return structOnlyError(base)
}
columns, err := r.Columns() // 获取表中所有的列名。而不是列的值。
if err != nil {
return err
}
// 输出 pointer 的Kind类型,例如: int,string,并且表中至少有2列。则返回错误。
if ok && len(columns) > 1 {
return fmt.Errorf("scannable dest type %s with >1 columns (%d) in result", base.Kind(), len(columns))
}
// 如果 pointer 是 int,string...类型,并且表中只有一列。
if ok {
return r.scan(pointer)
}
m := r.Mapper
// 获取表中列的索引。例如输出: [[0] [1] [2] [3] [4] [5]]。
colsIndex := m.TraversalsByName(v.Type(), columns)
if f, err1 := missingFields(colsIndex); err1 != nil && !r.unsafe {
return fmt.Errorf("缺少目的地名称 %s in %T", columns[f], pointer)
}
values := make([]interface{}, len(columns))
// 按顺序输出表中列的值的内存地址。
err = fieldsByTraversal(v, colsIndex, values, true)
if err != nil {
return err
}
// 扫描到结构体字段指针并将其附加到我们的结果中。
return r.scan(values...)
}
// Scan 将 Row 结果扫描进<pointer>中。<pointer>如果是结构体,则它只能是结构体的指针类型。
// 参数<pointer>如果为 nil,则底层直接调用 SliceScan(),将返回: []interface{},error。
// 参数<pointer>如果是 map[string]interface{}类型,则底层直接调用 MapScan(),将返回: nil,error。
// 参数<pointer>如果是 *struct,则底层直接调用 Row.scanAny(),将返回: nil,error。
func (r *Row)Scan(pointer interface{})([]interface{}, error){
if res,ok := pointer.(map[string]interface{});ok {
return nil,MapScan(r, res)
}
if pointer == nil {
return SliceScan(r)
}
kind := reflect.Indirect(reflect.ValueOf(pointer)).Kind()
if kind != reflect.Struct {
r.scan(pointer)
}
return nil,r.scanAny(pointer, true)
}
// Rows 是对 sql.Rows 的扩展
type Rows struct {
*sql.Rows
unsafe bool
Mapper *reflectx.Mapper
started bool // 这些字段在迭代过程中缓存行使用的内存w structScan
fields [][]int
values []interface{}
}
// ScanX (原StructScan) 类似于 sql.Rows.Scan,但是是将单个Row扫描到单个Struct中。
// 使用此方法,并在Select() 的内存负载可能过高的情况下,手动遍历Rows。
// Rows.StructScan缓存将列位置匹配到字段的反射工作,以避免每次扫描的开销。
// 这意味着在具有不同结构类型的同一Rows实例上运行StructScan是不安全的。
//
// 参数<pointer>如果为 nil,则底层直接调用 SliceScan(),将返回: []interface{},error。
// 参数<pointer>如果是 map[string]interface{}类型,则底层直接调用 MapScan(),将返回: nil,error。
// 参数<pointer>如果是结构体,则它只能是结构体的指针类型。
func (r *Rows) ScanX(pointer... interface{}) ([]interface{}, error) {
if len(pointer)>1 {
return nil,errors.New(" 只能有1个<pointer>参数,pointer个数不能超过一个!")
}
if len(pointer) == 0 {
return SliceScan(r)
}
if res,ok := pointer[0].(map[string]interface{});ok {
return nil,MapScan(r, res)
}
v := reflect.ValueOf(pointer[0])
if v.Kind() != reflect.Ptr {
return nil,errors.New("必须将一个指针而不是值传递给ScanX()的 <pointer>")
}
//kind := reflect.Indirect(reflect.ValueOf(pointer)).Kind()
//if kind != reflect.Struct {
// r.Scan(pointer)
//}
v = v.Elem()
if !r.started {
columns, err := r.Columns()
if err != nil {
return nil,err
}
m := r.Mapper
r.fields = m.TraversalsByName(v.Type(), columns)
// 如果我们不是不安全且缺少字段,则返回错误
if f, err1 := missingFields(r.fields); err1 != nil && !r.unsafe {
return nil,fmt.Errorf("missing destination name %s in %T", columns[f], pointer)
}
r.values = make([]interface{}, len(columns))
r.started = true
}
err := fieldsByTraversal(v, r.fields, r.values, true)
if err != nil {
return nil,err
}
// 扫描到struct字段指针并将其附加到我们的结果中。
err = r.Scan(r.values...)
if err != nil {
return nil,err
}
return nil,r.Err()
}
func (r *Rows)scan(pointer ...interface{}) error{
return nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。