Load Rows for Query
This commit is contained in:
parent
d7ac078e4c
commit
ee50dfa818
@ -3,7 +3,9 @@ package sqlite
|
||||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/jinzhu/gorm/dialects/common/sqlbuilder"
|
||||
@ -157,9 +159,90 @@ func (dialect *Dialect) Query(tx *gorm.DB) (err error) {
|
||||
_, err = builder.SQL.WriteTo(s)
|
||||
args = append(args, builder.Args)
|
||||
}
|
||||
|
||||
rows, err := dialect.DB.Query(s.String(), args)
|
||||
|
||||
if err == nil {
|
||||
err = scanRows(rows, tx.Statement.Dest)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func scanRows(rows *sql.Rows, values interface{}) (err error) {
|
||||
var (
|
||||
isSlice bool
|
||||
results = indirect(reflect.ValueOf(values))
|
||||
)
|
||||
columns, err := rows.Columns()
|
||||
|
||||
if kind := results.Kind(); kind == reflect.Slice {
|
||||
isSlice = true
|
||||
resultType := results.Type().Elem()
|
||||
results.Set(reflect.MakeSlice(resultType, 0, 0))
|
||||
} else if kind != reflect.Struct || kind != reflect.Map {
|
||||
return errors.New("unsupported destination, should be slice or map or struct")
|
||||
}
|
||||
|
||||
for rows.Next() {
|
||||
elem := results
|
||||
if isSlice {
|
||||
elem = reflect.New(results.Type().Elem()).Elem()
|
||||
}
|
||||
|
||||
dests, err := toScanMap(columns, elem)
|
||||
|
||||
if err == nil {
|
||||
err = rows.Scan(dests...)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if isSlice {
|
||||
results.Set(reflect.Append(results, elem))
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func toScanMap(columns []string, elem reflect.Value) (results []interface{}, err error) {
|
||||
results = make([]interface{}, len(columns))
|
||||
|
||||
switch elem.Kind() {
|
||||
case reflect.Map:
|
||||
for idx, column := range columns {
|
||||
var value interface{}
|
||||
elem.SetMapIndex(reflect.ValueOf(column), reflect.ValueOf(value))
|
||||
results[idx] = &value
|
||||
}
|
||||
case reflect.Struct:
|
||||
fieldsMap := model.Parse(elem.Interface()).FieldsMap()
|
||||
for idx, column := range columns {
|
||||
if f, ok := fieldsMap[column]; ok {
|
||||
results[idx] = f.Value.Addr().Interface()
|
||||
}
|
||||
}
|
||||
case reflect.Ptr:
|
||||
if elem.IsNil() {
|
||||
elem.Set(reflect.New(elem.Type().Elem()))
|
||||
}
|
||||
return toScanMap(columns, elem)
|
||||
default:
|
||||
return nil, errors.New("unsupported destination")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func indirect(reflectValue reflect.Value) reflect.Value {
|
||||
for reflectValue.Kind() == reflect.Ptr {
|
||||
reflectValue = reflectValue.Elem()
|
||||
}
|
||||
return reflectValue
|
||||
}
|
||||
|
||||
// Update update
|
||||
func (dialect *Dialect) Update(tx *gorm.DB) (err error) {
|
||||
var (
|
||||
|
@ -16,6 +16,37 @@ import (
|
||||
// }
|
||||
var DefaultTableNameHandler func(tx *gorm.DB, tableName string) string
|
||||
|
||||
// Parse parse model
|
||||
func Parse(value interface{}) *Model {
|
||||
return &Model{
|
||||
ReflectValue: reflect.ValueOf(value),
|
||||
Schema: schema.Parse(value),
|
||||
}
|
||||
}
|
||||
|
||||
// Model model struct
|
||||
type Model struct {
|
||||
ReflectValue reflect.Value
|
||||
Schema *schema.Schema
|
||||
}
|
||||
|
||||
// FieldsMap fields map
|
||||
func (model *Model) FieldsMap() map[string]*Field {
|
||||
fieldsMap := map[string]*Field{}
|
||||
|
||||
for _, sf := range model.Schema.Fields {
|
||||
obj := model.ReflectValue
|
||||
for _, bn := range sf.BindNames {
|
||||
obj = obj.FieldByName(bn)
|
||||
}
|
||||
field := &Field{Field: sf, Value: obj}
|
||||
|
||||
fieldsMap[sf.DBName] = field
|
||||
}
|
||||
|
||||
return fieldsMap
|
||||
}
|
||||
|
||||
// Field GORM model field
|
||||
type Field struct {
|
||||
*schema.Field
|
||||
|
@ -2,6 +2,7 @@ package model
|
||||
|
||||
import "reflect"
|
||||
|
||||
// IsBlank check value is blank or not
|
||||
func IsBlank(value reflect.Value) bool {
|
||||
switch value.Kind() {
|
||||
case reflect.String:
|
||||
|
Loading…
x
Reference in New Issue
Block a user