gtsocial-umbx

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

model_map.go (3119B)


      1 package bun
      2 
      3 import (
      4 	"context"
      5 	"database/sql"
      6 	"reflect"
      7 	"sort"
      8 
      9 	"github.com/uptrace/bun/schema"
     10 )
     11 
     12 type mapModel struct {
     13 	db *DB
     14 
     15 	dest *map[string]interface{}
     16 	m    map[string]interface{}
     17 
     18 	rows         *sql.Rows
     19 	columns      []string
     20 	_columnTypes []*sql.ColumnType
     21 	scanIndex    int
     22 }
     23 
     24 var _ Model = (*mapModel)(nil)
     25 
     26 func newMapModel(db *DB, dest *map[string]interface{}) *mapModel {
     27 	m := &mapModel{
     28 		db:   db,
     29 		dest: dest,
     30 	}
     31 	if dest != nil {
     32 		m.m = *dest
     33 	}
     34 	return m
     35 }
     36 
     37 func (m *mapModel) Value() interface{} {
     38 	return m.dest
     39 }
     40 
     41 func (m *mapModel) ScanRows(ctx context.Context, rows *sql.Rows) (int, error) {
     42 	if !rows.Next() {
     43 		return 0, rows.Err()
     44 	}
     45 
     46 	columns, err := rows.Columns()
     47 	if err != nil {
     48 		return 0, err
     49 	}
     50 
     51 	m.rows = rows
     52 	m.columns = columns
     53 	dest := makeDest(m, len(columns))
     54 
     55 	if m.m == nil {
     56 		m.m = make(map[string]interface{}, len(m.columns))
     57 	}
     58 
     59 	m.scanIndex = 0
     60 	if err := rows.Scan(dest...); err != nil {
     61 		return 0, err
     62 	}
     63 
     64 	*m.dest = m.m
     65 
     66 	return 1, nil
     67 }
     68 
     69 func (m *mapModel) Scan(src interface{}) error {
     70 	if _, ok := src.([]byte); !ok {
     71 		return m.scanRaw(src)
     72 	}
     73 
     74 	columnTypes, err := m.columnTypes()
     75 	if err != nil {
     76 		return err
     77 	}
     78 
     79 	scanType := columnTypes[m.scanIndex].ScanType()
     80 	switch scanType.Kind() {
     81 	case reflect.Interface:
     82 		return m.scanRaw(src)
     83 	case reflect.Slice:
     84 		if scanType.Elem().Kind() == reflect.Uint8 {
     85 			return m.scanRaw(src)
     86 		}
     87 	}
     88 
     89 	dest := reflect.New(scanType).Elem()
     90 	if err := schema.Scanner(scanType)(dest, src); err != nil {
     91 		return err
     92 	}
     93 
     94 	return m.scanRaw(dest.Interface())
     95 }
     96 
     97 func (m *mapModel) columnTypes() ([]*sql.ColumnType, error) {
     98 	if m._columnTypes == nil {
     99 		columnTypes, err := m.rows.ColumnTypes()
    100 		if err != nil {
    101 			return nil, err
    102 		}
    103 		m._columnTypes = columnTypes
    104 	}
    105 	return m._columnTypes, nil
    106 }
    107 
    108 func (m *mapModel) scanRaw(src interface{}) error {
    109 	columnName := m.columns[m.scanIndex]
    110 	m.scanIndex++
    111 	m.m[columnName] = src
    112 	return nil
    113 }
    114 
    115 func (m *mapModel) appendColumnsValues(fmter schema.Formatter, b []byte) []byte {
    116 	keys := make([]string, 0, len(m.m))
    117 
    118 	for k := range m.m {
    119 		keys = append(keys, k)
    120 	}
    121 	sort.Strings(keys)
    122 
    123 	b = append(b, " ("...)
    124 
    125 	for i, k := range keys {
    126 		if i > 0 {
    127 			b = append(b, ", "...)
    128 		}
    129 		b = fmter.AppendIdent(b, k)
    130 	}
    131 
    132 	b = append(b, ") VALUES ("...)
    133 
    134 	isTemplate := fmter.IsNop()
    135 	for i, k := range keys {
    136 		if i > 0 {
    137 			b = append(b, ", "...)
    138 		}
    139 		if isTemplate {
    140 			b = append(b, '?')
    141 		} else {
    142 			b = schema.Append(fmter, b, m.m[k])
    143 		}
    144 	}
    145 
    146 	b = append(b, ")"...)
    147 
    148 	return b
    149 }
    150 
    151 func (m *mapModel) appendSet(fmter schema.Formatter, b []byte) []byte {
    152 	keys := make([]string, 0, len(m.m))
    153 
    154 	for k := range m.m {
    155 		keys = append(keys, k)
    156 	}
    157 	sort.Strings(keys)
    158 
    159 	isTemplate := fmter.IsNop()
    160 	for i, k := range keys {
    161 		if i > 0 {
    162 			b = append(b, ", "...)
    163 		}
    164 
    165 		b = fmter.AppendIdent(b, k)
    166 		b = append(b, " = "...)
    167 		if isTemplate {
    168 			b = append(b, '?')
    169 		} else {
    170 			b = schema.Append(fmter, b, m.m[k])
    171 		}
    172 	}
    173 
    174 	return b
    175 }
    176 
    177 func makeDest(v interface{}, n int) []interface{} {
    178 	dest := make([]interface{}, n)
    179 	for i := range dest {
    180 		dest[i] = v
    181 	}
    182 	return dest
    183 }