Upgrade xorm to v1.0.0 (#10646)

* Upgrade xorm to v1.0.0

* small nit

* Fix tests

* Update xorm

* Update xorm

* fix go.sum

* fix test

* Fix bug when dump

* Fix bug

* update xorm to latest

* Fix migration test

* update xorm to latest

* Fix import order

* Use xorm tag
This commit is contained in:
Lunny Xiao 2020-03-22 23:12:55 +08:00 committed by GitHub
parent dcaa5643d7
commit c61b902538
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
154 changed files with 7195 additions and 5962 deletions

5
go.mod
View file

@ -116,7 +116,6 @@ require (
gopkg.in/testfixtures.v2 v2.5.0 gopkg.in/testfixtures.v2 v2.5.0
mvdan.cc/xurls/v2 v2.1.0 mvdan.cc/xurls/v2 v2.1.0
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
xorm.io/builder v0.3.6 xorm.io/builder v0.3.7
xorm.io/core v0.7.3 xorm.io/xorm v1.0.0
xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a
) )

10
go.sum
View file

@ -39,6 +39,8 @@ gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d h1:XLww3CvnFZkXVwau
gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY= gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY=
gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 h1:N9QFoeNsUXLhl14mefLzGluqV7w2mGU3u+iZU+jCeWk= gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7 h1:N9QFoeNsUXLhl14mefLzGluqV7w2mGU3u+iZU+jCeWk=
gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7/go.mod h1:kgsbFPPS4P+acDYDOPDa3N4IWWOuDJt5/INKRUz7aks= gitea.com/macaron/toolbox v0.0.0-20190822013122-05ff0fc766b7/go.mod h1:kgsbFPPS4P+acDYDOPDa3N4IWWOuDJt5/INKRUz7aks=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@ -793,11 +795,11 @@ strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY= strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
xorm.io/builder v0.3.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8= xorm.io/builder v0.3.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8=
xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU= xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU=
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw= xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw=
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
xorm.io/core v0.7.3 h1:W8ws1PlrnkS1CZU1YWaYLMQcQilwAmQXU0BJDJon+H0=
xorm.io/core v0.7.3/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM=
xorm.io/xorm v0.8.0 h1:iALxgJrX8O00f8Jk22GbZwPmxJNgssV5Mv4uc2HL9PM= xorm.io/xorm v0.8.0 h1:iALxgJrX8O00f8Jk22GbZwPmxJNgssV5Mv4uc2HL9PM=
xorm.io/xorm v0.8.0/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY= xorm.io/xorm v0.8.0/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY=
xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a h1:hzGd080rlkZ5a7v6Tr3x8PJJnWPfKxGMMl92c8DNcww= xorm.io/xorm v1.0.0 h1:ceiwUTrJHqfNFxIUcWjkcbz6kt7sINf2dOXlgLLhaQM=
xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY= xorm.io/xorm v1.0.0/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY=

View file

@ -207,7 +207,12 @@ func (repo *Repository) refreshAccesses(e Engine, accessMap map[int64]*userAcces
// Delete old accesses and insert new ones for repository. // Delete old accesses and insert new ones for repository.
if _, err = e.Delete(&Access{RepoID: repo.ID}); err != nil { if _, err = e.Delete(&Access{RepoID: repo.ID}); err != nil {
return fmt.Errorf("delete old accesses: %v", err) return fmt.Errorf("delete old accesses: %v", err)
} else if _, err = e.Insert(newAccesses); err != nil { }
if len(newAccesses) == 0 {
return nil
}
if _, err = e.Insert(newAccesses); err != nil {
return fmt.Errorf("insert new accesses: %v", err) return fmt.Errorf("insert new accesses: %v", err)
} }
return nil return nil

View file

@ -25,6 +25,9 @@ func (opts ListOptions) getPaginatedSession() *xorm.Session {
func (opts ListOptions) setSessionPagination(sess *xorm.Session) *xorm.Session { func (opts ListOptions) setSessionPagination(sess *xorm.Session) *xorm.Session {
opts.setDefaultValues() opts.setDefaultValues()
if opts.PageSize <= 0 {
return sess
}
return sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize) return sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize)
} }

View file

@ -9,7 +9,7 @@ import (
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
"xorm.io/core" xormlog "xorm.io/xorm/log"
) )
// XORMLogBridge a logger bridge from Logger to xorm // XORMLogBridge a logger bridge from Logger to xorm
@ -19,7 +19,7 @@ type XORMLogBridge struct {
} }
// NewXORMLogger inits a log bridge for xorm // NewXORMLogger inits a log bridge for xorm
func NewXORMLogger(showSQL bool) core.ILogger { func NewXORMLogger(showSQL bool) xormlog.Logger {
return &XORMLogBridge{ return &XORMLogBridge{
showSQL: showSQL, showSQL: showSQL,
logger: log.GetLogger("xorm"), logger: log.GetLogger("xorm"),
@ -72,22 +72,22 @@ func (l *XORMLogBridge) Warnf(format string, v ...interface{}) {
} }
// Level get logger level // Level get logger level
func (l *XORMLogBridge) Level() core.LogLevel { func (l *XORMLogBridge) Level() xormlog.LogLevel {
switch l.logger.GetLevel() { switch l.logger.GetLevel() {
case log.TRACE, log.DEBUG: case log.TRACE, log.DEBUG:
return core.LOG_DEBUG return xormlog.LOG_DEBUG
case log.INFO: case log.INFO:
return core.LOG_INFO return xormlog.LOG_INFO
case log.WARN: case log.WARN:
return core.LOG_WARNING return xormlog.LOG_WARNING
case log.ERROR, log.CRITICAL: case log.ERROR, log.CRITICAL:
return core.LOG_ERR return xormlog.LOG_ERR
} }
return core.LOG_OFF return xormlog.LOG_OFF
} }
// SetLevel set the logger level // SetLevel set the logger level
func (l *XORMLogBridge) SetLevel(lvl core.LogLevel) { func (l *XORMLogBridge) SetLevel(lvl xormlog.LogLevel) {
} }
// ShowSQL set if record SQL // ShowSQL set if record SQL

View file

@ -22,8 +22,8 @@ import (
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"github.com/unknwon/com" "github.com/unknwon/com"
"xorm.io/core"
"xorm.io/xorm" "xorm.io/xorm"
"xorm.io/xorm/convert"
) )
// LoginType represents an login type. // LoginType represents an login type.
@ -60,11 +60,11 @@ var SecurityProtocolNames = map[ldap.SecurityProtocol]string{
// Ensure structs implemented interface. // Ensure structs implemented interface.
var ( var (
_ core.Conversion = &LDAPConfig{} _ convert.Conversion = &LDAPConfig{}
_ core.Conversion = &SMTPConfig{} _ convert.Conversion = &SMTPConfig{}
_ core.Conversion = &PAMConfig{} _ convert.Conversion = &PAMConfig{}
_ core.Conversion = &OAuth2Config{} _ convert.Conversion = &OAuth2Config{}
_ core.Conversion = &SSPIConfig{} _ convert.Conversion = &SSPIConfig{}
) )
// LDAPConfig holds configuration for LDAP login source. // LDAPConfig holds configuration for LDAP login source.
@ -168,7 +168,7 @@ type LoginSource struct {
Name string `xorm:"UNIQUE"` Name string `xorm:"UNIQUE"`
IsActived bool `xorm:"INDEX NOT NULL DEFAULT false"` IsActived bool `xorm:"INDEX NOT NULL DEFAULT false"`
IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"` IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
Cfg core.Conversion `xorm:"TEXT"` Cfg convert.Conversion `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`

View file

@ -5,32 +5,26 @@
package migrations package migrations
import ( import (
"xorm.io/core"
"xorm.io/xorm" "xorm.io/xorm"
"xorm.io/xorm/schemas"
) )
func changeReviewContentToText(x *xorm.Engine) error { func changeReviewContentToText(x *xorm.Engine) error {
switch x.Dialect().URI().DBType {
if x.Dialect().DBType() == core.MYSQL { case schemas.MYSQL:
_, err := x.Exec("ALTER TABLE review MODIFY COLUMN content TEXT") _, err := x.Exec("ALTER TABLE review MODIFY COLUMN content TEXT")
return err return err
} case schemas.ORACLE:
if x.Dialect().DBType() == core.ORACLE {
_, err := x.Exec("ALTER TABLE review MODIFY content TEXT") _, err := x.Exec("ALTER TABLE review MODIFY content TEXT")
return err return err
} case schemas.MSSQL:
if x.Dialect().DBType() == core.MSSQL {
_, err := x.Exec("ALTER TABLE review ALTER COLUMN content TEXT") _, err := x.Exec("ALTER TABLE review ALTER COLUMN content TEXT")
return err return err
} case schemas.POSTGRES:
if x.Dialect().DBType() == core.POSTGRES {
_, err := x.Exec("ALTER TABLE review ALTER COLUMN content TYPE TEXT") _, err := x.Exec("ALTER TABLE review ALTER COLUMN content TYPE TEXT")
return err return err
} default:
// SQLite doesn't support ALTER COLUMN, and it seem to already make String to _TEXT_ default so no migration needed // SQLite doesn't support ALTER COLUMN, and it seem to already make String to _TEXT_ default so no migration needed
return nil return nil
}
} }

View file

@ -8,17 +8,18 @@ import (
"fmt" "fmt"
"xorm.io/xorm" "xorm.io/xorm"
"xorm.io/xorm/schemas"
) )
func changeU2FCounterType(x *xorm.Engine) error { func changeU2FCounterType(x *xorm.Engine) error {
var err error var err error
switch x.Dialect().DriverName() { switch x.Dialect().URI().DBType {
case "mysql": case schemas.MYSQL:
_, err = x.Exec("ALTER TABLE `u2f_registration` MODIFY `counter` BIGINT") _, err = x.Exec("ALTER TABLE `u2f_registration` MODIFY `counter` BIGINT")
case "postgres": case schemas.POSTGRES:
_, err = x.Exec("ALTER TABLE `u2f_registration` ALTER COLUMN `counter` SET DATA TYPE bigint") _, err = x.Exec("ALTER TABLE `u2f_registration` ALTER COLUMN `counter` SET DATA TYPE bigint")
case "mssql": case schemas.MSSQL:
_, err = x.Exec("ALTER TABLE `u2f_registration` ALTER COLUMN `counter` BIGINT") _, err = x.Exec("ALTER TABLE `u2f_registration` ALTER COLUMN `counter` BIGINT")
} }

View file

@ -15,8 +15,9 @@ import (
// Needed for the MySQL driver // Needed for the MySQL driver
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"xorm.io/core"
"xorm.io/xorm" "xorm.io/xorm"
"xorm.io/xorm/names"
"xorm.io/xorm/schemas"
// Needed for the Postgresql driver // Needed for the Postgresql driver
_ "github.com/lib/pq" _ "github.com/lib/pq"
@ -127,7 +128,7 @@ func init() {
gonicNames := []string{"SSL", "UID"} gonicNames := []string{"SSL", "UID"}
for _, name := range gonicNames { for _, name := range gonicNames {
core.LintGonicMapper[name] = true names.LintGonicMapper[name] = true
} }
} }
@ -152,8 +153,7 @@ func NewTestEngine(x *xorm.Engine) (err error) {
return fmt.Errorf("Connect to database: %v", err) return fmt.Errorf("Connect to database: %v", err)
} }
x.ShowExecTime(true) x.SetMapper(names.GonicMapper{})
x.SetMapper(core.GonicMapper{})
x.SetLogger(NewXORMLogger(!setting.ProdMode)) x.SetLogger(NewXORMLogger(!setting.ProdMode))
x.ShowSQL(!setting.ProdMode) x.ShowSQL(!setting.ProdMode)
return x.StoreEngine("InnoDB").Sync2(tables...) return x.StoreEngine("InnoDB").Sync2(tables...)
@ -166,8 +166,7 @@ func SetEngine() (err error) {
return fmt.Errorf("Failed to connect to database: %v", err) return fmt.Errorf("Failed to connect to database: %v", err)
} }
x.ShowExecTime(true) x.SetMapper(names.GonicMapper{})
x.SetMapper(core.GonicMapper{})
// WARNING: for serv command, MUST remove the output to os.stdout, // WARNING: for serv command, MUST remove the output to os.stdout,
// so use log file to instead print to stdout. // so use log file to instead print to stdout.
x.SetLogger(NewXORMLogger(setting.Database.LogSQL)) x.SetLogger(NewXORMLogger(setting.Database.LogSQL))
@ -249,21 +248,26 @@ func Ping() error {
// DumpDatabase dumps all data from database according the special database SQL syntax to file system. // DumpDatabase dumps all data from database according the special database SQL syntax to file system.
func DumpDatabase(filePath string, dbType string) error { func DumpDatabase(filePath string, dbType string) error {
var tbs []*core.Table var tbs []*schemas.Table
for _, t := range tables { for _, t := range tables {
t := x.TableInfo(t) t, err := x.TableInfo(t)
t.Table.Name = t.Name if err != nil {
tbs = append(tbs, t.Table) return err
}
tbs = append(tbs, t)
} }
if len(dbType) > 0 { if len(dbType) > 0 {
return x.DumpTablesToFile(tbs, filePath, core.DbType(dbType)) return x.DumpTablesToFile(tbs, filePath, schemas.DBType(dbType))
} }
return x.DumpTablesToFile(tbs, filePath) return x.DumpTablesToFile(tbs, filePath)
} }
// MaxBatchInsertSize returns the table's max batch insert size // MaxBatchInsertSize returns the table's max batch insert size
func MaxBatchInsertSize(bean interface{}) int { func MaxBatchInsertSize(bean interface{}) int {
t := x.TableInfo(bean) t, err := x.TableInfo(bean)
if err != nil {
return 50
}
return 999 / len(t.ColumnsSeq()) return 999 / len(t.ColumnsSeq())
} }

View file

@ -1072,6 +1072,7 @@ func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
return err return err
} }
if len(units) > 0 {
if _, err = sess.Insert(units); err != nil { if _, err = sess.Insert(units); err != nil {
errRollback := sess.Rollback() errRollback := sess.Rollback()
if errRollback != nil { if errRollback != nil {
@ -1079,6 +1080,7 @@ func UpdateTeamUnits(team *Team, units []TeamUnit) (err error) {
} }
return err return err
} }
}
return sess.Commit() return sess.Commit()
} }

View file

@ -1417,9 +1417,11 @@ func UpdateRepositoryUnits(repo *Repository, units []RepoUnit, deleteUnitTypes [
return err return err
} }
if len(units) > 0 {
if _, err = sess.Insert(units); err != nil { if _, err = sess.Insert(units); err != nil {
return err return err
} }
}
return sess.Commit() return sess.Commit()
} }

View file

@ -10,8 +10,8 @@ import (
"code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/timeutil"
"github.com/unknwon/com" "github.com/unknwon/com"
"xorm.io/core"
"xorm.io/xorm" "xorm.io/xorm"
"xorm.io/xorm/convert"
) )
// RepoUnit describes all units of a repository // RepoUnit describes all units of a repository
@ -19,7 +19,7 @@ type RepoUnit struct {
ID int64 ID int64
RepoID int64 `xorm:"INDEX(s)"` RepoID int64 `xorm:"INDEX(s)"`
Type UnitType `xorm:"INDEX(s)"` Type UnitType `xorm:"INDEX(s)"`
Config core.Conversion `xorm:"TEXT"` Config convert.Conversion `xorm:"TEXT"`
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
} }

View file

@ -524,7 +524,7 @@ func AddPublicKey(ownerID int64, name, content string, loginSourceID int64) (*Pu
func GetPublicKeyByID(keyID int64) (*PublicKey, error) { func GetPublicKeyByID(keyID int64) (*PublicKey, error) {
key := new(PublicKey) key := new(PublicKey)
has, err := x. has, err := x.
Id(keyID). ID(keyID).
Get(key) Get(key)
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -9,6 +9,7 @@ import (
"time" "time"
"gopkg.in/testfixtures.v2" "gopkg.in/testfixtures.v2"
"xorm.io/xorm/schemas"
) )
var fixtures *testfixtures.Context var fixtures *testfixtures.Context
@ -36,7 +37,7 @@ func LoadFixtures() error {
fmt.Printf("LoadFixtures failed after retries: %v\n", err) fmt.Printf("LoadFixtures failed after retries: %v\n", err)
} }
// Now if we're running postgres we need to tell it to update the sequences // Now if we're running postgres we need to tell it to update the sequences
if x.Dialect().DriverName() == "postgres" { if x.Dialect().URI().DBType == schemas.POSTGRES {
results, err := x.QueryString(`SELECT 'SELECT SETVAL(' || results, err := x.QueryString(`SELECT 'SELECT SETVAL(' ||
quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) || quote_literal(quote_ident(PGT.schemaname) || '.' || quote_ident(S.relname)) ||
', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' || ', COALESCE(MAX(' ||quote_ident(C.attname)|| '), 1) ) FROM ' ||

View file

@ -20,8 +20,8 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/unknwon/com" "github.com/unknwon/com"
"gopkg.in/testfixtures.v2" "gopkg.in/testfixtures.v2"
"xorm.io/core"
"xorm.io/xorm" "xorm.io/xorm"
"xorm.io/xorm/names"
) )
// NonexistentID an ID that will never exist // NonexistentID an ID that will never exist
@ -92,7 +92,7 @@ func CreateTestEngine(fixturesDir string) error {
if err != nil { if err != nil {
return err return err
} }
x.SetMapper(core.GonicMapper{}) x.SetMapper(names.GonicMapper{})
if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil { if err = x.StoreEngine("InnoDB").Sync2(tables...); err != nil {
return err return err
} }

View file

@ -20,7 +20,7 @@ import (
"code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/util"
"github.com/unknwon/com" "github.com/unknwon/com"
"xorm.io/core" "xorm.io/xorm/convert"
) )
const ( const (
@ -214,7 +214,7 @@ func NewAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
ctx.Data["SSPIDefaultLanguage"] = "" ctx.Data["SSPIDefaultLanguage"] = ""
hasTLS := false hasTLS := false
var config core.Conversion var config convert.Conversion
switch models.LoginType(form.Type) { switch models.LoginType(form.Type) {
case models.LoginLDAP, models.LoginDLDAP: case models.LoginLDAP, models.LoginDLDAP:
config = parseLDAPConfig(form) config = parseLDAPConfig(form)
@ -322,7 +322,7 @@ func EditAuthSourcePost(ctx *context.Context, form auth.AuthenticationForm) {
return return
} }
var config core.Conversion var config convert.Conversion
switch models.LoginType(form.Type) { switch models.LoginType(form.Type) {
case models.LoginLDAP, models.LoginDLDAP: case models.LoginLDAP, models.LoginDLDAP:
config = parseLDAPConfig(form) config = parseLDAPConfig(form)

19
vendor/modules.txt vendored
View file

@ -766,12 +766,21 @@ mvdan.cc/xurls/v2
# strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 # strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
## explicit ## explicit
strk.kbt.io/projects/go/libravatar strk.kbt.io/projects/go/libravatar
# xorm.io/builder v0.3.6 # xorm.io/builder v0.3.7
## explicit ## explicit
xorm.io/builder xorm.io/builder
# xorm.io/core v0.7.3 # xorm.io/xorm v1.0.0
## explicit
xorm.io/core
# xorm.io/xorm v0.8.2-0.20200120024500-c37aff9b3a4a
## explicit ## explicit
xorm.io/xorm xorm.io/xorm
xorm.io/xorm/caches
xorm.io/xorm/contexts
xorm.io/xorm/convert
xorm.io/xorm/core
xorm.io/xorm/dialects
xorm.io/xorm/internal/json
xorm.io/xorm/internal/statements
xorm.io/xorm/internal/utils
xorm.io/xorm/log
xorm.io/xorm/names
xorm.io/xorm/schemas
xorm.io/xorm/tags

71
vendor/xorm.io/builder/.drone.yml generated vendored
View file

@ -1,31 +1,6 @@
--- ---
kind: pipeline kind: pipeline
name: go1.10 name: testing
workspace:
base: /go
path: src/xorm.io/builder
steps:
- name: test
pull: default
image: golang:1.10
commands:
- go get -u golang.org/x/lint/golint
- go get -u github.com/stretchr/testify/assert
- go get -u github.com/go-xorm/sqlfiddle
- golint ./...
- go vet
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
when:
event:
- push
- tag
- pull_request
---
kind: pipeline
name: go1.11
steps: steps:
- name: test - name: test
@ -44,47 +19,3 @@ steps:
- push - push
- tag - tag
- pull_request - pull_request
---
kind: pipeline
name: go1.12
steps:
- name: test
pull: default
image: golang:1.12
commands:
- go get -u golang.org/x/lint/golint
- golint ./...
- go vet
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
environment:
GOPROXY: https://goproxy.cn
GO111MODULE: "on"
when:
event:
- push
- tag
- pull_request
---
kind: pipeline
name: go1.13
steps:
- name: test
pull: default
image: golang:1.13
commands:
- go get -u golang.org/x/lint/golint
- golint ./...
- go vet
- go test -v -race -coverprofile=coverage.txt -covermode=atomic
environment:
GOPROXY: https://goproxy.cn
GO111MODULE: "on"
when:
event:
- push
- tag
- pull_request

1
vendor/xorm.io/builder/.gitignore generated vendored Normal file
View file

@ -0,0 +1 @@
.idea

58
vendor/xorm.io/builder/builder.go generated vendored
View file

@ -17,7 +17,7 @@ const (
insertType // insert insertType // insert
updateType // update updateType // update
deleteType // delete deleteType // delete
unionType // union setOpType // set operation
) )
// all databasees // all databasees
@ -27,6 +27,10 @@ const (
MYSQL = "mysql" MYSQL = "mysql"
MSSQL = "mssql" MSSQL = "mssql"
ORACLE = "oracle" ORACLE = "oracle"
UNION = "union"
INTERSECT = "intersect"
EXCEPT = "except"
) )
type join struct { type join struct {
@ -35,8 +39,9 @@ type join struct {
joinCond Cond joinCond Cond
} }
type union struct { type setOp struct {
unionType string opType string
distinctType string
builder *Builder builder *Builder
} }
@ -56,7 +61,7 @@ type Builder struct {
cond Cond cond Cond
selects []string selects []string
joins []join joins []join
unions []union setOps []setOp
limitation *limit limitation *limit
insertCols []string insertCols []string
insertVals []interface{} insertVals []interface{}
@ -144,33 +149,48 @@ func (b *Builder) Into(tableName string) *Builder {
} }
// Union sets union conditions // Union sets union conditions
func (b *Builder) Union(unionTp string, unionCond *Builder) *Builder { func (b *Builder) Union(distinctType string, cond *Builder) *Builder {
return b.setOperation(UNION, distinctType, cond)
}
// Intersect sets intersect conditions
func (b *Builder) Intersect(distinctType string, cond *Builder) *Builder {
return b.setOperation(INTERSECT, distinctType, cond)
}
// Except sets except conditions
func (b *Builder) Except(distinctType string, cond *Builder) *Builder {
return b.setOperation(EXCEPT, distinctType, cond)
}
func (b *Builder) setOperation(opType, distinctType string, cond *Builder) *Builder {
var builder *Builder var builder *Builder
if b.optype != unionType { if b.optype != setOpType {
builder = &Builder{cond: NewCond()} builder = &Builder{cond: NewCond()}
builder.optype = unionType builder.optype = setOpType
builder.dialect = b.dialect builder.dialect = b.dialect
builder.selects = b.selects builder.selects = b.selects
currentUnions := b.unions currentSetOps := b.setOps
// erase sub unions (actually append to new Builder.unions) // erase sub setOps (actually append to new Builder.unions)
b.unions = nil b.setOps = nil
for e := range currentUnions { for e := range currentSetOps {
currentUnions[e].builder.dialect = b.dialect currentSetOps[e].builder.dialect = b.dialect
} }
builder.unions = append(append(builder.unions, union{"", b}), currentUnions...) builder.setOps = append(append(builder.setOps, setOp{opType, "", b}), currentSetOps...)
} else { } else {
builder = b builder = b
} }
if unionCond != nil { if cond != nil {
if unionCond.dialect == "" && builder.dialect != "" { if cond.dialect == "" && builder.dialect != "" {
unionCond.dialect = builder.dialect cond.dialect = builder.dialect
} }
builder.unions = append(builder.unions, union{unionTp, unionCond}) builder.setOps = append(builder.setOps, setOp{opType, distinctType, cond})
} }
return builder return builder
@ -240,8 +260,8 @@ func (b *Builder) WriteTo(w Writer) error {
return b.updateWriteTo(w) return b.updateWriteTo(w)
case deleteType: case deleteType:
return b.deleteWriteTo(w) return b.deleteWriteTo(w)
case unionType: case setOpType:
return b.unionWriteTo(w) return b.setOpWriteTo(w)
} }
return ErrNotSupportType return ErrNotSupportType

View file

@ -58,6 +58,8 @@ func (b *Builder) insertWriteTo(w Writer) error {
if e, ok := value.(expr); ok { if e, ok := value.(expr); ok {
fmt.Fprintf(valBuffer, "(%s)", e.sql) fmt.Fprintf(valBuffer, "(%s)", e.sql)
args = append(args, e.args...) args = append(args, e.args...)
} else if value == nil {
fmt.Fprintf(valBuffer, `null`)
} else { } else {
fmt.Fprint(valBuffer, "?") fmt.Fprint(valBuffer, "?")
args = append(args, value) args = append(args, value)

View file

@ -21,6 +21,9 @@ func (b *Builder) limitWriteTo(w Writer) error {
} }
// erase limit condition // erase limit condition
b.limitation = nil b.limitation = nil
defer func() {
b.limitation = limit
}()
ow := w.(*BytesWriter) ow := w.(*BytesWriter)
switch strings.ToLower(strings.TrimSpace(b.dialect)) { switch strings.ToLower(strings.TrimSpace(b.dialect)) {
@ -34,7 +37,7 @@ func (b *Builder) limitWriteTo(w Writer) error {
b.selects = append(selects, "ROWNUM RN") b.selects = append(selects, "ROWNUM RN")
var wb *Builder var wb *Builder
if b.optype == unionType { if b.optype == setOpType {
wb = Dialect(b.dialect).Select("at.*", "ROWNUM RN"). wb = Dialect(b.dialect).Select("at.*", "ROWNUM RN").
From(b, "at") From(b, "at")
} else { } else {
@ -55,7 +58,7 @@ func (b *Builder) limitWriteTo(w Writer) error {
return final.WriteTo(ow) return final.WriteTo(ow)
case SQLITE, MYSQL, POSTGRES: case SQLITE, MYSQL, POSTGRES:
// if type UNION, we need to write previous content back to current writer // if type UNION, we need to write previous content back to current writer
if b.optype == unionType { if b.optype == setOpType {
if err := b.WriteTo(ow); err != nil { if err := b.WriteTo(ow); err != nil {
return err return err
} }
@ -77,7 +80,7 @@ func (b *Builder) limitWriteTo(w Writer) error {
b.selects[1:]...), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN") b.selects[1:]...), "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN")
var wb *Builder var wb *Builder
if b.optype == unionType { if b.optype == setOpType {
wb = Dialect(b.dialect).Select("*", "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN"). wb = Dialect(b.dialect).Select("*", "ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS RN").
From(b, "at") From(b, "at")
} else { } else {

View file

@ -63,7 +63,7 @@ func (b *Builder) selectWriteTo(w Writer) error {
} }
switch b.subQuery.optype { switch b.subQuery.optype {
case selectType, unionType: case selectType, setOpType:
fmt.Fprint(w, " FROM (") fmt.Fprint(w, " FROM (")
if err := b.subQuery.WriteTo(w); err != nil { if err := b.subQuery.WriteTo(w); err != nil {
return err return err

View file

@ -9,19 +9,19 @@ import (
"strings" "strings"
) )
func (b *Builder) unionWriteTo(w Writer) error { func (b *Builder) setOpWriteTo(w Writer) error {
if b.limitation != nil || b.cond.IsValid() || if b.limitation != nil || b.cond.IsValid() ||
b.orderBy != "" || b.having != "" || b.groupBy != "" { b.orderBy != "" || b.having != "" || b.groupBy != "" {
return ErrNotUnexpectedUnionConditions return ErrNotUnexpectedUnionConditions
} }
for idx, u := range b.unions { for idx, o := range b.setOps {
current := u.builder current := o.builder
if current.optype != selectType { if current.optype != selectType {
return ErrUnsupportedUnionMembers return ErrUnsupportedUnionMembers
} }
if len(b.unions) == 1 { if len(b.setOps) == 1 {
if err := current.selectWriteTo(w); err != nil { if err := current.selectWriteTo(w); err != nil {
return err return err
} }
@ -31,7 +31,11 @@ func (b *Builder) unionWriteTo(w Writer) error {
} }
if idx != 0 { if idx != 0 {
fmt.Fprint(w, fmt.Sprintf(" UNION %v ", strings.ToUpper(u.unionType))) if o.distinctType == "" {
fmt.Fprint(w, fmt.Sprintf(" %s ", strings.ToUpper(o.opType)))
} else {
fmt.Fprint(w, fmt.Sprintf(" %s %s ", strings.ToUpper(o.opType), strings.ToUpper(o.distinctType)))
}
} }
fmt.Fprint(w, "(") fmt.Fprint(w, "(")

View file

@ -45,6 +45,10 @@ func (b *Builder) updateWriteTo(w Writer) error {
} }
} }
if !b.cond.IsValid() {
return nil
}
if _, err := fmt.Fprint(w, " WHERE "); err != nil { if _, err := fmt.Fprint(w, " WHERE "); err != nil {
return err return err
} }

4
vendor/xorm.io/builder/cond_eq.go generated vendored
View file

@ -64,6 +64,10 @@ func (eq Eq) OpWriteTo(op string, w Writer) error {
return err return err
} }
w.Append(int(v.(Decr))) w.Append(int(v.(Decr)))
case nil:
if _, err := fmt.Fprintf(w, "%s=null", k); err != nil {
return err
}
default: default:
if _, err := fmt.Fprintf(w, "%s=?", k); err != nil { if _, err := fmt.Fprintf(w, "%s=?", k); err != nil {
return err return err

2
vendor/xorm.io/builder/go.mod generated vendored
View file

@ -3,6 +3,6 @@ module xorm.io/builder
go 1.11 go 1.11
require ( require (
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a
github.com/stretchr/testify v1.3.0 github.com/stretchr/testify v1.3.0
) )

4
vendor/xorm.io/builder/go.sum generated vendored
View file

@ -1,7 +1,7 @@
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
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/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/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

9
vendor/xorm.io/builder/sql.go generated vendored
View file

@ -75,6 +75,7 @@ func noSQLQuoteNeeded(a interface{}) bool {
} }
t := reflect.TypeOf(a) t := reflect.TypeOf(a)
switch t.Kind() { switch t.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return true return true
@ -133,12 +134,16 @@ func ConvertToBoundSQL(sql string, args []interface{}) (string, error) {
return buf.String(), nil return buf.String(), nil
} }
// ConvertPlaceholder replaces ? to $1, $2 ... or :1, :2 ... according prefix // ConvertPlaceholder replaces the place holder ? to $1, $2 ... or :1, :2 ... according prefix
func ConvertPlaceholder(sql, prefix string) (string, error) { func ConvertPlaceholder(sql, prefix string) (string, error) {
buf := strings.Builder{} buf := strings.Builder{}
var i, j, start int var i, j, start int
var ready = true
for ; i < len(sql); i++ { for ; i < len(sql); i++ {
if sql[i] == '?' { if sql[i] == '\'' && i > 0 && sql[i-1] != '\\' {
ready = !ready
}
if ready && sql[i] == '?' {
if _, err := buf.WriteString(sql[start:i]); err != nil { if _, err := buf.WriteString(sql[start:i]); err != nil {
return "", err return "", err
} }

33
vendor/xorm.io/core/.drone.yml generated vendored
View file

@ -1,33 +0,0 @@
---
kind: pipeline
name: go1.12
steps:
- name: test
pull: default
image: golang:1.12
commands:
- go vet
- "go test -v -race -coverprofile=coverage.txt -covermode=atomic -dbConn=\"root:@tcp(mysql:3306)/core_test?charset=utf8mb4\""
environment:
GO111MODULE: "on"
GOPROXY: https://goproxy.cn
when:
event:
- push
- tag
- pull_request
services:
- name: mysql
pull: default
image: mysql:5.7
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: core_test
when:
event:
- push
- tag
- pull_request

1
vendor/xorm.io/core/.gitignore generated vendored
View file

@ -1 +0,0 @@
*.db

27
vendor/xorm.io/core/LICENSE generated vendored
View file

@ -1,27 +0,0 @@
Copyright (c) 2013 - 2015 Lunny Xiao <xiaolunwen@gmail.com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

118
vendor/xorm.io/core/README.md generated vendored
View file

@ -1,118 +0,0 @@
Core is a lightweight wrapper of sql.DB.
[![Build Status](https://drone.gitea.com/api/badges/xorm/core/status.svg)](https://drone.gitea.com/xorm/core)
[![Test Coverage](https://gocover.io/_badge/xorm.io/core)](https://gocover.io/xorm.io/core)
[![Go Report Card](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/xorm.io/core)
# Open
```Go
db, _ := core.Open(db, connstr)
```
# SetMapper
```Go
db.SetMapper(SameMapper())
```
## Scan usage
### Scan
```Go
rows, _ := db.Query()
for rows.Next() {
rows.Scan()
}
```
### ScanMap
```Go
rows, _ := db.Query()
for rows.Next() {
rows.ScanMap()
```
### ScanSlice
You can use `[]string`, `[][]byte`, `[]interface{}`, `[]*string`, `[]sql.NullString` to ScanSclice. Notice, slice's length should be equal or less than select columns.
```Go
rows, _ := db.Query()
cols, _ := rows.Columns()
for rows.Next() {
var s = make([]string, len(cols))
rows.ScanSlice(&s)
}
```
```Go
rows, _ := db.Query()
cols, _ := rows.Columns()
for rows.Next() {
var s = make([]*string, len(cols))
rows.ScanSlice(&s)
}
```
### ScanStruct
```Go
rows, _ := db.Query()
for rows.Next() {
rows.ScanStructByName()
rows.ScanStructByIndex()
}
```
## Query usage
```Go
rows, err := db.Query("select * from table where name = ?", name)
user = User{
Name:"lunny",
}
rows, err := db.QueryStruct("select * from table where name = ?Name",
&user)
var user = map[string]interface{}{
"name": "lunny",
}
rows, err = db.QueryMap("select * from table where name = ?name",
&user)
```
## QueryRow usage
```Go
row := db.QueryRow("select * from table where name = ?", name)
user = User{
Name:"lunny",
}
row := db.QueryRowStruct("select * from table where name = ?Name",
&user)
var user = map[string]interface{}{
"name": "lunny",
}
row = db.QueryRowMap("select * from table where name = ?name",
&user)
```
## Exec usage
```Go
db.Exec("insert into user (`name`, title, age, alias, nick_name,created) values (?,?,?,?,?,?)", name, title, age, alias...)
user = User{
Name:"lunny",
Title:"test",
Age: 18,
}
result, err = db.ExecStruct("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)",
&user)
var user = map[string]interface{}{
"Name": "lunny",
"Title": "test",
"Age": 18,
}
result, err = db.ExecMap("insert into user (`name`, title, age, alias, nick_name,created) values (?Name,?Title,?Age,?Alias,?NickName,?Created)",
&user)
```

1
vendor/xorm.io/core/benchmark.sh generated vendored
View file

@ -1 +0,0 @@
go test -v -bench=. -run=XXX

327
vendor/xorm.io/core/dialect.go generated vendored
View file

@ -1,327 +0,0 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core
import (
"fmt"
"strings"
"time"
)
type DbType string
type Uri struct {
DbType DbType
Proto string
Host string
Port string
DbName string
User string
Passwd string
Charset string
Laddr string
Raddr string
Timeout time.Duration
Schema string
}
// a dialect is a driver's wrapper
type Dialect interface {
SetLogger(logger ILogger)
Init(*DB, *Uri, string, string) error
URI() *Uri
DB() *DB
DBType() DbType
SqlType(*Column) string
FormatBytes(b []byte) string
DriverName() string
DataSourceName() string
IsReserved(string) bool
Quote(string) string
AndStr() string
OrStr() string
EqStr() string
RollBackStr() string
AutoIncrStr() string
SupportInsertMany() bool
SupportEngine() bool
SupportCharset() bool
SupportDropIfExists() bool
IndexOnTable() bool
ShowCreateNull() bool
IndexCheckSql(tableName, idxName string) (string, []interface{})
TableCheckSql(tableName string) (string, []interface{})
IsColumnExist(tableName string, colName string) (bool, error)
CreateTableSql(table *Table, tableName, storeEngine, charset string) string
DropTableSql(tableName string) string
CreateIndexSql(tableName string, index *Index) string
DropIndexSql(tableName string, index *Index) string
ModifyColumnSql(tableName string, col *Column) string
ForUpdateSql(query string) string
// CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error
// MustDropTable(tableName string) error
GetColumns(tableName string) ([]string, map[string]*Column, error)
GetTables() ([]*Table, error)
GetIndexes(tableName string) (map[string]*Index, error)
Filters() []Filter
SetParams(params map[string]string)
}
func OpenDialect(dialect Dialect) (*DB, error) {
return Open(dialect.DriverName(), dialect.DataSourceName())
}
// Base represents a basic dialect and all real dialects could embed this struct
type Base struct {
db *DB
dialect Dialect
driverName string
dataSourceName string
logger ILogger
*Uri
}
func (b *Base) DB() *DB {
return b.db
}
func (b *Base) SetLogger(logger ILogger) {
b.logger = logger
}
func (b *Base) Init(db *DB, dialect Dialect, uri *Uri, drivername, dataSourceName string) error {
b.db, b.dialect, b.Uri = db, dialect, uri
b.driverName, b.dataSourceName = drivername, dataSourceName
return nil
}
func (b *Base) URI() *Uri {
return b.Uri
}
func (b *Base) DBType() DbType {
return b.Uri.DbType
}
func (b *Base) FormatBytes(bs []byte) string {
return fmt.Sprintf("0x%x", bs)
}
func (b *Base) DriverName() string {
return b.driverName
}
func (b *Base) ShowCreateNull() bool {
return true
}
func (b *Base) DataSourceName() string {
return b.dataSourceName
}
func (b *Base) AndStr() string {
return "AND"
}
func (b *Base) OrStr() string {
return "OR"
}
func (b *Base) EqStr() string {
return "="
}
func (db *Base) RollBackStr() string {
return "ROLL BACK"
}
func (db *Base) SupportDropIfExists() bool {
return true
}
func (db *Base) DropTableSql(tableName string) string {
quote := db.dialect.Quote
return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName))
}
func (db *Base) HasRecords(query string, args ...interface{}) (bool, error) {
db.LogSQL(query, args)
rows, err := db.DB().Query(query, args...)
if err != nil {
return false, err
}
defer rows.Close()
if rows.Next() {
return true, nil
}
return false, nil
}
func (db *Base) IsColumnExist(tableName, colName string) (bool, error) {
query := fmt.Sprintf(
"SELECT %v FROM %v.%v WHERE %v = ? AND %v = ? AND %v = ?",
db.dialect.Quote("COLUMN_NAME"),
db.dialect.Quote("INFORMATION_SCHEMA"),
db.dialect.Quote("COLUMNS"),
db.dialect.Quote("TABLE_SCHEMA"),
db.dialect.Quote("TABLE_NAME"),
db.dialect.Quote("COLUMN_NAME"),
)
return db.HasRecords(query, db.DbName, tableName, colName)
}
/*
func (db *Base) CreateTableIfNotExists(table *Table, tableName, storeEngine, charset string) error {
sql, args := db.dialect.TableCheckSql(tableName)
rows, err := db.DB().Query(sql, args...)
if db.Logger != nil {
db.Logger.Info("[sql]", sql, args)
}
if err != nil {
return err
}
defer rows.Close()
if rows.Next() {
return nil
}
sql = db.dialect.CreateTableSql(table, tableName, storeEngine, charset)
_, err = db.DB().Exec(sql)
if db.Logger != nil {
db.Logger.Info("[sql]", sql)
}
return err
}*/
func (db *Base) CreateIndexSql(tableName string, index *Index) string {
quote := db.dialect.Quote
var unique string
var idxName string
if index.Type == UniqueType {
unique = " UNIQUE"
}
idxName = index.XName(tableName)
return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
quote(idxName), quote(tableName),
quote(strings.Join(index.Cols, quote(","))))
}
func (db *Base) DropIndexSql(tableName string, index *Index) string {
quote := db.dialect.Quote
var name string
if index.IsRegular {
name = index.XName(tableName)
} else {
name = index.Name
}
return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
}
func (db *Base) ModifyColumnSql(tableName string, col *Column) string {
return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, col.StringNoPk(db.dialect))
}
func (b *Base) CreateTableSql(table *Table, tableName, storeEngine, charset string) string {
var sql string
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
sql += b.dialect.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
if col.IsPrimaryKey && len(pkList) == 1 {
sql += col.String(b.dialect)
} else {
sql += col.StringNoPk(b.dialect)
}
sql = strings.TrimSpace(sql)
if b.DriverName() == MYSQL && len(col.Comment) > 0 {
sql += " COMMENT '" + col.Comment + "'"
}
sql += ", "
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += b.dialect.Quote(strings.Join(pkList, b.dialect.Quote(",")))
sql += " ), "
}
sql = sql[:len(sql)-2]
}
sql += ")"
if b.dialect.SupportEngine() && storeEngine != "" {
sql += " ENGINE=" + storeEngine
}
if b.dialect.SupportCharset() {
if len(charset) == 0 {
charset = b.dialect.URI().Charset
}
if len(charset) > 0 {
sql += " DEFAULT CHARSET " + charset
}
}
return sql
}
func (b *Base) ForUpdateSql(query string) string {
return query + " FOR UPDATE"
}
func (b *Base) LogSQL(sql string, args []interface{}) {
if b.logger != nil && b.logger.IsShowSQL() {
if len(args) > 0 {
b.logger.Infof("[SQL] %v %v", sql, args)
} else {
b.logger.Infof("[SQL] %v", sql)
}
}
}
func (b *Base) SetParams(params map[string]string) {
}
var (
dialects = map[string]func() Dialect{}
)
// RegisterDialect register database dialect
func RegisterDialect(dbName DbType, dialectFunc func() Dialect) {
if dialectFunc == nil {
panic("core: Register dialect is nil")
}
dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect
}
// QueryDialect query if registered database dialect
func QueryDialect(dbName DbType) Dialect {
if d, ok := dialects[strings.ToLower(string(dbName))]; ok {
return d()
}
return nil
}

31
vendor/xorm.io/core/driver.go generated vendored
View file

@ -1,31 +0,0 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core
type Driver interface {
Parse(string, string) (*Uri, error)
}
var (
drivers = map[string]Driver{}
)
func RegisterDriver(driverName string, driver Driver) {
if driver == nil {
panic("core: Register driver is nil")
}
if _, dup := drivers[driverName]; dup {
panic("core: Register called twice for driver " + driverName)
}
drivers[driverName] = driver
}
func QueryDriver(driverName string) Driver {
return drivers[driverName]
}
func RegisteredDriverSize() int {
return len(drivers)
}

93
vendor/xorm.io/core/filter.go generated vendored
View file

@ -1,93 +0,0 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core
import (
"fmt"
"strings"
)
// Filter is an interface to filter SQL
type Filter interface {
Do(sql string, dialect Dialect, table *Table) string
}
// QuoteFilter filter SQL replace ` to database's own quote character
type QuoteFilter struct {
}
func (s *QuoteFilter) Do(sql string, dialect Dialect, table *Table) string {
dummy := dialect.Quote("")
if len(dummy) != 2 {
return sql
}
prefix, suffix := dummy[0], dummy[1]
raw := []byte(sql)
for i, cnt := 0, 0; i < len(raw); i = i + 1 {
if raw[i] == '`' {
if cnt%2 == 0 {
raw[i] = prefix
} else {
raw[i] = suffix
}
cnt++
}
}
return string(raw)
}
// IdFilter filter SQL replace (id) to primary key column name
type IdFilter struct {
}
type Quoter struct {
dialect Dialect
}
func NewQuoter(dialect Dialect) *Quoter {
return &Quoter{dialect}
}
func (q *Quoter) Quote(content string) string {
return q.dialect.Quote(content)
}
func (i *IdFilter) Do(sql string, dialect Dialect, table *Table) string {
quoter := NewQuoter(dialect)
if table != nil && len(table.PrimaryKeys) == 1 {
sql = strings.Replace(sql, " `(id)` ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
sql = strings.Replace(sql, " "+quoter.Quote("(id)")+" ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
return strings.Replace(sql, " (id) ", " "+quoter.Quote(table.PrimaryKeys[0])+" ", -1)
}
return sql
}
// SeqFilter filter SQL replace ?, ? ... to $1, $2 ...
type SeqFilter struct {
Prefix string
Start int
}
func convertQuestionMark(sql, prefix string, start int) string {
var buf strings.Builder
var beginSingleQuote bool
var index = start
for _, c := range sql {
if !beginSingleQuote && c == '?' {
buf.WriteString(fmt.Sprintf("%s%v", prefix, index))
index++
} else {
if c == '\'' {
beginSingleQuote = !beginSingleQuote
}
buf.WriteRune(c)
}
}
return buf.String()
}
func (s *SeqFilter) Do(sql string, dialect Dialect, table *Table) string {
return convertQuestionMark(sql, s.Prefix, s.Start)
}

8
vendor/xorm.io/core/go.mod generated vendored
View file

@ -1,8 +0,0 @@
module xorm.io/core
require (
github.com/go-sql-driver/mysql v1.4.1
github.com/mattn/go-sqlite3 v1.10.0
github.com/stretchr/testify v1.4.0
google.golang.org/appengine v1.6.0 // indirect
)

20
vendor/xorm.io/core/go.sum generated vendored
View file

@ -1,20 +0,0 @@
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/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/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw=
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

37
vendor/xorm.io/core/ilogger.go generated vendored
View file

@ -1,37 +0,0 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package core
// LogLevel defines a log level
type LogLevel int
// enumerate all LogLevels
const (
// !nashtsai! following level also match syslog.Priority value
LOG_DEBUG LogLevel = iota
LOG_INFO
LOG_WARNING
LOG_ERR
LOG_OFF
LOG_UNKNOWN
)
// ILogger is a logger interface
type ILogger interface {
Debug(v ...interface{})
Debugf(format string, v ...interface{})
Error(v ...interface{})
Errorf(format string, v ...interface{})
Info(v ...interface{})
Infof(format string, v ...interface{})
Warn(v ...interface{})
Warnf(format string, v ...interface{})
Level() LogLevel
SetLevel(l LogLevel)
ShowSQL(show ...bool)
IsShowSQL() bool
}

53
vendor/xorm.io/xorm/.changelog.yml generated vendored Normal file
View file

@ -0,0 +1,53 @@
# The full repository name
repo: xorm/xorm
# Service type (gitea or github)
service: gitea
# Base URL for Gitea instance if using gitea service type (optional)
# Default: https://gitea.com
base-url:
# Changelog groups and which labeled PRs to add to each group
groups:
-
name: BREAKING
labels:
- kind/breaking
-
name: FEATURES
labels:
- kind/feature
-
name: SECURITY
labels:
- kind/security
-
name: BUGFIXES
labels:
- kind/bug
-
name: ENHANCEMENTS
labels:
- kind/enhancement
- kind/refactor
- kind/ui
-
name: TESTING
labels:
- kind/testing
-
name: BUILD
labels:
- kind/build
- kind/lint
-
name: DOCS
labels:
- kind/docs
-
name: MISC
default: true
# regex indicating which labels to skip for the changelog
skip-labels: skip-changelog|backport\/.+

151
vendor/xorm.io/xorm/.drone.yml generated vendored
View file

@ -3,8 +3,7 @@ kind: pipeline
name: testing name: testing
steps: steps:
- name: test-vet - name: test-vet
pull: default image: golang:1.11
image: golang:1.12
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
@ -16,44 +15,77 @@ steps:
- pull_request - pull_request
- name: test-sqlite - name: test-sqlite
pull: default
image: golang:1.12 image: golang:1.12
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
commands: commands:
- "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -coverprofile=coverage1-1.txt -covermode=atomic" - make test-sqlite
- "go test -v -race -db=\"sqlite3\" -conn_str=\"./test.db\" -cache=true -coverprofile=coverage1-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-sqlite
- TEST_QUOTE_POLICY=reserved make test-sqlite
- go test ./caches/... ./contexts/... ./convert/... ./core/... ./dialects/... \
./log/... ./migrate/... ./names/... ./schemas/... ./tags/... \
./internal/json/... ./internal/statements/... ./internal/utils/... \
when: when:
event: event:
- push - push
- pull_request - pull_request
- name: test-mysql - name: test-mysql
pull: default
image: golang:1.12 image: golang:1.12
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
TEST_MYSQL_HOST: mysql
TEST_MYSQL_CHARSET: utf8
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands: commands:
- "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -coverprofile=coverage2-1.txt -covermode=atomic" - make test-mysql
- "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test\" -cache=true -coverprofile=coverage2-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
when:
event:
- push
- pull_request
- name: test-mysql8
image: golang:1.12
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
TEST_MYSQL_HOST: mysql8
TEST_MYSQL_CHARSET: utf8mb4
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands:
- make test-mysql
- TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
when: when:
event: event:
- push - push
- pull_request - pull_request
- name: test-mysql-utf8mb4 - name: test-mysql-utf8mb4
pull: default
image: golang:1.12 image: golang:1.12
depends_on: depends_on:
- test-mysql - test-mysql
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
TEST_MYSQL_HOST: mysql
TEST_MYSQL_CHARSET: utf8mb4
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands: commands:
- "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -coverprofile=coverage2.1-1.txt -covermode=atomic" - make test-mysql
- "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(mysql)/xorm_test?charset=utf8mb4\" -cache=true -coverprofile=coverage2.1-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-mysql
- TEST_QUOTE_POLICY=reserved make test-mysql
when: when:
event: event:
- push - push
@ -67,9 +99,14 @@ steps:
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
TEST_MYSQL_HOST: mysql:3306
TEST_MYSQL_DBNAME: xorm_test
TEST_MYSQL_USERNAME: root
TEST_MYSQL_PASSWORD:
commands: commands:
- "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -coverprofile=coverage3-1.txt -covermode=atomic" - make test-mymysql
- "go test -v -race -db=\"mymysql\" -conn_str=\"tcp:mysql:3306*xorm_test/root/\" -cache=true -coverprofile=coverage3-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-mymysql
- TEST_QUOTE_POLICY=reserved make test-mymysql
when: when:
event: event:
- push - push
@ -81,9 +118,14 @@ steps:
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
TEST_PGSQL_HOST: pgsql
TEST_PGSQL_DBNAME: xorm_test
TEST_PGSQL_USERNAME: postgres
TEST_PGSQL_PASSWORD: postgres
commands: commands:
- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -coverprofile=coverage4-1.txt -covermode=atomic" - make test-postgres
- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -cache=true -coverprofile=coverage4-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-postgres
- TEST_QUOTE_POLICY=reserved make test-postgres
when: when:
event: event:
- push - push
@ -92,12 +134,20 @@ steps:
- name: test-postgres-schema - name: test-postgres-schema
pull: default pull: default
image: golang:1.12 image: golang:1.12
depends_on:
- test-postgres
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
TEST_PGSQL_HOST: pgsql
TEST_PGSQL_SCHEMA: xorm
TEST_PGSQL_DBNAME: xorm_test
TEST_PGSQL_USERNAME: postgres
TEST_PGSQL_PASSWORD: postgres
commands: commands:
- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -schema=xorm -coverprofile=coverage5-1.txt -covermode=atomic" - make test-postgres
- "go test -v -race -db=\"postgres\" -conn_str=\"postgres://postgres:@pgsql/xorm_test?sslmode=disable\" -schema=xorm -cache=true -coverprofile=coverage5-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-postgres
- TEST_QUOTE_POLICY=reserved make test-postgres
when: when:
event: event:
- push - push
@ -109,9 +159,14 @@ steps:
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
TEST_MSSQL_HOST: mssql
TEST_MSSQL_DBNAME: xorm_test
TEST_MSSQL_USERNAME: sa
TEST_MSSQL_PASSWORD: "yourStrong(!)Password"
commands: commands:
- "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -coverprofile=coverage6-1.txt -covermode=atomic" - make test-mssql
- "go test -v -race -db=\"mssql\" -conn_str=\"server=mssql;user id=sa;password=yourStrong(!)Password;database=xorm_test\" -cache=true -coverprofile=coverage6-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-mssql
- TEST_QUOTE_POLICY=reserved make test-mssql
when: when:
event: event:
- push - push
@ -123,9 +178,33 @@ steps:
environment: environment:
GO111MODULE: "on" GO111MODULE: "on"
GOPROXY: "https://goproxy.cn" GOPROXY: "https://goproxy.cn"
TEST_TIDB_HOST: "tidb:4000"
TEST_TIDB_DBNAME: xorm_test
TEST_TIDB_USERNAME: root
TEST_TIDB_PASSWORD:
commands: commands:
- "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -coverprofile=coverage7-1.txt -covermode=atomic" - make test-tidb
- "go test -v -race -db=\"mysql\" -conn_str=\"root:@tcp(tidb:4000)/xorm_test\" -ignore_select_update=true -cache=true -coverprofile=coverage7-2.txt -covermode=atomic" - TEST_CACHE_ENABLE=true make test-tidb
- TEST_QUOTE_POLICY=reserved make test-tidb
when:
event:
- push
- pull_request
- name: test-cockroach
pull: default
image: golang:1.13
environment:
GO111MODULE: "on"
GOPROXY: "https://goproxy.cn"
TEST_COCKROACH_HOST: "cockroach:26257"
TEST_COCKROACH_DBNAME: xorm_test
TEST_COCKROACH_USERNAME: root
TEST_COCKROACH_PASSWORD:
commands:
- sleep 10
- make test-cockroach
- TEST_CACHE_ENABLE=true make test-cockroach
when: when:
event: event:
- push - push
@ -141,15 +220,15 @@ steps:
- test-vet - test-vet
- test-sqlite - test-sqlite
- test-mysql - test-mysql
- test-mysql-utf8mb4 - test-mysql8
- test-mymysql - test-mymysql
- test-postgres - test-postgres
- test-postgres-schema - test-postgres-schema
- test-mssql - test-mssql
- test-tidb - test-tidb
- test-cockroach
commands: commands:
- go get github.com/wadey/gocovmerge - make coverage
- gocovmerge coverage1-1.txt coverage1-2.txt coverage2-1.txt coverage2-2.txt coverage2.1-1.txt coverage2.1-2.txt coverage3-1.txt coverage3-2.txt coverage4-1.txt coverage4-2.txt coverage5-1.txt coverage5-2.txt coverage6-1.txt coverage6-2.txt coverage7-1.txt coverage7-2.txt > coverage.txt
when: when:
event: event:
- push - push
@ -169,12 +248,25 @@ services:
- tag - tag
- pull_request - pull_request
- name: mysql8
pull: default
image: mysql:8.0
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: yes
MYSQL_DATABASE: xorm_test
when:
event:
- push
- tag
- pull_request
- name: pgsql - name: pgsql
pull: default pull: default
image: postgres:9.5 image: postgres:9.5
environment: environment:
POSTGRES_DB: xorm_test POSTGRES_DB: xorm_test
POSTGRES_USER: postgres POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
when: when:
event: event:
- push - push
@ -202,3 +294,14 @@ services:
- push - push
- tag - tag
- pull_request - pull_request
- name: cockroach
pull: default
image: cockroachdb/cockroach:v19.2.4
commands:
- /cockroach/cockroach start --insecure
when:
event:
- push
- tag
- pull_request

3
vendor/xorm.io/xorm/.gitignore generated vendored
View file

@ -7,6 +7,7 @@
# Folders # Folders
_obj _obj
_test _test
vendor/
# Architecture specific extensions/prefixes # Architecture specific extensions/prefixes
*.[568vq] *.[568vq]
@ -31,3 +32,5 @@ xorm.test
test.db.sql test.db.sql
.idea/ .idea/
*coverage.out

25
vendor/xorm.io/xorm/.revive.toml generated vendored Normal file
View file

@ -0,0 +1,25 @@
ignoreGeneratedHeader = false
severity = "warning"
confidence = 0.8
errorCode = 1
warningCode = 1
[rule.blank-imports]
[rule.context-as-argument]
[rule.context-keys-type]
[rule.dot-imports]
[rule.error-return]
[rule.error-strings]
[rule.error-naming]
[rule.exported]
[rule.if-return]
[rule.increment-decrement]
[rule.var-naming]
[rule.var-declaration]
[rule.package-comments]
[rule.range]
[rule.receiver-naming]
[rule.time-naming]
[rule.unexported-return]
[rule.indent-error-flow]
[rule.errorf]

173
vendor/xorm.io/xorm/CHANGELOG.md generated vendored Normal file
View file

@ -0,0 +1,173 @@
# Changelog
This changelog goes through all the changes that have been made in each release
without substantial changes to our git log.
## [1.0.0](https://gitea.com/xorm/xorm/pulls?q=&type=all&state=closed&milestone=1242) - 2020-03-22
* BREAKING
* Add context for dialects (#1558)
* Move zero functions to a standalone package (#1548)
* Merge core package back into the main repository and split into serval sub packages. (#1543)
* FEATURES
* Use a new ContextLogger interface to implement logger (#1557)
* BUGFIXES
* Fix setschema (#1606)
* Fix dump/import bug (#1603)
* Fix pk bug (#1602)
* Fix master/slave bug (#1601)
* Fix bug when dump (#1597)
* Ignore schema when dbtype is not postgres (#1593)
* Fix table name (#1590)
* Fix find alias bug (#1581)
* Fix rows bug (#1576)
* Fix map with cols (#1575)
* Fix bug on deleted with join (#1570)
* Improve quote policy (#1567)
* Fix break session sql enable feature (#1566)
* Fix mssql quote (#1535)
* Fix join table name quote bug (#1534)
* Fix mssql issue with duplicate columns. (#1225)
* Fix mysql8.0 sync failed (#808)
* ENHANCEMENTS
* Fix batch insert interface slice be panic (#1598)
* Move some codes to statement sub package (#1574)
* Remove circle file (#1569)
* Move statement as a sub package (#1564)
* Move maptype to tag parser (#1561)
* Move caches to manager (#1553)
* Improve code (#1552)
* Improve some codes (#1551)
* Improve statement (#1549)
* Move tag parser related codes as a standalone sub package (#1547)
* Move reserve words related files into dialects sub package (#1544)
* Fix `Conversion` method `ToDB() ([]byte, error)` return type is nil (#1296)
* Check driver.Valuer response, and skip the column if nil (#1167)
* Add cockroach support and tests (#896)
* TESTING
* Improve tests (#1572)
* BUILD
* Add changelog file and tool configuration (#1546)
* DOCS
* Fix outdate changelog (#1565)
## old changelog
* **v0.6.5**
* Postgres schema support
* vgo support
* Add FindAndCount
* Database special params support via NewEngineWithParams
* Some bugs fixed
* **v0.6.4**
* Automatical Read/Write seperatelly
* Query/QueryString/QueryInterface and action with Where/And
* Get support non-struct variables
* BufferSize on Iterate
* fix some other bugs.
* **v0.6.3**
* merge tests to main project
* add `Exist` function
* add `SumInt` function
* Mysql now support read and create column comment.
* fix time related bugs.
* fix some other bugs.
* **v0.6.2**
* refactor tag parse methods
* add Scan features to Get
* add QueryString method
* **v0.4.5**
* many bugs fixed
* extends support unlimited deep
* Delete Limit support
* **v0.4.4**
* ql database expriment support
* tidb database expriment support
* sql.NullString and etc. field support
* select ForUpdate support
* many bugs fixed
* **v0.4.3**
* Json column type support
* oracle expirement support
* bug fixed
* **v0.4.2**
* Transaction will auto rollback if not Rollback or Commit be called.
* Gonic Mapper support
* bug fixed
* **v0.4.1**
* deleted tag support for soft delete
* bug fixed
* **v0.4.0 RC1**
Changes:
* moved xorm cmd to [github.com/go-xorm/cmd](github.com/go-xorm/cmd)
* refactored general DB operation a core lib at [github.com/go-xorm/core](https://github.com/go-xorm/core)
* moved tests to github.com/go-xorm/tests [github.com/go-xorm/tests](github.com/go-xorm/tests)
Improvements:
* Prepared statement cache
* Add Incr API
* Specify Timezone Location
* **v0.3.2**
Improvements:
* Add AllCols & MustCols function
* Add TableName for custom table name
Bug Fixes:
* #46
* #51
* #53
* #89
* #86
* #92
* **v0.3.1**
Features:
* Support MSSQL DB via ODBC driver ([github.com/lunny/godbc](https://github.com/lunny/godbc));
* Composite Key, using multiple pk xorm tag
* Added Row() API as alternative to Iterate() API for traversing result set, provide similar usages to sql.Rows type
* ORM struct allowed declaration of pointer builtin type as members to allow null DB fields
* Before and After Event processors
Improvements:
* Allowed int/int32/int64/uint/uint32/uint64/string as Primary Key type
* Performance improvement for Get()/Find()/Iterate()
* **v0.2.3** : Improved documents; Optimistic Locking support; Timestamp with time zone support; Mapper change to tableMapper and columnMapper & added PrefixMapper & SuffixMapper support custom table or column name's prefix and suffix;Insert now return affected, err instead of id, err; Added UseBool & Distinct;
* **v0.2.2** : Postgres drivers now support lib/pq; Added method Iterate for record by record to handlerAdded SetMaxConns(go1.2+) support; some bugs fixed.
* **v0.2.1** : Added database reverse tool, now support generate go & c++ codes, see [Xorm Tool README](https://github.com/go-xorm/xorm/blob/master/xorm/README.md); some bug fixed.
* **v0.2.0** : Added Cache supported, select is speeder up 3~5x; Added SameMapper for same name between struct and table; Added Sync method for auto added tables, columns, indexes;
* **v0.1.9** : Added postgres and mymysql supported; Added ` and ? supported on Raw SQL even if postgres; Added Cols, StoreEngine, Charset function, Added many column data type supported, please see [Mapping Rules](#mapping).
* **v0.1.8** : Added union index and union unique supported, please see [Mapping Rules](#mapping).
* **v0.1.7** : Added IConnectPool interface and NoneConnectPool, SysConnectPool, SimpleConnectPool the three implements. You can choose one of them and the default is SysConnectPool. You can customrize your own connection pool. struct Engine added Close method, It should be invoked before system exit.
* **v0.1.6** : Added conversion interface support; added struct derive support; added single mapping support
* **v0.1.5** : Added multi threads support; added Sql() function for struct query; Get function changed return inteface; MakeSession and Create are instead with NewSession and NewEngine.
* **v0.1.4** : Added simple cascade load support; added more data type supports.
* **v0.1.3** : Find function now supports both slice and map; Add Table function for multi tables and temperory tables support
* **v0.1.2** : Insert function now supports both struct and slice pointer parameters, batch inserting and auto transaction
* **v0.1.1** : Add Id, In functions and improved README
* **v0.1.0** : Initial release.

41
vendor/xorm.io/xorm/CONTRIBUTING.md generated vendored
View file

@ -22,6 +22,47 @@ e.g.,
// !lunny! this is comments made by lunny // !lunny! this is comments made by lunny
``` ```
### Build xorm and test it locally
Once you write some codes on your feature branch, you could build and test locally at first. Just
```
make build
```
and
```
make test
```
The `make test` is an alias of `make test-sqlite`, it will run the tests on a sqlite database file. No extra thing needed to do except you need to cgo compile enviroment.
If you write a new test method, you could run
```
make test-sqlite#TestMyNewMethod
```
that will only run the special test method.
If you want to run another datase, you have to prepare a running database at first, and then, you could
```
TEST_MYSQL_HOST= TEST_MYSQL_CHARSET= TEST_MYSQL_DBNAME= TEST_MYSQL_USERNAME= TEST_MYSQL_PASSWORD= make test-mysql
```
or other databases:
```
TEST_MSSQL_HOST= TEST_MSSQL_DBNAME= TEST_MSSQL_USERNAME= TEST_MSSQL_PASSWORD= make test-mssql
```
```
TEST_PGSQL_HOST= TEST_PGSQL_SCHEMA= TEST_PGSQL_DBNAME= TEST_PGSQL_USERNAME= TEST_PGSQL_PASSWORD= make test-postgres
```
```
TEST_TIDB_HOST= TEST_TIDB_DBNAME= TEST_TIDB_USERNAME= TEST_TIDB_PASSWORD= make test-tidb
```
And if your branch is related with cache, you could also enable it via `TEST_CACHE_ENABLE=true`.
### Patch review ### Patch review
Help review existing open [pull requests](https://help.github.com/articles/using-pull-requests) by commenting on the code or Help review existing open [pull requests](https://help.github.com/articles/using-pull-requests) by commenting on the code or

214
vendor/xorm.io/xorm/Makefile generated vendored Normal file
View file

@ -0,0 +1,214 @@
IMPORT := xorm.io/xorm
export GO111MODULE=on
GO ?= go
GOFMT ?= gofmt -s
TAGS ?=
SED_INPLACE := sed -i
GOFILES := $(shell find . -name "*.go" -type f)
PACKAGES ?= $(shell GO111MODULE=on $(GO) list ./...)
TEST_COCKROACH_HOST ?= cockroach:26257
TEST_COCKROACH_SCHEMA ?=
TEST_COCKROACH_DBNAME ?= xorm_test
TEST_COCKROACH_USERNAME ?= postgres
TEST_COCKROACH_PASSWORD ?=
TEST_MSSQL_HOST ?= mssql:1433
TEST_MSSQL_DBNAME ?= gitea
TEST_MSSQL_USERNAME ?= sa
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
TEST_MYSQL_HOST ?= mysql:3306
TEST_MYSQL_CHARSET ?= utf8
TEST_MYSQL_DBNAME ?= xorm_test
TEST_MYSQL_USERNAME ?= root
TEST_MYSQL_PASSWORD ?=
TEST_PGSQL_HOST ?= pgsql:5432
TEST_PGSQL_SCHEMA ?=
TEST_PGSQL_DBNAME ?= xorm_test
TEST_PGSQL_USERNAME ?= postgres
TEST_PGSQL_PASSWORD ?= mysecretpassword
TEST_TIDB_HOST ?= tidb:4000
TEST_TIDB_DBNAME ?= xorm_test
TEST_TIDB_USERNAME ?= root
TEST_TIDB_PASSWORD ?=
TEST_CACHE_ENABLE ?= false
TEST_QUOTE_POLICY ?= always
.PHONY: all
all: build
.PHONY: build
build: go-check $(GO_SOURCES)
$(GO) build
.PHONY: clean
clean:
$(GO) clean -i ./...
rm -rf *.sql *.log test.db *coverage.out coverage.all
.PHONY: coverage
coverage:
@hash gocovmerge > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/wadey/gocovmerge; \
fi
gocovmerge $(shell find . -type f -name "coverage.out") > coverage.all;\
.PHONY: fmt
fmt:
$(GOFMT) -w $(GOFILES)
.PHONY: fmt-check
fmt-check:
# get all go files and run go fmt on them
@diff=$$($(GOFMT) -d $(GOFILES)); \
if [ -n "$$diff" ]; then \
echo "Please run 'make fmt' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi;
.PHONY: go-check
go-check:
$(eval GO_VERSION := $(shell printf "%03d%03d%03d" $(shell go version | grep -Eo '[0-9]+\.?[0-9]+?\.?[0-9]?\s' | tr '.' ' ');))
@if [ "$(GO_VERSION)" -lt "001011000" ]; then \
echo "Gitea requires Go 1.11.0 or greater to build. You can get it at https://golang.org/dl/"; \
exit 1; \
fi
.PHONY: help
help:
@echo "Make Routines:"
@echo " - equivalent to \"build\""
@echo " - build creates the entire project"
@echo " - clean delete integration files and build files but not css and js files"
@echo " - fmt format the code"
@echo " - lint run code linter revive"
@echo " - misspell check if a word is written wrong"
@echo " - test run default unit test"
@echo " - test-sqlite run unit test for sqlite"
@echo " - vet examines Go source code and reports suspicious constructs"
.PHONY: lint
lint: revive
.PHONY: revive
revive:
@hash revive > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/mgechev/revive; \
fi
revive -config .revive.toml -exclude=./vendor/... ./... || exit 1
.PHONY: misspell
misspell:
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/client9/misspell/cmd/misspell; \
fi
misspell -w -i unknwon $(GOFILES)
.PHONY: misspell-check
misspell-check:
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/client9/misspell/cmd/misspell; \
fi
misspell -error -i unknwon,destory $(GOFILES)
.PHONY: test
test: test-sqlite
.PNONY: test-cockroach
test-cockroach: go-check
$(GO) test -race -db=postgres -schema='$(TEST_COCKROACH_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="postgres://$(TEST_COCKROACH_USERNAME):$(TEST_COCKROACH_PASSWORD)@$(TEST_COCKROACH_HOST)/$(TEST_COCKROACH_DBNAME)?sslmode=disable&experimental_serial_normalization=sql_sequence" \
-ignore_update_limit=true -coverprofile=cockroach.$(TEST_COCKROACH_SCHEMA).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-cockroach\#%
test-cockroach\#%: go-check
$(GO) test -race -run $* -db=postgres -schema='$(TEST_COCKROACH_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="postgres://$(TEST_COCKROACH_USERNAME):$(TEST_COCKROACH_PASSWORD)@$(TEST_COCKROACH_HOST)/$(TEST_COCKROACH_DBNAME)?sslmode=disable&experimental_serial_normalization=sql_sequence" \
-ignore_update_limit=true -coverprofile=cockroach.$(TEST_COCKROACH_SCHEMA).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-mssql
test-mssql: go-check
$(GO) test -v -race -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \
-conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \
-coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-mssql\#%
test-mssql\#%: go-check
$(GO) test -v -race -run $* -db=mssql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \
-conn_str="server=$(TEST_MSSQL_HOST);user id=$(TEST_MSSQL_USERNAME);password=$(TEST_MSSQL_PASSWORD);database=$(TEST_MSSQL_DBNAME)" \
-coverprofile=mssql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-mymysql
test-mymysql: go-check
$(GO) test -v -race -db=mymysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \
-conn_str="tcp:$(TEST_MYSQL_HOST)*$(TEST_MYSQL_DBNAME)/$(TEST_MYSQL_USERNAME)/$(TEST_MYSQL_PASSWORD)" \
-coverprofile=mymysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-mymysql\#%
test-mymysql\#%: go-check
$(GO) test -v -race -run $* -db=mymysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \
-conn_str="tcp:$(TEST_MYSQL_HOST)*$(TEST_MYSQL_DBNAME)/$(TEST_MYSQL_USERNAME)/$(TEST_MYSQL_PASSWORD)" \
-coverprofile=mymysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-mysql
test-mysql: go-check
$(GO) test -v -race -db=mysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \
-conn_str="$(TEST_MYSQL_USERNAME):$(TEST_MYSQL_PASSWORD)@tcp($(TEST_MYSQL_HOST))/$(TEST_MYSQL_DBNAME)?charset=$(TEST_MYSQL_CHARSET)" \
-coverprofile=mysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-mysql\#%
test-mysql\#%: go-check
$(GO) test -v -race -run $* -db=mysql -cache=$(TEST_CACHE_ENABLE) -quote=$(TEST_QUOTE_POLICY) \
-conn_str="$(TEST_MYSQL_USERNAME):$(TEST_MYSQL_PASSWORD)@tcp($(TEST_MYSQL_HOST))/$(TEST_MYSQL_DBNAME)?charset=$(TEST_MYSQL_CHARSET)" \
-coverprofile=mysql.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-postgres
test-postgres: go-check
$(GO) test -v -race -db=postgres -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)?sslmode=disable" \
-quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-postgres\#%
test-postgres\#%: go-check
$(GO) test -v -race -run $* -db=postgres -schema='$(TEST_PGSQL_SCHEMA)' -cache=$(TEST_CACHE_ENABLE) \
-conn_str="postgres://$(TEST_PGSQL_USERNAME):$(TEST_PGSQL_PASSWORD)@$(TEST_PGSQL_HOST)/$(TEST_PGSQL_DBNAME)?sslmode=disable" \
-quote=$(TEST_QUOTE_POLICY) -coverprofile=postgres.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-sqlite
test-sqlite: go-check
$(GO) test -v -race -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \
-quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-sqlite-schema
test-sqlite-schema: go-check
$(GO) test -v -race -schema=xorm -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \
-quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-sqlite\#%
test-sqlite\#%: go-check
$(GO) test -v -race -run $* -cache=$(TEST_CACHE_ENABLE) -db=sqlite3 -conn_str="./test.db?cache=shared&mode=rwc" \
-quote=$(TEST_QUOTE_POLICY) -coverprofile=sqlite.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PNONY: test-tidb
test-tidb: go-check
$(GO) test -v -race -db=mysql -cache=$(TEST_CACHE_ENABLE) -ignore_select_update=true \
-conn_str="$(TEST_TIDB_USERNAME):$(TEST_TIDB_PASSWORD)@tcp($(TEST_TIDB_HOST))/$(TEST_TIDB_DBNAME)" \
-quote=$(TEST_QUOTE_POLICY) -coverprofile=tidb.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: test-tidb\#%
test-tidb\#%: go-check
$(GO) test -v -race -run $* -db=mysql -cache=$(TEST_CACHE_ENABLE) -ignore_select_update=true \
-conn_str="$(TEST_TIDB_USERNAME):$(TEST_TIDB_PASSWORD)@tcp($(TEST_TIDB_HOST))/$(TEST_TIDB_DBNAME)" \
-quote=$(TEST_QUOTE_POLICY) -coverprofile=tidb.$(TEST_QUOTE_POLICY).$(TEST_CACHE_ENABLE).coverage.out -covermode=atomic
.PHONY: vet
vet:
$(GO) vet $(PACKAGES)

67
vendor/xorm.io/xorm/README.md generated vendored
View file

@ -8,51 +8,50 @@ Xorm is a simple and powerful ORM for Go.
[![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm) [![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm)
[![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) [![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3)
## Notice
v1.0.0 has some break changes from v0.8.2.
- Removed some non gonic function name `Id`, `Sql`, please use `ID`, `SQL` instead.
- Removed the dependent from `xorm.io/core` and moved the codes to `xorm.io/xorm/core`, `xorm.io/xorm/names`, `xorm.io/xorm/schemas` and others.
- Renamed some interface names. i.e. `core.IMapper` -> `names.Mapper`, `core.ILogger` -> `log.Logger`.
## Features ## Features
* Struct <-> Table Mapping Support * Struct <-> Table Mapping Support
* Chainable APIs * Chainable APIs
* Transaction Support * Transaction Support
* Both ORM and raw SQL operation Support * Both ORM and raw SQL operation Support
* Sync database schema Support * Sync database schema Support
* Query Cache speed up * Query Cache speed up
* Database Reverse support via [xorm.io/reverse](https://xorm.io/reverse)
* Database Reverse support, See [Xorm Tool README](https://github.com/go-xorm/cmd/blob/master/README.md)
* Simple cascade loading support * Simple cascade loading support
* Optimistic Locking support * Optimistic Locking support
* SQL Builder support via [xorm.io/builder](https://xorm.io/builder) * SQL Builder support via [xorm.io/builder](https://xorm.io/builder)
* Automatical Read/Write seperatelly * Automatical Read/Write seperatelly
* Postgres schema support * Postgres schema support
* Context Cache support * Context Cache support
* Support log/SQLLog context
## Drivers Support ## Drivers Support
Drivers for Go's sql package which currently support database/sql includes: Drivers for Go's sql package which currently support database/sql includes:
* Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) * [Mysql5.*](https://github.com/mysql/mysql-server/tree/5.7) / [Mysql8.*](https://github.com/mysql/mysql-server) / [Mariadb](https://github.com/MariaDB/server) / [Tidb](https://github.com/pingcap/tidb)
- [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)
- [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv)
* MyMysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/tree/master/godrv) * [Postgres](https://github.com/postgres/postgres) / [Cockroach](https://github.com/cockroachdb/cockroach)
- [github.com/lib/pq](https://github.com/lib/pq)
* Postgres: [github.com/lib/pq](https://github.com/lib/pq) * [SQLite](https://sqlite.org)
- [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
* Tidb: [github.com/pingcap/tidb](https://github.com/pingcap/tidb) * MsSql
- [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
* SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) * Oracle
- [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (experiment)
* MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
* Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (experiment)
## Installation ## Installation
@ -62,7 +61,7 @@ Drivers for Go's sql package which currently support database/sql includes:
* [Manual](http://xorm.io/docs) * [Manual](http://xorm.io/docs)
* [GoDoc](http://godoc.org/xorm.io/xorm) * [GoDoc](http://pkg.go.dev/xorm.io/xorm)
## Quick Start ## Quick Start
@ -440,27 +439,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
## Changelog ## Changelog
* **v0.7.0** You can find all the changelog [here](CHANGELOG.md)
* Some bugs fixed
* **v0.6.6**
* Some bugs fixed
* **v0.6.5**
* Postgres schema support
* vgo support
* Add FindAndCount
* Database special params support via NewEngineWithParams
* Some bugs fixed
* **v0.6.4**
* Automatical Read/Write seperatelly
* Query/QueryString/QueryInterface and action with Where/And
* Get support non-struct variables
* BufferSize on Iterate
* fix some other bugs.
[More changes ...](https://github.com/go-xorm/manual-en-US/tree/master/chapter-16)
## Cases ## Cases

82
vendor/xorm.io/xorm/README_CN.md generated vendored
View file

@ -2,57 +2,55 @@
[English](https://gitea.com/xorm/xorm/src/branch/master/README.md) [English](https://gitea.com/xorm/xorm/src/branch/master/README.md)
xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。 xorm 是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作非常简便。
[![Build Status](https://drone.gitea.com/api/badges/xorm/builder/status.svg)](https://drone.gitea.com/xorm/builder) [![](http://gocover.io/_badge/xorm.io/xorm)](https://gocover.io/xorm.io/xorm) [![Build Status](https://drone.gitea.com/api/badges/xorm/xorm/status.svg)](https://drone.gitea.com/xorm/xorm) [![](http://gocover.io/_badge/xorm.io/xorm)](https://gocover.io/xorm.io/xorm)
[![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm) [![](https://goreportcard.com/badge/xorm.io/xorm)](https://goreportcard.com/report/xorm.io/xorm)
[![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3) [![Join the chat at https://img.shields.io/discord/323460943201959939.svg](https://img.shields.io/discord/323460943201959939.svg)](https://discord.gg/HuR2CF3)
## Notice
v1.0.0 相对于 v0.8.2 有以下不兼容的变更:
- 移除了部分不符合Go语言命名的函数`Id`, `Sql`,请使用 `ID`, `SQL` 替代。
- 删除了对 `xorm.io/core` 的依赖。大部分代码迁移到了 `xorm.io/xorm/core`, `xorm.io/xorm/names`, `xorm.io/xorm/schemas` 等等几个包中.
- 重命名了几个结构体,如: `core.IMapper` -> `names.Mapper`, `core.ILogger` -> `log.Logger`.
## 特性 ## 特性
* 支持Struct和数据库表之间的灵活映射并支持自动同步 * 支持 Struct 和数据库表之间的灵活映射,并支持自动同步
* 事务支持 * 事务支持
* 同时支持原始SQL语句和ORM操作的混合执行 * 同时支持原始SQL语句和ORM操作的混合执行
* 使用连写来简化调用 * 使用连写来简化调用
* 支持使用ID, In, Where, Limit, Join, Having, Table, SQL, Cols等函数和结构体等方式作为条件
* 支持使用Id, In, Where, Limit, Join, Having, Table, Sql, Cols等函数和结构体等方式作为条件
* 支持级联加载Struct * 支持级联加载Struct
* Schema支持仅Postgres * Schema支持仅Postgres
* 支持缓存 * 支持缓存
* 通过 [xorm.io/reverse](https://xorm.io/reverse) 支持根据数据库自动生成 xorm 结构体
* 支持根据数据库自动生成xorm的结构体
* 支持记录版本(即乐观锁) * 支持记录版本(即乐观锁)
* 通过 [xorm.io/builder](https://xorm.io/builder) 内置 SQL Builder 支持
* 内置SQL Builder支持
* 上下文缓存支持 * 上下文缓存支持
* 支持日志上下文
## 驱动支持 ## 驱动支持
目前支持的Go数据库驱动和对应的数据库如下 目前支持的Go数据库驱动和对应的数据库如下
* Mysql: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) * [Mysql5.*](https://github.com/mysql/mysql-server/tree/5.7) / [Mysql8.*](https://github.com/mysql/mysql-server) / [Mariadb](https://github.com/MariaDB/server) / [Tidb](https://github.com/pingcap/tidb)
- [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql)
- [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv)
* MyMysql: [github.com/ziutek/mymysql/godrv](https://github.com/ziutek/mymysql/godrv) * [Postgres](https://github.com/postgres/postgres) / [Cockroach](https://github.com/cockroachdb/cockroach)
- [github.com/lib/pq](https://github.com/lib/pq)
* Postgres: [github.com/lib/pq](https://github.com/lib/pq) * [SQLite](https://sqlite.org)
- [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3)
* Tidb: [github.com/pingcap/tidb](https://github.com/pingcap/tidb) * MsSql
- [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
* SQLite: [github.com/mattn/go-sqlite3](https://github.com/mattn/go-sqlite3) * Oracle
- [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (试验性支持)
* MsSql: [github.com/denisenkom/go-mssqldb](https://github.com/denisenkom/go-mssqldb)
* MsSql: [github.com/lunny/godbc](https://github.com/lunny/godbc)
* Oracle: [github.com/mattn/go-oci8](https://github.com/mattn/go-oci8) (试验性支持)
## 安装 ## 安装
@ -62,7 +60,7 @@ xorm是一个简单而强大的Go语言ORM库. 通过它可以使数据库操作
* [操作指南](http://xorm.io/docs) * [操作指南](http://xorm.io/docs)
* [Godoc代码文档](http://godoc.org/xorm.io/xorm) * [Godoc代码文档](http://pkg.go.dev/xorm.io/xorm)
# 快速开始 # 快速开始
@ -435,14 +433,14 @@ res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error)
# 案例 # 案例
* [Go语言中文网](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang)
* [Gitea](http://gitea.io) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea) * [Gitea](http://gitea.io) - [github.com/go-gitea/gitea](http://github.com/go-gitea/gitea)
* [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs) * [Gogs](http://try.gogits.org) - [github.com/gogits/gogs](http://github.com/gogits/gogs)
* [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana) * [grafana](https://grafana.com/) - [github.com/grafana/grafana](http://github.com/grafana/grafana)
* [Go语言中文网](http://studygolang.com/) - [github.com/studygolang/studygolang](https://github.com/studygolang/studygolang)
* [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader) * [github.com/m3ng9i/qreader](https://github.com/m3ng9i/qreader)
* [Wego](http://github.com/go-tango/wego) * [Wego](http://github.com/go-tango/wego)
@ -470,27 +468,7 @@ res, err := engine.Transaction(func(session *xorm.Session) (interface{}, error)
## 更新日志 ## 更新日志
* **v0.7.0** 请访问 [CHANGELOG.md](CHANGELOG.md) 获得更新日志。
* 修正部分Bug
* **v0.6.6**
* 修正部分Bug
* **v0.6.5**
* 通过 engine.SetSchema 来支持 schema当前仅支持Postgres
* vgo 支持
* 新增 `FindAndCount` 函数
* 通过 `NewEngineWithParams` 支持数据库特别参数
* 修正部分Bug
* **v0.6.4**
* 自动读写分离支持
* Query/QueryString/QueryInterface 支持与 Where/And 合用
* `Get` 支持获取非结构体变量
* `Iterate` 支持 `BufferSize`
* 修正部分Bug
[更多更新日志...](https://github.com/go-xorm/manual-zh-CN/tree/master/chapter-16)
## LICENSE ## LICENSE

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package core package caches
import ( import (
"bytes" "bytes"
@ -11,6 +11,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"time" "time"
"xorm.io/xorm/schemas"
) )
const ( const (
@ -28,6 +30,8 @@ const (
var ( var (
ErrCacheMiss = errors.New("xorm/cache: key not found") ErrCacheMiss = errors.New("xorm/cache: key not found")
ErrNotStored = errors.New("xorm/cache: not stored") ErrNotStored = errors.New("xorm/cache: not stored")
// ErrNotExist record does not exist error
ErrNotExist = errors.New("Record does not exist")
) )
// CacheStore is a interface to store cache // CacheStore is a interface to store cache
@ -53,7 +57,7 @@ type Cacher interface {
ClearBeans(tableName string) ClearBeans(tableName string)
} }
func encodeIds(ids []PK) (string, error) { func encodeIds(ids []schemas.PK) (string, error) {
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
enc := gob.NewEncoder(buf) enc := gob.NewEncoder(buf)
err := enc.Encode(ids) err := enc.Encode(ids)
@ -61,8 +65,8 @@ func encodeIds(ids []PK) (string, error) {
return buf.String(), err return buf.String(), err
} }
func decodeIds(s string) ([]PK, error) { func decodeIds(s string) ([]schemas.PK, error) {
pks := make([]PK, 0) pks := make([]schemas.PK, 0)
dec := gob.NewDecoder(strings.NewReader(s)) dec := gob.NewDecoder(strings.NewReader(s))
err := dec.Decode(&pks) err := dec.Decode(&pks)
@ -71,7 +75,7 @@ func decodeIds(s string) ([]PK, error) {
} }
// GetCacheSql returns cacher PKs via SQL // GetCacheSql returns cacher PKs via SQL
func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]PK, error) { func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]schemas.PK, error) {
bytes := m.GetIds(tableName, GenSqlKey(sql, args)) bytes := m.GetIds(tableName, GenSqlKey(sql, args))
if bytes == nil { if bytes == nil {
return nil, errors.New("Not Exist") return nil, errors.New("Not Exist")
@ -80,7 +84,7 @@ func GetCacheSql(m Cacher, tableName, sql string, args interface{}) ([]PK, error
} }
// PutCacheSql puts cacher SQL and PKs // PutCacheSql puts cacher SQL and PKs
func PutCacheSql(m Cacher, ids []PK, tableName, sql string, args interface{}) error { func PutCacheSql(m Cacher, ids []schemas.PK, tableName, sql string, args interface{}) error {
bytes, err := encodeIds(ids) bytes, err := encodeIds(ids)
if err != nil { if err != nil {
return err return err

58
vendor/xorm.io/xorm/caches/encode.go generated vendored Normal file
View file

@ -0,0 +1,58 @@
// Copyright 2020 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package caches
import (
"bytes"
"crypto/md5"
"encoding/gob"
"encoding/json"
"fmt"
"io"
)
// md5 hash string
func Md5(str string) string {
m := md5.New()
io.WriteString(m, str)
return fmt.Sprintf("%x", m.Sum(nil))
}
func Encode(data interface{}) ([]byte, error) {
//return JsonEncode(data)
return GobEncode(data)
}
func Decode(data []byte, to interface{}) error {
//return JsonDecode(data, to)
return GobDecode(data, to)
}
func GobEncode(data interface{}) ([]byte, error) {
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(&data)
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func GobDecode(data []byte, to interface{}) error {
buf := bytes.NewBuffer(data)
dec := gob.NewDecoder(buf)
return dec.Decode(to)
}
func JsonEncode(data interface{}) ([]byte, error) {
val, err := json.Marshal(data)
if err != nil {
return nil, err
}
return val, nil
}
func JsonDecode(data []byte, to interface{}) error {
return json.Unmarshal(data, to)
}

94
vendor/xorm.io/xorm/caches/leveldb.go generated vendored Normal file
View file

@ -0,0 +1,94 @@
// Copyright 2020 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package caches
import (
"log"
"github.com/syndtr/goleveldb/leveldb"
)
// LevelDBStore implements CacheStore provide local machine
type LevelDBStore struct {
store *leveldb.DB
Debug bool
v interface{}
}
var _ CacheStore = &LevelDBStore{}
func NewLevelDBStore(dbfile string) (*LevelDBStore, error) {
db := &LevelDBStore{}
h, err := leveldb.OpenFile(dbfile, nil)
if err != nil {
return nil, err
}
db.store = h
return db, nil
}
func (s *LevelDBStore) Put(key string, value interface{}) error {
val, err := Encode(value)
if err != nil {
if s.Debug {
log.Println("[LevelDB]EncodeErr: ", err, "Key:", key)
}
return err
}
err = s.store.Put([]byte(key), val, nil)
if err != nil {
if s.Debug {
log.Println("[LevelDB]PutErr: ", err, "Key:", key)
}
return err
}
if s.Debug {
log.Println("[LevelDB]Put: ", key)
}
return err
}
func (s *LevelDBStore) Get(key string) (interface{}, error) {
data, err := s.store.Get([]byte(key), nil)
if err != nil {
if s.Debug {
log.Println("[LevelDB]GetErr: ", err, "Key:", key)
}
if err == leveldb.ErrNotFound {
return nil, ErrNotExist
}
return nil, err
}
err = Decode(data, &s.v)
if err != nil {
if s.Debug {
log.Println("[LevelDB]DecodeErr: ", err, "Key:", key)
}
return nil, err
}
if s.Debug {
log.Println("[LevelDB]Get: ", key, s.v)
}
return s.v, err
}
func (s *LevelDBStore) Del(key string) error {
err := s.store.Delete([]byte(key), nil)
if err != nil {
if s.Debug {
log.Println("[LevelDB]DelErr: ", err, "Key:", key)
}
return err
}
if s.Debug {
log.Println("[LevelDB]Del: ", key)
}
return err
}
func (s *LevelDBStore) Close() {
s.store.Close()
}

View file

@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package caches
import ( import (
"container/list" "container/list"
"fmt" "fmt"
"sync" "sync"
"time" "time"
"xorm.io/core"
) )
// LRUCacher implments cache object facilities // LRUCacher implments cache object facilities
@ -19,7 +17,7 @@ type LRUCacher struct {
sqlList *list.List sqlList *list.List
idIndex map[string]map[string]*list.Element idIndex map[string]map[string]*list.Element
sqlIndex map[string]map[string]*list.Element sqlIndex map[string]map[string]*list.Element
store core.CacheStore store CacheStore
mutex sync.Mutex mutex sync.Mutex
MaxElementSize int MaxElementSize int
Expired time.Duration Expired time.Duration
@ -27,15 +25,15 @@ type LRUCacher struct {
} }
// NewLRUCacher creates a cacher // NewLRUCacher creates a cacher
func NewLRUCacher(store core.CacheStore, maxElementSize int) *LRUCacher { func NewLRUCacher(store CacheStore, maxElementSize int) *LRUCacher {
return NewLRUCacher2(store, 3600*time.Second, maxElementSize) return NewLRUCacher2(store, 3600*time.Second, maxElementSize)
} }
// NewLRUCacher2 creates a cache include different params // NewLRUCacher2 creates a cache include different params
func NewLRUCacher2(store core.CacheStore, expired time.Duration, maxElementSize int) *LRUCacher { func NewLRUCacher2(store CacheStore, expired time.Duration, maxElementSize int) *LRUCacher {
cacher := &LRUCacher{store: store, idList: list.New(), cacher := &LRUCacher{store: store, idList: list.New(),
sqlList: list.New(), Expired: expired, sqlList: list.New(), Expired: expired,
GcInterval: core.CacheGcInterval, MaxElementSize: maxElementSize, GcInterval: CacheGcInterval, MaxElementSize: maxElementSize,
sqlIndex: make(map[string]map[string]*list.Element), sqlIndex: make(map[string]map[string]*list.Element),
idIndex: make(map[string]map[string]*list.Element), idIndex: make(map[string]map[string]*list.Element),
} }
@ -57,7 +55,7 @@ func (m *LRUCacher) GC() {
defer m.mutex.Unlock() defer m.mutex.Unlock()
var removedNum int var removedNum int
for e := m.idList.Front(); e != nil; { for e := m.idList.Front(); e != nil; {
if removedNum <= core.CacheGcMaxRemoved && if removedNum <= CacheGcMaxRemoved &&
time.Now().Sub(e.Value.(*idNode).lastVisit) > m.Expired { time.Now().Sub(e.Value.(*idNode).lastVisit) > m.Expired {
removedNum++ removedNum++
next := e.Next() next := e.Next()
@ -71,7 +69,7 @@ func (m *LRUCacher) GC() {
removedNum = 0 removedNum = 0
for e := m.sqlList.Front(); e != nil; { for e := m.sqlList.Front(); e != nil; {
if removedNum <= core.CacheGcMaxRemoved && if removedNum <= CacheGcMaxRemoved &&
time.Now().Sub(e.Value.(*sqlNode).lastVisit) > m.Expired { time.Now().Sub(e.Value.(*sqlNode).lastVisit) > m.Expired {
removedNum++ removedNum++
next := e.Next() next := e.Next()
@ -268,11 +266,11 @@ type sqlNode struct {
} }
func genSQLKey(sql string, args interface{}) string { func genSQLKey(sql string, args interface{}) string {
return fmt.Sprintf("%v-%v", sql, args) return fmt.Sprintf("%s-%v", sql, args)
} }
func genID(prefix string, id string) string { func genID(prefix string, id string) string {
return fmt.Sprintf("%v-%v", prefix, id) return fmt.Sprintf("%s-%s", prefix, id)
} }
func newIDNode(tbName string, id string) *idNode { func newIDNode(tbName string, id string) *idNode {

56
vendor/xorm.io/xorm/caches/manager.go generated vendored Normal file
View file

@ -0,0 +1,56 @@
// Copyright 2020 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package caches
import "sync"
type Manager struct {
cacher Cacher
disableGlobalCache bool
cachers map[string]Cacher
cacherLock sync.RWMutex
}
func NewManager() *Manager {
return &Manager{
cachers: make(map[string]Cacher),
}
}
// SetDisableGlobalCache disable global cache or not
func (mgr *Manager) SetDisableGlobalCache(disable bool) {
if mgr.disableGlobalCache != disable {
mgr.disableGlobalCache = disable
}
}
func (mgr *Manager) SetCacher(tableName string, cacher Cacher) {
mgr.cacherLock.Lock()
mgr.cachers[tableName] = cacher
mgr.cacherLock.Unlock()
}
func (mgr *Manager) GetCacher(tableName string) Cacher {
var cacher Cacher
var ok bool
mgr.cacherLock.RLock()
cacher, ok = mgr.cachers[tableName]
mgr.cacherLock.RUnlock()
if !ok && !mgr.disableGlobalCache {
cacher = mgr.cacher
}
return cacher
}
// SetDefaultCacher set the default cacher. Xorm's default not enable cacher.
func (mgr *Manager) SetDefaultCacher(cacher Cacher) {
mgr.cacher = cacher
}
// GetDefaultCacher returns the default cacher
func (mgr *Manager) GetDefaultCacher() Cacher {
return mgr.cacher
}

View file

@ -2,15 +2,13 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package caches
import ( import (
"sync" "sync"
"xorm.io/core"
) )
var _ core.CacheStore = NewMemoryStore() var _ CacheStore = NewMemoryStore()
// MemoryStore represents in-memory store // MemoryStore represents in-memory store
type MemoryStore struct { type MemoryStore struct {

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package contexts
// ContextCache is the interface that operates the cache data. // ContextCache is the interface that operates the cache data.
type ContextCache interface { type ContextCache interface {

125
vendor/xorm.io/xorm/convert.go generated vendored
View file

@ -346,3 +346,128 @@ func asBool(bs []byte) (bool, error) {
} }
return strconv.ParseBool(string(bs)) return strconv.ParseBool(string(bs))
} }
// str2PK convert string value to primary key value according to tp
func str2PKValue(s string, tp reflect.Type) (reflect.Value, error) {
var err error
var result interface{}
var defReturn = reflect.Zero(tp)
switch tp.Kind() {
case reflect.Int:
result, err = strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int: %s", s, err.Error())
}
case reflect.Int8:
x, err := strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int8: %s", s, err.Error())
}
result = int8(x)
case reflect.Int16:
x, err := strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int16: %s", s, err.Error())
}
result = int16(x)
case reflect.Int32:
x, err := strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int32: %s", s, err.Error())
}
result = int32(x)
case reflect.Int64:
result, err = strconv.ParseInt(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int64: %s", s, err.Error())
}
case reflect.Uint:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint: %s", s, err.Error())
}
result = uint(x)
case reflect.Uint8:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint8: %s", s, err.Error())
}
result = uint8(x)
case reflect.Uint16:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint16: %s", s, err.Error())
}
result = uint16(x)
case reflect.Uint32:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint32: %s", s, err.Error())
}
result = uint32(x)
case reflect.Uint64:
result, err = strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint64: %s", s, err.Error())
}
case reflect.String:
result = s
default:
return defReturn, errors.New("unsupported convert type")
}
return reflect.ValueOf(result).Convert(tp), nil
}
func str2PK(s string, tp reflect.Type) (interface{}, error) {
v, err := str2PKValue(s, tp)
if err != nil {
return nil, err
}
return v.Interface(), nil
}
func int64ToIntValue(id int64, tp reflect.Type) reflect.Value {
var v interface{}
kind := tp.Kind()
if kind == reflect.Ptr {
kind = tp.Elem().Kind()
}
switch kind {
case reflect.Int16:
temp := int16(id)
v = &temp
case reflect.Int32:
temp := int32(id)
v = &temp
case reflect.Int:
temp := int(id)
v = &temp
case reflect.Int64:
temp := id
v = &temp
case reflect.Uint16:
temp := uint16(id)
v = &temp
case reflect.Uint32:
temp := uint32(id)
v = &temp
case reflect.Uint64:
temp := uint64(id)
v = &temp
case reflect.Uint:
temp := uint(id)
v = &temp
}
if tp.Kind() == reflect.Ptr {
return reflect.ValueOf(v).Convert(tp)
}
return reflect.ValueOf(v).Elem().Convert(tp)
}
func int64ToInt(id int64, tp reflect.Type) interface{} {
return int64ToIntValue(id, tp).Interface()
}

View file

@ -1,8 +1,8 @@
// Copyright 2019 The Xorm Authors. All rights reserved. // Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package core package convert
// Conversion is an interface. A type implements Conversion will according // Conversion is an interface. A type implements Conversion will according
// the custom method to fill into database and retrieve from database. // the custom method to fill into database and retrieve from database.

View file

@ -12,6 +12,10 @@ import (
"reflect" "reflect"
"regexp" "regexp"
"sync" "sync"
"time"
"xorm.io/xorm/log"
"xorm.io/xorm/names"
) )
var ( var (
@ -76,9 +80,10 @@ type cacheStruct struct {
// DB is a wrap of sql.DB with extra contents // DB is a wrap of sql.DB with extra contents
type DB struct { type DB struct {
*sql.DB *sql.DB
Mapper IMapper Mapper names.Mapper
reflectCache map[reflect.Type]*cacheStruct reflectCache map[reflect.Type]*cacheStruct
reflectCacheMutex sync.RWMutex reflectCacheMutex sync.RWMutex
Logger log.ContextLogger
} }
// Open opens a database // Open opens a database
@ -89,7 +94,7 @@ func Open(driverName, dataSourceName string) (*DB, error) {
} }
return &DB{ return &DB{
DB: db, DB: db,
Mapper: NewCacheMapper(&SnakeMapper{}), Mapper: names.NewCacheMapper(&names.SnakeMapper{}),
reflectCache: make(map[reflect.Type]*cacheStruct), reflectCache: make(map[reflect.Type]*cacheStruct),
}, nil }, nil
} }
@ -98,11 +103,24 @@ func Open(driverName, dataSourceName string) (*DB, error) {
func FromDB(db *sql.DB) *DB { func FromDB(db *sql.DB) *DB {
return &DB{ return &DB{
DB: db, DB: db,
Mapper: NewCacheMapper(&SnakeMapper{}), Mapper: names.NewCacheMapper(&names.SnakeMapper{}),
reflectCache: make(map[reflect.Type]*cacheStruct), reflectCache: make(map[reflect.Type]*cacheStruct),
} }
} }
// NeedLogSQL returns true if need to log SQL
func (db *DB) NeedLogSQL(ctx context.Context) bool {
if db.Logger == nil {
return false
}
v := ctx.Value("__xorm_show_sql")
if showSQL, ok := v.(bool); ok {
return showSQL
}
return db.Logger.IsShowSQL()
}
func (db *DB) reflectNew(typ reflect.Type) reflect.Value { func (db *DB) reflectNew(typ reflect.Type) reflect.Value {
db.reflectCacheMutex.Lock() db.reflectCacheMutex.Lock()
defer db.reflectCacheMutex.Unlock() defer db.reflectCacheMutex.Unlock()
@ -118,7 +136,25 @@ func (db *DB) reflectNew(typ reflect.Type) reflect.Value {
// QueryContext overwrites sql.DB.QueryContext // QueryContext overwrites sql.DB.QueryContext
func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
start := time.Now()
showSQL := db.NeedLogSQL(ctx)
if showSQL {
db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
})
}
rows, err := db.DB.QueryContext(ctx, query, args...) rows, err := db.DB.QueryContext(ctx, query, args...)
if showSQL {
db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
if rows != nil { if rows != nil {
rows.Close() rows.Close()
@ -207,7 +243,7 @@ func (db *DB) ExecMapContext(ctx context.Context, query string, mp interface{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return db.DB.ExecContext(ctx, query, args...) return db.ExecContext(ctx, query, args...)
} }
func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) { func (db *DB) ExecMap(query string, mp interface{}) (sql.Result, error) {
@ -219,7 +255,30 @@ func (db *DB) ExecStructContext(ctx context.Context, query string, st interface{
if err != nil { if err != nil {
return nil, err return nil, err
} }
return db.DB.ExecContext(ctx, query, args...) return db.ExecContext(ctx, query, args...)
}
func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
start := time.Now()
showSQL := db.NeedLogSQL(ctx)
if showSQL {
db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
})
}
res, err := db.DB.ExecContext(ctx, query, args...)
if showSQL {
db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
return res, err
} }
func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) { func (db *DB) ExecStruct(query string, st interface{}) (sql.Result, error) {

View file

@ -9,6 +9,9 @@ import (
"database/sql" "database/sql"
"errors" "errors"
"reflect" "reflect"
"time"
"xorm.io/xorm/log"
) )
// Stmt reprents a stmt objects // Stmt reprents a stmt objects
@ -16,6 +19,7 @@ type Stmt struct {
*sql.Stmt *sql.Stmt
db *DB db *DB
names map[string]int names map[string]int
query string
} }
func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) { func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
@ -27,11 +31,28 @@ func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
return "?" return "?"
}) })
start := time.Now()
showSQL := db.NeedLogSQL(ctx)
if showSQL {
db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
})
}
stmt, err := db.DB.PrepareContext(ctx, query) stmt, err := db.DB.PrepareContext(ctx, query)
if showSQL {
db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Stmt{stmt, db, names}, nil
return &Stmt{stmt, db, names, query}, nil
} }
func (db *DB) Prepare(query string) (*Stmt, error) { func (db *DB) Prepare(query string) (*Stmt, error) {
@ -48,7 +69,7 @@ func (s *Stmt) ExecMapContext(ctx context.Context, mp interface{}) (sql.Result,
for k, i := range s.names { for k, i := range s.names {
args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface() args[i] = vv.Elem().MapIndex(reflect.ValueOf(k)).Interface()
} }
return s.Stmt.ExecContext(ctx, args...) return s.ExecContext(ctx, args...)
} }
func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) { func (s *Stmt) ExecMap(mp interface{}) (sql.Result, error) {
@ -65,15 +86,56 @@ func (s *Stmt) ExecStructContext(ctx context.Context, st interface{}) (sql.Resul
for k, i := range s.names { for k, i := range s.names {
args[i] = vv.Elem().FieldByName(k).Interface() args[i] = vv.Elem().FieldByName(k).Interface()
} }
return s.Stmt.ExecContext(ctx, args...) return s.ExecContext(ctx, args...)
} }
func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) { func (s *Stmt) ExecStruct(st interface{}) (sql.Result, error) {
return s.ExecStructContext(context.Background(), st) return s.ExecStructContext(context.Background(), st)
} }
func (s *Stmt) ExecContext(ctx context.Context, args ...interface{}) (sql.Result, error) {
start := time.Now()
showSQL := s.db.NeedLogSQL(ctx)
if showSQL {
s.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
})
}
res, err := s.Stmt.ExecContext(ctx, args)
if showSQL {
s.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
return res, err
}
func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) { func (s *Stmt) QueryContext(ctx context.Context, args ...interface{}) (*Rows, error) {
start := time.Now()
showSQL := s.db.NeedLogSQL(ctx)
if showSQL {
s.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
})
}
rows, err := s.Stmt.QueryContext(ctx, args...) rows, err := s.Stmt.QueryContext(ctx, args...)
if showSQL {
s.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: s.query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -7,6 +7,9 @@ package core
import ( import (
"context" "context"
"database/sql" "database/sql"
"time"
"xorm.io/xorm/log"
) )
type Tx struct { type Tx struct {
@ -15,7 +18,23 @@ type Tx struct {
} }
func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) { func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
start := time.Now()
showSQL := db.NeedLogSQL(ctx)
if showSQL {
db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: "BEGIN TRANSACTION",
})
}
tx, err := db.DB.BeginTx(ctx, opts) tx, err := db.DB.BeginTx(ctx, opts)
if showSQL {
db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: "BEGIN TRANSACTION",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -23,11 +42,7 @@ func (db *DB) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error) {
} }
func (db *DB) Begin() (*Tx, error) { func (db *DB) Begin() (*Tx, error) {
tx, err := db.DB.Begin() return db.BeginTx(context.Background(), nil)
if err != nil {
return nil, err
}
return &Tx{tx, db}, nil
} }
func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) { func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
@ -39,11 +54,27 @@ func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error) {
return "?" return "?"
}) })
start := time.Now()
showSQL := tx.db.NeedLogSQL(ctx)
if showSQL {
tx.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
})
}
stmt, err := tx.Tx.PrepareContext(ctx, query) stmt, err := tx.Tx.PrepareContext(ctx, query)
if showSQL {
tx.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: "PREPARE",
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &Stmt{stmt, tx.db, names}, nil return &Stmt{stmt, tx.db, names, query}, nil
} }
func (tx *Tx) Prepare(query string) (*Stmt, error) { func (tx *Tx) Prepare(query string) (*Stmt, error) {
@ -64,7 +95,7 @@ func (tx *Tx) ExecMapContext(ctx context.Context, query string, mp interface{})
if err != nil { if err != nil {
return nil, err return nil, err
} }
return tx.Tx.ExecContext(ctx, query, args...) return tx.ExecContext(ctx, query, args...)
} }
func (tx *Tx) ExecMap(query string, mp interface{}) (sql.Result, error) { func (tx *Tx) ExecMap(query string, mp interface{}) (sql.Result, error) {
@ -76,7 +107,30 @@ func (tx *Tx) ExecStructContext(ctx context.Context, query string, st interface{
if err != nil { if err != nil {
return nil, err return nil, err
} }
return tx.Tx.ExecContext(ctx, query, args...) return tx.ExecContext(ctx, query, args...)
}
func (tx *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error) {
start := time.Now()
showSQL := tx.db.NeedLogSQL(ctx)
if showSQL {
tx.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
})
}
res, err := tx.Tx.ExecContext(ctx, query, args...)
if showSQL {
tx.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
return res, err
} }
func (tx *Tx) ExecStruct(query string, st interface{}) (sql.Result, error) { func (tx *Tx) ExecStruct(query string, st interface{}) (sql.Result, error) {
@ -84,8 +138,29 @@ func (tx *Tx) ExecStruct(query string, st interface{}) (sql.Result, error) {
} }
func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) { func (tx *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error) {
start := time.Now()
showSQL := tx.db.NeedLogSQL(ctx)
if showSQL {
tx.db.Logger.BeforeSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
})
}
rows, err := tx.Tx.QueryContext(ctx, query, args...) rows, err := tx.Tx.QueryContext(ctx, query, args...)
if showSQL {
tx.db.Logger.AfterSQL(log.LogContext{
Ctx: ctx,
SQL: query,
Args: args,
ExecuteTime: time.Now().Sub(start),
Err: err,
})
}
if err != nil { if err != nil {
if rows != nil {
rows.Close()
}
return nil, err return nil, err
} }
return &Rows{rows, tx.db}, nil return &Rows{rows, tx.db}, nil

278
vendor/xorm.io/xorm/dialects/dialect.go generated vendored Normal file
View file

@ -0,0 +1,278 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dialects
import (
"context"
"fmt"
"strings"
"time"
"xorm.io/xorm/core"
"xorm.io/xorm/schemas"
)
// URI represents an uri to visit database
type URI struct {
DBType schemas.DBType
Proto string
Host string
Port string
DBName string
User string
Passwd string
Charset string
Laddr string
Raddr string
Timeout time.Duration
Schema string
}
// SetSchema set schema
func (uri *URI) SetSchema(schema string) {
if uri.DBType == schemas.POSTGRES {
uri.Schema = schema
}
}
// Dialect represents a kind of database
type Dialect interface {
Init(*core.DB, *URI) error
URI() *URI
DB() *core.DB
SQLType(*schemas.Column) string
FormatBytes(b []byte) string
DefaultSchema() string
IsReserved(string) bool
Quoter() schemas.Quoter
SetQuotePolicy(quotePolicy QuotePolicy)
AutoIncrStr() string
GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error)
IndexCheckSQL(tableName, idxName string) (string, []interface{})
CreateIndexSQL(tableName string, index *schemas.Index) string
DropIndexSQL(tableName string, index *schemas.Index) string
GetTables(ctx context.Context) ([]*schemas.Table, error)
IsTableExist(ctx context.Context, tableName string) (bool, error)
CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool)
DropTableSQL(tableName string) (string, bool)
GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error)
IsColumnExist(ctx context.Context, tableName string, colName string) (bool, error)
AddColumnSQL(tableName string, col *schemas.Column) string
ModifyColumnSQL(tableName string, col *schemas.Column) string
ForUpdateSQL(query string) string
Filters() []Filter
SetParams(params map[string]string)
}
// Base represents a basic dialect and all real dialects could embed this struct
type Base struct {
db *core.DB
dialect Dialect
uri *URI
quoter schemas.Quoter
}
func (b *Base) Quoter() schemas.Quoter {
return b.quoter
}
func (b *Base) DB() *core.DB {
return b.db
}
func (b *Base) DefaultSchema() string {
return ""
}
func (b *Base) Init(db *core.DB, dialect Dialect, uri *URI) error {
b.db, b.dialect, b.uri = db, dialect, uri
return nil
}
func (b *Base) URI() *URI {
return b.uri
}
func (b *Base) DBType() schemas.DBType {
return b.uri.DBType
}
// String generate column description string according dialect
func (b *Base) String(col *schemas.Column) string {
sql := b.dialect.Quoter().Quote(col.Name) + " "
sql += b.dialect.SQLType(col) + " "
if col.IsPrimaryKey {
sql += "PRIMARY KEY "
if col.IsAutoIncrement {
sql += b.dialect.AutoIncrStr() + " "
}
}
if col.Default != "" {
sql += "DEFAULT " + col.Default + " "
}
if col.Nullable {
sql += "NULL "
} else {
sql += "NOT NULL "
}
return sql
}
// StringNoPk generate column description string according dialect without primary keys
func (b *Base) StringNoPk(col *schemas.Column) string {
sql := b.dialect.Quoter().Quote(col.Name) + " "
sql += b.dialect.SQLType(col) + " "
if col.Default != "" {
sql += "DEFAULT " + col.Default + " "
}
if col.Nullable {
sql += "NULL "
} else {
sql += "NOT NULL "
}
return sql
}
func (b *Base) FormatBytes(bs []byte) string {
return fmt.Sprintf("0x%x", bs)
}
func (db *Base) DropTableSQL(tableName string) (string, bool) {
quote := db.dialect.Quoter().Quote
return fmt.Sprintf("DROP TABLE IF EXISTS %s", quote(tableName)), true
}
func (db *Base) HasRecords(ctx context.Context, query string, args ...interface{}) (bool, error) {
rows, err := db.DB().QueryContext(ctx, query, args...)
if err != nil {
return false, err
}
defer rows.Close()
if rows.Next() {
return true, nil
}
return false, nil
}
func (db *Base) IsColumnExist(ctx context.Context, tableName, colName string) (bool, error) {
quote := db.dialect.Quoter().Quote
query := fmt.Sprintf(
"SELECT %v FROM %v.%v WHERE %v = ? AND %v = ? AND %v = ?",
quote("COLUMN_NAME"),
quote("INFORMATION_SCHEMA"),
quote("COLUMNS"),
quote("TABLE_SCHEMA"),
quote("TABLE_NAME"),
quote("COLUMN_NAME"),
)
return db.HasRecords(ctx, query, db.uri.DBName, tableName, colName)
}
func (db *Base) AddColumnSQL(tableName string, col *schemas.Column) string {
return fmt.Sprintf("ALTER TABLE %v ADD %v", db.dialect.Quoter().Quote(tableName),
db.String(col))
}
func (db *Base) CreateIndexSQL(tableName string, index *schemas.Index) string {
quoter := db.dialect.Quoter()
var unique string
var idxName string
if index.Type == schemas.UniqueType {
unique = " UNIQUE"
}
idxName = index.XName(tableName)
return fmt.Sprintf("CREATE%s INDEX %v ON %v (%v)", unique,
quoter.Quote(idxName), quoter.Quote(tableName),
quoter.Join(index.Cols, ","))
}
func (db *Base) DropIndexSQL(tableName string, index *schemas.Index) string {
quote := db.dialect.Quoter().Quote
var name string
if index.IsRegular {
name = index.XName(tableName)
} else {
name = index.Name
}
return fmt.Sprintf("DROP INDEX %v ON %s", quote(name), quote(tableName))
}
func (db *Base) ModifyColumnSQL(tableName string, col *schemas.Column) string {
return fmt.Sprintf("alter table %s MODIFY COLUMN %s", tableName, db.StringNoPk(col))
}
func (b *Base) ForUpdateSQL(query string) string {
return query + " FOR UPDATE"
}
func (b *Base) SetParams(params map[string]string) {
}
var (
dialects = map[string]func() Dialect{}
)
// RegisterDialect register database dialect
func RegisterDialect(dbName schemas.DBType, dialectFunc func() Dialect) {
if dialectFunc == nil {
panic("core: Register dialect is nil")
}
dialects[strings.ToLower(string(dbName))] = dialectFunc // !nashtsai! allow override dialect
}
// QueryDialect query if registered database dialect
func QueryDialect(dbName schemas.DBType) Dialect {
if d, ok := dialects[strings.ToLower(string(dbName))]; ok {
return d()
}
return nil
}
func regDrvsNDialects() bool {
providedDrvsNDialects := map[string]struct {
dbType schemas.DBType
getDriver func() Driver
getDialect func() Dialect
}{
"mssql": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }},
"odbc": {"mssql", func() Driver { return &odbcDriver{} }, func() Dialect { return &mssql{} }}, // !nashtsai! TODO change this when supporting MS Access
"mysql": {"mysql", func() Driver { return &mysqlDriver{} }, func() Dialect { return &mysql{} }},
"mymysql": {"mysql", func() Driver { return &mymysqlDriver{} }, func() Dialect { return &mysql{} }},
"postgres": {"postgres", func() Driver { return &pqDriver{} }, func() Dialect { return &postgres{} }},
"pgx": {"postgres", func() Driver { return &pqDriverPgx{} }, func() Dialect { return &postgres{} }},
"sqlite3": {"sqlite3", func() Driver { return &sqlite3Driver{} }, func() Dialect { return &sqlite3{} }},
"oci8": {"oracle", func() Driver { return &oci8Driver{} }, func() Dialect { return &oracle{} }},
"goracle": {"oracle", func() Driver { return &goracleDriver{} }, func() Dialect { return &oracle{} }},
}
for driverName, v := range providedDrvsNDialects {
if driver := QueryDriver(driverName); driver == nil {
RegisterDriver(driverName, v.getDriver())
RegisterDialect(v.dbType, v.getDialect)
}
}
return true
}
func init() {
regDrvsNDialects()
}

63
vendor/xorm.io/xorm/dialects/driver.go generated vendored Normal file
View file

@ -0,0 +1,63 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dialects
import (
"fmt"
"xorm.io/xorm/core"
)
type Driver interface {
Parse(string, string) (*URI, error)
}
var (
drivers = map[string]Driver{}
)
func RegisterDriver(driverName string, driver Driver) {
if driver == nil {
panic("core: Register driver is nil")
}
if _, dup := drivers[driverName]; dup {
panic("core: Register called twice for driver " + driverName)
}
drivers[driverName] = driver
}
func QueryDriver(driverName string) Driver {
return drivers[driverName]
}
func RegisteredDriverSize() int {
return len(drivers)
}
// OpenDialect opens a dialect via driver name and connection string
func OpenDialect(driverName, connstr string) (Dialect, error) {
driver := QueryDriver(driverName)
if driver == nil {
return nil, fmt.Errorf("Unsupported driver name: %v", driverName)
}
uri, err := driver.Parse(driverName, connstr)
if err != nil {
return nil, err
}
dialect := QueryDialect(uri.DBType)
if dialect == nil {
return nil, fmt.Errorf("Unsupported dialect type: %v", uri.DBType)
}
db, err := core.Open(driverName, connstr)
if err != nil {
return nil, err
}
dialect.Init(db, uri)
return dialect, nil
}

43
vendor/xorm.io/xorm/dialects/filter.go generated vendored Normal file
View file

@ -0,0 +1,43 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dialects
import (
"fmt"
"strings"
)
// Filter is an interface to filter SQL
type Filter interface {
Do(sql string) string
}
// SeqFilter filter SQL replace ?, ? ... to $1, $2 ...
type SeqFilter struct {
Prefix string
Start int
}
func convertQuestionMark(sql, prefix string, start int) string {
var buf strings.Builder
var beginSingleQuote bool
var index = start
for _, c := range sql {
if !beginSingleQuote && c == '?' {
buf.WriteString(fmt.Sprintf("%s%v", prefix, index))
index++
} else {
if c == '\'' {
beginSingleQuote = !beginSingleQuote
}
buf.WriteRune(c)
}
}
return buf.String()
}
func (s *SeqFilter) Do(sql string) string {
return convertQuestionMark(sql, s.Prefix, s.Start)
}

View file

@ -2,16 +2,18 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package dialects
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"xorm.io/core" "xorm.io/xorm/core"
"xorm.io/xorm/schemas"
) )
var ( var (
@ -202,67 +204,70 @@ var (
"EXIT": true, "EXIT": true,
"PROC": true, "PROC": true,
} }
mssqlQuoter = schemas.Quoter{'[', ']', schemas.AlwaysReserve}
) )
type mssql struct { type mssql struct {
core.Base Base
} }
func (db *mssql) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error { func (db *mssql) Init(d *core.DB, uri *URI) error {
return db.Base.Init(d, db, uri, drivername, dataSourceName) db.quoter = mssqlQuoter
return db.Base.Init(d, db, uri)
} }
func (db *mssql) SqlType(c *core.Column) string { func (db *mssql) SQLType(c *schemas.Column) string {
var res string var res string
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case core.Bool: case schemas.Bool:
res = core.Bit res = schemas.Bit
if strings.EqualFold(c.Default, "true") { if strings.EqualFold(c.Default, "true") {
c.Default = "1" c.Default = "1"
} else if strings.EqualFold(c.Default, "false") { } else if strings.EqualFold(c.Default, "false") {
c.Default = "0" c.Default = "0"
} }
case core.Serial: case schemas.Serial:
c.IsAutoIncrement = true c.IsAutoIncrement = true
c.IsPrimaryKey = true c.IsPrimaryKey = true
c.Nullable = false c.Nullable = false
res = core.Int res = schemas.Int
case core.BigSerial: case schemas.BigSerial:
c.IsAutoIncrement = true c.IsAutoIncrement = true
c.IsPrimaryKey = true c.IsPrimaryKey = true
c.Nullable = false c.Nullable = false
res = core.BigInt res = schemas.BigInt
case core.Bytea, core.Blob, core.Binary, core.TinyBlob, core.MediumBlob, core.LongBlob: case schemas.Bytea, schemas.Blob, schemas.Binary, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob:
res = core.VarBinary res = schemas.VarBinary
if c.Length == 0 { if c.Length == 0 {
c.Length = 50 c.Length = 50
} }
case core.TimeStamp: case schemas.TimeStamp:
res = core.DateTime res = schemas.DateTime
case core.TimeStampz: case schemas.TimeStampz:
res = "DATETIMEOFFSET" res = "DATETIMEOFFSET"
c.Length = 7 c.Length = 7
case core.MediumInt: case schemas.MediumInt:
res = core.Int res = schemas.Int
case core.Text, core.MediumText, core.TinyText, core.LongText, core.Json: case schemas.Text, schemas.MediumText, schemas.TinyText, schemas.LongText, schemas.Json:
res = core.Varchar + "(MAX)" res = schemas.Varchar + "(MAX)"
case core.Double: case schemas.Double:
res = core.Real res = schemas.Real
case core.Uuid: case schemas.Uuid:
res = core.Varchar res = schemas.Varchar
c.Length = 40 c.Length = 40
case core.TinyInt: case schemas.TinyInt:
res = core.TinyInt res = schemas.TinyInt
c.Length = 0 c.Length = 0
case core.BigInt: case schemas.BigInt:
res = core.BigInt res = schemas.BigInt
c.Length = 0 c.Length = 0
default: default:
res = t res = t
} }
if res == core.Int { if res == schemas.Int {
return core.Int return schemas.Int
} }
hasLen1 := (c.Length > 0) hasLen1 := (c.Length > 0)
@ -276,88 +281,78 @@ func (db *mssql) SqlType(c *core.Column) string {
return res return res
} }
func (db *mssql) SupportInsertMany() bool {
return true
}
func (db *mssql) IsReserved(name string) bool { func (db *mssql) IsReserved(name string) bool {
_, ok := mssqlReservedWords[name] _, ok := mssqlReservedWords[strings.ToUpper(name)]
return ok return ok
} }
func (db *mssql) Quote(name string) string { func (db *mssql) SetQuotePolicy(quotePolicy QuotePolicy) {
return "\"" + name + "\"" switch quotePolicy {
} case QuotePolicyNone:
var q = mssqlQuoter
func (db *mssql) SupportEngine() bool { q.IsReserved = schemas.AlwaysNoReserve
return false db.quoter = q
case QuotePolicyReserved:
var q = mssqlQuoter
q.IsReserved = db.IsReserved
db.quoter = q
case QuotePolicyAlways:
fallthrough
default:
db.quoter = mssqlQuoter
}
} }
func (db *mssql) AutoIncrStr() string { func (db *mssql) AutoIncrStr() string {
return "IDENTITY" return "IDENTITY"
} }
func (db *mssql) DropTableSql(tableName string) string { func (db *mssql) DropTableSQL(tableName string) (string, bool) {
return fmt.Sprintf("IF EXISTS (SELECT * FROM sysobjects WHERE id = "+ return fmt.Sprintf("IF EXISTS (SELECT * FROM sysobjects WHERE id = "+
"object_id(N'%s') and OBJECTPROPERTY(id, N'IsUserTable') = 1) "+ "object_id(N'%s') and OBJECTPROPERTY(id, N'IsUserTable') = 1) "+
"DROP TABLE \"%s\"", tableName, tableName) "DROP TABLE \"%s\"", tableName, tableName), true
} }
func (db *mssql) SupportCharset() bool { func (db *mssql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
return false
}
func (db *mssql) IndexOnTable() bool {
return true
}
func (db *mssql) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
args := []interface{}{idxName} args := []interface{}{idxName}
sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?" sql := "select name from sysindexes where id=object_id('" + tableName + "') and name=?"
return sql, args return sql, args
} }
/*func (db *mssql) ColumnCheckSql(tableName, colName string) (string, []interface{}) { func (db *mssql) IsColumnExist(ctx context.Context, tableName, colName string) (bool, error) {
args := []interface{}{tableName, colName}
sql := `SELECT "COLUMN_NAME" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "COLUMN_NAME" = ?`
return sql, args
}*/
func (db *mssql) IsColumnExist(tableName, colName string) (bool, error) {
query := `SELECT "COLUMN_NAME" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "COLUMN_NAME" = ?` query := `SELECT "COLUMN_NAME" FROM "INFORMATION_SCHEMA"."COLUMNS" WHERE "TABLE_NAME" = ? AND "COLUMN_NAME" = ?`
return db.HasRecords(query, tableName, colName) return db.HasRecords(ctx, query, tableName, colName)
} }
func (db *mssql) TableCheckSql(tableName string) (string, []interface{}) { func (db *mssql) IsTableExist(ctx context.Context, tableName string) (bool, error) {
args := []interface{}{}
sql := "select * from sysobjects where id = object_id(N'" + tableName + "') and OBJECTPROPERTY(id, N'IsUserTable') = 1" sql := "select * from sysobjects where id = object_id(N'" + tableName + "') and OBJECTPROPERTY(id, N'IsUserTable') = 1"
return sql, args return db.HasRecords(ctx, sql)
} }
func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { func (db *mssql) GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{} args := []interface{}{}
s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale,a.is_nullable as nullable, s := `select a.name as name, b.name as ctype,a.max_length,a.precision,a.scale,a.is_nullable as nullable,
"default_is_null" = (CASE WHEN c.text is null THEN 1 ELSE 0 END), "default_is_null" = (CASE WHEN c.text is null THEN 1 ELSE 0 END),
replace(replace(isnull(c.text,''),'(',''),')','') as vdefault, replace(replace(isnull(c.text,''),'(',''),')','') as vdefault,
ISNULL(i.is_primary_key, 0), a.is_identity as is_identity ISNULL(p.is_primary_key, 0), a.is_identity as is_identity
from sys.columns a from sys.columns a
left join sys.types b on a.user_type_id=b.user_type_id left join sys.types b on a.user_type_id=b.user_type_id
left join sys.syscomments c on a.default_object_id=c.id left join sys.syscomments c on a.default_object_id=c.id
LEFT OUTER JOIN LEFT OUTER JOIN (SELECT i.object_id, ic.column_id, i.is_primary_key
sys.index_columns ic ON ic.object_id = a.object_id AND ic.column_id = a.column_id FROM sys.indexes i
LEFT OUTER JOIN LEFT JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
sys.indexes i ON ic.object_id = i.object_id AND ic.index_id = i.index_id WHERE i.is_primary_key = 1
) as p on p.object_id = a.object_id AND p.column_id = a.column_id
where a.object_id=object_id('` + tableName + `')` where a.object_id=object_id('` + tableName + `')`
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
defer rows.Close() defer rows.Close()
cols := make(map[string]*core.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
var name, ctype, vdefault string var name, ctype, vdefault string
@ -368,7 +363,7 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
return nil, nil, err return nil, nil, err
} }
col := new(core.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
col.Name = strings.Trim(name, "` ") col.Name = strings.Trim(name, "` ")
col.Nullable = nullable col.Nullable = nullable
@ -387,14 +382,14 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
} }
switch ct { switch ct {
case "DATETIMEOFFSET": case "DATETIMEOFFSET":
col.SQLType = core.SQLType{Name: core.TimeStampz, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
case "NVARCHAR": case "NVARCHAR":
col.SQLType = core.SQLType{Name: core.NVarchar, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.NVarchar, DefaultLength: 0, DefaultLength2: 0}
case "IMAGE": case "IMAGE":
col.SQLType = core.SQLType{Name: core.VarBinary, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.VarBinary, DefaultLength: 0, DefaultLength2: 0}
default: default:
if _, ok := core.SqlTypes[ct]; ok { if _, ok := schemas.SqlTypes[ct]; ok {
col.SQLType = core.SQLType{Name: ct, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: ct, DefaultLength: 0, DefaultLength2: 0}
} else { } else {
return nil, nil, fmt.Errorf("Unknown colType %v for %v - %v", ct, tableName, col.Name) return nil, nil, fmt.Errorf("Unknown colType %v for %v - %v", ct, tableName, col.Name)
} }
@ -406,20 +401,19 @@ func (db *mssql) GetColumns(tableName string) ([]string, map[string]*core.Column
return colSeq, cols, nil return colSeq, cols, nil
} }
func (db *mssql) GetTables() ([]*core.Table, error) { func (db *mssql) GetTables(ctx context.Context) ([]*schemas.Table, error) {
args := []interface{}{} args := []interface{}{}
s := `select name from sysobjects where xtype ='U'` s := `select name from sysobjects where xtype ='U'`
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
tables := make([]*core.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
table := core.NewEmptyTable() table := schemas.NewEmptyTable()
var name string var name string
err = rows.Scan(&name) err = rows.Scan(&name)
if err != nil { if err != nil {
@ -431,7 +425,7 @@ func (db *mssql) GetTables() ([]*core.Table, error) {
return tables, nil return tables, nil
} }
func (db *mssql) GetIndexes(tableName string) (map[string]*core.Index, error) { func (db *mssql) GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []interface{}{tableName}
s := `SELECT s := `SELECT
IXS.NAME AS [INDEX_NAME], IXS.NAME AS [INDEX_NAME],
@ -444,15 +438,14 @@ INNER JOIN SYS.COLUMNS C ON IXS.OBJECT_ID=C.OBJECT_ID
AND IXCS.COLUMN_ID=C.COLUMN_ID AND IXCS.COLUMN_ID=C.COLUMN_ID
WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =? WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
` `
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*core.Index, 0) indexes := make(map[string]*schemas.Index, 0)
for rows.Next() { for rows.Next() {
var indexType int var indexType int
var indexName, colName, isUnique string var indexName, colName, isUnique string
@ -468,9 +461,9 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
} }
if i { if i {
indexType = core.UniqueType indexType = schemas.UniqueType
} else { } else {
indexType = core.IndexType indexType = schemas.IndexType
} }
colName = strings.Trim(colName, "` ") colName = strings.Trim(colName, "` ")
@ -480,10 +473,10 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
isRegular = true isRegular = true
} }
var index *core.Index var index *schemas.Index
var ok bool var ok bool
if index, ok = indexes[indexName]; !ok { if index, ok = indexes[indexName]; !ok {
index = new(core.Index) index = new(schemas.Index)
index.Type = indexType index.Type = indexType
index.Name = indexName index.Name = indexName
index.IsRegular = isRegular index.IsRegular = isRegular
@ -494,7 +487,7 @@ WHERE IXS.TYPE_DESC='NONCLUSTERED' and OBJECT_NAME(IXS.OBJECT_ID) =?
return indexes, nil return indexes, nil
} }
func (db *mssql) CreateTableSql(table *core.Table, tableName, storeEngine, charset string) string { func (db *mssql) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
var sql string var sql string
if tableName == "" { if tableName == "" {
tableName = table.Name tableName = table.Name
@ -502,16 +495,16 @@ 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.Quote(tableName) + " (" sql += db.Quoter().Quote(tableName) + " ("
pkList := table.PrimaryKeys pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() { for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName) col := table.GetColumn(colName)
if col.IsPrimaryKey && len(pkList) == 1 { if col.IsPrimaryKey && len(pkList) == 1 {
sql += col.String(db) sql += db.String(col)
} else { } else {
sql += col.StringNoPk(db) sql += db.StringNoPk(col)
} }
sql = strings.TrimSpace(sql) sql = strings.TrimSpace(sql)
sql += ", " sql += ", "
@ -525,21 +518,21 @@ func (db *mssql) CreateTableSql(table *core.Table, tableName, storeEngine, chars
sql = sql[:len(sql)-2] + ")" sql = sql[:len(sql)-2] + ")"
sql += ";" sql += ";"
return sql return []string{sql}, true
} }
func (db *mssql) ForUpdateSql(query string) string { func (db *mssql) ForUpdateSQL(query string) string {
return query return query
} }
func (db *mssql) Filters() []core.Filter { func (db *mssql) Filters() []Filter {
return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}} return []Filter{}
} }
type odbcDriver struct { type odbcDriver struct {
} }
func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *odbcDriver) Parse(driverName, dataSourceName string) (*URI, error) {
var dbName string var dbName string
if strings.HasPrefix(dataSourceName, "sqlserver://") { if strings.HasPrefix(dataSourceName, "sqlserver://") {
@ -563,5 +556,5 @@ func (p *odbcDriver) Parse(driverName, dataSourceName string) (*core.Uri, error)
if dbName == "" { if dbName == "" {
return nil, errors.New("no db name provided") return nil, errors.New("no db name provided")
} }
return &core.Uri{DbName: dbName, DbType: core.MSSQL}, nil return &URI{DBName: dbName, DBType: schemas.MSSQL}, nil
} }

View file

@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package dialects
import ( import (
"context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt" "fmt"
@ -13,7 +14,8 @@ import (
"strings" "strings"
"time" "time"
"xorm.io/core" "xorm.io/xorm/core"
"xorm.io/xorm/schemas"
) )
var ( var (
@ -159,10 +161,12 @@ var (
"YEAR_MONTH": true, "YEAR_MONTH": true,
"ZEROFILL": true, "ZEROFILL": true,
} }
mysqlQuoter = schemas.Quoter{'`', '`', schemas.AlwaysReserve}
) )
type mysql struct { type mysql struct {
core.Base Base
net string net string
addr string addr string
params map[string]string params map[string]string
@ -175,8 +179,9 @@ type mysql struct {
rowFormat string rowFormat string
} }
func (db *mysql) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error { func (db *mysql) Init(d *core.DB, uri *URI) error {
return db.Base.Init(d, db, uri, drivername, dataSourceName) db.quoter = mysqlQuoter
return db.Base.Init(d, db, uri)
} }
func (db *mysql) SetParams(params map[string]string) { func (db *mysql) SetParams(params map[string]string) {
@ -199,29 +204,29 @@ func (db *mysql) SetParams(params map[string]string) {
} }
} }
func (db *mysql) SqlType(c *core.Column) string { func (db *mysql) SQLType(c *schemas.Column) string {
var res string var res string
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case core.Bool: case schemas.Bool:
res = core.TinyInt res = schemas.TinyInt
c.Length = 1 c.Length = 1
case core.Serial: case schemas.Serial:
c.IsAutoIncrement = true c.IsAutoIncrement = true
c.IsPrimaryKey = true c.IsPrimaryKey = true
c.Nullable = false c.Nullable = false
res = core.Int res = schemas.Int
case core.BigSerial: case schemas.BigSerial:
c.IsAutoIncrement = true c.IsAutoIncrement = true
c.IsPrimaryKey = true c.IsPrimaryKey = true
c.Nullable = false c.Nullable = false
res = core.BigInt res = schemas.BigInt
case core.Bytea: case schemas.Bytea:
res = core.Blob res = schemas.Blob
case core.TimeStampz: case schemas.TimeStampz:
res = core.Char res = schemas.Char
c.Length = 64 c.Length = 64
case core.Enum: // mysql enum case schemas.Enum: // mysql enum
res = core.Enum res = schemas.Enum
res += "(" res += "("
opts := "" opts := ""
for v := range c.EnumOptions { for v := range c.EnumOptions {
@ -229,8 +234,8 @@ func (db *mysql) SqlType(c *core.Column) string {
} }
res += strings.TrimLeft(opts, ",") res += strings.TrimLeft(opts, ",")
res += ")" res += ")"
case core.Set: // mysql set case schemas.Set: // mysql set
res = core.Set res = schemas.Set
res += "(" res += "("
opts := "" opts := ""
for v := range c.SetOptions { for v := range c.SetOptions {
@ -238,13 +243,13 @@ func (db *mysql) SqlType(c *core.Column) string {
} }
res += strings.TrimLeft(opts, ",") res += strings.TrimLeft(opts, ",")
res += ")" res += ")"
case core.NVarchar: case schemas.NVarchar:
res = core.Varchar res = schemas.Varchar
case core.Uuid: case schemas.Uuid:
res = core.Varchar res = schemas.Varchar
c.Length = 40 c.Length = 40
case core.Json: case schemas.Json:
res = core.Text res = schemas.Text
default: default:
res = t res = t
} }
@ -252,7 +257,7 @@ func (db *mysql) SqlType(c *core.Column) string {
hasLen1 := (c.Length > 0) hasLen1 := (c.Length > 0)
hasLen2 := (c.Length2 > 0) hasLen2 := (c.Length2 > 0)
if res == core.BigInt && !hasLen1 && !hasLen2 { if res == schemas.BigInt && !hasLen1 && !hasLen2 {
c.Length = 20 c.Length = 20
hasLen1 = true hasLen1 = true
} }
@ -265,70 +270,52 @@ func (db *mysql) SqlType(c *core.Column) string {
return res return res
} }
func (db *mysql) SupportInsertMany() bool {
return true
}
func (db *mysql) IsReserved(name string) bool { func (db *mysql) IsReserved(name string) bool {
_, ok := mysqlReservedWords[name] _, ok := mysqlReservedWords[strings.ToUpper(name)]
return ok return ok
} }
func (db *mysql) Quote(name string) string {
return "`" + name + "`"
}
func (db *mysql) SupportEngine() bool {
return true
}
func (db *mysql) AutoIncrStr() string { func (db *mysql) AutoIncrStr() string {
return "AUTO_INCREMENT" return "AUTO_INCREMENT"
} }
func (db *mysql) SupportCharset() bool { func (db *mysql) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
return true args := []interface{}{db.uri.DBName, tableName, idxName}
}
func (db *mysql) IndexOnTable() bool {
return true
}
func (db *mysql) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
args := []interface{}{db.DbName, tableName, idxName}
sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`" sql := "SELECT `INDEX_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS`"
sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?" sql += " WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `INDEX_NAME`=?"
return sql, args return sql, args
} }
/*func (db *mysql) ColumnCheckSql(tableName, colName string) (string, []interface{}) { func (db *mysql) IsTableExist(ctx context.Context, tableName string) (bool, error) {
args := []interface{}{db.DbName, tableName, colName}
sql := "SELECT `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ? AND `COLUMN_NAME` = ?"
return sql, args
}*/
func (db *mysql) TableCheckSql(tableName string) (string, []interface{}) {
args := []interface{}{db.DbName, tableName}
sql := "SELECT `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? and `TABLE_NAME`=?" sql := "SELECT `TABLE_NAME` from `INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? and `TABLE_NAME`=?"
return sql, args return db.HasRecords(ctx, sql, db.uri.DBName, tableName)
} }
func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { func (db *mysql) AddColumnSQL(tableName string, col *schemas.Column) string {
args := []interface{}{db.DbName, tableName} quoter := db.dialect.Quoter()
sql := fmt.Sprintf("ALTER TABLE %v ADD %v", quoter.Quote(tableName),
db.String(col))
if len(col.Comment) > 0 {
sql += " COMMENT '" + col.Comment + "'"
}
return sql
}
func (db *mysql) GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{db.uri.DBName, tableName}
s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," + s := "SELECT `COLUMN_NAME`, `IS_NULLABLE`, `COLUMN_DEFAULT`, `COLUMN_TYPE`," +
" `COLUMN_KEY`, `EXTRA`,`COLUMN_COMMENT` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" " `COLUMN_KEY`, `EXTRA`,`COLUMN_COMMENT` FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
defer rows.Close() defer rows.Close()
cols := make(map[string]*core.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
col := new(core.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
var columnName, isNullable, colType, colKey, extra, comment string var columnName, isNullable, colType, colKey, extra, comment string
@ -356,7 +343,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 == schemas.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 {
@ -364,7 +351,7 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column
v = strings.Trim(v, "'") v = strings.Trim(v, "'")
col.EnumOptions[v] = k col.EnumOptions[v] = k
} }
} else if colType == core.Set && cts[1][0] == '\'' { } else if colType == schemas.Set && cts[1][0] == '\'' {
options := strings.Split(cts[1][0:idx], ",") options := strings.Split(cts[1][0:idx], ",")
col.SetOptions = make(map[string]int) col.SetOptions = make(map[string]int)
for k, v := range options { for k, v := range options {
@ -394,8 +381,8 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column
} }
col.Length = len1 col.Length = len1
col.Length2 = len2 col.Length2 = len2
if _, ok := core.SqlTypes[colType]; ok { if _, ok := schemas.SqlTypes[colType]; ok {
col.SQLType = core.SQLType{Name: colType, DefaultLength: len1, DefaultLength2: len2} col.SQLType = schemas.SQLType{Name: colType, DefaultLength: len1, DefaultLength2: len2}
} else { } else {
return nil, nil, fmt.Errorf("Unknown colType %v", colType) return nil, nil, fmt.Errorf("Unknown colType %v", colType)
} }
@ -424,48 +411,65 @@ func (db *mysql) GetColumns(tableName string) ([]string, map[string]*core.Column
return colSeq, cols, nil return colSeq, cols, nil
} }
func (db *mysql) GetTables() ([]*core.Table, error) { func (db *mysql) GetTables(ctx context.Context) ([]*schemas.Table, error) {
args := []interface{}{db.DbName} args := []interface{}{db.uri.DBName}
s := "SELECT `TABLE_NAME`, `ENGINE`, `TABLE_ROWS`, `AUTO_INCREMENT`, `TABLE_COMMENT` from " + s := "SELECT `TABLE_NAME`, `ENGINE`, `AUTO_INCREMENT`, `TABLE_COMMENT` from " +
"`INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? AND (`ENGINE`='MyISAM' OR `ENGINE` = 'InnoDB' OR `ENGINE` = 'TokuDB')" "`INFORMATION_SCHEMA`.`TABLES` WHERE `TABLE_SCHEMA`=? AND (`ENGINE`='MyISAM' OR `ENGINE` = 'InnoDB' OR `ENGINE` = 'TokuDB')"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
tables := make([]*core.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
table := core.NewEmptyTable() table := schemas.NewEmptyTable()
var name, engine, tableRows, comment string var name, engine string
var autoIncr *string var autoIncr, comment *string
err = rows.Scan(&name, &engine, &tableRows, &autoIncr, &comment) err = rows.Scan(&name, &engine, &autoIncr, &comment)
if err != nil { if err != nil {
return nil, err return nil, err
} }
table.Name = name table.Name = name
table.Comment = comment if comment != nil {
table.Comment = *comment
}
table.StoreEngine = engine table.StoreEngine = engine
tables = append(tables, table) tables = append(tables, table)
} }
return tables, nil return tables, nil
} }
func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) { func (db *mysql) SetQuotePolicy(quotePolicy QuotePolicy) {
args := []interface{}{db.DbName, tableName} switch quotePolicy {
s := "SELECT `INDEX_NAME`, `NON_UNIQUE`, `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?" case QuotePolicyNone:
db.LogSQL(s, args) var q = mysqlQuoter
q.IsReserved = schemas.AlwaysNoReserve
db.quoter = q
case QuotePolicyReserved:
var q = mysqlQuoter
q.IsReserved = db.IsReserved
db.quoter = q
case QuotePolicyAlways:
fallthrough
default:
db.quoter = mysqlQuoter
}
}
rows, err := db.DB().Query(s, args...) func (db *mysql) GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{db.uri.DBName, tableName}
s := "SELECT `INDEX_NAME`, `NON_UNIQUE`, `COLUMN_NAME` FROM `INFORMATION_SCHEMA`.`STATISTICS` WHERE `TABLE_SCHEMA` = ? AND `TABLE_NAME` = ?"
rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*core.Index, 0) indexes := make(map[string]*schemas.Index, 0)
for rows.Next() { for rows.Next() {
var indexType int var indexType int
var indexName, colName, nonUnique string var indexName, colName, nonUnique string
@ -479,9 +483,9 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
} }
if "YES" == nonUnique || nonUnique == "1" { if "YES" == nonUnique || nonUnique == "1" {
indexType = core.IndexType indexType = schemas.IndexType
} else { } else {
indexType = core.UniqueType indexType = schemas.UniqueType
} }
colName = strings.Trim(colName, "` ") colName = strings.Trim(colName, "` ")
@ -491,10 +495,10 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
isRegular = true isRegular = true
} }
var index *core.Index var index *schemas.Index
var ok bool var ok bool
if index, ok = indexes[indexName]; !ok { if index, ok = indexes[indexName]; !ok {
index = new(core.Index) index = new(schemas.Index)
index.IsRegular = isRegular index.IsRegular = isRegular
index.Type = indexType index.Type = indexType
index.Name = indexName index.Name = indexName
@ -505,14 +509,15 @@ func (db *mysql) GetIndexes(tableName string) (map[string]*core.Index, error) {
return indexes, nil return indexes, nil
} }
func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, charset string) string { func (db *mysql) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
var sql string var sql = "CREATE TABLE IF NOT EXISTS "
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" { if tableName == "" {
tableName = table.Name tableName = table.Name
} }
sql += db.Quote(tableName) quoter := db.Quoter()
sql += quoter.Quote(tableName)
sql += " (" sql += " ("
if len(table.ColumnsSeq()) > 0 { if len(table.ColumnsSeq()) > 0 {
@ -521,9 +526,9 @@ func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, chars
for _, colName := range table.ColumnsSeq() { for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName) col := table.GetColumn(colName)
if col.IsPrimaryKey && len(pkList) == 1 { if col.IsPrimaryKey && len(pkList) == 1 {
sql += col.String(db) sql += db.String(col)
} else { } else {
sql += col.StringNoPk(db) sql += db.StringNoPk(col)
} }
sql = strings.TrimSpace(sql) sql = strings.TrimSpace(sql)
if len(col.Comment) > 0 { if len(col.Comment) > 0 {
@ -534,7 +539,7 @@ func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, chars
if len(pkList) > 1 { if len(pkList) > 1 {
sql += "PRIMARY KEY ( " sql += "PRIMARY KEY ( "
sql += db.Quote(strings.Join(pkList, db.Quote(","))) sql += quoter.Join(pkList, ",")
sql += " ), " sql += " ), "
} }
@ -542,10 +547,11 @@ func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, chars
} }
sql += ")" sql += ")"
if storeEngine != "" { if table.StoreEngine != "" {
sql += " ENGINE=" + storeEngine sql += " ENGINE=" + table.StoreEngine
} }
var charset = table.Charset
if len(charset) == 0 { if len(charset) == 0 {
charset = db.URI().Charset charset = db.URI().Charset
} }
@ -556,18 +562,18 @@ func (db *mysql) CreateTableSql(table *core.Table, tableName, storeEngine, chars
if db.rowFormat != "" { if db.rowFormat != "" {
sql += " ROW_FORMAT=" + db.rowFormat sql += " ROW_FORMAT=" + db.rowFormat
} }
return sql return []string{sql}, true
} }
func (db *mysql) Filters() []core.Filter { func (db *mysql) Filters() []Filter {
return []core.Filter{&core.IdFilter{}} return []Filter{}
} }
type mymysqlDriver struct { type mymysqlDriver struct {
} }
func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*URI, error) {
db := &core.Uri{DbType: core.MYSQL} uri := &URI{DBType: schemas.MYSQL}
pd := strings.SplitN(dataSourceName, "*", 2) pd := strings.SplitN(dataSourceName, "*", 2)
if len(pd) == 2 { if len(pd) == 2 {
@ -576,9 +582,9 @@ func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, err
if len(p) != 2 { if len(p) != 2 {
return nil, errors.New("Wrong protocol part of URI") return nil, errors.New("Wrong protocol part of URI")
} }
db.Proto = p[0] uri.Proto = p[0]
options := strings.Split(p[1], ",") options := strings.Split(p[1], ",")
db.Raddr = options[0] uri.Raddr = options[0]
for _, o := range options[1:] { for _, o := range options[1:] {
kv := strings.SplitN(o, "=", 2) kv := strings.SplitN(o, "=", 2)
var k, v string var k, v string
@ -589,13 +595,13 @@ func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, err
} }
switch k { switch k {
case "laddr": case "laddr":
db.Laddr = v uri.Laddr = v
case "timeout": case "timeout":
to, err := time.ParseDuration(v) to, err := time.ParseDuration(v)
if err != nil { if err != nil {
return nil, err return nil, err
} }
db.Timeout = to uri.Timeout = to
default: default:
return nil, errors.New("Unknown option: " + k) return nil, errors.New("Unknown option: " + k)
} }
@ -608,17 +614,17 @@ func (p *mymysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, err
if len(dup) != 3 { if len(dup) != 3 {
return nil, errors.New("Wrong database part of URI") return nil, errors.New("Wrong database part of URI")
} }
db.DbName = dup[0] uri.DBName = dup[0]
db.User = dup[1] uri.User = dup[1]
db.Passwd = dup[2] uri.Passwd = dup[2]
return db, nil return uri, nil
} }
type mysqlDriver struct { type mysqlDriver struct {
} }
func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*URI, error) {
dsnPattern := regexp.MustCompile( dsnPattern := regexp.MustCompile(
`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@] `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
`(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]] `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
@ -628,12 +634,12 @@ func (p *mysqlDriver) Parse(driverName, dataSourceName string) (*core.Uri, error
// 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 := &URI{DBType: schemas.MYSQL}
for i, match := range matches { for i, match := range matches {
switch names[i] { switch names[i] {
case "dbname": case "dbname":
uri.DbName = match uri.DBName = match
case "params": case "params":
if len(match) > 0 { if len(match) > 0 {
kvs := strings.Split(match, "&") kvs := strings.Split(match, "&")

View file

@ -2,16 +2,18 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package dialects
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"xorm.io/core" "xorm.io/xorm/core"
"xorm.io/xorm/schemas"
) )
var ( var (
@ -496,32 +498,35 @@ var (
"YEAR": true, "YEAR": true,
"ZONE": true, "ZONE": true,
} }
oracleQuoter = schemas.Quoter{'[', ']', schemas.AlwaysReserve}
) )
type oracle struct { type oracle struct {
core.Base Base
} }
func (db *oracle) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error { func (db *oracle) Init(d *core.DB, uri *URI) error {
return db.Base.Init(d, db, uri, drivername, dataSourceName) db.quoter = oracleQuoter
return db.Base.Init(d, db, uri)
} }
func (db *oracle) SqlType(c *core.Column) string { func (db *oracle) SQLType(c *schemas.Column) string {
var res string var res string
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case core.Bit, core.TinyInt, core.SmallInt, core.MediumInt, core.Int, core.Integer, core.BigInt, core.Bool, core.Serial, core.BigSerial: case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt, schemas.Bool, schemas.Serial, schemas.BigSerial:
res = "NUMBER" res = "NUMBER"
case core.Binary, core.VarBinary, core.Blob, core.TinyBlob, core.MediumBlob, core.LongBlob, core.Bytea: case schemas.Binary, schemas.VarBinary, schemas.Blob, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob, schemas.Bytea:
return core.Blob return schemas.Blob
case core.Time, core.DateTime, core.TimeStamp: case schemas.Time, schemas.DateTime, schemas.TimeStamp:
res = core.TimeStamp res = schemas.TimeStamp
case core.TimeStampz: case schemas.TimeStampz:
res = "TIMESTAMP WITH TIME ZONE" res = "TIMESTAMP WITH TIME ZONE"
case core.Float, core.Double, core.Numeric, core.Decimal: case schemas.Float, schemas.Double, schemas.Numeric, schemas.Decimal:
res = "NUMBER" res = "NUMBER"
case core.Text, core.MediumText, core.LongText, core.Json: case schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json:
res = "CLOB" res = "CLOB"
case core.Char, core.Varchar, core.TinyText: case schemas.Char, schemas.Varchar, schemas.TinyText:
res = "VARCHAR2" res = "VARCHAR2"
default: default:
res = t res = t
@ -542,47 +547,23 @@ func (db *oracle) AutoIncrStr() string {
return "AUTO_INCREMENT" return "AUTO_INCREMENT"
} }
func (db *oracle) SupportInsertMany() bool {
return true
}
func (db *oracle) IsReserved(name string) bool { func (db *oracle) IsReserved(name string) bool {
_, ok := oracleReservedWords[name] _, ok := oracleReservedWords[strings.ToUpper(name)]
return ok return ok
} }
func (db *oracle) Quote(name string) string { func (db *oracle) DropTableSQL(tableName string) (string, bool) {
return "[" + name + "]" return fmt.Sprintf("DROP TABLE `%s`", tableName), false
} }
func (db *oracle) SupportEngine() bool { func (db *oracle) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
return false var sql = "CREATE TABLE "
}
func (db *oracle) SupportCharset() bool {
return false
}
func (db *oracle) SupportDropIfExists() bool {
return false
}
func (db *oracle) IndexOnTable() bool {
return false
}
func (db *oracle) DropTableSql(tableName string) string {
return fmt.Sprintf("DROP TABLE `%s`", tableName)
}
func (db *oracle) CreateTableSql(table *core.Table, tableName, storeEngine, charset string) string {
var sql string
sql = "CREATE TABLE "
if tableName == "" { if tableName == "" {
tableName = table.Name tableName = table.Name
} }
sql += db.Quote(tableName) + " (" quoter := db.Quoter()
sql += quoter.Quote(tableName) + " ("
pkList := table.PrimaryKeys pkList := table.PrimaryKeys
@ -591,7 +572,7 @@ func (db *oracle) CreateTableSql(table *core.Table, tableName, storeEngine, char
/*if col.IsPrimaryKey && len(pkList) == 1 { /*if col.IsPrimaryKey && len(pkList) == 1 {
sql += col.String(b.dialect) sql += col.String(b.dialect)
} else {*/ } else {*/
sql += col.StringNoPk(db) sql += db.StringNoPk(col)
// } // }
sql = strings.TrimSpace(sql) sql = strings.TrimSpace(sql)
sql += ", " sql += ", "
@ -599,97 +580,63 @@ func (db *oracle) CreateTableSql(table *core.Table, tableName, storeEngine, char
if len(pkList) > 0 { if len(pkList) > 0 {
sql += "PRIMARY KEY ( " sql += "PRIMARY KEY ( "
sql += db.Quote(strings.Join(pkList, db.Quote(","))) sql += quoter.Join(pkList, ",")
sql += " ), " sql += " ), "
} }
sql = sql[:len(sql)-2] + ")" sql = sql[:len(sql)-2] + ")"
if db.SupportEngine() && storeEngine != "" { return []string{sql}, false
sql += " ENGINE=" + storeEngine
}
if db.SupportCharset() {
if len(charset) == 0 {
charset = db.URI().Charset
}
if len(charset) > 0 {
sql += " DEFAULT CHARSET " + charset
}
}
return sql
} }
func (db *oracle) IndexCheckSql(tableName, idxName string) (string, []interface{}) { func (db *oracle) SetQuotePolicy(quotePolicy QuotePolicy) {
switch quotePolicy {
case QuotePolicyNone:
var q = oracleQuoter
q.IsReserved = schemas.AlwaysNoReserve
db.quoter = q
case QuotePolicyReserved:
var q = oracleQuoter
q.IsReserved = db.IsReserved
db.quoter = q
case QuotePolicyAlways:
fallthrough
default:
db.quoter = oracleQuoter
}
}
func (db *oracle) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
args := []interface{}{tableName, idxName} args := []interface{}{tableName, idxName}
return `SELECT INDEX_NAME FROM USER_INDEXES ` + return `SELECT INDEX_NAME FROM USER_INDEXES ` +
`WHERE TABLE_NAME = :1 AND INDEX_NAME = :2`, args `WHERE TABLE_NAME = :1 AND INDEX_NAME = :2`, args
} }
func (db *oracle) TableCheckSql(tableName string) (string, []interface{}) { func (db *oracle) IsTableExist(ctx context.Context, tableName string) (bool, error) {
args := []interface{}{tableName} return db.HasRecords(ctx, `SELECT table_name FROM user_tables WHERE table_name = :1`, tableName)
return `SELECT table_name FROM user_tables WHERE table_name = :1`, args
} }
func (db *oracle) MustDropTable(tableName string) error { func (db *oracle) IsColumnExist(ctx context.Context, tableName, colName string) (bool, error) {
sql, args := db.TableCheckSql(tableName)
db.LogSQL(sql, args)
rows, err := db.DB().Query(sql, args...)
if err != nil {
return err
}
defer rows.Close()
if !rows.Next() {
return nil
}
sql = "Drop Table \"" + tableName + "\""
db.LogSQL(sql, args)
_, err = db.DB().Exec(sql)
return err
}
/*func (db *oracle) ColumnCheckSql(tableName, colName string) (string, []interface{}) {
args := []interface{}{strings.ToUpper(tableName), strings.ToUpper(colName)}
return "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = ?" +
" AND column_name = ?", args
}*/
func (db *oracle) IsColumnExist(tableName, colName string) (bool, error) {
args := []interface{}{tableName, colName} args := []interface{}{tableName, colName}
query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = :1" + query := "SELECT column_name FROM USER_TAB_COLUMNS WHERE table_name = :1" +
" AND column_name = :2" " AND column_name = :2"
db.LogSQL(query, args) return db.HasRecords(ctx, query, args...)
rows, err := db.DB().Query(query, args...)
if err != nil {
return false, err
}
defer rows.Close()
if rows.Next() {
return true, nil
}
return false, nil
} }
func (db *oracle) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { func (db *oracle) GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{tableName} args := []interface{}{tableName}
s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," + s := "SELECT column_name,data_default,data_type,data_length,data_precision,data_scale," +
"nullable FROM USER_TAB_COLUMNS WHERE table_name = :1" "nullable FROM USER_TAB_COLUMNS WHERE table_name = :1"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
defer rows.Close() defer rows.Close()
cols := make(map[string]*core.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
col := new(core.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
var colName, colDefault, nullable, dataType, dataPrecision, dataScale *string var colName, colDefault, nullable, dataType, dataPrecision, dataScale *string
@ -731,30 +678,30 @@ func (db *oracle) GetColumns(tableName string) ([]string, map[string]*core.Colum
switch dt { switch dt {
case "VARCHAR2": case "VARCHAR2":
col.SQLType = core.SQLType{Name: core.Varchar, DefaultLength: len1, DefaultLength2: len2} col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: len1, DefaultLength2: len2}
case "NVARCHAR2": case "NVARCHAR2":
col.SQLType = core.SQLType{Name: core.NVarchar, DefaultLength: len1, DefaultLength2: len2} col.SQLType = schemas.SQLType{Name: schemas.NVarchar, DefaultLength: len1, DefaultLength2: len2}
case "TIMESTAMP WITH TIME ZONE": case "TIMESTAMP WITH TIME ZONE":
col.SQLType = core.SQLType{Name: core.TimeStampz, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
case "NUMBER": case "NUMBER":
col.SQLType = core.SQLType{Name: core.Double, DefaultLength: len1, DefaultLength2: len2} col.SQLType = schemas.SQLType{Name: schemas.Double, DefaultLength: len1, DefaultLength2: len2}
case "LONG", "LONG RAW": case "LONG", "LONG RAW":
col.SQLType = core.SQLType{Name: core.Text, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Text, DefaultLength: 0, DefaultLength2: 0}
case "RAW": case "RAW":
col.SQLType = core.SQLType{Name: core.Binary, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Binary, DefaultLength: 0, DefaultLength2: 0}
case "ROWID": case "ROWID":
col.SQLType = core.SQLType{Name: core.Varchar, DefaultLength: 18, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: 18, DefaultLength2: 0}
case "AQ$_SUBSCRIBERS": case "AQ$_SUBSCRIBERS":
ignore = true ignore = true
default: default:
col.SQLType = core.SQLType{Name: strings.ToUpper(dt), DefaultLength: len1, DefaultLength2: len2} col.SQLType = schemas.SQLType{Name: strings.ToUpper(dt), DefaultLength: len1, DefaultLength2: len2}
} }
if ignore { if ignore {
continue continue
} }
if _, ok := core.SqlTypes[col.SQLType.Name]; !ok { if _, ok := schemas.SqlTypes[col.SQLType.Name]; !ok {
return nil, nil, fmt.Errorf("Unknown colType %v %v", *dataType, col.SQLType) return nil, nil, fmt.Errorf("Unknown colType %v %v", *dataType, col.SQLType)
} }
@ -772,20 +719,19 @@ func (db *oracle) GetColumns(tableName string) ([]string, map[string]*core.Colum
return colSeq, cols, nil return colSeq, cols, nil
} }
func (db *oracle) GetTables() ([]*core.Table, error) { func (db *oracle) GetTables(ctx context.Context) ([]*schemas.Table, error) {
args := []interface{}{} args := []interface{}{}
s := "SELECT table_name FROM user_tables" s := "SELECT table_name FROM user_tables"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
tables := make([]*core.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
table := core.NewEmptyTable() table := schemas.NewEmptyTable()
err = rows.Scan(&table.Name) err = rows.Scan(&table.Name)
if err != nil { if err != nil {
return nil, err return nil, err
@ -796,19 +742,18 @@ func (db *oracle) GetTables() ([]*core.Table, error) {
return tables, nil return tables, nil
} }
func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) { func (db *oracle) GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []interface{}{tableName}
s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " + s := "SELECT t.column_name,i.uniqueness,i.index_name FROM user_ind_columns t,user_indexes i " +
"WHERE t.index_name = i.index_name and t.table_name = i.table_name and t.table_name =:1" "WHERE t.index_name = i.index_name and t.table_name = i.table_name and t.table_name =:1"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*core.Index, 0) indexes := make(map[string]*schemas.Index, 0)
for rows.Next() { for rows.Next() {
var indexType int var indexType int
var indexName, colName, uniqueness string var indexName, colName, uniqueness string
@ -827,15 +772,15 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) {
} }
if uniqueness == "UNIQUE" { if uniqueness == "UNIQUE" {
indexType = core.UniqueType indexType = schemas.UniqueType
} else { } else {
indexType = core.IndexType indexType = schemas.IndexType
} }
var index *core.Index var index *schemas.Index
var ok bool var ok bool
if index, ok = indexes[indexName]; !ok { if index, ok = indexes[indexName]; !ok {
index = new(core.Index) index = new(schemas.Index)
index.Type = indexType index.Type = indexType
index.Name = indexName index.Name = indexName
index.IsRegular = isRegular index.IsRegular = isRegular
@ -846,15 +791,17 @@ func (db *oracle) GetIndexes(tableName string) (map[string]*core.Index, error) {
return indexes, nil return indexes, nil
} }
func (db *oracle) Filters() []core.Filter { func (db *oracle) Filters() []Filter {
return []core.Filter{&core.QuoteFilter{}, &core.SeqFilter{Prefix: ":", Start: 1}, &core.IdFilter{}} return []Filter{
&SeqFilter{Prefix: ":", Start: 1},
}
} }
type goracleDriver struct { type goracleDriver struct {
} }
func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*URI, error) {
db := &core.Uri{DbType: core.ORACLE} db := &URI{DBType: schemas.ORACLE}
dsnPattern := regexp.MustCompile( dsnPattern := regexp.MustCompile(
`^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@] `^(?:(?P<user>.*?)(?::(?P<passwd>.*))?@)?` + // [user[:password]@]
`(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]] `(?:(?P<net>[^\(]*)(?:\((?P<addr>[^\)]*)\))?)?` + // [net[(addr)]]
@ -867,10 +814,10 @@ func (cfg *goracleDriver) Parse(driverName, dataSourceName string) (*core.Uri, e
for i, match := range matches { for i, match := range matches {
switch names[i] { switch names[i] {
case "dbname": case "dbname":
db.DbName = match db.DBName = match
} }
} }
if db.DbName == "" { if db.DBName == "" {
return nil, errors.New("dbname is empty") return nil, errors.New("dbname is empty")
} }
return db, nil return db, nil
@ -881,8 +828,8 @@ 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) (*URI, error) {
db := &core.Uri{DbType: core.ORACLE} db := &URI{DBType: schemas.ORACLE}
dsnPattern := regexp.MustCompile( dsnPattern := regexp.MustCompile(
`^(?P<user>.*)\/(?P<password>.*)@` + // user:password@ `^(?P<user>.*)\/(?P<password>.*)@` + // user:password@
`(?P<net>.*)` + // ip:port `(?P<net>.*)` + // ip:port
@ -892,10 +839,10 @@ func (p *oci8Driver) Parse(driverName, dataSourceName string) (*core.Uri, error)
for i, match := range matches { for i, match := range matches {
switch names[i] { switch names[i] {
case "dbname": case "dbname":
db.DbName = match db.DBName = match
} }
} }
if db.DbName == "" { if db.DBName == "" {
return nil, errors.New("dbname is empty") return nil, errors.New("dbname is empty")
} }
return db, nil return db, nil

View file

@ -2,16 +2,18 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package dialects
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"xorm.io/core" "xorm.io/xorm/core"
"xorm.io/xorm/schemas"
) )
// from http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html // from http://www.postgresql.org/docs/current/static/sql-keywords-appendix.html
@ -765,71 +767,104 @@ var (
"ZONE": true, "ZONE": true,
} }
// DefaultPostgresSchema default postgres schema postgresQuoter = schemas.Quoter{'"', '"', schemas.AlwaysReserve}
DefaultPostgresSchema = "public"
) )
const postgresPublicSchema = "public" const postgresPublicSchema = "public"
type postgres struct { type postgres struct {
core.Base Base
} }
func (db *postgres) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error { func (db *postgres) Init(d *core.DB, uri *URI) error {
err := db.Base.Init(d, db, uri, drivername, dataSourceName) db.quoter = postgresQuoter
err := db.Base.Init(d, db, uri)
if err != nil { if err != nil {
return err return err
} }
if db.Schema == "" { if db.uri.Schema == "" {
db.Schema = DefaultPostgresSchema db.uri.Schema = postgresPublicSchema
} }
return nil return nil
} }
func (db *postgres) SqlType(c *core.Column) string { func (db *postgres) needQuote(name string) bool {
if db.IsReserved(name) {
return true
}
for _, c := range name {
if c >= 'A' && c <= 'Z' {
return true
}
}
return false
}
func (db *postgres) SetQuotePolicy(quotePolicy QuotePolicy) {
switch quotePolicy {
case QuotePolicyNone:
var q = postgresQuoter
q.IsReserved = schemas.AlwaysNoReserve
db.quoter = q
case QuotePolicyReserved:
var q = postgresQuoter
q.IsReserved = db.needQuote
db.quoter = q
case QuotePolicyAlways:
fallthrough
default:
db.quoter = postgresQuoter
}
}
func (db *postgres) DefaultSchema() string {
return postgresPublicSchema
}
func (db *postgres) SQLType(c *schemas.Column) string {
var res string var res string
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case core.TinyInt: case schemas.TinyInt:
res = core.SmallInt res = schemas.SmallInt
return res return res
case core.Bit: case schemas.Bit:
res = core.Boolean res = schemas.Boolean
return res return res
case core.MediumInt, core.Int, core.Integer: case schemas.MediumInt, schemas.Int, schemas.Integer:
if c.IsAutoIncrement { if c.IsAutoIncrement {
return core.Serial return schemas.Serial
} }
return core.Integer return schemas.Integer
case core.BigInt: case schemas.BigInt:
if c.IsAutoIncrement { if c.IsAutoIncrement {
return core.BigSerial return schemas.BigSerial
} }
return core.BigInt return schemas.BigInt
case core.Serial, core.BigSerial: case schemas.Serial, schemas.BigSerial:
c.IsAutoIncrement = true c.IsAutoIncrement = true
c.Nullable = false c.Nullable = false
res = t res = t
case core.Binary, core.VarBinary: case schemas.Binary, schemas.VarBinary:
return core.Bytea return schemas.Bytea
case core.DateTime: case schemas.DateTime:
res = core.TimeStamp res = schemas.TimeStamp
case core.TimeStampz: case schemas.TimeStampz:
return "timestamp with time zone" return "timestamp with time zone"
case core.Float: case schemas.Float:
res = core.Real res = schemas.Real
case core.TinyText, core.MediumText, core.LongText: case schemas.TinyText, schemas.MediumText, schemas.LongText:
res = core.Text res = schemas.Text
case core.NVarchar: case schemas.NVarchar:
res = core.Varchar res = schemas.Varchar
case core.Uuid: case schemas.Uuid:
return core.Uuid return schemas.Uuid
case core.Blob, core.TinyBlob, core.MediumBlob, core.LongBlob: case schemas.Blob, schemas.TinyBlob, schemas.MediumBlob, schemas.LongBlob:
return core.Bytea return schemas.Bytea
case core.Double: case schemas.Double:
return "DOUBLE PRECISION" return "DOUBLE PRECISION"
default: default:
if c.IsAutoIncrement { if c.IsAutoIncrement {
return core.Serial return schemas.Serial
} }
res = t res = t
} }
@ -849,68 +884,83 @@ func (db *postgres) SqlType(c *core.Column) string {
return res return res
} }
func (db *postgres) SupportInsertMany() bool {
return true
}
func (db *postgres) IsReserved(name string) bool { func (db *postgres) IsReserved(name string) bool {
_, ok := postgresReservedWords[name] _, ok := postgresReservedWords[strings.ToUpper(name)]
return ok return ok
} }
func (db *postgres) Quote(name string) string {
name = strings.Replace(name, ".", `"."`, -1)
return "\"" + name + "\""
}
func (db *postgres) AutoIncrStr() string { func (db *postgres) AutoIncrStr() string {
return "" return ""
} }
func (db *postgres) SupportEngine() bool { func (db *postgres) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
return false var sql string
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
quoter := db.Quoter()
sql += quoter.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
if col.IsPrimaryKey && len(pkList) == 1 {
sql += db.String(col)
} else {
sql += db.StringNoPk(col)
}
sql = strings.TrimSpace(sql)
sql += ", "
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += quoter.Join(pkList, ",")
sql += " ), "
}
sql = sql[:len(sql)-2]
}
sql += ")"
return []string{sql}, true
} }
func (db *postgres) SupportCharset() bool { func (db *postgres) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
return false if len(db.uri.Schema) == 0 {
}
func (db *postgres) IndexOnTable() bool {
return false
}
func (db *postgres) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
if len(db.Schema) == 0 {
args := []interface{}{tableName, idxName} args := []interface{}{tableName, idxName}
return `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`, args return `SELECT indexname FROM pg_indexes WHERE tablename = ? AND indexname = ?`, args
} }
args := []interface{}{db.Schema, tableName, idxName} args := []interface{}{db.uri.Schema, tableName, idxName}
return `SELECT indexname FROM pg_indexes ` + return `SELECT indexname FROM pg_indexes ` +
`WHERE schemaname = ? AND tablename = ? AND indexname = ?`, args `WHERE schemaname = ? AND tablename = ? AND indexname = ?`, args
} }
func (db *postgres) TableCheckSql(tableName string) (string, []interface{}) { func (db *postgres) IsTableExist(ctx context.Context, tableName string) (bool, error) {
if len(db.Schema) == 0 { if len(db.uri.Schema) == 0 {
args := []interface{}{tableName} return db.HasRecords(ctx, `SELECT tablename FROM pg_tables WHERE tablename = $1`, tableName)
return `SELECT tablename FROM pg_tables WHERE tablename = ?`, args
} }
args := []interface{}{db.Schema, tableName} return db.HasRecords(ctx, `SELECT tablename FROM pg_tables WHERE schemaname = $1 AND tablename = $2`,
return `SELECT tablename FROM pg_tables WHERE schemaname = ? AND tablename = ?`, args db.uri.Schema, tableName)
} }
func (db *postgres) ModifyColumnSql(tableName string, col *core.Column) string { func (db *postgres) ModifyColumnSQL(tableName string, col *schemas.Column) string {
if len(db.Schema) == 0 || strings.Contains(tableName, ".") { if len(db.uri.Schema) == 0 || strings.Contains(tableName, ".") {
return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s", return fmt.Sprintf("alter table %s ALTER COLUMN %s TYPE %s",
tableName, col.Name, db.SqlType(col)) tableName, col.Name, db.SQLType(col))
} }
return fmt.Sprintf("alter table %s.%s ALTER COLUMN %s TYPE %s", return fmt.Sprintf("alter table %s.%s ALTER COLUMN %s TYPE %s",
db.Schema, tableName, col.Name, db.SqlType(col)) db.uri.Schema, tableName, col.Name, db.SQLType(col))
} }
func (db *postgres) DropIndexSql(tableName string, index *core.Index) string { func (db *postgres) DropIndexSQL(tableName string, index *schemas.Index) string {
quote := db.Quote
idxName := index.Name idxName := index.Name
tableParts := strings.Split(strings.Replace(tableName, `"`, "", -1), ".") tableParts := strings.Split(strings.Replace(tableName, `"`, "", -1), ".")
@ -918,30 +968,29 @@ func (db *postgres) DropIndexSql(tableName string, index *core.Index) string {
if !strings.HasPrefix(idxName, "UQE_") && if !strings.HasPrefix(idxName, "UQE_") &&
!strings.HasPrefix(idxName, "IDX_") { !strings.HasPrefix(idxName, "IDX_") {
if index.Type == core.UniqueType { if index.Type == schemas.UniqueType {
idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name) idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
} else { } else {
idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name) idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
} }
} }
if db.Uri.Schema != "" { if db.uri.Schema != "" {
idxName = db.Uri.Schema + "." + idxName idxName = db.uri.Schema + "." + idxName
} }
return fmt.Sprintf("DROP INDEX %v", quote(idxName)) return fmt.Sprintf("DROP INDEX %v", db.Quoter().Quote(idxName))
} }
func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) { func (db *postgres) IsColumnExist(ctx context.Context, tableName, colName string) (bool, error) {
args := []interface{}{db.Schema, tableName, colName} args := []interface{}{db.uri.Schema, tableName, colName}
query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" + query := "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = $1 AND table_name = $2" +
" AND column_name = $3" " AND column_name = $3"
if len(db.Schema) == 0 { if len(db.uri.Schema) == 0 {
args = []interface{}{tableName, colName} args = []interface{}{tableName, colName}
query = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" + query = "SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = $1" +
" AND column_name = $2" " AND column_name = $2"
} }
db.LogSQL(query, args)
rows, err := db.DB().Query(query, args...) rows, err := db.DB().QueryContext(ctx, query, args...)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -950,8 +999,8 @@ func (db *postgres) IsColumnExist(tableName, colName string) (bool, error) {
return rows.Next(), nil return rows.Next(), nil
} }
func (db *postgres) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { func (db *postgres) GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{tableName} args := []interface{}{db.uri.Schema, tableName, db.uri.Schema}
s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length, s := `SELECT column_name, column_default, is_nullable, data_type, character_maximum_length,
CASE WHEN p.contype = 'p' THEN true ELSE false END AS primarykey, CASE WHEN p.contype = 'p' THEN true ELSE false END AS primarykey,
CASE WHEN p.contype = 'u' THEN true ELSE false END AS uniquekey CASE WHEN p.contype = 'u' THEN true ELSE false END AS uniquekey
@ -962,28 +1011,19 @@ FROM pg_attribute f
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey) LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)
LEFT JOIN pg_class AS g ON p.confrelid = g.oid LEFT JOIN pg_class AS g ON p.confrelid = g.oid
LEFT JOIN INFORMATION_SCHEMA.COLUMNS s ON s.column_name=f.attname AND c.relname=s.table_name LEFT JOIN INFORMATION_SCHEMA.COLUMNS s ON s.column_name=f.attname AND c.relname=s.table_name
WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.attnum;` WHERE n.nspname= $1 AND c.relkind = 'r'::char AND c.relname = $2 AND s.table_schema = $3 AND f.attnum > 0 ORDER BY f.attnum;`
var f string rows, err := db.DB().QueryContext(ctx, s, args...)
if len(db.Schema) != 0 {
args = append(args, db.Schema)
f = " AND s.table_schema = $2"
}
s = fmt.Sprintf(s, f)
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
defer rows.Close() defer rows.Close()
cols := make(map[string]*core.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for rows.Next() { for rows.Next() {
col := new(core.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
var colName, isNullable, dataType string var colName, isNullable, dataType string
@ -994,7 +1034,6 @@ WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.att
return nil, nil, err return nil, nil, err
} }
// fmt.Println(args, colName, isNullable, dataType, maxLenStr, colDefault, isPK, isUnique)
var maxLen int var maxLen int
if maxLenStr != nil { if maxLenStr != nil {
maxLen, err = strconv.Atoi(*maxLenStr) maxLen, err = strconv.Atoi(*maxLenStr)
@ -1006,10 +1045,27 @@ WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.att
col.Name = strings.Trim(colName, `" `) col.Name = strings.Trim(colName, `" `)
if colDefault != nil { if colDefault != nil {
col.Default = *colDefault var theDefault = *colDefault
// cockroach has type with the default value with :::
// and postgres with ::, we should remove them before store them
idx := strings.Index(theDefault, ":::")
if idx == -1 {
idx = strings.Index(theDefault, "::")
}
if idx > -1 {
theDefault = theDefault[:idx]
}
if strings.HasSuffix(theDefault, "+00:00'") {
theDefault = theDefault[:len(theDefault)-7] + "'"
}
col.Default = theDefault
col.DefaultIsEmpty = false col.DefaultIsEmpty = false
if strings.HasPrefix(col.Default, "nextval(") { if strings.HasPrefix(col.Default, "nextval(") {
col.IsAutoIncrement = true col.IsAutoIncrement = true
col.Default = ""
col.DefaultIsEmpty = true
} }
} else { } else {
col.DefaultIsEmpty = true col.DefaultIsEmpty = true
@ -1021,26 +1077,37 @@ WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.att
col.Nullable = (isNullable == "YES") col.Nullable = (isNullable == "YES")
switch dataType { switch strings.ToLower(dataType) {
case "character varying", "character": case "character varying", "character", "string":
col.SQLType = core.SQLType{Name: core.Varchar, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Varchar, DefaultLength: 0, DefaultLength2: 0}
case "timestamp without time zone": case "timestamp without time zone":
col.SQLType = core.SQLType{Name: core.DateTime, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.DateTime, DefaultLength: 0, DefaultLength2: 0}
case "timestamp with time zone": case "timestamp with time zone":
col.SQLType = core.SQLType{Name: core.TimeStampz, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.TimeStampz, DefaultLength: 0, DefaultLength2: 0}
case "double precision": case "double precision":
col.SQLType = core.SQLType{Name: core.Double, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Double, DefaultLength: 0, DefaultLength2: 0}
case "boolean": case "boolean":
col.SQLType = core.SQLType{Name: core.Bool, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Bool, DefaultLength: 0, DefaultLength2: 0}
case "time without time zone": case "time without time zone":
col.SQLType = core.SQLType{Name: core.Time, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.Time, DefaultLength: 0, DefaultLength2: 0}
case "bytes":
col.SQLType = schemas.SQLType{Name: schemas.Binary, DefaultLength: 0, DefaultLength2: 0}
case "oid": case "oid":
col.SQLType = core.SQLType{Name: core.BigInt, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: schemas.BigInt, DefaultLength: 0, DefaultLength2: 0}
case "array":
col.SQLType = schemas.SQLType{Name: schemas.Array, DefaultLength: 0, DefaultLength2: 0}
default: default:
col.SQLType = core.SQLType{Name: strings.ToUpper(dataType), DefaultLength: 0, DefaultLength2: 0} startIdx := strings.Index(strings.ToLower(dataType), "string(")
if startIdx != -1 && strings.HasSuffix(dataType, ")") {
length := dataType[startIdx+8 : len(dataType)-1]
l, _ := strconv.Atoi(length)
col.SQLType = schemas.SQLType{Name: "STRING", DefaultLength: l, DefaultLength2: 0}
} else {
col.SQLType = schemas.SQLType{Name: strings.ToUpper(dataType), DefaultLength: 0, DefaultLength2: 0}
} }
if _, ok := core.SqlTypes[col.SQLType.Name]; !ok { }
return nil, nil, fmt.Errorf("Unknown colType: %v", dataType) if _, ok := schemas.SqlTypes[col.SQLType.Name]; !ok {
return nil, nil, fmt.Errorf("Unknown colType: %s - %s", dataType, col.SQLType.Name)
} }
col.Length = maxLen col.Length = maxLen
@ -1065,25 +1132,23 @@ WHERE c.relkind = 'r'::char AND c.relname = $1%s AND f.attnum > 0 ORDER BY f.att
return colSeq, cols, nil return colSeq, cols, nil
} }
func (db *postgres) GetTables() ([]*core.Table, error) { func (db *postgres) GetTables(ctx context.Context) ([]*schemas.Table, error) {
args := []interface{}{} args := []interface{}{}
s := "SELECT tablename FROM pg_tables" s := "SELECT tablename FROM pg_tables"
if len(db.Schema) != 0 { if len(db.uri.Schema) != 0 {
args = append(args, db.Schema) args = append(args, db.uri.Schema)
s = s + " WHERE schemaname = $1" s = s + " WHERE schemaname = $1"
} }
db.LogSQL(s, args) rows, err := db.DB().QueryContext(ctx, s, args...)
rows, err := db.DB().Query(s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
tables := make([]*core.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
table := core.NewEmptyTable() table := schemas.NewEmptyTable()
var name string var name string
err = rows.Scan(&name) err = rows.Scan(&name)
if err != nil { if err != nil {
@ -1106,22 +1171,21 @@ func getIndexColName(indexdef string) []string {
return colNames return colNames
} }
func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error) { func (db *postgres) GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []interface{}{tableName}
s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1") s := fmt.Sprintf("SELECT indexname, indexdef FROM pg_indexes WHERE tablename=$1")
if len(db.Schema) != 0 { if len(db.uri.Schema) != 0 {
args = append(args, db.Schema) args = append(args, db.uri.Schema)
s = s + " AND schemaname=$2" s = s + " AND schemaname=$2"
} }
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*core.Index, 0) indexes := make(map[string]*schemas.Index, 0)
for rows.Next() { for rows.Next() {
var indexType int var indexType int
var indexName, indexdef string var indexName, indexdef string
@ -1130,14 +1194,18 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if indexName == "primary" {
continue
}
indexName = strings.Trim(indexName, `" `) indexName = strings.Trim(indexName, `" `)
if strings.HasSuffix(indexName, "_pkey") { if strings.HasSuffix(indexName, "_pkey") {
continue continue
} }
if strings.HasPrefix(indexdef, "CREATE UNIQUE INDEX") { if strings.HasPrefix(indexdef, "CREATE UNIQUE INDEX") {
indexType = core.UniqueType indexType = schemas.UniqueType
} else { } else {
indexType = core.IndexType indexType = schemas.IndexType
} }
colNames = getIndexColName(indexdef) colNames = getIndexColName(indexdef)
var isRegular bool var isRegular bool
@ -1149,9 +1217,9 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
} }
} }
index := &core.Index{Name: indexName, Type: indexType, Cols: make([]string, 0)} index := &schemas.Index{Name: indexName, Type: indexType, Cols: make([]string, 0)}
for _, colName := range colNames { for _, colName := range colNames {
index.Cols = append(index.Cols, strings.Trim(colName, `" `)) index.Cols = append(index.Cols, strings.TrimSpace(strings.Replace(colName, `"`, "", -1)))
} }
index.IsRegular = isRegular index.IsRegular = isRegular
indexes[index.Name] = index indexes[index.Name] = index
@ -1159,8 +1227,8 @@ func (db *postgres) GetIndexes(tableName string) (map[string]*core.Index, error)
return indexes, nil return indexes, nil
} }
func (db *postgres) Filters() []core.Filter { func (db *postgres) Filters() []Filter {
return []core.Filter{&core.IdFilter{}, &core.QuoteFilter{}, &core.SeqFilter{Prefix: "$", Start: 1}} return []Filter{&SeqFilter{Prefix: "$", Start: 1}}
} }
type pqDriver struct { type pqDriver struct {
@ -1214,12 +1282,12 @@ func parseOpts(name string, o values) error {
return nil return nil
} }
func (p *pqDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *pqDriver) Parse(driverName, dataSourceName string) (*URI, error) {
db := &core.Uri{DbType: core.POSTGRES} db := &URI{DBType: schemas.POSTGRES}
var err error var err error
if strings.HasPrefix(dataSourceName, "postgresql://") || strings.HasPrefix(dataSourceName, "postgres://") { if strings.HasPrefix(dataSourceName, "postgresql://") || strings.HasPrefix(dataSourceName, "postgres://") {
db.DbName, err = parseURL(dataSourceName) db.DBName, err = parseURL(dataSourceName)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1230,10 +1298,10 @@ func (p *pqDriver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
return nil, err return nil, err
} }
db.DbName = o.Get("dbname") db.DBName = o.Get("dbname")
} }
if db.DbName == "" { if db.DBName == "" {
return nil, errors.New("dbname is empty") return nil, errors.New("dbname is empty")
} }
@ -1244,7 +1312,7 @@ type pqDriverPgx struct {
pqDriver pqDriver
} }
func (pgx *pqDriverPgx) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (pgx *pqDriverPgx) Parse(driverName, dataSourceName string) (*URI, error) {
// Remove the leading characters for driver to work // Remove the leading characters for driver to work
if len(dataSourceName) >= 9 && dataSourceName[0] == 0 { if len(dataSourceName) >= 9 && dataSourceName[0] == 0 {
dataSourceName = dataSourceName[9:] dataSourceName = dataSourceName[9:]

15
vendor/xorm.io/xorm/dialects/quote.go generated vendored Normal file
View file

@ -0,0 +1,15 @@
// Copyright 2020 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dialects
// QuotePolicy describes quote handle policy
type QuotePolicy int
// All QuotePolicies
const (
QuotePolicyAlways QuotePolicy = iota
QuotePolicyNone
QuotePolicyReserved
)

View file

@ -2,16 +2,18 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package dialects
import ( import (
"context"
"database/sql" "database/sql"
"errors" "errors"
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
"xorm.io/core" "xorm.io/xorm/core"
"xorm.io/xorm/schemas"
) )
var ( var (
@ -141,45 +143,65 @@ var (
"WITH": true, "WITH": true,
"WITHOUT": true, "WITHOUT": true,
} }
sqlite3Quoter = schemas.Quoter{'`', '`', schemas.AlwaysReserve}
) )
type sqlite3 struct { type sqlite3 struct {
core.Base Base
} }
func (db *sqlite3) Init(d *core.DB, uri *core.Uri, drivername, dataSourceName string) error { func (db *sqlite3) Init(d *core.DB, uri *URI) error {
return db.Base.Init(d, db, uri, drivername, dataSourceName) db.quoter = sqlite3Quoter
return db.Base.Init(d, db, uri)
} }
func (db *sqlite3) SqlType(c *core.Column) string { func (db *sqlite3) SetQuotePolicy(quotePolicy QuotePolicy) {
switch quotePolicy {
case QuotePolicyNone:
var q = sqlite3Quoter
q.IsReserved = schemas.AlwaysNoReserve
db.quoter = q
case QuotePolicyReserved:
var q = sqlite3Quoter
q.IsReserved = db.IsReserved
db.quoter = q
case QuotePolicyAlways:
fallthrough
default:
db.quoter = sqlite3Quoter
}
}
func (db *sqlite3) SQLType(c *schemas.Column) string {
switch t := c.SQLType.Name; t { switch t := c.SQLType.Name; t {
case core.Bool: case schemas.Bool:
if c.Default == "true" { if c.Default == "true" {
c.Default = "1" c.Default = "1"
} else if c.Default == "false" { } else if c.Default == "false" {
c.Default = "0" c.Default = "0"
} }
return core.Integer return schemas.Integer
case core.Date, core.DateTime, core.TimeStamp, core.Time: case schemas.Date, schemas.DateTime, schemas.TimeStamp, schemas.Time:
return core.DateTime return schemas.DateTime
case core.TimeStampz: case schemas.TimeStampz:
return core.Text return schemas.Text
case core.Char, core.Varchar, core.NVarchar, core.TinyText, case schemas.Char, schemas.Varchar, schemas.NVarchar, schemas.TinyText,
core.Text, core.MediumText, core.LongText, core.Json: schemas.Text, schemas.MediumText, schemas.LongText, schemas.Json:
return core.Text return schemas.Text
case core.Bit, core.TinyInt, core.SmallInt, core.MediumInt, core.Int, core.Integer, core.BigInt: case schemas.Bit, schemas.TinyInt, schemas.SmallInt, schemas.MediumInt, schemas.Int, schemas.Integer, schemas.BigInt:
return core.Integer return schemas.Integer
case core.Float, core.Double, core.Real: case schemas.Float, schemas.Double, schemas.Real:
return core.Real return schemas.Real
case core.Decimal, core.Numeric: case schemas.Decimal, schemas.Numeric:
return core.Numeric return schemas.Numeric
case core.TinyBlob, core.Blob, core.MediumBlob, core.LongBlob, core.Bytea, core.Binary, core.VarBinary: case schemas.TinyBlob, schemas.Blob, schemas.MediumBlob, schemas.LongBlob, schemas.Bytea, schemas.Binary, schemas.VarBinary:
return core.Blob return schemas.Blob
case core.Serial, core.BigSerial: case schemas.Serial, schemas.BigSerial:
c.IsPrimaryKey = true c.IsPrimaryKey = true
c.IsAutoIncrement = true c.IsAutoIncrement = true
c.Nullable = false c.Nullable = false
return core.Integer return schemas.Integer
default: default:
return t return t
} }
@ -189,84 +211,100 @@ func (db *sqlite3) FormatBytes(bs []byte) string {
return fmt.Sprintf("X'%x'", bs) return fmt.Sprintf("X'%x'", bs)
} }
func (db *sqlite3) SupportInsertMany() bool {
return true
}
func (db *sqlite3) IsReserved(name string) bool { func (db *sqlite3) IsReserved(name string) bool {
_, ok := sqlite3ReservedWords[name] _, ok := sqlite3ReservedWords[strings.ToUpper(name)]
return ok return ok
} }
func (db *sqlite3) Quote(name string) string {
return "`" + name + "`"
}
func (db *sqlite3) AutoIncrStr() string { func (db *sqlite3) AutoIncrStr() string {
return "AUTOINCREMENT" return "AUTOINCREMENT"
} }
func (db *sqlite3) SupportEngine() bool { func (db *sqlite3) IndexCheckSQL(tableName, idxName string) (string, []interface{}) {
return false
}
func (db *sqlite3) SupportCharset() bool {
return false
}
func (db *sqlite3) IndexOnTable() bool {
return false
}
func (db *sqlite3) IndexCheckSql(tableName, idxName string) (string, []interface{}) {
args := []interface{}{idxName} args := []interface{}{idxName}
return "SELECT name FROM sqlite_master WHERE type='index' and name = ?", args return "SELECT name FROM sqlite_master WHERE type='index' and name = ?", args
} }
func (db *sqlite3) TableCheckSql(tableName string) (string, []interface{}) { func (db *sqlite3) IsTableExist(ctx context.Context, tableName string) (bool, error) {
args := []interface{}{tableName} return db.HasRecords(ctx, "SELECT name FROM sqlite_master WHERE type='table' and name = ?", tableName)
return "SELECT name FROM sqlite_master WHERE type='table' and name = ?", args
} }
func (db *sqlite3) DropIndexSql(tableName string, index *core.Index) string { func (db *sqlite3) DropIndexSQL(tableName string, index *schemas.Index) string {
// var unique string // var unique string
quote := db.Quote
idxName := index.Name idxName := index.Name
if !strings.HasPrefix(idxName, "UQE_") && if !strings.HasPrefix(idxName, "UQE_") &&
!strings.HasPrefix(idxName, "IDX_") { !strings.HasPrefix(idxName, "IDX_") {
if index.Type == core.UniqueType { if index.Type == schemas.UniqueType {
idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name) idxName = fmt.Sprintf("UQE_%v_%v", tableName, index.Name)
} else { } else {
idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name) idxName = fmt.Sprintf("IDX_%v_%v", tableName, index.Name)
} }
} }
return fmt.Sprintf("DROP INDEX %v", quote(idxName)) return fmt.Sprintf("DROP INDEX %v", db.Quoter().Quote(idxName))
} }
func (db *sqlite3) ForUpdateSql(query string) string { func (db *sqlite3) CreateTableSQL(table *schemas.Table, tableName string) ([]string, bool) {
var sql string
sql = "CREATE TABLE IF NOT EXISTS "
if tableName == "" {
tableName = table.Name
}
quoter := db.Quoter()
sql += quoter.Quote(tableName)
sql += " ("
if len(table.ColumnsSeq()) > 0 {
pkList := table.PrimaryKeys
for _, colName := range table.ColumnsSeq() {
col := table.GetColumn(colName)
if col.IsPrimaryKey && len(pkList) == 1 {
sql += db.String(col)
} else {
sql += db.StringNoPk(col)
}
sql = strings.TrimSpace(sql)
sql += ", "
}
if len(pkList) > 1 {
sql += "PRIMARY KEY ( "
sql += quoter.Join(pkList, ",")
sql += " ), "
}
sql = sql[:len(sql)-2]
}
sql += ")"
return []string{sql}, true
}
func (db *sqlite3) ForUpdateSQL(query string) string {
return query return query
} }
/*func (db *sqlite3) ColumnCheckSql(tableName, colName string) (string, []interface{}) { func (db *sqlite3) IsColumnExist(ctx context.Context, tableName, colName string) (bool, error) {
args := []interface{}{tableName} query := "SELECT * FROM " + tableName + " LIMIT 0"
sql := "SELECT name FROM sqlite_master WHERE type='table' and name = ? and ((sql like '%`" + colName + "`%') or (sql like '%[" + colName + "]%'))" rows, err := db.DB().QueryContext(ctx, query)
return sql, args
}*/
func (db *sqlite3) IsColumnExist(tableName, colName string) (bool, error) {
args := []interface{}{tableName}
query := "SELECT name FROM sqlite_master WHERE type='table' and name = ? and ((sql like '%`" + colName + "`%') or (sql like '%[" + colName + "]%'))"
db.LogSQL(query, args)
rows, err := db.DB().Query(query, args...)
if err != nil { if err != nil {
return false, err return false, err
} }
defer rows.Close() defer rows.Close()
if rows.Next() { cols, err := rows.Columns()
if err != nil {
return false, err
}
for _, col := range cols {
if strings.EqualFold(col, colName) {
return true, nil return true, nil
} }
}
return false, nil return false, nil
} }
@ -298,9 +336,9 @@ func splitColStr(colStr string) []string {
return results return results
} }
func parseString(colStr string) (*core.Column, error) { func parseString(colStr string) (*schemas.Column, error) {
fields := splitColStr(colStr) fields := splitColStr(colStr)
col := new(core.Column) col := new(schemas.Column)
col.Indexes = make(map[string]int) col.Indexes = make(map[string]int)
col.Nullable = true col.Nullable = true
col.DefaultIsEmpty = true col.DefaultIsEmpty = true
@ -310,7 +348,7 @@ func parseString(colStr string) (*core.Column, error) {
col.Name = strings.Trim(strings.Trim(field, "`[] "), `"`) col.Name = strings.Trim(strings.Trim(field, "`[] "), `"`)
continue continue
} else if idx == 1 { } else if idx == 1 {
col.SQLType = core.SQLType{Name: field, DefaultLength: 0, DefaultLength2: 0} col.SQLType = schemas.SQLType{Name: field, DefaultLength: 0, DefaultLength2: 0}
continue continue
} }
switch field { switch field {
@ -332,11 +370,11 @@ func parseString(colStr string) (*core.Column, error) {
return col, nil return col, nil
} }
func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Column, error) { func (db *sqlite3) GetColumns(ctx context.Context, tableName string) ([]string, map[string]*schemas.Column, error) {
args := []interface{}{tableName} args := []interface{}{tableName}
s := "SELECT sql FROM sqlite_master WHERE type='table' and name = ?" s := "SELECT sql FROM sqlite_master WHERE type='table' and name = ?"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -359,7 +397,7 @@ func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Colu
nEnd := strings.LastIndex(name, ")") nEnd := strings.LastIndex(name, ")")
reg := regexp.MustCompile(`[^\(,\)]*(\([^\(]*\))?`) reg := regexp.MustCompile(`[^\(,\)]*(\([^\(]*\))?`)
colCreates := reg.FindAllString(name[nStart+1:nEnd], -1) colCreates := reg.FindAllString(name[nStart+1:nEnd], -1)
cols := make(map[string]*core.Column) cols := make(map[string]*schemas.Column)
colSeq := make([]string, 0) colSeq := make([]string, 0)
for _, colStr := range colCreates { for _, colStr := range colCreates {
@ -389,20 +427,19 @@ func (db *sqlite3) GetColumns(tableName string) ([]string, map[string]*core.Colu
return colSeq, cols, nil return colSeq, cols, nil
} }
func (db *sqlite3) GetTables() ([]*core.Table, error) { func (db *sqlite3) GetTables(ctx context.Context) ([]*schemas.Table, error) {
args := []interface{}{} args := []interface{}{}
s := "SELECT name FROM sqlite_master WHERE type='table'" s := "SELECT name FROM sqlite_master WHERE type='table'"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
tables := make([]*core.Table, 0) tables := make([]*schemas.Table, 0)
for rows.Next() { for rows.Next() {
table := core.NewEmptyTable() table := schemas.NewEmptyTable()
err = rows.Scan(&table.Name) err = rows.Scan(&table.Name)
if err != nil { if err != nil {
return nil, err return nil, err
@ -415,18 +452,17 @@ func (db *sqlite3) GetTables() ([]*core.Table, error) {
return tables, nil return tables, nil
} }
func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error) { func (db *sqlite3) GetIndexes(ctx context.Context, tableName string) (map[string]*schemas.Index, error) {
args := []interface{}{tableName} args := []interface{}{tableName}
s := "SELECT sql FROM sqlite_master WHERE type='index' and tbl_name = ?" s := "SELECT sql FROM sqlite_master WHERE type='index' and tbl_name = ?"
db.LogSQL(s, args)
rows, err := db.DB().Query(s, args...) rows, err := db.DB().QueryContext(ctx, s, args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer rows.Close() defer rows.Close()
indexes := make(map[string]*core.Index, 0) indexes := make(map[string]*schemas.Index, 0)
for rows.Next() { for rows.Next() {
var tmpSQL sql.NullString var tmpSQL sql.NullString
err = rows.Scan(&tmpSQL) err = rows.Scan(&tmpSQL)
@ -439,7 +475,7 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error)
} }
sql := tmpSQL.String sql := tmpSQL.String
index := new(core.Index) index := new(schemas.Index)
nNStart := strings.Index(sql, "INDEX") nNStart := strings.Index(sql, "INDEX")
nNEnd := strings.Index(sql, "ON") nNEnd := strings.Index(sql, "ON")
if nNStart == -1 || nNEnd == -1 { if nNStart == -1 || nNEnd == -1 {
@ -456,9 +492,9 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error)
} }
if strings.HasPrefix(sql, "CREATE UNIQUE INDEX") { if strings.HasPrefix(sql, "CREATE UNIQUE INDEX") {
index.Type = core.UniqueType index.Type = schemas.UniqueType
} else { } else {
index.Type = core.IndexType index.Type = schemas.IndexType
} }
nStart := strings.Index(sql, "(") nStart := strings.Index(sql, "(")
@ -476,17 +512,17 @@ func (db *sqlite3) GetIndexes(tableName string) (map[string]*core.Index, error)
return indexes, nil return indexes, nil
} }
func (db *sqlite3) Filters() []core.Filter { func (db *sqlite3) Filters() []Filter {
return []core.Filter{&core.IdFilter{}} return []Filter{}
} }
type sqlite3Driver struct { type sqlite3Driver struct {
} }
func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*URI, error) {
if strings.Contains(dataSourceName, "?") { if strings.Contains(dataSourceName, "?") {
dataSourceName = dataSourceName[:strings.Index(dataSourceName, "?")] dataSourceName = dataSourceName[:strings.Index(dataSourceName, "?")]
} }
return &core.Uri{DbType: core.SQLITE, DbName: dataSourceName}, nil return &URI{DBType: schemas.SQLITE, DBName: dataSourceName}, nil
} }

90
vendor/xorm.io/xorm/dialects/table_name.go generated vendored Normal file
View file

@ -0,0 +1,90 @@
// Copyright 2015 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dialects
import (
"fmt"
"reflect"
"strings"
"xorm.io/xorm/internal/utils"
"xorm.io/xorm/names"
)
// TableNameWithSchema will add schema prefix on table name if possible
func TableNameWithSchema(dialect Dialect, tableName string) string {
// Add schema name as prefix of table name.
// Only for postgres database.
if dialect.URI().Schema != "" &&
dialect.URI().Schema != dialect.DefaultSchema() &&
strings.Index(tableName, ".") == -1 {
return fmt.Sprintf("%s.%s", dialect.URI().Schema, tableName)
}
return tableName
}
// TableNameNoSchema returns table name with given tableName
func TableNameNoSchema(dialect Dialect, mapper names.Mapper, tableName interface{}) string {
quote := dialect.Quoter().Quote
switch tableName.(type) {
case []string:
t := tableName.([]string)
if len(t) > 1 {
return fmt.Sprintf("%v AS %v", quote(t[0]), quote(t[1]))
} else if len(t) == 1 {
return quote(t[0])
}
case []interface{}:
t := tableName.([]interface{})
l := len(t)
var table string
if l > 0 {
f := t[0]
switch f.(type) {
case string:
table = f.(string)
case names.TableName:
table = f.(names.TableName).TableName()
default:
v := utils.ReflectValue(f)
t := v.Type()
if t.Kind() == reflect.Struct {
table = names.GetTableName(mapper, v)
} else {
table = quote(fmt.Sprintf("%v", f))
}
}
}
if l > 1 {
return fmt.Sprintf("%v AS %v", quote(table), quote(fmt.Sprintf("%v", t[1])))
} else if l == 1 {
return quote(table)
}
case names.TableName:
return tableName.(names.TableName).TableName()
case string:
return tableName.(string)
case reflect.Value:
v := tableName.(reflect.Value)
return names.GetTableName(mapper, v)
default:
v := utils.ReflectValue(tableName)
t := v.Type()
if t.Kind() == reflect.Struct {
return names.GetTableName(mapper, v)
}
return quote(fmt.Sprintf("%v", tableName))
}
return ""
}
// FullTableName returns table name with quote and schema according parameter
func FullTableName(dialect Dialect, mapper names.Mapper, bean interface{}, includeSchema ...bool) string {
tbName := TableNameNoSchema(dialect, mapper, bean)
if len(includeSchema) > 0 && includeSchema[0] && !utils.IsSubQuery(tbName) {
tbName = TableNameWithSchema(dialect, tbName)
}
return tbName
}

49
vendor/xorm.io/xorm/dialects/time.go generated vendored Normal file
View file

@ -0,0 +1,49 @@
// Copyright 2015 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package dialects
import (
"time"
"xorm.io/xorm/schemas"
)
// FormatTime format time as column type
func FormatTime(dialect Dialect, sqlTypeName string, t time.Time) (v interface{}) {
switch sqlTypeName {
case schemas.Time:
s := t.Format("2006-01-02 15:04:05") // time.RFC3339
v = s[11:19]
case schemas.Date:
v = t.Format("2006-01-02")
case schemas.DateTime, schemas.TimeStamp, schemas.Varchar: // !DarthPestilane! format time when sqlTypeName is schemas.Varchar.
v = t.Format("2006-01-02 15:04:05")
case schemas.TimeStampz:
if dialect.URI().DBType == schemas.MSSQL {
v = t.Format("2006-01-02T15:04:05.9999999Z07:00")
} else {
v = t.Format(time.RFC3339Nano)
}
case schemas.BigInt, schemas.Int:
v = t.Unix()
default:
v = t
}
return
}
func FormatColumnTime(dialect Dialect, defaultTimeZone *time.Location, col *schemas.Column, t time.Time) (v interface{}) {
if t.IsZero() {
if col.Nullable {
return nil
}
return ""
}
if col.TimeZone != nil {
return FormatTime(dialect, col.SQLType.Name, t.In(col.TimeZone))
}
return FormatTime(dialect, col.SQLType.Name, t.In(defaultTimeZone))
}

2
vendor/xorm.io/xorm/doc.go generated vendored
View file

@ -126,7 +126,7 @@ Attention: the above 8 methods should be the last chainable method.
engine.ID(1).Get(&user) // for single primary key engine.ID(1).Get(&user) // for single primary key
// SELECT * FROM user WHERE id = 1 // SELECT * FROM user WHERE id = 1
engine.ID(core.PK{1, 2}).Get(&user) // for composite primary keys engine.ID(schemas.PK{1, 2}).Get(&user) // for composite primary keys
// SELECT * FROM user WHERE id1 = 1 AND id2 = 2 // SELECT * FROM user WHERE id1 = 1 AND id2 = 2
engine.In("id", 1, 2, 3).Find(&users) engine.In("id", 1, 2, 3).Find(&users)
// SELECT * FROM user WHERE id IN (1, 2, 3) // SELECT * FROM user WHERE id IN (1, 2, 3)

816
vendor/xorm.io/xorm/engine.go generated vendored

File diff suppressed because it is too large Load diff

232
vendor/xorm.io/xorm/engine_cond.go generated vendored
View file

@ -1,232 +0,0 @@
// Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package xorm
import (
"database/sql/driver"
"fmt"
"reflect"
"strings"
"time"
"xorm.io/builder"
"xorm.io/core"
)
func (engine *Engine) buildConds(table *core.Table, bean interface{},
includeVersion bool, includeUpdated bool, includeNil bool,
includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool,
mustColumnMap map[string]bool, tableName, aliasName string, addedTableName bool) (builder.Cond, error) {
var conds []builder.Cond
for _, col := range table.Columns() {
if !includeVersion && col.IsVersion {
continue
}
if !includeUpdated && col.IsUpdated {
continue
}
if !includeAutoIncr && col.IsAutoIncrement {
continue
}
if engine.dialect.DBType() == core.MSSQL && (col.SQLType.Name == core.Text || col.SQLType.IsBlob() || col.SQLType.Name == core.TimeStampz) {
continue
}
if col.SQLType.IsJson() {
continue
}
var colName string
if addedTableName {
var nm = tableName
if len(aliasName) > 0 {
nm = aliasName
}
colName = engine.Quote(nm) + "." + engine.Quote(col.Name)
} else {
colName = engine.Quote(col.Name)
}
fieldValuePtr, err := col.ValueOf(bean)
if err != nil {
if !strings.Contains(err.Error(), "is not valid") {
engine.logger.Warn(err)
}
continue
}
if col.IsDeleted && !unscoped { // tag "deleted" is enabled
conds = append(conds, engine.CondDeleted(colName))
}
fieldValue := *fieldValuePtr
if fieldValue.Interface() == nil {
continue
}
fieldType := reflect.TypeOf(fieldValue.Interface())
requiredField := useAllCols
if b, ok := getFlagForColumn(mustColumnMap, col); ok {
if b {
requiredField = true
} else {
continue
}
}
if fieldType.Kind() == reflect.Ptr {
if fieldValue.IsNil() {
if includeNil {
conds = append(conds, builder.Eq{colName: nil})
}
continue
} else if !fieldValue.IsValid() {
continue
} else {
// dereference ptr type to instance type
fieldValue = fieldValue.Elem()
fieldType = reflect.TypeOf(fieldValue.Interface())
requiredField = true
}
}
var val interface{}
switch fieldType.Kind() {
case reflect.Bool:
if allUseBool || requiredField {
val = fieldValue.Interface()
} else {
// if a bool in a struct, it will not be as a condition because it default is false,
// please use Where() instead
continue
}
case reflect.String:
if !requiredField && fieldValue.String() == "" {
continue
}
// for MyString, should convert to string or panic
if fieldType.String() != reflect.String.String() {
val = fieldValue.String()
} else {
val = fieldValue.Interface()
}
case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64:
if !requiredField && fieldValue.Int() == 0 {
continue
}
val = fieldValue.Interface()
case reflect.Float32, reflect.Float64:
if !requiredField && fieldValue.Float() == 0.0 {
continue
}
val = fieldValue.Interface()
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
if !requiredField && fieldValue.Uint() == 0 {
continue
}
t := int64(fieldValue.Uint())
val = reflect.ValueOf(&t).Interface()
case reflect.Struct:
if fieldType.ConvertibleTo(core.TimeType) {
t := fieldValue.Convert(core.TimeType).Interface().(time.Time)
if !requiredField && (t.IsZero() || !fieldValue.IsValid()) {
continue
}
val = engine.formatColTime(col, t)
} else if _, ok := reflect.New(fieldType).Interface().(core.Conversion); ok {
continue
} else if valNul, ok := fieldValue.Interface().(driver.Valuer); ok {
val, _ = valNul.Value()
if val == nil {
continue
}
} else {
if col.SQLType.IsJson() {
if col.SQLType.IsText() {
bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
engine.logger.Error(err)
continue
}
val = string(bytes)
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
bytes, err = DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
engine.logger.Error(err)
continue
}
val = bytes
}
} else {
engine.autoMapType(fieldValue)
if table, ok := engine.Tables[fieldValue.Type()]; ok {
if len(table.PrimaryKeys) == 1 {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName)
// fix non-int pk issues
//if pkField.Int() != 0 {
if pkField.IsValid() && !isZero(pkField.Interface()) {
val = pkField.Interface()
} else {
continue
}
} else {
//TODO: how to handler?
return nil, fmt.Errorf("not supported %v as %v", fieldValue.Interface(), table.PrimaryKeys)
}
} else {
val = fieldValue.Interface()
}
}
}
case reflect.Array:
continue
case reflect.Slice, reflect.Map:
if fieldValue == reflect.Zero(fieldType) {
continue
}
if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
continue
}
if col.SQLType.IsText() {
bytes, err := DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
engine.logger.Error(err)
continue
}
val = string(bytes)
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
fieldType.Elem().Kind() == reflect.Uint8 {
if fieldValue.Len() > 0 {
val = fieldValue.Bytes()
} else {
continue
}
} else {
bytes, err = DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
engine.logger.Error(err)
continue
}
val = bytes
}
} else {
continue
}
default:
val = fieldValue.Interface()
}
conds = append(conds, builder.Eq{colName: val})
}
return builder.And(conds...), nil
}

View file

@ -1,28 +0,0 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.8
package xorm
import "context"
// Context creates a session with the context
func (engine *Engine) Context(ctx context.Context) *Session {
session := engine.NewSession()
session.isAutoClose = true
return session.Context(ctx)
}
// SetDefaultContext set the default context
func (engine *Engine) SetDefaultContext(ctx context.Context) {
engine.defaultContext = ctx
}
// PingContext tests if database is alive
func (engine *Engine) PingContext(ctx context.Context) error {
session := engine.NewSession()
defer session.Close()
return session.PingContext(ctx)
}

42
vendor/xorm.io/xorm/engine_group.go generated vendored
View file

@ -8,7 +8,10 @@ import (
"context" "context"
"time" "time"
"xorm.io/core" "xorm.io/xorm/caches"
"xorm.io/xorm/dialects"
"xorm.io/xorm/log"
"xorm.io/xorm/names"
) )
// EngineGroup defines an engine group // EngineGroup defines an engine group
@ -109,10 +112,10 @@ func (eg *EngineGroup) Ping() error {
} }
// SetColumnMapper set the column name mapping rule // SetColumnMapper set the column name mapping rule
func (eg *EngineGroup) SetColumnMapper(mapper core.IMapper) { func (eg *EngineGroup) SetColumnMapper(mapper names.Mapper) {
eg.Engine.ColumnMapper = mapper eg.Engine.SetColumnMapper(mapper)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].ColumnMapper = mapper eg.slaves[i].SetColumnMapper(mapper)
} }
} }
@ -125,7 +128,7 @@ func (eg *EngineGroup) SetConnMaxLifetime(d time.Duration) {
} }
// SetDefaultCacher set the default cacher // SetDefaultCacher set the default cacher
func (eg *EngineGroup) SetDefaultCacher(cacher core.Cacher) { func (eg *EngineGroup) SetDefaultCacher(cacher caches.Cacher) {
eg.Engine.SetDefaultCacher(cacher) eg.Engine.SetDefaultCacher(cacher)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].SetDefaultCacher(cacher) eg.slaves[i].SetDefaultCacher(cacher)
@ -133,7 +136,7 @@ func (eg *EngineGroup) SetDefaultCacher(cacher core.Cacher) {
} }
// SetLogger set the new logger // SetLogger set the new logger
func (eg *EngineGroup) SetLogger(logger core.ILogger) { func (eg *EngineGroup) SetLogger(logger interface{}) {
eg.Engine.SetLogger(logger) eg.Engine.SetLogger(logger)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].SetLogger(logger) eg.slaves[i].SetLogger(logger)
@ -141,7 +144,7 @@ func (eg *EngineGroup) SetLogger(logger core.ILogger) {
} }
// SetLogLevel sets the logger level // SetLogLevel sets the logger level
func (eg *EngineGroup) SetLogLevel(level core.LogLevel) { func (eg *EngineGroup) SetLogLevel(level log.LogLevel) {
eg.Engine.SetLogLevel(level) eg.Engine.SetLogLevel(level)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].SetLogLevel(level) eg.slaves[i].SetLogLevel(level)
@ -149,7 +152,7 @@ func (eg *EngineGroup) SetLogLevel(level core.LogLevel) {
} }
// SetMapper set the name mapping rules // SetMapper set the name mapping rules
func (eg *EngineGroup) SetMapper(mapper core.IMapper) { func (eg *EngineGroup) SetMapper(mapper names.Mapper) {
eg.Engine.SetMapper(mapper) eg.Engine.SetMapper(mapper)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].SetMapper(mapper) eg.slaves[i].SetMapper(mapper)
@ -158,17 +161,17 @@ func (eg *EngineGroup) SetMapper(mapper core.IMapper) {
// SetMaxIdleConns set the max idle connections on pool, default is 2 // SetMaxIdleConns set the max idle connections on pool, default is 2
func (eg *EngineGroup) SetMaxIdleConns(conns int) { func (eg *EngineGroup) SetMaxIdleConns(conns int) {
eg.Engine.db.SetMaxIdleConns(conns) eg.Engine.dialect.DB().SetMaxIdleConns(conns)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].db.SetMaxIdleConns(conns) eg.slaves[i].dialect.DB().SetMaxIdleConns(conns)
} }
} }
// SetMaxOpenConns is only available for go 1.2+ // SetMaxOpenConns is only available for go 1.2+
func (eg *EngineGroup) SetMaxOpenConns(conns int) { func (eg *EngineGroup) SetMaxOpenConns(conns int) {
eg.Engine.db.SetMaxOpenConns(conns) eg.Engine.dialect.DB().SetMaxOpenConns(conns)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].db.SetMaxOpenConns(conns) eg.slaves[i].dialect.DB().SetMaxOpenConns(conns)
} }
} }
@ -178,19 +181,18 @@ func (eg *EngineGroup) SetPolicy(policy GroupPolicy) *EngineGroup {
return eg return eg
} }
// SetTableMapper set the table name mapping rule func (eg *EngineGroup) SetQuotePolicy(quotePolicy dialects.QuotePolicy) {
func (eg *EngineGroup) SetTableMapper(mapper core.IMapper) { eg.Engine.SetQuotePolicy(quotePolicy)
eg.Engine.TableMapper = mapper
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].TableMapper = mapper eg.slaves[i].SetQuotePolicy(quotePolicy)
} }
} }
// ShowExecTime show SQL statement and execute time or not on logger if log level is great than INFO // SetTableMapper set the table name mapping rule
func (eg *EngineGroup) ShowExecTime(show ...bool) { func (eg *EngineGroup) SetTableMapper(mapper names.Mapper) {
eg.Engine.ShowExecTime(show...) eg.Engine.SetTableMapper(mapper)
for i := 0; i < len(eg.slaves); i++ { for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].ShowExecTime(show...) eg.slaves[i].SetTableMapper(mapper)
} }
} }

113
vendor/xorm.io/xorm/engine_table.go generated vendored
View file

@ -1,113 +0,0 @@
// Copyright 2018 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package xorm
import (
"fmt"
"reflect"
"strings"
"xorm.io/core"
)
// tbNameWithSchema will automatically add schema prefix on table name
func (engine *Engine) tbNameWithSchema(v string) string {
// Add schema name as prefix of table name.
// Only for postgres database.
if engine.dialect.DBType() == core.POSTGRES &&
engine.dialect.URI().Schema != "" &&
engine.dialect.URI().Schema != postgresPublicSchema &&
strings.Index(v, ".") == -1 {
return engine.dialect.URI().Schema + "." + v
}
return v
}
// TableName returns table name with schema prefix if has
func (engine *Engine) TableName(bean interface{}, includeSchema ...bool) string {
tbName := engine.tbNameNoSchema(bean)
if len(includeSchema) > 0 && includeSchema[0] {
tbName = engine.tbNameWithSchema(tbName)
}
return tbName
}
// tbName get some table's table name
func (session *Session) tbNameNoSchema(table *core.Table) string {
if len(session.statement.AltTableName) > 0 {
return session.statement.AltTableName
}
return table.Name
}
func (engine *Engine) tbNameForMap(v reflect.Value) string {
if v.Type().Implements(tpTableName) {
return v.Interface().(TableName).TableName()
}
if v.Kind() == reflect.Ptr {
v = v.Elem()
if v.Type().Implements(tpTableName) {
return v.Interface().(TableName).TableName()
}
}
return engine.TableMapper.Obj2Table(v.Type().Name())
}
func (engine *Engine) tbNameNoSchema(tablename interface{}) string {
switch tablename.(type) {
case []string:
t := tablename.([]string)
if len(t) > 1 {
return fmt.Sprintf("%v AS %v", engine.Quote(t[0]), engine.Quote(t[1]))
} else if len(t) == 1 {
return engine.Quote(t[0])
}
case []interface{}:
t := tablename.([]interface{})
l := len(t)
var table string
if l > 0 {
f := t[0]
switch f.(type) {
case string:
table = f.(string)
case TableName:
table = f.(TableName).TableName()
default:
v := rValue(f)
t := v.Type()
if t.Kind() == reflect.Struct {
table = engine.tbNameForMap(v)
} else {
table = engine.Quote(fmt.Sprintf("%v", f))
}
}
}
if l > 1 {
return fmt.Sprintf("%v AS %v", engine.Quote(table),
engine.Quote(fmt.Sprintf("%v", t[1])))
} else if l == 1 {
return engine.Quote(table)
}
case TableName:
return tablename.(TableName).TableName()
case string:
return tablename.(string)
case reflect.Value:
v := tablename.(reflect.Value)
return engine.tbNameForMap(v)
default:
v := rValue(tablename)
t := v.Type()
if t.Kind() == reflect.Struct {
return engine.tbNameForMap(v)
}
return engine.Quote(fmt.Sprintf("%v", tablename))
}
return ""
}

27
vendor/xorm.io/xorm/error.go generated vendored
View file

@ -6,7 +6,6 @@ package xorm
import ( import (
"errors" "errors"
"fmt"
) )
var ( var (
@ -20,32 +19,6 @@ var (
ErrNotExist = errors.New("Record does not exist") ErrNotExist = errors.New("Record does not exist")
// ErrCacheFailed cache failed error // ErrCacheFailed cache failed error
ErrCacheFailed = errors.New("Cache failed") ErrCacheFailed = errors.New("Cache failed")
// ErrNeedDeletedCond delete needs less one condition error
ErrNeedDeletedCond = errors.New("Delete action needs at least one condition")
// ErrNotImplemented not implemented
ErrNotImplemented = errors.New("Not implemented")
// ErrConditionType condition type unsupported // ErrConditionType condition type unsupported
ErrConditionType = errors.New("Unsupported condition type") ErrConditionType = errors.New("Unsupported condition type")
// ErrUnSupportedSQLType parameter of SQL is not supported
ErrUnSupportedSQLType = errors.New("unsupported sql type")
) )
// ErrFieldIsNotExist columns does not exist
type ErrFieldIsNotExist struct {
FieldName string
TableName string
}
func (e ErrFieldIsNotExist) Error() string {
return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
}
// ErrFieldIsNotValid is not valid
type ErrFieldIsNotValid struct {
FieldName string
TableName string
}
func (e ErrFieldIsNotValid) Error() string {
return fmt.Sprintf("field %s is not valid on table %s", e.FieldName, e.TableName)
}

5
vendor/xorm.io/xorm/go.mod generated vendored
View file

@ -9,7 +9,8 @@ require (
github.com/lib/pq v1.0.0 github.com/lib/pq v1.0.0
github.com/mattn/go-sqlite3 v1.10.0 github.com/mattn/go-sqlite3 v1.10.0
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.4.0
github.com/syndtr/goleveldb v1.0.0
github.com/ziutek/mymysql v1.5.4 github.com/ziutek/mymysql v1.5.4
xorm.io/builder v0.3.6 google.golang.org/appengine v1.6.0 // indirect
xorm.io/core v0.7.2 xorm.io/builder v0.3.7
) )

19
vendor/xorm.io/xorm/go.sum generated vendored
View file

@ -2,6 +2,7 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
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 h1:glPeL3BQJsbF6aIIYfZizMwc5LTYz250bDMjttbBGAU=
cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw= cloud.google.com/go v0.37.4/go.mod h1:NHPJ89PdicEuT9hdPXMROBD91xc5uRDxsMtSB16k7hw=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 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/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/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
@ -18,6 +19,7 @@ github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zA
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= 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/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/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 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-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-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -31,7 +33,9 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 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.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/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 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
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 h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 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/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=
@ -42,6 +46,7 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= 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/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/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 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/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@ -60,7 +65,9 @@ github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsO
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 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/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.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.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 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 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/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/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@ -83,6 +90,8 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
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/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
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=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -101,20 +110,24 @@ golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/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-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-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 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-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 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-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-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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-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-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-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-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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/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 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/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/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-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -135,7 +148,9 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 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.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
@ -145,5 +160,5 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/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.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8= xorm.io/builder v0.3.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8=
xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU= xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU=
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw= xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI=
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=

332
vendor/xorm.io/xorm/helpers.go generated vendored
View file

@ -1,332 +0,0 @@
// Copyright 2015 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package xorm
import (
"errors"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"xorm.io/core"
)
// str2PK convert string value to primary key value according to tp
func str2PKValue(s string, tp reflect.Type) (reflect.Value, error) {
var err error
var result interface{}
var defReturn = reflect.Zero(tp)
switch tp.Kind() {
case reflect.Int:
result, err = strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int: %s", s, err.Error())
}
case reflect.Int8:
x, err := strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int8: %s", s, err.Error())
}
result = int8(x)
case reflect.Int16:
x, err := strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int16: %s", s, err.Error())
}
result = int16(x)
case reflect.Int32:
x, err := strconv.Atoi(s)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int32: %s", s, err.Error())
}
result = int32(x)
case reflect.Int64:
result, err = strconv.ParseInt(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as int64: %s", s, err.Error())
}
case reflect.Uint:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint: %s", s, err.Error())
}
result = uint(x)
case reflect.Uint8:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint8: %s", s, err.Error())
}
result = uint8(x)
case reflect.Uint16:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint16: %s", s, err.Error())
}
result = uint16(x)
case reflect.Uint32:
x, err := strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint32: %s", s, err.Error())
}
result = uint32(x)
case reflect.Uint64:
result, err = strconv.ParseUint(s, 10, 64)
if err != nil {
return defReturn, fmt.Errorf("convert %s as uint64: %s", s, err.Error())
}
case reflect.String:
result = s
default:
return defReturn, errors.New("unsupported convert type")
}
return reflect.ValueOf(result).Convert(tp), nil
}
func str2PK(s string, tp reflect.Type) (interface{}, error) {
v, err := str2PKValue(s, tp)
if err != nil {
return nil, err
}
return v.Interface(), nil
}
func splitTag(tag string) (tags []string) {
tag = strings.TrimSpace(tag)
var hasQuote = false
var lastIdx = 0
for i, t := range tag {
if t == '\'' {
hasQuote = !hasQuote
} else if t == ' ' {
if lastIdx < i && !hasQuote {
tags = append(tags, strings.TrimSpace(tag[lastIdx:i]))
lastIdx = i + 1
}
}
}
if lastIdx < len(tag) {
tags = append(tags, strings.TrimSpace(tag[lastIdx:]))
}
return
}
type zeroable interface {
IsZero() bool
}
func isZero(k interface{}) bool {
switch k.(type) {
case int:
return k.(int) == 0
case int8:
return k.(int8) == 0
case int16:
return k.(int16) == 0
case int32:
return k.(int32) == 0
case int64:
return k.(int64) == 0
case uint:
return k.(uint) == 0
case uint8:
return k.(uint8) == 0
case uint16:
return k.(uint16) == 0
case uint32:
return k.(uint32) == 0
case uint64:
return k.(uint64) == 0
case float32:
return k.(float32) == 0
case float64:
return k.(float64) == 0
case bool:
return k.(bool) == false
case string:
return k.(string) == ""
case zeroable:
return k.(zeroable).IsZero()
}
return false
}
func isStructZero(v reflect.Value) bool {
if !v.IsValid() {
return true
}
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
switch field.Kind() {
case reflect.Ptr:
field = field.Elem()
fallthrough
case reflect.Struct:
if !isStructZero(field) {
return false
}
default:
if field.CanInterface() && !isZero(field.Interface()) {
return false
}
}
}
return true
}
func isArrayValueZero(v reflect.Value) bool {
if !v.IsValid() || v.Len() == 0 {
return true
}
for i := 0; i < v.Len(); i++ {
if !isZero(v.Index(i).Interface()) {
return false
}
}
return true
}
func int64ToIntValue(id int64, tp reflect.Type) reflect.Value {
var v interface{}
kind := tp.Kind()
if kind == reflect.Ptr {
kind = tp.Elem().Kind()
}
switch kind {
case reflect.Int16:
temp := int16(id)
v = &temp
case reflect.Int32:
temp := int32(id)
v = &temp
case reflect.Int:
temp := int(id)
v = &temp
case reflect.Int64:
temp := id
v = &temp
case reflect.Uint16:
temp := uint16(id)
v = &temp
case reflect.Uint32:
temp := uint32(id)
v = &temp
case reflect.Uint64:
temp := uint64(id)
v = &temp
case reflect.Uint:
temp := uint(id)
v = &temp
}
if tp.Kind() == reflect.Ptr {
return reflect.ValueOf(v).Convert(tp)
}
return reflect.ValueOf(v).Elem().Convert(tp)
}
func int64ToInt(id int64, tp reflect.Type) interface{} {
return int64ToIntValue(id, tp).Interface()
}
func isPKZero(pk core.PK) bool {
for _, k := range pk {
if isZero(k) {
return true
}
}
return false
}
func indexNoCase(s, sep string) int {
return strings.Index(strings.ToLower(s), strings.ToLower(sep))
}
func splitNoCase(s, sep string) []string {
idx := indexNoCase(s, sep)
if idx < 0 {
return []string{s}
}
return strings.Split(s, s[idx:idx+len(sep)])
}
func splitNNoCase(s, sep string, n int) []string {
idx := indexNoCase(s, sep)
if idx < 0 {
return []string{s}
}
return strings.SplitN(s, s[idx:idx+len(sep)], n)
}
func makeArray(elem string, count int) []string {
res := make([]string, count)
for i := 0; i < count; i++ {
res[i] = elem
}
return res
}
func rValue(bean interface{}) reflect.Value {
return reflect.Indirect(reflect.ValueOf(bean))
}
func rType(bean interface{}) reflect.Type {
sliceValue := reflect.Indirect(reflect.ValueOf(bean))
// return reflect.TypeOf(sliceValue.Interface())
return sliceValue.Type()
}
func structName(v reflect.Type) string {
for v.Kind() == reflect.Ptr {
v = v.Elem()
}
return v.Name()
}
func sliceEq(left, right []string) bool {
if len(left) != len(right) {
return false
}
sort.Sort(sort.StringSlice(left))
sort.Sort(sort.StringSlice(right))
for i := 0; i < len(left); i++ {
if left[i] != right[i] {
return false
}
}
return true
}
func indexName(tableName, idxName string) string {
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+" ")
}

21
vendor/xorm.io/xorm/helpler_time.go generated vendored
View file

@ -1,21 +0,0 @@
// Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package xorm
import "time"
const (
zeroTime0 = "0000-00-00 00:00:00"
zeroTime1 = "0001-01-01 00:00:00"
)
func formatTime(t time.Time) string {
return t.Format("2006-01-02 15:04:05")
}
func isTimeZero(t time.Time) bool {
return t.IsZero() || formatTime(t) == zeroTime0 ||
formatTime(t) == zeroTime1
}

41
vendor/xorm.io/xorm/interface.go generated vendored
View file

@ -10,7 +10,11 @@ import (
"reflect" "reflect"
"time" "time"
"xorm.io/core" "xorm.io/xorm/caches"
"xorm.io/xorm/dialects"
"xorm.io/xorm/log"
"xorm.io/xorm/names"
"xorm.io/xorm/schemas"
) )
// Interface defines the interface which Engine, EngineGroup and Session will implementate. // Interface defines the interface which Engine, EngineGroup and Session will implementate.
@ -55,6 +59,7 @@ type Interface interface {
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, interface{}) *Session SetExpr(string, interface{}) *Session
Select(string) *Session
SQL(interface{}, ...interface{}) *Session SQL(interface{}, ...interface{}) *Session
Sum(bean interface{}, colName string) (float64, error) Sum(bean interface{}, colName string) (float64, error)
SumInt(bean interface{}, colName string) (int64, error) SumInt(bean interface{}, colName string) (int64, error)
@ -76,37 +81,41 @@ type EngineInterface interface {
ClearCache(...interface{}) error ClearCache(...interface{}) error
Context(context.Context) *Session Context(context.Context) *Session
CreateTables(...interface{}) error CreateTables(...interface{}) error
DBMetas() ([]*core.Table, error) DBMetas() ([]*schemas.Table, error)
Dialect() core.Dialect Dialect() dialects.Dialect
DriverName() string
DropTables(...interface{}) error DropTables(...interface{}) error
DumpAllToFile(fp string, tp ...core.DbType) error DumpAllToFile(fp string, tp ...schemas.DBType) error
GetCacher(string) core.Cacher GetCacher(string) caches.Cacher
GetColumnMapper() core.IMapper GetColumnMapper() names.Mapper
GetDefaultCacher() core.Cacher GetDefaultCacher() caches.Cacher
GetTableMapper() core.IMapper GetTableMapper() names.Mapper
GetTZDatabase() *time.Location GetTZDatabase() *time.Location
GetTZLocation() *time.Location GetTZLocation() *time.Location
MapCacher(interface{}, core.Cacher) error ImportFile(fp string) ([]sql.Result, error)
MapCacher(interface{}, caches.Cacher) error
NewSession() *Session NewSession() *Session
NoAutoTime() *Session NoAutoTime() *Session
Quote(string) string Quote(string) string
SetCacher(string, core.Cacher) SetCacher(string, caches.Cacher)
SetConnMaxLifetime(time.Duration) SetConnMaxLifetime(time.Duration)
SetDefaultCacher(core.Cacher) SetColumnMapper(names.Mapper)
SetLogger(logger core.ILogger) SetDefaultCacher(caches.Cacher)
SetLogLevel(core.LogLevel) SetLogger(logger interface{})
SetMapper(core.IMapper) SetLogLevel(log.LogLevel)
SetMapper(names.Mapper)
SetMaxOpenConns(int) SetMaxOpenConns(int)
SetMaxIdleConns(int) SetMaxIdleConns(int)
SetQuotePolicy(dialects.QuotePolicy)
SetSchema(string) SetSchema(string)
SetTableMapper(names.Mapper)
SetTZDatabase(tz *time.Location) SetTZDatabase(tz *time.Location)
SetTZLocation(tz *time.Location) SetTZLocation(tz *time.Location)
ShowExecTime(...bool)
ShowSQL(show ...bool) ShowSQL(show ...bool)
Sync(...interface{}) error Sync(...interface{}) error
Sync2(...interface{}) error Sync2(...interface{}) error
StoreEngine(storeEngine string) *Session StoreEngine(storeEngine string) *Session
TableInfo(bean interface{}) *Table TableInfo(bean interface{}) (*schemas.Table, error)
TableName(interface{}, ...bool) string TableName(interface{}, ...bool) string
UnMapType(reflect.Type) UnMapType(reflect.Type)
} }

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package json
import "encoding/json" import "encoding/json"

79
vendor/xorm.io/xorm/internal/statements/cache.go generated vendored Normal file
View file

@ -0,0 +1,79 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"fmt"
"strings"
"xorm.io/xorm/internal/utils"
"xorm.io/xorm/schemas"
)
func (statement *Statement) ConvertIDSQL(sqlStr string) string {
if statement.RefTable != nil {
cols := statement.RefTable.PKColumns()
if len(cols) == 0 {
return ""
}
colstrs := statement.joinColumns(cols, false)
sqls := utils.SplitNNoCase(sqlStr, " from ", 2)
if len(sqls) != 2 {
return ""
}
var top string
pLimitN := statement.LimitN
if pLimitN != nil && statement.dialect.URI().DBType == schemas.MSSQL {
top = fmt.Sprintf("TOP %d ", *pLimitN)
}
newsql := fmt.Sprintf("SELECT %s%s FROM %v", top, colstrs, sqls[1])
return newsql
}
return ""
}
func (statement *Statement) ConvertUpdateSQL(sqlStr string) (string, string) {
if statement.RefTable == nil || len(statement.RefTable.PrimaryKeys) != 1 {
return "", ""
}
colstrs := statement.joinColumns(statement.RefTable.PKColumns(), true)
sqls := utils.SplitNNoCase(sqlStr, "where", 2)
if len(sqls) != 2 {
if len(sqls) == 1 {
return sqls[0], fmt.Sprintf("SELECT %v FROM %v",
colstrs, statement.quote(statement.TableName()))
}
return "", ""
}
var whereStr = sqls[1]
// TODO: for postgres only, if any other database?
var paraStr string
if statement.dialect.URI().DBType == schemas.POSTGRES {
paraStr = "$"
} else if statement.dialect.URI().DBType == schemas.MSSQL {
paraStr = ":"
}
if paraStr != "" {
if strings.Contains(sqls[1], paraStr) {
dollers := strings.Split(sqls[1], paraStr)
whereStr = dollers[0]
for i, c := range dollers[1:] {
ccs := strings.SplitN(c, " ", 2)
whereStr += fmt.Sprintf(paraStr+"%v %v", i+1, ccs[1])
}
}
}
return sqls[0], fmt.Sprintf("SELECT %v FROM %v WHERE %v",
colstrs, statement.quote(statement.TableName()),
whereStr)
}

66
vendor/xorm.io/xorm/internal/statements/column_map.go generated vendored Normal file
View file

@ -0,0 +1,66 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"strings"
"xorm.io/xorm/schemas"
)
type columnMap []string
func (m columnMap) Contain(colName string) bool {
if len(m) == 0 {
return false
}
n := len(colName)
for _, mk := range m {
if len(mk) != n {
continue
}
if strings.EqualFold(mk, colName) {
return true
}
}
return false
}
func (m columnMap) Len() int {
return len(m)
}
func (m columnMap) IsEmpty() bool {
return len(m) == 0
}
func (m *columnMap) Add(colName string) bool {
if m.Contain(colName) {
return false
}
*m = append(*m, colName)
return true
}
func getFlagForColumn(m map[string]bool, col *schemas.Column) (val bool, has bool) {
if len(m) == 0 {
return false, false
}
n := len(col.Name)
for mk := range m {
if len(mk) != n {
continue
}
if strings.EqualFold(mk, col.Name) {
return m[mk], true
}
}
return false, false
}

View file

@ -2,13 +2,14 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package statements
import ( import (
"fmt" "fmt"
"strings" "strings"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/xorm/schemas"
) )
type ErrUnsupportedExprType struct { type ErrUnsupportedExprType struct {
@ -25,22 +26,22 @@ type exprParam struct {
} }
type exprParams struct { type exprParams struct {
colNames []string ColNames []string
args []interface{} Args []interface{}
} }
func (exprs *exprParams) Len() int { func (exprs *exprParams) Len() int {
return len(exprs.colNames) return len(exprs.ColNames)
} }
func (exprs *exprParams) addParam(colName string, arg interface{}) { func (exprs *exprParams) addParam(colName string, arg interface{}) {
exprs.colNames = append(exprs.colNames, colName) exprs.ColNames = append(exprs.ColNames, colName)
exprs.args = append(exprs.args, arg) exprs.Args = append(exprs.Args, arg)
} }
func (exprs *exprParams) isColExist(colName string) bool { func (exprs *exprParams) IsColExist(colName string) bool {
for _, name := range exprs.colNames { for _, name := range exprs.ColNames {
if strings.EqualFold(trimQuote(name), trimQuote(colName)) { if strings.EqualFold(schemas.CommonQuoter.Trim(name), schemas.CommonQuoter.Trim(colName)) {
return true return true
} }
} }
@ -48,16 +49,16 @@ func (exprs *exprParams) isColExist(colName string) bool {
} }
func (exprs *exprParams) getByName(colName string) (exprParam, bool) { func (exprs *exprParams) getByName(colName string) (exprParam, bool) {
for i, name := range exprs.colNames { for i, name := range exprs.ColNames {
if strings.EqualFold(name, colName) { if strings.EqualFold(name, colName) {
return exprParam{name, exprs.args[i]}, true return exprParam{name, exprs.Args[i]}, true
} }
} }
return exprParam{}, false return exprParam{}, false
} }
func (exprs *exprParams) writeArgs(w *builder.BytesWriter) error { func (exprs *exprParams) WriteArgs(w *builder.BytesWriter) error {
for i, expr := range exprs.args { for i, expr := range exprs.Args {
switch arg := expr.(type) { switch arg := expr.(type) {
case *builder.Builder: case *builder.Builder:
if _, err := w.WriteString("("); err != nil { if _, err := w.WriteString("("); err != nil {
@ -82,7 +83,7 @@ func (exprs *exprParams) writeArgs(w *builder.BytesWriter) error {
} }
w.Append(arg) w.Append(arg)
} }
if i != len(exprs.args)-1 { if i != len(exprs.Args)-1 {
if _, err := w.WriteString(","); err != nil { if _, err := w.WriteString(","); err != nil {
return err return err
} }
@ -92,7 +93,7 @@ func (exprs *exprParams) writeArgs(w *builder.BytesWriter) error {
} }
func (exprs *exprParams) writeNameArgs(w *builder.BytesWriter) error { func (exprs *exprParams) writeNameArgs(w *builder.BytesWriter) error {
for i, colName := range exprs.colNames { for i, colName := range exprs.ColNames {
if _, err := w.WriteString(colName); err != nil { if _, err := w.WriteString(colName); err != nil {
return err return err
} }
@ -100,7 +101,7 @@ func (exprs *exprParams) writeNameArgs(w *builder.BytesWriter) error {
return err return err
} }
switch arg := exprs.args[i].(type) { switch arg := exprs.Args[i].(type) {
case *builder.Builder: case *builder.Builder:
if _, err := w.WriteString("("); err != nil { if _, err := w.WriteString("("); err != nil {
return err return err
@ -112,10 +113,10 @@ func (exprs *exprParams) writeNameArgs(w *builder.BytesWriter) error {
return err return err
} }
default: default:
w.Append(exprs.args[i]) w.Append(exprs.Args[i])
} }
if i+1 != len(exprs.colNames) { if i+1 != len(exprs.ColNames) {
if _, err := w.WriteString(","); err != nil { if _, err := w.WriteString(","); err != nil {
return err return err
} }

143
vendor/xorm.io/xorm/internal/statements/insert.go generated vendored Normal file
View file

@ -0,0 +1,143 @@
// Copyright 2020 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"strings"
"xorm.io/builder"
"xorm.io/xorm/schemas"
)
func (statement *Statement) writeInsertOutput(buf *strings.Builder, table *schemas.Table) error {
if statement.dialect.URI().DBType == schemas.MSSQL && len(table.AutoIncrement) > 0 {
if _, err := buf.WriteString(" OUTPUT Inserted."); err != nil {
return err
}
if _, err := buf.WriteString(table.AutoIncrement); err != nil {
return err
}
}
return nil
}
func (statement *Statement) GenInsertSQL(colNames []string, args []interface{}) (string, []interface{}, error) {
var (
table = statement.RefTable
tableName = statement.TableName()
exprs = statement.ExprColumns
colPlaces = strings.Repeat("?, ", len(colNames))
)
if exprs.Len() <= 0 && len(colPlaces) > 0 {
colPlaces = colPlaces[0 : len(colPlaces)-2]
}
var buf = builder.NewWriter()
if _, err := buf.WriteString("INSERT INTO "); err != nil {
return "", nil, err
}
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, tableName); err != nil {
return "", nil, err
}
if len(colPlaces) <= 0 {
if statement.dialect.URI().DBType == schemas.MYSQL {
if _, err := buf.WriteString(" VALUES ()"); err != nil {
return "", nil, err
}
} else {
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
return "", nil, err
}
if _, err := buf.WriteString(" DEFAULT VALUES"); err != nil {
return "", nil, err
}
}
} else {
if _, err := buf.WriteString(" ("); err != nil {
return "", nil, err
}
if err := statement.dialect.Quoter().JoinWrite(buf.Builder, append(colNames, exprs.ColNames...), ","); err != nil {
return "", nil, err
}
if statement.Conds().IsValid() {
if _, err := buf.WriteString(")"); err != nil {
return "", nil, err
}
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
return "", nil, err
}
if _, err := buf.WriteString(" SELECT "); err != nil {
return "", nil, err
}
if err := statement.WriteArgs(buf, args); err != nil {
return "", nil, err
}
if len(exprs.Args) > 0 {
if _, err := buf.WriteString(","); err != nil {
return "", nil, err
}
}
if err := exprs.WriteArgs(buf); err != nil {
return "", nil, err
}
if _, err := buf.WriteString(" FROM "); err != nil {
return "", nil, err
}
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, tableName); err != nil {
return "", nil, err
}
if _, err := buf.WriteString(" WHERE "); err != nil {
return "", nil, err
}
if err := statement.Conds().WriteTo(buf); err != nil {
return "", nil, err
}
} else {
buf.Append(args...)
if _, err := buf.WriteString(")"); err != nil {
return "", nil, err
}
if err := statement.writeInsertOutput(buf.Builder, table); err != nil {
return "", nil, err
}
if _, err := buf.WriteString(" VALUES ("); err != nil {
return "", nil, err
}
if _, err := buf.WriteString(colPlaces); err != nil {
return "", nil, err
}
if err := exprs.WriteArgs(buf); err != nil {
return "", nil, err
}
if _, err := buf.WriteString(")"); err != nil {
return "", nil, err
}
}
}
if len(table.AutoIncrement) > 0 && statement.dialect.URI().DBType == schemas.POSTGRES {
if _, err := buf.WriteString(" RETURNING "); err != nil {
return "", nil, err
}
if err := statement.dialect.Quoter().QuoteTo(buf.Builder, table.AutoIncrement); err != nil {
return "", nil, err
}
}
return buf.String(), buf.Args(), nil
}

79
vendor/xorm.io/xorm/internal/statements/pk.go generated vendored Normal file
View file

@ -0,0 +1,79 @@
// Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"fmt"
"reflect"
"xorm.io/builder"
"xorm.io/xorm/schemas"
)
var (
ptrPkType = reflect.TypeOf(&schemas.PK{})
pkType = reflect.TypeOf(schemas.PK{})
stringType = reflect.TypeOf("")
intType = reflect.TypeOf(int64(0))
uintType = reflect.TypeOf(uint64(0))
)
// ID generate "where id = ? " statement or for composite key "where key1 = ? and key2 = ?"
func (statement *Statement) ID(id interface{}) *Statement {
switch t := id.(type) {
case *schemas.PK:
statement.idParam = *t
case schemas.PK:
statement.idParam = t
case string, int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
statement.idParam = schemas.PK{id}
default:
idValue := reflect.ValueOf(id)
idType := idValue.Type()
switch idType.Kind() {
case reflect.String:
statement.idParam = schemas.PK{idValue.Convert(stringType).Interface()}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
statement.idParam = schemas.PK{idValue.Convert(intType).Interface()}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
statement.idParam = schemas.PK{idValue.Convert(uintType).Interface()}
case reflect.Slice:
if idType.ConvertibleTo(pkType) {
statement.idParam = idValue.Convert(pkType).Interface().(schemas.PK)
}
case reflect.Ptr:
if idType.ConvertibleTo(ptrPkType) {
statement.idParam = idValue.Convert(ptrPkType).Elem().Interface().(schemas.PK)
}
}
}
if statement.idParam == nil {
statement.LastError = fmt.Errorf("ID param %#v is not supported", id)
}
return statement
}
func (statement *Statement) ProcessIDParam() error {
if statement.idParam == nil || statement.RefTable == nil {
return nil
}
if len(statement.RefTable.PrimaryKeys) != len(statement.idParam) {
fmt.Println("=====", statement.RefTable.PrimaryKeys, statement.idParam)
return fmt.Errorf("ID condition is error, expect %d primarykeys, there are %d",
len(statement.RefTable.PrimaryKeys),
len(statement.idParam),
)
}
for i, col := range statement.RefTable.PKColumns() {
var colName = statement.colName(col, statement.TableName())
statement.cond = statement.cond.And(builder.Eq{colName: statement.idParam[i]})
}
return nil
}

441
vendor/xorm.io/xorm/internal/statements/query.go generated vendored Normal file
View file

@ -0,0 +1,441 @@
// Copyright 2019 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"errors"
"fmt"
"reflect"
"strings"
"xorm.io/builder"
"xorm.io/xorm/schemas"
)
func (statement *Statement) GenQuerySQL(sqlOrArgs ...interface{}) (string, []interface{}, error) {
if len(sqlOrArgs) > 0 {
return statement.ConvertSQLOrArgs(sqlOrArgs...)
}
if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil
}
if len(statement.TableName()) <= 0 {
return "", nil, ErrTableNotFound
}
var columnStr = statement.ColumnStr()
if len(statement.SelectStr) > 0 {
columnStr = statement.SelectStr
} else {
if statement.JoinStr == "" {
if columnStr == "" {
if statement.GroupByStr != "" {
columnStr = statement.quoteColumnStr(statement.GroupByStr)
} else {
columnStr = statement.genColumnStr()
}
}
} else {
if columnStr == "" {
if statement.GroupByStr != "" {
columnStr = statement.quoteColumnStr(statement.GroupByStr)
} else {
columnStr = "*"
}
}
}
if columnStr == "" {
columnStr = "*"
}
}
if err := statement.ProcessIDParam(); err != nil {
return "", nil, err
}
sqlStr, condArgs, err := statement.genSelectSQL(columnStr, true, true)
if err != nil {
return "", nil, err
}
args := append(statement.joinArgs, condArgs...)
// for mssql and use limit
qs := strings.Count(sqlStr, "?")
if len(args)*2 == qs {
args = append(args, args...)
}
return sqlStr, args, nil
}
func (statement *Statement) GenSumSQL(bean interface{}, columns ...string) (string, []interface{}, error) {
if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil
}
statement.SetRefBean(bean)
var sumStrs = make([]string, 0, len(columns))
for _, colName := range columns {
if !strings.Contains(colName, " ") && !strings.Contains(colName, "(") {
colName = statement.quote(colName)
} else {
colName = statement.ReplaceQuote(colName)
}
sumStrs = append(sumStrs, fmt.Sprintf("COALESCE(sum(%s),0)", colName))
}
sumSelect := strings.Join(sumStrs, ", ")
if err := statement.mergeConds(bean); err != nil {
return "", nil, err
}
sqlStr, condArgs, err := statement.genSelectSQL(sumSelect, true, true)
if err != nil {
return "", nil, err
}
return sqlStr, append(statement.joinArgs, condArgs...), nil
}
func (statement *Statement) GenGetSQL(bean interface{}) (string, []interface{}, error) {
v := rValue(bean)
isStruct := v.Kind() == reflect.Struct
if isStruct {
statement.SetRefBean(bean)
}
var columnStr = statement.ColumnStr()
if len(statement.SelectStr) > 0 {
columnStr = statement.SelectStr
} else {
// TODO: always generate column names, not use * even if join
if len(statement.JoinStr) == 0 {
if len(columnStr) == 0 {
if len(statement.GroupByStr) > 0 {
columnStr = statement.quoteColumnStr(statement.GroupByStr)
} else {
columnStr = statement.genColumnStr()
}
}
} else {
if len(columnStr) == 0 {
if len(statement.GroupByStr) > 0 {
columnStr = statement.quoteColumnStr(statement.GroupByStr)
}
}
}
}
if len(columnStr) == 0 {
columnStr = "*"
}
if isStruct {
if err := statement.mergeConds(bean); err != nil {
return "", nil, err
}
} else {
if err := statement.ProcessIDParam(); err != nil {
return "", nil, err
}
}
sqlStr, condArgs, err := statement.genSelectSQL(columnStr, true, true)
if err != nil {
return "", nil, err
}
return sqlStr, append(statement.joinArgs, condArgs...), nil
}
// GenCountSQL generates the SQL for counting
func (statement *Statement) GenCountSQL(beans ...interface{}) (string, []interface{}, error) {
if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil
}
var condArgs []interface{}
var err error
if len(beans) > 0 {
statement.SetRefBean(beans[0])
if err := statement.mergeConds(beans[0]); err != nil {
return "", nil, err
}
}
var selectSQL = statement.SelectStr
if len(selectSQL) <= 0 {
if statement.IsDistinct {
selectSQL = fmt.Sprintf("count(DISTINCT %s)", statement.ColumnStr())
} else if statement.ColumnStr() != "" {
selectSQL = fmt.Sprintf("count(%s)", statement.ColumnStr())
} else {
selectSQL = "count(*)"
}
}
sqlStr, condArgs, err := statement.genSelectSQL(selectSQL, false, false)
if err != nil {
return "", nil, err
}
return sqlStr, append(statement.joinArgs, condArgs...), nil
}
func (statement *Statement) genSelectSQL(columnStr string, needLimit, needOrderBy bool) (string, []interface{}, error) {
var (
distinct string
dialect = statement.dialect
quote = statement.quote
fromStr = " FROM "
top, mssqlCondi, whereStr string
)
if statement.IsDistinct && !strings.HasPrefix(columnStr, "count") {
distinct = "DISTINCT "
}
condSQL, condArgs, err := statement.GenCondSQL(statement.cond)
if err != nil {
return "", nil, err
}
if len(condSQL) > 0 {
whereStr = " WHERE " + condSQL
}
if dialect.URI().DBType == schemas.MSSQL && strings.Contains(statement.TableName(), "..") {
fromStr += statement.TableName()
} else {
fromStr += quote(statement.TableName())
}
if statement.TableAlias != "" {
if dialect.URI().DBType == schemas.ORACLE {
fromStr += " " + quote(statement.TableAlias)
} else {
fromStr += " AS " + quote(statement.TableAlias)
}
}
if statement.JoinStr != "" {
fromStr = fmt.Sprintf("%v %v", fromStr, statement.JoinStr)
}
pLimitN := statement.LimitN
if dialect.URI().DBType == schemas.MSSQL {
if pLimitN != nil {
LimitNValue := *pLimitN
top = fmt.Sprintf("TOP %d ", LimitNValue)
}
if statement.Start > 0 {
var column string
if len(statement.RefTable.PKColumns()) == 0 {
for _, index := range statement.RefTable.Indexes {
if len(index.Cols) == 1 {
column = index.Cols[0]
break
}
}
if len(column) == 0 {
column = statement.RefTable.ColumnsSeq()[0]
}
} else {
column = statement.RefTable.PKColumns()[0].Name
}
if statement.needTableName() {
if len(statement.TableAlias) > 0 {
column = statement.TableAlias + "." + column
} else {
column = statement.TableName() + "." + column
}
}
var orderStr string
if needOrderBy && len(statement.OrderStr) > 0 {
orderStr = " ORDER BY " + statement.OrderStr
}
var groupStr string
if len(statement.GroupByStr) > 0 {
groupStr = " GROUP BY " + statement.GroupByStr
}
mssqlCondi = fmt.Sprintf("(%s NOT IN (SELECT TOP %d %s%s%s%s%s))",
column, statement.Start, column, fromStr, whereStr, orderStr, groupStr)
}
}
var buf strings.Builder
fmt.Fprintf(&buf, "SELECT %v%v%v%v%v", distinct, top, columnStr, fromStr, whereStr)
if len(mssqlCondi) > 0 {
if len(whereStr) > 0 {
fmt.Fprint(&buf, " AND ", mssqlCondi)
} else {
fmt.Fprint(&buf, " WHERE ", mssqlCondi)
}
}
if statement.GroupByStr != "" {
fmt.Fprint(&buf, " GROUP BY ", statement.GroupByStr)
}
if statement.HavingStr != "" {
fmt.Fprint(&buf, " ", statement.HavingStr)
}
if needOrderBy && statement.OrderStr != "" {
fmt.Fprint(&buf, " ORDER BY ", statement.OrderStr)
}
if needLimit {
if dialect.URI().DBType != schemas.MSSQL && dialect.URI().DBType != schemas.ORACLE {
if statement.Start > 0 {
if pLimitN != nil {
fmt.Fprintf(&buf, " LIMIT %v OFFSET %v", *pLimitN, statement.Start)
} else {
fmt.Fprintf(&buf, "LIMIT 0 OFFSET %v", statement.Start)
}
} else if pLimitN != nil {
fmt.Fprint(&buf, " LIMIT ", *pLimitN)
}
} else if dialect.URI().DBType == schemas.ORACLE {
if statement.Start != 0 || pLimitN != nil {
oldString := buf.String()
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",
columnStr, rawColStr, oldString, statement.Start+*pLimitN, statement.Start)
}
}
}
if statement.IsForUpdate {
return dialect.ForUpdateSQL(buf.String()), condArgs, nil
}
return buf.String(), condArgs, nil
}
func (statement *Statement) GenExistSQL(bean ...interface{}) (string, []interface{}, error) {
if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil
}
var sqlStr string
var args []interface{}
var joinStr string
var err error
if len(bean) == 0 {
tableName := statement.TableName()
if len(tableName) <= 0 {
return "", nil, ErrTableNotFound
}
tableName = statement.quote(tableName)
if len(statement.JoinStr) > 0 {
joinStr = statement.JoinStr
}
if statement.Conds().IsValid() {
condSQL, condArgs, err := statement.GenCondSQL(statement.Conds())
if err != nil {
return "", nil, err
}
if statement.dialect.URI().DBType == schemas.MSSQL {
sqlStr = fmt.Sprintf("SELECT TOP 1 * FROM %s %s WHERE %s", tableName, joinStr, condSQL)
} else if statement.dialect.URI().DBType == schemas.ORACLE {
sqlStr = fmt.Sprintf("SELECT * FROM %s WHERE (%s) %s AND ROWNUM=1", tableName, joinStr, condSQL)
} else {
sqlStr = fmt.Sprintf("SELECT * FROM %s %s WHERE %s LIMIT 1", tableName, joinStr, condSQL)
}
args = condArgs
} else {
if statement.dialect.URI().DBType == schemas.MSSQL {
sqlStr = fmt.Sprintf("SELECT TOP 1 * FROM %s %s", tableName, joinStr)
} else if statement.dialect.URI().DBType == schemas.ORACLE {
sqlStr = fmt.Sprintf("SELECT * FROM %s %s WHERE ROWNUM=1", tableName, joinStr)
} else {
sqlStr = fmt.Sprintf("SELECT * FROM %s %s LIMIT 1", tableName, joinStr)
}
args = []interface{}{}
}
} else {
beanValue := reflect.ValueOf(bean[0])
if beanValue.Kind() != reflect.Ptr {
return "", nil, errors.New("needs a pointer")
}
if beanValue.Elem().Kind() == reflect.Struct {
if err := statement.SetRefBean(bean[0]); err != nil {
return "", nil, err
}
}
if len(statement.TableName()) <= 0 {
return "", nil, ErrTableNotFound
}
statement.Limit(1)
sqlStr, args, err = statement.GenGetSQL(bean[0])
if err != nil {
return "", nil, err
}
}
return sqlStr, args, nil
}
func (statement *Statement) GenFindSQL(autoCond builder.Cond) (string, []interface{}, error) {
if statement.RawSQL != "" {
return statement.GenRawSQL(), statement.RawParams, nil
}
var sqlStr string
var args []interface{}
var err error
if len(statement.TableName()) <= 0 {
return "", nil, ErrTableNotFound
}
var columnStr = statement.ColumnStr()
if len(statement.SelectStr) > 0 {
columnStr = statement.SelectStr
} else {
if statement.JoinStr == "" {
if columnStr == "" {
if statement.GroupByStr != "" {
columnStr = statement.quoteColumnStr(statement.GroupByStr)
} else {
columnStr = statement.genColumnStr()
}
}
} else {
if columnStr == "" {
if statement.GroupByStr != "" {
columnStr = statement.quoteColumnStr(statement.GroupByStr)
} else {
columnStr = "*"
}
}
}
if columnStr == "" {
columnStr = "*"
}
}
statement.cond = statement.cond.And(autoCond)
sqlStr, condArgs, err := statement.genSelectSQL(columnStr, true, true)
if err != nil {
return "", nil, err
}
args = append(statement.joinArgs, condArgs...)
// for mssql and use limit
qs := strings.Count(sqlStr, "?")
if len(args)*2 == qs {
args = append(args, args...)
}
return sqlStr, args, nil
}

996
vendor/xorm.io/xorm/internal/statements/statement.go generated vendored Normal file
View file

@ -0,0 +1,996 @@
// Copyright 2015 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"database/sql/driver"
"errors"
"fmt"
"reflect"
"strings"
"time"
"xorm.io/builder"
"xorm.io/xorm/contexts"
"xorm.io/xorm/convert"
"xorm.io/xorm/dialects"
"xorm.io/xorm/internal/json"
"xorm.io/xorm/internal/utils"
"xorm.io/xorm/schemas"
"xorm.io/xorm/tags"
)
var (
// ErrConditionType condition type unsupported
ErrConditionType = errors.New("Unsupported condition type")
// ErrUnSupportedSQLType parameter of SQL is not supported
ErrUnSupportedSQLType = errors.New("Unsupported sql type")
// ErrUnSupportedType unsupported error
ErrUnSupportedType = errors.New("Unsupported type error")
// ErrTableNotFound table not found error
ErrTableNotFound = errors.New("Table not found")
)
// Statement save all the sql info for executing SQL
type Statement struct {
RefTable *schemas.Table
dialect dialects.Dialect
defaultTimeZone *time.Location
tagParser *tags.Parser
Start int
LimitN *int
idParam schemas.PK
OrderStr string
JoinStr string
joinArgs []interface{}
GroupByStr string
HavingStr string
SelectStr string
useAllCols bool
AltTableName string
tableName string
RawSQL string
RawParams []interface{}
UseCascade bool
UseAutoJoin bool
StoreEngine string
Charset string
UseCache bool
UseAutoTime bool
NoAutoCondition bool
IsDistinct bool
IsForUpdate bool
TableAlias string
allUseBool bool
CheckVersion bool
unscoped bool
ColumnMap columnMap
OmitColumnMap columnMap
MustColumnMap map[string]bool
NullableMap map[string]bool
IncrColumns exprParams
DecrColumns exprParams
ExprColumns exprParams
cond builder.Cond
BufferSize int
Context contexts.ContextCache
LastError error
}
// NewStatement creates a new statement
func NewStatement(dialect dialects.Dialect, tagParser *tags.Parser, defaultTimeZone *time.Location) *Statement {
statement := &Statement{
dialect: dialect,
tagParser: tagParser,
defaultTimeZone: defaultTimeZone,
}
statement.Reset()
return statement
}
func (statement *Statement) SetTableName(tableName string) {
statement.tableName = tableName
}
func (statement *Statement) omitStr() string {
return statement.dialect.Quoter().Join(statement.OmitColumnMap, " ,")
}
// GenRawSQL generates correct raw sql
func (statement *Statement) GenRawSQL() string {
return statement.ReplaceQuote(statement.RawSQL)
}
func (statement *Statement) GenCondSQL(condOrBuilder interface{}) (string, []interface{}, error) {
condSQL, condArgs, err := builder.ToSQL(condOrBuilder)
if err != nil {
return "", nil, err
}
return statement.ReplaceQuote(condSQL), condArgs, nil
}
func (statement *Statement) ReplaceQuote(sql string) string {
if sql == "" || statement.dialect.URI().DBType == schemas.MYSQL ||
statement.dialect.URI().DBType == schemas.SQLITE {
return sql
}
return statement.dialect.Quoter().Replace(sql)
}
func (statement *Statement) SetContextCache(ctxCache contexts.ContextCache) {
statement.Context = ctxCache
}
// Init reset all the statement's fields
func (statement *Statement) Reset() {
statement.RefTable = nil
statement.Start = 0
statement.LimitN = nil
statement.OrderStr = ""
statement.UseCascade = true
statement.JoinStr = ""
statement.joinArgs = make([]interface{}, 0)
statement.GroupByStr = ""
statement.HavingStr = ""
statement.ColumnMap = columnMap{}
statement.OmitColumnMap = columnMap{}
statement.AltTableName = ""
statement.tableName = ""
statement.idParam = nil
statement.RawSQL = ""
statement.RawParams = make([]interface{}, 0)
statement.UseCache = true
statement.UseAutoTime = true
statement.NoAutoCondition = false
statement.IsDistinct = false
statement.IsForUpdate = false
statement.TableAlias = ""
statement.SelectStr = ""
statement.allUseBool = false
statement.useAllCols = false
statement.MustColumnMap = make(map[string]bool)
statement.NullableMap = make(map[string]bool)
statement.CheckVersion = true
statement.unscoped = false
statement.IncrColumns = exprParams{}
statement.DecrColumns = exprParams{}
statement.ExprColumns = exprParams{}
statement.cond = builder.NewCond()
statement.BufferSize = 0
statement.Context = nil
statement.LastError = nil
}
// NoAutoCondition if you do not want convert bean's field as query condition, then use this function
func (statement *Statement) SetNoAutoCondition(no ...bool) *Statement {
statement.NoAutoCondition = true
if len(no) > 0 {
statement.NoAutoCondition = no[0]
}
return statement
}
// Alias set the table alias
func (statement *Statement) Alias(alias string) *Statement {
statement.TableAlias = alias
return statement
}
// SQL adds raw sql statement
func (statement *Statement) SQL(query interface{}, args ...interface{}) *Statement {
switch query.(type) {
case (*builder.Builder):
var err error
statement.RawSQL, statement.RawParams, err = query.(*builder.Builder).ToSQL()
if err != nil {
statement.LastError = err
}
case string:
statement.RawSQL = query.(string)
statement.RawParams = args
default:
statement.LastError = ErrUnSupportedSQLType
}
return statement
}
// Where add Where statement
func (statement *Statement) Where(query interface{}, args ...interface{}) *Statement {
return statement.And(query, args...)
}
func (statement *Statement) quote(s string) string {
return statement.dialect.Quoter().Quote(s)
}
// And add Where & and statement
func (statement *Statement) And(query interface{}, args ...interface{}) *Statement {
switch query.(type) {
case string:
cond := builder.Expr(query.(string), args...)
statement.cond = statement.cond.And(cond)
case map[string]interface{}:
queryMap := query.(map[string]interface{})
newMap := make(map[string]interface{})
for k, v := range queryMap {
newMap[statement.quote(k)] = v
}
statement.cond = statement.cond.And(builder.Eq(newMap))
case builder.Cond:
cond := query.(builder.Cond)
statement.cond = statement.cond.And(cond)
for _, v := range args {
if vv, ok := v.(builder.Cond); ok {
statement.cond = statement.cond.And(vv)
}
}
default:
statement.LastError = ErrConditionType
}
return statement
}
// Or add Where & Or statement
func (statement *Statement) Or(query interface{}, args ...interface{}) *Statement {
switch query.(type) {
case string:
cond := builder.Expr(query.(string), args...)
statement.cond = statement.cond.Or(cond)
case map[string]interface{}:
cond := builder.Eq(query.(map[string]interface{}))
statement.cond = statement.cond.Or(cond)
case builder.Cond:
cond := query.(builder.Cond)
statement.cond = statement.cond.Or(cond)
for _, v := range args {
if vv, ok := v.(builder.Cond); ok {
statement.cond = statement.cond.Or(vv)
}
}
default:
// TODO: not support condition type
}
return statement
}
// In generate "Where column IN (?) " statement
func (statement *Statement) In(column string, args ...interface{}) *Statement {
in := builder.In(statement.quote(column), args...)
statement.cond = statement.cond.And(in)
return statement
}
// NotIn generate "Where column NOT IN (?) " statement
func (statement *Statement) NotIn(column string, args ...interface{}) *Statement {
notIn := builder.NotIn(statement.quote(column), args...)
statement.cond = statement.cond.And(notIn)
return statement
}
func (statement *Statement) SetRefValue(v reflect.Value) error {
var err error
statement.RefTable, err = statement.tagParser.ParseWithCache(reflect.Indirect(v))
if err != nil {
return err
}
statement.tableName = dialects.FullTableName(statement.dialect, statement.tagParser.GetTableMapper(), v, true)
return nil
}
func rValue(bean interface{}) reflect.Value {
return reflect.Indirect(reflect.ValueOf(bean))
}
func (statement *Statement) SetRefBean(bean interface{}) error {
var err error
statement.RefTable, err = statement.tagParser.ParseWithCache(rValue(bean))
if err != nil {
return err
}
statement.tableName = dialects.FullTableName(statement.dialect, statement.tagParser.GetTableMapper(), bean, true)
return nil
}
func (statement *Statement) needTableName() bool {
return len(statement.JoinStr) > 0
}
func (statement *Statement) colName(col *schemas.Column, tableName string) string {
if statement.needTableName() {
var nm = tableName
if len(statement.TableAlias) > 0 {
nm = statement.TableAlias
}
return statement.quote(nm) + "." + statement.quote(col.Name)
}
return statement.quote(col.Name)
}
// TableName return current tableName
func (statement *Statement) TableName() string {
if statement.AltTableName != "" {
return statement.AltTableName
}
return statement.tableName
}
// Incr Generate "Update ... Set column = column + arg" statement
func (statement *Statement) Incr(column string, arg ...interface{}) *Statement {
if len(arg) > 0 {
statement.IncrColumns.addParam(column, arg[0])
} else {
statement.IncrColumns.addParam(column, 1)
}
return statement
}
// Decr Generate "Update ... Set column = column - arg" statement
func (statement *Statement) Decr(column string, arg ...interface{}) *Statement {
if len(arg) > 0 {
statement.DecrColumns.addParam(column, arg[0])
} else {
statement.DecrColumns.addParam(column, 1)
}
return statement
}
// SetExpr Generate "Update ... Set column = {expression}" statement
func (statement *Statement) SetExpr(column string, expression interface{}) *Statement {
if e, ok := expression.(string); ok {
statement.ExprColumns.addParam(column, statement.dialect.Quoter().Replace(e))
} else {
statement.ExprColumns.addParam(column, expression)
}
return statement
}
// Distinct generates "DISTINCT col1, col2 " statement
func (statement *Statement) Distinct(columns ...string) *Statement {
statement.IsDistinct = true
statement.Cols(columns...)
return statement
}
// ForUpdate generates "SELECT ... FOR UPDATE" statement
func (statement *Statement) ForUpdate() *Statement {
statement.IsForUpdate = true
return statement
}
// Select replace select
func (statement *Statement) Select(str string) *Statement {
statement.SelectStr = statement.ReplaceQuote(str)
return statement
}
func col2NewCols(columns ...string) []string {
newColumns := make([]string, 0, len(columns))
for _, col := range columns {
col = strings.Replace(col, "`", "", -1)
col = strings.Replace(col, `"`, "", -1)
ccols := strings.Split(col, ",")
for _, c := range ccols {
newColumns = append(newColumns, strings.TrimSpace(c))
}
}
return newColumns
}
// Cols generate "col1, col2" statement
func (statement *Statement) Cols(columns ...string) *Statement {
cols := col2NewCols(columns...)
for _, nc := range cols {
statement.ColumnMap.Add(nc)
}
return statement
}
func (statement *Statement) ColumnStr() string {
return statement.dialect.Quoter().Join(statement.ColumnMap, ", ")
}
// AllCols update use only: update all columns
func (statement *Statement) AllCols() *Statement {
statement.useAllCols = true
return statement
}
// MustCols update use only: must update columns
func (statement *Statement) MustCols(columns ...string) *Statement {
newColumns := col2NewCols(columns...)
for _, nc := range newColumns {
statement.MustColumnMap[strings.ToLower(nc)] = true
}
return statement
}
// UseBool indicates that use bool fields as update contents and query contiditions
func (statement *Statement) UseBool(columns ...string) *Statement {
if len(columns) > 0 {
statement.MustCols(columns...)
} else {
statement.allUseBool = true
}
return statement
}
// Omit do not use the columns
func (statement *Statement) Omit(columns ...string) {
newColumns := col2NewCols(columns...)
for _, nc := range newColumns {
statement.OmitColumnMap = append(statement.OmitColumnMap, nc)
}
}
// Nullable Update use only: update columns to null when value is nullable and zero-value
func (statement *Statement) Nullable(columns ...string) {
newColumns := col2NewCols(columns...)
for _, nc := range newColumns {
statement.NullableMap[strings.ToLower(nc)] = true
}
}
// Top generate LIMIT limit statement
func (statement *Statement) Top(limit int) *Statement {
statement.Limit(limit)
return statement
}
// Limit generate LIMIT start, limit statement
func (statement *Statement) Limit(limit int, start ...int) *Statement {
statement.LimitN = &limit
if len(start) > 0 {
statement.Start = start[0]
}
return statement
}
// OrderBy generate "Order By order" statement
func (statement *Statement) OrderBy(order string) *Statement {
if len(statement.OrderStr) > 0 {
statement.OrderStr += ", "
}
statement.OrderStr += statement.ReplaceQuote(order)
return statement
}
// Desc generate `ORDER BY xx DESC`
func (statement *Statement) Desc(colNames ...string) *Statement {
var buf strings.Builder
if len(statement.OrderStr) > 0 {
fmt.Fprint(&buf, statement.OrderStr, ", ")
}
for i, col := range colNames {
if i > 0 {
fmt.Fprint(&buf, ", ")
}
statement.dialect.Quoter().QuoteTo(&buf, col)
fmt.Fprint(&buf, " DESC")
}
statement.OrderStr = buf.String()
return statement
}
// Asc provide asc order by query condition, the input parameters are columns.
func (statement *Statement) Asc(colNames ...string) *Statement {
var buf strings.Builder
if len(statement.OrderStr) > 0 {
fmt.Fprint(&buf, statement.OrderStr, ", ")
}
for i, col := range colNames {
if i > 0 {
fmt.Fprint(&buf, ", ")
}
statement.dialect.Quoter().QuoteTo(&buf, col)
fmt.Fprint(&buf, " ASC")
}
statement.OrderStr = buf.String()
return statement
}
func (statement *Statement) Conds() builder.Cond {
return statement.cond
}
// Table tempororily set table name, the parameter could be a string or a pointer of struct
func (statement *Statement) SetTable(tableNameOrBean interface{}) error {
v := rValue(tableNameOrBean)
t := v.Type()
if t.Kind() == reflect.Struct {
var err error
statement.RefTable, err = statement.tagParser.ParseWithCache(v)
if err != nil {
return err
}
}
statement.AltTableName = dialects.FullTableName(statement.dialect, statement.tagParser.GetTableMapper(), tableNameOrBean, true)
return nil
}
// Join The joinOP should be one of INNER, LEFT OUTER, CROSS etc - this will be prepended to JOIN
func (statement *Statement) Join(joinOP string, tablename interface{}, condition string, args ...interface{}) *Statement {
var buf strings.Builder
if len(statement.JoinStr) > 0 {
fmt.Fprintf(&buf, "%v %v JOIN ", statement.JoinStr, joinOP)
} else {
fmt.Fprintf(&buf, "%v JOIN ", joinOP)
}
switch tp := tablename.(type) {
case builder.Builder:
subSQL, subQueryArgs, err := tp.ToSQL()
if err != nil {
statement.LastError = err
return statement
}
fields := strings.Split(tp.TableName(), ".")
aliasName := statement.dialect.Quoter().Trim(fields[len(fields)-1])
aliasName = schemas.CommonQuoter.Trim(aliasName)
fmt.Fprintf(&buf, "(%s) %s ON %v", statement.ReplaceQuote(subSQL), aliasName, statement.ReplaceQuote(condition))
statement.joinArgs = append(statement.joinArgs, subQueryArgs...)
case *builder.Builder:
subSQL, subQueryArgs, err := tp.ToSQL()
if err != nil {
statement.LastError = err
return statement
}
fields := strings.Split(tp.TableName(), ".")
aliasName := statement.dialect.Quoter().Trim(fields[len(fields)-1])
aliasName = schemas.CommonQuoter.Trim(aliasName)
fmt.Fprintf(&buf, "(%s) %s ON %v", statement.ReplaceQuote(subSQL), aliasName, statement.ReplaceQuote(condition))
statement.joinArgs = append(statement.joinArgs, subQueryArgs...)
default:
tbName := dialects.FullTableName(statement.dialect, statement.tagParser.GetTableMapper(), tablename, true)
if !utils.IsSubQuery(tbName) {
var buf strings.Builder
statement.dialect.Quoter().QuoteTo(&buf, tbName)
tbName = buf.String()
}
fmt.Fprintf(&buf, "%s ON %v", tbName, statement.ReplaceQuote(condition))
}
statement.JoinStr = buf.String()
statement.joinArgs = append(statement.joinArgs, args...)
return statement
}
// tbName get some table's table name
func (statement *Statement) tbNameNoSchema(table *schemas.Table) string {
if len(statement.AltTableName) > 0 {
return statement.AltTableName
}
return table.Name
}
// GroupBy generate "Group By keys" statement
func (statement *Statement) GroupBy(keys string) *Statement {
statement.GroupByStr = statement.ReplaceQuote(keys)
return statement
}
// Having generate "Having conditions" statement
func (statement *Statement) Having(conditions string) *Statement {
statement.HavingStr = fmt.Sprintf("HAVING %v", statement.ReplaceQuote(conditions))
return statement
}
// Unscoped always disable struct tag "deleted"
func (statement *Statement) SetUnscoped() *Statement {
statement.unscoped = true
return statement
}
func (statement *Statement) GetUnscoped() bool {
return statement.unscoped
}
func (statement *Statement) genColumnStr() string {
if statement.RefTable == nil {
return ""
}
var buf strings.Builder
columns := statement.RefTable.Columns()
for _, col := range columns {
if statement.OmitColumnMap.Contain(col.Name) {
continue
}
if len(statement.ColumnMap) > 0 && !statement.ColumnMap.Contain(col.Name) {
continue
}
if col.MapType == schemas.ONLYTODB {
continue
}
if buf.Len() != 0 {
buf.WriteString(", ")
}
if statement.JoinStr != "" {
if statement.TableAlias != "" {
buf.WriteString(statement.TableAlias)
} else {
buf.WriteString(statement.TableName())
}
buf.WriteString(".")
}
statement.dialect.Quoter().QuoteTo(&buf, col.Name)
}
return buf.String()
}
func (statement *Statement) GenCreateTableSQL() []string {
statement.RefTable.StoreEngine = statement.StoreEngine
statement.RefTable.Charset = statement.Charset
s, _ := statement.dialect.CreateTableSQL(statement.RefTable, statement.TableName())
return s
}
func (statement *Statement) GenIndexSQL() []string {
var sqls []string
tbName := statement.TableName()
for _, index := range statement.RefTable.Indexes {
if index.Type == schemas.IndexType {
sql := statement.dialect.CreateIndexSQL(tbName, index)
sqls = append(sqls, sql)
}
}
return sqls
}
func uniqueName(tableName, uqeName string) string {
return fmt.Sprintf("UQE_%v_%v", tableName, uqeName)
}
func (statement *Statement) GenUniqueSQL() []string {
var sqls []string
tbName := statement.TableName()
for _, index := range statement.RefTable.Indexes {
if index.Type == schemas.UniqueType {
sql := statement.dialect.CreateIndexSQL(tbName, index)
sqls = append(sqls, sql)
}
}
return sqls
}
func (statement *Statement) GenDelIndexSQL() []string {
var sqls []string
tbName := statement.TableName()
idx := strings.Index(tbName, ".")
if idx > -1 {
tbName = tbName[idx+1:]
}
for _, index := range statement.RefTable.Indexes {
sqls = append(sqls, statement.dialect.DropIndexSQL(tbName, index))
}
return sqls
}
func (statement *Statement) buildConds2(table *schemas.Table, bean interface{},
includeVersion bool, includeUpdated bool, includeNil bool,
includeAutoIncr bool, allUseBool bool, useAllCols bool, unscoped bool,
mustColumnMap map[string]bool, tableName, aliasName string, addedTableName bool) (builder.Cond, error) {
var conds []builder.Cond
for _, col := range table.Columns() {
if !includeVersion && col.IsVersion {
continue
}
if !includeUpdated && col.IsUpdated {
continue
}
if !includeAutoIncr && col.IsAutoIncrement {
continue
}
if statement.dialect.URI().DBType == schemas.MSSQL && (col.SQLType.Name == schemas.Text ||
col.SQLType.IsBlob() || col.SQLType.Name == schemas.TimeStampz) {
continue
}
if col.SQLType.IsJson() {
continue
}
var colName string
if addedTableName {
var nm = tableName
if len(aliasName) > 0 {
nm = aliasName
}
colName = statement.quote(nm) + "." + statement.quote(col.Name)
} else {
colName = statement.quote(col.Name)
}
fieldValuePtr, err := col.ValueOf(bean)
if err != nil {
if !strings.Contains(err.Error(), "is not valid") {
//engine.logger.Warn(err)
}
continue
}
if col.IsDeleted && !unscoped { // tag "deleted" is enabled
conds = append(conds, statement.CondDeleted(col))
}
fieldValue := *fieldValuePtr
if fieldValue.Interface() == nil {
continue
}
fieldType := reflect.TypeOf(fieldValue.Interface())
requiredField := useAllCols
if b, ok := getFlagForColumn(mustColumnMap, col); ok {
if b {
requiredField = true
} else {
continue
}
}
if fieldType.Kind() == reflect.Ptr {
if fieldValue.IsNil() {
if includeNil {
conds = append(conds, builder.Eq{colName: nil})
}
continue
} else if !fieldValue.IsValid() {
continue
} else {
// dereference ptr type to instance type
fieldValue = fieldValue.Elem()
fieldType = reflect.TypeOf(fieldValue.Interface())
requiredField = true
}
}
var val interface{}
switch fieldType.Kind() {
case reflect.Bool:
if allUseBool || requiredField {
val = fieldValue.Interface()
} else {
// if a bool in a struct, it will not be as a condition because it default is false,
// please use Where() instead
continue
}
case reflect.String:
if !requiredField && fieldValue.String() == "" {
continue
}
// for MyString, should convert to string or panic
if fieldType.String() != reflect.String.String() {
val = fieldValue.String()
} else {
val = fieldValue.Interface()
}
case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64:
if !requiredField && fieldValue.Int() == 0 {
continue
}
val = fieldValue.Interface()
case reflect.Float32, reflect.Float64:
if !requiredField && fieldValue.Float() == 0.0 {
continue
}
val = fieldValue.Interface()
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
if !requiredField && fieldValue.Uint() == 0 {
continue
}
t := int64(fieldValue.Uint())
val = reflect.ValueOf(&t).Interface()
case reflect.Struct:
if fieldType.ConvertibleTo(schemas.TimeType) {
t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
if !requiredField && (t.IsZero() || !fieldValue.IsValid()) {
continue
}
val = dialects.FormatColumnTime(statement.dialect, statement.defaultTimeZone, col, t)
} else if _, ok := reflect.New(fieldType).Interface().(convert.Conversion); ok {
continue
} else if valNul, ok := fieldValue.Interface().(driver.Valuer); ok {
val, _ = valNul.Value()
if val == nil && !requiredField {
continue
}
} else {
if col.SQLType.IsJson() {
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = string(bytes)
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = bytes
}
} else {
table, err := statement.tagParser.ParseWithCache(fieldValue)
if err != nil {
val = fieldValue.Interface()
} else {
if len(table.PrimaryKeys) == 1 {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName)
// fix non-int pk issues
//if pkField.Int() != 0 {
if pkField.IsValid() && !utils.IsZero(pkField.Interface()) {
val = pkField.Interface()
} else {
continue
}
} else {
//TODO: how to handler?
return nil, fmt.Errorf("not supported %v as %v", fieldValue.Interface(), table.PrimaryKeys)
}
}
}
}
case reflect.Array:
continue
case reflect.Slice, reflect.Map:
if fieldValue == reflect.Zero(fieldType) {
continue
}
if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
continue
}
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = string(bytes)
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
if (fieldType.Kind() == reflect.Array || fieldType.Kind() == reflect.Slice) &&
fieldType.Elem().Kind() == reflect.Uint8 {
if fieldValue.Len() > 0 {
val = fieldValue.Bytes()
} else {
continue
}
} else {
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
val = bytes
}
} else {
continue
}
default:
val = fieldValue.Interface()
}
conds = append(conds, builder.Eq{colName: val})
}
return builder.And(conds...), nil
}
func (statement *Statement) BuildConds(table *schemas.Table, bean interface{}, includeVersion bool, includeUpdated bool, includeNil bool, includeAutoIncr bool, addedTableName bool) (builder.Cond, error) {
return statement.buildConds2(table, bean, includeVersion, includeUpdated, includeNil, includeAutoIncr, statement.allUseBool, statement.useAllCols,
statement.unscoped, statement.MustColumnMap, statement.TableName(), statement.TableAlias, addedTableName)
}
func (statement *Statement) mergeConds(bean interface{}) error {
if !statement.NoAutoCondition {
var addedTableName = (len(statement.JoinStr) > 0)
autoCond, err := statement.BuildConds(statement.RefTable, bean, true, true, false, true, addedTableName)
if err != nil {
return err
}
statement.cond = statement.cond.And(autoCond)
}
if err := statement.ProcessIDParam(); err != nil {
return err
}
return nil
}
func (statement *Statement) GenConds(bean interface{}) (string, []interface{}, error) {
if err := statement.mergeConds(bean); err != nil {
return "", nil, err
}
return statement.GenCondSQL(statement.cond)
}
func (statement *Statement) quoteColumnStr(columnStr string) string {
columns := strings.Split(columnStr, ",")
return statement.dialect.Quoter().Join(columns, ",")
}
func (statement *Statement) ConvertSQLOrArgs(sqlOrArgs ...interface{}) (string, []interface{}, error) {
sql, args, err := convertSQLOrArgs(sqlOrArgs...)
if err != nil {
return "", nil, err
}
return statement.ReplaceQuote(sql), args, nil
}
func convertSQLOrArgs(sqlOrArgs ...interface{}) (string, []interface{}, error) {
switch sqlOrArgs[0].(type) {
case string:
return sqlOrArgs[0].(string), sqlOrArgs[1:], nil
case *builder.Builder:
return sqlOrArgs[0].(*builder.Builder).ToSQL()
case builder.Builder:
bd := sqlOrArgs[0].(builder.Builder)
return bd.ToSQL()
}
return "", nil, ErrUnSupportedType
}
func (statement *Statement) joinColumns(cols []*schemas.Column, includeTableName bool) string {
var colnames = make([]string, len(cols))
for i, col := range cols {
if includeTableName {
colnames[i] = statement.quote(statement.TableName()) +
"." + statement.quote(col.Name)
} else {
colnames[i] = statement.quote(col.Name)
}
}
return strings.Join(colnames, ", ")
}
// CondDeleted returns the conditions whether a record is soft deleted.
func (statement *Statement) CondDeleted(col *schemas.Column) builder.Cond {
var colName = col.Name
if statement.JoinStr != "" {
var prefix string
if statement.TableAlias != "" {
prefix = statement.TableAlias
} else {
prefix = statement.TableName()
}
colName = statement.quote(prefix) + "." + statement.quote(col.Name)
}
var cond = builder.NewCond()
if col.SQLType.IsNumeric() {
cond = builder.Eq{colName: 0}
} else {
// FIXME: mssql: The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value.
if statement.dialect.URI().DBType != schemas.MSSQL {
cond = builder.Eq{colName: utils.ZeroTime1}
}
}
if col.Nullable {
cond = cond.Or(builder.IsNull{colName})
}
return cond
}

View file

@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package xorm package statements
import ( import (
"fmt" "fmt"
@ -11,7 +11,7 @@ import (
"time" "time"
"xorm.io/builder" "xorm.io/builder"
"xorm.io/core" "xorm.io/xorm/schemas"
) )
func quoteNeeded(a interface{}) bool { func quoteNeeded(a interface{}) bool {
@ -77,10 +77,10 @@ func convertArg(arg interface{}, convertFunc func(string) string) string {
const insertSelectPlaceHolder = true const insertSelectPlaceHolder = true
func (statement *Statement) writeArg(w *builder.BytesWriter, arg interface{}) error { func (statement *Statement) WriteArg(w *builder.BytesWriter, arg interface{}) error {
switch argv := arg.(type) { switch argv := arg.(type) {
case bool: case bool:
if statement.Engine.dialect.DBType() == core.MSSQL { if statement.dialect.URI().DBType == schemas.MSSQL {
if argv { if argv {
if _, err := w.WriteString("1"); err != nil { if _, err := w.WriteString("1"); err != nil {
return err return err
@ -119,7 +119,7 @@ func (statement *Statement) writeArg(w *builder.BytesWriter, arg interface{}) er
w.Append(arg) w.Append(arg)
} else { } else {
var convertFunc = convertStringSingleQuote var convertFunc = convertStringSingleQuote
if statement.Engine.dialect.DBType() == core.MYSQL { if statement.dialect.URI().DBType == schemas.MYSQL {
convertFunc = convertString convertFunc = convertString
} }
if _, err := w.WriteString(convertArg(arg, convertFunc)); err != nil { if _, err := w.WriteString(convertArg(arg, convertFunc)); err != nil {
@ -130,9 +130,9 @@ func (statement *Statement) writeArg(w *builder.BytesWriter, arg interface{}) er
return nil return nil
} }
func (statement *Statement) writeArgs(w *builder.BytesWriter, args []interface{}) error { func (statement *Statement) WriteArgs(w *builder.BytesWriter, args []interface{}) error {
for i, arg := range args { for i, arg := range args {
if err := statement.writeArg(w, arg); err != nil { if err := statement.WriteArg(w, arg); err != nil {
return err return err
} }
@ -144,27 +144,3 @@ func (statement *Statement) writeArgs(w *builder.BytesWriter, args []interface{}
} }
return nil return nil
} }
func writeStrings(w *builder.BytesWriter, cols []string, leftQuote, rightQuote string) error {
for i, colName := range cols {
if len(leftQuote) > 0 && colName[0] != '`' {
if _, err := w.WriteString(leftQuote); err != nil {
return err
}
}
if _, err := w.WriteString(colName); err != nil {
return err
}
if len(rightQuote) > 0 && colName[len(colName)-1] != '`' {
if _, err := w.WriteString(rightQuote); err != nil {
return err
}
}
if i+1 != len(cols) {
if _, err := w.WriteString(","); err != nil {
return err
}
}
}
return nil
}

295
vendor/xorm.io/xorm/internal/statements/update.go generated vendored Normal file
View file

@ -0,0 +1,295 @@
// Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"database/sql/driver"
"errors"
"fmt"
"reflect"
"time"
"xorm.io/xorm/convert"
"xorm.io/xorm/dialects"
"xorm.io/xorm/internal/json"
"xorm.io/xorm/internal/utils"
"xorm.io/xorm/schemas"
)
func (statement *Statement) ifAddColUpdate(col *schemas.Column, includeVersion, includeUpdated, includeNil,
includeAutoIncr, update bool) (bool, error) {
columnMap := statement.ColumnMap
omitColumnMap := statement.OmitColumnMap
unscoped := statement.unscoped
if !includeVersion && col.IsVersion {
return false, nil
}
if col.IsCreated && !columnMap.Contain(col.Name) {
return false, nil
}
if !includeUpdated && col.IsUpdated {
return false, nil
}
if !includeAutoIncr && col.IsAutoIncrement {
return false, nil
}
if col.IsDeleted && !unscoped {
return false, nil
}
if omitColumnMap.Contain(col.Name) {
return false, nil
}
if len(columnMap) > 0 && !columnMap.Contain(col.Name) {
return false, nil
}
if col.MapType == schemas.ONLYFROMDB {
return false, nil
}
if statement.IncrColumns.IsColExist(col.Name) {
return false, nil
} else if statement.DecrColumns.IsColExist(col.Name) {
return false, nil
} else if statement.ExprColumns.IsColExist(col.Name) {
return false, nil
}
return true, nil
}
// BuildUpdates auto generating update columnes and values according a struct
func (statement *Statement) BuildUpdates(tableValue reflect.Value,
includeVersion, includeUpdated, includeNil,
includeAutoIncr, update bool) ([]string, []interface{}, error) {
table := statement.RefTable
allUseBool := statement.allUseBool
useAllCols := statement.useAllCols
mustColumnMap := statement.MustColumnMap
nullableMap := statement.NullableMap
var colNames = make([]string, 0)
var args = make([]interface{}, 0)
for _, col := range table.Columns() {
ok, err := statement.ifAddColUpdate(col, includeVersion, includeUpdated, includeNil,
includeAutoIncr, update)
if err != nil {
return nil, nil, err
}
if !ok {
continue
}
fieldValuePtr, err := col.ValueOfV(&tableValue)
if err != nil {
return nil, nil, err
}
fieldValue := *fieldValuePtr
fieldType := reflect.TypeOf(fieldValue.Interface())
if fieldType == nil {
continue
}
requiredField := useAllCols
includeNil := useAllCols
if b, ok := getFlagForColumn(mustColumnMap, col); ok {
if b {
requiredField = true
} else {
continue
}
}
// !evalphobia! set fieldValue as nil when column is nullable and zero-value
if b, ok := getFlagForColumn(nullableMap, col); ok {
if b && col.Nullable && utils.IsZero(fieldValue.Interface()) {
var nilValue *int
fieldValue = reflect.ValueOf(nilValue)
fieldType = reflect.TypeOf(fieldValue.Interface())
includeNil = true
}
}
var val interface{}
if fieldValue.CanAddr() {
if structConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {
data, err := structConvert.ToDB()
if err != nil {
return nil, nil, err
}
val = data
goto APPEND
}
}
if structConvert, ok := fieldValue.Interface().(convert.Conversion); ok {
data, err := structConvert.ToDB()
if err != nil {
return nil, nil, err
}
val = data
goto APPEND
}
if fieldType.Kind() == reflect.Ptr {
if fieldValue.IsNil() {
if includeNil {
args = append(args, nil)
colNames = append(colNames, fmt.Sprintf("%v=?", statement.quote(col.Name)))
}
continue
} else if !fieldValue.IsValid() {
continue
} else {
// dereference ptr type to instance type
fieldValue = fieldValue.Elem()
fieldType = reflect.TypeOf(fieldValue.Interface())
requiredField = true
}
}
switch fieldType.Kind() {
case reflect.Bool:
if allUseBool || requiredField {
val = fieldValue.Interface()
} else {
// if a bool in a struct, it will not be as a condition because it default is false,
// please use Where() instead
continue
}
case reflect.String:
if !requiredField && fieldValue.String() == "" {
continue
}
// for MyString, should convert to string or panic
if fieldType.String() != reflect.String.String() {
val = fieldValue.String()
} else {
val = fieldValue.Interface()
}
case reflect.Int8, reflect.Int16, reflect.Int, reflect.Int32, reflect.Int64:
if !requiredField && fieldValue.Int() == 0 {
continue
}
val = fieldValue.Interface()
case reflect.Float32, reflect.Float64:
if !requiredField && fieldValue.Float() == 0.0 {
continue
}
val = fieldValue.Interface()
case reflect.Uint8, reflect.Uint16, reflect.Uint, reflect.Uint32, reflect.Uint64:
if !requiredField && fieldValue.Uint() == 0 {
continue
}
t := int64(fieldValue.Uint())
val = reflect.ValueOf(&t).Interface()
case reflect.Struct:
if fieldType.ConvertibleTo(schemas.TimeType) {
t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
if !requiredField && (t.IsZero() || !fieldValue.IsValid()) {
continue
}
val = dialects.FormatColumnTime(statement.dialect, statement.defaultTimeZone, col, t)
} else if nulType, ok := fieldValue.Interface().(driver.Valuer); ok {
val, _ = nulType.Value()
if val == nil && !requiredField {
continue
}
} else {
if !col.SQLType.IsJson() {
table, err := statement.tagParser.ParseWithCache(fieldValue)
if err != nil {
val = fieldValue.Interface()
} else {
if len(table.PrimaryKeys) == 1 {
pkField := reflect.Indirect(fieldValue).FieldByName(table.PKColumns()[0].FieldName)
// fix non-int pk issues
if pkField.IsValid() && (!requiredField && !utils.IsZero(pkField.Interface())) {
val = pkField.Interface()
} else {
continue
}
} else {
return nil, nil, errors.New("Not supported multiple primary keys")
}
}
} else {
// Blank struct could not be as update data
if requiredField || !utils.IsStructZero(fieldValue) {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, nil, fmt.Errorf("mashal %v failed", fieldValue.Interface())
}
if col.SQLType.IsText() {
val = string(bytes)
} else if col.SQLType.IsBlob() {
val = bytes
}
} else {
continue
}
}
}
case reflect.Array, reflect.Slice, reflect.Map:
if !requiredField {
if fieldValue == reflect.Zero(fieldType) {
continue
}
if fieldType.Kind() == reflect.Array {
if utils.IsArrayZero(fieldValue) {
continue
}
} else if fieldValue.IsNil() || !fieldValue.IsValid() || fieldValue.Len() == 0 {
continue
}
}
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, nil, err
}
val = string(bytes)
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
if fieldType.Kind() == reflect.Slice &&
fieldType.Elem().Kind() == reflect.Uint8 {
if fieldValue.Len() > 0 {
val = fieldValue.Bytes()
} else {
continue
}
} else if fieldType.Kind() == reflect.Array &&
fieldType.Elem().Kind() == reflect.Uint8 {
val = fieldValue.Slice(0, 0).Interface()
} else {
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, nil, err
}
val = bytes
}
} else {
continue
}
default:
val = fieldValue.Interface()
}
APPEND:
args = append(args, val)
colNames = append(colNames, fmt.Sprintf("%v = ?", statement.quote(col.Name)))
}
return colNames, args, nil
}

154
vendor/xorm.io/xorm/internal/statements/values.go generated vendored Normal file
View file

@ -0,0 +1,154 @@
// Copyright 2017 The Xorm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package statements
import (
"database/sql"
"database/sql/driver"
"fmt"
"reflect"
"time"
"xorm.io/xorm/convert"
"xorm.io/xorm/dialects"
"xorm.io/xorm/internal/json"
"xorm.io/xorm/schemas"
)
var (
nullFloatType = reflect.TypeOf(sql.NullFloat64{})
)
// Value2Interface convert a field value of a struct to interface for puting into database
func (statement *Statement) Value2Interface(col *schemas.Column, fieldValue reflect.Value) (interface{}, error) {
if fieldValue.CanAddr() {
if fieldConvert, ok := fieldValue.Addr().Interface().(convert.Conversion); ok {
data, err := fieldConvert.ToDB()
if err != nil {
return nil, err
}
if col.SQLType.IsBlob() {
return data, nil
}
return string(data), nil
}
}
if fieldConvert, ok := fieldValue.Interface().(convert.Conversion); ok {
data, err := fieldConvert.ToDB()
if err != nil {
return nil, err
}
if col.SQLType.IsBlob() {
return data, nil
}
if nil == data {
return nil, nil
}
return string(data), nil
}
fieldType := fieldValue.Type()
k := fieldType.Kind()
if k == reflect.Ptr {
if fieldValue.IsNil() {
return nil, nil
} else if !fieldValue.IsValid() {
return nil, nil
} else {
// !nashtsai! deference pointer type to instance type
fieldValue = fieldValue.Elem()
fieldType = fieldValue.Type()
k = fieldType.Kind()
}
}
switch k {
case reflect.Bool:
return fieldValue.Bool(), nil
case reflect.String:
return fieldValue.String(), nil
case reflect.Struct:
if fieldType.ConvertibleTo(schemas.TimeType) {
t := fieldValue.Convert(schemas.TimeType).Interface().(time.Time)
tf := dialects.FormatColumnTime(statement.dialect, statement.defaultTimeZone, col, t)
return tf, nil
} else if fieldType.ConvertibleTo(nullFloatType) {
t := fieldValue.Convert(nullFloatType).Interface().(sql.NullFloat64)
if !t.Valid {
return nil, nil
}
return t.Float64, nil
}
if !col.SQLType.IsJson() {
// !<winxxp>! 增加支持driver.Valuer接口的结构如sql.NullString
if v, ok := fieldValue.Interface().(driver.Valuer); ok {
return v.Value()
}
fieldTable, err := statement.tagParser.ParseWithCache(fieldValue)
if err != nil {
return nil, err
}
if len(fieldTable.PrimaryKeys) == 1 {
pkField := reflect.Indirect(fieldValue).FieldByName(fieldTable.PKColumns()[0].FieldName)
return pkField.Interface(), nil
}
return nil, fmt.Errorf("no primary key for col %v", col.Name)
}
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
return string(bytes), nil
} else if col.SQLType.IsBlob() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
return bytes, nil
}
return nil, fmt.Errorf("Unsupported type %v", fieldValue.Type())
case reflect.Complex64, reflect.Complex128:
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
return string(bytes), nil
case reflect.Array, reflect.Slice, reflect.Map:
if !fieldValue.IsValid() {
return fieldValue.Interface(), nil
}
if col.SQLType.IsText() {
bytes, err := json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
return string(bytes), nil
} else if col.SQLType.IsBlob() {
var bytes []byte
var err error
if (k == reflect.Slice) &&
(fieldValue.Type().Elem().Kind() == reflect.Uint8) {
bytes = fieldValue.Bytes()
} else {
bytes, err = json.DefaultJSONHandler.Marshal(fieldValue.Interface())
if err != nil {
return nil, err
}
}
return bytes, nil
}
return nil, ErrUnSupportedType
case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint:
return int64(fieldValue.Uint()), nil
default:
return fieldValue.Interface(), nil
}
}

Some files were not shown because too many files have changed in this diff Show more