Browse Source

Added test environment for mssql (#4282)

* Added test environment for m$sql

* Added template for test environment for m$sql

* Fix password

* Fix password (again)

* Fix password (again again)

* Fix db

* Ci trigger (Looking at you drone....)

* Ci trigger (Looking at you drone....)

* Ci trigger (Looking at you drone....)

* Ci trigger (Looking at you drone....)

* Create master database for mssql integration tests

Signed-off-by: Jonas Franz <info@jonasfranz.software>

* Create database only if master do not exist

Signed-off-by: Jonas Franz <info@jonasfranz.software>

* Fix mssql integration tests by using custom database "gitea"

Signed-off-by: Jonas Franz <info@jonasfranz.software>

* Moved defer

* bump xorm

* updated xorm

* Fixed build
tags/v1.7.0-dev
kolaente 5 years ago
parent
commit
6db7dbd333

+ 23
- 0
.drone.yml View File

when: when:
event: [ push, tag, pull_request ] event: [ push, tag, pull_request ]


test-mssql:
image: golang:1.10
pull: true
group: test
environment:
TAGS: bindata
TEST_LDAP: "1"
commands:
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
- apt-get install -y git-lfs
- make test-mssql
when:
event: [ push, tag, pull_request ]

generate-coverage: generate-coverage:
image: golang:1.11 image: golang:1.11
pull: true pull: true
when: when:
event: [ push, tag, pull_request ] event: [ push, tag, pull_request ]


mssql:
image: microsoft/mssql-server-linux:latest
environment:
- ACCEPT_EULA=Y
- SA_PASSWORD=MwantsaSecurePassword1
- MSSQL_PID=Standard
when:
event: [ push, tag, pull_request ]

ldap: ldap:
image: gitea/test-openldap:latest image: gitea/test-openldap:latest
when: when:

+ 3
- 0
.gitignore View File

/integrations/gitea-integration-mysql /integrations/gitea-integration-mysql
/integrations/gitea-integration-pgsql /integrations/gitea-integration-pgsql
/integrations/gitea-integration-sqlite /integrations/gitea-integration-sqlite
/integrations/gitea-integration-mssql
/integrations/indexers-mysql /integrations/indexers-mysql
/integrations/indexers-pgsql /integrations/indexers-pgsql
/integrations/indexers-sqlite /integrations/indexers-sqlite
/integrations/indexers-mssql
/integrations/mysql.ini /integrations/mysql.ini
/integrations/pgsql.ini /integrations/pgsql.ini
/integrations/mssql.ini
/node_modules /node_modules





+ 2
- 2
Gopkg.lock View File

version = "v0.6.0" version = "v0.6.0"


[[projects]] [[projects]]
digest = "1:22a1ac7f654095f6817076eb975368bab5481e42554d0121ea37e28a86a3f83d"
digest = "1:931a62a1aacc37a5e4c309a111642ec4da47b4dc453cd4ba5481b12eedb04a5d"
name = "github.com/go-xorm/xorm" name = "github.com/go-xorm/xorm"
packages = ["."] packages = ["."]
pruneopts = "NUT" pruneopts = "NUT"
revision = "ad69f7d8f0861a29438154bb0a20b60501298480"
revision = "401f4ee8ff8cbc40a4754cb12192fbe4f02f3979"


[[projects]] [[projects]]
branch = "master" branch = "master"

+ 1
- 2
Gopkg.toml View File



[[override]] [[override]]
name = "github.com/go-xorm/xorm" name = "github.com/go-xorm/xorm"
#version = "0.6.5"
revision = "ad69f7d8f0861a29438154bb0a20b60501298480"
revision = "401f4ee8ff8cbc40a4754cb12192fbe4f02f3979"


[[override]] [[override]]
name = "github.com/go-sql-driver/mysql" name = "github.com/go-sql-driver/mysql"

+ 16
- 3
Makefile View File

TEST_PGSQL_DBNAME ?= testgitea TEST_PGSQL_DBNAME ?= testgitea
TEST_PGSQL_USERNAME ?= postgres TEST_PGSQL_USERNAME ?= postgres
TEST_PGSQL_PASSWORD ?= postgres TEST_PGSQL_PASSWORD ?= postgres
TEST_MSSQL_HOST ?= mssql:1433
TEST_MSSQL_DBNAME ?= gitea
TEST_MSSQL_USERNAME ?= sa
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1


ifeq ($(OS), Windows_NT) ifeq ($(OS), Windows_NT)
EXECUTABLE := gitea.exe EXECUTABLE := gitea.exe
$(GO) clean -i ./... $(GO) clean -i ./...
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) \ rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) \
integrations*.test \ integrations*.test \
integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-sqlite/ \
integrations/indexers-mysql/ integrations/indexers-pgsql integrations/indexers-sqlite \
integrations/mysql.ini integrations/pgsql.ini
integrations/gitea-integration-pgsql/ integrations/gitea-integration-mysql/ integrations/gitea-integration-sqlite/ integrations/gitea-integration-mssql/ \
integrations/indexers-mysql/ integrations/indexers-pgsql integrations/indexers-sqlite integrations/indexers-mssql \
integrations/mysql.ini integrations/pgsql.ini integrations/mssql.ini


.PHONY: fmt .PHONY: fmt
fmt: fmt:
-e 's|{{TEST_PGSQL_USERNAME}}|${TEST_PGSQL_USERNAME}|g' \ -e 's|{{TEST_PGSQL_USERNAME}}|${TEST_PGSQL_USERNAME}|g' \
-e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \ -e 's|{{TEST_PGSQL_PASSWORD}}|${TEST_PGSQL_PASSWORD}|g' \
integrations/pgsql.ini.tmpl > integrations/pgsql.ini integrations/pgsql.ini.tmpl > integrations/pgsql.ini
sed -e 's|{{TEST_MSSQL_HOST}}|${TEST_MSSQL_HOST}|g' \
-e 's|{{TEST_MSSQL_DBNAME}}|${TEST_MSSQL_DBNAME}|g' \
-e 's|{{TEST_MSSQL_USERNAME}}|${TEST_MSSQL_USERNAME}|g' \
-e 's|{{TEST_MSSQL_PASSWORD}}|${TEST_MSSQL_PASSWORD}|g' \
integrations/mssql.ini.tmpl > integrations/mssql.ini


.PHONY: test-mysql .PHONY: test-mysql
test-mysql: integrations.test generate-ini test-mysql: integrations.test generate-ini
test-pgsql: integrations.test generate-ini test-pgsql: integrations.test generate-ini
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.test GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.test


.PHONY: test-mssql
test-mssql: integrations.test generate-ini
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.test

.PHONY: bench-sqlite .PHONY: bench-sqlite
bench-sqlite: integrations.sqlite.test bench-sqlite: integrations.sqlite.test
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench . GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .

+ 13
- 0
integrations/integration_test.go View File

helper = &testfixtures.PostgreSQL{} helper = &testfixtures.PostgreSQL{}
} else if setting.UseSQLite3 { } else if setting.UseSQLite3 {
helper = &testfixtures.SQLite{} helper = &testfixtures.SQLite{}
} else if setting.UseMSSQL {
helper = &testfixtures.SQLServer{}
} else { } else {
fmt.Println("Unsupported RDBMS for integration tests") fmt.Println("Unsupported RDBMS for integration tests")
os.Exit(1) os.Exit(1)
if _, err = db.Exec("CREATE DATABASE testgitea"); err != nil { if _, err = db.Exec("CREATE DATABASE testgitea"); err != nil {
log.Fatalf("db.Exec: %v", err) log.Fatalf("db.Exec: %v", err)
} }
case setting.UseMSSQL:
host, port := models.ParseMSSQLHostPort(models.DbCfg.Host)
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
host, port, "master", models.DbCfg.User, models.DbCfg.Passwd))
if err != nil {
log.Fatalf("sql.Open: %v", err)
}
if _, err := db.Exec("If(db_id(N'gitea') IS NULL) BEGIN CREATE DATABASE gitea; END;"); err != nil {
log.Fatalf("db.Exec: %v", err)
}
defer db.Close()
} }
routers.GlobalInit() routers.GlobalInit()
} }

+ 72
- 0
integrations/mssql.ini.tmpl View File

APP_NAME = Gitea: Git with a cup of tea
RUN_MODE = prod

[database]
DB_TYPE = mssql
HOST = {{TEST_MSSQL_HOST}}
NAME = {{TEST_MSSQL_DBNAME}}
USER = {{TEST_MSSQL_USERNAME}}
PASSWD = {{TEST_MSSQL_PASSWORD}}
SSL_MODE = disable

[indexer]
ISSUE_INDEXER_PATH = integrations/indexers-mssql/issues.bleve
REPO_INDEXER_ENABLED = true
REPO_INDEXER_PATH = integrations/indexers-mssql/repos.bleve

[repository]
ROOT = integrations/gitea-integration-mssql/gitea-repositories

[repository.local]
LOCAL_COPY_PATH = tmp/local-repo-mssql
LOCAL_WIKI_PATH = tmp/local-wiki-mssql

[server]
SSH_DOMAIN = localhost
HTTP_PORT = 3003
ROOT_URL = http://localhost:3003/
DISABLE_SSH = false
SSH_LISTEN_HOST = localhost
SSH_PORT = 2201
START_SSH_SERVER = true
LFS_START_SERVER = true
LFS_CONTENT_PATH = data/lfs-mssql
OFFLINE_MODE = false
LFS_JWT_SECRET = Tv_MjmZuHqpIY6GFl12ebgkRAMt4RlWt0v4EHKSXO0w
APP_DATA_PATH = integrations/gitea-integration-mssql/data

[mailer]
ENABLED = false

[service]
REGISTER_EMAIL_CONFIRM = false
ENABLE_NOTIFY_MAIL = false
DISABLE_REGISTRATION = false
ENABLE_CAPTCHA = false
REQUIRE_SIGNIN_VIEW = false
DEFAULT_KEEP_EMAIL_PRIVATE = false
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
NO_REPLY_ADDRESS = noreply.example.org

[picture]
DISABLE_GRAVATAR = false
ENABLE_FEDERATED_AVATAR = false

[session]
PROVIDER = file
PROVIDER_CONFIG = data/sessions-mssql

[log]
MODE = console,file
ROOT_PATH = mssql-log

[log.console]
LEVEL = Warn

[log.file]
LEVEL = Debug

[security]
INSTALL_LOCK = true
SECRET_KEY = 9pCviYTWSb
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTU1NTE2MTh9.hhSVGOANkaKk3vfCd2jDOIww4pUk0xtg9JRde5UogyQ

+ 4
- 3
models/models.go View File

Count(...interface{}) (int64, error) Count(...interface{}) (int64, error)
Decr(column string, arg ...interface{}) *xorm.Session Decr(column string, arg ...interface{}) *xorm.Session
Delete(interface{}) (int64, error) Delete(interface{}) (int64, error)
Exec(string, ...interface{}) (sql.Result, error)
Exec(...interface{}) (sql.Result, error)
Find(interface{}, ...interface{}) error Find(interface{}, ...interface{}) error
Get(interface{}) (bool, error) Get(interface{}) (bool, error)
ID(interface{}) *xorm.Session ID(interface{}) *xorm.Session
return return
} }


func parseMSSQLHostPort(info string) (string, string) {
// ParseMSSQLHostPort splits the host into host and port
func ParseMSSQLHostPort(info string) (string, string) {
host, port := "127.0.0.1", "1433" host, port := "127.0.0.1", "1433"
if strings.Contains(info, ":") { if strings.Contains(info, ":") {
host = strings.Split(info, ":")[0] host = strings.Split(info, ":")[0]
case "postgres": case "postgres":
connStr = getPostgreSQLConnectionString(DbCfg.Host, DbCfg.User, DbCfg.Passwd, DbCfg.Name, Param, DbCfg.SSLMode) connStr = getPostgreSQLConnectionString(DbCfg.Host, DbCfg.User, DbCfg.Passwd, DbCfg.Name, Param, DbCfg.SSLMode)
case "mssql": case "mssql":
host, port := parseMSSQLHostPort(DbCfg.Host)
host, port := ParseMSSQLHostPort(DbCfg.Host)
connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, DbCfg.Name, DbCfg.User, DbCfg.Passwd) connStr = fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;", host, port, DbCfg.Name, DbCfg.User, DbCfg.Passwd)
case "sqlite3": case "sqlite3":
if !EnableSQLite3 { if !EnableSQLite3 {

+ 30
- 0
vendor/github.com/go-xorm/xorm/context_cache.go View File

// 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

// ContextCache is the interface that operates the cache data.
type ContextCache interface {
// Put puts value into cache with key.
Put(key string, val interface{})
// Get gets cached value by given key.
Get(key string) interface{}
}

type memoryContextCache map[string]interface{}

// NewMemoryContextCache return memoryContextCache
func NewMemoryContextCache() memoryContextCache {
return make(map[string]interface{})
}

// Put puts value into cache with key.
func (m memoryContextCache) Put(key string, val interface{}) {
m[key] = val
}

// Get gets cached value by given key.
func (m memoryContextCache) Get(key string) interface{} {
return m[key]
}

+ 1
- 1
vendor/github.com/go-xorm/xorm/dialect_mssql.go View File

res = core.Bit res = core.Bit
if strings.EqualFold(c.Default, "true") { if strings.EqualFold(c.Default, "true") {
c.Default = "1" c.Default = "1"
} else {
} else if strings.EqualFold(c.Default, "false") {
c.Default = "0" c.Default = "0"
} }
case core.Serial: case core.Serial:

+ 4
- 1
vendor/github.com/go-xorm/xorm/dialect_mysql.go View File



if len(charset) == 0 { if len(charset) == 0 {
charset = db.URI().Charset charset = db.URI().Charset
} else if len(charset) > 0 {
}
if len(charset) != 0 {
sql += " DEFAULT CHARSET " + charset sql += " DEFAULT CHARSET " + charset
} }


if db.rowFormat != "" { if db.rowFormat != "" {
sql += " ROW_FORMAT=" + db.rowFormat sql += " ROW_FORMAT=" + db.rowFormat

+ 5
- 1
vendor/github.com/go-xorm/xorm/dialect_sqlite3.go View File

} }


func (db *sqlite3) DropIndexSql(tableName string, index *core.Index) string { func (db *sqlite3) DropIndexSql(tableName string, index *core.Index) string {
//var unique string
// var unique string
quote := db.Quote quote := db.Quote
idxName := index.Name idxName := index.Name


} }


func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) { func (p *sqlite3Driver) Parse(driverName, dataSourceName string) (*core.Uri, error) {
if strings.Contains(dataSourceName, "?") {
dataSourceName = dataSourceName[:strings.Index(dataSourceName, "?")]
}

return &core.Uri{DbType: core.SQLITE, DbName: dataSourceName}, nil return &core.Uri{DbType: core.SQLITE, DbName: dataSourceName}, nil
} }

+ 15
- 2
vendor/github.com/go-xorm/xorm/engine.go View File

return engine.dialect.QuoteStr() return engine.dialect.QuoteStr()
} }


func (engine *Engine) quoteColumns(columnStr string) string {
columns := strings.Split(columnStr, ",")
for i := 0; i < len(columns); i++ {
columns[i] = engine.Quote(strings.TrimSpace(columns[i]))
}
return strings.Join(columns, ",")
}

// Quote Use QuoteStr quote the string sql // Quote Use QuoteStr quote the string sql
func (engine *Engine) Quote(value string) string { func (engine *Engine) Quote(value string) string {
value = strings.TrimSpace(value) value = strings.TrimSpace(value)
return engine.dialect.AutoIncrStr() return engine.dialect.AutoIncrStr()
} }


// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
func (engine *Engine) SetConnMaxLifetime(d time.Duration) {
engine.db.SetConnMaxLifetime(d)
}

// SetMaxOpenConns is only available for go 1.2+ // SetMaxOpenConns is only available for go 1.2+
func (engine *Engine) SetMaxOpenConns(conns int) { func (engine *Engine) SetMaxOpenConns(conns int) {
engine.db.SetMaxOpenConns(conns) engine.db.SetMaxOpenConns(conns)
} }


// Exec raw sql // Exec raw sql
func (engine *Engine) Exec(sql string, args ...interface{}) (sql.Result, error) {
func (engine *Engine) Exec(sqlorArgs ...interface{}) (sql.Result, error) {
session := engine.NewSession() session := engine.NewSession()
defer session.Close() defer session.Close()
return session.Exec(sql, args...)
return session.Exec(sqlorArgs...)
} }


// Query a raw sql and return records as []map[string][]byte // Query a raw sql and return records as []map[string][]byte

+ 10
- 0
vendor/github.com/go-xorm/xorm/engine_group.go View File

package xorm package xorm


import ( import (
"time"

"github.com/go-xorm/core" "github.com/go-xorm/core"
) )


} }
} }


// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
func (eg *EngineGroup) SetConnMaxLifetime(d time.Duration) {
eg.Engine.SetConnMaxLifetime(d)
for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].SetConnMaxLifetime(d)
}
}

// SetDefaultCacher set the default cacher // SetDefaultCacher set the default cacher
func (eg *EngineGroup) SetDefaultCacher(cacher core.Cacher) { func (eg *EngineGroup) SetDefaultCacher(cacher core.Cacher) {
eg.Engine.SetDefaultCacher(cacher) eg.Engine.SetDefaultCacher(cacher)

+ 0
- 22
vendor/github.com/go-xorm/xorm/engine_maxlife.go View File

// 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.

// +build go1.6

package xorm

import "time"

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
func (engine *Engine) SetConnMaxLifetime(d time.Duration) {
engine.db.SetConnMaxLifetime(d)
}

// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
func (eg *EngineGroup) SetConnMaxLifetime(d time.Duration) {
eg.Engine.SetConnMaxLifetime(d)
for i := 0; i < len(eg.slaves); i++ {
eg.slaves[i].SetConnMaxLifetime(d)
}
}

+ 8
- 1
vendor/github.com/go-xorm/xorm/interface.go View File

Delete(interface{}) (int64, error) Delete(interface{}) (int64, error)
Distinct(columns ...string) *Session Distinct(columns ...string) *Session
DropIndexes(bean interface{}) error DropIndexes(bean interface{}) error
Exec(string, ...interface{}) (sql.Result, error)
Exec(sqlOrAgrs ...interface{}) (sql.Result, error)
Exist(bean ...interface{}) (bool, error) Exist(bean ...interface{}) (bool, error)
Find(interface{}, ...interface{}) error Find(interface{}, ...interface{}) error
FindAndCount(interface{}, ...interface{}) (int64, error) FindAndCount(interface{}, ...interface{}) (int64, error)


Before(func(interface{})) *Session Before(func(interface{})) *Session
Charset(charset string) *Session Charset(charset string) *Session
ClearCache(...interface{}) error
CreateTables(...interface{}) error CreateTables(...interface{}) error
DBMetas() ([]*core.Table, error) DBMetas() ([]*core.Table, error)
Dialect() core.Dialect Dialect() core.Dialect
GetTableMapper() core.IMapper GetTableMapper() core.IMapper
GetTZDatabase() *time.Location GetTZDatabase() *time.Location
GetTZLocation() *time.Location GetTZLocation() *time.Location
MapCacher(interface{}, core.Cacher) error
NewSession() *Session NewSession() *Session
NoAutoTime() *Session NoAutoTime() *Session
Quote(string) string Quote(string) string
SetCacher(string, core.Cacher) SetCacher(string, core.Cacher)
SetConnMaxLifetime(time.Duration)
SetDefaultCacher(core.Cacher) SetDefaultCacher(core.Cacher)
SetLogger(logger core.ILogger)
SetLogLevel(core.LogLevel) SetLogLevel(core.LogLevel)
SetMapper(core.IMapper) SetMapper(core.IMapper)
SetMaxOpenConns(int)
SetMaxIdleConns(int)
SetSchema(string) SetSchema(string)
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

+ 15
- 0
vendor/github.com/go-xorm/xorm/session.go View File

} }
} }


// ContextCache enable context cache or not
func (session *Session) ContextCache(context ContextCache) *Session {
session.statement.context = context
return session
}

// IsClosed returns if session is closed // IsClosed returns if session is closed
func (session *Session) IsClosed() bool { func (session *Session) IsClosed() bool {
return session.db == nil return session.db == nil
session.statement.Unscoped() session.statement.Unscoped()
return session return session
} }

func (session *Session) incrVersionFieldValue(fieldValue *reflect.Value) {
switch fieldValue.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
fieldValue.SetInt(fieldValue.Int() + 1)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
fieldValue.SetUint(fieldValue.Uint() + 1)
}
}

+ 1
- 1
vendor/github.com/go-xorm/xorm/session_delete.go View File

}) })
} }


if cacher := session.engine.getCacher(tableName); cacher != nil && session.statement.UseCache {
if cacher := session.engine.getCacher(tableNameNoQuote); cacher != nil && session.statement.UseCache {
session.cacheDelete(table, tableNameNoQuote, deleteSQL, argsForCache...) session.cacheDelete(table, tableNameNoQuote, deleteSQL, argsForCache...)
} }



+ 3
- 3
vendor/github.com/go-xorm/xorm/session_find.go View File

if session.statement.JoinStr == "" { if session.statement.JoinStr == "" {
if columnStr == "" { if columnStr == "" {
if session.statement.GroupByStr != "" { if session.statement.GroupByStr != "" {
columnStr = session.statement.Engine.Quote(strings.Replace(session.statement.GroupByStr, ",", session.engine.Quote(","), -1))
columnStr = session.engine.quoteColumns(session.statement.GroupByStr)
} else { } else {
columnStr = session.statement.genColumnStr() columnStr = session.statement.genColumnStr()
} }
} else { } else {
if columnStr == "" { if columnStr == "" {
if session.statement.GroupByStr != "" { if session.statement.GroupByStr != "" {
columnStr = session.statement.Engine.Quote(strings.Replace(session.statement.GroupByStr, ",", session.engine.Quote(","), -1))
columnStr = session.engine.quoteColumns(session.statement.GroupByStr)
} else { } else {
columnStr = "*" columnStr = "*"
} }
} }


if session.canCache() { if session.canCache() {
if cacher := session.engine.getCacher(table.Name); cacher != nil &&
if cacher := session.engine.getCacher(session.statement.TableName()); cacher != nil &&
!session.statement.IsDistinct && !session.statement.IsDistinct &&
!session.statement.unscoped { !session.statement.unscoped {
err = session.cacheFind(sliceElementType, sqlStr, rowsSlicePtr, args...) err = session.cacheFind(sliceElementType, sqlStr, rowsSlicePtr, args...)

+ 27
- 2
vendor/github.com/go-xorm/xorm/session_get.go View File

import ( import (
"database/sql" "database/sql"
"errors" "errors"
"fmt"
"reflect" "reflect"
"strconv" "strconv"


table := session.statement.RefTable table := session.statement.RefTable


if session.canCache() && beanValue.Elem().Kind() == reflect.Struct { if session.canCache() && beanValue.Elem().Kind() == reflect.Struct {
if cacher := session.engine.getCacher(table.Name); cacher != nil &&
if cacher := session.engine.getCacher(session.statement.TableName()); cacher != nil &&
!session.statement.unscoped { !session.statement.unscoped {
has, err := session.cacheGet(bean, sqlStr, args...) has, err := session.cacheGet(bean, sqlStr, args...)
if err != ErrCacheFailed { if err != ErrCacheFailed {
} }
} }


return session.nocacheGet(beanValue.Elem().Kind(), table, bean, sqlStr, args...)
context := session.statement.context
if context != nil {
res := context.Get(fmt.Sprintf("%v-%v", sqlStr, args))
if res != nil {
structValue := reflect.Indirect(reflect.ValueOf(bean))
structValue.Set(reflect.Indirect(reflect.ValueOf(res)))
session.lastSQL = ""
session.lastSQLArgs = nil
return true, nil
}
}

has, err := session.nocacheGet(beanValue.Elem().Kind(), table, bean, sqlStr, args...)
if err != nil || !has {
return has, err
}

if context != nil {
context.Put(fmt.Sprintf("%v-%v", sqlStr, args), bean)
}

return true, nil
} }


func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bean interface{}, sqlStr string, args ...interface{}) (bool, error) { func (session *Session) nocacheGet(beanKind reflect.Kind, table *core.Table, bean interface{}, sqlStr string, args ...interface{}) (bool, error) {
defer rows.Close() defer rows.Close()


if !rows.Next() { if !rows.Next() {
if rows.Err() != nil {
return false, rows.Err()
}
return false, nil return false, nil
} }



+ 3
- 3
vendor/github.com/go-xorm/xorm/session_insert.go View File

if err != nil { if err != nil {
session.engine.logger.Error(err) session.engine.logger.Error(err)
} else if verValue.IsValid() && verValue.CanSet() { } else if verValue.IsValid() && verValue.CanSet() {
verValue.SetInt(1)
session.incrVersionFieldValue(verValue)
} }
} }


if err != nil { if err != nil {
session.engine.logger.Error(err) session.engine.logger.Error(err)
} else if verValue.IsValid() && verValue.CanSet() { } else if verValue.IsValid() && verValue.CanSet() {
verValue.SetInt(1)
session.incrVersionFieldValue(verValue)
} }
} }


if err != nil { if err != nil {
session.engine.logger.Error(err) session.engine.logger.Error(err)
} else if verValue.IsValid() && verValue.CanSet() { } else if verValue.IsValid() && verValue.CanSet() {
verValue.SetInt(1)
session.incrVersionFieldValue(verValue)
} }
} }



+ 67
- 13
vendor/github.com/go-xorm/xorm/session_query.go View File



func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interface{}, error) { func (session *Session) genQuerySQL(sqlorArgs ...interface{}) (string, []interface{}, error) {
if len(sqlorArgs) > 0 { if len(sqlorArgs) > 0 {
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()
default:
return "", nil, ErrUnSupportedType
}
return convertSQLOrArgs(sqlorArgs...)
} }


if session.statement.RawSQL != "" { if session.statement.RawSQL != "" {
if session.statement.JoinStr == "" { if session.statement.JoinStr == "" {
if columnStr == "" { if columnStr == "" {
if session.statement.GroupByStr != "" { if session.statement.GroupByStr != "" {
columnStr = session.statement.Engine.Quote(strings.Replace(session.statement.GroupByStr, ",", session.engine.Quote(","), -1))
columnStr = session.engine.quoteColumns(session.statement.GroupByStr)
} else { } else {
columnStr = session.statement.genColumnStr() columnStr = session.statement.genColumnStr()
} }
} else { } else {
if columnStr == "" { if columnStr == "" {
if session.statement.GroupByStr != "" { if session.statement.GroupByStr != "" {
columnStr = session.statement.Engine.Quote(strings.Replace(session.statement.GroupByStr, ",", session.engine.Quote(","), -1))
columnStr = session.engine.quoteColumns(session.statement.GroupByStr)
} else { } else {
columnStr = "*" columnStr = "*"
} }
return result, nil return result, nil
} }


func row2sliceStr(rows *core.Rows, fields []string) (results []string, err error) {
result := make([]string, 0, len(fields))
scanResultContainers := make([]interface{}, len(fields))
for i := 0; i < len(fields); i++ {
var scanResultContainer interface{}
scanResultContainers[i] = &scanResultContainer
}
if err := rows.Scan(scanResultContainers...); err != nil {
return nil, err
}

for i := 0; i < len(fields); i++ {
rawValue := reflect.Indirect(reflect.ValueOf(scanResultContainers[i]))
// if row is null then as empty string
if rawValue.Interface() == nil {
result = append(result, "")
continue
}

if data, err := value2String(&rawValue); err == nil {
result = append(result, data)
} else {
return nil, err
}
}
return result, nil
}

func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) { func rows2Strings(rows *core.Rows) (resultsSlice []map[string]string, err error) {
fields, err := rows.Columns() fields, err := rows.Columns()
if err != nil { if err != nil {
return resultsSlice, nil return resultsSlice, nil
} }


func rows2SliceString(rows *core.Rows) (resultsSlice [][]string, err error) {
fields, err := rows.Columns()
if err != nil {
return nil, err
}
for rows.Next() {
record, err := row2sliceStr(rows, fields)
if err != nil {
return nil, err
}
resultsSlice = append(resultsSlice, record)
}

return resultsSlice, nil
}

// QueryString runs a raw sql and return records as []map[string]string // QueryString runs a raw sql and return records as []map[string]string
func (session *Session) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) { func (session *Session) QueryString(sqlorArgs ...interface{}) ([]map[string]string, error) {
if session.isAutoClose { if session.isAutoClose {
return rows2Strings(rows) return rows2Strings(rows)
} }


// QuerySliceString runs a raw sql and return records as [][]string
func (session *Session) QuerySliceString(sqlorArgs ...interface{}) ([][]string, error) {
if session.isAutoClose {
defer session.Close()
}

sqlStr, args, err := session.genQuerySQL(sqlorArgs...)
if err != nil {
return nil, err
}

rows, err := session.queryRows(sqlStr, args...)
if err != nil {
return nil, err
}
defer rows.Close()

return rows2SliceString(rows)
}

func row2mapInterface(rows *core.Rows, fields []string) (resultsMap map[string]interface{}, err error) { func row2mapInterface(rows *core.Rows, fields []string) (resultsMap map[string]interface{}, err error) {
resultsMap = make(map[string]interface{}, len(fields)) resultsMap = make(map[string]interface{}, len(fields))
scanResultContainers := make([]interface{}, len(fields)) scanResultContainers := make([]interface{}, len(fields))

+ 25
- 1
vendor/github.com/go-xorm/xorm/session_raw.go View File

"reflect" "reflect"
"time" "time"


"github.com/go-xorm/builder"
"github.com/go-xorm/core" "github.com/go-xorm/core"
) )


return session.DB().Exec(sqlStr, args...) return session.DB().Exec(sqlStr, args...)
} }


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
}

// Exec raw sql // Exec raw sql
func (session *Session) Exec(sqlStr string, args ...interface{}) (sql.Result, error) {
func (session *Session) Exec(sqlorArgs ...interface{}) (sql.Result, error) {
if session.isAutoClose { if session.isAutoClose {
defer session.Close() defer session.Close()
} }


if len(sqlorArgs) == 0 {
return nil, ErrUnSupportedType
}

sqlStr, args, err := convertSQLOrArgs(sqlorArgs...)
if err != nil {
return nil, err
}

return session.exec(sqlStr, args...) return session.exec(sqlStr, args...)
} }

+ 3
- 3
vendor/github.com/go-xorm/xorm/session_update.go View File

} else { } else {
session.engine.logger.Debug("[cacheUpdate] set bean field", bean, colName, fieldValue.Interface()) session.engine.logger.Debug("[cacheUpdate] set bean field", bean, colName, fieldValue.Interface())
if col.IsVersion && session.statement.checkVersion { if col.IsVersion && session.statement.checkVersion {
fieldValue.SetInt(fieldValue.Int() + 1)
session.incrVersionFieldValue(fieldValue)
} else { } else {
fieldValue.Set(reflect.ValueOf(args[idx])) fieldValue.Set(reflect.ValueOf(args[idx]))
} }
return 0, err return 0, err
} else if doIncVer { } else if doIncVer {
if verValue != nil && verValue.IsValid() && verValue.CanSet() { if verValue != nil && verValue.IsValid() && verValue.CanSet() {
verValue.SetInt(verValue.Int() + 1)
session.incrVersionFieldValue(verValue)
} }
} }


} }
} }


if col.IsDeleted || col.IsCreated {
if (col.IsDeleted && !session.statement.unscoped) || col.IsCreated {
continue continue
} }



+ 4
- 2
vendor/github.com/go-xorm/xorm/statement.go View File

exprColumns map[string]exprParam exprColumns map[string]exprParam
cond builder.Cond cond builder.Cond
bufferSize int bufferSize int
context ContextCache
} }


// Init reset all the statement's fields // Init reset all the statement's fields
statement.exprColumns = make(map[string]exprParam) statement.exprColumns = make(map[string]exprParam)
statement.cond = builder.NewCond() statement.cond = builder.NewCond()
statement.bufferSize = 0 statement.bufferSize = 0
statement.context = nil
} }


// NoAutoCondition if you do not want convert bean's field as query condition, then use this function // NoAutoCondition if you do not want convert bean's field as query condition, then use this function
if len(statement.JoinStr) == 0 { if len(statement.JoinStr) == 0 {
if len(columnStr) == 0 { if len(columnStr) == 0 {
if len(statement.GroupByStr) > 0 { if len(statement.GroupByStr) > 0 {
columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1))
columnStr = statement.Engine.quoteColumns(statement.GroupByStr)
} else { } else {
columnStr = statement.genColumnStr() columnStr = statement.genColumnStr()
} }
} else { } else {
if len(columnStr) == 0 { if len(columnStr) == 0 {
if len(statement.GroupByStr) > 0 { if len(statement.GroupByStr) > 0 {
columnStr = statement.Engine.Quote(strings.Replace(statement.GroupByStr, ",", statement.Engine.Quote(","), -1))
columnStr = statement.Engine.quoteColumns(statement.GroupByStr)
} }
} }
} }

+ 26
- 0
vendor/github.com/go-xorm/xorm/transaction.go View File

// 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

// Transaction Execute sql wrapped in a transaction(abbr as tx), tx will automatic commit if no errors occurred
func (engine *Engine) Transaction(f func(*Session) (interface{}, error)) (interface{}, error) {
session := engine.NewSession()
defer session.Close()

if err := session.Begin(); err != nil {
return nil, err
}

result, err := f(session)
if err != nil {
return nil, err
}

if err := session.Commit(); err != nil {
return nil, err
}

return result, nil
}

+ 2
- 0
vendor/github.com/go-xorm/xorm/xorm.go View File

// 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.


// +build go1.8

package xorm package xorm


import ( import (

Loading…
Cancel
Save