diff --git a/config/database.go b/config/database.go index ef546a7e5e..f2447b2b27 100644 --- a/config/database.go +++ b/config/database.go @@ -25,6 +25,7 @@ import ( "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" + "github.com/mattermost/mattermost-server/v6/store/sqlstore" "github.com/mattermost/morph" "github.com/mattermost/morph/drivers" @@ -124,12 +125,12 @@ func (ds *DatabaseStore) initializeConfigurationsTable() error { var driver drivers.Driver switch ds.driverName { case model.DatabaseDriverMysql: - dataSource, rErr := resetReadTimeout(ds.dataSourceName) + dataSource, rErr := sqlstore.ResetReadTimeout(ds.dataSourceName) if rErr != nil { return fmt.Errorf("failed to reset read timeout from datasource: %w", rErr) } - dataSource, err = appendMultipleStatementsFlag(dataSource) + dataSource, err = sqlstore.AppendMultipleStatementsFlag(dataSource) if err != nil { return err } diff --git a/config/utils.go b/config/utils.go index 9def14e471..3034db01ab 100644 --- a/config/utils.go +++ b/config/utils.go @@ -10,7 +10,6 @@ import ( "reflect" "strings" - "github.com/go-sql-driver/mysql" "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/i18n" "github.com/mattermost/mattermost-server/v6/shared/mlog" @@ -262,29 +261,3 @@ func equal(oldCfg, newCfg *model.Config) (bool, error) { } return !bytes.Equal(oldCfgBytes, newCfgBytes), nil } - -// appendMultipleStatementsFlag attached dsn parameters to MySQL dsn in order to make migrations work. -func appendMultipleStatementsFlag(dataSource string) (string, error) { - - config, err := mysql.ParseDSN(dataSource) - if err != nil { - return "", err - } - - if config.Params == nil { - config.Params = map[string]string{} - } - - config.Params["multiStatements"] = "true" - return config.FormatDSN(), nil -} - -// resetReadTimeout removes the timeout contraint from the MySQL dsn. -func resetReadTimeout(dataSource string) (string, error) { - config, err := mysql.ParseDSN(dataSource) - if err != nil { - return "", err - } - config.ReadTimeout = 0 - return config.FormatDSN(), nil -} diff --git a/store/sqlstore/store.go b/store/sqlstore/store.go index 73db453557..f09390eb9e 100644 --- a/store/sqlstore/store.go +++ b/store/sqlstore/store.go @@ -275,7 +275,7 @@ func (ss *SqlStore) initConnection() { // covers that already. Ideally we'd like to do this only for the upgrade // step. To be reviewed in MM-35789. var err error - dataSource, err = resetReadTimeout(dataSource) + dataSource, err = ResetReadTimeout(dataSource) if err != nil { mlog.Fatal("Failed to reset read timeout from datasource.", mlog.Err(err), mlog.String("src", dataSource)) } @@ -981,12 +981,12 @@ func (ss *SqlStore) migrate(direction migrationDirection) error { var driver drivers.Driver switch ss.DriverName() { case model.DatabaseDriverMysql: - dataSource, rErr := resetReadTimeout(*ss.settings.DataSource) + dataSource, rErr := ResetReadTimeout(*ss.settings.DataSource) if rErr != nil { mlog.Fatal("Failed to reset read timeout from datasource.", mlog.Err(rErr), mlog.String("src", *ss.settings.DataSource)) return rErr } - dataSource, err = ss.appendMultipleStatementsFlag(dataSource) + dataSource, err = AppendMultipleStatementsFlag(dataSource) if err != nil { return err } @@ -1029,35 +1029,6 @@ func (ss *SqlStore) migrate(direction migrationDirection) error { } } -func (ss *SqlStore) appendMultipleStatementsFlag(dataSource string) (string, error) { - // We need to tell the MySQL driver that we want to use multiStatements - // in order to make migrations work. - if ss.DriverName() == model.DatabaseDriverMysql { - config, err := mysql.ParseDSN(dataSource) - if err != nil { - return "", err - } - - if config.Params == nil { - config.Params = map[string]string{} - } - - config.Params["multiStatements"] = "true" - return config.FormatDSN(), nil - } - - return dataSource, nil -} - -func resetReadTimeout(dataSource string) (string, error) { - config, err := mysql.ParseDSN(dataSource) - if err != nil { - return "", err - } - config.ReadTimeout = 0 - return config.FormatDSN(), nil -} - func convertMySQLFullTextColumnsToPostgres(columnNames string) string { columns := strings.Split(columnNames, ", ") concatenatedColumnNames := "" diff --git a/store/sqlstore/store_test.go b/store/sqlstore/store_test.go index f6d90ba085..180780661c 100644 --- a/store/sqlstore/store_test.go +++ b/store/sqlstore/store_test.go @@ -753,43 +753,6 @@ func TestReplicaLagQuery(t *testing.T) { } } -func TestAppendMultipleStatementsFlagMysql(t *testing.T) { - testCases := []struct { - Scenario string - DSN string - ExpectedDSN string - Driver string - }{ - { - "Should append multiStatements param to the DSN path with existing params", - "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost?writeTimeout=30s", - "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost?writeTimeout=30s&multiStatements=true", - model.DatabaseDriverMysql, - }, - { - "Should append multiStatements param to the DSN path with no existing params", - "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost", - "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost?multiStatements=true", - model.DatabaseDriverMysql, - }, - { - "Should not multiStatements param to the DSN when driver is not MySQL", - "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost", - "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost", - model.DatabaseDriverPostgres, - }, - } - - for _, tc := range testCases { - t.Run(tc.Scenario, func(t *testing.T) { - store := &SqlStore{settings: &model.SqlSettings{DriverName: &tc.Driver, DataSource: &tc.DSN}} - res, err := store.appendMultipleStatementsFlag(*store.settings.DataSource) - require.NoError(t, err) - assert.Equal(t, tc.ExpectedDSN, res) - }) - } -} - func makeSqlSettings(driver string) *model.SqlSettings { switch driver { case model.DatabaseDriverPostgres: diff --git a/store/sqlstore/utils.go b/store/sqlstore/utils.go index 25f68e140a..160111aab5 100644 --- a/store/sqlstore/utils.go +++ b/store/sqlstore/utils.go @@ -12,6 +12,8 @@ import ( "github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/shared/mlog" + + "github.com/go-sql-driver/mysql" ) var escapeLikeSearchChar = []string{ @@ -170,3 +172,28 @@ func DSNHasBinaryParam(dsn string) (bool, error) { func AppendBinaryFlag(buf []byte) []byte { return append([]byte{0x01}, buf...) } + +// AppendMultipleStatementsFlag attached dsn parameters to MySQL dsn in order to make migrations work. +func AppendMultipleStatementsFlag(dataSource string) (string, error) { + config, err := mysql.ParseDSN(dataSource) + if err != nil { + return "", err + } + + if config.Params == nil { + config.Params = map[string]string{} + } + + config.Params["multiStatements"] = "true" + return config.FormatDSN(), nil +} + +// ResetReadTimeout removes the timeout constraint from the MySQL dsn. +func ResetReadTimeout(dataSource string) (string, error) { + config, err := mysql.ParseDSN(dataSource) + if err != nil { + return "", err + } + config.ReadTimeout = 0 + return config.FormatDSN(), nil +} diff --git a/store/sqlstore/utils_test.go b/store/sqlstore/utils_test.go index 10e772ae13..187244c40e 100644 --- a/store/sqlstore/utils_test.go +++ b/store/sqlstore/utils_test.go @@ -133,3 +133,30 @@ func TestMySQLJSONArgs(t *testing.T) { assert.Equal(t, test.argString, argString) } } + +func TestAppendMultipleStatementsFlag(t *testing.T) { + testCases := []struct { + Scenario string + DSN string + ExpectedDSN string + }{ + { + "Should append multiStatements param to the DSN path with existing params", + "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost?writeTimeout=30s", + "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost?writeTimeout=30s&multiStatements=true", + }, + { + "Should append multiStatements param to the DSN path with no existing params", + "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost", + "user:rand?&ompasswith@character@unix(/var/run/mysqld/mysqld.sock)/mattermost?multiStatements=true", + }, + } + + for _, tc := range testCases { + t.Run(tc.Scenario, func(t *testing.T) { + res, err := AppendMultipleStatementsFlag(tc.DSN) + require.NoError(t, err) + assert.Equal(t, tc.ExpectedDSN, res) + }) + } +}