1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/bigpigeon-toyorm

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
Клонировать/Скачать
model.go 7.1 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
bigpigeon Отправлено 08.12.2018 19:06 a7884f8
/*
* Copyright 2018. bigpigeon. All rights reserved.
* Use of this source code is governed by a MIT style
* license that can be found in the LICENSE file.
*/
package toyorm
import (
"errors"
"fmt"
"reflect"
"time"
)
type tabler interface {
TableName() string
}
// table struct used to save all sql attribute with struct
// column is table name attribute
// AllFields is all struct field and it's Anonymous struct
// SqlFields is all about sql field
// OffsetFields is map field offset
// NameFields is map field name
// PrimaryFields is all about primary key field
// IndexFields is all about index fields
// UniqueIndexFields is all about unique index fields
// StructFieldFields is map unknown struct type or slice struct type
type Model struct {
Name string
ReflectType reflect.Type
AllFields []*modelField
SqlFields []*modelField
OffsetFields map[uintptr]*modelField
NameFields map[string]*modelField
SqlFieldMap map[string]*modelField
PrimaryFields []*modelField
IndexFields map[string][]*modelField
UniqueIndexFields map[string][]*modelField
StructFieldFields map[reflect.Type][]*modelField
Association [AssociationTypeEnd]map[string]*modelField
}
func (m *Model) GetPosFields(pos []int) []Field {
fields := make([]Field, 0, len(pos))
for _, i := range pos {
fields = append(fields, m.AllFields[i])
}
return fields
}
func (m *Model) GetPosField(pos int) Field {
return m.AllFields[pos]
}
func (m *Model) GetSqlFields() []Field {
fields := make([]Field, len(m.SqlFields))
for i, f := range m.SqlFields {
fields[i] = f
}
return fields
}
func (m *Model) GetNameFieldMap() map[string]Field {
fields := make(map[string]Field, len(m.NameFields))
for n, f := range m.NameFields {
fields[n] = f
}
return fields
}
func (m *Model) GetOffsetFieldMap() map[uintptr]Field {
fields := make(map[uintptr]Field, len(m.OffsetFields))
for o, f := range m.OffsetFields {
fields[o] = f
}
return fields
}
func (m *Model) GetOffsetField(offset uintptr) Field {
if field, ok := m.OffsetFields[offset]; ok {
return field
}
return nil
}
func (m *Model) GetFieldWithName(name string) Field {
if field, ok := m.NameFields[name]; ok {
return field
}
return nil
}
func (m *Model) GetPrimary() []Field {
fields := make([]Field, len(m.PrimaryFields))
for i, f := range m.PrimaryFields {
fields[i] = f
}
return fields
}
func (m *Model) GetOnePrimary() Field {
if len(m.PrimaryFields) > 1 {
panic(errors.New(fmt.Sprintf("%s have more than 1 primary", m.Name)))
}
return m.PrimaryFields[0]
}
func (m *Model) GetIndexMap() map[string][]Field {
fieldMap := make(map[string][]Field, len(m.IndexFields))
for s, fields := range m.IndexFields {
fieldMap[s] = make([]Field, 0, len(fields))
for _, f := range fields {
fieldMap[s] = append(fieldMap[s], f)
}
}
return fieldMap
}
func (m *Model) GetUniqueIndexMap() map[string][]Field {
fieldMap := make(map[string][]Field, len(m.UniqueIndexFields))
for s, fields := range m.UniqueIndexFields {
fieldMap[s] = make([]Field, 0, len(fields))
for _, f := range fields {
fieldMap[s] = append(fieldMap[s], f)
}
}
return fieldMap
}
func NewModel(val reflect.Value) *Model {
if val.Kind() != reflect.Struct {
panic(ErrInvalidModelType(val.Type().Name()))
}
if val.Type().Name() == "" {
panic(ErrInvalidModelName{})
}
return newModel(val, ModelName(val))
}
func NewMiddleModel(model, subModel *Model) *Model {
return newMiddleModel(model, subModel, `toyorm:"primary key"`)
}
func newMiddleModel(model, subModel *Model, tag reflect.StructTag) *Model {
var fields [2]reflect.StructField
var sortdModel [2]*Model
if model.Name < subModel.Name {
sortdModel = [2]*Model{model, subModel}
} else {
sortdModel = [2]*Model{subModel, model}
}
for i, model := range sortdModel {
field := model.GetOnePrimary().StructField()
field.Tag = tag
field.Name = GetRelationFieldName(model)
fields[i] = field
}
if fields[0].Name == fields[1].Name {
fields[0].Name = "L_" + fields[0].Name
fields[1].Name = "R_" + fields[1].Name
}
return newModel(reflect.Zero(reflect.StructOf(fields[:])), fmt.Sprintf("%s_%s", sortdModel[0].Name, sortdModel[1].Name))
}
func newModel(val reflect.Value, modelName string) *Model {
_type := val.Type()
model := &Model{
Name: modelName,
ReflectType: _type,
OffsetFields: map[uintptr]*modelField{},
NameFields: map[string]*modelField{},
SqlFieldMap: map[string]*modelField{},
PrimaryFields: []*modelField{},
IndexFields: map[string][]*modelField{},
UniqueIndexFields: map[string][]*modelField{},
StructFieldFields: map[reflect.Type][]*modelField{},
Association: [AssociationTypeEnd]map[string]*modelField{},
}
for i := range model.Association {
model.Association[i] = make(map[string]*modelField)
}
for i := 0; i < _type.NumField(); i++ {
field := _type.Field(i)
fieldVal := val.Field(i)
if field.Anonymous && field.Type.Kind() == reflect.Struct {
embedTable := newModel(fieldVal, model.Name)
for _, tabField := range embedTable.AllFields {
tabField.offset += field.Offset
model.AllFields = append(model.AllFields, tabField)
}
} else {
tField := NewField(&field, fieldVal, model.Name)
model.AllFields = append(model.AllFields, tField)
}
}
// cache field attribute with model
for i := 0; i < len(model.AllFields); i++ {
field := model.AllFields[i]
model.OffsetFields[field.offset] = field
if _, ok := model.NameFields[field.Name()]; ok {
panic(ErrRepeatField{model.Name, field.field.Name})
}
model.NameFields[field.Name()] = field
if field.isPrimary {
model.PrimaryFields = append(model.PrimaryFields, field)
}
if field.index != "" {
model.IndexFields[field.index] = append(model.IndexFields[field.index], field)
}
if field.uniqueIndex != "" {
model.UniqueIndexFields[field.uniqueIndex] = append(model.UniqueIndexFields[field.uniqueIndex], field)
}
for association, val := range field.Association {
if _, ok := model.Association[association][val]; ok {
panic(ErrModelDuplicateAssociation{model.Name, association, field.field.Name})
}
model.Association[association][val] = field
}
if field.ignore == false {
if oldField, ok := model.SqlFieldMap[field.column]; ok {
panic(ErrSameColumnName{model.Name, field.column, oldField.field.Name, field.field.Name})
}
model.SqlFieldMap[field.column] = field
model.SqlFields = append(model.SqlFields, field)
} else {
// preload
var fieldType = LoopTypeIndirectSliceAndPtr(field.field.Type)
model.StructFieldFields[fieldType] = append(model.StructFieldFields[fieldType], field)
}
}
return model
}
type FieldSelection interface{}
func (m *Model) fieldSelect(v FieldSelection) Field {
switch v := v.(type) {
case int:
return m.SqlFields[v]
case uintptr:
return m.OffsetFields[v]
case string:
return m.NameFields[v]
case Field:
return v
default:
panic("invalid field value")
}
}
type ModelDefault struct {
ID uint32 `toyorm:"primary key;auto_increment"`
CreatedAt time.Time `toyorm:"NULL"`
UpdatedAt time.Time `toyorm:"NULL"`
DeletedAt *time.Time `toyorm:"index;NULL"`
}

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/bigpigeon-toyorm.git
git@api.gitlife.ru:oschina-mirror/bigpigeon-toyorm.git
oschina-mirror
bigpigeon-toyorm
bigpigeon-toyorm
master