Files
stash/vendor/github.com/doug-martin/goqu/v9/exp/insert.go
WithoutPants 5495d72849 File storage rewrite (#2676)
* Restructure data layer part 2 (#2599)
* Refactor and separate image model
* Refactor image query builder
* Handle relationships in image query builder
* Remove relationship management methods
* Refactor gallery model/query builder
* Add scenes to gallery model
* Convert scene model
* Refactor scene models
* Remove unused methods
* Add unit tests for gallery
* Add image tests
* Add scene tests
* Convert unnecessary scene value pointers to values
* Convert unnecessary pointer values to values
* Refactor scene partial
* Add scene partial tests
* Refactor ImagePartial
* Add image partial tests
* Refactor gallery partial update
* Add partial gallery update tests
* Use zero/null package for null values
* Add files and scan system
* Add sqlite implementation for files/folders
* Add unit tests for files/folders
* Image refactors
* Update image data layer
* Refactor gallery model and creation
* Refactor scene model
* Refactor scenes
* Don't set title from filename
* Allow galleries to freely add/remove images
* Add multiple scene file support to graphql and UI
* Add multiple file support for images in graphql/UI
* Add multiple file for galleries in graphql/UI
* Remove use of some deprecated fields
* Remove scene path usage
* Remove gallery path usage
* Remove path from image
* Move funscript to video file
* Refactor caption detection
* Migrate existing data
* Add post commit/rollback hook system
* Lint. Comment out import/export tests
* Add WithDatabase read only wrapper
* Prepend tasks to list
* Add 32 pre-migration
* Add warnings in release and migration notes
2022-09-06 07:03:42 +00:00

164 lines
4.2 KiB
Go

package exp
import (
"reflect"
"sort"
"github.com/doug-martin/goqu/v9/internal/errors"
"github.com/doug-martin/goqu/v9/internal/util"
)
type (
insert struct {
from AppendableExpression
cols ColumnListExpression
vals [][]interface{}
}
)
func NewInsertExpression(rows ...interface{}) (insertExpression InsertExpression, err error) {
switch len(rows) {
case 0:
return new(insert), nil
case 1:
val := reflect.ValueOf(rows[0])
if val.Kind() == reflect.Slice {
vals := make([]interface{}, 0, val.Len())
for i := 0; i < val.Len(); i++ {
vals = append(vals, val.Index(i).Interface())
}
return NewInsertExpression(vals...)
}
if ae, ok := rows[0].(AppendableExpression); ok {
return &insert{from: ae}, nil
}
}
return newInsert(rows...)
}
func (i *insert) Expression() Expression {
return i
}
func (i *insert) Clone() Expression {
return i.clone()
}
func (i *insert) clone() *insert {
return &insert{from: i.from, cols: i.cols, vals: i.vals}
}
func (i *insert) IsEmpty() bool {
return i.from == nil && (i.cols == nil || i.cols.IsEmpty())
}
func (i *insert) IsInsertFrom() bool {
return i.from != nil
}
func (i *insert) From() AppendableExpression {
return i.from
}
func (i *insert) Cols() ColumnListExpression {
return i.cols
}
func (i *insert) SetCols(cols ColumnListExpression) InsertExpression {
ci := i.clone()
ci.cols = cols
return ci
}
func (i *insert) Vals() [][]interface{} {
return i.vals
}
func (i *insert) SetVals(vals [][]interface{}) InsertExpression {
ci := i.clone()
ci.vals = vals
return ci
}
// parses the rows gathering and sorting unique columns and values for each record
func newInsert(rows ...interface{}) (insertExp InsertExpression, err error) {
var mapKeys util.ValueSlice
rowValue := reflect.Indirect(reflect.ValueOf(rows[0]))
rowType := rowValue.Type()
rowKind := rowValue.Kind()
if rowKind == reflect.Struct {
return createStructSliceInsert(rows...)
}
vals := make([][]interface{}, 0, len(rows))
var columns ColumnListExpression
for _, row := range rows {
if rowType != reflect.Indirect(reflect.ValueOf(row)).Type() {
return nil, errors.New(
"rows must be all the same type expected %+v got %+v",
rowType,
reflect.Indirect(reflect.ValueOf(row)).Type(),
)
}
newRowValue := reflect.Indirect(reflect.ValueOf(row))
switch rowKind {
case reflect.Map:
if columns == nil {
mapKeys = util.ValueSlice(newRowValue.MapKeys())
sort.Sort(mapKeys)
colKeys := make([]interface{}, 0, len(mapKeys))
for _, key := range mapKeys {
colKeys = append(colKeys, key.Interface())
}
columns = NewColumnListExpression(colKeys...)
}
newMapKeys := util.ValueSlice(newRowValue.MapKeys())
if len(newMapKeys) != len(mapKeys) {
return nil, errors.New("rows with different value length expected %d got %d", len(mapKeys), len(newMapKeys))
}
if !mapKeys.Equal(newMapKeys) {
return nil, errors.New("rows with different keys expected %s got %s", mapKeys.String(), newMapKeys.String())
}
rowVals := make([]interface{}, 0, len(mapKeys))
for _, key := range mapKeys {
rowVals = append(rowVals, newRowValue.MapIndex(key).Interface())
}
vals = append(vals, rowVals)
default:
return nil, errors.New(
"unsupported insert must be map, goqu.Record, or struct type got: %T",
row,
)
}
}
return &insert{cols: columns, vals: vals}, nil
}
func createStructSliceInsert(rows ...interface{}) (insertExp InsertExpression, err error) {
rowValue := reflect.Indirect(reflect.ValueOf(rows[0]))
rowType := rowValue.Type()
recordRows := make([]interface{}, 0, len(rows))
for _, row := range rows {
if rowType != reflect.Indirect(reflect.ValueOf(row)).Type() {
return nil, errors.New(
"rows must be all the same type expected %+v got %+v",
rowType,
reflect.Indirect(reflect.ValueOf(row)).Type(),
)
}
newRowValue := reflect.Indirect(reflect.ValueOf(row))
record, err := getFieldsValuesFromStruct(newRowValue)
if err != nil {
return nil, err
}
recordRows = append(recordRows, record)
}
return newInsert(recordRows...)
}
func getFieldsValuesFromStruct(value reflect.Value) (row Record, err error) {
if value.IsValid() {
return NewRecordFromStruct(value.Interface(), true, false)
}
return
}