diff --git a/app/plugin_api_tests/test_db_driver/main.go b/app/plugin_api_tests/test_db_driver/main.go index cec9cad094..c97b10ed2e 100644 --- a/app/plugin_api_tests/test_db_driver/main.go +++ b/app/plugin_api_tests/test_db_driver/main.go @@ -32,13 +32,10 @@ func (p *MyPlugin) MessageWillBePosted(_ *plugin.Context, _ *model.Post) (*model settings := p.API.GetUnsanitizedConfig().SqlSettings settings.Trace = model.NewBool(false) store := sqlstore.New(settings, nil) - store.GetMaster().Db.Close() + store.GetMasterX().Close() for _, isMaster := range []bool{true, false} { - // We replace the master DB with master and replica both just to make - // gorp APIs work. handle := sql.OpenDB(driver.NewConnector(p.Driver, isMaster)) - store.GetMaster().Db = handle store.SetMasterX(handle) wrapper := sqlstore.NewStoreTestWrapper(store) @@ -49,7 +46,7 @@ func (p *MyPlugin) MessageWillBePosted(_ *plugin.Context, _ *model.Post) (*model storetest.TestChannelStore(p.t, store, wrapper) storetest.TestBotStore(p.t, store, wrapper) - store.GetMaster().Db.Close() + store.GetMasterX().Close() } // Use the API to instantiate the driver diff --git a/app/plugin_db_driver.go b/app/plugin_db_driver.go index 6b99602a61..2b9cfbac7d 100644 --- a/app/plugin_db_driver.go +++ b/app/plugin_db_driver.go @@ -40,11 +40,11 @@ func NewDriverImpl(s *Server) *DriverImpl { } func (d *DriverImpl) Conn(isMaster bool) (string, error) { - dbFunc := d.s.sqlStore.GetMaster + dbFunc := d.s.sqlStore.GetMasterX if !isMaster { - dbFunc = d.s.sqlStore.GetReplica + dbFunc = d.s.sqlStore.GetReplicaX } - conn, err := dbFunc().Db.Conn(context.Background()) + conn, err := dbFunc().Conn(context.Background()) if err != nil { return "", err } diff --git a/app/server_test.go b/app/server_test.go index 29b2e78aef..e2d650c789 100644 --- a/app/server_test.go +++ b/app/server_test.go @@ -90,7 +90,7 @@ func TestReadReplicaDisabledBasedOnLicense(t *testing.T) { }) require.NoError(t, err) defer s.Shutdown() - require.Same(t, s.sqlStore.GetMaster(), s.sqlStore.GetReplica()) + require.Same(t, s.sqlStore.GetMasterX(), s.sqlStore.GetReplicaX()) require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 1) }) @@ -103,7 +103,7 @@ func TestReadReplicaDisabledBasedOnLicense(t *testing.T) { }) require.NoError(t, err) defer s.Shutdown() - require.NotSame(t, s.sqlStore.GetMaster(), s.sqlStore.GetReplica()) + require.NotSame(t, s.sqlStore.GetMasterX(), s.sqlStore.GetReplicaX()) require.Len(t, s.Config().SqlSettings.DataSourceReplicas, 1) }) @@ -116,7 +116,7 @@ func TestReadReplicaDisabledBasedOnLicense(t *testing.T) { }) require.NoError(t, err) defer s.Shutdown() - require.Same(t, s.sqlStore.GetMaster(), s.sqlStore.GetSearchReplica()) + require.Same(t, s.sqlStore.GetMasterX(), s.sqlStore.GetSearchReplicaX()) require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 1) }) @@ -130,7 +130,7 @@ func TestReadReplicaDisabledBasedOnLicense(t *testing.T) { }) require.NoError(t, err) defer s.Shutdown() - require.NotSame(t, s.sqlStore.GetMaster(), s.sqlStore.GetSearchReplica()) + require.NotSame(t, s.sqlStore.GetMasterX(), s.sqlStore.GetSearchReplicaX()) require.Len(t, s.Config().SqlSettings.DataSourceSearchReplicas, 1) }) } diff --git a/config/database_test.go b/config/database_test.go index 3dccfce6b3..f6eaeaa289 100644 --- a/config/database_test.go +++ b/config/database_test.go @@ -12,7 +12,6 @@ import ( "testing" "time" - "github.com/jmoiron/sqlx" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -80,8 +79,7 @@ func getActualDatabaseConfig(t *testing.T) (string, *model.Config) { ID string `db:"id"` Value []byte `db:"value"` } - db := sqlx.NewDb(mainHelper.GetSQLStore().GetMaster().Db, *mainHelper.GetSQLSettings().DriverName) - err := db.Get(&actual, "SELECT Id, Value FROM Configurations WHERE Active") + err := mainHelper.GetSQLStore().GetMasterX().Get(&actual, "SELECT Id, Value FROM Configurations WHERE Active") require.NoError(t, err) var actualCfg *model.Config @@ -93,8 +91,7 @@ func getActualDatabaseConfig(t *testing.T) (string, *model.Config) { ID string `db:"Id"` Value []byte `db:"Value"` } - db := sqlx.NewDb(mainHelper.GetSQLStore().GetMaster().Db, *mainHelper.GetSQLSettings().DriverName) - err := db.Get(&actual, "SELECT Id, Value FROM Configurations WHERE Active") + err := mainHelper.GetSQLStore().GetMasterX().Get(&actual, "SELECT Id, Value FROM Configurations WHERE Active") require.NoError(t, err) var actualCfg *model.Config @@ -553,9 +550,7 @@ func TestDatabaseStoreSet(t *testing.T) { require.NoError(t, err) defer ds.Close() - sqlSettings := mainHelper.GetSQLSettings() - db := sqlx.NewDb(mainHelper.GetSQLStore().GetMaster().Db, *sqlSettings.DriverName) - _, err = db.Exec("DROP TABLE Configurations") + _, err = mainHelper.GetSQLStore().GetMasterX().Exec("DROP TABLE Configurations") require.NoError(t, err) newCfg := minimalConfig @@ -835,16 +830,15 @@ func TestDatabaseStoreLoad(t *testing.T) { cfgData, err := marshalConfig(invalidConfig) require.NoError(t, err) - sqlSettings := mainHelper.GetSQLSettings() - db := sqlx.NewDb(mainHelper.GetSQLStore().GetMaster().Db, *sqlSettings.DriverName) truncateTables(t) id := model.NewId() - _, err = db.NamedExec("INSERT INTO Configurations (Id, Value, CreateAt, Active) VALUES(:Id, :Value, :CreateAt, TRUE)", map[string]interface{}{ - "Id": id, - "Value": cfgData, - "CreateAt": model.GetMillis(), + _, err = mainHelper.GetSQLStore().GetMasterX().NamedExec("INSERT INTO Configurations (Id, Value, CreateAt, Active) VALUES(:id, :value, :createat, TRUE)", map[string]interface{}{ + "id": id, + "value": cfgData, + "createat": model.GetMillis(), }) - require.NoError(t, err) + t.Logf("%v\n", err) + require.NoErrorf(t, err, "what is - %v", err) err = ds.Load() if assert.Error(t, err) { diff --git a/config/main_test.go b/config/main_test.go index 2d203bbb75..c2468e7963 100644 --- a/config/main_test.go +++ b/config/main_test.go @@ -36,7 +36,7 @@ func truncateTable(t *testing.T, table string) { switch *sqlSetting.DriverName { case model.DatabaseDriverMysql: - _, err := sqlStore.GetMaster().Db.Exec(fmt.Sprintf("TRUNCATE TABLE %s", table)) + _, err := sqlStore.GetMasterX().Exec(fmt.Sprintf("TRUNCATE TABLE %s", table)) if err != nil { if driverErr, ok := err.(*mysql.MySQLError); ok { // Ignore if the Configurations table does not exist. @@ -48,7 +48,7 @@ func truncateTable(t *testing.T, table string) { require.NoError(t, err) case model.DatabaseDriverPostgres: - _, err := sqlStore.GetMaster().Db.Exec(fmt.Sprintf("TRUNCATE TABLE %s", table)) + _, err := sqlStore.GetMasterX().Exec(fmt.Sprintf("TRUNCATE TABLE %s", table)) if err != nil { if driverErr, ok := err.(*pq.Error); ok { // Ignore if the Configurations table does not exist. diff --git a/go.mod b/go.mod index c0509e68a2..16c29addd8 100644 --- a/go.mod +++ b/go.mod @@ -59,7 +59,6 @@ require ( github.com/lib/pq v1.10.4 github.com/mailru/easyjson v0.7.7 // indirect github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 - github.com/mattermost/gorp v1.6.2-0.20210714143452-8b50f5209a7f github.com/mattermost/gosaml2 v0.3.3 github.com/mattermost/gziphandler v0.0.1 github.com/mattermost/ldap v0.0.0-20201202150706-ee0e6284187d @@ -67,6 +66,7 @@ require ( github.com/mattermost/morph v0.0.0-20220222074146-cff3f12ff131 github.com/mattermost/rsc v0.0.0-20160330161541-bbaefb05eaa0 github.com/mattn/go-runewidth v0.0.13 // indirect + github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect github.com/mholt/archiver/v3 v3.5.1 github.com/microcosm-cc/bluemonday v1.0.18 github.com/miekg/dns v1.1.46 // indirect diff --git a/go.sum b/go.sum index 6a68235555..cc561500e0 100644 --- a/go.sum +++ b/go.sum @@ -995,8 +995,6 @@ github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kN github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404 h1:Khvh6waxG1cHc4Cz5ef9n3XVCxRWpAKUtqg9PJl5+y8= github.com/mattermost/go-i18n v1.11.1-0.20211013152124-5c415071e404/go.mod h1:RyS7FDNQlzF1PsjbJWHRI35exqaKGSO9qD4iv8QjE34= -github.com/mattermost/gorp v1.6.2-0.20210714143452-8b50f5209a7f h1:J47te5ubXIEbEaXi/nwStKQ/sLniXACgZ7LhK365YIY= -github.com/mattermost/gorp v1.6.2-0.20210714143452-8b50f5209a7f/go.mod h1:QCQ3U0M9T/BlAdjKFJo0I1oe/YAgbyjNdhU8bpOLafk= github.com/mattermost/gosaml2 v0.3.3 h1:ysWrjp08tpWmo6rV2MQ88Eag/Ttjuj91fZsvibF4/Tg= github.com/mattermost/gosaml2 v0.3.3/go.mod h1:Z429EIOiEi9kbq6yHoApfzlcXpa6dzRDc6pO+Vy2Ksk= github.com/mattermost/gziphandler v0.0.1 h1:uXHcXF5agnQ6bXabvpiwwwZOlCYoa7mKHH0lxns/o8w= @@ -1149,7 +1147,6 @@ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= @@ -1326,7 +1323,6 @@ github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiB github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -1530,8 +1526,6 @@ github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= -github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= diff --git a/i18n/en.json b/i18n/en.json index 92dbe47b30..fa9cb87050 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -9191,18 +9191,6 @@ "id": "sharedchannel.permalink.not_found", "translation": "This post contains permalinks to other channels which may not be visible to users in other sites." }, - { - "id": "store.sql.convert_string_array", - "translation": "FromDb: Unable to convert StringArray to *string" - }, - { - "id": "store.sql.convert_string_interface", - "translation": "FromDb: Unable to convert StringInterface to *string" - }, - { - "id": "store.sql.convert_string_map", - "translation": "FromDb: Unable to convert StringMap to *string" - }, { "id": "store.sql_bot.get.missing.app_error", "translation": "Bot does not exist." diff --git a/store/sqlstore/adapters.go b/store/sqlstore/adapters.go index 2e264834f4..c7b1e95632 100644 --- a/store/sqlstore/adapters.go +++ b/store/sqlstore/adapters.go @@ -6,17 +6,11 @@ package sqlstore import ( "bytes" "database/sql/driver" - "encoding/json" "fmt" "strconv" "strings" - "github.com/dyatlov/go-opengraph/opengraph" - "github.com/mattermost/gorp" - "github.com/mattermost/mattermost-server/v6/model" - "github.com/mattermost/mattermost-server/v6/shared/i18n" "github.com/mattermost/mattermost-server/v6/shared/mlog" - "github.com/pkg/errors" ) type jsonArray []string @@ -68,85 +62,3 @@ func (t *TraceOnAdapter) Printf(format string, v ...interface{}) { type JSONSerializable interface { ToJSON() string } - -type mattermConverter struct{} - -func (me mattermConverter) ToDb(val interface{}) (interface{}, error) { - switch t := val.(type) { - case model.StringMap: - return model.MapToJSON(t), nil - case map[string]string: - return model.MapToJSON(model.StringMap(t)), nil - case model.StringArray: - return model.ArrayToJSON(t), nil - case model.StringInterface: - return model.StringInterfaceToJSON(t), nil - case map[string]interface{}: - return model.StringInterfaceToJSON(model.StringInterface(t)), nil - case JSONSerializable: - return t.ToJSON(), nil - case *opengraph.OpenGraph: - return json.Marshal(t) - case *model.PostImage: - return json.Marshal(t) - } - - return val, nil -} - -func (me mattermConverter) FromDb(target interface{}) (gorp.CustomScanner, bool) { - switch target.(type) { - case *model.StringMap: - binder := func(holder, target interface{}) error { - s, ok := holder.(*string) - if !ok { - return errors.New(i18n.T("store.sql.convert_string_map")) - } - b := []byte(*s) - return json.Unmarshal(b, target) - } - return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true - case *map[string]string: - binder := func(holder, target interface{}) error { - s, ok := holder.(*string) - if !ok { - return errors.New(i18n.T("store.sql.convert_string_map")) - } - b := []byte(*s) - return json.Unmarshal(b, target) - } - return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true - case *model.StringArray: - binder := func(holder, target interface{}) error { - s, ok := holder.(*string) - if !ok { - return errors.New(i18n.T("store.sql.convert_string_array")) - } - b := []byte(*s) - return json.Unmarshal(b, target) - } - return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true - case *model.StringInterface: - binder := func(holder, target interface{}) error { - s, ok := holder.(*string) - if !ok { - return errors.New(i18n.T("store.sql.convert_string_interface")) - } - b := []byte(*s) - return json.Unmarshal(b, target) - } - return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true - case *map[string]interface{}: - binder := func(holder, target interface{}) error { - s, ok := holder.(*string) - if !ok { - return errors.New(i18n.T("store.sql.convert_string_interface")) - } - b := []byte(*s) - return json.Unmarshal(b, target) - } - return gorp.CustomScanner{Holder: new(string), Target: target, Binder: binder}, true - } - - return gorp.CustomScanner{}, false -} diff --git a/store/sqlstore/context.go b/store/sqlstore/context.go index d1bbb27536..859fbe0027 100644 --- a/store/sqlstore/context.go +++ b/store/sqlstore/context.go @@ -5,8 +5,6 @@ package sqlstore import ( "context" - - "github.com/mattermost/gorp" ) // storeContextKey is the base type for all context keys for the store. @@ -35,14 +33,6 @@ func hasMaster(ctx context.Context) bool { return false } -// DBFromContext is a helper utility that returns the DB handle from a given context. -func (ss *SqlStore) DBFromContext(ctx context.Context) *gorp.DbMap { - if hasMaster(ctx) { - return ss.GetMaster() - } - return ss.GetReplica() -} - // DBXFromContext is a helper utility that returns the sqlx DB handle from a given context. func (ss *SqlStore) DBXFromContext(ctx context.Context) *sqlxDBWrapper { if hasMaster(ctx) { diff --git a/store/sqlstore/preference_store_test.go b/store/sqlstore/preference_store_test.go index c97f84cffc..4bf7413181 100644 --- a/store/sqlstore/preference_store_test.go +++ b/store/sqlstore/preference_store_test.go @@ -58,22 +58,23 @@ func TestDeleteUnusedFeatures(t *testing.T) { ss.Preference().(*SqlPreferenceStore).deleteUnusedFeatures() //make sure features with value "false" have actually been deleted from the database - if val, err := ss.Preference().(*SqlPreferenceStore).GetReplica().SelectInt(`SELECT COUNT(*) + var val int64 + if err := ss.Preference().(*SqlPreferenceStore).GetReplicaX().Get(&val, `SELECT COUNT(*) FROM Preferences - WHERE Category = :Category - AND Value = :Val - AND Name LIKE '`+store.FeatureTogglePrefix+`%'`, map[string]interface{}{"Category": model.PreferenceCategoryAdvancedSettings, "Val": "false"}); err != nil { + WHERE Category = ? + AND Value = ? + AND Name LIKE '`+store.FeatureTogglePrefix+`%'`, model.PreferenceCategoryAdvancedSettings, "false"); err != nil { require.NoError(t, err) } else if val != 0 { require.Fail(t, "Found %d features with value 'false', expected all to be deleted", val) } // // make sure features with value "true" remain saved - if val, err := ss.Preference().(*SqlPreferenceStore).GetReplica().SelectInt(`SELECT COUNT(*) + if err := ss.Preference().(*SqlPreferenceStore).GetReplicaX().Get(&val, `SELECT COUNT(*) FROM Preferences - WHERE Category = :Category - AND Value = :Val - AND Name LIKE '`+store.FeatureTogglePrefix+`%'`, map[string]interface{}{"Category": model.PreferenceCategoryAdvancedSettings, "Val": "true"}); err != nil { + WHERE Category = ? + AND Value = ? + AND Name LIKE '`+store.FeatureTogglePrefix+`%'`, model.PreferenceCategoryAdvancedSettings, "true"); err != nil { require.NoError(t, err) } else if val == 0 { require.Fail(t, "Found %d features with value 'true', expected to find at least %d features", val, 2) diff --git a/store/sqlstore/sqlx_wrapper.go b/store/sqlstore/sqlx_wrapper.go index 6bf8973d1c..b29d56ce96 100644 --- a/store/sqlstore/sqlx_wrapper.go +++ b/store/sqlstore/sqlx_wrapper.go @@ -14,7 +14,6 @@ import ( "github.com/jmoiron/sqlx" - "github.com/mattermost/gorp" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" "github.com/mattermost/mattermost-server/v6/store/storetest" @@ -28,10 +27,6 @@ func NewStoreTestWrapper(orig *SqlStore) *StoreTestWrapper { return &StoreTestWrapper{orig} } -func (w *StoreTestWrapper) GetMaster() *gorp.DbMap { - return w.orig.GetMaster() -} - func (w *StoreTestWrapper) GetMasterX() storetest.SqlXExecutor { return w.orig.GetMasterX() } @@ -251,6 +246,18 @@ func (w *sqlxTxWrapper) Exec(query string, args ...interface{}) (sql.Result, err return w.ExecRaw(query, args...) } +func (w *sqlxTxWrapper) ExecNoTimeout(query string, args ...interface{}) (sql.Result, error) { + query = w.Tx.Rebind(query) + + if w.trace { + defer func(then time.Time) { + printArgs(query, time.Since(then), args) + }(time.Now()) + } + + return w.Tx.ExecContext(context.Background(), query, args...) +} + // ExecRaw is like Exec but without any rebinding of params. You need to pass // the exact param types of your target database. func (w *sqlxTxWrapper) ExecRaw(query string, args ...interface{}) (sql.Result, error) { diff --git a/store/sqlstore/store.go b/store/sqlstore/store.go index 8dadbdaa7d..a740bdbd8f 100644 --- a/store/sqlstore/store.go +++ b/store/sqlstore/store.go @@ -27,7 +27,6 @@ import ( _ "github.com/golang-migrate/migrate/v4/source/file" "github.com/jmoiron/sqlx" "github.com/lib/pq" - "github.com/mattermost/gorp" mbindata "github.com/mattermost/morph/sources/go_bindata" "github.com/pkg/errors" @@ -113,13 +112,10 @@ type SqlStore struct { rrCounter int64 srCounter int64 - master *gorp.DbMap masterX *sqlxDBWrapper - Replicas []*gorp.DbMap ReplicaXs []*sqlxDBWrapper - searchReplicas []*gorp.DbMap searchReplicaXs []*sqlxDBWrapper replicaLagHandles []*dbsql.DB @@ -248,34 +244,6 @@ func setupConnection(connType string, dataSource string, settings *model.SqlSett return db } -func getDBMap(settings *model.SqlSettings, db *dbsql.DB) *gorp.DbMap { - connectionTimeout := time.Duration(*settings.QueryTimeout) * time.Second - var dbMap *gorp.DbMap - switch *settings.DriverName { - case model.DatabaseDriverMysql: - dbMap = &gorp.DbMap{ - Db: db, - TypeConverter: mattermConverter{}, - Dialect: gorp.MySQLDialect{Engine: "InnoDB", Encoding: "UTF8MB4"}, - QueryTimeout: connectionTimeout, - } - case model.DatabaseDriverPostgres: - dbMap = &gorp.DbMap{ - Db: db, - TypeConverter: mattermConverter{}, - Dialect: gorp.PostgresDialect{}, - QueryTimeout: connectionTimeout, - } - default: - mlog.Fatal("Failed to create dialect specific driver") - return nil - } - if settings.Trace != nil && *settings.Trace { - dbMap.TraceOn("sql-trace:", &TraceOnAdapter{}) - } - return dbMap -} - func (ss *SqlStore) SetContext(context context.Context) { ss.context = context } @@ -300,7 +268,6 @@ func (ss *SqlStore) initConnection() { } handle := setupConnection("master", dataSource, ss.settings) - ss.master = getDBMap(ss.settings, handle) ss.masterX = newSqlxDBWrapper(sqlx.NewDb(handle, ss.DriverName()), time.Duration(*ss.settings.QueryTimeout)*time.Second, *ss.settings.Trace) @@ -309,11 +276,9 @@ func (ss *SqlStore) initConnection() { } if len(ss.settings.DataSourceReplicas) > 0 { - ss.Replicas = make([]*gorp.DbMap, len(ss.settings.DataSourceReplicas)) ss.ReplicaXs = make([]*sqlxDBWrapper, len(ss.settings.DataSourceReplicas)) for i, replica := range ss.settings.DataSourceReplicas { handle := setupConnection(fmt.Sprintf("replica-%v", i), replica, ss.settings) - ss.Replicas[i] = getDBMap(ss.settings, handle) ss.ReplicaXs[i] = newSqlxDBWrapper(sqlx.NewDb(handle, ss.DriverName()), time.Duration(*ss.settings.QueryTimeout)*time.Second, *ss.settings.Trace) @@ -324,11 +289,9 @@ func (ss *SqlStore) initConnection() { } if len(ss.settings.DataSourceSearchReplicas) > 0 { - ss.searchReplicas = make([]*gorp.DbMap, len(ss.settings.DataSourceSearchReplicas)) ss.searchReplicaXs = make([]*sqlxDBWrapper, len(ss.settings.DataSourceSearchReplicas)) for i, replica := range ss.settings.DataSourceSearchReplicas { handle := setupConnection(fmt.Sprintf("search-replica-%v", i), replica, ss.settings) - ss.searchReplicas[i] = getDBMap(ss.settings, handle) ss.searchReplicaXs[i] = newSqlxDBWrapper(sqlx.NewDb(handle, ss.DriverName()), time.Duration(*ss.settings.QueryTimeout)*time.Second, *ss.settings.Trace) @@ -386,10 +349,6 @@ func (ss *SqlStore) GetDbVersion(numerical bool) (string, error) { } -func (ss *SqlStore) GetMaster() *gorp.DbMap { - return ss.master -} - func (ss *SqlStore) GetMasterX() *sqlxDBWrapper { return ss.masterX } @@ -403,22 +362,6 @@ func (ss *SqlStore) SetMasterX(db *sql.DB) { } } -func (ss *SqlStore) GetSearchReplica() *gorp.DbMap { - ss.licenseMutex.RLock() - license := ss.license - ss.licenseMutex.RUnlock() - if license == nil { - return ss.GetMaster() - } - - if len(ss.settings.DataSourceSearchReplicas) == 0 { - return ss.GetReplica() - } - - rrNum := atomic.AddInt64(&ss.srCounter, 1) % int64(len(ss.searchReplicas)) - return ss.searchReplicas[rrNum] -} - func (ss *SqlStore) GetSearchReplicaX() *sqlxDBWrapper { ss.licenseMutex.RLock() license := ss.license @@ -435,18 +378,6 @@ func (ss *SqlStore) GetSearchReplicaX() *sqlxDBWrapper { return ss.searchReplicaXs[rrNum] } -func (ss *SqlStore) GetReplica() *gorp.DbMap { - ss.licenseMutex.RLock() - license := ss.license - ss.licenseMutex.RUnlock() - if len(ss.settings.DataSourceReplicas) == 0 || ss.lockedToMaster || license == nil { - return ss.GetMaster() - } - - rrNum := atomic.AddInt64(&ss.rrCounter, 1) % int64(len(ss.Replicas)) - return ss.Replicas[rrNum] -} - func (ss *SqlStore) GetReplicaX() *sqlxDBWrapper { ss.licenseMutex.RLock() license := ss.license @@ -455,7 +386,7 @@ func (ss *SqlStore) GetReplicaX() *sqlxDBWrapper { return ss.GetMasterX() } - rrNum := atomic.AddInt64(&ss.rrCounter, 1) % int64(len(ss.Replicas)) + rrNum := atomic.AddInt64(&ss.rrCounter, 1) % int64(len(ss.ReplicaXs)) return ss.ReplicaXs[rrNum] } @@ -507,8 +438,8 @@ func (ss *SqlStore) TotalReadDbConnections() int { } count := 0 - for _, db := range ss.Replicas { - count = count + db.Db.Stats().OpenConnections + for _, db := range ss.ReplicaXs { + count = count + db.Stats().OpenConnections } return count @@ -520,8 +451,8 @@ func (ss *SqlStore) TotalSearchDbConnections() int { } count := 0 - for _, db := range ss.searchReplicas { - count = count + db.Db.Stats().OpenConnections + for _, db := range ss.searchReplicaXs { + count = count + db.Stats().OpenConnections } return count @@ -748,10 +679,10 @@ func IsUniqueConstraintError(err error, indexName []string) bool { return unique && field } -func (ss *SqlStore) GetAllConns() []*gorp.DbMap { - all := make([]*gorp.DbMap, len(ss.Replicas)+1) - copy(all, ss.Replicas) - all[len(ss.Replicas)] = ss.master +func (ss *SqlStore) GetAllConns() []*sqlxDBWrapper { + all := make([]*sqlxDBWrapper, len(ss.ReplicaXs)+1) + copy(all, ss.ReplicaXs) + all[len(ss.ReplicaXs)] = ss.masterX return all } @@ -762,24 +693,24 @@ func (ss *SqlStore) RecycleDBConnections(d time.Duration) { originalDuration := time.Duration(*ss.settings.ConnMaxLifetimeMilliseconds) * time.Millisecond // Set the max lifetimes for all connections. for _, conn := range ss.GetAllConns() { - conn.Db.SetConnMaxLifetime(d) + conn.SetConnMaxLifetime(d) } // Wait for that period with an additional 2 seconds of scheduling delay. time.Sleep(d + 2*time.Second) // Reset max lifetime back to original value. for _, conn := range ss.GetAllConns() { - conn.Db.SetConnMaxLifetime(originalDuration) + conn.SetConnMaxLifetime(originalDuration) } } func (ss *SqlStore) Close() { - ss.master.Db.Close() - for _, replica := range ss.Replicas { - replica.Db.Close() + ss.masterX.Close() + for _, replica := range ss.ReplicaXs { + replica.Close() } - for _, replica := range ss.searchReplicas { - replica.Db.Close() + for _, replica := range ss.searchReplicaXs { + replica.Close() } } diff --git a/store/sqlstore/store_test.go b/store/sqlstore/store_test.go index 0b8bc2c808..e28a2afc1a 100644 --- a/store/sqlstore/store_test.go +++ b/store/sqlstore/store_test.go @@ -17,7 +17,6 @@ import ( "github.com/go-sql-driver/mysql" "github.com/lib/pq" - "github.com/mattermost/gorp" "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -186,12 +185,12 @@ func TestStoreLicenseRace(t *testing.T) { }() go func() { - store.GetReplica() + store.GetReplicaX() wg.Done() }() go func() { - store.GetSearchReplica() + store.GetSearchReplicaX() wg.Done() }() @@ -276,14 +275,14 @@ func TestGetReplica(t *testing.T) { store.UpdateLicense(&model.License{}) - replicas := make(map[*gorp.DbMap]bool) + replicas := make(map[*sqlxDBWrapper]bool) for i := 0; i < 5; i++ { - replicas[store.GetReplica()] = true + replicas[store.GetReplicaX()] = true } - searchReplicas := make(map[*gorp.DbMap]bool) + searchReplicas := make(map[*sqlxDBWrapper]bool) for i := 0; i < 5; i++ { - searchReplicas[store.GetSearchReplica()] = true + searchReplicas[store.GetSearchReplicaX()] = true } if testCase.DataSourceReplicaNum > 0 { @@ -291,13 +290,13 @@ func TestGetReplica(t *testing.T) { assert.Len(t, replicas, testCase.DataSourceReplicaNum) for replica := range replicas { - assert.NotSame(t, store.GetMaster(), replica) + assert.NotSame(t, store.GetMasterX(), replica) } } else if assert.Len(t, replicas, 1) { // Otherwise ensure the replicas contains only the master. for replica := range replicas { - assert.Same(t, store.GetMaster(), replica) + assert.Same(t, store.GetMasterX(), replica) } } @@ -306,7 +305,7 @@ func TestGetReplica(t *testing.T) { assert.Len(t, searchReplicas, testCase.DataSourceSearchReplicaNum) for searchReplica := range searchReplicas { - assert.NotSame(t, store.GetMaster(), searchReplica) + assert.NotSame(t, store.GetMasterX(), searchReplica) for replica := range replicas { assert.NotSame(t, searchReplica, replica) } @@ -319,7 +318,7 @@ func TestGetReplica(t *testing.T) { } else if testCase.DataSourceReplicaNum == 0 && assert.Len(t, searchReplicas, 1) { // Otherwise ensure the search replicas contains the master. for searchReplica := range searchReplicas { - assert.Same(t, store.GetMaster(), searchReplica) + assert.Same(t, store.GetMasterX(), searchReplica) } } }) @@ -344,14 +343,14 @@ func TestGetReplica(t *testing.T) { storetest.CleanupSqlSettings(settings) }() - replicas := make(map[*gorp.DbMap]bool) + replicas := make(map[*sqlxDBWrapper]bool) for i := 0; i < 5; i++ { - replicas[store.GetReplica()] = true + replicas[store.GetReplicaX()] = true } - searchReplicas := make(map[*gorp.DbMap]bool) + searchReplicas := make(map[*sqlxDBWrapper]bool) for i := 0; i < 5; i++ { - searchReplicas[store.GetSearchReplica()] = true + searchReplicas[store.GetSearchReplicaX()] = true } if testCase.DataSourceReplicaNum > 0 { @@ -359,13 +358,13 @@ func TestGetReplica(t *testing.T) { assert.Len(t, replicas, 1) for replica := range replicas { - assert.Same(t, store.GetMaster(), replica) + assert.Same(t, store.GetMasterX(), replica) } } else if assert.Len(t, replicas, 1) { // Otherwise ensure the replicas contains only the master. for replica := range replicas { - assert.Same(t, store.GetMaster(), replica) + assert.Same(t, store.GetMasterX(), replica) } } @@ -374,7 +373,7 @@ func TestGetReplica(t *testing.T) { assert.Len(t, searchReplicas, 1) for searchReplica := range searchReplicas { - assert.Same(t, store.GetMaster(), searchReplica) + assert.Same(t, store.GetMasterX(), searchReplica) } } else if testCase.DataSourceReplicaNum > 0 { @@ -385,7 +384,7 @@ func TestGetReplica(t *testing.T) { } else if assert.Len(t, searchReplicas, 1) { // Otherwise ensure the search replicas contains the master. for searchReplica := range searchReplicas { - assert.Same(t, store.GetMaster(), searchReplica) + assert.Same(t, store.GetMasterX(), searchReplica) } } }) @@ -755,10 +754,10 @@ func TestExecNoTimeout(t *testing.T) { StoreTest(t, func(t *testing.T, ss store.Store) { sqlStore := ss.(*SqlStore) var query string - timeout := sqlStore.master.QueryTimeout - sqlStore.master.QueryTimeout = 1 + timeout := sqlStore.masterX.queryTimeout + sqlStore.masterX.queryTimeout = 1 defer func() { - sqlStore.master.QueryTimeout = timeout + sqlStore.masterX.queryTimeout = timeout }() if sqlStore.DriverName() == model.DatabaseDriverMysql { query = `SELECT SLEEP(2);` diff --git a/store/sqlstore/team_store.go b/store/sqlstore/team_store.go index 3a062040e1..10d434dd8b 100644 --- a/store/sqlstore/team_store.go +++ b/store/sqlstore/team_store.go @@ -922,7 +922,7 @@ func (s SqlTeamStore) GetMember(ctx context.Context, teamId string, userId strin } var dbMember teamMemberWithSchemeRoles - err = s.DBFromContext(ctx).SelectOne(&dbMember, queryString, args...) + err = s.DBXFromContext(ctx).Get(&dbMember, queryString, args...) if err != nil { if err == sql.ErrNoRows { return nil, store.NewErrNotFound("TeamMember", fmt.Sprintf("teamId=%s, userId=%s", teamId, userId)) @@ -1068,7 +1068,7 @@ func (s SqlTeamStore) GetTeamsForUser(ctx context.Context, userId string) ([]*mo } dbMembers := teamMemberWithSchemeRolesList{} - _, err = s.SqlStore.DBFromContext(ctx).Select(&dbMembers, queryString, args...) + err = s.SqlStore.DBXFromContext(ctx).Select(&dbMembers, queryString, args...) if err != nil { return nil, errors.Wrapf(err, "failed to find TeamMembers with userId=%s", userId) } diff --git a/store/sqlstore/upgrade.go b/store/sqlstore/upgrade.go index def7262e39..48de6e6731 100644 --- a/store/sqlstore/upgrade.go +++ b/store/sqlstore/upgrade.go @@ -282,27 +282,22 @@ func themeMigrationFailed(err error) { func upgradeDatabaseToVersion33(sqlStore *SqlStore) { if shouldPerformUpgrade(sqlStore, Version320, Version330) { if sqlStore.DoesColumnExist("Users", "ThemeProps") { - params := map[string]interface{}{ - "Category": model.PreferenceCategoryTheme, - "Name": "", - } - - transaction, err := sqlStore.GetMaster().Begin() + transaction, err := sqlStore.GetMasterX().Beginx() if err != nil { themeMigrationFailed(err) } - defer finalizeTransaction(transaction) + defer finalizeTransactionX(transaction) // copy data across if _, err := transaction.ExecNoTimeout( `INSERT INTO Preferences(UserId, Category, Name, Value) SELECT - Id, '`+model.PreferenceCategoryTheme+`', '', ThemeProps + Id, '` + model.PreferenceCategoryTheme + `', '', ThemeProps FROM Users WHERE - Users.ThemeProps != 'null'`, params); err != nil { + Users.ThemeProps != 'null'`); err != nil { themeMigrationFailed(err) return } @@ -554,8 +549,8 @@ func upgradeDatabaseToVersion510(sqlStore *SqlStore) { func upgradeDatabaseToVersion511(sqlStore *SqlStore) { if shouldPerformUpgrade(sqlStore, Version5100, Version5110) { // Enforce all teams have an InviteID set - var teams []*model.Team - if _, err := sqlStore.GetReplica().Select(&teams, "SELECT * FROM Teams WHERE InviteId = ''"); err != nil { + teams := []*model.Team{} + if err := sqlStore.GetReplicaX().Select(&teams, "SELECT * FROM Teams WHERE InviteId = ''"); err != nil { mlog.Error("Error fetching Teams without InviteID", mlog.Err(err)) } else { for _, team := range teams { @@ -701,7 +696,7 @@ func precheckMigrationToVersion528(sqlStore *SqlStore) error { } var schemeIDWrong, typeWrong int - row := sqlStore.GetMaster().Db.QueryRow(teamsQuery) + row := sqlStore.GetMasterX().QueryRow(teamsQuery) if err = row.Scan(&schemeIDWrong, &typeWrong); err != nil && err != sql.ErrNoRows { return err } else if err == nil && schemeIDWrong > 0 { diff --git a/store/sqlstore/user_store.go b/store/sqlstore/user_store.go index 5e3a9bdaa7..559f8afe5b 100644 --- a/store/sqlstore/user_store.go +++ b/store/sqlstore/user_store.go @@ -390,7 +390,7 @@ func (us SqlUserStore) GetMany(ctx context.Context, ids []string) ([]*model.User } users := []*model.User{} - if _, err := us.SqlStore.DBFromContext(ctx).Select(&users, queryString, args...); err != nil { + if err := us.SqlStore.DBXFromContext(ctx).Select(&users, queryString, args...); err != nil { return nil, errors.Wrap(err, "users_get_many_select") } @@ -403,7 +403,7 @@ func (us SqlUserStore) Get(ctx context.Context, id string) (*model.User, error) if err != nil { return nil, errors.Wrap(err, "users_get_tosql") } - row := us.SqlStore.DBFromContext(ctx).Db.QueryRow(queryString, args...) + row := us.SqlStore.DBXFromContext(ctx).QueryRow(queryString, args...) var user model.User var props, notifyProps, timezone []byte @@ -774,7 +774,7 @@ func (us SqlUserStore) GetAllProfilesInChannel(ctx context.Context, channelID st } users := []*model.User{} - rows, err := us.SqlStore.DBFromContext(ctx).Db.Query(queryString, args...) + rows, err := us.SqlStore.DBXFromContext(ctx).Query(queryString, args...) if err != nil { return nil, errors.Wrap(err, "failed to find Users") } @@ -998,7 +998,7 @@ func (us SqlUserStore) GetProfileByIds(ctx context.Context, userIds []string, op return nil, errors.Wrap(err, "get_profile_by_ids_tosql") } - if _, err := us.SqlStore.DBFromContext(ctx).Select(&users, queryString, args...); err != nil { + if err := us.SqlStore.DBXFromContext(ctx).Select(&users, queryString, args...); err != nil { return nil, errors.Wrap(err, "failed to find Users") } @@ -1679,7 +1679,7 @@ func (us SqlUserStore) GetUsersBatchForIndexing(startTime, endTime int64, limit OrderBy("u.CreateAt"). Limit(uint64(limit)). ToSql() - _, err := us.GetSearchReplica().Select(&users, usersQuery, args...) + err := us.GetSearchReplicaX().Select(&users, usersQuery, args...) if err != nil { return nil, errors.Wrap(err, "failed to find Users") } @@ -1689,7 +1689,7 @@ func (us SqlUserStore) GetUsersBatchForIndexing(startTime, endTime int64, limit userIds = append(userIds, user.Id) } - var channelMembers []*model.ChannelMember + channelMembers := []*model.ChannelMember{} channelMembersQuery, args, _ := us.getQueryBuilder(). Select(` cm.ChannelId, @@ -1709,18 +1709,18 @@ func (us SqlUserStore) GetUsersBatchForIndexing(startTime, endTime int64, limit Join("Channels c ON cm.ChannelId = c.Id"). Where(sq.Eq{"c.Type": model.ChannelTypeOpen, "cm.UserId": userIds}). ToSql() - _, err = us.GetSearchReplica().Select(&channelMembers, channelMembersQuery, args...) + err = us.GetSearchReplicaX().Select(&channelMembers, channelMembersQuery, args...) if err != nil { return nil, errors.Wrap(err, "failed to find ChannelMembers") } - var teamMembers []*model.TeamMember + teamMembers := []*model.TeamMember{} teamMembersQuery, args, _ := us.getQueryBuilder(). Select("TeamId, UserId, Roles, DeleteAt, (SchemeGuest IS NOT NULL AND SchemeGuest) as SchemeGuest, SchemeUser, SchemeAdmin"). From("TeamMembers"). Where(sq.Eq{"UserId": userIds, "DeleteAt": 0}). ToSql() - _, err = us.GetSearchReplica().Select(&teamMembers, teamMembersQuery, args...) + err = us.GetSearchReplicaX().Select(&teamMembers, teamMembersQuery, args...) if err != nil { return nil, errors.Wrap(err, "failed to find TeamMembers") } diff --git a/store/sqlstore/user_terms_of_service.go b/store/sqlstore/user_terms_of_service.go index 4187bd0bce..c99b777cbb 100644 --- a/store/sqlstore/user_terms_of_service.go +++ b/store/sqlstore/user_terms_of_service.go @@ -17,15 +17,7 @@ type SqlUserTermsOfServiceStore struct { } func newSqlUserTermsOfServiceStore(sqlStore *SqlStore) store.UserTermsOfServiceStore { - s := SqlUserTermsOfServiceStore{sqlStore} - - for _, db := range sqlStore.GetAllConns() { - table := db.AddTableWithName(model.UserTermsOfService{}, "UserTermsOfService").SetKeys(false, "UserId") - table.ColMap("UserId").SetMaxSize(26) - table.ColMap("TermsOfServiceId").SetMaxSize(26) - } - - return s + return SqlUserTermsOfServiceStore{sqlStore} } func (s SqlUserTermsOfServiceStore) GetByUser(userId string) (*model.UserTermsOfService, error) { diff --git a/store/sqlstore/utils.go b/store/sqlstore/utils.go index 32ed9a07ae..8275549842 100644 --- a/store/sqlstore/utils.go +++ b/store/sqlstore/utils.go @@ -9,8 +9,6 @@ import ( "strings" "unicode" - "github.com/mattermost/gorp" - "github.com/mattermost/mattermost-server/v6/shared/mlog" ) @@ -47,14 +45,6 @@ func MapStringsToQueryParams(list []string, paramPrefix string) (string, map[str return "(" + keys.String() + ")", params } -// finalizeTransaction ensures a transaction is closed after use, rolling back if not already committed. -func finalizeTransaction(transaction *gorp.Transaction) { - // Rollback returns sql.ErrTxDone if the transaction was already closed. - if err := transaction.Rollback(); err != nil && err != sql.ErrTxDone { - mlog.Error("Failed to rollback transaction", mlog.Err(err)) - } -} - // finalizeTransactionX ensures a transaction is closed after use, rolling back if not already committed. func finalizeTransactionX(transaction *sqlxTxWrapper) { // Rollback returns sql.ErrTxDone if the transaction was already closed. diff --git a/testlib/helper.go b/testlib/helper.go index 2e3c6b1c3a..72418f7f41 100644 --- a/testlib/helper.go +++ b/testlib/helper.go @@ -180,7 +180,7 @@ func (h *MainHelper) PreloadMigrations() { panic(fmt.Errorf("cannot read file: %v", err)) } } - handle := h.SQLStore.GetMaster() + handle := h.SQLStore.GetMasterX() _, err = handle.Exec(string(buf)) if err != nil { panic(errors.Wrap(err, "Error preloading migrations. Check if you have &multiStatements=true in your DSN if you are using MySQL. Or perhaps the schema changed? If yes, then update the warmup files accordingly")) @@ -271,7 +271,7 @@ func (h *MainHelper) SetReplicationLagForTesting(seconds int) error { } func (h *MainHelper) execOnEachReplica(query string, args ...interface{}) error { - for _, replica := range h.SQLStore.Replicas { + for _, replica := range h.SQLStore.ReplicaXs { _, err := replica.Exec(query, args...) if err != nil { return err diff --git a/vendor/github.com/mattermost/gorp/.gitignore b/vendor/github.com/mattermost/gorp/.gitignore deleted file mode 100644 index c1bbd21d1f..0000000000 --- a/vendor/github.com/mattermost/gorp/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -_test -*.test -_testmain.go -_obj -*~ -*.6 -6.out -gorptest.bin -tmp -*.swp diff --git a/vendor/github.com/mattermost/gorp/CONTRIBUTING.md b/vendor/github.com/mattermost/gorp/CONTRIBUTING.md deleted file mode 100644 index 7bc145fd7c..0000000000 --- a/vendor/github.com/mattermost/gorp/CONTRIBUTING.md +++ /dev/null @@ -1,34 +0,0 @@ -# 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. diff --git a/vendor/github.com/mattermost/gorp/LICENSE b/vendor/github.com/mattermost/gorp/LICENSE deleted file mode 100644 index b661111d0a..0000000000 --- a/vendor/github.com/mattermost/gorp/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -(The MIT License) - -Copyright (c) 2012 James Cooper - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -'Software'), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/mattermost/gorp/Makefile b/vendor/github.com/mattermost/gorp/Makefile deleted file mode 100644 index 25188fb062..0000000000 --- a/vendor/github.com/mattermost/gorp/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -GOTESTFLAGS ?= -test.count=1 - -test-all: test-unit test-mymysql test-gomysql test-postgres test-sqlite - -test-unit: - echo "Running unit tests" - ginkgo -r -race -randomizeAllSpecs -keepGoing -- -test.run TestGorp - -test-mymysql: - echo "Testing against mymysql" - go test . $(GOTESTFLAGS) -dsn="tcp:localhost:3306*gorptest/gorptest/gorptest" -dialect="mysql" - -test-gomysql: - echo "Testing against gomysql" - go test . $(GOTESTFLAGS) -dsn="gorptest:gorptest@tcp(localhost:3306)/gorptest" -dialect="gomysql" - -test-postgres: - echo "Testing against postgres" - go test . $(GOTESTFLAGS) -dsn="host=localhost user=gorptest password=gorptest dbname=gorptest sslmode=disable" -dialect="postgres" - -test-sqlite: - echo "Testing against sqlite" - go test . $(GOTESTFLAGS) -dsn="/tmp/gorptest.bin" -dialect="sqlite" - rm -f /tmp/gorptest.bin \ No newline at end of file diff --git a/vendor/github.com/mattermost/gorp/README.md b/vendor/github.com/mattermost/gorp/README.md deleted file mode 100644 index 144af16d56..0000000000 --- a/vendor/github.com/mattermost/gorp/README.md +++ /dev/null @@ -1,805 +0,0 @@ -# Go Relational Persistence - -[![build status](https://img.shields.io/travis/go-gorp/gorp.svg)](http://travis-ci.org/go-gorp/gorp) -[![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 2016-11-13: Future versions - -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. - -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). - -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. - -* Bind struct fields to table columns via API or tag -* Support for embedded structs -* Support for transactions -* Forward engineer db schema from structs (great for unit tests) -* Pre/post insert/update/delete hooks -* Automatically generate insert/update/delete statements for a struct -* Automatic binding of auto increment PKs back to struct after insert -* Delete by primary key(s) -* Select by primary key(s) -* Optional trace sql logging -* 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) - -## Installation - -Use `go get` or your favorite vendoring tool, using whichever import -path you'd like. - -## Versioning - -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. - -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. - -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. - -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 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. - -## 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 - -```go -package main - -import ( - "database/sql" - "gopkg.in/gorp.v1" - _ "github.com/mattn/go-sqlite3" - "log" - "time" -) - -func main() { - // initialize the DbMap - dbmap := initDb() - defer dbmap.Db.Close() - - // delete any existing rows - err := dbmap.TruncateTables() - checkErr(err, "TruncateTables failed") - - // create two posts - p1 := newPost("Go 1.1 released!", "Lorem ipsum lorem ipsum") - p2 := newPost("Go 1.2 released!", "Lorem ipsum lorem ipsum") - - // insert rows - auto increment PKs will be set properly after the insert - err = dbmap.Insert(&p1, &p2) - checkErr(err, "Insert failed") - - // use convenience SelectInt - count, err := dbmap.SelectInt("select count(*) from posts") - checkErr(err, "select count(*) failed") - log.Println("Rows after inserting:", count) - - // update a row - p2.Title = "Go 1.2 is better than ever" - count, err = dbmap.Update(&p2) - checkErr(err, "Update failed") - log.Println("Rows updated:", count) - - // fetch one row - note use of "post_id" instead of "Id" since column is aliased - // - // Postgres users should use $1 instead of ? placeholders - // See 'Known Issues' below - // - err = dbmap.SelectOne(&p2, "select * from posts where post_id=?", p2.Id) - checkErr(err, "SelectOne failed") - log.Println("p2 row:", p2) - - // fetch all rows - var posts []Post - _, err = dbmap.Select(&posts, "select * from posts order by post_id") - checkErr(err, "Select failed") - log.Println("All rows:") - for x, p := range posts { - log.Printf(" %d: %v\n", x, p) - } - - // delete row by PK - count, err = dbmap.Delete(&p1) - checkErr(err, "Delete failed") - log.Println("Rows deleted:", count) - - // delete row manually via Exec - _, err = dbmap.Exec("delete from posts where post_id=?", p2.Id) - checkErr(err, "Exec failed") - - // confirm count is zero - count, err = dbmap.SelectInt("select count(*) from posts") - checkErr(err, "select count(*) failed") - log.Println("Row count - should be zero:", count) - - log.Println("Done!") -} - -type Post struct { - // db tag lets you specify the column name if it differs from the struct field - Id int64 `db:"post_id"` - Created int64 - Title string `db:",size:50"` // Column size set to 50 - Body string `db:"article_body,size:1024"` // Set both column name and size -} - -func newPost(title, body string) Post { - return Post{ - Created: time.Now().UnixNano(), - Title: title, - Body: body, - } -} - -func initDb() *gorp.DbMap { - // connect to db using standard Go database/sql API - // use whatever database/sql driver you wish - db, err := sql.Open("sqlite3", "/tmp/post_db.bin") - checkErr(err, "sql.Open failed") - - // construct a gorp DbMap - dbmap := &gorp.DbMap{Db: db, Dialect: gorp.SqliteDialect{}} - - // add a table, setting the table name to 'posts' and - // specifying that the Id property is an auto incrementing PK - dbmap.AddTableWithName(Post{}, "posts").SetKeys(true, "Id") - - // create the table. in a production system you'd generally - // use a migration tool, or create the tables via scripts - err = dbmap.CreateTablesIfNotExists() - checkErr(err, "Create tables failed") - - return dbmap -} - -func checkErr(err error, msg string) { - if err != nil { - log.Fatalln(msg, err) - } -} -``` - -## Examples - -### Mapping structs to tables - -First define some types: - -```go -type Invoice struct { - Id int64 - Created int64 - Updated int64 - Memo string - PersonId int64 -} - -type Person struct { - Id int64 - Created int64 - Updated int64 - FName string - LName string -} - -// Example of using tags to alias fields to column names -// The 'db' value is the column name -// -// A hyphen will cause gorp to skip this field, similar to the -// Go json package. -// -// This is equivalent to using the ColMap methods: -// -// table := dbmap.AddTableWithName(Product{}, "product") -// table.ColMap("Id").Rename("product_id") -// table.ColMap("Price").Rename("unit_price") -// table.ColMap("IgnoreMe").SetTransient(true) -// -// You can optionally declare the field to be a primary key and/or autoincrement -// -type Product struct { - Id int64 `db:"product_id, primarykey, autoincrement"` - Price int64 `db:"unit_price"` - IgnoreMe string `db:"-"` -} -``` - -Then create a mapper, typically you'd do this one time at app startup: - -```go -// connect to db using standard Go database/sql API -// use whatever database/sql driver you wish -db, err := sql.Open("mymysql", "tcp:localhost:3306*mydb/myuser/mypassword") - -// construct a gorp DbMap -dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}} - -// register the structs you wish to use with gorp -// you can also use the shorter dbmap.AddTable() if you -// don't want to override the table name -// -// SetKeys(true) means we have a auto increment primary key, which -// will get automatically bound to your struct post-insert -// -t1 := dbmap.AddTableWithName(Invoice{}, "invoice_test").SetKeys(true, "Id") -t2 := dbmap.AddTableWithName(Person{}, "person_test").SetKeys(true, "Id") -t3 := dbmap.AddTableWithName(Product{}, "product_test").SetKeys(true, "Id") -``` - -### Struct Embedding - -gorp supports embedding structs. For example: - -```go -type Names struct { - FirstName string - LastName string -} - -type WithEmbeddedStruct struct { - Id int64 - Names -} - -es := &WithEmbeddedStruct{-1, Names{FirstName: "Alice", LastName: "Smith"}} -err := dbmap.Insert(es) -``` - -See the `TestWithEmbeddedStruct` function in `gorp_test.go` for a full example. - -### Create/Drop Tables ### - -Automatically create / drop registered tables. This is useful for unit tests -but is entirely optional. You can of course use gorp with tables created manually, -or with a separate migration tool (like [goose](https://bitbucket.org/liamstask/goose) or [migrate](https://github.com/mattes/migrate)). - -```go -// create all registered tables -dbmap.CreateTables() - -// same as above, but uses "if not exists" clause to skip tables that are -// already defined -dbmap.CreateTablesIfNotExists() - -// drop -dbmap.DropTables() -``` - -### SQL Logging - -Optionally you can pass in a logger to trace all SQL statements. -I recommend enabling this initially while you're getting the feel for what -gorp is doing on your behalf. - -Gorp defines a `GorpLogger` interface that Go's built in `log.Logger` satisfies. -However, you can write your own `GorpLogger` implementation, or use a package such -as `glog` if you want more control over how statements are logged. - -```go -// Will log all SQL statements + args as they are run -// The first arg is a string prefix to prepend to all log messages -dbmap.TraceOn("[gorp]", log.New(os.Stdout, "myapp:", log.Lmicroseconds)) - -// Turn off tracing -dbmap.TraceOff() -``` - -### Insert - -```go -// Must declare as pointers so optional callback hooks -// can operate on your data, not copies -inv1 := &Invoice{0, 100, 200, "first order", 0} -inv2 := &Invoice{0, 100, 200, "second order", 0} - -// Insert your rows -err := dbmap.Insert(inv1, inv2) - -// Because we called SetKeys(true) on Invoice, the Id field -// will be populated after the Insert() automatically -fmt.Printf("inv1.Id=%d inv2.Id=%d\n", inv1.Id, inv2.Id) -``` - -### Update - -Continuing the above example, use the `Update` method to modify an Invoice: - -```go -// count is the # of rows updated, which should be 1 in this example -count, err := dbmap.Update(inv1) -``` - -### Delete - -If you have primary key(s) defined for a struct, you can use the `Delete` -method to remove rows: - -```go -count, err := dbmap.Delete(inv1) -``` - -### Select by Key - -Use the `Get` method to fetch a single row by primary key. It returns -nil if no row is found. - -```go -// fetch Invoice with Id=99 -obj, err := dbmap.Get(Invoice{}, 99) -inv := obj.(*Invoice) -``` - -### Ad Hoc SQL - -#### SELECT - -`Select()` and `SelectOne()` provide a simple way to bind arbitrary queries to a slice -or a single struct. - -```go -// Select a slice - first return value is not needed when a slice pointer is passed to Select() -var posts []Post -_, err := dbmap.Select(&posts, "select * from post order by id") - -// You can also use primitive types -var ids []string -_, err := dbmap.Select(&ids, "select id from post") - -// Select a single row. -// Returns an error if no row found, or if more than one row is found -var post Post -err := dbmap.SelectOne(&post, "select * from post where id=?", id) -``` - -Want to do joins? Just write the SQL and the struct. gorp will bind them: - -```go -// Define a type for your join -// It *must* contain all the columns in your SELECT statement -// -// The names here should match the aliased column names you specify -// in your SQL - no additional binding work required. simple. -// -type InvoicePersonView struct { - InvoiceId int64 - PersonId int64 - Memo string - FName string -} - -// Create some rows -p1 := &Person{0, 0, 0, "bob", "smith"} -dbmap.Insert(p1) - -// notice how we can wire up p1.Id to the invoice easily -inv1 := &Invoice{0, 0, 0, "xmas order", p1.Id} -dbmap.Insert(inv1) - -// Run your query -query := "select i.Id InvoiceId, p.Id PersonId, i.Memo, p.FName " + - "from invoice_test i, person_test p " + - "where i.PersonId = p.Id" - -// pass a slice to Select() -var list []InvoicePersonView -_, err := dbmap.Select(&list, query) - -// this should test true -expected := InvoicePersonView{inv1.Id, p1.Id, inv1.Memo, p1.FName} -if reflect.DeepEqual(list[0], expected) { - fmt.Println("Woot! My join worked!") -} -``` - -#### SELECT string or int64 - -gorp provides a few convenience methods for selecting a single string or int64. - -```go -// select single int64 from db (use $1 instead of ? for postgresql) -i64, err := dbmap.SelectInt("select count(*) from foo where blah=?", blahVal) - -// select single string from db: -s, err := dbmap.SelectStr("select name from foo where blah=?", blahVal) - -``` - -#### Named bind parameters - -You may use a map or struct to bind parameters by name. This is currently -only supported in SELECT queries. - -```go -_, err := dbm.Select(&dest, "select * from Foo where name = :name and age = :age", map[string]interface{}{ - "name": "Rob", - "age": 31, -}) -``` - -#### UPDATE / DELETE - -You can execute raw SQL if you wish. Particularly good for batch operations. - -```go -res, err := dbmap.Exec("delete from invoice_test where PersonId=?", 10) -``` - -### Transactions - -You can batch operations into a transaction: - -```go -func InsertInv(dbmap *DbMap, inv *Invoice, per *Person) error { - // Start a new transaction - trans, err := dbmap.Begin() - if err != nil { - return err - } - - trans.Insert(per) - inv.PersonId = per.Id - trans.Insert(inv) - - // if the commit is successful, a nil error is returned - return trans.Commit() -} -``` - -### Hooks - -Use hooks to update data before/after saving to the db. Good for timestamps: - -```go -// implement the PreInsert and PreUpdate hooks -func (i *Invoice) PreInsert(s gorp.SqlExecutor) error { - i.Created = time.Now().UnixNano() - i.Updated = i.Created - return nil -} - -func (i *Invoice) PreUpdate(s gorp.SqlExecutor) error { - i.Updated = time.Now().UnixNano() - return nil -} - -// You can use the SqlExecutor to cascade additional SQL -// Take care to avoid cycles. gorp won't prevent them. -// -// Here's an example of a cascading delete -// -func (p *Person) PreDelete(s gorp.SqlExecutor) error { - query := "delete from invoice_test where PersonId=?" - - _, err := s.Exec(query, p.Id) - - if err != nil { - return err - } - return nil -} -``` - -Full list of hooks that you can implement: - - PostGet - PreInsert - PostInsert - PreUpdate - PostUpdate - PreDelete - PostDelete - - All have the same signature. for example: - - func (p *MyStruct) PostUpdate(s gorp.SqlExecutor) error - -### Optimistic Locking - -#### 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. - -```go -// Version is an auto-incremented number, managed by gorp -// If this property is present on your struct, update -// operations will be constrained -// -// For example, say we defined Person as: - -type Person struct { - Id int64 - Created int64 - Updated int64 - FName string - LName string - - // automatically used as the Version col - // use table.SetVersionCol("columnName") to map a different - // struct field as the version field - Version int64 -} - -p1 := &Person{0, 0, 0, "Bob", "Smith", 0} -dbmap.Insert(p1) // Version is now 1 - -obj, err := dbmap.Get(Person{}, p1.Id) -p2 := obj.(*Person) -p2.LName = "Edwards" -dbmap.Update(p2) // Version is now 2 - -p1.LName = "Howard" - -// Raises error because p1.Version == 1, which is out of date -count, err := dbmap.Update(p1) -_, ok := err.(gorp.OptimisticLockError) -if ok { - // should reach this statement - - // in a real app you might reload the row and retry, or - // you might propegate this to the user, depending on the desired - // semantics - fmt.Printf("Tried to update row with stale data: %v\n", err) -} else { - // some other db error occurred - log or return up the stack - fmt.Printf("Unknown db err: %v\n", err) -} -``` -### 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. - -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. - -``` -type Account struct { - Id int64 - AcctId string // e.g. this might be a long uuid for portability -} - -// indexType (the 2nd param to AddIndex call) is "Btree" or "Hash" for MySQL. -// demonstrate adding a second index on AcctId, and constrain that field to have unique values. -dbm.AddTable(iptab.Account{}).SetKeys(true, "Id").AddIndex("AcctIdIndex", "Btree", []string{"AcctId"}).SetUnique(true) - -err = dbm.CreateTablesIfNotExists() -checkErr(err, "CreateTablesIfNotExists failed") - -err = dbm.CreateIndex() -checkErr(err, "CreateIndex failed") - -``` -Check the effect of the CreateIndex() call in mysql: -``` -$ mysql - -MariaDB [test]> show create table Account; -+---------+--------------------------+ -| Account | CREATE TABLE `Account` ( - `Id` bigint(20) NOT NULL AUTO_INCREMENT, - `AcctId` varchar(255) DEFAULT NULL, - PRIMARY KEY (`Id`), - UNIQUE KEY `AcctIdIndex` (`AcctId`) USING BTREE <<<--- yes! index added. -) ENGINE=InnoDB DEFAULT CHARSET=utf8 -+---------+--------------------------+ - -``` - - -## Database Drivers - -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: - -* MySQL -* PostgreSQL -* sqlite3 - -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 - -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. - -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: - -```go -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: - -```go -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. - -### 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. - -MySQL users should be especially cautious. See [this PR](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. -- 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 flags, dsn and dialect, in order to test the environment you want. -If not flag is passed the tests are going to use the default ones which are: -- DSN: `gorptest:gorptest@tcp(localhost:3306)/gorptest` -- Dialect: `gomysql` - -```bash -# MySQL example: -# run the tests -go test -dsn="gorptest:gorptest@tcp(localhost:3306)/gorptest" -dialect="gomysql" - -# run the tests and benchmarks -go test -bench="Bench" -benchtime 10 -``` - -Valid `dialect` flag values are: - -- [mysql](https://github.com/ziutek/mymysql) -- [gomysql](https://github.com/Go-SQL-Driver/MySQL) -- [postgres](https://github.com/lib/pq) -- [sqlite](https://github.com/mattn/go-sqlite3) - -## 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. - - -## Contributors - -* matthias-margush - column aliasing via tags -* Rob Figueiredo - @robfig -* Quinn Slack - @sqs diff --git a/vendor/github.com/mattermost/gorp/column.go b/vendor/github.com/mattermost/gorp/column.go deleted file mode 100644 index 995324e72d..0000000000 --- a/vendor/github.com/mattermost/gorp/column.go +++ /dev/null @@ -1,103 +0,0 @@ -// 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 - -import "reflect" - -// ColumnMap represents a mapping between a Go struct field and a single -// column in a table. -// Unique and MaxSize only inform the -// CreateTables() function and are not used by Insert/Update/Delete/Get. -type ColumnMap struct { - // Column name in db table - ColumnName string - - // If true, this column is skipped in generated SQL statements - Transient bool - - // If true, " unique" is added to create table statements. - // Not used elsewhere - Unique bool - - // If not nil, " default 'value'" is added to the create table statements. - // Not used elsewhere - DefaultConstraint *string - - // Query used for getting generated id after insert - GeneratedIdQuery string - - // Passed to Dialect.ToSqlType() to assist in informing the - // correct column type to map to in CreateTables() - MaxSize int - - DefaultValue string - - // The column data type. If set it overrides the one converted from the Go type. - DataType string - - fieldName string - gotype reflect.Type - isPK bool - isAutoIncr bool - isNotNull bool -} - -// Rename allows you to specify the column name in the table -// -// Example: table.ColMap("Updated").Rename("date_updated") -// -func (c *ColumnMap) Rename(colname string) *ColumnMap { - c.ColumnName = colname - return c -} - -// SetTransient allows you to mark the column as transient. If true -// this column will be skipped when SQL statements are generated -func (c *ColumnMap) SetTransient(b bool) *ColumnMap { - c.Transient = b - return c -} - -// SetUnique adds "unique" to the create table statements for this -// column, if b is true. -func (c *ColumnMap) SetUnique(b bool) *ColumnMap { - c.Unique = b - return c -} - -// SetNotNull adds "not null" to the create table statements for this -// column, if nn is true. -func (c *ColumnMap) SetNotNull(nn bool) *ColumnMap { - c.isNotNull = nn - return c -} - -// SetMaxSize specifies the max length of values of this column. This is -// passed to the dialect.ToSqlType() function, which can use the value -// to alter the generated type for "create table" statements -func (c *ColumnMap) SetMaxSize(size int) *ColumnMap { - c.MaxSize = size - return c -} - -// SetDataType allows to specify a custom data type for the column. -func (c *ColumnMap) SetDataType(dataType string) *ColumnMap { - c.DataType = dataType - return c -} - -// SetDefaultConstraint adds " default 'value'" to the create table statements for this -// column, if value is not nil. Not used elsewhere -func (c *ColumnMap) SetDefaultConstraint(value *string) *ColumnMap { - c.DefaultConstraint = value - return c -} diff --git a/vendor/github.com/mattermost/gorp/db.go b/vendor/github.com/mattermost/gorp/db.go deleted file mode 100644 index d25028fd94..0000000000 --- a/vendor/github.com/mattermost/gorp/db.go +++ /dev/null @@ -1,815 +0,0 @@ -// 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 - -import ( - "context" - "database/sql" - "database/sql/driver" - "errors" - "fmt" - "reflect" - "strconv" - "strings" - "time" -) - -// DbMap is the root gorp mapping object. Create one of these for each -// database schema you wish to map. Each DbMap contains a list of -// mapped tables. -// -// Example: -// -// dialect := gorp.MySQLDialect{"InnoDB", "UTF8"} -// dbmap := &gorp.DbMap{Db: db, Dialect: dialect} -// -type DbMap struct { - // Db handle to use with this map - Db *sql.DB - - // Dialect implementation to use with this map - Dialect Dialect - - TypeConverter TypeConverter - - 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 { - - var err error - dialect := reflect.TypeOf(m.Dialect) - for _, table := range m.tables { - for _, index := range table.indexes { - 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 := strings.Builder{} - 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 -} - -func (t *TableMap) DropIndex(name string) error { - - var err error - dialect := reflect.TypeOf(t.dbmap.Dialect) - for _, idx := range t.indexes { - if idx.IndexName == name { - s := strings.Builder{} - s.WriteString(fmt.Sprintf("DROP INDEX %s", idx.IndexName)) - - if dname := dialect.Name(); dname == "MySQLDialect" { - s.WriteString(fmt.Sprintf(" %s %s", t.dbmap.Dialect.DropIndexSuffix(), t.TableName)) - } - s.WriteString(";") - _, e := t.dbmap.ExecNoTimeout(s.String()) - if e != nil { - err = e - } - break - } - } - t.ResetSql() - return err -} - -// AddTable registers the given interface type with gorp. The table name -// will be given the name of the TypeOf(i). You must call this function, -// or AddTableWithName, for any struct type you wish to persist with -// the given DbMap. -// -// This operation is idempotent. If i's type is already mapped, the -// existing *TableMap is returned -func (m *DbMap) AddTable(i interface{}) *TableMap { - return m.AddTableWithName(i, "") -} - -// AddTableWithName has the same behavior as AddTable, but sets -// table.TableName to name. -func (m *DbMap) AddTableWithName(i interface{}, name string) *TableMap { - return m.AddTableWithNameAndSchema(i, "", name) -} - -// AddTableWithNameAndSchema has the same behavior as AddTable, but sets -// table.TableName to name. -func (m *DbMap) AddTableWithNameAndSchema(i interface{}, schema string, name string) *TableMap { - t := reflect.TypeOf(i) - if name == "" { - name = t.Name() - } - - // check if we have a table for this type already - // if so, update the name and return the existing pointer - for i := range m.tables { - table := m.tables[i] - if table.gotype == t { - table.TableName = name - return table - } - } - - tmap := &TableMap{gotype: t, TableName: name, SchemaName: schema, dbmap: m} - var primaryKey []*ColumnMap - tmap.Columns, primaryKey = m.readStructColumns(t) - m.tables = append(m.tables, tmap) - if len(primaryKey) > 0 { - tmap.keys = append(tmap.keys, primaryKey...) - } - - 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() - for i := 0; i < n; i++ { - f := t.Field(i) - if f.Anonymous && f.Type.Kind() == reflect.Struct { - // Recursively add nested fields in embedded structs. - subcols, subpk := m.readStructColumns(f.Type) - // Don't append nested fields that have the same field - // name as an already-mapped field. - for _, subcol := range subcols { - shouldAppend := true - for _, col := range cols { - if !subcol.Transient && subcol.fieldName == col.fieldName { - shouldAppend = false - break - } - } - if shouldAppend { - cols = append(cols, subcol) - } - } - if subpk != nil { - primaryKey = append(primaryKey, subpk...) - } - } else { - // Tag = Name { ',' Option } - // Option = OptionKey [ ':' OptionValue ] - cArguments := strings.Split(f.Tag.Get("db"), ",") - columnName := cArguments[0] - var maxSize int - 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) - - // check mandatory/unexpected option values - switch arg[0] { - case "size", "default": - // options requiring value - if len(arg) == 1 { - panic(fmt.Sprintf("missing option value for option %v on field %v", arg[0], f.Name)) - } - default: - // options where value is invalid (currently all other options) - if len(arg) == 2 { - panic(fmt.Sprintf("unexpected option value for option %v on field %v", arg[0], f.Name)) - } - } - - switch arg[0] { - case "size": - maxSize, _ = strconv.Atoi(arg[1]) - case "default": - defaultValue = arg[1] - case "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)) - } - } - if columnName == "" { - columnName = f.Name - } - - gotype := f.Type - valueType := gotype - if valueType.Kind() == reflect.Ptr { - valueType = valueType.Elem() - } - value := reflect.New(valueType).Interface() - if m.TypeConverter != nil { - // Make a new pointer to a value of type gotype and - // pass it to the TypeConverter's FromDb method to see - // if a different type should be used for the column - // type during table creation. - scanner, useHolder := m.TypeConverter.FromDb(value) - if useHolder { - value = scanner.Holder - gotype = reflect.TypeOf(value) - } - } - if typer, ok := value.(SqlTyper); ok { - gotype = reflect.TypeOf(typer.SqlType()) - } else if valuer, ok := value.(driver.Valuer); ok { - // Only check for driver.Valuer if SqlTyper wasn't - // found. - v, err := valuer.Value() - if err == nil && v != nil { - gotype = reflect.TypeOf(v) - } - } - cm := &ColumnMap{ - ColumnName: columnName, - DefaultValue: defaultValue, - Transient: columnName == "-", - fieldName: f.Name, - gotype: gotype, - isPK: isPK, - isAutoIncr: isAuto, - isNotNull: isNotNull, - MaxSize: maxSize, - } - if isPK { - primaryKey = append(primaryKey, cm) - } - // Check for nested fields of the same field name and - // override them. - shouldAppend := true - for index, col := range cols { - if !col.Transient && col.fieldName == cm.fieldName { - cols[index] = cm - shouldAppend = false - break - } - } - if shouldAppend { - cols = append(cols, cm) - } - } - - } - return -} - -// CreateTables iterates through TableMaps registered to this DbMap and -// executes "create table" statements against the database for each. -// -// This is particularly useful in unit tests where you want to create -// and destroy the schema automatically. -func (m *DbMap) CreateTables() error { - return m.createTables(false) -} - -// CreateTablesIfNotExists is similar to CreateTables, but starts -// each statement with "create table if not exists" so that existing -// tables do not raise errors -func (m *DbMap) CreateTablesIfNotExists() error { - return m.createTables(true) -} - -func (m *DbMap) createTables(ifNotExists bool) error { - var err error - for i := range m.tables { - table := m.tables[i] - sql := table.SqlForCreate(ifNotExists) - _, err = m.ExecNoTimeout(sql) - if err != nil { - return err - } - } - - for _, tbl := range m.dynamicTableMap() { - sql := tbl.SqlForCreate(ifNotExists) - _, err = m.ExecNoTimeout(sql) - if err != nil { - return err - } - } - - return err -} - -// DropTable drops an individual table. -// Returns an error when the table does not exist. -func (m *DbMap) DropTable(table interface{}) error { - t := reflect.TypeOf(table) - - 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) - - 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 -// executes "drop table" statements against the database for each. -func (m *DbMap) DropTables() error { - return m.dropTables(false) -} - -// DropTablesIfExists is the same as DropTables, but uses the "if exists" clause to -// avoid errors for tables that do not exist. -func (m *DbMap) DropTablesIfExists() error { - return m.dropTables(true) -} - -// Goes through all the registered tables, dropping them one by one. -// If an error is encountered, then it is returned and the rest of -// the tables are not dropped. -func (m *DbMap) dropTables(addIfExists bool) (err error) { - for _, table := range m.tables { - err = m.dropTableImpl(table, addIfExists) - if err != nil { - 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, name string, addIfExists bool) error { - table := tableOrNil(m, t, name) - if table == nil { - return fmt.Errorf("table %s was not registered", table.TableName) - } - - return m.dropTableImpl(table, addIfExists) -} - -func (m *DbMap) dropTableImpl(table *TableMap, ifExists bool) (err error) { - tableDrop := "drop table" - if ifExists { - tableDrop = m.Dialect.IfTableExists(tableDrop, table.SchemaName, table.TableName) - } - _, err = m.ExecNoTimeout(fmt.Sprintf("%s %s;", tableDrop, m.Dialect.QuotedTableForQuery(table.SchemaName, table.TableName))) - return err -} - -// TruncateTables iterates through TableMaps registered to this DbMap and -// executes "truncate table" statements against the database for each, or in the case of -// sqlite, a "delete from" with no "where" clause, which uses the truncate optimization -// (http://www.sqlite.org/lang_delete.html) -func (m *DbMap) TruncateTables() error { - var err error - for i := range m.tables { - table := m.tables[i] - _, 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 -} - -// Insert runs a SQL INSERT statement for each element in list. List -// items must be pointers. -// -// Any interface whose TableMap has an auto-increment primary key will -// have its last insert id bound to the PK field on the struct. -// -// The hook functions PreInsert() and/or PostInsert() will be executed -// before/after the INSERT statement if the interface defines them. -// -// Panics if any interface in the list has not been registered with AddTable -func (m *DbMap) Insert(list ...interface{}) error { - return insert(m, m, list...) -} - -// Update runs a SQL UPDATE statement for each element in list. List -// items must be pointers. -// -// The hook functions PreUpdate() and/or PostUpdate() will be executed -// before/after the UPDATE statement if the interface defines them. -// -// Returns the number of rows updated. -// -// Returns an error if SetKeys has not been called on the TableMap -// Panics if any interface in the list has not been registered with AddTable -func (m *DbMap) Update(list ...interface{}) (int64, error) { - return update(m, m, nil, list...) -} - -// UpdateColumns runs a SQL UPDATE statement for each element in list. List -// items must be pointers. -// -// Only the columns accepted by filter are included in the UPDATE. -// -// The hook functions PreUpdate() and/or PostUpdate() will be executed -// before/after the UPDATE statement if the interface defines them. -// -// Returns the number of rows updated. -// -// Returns an error if SetKeys has not been called on the TableMap -// Panics if any interface in the list has not been registered with AddTable -func (m *DbMap) UpdateColumns(filter ColumnFilter, list ...interface{}) (int64, error) { - return update(m, m, filter, list...) -} - -// Delete runs a SQL DELETE statement for each element in list. List -// items must be pointers. -// -// The hook functions PreDelete() and/or PostDelete() will be executed -// before/after the DELETE statement if the interface defines them. -// -// Returns the number of rows deleted. -// -// Returns an error if SetKeys has not been called on the TableMap -// Panics if any interface in the list has not been registered with AddTable -func (m *DbMap) Delete(list ...interface{}) (int64, error) { - return delete(m, m, list...) -} - -// Get runs a SQL SELECT to fetch a single row from the table based on the -// primary key(s) -// -// i should be an empty value for the struct to load. keys should be -// the primary key value(s) for the row to load. If multiple keys -// exist on the table, the order should match the column order -// specified in SetKeys() when the table mapping was defined. -// -// The hook function PostGet() will be executed after the SELECT -// statement if the interface defines them. -// -// Returns a pointer to a struct that matches or nil if no row is found. -// -// Returns an error if SetKeys has not been called on the TableMap -// Panics if any interface in the list has not been registered with AddTable -func (m *DbMap) Get(i interface{}, keys ...interface{}) (interface{}, error) { - return get(m, m, i, keys...) -} - -// Select runs an arbitrary SQL query, binding the columns in the result -// to fields on the struct specified by i. args represent the bind -// parameters for the SQL statement. -// -// Column names on the SELECT statement should be aliased to the field names -// on the struct i. Returns an error if one or more columns in the result -// do not match. It is OK if fields on i are not part of the SQL -// statement. -// -// The hook function PostGet() will be executed after the SELECT -// statement if the interface defines them. -// -// Values are returned in one of two ways: -// 1. If i is a struct or a pointer to a struct, returns a slice of pointers to -// matching rows of type i. -// 2. If i is a pointer to a slice, the results will be appended to that slice -// and nil returned. -// -// i does NOT need to be registered with AddTable() -func (m *DbMap) Select(i interface{}, query string, args ...interface{}) ([]interface{}, error) { - return hookedselect(m, m, i, query, args...) -} - -// 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, 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 -func (m *DbMap) SelectInt(query string, args ...interface{}) (int64, error) { - return SelectInt(m, query, args...) -} - -// SelectNullInt is a convenience wrapper around the gorp.SelectNullInt function -func (m *DbMap) SelectNullInt(query string, args ...interface{}) (sql.NullInt64, error) { - return SelectNullInt(m, query, args...) -} - -// SelectFloat is a convenience wrapper around the gorp.SelectFloat function -func (m *DbMap) SelectFloat(query string, args ...interface{}) (float64, error) { - return SelectFloat(m, query, args...) -} - -// SelectNullFloat is a convenience wrapper around the gorp.SelectNullFloat function -func (m *DbMap) SelectNullFloat(query string, args ...interface{}) (sql.NullFloat64, error) { - return SelectNullFloat(m, query, args...) -} - -// SelectStr is a convenience wrapper around the gorp.SelectStr function -func (m *DbMap) SelectStr(query string, args ...interface{}) (string, error) { - return SelectStr(m, query, args...) -} - -// SelectNullStr is a convenience wrapper around the gorp.SelectNullStr function -func (m *DbMap) SelectNullStr(query string, args ...interface{}) (sql.NullString, error) { - return SelectNullStr(m, query, args...) -} - -// SelectOne is a convenience wrapper around the gorp.SelectOne function -func (m *DbMap) SelectOne(holder interface{}, query string, args ...interface{}) error { - return SelectOne(m, m, holder, query, args...) -} - -// Begin starts a gorp Transaction -func (m *DbMap) Begin() (*Transaction, error) { - if m.logger != nil { - now := time.Now() - defer m.trace(now, "begin;") - } - tx, err := m.Db.Begin() - if err != nil { - return nil, err - } - return &Transaction{m, tx, false}, nil -} - -// Begin starts a gorp Transaction with a given context and opts. -func (m *DbMap) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Transaction, error) { - if m.logger != nil { - now := time.Now() - defer m.trace(now, "begin;") - } - tx, err := m.Db.BeginTx(ctx, opts) - if err != nil { - return nil, err - } - return &Transaction{m, tx, false}, nil -} - -// TableFor returns the *TableMap corresponding to the given Go Type -// 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, "") - if table == nil { - return nil, fmt.Errorf("no table found for type: %v", t.Name()) - } - - 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 -} - -// 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 -func (m *DbMap) Prepare(query string) (*sql.Stmt, error) { - if m.logger != nil { - now := time.Now() - defer m.trace(now, query, nil) - } - return m.Db.Prepare(query) -} - -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 { - return table - } - } - return nil -} - -func (m *DbMap) tableForPointer(ptr interface{}, checkPK bool) (*TableMap, reflect.Value, error) { - ptrv := reflect.ValueOf(ptr) - if ptrv.Kind() != reflect.Ptr { - e := fmt.Sprintf("gorp: passed non-pointer: %v (kind=%v)", ptr, - ptrv.Kind()) - return nil, reflect.Value{}, errors.New(e) - } - elem := ptrv.Elem() - 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 - } - - return t, elem, nil -} - -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) 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...) - m.logger.Printf("%s%s [%s] (%v)", m.logPrefix, query, margs, (time.Now().Sub(started))) - } -} diff --git a/vendor/github.com/mattermost/gorp/dialect.go b/vendor/github.com/mattermost/gorp/dialect.go deleted file mode 100644 index 9222126405..0000000000 --- a/vendor/github.com/mattermost/gorp/dialect.go +++ /dev/null @@ -1,114 +0,0 @@ -// 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 - -import "reflect" - -// The Dialect interface encapsulates behaviors that differ across -// SQL databases. At present the Dialect is only used by CreateTables() -// but this could change in the future -type Dialect interface { - - // dialect name - Name() string - - // adds a suffix to any query, usually ";" - QuerySuffix() string - - // ToSqlType returns the SQL column type to use when creating a - // table of the given Go Type. maxsize can be used to switch based on - // size. For example, in MySQL []byte could map to BLOB, MEDIUMBLOB, - // or LONGBLOB depending on the maxsize - ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string - - // string to append to primary key column definitions - AutoIncrStr() string - - // string to bind autoincrement columns to. Empty string will - // remove reference to those columns in the INSERT statement. - AutoIncrBindValue() string - - AutoIncrInsertSuffix(col *ColumnMap) string - - // string to append to "create table" statement for vendor specific - // table attributes - CreateTableSuffix() string - - // string to append to "create index" statement - CreateIndexSuffix() string - - // string to append to "drop index" statement - DropIndexSuffix() string - - // string to truncate tables - TruncateClause() string - - // bind variable string to use when forming SQL statements - // in many dbs it is "?", but Postgres appears to use $1 - // - // i is a zero based index of the bind variable in this statement - // - BindVar(i int) string - - // Handles quoting of a field name to ensure that it doesn't raise any - // SQL parsing exceptions by using a reserved word as a field name. - QuoteField(field string) string - - // Handles building up of a schema.database string that is compatible with - // the given dialect - // - // schema - The schema that lives in - // table - The table name - QuotedTableForQuery(schema string, table string) string - - // Existance clause for table creation / deletion - IfSchemaNotExists(command, schema string) string - IfTableExists(command, schema, table string) string - IfTableNotExists(command, schema, table string) string -} - -// IntegerAutoIncrInserter is implemented by dialects that can perform -// inserts with automatically incremented integer primary keys. If -// the dialect can handle automatic assignment of more than just -// integers, see TargetedAutoIncrInserter. -type IntegerAutoIncrInserter interface { - InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) -} - -// TargetedAutoIncrInserter is implemented by dialects that can -// perform automatic assignment of any primary key type (i.e. strings -// for uuids, integers for serials, etc). -type TargetedAutoIncrInserter interface { - // InsertAutoIncrToTarget runs an insert operation and assigns the - // automatically generated primary key directly to the passed in - // target. The target should be a pointer to the primary key - // field of the value being inserted. - InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error -} - -// TargetQueryInserter is implemented by dialects that can perform -// assignment of integer primary key type by executing a query -// like "select sequence.currval from dual". -type TargetQueryInserter interface { - // TargetQueryInserter runs an insert operation and assigns the - // automatically generated primary key retrived by the query - // extracted from the GeneratedIdQuery field of the id column. - InsertQueryToTarget(exec SqlExecutor, insertSql, idSql string, target interface{}, params ...interface{}) error -} - -func standardInsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) { - res, err := exec.Exec(insertSql, params...) - if err != nil { - return 0, err - } - return res.LastInsertId() -} diff --git a/vendor/github.com/mattermost/gorp/dialect_mysql.go b/vendor/github.com/mattermost/gorp/dialect_mysql.go deleted file mode 100644 index d4c245a206..0000000000 --- a/vendor/github.com/mattermost/gorp/dialect_mysql.go +++ /dev/null @@ -1,173 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" - "strings" -) - -// Implementation of Dialect for MySQL databases. -type MySQLDialect struct { - - // Engine is the storage engine to use "InnoDB" vs "MyISAM" for example - Engine string - - // Encoding is the character encoding to use for created tables - 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 { - switch val.Kind() { - case reflect.Ptr: - return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) - case reflect.Bool: - return "boolean" - case reflect.Int8: - return "tinyint" - case reflect.Uint8: - return "tinyint unsigned" - case reflect.Int16: - return "smallint" - case reflect.Uint16: - return "smallint unsigned" - case reflect.Int, reflect.Int32: - return "int" - case reflect.Uint, reflect.Uint32: - return "int unsigned" - case reflect.Int64: - return "bigint" - case reflect.Uint64: - return "bigint unsigned" - case reflect.Float64, reflect.Float32: - return "double" - case reflect.Slice: - if val.Elem().Kind() == reflect.Uint8 { - return "mediumblob" - } - } - - switch val.Name() { - case "NullInt64": - return "bigint" - case "NullFloat64": - return "double" - case "NullBool": - return "tinyint" - case "Time": - return "datetime" - } - - /* == About varchar(N) == - * N is number of characters. - * According to the documentation, 0 < N <= 65535. - * But one utf-8 character takes 3 bytes and each row can - * be only 65535 bytes. So there is no way to know exactly - * how many chars a varchar column can actually store. - * Text columns contribute only up to 12 bytes to the row - * size as their contents are stored off-page. - * Hence, we use a conservative maximum of 512 for varchar, - * after which we switch to the text type. - */ - if maxsize == 0 { - // Closer match for unbounded text - return "longtext" - } else if maxsize < 256 { - return fmt.Sprintf("varchar(%d)", maxsize) - } else { - return "text" - } -} - -// Returns auto_increment -func (d MySQLDialect) AutoIncrStr() string { - return "auto_increment" -} - -func (d MySQLDialect) AutoIncrBindValue() string { - return "null" -} - -func (d MySQLDialect) AutoIncrInsertSuffix(col *ColumnMap) string { - return "" -} - -// Returns engine=%s charset=%s based on values stored on struct -func (d MySQLDialect) CreateTableSuffix() string { - if d.Engine == "" || d.Encoding == "" { - msg := "gorp - undefined" - - if d.Engine == "" { - msg += " MySQLDialect.Engine" - } - if d.Engine == "" && d.Encoding == "" { - msg += "," - } - if d.Encoding == "" { - msg += " MySQLDialect.Encoding" - } - msg += ". Check that your MySQLDialect was correctly initialized when declared." - panic(msg) - } - - return fmt.Sprintf(" engine=%s charset=%s", d.Engine, d.Encoding) -} - -func (m MySQLDialect) CreateIndexSuffix() string { - return "using" -} - -func (m MySQLDialect) DropIndexSuffix() string { - return "on" -} - -func (m MySQLDialect) TruncateClause() string { - return "truncate" -} - -// Returns "?" -func (d MySQLDialect) BindVar(i int) string { - return "?" -} - -func (d MySQLDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) { - return standardInsertAutoIncr(exec, insertSql, params...) -} - -func (d MySQLDialect) QuoteField(f string) string { - return "`" + f + "`" -} - -func (d MySQLDialect) QuotedTableForQuery(schema string, table string) string { - if strings.TrimSpace(schema) == "" { - return d.QuoteField(table) - } - - return schema + "." + d.QuoteField(table) -} - -func (d MySQLDialect) IfSchemaNotExists(command, schema string) string { - return fmt.Sprintf("%s if not exists", command) -} - -func (d MySQLDialect) IfTableExists(command, schema, table string) string { - return fmt.Sprintf("%s if exists", command) -} - -func (d MySQLDialect) IfTableNotExists(command, schema, table string) string { - return fmt.Sprintf("%s if not exists", command) -} diff --git a/vendor/github.com/mattermost/gorp/dialect_oracle.go b/vendor/github.com/mattermost/gorp/dialect_oracle.go deleted file mode 100644 index b1cee0a0a1..0000000000 --- a/vendor/github.com/mattermost/gorp/dialect_oracle.go +++ /dev/null @@ -1,148 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" - "strings" -) - -// 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 "" } - -func (d OracleDialect) DropIndexSuffix() string { return "" } - -func (d OracleDialect) ToSqlType(val reflect.Type, maxsize int, isAutoIncr bool) string { - switch val.Kind() { - case reflect.Ptr: - return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) - case reflect.Bool: - return "boolean" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: - if isAutoIncr { - return "serial" - } - return "integer" - case reflect.Int64, reflect.Uint64: - if isAutoIncr { - return "bigserial" - } - return "bigint" - case reflect.Float64: - return "double precision" - case reflect.Float32: - return "real" - case reflect.Slice: - if val.Elem().Kind() == reflect.Uint8 { - return "bytea" - } - } - - switch val.Name() { - case "NullInt64": - return "bigint" - case "NullFloat64": - return "double precision" - case "NullBool": - return "boolean" - case "NullTime", "Time": - return "timestamp with time zone" - } - - if maxsize > 0 { - return fmt.Sprintf("varchar(%d)", maxsize) - } else { - return "text" - } - -} - -// Returns empty string -func (d OracleDialect) AutoIncrStr() string { - return "" -} - -func (d OracleDialect) AutoIncrBindValue() string { - return "NULL" -} - -func (d OracleDialect) AutoIncrInsertSuffix(col *ColumnMap) string { - return "" -} - -// Returns suffix -func (d OracleDialect) CreateTableSuffix() string { - return "" -} - -func (d OracleDialect) TruncateClause() string { - return "truncate" -} - -// Returns "$(i+1)" -func (d OracleDialect) BindVar(i int) string { - return fmt.Sprintf(":%d", i+1) -} - -// After executing the insert uses the ColMap IdQuery to get the generated id -func (d OracleDialect) InsertQueryToTarget(exec SqlExecutor, insertSql, idSql string, target interface{}, params ...interface{}) error { - _, err := exec.Exec(insertSql, params...) - if err != nil { - return err - } - id, err := exec.SelectInt(idSql) - if err != nil { - return err - } - switch target.(type) { - case *int64: - *(target.(*int64)) = id - case *int32: - *(target.(*int32)) = int32(id) - case int: - *(target.(*int)) = int(id) - default: - return fmt.Errorf("Id field can be int, int32 or int64") - } - return nil -} - -func (d OracleDialect) QuoteField(f string) string { - return `"` + strings.ToUpper(f) + `"` -} - -func (d OracleDialect) QuotedTableForQuery(schema string, table string) string { - if strings.TrimSpace(schema) == "" { - return d.QuoteField(table) - } - - return schema + "." + d.QuoteField(table) -} - -func (d OracleDialect) IfSchemaNotExists(command, schema string) string { - return fmt.Sprintf("%s if not exists", command) -} - -func (d OracleDialect) IfTableExists(command, schema, table string) string { - return fmt.Sprintf("%s if exists", command) -} - -func (d OracleDialect) IfTableNotExists(command, schema, table string) string { - return fmt.Sprintf("%s if not exists", command) -} diff --git a/vendor/github.com/mattermost/gorp/dialect_postgres.go b/vendor/github.com/mattermost/gorp/dialect_postgres.go deleted file mode 100644 index aa7f34cbad..0000000000 --- a/vendor/github.com/mattermost/gorp/dialect_postgres.go +++ /dev/null @@ -1,149 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" - "strings" -) - -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 { - switch val.Kind() { - case reflect.Ptr: - return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) - case reflect.Bool: - return "boolean" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32: - if isAutoIncr { - return "serial" - } - return "integer" - case reflect.Int64, reflect.Uint64: - if isAutoIncr { - return "bigserial" - } - return "bigint" - case reflect.Float64: - return "double precision" - case reflect.Float32: - return "real" - case reflect.Slice: - if val.Elem().Kind() == reflect.Uint8 { - return "bytea" - } - } - - switch val.Name() { - case "NullInt64": - return "bigint" - case "NullFloat64": - return "double precision" - case "NullBool": - return "boolean" - case "Time", "NullTime": - return "timestamp with time zone" - } - - if maxsize > 0 { - return fmt.Sprintf("varchar(%d)", maxsize) - } else { - return "text" - } - -} - -// Returns empty string -func (d PostgresDialect) AutoIncrStr() string { - return "" -} - -func (d PostgresDialect) AutoIncrBindValue() string { - return "default" -} - -func (d PostgresDialect) AutoIncrInsertSuffix(col *ColumnMap) string { - return " returning " + d.QuoteField(col.ColumnName) -} - -// Returns suffix -func (d PostgresDialect) CreateTableSuffix() string { - return d.suffix -} - -func (d PostgresDialect) CreateIndexSuffix() string { - return "using" -} - -func (d PostgresDialect) DropIndexSuffix() string { - return "" -} - -func (d PostgresDialect) TruncateClause() string { - return "truncate" -} - -// Returns "$(i+1)" -func (d PostgresDialect) BindVar(i int) string { - return fmt.Sprintf("$%d", i+1) -} - -func (d PostgresDialect) InsertAutoIncrToTarget(exec SqlExecutor, insertSql string, target interface{}, params ...interface{}) error { - rows, err := exec.Query(insertSql, params...) - if err != nil { - return err - } - defer rows.Close() - - if !rows.Next() { - return fmt.Errorf("No serial value returned for insert: %s Encountered error: %s", insertSql, rows.Err()) - } - if err := rows.Scan(target); err != nil { - return err - } - if rows.Next() { - return fmt.Errorf("more than two serial value returned for insert: %s", insertSql) - } - return rows.Err() -} - -func (d PostgresDialect) QuoteField(f string) string { - return `"` + strings.ToLower(f) + `"` -} - -func (d PostgresDialect) QuotedTableForQuery(schema string, table string) string { - if strings.TrimSpace(schema) == "" { - return d.QuoteField(table) - } - - return schema + "." + d.QuoteField(table) -} - -func (d PostgresDialect) IfSchemaNotExists(command, schema string) string { - return fmt.Sprintf("%s if not exists", command) -} - -func (d PostgresDialect) IfTableExists(command, schema, table string) string { - return fmt.Sprintf("%s if exists", command) -} - -func (d PostgresDialect) IfTableNotExists(command, schema, table string) string { - return fmt.Sprintf("%s if not exists", command) -} diff --git a/vendor/github.com/mattermost/gorp/dialect_sqlite.go b/vendor/github.com/mattermost/gorp/dialect_sqlite.go deleted file mode 100644 index e78605983f..0000000000 --- a/vendor/github.com/mattermost/gorp/dialect_sqlite.go +++ /dev/null @@ -1,121 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" -) - -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 { - switch val.Kind() { - case reflect.Ptr: - return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) - case reflect.Bool: - return "integer" - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return "integer" - case reflect.Float64, reflect.Float32: - return "real" - case reflect.Slice: - if val.Elem().Kind() == reflect.Uint8 { - return "blob" - } - } - - switch val.Name() { - case "NullInt64": - return "integer" - case "NullFloat64": - return "real" - case "NullBool": - return "integer" - case "Time": - return "datetime" - } - - if maxsize < 1 { - maxsize = 255 - } - return fmt.Sprintf("varchar(%d)", maxsize) -} - -// Returns autoincrement -func (d SqliteDialect) AutoIncrStr() string { - return "autoincrement" -} - -func (d SqliteDialect) AutoIncrBindValue() string { - return "null" -} - -func (d SqliteDialect) AutoIncrInsertSuffix(col *ColumnMap) string { - return "" -} - -// Returns suffix -func (d SqliteDialect) CreateTableSuffix() string { - return d.suffix -} - -func (d SqliteDialect) CreateIndexSuffix() string { - return "" -} - -func (d SqliteDialect) DropIndexSuffix() string { - return "" -} - -// With sqlite, there technically isn't a TRUNCATE statement, -// but a DELETE FROM uses a truncate optimization: -// http://www.sqlite.org/lang_delete.html -func (d SqliteDialect) TruncateClause() string { - return "delete from" -} - -// Returns "?" -func (d SqliteDialect) BindVar(i int) string { - return "?" -} - -func (d SqliteDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) { - return standardInsertAutoIncr(exec, insertSql, params...) -} - -func (d SqliteDialect) QuoteField(f string) string { - return `"` + f + `"` -} - -// sqlite does not have schemas like PostgreSQL does, so just escape it like normal -func (d SqliteDialect) QuotedTableForQuery(schema string, table string) string { - return d.QuoteField(table) -} - -func (d SqliteDialect) IfSchemaNotExists(command, schema string) string { - return fmt.Sprintf("%s if not exists", command) -} - -func (d SqliteDialect) IfTableExists(command, schema, table string) string { - return fmt.Sprintf("%s if exists", command) -} - -func (d SqliteDialect) IfTableNotExists(command, schema, table string) string { - return fmt.Sprintf("%s if not exists", command) -} diff --git a/vendor/github.com/mattermost/gorp/dialect_sqlserver.go b/vendor/github.com/mattermost/gorp/dialect_sqlserver.go deleted file mode 100644 index 904110e35b..0000000000 --- a/vendor/github.com/mattermost/gorp/dialect_sqlserver.go +++ /dev/null @@ -1,154 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" - "strings" -) - -// Implementation of Dialect for Microsoft SQL Server databases. -// Use gorp.SqlServerDialect{"2005"} for legacy datatypes. -// Tested with driver: github.com/denisenkom/go-mssqldb - -type SqlServerDialect struct { - - // If set to "2005" legacy datatypes will be used - 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: - return d.ToSqlType(val.Elem(), maxsize, isAutoIncr) - case reflect.Bool: - return "bit" - case reflect.Int8: - return "tinyint" - case reflect.Uint8: - return "smallint" - case reflect.Int16: - return "smallint" - case reflect.Uint16: - return "int" - case reflect.Int, reflect.Int32: - return "int" - case reflect.Uint, reflect.Uint32: - return "bigint" - case reflect.Int64: - return "bigint" - case reflect.Uint64: - return "numeric(20,0)" - case reflect.Float32: - return "float(24)" - case reflect.Float64: - return "float(53)" - case reflect.Slice: - if val.Elem().Kind() == reflect.Uint8 { - return "varbinary" - } - } - - switch val.Name() { - case "NullInt64": - return "bigint" - case "NullFloat64": - return "float(53)" - case "NullBool": - return "bit" - case "NullTime", "Time": - if d.Version == "2005" { - return "datetime" - } - return "datetime2" - } - - if maxsize < 1 { - if d.Version == "2005" { - maxsize = 255 - } else { - return fmt.Sprintf("nvarchar(max)") - } - } - return fmt.Sprintf("nvarchar(%d)", maxsize) -} - -// Returns auto_increment -func (d SqlServerDialect) AutoIncrStr() string { - return "identity(0,1)" -} - -// Empty string removes autoincrement columns from the INSERT statements. -func (d SqlServerDialect) AutoIncrBindValue() string { - return "" -} - -func (d SqlServerDialect) AutoIncrInsertSuffix(col *ColumnMap) string { - return "" -} - -func (d SqlServerDialect) CreateTableSuffix() string { return ";" } - -func (d SqlServerDialect) TruncateClause() string { - return "truncate table" -} - -// Returns "?" -func (d SqlServerDialect) BindVar(i int) string { - return "?" -} - -func (d SqlServerDialect) InsertAutoIncr(exec SqlExecutor, insertSql string, params ...interface{}) (int64, error) { - return standardInsertAutoIncr(exec, insertSql, params...) -} - -func (d SqlServerDialect) QuoteField(f string) string { - return "[" + strings.Replace(f, "]", "]]", -1) + "]" -} - -func (d SqlServerDialect) QuotedTableForQuery(schema string, table string) string { - if strings.TrimSpace(schema) == "" { - return d.QuoteField(table) - } - return d.QuoteField(schema) + "." + d.QuoteField(table) -} - -func (d SqlServerDialect) QuerySuffix() string { return ";" } - -func (d SqlServerDialect) IfSchemaNotExists(command, schema string) string { - s := fmt.Sprintf("if schema_id(N'%s') is null %s", schema, command) - return s -} - -func (d SqlServerDialect) IfTableExists(command, schema, table string) string { - var schema_clause string - if strings.TrimSpace(schema) != "" { - schema_clause = fmt.Sprintf("%s.", d.QuoteField(schema)) - } - s := fmt.Sprintf("if object_id('%s%s') is not null %s", schema_clause, d.QuoteField(table), command) - return s -} - -func (d SqlServerDialect) IfTableNotExists(command, schema, table string) string { - var schema_clause string - if strings.TrimSpace(schema) != "" { - schema_clause = fmt.Sprintf("%s.", schema) - } - s := fmt.Sprintf("if object_id('%s%s') is null %s", schema_clause, table, command) - return s -} - -func (d SqlServerDialect) CreateIndexSuffix() string { return "" } -func (d SqlServerDialect) DropIndexSuffix() string { return "" } diff --git a/vendor/github.com/mattermost/gorp/errors.go b/vendor/github.com/mattermost/gorp/errors.go deleted file mode 100644 index d13f03fc3c..0000000000 --- a/vendor/github.com/mattermost/gorp/errors.go +++ /dev/null @@ -1,38 +0,0 @@ -// 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 - -import ( - "fmt" -) - -// A non-fatal error, when a select query returns columns that do not exist -// as fields in the struct it is being mapped to -// TODO: discuss wether this needs an error. encoding/json silently ignores missing fields -type NoFieldInTypeError struct { - TypeName string - MissingColNames []string -} - -func (err *NoFieldInTypeError) Error() string { - return fmt.Sprintf("gorp: no fields %+v in type %s", err.MissingColNames, err.TypeName) -} - -// returns true if the error is non-fatal (ie, we shouldn't immediately return) -func NonFatalError(err error) bool { - switch err.(type) { - case *NoFieldInTypeError: - return true - default: - return false - } -} diff --git a/vendor/github.com/mattermost/gorp/go.mod b/vendor/github.com/mattermost/gorp/go.mod deleted file mode 100644 index e183a2dbf7..0000000000 --- a/vendor/github.com/mattermost/gorp/go.mod +++ /dev/null @@ -1,13 +0,0 @@ -module github.com/mattermost/gorp - -go 1.13 - -require ( - github.com/go-sql-driver/mysql v1.5.0 - github.com/lib/pq v1.3.0 - github.com/mattn/go-sqlite3 v2.0.3+incompatible - github.com/onsi/ginkgo v1.13.0 - github.com/onsi/gomega v1.10.1 - github.com/ziutek/mymysql v1.5.4 - golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 // indirect -) diff --git a/vendor/github.com/mattermost/gorp/go.sum b/vendor/github.com/mattermost/gorp/go.sum deleted file mode 100644 index 441b96dc58..0000000000 --- a/vendor/github.com/mattermost/gorp/go.sum +++ /dev/null @@ -1,79 +0,0 @@ -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= -github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= -github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.13.0 h1:M76yO2HkZASFjXL0HSoZJ1AYEmQxNJmY41Jx1zNUq1Y= -github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1lskyM0= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= -github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs= -github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e h1:N7DeIrjYszNmSW409R3frPPwglRwMkXSBzwVbkOjLLA= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4= -golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/mattermost/gorp/gorp.go b/vendor/github.com/mattermost/gorp/gorp.go deleted file mode 100644 index ee7ad1db82..0000000000 --- a/vendor/github.com/mattermost/gorp/gorp.go +++ /dev/null @@ -1,608 +0,0 @@ -// 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 - -import ( - "context" - "database/sql" - "database/sql/driver" - "fmt" - "reflect" - "regexp" - "strings" - "time" -) - -// OracleString (empty string is null) -// TODO: move to dialect/oracle?, rename to String? -type OracleString struct { - sql.NullString -} - -// Scan implements the Scanner interface. -func (os *OracleString) Scan(value interface{}) error { - if value == nil { - os.String, os.Valid = "", false - return nil - } - os.Valid = true - return os.NullString.Scan(value) -} - -// Value implements the driver Valuer interface. -func (os OracleString) Value() (driver.Value, error) { - if !os.Valid || os.String == "" { - return nil, nil - } - return os.String, nil -} - -// SqlTyper is a type that returns its database type. Most of the -// time, the type can just use "database/sql/driver".Valuer; but when -// it returns nil for its empty value, it needs to implement SqlTyper -// to have its column type detected properly during table creation. -type SqlTyper interface { - SqlType() driver.Valuer -} - -// for fields that exists in DB table, but not exists in struct -type dummyField struct{} - -// Scan implements the Scanner interface. -func (nt *dummyField) Scan(value interface{}) error { - return nil -} - -var zeroVal reflect.Value -var versFieldConst = "[gorp_ver_field]" - -// The TypeConverter interface provides a way to map a value of one -// type to another type when persisting to, or loading from, a database. -// -// Example use cases: Implement type converter to convert bool types to "y"/"n" strings, -// or serialize a struct member as a JSON blob. -type TypeConverter interface { - // ToDb converts val to another type. Called before INSERT/UPDATE operations - ToDb(val interface{}) (interface{}, error) - - // FromDb returns a CustomScanner appropriate for this type. This will be used - // to hold values returned from SELECT queries. - // - // In particular the CustomScanner returned should implement a Binder - // function appropriate for the Go type you wish to convert the db value to - // - // If bool==false, then no custom scanner will be used for this field. - FromDb(target interface{}) (CustomScanner, bool) -} - -// Executor exposes the sql.DB and sql.Tx Exec function so that it can be used -// 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 -// hooks. This hides whether the current operation that triggered the -// hook is in a transaction. -// -// See the DbMap function docs for each of the functions below for more -// information. -type SqlExecutor interface { - Get(i interface{}, keys ...interface{}) (interface{}, error) - Insert(list ...interface{}) error - 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) - SelectNullInt(query string, args ...interface{}) (sql.NullInt64, error) - SelectFloat(query string, args ...interface{}) (float64, error) - SelectNullFloat(query string, args ...interface{}) (sql.NullFloat64, error) - 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) - 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 -// interface. -var _, _ SqlExecutor = &DbMap{}, &Transaction{} - -func argsString(args ...interface{}) string { - var margs string - for i, a := range args { - var v interface{} = a - if x, ok := v.(driver.Valuer); ok { - y, err := x.Value() - if err == nil { - v = y - } - } - switch v.(type) { - case string: - v = fmt.Sprintf("%q", v) - default: - v = fmt.Sprintf("%v", v) - } - margs += fmt.Sprintf("%d:%s", i+1, v) - if i+1 < len(args) { - margs += " " - } - } - return margs -} - -// Calls the Exec function on the executor, but attempts to expand any eligible named -// query arguments first. -func exec(e SqlExecutor, query string, doTimeout bool, args ...interface{}) (sql.Result, error) { - var dbMap *DbMap - var executor executor - switch m := e.(type) { - case *DbMap: - executor = m.Db - dbMap = m - case *Transaction: - executor = m.tx - dbMap = m.dbmap - } - - if len(args) == 1 { - query, args = maybeExpandNamedQuery(dbMap, query, args) - } - - if doTimeout { - ctx, cancel := context.WithTimeout(context.Background(), dbMap.QueryTimeout) - defer cancel() - return executor.ExecContext(ctx, query, args...) - } - - return executor.Exec(query, args...) -} - -// maybeExpandNamedQuery checks the given arg to see if it's eligible to be used -// as input to a named query. If so, it rewrites the query to use -// dialect-dependent bindvars and instantiates the corresponding slice of -// parameters by extracting data from the map / struct. -// If not, returns the input values unchanged. -func maybeExpandNamedQuery(m *DbMap, query string, args []interface{}) (string, []interface{}) { - var ( - arg = args[0] - argval = reflect.ValueOf(arg) - ) - if argval.Kind() == reflect.Ptr { - argval = argval.Elem() - } - - if argval.Kind() == reflect.Map && argval.Type().Key().Kind() == reflect.String { - return expandNamedQuery(m, query, func(key string) reflect.Value { - return argval.MapIndex(reflect.ValueOf(key)) - }) - } - if argval.Kind() != reflect.Struct { - return query, args - } - if _, ok := arg.(time.Time); ok { - // time.Time is driver.Value - return query, args - } - if _, ok := arg.(driver.Valuer); ok { - // driver.Valuer will be converted to driver.Value. - return query, args - } - - return expandNamedQuery(m, query, argval.FieldByName) -} - -var keyRegexp = regexp.MustCompile(`:[[:word:]]+`) - -// expandNamedQuery accepts a query with placeholders of the form ":key", and a -// single arg of Kind Struct or Map[string]. It returns the query with the -// dialect's placeholders, and a slice of args ready for positional insertion -// into the query. -func expandNamedQuery(m *DbMap, query string, keyGetter func(key string) reflect.Value) (string, []interface{}) { - var ( - n int - args []interface{} - ) - return keyRegexp.ReplaceAllStringFunc(query, func(key string) string { - val := keyGetter(key[1:]) - if !val.IsValid() { - return key - } - args = append(args, val.Interface()) - newVar := m.Dialect.BindVar(n) - n++ - return newVar - }), args -} - -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, name) - if table != nil { - tableMapped = true - } - - // Loop over column names and find field in i to bind to - // based on column name. all returned columns must match - // a field in the i struct - missingColNames := []string{} - for x := range cols { - colName := strings.ToLower(cols[x]) - field, found := t.FieldByNameFunc(func(fieldName string) bool { - field, _ := t.FieldByName(fieldName) - cArguments := strings.Split(field.Tag.Get("db"), ",") - fieldName = cArguments[0] - - if fieldName == "" || fieldName == "-" { - fieldName = field.Name - } - if tableMapped { - colMap := colMapOrNil(table, fieldName) - if colMap != nil && colMap.ColumnName != "-" { - fieldName = colMap.ColumnName - } - } - return colName == strings.ToLower(fieldName) - }) - if found { - colToFieldIndex[x] = field.Index - } - if colToFieldIndex[x] == nil { - missingColNames = append(missingColNames, colName) - } - } - if len(missingColNames) > 0 { - return colToFieldIndex, &NoFieldInTypeError{ - TypeName: t.Name(), - MissingColNames: missingColNames, - } - } - return colToFieldIndex, nil -} - -func fieldByName(val reflect.Value, fieldName string) *reflect.Value { - // try to find field by exact match - f := val.FieldByName(fieldName) - - if f != zeroVal { - return &f - } - - // try to find by case insensitive match - only the Postgres driver - // seems to require this - in the case where columns are aliased in the sql - fieldNameL := strings.ToLower(fieldName) - fieldCount := val.NumField() - t := val.Type() - for i := 0; i < fieldCount; i++ { - sf := t.Field(i) - if strings.ToLower(sf.Name) == fieldNameL { - f := val.Field(i) - return &f - } - } - - return nil -} - -// toSliceType returns the element type of the given object, if the object is a -// "*[]*Element" or "*[]Element". If not, returns nil. -// err is returned if the user was trying to pass a pointer-to-slice but failed. -func toSliceType(i interface{}) (reflect.Type, error) { - t := reflect.TypeOf(i) - if t.Kind() != reflect.Ptr { - // If it's a slice, return a more helpful error message - if t.Kind() == reflect.Slice { - return nil, fmt.Errorf("gorp: cannot SELECT into a non-pointer slice: %v", t) - } - return nil, nil - } - if t = t.Elem(); t.Kind() != reflect.Slice { - return nil, nil - } - return t.Elem(), nil -} - -func toType(i interface{}) (reflect.Type, error) { - t := reflect.TypeOf(i) - - // If a Pointer to a type, follow - for t.Kind() == reflect.Ptr { - t = t.Elem() - } - - if t.Kind() != reflect.Struct { - return nil, fmt.Errorf("gorp: cannot SELECT into this type: %v", reflect.TypeOf(i)) - } - 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) { - - t, err := toType(i) - if err != nil { - return nil, err - } - - 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 - custScan := make([]CustomScanner, 0) - - for x, fieldName := range plan.argFields { - f := v.Elem().FieldByName(fieldName) - target := f.Addr().Interface() - if conv != nil { - scanner, ok := conv.FromDb(target) - if ok { - target = scanner.Holder - custScan = append(custScan, scanner) - } - } - dest[x] = target - } - - ctx, cancel := context.WithTimeout(context.Background(), m.QueryTimeout) - defer cancel() - row := exec.QueryRowContext(ctx, plan.query, keys...) - - err = row.Scan(dest...) - if err != nil { - if err == sql.ErrNoRows { - err = nil - } - return nil, err - } - - for _, c := range custScan { - err = c.Bind() - if err != nil { - return nil, err - } - } - - if v, ok := v.Interface().(HasPostGet); ok { - err := v.PostGet(exec) - if err != nil { - return nil, err - } - } - - return v.Interface(), nil -} - -func delete(m *DbMap, exec SqlExecutor, list ...interface{}) (int64, error) { - count := int64(0) - for _, ptr := range list { - table, elem, err := m.tableForPointer(ptr, true) - if err != nil { - return -1, err - } - - eval := elem.Addr().Interface() - if v, ok := eval.(HasPreDelete); ok { - err = v.PreDelete(exec) - if err != nil { - return -1, err - } - } - - bi, err := table.bindDelete(elem) - if err != nil { - return -1, err - } - - res, err := exec.Exec(bi.query, bi.args...) - if err != nil { - return -1, err - } - rows, err := res.RowsAffected() - if err != nil { - return -1, err - } - - if rows == 0 && bi.existingVersion > 0 { - return lockError(m, exec, table.TableName, - bi.existingVersion, elem, bi.keys...) - } - - count += rows - - if v, ok := eval.(HasPostDelete); ok { - err := v.PostDelete(exec) - if err != nil { - return -1, err - } - } - } - - return count, nil -} - -func update(m *DbMap, exec SqlExecutor, colFilter ColumnFilter, list ...interface{}) (int64, error) { - count := int64(0) - for _, ptr := range list { - table, elem, err := m.tableForPointer(ptr, true) - if err != nil { - return -1, err - } - - eval := elem.Addr().Interface() - if v, ok := eval.(HasPreUpdate); ok { - err = v.PreUpdate(exec) - if err != nil { - return -1, err - } - } - - bi, err := table.bindUpdate(elem, colFilter) - if err != nil { - return -1, err - } - - res, err := exec.Exec(bi.query, bi.args...) - if err != nil { - return -1, err - } - - rows, err := res.RowsAffected() - if err != nil { - return -1, err - } - - if rows == 0 && bi.existingVersion > 0 { - return lockError(m, exec, table.TableName, - bi.existingVersion, elem, bi.keys...) - } - - if bi.versField != "" { - elem.FieldByName(bi.versField).SetInt(bi.existingVersion + 1) - } - - count += rows - - if v, ok := eval.(HasPostUpdate); ok { - err = v.PostUpdate(exec) - if err != nil { - return -1, err - } - } - } - return count, nil -} - -func insert(m *DbMap, exec SqlExecutor, list ...interface{}) error { - for _, ptr := range list { - table, elem, err := m.tableForPointer(ptr, false) - if err != nil { - return err - } - - eval := elem.Addr().Interface() - if v, ok := eval.(HasPreInsert); ok { - err := v.PreInsert(exec) - if err != nil { - return err - } - } - - bi, err := table.bindInsert(elem) - if err != nil { - return err - } - - if bi.autoIncrIdx > -1 { - f := elem.FieldByName(bi.autoIncrFieldName) - switch inserter := m.Dialect.(type) { - case IntegerAutoIncrInserter: - id, err := inserter.InsertAutoIncr(exec, bi.query, bi.args...) - if err != nil { - return err - } - k := f.Kind() - if (k == reflect.Int) || (k == reflect.Int16) || (k == reflect.Int32) || (k == reflect.Int64) { - f.SetInt(id) - } else if (k == reflect.Uint) || (k == reflect.Uint16) || (k == reflect.Uint32) || (k == reflect.Uint64) { - f.SetUint(uint64(id)) - } else { - return fmt.Errorf("gorp: cannot set autoincrement value on non-Int field. SQL=%s autoIncrIdx=%d autoIncrFieldName=%s", bi.query, bi.autoIncrIdx, bi.autoIncrFieldName) - } - case TargetedAutoIncrInserter: - err := inserter.InsertAutoIncrToTarget(exec, bi.query, f.Addr().Interface(), bi.args...) - if err != nil { - return err - } - case TargetQueryInserter: - var idQuery = table.ColMap(bi.autoIncrFieldName).GeneratedIdQuery - if idQuery == "" { - return fmt.Errorf("gorp: cannot set %s value if its ColumnMap.GeneratedIdQuery is empty", bi.autoIncrFieldName) - } - err := inserter.InsertQueryToTarget(exec, bi.query, idQuery, f.Addr().Interface(), bi.args...) - if err != nil { - return err - } - default: - return fmt.Errorf("gorp: cannot use autoincrement fields on dialects that do not implement an autoincrementing interface") - } - } else { - _, err := exec.Exec(bi.query, bi.args...) - if err != nil { - return err - } - } - - if v, ok := eval.(HasPostInsert); ok { - err := v.PostInsert(exec) - if err != nil { - return err - } - } - } - return nil -} diff --git a/vendor/github.com/mattermost/gorp/hooks.go b/vendor/github.com/mattermost/gorp/hooks.go deleted file mode 100644 index 192b51f00a..0000000000 --- a/vendor/github.com/mattermost/gorp/hooks.go +++ /dev/null @@ -1,49 +0,0 @@ -// 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 - -//++ TODO v2-phase3: HasPostGet => PostGetter, HasPostDelete => PostDeleter, etc. - -// PostUpdate() will be executed after the GET statement. -type HasPostGet interface { - PostGet(SqlExecutor) error -} - -// PostUpdate() will be executed after the DELETE statement -type HasPostDelete interface { - PostDelete(SqlExecutor) error -} - -// PostUpdate() will be executed after the UPDATE statement -type HasPostUpdate interface { - PostUpdate(SqlExecutor) error -} - -// PostInsert() will be executed after the INSERT statement -type HasPostInsert interface { - PostInsert(SqlExecutor) error -} - -// PreDelete() will be executed before the DELETE statement. -type HasPreDelete interface { - PreDelete(SqlExecutor) error -} - -// PreUpdate() will be executed before UPDATE statement. -type HasPreUpdate interface { - PreUpdate(SqlExecutor) error -} - -// PreInsert() will be executed before INSERT statement. -type HasPreInsert interface { - PreInsert(SqlExecutor) error -} diff --git a/vendor/github.com/mattermost/gorp/index.go b/vendor/github.com/mattermost/gorp/index.go deleted file mode 100644 index 01ecd9ecaa..0000000000 --- a/vendor/github.com/mattermost/gorp/index.go +++ /dev/null @@ -1,56 +0,0 @@ -// 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 - -// IndexMap represents a mapping between a Go struct field and a single -// index in a table. -// Unique and MaxSize only inform the -// CreateTables() function and are not used by Insert/Update/Delete/Get. -type IndexMap struct { - // Index name in db table - IndexName string - - // If true, " unique" is added to create index statements. - // Not used elsewhere - Unique bool - - // Index type supported by Dialect - // Postgres: B-tree, Hash, GiST and GIN. - // Mysql: Btree, Hash. - // Sqlite: nil. - IndexType string - - // Columns name for single and multiple indexes - columns []string -} - -// Rename allows you to specify the index name in the table -// -// Example: table.IndMap("customer_test_idx").Rename("customer_idx") -// -func (idx *IndexMap) Rename(indname string) *IndexMap { - idx.IndexName = indname - return idx -} - -// SetUnique adds "unique" to the create index statements for this -// index, if b is true. -func (idx *IndexMap) SetUnique(b bool) *IndexMap { - idx.Unique = b - return idx -} - -// SetIndexType specifies the index type supported by chousen SQL Dialect -func (idx *IndexMap) SetIndexType(indtype string) *IndexMap { - idx.IndexType = indtype - return idx -} diff --git a/vendor/github.com/mattermost/gorp/lockerror.go b/vendor/github.com/mattermost/gorp/lockerror.go deleted file mode 100644 index 07b3047aef..0000000000 --- a/vendor/github.com/mattermost/gorp/lockerror.go +++ /dev/null @@ -1,63 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" -) - -// OptimisticLockError is returned by Update() or Delete() if the -// struct being modified has a Version field and the value is not equal to -// the current value in the database -type OptimisticLockError struct { - // Table name where the lock error occurred - TableName string - - // Primary key values of the row being updated/deleted - Keys []interface{} - - // true if a row was found with those keys, indicating the - // LocalVersion is stale. false if no value was found with those - // keys, suggesting the row has been deleted since loaded, or - // was never inserted to begin with - RowExists bool - - // Version value on the struct passed to Update/Delete. This value is - // out of sync with the database. - LocalVersion int64 -} - -// Error returns a description of the cause of the lock error -func (e OptimisticLockError) Error() string { - if e.RowExists { - return fmt.Sprintf("gorp: OptimisticLockError table=%s keys=%v out of date version=%d", e.TableName, e.Keys, e.LocalVersion) - } - - return fmt.Sprintf("gorp: OptimisticLockError no row found for table=%s keys=%v", e.TableName, e.Keys) -} - -func lockError(m *DbMap, exec SqlExecutor, tableName string, - existingVer int64, elem reflect.Value, - keys ...interface{}) (int64, error) { - - existing, err := get(m, exec, elem.Interface(), keys...) - if err != nil { - return -1, err - } - - ole := OptimisticLockError{tableName, keys, true, existingVer} - if existing == nil { - ole.RowExists = false - } - return -1, ole -} diff --git a/vendor/github.com/mattermost/gorp/logging.go b/vendor/github.com/mattermost/gorp/logging.go deleted file mode 100644 index 89d6c0e79e..0000000000 --- a/vendor/github.com/mattermost/gorp/logging.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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 - -import "fmt" - -type GorpLogger interface { - Printf(format string, v ...interface{}) -} - -// TraceOn turns on SQL statement logging for this DbMap. After this is -// called, all SQL statements will be sent to the logger. If prefix is -// a non-empty string, it will be written to the front of all logged -// strings, which can aid in filtering log lines. -// -// Use TraceOn if you want to spy on the SQL statements that gorp -// generates. -// -// Note that the base log.Logger type satisfies GorpLogger, but adapters can -// easily be written for other logging packages (e.g., the golang-sanctioned -// glog framework). -func (m *DbMap) TraceOn(prefix string, logger GorpLogger) { - m.logger = logger - if prefix == "" { - m.logPrefix = prefix - } else { - m.logPrefix = fmt.Sprintf("%s ", prefix) - } -} - -// TraceOff turns off tracing. It is idempotent. -func (m *DbMap) TraceOff() { - m.logger = nil - m.logPrefix = "" -} diff --git a/vendor/github.com/mattermost/gorp/nulltypes.go b/vendor/github.com/mattermost/gorp/nulltypes.go deleted file mode 100644 index 8dee1d408e..0000000000 --- a/vendor/github.com/mattermost/gorp/nulltypes.go +++ /dev/null @@ -1,70 +0,0 @@ -// 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 - -import ( - "database/sql/driver" - "time" -) - -// A nullable Time value -type NullTime struct { - Time time.Time - Valid bool // Valid is true if Time is not NULL -} - -// Scan implements the Scanner interface. -func (nt *NullTime) Scan(value interface{}) error { - switch t := value.(type) { - case time.Time: - nt.Time, nt.Valid = t, true - case []byte: - v := strToTime(string(t)) - if v != nil { - nt.Valid = true - nt.Time = *v - } - case string: - v := strToTime(t) - if v != nil { - nt.Valid = true - nt.Time = *v - } - } - return nil -} - -func strToTime(v string) *time.Time { - for _, dtfmt := range []string{ - "2006-01-02 15:04:05.999999999", - "2006-01-02T15:04:05.999999999", - "2006-01-02 15:04:05", - "2006-01-02T15:04:05", - "2006-01-02 15:04", - "2006-01-02T15:04", - "2006-01-02", - "2006-01-02 15:04:05-07:00", - } { - if t, err := time.Parse(dtfmt, v); err == nil { - return &t - } - } - return nil -} - -// Value implements the driver Valuer interface. -func (nt NullTime) Value() (driver.Value, error) { - if !nt.Valid { - return nil, nil - } - return nt.Time, nil -} diff --git a/vendor/github.com/mattermost/gorp/select.go b/vendor/github.com/mattermost/gorp/select.go deleted file mode 100644 index 10c84b0844..0000000000 --- a/vendor/github.com/mattermost/gorp/select.go +++ /dev/null @@ -1,372 +0,0 @@ -// 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 - -import ( - "context" - "database/sql" - "fmt" - "reflect" -) - -// SelectInt executes the given query, which should be a SELECT statement for a single -// integer column, and returns the value of the first row returned. If no rows are -// found, zero is returned. -func SelectInt(e SqlExecutor, query string, args ...interface{}) (int64, error) { - var h int64 - err := selectVal(e, &h, query, args...) - if err != nil && err != sql.ErrNoRows { - return 0, err - } - return h, nil -} - -// SelectNullInt executes the given query, which should be a SELECT statement for a single -// integer column, and returns the value of the first row returned. If no rows are -// found, the empty sql.NullInt64 value is returned. -func SelectNullInt(e SqlExecutor, query string, args ...interface{}) (sql.NullInt64, error) { - var h sql.NullInt64 - err := selectVal(e, &h, query, args...) - if err != nil && err != sql.ErrNoRows { - return h, err - } - return h, nil -} - -// SelectFloat executes the given query, which should be a SELECT statement for a single -// float column, and returns the value of the first row returned. If no rows are -// found, zero is returned. -func SelectFloat(e SqlExecutor, query string, args ...interface{}) (float64, error) { - var h float64 - err := selectVal(e, &h, query, args...) - if err != nil && err != sql.ErrNoRows { - return 0, err - } - return h, nil -} - -// SelectNullFloat executes the given query, which should be a SELECT statement for a single -// float column, and returns the value of the first row returned. If no rows are -// found, the empty sql.NullInt64 value is returned. -func SelectNullFloat(e SqlExecutor, query string, args ...interface{}) (sql.NullFloat64, error) { - var h sql.NullFloat64 - err := selectVal(e, &h, query, args...) - if err != nil && err != sql.ErrNoRows { - return h, err - } - return h, nil -} - -// SelectStr executes the given query, which should be a SELECT statement for a single -// char/varchar column, and returns the value of the first row returned. If no rows are -// found, an empty string is returned. -func SelectStr(e SqlExecutor, query string, args ...interface{}) (string, error) { - var h string - err := selectVal(e, &h, query, args...) - if err != nil && err != sql.ErrNoRows { - return "", err - } - return h, nil -} - -// SelectNullStr executes the given query, which should be a SELECT -// statement for a single char/varchar column, and returns the value -// of the first row returned. If no rows are found, the empty -// sql.NullString is returned. -func SelectNullStr(e SqlExecutor, query string, args ...interface{}) (sql.NullString, error) { - var h sql.NullString - err := selectVal(e, &h, query, args...) - if err != nil && err != sql.ErrNoRows { - return h, err - } - return h, nil -} - -// SelectOne executes the given query (which should be a SELECT statement) -// and binds the result to holder, which must be a pointer. -// -// If no row is found, an error (sql.ErrNoRows specifically) will be returned -// -// If more than one row is found, an error will be returned. -// -func SelectOne(m *DbMap, e SqlExecutor, holder interface{}, query string, args ...interface{}) error { - t := reflect.TypeOf(holder) - if t.Kind() == reflect.Ptr { - t = t.Elem() - } else { - return fmt.Errorf("gorp: SelectOne holder must be a pointer, but got: %t", holder) - } - - // Handle pointer to pointer - isptr := false - if t.Kind() == reflect.Ptr { - isptr = true - t = t.Elem() - } - - if t.Kind() == reflect.Struct { - var nonFatalErr error - - list, err := hookedselect(m, e, holder, query, args...) - if err != nil { - if !NonFatalError(err) { // FIXME: double negative, rename NonFatalError to FatalError - return err - } - nonFatalErr = err - } - - dest := reflect.ValueOf(holder) - if isptr { - dest = dest.Elem() - } - - if list != nil && len(list) > 0 { // FIXME: invert if/else - // check for multiple rows - if len(list) > 1 { - return fmt.Errorf("gorp: multiple rows returned for: %s - %v", query, args) - } - - // Initialize if nil - if dest.IsNil() { - dest.Set(reflect.New(t)) - } - - // only one row found - src := reflect.ValueOf(list[0]) - dest.Elem().Set(src.Elem()) - } else { - // No rows found, return a proper error. - return sql.ErrNoRows - } - - return nonFatalErr - } - - return selectVal(e, holder, query, args...) -} - -func selectVal(e SqlExecutor, holder interface{}, query string, args ...interface{}) error { - var dbMap *DbMap - switch m := e.(type) { - case *DbMap: - dbMap = m - case *Transaction: - dbMap = m.dbmap - } - - if len(args) == 1 { - query, args = maybeExpandNamedQuery(dbMap, query, args) - } - - ctx, cancel := context.WithTimeout(context.Background(), dbMap.QueryTimeout) - defer cancel() - rows, err := e.QueryContext(ctx, query, args...) - - if err != nil { - return err - } - defer rows.Close() - - if !rows.Next() { - return sql.ErrNoRows - } - - return rows.Scan(holder) -} - -func hookedselect(m *DbMap, exec SqlExecutor, i interface{}, query string, - args ...interface{}) ([]interface{}, error) { - - list, err := rawselect(m, exec, i, query, args...) - if err != nil { - if !NonFatalError(err) { - return nil, err - } - } - - // Determine where the results are: written to i, or returned in list - if t, _ := toSliceType(i); t == nil { - for _, v := range list { - if v, ok := v.(HasPostGet); ok { - err := v.PostGet(exec) - if err != nil { - return nil, err - } - } - } - } else { - resultsValue := reflect.Indirect(reflect.ValueOf(i)) - for i := 0; i < resultsValue.Len(); i++ { - if v, ok := resultsValue.Index(i).Interface().(HasPostGet); ok { - err := v.PostGet(exec) - if err != nil { - return nil, err - } - } - } - } - - return list, nil -} - -func rawselect(m *DbMap, exec SqlExecutor, i interface{}, query string, - args ...interface{}) ([]interface{}, error) { - var ( - appendToSlice = false // Write results to i directly? - intoStruct = true // Selecting into a struct? - pointerElements = true // Are the slice elements pointers (vs values)? - ) - - 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 { - var err2 error - if t, err2 = toSliceType(i); t == nil { - if err2 != nil { - return nil, err2 - } - return nil, err - } - pointerElements = t.Kind() == reflect.Ptr - if pointerElements { - t = t.Elem() - } - appendToSlice = true - intoStruct = t.Kind() == reflect.Struct - } - - // If the caller supplied a single struct/map argument, assume a "named - // parameter" query. Extract the named arguments from the struct/map, create - // the flat arg slice, and rewrite the query to use the dialect's placeholder. - if len(args) == 1 { - query, args = maybeExpandNamedQuery(m, query, args) - } - - // Run the query - ctx, cancel := context.WithTimeout(context.Background(), m.QueryTimeout) - defer cancel() - rows, err := exec.QueryContext(ctx, query, args...) - - if err != nil { - return nil, err - } - defer rows.Close() - - // Fetch the column names as returned from db - cols, err := rows.Columns() - if err != nil { - return nil, err - } - - if !intoStruct && len(cols) > 1 { - return nil, fmt.Errorf("gorp: select into non-struct slice requires 1 column, got %d", len(cols)) - } - - var colToFieldIndex [][]int - if intoStruct { - colToFieldIndex, err = columnToFieldIndex(m, t, tableName, cols) - if err != nil { - if !NonFatalError(err) { - return nil, err - } - nonFatalErr = err - } - } - - conv := m.TypeConverter - - // Add results to one of these two slices. - var ( - list = make([]interface{}, 0) - sliceValue = reflect.Indirect(reflect.ValueOf(i)) - ) - - for { - if !rows.Next() { - // if error occured return rawselect - if rows.Err() != nil { - return nil, rows.Err() - } - // time to exit from outer "for" loop - break - } - v := reflect.New(t) - - if isDynamic { - v.Interface().(DynamicTable).SetTableName(tableName) - } - - dest := make([]interface{}, len(cols)) - - custScan := make([]CustomScanner, 0) - - for x := range cols { - f := v.Elem() - if intoStruct { - index := colToFieldIndex[x] - if index == nil { - // this field is not present in the struct, so create a dummy - // value for rows.Scan to scan into - var dummy dummyField - dest[x] = &dummy - continue - } - f = f.FieldByIndex(index) - } - target := f.Addr().Interface() - if conv != nil { - scanner, ok := conv.FromDb(target) - if ok { - target = scanner.Holder - custScan = append(custScan, scanner) - } - } - dest[x] = target - } - - err = rows.Scan(dest...) - if err != nil { - return nil, err - } - - for _, c := range custScan { - err = c.Bind() - if err != nil { - return nil, err - } - } - - if appendToSlice { - if !pointerElements { - v = v.Elem() - } - sliceValue.Set(reflect.Append(sliceValue, v)) - } else { - list = append(list, v.Interface()) - } - } - - if appendToSlice && sliceValue.IsNil() { - sliceValue.Set(reflect.MakeSlice(sliceValue.Type(), 0, 0)) - } - - return list, nonFatalErr -} diff --git a/vendor/github.com/mattermost/gorp/table.go b/vendor/github.com/mattermost/gorp/table.go deleted file mode 100644 index 0d1d0e4c89..0000000000 --- a/vendor/github.com/mattermost/gorp/table.go +++ /dev/null @@ -1,271 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" - "strings" -) - -// TableMap represents a mapping between a Go struct and a database table -// Use dbmap.AddTable() or dbmap.AddTableWithName() to create these -type TableMap struct { - // Name of database table. - TableName string - SchemaName string - gotype reflect.Type - Columns []*ColumnMap - keys []*ColumnMap - indexes []*IndexMap - uniqueTogether [][]string - version *ColumnMap - insertPlan bindPlan - updatePlan bindPlan - deletePlan bindPlan - getPlan bindPlan - dbmap *DbMap -} - -// ResetSql removes cached insert/update/select/delete SQL strings -// associated with this TableMap. Call this if you've modified -// any column names or the table name itself. -func (t *TableMap) ResetSql() { - t.insertPlan = bindPlan{} - t.updatePlan = bindPlan{} - t.deletePlan = bindPlan{} - t.getPlan = bindPlan{} -} - -// SetKeys lets you specify the fields on a struct that map to primary -// key columns on the table. If isAutoIncr is set, result.LastInsertId() -// will be used after INSERT to bind the generated id to the Go struct. -// -// Automatically calls ResetSql() to ensure SQL statements are regenerated. -// -// Panics if isAutoIncr is true, and fieldNames length != 1 -// -func (t *TableMap) SetKeys(isAutoIncr bool, fieldNames ...string) *TableMap { - if isAutoIncr && len(fieldNames) != 1 { - panic(fmt.Sprintf( - "gorp: SetKeys: fieldNames length must be 1 if key is auto-increment. (Saw %v fieldNames)", - len(fieldNames))) - } - t.keys = make([]*ColumnMap, 0) - for _, name := range fieldNames { - colmap := t.ColMap(name) - colmap.isPK = true - colmap.isAutoIncr = isAutoIncr - t.keys = append(t.keys, colmap) - } - t.ResetSql() - - return t -} - -// SetUniqueTogether lets you specify uniqueness constraints across multiple -// columns on the table. Each call adds an additional constraint for the -// specified columns. -// -// Automatically calls ResetSql() to ensure SQL statements are regenerated. -// -// Panics if fieldNames length < 2. -// -func (t *TableMap) SetUniqueTogether(fieldNames ...string) *TableMap { - if len(fieldNames) < 2 { - panic(fmt.Sprintf( - "gorp: SetUniqueTogether: must provide at least two fieldNames to set uniqueness constraint.")) - } - - columns := make([]string, 0, len(fieldNames)) - for _, name := range fieldNames { - columns = append(columns, name) - } - - alreadyExists := false -checkDuplicates: - for _, existingColumns := range t.uniqueTogether { - if len(existingColumns) == len(columns) { - for i := range columns { - if existingColumns[i] != columns[i] { - continue checkDuplicates - } - } - - alreadyExists = true - break checkDuplicates - } - } - if !alreadyExists { - t.uniqueTogether = append(t.uniqueTogether, columns) - t.ResetSql() - } - - return t -} - -// ColMap returns the ColumnMap pointer matching the given struct field -// name. It panics if the struct does not contain a field matching this -// name. -func (t *TableMap) ColMap(field string) *ColumnMap { - col := colMapOrNil(t, field) - if col == nil { - e := fmt.Sprintf("No ColumnMap in table %s type %s with field %s", - t.TableName, t.gotype.Name(), field) - - panic(e) - } - return col -} - -func colMapOrNil(t *TableMap, field string) *ColumnMap { - for _, col := range t.Columns { - if col.fieldName == field || col.ColumnName == field { - return col - } - } - return nil -} - -// IdxMap returns the IndexMap pointer matching the given index name. -func (t *TableMap) IdxMap(field string) *IndexMap { - for _, idx := range t.indexes { - if idx.IndexName == field { - return idx - } - } - return nil -} - -// AddIndex registers the index with gorp for specified table with given parameters. -// This operation is idempotent. If index is already mapped, the -// existing *IndexMap is returned -// Function will panic if one of the given for index columns does not exists -// -// Automatically calls ResetSql() to ensure SQL statements are regenerated. -// -func (t *TableMap) AddIndex(name string, idxtype string, columns []string) *IndexMap { - // check if we have a index with this name already - for _, idx := range t.indexes { - if idx.IndexName == name { - return idx - } - } - for _, icol := range columns { - if res := t.ColMap(icol); res == nil { - e := fmt.Sprintf("No ColumnName in table %s to create index on", t.TableName) - panic(e) - } - } - - idx := &IndexMap{IndexName: name, Unique: false, IndexType: idxtype, columns: columns} - t.indexes = append(t.indexes, idx) - t.ResetSql() - return idx -} - -// SetVersionCol sets the column to use as the Version field. By default -// the "Version" field is used. Returns the column found, or panics -// if the struct does not contain a field matching this name. -// -// Automatically calls ResetSql() to ensure SQL statements are regenerated. -func (t *TableMap) SetVersionCol(field string) *ColumnMap { - c := t.ColMap(field) - t.version = c - t.ResetSql() - return c -} - -// SqlForCreateTable gets a sequence of SQL commands that will create -// the specified table and any associated schema -func (t *TableMap) SqlForCreate(ifNotExists bool) string { - s := strings.Builder{} - dialect := t.dbmap.Dialect - - if strings.TrimSpace(t.SchemaName) != "" { - schemaCreate := "create schema" - if ifNotExists { - s.WriteString(dialect.IfSchemaNotExists(schemaCreate, t.SchemaName)) - } else { - s.WriteString(schemaCreate) - } - s.WriteString(fmt.Sprintf(" %s;", t.SchemaName)) - } - - tableCreate := "create table" - if ifNotExists { - s.WriteString(dialect.IfTableNotExists(tableCreate, t.SchemaName, t.TableName)) - } else { - s.WriteString(tableCreate) - } - s.WriteString(fmt.Sprintf(" %s (", dialect.QuotedTableForQuery(t.SchemaName, t.TableName))) - - x := 0 - for _, col := range t.Columns { - if !col.Transient { - if x > 0 { - s.WriteString(", ") - } - - stype := col.DataType - if stype == "" { - stype = dialect.ToSqlType(col.gotype, col.MaxSize, col.isAutoIncr) - } - - s.WriteString(fmt.Sprintf("%s %s", dialect.QuoteField(col.ColumnName), stype)) - - if col.isPK || col.isNotNull { - s.WriteString(" not null") - } - if col.DefaultConstraint != nil { - s.WriteString(fmt.Sprintf(" default '%s'", *col.DefaultConstraint)) - } - if col.isPK && len(t.keys) == 1 { - s.WriteString(" primary key") - } - if col.Unique { - s.WriteString(" unique") - } - if col.isAutoIncr { - s.WriteString(fmt.Sprintf(" %s", dialect.AutoIncrStr())) - } - - x++ - } - } - if len(t.keys) > 1 { - s.WriteString(", primary key (") - for x := range t.keys { - if x > 0 { - s.WriteString(", ") - } - s.WriteString(dialect.QuoteField(t.keys[x].ColumnName)) - } - s.WriteString(")") - } - if len(t.uniqueTogether) > 0 { - for _, columns := range t.uniqueTogether { - s.WriteString(", unique (") - for i, column := range columns { - if i > 0 { - s.WriteString(", ") - } - s.WriteString(dialect.QuoteField(column)) - } - s.WriteString(")") - } - } - s.WriteString(") ") - s.WriteString(dialect.CreateTableSuffix()) - s.WriteString(dialect.QuerySuffix()) - return s.String() -} diff --git a/vendor/github.com/mattermost/gorp/table_bindings.go b/vendor/github.com/mattermost/gorp/table_bindings.go deleted file mode 100644 index 2b1f6c2348..0000000000 --- a/vendor/github.com/mattermost/gorp/table_bindings.go +++ /dev/null @@ -1,312 +0,0 @@ -// 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 - -import ( - "fmt" - "reflect" - "strings" - "sync" -) - -// CustomScanner binds a database column value to a Go type -type CustomScanner struct { - // After a row is scanned, Holder will contain the value from the database column. - // Initialize the CustomScanner with the concrete Go type you wish the database - // driver to scan the raw column into. - Holder interface{} - // Target typically holds a pointer to the target struct field to bind the Holder - // value to. - Target interface{} - // Binder is a custom function that converts the holder value to the target type - // and sets target accordingly. This function should return error if a problem - // occurs converting the holder to the target. - Binder func(holder interface{}, target interface{}) error -} - -// Used to filter columns when selectively updating -type ColumnFilter func(*ColumnMap) bool - -func acceptAllFilter(col *ColumnMap) bool { - return true -} - -// Bind is called automatically by gorp after Scan() -func (me CustomScanner) Bind() error { - return me.Binder(me.Holder, me.Target) -} - -type bindPlan struct { - query string - argFields []string - keyFields []string - versField string - autoIncrIdx int - autoIncrFieldName string - once sync.Once -} - -func (plan *bindPlan) createBindInstance(elem reflect.Value, conv TypeConverter) (bindInstance, error) { - bi := bindInstance{query: plan.query, autoIncrIdx: plan.autoIncrIdx, autoIncrFieldName: plan.autoIncrFieldName, versField: plan.versField} - if plan.versField != "" { - bi.existingVersion = elem.FieldByName(plan.versField).Int() - } - - var err error - - for i := 0; i < len(plan.argFields); i++ { - k := plan.argFields[i] - if k == versFieldConst { - newVer := bi.existingVersion + 1 - bi.args = append(bi.args, newVer) - if bi.existingVersion == 0 { - elem.FieldByName(plan.versField).SetInt(int64(newVer)) - } - } else { - val := elem.FieldByName(k).Interface() - if conv != nil { - val, err = conv.ToDb(val) - if err != nil { - return bindInstance{}, err - } - } - bi.args = append(bi.args, val) - } - } - - for i := 0; i < len(plan.keyFields); i++ { - k := plan.keyFields[i] - val := elem.FieldByName(k).Interface() - if conv != nil { - val, err = conv.ToDb(val) - if err != nil { - return bindInstance{}, err - } - } - bi.keys = append(bi.keys, val) - } - - return bi, nil -} - -type bindInstance struct { - query string - args []interface{} - keys []interface{} - existingVersion int64 - versField string - autoIncrIdx int - autoIncrFieldName string -} - -func (t *TableMap) bindInsert(elem reflect.Value) (bindInstance, error) { - plan := &t.insertPlan - plan.once.Do(func() { - plan.autoIncrIdx = -1 - - s := strings.Builder{} - s2 := strings.Builder{} - s.WriteString(fmt.Sprintf("insert into %s (", t.dbmap.Dialect.QuotedTableForQuery(t.SchemaName, t.TableName))) - - x := 0 - first := true - for y := range t.Columns { - col := t.Columns[y] - if !(col.isAutoIncr && t.dbmap.Dialect.AutoIncrBindValue() == "") { - if !col.Transient { - if !first { - s.WriteString(",") - s2.WriteString(",") - } - s.WriteString(t.dbmap.Dialect.QuoteField(col.ColumnName)) - - if col.isAutoIncr { - s2.WriteString(t.dbmap.Dialect.AutoIncrBindValue()) - plan.autoIncrIdx = y - plan.autoIncrFieldName = col.fieldName - } else { - if col.DefaultValue == "" { - s2.WriteString(t.dbmap.Dialect.BindVar(x)) - if col == t.version { - plan.versField = col.fieldName - plan.argFields = append(plan.argFields, versFieldConst) - } else { - plan.argFields = append(plan.argFields, col.fieldName) - } - x++ - } else { - s2.WriteString(col.DefaultValue) - } - } - first = false - } - } else { - plan.autoIncrIdx = y - plan.autoIncrFieldName = col.fieldName - } - } - s.WriteString(") values (") - s.WriteString(s2.String()) - s.WriteString(")") - if plan.autoIncrIdx > -1 { - s.WriteString(t.dbmap.Dialect.AutoIncrInsertSuffix(t.Columns[plan.autoIncrIdx])) - } - s.WriteString(t.dbmap.Dialect.QuerySuffix()) - - plan.query = s.String() - }) - - return plan.createBindInstance(elem, t.dbmap.TypeConverter) -} - -func (t *TableMap) bindUpdate(elem reflect.Value, colFilter ColumnFilter) (bindInstance, error) { - if colFilter == nil { - colFilter = acceptAllFilter - } - - plan := &t.updatePlan - plan.once.Do(func() { - s := strings.Builder{} - s.WriteString(fmt.Sprintf("update %s set ", t.dbmap.Dialect.QuotedTableForQuery(t.SchemaName, t.TableName))) - x := 0 - - for y := range t.Columns { - col := t.Columns[y] - if !col.isAutoIncr && !col.Transient && colFilter(col) { - if x > 0 { - s.WriteString(", ") - } - s.WriteString(t.dbmap.Dialect.QuoteField(col.ColumnName)) - s.WriteString("=") - s.WriteString(t.dbmap.Dialect.BindVar(x)) - - if col == t.version { - plan.versField = col.fieldName - plan.argFields = append(plan.argFields, versFieldConst) - } else { - plan.argFields = append(plan.argFields, col.fieldName) - } - x++ - } - } - - s.WriteString(" where ") - for y := range t.keys { - col := t.keys[y] - if y > 0 { - s.WriteString(" and ") - } - s.WriteString(t.dbmap.Dialect.QuoteField(col.ColumnName)) - s.WriteString("=") - s.WriteString(t.dbmap.Dialect.BindVar(x)) - - plan.argFields = append(plan.argFields, col.fieldName) - plan.keyFields = append(plan.keyFields, col.fieldName) - x++ - } - if plan.versField != "" { - s.WriteString(" and ") - s.WriteString(t.dbmap.Dialect.QuoteField(t.version.ColumnName)) - s.WriteString("=") - s.WriteString(t.dbmap.Dialect.BindVar(x)) - plan.argFields = append(plan.argFields, plan.versField) - } - s.WriteString(t.dbmap.Dialect.QuerySuffix()) - - plan.query = s.String() - }) - - return plan.createBindInstance(elem, t.dbmap.TypeConverter) -} - -func (t *TableMap) bindDelete(elem reflect.Value) (bindInstance, error) { - plan := &t.deletePlan - plan.once.Do(func() { - s := strings.Builder{} - s.WriteString(fmt.Sprintf("delete from %s", t.dbmap.Dialect.QuotedTableForQuery(t.SchemaName, t.TableName))) - - for y := range t.Columns { - col := t.Columns[y] - if !col.Transient { - if col == t.version { - plan.versField = col.fieldName - } - } - } - - s.WriteString(" where ") - for x := range t.keys { - k := t.keys[x] - if x > 0 { - s.WriteString(" and ") - } - s.WriteString(t.dbmap.Dialect.QuoteField(k.ColumnName)) - s.WriteString("=") - s.WriteString(t.dbmap.Dialect.BindVar(x)) - - plan.keyFields = append(plan.keyFields, k.fieldName) - plan.argFields = append(plan.argFields, k.fieldName) - } - if plan.versField != "" { - s.WriteString(" and ") - s.WriteString(t.dbmap.Dialect.QuoteField(t.version.ColumnName)) - s.WriteString("=") - s.WriteString(t.dbmap.Dialect.BindVar(len(plan.argFields))) - - plan.argFields = append(plan.argFields, plan.versField) - } - s.WriteString(t.dbmap.Dialect.QuerySuffix()) - - plan.query = s.String() - }) - - return plan.createBindInstance(elem, t.dbmap.TypeConverter) -} - -func (t *TableMap) bindGet() *bindPlan { - plan := &t.getPlan - plan.once.Do(func() { - s := strings.Builder{} - s.WriteString("select ") - - x := 0 - for _, col := range t.Columns { - if !col.Transient { - if x > 0 { - s.WriteString(",") - } - s.WriteString(t.dbmap.Dialect.QuoteField(col.ColumnName)) - plan.argFields = append(plan.argFields, col.fieldName) - x++ - } - } - s.WriteString(" from ") - s.WriteString(t.dbmap.Dialect.QuotedTableForQuery(t.SchemaName, t.TableName)) - s.WriteString(" where ") - for x := range t.keys { - col := t.keys[x] - if x > 0 { - s.WriteString(" and ") - } - s.WriteString(t.dbmap.Dialect.QuoteField(col.ColumnName)) - s.WriteString("=") - s.WriteString(t.dbmap.Dialect.BindVar(x)) - - plan.keyFields = append(plan.keyFields, col.fieldName) - } - s.WriteString(t.dbmap.Dialect.QuerySuffix()) - - plan.query = s.String() - }) - - return plan -} diff --git a/vendor/github.com/mattermost/gorp/transaction.go b/vendor/github.com/mattermost/gorp/transaction.go deleted file mode 100644 index a9706ee653..0000000000 --- a/vendor/github.com/mattermost/gorp/transaction.go +++ /dev/null @@ -1,219 +0,0 @@ -// 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 - -import ( - "context" - "database/sql" - "time" -) - -// Transaction represents a database transaction. -// Insert/Update/Delete/Get/Exec operations will be run in the context -// of that transaction. Transactions should be terminated with -// a call to Commit() or Rollback() -type Transaction struct { - dbmap *DbMap - tx *sql.Tx - closed bool -} - -// Insert has the same behavior as DbMap.Insert(), but runs in a transaction. -func (t *Transaction) Insert(list ...interface{}) error { - return insert(t.dbmap, t, list...) -} - -// Update had the same behavior as DbMap.Update(), but runs in a transaction. -func (t *Transaction) Update(list ...interface{}) (int64, error) { - return update(t.dbmap, t, nil, list...) -} - -// UpdateColumns had the same behavior as DbMap.UpdateColumns(), but runs in a transaction. -func (t *Transaction) UpdateColumns(filter ColumnFilter, list ...interface{}) (int64, error) { - return update(t.dbmap, t, filter, list...) -} - -// Delete has the same behavior as DbMap.Delete(), but runs in a transaction. -func (t *Transaction) Delete(list ...interface{}) (int64, error) { - return delete(t.dbmap, t, list...) -} - -// Get has the same behavior as DbMap.Get(), but runs in a transaction. -func (t *Transaction) Get(i interface{}, keys ...interface{}) (interface{}, error) { - return get(t.dbmap, t, i, keys...) -} - -// Select has the same behavior as DbMap.Select(), but runs in a transaction. -func (t *Transaction) Select(i interface{}, query string, args ...interface{}) ([]interface{}, error) { - return hookedselect(t.dbmap, t, i, query, args...) -} - -// Exec has the same behavior as DbMap.Exec(), but runs in a transaction. -func (t *Transaction) Exec(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, 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. -func (t *Transaction) SelectInt(query string, args ...interface{}) (int64, error) { - return SelectInt(t, query, args...) -} - -// SelectNullInt is a convenience wrapper around the gorp.SelectNullInt function. -func (t *Transaction) SelectNullInt(query string, args ...interface{}) (sql.NullInt64, error) { - return SelectNullInt(t, query, args...) -} - -// SelectFloat is a convenience wrapper around the gorp.SelectFloat function. -func (t *Transaction) SelectFloat(query string, args ...interface{}) (float64, error) { - return SelectFloat(t, query, args...) -} - -// SelectNullFloat is a convenience wrapper around the gorp.SelectNullFloat function. -func (t *Transaction) SelectNullFloat(query string, args ...interface{}) (sql.NullFloat64, error) { - return SelectNullFloat(t, query, args...) -} - -// SelectStr is a convenience wrapper around the gorp.SelectStr function. -func (t *Transaction) SelectStr(query string, args ...interface{}) (string, error) { - return SelectStr(t, query, args...) -} - -// SelectNullStr is a convenience wrapper around the gorp.SelectNullStr function. -func (t *Transaction) SelectNullStr(query string, args ...interface{}) (sql.NullString, error) { - return SelectNullStr(t, query, args...) -} - -// SelectOne is a convenience wrapper around the gorp.SelectOne function. -func (t *Transaction) SelectOne(holder interface{}, query string, args ...interface{}) error { - return SelectOne(t.dbmap, t, holder, query, args...) -} - -// Commit commits the underlying database transaction. -func (t *Transaction) Commit() error { - if !t.closed { - t.closed = true - if t.dbmap.logger != nil { - now := time.Now() - defer t.dbmap.trace(now, "commit;") - } - return t.tx.Commit() - } - - return sql.ErrTxDone -} - -// Rollback rolls back the underlying database transaction. -func (t *Transaction) Rollback() error { - if !t.closed { - t.closed = true - if t.dbmap.logger != nil { - now := time.Now() - defer t.dbmap.trace(now, "rollback;") - } - return t.tx.Rollback() - } - - return sql.ErrTxDone -} - -// Savepoint creates a savepoint with the given name. The name is interpolated -// directly into the SQL SAVEPOINT statement, so you must sanitize it if it is -// derived from user input. -func (t *Transaction) Savepoint(name string) error { - query := "savepoint " + t.dbmap.Dialect.QuoteField(name) - if t.dbmap.logger != nil { - now := time.Now() - defer t.dbmap.trace(now, query, nil) - } - _, err := t.tx.Exec(query) - return err -} - -// RollbackToSavepoint rolls back to the savepoint with the given name. The -// name is interpolated directly into the SQL SAVEPOINT statement, so you must -// sanitize it if it is derived from user input. -func (t *Transaction) RollbackToSavepoint(savepoint string) error { - query := "rollback to savepoint " + t.dbmap.Dialect.QuoteField(savepoint) - if t.dbmap.logger != nil { - now := time.Now() - defer t.dbmap.trace(now, query, nil) - } - _, err := t.tx.Exec(query) - return err -} - -// ReleaseSavepint releases the savepoint with the given name. The name is -// interpolated directly into the SQL SAVEPOINT statement, so you must sanitize -// it if it is derived from user input. -func (t *Transaction) ReleaseSavepoint(savepoint string) error { - query := "release savepoint " + t.dbmap.Dialect.QuoteField(savepoint) - if t.dbmap.logger != nil { - now := time.Now() - defer t.dbmap.trace(now, query, nil) - } - _, err := t.tx.Exec(query) - return err -} - -// Prepare has the same behavior as DbMap.Prepare(), but runs in a transaction. -func (t *Transaction) Prepare(query string) (*sql.Stmt, error) { - if t.dbmap.logger != nil { - now := time.Now() - defer t.dbmap.trace(now, query, nil) - } - return t.tx.Prepare(query) -} - -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...) - } - return t.tx.QueryRow(query, args...) -} - -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...) -} diff --git a/vendor/modules.txt b/vendor/modules.txt index b997b3ba1e..f1055f1887 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -387,9 +387,6 @@ github.com/mattermost/go-i18n/i18n github.com/mattermost/go-i18n/i18n/bundle github.com/mattermost/go-i18n/i18n/language github.com/mattermost/go-i18n/i18n/translation -# github.com/mattermost/gorp v1.6.2-0.20210714143452-8b50f5209a7f -## explicit -github.com/mattermost/gorp # github.com/mattermost/gosaml2 v0.3.3 ## explicit github.com/mattermost/gosaml2 @@ -429,6 +426,8 @@ github.com/mattn/go-isatty # github.com/mattn/go-runewidth v0.0.13 ## explicit github.com/mattn/go-runewidth +# github.com/mattn/go-sqlite3 v2.0.3+incompatible +## explicit # github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/mholt/archiver/v3 v3.5.1