Merge branch 'adamar-master'
This commit is contained in:
		
						commit
						b8976ab20f
					
				
							
								
								
									
										36
									
								
								callback.go
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								callback.go
									
									
									
									
									
								
							@ -9,10 +9,10 @@ type callback struct {
 | 
				
			|||||||
	updates    []*func(scope *Scope)
 | 
						updates    []*func(scope *Scope)
 | 
				
			||||||
	deletes    []*func(scope *Scope)
 | 
						deletes    []*func(scope *Scope)
 | 
				
			||||||
	queries    []*func(scope *Scope)
 | 
						queries    []*func(scope *Scope)
 | 
				
			||||||
	processors []*callback_processor
 | 
						processors []*callbackProcessor
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type callback_processor struct {
 | 
					type callbackProcessor struct {
 | 
				
			||||||
	name      string
 | 
						name      string
 | 
				
			||||||
	before    string
 | 
						before    string
 | 
				
			||||||
	after     string
 | 
						after     string
 | 
				
			||||||
@ -23,8 +23,8 @@ type callback_processor struct {
 | 
				
			|||||||
	callback  *callback
 | 
						callback  *callback
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *callback) addProcessor(typ string) *callback_processor {
 | 
					func (c *callback) addProcessor(typ string) *callbackProcessor {
 | 
				
			||||||
	cp := &callback_processor{typ: typ, callback: c}
 | 
						cp := &callbackProcessor{typ: typ, callback: c}
 | 
				
			||||||
	c.processors = append(c.processors, cp)
 | 
						c.processors = append(c.processors, cp)
 | 
				
			||||||
	return cp
 | 
						return cp
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -33,46 +33,46 @@ func (c *callback) clone() *callback {
 | 
				
			|||||||
	return &callback{processors: c.processors}
 | 
						return &callback{processors: c.processors}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *callback) Create() *callback_processor {
 | 
					func (c *callback) Create() *callbackProcessor {
 | 
				
			||||||
	return c.addProcessor("create")
 | 
						return c.addProcessor("create")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *callback) Update() *callback_processor {
 | 
					func (c *callback) Update() *callbackProcessor {
 | 
				
			||||||
	return c.addProcessor("update")
 | 
						return c.addProcessor("update")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *callback) Delete() *callback_processor {
 | 
					func (c *callback) Delete() *callbackProcessor {
 | 
				
			||||||
	return c.addProcessor("delete")
 | 
						return c.addProcessor("delete")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *callback) Query() *callback_processor {
 | 
					func (c *callback) Query() *callbackProcessor {
 | 
				
			||||||
	return c.addProcessor("query")
 | 
						return c.addProcessor("query")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cp *callback_processor) Before(name string) *callback_processor {
 | 
					func (cp *callbackProcessor) Before(name string) *callbackProcessor {
 | 
				
			||||||
	cp.before = name
 | 
						cp.before = name
 | 
				
			||||||
	return cp
 | 
						return cp
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cp *callback_processor) After(name string) *callback_processor {
 | 
					func (cp *callbackProcessor) After(name string) *callbackProcessor {
 | 
				
			||||||
	cp.after = name
 | 
						cp.after = name
 | 
				
			||||||
	return cp
 | 
						return cp
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cp *callback_processor) Register(name string, fc func(scope *Scope)) {
 | 
					func (cp *callbackProcessor) Register(name string, fc func(scope *Scope)) {
 | 
				
			||||||
	cp.name = name
 | 
						cp.name = name
 | 
				
			||||||
	cp.processor = &fc
 | 
						cp.processor = &fc
 | 
				
			||||||
	cp.callback.sort()
 | 
						cp.callback.sort()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cp *callback_processor) Remove(name string) {
 | 
					func (cp *callbackProcessor) Remove(name string) {
 | 
				
			||||||
	fmt.Printf("[info] removing callback `%v` from %v\n", name, fileWithLineNum())
 | 
						fmt.Printf("[info] removing callback `%v` from %v\n", name, fileWithLineNum())
 | 
				
			||||||
	cp.name = name
 | 
						cp.name = name
 | 
				
			||||||
	cp.remove = true
 | 
						cp.remove = true
 | 
				
			||||||
	cp.callback.sort()
 | 
						cp.callback.sort()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (cp *callback_processor) Replace(name string, fc func(scope *Scope)) {
 | 
					func (cp *callbackProcessor) Replace(name string, fc func(scope *Scope)) {
 | 
				
			||||||
	fmt.Printf("[info] replacing callback `%v` from %v\n", name, fileWithLineNum())
 | 
						fmt.Printf("[info] replacing callback `%v` from %v\n", name, fileWithLineNum())
 | 
				
			||||||
	cp.name = name
 | 
						cp.name = name
 | 
				
			||||||
	cp.processor = &fc
 | 
						cp.processor = &fc
 | 
				
			||||||
@ -89,8 +89,8 @@ func getRIndex(strs []string, str string) int {
 | 
				
			|||||||
	return -1
 | 
						return -1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func sortProcessors(cps []*callback_processor) []*func(scope *Scope) {
 | 
					func sortProcessors(cps []*callbackProcessor) []*func(scope *Scope) {
 | 
				
			||||||
	var sortCallbackProcessor func(c *callback_processor)
 | 
						var sortCallbackProcessor func(c *callbackProcessor)
 | 
				
			||||||
	var names, sortedNames = []string{}, []string{}
 | 
						var names, sortedNames = []string{}, []string{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, cp := range cps {
 | 
						for _, cp := range cps {
 | 
				
			||||||
@ -102,7 +102,7 @@ func sortProcessors(cps []*callback_processor) []*func(scope *Scope) {
 | 
				
			|||||||
		names = append(names, cp.name)
 | 
							names = append(names, cp.name)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sortCallbackProcessor = func(c *callback_processor) {
 | 
						sortCallbackProcessor = func(c *callbackProcessor) {
 | 
				
			||||||
		if getRIndex(sortedNames, c.name) > -1 {
 | 
							if getRIndex(sortedNames, c.name) > -1 {
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -162,7 +162,7 @@ func sortProcessors(cps []*callback_processor) []*func(scope *Scope) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *callback) sort() {
 | 
					func (c *callback) sort() {
 | 
				
			||||||
	creates, updates, deletes, queries := []*callback_processor{}, []*callback_processor{}, []*callback_processor{}, []*callback_processor{}
 | 
						creates, updates, deletes, queries := []*callbackProcessor{}, []*callbackProcessor{}, []*callbackProcessor{}, []*callbackProcessor{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, processor := range c.processors {
 | 
						for _, processor := range c.processors {
 | 
				
			||||||
		switch processor.typ {
 | 
							switch processor.typ {
 | 
				
			||||||
@ -183,4 +183,4 @@ func (c *callback) sort() {
 | 
				
			|||||||
	c.queries = sortProcessors(queries)
 | 
						c.queries = sortProcessors(queries)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var DefaultCallback = &callback{processors: []*callback_processor{}}
 | 
					var DefaultCallback = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,7 @@ func Query(scope *Scope) {
 | 
				
			|||||||
		columns, _ := rows.Columns()
 | 
							columns, _ := rows.Columns()
 | 
				
			||||||
		defer rows.Close()
 | 
							defer rows.Close()
 | 
				
			||||||
		for rows.Next() {
 | 
							for rows.Next() {
 | 
				
			||||||
			scope.db.RowsAffected += 1
 | 
								scope.db.RowsAffected++
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			anyRecordFound = true
 | 
								anyRecordFound = true
 | 
				
			||||||
			elem := dest
 | 
								elem := dest
 | 
				
			||||||
 | 
				
			|||||||
@ -16,97 +16,97 @@ func equalFuncs(funcs []*func(s *Scope), fnames []string) bool {
 | 
				
			|||||||
	return reflect.DeepEqual(names, fnames)
 | 
						return reflect.DeepEqual(names, fnames)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func create(s *Scope)         {}
 | 
					func create(s *Scope)        {}
 | 
				
			||||||
func before_create1(s *Scope) {}
 | 
					func beforeCreate1(s *Scope) {}
 | 
				
			||||||
func before_create2(s *Scope) {}
 | 
					func beforeCreate2(s *Scope) {}
 | 
				
			||||||
func after_create1(s *Scope)  {}
 | 
					func afterCreate1(s *Scope)  {}
 | 
				
			||||||
func after_create2(s *Scope)  {}
 | 
					func afterCreate2(s *Scope)  {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRegisterCallback(t *testing.T) {
 | 
					func TestRegisterCallback(t *testing.T) {
 | 
				
			||||||
	var callback = &callback{processors: []*callback_processor{}}
 | 
						var callback = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	callback.Create().Register("before_create1", before_create1)
 | 
						callback.Create().Register("before_create1", beforeCreate1)
 | 
				
			||||||
	callback.Create().Register("before_create2", before_create2)
 | 
						callback.Create().Register("before_create2", beforeCreate2)
 | 
				
			||||||
	callback.Create().Register("create", create)
 | 
						callback.Create().Register("create", create)
 | 
				
			||||||
	callback.Create().Register("after_create1", after_create1)
 | 
						callback.Create().Register("after_create1", afterCreate1)
 | 
				
			||||||
	callback.Create().Register("after_create2", after_create2)
 | 
						callback.Create().Register("after_create2", afterCreate2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !equalFuncs(callback.creates, []string{"before_create1", "before_create2", "create", "after_create1", "after_create2"}) {
 | 
						if !equalFuncs(callback.creates, []string{"beforeCreate1", "beforeCreate2", "create", "afterCreate1", "afterCreate2"}) {
 | 
				
			||||||
		t.Errorf("register callback")
 | 
							t.Errorf("register callback")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRegisterCallbackWithOrder(t *testing.T) {
 | 
					func TestRegisterCallbackWithOrder(t *testing.T) {
 | 
				
			||||||
	var callback1 = &callback{processors: []*callback_processor{}}
 | 
						var callback1 = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
	callback1.Create().Register("before_create1", before_create1)
 | 
						callback1.Create().Register("before_create1", beforeCreate1)
 | 
				
			||||||
	callback1.Create().Register("create", create)
 | 
						callback1.Create().Register("create", create)
 | 
				
			||||||
	callback1.Create().Register("after_create1", after_create1)
 | 
						callback1.Create().Register("after_create1", afterCreate1)
 | 
				
			||||||
	callback1.Create().Before("after_create1").Register("after_create2", after_create2)
 | 
						callback1.Create().Before("after_create1").Register("after_create2", afterCreate2)
 | 
				
			||||||
	if !equalFuncs(callback1.creates, []string{"before_create1", "create", "after_create2", "after_create1"}) {
 | 
						if !equalFuncs(callback1.creates, []string{"beforeCreate1", "create", "afterCreate2", "afterCreate1"}) {
 | 
				
			||||||
		t.Errorf("register callback with order")
 | 
							t.Errorf("register callback with order")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var callback2 = &callback{processors: []*callback_processor{}}
 | 
						var callback2 = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	callback2.Update().Register("create", create)
 | 
						callback2.Update().Register("create", create)
 | 
				
			||||||
	callback2.Update().Before("create").Register("before_create1", before_create1)
 | 
						callback2.Update().Before("create").Register("before_create1", beforeCreate1)
 | 
				
			||||||
	callback2.Update().After("after_create2").Register("after_create1", after_create1)
 | 
						callback2.Update().After("after_create2").Register("after_create1", afterCreate1)
 | 
				
			||||||
	callback2.Update().Before("before_create1").Register("before_create2", before_create2)
 | 
						callback2.Update().Before("before_create1").Register("before_create2", beforeCreate2)
 | 
				
			||||||
	callback2.Update().Register("after_create2", after_create2)
 | 
						callback2.Update().Register("after_create2", afterCreate2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !equalFuncs(callback2.updates, []string{"before_create2", "before_create1", "create", "after_create2", "after_create1"}) {
 | 
						if !equalFuncs(callback2.updates, []string{"beforeCreate2", "beforeCreate1", "create", "afterCreate2", "afterCreate1"}) {
 | 
				
			||||||
		t.Errorf("register callback with order")
 | 
							t.Errorf("register callback with order")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRegisterCallbackWithComplexOrder(t *testing.T) {
 | 
					func TestRegisterCallbackWithComplexOrder(t *testing.T) {
 | 
				
			||||||
	var callback1 = &callback{processors: []*callback_processor{}}
 | 
						var callback1 = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	callback1.Query().Before("after_create1").After("before_create1").Register("create", create)
 | 
						callback1.Query().Before("after_create1").After("before_create1").Register("create", create)
 | 
				
			||||||
	callback1.Query().Register("before_create1", before_create1)
 | 
						callback1.Query().Register("before_create1", beforeCreate1)
 | 
				
			||||||
	callback1.Query().Register("after_create1", after_create1)
 | 
						callback1.Query().Register("after_create1", afterCreate1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !equalFuncs(callback1.queries, []string{"before_create1", "create", "after_create1"}) {
 | 
						if !equalFuncs(callback1.queries, []string{"beforeCreate1", "create", "afterCreate1"}) {
 | 
				
			||||||
		t.Errorf("register callback with order")
 | 
							t.Errorf("register callback with order")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var callback2 = &callback{processors: []*callback_processor{}}
 | 
						var callback2 = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	callback2.Delete().Before("after_create1").After("before_create1").Register("create", create)
 | 
						callback2.Delete().Before("after_create1").After("before_create1").Register("create", create)
 | 
				
			||||||
	callback2.Delete().Before("create").Register("before_create1", before_create1)
 | 
						callback2.Delete().Before("create").Register("before_create1", beforeCreate1)
 | 
				
			||||||
	callback2.Delete().After("before_create1").Register("before_create2", before_create2)
 | 
						callback2.Delete().After("before_create1").Register("before_create2", beforeCreate2)
 | 
				
			||||||
	callback2.Delete().Register("after_create1", after_create1)
 | 
						callback2.Delete().Register("after_create1", afterCreate1)
 | 
				
			||||||
	callback2.Delete().After("after_create1").Register("after_create2", after_create2)
 | 
						callback2.Delete().After("after_create1").Register("after_create2", afterCreate2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !equalFuncs(callback2.deletes, []string{"before_create1", "before_create2", "create", "after_create1", "after_create2"}) {
 | 
						if !equalFuncs(callback2.deletes, []string{"beforeCreate1", "beforeCreate2", "create", "afterCreate1", "afterCreate2"}) {
 | 
				
			||||||
		t.Errorf("register callback with order")
 | 
							t.Errorf("register callback with order")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func replace_create(s *Scope) {}
 | 
					func replaceCreate(s *Scope) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestReplaceCallback(t *testing.T) {
 | 
					func TestReplaceCallback(t *testing.T) {
 | 
				
			||||||
	var callback = &callback{processors: []*callback_processor{}}
 | 
						var callback = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	callback.Create().Before("after_create1").After("before_create1").Register("create", create)
 | 
						callback.Create().Before("after_create1").After("before_create1").Register("create", create)
 | 
				
			||||||
	callback.Create().Register("before_create1", before_create1)
 | 
						callback.Create().Register("before_create1", beforeCreate1)
 | 
				
			||||||
	callback.Create().Register("after_create1", after_create1)
 | 
						callback.Create().Register("after_create1", afterCreate1)
 | 
				
			||||||
	callback.Create().Replace("create", replace_create)
 | 
						callback.Create().Replace("create", replaceCreate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !equalFuncs(callback.creates, []string{"before_create1", "replace_create", "after_create1"}) {
 | 
						if !equalFuncs(callback.creates, []string{"beforeCreate1", "replaceCreate", "afterCreate1"}) {
 | 
				
			||||||
		t.Errorf("replace callback")
 | 
							t.Errorf("replace callback")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRemoveCallback(t *testing.T) {
 | 
					func TestRemoveCallback(t *testing.T) {
 | 
				
			||||||
	var callback = &callback{processors: []*callback_processor{}}
 | 
						var callback = &callback{processors: []*callbackProcessor{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	callback.Create().Before("after_create1").After("before_create1").Register("create", create)
 | 
						callback.Create().Before("after_create1").After("before_create1").Register("create", create)
 | 
				
			||||||
	callback.Create().Register("before_create1", before_create1)
 | 
						callback.Create().Register("before_create1", beforeCreate1)
 | 
				
			||||||
	callback.Create().Register("after_create1", after_create1)
 | 
						callback.Create().Register("after_create1", afterCreate1)
 | 
				
			||||||
	callback.Create().Remove("create")
 | 
						callback.Create().Remove("create")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !equalFuncs(callback.creates, []string{"before_create1", "after_create1"}) {
 | 
						if !equalFuncs(callback.creates, []string{"beforeCreate1", "afterCreate1"}) {
 | 
				
			||||||
		t.Errorf("remove callback")
 | 
							t.Errorf("remove callback")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@ func (s *commonDialect) HasTop() bool {
 | 
				
			|||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *commonDialect) SqlTag(value reflect.Value, size int) string {
 | 
					func (s *commonDialect) SqlTag(value reflect.Value, size int) string {
 | 
				
			||||||
	switch value.Kind() {
 | 
						switch value.Kind() {
 | 
				
			||||||
	case reflect.Bool:
 | 
						case reflect.Bool:
 | 
				
			||||||
		return "BOOLEAN"
 | 
							return "BOOLEAN"
 | 
				
			||||||
@ -33,9 +33,8 @@ func (d *commonDialect) SqlTag(value reflect.Value, size int) string {
 | 
				
			|||||||
	case reflect.String:
 | 
						case reflect.String:
 | 
				
			||||||
		if size > 0 && size < 65532 {
 | 
							if size > 0 && size < 65532 {
 | 
				
			||||||
			return fmt.Sprintf("VARCHAR(%d)", size)
 | 
								return fmt.Sprintf("VARCHAR(%d)", size)
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return "VARCHAR(65532)"
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return "VARCHAR(65532)"
 | 
				
			||||||
	case reflect.Struct:
 | 
						case reflect.Struct:
 | 
				
			||||||
		if value.Type() == timeType {
 | 
							if value.Type() == timeType {
 | 
				
			||||||
			return "TIMESTAMP"
 | 
								return "TIMESTAMP"
 | 
				
			||||||
@ -44,21 +43,20 @@ func (d *commonDialect) SqlTag(value reflect.Value, size int) string {
 | 
				
			|||||||
		if _, ok := value.Interface().([]byte); ok {
 | 
							if _, ok := value.Interface().([]byte); ok {
 | 
				
			||||||
			if size > 0 && size < 65532 {
 | 
								if size > 0 && size < 65532 {
 | 
				
			||||||
				return fmt.Sprintf("BINARY(%d)", size)
 | 
									return fmt.Sprintf("BINARY(%d)", size)
 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				return "BINARY(65532)"
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								return "BINARY(65532)"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	panic(fmt.Sprintf("invalid sql type %s (%s) for commonDialect", value.Type().Name(), value.Kind().String()))
 | 
						panic(fmt.Sprintf("invalid sql type %s (%s) for commonDialect", value.Type().Name(), value.Kind().String()))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *commonDialect) PrimaryKeyTag(value reflect.Value, size int) string {
 | 
					func (s *commonDialect) PrimaryKeyTag(value reflect.Value, size int) string {
 | 
				
			||||||
	suffix_str := " NOT NULL PRIMARY KEY"
 | 
						suffix := " NOT NULL PRIMARY KEY"
 | 
				
			||||||
	switch value.Kind() {
 | 
						switch value.Kind() {
 | 
				
			||||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
 | 
						case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
 | 
				
			||||||
		return "INTEGER" + suffix_str
 | 
							return "INTEGER" + suffix
 | 
				
			||||||
	case reflect.Int64, reflect.Uint64:
 | 
						case reflect.Int64, reflect.Uint64:
 | 
				
			||||||
		return "BIGINT" + suffix_str
 | 
							return "BIGINT" + suffix
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("Invalid primary key type")
 | 
							panic("Invalid primary key type")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								errors.go
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								errors.go
									
									
									
									
									
								
							@ -3,9 +3,9 @@ package gorm
 | 
				
			|||||||
import "errors"
 | 
					import "errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	RecordNotFound       = errors.New("Record Not Found")
 | 
						RecordNotFound       = errors.New("record not found")
 | 
				
			||||||
	InvalidSql           = errors.New("Invalid SQL")
 | 
						InvalidSql           = errors.New("invalid sql")
 | 
				
			||||||
	NoNewAttrs           = errors.New("No new Attributes")
 | 
						NoNewAttrs           = errors.New("no new attributes")
 | 
				
			||||||
	NoValidTransaction   = errors.New("No valid transaction")
 | 
						NoValidTransaction   = errors.New("no valid transaction")
 | 
				
			||||||
	CantStartTransaction = errors.New("Can't start transaction")
 | 
						CantStartTransaction = errors.New("can't start transaction")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										3
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								main.go
									
									
									
									
									
								
							@ -265,9 +265,8 @@ func (s *DB) Save(value interface{}) *DB {
 | 
				
			|||||||
	scope := s.clone().NewScope(value)
 | 
						scope := s.clone().NewScope(value)
 | 
				
			||||||
	if scope.PrimaryKeyZero() {
 | 
						if scope.PrimaryKeyZero() {
 | 
				
			||||||
		return scope.callCallbacks(s.parent.callback.creates).db
 | 
							return scope.callCallbacks(s.parent.callback.creates).db
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return scope.callCallbacks(s.parent.callback.updates).db
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return scope.callCallbacks(s.parent.callback.updates).db
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *DB) Create(value interface{}) *DB {
 | 
					func (s *DB) Create(value interface{}) *DB {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										16
									
								
								main_test.go
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								main_test.go
									
									
									
									
									
								
							@ -588,10 +588,10 @@ func BenchmarkGorm(b *testing.B) {
 | 
				
			|||||||
func BenchmarkRawSql(b *testing.B) {
 | 
					func BenchmarkRawSql(b *testing.B) {
 | 
				
			||||||
	DB, _ := sql.Open("postgres", "user=gorm DB.ame=gorm sslmode=disable")
 | 
						DB, _ := sql.Open("postgres", "user=gorm DB.ame=gorm sslmode=disable")
 | 
				
			||||||
	DB.SetMaxIdleConns(10)
 | 
						DB.SetMaxIdleConns(10)
 | 
				
			||||||
	insert_sql := "INSERT INTO emails (user_id,email,user_agent,registered_at,created_at,updated_at) VALUES ($1,$2,$3,$4,$5,$6) RETURNING id"
 | 
						insertSql := "INSERT INTO emails (user_id,email,user_agent,registered_at,created_at,updated_at) VALUES ($1,$2,$3,$4,$5,$6) RETURNING id"
 | 
				
			||||||
	query_sql := "SELECT * FROM emails WHERE email = $1 ORDER BY id LIMIT 1"
 | 
						querySql := "SELECT * FROM emails WHERE email = $1 ORDER BY id LIMIT 1"
 | 
				
			||||||
	update_sql := "UPDATE emails SET email = $1, updated_at = $2 WHERE id = $3"
 | 
						updateSql := "UPDATE emails SET email = $1, updated_at = $2 WHERE id = $3"
 | 
				
			||||||
	delete_sql := "DELETE FROM orders WHERE id = $1"
 | 
						deleteSql := "DELETE FROM orders WHERE id = $1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b.N = 2000
 | 
						b.N = 2000
 | 
				
			||||||
	for x := 0; x < b.N; x++ {
 | 
						for x := 0; x < b.N; x++ {
 | 
				
			||||||
@ -599,13 +599,13 @@ func BenchmarkRawSql(b *testing.B) {
 | 
				
			|||||||
		e := strconv.Itoa(x) + "benchmark@example.org"
 | 
							e := strconv.Itoa(x) + "benchmark@example.org"
 | 
				
			||||||
		email := BigEmail{Email: e, UserAgent: "pc", RegisteredAt: time.Now()}
 | 
							email := BigEmail{Email: e, UserAgent: "pc", RegisteredAt: time.Now()}
 | 
				
			||||||
		// Insert
 | 
							// Insert
 | 
				
			||||||
		DB.QueryRow(insert_sql, email.UserId, email.Email, email.UserAgent, email.RegisteredAt, time.Now(), time.Now()).Scan(&id)
 | 
							DB.QueryRow(insertSql, email.UserId, email.Email, email.UserAgent, email.RegisteredAt, time.Now(), time.Now()).Scan(&id)
 | 
				
			||||||
		// Query
 | 
							// Query
 | 
				
			||||||
		rows, _ := DB.Query(query_sql, email.Email)
 | 
							rows, _ := DB.Query(querySql, email.Email)
 | 
				
			||||||
		rows.Close()
 | 
							rows.Close()
 | 
				
			||||||
		// Update
 | 
							// Update
 | 
				
			||||||
		DB.Exec(update_sql, "new-"+e, time.Now(), id)
 | 
							DB.Exec(updateSql, "new-"+e, time.Now(), id)
 | 
				
			||||||
		// Delete
 | 
							// Delete
 | 
				
			||||||
		DB.Exec(delete_sql, id)
 | 
							DB.Exec(deleteSql, id)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								mssql.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								mssql.go
									
									
									
									
									
								
							@ -20,7 +20,7 @@ func (s *mssql) HasTop() bool {
 | 
				
			|||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *mssql) SqlTag(value reflect.Value, size int) string {
 | 
					func (s *mssql) SqlTag(value reflect.Value, size int) string {
 | 
				
			||||||
	switch value.Kind() {
 | 
						switch value.Kind() {
 | 
				
			||||||
	case reflect.Bool:
 | 
						case reflect.Bool:
 | 
				
			||||||
		return "bit"
 | 
							return "bit"
 | 
				
			||||||
@ -33,9 +33,8 @@ func (d *mssql) SqlTag(value reflect.Value, size int) string {
 | 
				
			|||||||
	case reflect.String:
 | 
						case reflect.String:
 | 
				
			||||||
		if size > 0 && size < 65532 {
 | 
							if size > 0 && size < 65532 {
 | 
				
			||||||
			return fmt.Sprintf("nvarchar(%d)", size)
 | 
								return fmt.Sprintf("nvarchar(%d)", size)
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return "text"
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return "text"
 | 
				
			||||||
	case reflect.Struct:
 | 
						case reflect.Struct:
 | 
				
			||||||
		if value.Type() == timeType {
 | 
							if value.Type() == timeType {
 | 
				
			||||||
			return "datetime2"
 | 
								return "datetime2"
 | 
				
			||||||
@ -44,21 +43,20 @@ func (d *mssql) SqlTag(value reflect.Value, size int) string {
 | 
				
			|||||||
		if _, ok := value.Interface().([]byte); ok {
 | 
							if _, ok := value.Interface().([]byte); ok {
 | 
				
			||||||
			if size > 0 && size < 65532 {
 | 
								if size > 0 && size < 65532 {
 | 
				
			||||||
				return fmt.Sprintf("varchar(%d)", size)
 | 
									return fmt.Sprintf("varchar(%d)", size)
 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				return "text"
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								return "text"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	panic(fmt.Sprintf("invalid sql type %s (%s) for mssql", value.Type().Name(), value.Kind().String()))
 | 
						panic(fmt.Sprintf("invalid sql type %s (%s) for mssql", value.Type().Name(), value.Kind().String()))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *mssql) PrimaryKeyTag(value reflect.Value, size int) string {
 | 
					func (s *mssql) PrimaryKeyTag(value reflect.Value, size int) string {
 | 
				
			||||||
	suffix_str := " IDENTITY(1,1) PRIMARY KEY"
 | 
						suffix := " IDENTITY(1,1) PRIMARY KEY"
 | 
				
			||||||
	switch value.Kind() {
 | 
						switch value.Kind() {
 | 
				
			||||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
 | 
						case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
 | 
				
			||||||
		return "int" + suffix_str
 | 
							return "int" + suffix
 | 
				
			||||||
	case reflect.Int64, reflect.Uint64:
 | 
						case reflect.Int64, reflect.Uint64:
 | 
				
			||||||
		return "bigint" + suffix_str
 | 
							return "bigint" + suffix
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("Invalid primary key type")
 | 
							panic("Invalid primary key type")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								mysql.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								mysql.go
									
									
									
									
									
								
							@ -20,7 +20,7 @@ func (s *mysql) HasTop() bool {
 | 
				
			|||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *mysql) SqlTag(value reflect.Value, size int) string {
 | 
					func (s *mysql) SqlTag(value reflect.Value, size int) string {
 | 
				
			||||||
	switch value.Kind() {
 | 
						switch value.Kind() {
 | 
				
			||||||
	case reflect.Bool:
 | 
						case reflect.Bool:
 | 
				
			||||||
		return "boolean"
 | 
							return "boolean"
 | 
				
			||||||
@ -33,9 +33,8 @@ func (d *mysql) SqlTag(value reflect.Value, size int) string {
 | 
				
			|||||||
	case reflect.String:
 | 
						case reflect.String:
 | 
				
			||||||
		if size > 0 && size < 65532 {
 | 
							if size > 0 && size < 65532 {
 | 
				
			||||||
			return fmt.Sprintf("varchar(%d)", size)
 | 
								return fmt.Sprintf("varchar(%d)", size)
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return "longtext"
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return "longtext"
 | 
				
			||||||
	case reflect.Struct:
 | 
						case reflect.Struct:
 | 
				
			||||||
		if value.Type() == timeType {
 | 
							if value.Type() == timeType {
 | 
				
			||||||
			return "timestamp NULL"
 | 
								return "timestamp NULL"
 | 
				
			||||||
@ -44,21 +43,20 @@ func (d *mysql) SqlTag(value reflect.Value, size int) string {
 | 
				
			|||||||
		if _, ok := value.Interface().([]byte); ok {
 | 
							if _, ok := value.Interface().([]byte); ok {
 | 
				
			||||||
			if size > 0 && size < 65532 {
 | 
								if size > 0 && size < 65532 {
 | 
				
			||||||
				return fmt.Sprintf("varbinary(%d)", size)
 | 
									return fmt.Sprintf("varbinary(%d)", size)
 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				return "longblob"
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								return "longblob"
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	panic(fmt.Sprintf("invalid sql type %s (%s) for mysql", value.Type().Name(), value.Kind().String()))
 | 
						panic(fmt.Sprintf("invalid sql type %s (%s) for mysql", value.Type().Name(), value.Kind().String()))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *mysql) PrimaryKeyTag(value reflect.Value, size int) string {
 | 
					func (s *mysql) PrimaryKeyTag(value reflect.Value, size int) string {
 | 
				
			||||||
	suffix_str := " NOT NULL AUTO_INCREMENT PRIMARY KEY"
 | 
						suffix := " NOT NULL AUTO_INCREMENT PRIMARY KEY"
 | 
				
			||||||
	switch value.Kind() {
 | 
						switch value.Kind() {
 | 
				
			||||||
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
 | 
						case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uintptr:
 | 
				
			||||||
		return "int" + suffix_str
 | 
							return "int" + suffix
 | 
				
			||||||
	case reflect.Int64, reflect.Uint64:
 | 
						case reflect.Int64, reflect.Uint64:
 | 
				
			||||||
		return "bigint" + suffix_str
 | 
							return "bigint" + suffix
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		panic("Invalid primary key type")
 | 
							panic("Invalid primary key type")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@ func (s *postgres) HasTop() bool {
 | 
				
			|||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *postgres) SqlTag(value reflect.Value, size int) string {
 | 
					func (s *postgres) SqlTag(value reflect.Value, size int) string {
 | 
				
			||||||
	switch value.Kind() {
 | 
						switch value.Kind() {
 | 
				
			||||||
	case reflect.Bool:
 | 
						case reflect.Bool:
 | 
				
			||||||
		return "boolean"
 | 
							return "boolean"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										91
									
								
								scope.go
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								scope.go
									
									
									
									
									
								
							@ -41,7 +41,7 @@ func (db *DB) NewScope(value interface{}) *Scope {
 | 
				
			|||||||
func (scope *Scope) NeedPtr() *Scope {
 | 
					func (scope *Scope) NeedPtr() *Scope {
 | 
				
			||||||
	reflectKind := reflect.ValueOf(scope.Value).Kind()
 | 
						reflectKind := reflect.ValueOf(scope.Value).Kind()
 | 
				
			||||||
	if !((reflectKind == reflect.Invalid) || (reflectKind == reflect.Ptr)) {
 | 
						if !((reflectKind == reflect.Invalid) || (reflectKind == reflect.Ptr)) {
 | 
				
			||||||
		err := errors.New(fmt.Sprintf("%v %v\n", fileWithLineNum(), "using unaddressable value"))
 | 
							err := fmt.Errorf("%v %v\n", fileWithLineNum(), "using unaddressable value")
 | 
				
			||||||
		scope.Err(err)
 | 
							scope.Err(err)
 | 
				
			||||||
		fmt.Printf(err.Error())
 | 
							fmt.Printf(err.Error())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -125,9 +125,8 @@ func (scope *Scope) PrimaryKeyField() *Field {
 | 
				
			|||||||
func (scope *Scope) PrimaryKey() string {
 | 
					func (scope *Scope) PrimaryKey() string {
 | 
				
			||||||
	if field := scope.PrimaryKeyField(); field != nil {
 | 
						if field := scope.PrimaryKeyField(); field != nil {
 | 
				
			||||||
		return field.DBName
 | 
							return field.DBName
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PrimaryKeyZero check the primary key is blank or not
 | 
					// PrimaryKeyZero check the primary key is blank or not
 | 
				
			||||||
@ -139,9 +138,8 @@ func (scope *Scope) PrimaryKeyZero() bool {
 | 
				
			|||||||
func (scope *Scope) PrimaryKeyValue() interface{} {
 | 
					func (scope *Scope) PrimaryKeyValue() interface{} {
 | 
				
			||||||
	if field := scope.PrimaryKeyField(); field != nil {
 | 
						if field := scope.PrimaryKeyField(); field != nil {
 | 
				
			||||||
		return field.Field.Interface()
 | 
							return field.Field.Interface()
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return 0
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HasColumn to check if has column
 | 
					// HasColumn to check if has column
 | 
				
			||||||
@ -207,7 +205,7 @@ func (scope *Scope) CallMethod(name string) {
 | 
				
			|||||||
			case func(s *DB) error:
 | 
								case func(s *DB) error:
 | 
				
			||||||
				scope.Err(f(scope.db.New()))
 | 
									scope.Err(f(scope.db.New()))
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				scope.Err(errors.New(fmt.Sprintf("unsupported function %v", name)))
 | 
									scope.Err(fmt.Errorf("unsupported function %v", name))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -234,53 +232,54 @@ var pluralMapValues = []string{"ches", "sses", "shes", "days", "ies", "xes", "${
 | 
				
			|||||||
func (scope *Scope) TableName() string {
 | 
					func (scope *Scope) TableName() string {
 | 
				
			||||||
	if scope.Search != nil && len(scope.Search.TableName) > 0 {
 | 
						if scope.Search != nil && len(scope.Search.TableName) > 0 {
 | 
				
			||||||
		return scope.Search.TableName
 | 
							return scope.Search.TableName
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if scope.Value == nil {
 | 
					 | 
				
			||||||
			scope.Err(errors.New("can't get table name"))
 | 
					 | 
				
			||||||
			return ""
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		data := scope.IndirectValue()
 | 
					 | 
				
			||||||
		if data.Kind() == reflect.Slice {
 | 
					 | 
				
			||||||
			elem := data.Type().Elem()
 | 
					 | 
				
			||||||
			if elem.Kind() == reflect.Ptr {
 | 
					 | 
				
			||||||
				elem = elem.Elem()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			data = reflect.New(elem).Elem()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if fm := data.MethodByName("TableName"); fm.IsValid() {
 | 
					 | 
				
			||||||
			if v := fm.Call([]reflect.Value{}); len(v) > 0 {
 | 
					 | 
				
			||||||
				if result, ok := v[0].Interface().(string); ok {
 | 
					 | 
				
			||||||
					return result
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		str := ToSnake(data.Type().Name())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		if scope.db == nil || !scope.db.parent.singularTable {
 | 
					 | 
				
			||||||
			for index, reg := range pluralMapKeys {
 | 
					 | 
				
			||||||
				if reg.MatchString(str) {
 | 
					 | 
				
			||||||
					return reg.ReplaceAllString(str, pluralMapValues[index])
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return str
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if scope.Value == nil {
 | 
				
			||||||
 | 
							scope.Err(errors.New("can't get table name"))
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data := scope.IndirectValue()
 | 
				
			||||||
 | 
						if data.Kind() == reflect.Slice {
 | 
				
			||||||
 | 
							elem := data.Type().Elem()
 | 
				
			||||||
 | 
							if elem.Kind() == reflect.Ptr {
 | 
				
			||||||
 | 
								elem = elem.Elem()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							data = reflect.New(elem).Elem()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if fm := data.MethodByName("TableName"); fm.IsValid() {
 | 
				
			||||||
 | 
							if v := fm.Call([]reflect.Value{}); len(v) > 0 {
 | 
				
			||||||
 | 
								if result, ok := v[0].Interface().(string); ok {
 | 
				
			||||||
 | 
									return result
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						str := ToSnake(data.Type().Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if scope.db == nil || !scope.db.parent.singularTable {
 | 
				
			||||||
 | 
							for index, reg := range pluralMapKeys {
 | 
				
			||||||
 | 
								if reg.MatchString(str) {
 | 
				
			||||||
 | 
									return reg.ReplaceAllString(str, pluralMapValues[index])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return str
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (scope *Scope) QuotedTableName() string {
 | 
					func (scope *Scope) QuotedTableName() string {
 | 
				
			||||||
	if scope.Search != nil && len(scope.Search.TableName) > 0 {
 | 
						if scope.Search != nil && len(scope.Search.TableName) > 0 {
 | 
				
			||||||
		return scope.Search.TableName
 | 
							return scope.Search.TableName
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		keys := strings.Split(scope.TableName(), ".")
 | 
					 | 
				
			||||||
		for i, v := range keys {
 | 
					 | 
				
			||||||
			keys[i] = scope.Quote(v)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return strings.Join(keys, ".")
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						keys := strings.Split(scope.TableName(), ".")
 | 
				
			||||||
 | 
						for i, v := range keys {
 | 
				
			||||||
 | 
							keys[i] = scope.Quote(v)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return strings.Join(keys, ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CombinedConditionSql get combined condition sql
 | 
					// CombinedConditionSql get combined condition sql
 | 
				
			||||||
 | 
				
			|||||||
@ -215,87 +215,80 @@ func (scope *Scope) whereSql() (sql string) {
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) selectSql() string {
 | 
					func (scope *Scope) selectSql() string {
 | 
				
			||||||
	if len(s.Search.Selects) == 0 {
 | 
						if len(scope.Search.Selects) == 0 {
 | 
				
			||||||
		return "*"
 | 
							return "*"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var selectQueries []string
 | 
						var selectQueries []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, clause := range s.Search.Selects {
 | 
						for _, clause := range scope.Search.Selects {
 | 
				
			||||||
		selectQueries = append(selectQueries, s.buildSelectQuery(clause))
 | 
							selectQueries = append(selectQueries, scope.buildSelectQuery(clause))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return strings.Join(selectQueries, ", ")
 | 
						return strings.Join(selectQueries, ", ")
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) orderSql() string {
 | 
					func (scope *Scope) orderSql() string {
 | 
				
			||||||
	if len(s.Search.Orders) == 0 {
 | 
						if len(scope.Search.Orders) == 0 {
 | 
				
			||||||
		return ""
 | 
							return ""
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return " ORDER BY " + strings.Join(s.Search.Orders, ",")
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return " ORDER BY " + strings.Join(scope.Search.Orders, ",")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) limitSql() string {
 | 
					func (scope *Scope) limitSql() string {
 | 
				
			||||||
	if !s.Dialect().HasTop() {
 | 
						if !scope.Dialect().HasTop() {
 | 
				
			||||||
		if len(s.Search.Limit) == 0 {
 | 
							if len(scope.Search.Limit) == 0 {
 | 
				
			||||||
			return ""
 | 
								return ""
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return " LIMIT " + s.Search.Limit
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
							return " LIMIT " + scope.Search.Limit
 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) topSql() string {
 | 
					func (scope *Scope) topSql() string {
 | 
				
			||||||
	if s.Dialect().HasTop() && len(s.Search.Offset) == 0 {
 | 
						if scope.Dialect().HasTop() && len(scope.Search.Offset) == 0 {
 | 
				
			||||||
		if len(s.Search.Limit) == 0 {
 | 
							if len(scope.Search.Limit) == 0 {
 | 
				
			||||||
			return ""
 | 
								return ""
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return " TOP(" + s.Search.Limit + ")"
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
							return " TOP(" + scope.Search.Limit + ")"
 | 
				
			||||||
		return ""
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) offsetSql() string {
 | 
					func (scope *Scope) offsetSql() string {
 | 
				
			||||||
	if len(s.Search.Offset) == 0 {
 | 
						if len(scope.Search.Offset) == 0 {
 | 
				
			||||||
		return ""
 | 
							return ""
 | 
				
			||||||
	} else {
 | 
						}
 | 
				
			||||||
		if s.Dialect().HasTop() {
 | 
					
 | 
				
			||||||
			sql := " OFFSET " + s.Search.Offset + " ROW "
 | 
						if scope.Dialect().HasTop() {
 | 
				
			||||||
			if len(s.Search.Limit) > 0 {
 | 
							sql := " OFFSET " + scope.Search.Offset + " ROW "
 | 
				
			||||||
				sql += "FETCH NEXT " + s.Search.Limit + " ROWS ONLY"
 | 
							if len(scope.Search.Limit) > 0 {
 | 
				
			||||||
			}
 | 
								sql += "FETCH NEXT " + scope.Search.Limit + " ROWS ONLY"
 | 
				
			||||||
			return sql
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return " OFFSET " + s.Search.Offset
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return sql
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return " OFFSET " + scope.Search.Offset
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) groupSql() string {
 | 
					func (scope *Scope) groupSql() string {
 | 
				
			||||||
	if len(s.Search.Group) == 0 {
 | 
						if len(scope.Search.Group) == 0 {
 | 
				
			||||||
		return ""
 | 
							return ""
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return " GROUP BY " + s.Search.Group
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return " GROUP BY " + scope.Search.Group
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) havingSql() string {
 | 
					func (scope *Scope) havingSql() string {
 | 
				
			||||||
	if s.Search.HavingCondition == nil {
 | 
						if scope.Search.HavingCondition == nil {
 | 
				
			||||||
		return ""
 | 
							return ""
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return " HAVING " + s.buildWhereCondition(s.Search.HavingCondition)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						return " HAVING " + scope.buildWhereCondition(scope.Search.HavingCondition)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Scope) joinsSql() string {
 | 
					func (scope *Scope) joinsSql() string {
 | 
				
			||||||
	return s.Search.Joins + " "
 | 
						return scope.Search.Joins + " "
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (scope *Scope) prepareQuerySql() {
 | 
					func (scope *Scope) prepareQuerySql() {
 | 
				
			||||||
@ -479,9 +472,9 @@ func (scope *Scope) typeName() string {
 | 
				
			|||||||
	value := scope.IndirectValue()
 | 
						value := scope.IndirectValue()
 | 
				
			||||||
	if value.Kind() == reflect.Slice {
 | 
						if value.Kind() == reflect.Slice {
 | 
				
			||||||
		return value.Type().Elem().Name()
 | 
							return value.Type().Elem().Name()
 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return value.Type().Name()
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return value.Type().Name()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (scope *Scope) related(value interface{}, foreignKeys ...string) *Scope {
 | 
					func (scope *Scope) related(value interface{}, foreignKeys ...string) *Scope {
 | 
				
			||||||
@ -634,9 +627,9 @@ func (scope *Scope) addIndex(unique bool, indexName string, column ...string) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (scope *Scope) addForeignKey(field string, dest string, onDelete string, onUpdate string) {
 | 
					func (scope *Scope) addForeignKey(field string, dest string, onDelete string, onUpdate string) {
 | 
				
			||||||
	var table string = scope.TableName()
 | 
						var table = scope.TableName()
 | 
				
			||||||
	var keyName string = fmt.Sprintf("%s_%s_foreign", table, field)
 | 
						var keyName = fmt.Sprintf("%s_%s_foreign", table, field)
 | 
				
			||||||
	var query string = `
 | 
						var query = `
 | 
				
			||||||
		ALTER TABLE %s
 | 
							ALTER TABLE %s
 | 
				
			||||||
		ADD CONSTRAINT %s
 | 
							ADD CONSTRAINT %s
 | 
				
			||||||
		FOREIGN KEY (%s)
 | 
							FOREIGN KEY (%s)
 | 
				
			||||||
 | 
				
			|||||||
@ -32,9 +32,8 @@ func (s *sqlite3) SqlTag(value reflect.Value, size int) string {
 | 
				
			|||||||
	case reflect.String:
 | 
						case reflect.String:
 | 
				
			||||||
		if size > 0 && size < 65532 {
 | 
							if size > 0 && size < 65532 {
 | 
				
			||||||
			return fmt.Sprintf("varchar(%d)", size)
 | 
								return fmt.Sprintf("varchar(%d)", size)
 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return "text"
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							return "text"
 | 
				
			||||||
	case reflect.Struct:
 | 
						case reflect.Struct:
 | 
				
			||||||
		if value.Type() == timeType {
 | 
							if value.Type() == timeType {
 | 
				
			||||||
			return "datetime"
 | 
								return "datetime"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								utils.go
									
									
									
									
									
								
							@ -34,7 +34,7 @@ func FieldValueByName(name string, value interface{}) (i interface{}, err error)
 | 
				
			|||||||
		if field := data.FieldByName(name); field.IsValid() {
 | 
							if field := data.FieldByName(name); field.IsValid() {
 | 
				
			||||||
			i = field.Interface()
 | 
								i = field.Interface()
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return nil, errors.New(fmt.Sprintf("struct has no field with name %s", name))
 | 
								return nil, fmt.Errorf("struct has no field with name %s", name)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return nil, errors.New("value must be of kind struct")
 | 
							return nil, errors.New("value must be of kind struct")
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user