From 005900baead84d02b276a2179dee10f00d4d251b Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 13 Sep 2017 13:18:22 +0800 Subject: [PATCH] Use created & updated instead BeforeInsert & BeforeUpdate (#2482) * use created & updated instead BeforeInsert & BeforeUpdate * fix vendor checksum * only show generated SQL when development mode * remove extra update column updated_unix * remove trace config --- models/action.go | 8 +- models/admin.go | 7 +- models/attachment.go | 7 +- models/branches.go | 15 +- models/issue.go | 12 +- models/issue_comment.go | 16 +- models/lfs.go | 10 +- models/login_source.go | 15 +- models/models.go | 1 + models/repo.go | 15 +- models/repo_mirror.go | 16 +- models/ssh_key.go | 36 +- models/status.go | 15 +- models/token.go | 14 +- models/twofactor.go | 14 +- models/unit_tests.go | 1 + models/user.go | 12 +- models/webhook.go | 17 +- vendor/github.com/go-xorm/core/type.go | 5 +- vendor/github.com/go-xorm/xorm/README.md | 2 +- vendor/github.com/go-xorm/xorm/cache_lru.go | 34 +- vendor/github.com/go-xorm/xorm/circle.yml | 11 +- vendor/github.com/go-xorm/xorm/convert.go | 12 + .../go-xorm/xorm/dialect_postgres.go | 3 + vendor/github.com/go-xorm/xorm/doc.go | 2 +- vendor/github.com/go-xorm/xorm/engine.go | 37 +- vendor/github.com/go-xorm/xorm/rows.go | 41 +- vendor/github.com/go-xorm/xorm/session.go | 14 +- .../go-xorm/xorm/session_convert.go | 11 +- .../github.com/go-xorm/xorm/session_delete.go | 34 +- .../github.com/go-xorm/xorm/session_exist.go | 16 +- .../github.com/go-xorm/xorm/session_find.go | 46 +-- vendor/github.com/go-xorm/xorm/session_get.go | 57 ++- .../github.com/go-xorm/xorm/session_insert.go | 35 +- .../go-xorm/xorm/session_iterate.go | 4 + .../github.com/go-xorm/xorm/session_query.go | 177 +++++++++ vendor/github.com/go-xorm/xorm/session_raw.go | 360 ++++++------------ .../github.com/go-xorm/xorm/session_schema.go | 25 +- .../github.com/go-xorm/xorm/session_stats.go | 26 +- .../github.com/go-xorm/xorm/session_update.go | 31 +- vendor/github.com/go-xorm/xorm/statement.go | 3 +- .../go-xorm/xorm/test_mssql_cache.sh | 1 + .../go-xorm/xorm/test_mymysql_cache.sh | 1 + .../go-xorm/xorm/test_mysql_cache.sh | 1 + .../go-xorm/xorm/test_postgres_cache.sh | 1 + .../go-xorm/xorm/test_sqlite_cache.sh | 1 + vendor/github.com/go-xorm/xorm/xorm.go | 2 +- vendor/vendor.json | 12 +- 48 files changed, 519 insertions(+), 717 deletions(-) create mode 100644 vendor/github.com/go-xorm/xorm/session_query.go create mode 100755 vendor/github.com/go-xorm/xorm/test_mssql_cache.sh create mode 100755 vendor/github.com/go-xorm/xorm/test_mymysql_cache.sh create mode 100755 vendor/github.com/go-xorm/xorm/test_mysql_cache.sh create mode 100755 vendor/github.com/go-xorm/xorm/test_postgres_cache.sh create mode 100755 vendor/github.com/go-xorm/xorm/test_sqlite_cache.sh diff --git a/models/action.go b/models/action.go index 32b3dbd7b..8793a4a24 100644 --- a/models/action.go +++ b/models/action.go @@ -86,13 +86,7 @@ type Action struct { IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"` Content string `xorm:"TEXT"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` -} - -// BeforeInsert will be invoked by XORM before inserting a record -// representing this object. -func (a *Action) BeforeInsert() { - a.CreatedUnix = time.Now().Unix() + CreatedUnix int64 `xorm:"INDEX created"` } // AfterSet updates the webhook object upon setting a column. diff --git a/models/admin.go b/models/admin.go index f8645202d..eb78f6e86 100644 --- a/models/admin.go +++ b/models/admin.go @@ -29,12 +29,7 @@ type Notice struct { Type NoticeType Description string `xorm:"TEXT"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` -} - -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (n *Notice) BeforeInsert() { - n.CreatedUnix = time.Now().Unix() + CreatedUnix int64 `xorm:"INDEX created"` } // AfterSet is invoked from XORM after setting the value of a field of this object. diff --git a/models/attachment.go b/models/attachment.go index 3b3521bf6..2731ca4b7 100644 --- a/models/attachment.go +++ b/models/attachment.go @@ -28,12 +28,7 @@ type Attachment struct { Name string DownloadCount int64 `xorm:"DEFAULT 0"` Created time.Time `xorm:"-"` - CreatedUnix int64 -} - -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (a *Attachment) BeforeInsert() { - a.CreatedUnix = time.Now().Unix() + CreatedUnix int64 `xorm:"created"` } // AfterSet is invoked from XORM after setting the value of a field of diff --git a/models/branches.go b/models/branches.go index 6115f9c68..4461da006 100644 --- a/models/branches.go +++ b/models/branches.go @@ -22,20 +22,9 @@ type ProtectedBranch struct { BranchName string `xorm:"UNIQUE(s)"` CanPush bool Created time.Time `xorm:"-"` - CreatedUnix int64 + CreatedUnix int64 `xorm:"created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 -} - -// BeforeInsert before protected branch insert create and update time -func (protectBranch *ProtectedBranch) BeforeInsert() { - protectBranch.CreatedUnix = time.Now().Unix() - protectBranch.UpdatedUnix = protectBranch.CreatedUnix -} - -// BeforeUpdate before protected branch update time -func (protectBranch *ProtectedBranch) BeforeUpdate() { - protectBranch.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"updated"` } // GetProtectedBranchByRepoID getting protected branch by repo ID diff --git a/models/issue.go b/models/issue.go index 8723dda91..2b71e0776 100644 --- a/models/issue.go +++ b/models/issue.go @@ -54,23 +54,16 @@ type Issue struct { Deadline time.Time `xorm:"-"` DeadlineUnix int64 `xorm:"INDEX"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"INDEX"` + UpdatedUnix int64 `xorm:"INDEX updated"` Attachments []*Attachment `xorm:"-"` Comments []*Comment `xorm:"-"` } -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (issue *Issue) BeforeInsert() { - issue.CreatedUnix = time.Now().Unix() - issue.UpdatedUnix = issue.CreatedUnix -} - // BeforeUpdate is invoked from XORM before updating this object. func (issue *Issue) BeforeUpdate() { - issue.UpdatedUnix = time.Now().Unix() issue.DeadlineUnix = issue.Deadline.Unix() } @@ -581,7 +574,6 @@ func (issue *Issue) ReadBy(userID int64) error { } func updateIssueCols(e Engine, issue *Issue, cols ...string) error { - cols = append(cols, "updated_unix") if _, err := e.Id(issue.ID).Cols(cols...).Update(issue); err != nil { return err } diff --git a/models/issue_comment.go b/models/issue_comment.go index fe2223e9d..6c9c75b1e 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -99,9 +99,9 @@ type Comment struct { RenderedContent string `xorm:"-"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"INDEX"` + UpdatedUnix int64 `xorm:"INDEX updated"` // Reference issue in commit message CommitSHA string `xorm:"VARCHAR(40)"` @@ -112,18 +112,6 @@ type Comment struct { ShowTag CommentTag `xorm:"-"` } -// BeforeInsert will be invoked by XORM before inserting a record -// representing this object. -func (c *Comment) BeforeInsert() { - c.CreatedUnix = time.Now().Unix() - c.UpdatedUnix = c.CreatedUnix -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (c *Comment) BeforeUpdate() { - c.UpdatedUnix = time.Now().Unix() -} - // AfterSet is invoked from XORM after setting the value of a field of this object. func (c *Comment) AfterSet(colName string, _ xorm.Cell) { var err error diff --git a/models/lfs.go b/models/lfs.go index f908cae1f..be99306d7 100644 --- a/models/lfs.go +++ b/models/lfs.go @@ -2,8 +2,9 @@ package models import ( "errors" - "github.com/go-xorm/xorm" "time" + + "github.com/go-xorm/xorm" ) // LFSMetaObject stores metadata for LFS tracked files. @@ -14,7 +15,7 @@ type LFSMetaObject struct { RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"` Existing bool `xorm:"-"` Created time.Time `xorm:"-"` - CreatedUnix int64 + CreatedUnix int64 `xorm:"created"` } // LFSTokenResponse defines the JSON structure in which the JWT token is stored. @@ -108,11 +109,6 @@ func RemoveLFSMetaObjectByOid(oid string) error { return sess.Commit() } -// BeforeInsert sets the time at which the LFSMetaObject was created. -func (m *LFSMetaObject) BeforeInsert() { - m.CreatedUnix = time.Now().Unix() -} - // AfterSet stores the LFSMetaObject creation time in the database as local time. func (m *LFSMetaObject) AfterSet(colName string, _ xorm.Cell) { switch colName { diff --git a/models/login_source.go b/models/login_source.go index e4dc77714..186a5e051 100644 --- a/models/login_source.go +++ b/models/login_source.go @@ -148,20 +148,9 @@ type LoginSource struct { Cfg core.Conversion `xorm:"TEXT"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"INDEX"` -} - -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (source *LoginSource) BeforeInsert() { - source.CreatedUnix = time.Now().Unix() - source.UpdatedUnix = source.CreatedUnix -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (source *LoginSource) BeforeUpdate() { - source.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"INDEX updated"` } // Cell2Int64 converts a xorm.Cell type to int64, diff --git a/models/models.go b/models/models.go index 0bcb3674d..1e64f70f4 100644 --- a/models/models.go +++ b/models/models.go @@ -241,6 +241,7 @@ func NewTestEngine(x *xorm.Engine) (err error) { x.SetMapper(core.GonicMapper{}) x.SetLogger(log.XORMLogger) + x.ShowSQL(!setting.ProdMode) return x.StoreEngine("InnoDB").Sync2(tables...) } diff --git a/models/repo.go b/models/repo.go index 1cce3854e..a2e63e2af 100644 --- a/models/repo.go +++ b/models/repo.go @@ -211,20 +211,9 @@ type Repository struct { Size int64 `xorm:"NOT NULL DEFAULT 0"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"INDEX"` -} - -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (repo *Repository) BeforeInsert() { - repo.CreatedUnix = time.Now().Unix() - repo.UpdatedUnix = repo.CreatedUnix -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (repo *Repository) BeforeUpdate() { - repo.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"INDEX updated"` } // AfterSet is invoked from XORM after setting the value of a field of this object. diff --git a/models/repo_mirror.go b/models/repo_mirror.go index 458859774..526b7cd02 100644 --- a/models/repo_mirror.go +++ b/models/repo_mirror.go @@ -40,18 +40,26 @@ type Mirror struct { // BeforeInsert will be invoked by XORM before inserting a record func (m *Mirror) BeforeInsert() { - m.UpdatedUnix = time.Now().Unix() - m.NextUpdateUnix = m.NextUpdate.Unix() + if m != nil { + m.UpdatedUnix = time.Now().Unix() + m.NextUpdateUnix = m.NextUpdate.Unix() + } } // BeforeUpdate is invoked from XORM before updating this object. func (m *Mirror) BeforeUpdate() { - m.UpdatedUnix = time.Now().Unix() - m.NextUpdateUnix = m.NextUpdate.Unix() + if m != nil { + m.UpdatedUnix = time.Now().Unix() + m.NextUpdateUnix = m.NextUpdate.Unix() + } } // AfterSet is invoked from XORM after setting the value of a field of this object. func (m *Mirror) AfterSet(colName string, _ xorm.Cell) { + if m == nil { + return + } + var err error switch colName { case "repo_id": diff --git a/models/ssh_key.go b/models/ssh_key.go index 649c50be6..873eab3bf 100644 --- a/models/ssh_key.go +++ b/models/ssh_key.go @@ -55,21 +55,11 @@ type PublicKey struct { Type KeyType `xorm:"NOT NULL DEFAULT 1"` Created time.Time `xorm:"-"` - CreatedUnix int64 + CreatedUnix int64 `xorm:"created"` Updated time.Time `xorm:"-"` // Note: Updated must below Created for AfterSet. - UpdatedUnix int64 - HasRecentActivity bool `xorm:"-"` - HasUsed bool `xorm:"-"` -} - -// BeforeInsert will be invoked by XORM before inserting a record -func (key *PublicKey) BeforeInsert() { - key.CreatedUnix = time.Now().Unix() -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (key *PublicKey) BeforeUpdate() { - key.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"updated"` + HasRecentActivity bool `xorm:"-"` + HasUsed bool `xorm:"-"` } // AfterSet is invoked from XORM after setting the value of a field of this object. @@ -633,21 +623,11 @@ type DeployKey struct { Content string `xorm:"-"` Created time.Time `xorm:"-"` - CreatedUnix int64 + CreatedUnix int64 `xorm:"created"` Updated time.Time `xorm:"-"` // Note: Updated must below Created for AfterSet. - UpdatedUnix int64 - HasRecentActivity bool `xorm:"-"` - HasUsed bool `xorm:"-"` -} - -// BeforeInsert will be invoked by XORM before inserting a record -func (key *DeployKey) BeforeInsert() { - key.CreatedUnix = time.Now().Unix() -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (key *DeployKey) BeforeUpdate() { - key.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"updated"` + HasRecentActivity bool `xorm:"-"` + HasUsed bool `xorm:"-"` } // AfterSet is invoked from XORM after setting the value of a field of this object. diff --git a/models/status.go b/models/status.go index 2ce588bea..e300c763f 100644 --- a/models/status.go +++ b/models/status.go @@ -66,20 +66,9 @@ type CommitStatus struct { CreatorID int64 Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"INDEX"` -} - -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (status *CommitStatus) BeforeInsert() { - status.CreatedUnix = time.Now().Unix() - status.UpdatedUnix = status.CreatedUnix -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (status *CommitStatus) BeforeUpdate() { - status.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"INDEX updated"` } // AfterSet is invoked from XORM after setting the value of a field of diff --git a/models/token.go b/models/token.go index b2e0a28a5..d4b86eb3a 100644 --- a/models/token.go +++ b/models/token.go @@ -21,23 +21,13 @@ type AccessToken struct { Sha1 string `xorm:"UNIQUE VARCHAR(40)"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` // Note: Updated must below Created for AfterSet. - UpdatedUnix int64 `xorm:"INDEX"` + UpdatedUnix int64 `xorm:"INDEX updated"` HasRecentActivity bool `xorm:"-"` HasUsed bool `xorm:"-"` } -// BeforeInsert will be invoked by XORM before inserting a record representing this object. -func (t *AccessToken) BeforeInsert() { - t.CreatedUnix = time.Now().Unix() -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (t *AccessToken) BeforeUpdate() { - t.UpdatedUnix = time.Now().Unix() -} - // AfterSet is invoked from XORM after setting the value of a field of this object. func (t *AccessToken) AfterSet(colName string, _ xorm.Cell) { switch colName { diff --git a/models/twofactor.go b/models/twofactor.go index 4c0d3702d..c983b56a5 100644 --- a/models/twofactor.go +++ b/models/twofactor.go @@ -26,19 +26,9 @@ type TwoFactor struct { ScratchToken string Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` // Note: Updated must below Created for AfterSet. - UpdatedUnix int64 `xorm:"INDEX"` -} - -// BeforeInsert will be invoked by XORM before inserting a record representing this object. -func (t *TwoFactor) BeforeInsert() { - t.CreatedUnix = time.Now().Unix() -} - -// BeforeUpdate is invoked from XORM before updating this object. -func (t *TwoFactor) BeforeUpdate() { - t.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"INDEX updated"` } // AfterSet is invoked from XORM after setting the value of a field of this object. diff --git a/models/unit_tests.go b/models/unit_tests.go index 315627d8e..ce328b579 100644 --- a/models/unit_tests.go +++ b/models/unit_tests.go @@ -28,6 +28,7 @@ func CreateTestEngine(fixturesDir string) error { if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil { return err } + x.ShowSQL(true) return InitFixtures(&testfixtures.SQLite{}, fixturesDir) } diff --git a/models/user.go b/models/user.go index 1e2502ebc..f6d705101 100644 --- a/models/user.go +++ b/models/user.go @@ -94,9 +94,9 @@ type User struct { Salt string `xorm:"VARCHAR(10)"` Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"INDEX"` + UpdatedUnix int64 `xorm:"INDEX updated"` LastLogin time.Time `xorm:"-"` LastLoginUnix int64 `xorm:"INDEX"` @@ -135,18 +135,11 @@ type User struct { DiffViewStyle string `xorm:"NOT NULL DEFAULT ''"` } -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (u *User) BeforeInsert() { - u.CreatedUnix = time.Now().Unix() - u.UpdatedUnix = u.CreatedUnix -} - // BeforeUpdate is invoked from XORM before updating this object. func (u *User) BeforeUpdate() { if u.MaxRepoCreation < -1 { u.MaxRepoCreation = -1 } - u.UpdatedUnix = time.Now().Unix() } // SetLastLogin set time to last login @@ -897,7 +890,6 @@ func UpdateUserCols(u *User, cols ...string) error { u.Website = base.TruncateString(u.Website, 255) u.Description = base.TruncateString(u.Description, 255) - cols = append(cols, "updated_unix") _, err := x.Id(u.ID).Cols(cols...).Update(u) return err } diff --git a/models/webhook.go b/models/webhook.go index fa0c498f3..bc7926c23 100644 --- a/models/webhook.go +++ b/models/webhook.go @@ -107,22 +107,9 @@ type Webhook struct { LastStatus HookStatus // Last delivery status Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"INDEX"` + CreatedUnix int64 `xorm:"INDEX created"` Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"INDEX"` -} - -// BeforeInsert will be invoked by XORM before inserting a record -// representing this object -func (w *Webhook) BeforeInsert() { - w.CreatedUnix = time.Now().Unix() - w.UpdatedUnix = w.CreatedUnix -} - -// BeforeUpdate will be invoked by XORM before updating a record -// representing this object -func (w *Webhook) BeforeUpdate() { - w.UpdatedUnix = time.Now().Unix() + UpdatedUnix int64 `xorm:"INDEX updated"` } // AfterSet updates the webhook object upon setting a column diff --git a/vendor/github.com/go-xorm/core/type.go b/vendor/github.com/go-xorm/core/type.go index 860482251..8010a2220 100644 --- a/vendor/github.com/go-xorm/core/type.go +++ b/vendor/github.com/go-xorm/core/type.go @@ -100,7 +100,8 @@ var ( LongBlob = "LONGBLOB" Bytea = "BYTEA" - Bool = "BOOL" + Bool = "BOOL" + Boolean = "BOOLEAN" Serial = "SERIAL" BigSerial = "BIGSERIAL" @@ -163,7 +164,7 @@ var ( uintTypes = sort.StringSlice{"*uint", "*uint16", "*uint32", "*uint8"} ) -// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparision +// !nashtsai! treat following var as interal const values, these are used for reflect.TypeOf comparison var ( c_EMPTY_STRING string c_BOOL_DEFAULT bool diff --git a/vendor/github.com/go-xorm/xorm/README.md b/vendor/github.com/go-xorm/xorm/README.md index bf3548890..c8c43894c 100644 --- a/vendor/github.com/go-xorm/xorm/README.md +++ b/vendor/github.com/go-xorm/xorm/README.md @@ -34,7 +34,7 @@ Drivers for Go's sql package which currently support database/sql includes: * Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) -* MyMysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv) +* MyMysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/tree/master/godrv) * Postgres: [github.com/lib/pq](https://github.com/lib/pq) diff --git a/vendor/github.com/go-xorm/xorm/cache_lru.go b/vendor/github.com/go-xorm/xorm/cache_lru.go index 4a7450435..c9672cebe 100644 --- a/vendor/github.com/go-xorm/xorm/cache_lru.go +++ b/vendor/github.com/go-xorm/xorm/cache_lru.go @@ -15,13 +15,12 @@ import ( // LRUCacher implments cache object facilities type LRUCacher struct { - idList *list.List - sqlList *list.List - idIndex map[string]map[string]*list.Element - sqlIndex map[string]map[string]*list.Element - store core.CacheStore - mutex sync.Mutex - // maxSize int + idList *list.List + sqlList *list.List + idIndex map[string]map[string]*list.Element + sqlIndex map[string]map[string]*list.Element + store core.CacheStore + mutex sync.Mutex MaxElementSize int Expired time.Duration GcInterval time.Duration @@ -54,8 +53,6 @@ func (m *LRUCacher) RunGC() { // GC check ids lit and sql list to remove all element expired func (m *LRUCacher) GC() { - //fmt.Println("begin gc ...") - //defer fmt.Println("end gc ...") m.mutex.Lock() defer m.mutex.Unlock() var removedNum int @@ -64,12 +61,10 @@ func (m *LRUCacher) GC() { time.Now().Sub(e.Value.(*idNode).lastVisit) > m.Expired { removedNum++ next := e.Next() - //fmt.Println("removing ...", e.Value) node := e.Value.(*idNode) m.delBean(node.tbName, node.id) e = next } else { - //fmt.Printf("removing %d cache nodes ..., left %d\n", removedNum, m.idList.Len()) break } } @@ -80,12 +75,10 @@ func (m *LRUCacher) GC() { time.Now().Sub(e.Value.(*sqlNode).lastVisit) > m.Expired { removedNum++ next := e.Next() - //fmt.Println("removing ...", e.Value) node := e.Value.(*sqlNode) m.delIds(node.tbName, node.sql) e = next } else { - //fmt.Printf("removing %d cache nodes ..., left %d\n", removedNum, m.sqlList.Len()) break } } @@ -116,7 +109,6 @@ func (m *LRUCacher) GetIds(tableName, sql string) interface{} { } m.delIds(tableName, sql) - return nil } @@ -134,7 +126,6 @@ func (m *LRUCacher) GetBean(tableName string, id string) interface{} { // if expired, remove the node and return nil if time.Now().Sub(lastTime) > m.Expired { m.delBean(tableName, id) - //m.clearIds(tableName) return nil } m.idList.MoveToBack(el) @@ -148,7 +139,6 @@ func (m *LRUCacher) GetBean(tableName string, id string) interface{} { // store bean is not exist, then remove memory's index m.delBean(tableName, id) - //m.clearIds(tableName) return nil } @@ -166,8 +156,8 @@ func (m *LRUCacher) clearIds(tableName string) { // ClearIds clears all sql-ids mapping on table tableName from cache func (m *LRUCacher) ClearIds(tableName string) { m.mutex.Lock() - defer m.mutex.Unlock() m.clearIds(tableName) + m.mutex.Unlock() } func (m *LRUCacher) clearBeans(tableName string) { @@ -184,14 +174,13 @@ func (m *LRUCacher) clearBeans(tableName string) { // ClearBeans clears all beans in some table func (m *LRUCacher) ClearBeans(tableName string) { m.mutex.Lock() - defer m.mutex.Unlock() m.clearBeans(tableName) + m.mutex.Unlock() } // PutIds pus ids into table func (m *LRUCacher) PutIds(tableName, sql string, ids interface{}) { m.mutex.Lock() - defer m.mutex.Unlock() if _, ok := m.sqlIndex[tableName]; !ok { m.sqlIndex[tableName] = make(map[string]*list.Element) } @@ -207,12 +196,12 @@ func (m *LRUCacher) PutIds(tableName, sql string, ids interface{}) { node := e.Value.(*sqlNode) m.delIds(node.tbName, node.sql) } + m.mutex.Unlock() } // PutBean puts beans into table func (m *LRUCacher) PutBean(tableName string, id string, obj interface{}) { m.mutex.Lock() - defer m.mutex.Unlock() var el *list.Element var ok bool @@ -229,6 +218,7 @@ func (m *LRUCacher) PutBean(tableName string, id string, obj interface{}) { node := e.Value.(*idNode) m.delBean(node.tbName, node.id) } + m.mutex.Unlock() } func (m *LRUCacher) delIds(tableName, sql string) { @@ -244,8 +234,8 @@ func (m *LRUCacher) delIds(tableName, sql string) { // DelIds deletes ids func (m *LRUCacher) DelIds(tableName, sql string) { m.mutex.Lock() - defer m.mutex.Unlock() m.delIds(tableName, sql) + m.mutex.Unlock() } func (m *LRUCacher) delBean(tableName string, id string) { @@ -261,8 +251,8 @@ func (m *LRUCacher) delBean(tableName string, id string) { // DelBean deletes beans in some table func (m *LRUCacher) DelBean(tableName string, id string) { m.mutex.Lock() - defer m.mutex.Unlock() m.delBean(tableName, id) + m.mutex.Unlock() } type idNode struct { diff --git a/vendor/github.com/go-xorm/xorm/circle.yml b/vendor/github.com/go-xorm/xorm/circle.yml index e81bdb0e3..69fc7164b 100644 --- a/vendor/github.com/go-xorm/xorm/circle.yml +++ b/vendor/github.com/go-xorm/xorm/circle.yml @@ -21,7 +21,16 @@ database: test: override: # './...' is a relative pattern which means all subdirectories - - go test -v -race -db="sqlite3::mysql::mymysql::postgres" -conn_str="./test.db::root:@/xorm_test::xorm_test/root/::dbname=xorm_test sslmode=disable" -coverprofile=coverage.txt -covermode=atomic + - go get -u github.com/wadey/gocovmerge; + - go test -v -race -db="sqlite3" -conn_str="./test.db" -coverprofile=coverage1-1.txt -covermode=atomic + - go test -v -race -db="sqlite3" -conn_str="./test.db" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic + - go test -v -race -db="mysql" -conn_str="root:@/xorm_test" -coverprofile=coverage2-1.txt -covermode=atomic + - go test -v -race -db="mysql" -conn_str="root:@/xorm_test" -cache=true -coverprofile=coverage2-2.txt -covermode=atomic + - go test -v -race -db="mymysql" -conn_str="xorm_test/root/" -coverprofile=coverage3-1.txt -covermode=atomic + - go test -v -race -db="mymysql" -conn_str="xorm_test/root/" -cache=true -coverprofile=coverage3-2.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="dbname=xorm_test sslmode=disable" -coverprofile=coverage4-1.txt -covermode=atomic + - go test -v -race -db="postgres" -conn_str="dbname=xorm_test sslmode=disable" -cache=true -coverprofile=coverage4-2.txt -covermode=atomic + - gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt > coverage.txt - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./sqlite3.sh - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./mysql.sh - cd /home/ubuntu/.go_workspace/src/github.com/go-xorm/tests && ./postgres.sh diff --git a/vendor/github.com/go-xorm/xorm/convert.go b/vendor/github.com/go-xorm/xorm/convert.go index fbd24b5b3..0504bef15 100644 --- a/vendor/github.com/go-xorm/xorm/convert.go +++ b/vendor/github.com/go-xorm/xorm/convert.go @@ -334,3 +334,15 @@ func convertInt(v interface{}) (int64, error) { } return 0, fmt.Errorf("unsupported type: %v", v) } + +func asBool(bs []byte) (bool, error) { + if len(bs) == 0 { + return false, nil + } + if bs[0] == 0x00 { + return false, nil + } else if bs[0] == 0x01 { + return true, nil + } + return strconv.ParseBool(string(bs)) +} diff --git a/vendor/github.com/go-xorm/xorm/dialect_postgres.go b/vendor/github.com/go-xorm/xorm/dialect_postgres.go index 1d4daa279..3f5c526f7 100644 --- a/vendor/github.com/go-xorm/xorm/dialect_postgres.go +++ b/vendor/github.com/go-xorm/xorm/dialect_postgres.go @@ -781,6 +781,9 @@ func (db *postgres) SqlType(c *core.Column) string { case core.TinyInt: res = core.SmallInt return res + case core.Bit: + res = core.Boolean + return res case core.MediumInt, core.Int, core.Integer: if c.IsAutoIncrement { return core.Serial diff --git a/vendor/github.com/go-xorm/xorm/doc.go b/vendor/github.com/go-xorm/xorm/doc.go index bf412bdaa..a687e6947 100644 --- a/vendor/github.com/go-xorm/xorm/doc.go +++ b/vendor/github.com/go-xorm/xorm/doc.go @@ -90,7 +90,7 @@ another is Rows 5. Update one or more records - affected, err := engine.Id(...).Update(&user) + affected, err := engine.ID(...).Update(&user) // UPDATE user SET ... 6. Delete one or more records, Delete MUST has condition diff --git a/vendor/github.com/go-xorm/xorm/engine.go b/vendor/github.com/go-xorm/xorm/engine.go index cfa0933ee..0d34bf962 100644 --- a/vendor/github.com/go-xorm/xorm/engine.go +++ b/vendor/github.com/go-xorm/xorm/engine.go @@ -273,36 +273,6 @@ func (engine *Engine) logSQL(sqlStr string, sqlArgs ...interface{}) { } } -func (engine *Engine) logSQLQueryTime(sqlStr string, args []interface{}, executionBlock func() (*core.Stmt, *core.Rows, error)) (*core.Stmt, *core.Rows, error) { - if engine.showSQL && engine.showExecTime { - b4ExecTime := time.Now() - stmt, res, err := executionBlock() - execDuration := time.Since(b4ExecTime) - if len(args) > 0 { - engine.logger.Infof("[SQL] %s %v - took: %v", sqlStr, args, execDuration) - } else { - engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration) - } - return stmt, res, err - } - return executionBlock() -} - -func (engine *Engine) logSQLExecutionTime(sqlStr string, args []interface{}, executionBlock func() (sql.Result, error)) (sql.Result, error) { - if engine.showSQL && engine.showExecTime { - b4ExecTime := time.Now() - res, err := executionBlock() - execDuration := time.Since(b4ExecTime) - if len(args) > 0 { - engine.logger.Infof("[sql] %s [args] %v - took: %v", sqlStr, args, execDuration) - } else { - engine.logger.Infof("[sql] %s - took: %v", sqlStr, execDuration) - } - return res, err - } - return executionBlock() -} - // Sql provides raw sql input parameter. When you have a complex SQL statement // and cannot use Where, Id, In and etc. Methods to describe, you can use SQL. // @@ -1384,6 +1354,13 @@ func (engine *Engine) QueryString(sqlStr string, args ...interface{}) ([]map[str return session.QueryString(sqlStr, args...) } +// QueryInterface runs a raw sql and return records as []map[string]interface{} +func (engine *Engine) QueryInterface(sqlStr string, args ...interface{}) ([]map[string]interface{}, error) { + session := engine.NewSession() + defer session.Close() + return session.QueryInterface(sqlStr, args...) +} + // Insert one or more records func (engine *Engine) Insert(beans ...interface{}) (int64, error) { session := engine.NewSession() diff --git a/vendor/github.com/go-xorm/xorm/rows.go b/vendor/github.com/go-xorm/xorm/rows.go index 444e3d435..258d9f279 100644 --- a/vendor/github.com/go-xorm/xorm/rows.go +++ b/vendor/github.com/go-xorm/xorm/rows.go @@ -17,7 +17,6 @@ type Rows struct { NoTypeCheck bool session *Session - stmt *core.Stmt rows *core.Rows fields []string beanType reflect.Type @@ -29,8 +28,6 @@ func newRows(session *Session, bean interface{}) (*Rows, error) { rows.session = session rows.beanType = reflect.Indirect(reflect.ValueOf(bean)).Type() - defer rows.session.resetStatement() - var sqlStr string var args []interface{} var err error @@ -53,32 +50,11 @@ func newRows(session *Session, bean interface{}) (*Rows, error) { args = rows.session.statement.RawParams } - for _, filter := range rows.session.engine.dialect.Filters() { - sqlStr = filter.Do(sqlStr, session.engine.dialect, rows.session.statement.RefTable) - } - - rows.session.saveLastSQL(sqlStr, args...) - if rows.session.prepareStmt { - rows.stmt, err = rows.session.DB().Prepare(sqlStr) - if err != nil { - rows.lastError = err - rows.Close() - return nil, err - } - - rows.rows, err = rows.stmt.Query(args...) - if err != nil { - rows.lastError = err - rows.Close() - return nil, err - } - } else { - rows.rows, err = rows.session.DB().Query(sqlStr, args...) - if err != nil { - rows.lastError = err - rows.Close() - return nil, err - } + rows.rows, err = rows.session.queryRows(sqlStr, args...) + if err != nil { + rows.lastError = err + rows.Close() + return nil, err } rows.fields, err = rows.rows.Columns() @@ -142,17 +118,10 @@ func (rows *Rows) Close() error { if rows.rows != nil { rows.lastError = rows.rows.Close() if rows.lastError != nil { - defer rows.stmt.Close() return rows.lastError } } - if rows.stmt != nil { - rows.lastError = rows.stmt.Close() - } } else { - if rows.stmt != nil { - defer rows.stmt.Close() - } if rows.rows != nil { defer rows.rows.Close() } diff --git a/vendor/github.com/go-xorm/xorm/session.go b/vendor/github.com/go-xorm/xorm/session.go index 9d0414027..c69ac9e5c 100644 --- a/vendor/github.com/go-xorm/xorm/session.go +++ b/vendor/github.com/go-xorm/xorm/session.go @@ -303,6 +303,7 @@ func (session *Session) rows2Beans(rows *core.Rows, fields []string, fieldsCount var newValue = newElemFunc(fields) bean := newValue.Interface() dataStruct := rValue(bean) + // handle beforeClosures scanResults, err := session.row2Slice(rows, fields, fieldsCount, bean) if err != nil { @@ -312,7 +313,6 @@ func (session *Session) rows2Beans(rows *core.Rows, fields []string, fieldsCount if err != nil { return err } - err = sliceValueSetFunc(&newValue, pk) if err != nil { return err @@ -631,9 +631,7 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, f // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne // property to be fetched lazily structInter := reflect.New(fieldValue.Type()) - newsession := session.engine.NewSession() - defer newsession.Close() - has, err := newsession.ID(pk).NoCascade().Get(structInter.Interface()) + has, err := session.ID(pk).NoCascade().get(structInter.Interface()) if err != nil { return nil, err } @@ -777,14 +775,6 @@ func (session *Session) slice2Bean(scanResults []interface{}, fields []string, f return pk, nil } -func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) { - for _, filter := range session.engine.dialect.Filters() { - *sqlStr = filter.Do(*sqlStr, session.engine.dialect, session.statement.RefTable) - } - - session.saveLastSQL(*sqlStr, paramStr...) -} - // saveLastSQL stores executed query information func (session *Session) saveLastSQL(sql string, args ...interface{}) { session.lastSQL = sql diff --git a/vendor/github.com/go-xorm/xorm/session_convert.go b/vendor/github.com/go-xorm/xorm/session_convert.go index 85002d27c..f2c949bac 100644 --- a/vendor/github.com/go-xorm/xorm/session_convert.go +++ b/vendor/github.com/go-xorm/xorm/session_convert.go @@ -144,8 +144,7 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, case reflect.String: fieldValue.SetString(string(data)) case reflect.Bool: - d := string(data) - v, err := strconv.ParseBool(d) + v, err := asBool(data) if err != nil { return fmt.Errorf("arg %v as bool: %s", key, err.Error()) } @@ -227,9 +226,7 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne // property to be fetched lazily structInter := reflect.New(fieldValue.Type()) - newsession := session.engine.NewSession() - defer newsession.Close() - has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface()) + has, err := session.ID(pk).NoCascade().get(structInter.Interface()) if err != nil { return err } @@ -510,9 +507,7 @@ func (session *Session) bytes2Value(col *core.Column, fieldValue *reflect.Value, // !nashtsai! TODO for hasOne relationship, it's preferred to use join query for eager fetch // however, also need to consider adding a 'lazy' attribute to xorm tag which allow hasOne // property to be fetched lazily - newsession := session.engine.NewSession() - defer newsession.Close() - has, err := newsession.Id(pk).NoCascade().Get(structInter.Interface()) + has, err := session.ID(pk).NoCascade().get(structInter.Interface()) if err != nil { return err } diff --git a/vendor/github.com/go-xorm/xorm/session_delete.go b/vendor/github.com/go-xorm/xorm/session_delete.go index 9fd7b8aff..1d7d662cd 100644 --- a/vendor/github.com/go-xorm/xorm/session_delete.go +++ b/vendor/github.com/go-xorm/xorm/session_delete.go @@ -12,14 +12,14 @@ import ( "github.com/go-xorm/core" ) -func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error { - if session.statement.RefTable == nil || +func (session *Session) cacheDelete(table *core.Table, tableName, sqlStr string, args ...interface{}) error { + if table == nil || session.tx != nil { return ErrCacheFailed } for _, filter := range session.engine.dialect.Filters() { - sqlStr = filter.Do(sqlStr, session.engine.dialect, session.statement.RefTable) + sqlStr = filter.Do(sqlStr, session.engine.dialect, table) } newsql := session.statement.convertIDSQL(sqlStr) @@ -27,11 +27,11 @@ func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error { return ErrCacheFailed } - cacher := session.engine.getCacher2(session.statement.RefTable) - tableName := session.statement.TableName() + cacher := session.engine.getCacher2(table) + pkColumns := table.PKColumns() ids, err := core.GetCacheSql(cacher, tableName, newsql, args) if err != nil { - resultsSlice, err := session.query(newsql, args...) + resultsSlice, err := session.queryBytes(newsql, args...) if err != nil { return err } @@ -40,7 +40,7 @@ func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error { for _, data := range resultsSlice { var id int64 var pk core.PK = make([]interface{}, 0) - for _, col := range session.statement.RefTable.PKColumns() { + for _, col := range pkColumns { if v, ok := data[col.Name]; !ok { return errors.New("no id") } else if col.SQLType.IsText() { @@ -58,27 +58,23 @@ func (session *Session) cacheDelete(sqlStr string, args ...interface{}) error { ids = append(ids, pk) } } - } /*else { - session.engine.LogDebug("delete cache sql %v", newsql) - cacher.DelIds(tableName, genSqlKey(newsql, args)) - }*/ + } for _, id := range ids { - session.engine.logger.Debug("[cacheDelete] delete cache obj", tableName, id) + session.engine.logger.Debug("[cacheDelete] delete cache obj:", tableName, id) sid, err := id.ToString() if err != nil { return err } cacher.DelBean(tableName, sid) } - session.engine.logger.Debug("[cacheDelete] clear cache sql", tableName) + session.engine.logger.Debug("[cacheDelete] clear cache table:", tableName) cacher.ClearIds(tableName) return nil } // Delete records, bean's non-empty fields are conditions func (session *Session) Delete(bean interface{}) (int64, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -86,7 +82,6 @@ func (session *Session) Delete(bean interface{}) (int64, error) { if err := session.statement.setRefValue(rValue(bean)); err != nil { return 0, err } - var table = session.statement.RefTable // handle before delete processors for _, closure := range session.beforeClosures { @@ -106,7 +101,9 @@ func (session *Session) Delete(bean interface{}) (int64, error) { return 0, ErrNeedDeletedCond } - var tableName = session.engine.Quote(session.statement.TableName()) + var tableNameNoQuote = session.statement.TableName() + var tableName = session.engine.Quote(tableNameNoQuote) + var table = session.statement.RefTable var deleteSQL string if len(condSQL) > 0 { deleteSQL = fmt.Sprintf("DELETE FROM %v WHERE %v", tableName, condSQL) @@ -202,10 +199,11 @@ func (session *Session) Delete(bean interface{}) (int64, error) { }) } - if cacher := session.engine.getCacher2(session.statement.RefTable); cacher != nil && session.statement.UseCache { - session.cacheDelete(deleteSQL, argsForCache...) + if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache { + session.cacheDelete(table, tableNameNoQuote, deleteSQL, argsForCache...) } + session.statement.RefTable = table res, err := session.exec(realSQL, condArgs...) if err != nil { return 0, err diff --git a/vendor/github.com/go-xorm/xorm/session_exist.go b/vendor/github.com/go-xorm/xorm/session_exist.go index 91d1cd601..049c1ddff 100644 --- a/vendor/github.com/go-xorm/xorm/session_exist.go +++ b/vendor/github.com/go-xorm/xorm/session_exist.go @@ -10,12 +10,10 @@ import ( "reflect" "github.com/go-xorm/builder" - "github.com/go-xorm/core" ) // Exist returns true if the record exist otherwise return false func (session *Session) Exist(bean ...interface{}) (bool, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -69,19 +67,11 @@ func (session *Session) Exist(bean ...interface{}) (bool, error) { args = session.statement.RawParams } - session.queryPreprocess(&sqlStr, args...) - - var rawRows *core.Rows - if session.isAutoCommit { - _, rawRows, err = session.innerQuery(sqlStr, args...) - } else { - rawRows, err = session.tx.Query(sqlStr, args...) - } + rows, err := session.queryRows(sqlStr, args...) if err != nil { return false, err } + defer rows.Close() - defer rawRows.Close() - - return rawRows.Next(), nil + return rows.Next(), nil } diff --git a/vendor/github.com/go-xorm/xorm/session_find.go b/vendor/github.com/go-xorm/xorm/session_find.go index 42b3506eb..05ec724f9 100644 --- a/vendor/github.com/go-xorm/xorm/session_find.go +++ b/vendor/github.com/go-xorm/xorm/session_find.go @@ -23,11 +23,13 @@ const ( // are conditions. beans could be []Struct, []*Struct, map[int64]Struct // map[int64]*Struct func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) error { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } + return session.find(rowsSlicePtr, condiBean...) +} +func (session *Session) find(rowsSlicePtr interface{}, condiBean ...interface{}) error { sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr)) if sliceValue.Kind() != reflect.Slice && sliceValue.Kind() != reflect.Map { return errors.New("needs a pointer to a slice or a map") @@ -157,21 +159,13 @@ func (session *Session) Find(rowsSlicePtr interface{}, condiBean ...interface{}) } func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Value, sqlStr string, args ...interface{}) error { - var rawRows *core.Rows - var err error - - session.queryPreprocess(&sqlStr, args...) - if session.isAutoCommit { - _, rawRows, err = session.innerQuery(sqlStr, args...) - } else { - rawRows, err = session.tx.Query(sqlStr, args...) - } + rows, err := session.queryRows(sqlStr, args...) if err != nil { return err } - defer rawRows.Close() + defer rows.Close() - fields, err := rawRows.Columns() + fields, err := rows.Columns() if err != nil { return err } @@ -245,20 +239,20 @@ func (session *Session) noCacheFind(table *core.Table, containerValue reflect.Va if err != nil { return err } - return session.rows2Beans(rawRows, fields, len(fields), tb, newElemFunc, containerValueSetFunc) + return session.rows2Beans(rows, fields, len(fields), tb, newElemFunc, containerValueSetFunc) } - for rawRows.Next() { + for rows.Next() { var newValue = newElemFunc(fields) bean := newValue.Interface() switch elemType.Kind() { case reflect.Slice: - err = rawRows.ScanSlice(bean) + err = rows.ScanSlice(bean) case reflect.Map: - err = rawRows.ScanMap(bean) + err = rows.ScanMap(bean) default: - err = rawRows.Scan(bean) + err = rows.Scan(bean) } if err != nil { @@ -299,12 +293,11 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in } tableName := session.statement.TableName() - table := session.statement.RefTable cacher := session.engine.getCacher2(table) ids, err := core.GetCacheSql(cacher, tableName, newsql, args) if err != nil { - rows, err := session.DB().Query(newsql, args...) + rows, err := session.queryRows(newsql, args...) if err != nil { return err } @@ -334,13 +327,13 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in ids = append(ids, pk) } - session.engine.logger.Debug("[cacheFind] cache sql:", ids, tableName, newsql, args) + session.engine.logger.Debug("[cacheFind] cache sql:", ids, tableName, sqlStr, newsql, args) err = core.PutCacheSql(cacher, ids, tableName, newsql, args) if err != nil { return err } } else { - session.engine.logger.Debug("[cacheFind] cache hit sql:", newsql, args) + session.engine.logger.Debug("[cacheFind] cache hit sql:", tableName, sqlStr, newsql, args) } sliceValue := reflect.Indirect(reflect.ValueOf(rowsSlicePtr)) @@ -355,7 +348,7 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in return err } bean := cacher.GetBean(tableName, sid) - if bean == nil { + if bean == nil || reflect.ValueOf(bean).Elem().Type() != t { ides = append(ides, id) ididxes[sid] = idx } else { @@ -376,9 +369,6 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in } if len(ides) > 0 { - newSession := session.engine.NewSession() - defer newSession.Close() - slices := reflect.New(reflect.SliceOf(t)) beans := slices.Interface() @@ -388,18 +378,18 @@ func (session *Session) cacheFind(t reflect.Type, sqlStr string, rowsSlicePtr in ff = append(ff, ie[0]) } - newSession.In("`"+table.PrimaryKeys[0]+"`", ff...) + session.In("`"+table.PrimaryKeys[0]+"`", ff...) } else { for _, ie := range ides { cond := builder.NewCond() for i, name := range table.PrimaryKeys { cond = cond.And(builder.Eq{"`" + name + "`": ie[i]}) } - newSession.Or(cond) + session.Or(cond) } } - err = newSession.NoCache().Find(beans) + err = session.NoCache().Table(tableName).find(beans) if err != nil { return err } diff --git a/vendor/github.com/go-xorm/xorm/session_get.go b/vendor/github.com/go-xorm/xorm/session_get.go index d5f768c69..1f1e61cdd 100644 --- a/vendor/github.com/go-xorm/xorm/session_get.go +++ b/vendor/github.com/go-xorm/xorm/session_get.go @@ -15,11 +15,13 @@ import ( // Get retrieve one record from database, bean's non-empty fields // will be as conditions func (session *Session) Get(bean interface{}) (bool, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } + return session.get(bean) +} +func (session *Session) get(bean interface{}) (bool, error) { beanValue := reflect.ValueOf(bean) if beanValue.Kind() != reflect.Ptr { return false, errors.New("needs a pointer to a value") @@ -51,8 +53,10 @@ func (session *Session) Get(bean interface{}) (bool, error) { args = session.statement.RawParams } + table := session.statement.RefTable + if session.canCache() && beanValue.Elem().Kind() == reflect.Struct { - if cacher := session.engine.getCacher2(session.statement.RefTable); cacher != nil && + if cacher := session.engine.getCacher2(table); cacher != nil && !session.statement.unscoped { has, err := session.cacheGet(bean, sqlStr, args...) if err != ErrCacheFailed { @@ -61,54 +65,43 @@ func (session *Session) Get(bean interface{}) (bool, error) { } } - return session.nocacheGet(beanValue.Elem().Kind(), bean, sqlStr, args...) + return session.nocacheGet(beanValue.Elem().Kind(), table, bean, sqlStr, args...) } -func (session *Session) nocacheGet(beanKind reflect.Kind, bean interface{}, sqlStr string, args ...interface{}) (bool, error) { - session.queryPreprocess(&sqlStr, args...) - - var rawRows *core.Rows - var err error - if session.isAutoCommit { - _, rawRows, err = session.innerQuery(sqlStr, args...) - } else { - rawRows, err = session.tx.Query(sqlStr, args...) - } +func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bean interface{}, sqlStr string, args ...interface{}) (bool, error) { + rows, err := session.queryRows(sqlStr, args...) if err != nil { return false, err } + defer rows.Close() - defer rawRows.Close() - - if !rawRows.Next() { + if !rows.Next() { return false, nil } switch beanKind { case reflect.Struct: - fields, err := rawRows.Columns() + fields, err := rows.Columns() if err != nil { - // WARN: Alougth rawRows return true, but get fields failed + // WARN: Alougth rows return true, but get fields failed return true, err } - dataStruct := rValue(bean) - if err := session.statement.setRefValue(dataStruct); err != nil { - return false, err - } - scanResults, err := session.row2Slice(rawRows, fields, len(fields), bean) + scanResults, err := session.row2Slice(rows, fields, len(fields), bean) if err != nil { return false, err } - rawRows.Close() + // close it before covert data + rows.Close() - _, err = session.slice2Bean(scanResults, fields, len(fields), bean, &dataStruct, session.statement.RefTable) + dataStruct := rValue(bean) + _, err = session.slice2Bean(scanResults, fields, len(fields), bean, &dataStruct, table) case reflect.Slice: - err = rawRows.ScanSlice(bean) + err = rows.ScanSlice(bean) case reflect.Map: - err = rawRows.ScanMap(bean) + err = rows.ScanMap(bean) default: - err = rawRows.Scan(bean) + err = rows.Scan(bean) } return true, err @@ -131,11 +124,11 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf cacher := session.engine.getCacher2(session.statement.RefTable) tableName := session.statement.TableName() session.engine.logger.Debug("[cacheGet] find sql:", newsql, args) - ids, err := core.GetCacheSql(cacher, tableName, newsql, args) table := session.statement.RefTable + ids, err := core.GetCacheSql(cacher, tableName, newsql, args) if err != nil { var res = make([]string, len(table.PrimaryKeys)) - rows, err := session.DB().Query(newsql, args...) + rows, err := session.NoCache().queryRows(newsql, args...) if err != nil { return false, err } @@ -172,7 +165,7 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf return false, err } } else { - session.engine.logger.Debug("[cacheGet] cache hit sql:", newsql) + session.engine.logger.Debug("[cacheGet] cache hit sql:", newsql, ids) } if len(ids) > 0 { @@ -186,7 +179,7 @@ func (session *Session) cacheGet(bean interface{}, sqlStr string, args ...interf cacheBean := cacher.GetBean(tableName, sid) if cacheBean == nil { cacheBean = bean - has, err = session.nocacheGet(reflect.Struct, cacheBean, sqlStr, args...) + has, err = session.nocacheGet(reflect.Struct, table, cacheBean, sqlStr, args...) if err != nil || !has { return has, err } diff --git a/vendor/github.com/go-xorm/xorm/session_insert.go b/vendor/github.com/go-xorm/xorm/session_insert.go index 02edf5744..705f6a895 100644 --- a/vendor/github.com/go-xorm/xorm/session_insert.go +++ b/vendor/github.com/go-xorm/xorm/session_insert.go @@ -22,7 +22,6 @@ func (session *Session) Insert(beans ...interface{}) (int64, error) { if session.isAutoClose { defer session.Close() } - defer session.resetStatement() for _, bean := range beans { sliceValue := reflect.Indirect(reflect.ValueOf(bean)) @@ -214,22 +213,23 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error var sql = "INSERT INTO %s (%v%v%v) VALUES (%v)" var statement string + var tableName = session.statement.TableName() if session.engine.dialect.DBType() == core.ORACLE { sql = "INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL" temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (", - session.engine.Quote(session.statement.TableName()), + session.engine.Quote(tableName), session.engine.QuoteStr(), strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()), session.engine.QuoteStr()) statement = fmt.Sprintf(sql, - session.engine.Quote(session.statement.TableName()), + session.engine.Quote(tableName), session.engine.QuoteStr(), strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()), session.engine.QuoteStr(), strings.Join(colMultiPlaces, temp)) } else { statement = fmt.Sprintf(sql, - session.engine.Quote(session.statement.TableName()), + session.engine.Quote(tableName), session.engine.QuoteStr(), strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()), session.engine.QuoteStr(), @@ -241,7 +241,7 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error } if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache { - session.cacheInsert(session.statement.TableName()) + session.cacheInsert(table, tableName) } lenAfterClosures := len(session.afterClosures) @@ -280,7 +280,6 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error // InsertMulti insert multiple records func (session *Session) InsertMulti(rowsSlicePtr interface{}) (int64, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -349,18 +348,19 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { } var sqlStr string + var tableName = session.statement.TableName() if len(colPlaces) > 0 { sqlStr = fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)", - session.engine.Quote(session.statement.TableName()), + session.engine.Quote(tableName), session.engine.QuoteStr(), strings.Join(colNames, session.engine.Quote(", ")), session.engine.QuoteStr(), colPlaces) } else { if session.engine.dialect.DBType() == core.MYSQL { - sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.engine.Quote(session.statement.TableName())) + sqlStr = fmt.Sprintf("INSERT INTO %s VALUES ()", session.engine.Quote(tableName)) } else { - sqlStr = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES", session.engine.Quote(session.statement.TableName())) + sqlStr = fmt.Sprintf("INSERT INTO %s DEFAULT VALUES", session.engine.Quote(tableName)) } } @@ -395,7 +395,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { // for postgres, many of them didn't implement lastInsertId, so we should // implemented it ourself. if session.engine.dialect.DBType() == core.ORACLE && len(table.AutoIncrement) > 0 { - res, err := session.query("select seq_atable.currval from dual", args...) + res, err := session.queryBytes("select seq_atable.currval from dual", args...) if err != nil { return 0, err } @@ -403,7 +403,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { handleAfterInsertProcessorFunc(bean) if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache { - session.cacheInsert(session.statement.TableName()) + session.cacheInsert(table, tableName) } if table.Version != "" && session.statement.checkVersion { @@ -440,7 +440,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { } else if session.engine.dialect.DBType() == core.POSTGRES && len(table.AutoIncrement) > 0 { //assert table.AutoIncrement != "" sqlStr = sqlStr + " RETURNING " + session.engine.Quote(table.AutoIncrement) - res, err := session.query(sqlStr, args...) + res, err := session.queryBytes(sqlStr, args...) if err != nil { return 0, err @@ -448,7 +448,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { handleAfterInsertProcessorFunc(bean) if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache { - session.cacheInsert(session.statement.TableName()) + session.cacheInsert(table, tableName) } if table.Version != "" && session.statement.checkVersion { @@ -491,7 +491,7 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { defer handleAfterInsertProcessorFunc(bean) if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache { - session.cacheInsert(session.statement.TableName()) + session.cacheInsert(table, tableName) } if table.Version != "" && session.statement.checkVersion { @@ -532,7 +532,6 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) { // The in parameter bean must a struct or a point to struct. The return // parameter is inserted and error func (session *Session) InsertOne(bean interface{}) (int64, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -540,14 +539,12 @@ func (session *Session) InsertOne(bean interface{}) (int64, error) { return session.innerInsert(bean) } -func (session *Session) cacheInsert(tables ...string) error { - if session.statement.RefTable == nil { +func (session *Session) cacheInsert(table *core.Table, tables ...string) error { + if table == nil { return ErrCacheFailed } - table := session.statement.RefTable cacher := session.engine.getCacher2(table) - for _, t := range tables { session.engine.logger.Debug("[cache] clear sql:", t) cacher.ClearIds(t) diff --git a/vendor/github.com/go-xorm/xorm/session_iterate.go b/vendor/github.com/go-xorm/xorm/session_iterate.go index 7c1480959..a2f957a27 100644 --- a/vendor/github.com/go-xorm/xorm/session_iterate.go +++ b/vendor/github.com/go-xorm/xorm/session_iterate.go @@ -19,6 +19,10 @@ func (session *Session) Rows(bean interface{}) (*Rows, error) { // are conditions. beans could be []Struct, []*Struct, map[int64]Struct // map[int64]*Struct func (session *Session) Iterate(bean interface{}, fun IterFunc) error { + if session.isAutoClose { + defer session.Close() + } + rows, err := session.Rows(bean) if err != nil { return err diff --git a/vendor/github.com/go-xorm/xorm/session_query.go b/vendor/github.com/go-xorm/xorm/session_query.go new file mode 100644 index 000000000..a693bace3 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/session_query.go @@ -0,0 +1,177 @@ +// Copyright 2017 The Xorm Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xorm + +import ( + "fmt" + "reflect" + "strconv" + "time" + + "github.com/go-xorm/core" +) + +// Query runs a raw sql and return records as []map[string][]byte +func (session *Session) Query(sqlStr string, args ...interface{}) ([]map[string][]byte, error) { + if session.isAutoClose { + defer session.Close() + } + + return session.queryBytes(sqlStr, args...) +} + +func value2String(rawValue *reflect.Value) (str string, err error) { + aa := reflect.TypeOf((*rawValue).Interface()) + vv := reflect.ValueOf((*rawValue).Interface()) + switch aa.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + str = strconv.FormatInt(vv.Int(), 10) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + str = strconv.FormatUint(vv.Uint(), 10) + case reflect.Float32, reflect.Float64: + str = strconv.FormatFloat(vv.Float(), 'f', -1, 64) + case reflect.String: + str = vv.String() + case reflect.Array, reflect.Slice: + switch aa.Elem().Kind() { + case reflect.Uint8: + data := rawValue.Interface().([]byte) + str = string(data) + if str == "\x00" { + str = "0" + } + default: + err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name()) + } + // time type + case reflect.Struct: + if aa.ConvertibleTo(core.TimeType) { + str = vv.Convert(core.TimeType).Interface().(time.Time).Format(time.RFC3339Nano) + } else { + err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name()) + } + case reflect.Bool: + str = strconv.FormatBool(vv.Bool()) + case reflect.Complex128, reflect.Complex64: + str = fmt.Sprintf("%v", vv.Complex()) + /* TODO: unsupported types below + case reflect.Map: + case reflect.Ptr: + case reflect.Uintptr: + case reflect.UnsafePointer: + case reflect.Chan, reflect.Func, reflect.Interface: + */ + default: + err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name()) + } + return +} + +func row2mapStr(rows *core.Rows, fields []string) (resultsMap map[string]string, err error) { + result := make(map[string]string) + scanResultContainers := make([]interface{}, len(fields)) + for i := 0; i < len(fields); i++ { + var scanResultContainer interface{} + scanResultContainers[i] = &scanResultContainer + } + if err := rows.Scan(scanResultContainers...); err != nil { + return nil, err + } + + for ii, key := range fields { + rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])) + // if row is null then as empty string + if rawValue.Interface() == nil { + result[key] = "" + continue + } + + if data, err := value2String(&rawValue); err == nil { + result[key] = data + } else { + return nil, err + } + } + return result, nil +} + +func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) { + fields, err := rows.Columns() + if err != nil { + return nil, err + } + for rows.Next() { + result, err := row2mapStr(rows, fields) + if err != nil { + return nil, err + } + resultsSlice = append(resultsSlice, result) + } + + return resultsSlice, nil +} + +// QueryString runs a raw sql and return records as []map[string]string +func (session *Session) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) { + if session.isAutoClose { + defer session.Close() + } + + rows, err := session.queryRows(sqlStr, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + return rows2Strings(rows) +} + +func row2mapInterface(rows *core.Rows, fields []string) (resultsMap map[string]interface{}, err error) { + resultsMap = make(map[string]interface{}, len(fields)) + scanResultContainers := make([]interface{}, len(fields)) + for i := 0; i < len(fields); i++ { + var scanResultContainer interface{} + scanResultContainers[i] = &scanResultContainer + } + if err := rows.Scan(scanResultContainers...); err != nil { + return nil, err + } + + for ii, key := range fields { + resultsMap[key] = reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])).Interface() + } + return +} + +func rows2Interfaces(rows *core.Rows) (resultsSlice []map[string]interface{}, err error) { + fields, err := rows.Columns() + if err != nil { + return nil, err + } + for rows.Next() { + result, err := row2mapInterface(rows, fields) + if err != nil { + return nil, err + } + resultsSlice = append(resultsSlice, result) + } + + return resultsSlice, nil +} + +// QueryInterface runs a raw sql and return records as []map[string]interface{} +func (session *Session) QueryInterface(sqlStr string, args ...interface{}) ([]map[string]interface{}, error) { + if session.isAutoClose { + defer session.Close() + } + + rows, err := session.queryRows(sqlStr, args...) + if err != nil { + return nil, err + } + defer rows.Close() + + return rows2Interfaces(rows) +} diff --git a/vendor/github.com/go-xorm/xorm/session_raw.go b/vendor/github.com/go-xorm/xorm/session_raw.go index 05223c465..c225598e6 100644 --- a/vendor/github.com/go-xorm/xorm/session_raw.go +++ b/vendor/github.com/go-xorm/xorm/session_raw.go @@ -6,61 +6,113 @@ package xorm import ( "database/sql" - "fmt" "reflect" - "strconv" "time" "github.com/go-xorm/core" ) -func (session *Session) query(sqlStr string, paramStr ...interface{}) ([]map[string][]byte, error) { - session.queryPreprocess(&sqlStr, paramStr...) - - if session.isAutoCommit { - return session.innerQuery2(sqlStr, paramStr...) +func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) { + for _, filter := range session.engine.dialect.Filters() { + *sqlStr = filter.Do(*sqlStr, session.engine.dialect, session.statement.RefTable) } - return session.txQuery(session.tx, sqlStr, paramStr...) + + session.lastSQL = *sqlStr + session.lastSQLArgs = paramStr } -func (session *Session) txQuery(tx *core.Tx, sqlStr string, params ...interface{}) ([]map[string][]byte, error) { - rows, err := tx.Query(sqlStr, params...) +func (session *Session) queryRows(sqlStr string, args ...interface{}) (*core.Rows, error) { + defer session.resetStatement() + + session.queryPreprocess(&sqlStr, args...) + + if session.engine.showSQL { + if session.engine.showExecTime { + b4ExecTime := time.Now() + defer func() { + execDuration := time.Since(b4ExecTime) + if len(args) > 0 { + session.engine.logger.Infof("[SQL] %s %#v - took: %v", sqlStr, args, execDuration) + } else { + session.engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration) + } + }() + } else { + if len(args) > 0 { + session.engine.logger.Infof("[SQL] %v %#v", sqlStr, args) + } else { + session.engine.logger.Infof("[SQL] %v", sqlStr) + } + } + } + + if session.isAutoCommit { + if session.prepareStmt { + // don't clear stmt since session will cache them + stmt, err := session.doPrepare(sqlStr) + if err != nil { + return nil, err + } + + rows, err := stmt.Query(args...) + if err != nil { + return nil, err + } + return rows, nil + } + + rows, err := session.DB().Query(sqlStr, args...) + if err != nil { + return nil, err + } + return rows, nil + } + + rows, err := session.tx.Query(sqlStr, args...) if err != nil { return nil, err } - defer rows.Close() - - return rows2maps(rows) + return rows, nil } -func (session *Session) innerQuery(sqlStr string, params ...interface{}) (*core.Stmt, *core.Rows, error) { - var callback func() (*core.Stmt, *core.Rows, error) - if session.prepareStmt { - callback = func() (*core.Stmt, *core.Rows, error) { - stmt, err := session.doPrepare(sqlStr) - if err != nil { - return nil, nil, err - } - rows, err := stmt.Query(params...) - if err != nil { - return nil, nil, err - } - return stmt, rows, nil - } - } else { - callback = func() (*core.Stmt, *core.Rows, error) { - rows, err := session.DB().Query(sqlStr, params...) - if err != nil { - return nil, nil, err - } - return nil, rows, err - } - } - stmt, rows, err := session.engine.logSQLQueryTime(sqlStr, params, callback) +func (session *Session) queryRow(sqlStr string, args ...interface{}) *core.Row { + return core.NewRow(session.queryRows(sqlStr, args...)) +} + +func value2Bytes(rawValue *reflect.Value) ([]byte, error) { + str, err := value2String(rawValue) if err != nil { - return nil, nil, err + return nil, err } - return stmt, rows, nil + return []byte(str), nil +} + +func row2map(rows *core.Rows, fields []string) (resultsMap map[string][]byte, err error) { + result := make(map[string][]byte) + scanResultContainers := make([]interface{}, len(fields)) + for i := 0; i < len(fields); i++ { + var scanResultContainer interface{} + scanResultContainers[i] = &scanResultContainer + } + if err := rows.Scan(scanResultContainers...); err != nil { + return nil, err + } + + for ii, key := range fields { + rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])) + //if row is null then ignore + if rawValue.Interface() == nil { + result[key] = []byte{} + continue + } + + if data, err := value2Bytes(&rawValue); err == nil { + result[key] = data + } else { + return nil, err // !nashtsai! REVIEW, should return err or just error log? + } + } + return result, nil } func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) { @@ -79,197 +131,45 @@ func rows2maps(rows *core.Rows) (resultsSlice []map[string][]byte, err error) { return resultsSlice, nil } -func value2Bytes(rawValue *reflect.Value) (data []byte, err error) { - var str string - str, err = reflect2value(rawValue) - if err != nil { - return - } - data = []byte(str) - return -} - -func row2map(rows *core.Rows, fields []string) (resultsMap map[string][]byte, err error) { - result := make(map[string][]byte) - scanResultContainers := make([]interface{}, len(fields)) - for i := 0; i < len(fields); i++ { - var scanResultContainer interface{} - scanResultContainers[i] = &scanResultContainer - } - if err := rows.Scan(scanResultContainers...); err != nil { - return nil, err - } - - for ii, key := range fields { - rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])) - //if row is null then ignore - if rawValue.Interface() == nil { - //fmt.Println("ignore ...", key, rawValue) - continue - } - - if data, err := value2Bytes(&rawValue); err == nil { - result[key] = data - } else { - return nil, err // !nashtsai! REVIEW, should return err or just error log? - } - } - return result, nil -} - -func (session *Session) innerQuery2(sqlStr string, params ...interface{}) ([]map[string][]byte, error) { - _, rows, err := session.innerQuery(sqlStr, params...) - if rows != nil { - defer rows.Close() - } +func (session *Session) queryBytes(sqlStr string, args ...interface{}) ([]map[string][]byte, error) { + rows, err := session.queryRows(sqlStr, args...) if err != nil { return nil, err } + defer rows.Close() + return rows2maps(rows) } -// Query runs a raw sql and return records as []map[string][]byte -func (session *Session) Query(sqlStr string, paramStr ...interface{}) ([]map[string][]byte, error) { +func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) { defer session.resetStatement() - if session.isAutoClose { - defer session.Close() - } - - return session.query(sqlStr, paramStr...) -} - -func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) { - fields, err := rows.Columns() - if err != nil { - return nil, err - } - for rows.Next() { - result, err := row2mapStr(rows, fields) - if err != nil { - return nil, err - } - resultsSlice = append(resultsSlice, result) - } - - return resultsSlice, nil -} - -func reflect2value(rawValue *reflect.Value) (str string, err error) { - aa := reflect.TypeOf((*rawValue).Interface()) - vv := reflect.ValueOf((*rawValue).Interface()) - switch aa.Kind() { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - str = strconv.FormatInt(vv.Int(), 10) - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - str = strconv.FormatUint(vv.Uint(), 10) - case reflect.Float32, reflect.Float64: - str = strconv.FormatFloat(vv.Float(), 'f', -1, 64) - case reflect.String: - str = vv.String() - case reflect.Array, reflect.Slice: - switch aa.Elem().Kind() { - case reflect.Uint8: - data := rawValue.Interface().([]byte) - str = string(data) - default: - err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name()) - } - // time type - case reflect.Struct: - if aa.ConvertibleTo(core.TimeType) { - str = vv.Convert(core.TimeType).Interface().(time.Time).Format(time.RFC3339Nano) - } else { - err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name()) - } - case reflect.Bool: - str = strconv.FormatBool(vv.Bool()) - case reflect.Complex128, reflect.Complex64: - str = fmt.Sprintf("%v", vv.Complex()) - /* TODO: unsupported types below - case reflect.Map: - case reflect.Ptr: - case reflect.Uintptr: - case reflect.UnsafePointer: - case reflect.Chan, reflect.Func, reflect.Interface: - */ - default: - err = fmt.Errorf("Unsupported struct type %v", vv.Type().Name()) - } - return -} - -func value2String(rawValue *reflect.Value) (data string, err error) { - data, err = reflect2value(rawValue) - if err != nil { - return - } - return -} - -func row2mapStr(rows *core.Rows, fields []string) (resultsMap map[string]string, err error) { - result := make(map[string]string) - scanResultContainers := make([]interface{}, len(fields)) - for i := 0; i < len(fields); i++ { - var scanResultContainer interface{} - scanResultContainers[i] = &scanResultContainer - } - if err := rows.Scan(scanResultContainers...); err != nil { - return nil, err - } - - for ii, key := range fields { - rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[ii])) - //if row is null then ignore - if rawValue.Interface() == nil { - //fmt.Println("ignore ...", key, rawValue) - continue - } - - if data, err := value2String(&rawValue); err == nil { - result[key] = data - } else { - return nil, err // !nashtsai! REVIEW, should return err or just error log? - } - } - return result, nil -} - -func txQuery2(tx *core.Tx, sqlStr string, params ...interface{}) ([]map[string]string, error) { - rows, err := tx.Query(sqlStr, params...) - if err != nil { - return nil, err - } - defer rows.Close() - - return rows2Strings(rows) -} - -func query2(db *core.DB, sqlStr string, params ...interface{}) ([]map[string]string, error) { - rows, err := db.Query(sqlStr, params...) - if err != nil { - return nil, err - } - defer rows.Close() - return rows2Strings(rows) -} - -// QueryString runs a raw sql and return records as []map[string]string -func (session *Session) QueryString(sqlStr string, args ...interface{}) ([]map[string]string, error) { - defer session.resetStatement() - if session.isAutoClose { - defer session.Close() - } session.queryPreprocess(&sqlStr, args...) - if session.isAutoCommit { - return query2(session.DB(), sqlStr, args...) + if session.engine.showSQL { + if session.engine.showExecTime { + b4ExecTime := time.Now() + defer func() { + execDuration := time.Since(b4ExecTime) + if len(args) > 0 { + session.engine.logger.Infof("[SQL] %s %#v - took: %v", sqlStr, args, execDuration) + } else { + session.engine.logger.Infof("[SQL] %s - took: %v", sqlStr, execDuration) + } + }() + } else { + if len(args) > 0 { + session.engine.logger.Infof("[SQL] %v %#v", sqlStr, args) + } else { + session.engine.logger.Infof("[SQL] %v", sqlStr) + } + } + } + + if !session.isAutoCommit { + return session.tx.Exec(sqlStr, args...) } - return txQuery2(session.tx, sqlStr, args...) -} -// Execute sql -func (session *Session) innerExec(sqlStr string, args ...interface{}) (sql.Result, error) { if session.prepareStmt { stmt, err := session.doPrepare(sqlStr) if err != nil { @@ -286,32 +186,8 @@ func (session *Session) innerExec(sqlStr string, args ...interface{}) (sql.Resul return session.DB().Exec(sqlStr, args...) } -func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, error) { - for _, filter := range session.engine.dialect.Filters() { - // TODO: for table name, it's no need to RefTable - sqlStr = filter.Do(sqlStr, session.engine.dialect, session.statement.RefTable) - } - - session.saveLastSQL(sqlStr, args...) - - return session.engine.logSQLExecutionTime(sqlStr, args, func() (sql.Result, error) { - if session.isAutoCommit { - // FIXME: oci8 can not auto commit (github.com/mattn/go-oci8) - if session.engine.dialect.DBType() == core.ORACLE { - session.Begin() - r, err := session.tx.Exec(sqlStr, args...) - session.Commit() - return r, err - } - return session.innerExec(sqlStr, args...) - } - return session.tx.Exec(sqlStr, args...) - }) -} - // Exec raw sql func (session *Session) Exec(sqlStr string, args ...interface{}) (sql.Result, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } diff --git a/vendor/github.com/go-xorm/xorm/session_schema.go b/vendor/github.com/go-xorm/xorm/session_schema.go index c1d5088d7..a2708b736 100644 --- a/vendor/github.com/go-xorm/xorm/session_schema.go +++ b/vendor/github.com/go-xorm/xorm/session_schema.go @@ -16,7 +16,6 @@ import ( // Ping test if database is ok func (session *Session) Ping() error { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -35,7 +34,6 @@ func (session *Session) CreateTable(bean interface{}) error { } func (session *Session) createTable(bean interface{}) error { - defer session.resetStatement() v := rValue(bean) if err := session.statement.setRefValue(v); err != nil { return err @@ -56,7 +54,6 @@ func (session *Session) CreateIndexes(bean interface{}) error { } func (session *Session) createIndexes(bean interface{}) error { - defer session.resetStatement() v := rValue(bean) if err := session.statement.setRefValue(v); err != nil { return err @@ -81,7 +78,6 @@ func (session *Session) CreateUniques(bean interface{}) error { } func (session *Session) createUniques(bean interface{}) error { - defer session.resetStatement() v := rValue(bean) if err := session.statement.setRefValue(v); err != nil { return err @@ -107,7 +103,6 @@ func (session *Session) DropIndexes(bean interface{}) error { } func (session *Session) dropIndexes(bean interface{}) error { - defer session.resetStatement() v := rValue(bean) if err := session.statement.setRefValue(v); err != nil { return err @@ -133,7 +128,6 @@ func (session *Session) DropTable(beanOrTableName interface{}) error { } func (session *Session) dropTable(beanOrTableName interface{}) error { - defer session.resetStatement() tableName, err := session.engine.tableName(beanOrTableName) if err != nil { return err @@ -142,7 +136,7 @@ func (session *Session) dropTable(beanOrTableName interface{}) error { var needDrop = true if !session.engine.dialect.SupportDropIfExists() { sqlStr, args := session.engine.dialect.TableCheckSql(tableName) - results, err := session.query(sqlStr, args...) + results, err := session.queryBytes(sqlStr, args...) if err != nil { return err } @@ -172,9 +166,8 @@ func (session *Session) IsTableExist(beanOrTableName interface{}) (bool, error) } func (session *Session) isTableExist(tableName string) (bool, error) { - defer session.resetStatement() sqlStr, args := session.engine.dialect.TableCheckSql(tableName) - results, err := session.query(sqlStr, args...) + results, err := session.queryBytes(sqlStr, args...) return len(results) > 0, err } @@ -196,12 +189,9 @@ func (session *Session) IsTableEmpty(bean interface{}) (bool, error) { } func (session *Session) isTableEmpty(tableName string) (bool, error) { - defer session.resetStatement() - var total int64 sqlStr := fmt.Sprintf("select count(*) from %s", session.engine.Quote(tableName)) - err := session.DB().QueryRow(sqlStr).Scan(&total) - session.saveLastSQL(sqlStr) + err := session.queryRow(sqlStr).Scan(&total) if err != nil { if err == sql.ErrNoRows { err = nil @@ -214,8 +204,6 @@ func (session *Session) isTableEmpty(tableName string) (bool, error) { // find if index is exist according cols func (session *Session) isIndexExist2(tableName string, cols []string, unique bool) (bool, error) { - defer session.resetStatement() - indexes, err := session.engine.dialect.GetIndexes(tableName) if err != nil { return false, err @@ -233,8 +221,6 @@ func (session *Session) isIndexExist2(tableName string, cols []string, unique bo } func (session *Session) addColumn(colName string) error { - defer session.resetStatement() - col := session.statement.RefTable.GetColumn(colName) sql, args := session.statement.genAddColumnStr(col) _, err := session.exec(sql, args...) @@ -242,18 +228,13 @@ func (session *Session) addColumn(colName string) error { } func (session *Session) addIndex(tableName, idxName string) error { - defer session.resetStatement() - index := session.statement.RefTable.Indexes[idxName] sqlStr := session.engine.dialect.CreateIndexSql(tableName, index) - _, err := session.exec(sqlStr) return err } func (session *Session) addUnique(tableName, uqeName string) error { - defer session.resetStatement() - index := session.statement.RefTable.Indexes[uqeName] sqlStr := session.engine.dialect.CreateIndexSql(tableName, index) _, err := session.exec(sqlStr) diff --git a/vendor/github.com/go-xorm/xorm/session_stats.go b/vendor/github.com/go-xorm/xorm/session_stats.go index df02e95a8..c2cac8306 100644 --- a/vendor/github.com/go-xorm/xorm/session_stats.go +++ b/vendor/github.com/go-xorm/xorm/session_stats.go @@ -13,7 +13,6 @@ import ( // Count counts the records. bean's non-empty fields // are conditions. func (session *Session) Count(bean ...interface{}) (int64, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -31,15 +30,8 @@ func (session *Session) Count(bean ...interface{}) (int64, error) { args = session.statement.RawParams } - session.queryPreprocess(&sqlStr, args...) - var total int64 - if session.isAutoCommit { - err = session.DB().QueryRow(sqlStr, args...).Scan(&total) - } else { - err = session.tx.QueryRow(sqlStr, args...).Scan(&total) - } - + err = session.queryRow(sqlStr, args...).Scan(&total) if err == sql.ErrNoRows || err == nil { return total, nil } @@ -49,7 +41,6 @@ func (session *Session) Count(bean ...interface{}) (int64, error) { // sum call sum some column. bean's non-empty fields are conditions. func (session *Session) sum(res interface{}, bean interface{}, columnNames ...string) error { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -73,22 +64,11 @@ func (session *Session) sum(res interface{}, bean interface{}, columnNames ...st args = session.statement.RawParams } - session.queryPreprocess(&sqlStr, args...) - if isSlice { - if session.isAutoCommit { - err = session.DB().QueryRow(sqlStr, args...).ScanSlice(res) - } else { - err = session.tx.QueryRow(sqlStr, args...).ScanSlice(res) - } + err = session.queryRow(sqlStr, args...).ScanSlice(res) } else { - if session.isAutoCommit { - err = session.DB().QueryRow(sqlStr, args...).Scan(res) - } else { - err = session.tx.QueryRow(sqlStr, args...).Scan(res) - } + err = session.queryRow(sqlStr, args...).Scan(res) } - if err == sql.ErrNoRows || err == nil { return nil } diff --git a/vendor/github.com/go-xorm/xorm/session_update.go b/vendor/github.com/go-xorm/xorm/session_update.go index e80cd0b57..6e9d11681 100644 --- a/vendor/github.com/go-xorm/xorm/session_update.go +++ b/vendor/github.com/go-xorm/xorm/session_update.go @@ -15,8 +15,8 @@ import ( "github.com/go-xorm/core" ) -func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error { - if session.statement.RefTable == nil || +func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string, args ...interface{}) error { + if table == nil || session.tx != nil { return ErrCacheFailed } @@ -26,7 +26,7 @@ func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error { return ErrCacheFailed } for _, filter := range session.engine.dialect.Filters() { - newsql = filter.Do(newsql, session.engine.dialect, session.statement.RefTable) + newsql = filter.Do(newsql, session.engine.dialect, table) } session.engine.logger.Debug("[cacheUpdate] new sql", oldhead, newsql) @@ -39,13 +39,12 @@ func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error { nStart = strings.Count(oldhead, "$") } } - table := session.statement.RefTable + cacher := session.engine.getCacher2(table) - tableName := session.statement.TableName() session.engine.logger.Debug("[cacheUpdate] get cache sql", newsql, args[nStart:]) ids, err := core.GetCacheSql(cacher, tableName, newsql, args[nStart:]) if err != nil { - rows, err := session.DB().Query(newsql, args[nStart:]...) + rows, err := session.NoCache().queryRows(newsql, args[nStart:]...) if err != nil { return err } @@ -144,7 +143,6 @@ func (session *Session) cacheUpdate(sqlStr string, args ...interface{}) error { // You should call UseBool if you have bool to use. // 2.float32 & float64 may be not inexact as conditions func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int64, error) { - defer session.resetStatement() if session.isAutoClose { defer session.Close() } @@ -249,8 +247,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } } - st := session.statement - defer session.resetStatement() + st := &session.statement var sqlStr string var condArgs []interface{} @@ -282,6 +279,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 condSQL = condSQL + fmt.Sprintf(" ORDER BY %v", st.OrderStr) } + var tableName = session.statement.TableName() // TODO: Oracle support needed var top string if st.LimitN > 0 { @@ -290,7 +288,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } else if st.Engine.dialect.DBType() == core.SQLITE { tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) cond = cond.And(builder.Expr(fmt.Sprintf("rowid IN (SELECT rowid FROM %v %v)", - session.engine.Quote(session.statement.TableName()), tempCondSQL), condArgs...)) + session.engine.Quote(tableName), tempCondSQL), condArgs...)) condSQL, condArgs, err = builder.ToSQL(cond) if err != nil { return 0, err @@ -301,7 +299,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 } else if st.Engine.dialect.DBType() == core.POSTGRES { tempCondSQL := condSQL + fmt.Sprintf(" LIMIT %d", st.LimitN) cond = cond.And(builder.Expr(fmt.Sprintf("CTID IN (SELECT CTID FROM %v %v)", - session.engine.Quote(session.statement.TableName()), tempCondSQL), condArgs...)) + session.engine.Quote(tableName), tempCondSQL), condArgs...)) condSQL, condArgs, err = builder.ToSQL(cond) if err != nil { return 0, err @@ -315,7 +313,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 table != nil && len(table.PrimaryKeys) == 1 { cond = builder.Expr(fmt.Sprintf("%s IN (SELECT TOP (%d) %s FROM %v%v)", table.PrimaryKeys[0], st.LimitN, table.PrimaryKeys[0], - session.engine.Quote(session.statement.TableName()), condSQL), condArgs...) + session.engine.Quote(tableName), condSQL), condArgs...) condSQL, condArgs, err = builder.ToSQL(cond) if err != nil { @@ -336,7 +334,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 sqlStr = fmt.Sprintf("UPDATE %v%v SET %v %v", top, - session.engine.Quote(session.statement.TableName()), + session.engine.Quote(tableName), strings.Join(colNames, ", "), condSQL) @@ -351,8 +349,9 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 if table != nil { if cacher := session.engine.getCacher2(table); cacher != nil && session.statement.UseCache { - cacher.ClearIds(session.statement.TableName()) - cacher.ClearBeans(session.statement.TableName()) + //session.cacheUpdate(table, tableName, sqlStr, args...) + cacher.ClearIds(tableName) + cacher.ClearBeans(tableName) } } @@ -362,7 +361,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6 closure(bean) } if processor, ok := interface{}(bean).(AfterUpdateProcessor); ok { - session.engine.logger.Debug("[event]", session.statement.TableName(), " has after update processor") + session.engine.logger.Debug("[event]", tableName, " has after update processor") processor.AfterUpdate() } } else { diff --git a/vendor/github.com/go-xorm/xorm/statement.go b/vendor/github.com/go-xorm/xorm/statement.go index 50008d1dd..dc8a0c9b2 100644 --- a/vendor/github.com/go-xorm/xorm/statement.go +++ b/vendor/github.com/go-xorm/xorm/statement.go @@ -1205,7 +1205,8 @@ func (statement *Statement) convertIDSQL(sqlStr string) string { top = fmt.Sprintf("TOP %d ", statement.LimitN) } - return fmt.Sprintf("SELECT %s%s FROM %v", top, colstrs, sqls[1]) + newsql := fmt.Sprintf("SELECT %s%s FROM %v", top, colstrs, sqls[1]) + return newsql } return "" } diff --git a/vendor/github.com/go-xorm/xorm/test_mssql_cache.sh b/vendor/github.com/go-xorm/xorm/test_mssql_cache.sh new file mode 100755 index 000000000..76efd6ca0 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mssql_cache.sh @@ -0,0 +1 @@ +go test -db=mssql -conn_str="server=192.168.1.58;user id=sa;password=123456;database=xorm_test" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mymysql_cache.sh b/vendor/github.com/go-xorm/xorm/test_mymysql_cache.sh new file mode 100755 index 000000000..0100286d6 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mymysql_cache.sh @@ -0,0 +1 @@ +go test -db=mymysql -conn_str="xorm_test/root/" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_mysql_cache.sh b/vendor/github.com/go-xorm/xorm/test_mysql_cache.sh new file mode 100755 index 000000000..c542e7359 --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_mysql_cache.sh @@ -0,0 +1 @@ +go test -db=mysql -conn_str="root:@/xorm_test" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_postgres_cache.sh b/vendor/github.com/go-xorm/xorm/test_postgres_cache.sh new file mode 100755 index 000000000..462fc948c --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_postgres_cache.sh @@ -0,0 +1 @@ +go test -db=postgres -conn_str="dbname=xorm_test sslmode=disable" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/test_sqlite_cache.sh b/vendor/github.com/go-xorm/xorm/test_sqlite_cache.sh new file mode 100755 index 000000000..75a054c3f --- /dev/null +++ b/vendor/github.com/go-xorm/xorm/test_sqlite_cache.sh @@ -0,0 +1 @@ +go test -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" -cache=true \ No newline at end of file diff --git a/vendor/github.com/go-xorm/xorm/xorm.go b/vendor/github.com/go-xorm/xorm/xorm.go index 4434c7ff3..4fdadf2fa 100644 --- a/vendor/github.com/go-xorm/xorm/xorm.go +++ b/vendor/github.com/go-xorm/xorm/xorm.go @@ -17,7 +17,7 @@ import ( const ( // Version show the xorm's version - Version string = "0.6.3.0713" + Version string = "0.6.4.0910" ) func regDrvsNDialects() bool { diff --git a/vendor/vendor.json b/vendor/vendor.json index 5fd393b8b..7c4c157f3 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -456,10 +456,10 @@ "revisionTime": "2017-05-19T03:21:30Z" }, { - "checksumSHA1": "KOHXTLwpgTMxBB9aGF2aIxkWdm8=", + "checksumSHA1": "HMavuxvDhKOwmbbFnYt9hfT6jE0=", "path": "github.com/go-xorm/core", - "revision": "71c1070a861118827352b1394eb86cbfeef5c513", - "revisionTime": "2017-08-22T05:50:40Z" + "revision": "da1adaf7a28ca792961721a34e6e04945200c890", + "revisionTime": "2017-09-09T08:56:53Z" }, { "checksumSHA1": "k52lEKLp8j5M+jFpe+3u+bIFpxQ=", @@ -468,10 +468,10 @@ "revisionTime": "2016-08-11T02:11:45Z" }, { - "checksumSHA1": "0F65zfDi1ys3KD/wMKtxC2k13DA=", + "checksumSHA1": "SoZDnkd5NdwE0g4MY1nTAl8ZtPo=", "path": "github.com/go-xorm/xorm", - "revision": "a10b5aba4bb97b30daa74e7c0363d3084ede0514", - "revisionTime": "2017-08-20T09:05:42Z" + "revision": "c29485f954ed6495861c0098f9a1642a467299c8", + "revisionTime": "2017-09-10T12:58:18Z" }, { "checksumSHA1": "1ft/4j5MFa7C9dPI9whL03HSUzk=",