Merge branch 'master' into master

This commit is contained in:
Lunny Xiao 2019-07-30 15:13:27 +08:00 committed by GitHub
commit 9e0cd1a08a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
62 changed files with 1845 additions and 1300 deletions

View File

@ -35,8 +35,8 @@ jobs:
- checkout - checkout
- run: go get -t -d -v ./... - run: go get -t -d -v ./...
- run: go get -u github.com/go-xorm/core - run: go get -u xorm.io/core
- run: go get -u github.com/go-xorm/builder - run: go get -u xorm.io/builder
- run: GO111MODULE=off go build -v - run: GO111MODULE=off go build -v
- run: GO111MODULE=on go build -v - run: GO111MODULE=on go build -v

View File

@ -59,8 +59,8 @@ pipeline:
image: golang:${GO_VERSION} image: golang:${GO_VERSION}
commands: commands:
- go get -t -d -v ./... - go get -t -d -v ./...
- go get -u github.com/go-xorm/core - go get -u xorm.io/core
- go get -u github.com/go-xorm/builder - go get -u xorm.io/builder
- go build -v - go build -v
when: when:
event: [ push, pull_request ] event: [ push, pull_request ]

View File

@ -28,7 +28,7 @@ Xorm is a simple and powerful ORM for Go.
* Optimistic Locking support * Optimistic Locking support
* SQL Builder support via [github.com/go-xorm/builder](https://github.com/go-xorm/builder) * SQL Builder support via [xorm.io/builder](https://xorm.io/builder)
* Automatical Read/Write seperatelly * Automatical Read/Write seperatelly
@ -284,6 +284,13 @@ counts, err := engine.Count(&user)
// SELECT count(*) AS total FROM user // SELECT count(*) AS total FROM user
``` ```
* `FindAndCount` combines function `Find` with `Count` which is usually used in query by page
```Go
var users []User
counts, err := engine.FindAndCount(&users)
```
* `Sum` sum functions * `Sum` sum functions
```Go ```Go

View File

@ -362,7 +362,7 @@ if _, err := session.Exec("delete from userinfo where username = ?", user2.Usern
return session.Commit() return session.Commit()
``` ```
* 事的简写方法 * 事的简写方法
```Go ```Go
res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) { res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) {

View File

@ -10,7 +10,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
// LRUCacher implments cache object facilities // LRUCacher implments cache object facilities

View File

@ -7,7 +7,7 @@ package xorm
import ( import (
"testing" "testing"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -7,7 +7,7 @@ package xorm
import ( import (
"sync" "sync"
"github.com/go-xorm/core" "xorm.io/core"
) )
var _ core.CacheStore = NewMemoryStore() var _ core.CacheStore = NewMemoryStore()

View File

@ -11,196 +11,196 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/go-xorm/core" "xorm.io/core"
) )
var ( var (
mssqlReservedWords = map[string]bool{ mssqlReservedWords = map[string]bool{
"ADD": true, "ADD": true,
"EXTERNAL": true, "EXTERNAL": true,
"PROCEDURE": true, "PROCEDURE": true,
"ALL": true, "ALL": true,
"FETCH": true, "FETCH": true,
"PUBLIC": true, "PUBLIC": true,
"ALTER": true, "ALTER": true,
"FILE": true, "FILE": true,
"RAISERROR": true, "RAISERROR": true,
"AND": true, "AND": true,
"FILLFACTOR": true, "FILLFACTOR": true,
"READ": true, "READ": true,
"ANY": true, "ANY": true,
"FOR": true, "FOR": true,
"READTEXT": true, "READTEXT": true,
"AS": true, "AS": true,
"FOREIGN": true, "FOREIGN": true,
"RECONFIGURE": true, "RECONFIGURE": true,
"ASC": true, "ASC": true,
"FREETEXT": true, "FREETEXT": true,
"REFERENCES": true, "REFERENCES": true,
"AUTHORIZATION": true, "AUTHORIZATION": true,
"FREETEXTTABLE": true, "FREETEXTTABLE": true,
"REPLICATION": true, "REPLICATION": true,
"BACKUP": true, "BACKUP": true,
"FROM": true, "FROM": true,
"RESTORE": true, "RESTORE": true,
"BEGIN": true, "BEGIN": true,
"FULL": true, "FULL": true,
"RESTRICT": true, "RESTRICT": true,
"BETWEEN": true, "BETWEEN": true,
"FUNCTION": true, "FUNCTION": true,
"RETURN": true, "RETURN": true,
"BREAK": true, "BREAK": true,
"GOTO": true, "GOTO": true,
"REVERT": true, "REVERT": true,
"BROWSE": true, "BROWSE": true,
"GRANT": true, "GRANT": true,
"REVOKE": true, "REVOKE": true,
"BULK": true, "BULK": true,
"GROUP": true, "GROUP": true,
"RIGHT": true, "RIGHT": true,
"BY": true, "BY": true,
"HAVING": true, "HAVING": true,
"ROLLBACK": true, "ROLLBACK": true,
"CASCADE": true, "CASCADE": true,
"HOLDLOCK": true, "HOLDLOCK": true,
"ROWCOUNT": true, "ROWCOUNT": true,
"CASE": true, "CASE": true,
"IDENTITY": true, "IDENTITY": true,
"ROWGUIDCOL": true, "ROWGUIDCOL": true,
"CHECK": true, "CHECK": true,
"IDENTITY_INSERT": true, "IDENTITY_INSERT": true,
"RULE": true, "RULE": true,
"CHECKPOINT": true, "CHECKPOINT": true,
"IDENTITYCOL": true, "IDENTITYCOL": true,
"SAVE": true, "SAVE": true,
"CLOSE": true, "CLOSE": true,
"IF": true, "IF": true,
"SCHEMA": true, "SCHEMA": true,
"CLUSTERED": true, "CLUSTERED": true,
"IN": true, "IN": true,
"SECURITYAUDIT": true, "SECURITYAUDIT": true,
"COALESCE": true, "COALESCE": true,
"INDEX": true, "INDEX": true,
"SELECT": true, "SELECT": true,
"COLLATE": true, "COLLATE": true,
"INNER": true, "INNER": true,
"SEMANTICKEYPHRASETABLE": true, "SEMANTICKEYPHRASETABLE": true,
"COLUMN": true, "COLUMN": true,
"INSERT": true, "INSERT": true,
"SEMANTICSIMILARITYDETAILSTABLE": true, "SEMANTICSIMILARITYDETAILSTABLE": true,
"COMMIT": true, "COMMIT": true,
"INTERSECT": true, "INTERSECT": true,
"SEMANTICSIMILARITYTABLE": true, "SEMANTICSIMILARITYTABLE": true,
"COMPUTE": true, "COMPUTE": true,
"INTO": true, "INTO": true,
"SESSION_USER": true, "SESSION_USER": true,
"CONSTRAINT": true, "CONSTRAINT": true,
"IS": true, "IS": true,
"SET": true, "SET": true,
"CONTAINS": true, "CONTAINS": true,
"JOIN": true, "JOIN": true,
"SETUSER": true, "SETUSER": true,
"CONTAINSTABLE": true, "CONTAINSTABLE": true,
"KEY": true, "KEY": true,
"SHUTDOWN": true, "SHUTDOWN": true,
"CONTINUE": true, "CONTINUE": true,
"KILL": true, "KILL": true,
"SOME": true, "SOME": true,
"CONVERT": true, "CONVERT": true,
"LEFT": true, "LEFT": true,
"STATISTICS": true, "STATISTICS": true,
"CREATE": true, "CREATE": true,
"LIKE": true, "LIKE": true,
"SYSTEM_USER": true, "SYSTEM_USER": true,
"CROSS": true, "CROSS": true,
"LINENO": true, "LINENO": true,
"TABLE": true, "TABLE": true,
"CURRENT": true, "CURRENT": true,
"LOAD": true, "LOAD": true,
"TABLESAMPLE": true, "TABLESAMPLE": true,
"CURRENT_DATE": true, "CURRENT_DATE": true,
"MERGE": true, "MERGE": true,
"TEXTSIZE": true, "TEXTSIZE": true,
"CURRENT_TIME": true, "CURRENT_TIME": true,
"NATIONAL": true, "NATIONAL": true,
"THEN": true, "THEN": true,
"CURRENT_TIMESTAMP": true, "CURRENT_TIMESTAMP": true,
"NOCHECK": true, "NOCHECK": true,
"TO": true, "TO": true,
"CURRENT_USER": true, "CURRENT_USER": true,
"NONCLUSTERED": true, "NONCLUSTERED": true,
"TOP": true, "TOP": true,
"CURSOR": true, "CURSOR": true,
"NOT": true, "NOT": true,
"TRAN": true, "TRAN": true,
"DATABASE": true, "DATABASE": true,
"NULL": true, "NULL": true,
"TRANSACTION": true, "TRANSACTION": true,
"DBCC": true, "DBCC": true,
"NULLIF": true, "NULLIF": true,
"TRIGGER": true, "TRIGGER": true,
"DEALLOCATE": true, "DEALLOCATE": true,
"OF": true, "OF": true,
"TRUNCATE": true, "TRUNCATE": true,
"DECLARE": true, "DECLARE": true,
"OFF": true, "OFF": true,
"TRY_CONVERT": true, "TRY_CONVERT": true,
"DEFAULT": true, "DEFAULT": true,
"OFFSETS": true, "OFFSETS": true,
"TSEQUAL": true, "TSEQUAL": true,
"DELETE": true, "DELETE": true,
"ON": true, "ON": true,
"UNION": true, "UNION": true,
"DENY": true, "DENY": true,
"OPEN": true, "OPEN": true,
"UNIQUE": true, "UNIQUE": true,
"DESC": true, "DESC": true,
"OPENDATASOURCE": true, "OPENDATASOURCE": true,
"UNPIVOT": true, "UNPIVOT": true,
"DISK": true, "DISK": true,
"OPENQUERY": true, "OPENQUERY": true,
"UPDATE": true, "UPDATE": true,
"DISTINCT": true, "DISTINCT": true,
"OPENROWSET": true, "OPENROWSET": true,
"UPDATETEXT": true, "UPDATETEXT": true,
"DISTRIBUTED": true, "DISTRIBUTED": true,
"OPENXML": true, "OPENXML": true,
"USE": true, "USE": true,
"DOUBLE": true, "DOUBLE": true,
"OPTION": true, "OPTION": true,
"USER": true, "USER": true,
"DROP": true, "DROP": true,
"OR": true, "OR": true,
"VALUES": true, "VALUES": true,
"DUMP": true, "DUMP": true,
"ORDER": true, "ORDER": true,
"VARYING": true, "VARYING": true,
"ELSE": true, "ELSE": true,
"OUTER": true, "OUTER": true,
"VIEW": true, "VIEW": true,
"END": true, "END": true,
"OVER": true, "OVER": true,
"WAITFOR": true, "WAITFOR": true,
"ERRLVL": true, "ERRLVL": true,
"PERCENT": true, "PERCENT": true,
"WHEN": true, "WHEN": true,
"ESCAPE": true, "ESCAPE": true,
"PIVOT": true, "PIVOT": true,
"WHERE": true, "WHERE": true,
"EXCEPT": true, "EXCEPT": true,
"PLAN": true, "PLAN": true,
"WHILE": true, "WHILE": true,
"EXEC": true, "EXEC": true,
"PRECISION": true, "PRECISION": true,
"WITH": true, "WITH": true,
"EXECUTE": true, "EXECUTE": true,
"PRIMARY": true, "PRIMARY": true,
"WITHIN": true, "WITHIN": true,
"EXISTS": true, "EXISTS": true,
"PRINT": true, "PRINT": true,
"WRITETEXT": true, "WRITETEXT": true,
"EXIT": true, "EXIT": true,
"PROC": true, "PROC": true,
} }
) )
@ -286,10 +286,6 @@ func (db *mssql) Quote(name string) string {
return "\"" + name + "\"" return "\"" + name + "\""
} }
func (db *mssql) QuoteStr() string {
return "\""
}
func (db *mssql) SupportEngine() bool { func (db *mssql) SupportEngine() bool {
return false return false
} }
@ -507,7 +503,7 @@ func (db *mssql) CreateTableSql(table *core.Table, tableName, storeEngine, chars
sql = "IF NOT EXISTS (SELECT [name] FROM sys.tables WHERE [name] = '" + tableName + "' ) CREATE TABLE " sql = "IF NOT EXISTS (SELECT [name] FROM sys.tables WHERE [name] = '" + tableName + "' ) CREATE TABLE "
sql += db.QuoteStr() + tableName + db.QuoteStr() + " (" sql += db.Quote(tableName) + " ("
pkList := table.PrimaryKeys pkList := table.PrimaryKeys

View File

@ -8,7 +8,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/go-xorm/core" "xorm.io/core"
) )
func TestParseMSSQL(t *testing.T) { func TestParseMSSQL(t *testing.T) {

View File

@ -13,7 +13,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
var ( var (
@ -220,7 +220,7 @@ func (db *mysql) SqlType(c *core.Column) string {
case core.TimeStampz: case core.TimeStampz:
res = core.Char res = core.Char
c.Length = 64 c.Length = 64
case core.Enum: //mysql enum case core.Enum: // mysql enum
res = core.Enum res = core.Enum
res += "(" res += "("
opts := "" opts := ""
@ -229,7 +229,7 @@ func (db *mysql) SqlType(c *core.Column) string {
} }
res += strings.TrimLeft(opts, ",") res += strings.TrimLeft(opts, ",")
res += ")" res += ")"
case core.Set: //mysql set case core.Set: // mysql set
res = core.Set res = core.Set
res += "(" res += "("
opts := "" opts := ""
@ -278,10 +278,6 @@ func (db *mysql) Quote(name string) string {
return "`" + name + "`" return "`" + name + "`"
} }
func (db *mysql) QuoteStr() string {
return "`"
}
func (db *mysql) SupportEngine() bool { func (db *mysql) SupportEngine() bool {
return true return true
} }
@ -360,7 +356,7 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column
var len1, len2 int var len1, len2 int
if len(cts) == 2 { if len(cts) == 2 {
idx := strings.Index(cts[1], ")") idx := strings.Index(cts[1], ")")
if colType == core.Enum && cts[1][0] == '\'' { //enum if colType == core.Enum && cts[1][0] == '\'' { // enum
options := strings.Split(cts[1][0:idx], ",") options := strings.Split(cts[1][0:idx], ",")
col.EnumOptions = make(map[string]int) col.EnumOptions = make(map[string]int)
for k, v := range options { for k, v := range options {
@ -408,7 +404,7 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column
col.IsPrimaryKey = true col.IsPrimaryKey = true
} }
if colKey == "UNI" { if colKey == "UNI" {
//col.is // col.is
} }
if extra == "auto_increment" { if extra == "auto_increment" {
@ -554,12 +550,10 @@ func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, chars
if len(charset) == 0 { if len(charset) == 0 {
charset = db.URI().Charset charset = db.URI().Charset
} }
if len(charset) != 0 { if len(charset) != 0 {
sql += " DEFAULT CHARSET " + charset sql += " DEFAULT CHARSET " + charset
} }
if db.rowFormat != "" { if db.rowFormat != "" {
sql += " ROW_FORMAT=" + db.rowFormat sql += " ROW_FORMAT=" + db.rowFormat
@ -633,7 +627,7 @@ func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error
`\/(?P<dbname>.*?)` + // /dbname `\/(?P<dbname>.*?)` + // /dbname
`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN] `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
matches := dsnPattern.FindStringSubmatch(dataSourceName) matches := dsnPattern.FindStringSubmatch(dataSourceName)
//tlsConfigRegister := make(map[string]*tls.Config) // tlsConfigRegister := make(map[string]*tls.Config)
names := dsnPattern.SubexpNames() names := dsnPattern.SubexpNames()
uri := &core.Uri{DbType: core.MYSQL} uri := &core.Uri{DbType: core.MYSQL}

View File

@ -11,7 +11,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/go-xorm/core" "xorm.io/core"
) )
var ( var (
@ -230,271 +230,271 @@ var (
"LOGGING": true, "LOGGING": true,
"LOGICAL_READS_PER_CALL": true, "LOGICAL_READS_PER_CALL": true,
"LOGICAL_READS_PER_SESSION": true, "LOGICAL_READS_PER_SESSION": true,
"LONG": true, "LONG": true,
"MANAGE": true, "MANAGE": true,
"MASTER": true, "MASTER": true,
"MAX": true, "MAX": true,
"MAXARCHLOGS": true, "MAXARCHLOGS": true,
"MAXDATAFILES": true, "MAXDATAFILES": true,
"MAXEXTENTS": true, "MAXEXTENTS": true,
"MAXINSTANCES": true, "MAXINSTANCES": true,
"MAXLOGFILES": true, "MAXLOGFILES": true,
"MAXLOGHISTORY": true, "MAXLOGHISTORY": true,
"MAXLOGMEMBERS": true, "MAXLOGMEMBERS": true,
"MAXSIZE": true, "MAXSIZE": true,
"MAXTRANS": true, "MAXTRANS": true,
"MAXVALUE": true, "MAXVALUE": true,
"MIN": true, "MIN": true,
"MEMBER": true, "MEMBER": true,
"MINIMUM": true, "MINIMUM": true,
"MINEXTENTS": true, "MINEXTENTS": true,
"MINUS": true, "MINUS": true,
"MINVALUE": true, "MINVALUE": true,
"MLSLABEL": true, "MLSLABEL": true,
"MLS_LABEL_FORMAT": true, "MLS_LABEL_FORMAT": true,
"MODE": true, "MODE": true,
"MODIFY": true, "MODIFY": true,
"MOUNT": true, "MOUNT": true,
"MOVE": true, "MOVE": true,
"MTS_DISPATCHERS": true, "MTS_DISPATCHERS": true,
"MULTISET": true, "MULTISET": true,
"NATIONAL": true, "NATIONAL": true,
"NCHAR": true, "NCHAR": true,
"NCHAR_CS": true, "NCHAR_CS": true,
"NCLOB": true, "NCLOB": true,
"NEEDED": true, "NEEDED": true,
"NESTED": true, "NESTED": true,
"NETWORK": true, "NETWORK": true,
"NEW": true, "NEW": true,
"NEXT": true, "NEXT": true,
"NOARCHIVELOG": true, "NOARCHIVELOG": true,
"NOAUDIT": true, "NOAUDIT": true,
"NOCACHE": true, "NOCACHE": true,
"NOCOMPRESS": true, "NOCOMPRESS": true,
"NOCYCLE": true, "NOCYCLE": true,
"NOFORCE": true, "NOFORCE": true,
"NOLOGGING": true, "NOLOGGING": true,
"NOMAXVALUE": true, "NOMAXVALUE": true,
"NOMINVALUE": true, "NOMINVALUE": true,
"NONE": true, "NONE": true,
"NOORDER": true, "NOORDER": true,
"NOOVERRIDE": true, "NOOVERRIDE": true,
"NOPARALLEL": true, "NOPARALLEL": true,
"NOREVERSE": true, "NOREVERSE": true,
"NORMAL": true, "NORMAL": true,
"NOSORT": true, "NOSORT": true,
"NOT": true, "NOT": true,
"NOTHING": true, "NOTHING": true,
"NOWAIT": true, "NOWAIT": true,
"NULL": true, "NULL": true,
"NUMBER": true, "NUMBER": true,
"NUMERIC": true, "NUMERIC": true,
"NVARCHAR2": true, "NVARCHAR2": true,
"OBJECT": true, "OBJECT": true,
"OBJNO": true, "OBJNO": true,
"OBJNO_REUSE": true, "OBJNO_REUSE": true,
"OF": true, "OF": true,
"OFF": true, "OFF": true,
"OFFLINE": true, "OFFLINE": true,
"OID": true, "OID": true,
"OIDINDEX": true, "OIDINDEX": true,
"OLD": true, "OLD": true,
"ON": true, "ON": true,
"ONLINE": true, "ONLINE": true,
"ONLY": true, "ONLY": true,
"OPCODE": true, "OPCODE": true,
"OPEN": true, "OPEN": true,
"OPTIMAL": true, "OPTIMAL": true,
"OPTIMIZER_GOAL": true, "OPTIMIZER_GOAL": true,
"OPTION": true, "OPTION": true,
"OR": true, "OR": true,
"ORDER": true, "ORDER": true,
"ORGANIZATION": true, "ORGANIZATION": true,
"OSLABEL": true, "OSLABEL": true,
"OVERFLOW": true, "OVERFLOW": true,
"OWN": true, "OWN": true,
"PACKAGE": true, "PACKAGE": true,
"PARALLEL": true, "PARALLEL": true,
"PARTITION": true, "PARTITION": true,
"PASSWORD": true, "PASSWORD": true,
"PASSWORD_GRACE_TIME": true, "PASSWORD_GRACE_TIME": true,
"PASSWORD_LIFE_TIME": true, "PASSWORD_LIFE_TIME": true,
"PASSWORD_LOCK_TIME": true, "PASSWORD_LOCK_TIME": true,
"PASSWORD_REUSE_MAX": true, "PASSWORD_REUSE_MAX": true,
"PASSWORD_REUSE_TIME": true, "PASSWORD_REUSE_TIME": true,
"PASSWORD_VERIFY_FUNCTION": true, "PASSWORD_VERIFY_FUNCTION": true,
"PCTFREE": true, "PCTFREE": true,
"PCTINCREASE": true, "PCTINCREASE": true,
"PCTTHRESHOLD": true, "PCTTHRESHOLD": true,
"PCTUSED": true, "PCTUSED": true,
"PCTVERSION": true, "PCTVERSION": true,
"PERCENT": true, "PERCENT": true,
"PERMANENT": true, "PERMANENT": true,
"PLAN": true, "PLAN": true,
"PLSQL_DEBUG": true, "PLSQL_DEBUG": true,
"POST_TRANSACTION": true, "POST_TRANSACTION": true,
"PRECISION": true, "PRECISION": true,
"PRESERVE": true, "PRESERVE": true,
"PRIMARY": true, "PRIMARY": true,
"PRIOR": true, "PRIOR": true,
"PRIVATE": true, "PRIVATE": true,
"PRIVATE_SGA": true, "PRIVATE_SGA": true,
"PRIVILEGE": true, "PRIVILEGE": true,
"PRIVILEGES": true, "PRIVILEGES": true,
"PROCEDURE": true, "PROCEDURE": true,
"PROFILE": true, "PROFILE": true,
"PUBLIC": true, "PUBLIC": true,
"PURGE": true, "PURGE": true,
"QUEUE": true, "QUEUE": true,
"QUOTA": true, "QUOTA": true,
"RANGE": true, "RANGE": true,
"RAW": true, "RAW": true,
"RBA": true, "RBA": true,
"READ": true, "READ": true,
"READUP": true, "READUP": true,
"REAL": true, "REAL": true,
"REBUILD": true, "REBUILD": true,
"RECOVER": true, "RECOVER": true,
"RECOVERABLE": true, "RECOVERABLE": true,
"RECOVERY": true, "RECOVERY": true,
"REF": true, "REF": true,
"REFERENCES": true, "REFERENCES": true,
"REFERENCING": true, "REFERENCING": true,
"REFRESH": true, "REFRESH": true,
"RENAME": true, "RENAME": true,
"REPLACE": true, "REPLACE": true,
"RESET": true, "RESET": true,
"RESETLOGS": true, "RESETLOGS": true,
"RESIZE": true, "RESIZE": true,
"RESOURCE": true, "RESOURCE": true,
"RESTRICTED": true, "RESTRICTED": true,
"RETURN": true, "RETURN": true,
"RETURNING": true, "RETURNING": true,
"REUSE": true, "REUSE": true,
"REVERSE": true, "REVERSE": true,
"REVOKE": true, "REVOKE": true,
"ROLE": true, "ROLE": true,
"ROLES": true, "ROLES": true,
"ROLLBACK": true, "ROLLBACK": true,
"ROW": true, "ROW": true,
"ROWID": true, "ROWID": true,
"ROWNUM": true, "ROWNUM": true,
"ROWS": true, "ROWS": true,
"RULE": true, "RULE": true,
"SAMPLE": true, "SAMPLE": true,
"SAVEPOINT": true, "SAVEPOINT": true,
"SB4": true, "SB4": true,
"SCAN_INSTANCES": true, "SCAN_INSTANCES": true,
"SCHEMA": true, "SCHEMA": true,
"SCN": true, "SCN": true,
"SCOPE": true, "SCOPE": true,
"SD_ALL": true, "SD_ALL": true,
"SD_INHIBIT": true, "SD_INHIBIT": true,
"SD_SHOW": true, "SD_SHOW": true,
"SEGMENT": true, "SEGMENT": true,
"SEG_BLOCK": true, "SEG_BLOCK": true,
"SEG_FILE": true, "SEG_FILE": true,
"SELECT": true, "SELECT": true,
"SEQUENCE": true, "SEQUENCE": true,
"SERIALIZABLE": true, "SERIALIZABLE": true,
"SESSION": true, "SESSION": true,
"SESSION_CACHED_CURSORS": true, "SESSION_CACHED_CURSORS": true,
"SESSIONS_PER_USER": true, "SESSIONS_PER_USER": true,
"SET": true, "SET": true,
"SHARE": true, "SHARE": true,
"SHARED": true, "SHARED": true,
"SHARED_POOL": true, "SHARED_POOL": true,
"SHRINK": true, "SHRINK": true,
"SIZE": true, "SIZE": true,
"SKIP": true, "SKIP": true,
"SKIP_UNUSABLE_INDEXES": true, "SKIP_UNUSABLE_INDEXES": true,
"SMALLINT": true, "SMALLINT": true,
"SNAPSHOT": true, "SNAPSHOT": true,
"SOME": true, "SOME": true,
"SORT": true, "SORT": true,
"SPECIFICATION": true, "SPECIFICATION": true,
"SPLIT": true, "SPLIT": true,
"SQL_TRACE": true, "SQL_TRACE": true,
"STANDBY": true, "STANDBY": true,
"START": true, "START": true,
"STATEMENT_ID": true, "STATEMENT_ID": true,
"STATISTICS": true, "STATISTICS": true,
"STOP": true, "STOP": true,
"STORAGE": true, "STORAGE": true,
"STORE": true, "STORE": true,
"STRUCTURE": true, "STRUCTURE": true,
"SUCCESSFUL": true, "SUCCESSFUL": true,
"SWITCH": true, "SWITCH": true,
"SYS_OP_ENFORCE_NOT_NULL$": true, "SYS_OP_ENFORCE_NOT_NULL$": true,
"SYS_OP_NTCIMG$": true, "SYS_OP_NTCIMG$": true,
"SYNONYM": true, "SYNONYM": true,
"SYSDATE": true, "SYSDATE": true,
"SYSDBA": true, "SYSDBA": true,
"SYSOPER": true, "SYSOPER": true,
"SYSTEM": true, "SYSTEM": true,
"TABLE": true, "TABLE": true,
"TABLES": true, "TABLES": true,
"TABLESPACE": true, "TABLESPACE": true,
"TABLESPACE_NO": true, "TABLESPACE_NO": true,
"TABNO": true, "TABNO": true,
"TEMPORARY": true, "TEMPORARY": true,
"THAN": true, "THAN": true,
"THE": true, "THE": true,
"THEN": true, "THEN": true,
"THREAD": true, "THREAD": true,
"TIMESTAMP": true, "TIMESTAMP": true,
"TIME": true, "TIME": true,
"TO": true, "TO": true,
"TOPLEVEL": true, "TOPLEVEL": true,
"TRACE": true, "TRACE": true,
"TRACING": true, "TRACING": true,
"TRANSACTION": true, "TRANSACTION": true,
"TRANSITIONAL": true, "TRANSITIONAL": true,
"TRIGGER": true, "TRIGGER": true,
"TRIGGERS": true, "TRIGGERS": true,
"TRUE": true, "TRUE": true,
"TRUNCATE": true, "TRUNCATE": true,
"TX": true, "TX": true,
"TYPE": true, "TYPE": true,
"UB2": true, "UB2": true,
"UBA": true, "UBA": true,
"UID": true, "UID": true,
"UNARCHIVED": true, "UNARCHIVED": true,
"UNDO": true, "UNDO": true,
"UNION": true, "UNION": true,
"UNIQUE": true, "UNIQUE": true,
"UNLIMITED": true, "UNLIMITED": true,
"UNLOCK": true, "UNLOCK": true,
"UNRECOVERABLE": true, "UNRECOVERABLE": true,
"UNTIL": true, "UNTIL": true,
"UNUSABLE": true, "UNUSABLE": true,
"UNUSED": true, "UNUSED": true,
"UPDATABLE": true, "UPDATABLE": true,
"UPDATE": true, "UPDATE": true,
"USAGE": true, "USAGE": true,
"USE": true, "USE": true,
"USER": true, "USER": true,
"USING": true, "USING": true,
"VALIDATE": true, "VALIDATE": true,
"VALIDATION": true, "VALIDATION": true,
"VALUE": true, "VALUE": true,
"VALUES": true, "VALUES": true,
"VARCHAR": true, "VARCHAR": true,
"VARCHAR2": true, "VARCHAR2": true,
"VARYING": true, "VARYING": true,
"VIEW": true, "VIEW": true,
"WHEN": true, "WHEN": true,
"WHENEVER": true, "WHENEVER": true,
"WHERE": true, "WHERE": true,
"WITH": true, "WITH": true,
"WITHOUT": true, "WITHOUT": true,
"WORK": true, "WORK": true,
"WRITE": true, "WRITE": true,
"WRITEDOWN": true, "WRITEDOWN": true,
"WRITEUP": true, "WRITEUP": true,
"XID": true, "XID": true,
"YEAR": true, "YEAR": true,
"ZONE": true, "ZONE": true,
} }
) )
@ -552,11 +552,7 @@ func (db *oracle) IsReserved(name string) bool {
} }
func (db *oracle) Quote(name string) string { func (db *oracle) Quote(name string) string {
return "\"" + name + "\"" return "[" + name + "]"
}
func (db *oracle) QuoteStr() string {
return "\""
} }
func (db *oracle) SupportEngine() bool { func (db *oracle) SupportEngine() bool {
@ -596,7 +592,7 @@ func (db *oracle) CreateTableSql(table *core.Table, tableName, storeEngine, char
sql += col.String(b.dialect) sql += col.String(b.dialect)
} else {*/ } else {*/
sql += col.StringNoPk(db) sql += col.StringNoPk(db)
//} // }
sql = strings.TrimSpace(sql) sql = strings.TrimSpace(sql)
sql += ", " sql += ", "
} }
@ -865,7 +861,7 @@ func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, e
`\/(?P<dbname>.*?)` + // /dbname `\/(?P<dbname>.*?)` + // /dbname
`(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN] `(?:\?(?P<params>[^\?]*))?$`) // [?param1=value1&paramN=valueN]
matches := dsnPattern.FindStringSubmatch(dataSourceName) matches := dsnPattern.FindStringSubmatch(dataSourceName)
//tlsConfigRegister := make(map[string]*tls.Config) // tlsConfigRegister := make(map[string]*tls.Config)
names := dsnPattern.SubexpNames() names := dsnPattern.SubexpNames()
for i, match := range matches { for i, match := range matches {
@ -883,8 +879,8 @@ func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, e
type oci8Driver struct { type oci8Driver struct {
} }
//dataSourceName=user/password@ipv4:port/dbname // dataSourceName=user/password@ipv4:port/dbname
//dataSourceName=user/password@[ipv6]:port/dbname // dataSourceName=user/password@[ipv6]:port/dbname
func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
db := &core.Uri{DbType: core.ORACLE} db := &core.Uri{DbType: core.ORACLE}
dsnPattern := regexp.MustCompile( dsnPattern := regexp.MustCompile(

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/jackc/pgx/stdlib" "github.com/jackc/pgx/stdlib"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -11,7 +11,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/go-xorm/core" "xorm.io/core"
) )
var ( var (
@ -202,10 +202,6 @@ func (db *sqlite3) Quote(name string) string {
return "`" + name + "`" return "`" + name + "`"
} }
func (db *sqlite3) QuoteStr() string {
return "`"
}
func (db *sqlite3) AutoIncrStr() string { func (db *sqlite3) AutoIncrStr() string {
return "AUTOINCREMENT" return "AUTOINCREMENT"
} }

View File

@ -20,8 +20,8 @@ import (
"sync" "sync"
"time" "time"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Engine is the major struct of xorm, it means a database manager. // Engine is the major struct of xorm, it means a database manager.
@ -125,6 +125,7 @@ func (engine *Engine) Logger() core.ILogger {
// SetLogger set the new logger // SetLogger set the new logger
func (engine *Engine) SetLogger(logger core.ILogger) { func (engine *Engine) SetLogger(logger core.ILogger) {
engine.logger = logger engine.logger = logger
engine.showSQL = logger.IsShowSQL()
engine.dialect.SetLogger(logger) engine.dialect.SetLogger(logger)
} }
@ -174,12 +175,6 @@ func (engine *Engine) SupportInsertMany() bool {
return engine.dialect.SupportInsertMany() return engine.dialect.SupportInsertMany()
} }
// QuoteStr Engine's database use which character as quote.
// mysql, sqlite use ` and postgres use "
func (engine *Engine) QuoteStr() string {
return engine.dialect.QuoteStr()
}
func (engine *Engine) quoteColumns(columnStr string) string { func (engine *Engine) quoteColumns(columnStr string) string {
columns := strings.Split(columnStr, ",") columns := strings.Split(columnStr, ",")
for i := 0; i < len(columns); i++ { for i := 0; i < len(columns); i++ {
@ -195,13 +190,10 @@ func (engine *Engine) Quote(value string) string {
return value return value
} }
if string(value[0]) == engine.dialect.QuoteStr() || value[0] == '`' { buf := builder.StringBuilder{}
return value engine.QuoteTo(&buf, value)
}
value = strings.Replace(value, ".", engine.dialect.QuoteStr()+"."+engine.dialect.QuoteStr(), -1) return buf.String()
return engine.dialect.QuoteStr() + value + engine.dialect.QuoteStr()
} }
// QuoteTo quotes string and writes into the buffer // QuoteTo quotes string and writes into the buffer
@ -215,20 +207,30 @@ func (engine *Engine) QuoteTo(buf *builder.StringBuilder, value string) {
return return
} }
if string(value[0]) == engine.dialect.QuoteStr() || value[0] == '`' { quotePair := engine.dialect.Quote("")
buf.WriteString(value)
if value[0] == '`' || len(quotePair) < 2 || value[0] == quotePair[0] { // no quote
_, _ = buf.WriteString(value)
return return
} else {
prefix, suffix := quotePair[0], quotePair[1]
_ = buf.WriteByte(prefix)
for i := 0; i < len(value); i++ {
if value[i] == '.' {
_ = buf.WriteByte(suffix)
_ = buf.WriteByte('.')
_ = buf.WriteByte(prefix)
} else {
_ = buf.WriteByte(value[i])
}
}
_ = buf.WriteByte(suffix)
} }
value = strings.Replace(value, ".", engine.dialect.QuoteStr()+"."+engine.dialect.QuoteStr(), -1)
buf.WriteString(engine.dialect.QuoteStr())
buf.WriteString(value)
buf.WriteString(engine.dialect.QuoteStr())
} }
func (engine *Engine) quote(sql string) string { func (engine *Engine) quote(sql string) string {
return engine.dialect.QuoteStr() + sql + engine.dialect.QuoteStr() return engine.dialect.Quote(sql)
} }
// SqlType will be deprecated, please use SQLType instead // SqlType will be deprecated, please use SQLType instead
@ -922,7 +924,16 @@ func (engine *Engine) mapType(v reflect.Value) (*core.Table, error) {
engine: engine, engine: engine,
} }
if strings.ToUpper(tags[0]) == "EXTENDS" { if strings.HasPrefix(strings.ToUpper(tags[0]), "EXTENDS") {
pStart := strings.Index(tags[0], "(")
if pStart > -1 && strings.HasSuffix(tags[0], ")") {
var tagPrefix = strings.TrimFunc(tags[0][pStart+1:len(tags[0])-1], func(r rune) bool {
return r == '\'' || r == '"'
})
ctx.params = []string{tagPrefix}
}
if err := ExtendsTagHandler(&ctx); err != nil { if err := ExtendsTagHandler(&ctx); err != nil {
return nil, err return nil, err
} }
@ -1354,31 +1365,31 @@ func (engine *Engine) DropIndexes(bean interface{}) error {
} }
// Exec raw sql // Exec raw sql
func (engine *Engine) Exec(sqlorArgs ...interface{}) (sql.Result, error) { func (engine *Engine) Exec(sqlOrArgs ...interface{}) (sql.Result, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Exec(sqlorArgs...) return session.Exec(sqlOrArgs...)
} }
// Query a raw sql and return records as []map[string][]byte // Query a raw sql and return records as []map[string][]byte
func (engine *Engine) Query(sqlorArgs ...interface{}) (resultsSlice []map[string][]byte, err error) { func (engine *Engine) Query(sqlOrArgs ...interface{}) (resultsSlice []map[string][]byte, err error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Query(sqlorArgs...) return session.Query(sqlOrArgs...)
} }
// QueryString runs a raw sql and return records as []map[string]string // QueryString runs a raw sql and return records as []map[string]string
func (engine *Engine) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) { func (engine *Engine) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.QueryString(sqlorArgs...) return session.QueryString(sqlOrArgs...)
} }
// QueryInterface runs a raw sql and return records as []map[string]interface{} // QueryInterface runs a raw sql and return records as []map[string]interface{}
func (engine *Engine) QueryInterface(sqlorArgs ...interface{}) ([]map[string]interface{}, error) { func (engine *Engine) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.QueryInterface(sqlorArgs...) return session.QueryInterface(sqlOrArgs...)
} }
// Insert one or more records // Insert one or more records
@ -1571,7 +1582,7 @@ func (engine *Engine) formatColTime(col *core.Column, t time.Time) (v interface{
func (engine *Engine) formatTime(sqlTypeName string, t time.Time) (v interface{}) { func (engine *Engine) formatTime(sqlTypeName string, t time.Time) (v interface{}) {
switch sqlTypeName { switch sqlTypeName {
case core.Time: case core.Time:
s := t.Format("2006-01-02 15:04:05") //time.RFC3339 s := t.Format("2006-01-02 15:04:05") // time.RFC3339
v = s[11:19] v = s[11:19]
case core.Date: case core.Date:
v = t.Format("2006-01-02") v = t.Format("2006-01-02")

View File

@ -11,8 +11,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
func (engine *Engine) buildConds(table *core.Table, bean interface{}, func (engine *Engine) buildConds(table *core.Table, bean interface{},

View File

@ -20,6 +20,8 @@ func TestPingContext(t *testing.T) {
ctx, canceled := context.WithTimeout(context.Background(), time.Nanosecond) ctx, canceled := context.WithTimeout(context.Background(), time.Nanosecond)
defer canceled() defer canceled()
time.Sleep(time.Nanosecond)
err := testEngine.(*Engine).PingContext(ctx) err := testEngine.(*Engine).PingContext(ctx)
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, err.Error(), "context deadline exceeded") assert.Contains(t, err.Error(), "context deadline exceeded")

View File

@ -8,7 +8,7 @@ import (
"context" "context"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
// EngineGroup defines an engine group // EngineGroup defines an engine group

View File

@ -9,7 +9,7 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/go-xorm/core" "xorm.io/core"
) )
// tbNameWithSchema will automatically add schema prefix on table name // tbNameWithSchema will automatically add schema prefix on table name

12
go.mod
View File

@ -1,15 +1,9 @@
module github.com/go-xorm/xorm module github.com/go-xorm/xorm
require ( require (
cloud.google.com/go v0.34.0 // indirect
github.com/cockroachdb/apd v1.1.0 // indirect github.com/cockroachdb/apd v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4
github.com/denisenkom/go-mssqldb v0.0.0-20190121005146-b04fd42d9952
github.com/go-sql-driver/mysql v1.4.1 github.com/go-sql-driver/mysql v1.4.1
github.com/go-xorm/builder v0.3.3
github.com/go-xorm/core v0.6.2
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a // indirect
github.com/google/go-cmp v0.2.0 // indirect
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 // indirect
github.com/jackc/pgx v3.3.0+incompatible github.com/jackc/pgx v3.3.0+incompatible
github.com/kr/pretty v0.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect
@ -20,6 +14,6 @@ require (
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 // indirect
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
github.com/ziutek/mymysql v1.5.4 github.com/ziutek/mymysql v1.5.4
golang.org/x/crypto v0.0.0-20190122013713-64072686203f // indirect xorm.io/builder v0.3.5
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect xorm.io/core v0.7.0
) )

120
go.sum
View File

@ -1,28 +1,61 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.37.4 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.0.0-20190121005146-b04fd42d9952 h1:b5OnbZD49x9g+/FcYbs/vukEt8C/jUbGhCJ3uduQmu8= github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 h1:YcpmyvADGYw5LqMnHqSkyIELsHCGF6PkrmM31V8rF7o=
github.com/denisenkom/go-mssqldb v0.0.0-20190121005146-b04fd42d9952/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-xorm/builder v0.3.3 h1:v8grgrwOGv/iHXIEhIvOwHZIPLrpxRKSX8yWSMLFn/4= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-xorm/builder v0.3.3/go.mod h1:v8mE3MFBgtL+RGFNfUnAMUqqfk/Y4W5KuwCFQIEpQLk=
github.com/go-xorm/core v0.6.2 h1:EJLcSxf336POJr670wKB55Mah9f93xzvGYzNRgnT8/Y=
github.com/go-xorm/core v0.6.2/go.mod h1:bwPIfLdm/FzWgVUH8WPVlr+uJhscvNGFcaZKXsI3n2c=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733 h1:vr3AYkKovP8uR8AvSGGUK1IDqRa5lAAvEkZG1LKaCRc=
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ= github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
github.com/jackc/pgx v3.3.0+incompatible h1:Wa90/+qsITBAPkAZjiByeIGHFcj3Ztu+VzrrIpHjL90= github.com/jackc/pgx v3.3.0+incompatible h1:Wa90/+qsITBAPkAZjiByeIGHFcj3Ztu+VzrrIpHjL90=
github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I= github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -32,24 +65,95 @@ github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t43dCZ5dqY4YTJCObLY1kIXl0uzMv+7DE=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
golang.org/x/crypto v0.0.0-20190122013713-64072686203f h1:u1CmMhe3a44hy8VIgpInORnI01UVaUYheqR7x9BxT3c= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
golang.org/x/crypto v0.0.0-20190122013713-64072686203f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
xorm.io/builder v0.3.5 h1:EilU39fvWDxjb1cDaELpYhsF+zziRBhew8xk4pngO+A=
xorm.io/builder v0.3.5/go.mod h1:ZFbByS/KxZI1FKRjL05PyJ4YrK2bcxlUaAxdum5aTR8=
xorm.io/core v0.6.3 h1:n1NhVZt1s2oLw1BZfX2ocIJsHyso259uPgg63BGr37M=
xorm.io/core v0.6.3/go.mod h1:8kz/C6arVW/O9vk3PgCiMJO2hIAm1UcuOL3dSPyZ2qo=

View File

@ -12,7 +12,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/go-xorm/core" "xorm.io/core"
) )
// str2PK convert string value to primary key value according to tp // str2PK convert string value to primary key value according to tp
@ -281,7 +281,7 @@ func rValue(bean interface{}) reflect.Value {
func rType(bean interface{}) reflect.Type { func rType(bean interface{}) reflect.Type {
sliceValue := reflect.Indirect(reflect.ValueOf(bean)) sliceValue := reflect.Indirect(reflect.ValueOf(bean))
//return reflect.TypeOf(sliceValue.Interface()) // return reflect.TypeOf(sliceValue.Interface())
return sliceValue.Type() return sliceValue.Type()
} }
@ -309,3 +309,24 @@ func sliceEq(left, right []string) bool {
func indexName(tableName, idxName string) string { func indexName(tableName, idxName string) string {
return fmt.Sprintf("IDX_%v_%v", tableName, idxName) return fmt.Sprintf("IDX_%v_%v", tableName, idxName)
} }
func eraseAny(value string, strToErase ...string) string {
if len(strToErase) == 0 {
return value
}
var replaceSeq []string
for _, s := range strToErase {
replaceSeq = append(replaceSeq, s, "")
}
replacer := strings.NewReplacer(replaceSeq...)
return replacer.Replace(value)
}
func quoteColumns(cols []string, quoteFunc func(string) string, sep string) string {
for i := range cols {
cols[i] = quoteFunc(cols[i])
}
return strings.Join(cols, sep+" ")
}

View File

@ -4,7 +4,11 @@
package xorm package xorm
import "testing" import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestSplitTag(t *testing.T) { func TestSplitTag(t *testing.T) {
var cases = []struct { var cases = []struct {
@ -24,3 +28,19 @@ func TestSplitTag(t *testing.T) {
} }
} }
} }
func TestEraseAny(t *testing.T) {
raw := "SELECT * FROM `table`.[table_name]"
assert.EqualValues(t, raw, eraseAny(raw))
assert.EqualValues(t, "SELECT * FROM table.[table_name]", eraseAny(raw, "`"))
assert.EqualValues(t, "SELECT * FROM table.table_name", eraseAny(raw, "`", "[", "]"))
}
func TestQuoteColumns(t *testing.T) {
cols := []string{"f1", "f2", "f3"}
quoteFunc := func(value string) string {
return "[" + value + "]"
}
assert.EqualValues(t, "[f1], [f2], [f3]", quoteColumns(cols, quoteFunc, ","))
}

View File

@ -10,7 +10,7 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Interface defines the interface which Engine, EngineGroup and Session will implementate. // Interface defines the interface which Engine, EngineGroup and Session will implementate.
@ -28,7 +28,7 @@ type Interface interface {
Delete(interface{}) (int64, error) Delete(interface{}) (int64, error)
Distinct(columns ...string) *Session Distinct(columns ...string) *Session
DropIndexes(bean interface{}) error DropIndexes(bean interface{}) error
Exec(sqlOrAgrs ...interface{}) (sql.Result, error) Exec(sqlOrArgs ...interface{}) (sql.Result, error)
Exist(bean ...interface{}) (bool, error) Exist(bean ...interface{}) (bool, error)
Find(interface{}, ...interface{}) error Find(interface{}, ...interface{}) error
FindAndCount(interface{}, ...interface{}) (int64, error) FindAndCount(interface{}, ...interface{}) (int64, error)
@ -50,9 +50,9 @@ type Interface interface {
Omit(columns ...string) *Session Omit(columns ...string) *Session
OrderBy(order string) *Session OrderBy(order string) *Session
Ping() error Ping() error
Query(sqlOrAgrs ...interface{}) (resultsSlice []map[string][]byte, err error) Query(sqlOrArgs ...interface{}) (resultsSlice []map[string][]byte, err error)
QueryInterface(sqlorArgs ...interface{}) ([]map[string]interface{}, error) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error)
QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error)
Rows(bean interface{}) (*Rows, error) Rows(bean interface{}) (*Rows, error)
SetExpr(string, string) *Session SetExpr(string, string) *Session
SQL(interface{}, ...interface{}) *Session SQL(interface{}, ...interface{}) *Session

View File

@ -9,7 +9,7 @@ import (
"io" "io"
"log" "log"
"github.com/go-xorm/core" "xorm.io/core"
) )
// default log options // default log options

16
rows.go
View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Rows rows wrapper a rows to // Rows rows wrapper a rows to
@ -113,17 +113,9 @@ func (rows *Rows) Close() error {
defer rows.session.Close() defer rows.session.Close()
} }
if rows.lastError == nil { if rows.rows != nil {
if rows.rows != nil { return rows.rows.Close()
rows.lastError = rows.rows.Close()
if rows.lastError != nil {
return rows.lastError
}
}
} else {
if rows.rows != nil {
defer rows.rows.Close()
}
} }
return rows.lastError return rows.lastError
} }

View File

@ -38,6 +38,22 @@ func TestRows(t *testing.T) {
cnt++ cnt++
} }
assert.EqualValues(t, 1, cnt) assert.EqualValues(t, 1, cnt)
assert.False(t, rows.Next())
assert.NoError(t, rows.Close())
rows0, err := testEngine.Where("1>1").Rows(new(UserRows))
assert.NoError(t, err)
defer rows0.Close()
cnt = 0
user0 := new(UserRows)
for rows0.Next() {
err = rows0.Scan(user0)
assert.NoError(t, err)
cnt++
}
assert.EqualValues(t, 0, cnt)
assert.NoError(t, rows0.Close())
sess := testEngine.NewSession() sess := testEngine.NewSession()
defer sess.Close() defer sess.Close()

View File

@ -14,7 +14,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
type sessionType int type sessionType int

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
type incrParam struct { type incrParam struct {

View File

@ -7,7 +7,7 @@ package xorm
import ( import (
"testing" "testing"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -4,7 +4,7 @@
package xorm package xorm
import "github.com/go-xorm/builder" import "xorm.io/builder"
// Sql provides raw sql input parameter. When you have a complex SQL statement // 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. // and cannot use Where, Id, In and etc. Methods to describe, you can use SQL.

View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -26,6 +26,9 @@ func TestQueryContext(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond) ctx, cancel := context.WithTimeout(context.Background(), time.Nanosecond)
defer cancel() defer cancel()
time.Sleep(time.Nanosecond)
has, err := testEngine.Context(ctx).Exist(&ContextQueryStruct{Name: "1"}) has, err := testEngine.Context(ctx).Exist(&ContextQueryStruct{Name: "1"})
assert.Error(t, err) assert.Error(t, err)
assert.Contains(t, err.Error(), "context deadline exceeded") assert.Contains(t, err.Error(), "context deadline exceeded")

View File

@ -14,7 +14,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
func (session *Session) str2Time(col *core.Column, data string) (outTime time.Time, outErr error) { func (session *Session) str2Time(col *core.Column, data string) (outTime time.Time, outErr error) {
@ -643,7 +643,7 @@ func (session *Session) value2Interface(col *core.Column, fieldValue reflect.Val
} else if col.SQLType.IsBlob() { } else if col.SQLType.IsBlob() {
var bytes []byte var bytes []byte
var err error var err error
if (k == reflect.Array || k == reflect.Slice) && if (k == reflect.Slice) &&
(fieldValue.Type().Elem().Kind() == reflect.Uint8) { (fieldValue.Type().Elem().Kind() == reflect.Uint8) {
bytes = fieldValue.Bytes() bytes = fieldValue.Bytes()
} else { } else {

View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"github.com/go-xorm/core" "xorm.io/core"
) )
func (session *Session) cacheDelete(table *core.Table, tableName, sqlStr string, args ...interface{}) error { func (session *Session) cacheDelete(table *core.Table, tableName, sqlStr string, args ...interface{}) error {

View File

@ -8,7 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -9,8 +9,8 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Exist returns true if the record exist otherwise return false // Exist returns true if the record exist otherwise return false

View File

@ -10,8 +10,8 @@ import (
"reflect" "reflect"
"strings" "strings"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
const ( const (

View File

@ -10,7 +10,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -11,7 +11,7 @@ import (
"reflect" "reflect"
"strconv" "strconv"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Get retrieve one record from database, bean's non-empty fields // Get retrieve one record from database, bean's non-empty fields
@ -114,6 +114,114 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bea
return true, rows.Scan(&bean) return true, rows.Scan(&bean)
case *sql.NullInt64, *sql.NullBool, *sql.NullFloat64, *sql.NullString: case *sql.NullInt64, *sql.NullBool, *sql.NullFloat64, *sql.NullString:
return true, rows.Scan(bean) return true, rows.Scan(bean)
case *string:
var res sql.NullString
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*string)) = res.String
}
return true, nil
case *int:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*int)) = int(res.Int64)
}
return true, nil
case *int8:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*int8)) = int8(res.Int64)
}
return true, nil
case *int16:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*int16)) = int16(res.Int64)
}
return true, nil
case *int32:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*int32)) = int32(res.Int64)
}
return true, nil
case *int64:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*int64)) = int64(res.Int64)
}
return true, nil
case *uint:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*uint)) = uint(res.Int64)
}
return true, nil
case *uint8:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*uint8)) = uint8(res.Int64)
}
return true, nil
case *uint16:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*uint16)) = uint16(res.Int64)
}
return true, nil
case *uint32:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*uint32)) = uint32(res.Int64)
}
return true, nil
case *uint64:
var res sql.NullInt64
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*uint64)) = uint64(res.Int64)
}
return true, nil
case *bool:
var res sql.NullBool
if err := rows.Scan(&res); err != nil {
return true, err
}
if res.Valid {
*(bean.(*bool)) = res.Bool
}
return true, nil
} }
switch beanKind { switch beanKind {
@ -142,6 +250,9 @@ func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bea
err = rows.ScanSlice(bean) err = rows.ScanSlice(bean)
case reflect.Map: case reflect.Map:
err = rows.ScanMap(bean) err = rows.ScanMap(bean)
case reflect.String, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
err = rows.Scan(&bean)
default: default:
err = rows.Scan(bean) err = rows.Scan(bean)
} }

View File

@ -10,8 +10,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"xorm.io/core"
) )
func TestGetVar(t *testing.T) { func TestGetVar(t *testing.T) {
@ -47,6 +47,12 @@ func TestGetVar(t *testing.T) {
assert.Equal(t, true, has) assert.Equal(t, true, has)
assert.Equal(t, 28, age) assert.Equal(t, 28, age)
var ageMax int
has, err = testEngine.SQL("SELECT max(age) FROM "+testEngine.TableName("get_var", true)+" WHERE `id` = ?", data.Id).Get(&ageMax)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.Equal(t, 28, ageMax)
var age2 int64 var age2 int64
has, err = testEngine.Table("get_var").Cols("age"). has, err = testEngine.Table("get_var").Cols("age").
Where("age > ?", 20). Where("age > ?", 20).
@ -56,6 +62,69 @@ func TestGetVar(t *testing.T) {
assert.Equal(t, true, has) assert.Equal(t, true, has)
assert.EqualValues(t, 28, age2) assert.EqualValues(t, 28, age2)
var age3 int8
has, err = testEngine.Table("get_var").Cols("age").Get(&age3)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age3)
var age4 int16
has, err = testEngine.Table("get_var").Cols("age").
Where("age > ?", 20).
And("age < ?", 30).
Get(&age4)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age4)
var age5 int32
has, err = testEngine.Table("get_var").Cols("age").
Where("age > ?", 20).
And("age < ?", 30).
Get(&age5)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age5)
var age6 int
has, err = testEngine.Table("get_var").Cols("age").Get(&age6)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age6)
var age7 int64
has, err = testEngine.Table("get_var").Cols("age").
Where("age > ?", 20).
And("age < ?", 30).
Get(&age7)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age7)
var age8 int8
has, err = testEngine.Table("get_var").Cols("age").Get(&age8)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age8)
var age9 int16
has, err = testEngine.Table("get_var").Cols("age").
Where("age > ?", 20).
And("age < ?", 30).
Get(&age9)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age9)
var age10 int32
has, err = testEngine.Table("get_var").Cols("age").
Where("age > ?", 20).
And("age < ?", 30).
Get(&age10)
assert.NoError(t, err)
assert.Equal(t, true, has)
assert.EqualValues(t, 28, age10)
var id sql.NullInt64 var id sql.NullInt64
has, err = testEngine.Table("get_var").Cols("id").Get(&id) has, err = testEngine.Table("get_var").Cols("id").Get(&id)
assert.NoError(t, err) assert.NoError(t, err)
@ -433,3 +502,85 @@ func TestGetCustomTableInterface(t *testing.T) {
assert.NoError(t, err) assert.NoError(t, err)
assert.True(t, has) assert.True(t, has)
} }
func TestGetNullVar(t *testing.T) {
type TestGetNullVarStruct struct {
Id int64
Name string
Age int
}
assert.NoError(t, prepareEngine())
assertSync(t, new(TestGetNullVarStruct))
affected, err := testEngine.Exec("insert into " + testEngine.TableName(new(TestGetNullVarStruct), true) + " (name,age) values (null,null)")
assert.NoError(t, err)
a, _ := affected.RowsAffected()
assert.EqualValues(t, 1, a)
var name string
has, err := testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("name").Get(&name)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, "", name)
var age int
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age)
var age2 int8
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age2)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age2)
var age3 int16
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age3)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age3)
var age4 int32
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age4)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age4)
var age5 int64
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age5)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age5)
var age6 uint
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age6)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age6)
var age7 uint8
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age7)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age7)
var age8 int16
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age8)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age8)
var age9 int32
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age9)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age9)
var age10 int64
has, err = testEngine.Table(new(TestGetNullVarStruct)).Where("id = ?", 1).Cols("age").Get(&age10)
assert.NoError(t, err)
assert.True(t, has)
assert.EqualValues(t, 0, age10)
}

View File

@ -12,7 +12,7 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Insert insert one or more beans // Insert insert one or more beans
@ -242,23 +242,17 @@ func (session *Session) innerInsertMulti(rowsSlicePtr interface{}) (int64, error
var sql string var sql string
if session.engine.dialect.DBType() == core.ORACLE { if session.engine.dialect.DBType() == core.ORACLE {
temp := fmt.Sprintf(") INTO %s (%v%v%v) VALUES (", temp := fmt.Sprintf(") INTO %s (%v) VALUES (",
session.engine.Quote(tableName), session.engine.Quote(tableName),
session.engine.QuoteStr(), quoteColumns(colNames, session.engine.Quote, ","))
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()), sql = fmt.Sprintf("INSERT ALL INTO %s (%v) VALUES (%v) SELECT 1 FROM DUAL",
session.engine.QuoteStr())
sql = fmt.Sprintf("INSERT ALL INTO %s (%v%v%v) VALUES (%v) SELECT 1 FROM DUAL",
session.engine.Quote(tableName), session.engine.Quote(tableName),
session.engine.QuoteStr(), quoteColumns(colNames, session.engine.Quote, ","),
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
session.engine.QuoteStr(),
strings.Join(colMultiPlaces, temp)) strings.Join(colMultiPlaces, temp))
} else { } else {
sql = fmt.Sprintf("INSERT INTO %s (%v%v%v) VALUES (%v)", sql = fmt.Sprintf("INSERT INTO %s (%v) VALUES (%v)",
session.engine.Quote(tableName), session.engine.Quote(tableName),
session.engine.QuoteStr(), quoteColumns(colNames, session.engine.Quote, ","),
strings.Join(colNames, session.engine.QuoteStr()+", "+session.engine.QuoteStr()),
session.engine.QuoteStr(),
strings.Join(colMultiPlaces, "),(")) strings.Join(colMultiPlaces, "),("))
} }
res, err := session.exec(sql, args...) res, err := session.exec(sql, args...)
@ -378,11 +372,9 @@ func (session *Session) innerInsert(bean interface{}) (int64, error) {
output = fmt.Sprintf(" OUTPUT Inserted.%s", table.AutoIncrement) output = fmt.Sprintf(" OUTPUT Inserted.%s", table.AutoIncrement)
} }
if len(colPlaces) > 0 { if len(colPlaces) > 0 {
sqlStr = fmt.Sprintf("INSERT INTO %s (%v%v%v)%s VALUES (%v)", sqlStr = fmt.Sprintf("INSERT INTO %s (%v)%s VALUES (%v)",
session.engine.Quote(tableName), session.engine.Quote(tableName),
session.engine.QuoteStr(), quoteColumns(colNames, session.engine.Quote, ","),
strings.Join(colNames, session.engine.Quote(", ")),
session.engine.QuoteStr(),
output, output,
colPlaces) colPlaces)
} else { } else {

View File

@ -9,7 +9,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -11,13 +11,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interface{}, error) { func (session *Session) genQuerySQL(sqlOrArgs ...interface{}) (string, []interface{}, error) {
if len(sqlorArgs) > 0 { if len(sqlOrArgs) > 0 {
return convertSQLOrArgs(sqlorArgs...) return convertSQLOrArgs(sqlOrArgs...)
} }
if session.statement.RawSQL != "" { if session.statement.RawSQL != "" {
@ -78,12 +78,12 @@ func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interfa
} }
// Query runs a raw sql and return records as []map[string][]byte // Query runs a raw sql and return records as []map[string][]byte
func (session *Session) Query(sqlorArgs ...interface{}) ([]map[string][]byte, error) { func (session *Session) Query(sqlOrArgs ...interface{}) ([]map[string][]byte, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
sqlStr, args, err := session.genQuerySQL(sqlorArgs...) sqlStr, args, err := session.genQuerySQL(sqlOrArgs...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -227,12 +227,12 @@ func rows2SliceString(rows *core.Rows) (resultsSlice [][]string, err error) {
} }
// QueryString runs a raw sql and return records as []map[string]string // QueryString runs a raw sql and return records as []map[string]string
func (session *Session) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) { func (session *Session) QueryString(sqlOrArgs ...interface{}) ([]map[string]string, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
sqlStr, args, err := session.genQuerySQL(sqlorArgs...) sqlStr, args, err := session.genQuerySQL(sqlOrArgs...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -247,12 +247,12 @@ func (session *Session) QueryString(sqlorArgs ...interface{}) ([]map[string]stri
} }
// QuerySliceString runs a raw sql and return records as [][]string // QuerySliceString runs a raw sql and return records as [][]string
func (session *Session) QuerySliceString(sqlorArgs ...interface{}) ([][]string, error) { func (session *Session) QuerySliceString(sqlOrArgs ...interface{}) ([][]string, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
sqlStr, args, err := session.genQuerySQL(sqlorArgs...) sqlStr, args, err := session.genQuerySQL(sqlOrArgs...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -300,12 +300,12 @@ func rows2Interfaces(rows *core.Rows) (resultsSlice []map[string]interface{}, er
} }
// QueryInterface runs a raw sql and return records as []map[string]interface{} // QueryInterface runs a raw sql and return records as []map[string]interface{}
func (session *Session) QueryInterface(sqlorArgs ...interface{}) ([]map[string]interface{}, error) { func (session *Session) QueryInterface(sqlOrArgs ...interface{}) ([]map[string]interface{}, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
sqlStr, args, err := session.genQuerySQL(sqlorArgs...) sqlStr, args, err := session.genQuerySQL(sqlOrArgs...)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -10,8 +10,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -9,8 +9,8 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) { func (session *Session) queryPreprocess(sqlStr *string, paramStr ...interface{}) {
@ -194,14 +194,14 @@ func (session *Session) exec(sqlStr string, args ...interface{}) (sql.Result, er
return session.DB().ExecContext(session.ctx, sqlStr, args...) return session.DB().ExecContext(session.ctx, sqlStr, args...)
} }
func convertSQLOrArgs(sqlorArgs ...interface{}) (string, []interface{}, error) { func convertSQLOrArgs(sqlOrArgs ...interface{}) (string, []interface{}, error) {
switch sqlorArgs[0].(type) { switch sqlOrArgs[0].(type) {
case string: case string:
return sqlorArgs[0].(string), sqlorArgs[1:], nil return sqlOrArgs[0].(string), sqlOrArgs[1:], nil
case *builder.Builder: case *builder.Builder:
return sqlorArgs[0].(*builder.Builder).ToSQL() return sqlOrArgs[0].(*builder.Builder).ToSQL()
case builder.Builder: case builder.Builder:
bd := sqlorArgs[0].(builder.Builder) bd := sqlOrArgs[0].(builder.Builder)
return bd.ToSQL() return bd.ToSQL()
} }
@ -209,16 +209,16 @@ func convertSQLOrArgs(sqlorArgs ...interface{}) (string, []interface{}, error) {
} }
// Exec raw sql // Exec raw sql
func (session *Session) Exec(sqlorArgs ...interface{}) (sql.Result, error) { func (session *Session) Exec(sqlOrArgs ...interface{}) (sql.Result, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }
if len(sqlorArgs) == 0 { if len(sqlOrArgs) == 0 {
return nil, ErrUnSupportedType return nil, ErrUnSupportedType
} }
sqlStr, args, err := convertSQLOrArgs(sqlorArgs...) sqlStr, args, err := convertSQLOrArgs(sqlOrArgs...)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Ping test if database is ok // Ping test if database is ok

View File

@ -9,7 +9,7 @@ import (
"strconv" "strconv"
"testing" "testing"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -9,7 +9,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -11,8 +11,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string, args ...interface{}) error { func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string, args ...interface{}) error {
@ -96,14 +96,15 @@ func (session *Session) cacheUpdate(table *core.Table, tableName, sqlStr string,
return ErrCacheFailed return ErrCacheFailed
} }
kvs := strings.Split(strings.TrimSpace(sqls[1]), ",") kvs := strings.Split(strings.TrimSpace(sqls[1]), ",")
for idx, kv := range kvs { for idx, kv := range kvs {
sps := strings.SplitN(kv, "=", 2) sps := strings.SplitN(kv, "=", 2)
sps2 := strings.Split(sps[0], ".") sps2 := strings.Split(sps[0], ".")
colName := sps2[len(sps2)-1] colName := sps2[len(sps2)-1]
if strings.Contains(colName, "`") { // treat quote prefix, suffix and '`' as quotes
colName = strings.TrimSpace(strings.Replace(colName, "`", "", -1)) quotes := append(strings.Split(session.engine.Quote(""), ""), "`")
} else if strings.Contains(colName, session.engine.QuoteStr()) { if strings.ContainsAny(colName, strings.Join(quotes, "")) {
colName = strings.TrimSpace(strings.Replace(colName, session.engine.QuoteStr(), "", -1)) colName = strings.TrimSpace(eraseAny(colName, quotes...))
} else { } else {
session.engine.logger.Debug("[cacheUpdate] cannot find column", tableName, colName) session.engine.logger.Debug("[cacheUpdate] cannot find column", tableName, colName)
return ErrCacheFailed return ErrCacheFailed
@ -221,19 +222,19 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
} }
} }
//for update action to like "column = column + ?" // for update action to like "column = column + ?"
incColumns := session.statement.getInc() incColumns := session.statement.getInc()
for _, v := range incColumns { for _, v := range incColumns {
colNames = append(colNames, session.engine.Quote(v.colName)+" = "+session.engine.Quote(v.colName)+" + ?") colNames = append(colNames, session.engine.Quote(v.colName)+" = "+session.engine.Quote(v.colName)+" + ?")
args = append(args, v.arg) args = append(args, v.arg)
} }
//for update action to like "column = column - ?" // for update action to like "column = column - ?"
decColumns := session.statement.getDec() decColumns := session.statement.getDec()
for _, v := range decColumns { for _, v := range decColumns {
colNames = append(colNames, session.engine.Quote(v.colName)+" = "+session.engine.Quote(v.colName)+" - ?") colNames = append(colNames, session.engine.Quote(v.colName)+" = "+session.engine.Quote(v.colName)+" - ?")
args = append(args, v.arg) args = append(args, v.arg)
} }
//for update action to like "column = expression" // for update action to like "column = expression"
exprColumns := session.statement.getExpr() exprColumns := session.statement.getExpr()
for _, v := range exprColumns { for _, v := range exprColumns {
colNames = append(colNames, session.engine.Quote(v.colName)+" = "+v.expr) colNames = append(colNames, session.engine.Quote(v.colName)+" = "+v.expr)
@ -382,7 +383,7 @@ func (session *Session) Update(bean interface{}, condiBean ...interface{}) (int6
} }
if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache { if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache {
//session.cacheUpdate(table, tableName, sqlStr, args...) // session.cacheUpdate(table, tableName, sqlStr, args...)
session.engine.logger.Debug("[cacheUpdate] clear table ", tableName) session.engine.logger.Debug("[cacheUpdate] clear table ", tableName)
cacher.ClearIds(tableName) cacher.ClearIds(tableName)
cacher.ClearBeans(tableName) cacher.ClearBeans(tableName)

View File

@ -11,8 +11,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"xorm.io/core"
) )
func TestUpdateMap(t *testing.T) { func TestUpdateMap(t *testing.T) {

View File

@ -6,14 +6,13 @@ package xorm
import ( import (
"database/sql/driver" "database/sql/driver"
"errors"
"fmt" "fmt"
"reflect" "reflect"
"strings" "strings"
"time" "time"
"github.com/go-xorm/builder" "xorm.io/builder"
"github.com/go-xorm/core" "xorm.io/core"
) )
// Statement save all the sql info for executing SQL // Statement save all the sql info for executing SQL
@ -402,7 +401,7 @@ func (statement *Statement) buildUpdates(bean interface{},
continue continue
} }
} else { } else {
//TODO: how to handler? // TODO: how to handler?
panic("not supported") panic("not supported")
} }
} else { } else {
@ -583,21 +582,9 @@ func (statement *Statement) getExpr() map[string]exprParam {
func (statement *Statement) col2NewColsWithQuote(columns ...string) []string { func (statement *Statement) col2NewColsWithQuote(columns ...string) []string {
newColumns := make([]string, 0) newColumns := make([]string, 0)
quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`")
for _, col := range columns { for _, col := range columns {
col = strings.Replace(col, "`", "", -1) newColumns = append(newColumns, statement.Engine.Quote(eraseAny(col, quotes...)))
col = strings.Replace(col, statement.Engine.QuoteStr(), "", -1)
ccols := strings.Split(col, ",")
for _, c := range ccols {
fields := strings.Split(strings.TrimSpace(c), ".")
if len(fields) == 1 {
newColumns = append(newColumns, statement.Engine.quote(fields[0]))
} else if len(fields) == 2 {
newColumns = append(newColumns, statement.Engine.quote(fields[0])+"."+
statement.Engine.quote(fields[1]))
} else {
panic(errors.New("unwanted colnames"))
}
}
} }
return newColumns return newColumns
} }
@ -768,7 +755,9 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition
return statement return statement
} }
tbs := strings.Split(tp.TableName(), ".") tbs := strings.Split(tp.TableName(), ".")
var aliasName = strings.Trim(tbs[len(tbs)-1], statement.Engine.QuoteStr()) quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`")
var aliasName = strings.Trim(tbs[len(tbs)-1], strings.Join(quotes, ""))
fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition) fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition)
statement.joinArgs = append(statement.joinArgs, subQueryArgs...) statement.joinArgs = append(statement.joinArgs, subQueryArgs...)
case *builder.Builder: case *builder.Builder:
@ -778,7 +767,9 @@ func (statement *Statement) Join(joinOP string, tablename interface{}, condition
return statement return statement
} }
tbs := strings.Split(tp.TableName(), ".") tbs := strings.Split(tp.TableName(), ".")
var aliasName = strings.Trim(tbs[len(tbs)-1], statement.Engine.QuoteStr()) quotes := append(strings.Split(statement.Engine.Quote(""), ""), "`")
var aliasName = strings.Trim(tbs[len(tbs)-1], strings.Join(quotes, ""))
fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition) fmt.Fprintf(&buf, "(%s) %s ON %v", subSQL, aliasName, condition)
statement.joinArgs = append(statement.joinArgs, subQueryArgs...) statement.joinArgs = append(statement.joinArgs, subQueryArgs...)
default: default:
@ -1161,8 +1152,12 @@ func (statement *Statement) genSelectSQL(columnStr, condSQL string, needLimit, n
if statement.Start != 0 || statement.LimitN != 0 { if statement.Start != 0 || statement.LimitN != 0 {
oldString := buf.String() oldString := buf.String()
buf.Reset() buf.Reset()
rawColStr := columnStr
if rawColStr == "*" {
rawColStr = "at.*"
}
fmt.Fprintf(&buf, "SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d", fmt.Fprintf(&buf, "SELECT %v FROM (SELECT %v,ROWNUM RN FROM (%v) at WHERE ROWNUM <= %d) aat WHERE RN > %d",
columnStr, columnStr, oldString, statement.Start+statement.LimitN, statement.Start) columnStr, rawColStr, oldString, statement.Start+statement.LimitN, statement.Start)
} }
} }
} }
@ -1246,7 +1241,7 @@ func (statement *Statement) convertUpdateSQL(sqlStr string) (string, string) {
var whereStr = sqls[1] var whereStr = sqls[1]
//TODO: for postgres only, if any other database? // TODO: for postgres only, if any other database?
var paraStr string var paraStr string
if statement.Engine.dialect.DBType() == core.POSTGRES { if statement.Engine.dialect.DBType() == core.POSTGRES {
paraStr = "$" paraStr = "$"

View File

@ -9,8 +9,8 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"xorm.io/core"
) )
var colStrTests = []struct { var colStrTests = []struct {
@ -237,3 +237,12 @@ func TestUpdateIgnoreOnlyFromDBFields(t *testing.T) {
testEngine.Update(record) testEngine.Update(record)
assertGetRecord() assertGetRecord()
} }
func TestCol2NewColsWithQuote(t *testing.T) {
cols := []string{"f1", "f2", "t3.f3"}
statement := createTestStatement()
quotedCols := statement.col2NewColsWithQuote(cols...)
assert.EqualValues(t, []string{statement.Engine.Quote("f1"), statement.Engine.Quote("f2"), statement.Engine.Quote("t3.f3")}, quotedCols)
}

View File

@ -10,7 +10,7 @@ import (
"fmt" "fmt"
"log/syslog" "log/syslog"
"github.com/go-xorm/core" "xorm.io/core"
) )
var _ core.ILogger = &SyslogLogger{} var _ core.ILogger = &SyslogLogger{}

22
tag.go
View File

@ -11,7 +11,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
type tagContext struct { type tagContext struct {
@ -244,6 +244,7 @@ func SQLTypeTagHandler(ctx *tagContext) error {
// ExtendsTagHandler describes extends tag handler // ExtendsTagHandler describes extends tag handler
func ExtendsTagHandler(ctx *tagContext) error { func ExtendsTagHandler(ctx *tagContext) error {
var fieldValue = ctx.fieldValue var fieldValue = ctx.fieldValue
var isPtr = false
switch fieldValue.Kind() { switch fieldValue.Kind() {
case reflect.Ptr: case reflect.Ptr:
f := fieldValue.Type().Elem() f := fieldValue.Type().Elem()
@ -254,6 +255,7 @@ func ExtendsTagHandler(ctx *tagContext) error {
fieldValue = reflect.New(f).Elem() fieldValue = reflect.New(f).Elem()
} }
} }
isPtr = true
fallthrough fallthrough
case reflect.Struct: case reflect.Struct:
parentTable, err := ctx.engine.mapType(fieldValue) parentTable, err := ctx.engine.mapType(fieldValue)
@ -262,6 +264,24 @@ func ExtendsTagHandler(ctx *tagContext) error {
} }
for _, col := range parentTable.Columns() { for _, col := range parentTable.Columns() {
col.FieldName = fmt.Sprintf("%v.%v", ctx.col.FieldName, col.FieldName) col.FieldName = fmt.Sprintf("%v.%v", ctx.col.FieldName, col.FieldName)
var tagPrefix = ctx.col.FieldName
if len(ctx.params) > 0 {
col.Nullable = isPtr
tagPrefix = ctx.params[0]
if col.IsPrimaryKey {
col.Name = ctx.col.FieldName
col.IsPrimaryKey = false
} else {
col.Name = fmt.Sprintf("%v%v", tagPrefix, col.Name)
}
}
if col.Nullable {
col.IsAutoIncrement = false
col.IsPrimaryKey = false
}
ctx.table.AddColumn(col) ctx.table.AddColumn(col)
for indexName, indexType := range col.Indexes { for indexName, indexType := range col.Indexes {
addIndex(indexName, ctx.table, col, indexType) addIndex(indexName, ctx.table, col, indexType)

View File

@ -10,7 +10,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -486,3 +486,123 @@ func TestExtends4(t *testing.T) {
panic(err) panic(err)
} }
} }
type Size struct {
ID int64 `xorm:"int(4) 'id' pk autoincr"`
Width float32 `json:"width" xorm:"float 'Width'"`
Height float32 `json:"height" xorm:"float 'Height'"`
}
type Book struct {
ID int64 `xorm:"int(4) 'id' pk autoincr"`
SizeOpen *Size `xorm:"extends('Open')"`
SizeClosed *Size `xorm:"extends('Closed')"`
Size *Size `xorm:"extends('')"`
}
func TestExtends5(t *testing.T) {
assert.NoError(t, prepareEngine())
err := testEngine.DropTables(&Book{}, &Size{})
if err != nil {
t.Error(err)
panic(err)
}
err = testEngine.CreateTables(&Size{}, &Book{})
if err != nil {
t.Error(err)
panic(err)
}
var sc = Size{Width: 0.2, Height: 0.4}
var so = Size{Width: 0.2, Height: 0.8}
var s = Size{Width: 0.15, Height: 1.5}
var bk1 = Book{
SizeOpen: &so,
SizeClosed: &sc,
Size: &s,
}
var bk2 = Book{
SizeOpen: &so,
}
var bk3 = Book{
SizeClosed: &sc,
Size: &s,
}
var bk4 = Book{}
var bk5 = Book{Size: &s}
_, err = testEngine.Insert(&sc, &so, &s, &bk1, &bk2, &bk3, &bk4, &bk5)
if err != nil {
t.Fatal(err)
}
var books = map[int64]Book{
bk1.ID: bk1,
bk2.ID: bk2,
bk3.ID: bk3,
bk4.ID: bk4,
bk5.ID: bk5,
}
session := testEngine.NewSession()
defer session.Close()
var mapper = testEngine.GetTableMapper().Obj2Table
var quote = testEngine.Quote
bookTableName := quote(testEngine.TableName(mapper("Book"), true))
sizeTableName := quote(testEngine.TableName(mapper("Size"), true))
list := make([]Book, 0)
err = session.
Select(fmt.Sprintf(
"%s.%s, sc.%s AS %s, sc.%s AS %s, s.%s, s.%s",
quote(bookTableName),
quote("id"),
quote("Width"),
quote("ClosedWidth"),
quote("Height"),
quote("ClosedHeight"),
quote("Width"),
quote("Height"),
)).
Table(bookTableName).
Join(
"LEFT",
sizeTableName+" AS `sc`",
bookTableName+".`SizeClosed`=sc.`id`",
).
Join(
"LEFT",
sizeTableName+" AS `s`",
bookTableName+".`Size`=s.`id`",
).
Find(&list)
if err != nil {
t.Error(err)
panic(err)
}
for _, book := range list {
if ok := assert.Equal(t, books[book.ID].SizeClosed.Width, book.SizeClosed.Width); !ok {
t.Error("Not bounded size closed")
panic("Not bounded size closed")
}
if ok := assert.Equal(t, books[book.ID].SizeClosed.Height, book.SizeClosed.Height); !ok {
t.Error("Not bounded size closed")
panic("Not bounded size closed")
}
if books[book.ID].Size != nil || book.Size != nil {
if ok := assert.Equal(t, books[book.ID].Size.Width, book.Size.Width); !ok {
t.Error("Not bounded size")
panic("Not bounded size")
}
if ok := assert.Equal(t, books[book.ID].Size.Height, book.Size.Height); !ok {
t.Error("Not bounded size")
panic("Not bounded size")
}
}
}
}

View File

@ -7,7 +7,7 @@ package xorm
import ( import (
"testing" "testing"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -11,8 +11,8 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-xorm/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"xorm.io/core"
) )
type UserCU struct { type UserCU struct {

View File

@ -7,7 +7,7 @@ package xorm
import ( import (
"reflect" "reflect"
"github.com/go-xorm/core" "xorm.io/core"
) )
var ( var (

View File

@ -9,7 +9,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/go-xorm/core" "xorm.io/core"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -15,7 +15,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/go-xorm/core" "xorm.io/core"
) )
const ( const (

View File

@ -15,7 +15,7 @@ import (
_ "github.com/denisenkom/go-mssqldb" _ "github.com/denisenkom/go-mssqldb"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/go-xorm/core" "xorm.io/core"
_ "github.com/lib/pq" _ "github.com/lib/pq"
_ "github.com/mattn/go-sqlite3" _ "github.com/mattn/go-sqlite3"
_ "github.com/ziutek/mymysql/godrv" _ "github.com/ziutek/mymysql/godrv"