forked from mirror/gorm
Use channel to make gorm faster
This commit is contained in:
parent
88917aa2ef
commit
bf1db1534e
5
field.go
5
field.go
|
@ -13,6 +13,7 @@ type Field struct {
|
|||
Value interface{}
|
||||
model *Model
|
||||
dbName string
|
||||
isBlank bool
|
||||
isPrimaryKey bool
|
||||
autoCreateTime bool
|
||||
autoUpdateTime bool
|
||||
|
@ -23,8 +24,8 @@ type Field struct {
|
|||
structField reflect.StructField
|
||||
}
|
||||
|
||||
func (f *Field) isBlank() bool {
|
||||
return isBlank(f.reflectValue)
|
||||
func (f *Field) parseBlank() {
|
||||
f.isBlank = isBlank(f.reflectValue)
|
||||
}
|
||||
|
||||
func (f *Field) isScanner() bool {
|
||||
|
|
|
@ -1365,7 +1365,7 @@ func TestQueryChain(t *testing.T) {
|
|||
}
|
||||
|
||||
func BenchmarkGorm(b *testing.B) {
|
||||
b.N = 5000
|
||||
b.N = 2000
|
||||
for x := 0; x < b.N; x++ {
|
||||
e := strconv.Itoa(x) + "benchmark@example.org"
|
||||
email := BigEmail{Email: e, UserAgent: "pc", RegisteredAt: time.Now()}
|
||||
|
@ -1388,7 +1388,7 @@ func BenchmarkRawSql(b *testing.B) {
|
|||
update_sql := "UPDATE emails SET email = $1, updated_at = $2 WHERE id = $3"
|
||||
delete_sql := "DELETE FROM orders WHERE id = $1"
|
||||
|
||||
b.N = 5000
|
||||
b.N = 2000
|
||||
for x := 0; x < b.N; x++ {
|
||||
var id int64
|
||||
e := strconv.Itoa(x) + "benchmark@example.org"
|
||||
|
|
3
main.go
3
main.go
|
@ -2,7 +2,6 @@ package gorm
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"github.com/jinzhu/gorm/dialect"
|
||||
)
|
||||
|
||||
|
@ -139,7 +138,7 @@ func (s *DB) Delete(value interface{}) *DB {
|
|||
}
|
||||
|
||||
func (s *DB) Exec(sql string) *DB {
|
||||
return s.do(nil).exec(sql).db
|
||||
return s.clone().do(nil).exec(sql).db
|
||||
}
|
||||
|
||||
func (s *DB) Model(value interface{}) *DB {
|
||||
|
|
74
model.go
74
model.go
|
@ -63,47 +63,65 @@ func getStructs(typ reflect.Type) (fs []reflect.StructField) {
|
|||
}
|
||||
|
||||
func (m *Model) fields(operation string) (fields []*Field) {
|
||||
if len(m._cache_fields[operation]) > 0 {
|
||||
return m._cache_fields[operation]
|
||||
}
|
||||
|
||||
indirect_value := m.reflectData()
|
||||
if !indirect_value.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
for _, filed_struct := range getStructs(indirect_value.Type()) {
|
||||
var field Field
|
||||
field.Name = filed_struct.Name
|
||||
field.dbName = toSnake(filed_struct.Name)
|
||||
field.isPrimaryKey = m.primaryKeyDb() == field.dbName
|
||||
value := indirect_value.FieldByName(filed_struct.Name)
|
||||
field.model = m
|
||||
structs := getStructs(indirect_value.Type())
|
||||
c := make(chan *Field, len(structs))
|
||||
for _, field_struct := range structs {
|
||||
go func(field_struct reflect.StructField, c chan *Field) {
|
||||
var field Field
|
||||
field.Name = field_struct.Name
|
||||
field.dbName = toSnake(field_struct.Name)
|
||||
field.isPrimaryKey = m.primaryKeyDb() == field.dbName
|
||||
value := indirect_value.FieldByName(field_struct.Name)
|
||||
field.model = m
|
||||
|
||||
if time_value, is_time := value.Interface().(time.Time); is_time {
|
||||
field.autoCreateTime = "created_at" == field.dbName
|
||||
field.autoUpdateTime = "updated_at" == field.dbName
|
||||
if time_value, is_time := value.Interface().(time.Time); is_time {
|
||||
field.autoCreateTime = "created_at" == field.dbName
|
||||
field.autoUpdateTime = "updated_at" == field.dbName
|
||||
|
||||
switch operation {
|
||||
case "create":
|
||||
if (field.autoCreateTime || field.autoUpdateTime) && time_value.IsZero() {
|
||||
value.Set(reflect.ValueOf(time.Now()))
|
||||
}
|
||||
case "update":
|
||||
if field.autoUpdateTime {
|
||||
value.Set(reflect.ValueOf(time.Now()))
|
||||
switch operation {
|
||||
case "create":
|
||||
if (field.autoCreateTime || field.autoUpdateTime) && time_value.IsZero() {
|
||||
value.Set(reflect.ValueOf(time.Now()))
|
||||
}
|
||||
case "update":
|
||||
if field.autoUpdateTime {
|
||||
value.Set(reflect.ValueOf(time.Now()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
field.structField = filed_struct
|
||||
field.reflectValue = value
|
||||
field.Value = value.Interface()
|
||||
field.parseAssociation()
|
||||
fields = append(fields, &field)
|
||||
field.structField = field_struct
|
||||
field.reflectValue = value
|
||||
field.Value = value.Interface()
|
||||
field.parseAssociation()
|
||||
field.parseBlank()
|
||||
c <- &field
|
||||
}(field_struct, c)
|
||||
}
|
||||
|
||||
for i := 0; i < len(structs); i++ {
|
||||
fields = append(fields, <-c)
|
||||
}
|
||||
close(c)
|
||||
|
||||
if len(m._cache_fields) == 0 {
|
||||
m._cache_fields = map[string][]*Field{}
|
||||
}
|
||||
m._cache_fields[operation] = fields
|
||||
return
|
||||
}
|
||||
|
||||
func (m *Model) columnsHasValue(operation string) (fields []*Field) {
|
||||
for _, field := range m.fields(operation) {
|
||||
if !field.isBlank() {
|
||||
if !field.isBlank {
|
||||
fields = append(fields, field)
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +254,7 @@ func (m *Model) setValueByColumn(name string, value interface{}, out interface{}
|
|||
|
||||
func (m *Model) beforeAssociations() (fields []*Field) {
|
||||
for _, field := range m.fields("null") {
|
||||
if field.beforeAssociation && !field.isBlank() {
|
||||
if field.beforeAssociation && !field.isBlank {
|
||||
fields = append(fields, field)
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +263,7 @@ func (m *Model) beforeAssociations() (fields []*Field) {
|
|||
|
||||
func (m *Model) afterAssociations() (fields []*Field) {
|
||||
for _, field := range m.fields("null") {
|
||||
if field.afterAssociation && !field.isBlank() {
|
||||
if field.afterAssociation && !field.isBlank {
|
||||
fields = append(fields, field)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue