Load Rows for Query
This commit is contained in:
parent
d7ac078e4c
commit
ee50dfa818
@ -3,7 +3,9 @@ package sqlite
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"github.com/jinzhu/gorm"
|
"github.com/jinzhu/gorm"
|
||||||
"github.com/jinzhu/gorm/dialects/common/sqlbuilder"
|
"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)
|
_, err = builder.SQL.WriteTo(s)
|
||||||
args = append(args, builder.Args)
|
args = append(args, builder.Args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rows, err := dialect.DB.Query(s.String(), args)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
err = scanRows(rows, tx.Statement.Dest)
|
||||||
|
}
|
||||||
|
|
||||||
return
|
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
|
// Update update
|
||||||
func (dialect *Dialect) Update(tx *gorm.DB) (err error) {
|
func (dialect *Dialect) Update(tx *gorm.DB) (err error) {
|
||||||
var (
|
var (
|
||||||
|
@ -16,6 +16,37 @@ import (
|
|||||||
// }
|
// }
|
||||||
var DefaultTableNameHandler func(tx *gorm.DB, tableName string) string
|
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
|
// Field GORM model field
|
||||||
type Field struct {
|
type Field struct {
|
||||||
*schema.Field
|
*schema.Field
|
||||||
|
@ -2,6 +2,7 @@ package model
|
|||||||
|
|
||||||
import "reflect"
|
import "reflect"
|
||||||
|
|
||||||
|
// IsBlank check value is blank or not
|
||||||
func IsBlank(value reflect.Value) bool {
|
func IsBlank(value reflect.Value) bool {
|
||||||
switch value.Kind() {
|
switch value.Kind() {
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user