PLT-6341/PLT-6342 Update gorp to mattermost fork and add connection timeout setting (#6410)

* Update gorp to mattermost fork and add connection timeout setting

* Add go dependency

* Rename from connection timeout to query timeout

* Properly add gorp dependency
Этот коммит содержится в:
Joram Wilander
2017-05-29 15:46:35 -04:00
коммит произвёл GitHub
родитель f9843b3800
Коммит 860e5d483c
40 изменённых файлов: 1423 добавлений и 434 удалений

Просмотреть файл

@@ -85,7 +85,8 @@
"MaxIdleConns": 20,
"MaxOpenConns": 300,
"Trace": false,
"AtRestEncryptKey": ""
"AtRestEncryptKey": "",
"QueryTimeout": 30
},
"LogSettings": {
"EnableConsole": true,

164
glide.lock сгенерированный
Просмотреть файл

@@ -1,107 +1,107 @@
hash: f433ef56bd1b8b49337869595b41bb46c9ab29f8f5d2c17d06b7b3fb29342ce2
updated: 2017-05-17T11:28:42.577896239-04:00
hash: 5b7ec282bc586a0d87d37c5a144127730ff7fde166e23a17a7a0639b51afdfe6
updated: 2017-05-29T13:59:34.473725185-04:00
imports:
- name: github.com/alecthomas/log4go
version: 3fbce08846379ec7f4f6bc7fce6dd01ce28fae4c
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
repo: https://github.com/mattermost/log4go.git
- name: github.com/armon/go-metrics
version: 93f237eba9b0602f3e73710416558854a81d9337
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/beorn7/perks
version: 4c0e84591b9aa9e6dcfdf3e020114cd81f89d5f9
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- quantile
- name: github.com/cpanato/html2text
version: d788b7d6dc58bea298b318059332a25442583880
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/dgryski/dgoogauth
version: 96977cbd42e27be71f9f731db6634123de7e861a
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/dimchansky/utfbom
version: 6c6132ff69f0f6c088739067407b5d32c52e1d0f
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/disintegration/imaging
version: ac27d1805a555e1754fa177216ee07f4e63c30b5
version: ""
- name: github.com/dyatlov/go-opengraph
version: 41a3523719dfbe7e8f853fbd4061867543db5270
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- opengraph
- name: github.com/fsnotify/fsnotify
version: 4da3e2cfbabc9f751898f250b49f2439785783a1
- name: github.com/go-gorp/gorp
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d
version: ""
- name: github.com/go-ini/ini
version: e7fea39b01aea8d5671f6858f0532f56e8bff3a5
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/go-ldap/ldap
version: 13cedcf58a1ea124045dea529a66c849d3444c8e
version: ""
- name: github.com/go-sql-driver/mysql
version: 382e13d099fcf5f5994290892ab258fbebbdc5e3
version: ""
- name: github.com/golang/freetype
version: bcfeb16b74e8aea9e2fe043406f2ef74b1cb0759
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- raster
- truetype
- name: github.com/golang/protobuf
version: fec3b39b059c0f88fa6b20f5ed012b1aa203a8b4
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- proto
- name: github.com/gorilla/context
version: 08b5f424b9271eedf6f9f0ce86cb9396ed337a42
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/gorilla/handlers
version: 13d73096a474cac93275c679c7b8a2dc17ddba82
version: ""
- name: github.com/gorilla/mux
version: 4c1c3952b7d9d0a061a3fa7b36fd373ba0398ebc
version: 392c28fe23e1c45ddba891b0320b3b5df220beea
- name: github.com/gorilla/websocket
version: a91eba7f97777409bc2c443f5534d41dd20c5720
version: ""
- name: github.com/hashicorp/errwrap
version: 7554cd9344cec97297fa6649b055a8c98c2a1e55
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/hashicorp/go-msgpack
version: fa3f63826f7c23912c15263591e65d54d080b458
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- codec
- name: github.com/hashicorp/go-multierror
version: ed905158d87462226a13fe39ddf685ea65f1c11f
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/hashicorp/go-sockaddr
version: acd314c5781ea706c710d9ea70069fd2e110d61d
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/hashicorp/golang-lru
version: 0a025b7e63adc15a622f29b0b2c4c3848243bbf6
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- simplelru
- name: github.com/hashicorp/hcl
version: 392dba7d905ed5d04a5794ba89f558b27e2ba1ca
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- hcl/ast
- hcl/parser
- hcl/scanner
- hcl/strconv
- hcl/token
- json/parser
- hcl/scanner
- hcl/strconv
- json/scanner
- json/token
- name: github.com/hashicorp/memberlist
version: 679583836ce521ac7a4cd6e6806bab9dba8fbdb8
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/inconshreveable/mousetrap
version: 76626ae9c91c4f2a10f34cad8ce83ea42c93bb75
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/jehiah/go-strftime
version: 834e15c05a45371503440cc195bbd05c9a0968d9
version: ""
- name: github.com/lib/pq
version: 2704adc878c21e1329f46f6e56a1c387d788ff94
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- oid
- name: github.com/magiconair/properties
version: 51463bfca2576e06c62a8504b5c0f06d61312647
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/mattermost/gorp
version: cab337059e349c91a4b917c9be50708813619543
- name: github.com/mattermost/rsc
version: bbaefb05eaa0389ea712340066837c8ce4d287f9
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- gf256
- qr
- qr/coding
- gf256
- name: github.com/matttproud/golang_protobuf_extensions
version: c12348ce28de40eed0136aa2b644d0ee0650e56c
version: ""
subpackages:
- pbutil
- name: github.com/miekg/dns
version: f282f80e243cc2bf8f6410c30d821b93b794e168
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/minio/go-homedir
version: a7ee80e4c344cab722502d3f074c5b7245d0bbe7
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/minio/minio-go
version: 85f15b007f08e11a62c769abe65299b812fd2e0d
version: ""
subpackages:
- pkg/credentials
- pkg/encrypt
@@ -110,128 +110,128 @@ imports:
- pkg/s3utils
- pkg/set
- name: github.com/mitchellh/mapstructure
version: cc8532a8e9a55ea36402aa21efdf403a60d34096
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/mssola/user_agent
version: 07efe2b857fb8c02d2dd85c12d0145f58554ec7c
version: ""
- name: github.com/nicksnyder/go-i18n
version: 3e70a1a463008cea6726380c908b1a6a8bdf7b24
version: ""
subpackages:
- i18n
- i18n/bundle
- i18n/language
- i18n/translation
- name: github.com/NYTimes/gziphandler
version: 22d4470af89e09998fc16b35029df973932df4ae
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/pborman/uuid
version: 1b00554d822231195d1babd97ff4a781231955c9
version: ""
- name: github.com/pelletier/go-buffruneio
version: c37440a7cf42ac63b919c752ca73a85067e05992
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/pelletier/go-toml
version: 5c26a6ff6fd178719e15decac1c8196da0d7d6d1
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/pkg/errors
version: c605e284fe17294bda444b34710735b29d1a9d90
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/prometheus/client_golang
version: 42552c195dd3f3089fbf9cf26e139da150af35aa
version: ""
subpackages:
- prometheus
- name: github.com/prometheus/client_model
version: 6f3806018612930941127f2a7c6c453ba2c527d2
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- go
- name: github.com/prometheus/common
version: 13ba4ddd0caa9c28ca7b7bffe1dfa9ed8d5ef207
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- expfmt
- name: github.com/prometheus/procfs
version: d098ca18df8bc825079013daf7bacefbb1ee877e
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/rsc/letsencrypt
version: 76104d26167d38b6a0010f42bfc8ec5487742e8b
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/rwcarlsen/goexif
version: 709fab3d192d7c62f86043caff1e7e3fb0f42bd8
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- exif
- tiff
- name: github.com/sean-/seed
version: e2103e2c35297fb7e17febb81e49b312087a2372
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/segmentio/analytics-go
version: bdb0aeca8a993b292b85c9ec17b5ce0ff81848c8
version: ""
- name: github.com/segmentio/backo-go
version: 204274ad699c0983a70203a566887f17a717fef4
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/spf13/afero
version: 9be650865eab0c12963d8753212f4f9c66cdcf12
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- mem
- name: github.com/spf13/cast
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/spf13/cobra
version: 4cdb38c072b86bf795d2c81de50784d9fdd6eb77
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/spf13/jwalterweatherman
version: 8f07c835e5cc1450c082fe3a439cf87b0cbb2d99
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/spf13/pflag
version: e57e3eeb33f795204c1ca35f56c44f83227c6e66
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/spf13/viper
version: 0967fc9aceab2ce9da34061253ac10fb99bba5b2
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: github.com/tylerb/graceful
version: d72b0151351a13d0421b763b88f791469c4f5dc7
version: ""
- name: github.com/xenolf/lego
version: aaa8e70aec58a858b6bef0706b367dd5e8d58128
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- acme
- name: github.com/xtgo/uuid
version: a0b114877d4caeffbd7f87e3757c17fce570fea7
version: ""
- name: golang.org/x/crypto
version: 0fe963104e9d1877082f8fb38f816fcd97eb1d10
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- bcrypt
- blowfish
- ocsp
- name: golang.org/x/image
version: f483456c9f61fd7c1e170033d58ef22ff5ffe291
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- bmp
- tiff
- font
- math/fixed
- tiff
- tiff/lzw
- name: golang.org/x/net
version: 34057069f4ab13dc4433c68d368737ebeafcccdc
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- context
- html
- html/atom
- context
- publicsuffix
- name: golang.org/x/sys
version: 98b5b1e7e80eb60271c8dc4eba6521ec2c3e811e
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- unix
- name: golang.org/x/text
version: 19e51611da83d6be54ddafce4a4af510cb3e9ea4
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- transform
- unicode/norm
- name: golang.org/x/time
version: 8be79e1e0910c292df4e79c241bb7e8f7e725959
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- rate
- name: gopkg.in/alexcesaro/quotedprintable.v3
version: 2caba252f4dc53eaf6b553000885530023f54623
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: gopkg.in/asn1-ber.v1
version: 379148ca0225df7a432012b8df0355c2a2063ac0
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: gopkg.in/gomail.v2
version: 81ebce5c23dfd25c6c67194b37d3dd3f338c98b1
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
- name: gopkg.in/olivere/elastic.v5
version: 3f49414dc29d45ba96fde19ba72bc646077dbffd
version: ""
subpackages:
- uritemplates
- name: gopkg.in/square/go-jose.v1
version: aa2e30fdd1fe9dd3394119af66451ae790d50e0d
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
subpackages:
- cipher
- json
- name: gopkg.in/throttled/throttled.v2
version: b5675e93f9d999b22f92d859a5bf2138d3641af4
version: ""
subpackages:
- store/memstore
- name: gopkg.in/yaml.v2
version: cd8b52f8269e0feb286dfeef29f8fe4d5b397e0b
version: e6f2a1168aff618c852d82a6fba11d9565f45ec5
testImports: []

Просмотреть файл

@@ -11,8 +11,6 @@ import:
- opengraph
- package: github.com/fsnotify/fsnotify
version: v1.4.2
- package: github.com/go-gorp/gorp
version: 0c9bc0918534d133cedb439a24adc7cbe66e4a9d
- package: github.com/go-ldap/ldap
version: v2.5.0
- package: github.com/go-sql-driver/mysql
@@ -83,3 +81,4 @@ import:
- package: github.com/cpanato/html2text
- package: gopkg.in/olivere/elastic.v5
version: v5.0.38
- package: github.com/mattermost/gorp

Просмотреть файл

@@ -4131,6 +4131,10 @@
"id": "model.config.is_valid.sql_idle.app_error",
"translation": "Invalid maximum idle connection for SQL settings. Must be a positive number."
},
{
"id": "model.config.is_valid.sql_query_timeout.app_error",
"translation": "Invalid query timeout for SQL settings. Must be a positive number."
},
{
"id": "model.config.is_valid.sql_max_conn.app_error",
"translation": "Invalid maximum open connection for SQL settings. Must be a positive number."

Просмотреть файл

@@ -6,6 +6,7 @@ package model
import (
"encoding/json"
"io"
"net/http"
"net/url"
)
@@ -195,6 +196,7 @@ type SqlSettings struct {
MaxOpenConns int
Trace bool
AtRestEncryptKey string
QueryTimeout *int
}
type LogSettings struct {
@@ -480,6 +482,11 @@ func (o *Config) SetDefaults() {
o.SqlSettings.AtRestEncryptKey = NewRandomString(32)
}
if o.SqlSettings.QueryTimeout == nil {
o.SqlSettings.QueryTimeout = new(int)
*o.SqlSettings.QueryTimeout = 30
}
if o.FileSettings.AmazonS3Endpoint == "" {
// Defaults to "s3.amazonaws.com"
o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com"
@@ -1322,6 +1329,10 @@ func (o *Config) IsValid() *AppError {
return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_idle.app_error", nil, "")
}
if *o.SqlSettings.QueryTimeout <= 0 {
return NewAppError("Config.IsValid", "model.config.is_valid.sql_query_timeout.app_error", nil, "", http.StatusBadRequest)
}
if len(o.SqlSettings.DataSource) == 0 {
return NewLocAppError("Config.IsValid", "model.config.is_valid.sql_data_src.app_error", nil, "")
}

Просмотреть файл

@@ -11,7 +11,7 @@ import (
"strings"
l4g "github.com/alecthomas/log4go"
"github.com/go-gorp/gorp"
"github.com/mattermost/gorp"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"

Просмотреть файл

@@ -7,7 +7,7 @@ import (
"net/http"
"strings"
"github.com/go-gorp/gorp"
"github.com/mattermost/gorp"
"github.com/mattermost/platform/model"
)

Просмотреть файл

@@ -5,7 +5,7 @@ package store
import (
l4g "github.com/alecthomas/log4go"
"github.com/go-gorp/gorp"
"github.com/mattermost/gorp"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)

Просмотреть файл

@@ -4,12 +4,12 @@
package store
import (
"github.com/mattermost/gorp"
"github.com/mattermost/platform/einterfaces"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
l4g "github.com/alecthomas/log4go"
"github.com/go-gorp/gorp"
)
const (

Просмотреть файл

@@ -24,9 +24,9 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/go-gorp/gorp"
_ "github.com/go-sql-driver/mysql"
_ "github.com/lib/pq"
"github.com/mattermost/gorp"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/utils"
)
@@ -211,12 +211,14 @@ func setupConnection(con_type string, driver string, dataSource string, maxIdle
var dbmap *gorp.DbMap
connectionTimeout := time.Duration(*utils.Cfg.SqlSettings.QueryTimeout) * time.Second
if driver == "sqlite3" {
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.SqliteDialect{}}
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.SqliteDialect{}, QueryTimeout: connectionTimeout}
} else if driver == model.DATABASE_DRIVER_MYSQL {
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8MB4"}}
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8MB4"}, QueryTimeout: connectionTimeout}
} else if driver == model.DATABASE_DRIVER_POSTGRES {
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.PostgresDialect{}}
dbmap = &gorp.DbMap{Db: db, TypeConverter: mattermConverter{}, Dialect: gorp.PostgresDialect{}, QueryTimeout: connectionTimeout}
} else {
l4g.Critical(utils.T("store.sql.dialect_driver.critical"))
time.Sleep(time.Second)
@@ -384,7 +386,7 @@ func (ss *SqlStore) CreateColumnIfNotExists(tableName string, columnName string,
}
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
_, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + postgresColType + " DEFAULT '" + defaultValue + "'")
_, err := ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " ADD " + columnName + " " + postgresColType + " DEFAULT '" + defaultValue + "'")
if err != nil {
l4g.Critical(utils.T("store.sql.create_column.critical"), err)
time.Sleep(time.Second)
@@ -394,7 +396,7 @@ func (ss *SqlStore) CreateColumnIfNotExists(tableName string, columnName string,
return true
} else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
_, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + mySqlColType + " DEFAULT '" + defaultValue + "'")
_, err := ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " ADD " + columnName + " " + mySqlColType + " DEFAULT '" + defaultValue + "'")
if err != nil {
l4g.Critical(utils.T("store.sql.create_column.critical"), err)
time.Sleep(time.Second)
@@ -417,7 +419,7 @@ func (ss *SqlStore) RemoveColumnIfExists(tableName string, columnName string) bo
return false
}
_, err := ss.GetMaster().Exec("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
_, err := ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " DROP COLUMN " + columnName)
if err != nil {
l4g.Critical("Failed to drop column %v", err)
time.Sleep(time.Second)
@@ -432,7 +434,7 @@ func (ss *SqlStore) RemoveTableIfExists(tableName string) bool {
return false
}
_, err := ss.GetMaster().Exec("DROP TABLE " + tableName)
_, err := ss.GetMaster().ExecNoTimeout("DROP TABLE " + tableName)
if err != nil {
l4g.Critical("Failed to drop table %v", err)
time.Sleep(time.Second)
@@ -449,9 +451,9 @@ func (ss *SqlStore) RenameColumnIfExists(tableName string, oldColumnName string,
var err error
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
_, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " CHANGE " + oldColumnName + " " + newColumnName + " " + colType)
_, err = ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " CHANGE " + oldColumnName + " " + newColumnName + " " + colType)
} else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
_, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " RENAME COLUMN " + oldColumnName + " TO " + newColumnName)
_, err = ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " RENAME COLUMN " + oldColumnName + " TO " + newColumnName)
}
if err != nil {
@@ -492,9 +494,9 @@ func (ss *SqlStore) AlterColumnTypeIfExists(tableName string, columnName string,
var err error
if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_MYSQL {
_, err = ss.GetMaster().Exec("ALTER TABLE " + tableName + " MODIFY " + columnName + " " + mySqlColType)
_, err = ss.GetMaster().ExecNoTimeout("ALTER TABLE " + tableName + " MODIFY " + columnName + " " + mySqlColType)
} else if utils.Cfg.SqlSettings.DriverName == model.DATABASE_DRIVER_POSTGRES {
_, err = ss.GetMaster().Exec("ALTER TABLE " + strings.ToLower(tableName) + " ALTER COLUMN " + strings.ToLower(columnName) + " TYPE " + postgresColType)
_, err = ss.GetMaster().ExecNoTimeout("ALTER TABLE " + strings.ToLower(tableName) + " ALTER COLUMN " + strings.ToLower(columnName) + " TYPE " + postgresColType)
}
if err != nil {
@@ -540,7 +542,7 @@ func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, c
query = "CREATE " + uniqueStr + "INDEX " + indexName + " ON " + tableName + " (" + columnName + ")"
}
_, err = ss.GetMaster().Exec(query)
_, err = ss.GetMaster().ExecNoTimeout(query)
if err != nil {
l4g.Critical(utils.T("store.sql.create_index.critical"), err)
time.Sleep(time.Second)
@@ -564,7 +566,7 @@ func (ss *SqlStore) createIndexIfNotExists(indexName string, tableName string, c
fullTextIndex = " FULLTEXT "
}
_, err = ss.GetMaster().Exec("CREATE " + uniqueStr + fullTextIndex + " INDEX " + indexName + " ON " + tableName + " (" + columnName + ")")
_, err = ss.GetMaster().ExecNoTimeout("CREATE " + uniqueStr + fullTextIndex + " INDEX " + indexName + " ON " + tableName + " (" + columnName + ")")
if err != nil {
l4g.Critical(utils.T("store.sql.create_index.critical"), err)
time.Sleep(time.Second)
@@ -588,7 +590,7 @@ func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) bool
return false
}
_, err = ss.GetMaster().Exec("DROP INDEX " + indexName)
_, err = ss.GetMaster().ExecNoTimeout("DROP INDEX " + indexName)
if err != nil {
l4g.Critical(utils.T("store.sql.remove_index.critical"), err)
time.Sleep(time.Second)
@@ -609,7 +611,7 @@ func (ss *SqlStore) RemoveIndexIfExists(indexName string, tableName string) bool
return false
}
_, err = ss.GetMaster().Exec("DROP INDEX " + indexName + " ON " + tableName)
_, err = ss.GetMaster().ExecNoTimeout("DROP INDEX " + indexName + " ON " + tableName)
if err != nil {
l4g.Critical(utils.T("store.sql.remove_index.critical"), err)
time.Sleep(time.Second)

1
vendor/github.com/go-gorp/gorp/.gitignore → vendor/github.com/mattermost/gorp/.gitignore сгенерированный поставляемый
Просмотреть файл

@@ -1,4 +1,5 @@
_test
*.test
_testmain.go
_obj
*~

Просмотреть файл

@@ -1,9 +1,13 @@
language: go
go:
- 1.3
- 1.4
- 1.6
- 1.7
- tip
matrix:
allow_failures:
- go: tip
services:
- mysql
- postgres
@@ -24,5 +28,6 @@ before_script:
- go get github.com/go-sql-driver/mysql
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
- go get github.com/onsi/ginkgo/ginkgo
script: ./test_all.sh

34
vendor/github.com/mattermost/gorp/CONTRIBUTING.md сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,34 @@
# Contributions are very welcome!
## First: Create an Issue
Even if your fix is simple, we'd like to have an issue to relate to
the PR. Discussion about the architecture and value can go on the
issue, leaving PR comments exclusively for coding style.
## Second: Make Your PR
- Fork the `master` branch
- Make your change
- Make a PR against the `master` branch
You don't need to wait for comments on the issue before making your
PR. If you do wait for comments, you'll have a better chance of
getting your PR accepted the first time around, but it's not
necessary.
## Third: Be Patient
- If your change breaks backward compatibility, this becomes
especially true.
We all have lives and jobs, and many of us are no longer on projects
that make use of `gorp`. We will get back to you, but it might take a
while.
## Fourth: Consider Becoming a Maintainer
We really do need help. We will likely ask you for help after a good
PR, but if we don't, please create an issue requesting maintainership.
Considering how few of us are currently active, we are unlikely to
refuse good help.

0
vendor/github.com/go-gorp/gorp/LICENSE → vendor/github.com/mattermost/gorp/LICENSE сгенерированный поставляемый
Просмотреть файл

254
vendor/github.com/go-gorp/gorp/README.md → vendor/github.com/mattermost/gorp/README.md сгенерированный поставляемый
Просмотреть файл

@@ -4,23 +4,40 @@
[![code coverage](https://img.shields.io/coveralls/go-gorp/gorp.svg)](https://coveralls.io/r/go-gorp/gorp)
[![issues](https://img.shields.io/github/issues/go-gorp/gorp.svg)](https://github.com/go-gorp/gorp/issues)
[![godoc v1](https://img.shields.io/badge/godoc-v1-375EAB.svg)](https://godoc.org/gopkg.in/gorp.v1)
[![godoc v2](https://img.shields.io/badge/godoc-v2-375EAB.svg)](https://godoc.org/gopkg.in/gorp.v2)
[![godoc bleeding edge](https://img.shields.io/badge/godoc-bleeding--edge-375EAB.svg)](https://godoc.org/github.com/go-gorp/gorp)
### Update 2015-07-01 Cleanup & feature freeze ([#270](https://github.com/go-gorp/gorp/issues/270))
### Update 2016-11-13: Future versions
We are currently cleaning up the backlog of issues and PR's. When this is done the codebase will be split into separate files and there will be breaking changes to the API's. We're also adding better tests and documentation. As a result of these changes the `master` branch will be unstable. Please use `gopkg.in/gorp.v1`. When the cleanup and changes are done, we will release `v2.0`.
As many of the maintainers have become busy with other projects,
progress toward the ever-elusive v2 has slowed to the point that we're
only occasionally making progress outside of merging pull requests.
In the interest of continuing to release, I'd like to lean toward a
more maintainable path forward.
At this time we won't accept new feature-related pull-requests because of changes to the codebase. Please create an issue for your feature and wait until `v2.0` has been released.
For more information, please read [#270](https://github.com/go-gorp/gorp/issues/270).
For the moment, I am releasing a v2 tag with the current feature set
from master, as some of those features have been actively used and
relied on by more than one project. Our next goal is to continue
cleaning up the code base with non-breaking changes as much as
possible, but if/when a breaking change is needed, we'll just release
new versions. This allows us to continue development at whatever pace
we're capable of, without delaying the release of features or refusing
PRs.
## Introduction
I hesitate to call gorp an ORM. Go doesn't really have objects, at least not in the classic Smalltalk/Java sense. There goes the "O". gorp doesn't know anything about the relationships between your structs (at least not yet). So the "R" is questionable too (but I use it in the name because, well, it seemed more clever).
I hesitate to call gorp an ORM. Go doesn't really have objects, at
least not in the classic Smalltalk/Java sense. There goes the "O".
gorp doesn't know anything about the relationships between your
structs (at least not yet). So the "R" is questionable too (but I use
it in the name because, well, it seemed more clever).
The "M" is alive and well. Given some Go structs and a database, gorp should remove a fair amount of boilerplate busy-work from your code.
The "M" is alive and well. Given some Go structs and a database, gorp
should remove a fair amount of boilerplate busy-work from your code.
I hope that gorp saves you time, minimizes the drudgery of getting data in and out of your database, and helps your code focus on algorithms, not infrastructure.
I hope that gorp saves you time, minimizes the drudgery of getting
data in and out of your database, and helps your code focus on
algorithms, not infrastructure.
* Bind struct fields to table columns via API or tag
* Support for embedded structs
@@ -35,42 +52,59 @@ I hope that gorp saves you time, minimizes the drudgery of getting data in and o
* Bind arbitrary SQL queries to a struct
* Bind slice to SELECT query results without type assertions
* Use positional or named bind parameters in custom SELECT queries
* Optional optimistic locking using a version column (for update/deletes)
* Optional optimistic locking using a version column (for
update/deletes)
## Installation
# install the library:
go get gopkg.in/gorp.v1
// use in your .go code:
import (
"gopkg.in/gorp.v1"
)
Use `go get` or your favorite vendoring tool, using whichever import
path you'd like.
## Versioning
This project provides a stable release (v1.x tags) and a bleeding edge codebase (master).
We use semantic version tags. Feel free to import through `gopkg.in`
(e.g. `gopkg.in/gorp.v2`) to get the latest tag for a major version,
or check out the tag using your favorite vendoring tool.
`gopkg.in/gorp.v1` points to the latest v1.x tag. The API's for v1 are stable and shouldn't change. Development takes place at the master branch. Althought the code in master should always compile and test successfully, it might break API's. We aim to maintain backwards compatibility, but API's and behaviour might be changed to fix a bug. Also note that API's that are new in the master branch can change until released as v2.
Development is not very active right now, but we have plans to
restructure `gorp` as we continue to move toward a more extensible
system. Whenever a breaking change is needed, the major version will
be bumped.
If you want to use bleeding edge, use `github.com/go-gorp/gorp` as import path.
The `master` branch is where all development is done, and breaking
changes may happen from time to time. That said, if you want to live
on the bleeding edge and are comfortable updating your code when we
make a breaking change, you may use `github.com/go-gorp/gorp` as your
import path.
## API Documentation
Full godoc output from the latest v1 release is available here:
https://godoc.org/gopkg.in/gorp.v1
For the latest code in master:
https://godoc.org/github.com/go-gorp/gorp
Check the version tags to see what's available. We'll make a good
faith effort to add badges for new versions, but we make no
guarantees.
## Supported Go versions
This package is compatible with the last 2 major versions of Go, at this time `1.3` and `1.4`.
This package is guaranteed to be compatible with the latest 2 major
versions of Go.
Any earlier versions are only supported on a best effort basis and can be dropped any time.
Go has a great compatibility promise. Upgrading your program to a newer version of Go should never really be a problem.
Any earlier versions are only supported on a best effort basis and can
be dropped any time. Go has a great compatibility promise. Upgrading
your program to a newer version of Go should never really be a
problem.
## Migration guide
#### Pre-v2 to v2
Automatic mapping of the version column used in optimistic locking has
been removed as it could cause problems if the type was not int. The
version column must now explicitly be set with
`tablemap.SetVersionCol()`.
## Help/Support
Use our [`gitter` channel](https://gitter.im/go-gorp/gorp). We used
to use IRC, but with most of us being pulled in many directions, we
often need the email notifications from `gitter` to yell at us to sign
in.
## Quickstart
@@ -530,10 +564,11 @@ Full list of hooks that you can implement:
#### Note that this behaviour has changed in v2. See [Migration Guide](#migration-guide).
gorp provides a simple optimistic locking feature, similar to Java's JPA, that
will raise an error if you try to update/delete a row whose `version` column
has a value different than the one in memory. This provides a safe way to do
"select then update" style operations without explicit read and write locks.
gorp provides a simple optimistic locking feature, similar to Java's
JPA, that will raise an error if you try to update/delete a row whose
`version` column has a value different than the one in memory. This
provides a safe way to do "select then update" style operations
without explicit read and write locks.
```go
// Version is an auto-incremented number, managed by gorp
@@ -582,13 +617,15 @@ if ok {
```
### Adding INDEX(es) on column(s) beyond the primary key ###
Indexes are frequently critical for performance. Here is how to add them to your tables.
Indexes are frequently critical for performance. Here is how to add
them to your tables.
NB: SqlServer and Oracle need testing and possible adjustment to the
NB: SqlServer and Oracle need testing and possible adjustment to the
CreateIndexSuffix() and DropIndexSuffix() methods to make AddIndex()
work for them.
In the example below we put an index both on the Id field, and on the AcctId field.
In the example below we put an index both on the Id field, and on the
AcctId field.
```
type Account struct {
@@ -626,76 +663,111 @@ MariaDB [test]> show create table Account;
## Database Drivers
gorp uses the Go 1 `database/sql` package. A full list of compliant drivers is available here:
gorp uses the Go 1 `database/sql` package. A full list of compliant
drivers is available here:
http://code.google.com/p/go-wiki/wiki/SQLDrivers
Sadly, SQL databases differ on various issues. gorp provides a Dialect interface that should be
implemented per database vendor. Dialects are provided for:
Sadly, SQL databases differ on various issues. gorp provides a Dialect
interface that should be implemented per database vendor. Dialects
are provided for:
* MySQL
* PostgreSQL
* sqlite3
Each of these three databases pass the test suite. See `gorp_test.go` for example
DSNs for these three databases.
Each of these three databases pass the test suite. See `gorp_test.go`
for example DSNs for these three databases.
Support is also provided for:
* Oracle (contributed by @klaidliadon)
* SQL Server (contributed by @qrawl) - use driver: github.com/denisenkom/go-mssqldb
* SQL Server (contributed by @qrawl) - use driver:
github.com/denisenkom/go-mssqldb
Note that these databases are not covered by CI and I (@coopernurse) have no good way to
test them locally. So please try them and send patches as needed, but expect a bit more
unpredicability.
Note that these databases are not covered by CI and I (@coopernurse)
have no good way to test them locally. So please try them and send
patches as needed, but expect a bit more unpredicability.
## Sqlite3 Extensions
In order to use sqlite3 extensions you need to first register a custom driver:
```go
import (
"database/sql"
// use whatever database/sql driver you wish
sqlite "github.com/mattn/go-sqlite3"
)
func customDriver() (*sql.DB, error) {
// create custom driver with extensions defined
sql.Register("sqlite3-custom", &sqlite.SQLiteDriver{
Extensions: []string{
"mod_spatialite",
},
})
// now you can then connect using the 'sqlite3-custom' driver instead of 'sqlite3'
return sql.Open("sqlite3-custom", "/tmp/post_db.bin")
}
```
## Known Issues
### SQL placeholder portability
Different databases use different strings to indicate variable placeholders in
prepared SQL statements. Unlike some database abstraction layers (such as JDBC),
Go's `database/sql` does not standardize this.
Different databases use different strings to indicate variable
placeholders in prepared SQL statements. Unlike some database
abstraction layers (such as JDBC), Go's `database/sql` does not
standardize this.
SQL generated by gorp in the `Insert`, `Update`, `Delete`, and `Get` methods delegates
to a Dialect implementation for each database, and will generate portable SQL.
SQL generated by gorp in the `Insert`, `Update`, `Delete`, and `Get`
methods delegates to a Dialect implementation for each database, and
will generate portable SQL.
Raw SQL strings passed to `Exec`, `Select`, `SelectOne`, `SelectInt`, etc will not be
parsed. Consequently you may have portability issues if you write a query like this:
Raw SQL strings passed to `Exec`, `Select`, `SelectOne`, `SelectInt`,
etc will not be parsed. Consequently you may have portability issues
if you write a query like this:
```go
// works on MySQL and Sqlite3, but not with Postgresql
err := dbmap.SelectOne(&val, "select * from foo where id = ?", 30)
```
```go // works on MySQL and Sqlite3, but not with Postgresql err :=
dbmap.SelectOne(&val, "select * from foo where id = ?", 30) ```
In `Select` and `SelectOne` you can use named parameters to work around this.
The following is portable:
In `Select` and `SelectOne` you can use named parameters to work
around this. The following is portable:
```go
err := dbmap.SelectOne(&val, "select * from foo where id = :id",
map[string]interface{} { "id": 30})
```
```go err := dbmap.SelectOne(&val, "select * from foo where id = :id",
map[string]interface{} { "id": 30}) ```
Additionally, when using Postgres as your database, you should utilize `$1` instead
of `?` placeholders as utilizing `?` placeholders when querying Postgres will result
in `pq: operator does not exist` errors. Alternatively, use
`dbMap.Dialect.BindVar(varIdx)` to get the proper variable binding for your dialect.
Additionally, when using Postgres as your database, you should utilize
`$1` instead of `?` placeholders as utilizing `?` placeholders when
querying Postgres will result in `pq: operator does not exist`
errors. Alternatively, use `dbMap.Dialect.BindVar(varIdx)` to get the
proper variable binding for your dialect.
### time.Time and time zones
gorp will pass `time.Time` fields through to the `database/sql` driver, but note that
the behavior of this type varies across database drivers.
gorp will pass `time.Time` fields through to the `database/sql`
driver, but note that the behavior of this type varies across database
drivers.
MySQL users should be especially cautious. See: https://github.com/ziutek/mymysql/pull/77
MySQL users should be especially cautious. See:
https://github.com/ziutek/mymysql/pull/77
To avoid any potential issues with timezone/DST, consider using an integer field for time
data and storing UNIX time.
To avoid any potential issues with timezone/DST, consider:
- Using an integer field for time data and storing UNIX time.
- Using a custom time type that implements some SQL types:
- [`"database/sql".Scanner`](https://golang.org/pkg/database/sql/#Scanner)
- [`"database/sql/driver".Valuer`](https://golang.org/pkg/database/sql/driver/#Valuer)
## Running the tests
The included tests may be run against MySQL, Postgresql, or sqlite3.
You must set two environment variables so the test code knows which driver to
use, and how to connect to your database.
You must set two environment variables so the test code knows which
driver to use, and how to connect to your database.
```sh
# MySQL example:
@@ -709,34 +781,18 @@ go test
go test -bench="Bench" -benchtime 10
```
Valid `GORP_TEST_DIALECT` values are: "mysql"(for mymysql), "gomysql"(for go-sql-driver), "postgres", "sqlite"
See the `test_all.sh` script for examples of all 3 databases. This is the script I run
locally to test the library.
Valid `GORP_TEST_DIALECT` values are: "mysql"(for mymysql),
"gomysql"(for go-sql-driver), "postgres", "sqlite" See the
`test_all.sh` script for examples of all 3 databases. This is the
script I run locally to test the library.
## Performance
gorp uses reflection to construct SQL queries and bind parameters. See the BenchmarkNativeCrud vs BenchmarkGorpCrud in gorp_test.go for a simple perf test. On my MacBook Pro gorp is about 2-3% slower than hand written SQL.
gorp uses reflection to construct SQL queries and bind parameters.
See the BenchmarkNativeCrud vs BenchmarkGorpCrud in gorp_test.go for a
simple perf test. On my MacBook Pro gorp is about 2-3% slower than
hand written SQL.
## Migration guide
#### Pre-v2 to v2
Automatic mapping of the version column used in optimistic locking has been removed as it could cause problems if the type was not int. The version column must now explicitly be set with tablemap.SetVersionCol().
## Help/Support
IRC: #gorp
Mailing list: gorp-dev@googlegroups.com
Bugs/Enhancements: Create a github issue
## Pull requests / Contributions
Contributions are very welcome. Please follow these guidelines:
* Fork the `master` branch and issue pull requests targeting the `master` branch
* If you are adding an enhancement, please open an issue first with your proposed change.
* Changes that break backwards compatibility in the public API are only accepted after we
discuss on a GitHub issue for a while.
Thanks!
## Contributors

0
vendor/github.com/go-gorp/gorp/column.go → vendor/github.com/mattermost/gorp/column.go сгенерированный поставляемый
Просмотреть файл

268
vendor/github.com/go-gorp/gorp/db.go → vendor/github.com/mattermost/gorp/db.go сгенерированный поставляемый
Просмотреть файл

@@ -13,6 +13,7 @@ package gorp
import (
"bytes"
"context"
"database/sql"
"database/sql/driver"
"errors"
@@ -41,9 +42,34 @@ type DbMap struct {
TypeConverter TypeConverter
tables []*TableMap
logger GorpLogger
logPrefix string
QueryTimeout time.Duration
tables []*TableMap
tablesDynamic map[string]*TableMap // tables that use same go-struct and different db table names
logger GorpLogger
logPrefix string
}
func (m *DbMap) dynamicTableAdd(tableName string, tbl *TableMap) {
if m.tablesDynamic == nil {
m.tablesDynamic = make(map[string]*TableMap)
}
m.tablesDynamic[tableName] = tbl
}
func (m *DbMap) dynamicTableFind(tableName string) (*TableMap, bool) {
if m.tablesDynamic == nil {
return nil, false
}
tbl, found := m.tablesDynamic[tableName]
return tbl, found
}
func (m *DbMap) dynamicTableMap() map[string]*TableMap {
if m.tablesDynamic == nil {
m.tablesDynamic = make(map[string]*TableMap)
}
return m.tablesDynamic
}
func (m *DbMap) CreateIndex() error {
@@ -52,36 +78,52 @@ func (m *DbMap) CreateIndex() error {
dialect := reflect.TypeOf(m.Dialect)
for _, table := range m.tables {
for _, index := range table.indexes {
s := bytes.Buffer{}
s.WriteString("create")
if index.Unique {
s.WriteString(" unique")
}
s.WriteString(" index")
s.WriteString(fmt.Sprintf(" %s on %s", index.IndexName, table.TableName))
if dname := dialect.Name(); dname == "PostgresDialect" && index.IndexType != "" {
s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
}
s.WriteString(" (")
for x, col := range index.columns {
if x > 0 {
s.WriteString(", ")
}
s.WriteString(m.Dialect.QuoteField(col))
}
s.WriteString(")")
if dname := dialect.Name(); dname == "MySQLDialect" && index.IndexType != "" {
s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
}
s.WriteString(";")
_, err = m.Exec(s.String())
err = m.createIndexImpl(dialect, table, index)
if err != nil {
break
}
}
}
for _, table := range m.dynamicTableMap() {
for _, index := range table.indexes {
err = m.createIndexImpl(dialect, table, index)
if err != nil {
break
}
}
}
return err
}
func (m *DbMap) createIndexImpl(dialect reflect.Type,
table *TableMap,
index *IndexMap) error {
s := bytes.Buffer{}
s.WriteString("create")
if index.Unique {
s.WriteString(" unique")
}
s.WriteString(" index")
s.WriteString(fmt.Sprintf(" %s on %s", index.IndexName, table.TableName))
if dname := dialect.Name(); dname == "PostgresDialect" && index.IndexType != "" {
s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
}
s.WriteString(" (")
for x, col := range index.columns {
if x > 0 {
s.WriteString(", ")
}
s.WriteString(m.Dialect.QuoteField(col))
}
s.WriteString(")")
if dname := dialect.Name(); dname == "MySQLDialect" && index.IndexType != "" {
s.WriteString(fmt.Sprintf(" %s %s", m.Dialect.CreateIndexSuffix(), index.IndexType))
}
s.WriteString(";")
_, err := m.ExecNoTimeout(s.String())
return err
}
@@ -98,7 +140,7 @@ func (t *TableMap) DropIndex(name string) error {
s.WriteString(fmt.Sprintf(" %s %s", t.dbmap.Dialect.DropIndexSuffix(), t.TableName))
}
s.WriteString(";")
_, e := t.dbmap.Exec(s.String())
_, e := t.dbmap.ExecNoTimeout(s.String())
if e != nil {
err = e
}
@@ -155,6 +197,36 @@ func (m *DbMap) AddTableWithNameAndSchema(i interface{}, schema string, name str
return tmap
}
// AddTableDynamic registers the given interface type with gorp.
// The table name will be dynamically determined at runtime by
// using the GetTableName method on DynamicTable interface
func (m *DbMap) AddTableDynamic(inp DynamicTable, schema string) *TableMap {
val := reflect.ValueOf(inp)
elm := val.Elem()
t := elm.Type()
name := inp.TableName()
if name == "" {
panic("Missing table name in DynamicTable instance")
}
// Check if there is another dynamic table with the same name
if _, found := m.dynamicTableFind(name); found {
panic(fmt.Sprintf("A table with the same name %v already exists", name))
}
tmap := &TableMap{gotype: t, TableName: name, SchemaName: schema, dbmap: m}
var primaryKey []*ColumnMap
tmap.Columns, primaryKey = m.readStructColumns(t)
if len(primaryKey) > 0 {
tmap.keys = append(tmap.keys, primaryKey...)
}
m.dynamicTableAdd(name, tmap)
return tmap
}
func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey []*ColumnMap) {
primaryKey = make([]*ColumnMap, 0)
n := t.NumField()
@@ -189,6 +261,7 @@ func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey
var defaultValue string
var isAuto bool
var isPK bool
var isNotNull bool
for _, argString := range cArguments[1:] {
argString = strings.TrimSpace(argString)
arg := strings.SplitN(argString, ":", 2)
@@ -216,6 +289,8 @@ func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey
isPK = true
case "autoincrement":
isAuto = true
case "notnull":
isNotNull = true
default:
panic(fmt.Sprintf("Unrecognized tag option for field %v: %v", f.Name, arg))
}
@@ -259,6 +334,7 @@ func (m *DbMap) readStructColumns(t reflect.Type) (cols []*ColumnMap, primaryKey
gotype: gotype,
isPK: isPK,
isAutoIncr: isAuto,
isNotNull: isNotNull,
MaxSize: maxSize,
}
if isPK {
@@ -304,11 +380,20 @@ func (m *DbMap) createTables(ifNotExists bool) error {
for i := range m.tables {
table := m.tables[i]
sql := table.SqlForCreate(ifNotExists)
_, err = m.Exec(sql)
_, err = m.ExecNoTimeout(sql)
if err != nil {
break
return err
}
}
for _, tbl := range m.dynamicTableMap() {
sql := tbl.SqlForCreate(ifNotExists)
_, err = m.ExecNoTimeout(sql)
if err != nil {
return err
}
}
return err
}
@@ -316,13 +401,25 @@ func (m *DbMap) createTables(ifNotExists bool) error {
// Returns an error when the table does not exist.
func (m *DbMap) DropTable(table interface{}) error {
t := reflect.TypeOf(table)
return m.dropTable(t, false)
tableName := ""
if dyn, ok := table.(DynamicTable); ok {
tableName = dyn.TableName()
}
return m.dropTable(t, tableName, false)
}
// DropTableIfExists drops an individual table when the table exists.
func (m *DbMap) DropTableIfExists(table interface{}) error {
t := reflect.TypeOf(table)
return m.dropTable(t, true)
tableName := ""
if dyn, ok := table.(DynamicTable); ok {
tableName = dyn.TableName()
}
return m.dropTable(t, tableName, true)
}
// DropTables iterates through TableMaps registered to this DbMap and
@@ -347,12 +444,20 @@ func (m *DbMap) dropTables(addIfExists bool) (err error) {
return err
}
}
for _, table := range m.dynamicTableMap() {
err = m.dropTableImpl(table, addIfExists)
if err != nil {
return err
}
}
return err
}
// Implementation of dropping a single table.
func (m *DbMap) dropTable(t reflect.Type, addIfExists bool) error {
table := tableOrNil(m, t)
func (m *DbMap) dropTable(t reflect.Type, name string, addIfExists bool) error {
table := tableOrNil(m, t, name)
if table == nil {
return fmt.Errorf("table %s was not registered", table.TableName)
}
@@ -365,7 +470,7 @@ func (m *DbMap) dropTableImpl(table *TableMap, ifExists bool) (err error) {
if ifExists {
tableDrop = m.Dialect.IfTableExists(tableDrop, table.SchemaName, table.TableName)
}
_, err = m.Exec(fmt.Sprintf("%s %s;", tableDrop, m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
_, err = m.ExecNoTimeout(fmt.Sprintf("%s %s;", tableDrop, m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
return err
}
@@ -377,11 +482,19 @@ func (m *DbMap) TruncateTables() error {
var err error
for i := range m.tables {
table := m.tables[i]
_, e := m.Exec(fmt.Sprintf("%s %s;", m.Dialect.TruncateClause(), m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
_, e := m.ExecNoTimeout(fmt.Sprintf("%s %s;", m.Dialect.TruncateClause(), m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
if e != nil {
err = e
}
}
for _, table := range m.dynamicTableMap() {
_, e := m.ExecNoTimeout(fmt.Sprintf("%s %s;", m.Dialect.TruncateClause(), m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName)))
if e != nil {
err = e
}
}
return err
}
@@ -487,12 +600,22 @@ func (m *DbMap) Select(i interface{}, query string, args ...interface{}) ([]inte
// Exec runs an arbitrary SQL statement. args represent the bind parameters.
// This is equivalent to running: Exec() using database/sql
// Times out based on the DbMap.QueryTimeout field
func (m *DbMap) Exec(query string, args ...interface{}) (sql.Result, error) {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
return exec(m, query, args...)
return exec(m, query, true, args...)
}
// ExecNoTimeout is the same as Exec except it will not time out
func (m *DbMap) ExecNoTimeout(query string, args ...interface{}) (sql.Result, error) {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
return exec(m, query, false, args...)
}
// SelectInt is a convenience wrapper around the gorp.SelectInt function
@@ -547,7 +670,7 @@ func (m *DbMap) Begin() (*Transaction, error) {
// If no table is mapped to that type an error is returned.
// If checkPK is true and the mapped table has no registered PKs, an error is returned.
func (m *DbMap) TableFor(t reflect.Type, checkPK bool) (*TableMap, error) {
table := tableOrNil(m, t)
table := tableOrNil(m, t, "")
if table == nil {
return nil, fmt.Errorf("no table found for type: %v", t.Name())
}
@@ -561,6 +684,25 @@ func (m *DbMap) TableFor(t reflect.Type, checkPK bool) (*TableMap, error) {
return table, nil
}
// DynamicTableFor returns the *TableMap for the dynamic table corresponding
// to the input tablename
// If no table is mapped to that tablename an error is returned.
// If checkPK is true and the mapped table has no registered PKs, an error is returned.
func (m *DbMap) DynamicTableFor(tableName string, checkPK bool) (*TableMap, error) {
table, found := m.dynamicTableFind(tableName)
if !found {
return nil, fmt.Errorf("gorp: no table found for name: %v", tableName)
}
if checkPK && len(table.keys) < 1 {
e := fmt.Sprintf("gorp: no keys defined for table: %s",
table.TableName)
return nil, errors.New(e)
}
return table, nil
}
// Prepare creates a prepared statement for later queries or executions.
// Multiple queries or executions may be run concurrently from the returned statement.
// This is equivalent to running: Prepare() using database/sql
@@ -572,7 +714,15 @@ func (m *DbMap) Prepare(query string) (*sql.Stmt, error) {
return m.Db.Prepare(query)
}
func tableOrNil(m *DbMap, t reflect.Type) *TableMap {
func tableOrNil(m *DbMap, t reflect.Type, name string) *TableMap {
if name != "" {
// Search by table name (dynamic tables)
if table, found := m.dynamicTableFind(name); found {
return table
}
return nil
}
for i := range m.tables {
table := m.tables[i]
if table.gotype == t {
@@ -590,8 +740,18 @@ func (m *DbMap) tableForPointer(ptr interface{}, checkPK bool) (*TableMap, refle
return nil, reflect.Value{}, errors.New(e)
}
elem := ptrv.Elem()
etype := reflect.TypeOf(elem.Interface())
t, err := m.TableFor(etype, checkPK)
ifc := elem.Interface()
var t *TableMap
var err error
tableName := ""
if dyn, isDyn := ptr.(DynamicTable); isDyn {
tableName = dyn.TableName()
t, err = m.DynamicTableFor(tableName, checkPK)
} else {
etype := reflect.TypeOf(ifc)
t, err = m.TableFor(etype, checkPK)
}
if err != nil {
return nil, reflect.Value{}, err
}
@@ -599,22 +759,42 @@ func (m *DbMap) tableForPointer(ptr interface{}, checkPK bool) (*TableMap, refle
return t, elem, nil
}
func (m *DbMap) queryRow(query string, args ...interface{}) *sql.Row {
func (m *DbMap) QueryRow(query string, args ...interface{}) *sql.Row {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
return m.Db.QueryRow(query, args...)
}
func (m *DbMap) query(query string, args ...interface{}) (*sql.Rows, error) {
func (m *DbMap) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
return m.Db.QueryRowContext(ctx, query, args...)
}
func (m *DbMap) Query(query string, args ...interface{}) (*sql.Rows, error) {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
return m.Db.Query(query, args...)
}
func (m *DbMap) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
if m.logger != nil {
now := time.Now()
defer m.trace(now, query, args...)
}
return m.Db.QueryContext(ctx, query, args...)
}
func (m *DbMap) trace(started time.Time, query string, args ...interface{}) {
if m.logger != nil {
var margs = argsString(args...)

3
vendor/github.com/go-gorp/gorp/dialect.go → vendor/github.com/mattermost/gorp/dialect.go сгенерированный поставляемый
Просмотреть файл

@@ -18,6 +18,9 @@ import "reflect"
// but this could change in the future
type Dialect interface {
// dialect name
Name() string
// adds a suffix to any query, usually ";"
QuerySuffix() string

Просмотреть файл

@@ -27,6 +27,8 @@ type MySQLDialect struct {
Encoding string
}
func (d MySQLDialect) Name() string { return "MySQLDialect" }
func (d MySQLDialect) QuerySuffix() string { return ";" }
func (d MySQLDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {

204
vendor/github.com/mattermost/gorp/dialect_mysql_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,204 @@
// Copyright 2012 James Cooper. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
// Package gorp provides a simple way to marshal Go structs to and from
// SQL databases. It uses the database/sql package, and should work with any
// compliant database/sql driver.
//
// Source code and project home:
// https://github.com/go-gorp/gorp
package gorp_test
import (
"database/sql"
"reflect"
"time"
// ginkgo/gomega functions read better as dot-imports.
. "github.com/onsi/ginkgo"
. "github.com/onsi/ginkgo/extensions/table"
. "github.com/onsi/gomega"
"github.com/go-gorp/gorp"
)
var _ = Describe("MySQLDialect", func() {
var (
engine, encoding string
dialect gorp.MySQLDialect
)
JustBeforeEach(func() {
dialect = gorp.MySQLDialect{
Engine: engine,
Encoding: encoding,
}
})
DescribeTable("ToSqlType",
func(value interface{}, maxsize int, autoIncr bool, expected string) {
typ := reflect.TypeOf(value)
sqlType := dialect.ToSqlType(typ, maxsize, autoIncr)
Expect(sqlType).To(Equal(expected))
},
Entry("bool", true, 0, false, "boolean"),
Entry("int8", int8(1), 0, false, "tinyint"),
Entry("uint8", uint8(1), 0, false, "tinyint unsigned"),
Entry("int16", int16(1), 0, false, "smallint"),
Entry("uint16", uint16(1), 0, false, "smallint unsigned"),
Entry("int32", int32(1), 0, false, "int"),
Entry("int (treated as int32)", int(1), 0, false, "int"),
Entry("uint32", uint32(1), 0, false, "int unsigned"),
Entry("uint (treated as uint32)", uint(1), 0, false, "int unsigned"),
Entry("int64", int64(1), 0, false, "bigint"),
Entry("uint64", uint64(1), 0, false, "bigint unsigned"),
Entry("float32", float32(1), 0, false, "double"),
Entry("float64", float64(1), 0, false, "double"),
Entry("[]uint8", []uint8{1}, 0, false, "mediumblob"),
Entry("NullInt64", sql.NullInt64{}, 0, false, "bigint"),
Entry("NullFloat64", sql.NullFloat64{}, 0, false, "double"),
Entry("NullBool", sql.NullBool{}, 0, false, "tinyint"),
Entry("Time", time.Time{}, 0, false, "datetime"),
Entry("default-size string", "", 0, false, "varchar(255)"),
Entry("sized string", "", 50, false, "varchar(50)"),
Entry("large string", "", 1024, false, "text"),
)
Describe("AutoIncrStr", func() {
It("returns the auto increment string", func() {
Expect(dialect.AutoIncrStr()).To(Equal("auto_increment"))
})
})
Describe("AutoIncrBindValue", func() {
It("returns the value used to bind the auto-increment value", func() {
Expect(dialect.AutoIncrBindValue()).To(Equal("null"))
})
})
Describe("AutoIncrInsertSuffix", func() {
It("returns the suffix needed for auto-incrementing", func() {
Expect(dialect.AutoIncrInsertSuffix(nil)).To(BeEmpty())
})
})
Describe("CreateTableSuffix", func() {
Context("with an empty engine", func() {
BeforeEach(func() {
engine = ""
encoding = "foo"
})
It("panics", func() {
Expect(func() {
dialect.CreateTableSuffix()
}).To(Panic())
})
})
Context("with an empty encoding", func() {
BeforeEach(func() {
engine = "foo"
encoding = ""
})
It("panics", func() {
Expect(func() {
dialect.CreateTableSuffix()
}).To(Panic())
})
})
Context("with an engine and an encoding", func() {
BeforeEach(func() {
engine = "foo"
encoding = "bar"
})
It("returns a valid suffix", func() {
Expect(dialect.CreateTableSuffix()).To(Equal(" engine=foo charset=bar"))
})
})
})
Describe("CreateIndexSuffix", func() {
It("returns the suffix for creating indexes", func() {
Expect(dialect.CreateIndexSuffix()).To(Equal("using"))
})
})
Describe("DropIndexSuffix", func() {
It("returns the suffix for deleting indexes", func() {
Expect(dialect.DropIndexSuffix()).To(Equal("on"))
})
})
Describe("TruncateClause", func() {
It("returns the clause for truncating a table", func() {
Expect(dialect.TruncateClause()).To(Equal("truncate"))
})
})
Describe("BindVar", func() {
It("returns the variable binding sequence", func() {
Expect(dialect.BindVar(0)).To(Equal("?"))
})
})
PDescribe("InsertAutoIncr", func() {})
Describe("QuoteField", func() {
It("returns the argument quoted as a field", func() {
Expect(dialect.QuoteField("foo")).To(Equal("`foo`"))
})
})
Describe("QuotedTableForQuery", func() {
var (
schema, table string
quotedTable string
)
JustBeforeEach(func() {
quotedTable = dialect.QuotedTableForQuery(schema, table)
})
Context("using the default schema", func() {
BeforeEach(func() {
schema = ""
table = "foo"
})
It("returns just the table", func() {
Expect(quotedTable).To(Equal("`foo`"))
})
})
Context("with a supplied schema", func() {
BeforeEach(func() {
schema = "foo"
table = "bar"
})
It("returns the schema and table", func() {
Expect(quotedTable).To(Equal("foo.`bar`"))
})
})
})
Describe("IfSchemaNotExists", func() {
It("appends 'if not exists' to the command", func() {
Expect(dialect.IfSchemaNotExists("foo", "bar")).To(Equal("foo if not exists"))
})
})
Describe("IfTableExists", func() {
It("appends 'if exists' to the command", func() {
Expect(dialect.IfTableExists("foo", "bar", "baz")).To(Equal("foo if exists"))
})
})
Describe("IfTableNotExists", func() {
It("appends 'if not exists' to the command", func() {
Expect(dialect.IfTableNotExists("foo", "bar", "baz")).To(Equal("foo if not exists"))
})
})
})

Просмотреть файл

@@ -20,6 +20,8 @@ import (
// Implementation of Dialect for Oracle databases.
type OracleDialect struct{}
func (d OracleDialect) Name() string { return "OracleDialect" }
func (d OracleDialect) QuerySuffix() string { return "" }
func (d OracleDialect) CreateIndexSuffix() string { return "" }

Просмотреть файл

@@ -21,6 +21,8 @@ type PostgresDialect struct {
suffix string
}
func (d PostgresDialect) Name() string { return "PostgresDialect" }
func (d PostgresDialect) QuerySuffix() string { return ";" }
func (d PostgresDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
@@ -78,7 +80,7 @@ func (d PostgresDialect) AutoIncrBindValue() string {
}
func (d PostgresDialect) AutoIncrInsertSuffix(col *ColumnMap) string {
return " returning " + col.ColumnName
return " returning " + d.QuoteField(col.ColumnName)
}
// Returns suffix
@@ -104,7 +106,7 @@ func (d PostgresDialect) BindVar(i int) string {
}
func (d PostgresDialect) InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error {
rows, err := exec.query(insertSql, params...)
rows, err := exec.Query(insertSql, params...)
if err != nil {
return err
}

Просмотреть файл

@@ -20,6 +20,8 @@ type SqliteDialect struct {
suffix string
}
func (d SqliteDialect) Name() string { return "SQLiteDialect" }
func (d SqliteDialect) QuerySuffix() string { return ";" }
func (d SqliteDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {

Просмотреть файл

@@ -27,6 +27,8 @@ type SqlServerDialect struct {
Version string
}
func (d SqlServerDialect) Name() string { return "SQLServerDialect" }
func (d SqlServerDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string {
switch val.Kind() {
case reflect.Ptr:

0
vendor/github.com/go-gorp/gorp/errors.go → vendor/github.com/mattermost/gorp/errors.go сгенерированный поставляемый
Просмотреть файл

73
vendor/github.com/go-gorp/gorp/gorp.go → vendor/github.com/mattermost/gorp/gorp.go сгенерированный поставляемый
Просмотреть файл

@@ -12,6 +12,7 @@
package gorp
import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
@@ -87,6 +88,7 @@ type TypeConverter interface {
// on internal functions that convert named parameters for the Exec function.
type executor interface {
Exec(query string, args ...interface{}) (sql.Result, error)
ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
}
// SqlExecutor exposes gorp operations that can be run from Pre/Post
@@ -101,6 +103,7 @@ type SqlExecutor interface {
Update(list ...interface{}) (int64, error)
Delete(list ...interface{}) (int64, error)
Exec(query string, args ...interface{}) (sql.Result, error)
ExecNoTimeout(query string, args ...interface{}) (sql.Result, error)
Select(i interface{}, query string,
args ...interface{}) ([]interface{}, error)
SelectInt(query string, args ...interface{}) (int64, error)
@@ -110,8 +113,18 @@ type SqlExecutor interface {
SelectStr(query string, args ...interface{}) (string, error)
SelectNullStr(query string, args ...interface{}) (sql.NullString, error)
SelectOne(holder interface{}, query string, args ...interface{}) error
query(query string, args ...interface{}) (*sql.Rows, error)
queryRow(query string, args ...interface{}) *sql.Row
Query(query string, args ...interface{}) (*sql.Rows, error)
QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
QueryRow(query string, args ...interface{}) *sql.Row
QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row
}
// DynamicTable allows the users of gorp to dynamically
// use different database table names during runtime
// while sharing the same golang struct for in-memory data
type DynamicTable interface {
TableName() string
SetTableName(string)
}
// Compile-time check that DbMap and Transaction implement the SqlExecutor
@@ -144,7 +157,7 @@ func argsString(args ...interface{}) string {
// Calls the Exec function on the executor, but attempts to expand any eligible named
// query arguments first.
func exec(e SqlExecutor, query string, args ...interface{}) (sql.Result, error) {
func exec(e SqlExecutor, query string, doTimeout bool, args ...interface{}) (sql.Result, error) {
var dbMap *DbMap
var executor executor
switch m := e.(type) {
@@ -160,7 +173,13 @@ func exec(e SqlExecutor, query string, args ...interface{}) (sql.Result, error)
query, args = maybeExpandNamedQuery(dbMap, query, args)
}
return executor.Exec(query, args...)
if doTimeout && dbMap.Dialect.Name() != "PostgresDialect" {
ctx, cancel := context.WithTimeout(context.Background(), dbMap.QueryTimeout)
defer cancel()
return executor.ExecContext(ctx, query, args...)
} else {
return executor.Exec(query, args...)
}
}
// maybeExpandNamedQuery checks the given arg to see if it's eligible to be used
@@ -220,13 +239,13 @@ func expandNamedQuery(m *DbMap, query string, keyGetter func(key string) reflect
}), args
}
func columnToFieldIndex(m *DbMap, t reflect.Type, cols []string) ([][]int, error) {
func columnToFieldIndex(m *DbMap, t reflect.Type, name string, cols []string) ([][]int, error) {
colToFieldIndex := make([][]int, len(cols))
// check if type t is a mapped table - if so we'll
// check the table for column aliasing below
tableMapped := false
table := tableOrNil(m, t)
table := tableOrNil(m, t, name)
if table != nil {
tableMapped = true
}
@@ -327,6 +346,30 @@ func toType(i interface{}) (reflect.Type, error) {
return t, nil
}
type foundTable struct {
table *TableMap
dynName *string
}
func tableFor(m *DbMap, t reflect.Type, i interface{}) (*foundTable, error) {
if dyn, isDynamic := i.(DynamicTable); isDynamic {
tableName := dyn.TableName()
table, err := m.DynamicTableFor(tableName, true)
if err != nil {
return nil, err
}
return &foundTable{
table: table,
dynName: &tableName,
}, nil
}
table, err := m.TableFor(t, true)
if err != nil {
return nil, err
}
return &foundTable{table: table}, nil
}
func get(m *DbMap, exec SqlExecutor, i interface{},
keys ...interface{}) (interface{}, error) {
@@ -335,14 +378,20 @@ func get(m *DbMap, exec SqlExecutor, i interface{},
return nil, err
}
table, err := m.TableFor(t, true)
foundTable, err := tableFor(m, t, i)
if err != nil {
return nil, err
}
table := foundTable.table
plan := table.bindGet()
v := reflect.New(t)
if foundTable.dynName != nil {
retDyn := v.Interface().(DynamicTable)
retDyn.SetTableName(*foundTable.dynName)
}
dest := make([]interface{}, len(plan.argFields))
conv := m.TypeConverter
@@ -361,7 +410,15 @@ func get(m *DbMap, exec SqlExecutor, i interface{},
dest[x] = target
}
row := exec.queryRow(plan.query, keys...)
var row *sql.Row
if m.Dialect.Name() != "PostgresDialect" {
ctx, cancel := context.WithTimeout(context.Background(), m.QueryTimeout)
defer cancel()
row = exec.QueryRowContext(ctx, plan.query, keys...)
} else {
row = exec.QueryRow(plan.query, keys...)
}
err = row.Scan(dest...)
if err != nil {
if err == sql.ErrNoRows {

13
vendor/github.com/mattermost/gorp/gorp_suite_test.go сгенерированный поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,13 @@
package gorp_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"testing"
)
func TestGorp(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Gorp Suite")
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

0
vendor/github.com/go-gorp/gorp/hooks.go → vendor/github.com/mattermost/gorp/hooks.go сгенерированный поставляемый
Просмотреть файл

0
vendor/github.com/go-gorp/gorp/index.go → vendor/github.com/mattermost/gorp/index.go сгенерированный поставляемый
Просмотреть файл

Просмотреть файл

0
vendor/github.com/go-gorp/gorp/logging.go → vendor/github.com/mattermost/gorp/logging.go сгенерированный поставляемый
Просмотреть файл

Просмотреть файл

60
vendor/github.com/go-gorp/gorp/select.go → vendor/github.com/mattermost/gorp/select.go сгенерированный поставляемый
Просмотреть файл

@@ -12,6 +12,7 @@
package gorp
import (
"context"
"database/sql"
"fmt"
"reflect"
@@ -154,15 +155,28 @@ func SelectOne(m *DbMap, e SqlExecutor, holder interface{}, query string, args .
}
func selectVal(e SqlExecutor, holder interface{}, query string, args ...interface{}) error {
if len(args) == 1 {
switch m := e.(type) {
case *DbMap:
query, args = maybeExpandNamedQuery(m, query, args)
case *Transaction:
query, args = maybeExpandNamedQuery(m.dbmap, query, args)
}
var dbMap *DbMap
switch m := e.(type) {
case *DbMap:
dbMap = m
case *Transaction:
dbMap = m.dbmap
}
rows, err := e.query(query, args...)
if len(args) == 1 {
query, args = maybeExpandNamedQuery(dbMap, query, args)
}
var rows *sql.Rows
var err error
if dbMap.Dialect.Name() != "PostgresDialect" {
ctx, cancel := context.WithTimeout(context.Background(), dbMap.QueryTimeout)
defer cancel()
rows, err = e.QueryContext(ctx, query, args...)
} else {
rows, err = e.Query(query, args...)
}
if err != nil {
return err
}
@@ -178,14 +192,11 @@ func selectVal(e SqlExecutor, holder interface{}, query string, args ...interfac
func hookedselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
args ...interface{}) ([]interface{}, error) {
var nonFatalErr error
list, err := rawselect(m, exec, i, query, args...)
if err != nil {
if !NonFatalError(err) {
return nil, err
}
nonFatalErr = err
}
// Determine where the results are: written to i, or returned in list
@@ -209,7 +220,8 @@ func hookedselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
}
}
}
return list, nonFatalErr
return list, nil
}
func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
@@ -222,6 +234,13 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
var nonFatalErr error
tableName := ""
var dynObj DynamicTable
isDynamic := false
if dynObj, isDynamic = i.(DynamicTable); isDynamic {
tableName = dynObj.TableName()
}
// get type for i, verifying it's a supported destination
t, err := toType(i)
if err != nil {
@@ -248,7 +267,15 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
}
// Run the query
rows, err := exec.query(query, args...)
var rows *sql.Rows
if m.Dialect.Name() != "PostgresDialect" {
ctx, cancel := context.WithTimeout(context.Background(), m.QueryTimeout)
defer cancel()
rows, err = exec.QueryContext(ctx, query, args...)
} else {
rows, err = exec.Query(query, args...)
}
if err != nil {
return nil, err
}
@@ -266,7 +293,7 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
var colToFieldIndex [][]int
if intoStruct {
colToFieldIndex, err = columnToFieldIndex(m, t, cols)
colToFieldIndex, err = columnToFieldIndex(m, t, tableName, cols)
if err != nil {
if !NonFatalError(err) {
return nil, err
@@ -293,6 +320,11 @@ func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string,
break
}
v := reflect.New(t)
if isDynamic {
v.Interface().(DynamicTable).SetTableName(tableName)
}
dest := make([]interface{}, len(cols))
custScan := make([]CustomScanner, 0)

0
vendor/github.com/go-gorp/gorp/table.go → vendor/github.com/mattermost/gorp/table.go сгенерированный поставляемый
Просмотреть файл

Просмотреть файл

Просмотреть файл

@@ -5,6 +5,9 @@
coveralls_testflags="-v -covermode=count -coverprofile=coverage.out"
echo "Running unit tests"
ginkgo -r -race -randomizeAllSpecs -keepGoing -- -test.run TestGorp
echo "Testing against mysql"
export GORP_TEST_DSN=gorptest/gorptest/gorptest
export GORP_TEST_DIALECT=mysql

Просмотреть файл

@@ -12,6 +12,7 @@
package gorp
import (
"context"
"database/sql"
"time"
)
@@ -62,7 +63,16 @@ func (t *Transaction) Exec(query string, args ...interface{}) (sql.Result, error
now := time.Now()
defer t.dbmap.trace(now, query, args...)
}
return exec(t, query, args...)
return exec(t, query, true, args...)
}
// ExecNoTimeout has the same behavior as DbMap.ExecNoTimeout(), but runs in a transaction.
func (t *Transaction) ExecNoTimeout(query string, args ...interface{}) (sql.Result, error) {
if t.dbmap.logger != nil {
now := time.Now()
defer t.dbmap.trace(now, query, args...)
}
return exec(t, query, false, args...)
}
// SelectInt is a convenience wrapper around the gorp.SelectInt function.
@@ -176,7 +186,7 @@ func (t *Transaction) Prepare(query string) (*sql.Stmt, error) {
return t.tx.Prepare(query)
}
func (t *Transaction) queryRow(query string, args ...interface{}) *sql.Row {
func (t *Transaction) QueryRow(query string, args ...interface{}) *sql.Row {
if t.dbmap.logger != nil {
now := time.Now()
defer t.dbmap.trace(now, query, args...)
@@ -184,10 +194,26 @@ func (t *Transaction) queryRow(query string, args ...interface{}) *sql.Row {
return t.tx.QueryRow(query, args...)
}
func (t *Transaction) query(query string, args ...interface{}) (*sql.Rows, error) {
func (t *Transaction) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row {
if t.dbmap.logger != nil {
now := time.Now()
defer t.dbmap.trace(now, query, args...)
}
return t.tx.QueryRowContext(ctx, query, args...)
}
func (t *Transaction) Query(query string, args ...interface{}) (*sql.Rows, error) {
if t.dbmap.logger != nil {
now := time.Now()
defer t.dbmap.trace(now, query, args...)
}
return t.tx.Query(query, args...)
}
func (t *Transaction) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error) {
if t.dbmap.logger != nil {
now := time.Now()
defer t.dbmap.trace(now, query, args...)
}
return t.tx.QueryContext(ctx, query, args...)
}

Просмотреть файл

@@ -29,6 +29,7 @@ export default class DatabaseSettings extends AdminSettings {
config.SqlSettings.MaxOpenConns = this.parseIntNonZero(this.state.maxOpenConns);
config.SqlSettings.AtRestEncryptKey = this.state.atRestEncryptKey;
config.SqlSettings.Trace = this.state.trace;
config.SqlSettings.QueryTimeout = this.parseIntNonZero(this.state.queryTimeout);
return config;
}
@@ -40,7 +41,8 @@ export default class DatabaseSettings extends AdminSettings {
maxIdleConns: config.SqlSettings.MaxIdleConns,
maxOpenConns: config.SqlSettings.MaxOpenConns,
atRestEncryptKey: config.SqlSettings.AtRestEncryptKey,
trace: config.SqlSettings.Trace
trace: config.SqlSettings.Trace,
queryTimeout: config.SqlSettings.QueryTimeout
};
}
@@ -128,6 +130,24 @@ export default class DatabaseSettings extends AdminSettings {
value={this.state.maxOpenConns}
onChange={this.handleChange}
/>
<TextSetting
id='queryTimeout'
label={
<FormattedMessage
id='admin.sql.queryTimeoutTitle'
defaultMessage='Query Timeout:'
/>
}
placeholder={Utils.localizeMessage('admin.sql.queryTimeoutExample', 'Ex "30"')}
helpText={
<FormattedMessage
id='admin.sql.queryTimeoutDescription'
defaultMessage='The number of seconds to wait for a response from the database after opening a connection and sending the query. Errors that you see in the UI or in the logs as a result of a query timeout can vary depending on the type of query. This setting has no effect on PostgreSQL databases.'
/>
}
value={this.state.queryTimeout}
onChange={this.handleChange}
/>
<GeneratedSetting
id='atRestEncryptKey'
label={

Просмотреть файл

@@ -818,6 +818,9 @@
"admin.sql.keyTitle": "At Rest Encrypt Key:",
"admin.sql.maxConnectionsDescription": "Maximum number of idle connections held open to the database.",
"admin.sql.maxConnectionsExample": "E.g.: \"10\"",
"admin.sql.queryTimeoutTitle": "Query Timeout:",
"admin.sql.queryTimeoutDescription": "The number of seconds to wait for a response from the database after opening a connection and sending the query. Errors that you see in the UI or in the logs as a result of a query timeout can vary depending on the type of query. This setting has no effect on PostgreSQL databases.",
"admin.sql.queryTimeoutExample": "E.g.: \"30\"",
"admin.sql.maxConnectionsTitle": "Maximum Idle Connections:",
"admin.sql.maxOpenDescription": "Maximum number of open connections held open to the database.",
"admin.sql.maxOpenExample": "E.g.: \"10\"",