示例#1
0
func (s *scanner) codecAndPipe() (*codec.Codec, *pipe.Pipe) {
	if c := codec.FromTag(s.Tag); c != nil {
		return c, pipe.FromTag(s.Tag)
	}
	return nil, nil
}
示例#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
}
示例#3
0
func (o *Orm) fields(table string, s *structs.Struct) (*driver.Fields, map[string]*reference, error) {
	methods, err := driver.MakeMethods(s.Type)
	if err != nil {
		return nil, nil, err
	}
	fields := &driver.Fields{
		Struct:     s,
		PrimaryKey: -1,
		Methods:    methods,
	}
	var references map[string]*reference
	for ii, v := range s.QNames {
		// XXX: Check if this quoting is enough
		fields.QuotedNames = append(fields.QuotedNames, fmt.Sprintf("\"%s\".\"%s\"", table, s.MNames[ii]))
		t := s.Types[ii]
		ftag := s.Tags[ii]
		// Check encoded types
		if cn := ftag.CodecName(); cn != "" {
			if codec.Get(cn) == nil {
				if imp := codec.RequiredImport(cn); imp != "" {
					return nil, nil, fmt.Errorf("please import %q to use the codec %q", imp, cn)
				}
				return nil, nil, fmt.Errorf("can't find codec %q. Perhaps you missed an import?", cn)
			}
		} else {
			switch t.Kind() {
			case reflect.Array, reflect.Chan, reflect.Func, reflect.Interface, reflect.Map:
				return nil, nil, fmt.Errorf("field %q in struct %s has invalid type %s", v, s.Type, t)
			}
		}
		if pn := ftag.PipeName(); pn != "" {
			// Check if the field has a codec and the pipe exists
			if ftag.CodecName() == "" {
				return nil, nil, fmt.Errorf("field %q has pipe %s but no codec - only encoded types can use pipes", v, pn)
			}
			if pipe.FromTag(ftag) == nil {
				return nil, nil, fmt.Errorf("can't find ORM pipe %q. Perhaps you missed an import?", pn)
			}
		}
		// Struct has flattened types, but we need to original type
		// to determine if it should be nullempty or omitempty by default
		field := s.Type.FieldByIndex(s.Indexes[ii])
		fields.OmitEmpty = append(fields.OmitEmpty, ftag.Has("omitempty") || (defaultsToOmitEmpty(field.Type, ftag) && !ftag.Has("notomitempty")))
		fields.NullEmpty = append(fields.NullEmpty, ftag.Has("nullempty") || (defaultsToNullEmpty(field.Type, ftag) && !ftag.Has("notnullempty")))
		if ftag.Has("primary_key") {
			if fields.PrimaryKey >= 0 {
				return nil, nil, fmt.Errorf("duplicate primary_key in struct %v (%s and %s)", s.Type, s.QNames[fields.PrimaryKey], v)
			}
			fields.PrimaryKey = ii
		}
		if ftag.Has("auto_increment") {
			if k := types.Kind(t.Kind()); k != types.Int && k != types.Uint {
				return nil, nil, fmt.Errorf("auto_increment field %q in struct %s must be of integer type (signed or unsigned", v, s.Type)
			}
			fields.AutoincrementPk = fields.PrimaryKey == ii
		}
		if ref := ftag.Value("references"); ref != "" {
			m := referencesRe.FindStringSubmatch(ref)
			if len(m) != 4 {
				return nil, nil, fmt.Errorf("field %q has invalid references %q. Must be in the form references=Model or references=Model(Field)", v, ref)
			}
			if references == nil {
				references = make(map[string]*reference)
			}
			references[v] = &reference{model: m[1], field: m[3]}
		}
	}
	if err := o.setFieldsDefaults(fields); err != nil {
		return nil, nil, err
	}
	return fields, references, nil
}