Example #1
0
func (o *Orm) save(m *model, obj interface{}) (Result, error) {
	if profile.On && profile.Profiling() {
		defer profile.Start(orm).Note("save", m.name).End()
	}
	var res Result
	var err error
	if m.fields.PrimaryKey >= 0 {
		pkName, pkVal := o.primaryKey(m.fields, obj)
		if driver.IsZero(pkVal) {
			return o.insert(m, obj)
		}
		res, err = o.update(m, Eq(pkName, pkVal.Interface()), obj)
	} else if len(m.fields.CompositePrimaryKey) > 0 {
		// Composite primary key
		names, values := o.compositePrimaryKey(m.fields, obj)
		for _, v := range values {
			if !driver.IsZero(v) {
				// We have a non-zero value, try to update
				qs := make([]query.Q, len(names))
				for ii := range names {
					qs[ii] = Eq(names[ii], values[ii].Interface())
				}
				res, err = o.update(m, And(qs...), obj)
				break
			}
		}
		if res == nil && err == nil {
			// Not updated. All the fields in the PK are zero
			return o.insert(m, obj)
		}
	} else {
		// No pk
		return o.insert(m, obj)
	}
	if err != nil {
		return nil, err
	}
	up, err := res.RowsAffected()
	if err != nil {
		return nil, err
	}
	if up == 0 {
		return o.insert(m, obj)
	}
	return res, nil
}
Example #2
0
func (d *Driver) saveParameters(m driver.Model, data interface{}) (reflect.Value, []string, []interface{}, error) {
	// data is guaranteed to be of m.Type()
	val := driver.Direct(reflect.ValueOf(data))
	fields := m.Fields()
	max := len(fields.MNames)
	names := make([]string, 0, max)
	values := make([]interface{}, 0, max)
	var err error
	if d.transforms != nil {
		for ii, v := range fields.Indexes {
			f := d.fieldByIndex(val, v, false)
			if !f.IsValid() {
				continue
			}
			if fields.OmitEmpty[ii] && driver.IsZero(f) {
				continue
			}
			ft := f.Type()
			var fval interface{}
			if _, ok := d.transforms[ft]; ok {
				fval, err = d.backend.TransformOutValue(f)
				if err != nil {
					return val, nil, nil, err
				}
				if fields.NullEmpty[ii] && driver.IsZero(reflect.ValueOf(fval)) {
					fval = nil
				}
			} else if !fields.NullEmpty[ii] || !driver.IsZero(f) {
				if c := codec.FromTag(fields.Tags[ii]); c != nil {
					fval, err = c.Encode(f.Interface())
					if err != nil {
						return val, nil, nil, err
					}
					if p := pipe.FromTag(fields.Tags[ii]); p != nil {
						data, err := p.Encode(fval.([]byte))
						if err != nil {
							return val, nil, nil, err
						}
						fval = data
					}
				} else {
					// Most sql drivers won't accept aliases for string type
					if ft.Kind() == reflect.String && ft != stringType {
						f = f.Convert(stringType)
					}
					fval = f.Interface()
				}
			}
			names = append(names, fields.MNames[ii])
			values = append(values, fval)
		}
	} else {
		for ii, v := range fields.Indexes {
			f := d.fieldByIndex(val, v, false)
			if !f.IsValid() {
				continue
			}
			if fields.OmitEmpty[ii] && driver.IsZero(f) {
				continue
			}
			var fval interface{}
			if !fields.NullEmpty[ii] || !driver.IsZero(f) {
				if c := codec.FromTag(fields.Tags[ii]); c != nil {
					fval, err = c.Encode(&f)
					if err != nil {
						return val, nil, nil, err
					}
				} else {
					ft := f.Type()
					// Most sql drivers won't accept aliases for string type
					if ft.Kind() == reflect.String && ft != stringType {
						f = f.Convert(stringType)
					}
					fval = f.Interface()
				}
			}
			names = append(names, fields.MNames[ii])
			values = append(values, fval)
		}
	}
	return val, names, values, nil
}