Select Git revision
-
Simao Gomes Viana authoredSimao Gomes Viana authored
query.go 2.48 KiB
package postgres
import (
"reflect"
"gitlab.com/xdevs23/goqlorm/database/dbdefs"
"github.com/joomcode/errorx"
"gitlab.com/xdevs23/goqlorm/reflectutil"
)
func (db Database) Select(collectionName string, args interface{}) (interface{}, error) {
if err := db.SelectInto(collectionName, args, args); err != nil {
return nil, err
}
return args, nil
}
func (db Database) SelectInto(collectionName string, args interface{}, model interface{}) error {
if err := db.tableModelQuery(collectionName, model, true).WherePK().Select(args); err != nil {
return errorx.EnsureStackTrace(err)
}
return nil
}
func (db Database) SelectAdvanced(collectionName string, model interface{}, query *dbdefs.SelectQuery) error {
actualModel := model
if query.IgnoreMultiple {
// Create a new slice first
actualModel = reflectutil.Wrap(reflectutil.NewSlice(model))
}
// This will give us a model that is made out of a modified struct
q, modifiedModel := tableModelQueryReturnModified(db.PgDB, collectionName, actualModel)
actualModel = modifiedModel
switch {
case query.Equals != nil:
q.Where(ToPgString(query.Where)+" = ?", query.Equals)
}
if err := q.Select(); err != nil {
return errorx.EnsureStackTrace(err)
}
modelVal := reflectutil.UnwrapValue(reflect.ValueOf(modifiedModel))
origType := reflectutil.PurifyType(reflect.TypeOf(model))
origNewSlice := reflectutil.NewSliceOfTypeWithSize(origType, modelVal.Len(), modelVal.Len())
origNewSliceVal := reflect.ValueOf(origNewSlice)
for i := 0; i < modelVal.Len(); i++ {
newVal := modelVal.Index(i)
// Create a new model that has the same type as the original one
origNewModel := reflectutil.NewFromType(origType)
// Now copy all the struct fields from the modified model to the original one
copyModel(
reflectutil.UnwrapType(newVal.Type()),
reflectutil.UnwrapValue(newVal),
origNewModel)
// And apply that to the slice
origNewSliceVal.Index(i).Set(reflect.ValueOf(origNewModel).Elem())
}
finalValue := origNewSliceVal
modelKind := reflectutil.UnwrapType(reflect.TypeOf(model)).Kind()
unwrappedValue := reflect.ValueOf(model).Elem()
if modelKind != reflect.Slice {
if query.IgnoreMultiple {
finalValue = origNewSliceVal.Index(0)
} else {
return errorx.IllegalArgument.New("SelectAdvanced: model is not a slice but IgnoreMultiple is false")
}
} else if !unwrappedValue.CanAddr() {
return errorx.IllegalArgument.New("Non-addressable value passed to SelectAdvanced, pass a ptr instead.")
}
unwrappedValue.Set(finalValue)
return nil
}