Пример #1
0
func (b *SqlBackend) ScanInt(val int64, goVal *reflect.Value, t *structs.Tag) error {
	if types.Kind(goVal.Kind()) == types.Uint {
		goVal.SetUint(uint64(val))
		return nil
	}
	goVal.SetInt(val)
	return nil
}
Пример #2
0
func valRepr(s *gosym.Sym, typ reflect.Type, values []string, _html bool) (r string) {
	val, _ := strconv.ParseUint(values[0], 0, 64)
	var val2 uint64
	if len(values) > 1 {
		val2, _ = strconv.ParseUint(values[1], 0, 64)
	}
	// If there's a panic prettyfy'ing the value just
	// assume it's a pointer. It's better than
	// omitting the error page.
	defer func() {
		if recover() != nil {
			r = pointerRepr(nil, val, false)
		}
	}()
	switch types.Kind(typ.Kind()) {
	case types.Bool:
		if val == 0 {
			return "= false"
		}
		return "= true"
	case types.Int:
		return "= " + strconv.FormatInt(int64(val), 10)
	case types.Uint:
		return "= " + strconv.FormatUint(val, 10)
	case types.Float:
		if typ.Kind() == reflect.Float32 {
			return "= " + strconv.FormatFloat(float64(math.Float32frombits(uint32(val))), 'g', -1, 32)
		}
		return "= " + strconv.FormatFloat(math.Float64frombits(uint64(val)), 'g', -1, 64)
	case types.Slice:
		return sliceRepr(val, val2, s)
	case types.String:
		v := stringRepr(val, val2)
		if _html {
			v = html.Escape(v)
		}
		return v
	case types.Interface:
		if typ.NumMethod() == 0 {
			return emptyInterfaceRepr(val, val2)
		}
		idata := [2]uintptr{uintptr(val), uintptr(val2)}
		v := reflect.NewAt(typ, unsafe.Pointer(&idata[0])).Elem()
		return descRepr(val, &v, _html)
	case types.Func:
		fn := reflect.NewAt(typ, unsafe.Pointer(&val)).Elem()
		f := runtime.FuncForPC(fn.Pointer())
		if f != nil {
			return "= " + f.Name()
		}
	}
	return pointerRepr(typ, val, _html)
}
Пример #3
0
func Number(lang i18n.Languager, number interface{}) (string, error) {
	val := reflect.Indirect(reflect.ValueOf(number))
	if val.IsValid() {
		switch types.Kind(val.Kind()) {
		case types.Int:
			return formatNumber(lang, strconv.FormatInt(val.Int(), 10), ""), nil
		case types.Uint:
			return formatNumber(lang, strconv.FormatUint(val.Uint(), 10), ""), nil
		case types.Float:
			return formatStringNumber(lang, strconv.FormatFloat(val.Float(), 'f', -1, 64)), nil
		case types.String:
			return formatStringNumber(lang, val.String()), nil
		}
	}
	return "", fmt.Errorf("can't format type %T as number", number)
}
Пример #4
0
func toHTMLValue(val interface{}) string {
	v := reflect.ValueOf(val)
	if v.IsValid() {
		for v.Kind() == reflect.Ptr {
			v = v.Elem()
		}
		if v.IsValid() {
			// Avoid enum types with a String() method to be represented
			// as a string. Use their numeric representation.
			k := types.Kind(v.Kind())
			if k == types.Int {
				return strconv.FormatInt(v.Int(), 10)
			}
			if k == types.Uint {
				return strconv.FormatUint(v.Uint(), 10)
			}
		}
	}
	return html.Escape(types.ToString(val))
}
Пример #5
0
func (b *Backend) ScanByteSlice(val []byte, goVal *reflect.Value, t *structs.Tag) error {
	// mysql returns u?int types as []byte under
	// some circumstances (not sure exactly when, but other
	// times they're returned as an int64).
	switch types.Kind(goVal.Kind()) {
	case types.Int:
		v, err := strconv.ParseInt(string(val), 10, 64)
		if err != nil {
			return err
		}
		goVal.SetInt(v)
		return nil
	case types.Uint:
		v, err := strconv.ParseUint(string(val), 10, 64)
		if err != nil {
			return err
		}
		goVal.SetUint(v)
		return nil
	}
	return b.SqlBackend.ScanByteSlice(val, goVal, t)
}
Пример #6
0
func (d *Driver) Insert(m driver.Model, data interface{}) (driver.Result, error) {
	var id int64
	fields := m.Fields()
	var pkVal *reflect.Value
	// TODO: If the PK is supplied by the user rather than auto-assigned, it
	// might conflict with PKs generated by datastore.AllocateIDs().
	if fields.PrimaryKey >= 0 {
		p := d.primaryKey(fields, data)
		if p.IsValid() && types.Kind(p.Kind()) == types.Int {
			id = p.Int()
			if id == 0 {
				// Must assign PK field value after calling AllocateIDs
				pkVal = &p
			}
		}
	}
	name := m.Table()
	// Make all objects of a given kind ancestors of the same key. While
	// this hurts scalability, it makes all reads strongly consistent.
	parent := d.parentKey(m)
	var err error
	if id == 0 {
		id, _, err = datastore.AllocateIDs(d.c, name, parent, 1)
		if err != nil {
			return nil, err
		}
	}
	if fields.AutoincrementPk && pkVal != nil {
		pkVal.SetInt(int64(id))
	}
	key := datastore.NewKey(d.c, name, "", id, parent)
	log.Debugf("DATASTORE: put %s %v", key, data)
	_, err = datastore.Put(d.c, key, data)
	if err != nil {
		return nil, err
	}
	return &result{key: key, count: 1}, nil
}
Пример #7
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
}