gtsocial-umbx

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

query_values.go (4364B)


      1 package bun
      2 
      3 import (
      4 	"fmt"
      5 	"reflect"
      6 	"strconv"
      7 
      8 	"github.com/uptrace/bun/dialect/feature"
      9 	"github.com/uptrace/bun/schema"
     10 )
     11 
     12 type ValuesQuery struct {
     13 	baseQuery
     14 	customValueQuery
     15 
     16 	withOrder bool
     17 }
     18 
     19 var (
     20 	_ Query                   = (*ValuesQuery)(nil)
     21 	_ schema.NamedArgAppender = (*ValuesQuery)(nil)
     22 )
     23 
     24 func NewValuesQuery(db *DB, model interface{}) *ValuesQuery {
     25 	q := &ValuesQuery{
     26 		baseQuery: baseQuery{
     27 			db:   db,
     28 			conn: db.DB,
     29 		},
     30 	}
     31 	q.setModel(model)
     32 	return q
     33 }
     34 
     35 func (q *ValuesQuery) Conn(db IConn) *ValuesQuery {
     36 	q.setConn(db)
     37 	return q
     38 }
     39 
     40 func (q *ValuesQuery) Err(err error) *ValuesQuery {
     41 	q.setErr(err)
     42 	return q
     43 }
     44 
     45 func (q *ValuesQuery) Column(columns ...string) *ValuesQuery {
     46 	for _, column := range columns {
     47 		q.addColumn(schema.UnsafeIdent(column))
     48 	}
     49 	return q
     50 }
     51 
     52 // Value overwrites model value for the column.
     53 func (q *ValuesQuery) Value(column string, expr string, args ...interface{}) *ValuesQuery {
     54 	if q.table == nil {
     55 		q.err = errNilModel
     56 		return q
     57 	}
     58 	q.addValue(q.table, column, expr, args)
     59 	return q
     60 }
     61 
     62 func (q *ValuesQuery) WithOrder() *ValuesQuery {
     63 	q.withOrder = true
     64 	return q
     65 }
     66 
     67 func (q *ValuesQuery) AppendNamedArg(fmter schema.Formatter, b []byte, name string) ([]byte, bool) {
     68 	switch name {
     69 	case "Columns":
     70 		bb, err := q.AppendColumns(fmter, b)
     71 		if err != nil {
     72 			q.setErr(err)
     73 			return b, true
     74 		}
     75 		return bb, true
     76 	}
     77 	return b, false
     78 }
     79 
     80 // AppendColumns appends the table columns. It is used by CTE.
     81 func (q *ValuesQuery) AppendColumns(fmter schema.Formatter, b []byte) (_ []byte, err error) {
     82 	if q.err != nil {
     83 		return nil, q.err
     84 	}
     85 	if q.model == nil {
     86 		return nil, errNilModel
     87 	}
     88 
     89 	if q.tableModel != nil {
     90 		fields, err := q.getFields()
     91 		if err != nil {
     92 			return nil, err
     93 		}
     94 
     95 		b = appendColumns(b, "", fields)
     96 
     97 		if q.withOrder {
     98 			b = append(b, ", _order"...)
     99 		}
    100 
    101 		return b, nil
    102 	}
    103 
    104 	switch model := q.model.(type) {
    105 	case *mapSliceModel:
    106 		return model.appendColumns(fmter, b)
    107 	}
    108 
    109 	return nil, fmt.Errorf("bun: Values does not support %T", q.model)
    110 }
    111 
    112 func (q *ValuesQuery) Operation() string {
    113 	return "VALUES"
    114 }
    115 
    116 func (q *ValuesQuery) AppendQuery(fmter schema.Formatter, b []byte) (_ []byte, err error) {
    117 	if q.err != nil {
    118 		return nil, q.err
    119 	}
    120 	if q.model == nil {
    121 		return nil, errNilModel
    122 	}
    123 
    124 	fmter = formatterWithModel(fmter, q)
    125 
    126 	if q.tableModel != nil {
    127 		fields, err := q.getFields()
    128 		if err != nil {
    129 			return nil, err
    130 		}
    131 		return q.appendQuery(fmter, b, fields)
    132 	}
    133 
    134 	switch model := q.model.(type) {
    135 	case *mapSliceModel:
    136 		return model.appendValues(fmter, b)
    137 	}
    138 
    139 	return nil, fmt.Errorf("bun: Values does not support %T", q.model)
    140 }
    141 
    142 func (q *ValuesQuery) appendQuery(
    143 	fmter schema.Formatter,
    144 	b []byte,
    145 	fields []*schema.Field,
    146 ) (_ []byte, err error) {
    147 	b = append(b, "VALUES "...)
    148 	if q.db.features.Has(feature.ValuesRow) {
    149 		b = append(b, "ROW("...)
    150 	} else {
    151 		b = append(b, '(')
    152 	}
    153 
    154 	switch model := q.tableModel.(type) {
    155 	case *structTableModel:
    156 		b, err = q.appendValues(fmter, b, fields, model.strct)
    157 		if err != nil {
    158 			return nil, err
    159 		}
    160 
    161 		if q.withOrder {
    162 			b = append(b, ", "...)
    163 			b = strconv.AppendInt(b, 0, 10)
    164 		}
    165 	case *sliceTableModel:
    166 		slice := model.slice
    167 		sliceLen := slice.Len()
    168 		for i := 0; i < sliceLen; i++ {
    169 			if i > 0 {
    170 				b = append(b, "), "...)
    171 				if q.db.features.Has(feature.ValuesRow) {
    172 					b = append(b, "ROW("...)
    173 				} else {
    174 					b = append(b, '(')
    175 				}
    176 			}
    177 
    178 			b, err = q.appendValues(fmter, b, fields, slice.Index(i))
    179 			if err != nil {
    180 				return nil, err
    181 			}
    182 
    183 			if q.withOrder {
    184 				b = append(b, ", "...)
    185 				b = strconv.AppendInt(b, int64(i), 10)
    186 			}
    187 		}
    188 	default:
    189 		return nil, fmt.Errorf("bun: Values does not support %T", q.model)
    190 	}
    191 
    192 	b = append(b, ')')
    193 
    194 	return b, nil
    195 }
    196 
    197 func (q *ValuesQuery) appendValues(
    198 	fmter schema.Formatter, b []byte, fields []*schema.Field, strct reflect.Value,
    199 ) (_ []byte, err error) {
    200 	isTemplate := fmter.IsNop()
    201 	for i, f := range fields {
    202 		if i > 0 {
    203 			b = append(b, ", "...)
    204 		}
    205 
    206 		app, ok := q.modelValues[f.Name]
    207 		if ok {
    208 			b, err = app.AppendQuery(fmter, b)
    209 			if err != nil {
    210 				return nil, err
    211 			}
    212 			continue
    213 		}
    214 
    215 		if isTemplate {
    216 			b = append(b, '?')
    217 		} else {
    218 			b = f.AppendValue(fmter, b, indirect(strct))
    219 		}
    220 
    221 		if fmter.HasFeature(feature.DoubleColonCast) {
    222 			b = append(b, "::"...)
    223 			b = append(b, f.UserSQLType...)
    224 		}
    225 	}
    226 	return b, nil
    227 }