gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

model.go (4389B)


      1 package bun
      2 
      3 import (
      4 	"context"
      5 	"database/sql"
      6 	"errors"
      7 	"fmt"
      8 	"reflect"
      9 	"time"
     10 
     11 	"github.com/uptrace/bun/schema"
     12 )
     13 
     14 var errNilModel = errors.New("bun: Model(nil)")
     15 
     16 var (
     17 	timeType  = reflect.TypeOf((*time.Time)(nil)).Elem()
     18 	bytesType = reflect.TypeOf((*[]byte)(nil)).Elem()
     19 )
     20 
     21 type Model = schema.Model
     22 
     23 type rowScanner interface {
     24 	ScanRow(ctx context.Context, rows *sql.Rows) error
     25 }
     26 
     27 type TableModel interface {
     28 	Model
     29 
     30 	schema.BeforeAppendModelHook
     31 	schema.BeforeScanRowHook
     32 	schema.AfterScanRowHook
     33 	ScanColumn(column string, src interface{}) error
     34 
     35 	Table() *schema.Table
     36 	Relation() *schema.Relation
     37 
     38 	join(string) *relationJoin
     39 	getJoin(string) *relationJoin
     40 	getJoins() []relationJoin
     41 	addJoin(relationJoin) *relationJoin
     42 
     43 	rootValue() reflect.Value
     44 	parentIndex() []int
     45 	mount(reflect.Value)
     46 
     47 	updateSoftDeleteField(time.Time) error
     48 }
     49 
     50 func newModel(db *DB, dest []interface{}) (Model, error) {
     51 	if len(dest) == 1 {
     52 		return _newModel(db, dest[0], true)
     53 	}
     54 
     55 	values := make([]reflect.Value, len(dest))
     56 
     57 	for i, el := range dest {
     58 		v := reflect.ValueOf(el)
     59 		if v.Kind() != reflect.Ptr {
     60 			return nil, fmt.Errorf("bun: Scan(non-pointer %T)", dest)
     61 		}
     62 
     63 		v = v.Elem()
     64 		if v.Kind() != reflect.Slice {
     65 			return newScanModel(db, dest), nil
     66 		}
     67 
     68 		values[i] = v
     69 	}
     70 
     71 	return newSliceModel(db, dest, values), nil
     72 }
     73 
     74 func newSingleModel(db *DB, dest interface{}) (Model, error) {
     75 	return _newModel(db, dest, false)
     76 }
     77 
     78 func _newModel(db *DB, dest interface{}, scan bool) (Model, error) {
     79 	switch dest := dest.(type) {
     80 	case nil:
     81 		return nil, errNilModel
     82 	case Model:
     83 		return dest, nil
     84 	case sql.Scanner:
     85 		if !scan {
     86 			return nil, fmt.Errorf("bun: Model(unsupported %T)", dest)
     87 		}
     88 		return newScanModel(db, []interface{}{dest}), nil
     89 	}
     90 
     91 	v := reflect.ValueOf(dest)
     92 	if !v.IsValid() {
     93 		return nil, errNilModel
     94 	}
     95 	if v.Kind() != reflect.Ptr {
     96 		return nil, fmt.Errorf("bun: Model(non-pointer %T)", dest)
     97 	}
     98 
     99 	if v.IsNil() {
    100 		typ := v.Type().Elem()
    101 		if typ.Kind() == reflect.Struct {
    102 			return newStructTableModel(db, dest, db.Table(typ)), nil
    103 		}
    104 		return nil, fmt.Errorf("bun: Model(nil %s %T)", typ.Kind(), dest)
    105 	}
    106 
    107 	v = v.Elem()
    108 	typ := v.Type()
    109 
    110 	switch typ {
    111 	case timeType, bytesType:
    112 		return newScanModel(db, []interface{}{dest}), nil
    113 	}
    114 
    115 	switch v.Kind() {
    116 	case reflect.Map:
    117 		if err := validMap(typ); err != nil {
    118 			return nil, err
    119 		}
    120 		mapPtr := v.Addr().Interface().(*map[string]interface{})
    121 		return newMapModel(db, mapPtr), nil
    122 	case reflect.Struct:
    123 		return newStructTableModelValue(db, dest, v), nil
    124 	case reflect.Slice:
    125 		switch elemType := sliceElemType(v); elemType.Kind() {
    126 		case reflect.Struct:
    127 			if elemType != timeType {
    128 				return newSliceTableModel(db, dest, v, elemType), nil
    129 			}
    130 		case reflect.Map:
    131 			if err := validMap(elemType); err != nil {
    132 				return nil, err
    133 			}
    134 			slicePtr := v.Addr().Interface().(*[]map[string]interface{})
    135 			return newMapSliceModel(db, slicePtr), nil
    136 		}
    137 		return newSliceModel(db, []interface{}{dest}, []reflect.Value{v}), nil
    138 	}
    139 
    140 	if scan {
    141 		return newScanModel(db, []interface{}{dest}), nil
    142 	}
    143 
    144 	return nil, fmt.Errorf("bun: Model(unsupported %T)", dest)
    145 }
    146 
    147 func newTableModelIndex(
    148 	db *DB,
    149 	table *schema.Table,
    150 	root reflect.Value,
    151 	index []int,
    152 	rel *schema.Relation,
    153 ) (TableModel, error) {
    154 	typ := typeByIndex(table.Type, index)
    155 
    156 	if typ.Kind() == reflect.Struct {
    157 		return &structTableModel{
    158 			db:    db,
    159 			table: table.Dialect().Tables().Get(typ),
    160 			rel:   rel,
    161 
    162 			root:  root,
    163 			index: index,
    164 		}, nil
    165 	}
    166 
    167 	if typ.Kind() == reflect.Slice {
    168 		structType := indirectType(typ.Elem())
    169 		if structType.Kind() == reflect.Struct {
    170 			m := sliceTableModel{
    171 				structTableModel: structTableModel{
    172 					db:    db,
    173 					table: table.Dialect().Tables().Get(structType),
    174 					rel:   rel,
    175 
    176 					root:  root,
    177 					index: index,
    178 				},
    179 			}
    180 			m.init(typ)
    181 			return &m, nil
    182 		}
    183 	}
    184 
    185 	return nil, fmt.Errorf("bun: NewModel(%s)", typ)
    186 }
    187 
    188 func validMap(typ reflect.Type) error {
    189 	if typ.Key().Kind() != reflect.String || typ.Elem().Kind() != reflect.Interface {
    190 		return fmt.Errorf("bun: Model(unsupported %s) (expected *map[string]interface{})",
    191 			typ)
    192 	}
    193 	return nil
    194 }
    195 
    196 //------------------------------------------------------------------------------
    197 
    198 func isSingleRowModel(m Model) bool {
    199 	switch m.(type) {
    200 	case *mapModel,
    201 		*structTableModel,
    202 		*scanModel:
    203 		return true
    204 	default:
    205 		return false
    206 	}
    207 }