Слияние кода завершено, страница обновится автоматически
/*
* 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 (
"database/sql"
"os"
"reflect"
)
type Toy struct {
db *sql.DB
objMustAddr bool
DefaultHandlerChain map[string]HandlersChain
DefaultModelHandlerChain map[reflect.Type]map[string]HandlersChain
ToyKernel
}
func Open(driverName, dataSourceName string) (*Toy, error) {
db, err := sql.Open(driverName, dataSourceName)
if err != nil {
return nil, err
}
var dialect Dialect
switch driverName {
case "mysql":
dialect = MySqlDialect{}
case "sqlite3":
dialect = Sqlite3Dialect{}
case "postgres":
dialect = PostgreSqlDialect{}
default:
dialect = DefaultDialect{}
}
return &Toy{
db: db,
DefaultHandlerChain: map[string]HandlersChain{
"CreateTable": {HandlerCreateTablePreload("CreateTable"), HandlerCreateTable},
"CreateTableIfNotExist": {HandlerCreateTablePreload("CreateTableIfNotExist"), HandlerExistTableAbort, HandlerCreateTable},
"DropTableIfExist": {HandlerDropTablePreload("DropTableIfExist"), HandlerNotExistTableAbort, HandlerDropTable},
"DropTable": {HandlerDropTablePreload("DropTable"), HandlerDropTable},
"Insert": {HandlerPreloadContainerCheck, HandlerPreloadInsertOrSave("Insert"), HandlerCasVersionPushOne, HandlerInsertTimeGenerate, HandlerInsert},
"Find": {HandlerPreloadContainerCheck, HandlerSoftDeleteCheck, HandlerFind, HandlerPreloadOnJoinFind, HandlerPreloadFind},
"Update": {HandlerSoftDeleteCheck, HandlerUpdateTimeGenerate, HandlerUpdate},
"Save": {HandlerPreloadContainerCheck, HandlerPreloadInsertOrSave("Save"), HandlerCasVersionPushOne, HandlerSaveTimeGenerate, HandlerSave},
"USave": {HandlerPreloadContainerCheck, HandlerPreloadInsertOrSave("USave"), HandlerCasVersionPushOne, HandlerUSaveTimeGenerate, HandlerUSave},
"HardDelete": {HandlerPreloadDelete, HandlerHardDelete},
"SoftDelete": {HandlerPreloadDelete, HandlerSoftDelete},
"HardDeleteWithPrimaryKey": {HandlerPreloadDelete, HandlerSearchWithPrimaryKey, HandlerHardDelete},
"SoftDeleteWithPrimaryKey": {HandlerPreloadDelete, HandlerSearchWithPrimaryKey, HandlerSoftDelete},
},
DefaultModelHandlerChain: map[reflect.Type]map[string]HandlersChain{},
ToyKernel: ToyKernel{
Dialect: dialect,
Logger: os.Stdout,
},
}, nil
}
func (t *Toy) Model(v interface{}) *ToyBrick {
vVal := LoopDivePtr(reflect.ValueOf(v))
if t.objMustAddr && vVal.CanAddr() == false {
panic("object must can addr")
}
model := t.GetModel(vVal)
toyBrick := NewToyBrick(t, model)
if t.debug {
toyBrick = toyBrick.Debug()
}
//toyBrick.objMustAddr = t.objMustAddr // wait to implement it
return toyBrick
}
// required object in Toy.[Model]
// TODO Brick.[Insert,Find,Update,Save,USave,Delete] method's parameter must be point object
func (t *Toy) MustAddr(b bool) {
t.objMustAddr = b
}
func (t *Toy) MiddleModel(v, sv interface{}) *ToyBrick {
vVal := LoopDivePtr(reflect.ValueOf(v))
svVal := LoopDivePtr(reflect.ValueOf(sv))
model, subModel := t.GetModel(vVal), t.GetModel(svVal)
middleModel := NewMiddleModel(model, subModel)
return NewToyBrick(t, middleModel)
}
func (t *Toy) ModelHandlers(option string, model *Model) HandlersChain {
handlers := make(HandlersChain, 0, len(t.DefaultHandlerChain[option])+len(t.DefaultModelHandlerChain[model.ReflectType][option]))
handlers = append(handlers, t.DefaultModelHandlerChain[model.ReflectType][option]...)
handlers = append(handlers, t.DefaultHandlerChain[option]...)
return handlers
}
func (t *Toy) Close() error {
if t == nil {
return nil
}
return t.db.Close()
}
func (t *Toy) BelongToPreload(model *Model, field Field) *BelongToPreload {
val := LoopDivePtr(field.FieldValue())
if val.Kind() != reflect.Struct {
return nil
}
if subModel := t.GetModel(val); subModel != nil {
if relationField, ok := model.Association[BelongToWith][field.Name()]; ok {
return t.BelongToBind(model, subModel, field, relationField)
}
if relationField := model.GetFieldWithName(GetBelongsIDFieldName(subModel, field)); relationField != nil {
return t.BelongToBind(model, subModel, field, relationField)
}
}
return nil
}
func (t *Toy) OneToOnePreload(model *Model, field Field) *OneToOnePreload {
val := LoopDivePtr(field.FieldValue())
if val.Kind() != reflect.Struct {
return nil
}
if subModel := t.GetModel(val); subModel != nil {
if relationField, ok := subModel.Association[OneToOneWith][field.Name()]; ok {
return t.OneToOneBind(model, subModel, field, relationField)
}
if relationField := subModel.GetFieldWithName(GetRelationFieldName(model)); relationField != nil {
return t.OneToOneBind(model, subModel, field, relationField)
}
}
return nil
}
func (t *Toy) OneToManyPreload(model *Model, field Field) *OneToManyPreload {
val := LoopDivePtr(field.FieldValue())
if val.Kind() == reflect.Slice {
elemVal := LoopDiveSliceAndPtr(val)
if subModel := t.GetModel(elemVal); subModel != nil {
if relationField, ok := subModel.Association[OneToManyWith][field.Name()]; ok {
return t.OneToManyBind(model, subModel, field, relationField)
}
if relationField := subModel.GetFieldWithName(GetRelationFieldName(model)); relationField != nil {
return t.OneToManyBind(model, subModel, field, relationField)
}
}
}
return nil
}
func (t *Toy) ManyToManyPreload(model *Model, field Field, isRight bool) *ManyToManyPreload {
return t.manyToManyPreloadWithTag(model, field, isRight, `toyorm:"primary key"`)
}
func (t *Toy) manyToManyPreloadWithTag(model *Model, field Field, isRight bool, tag reflect.StructTag) *ManyToManyPreload {
val := LoopDivePtr(field.FieldValue())
if val.Kind() == reflect.Slice {
elemVal := LoopDiveSliceAndPtr(val)
if subModel := t.GetModel(elemVal); subModel != nil {
middleModel := newMiddleModel(model, subModel, tag)
relationField := GetMiddleField(model, middleModel, isRight)
subRelationField := GetMiddleField(subModel, middleModel, !isRight)
return t.ManyToManyPreloadBind(model, subModel, middleModel, field, relationField, subRelationField)
}
}
return nil
}
func (t *Toy) Join(model *Model, field Field) *Join {
val := LoopDiveSliceAndPtr(field.FieldValue())
subModel := t.GetModel(val)
containerName := field.Name()
if model.Association[JoinWith][containerName] != nil && subModel.Association[JoinWith][containerName] != nil {
return &Join{
model,
subModel,
field,
model.Association[JoinWith][containerName],
subModel.Association[JoinWith][containerName],
}
}
return nil
}
func (t *Toy) BelongToBind(model, subModel *Model, containerField, relationField Field) *BelongToPreload {
if LoopTypeIndirect(relationField.StructField().Type) != subModel.GetOnePrimary().StructField().Type {
panic("relation key must have same type with sub model primary key")
}
return &BelongToPreload{
Model: model,
SubModel: subModel,
RelationField: relationField,
ContainerField: containerField,
}
}
func (t *Toy) OneToOneBind(model, subModel *Model, containerField, relationField Field) *OneToOnePreload {
if LoopTypeIndirect(relationField.StructField().Type) != model.GetOnePrimary().StructField().Type {
panic("relation key must have same type with model primary key")
}
return &OneToOnePreload{
Model: model,
SubModel: subModel,
RelationField: relationField,
ContainerField: containerField,
}
}
func (t *Toy) OneToManyBind(model, subModel *Model, containerField, relationField Field) *OneToManyPreload {
if LoopTypeIndirect(relationField.StructField().Type) != model.GetOnePrimary().StructField().Type {
panic("relation key must have same type with model primary key")
}
return &OneToManyPreload{
Model: model,
SubModel: subModel,
RelationField: relationField,
ContainerField: containerField,
}
}
func (t *Toy) ManyToManyPreloadBind(model, subModel, middleModel *Model, containerField, relationField, subRelationField Field) *ManyToManyPreload {
if LoopTypeIndirect(relationField.StructField().Type) != model.GetOnePrimary().StructField().Type {
panic("relation key must have same type with model primary key")
}
if LoopTypeIndirect(subRelationField.StructField().Type) != subModel.GetOnePrimary().StructField().Type {
panic("sub relation key must have same type with sub model primary key")
}
return &ManyToManyPreload{
Model: model,
SubModel: subModel,
MiddleModel: middleModel,
ContainerField: containerField,
RelationField: relationField,
SubRelationField: subRelationField,
}
}
func (t *Toy) DB() *sql.DB {
return t.db
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )