Пример #1
0
func NewModel(vi interface{}) (Model, error) {
	v := reflect.ValueOf(vi)
	if !v.IsValid() {
		return nil, errors.New("pg: NewModel(nil)")
	}
	v = reflect.Indirect(v)

	if v.Kind() == reflect.Slice {
		elType := indirectType(v.Type().Elem())
		if elType == timeType || elType.Kind() != reflect.Struct {
			return &sliceModel{
				slice:   v,
				decoder: types.Decoder(elType),
			}, nil
		}
	}

	return newTableModelValue(v)
}
Пример #2
0
func (t *Table) newField(typ reflect.Type, f reflect.StructField) *Field {
	sqlName, sqlOpt := parseTag(f.Tag.Get("sql"))

	if f.Name == "TableName" {
		t.Name = sqlName
		return nil
	}

	skip := sqlName == "-"
	if skip || sqlName == "" {
		sqlName = Underscore(f.Name)
	}

	if field, ok := t.FieldsMap[sqlName]; ok {
		return field
	}

	_, pgOpt := parseTag(f.Tag.Get("pg"))

	ftype := indirectType(f.Type)
	field := Field{
		GoName:  f.Name,
		SQLName: sqlName,

		Index: f.Index,

		append: types.Appender(ftype),
		decode: types.Decoder(ftype),

		isEmpty: isEmptier(ftype.Kind()),
		equal:   equaler(ftype.Kind()),
	}

	if skip {
		t.FieldsMap[field.SQLName] = &field
		return nil
	}

	if _, ok := pgOpt.Get("nullempty"); ok {
		field.flags |= NullEmptyFlag
	}
	if field.SQLName == "id" {
		field.flags |= PrimaryKeyFlag
		t.PKs = append(t.PKs, &field)
	} else if _, ok := sqlOpt.Get("pk"); ok {
		field.flags |= PrimaryKeyFlag
		t.PKs = append(t.PKs, &field)
	} else if strings.HasSuffix(field.SQLName, "_id") {
		field.flags |= ForeignKeyFlag
	}

	var polymorphic string
	if s, _ := pgOpt.Get("polymorphic:"); s != "" {
		polymorphic = Underscore(s) + "_"
	}

	switch ftype.Kind() {
	case reflect.Slice:
		if ftype.Elem().Kind() == reflect.Struct {
			joinTable := newTable(ftype.Elem())

			if m2mName, _ := pgOpt.Get("many2many:"); m2mName != "" {
				if m2mSlice, ok := typ.FieldByName(m2mName); ok {
					t.addRelation(&Relation{
						Field: &field,
						Join:  joinTable,
						M2M:   newTable(m2mSlice.Type.Elem()),
					})
				}
				return nil
			}

			var fks []*Field
			var prefix string
			if polymorphic != "" {
				prefix = polymorphic
			} else {
				prefix = t.ModelName + "_"
			}

			for _, pk := range t.PKs {
				fkName := prefix + pk.SQLName
				fk, ok := joinTable.FieldsMap[fkName]
				if ok {
					fks = append(fks, fk)
				}
			}

			if len(fks) > 0 {
				t.addRelation(&Relation{
					Polymorphic: polymorphic,
					Field:       &field,
					FKs:         fks,
					Join:        joinTable,
				})
				return nil
			}
		}
	case reflect.Struct:
		joinTable := newTable(ftype)
		if len(joinTable.Fields) == 0 {
			break
		}

		for _, ff := range joinTable.Fields {
			ff = ff.Copy()
			ff.SQLName = field.SQLName + "__" + ff.SQLName
			ff.Index = append(field.Index, ff.Index...)
			t.FieldsMap[ff.SQLName] = ff
		}

		var fks []*Field
		for _, pk := range joinTable.PKs {
			fkName := field.SQLName + "_" + pk.SQLName
			fk, ok := t.FieldsMap[fkName]
			if ok {
				fks = append(fks, fk)
			}
		}

		if len(fks) > 0 {
			t.addRelation(&Relation{
				One:   true,
				Field: &field,
				FKs:   fks,
				Join:  joinTable,
			})
		}

		t.FieldsMap[field.SQLName] = &field
		return nil
	}

	return &field
}