Skip to content

Commit

Permalink
feat(mysql): make multistatements parameter optional (#249)
Browse files Browse the repository at this point in the history
The #208 PR introduced an optimisation, which requires the
`multiStatements=true` parameter in connection string to work properly

It looks like that the requirement for that parameter (which is stated
in `README.md`) was not honored by users (e.g #240), so I want to
keep the old behavior for convenience

This commit:
* remove mention about parameter requirement from `README.md`
* revert default to `one query per one statement`
* allows to keep `one query per multiple statements` logic with a
  `testfixtures.AllowMultipleStatementsInOneQuery` flag
* some tests for both use cases
  • Loading branch information
slsyy authored Dec 22, 2024
1 parent 6ce88d0 commit 2d3ec07
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 8 deletions.
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,6 @@ Tested using the [github.com/lib/pq](https://github.com/lib/pq) and

### MySQL / MariaDB

Just make sure the connection string have
[the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements)
set to true, and use:

```go
testfixtures.New(
Expand All @@ -412,6 +409,20 @@ testfixtures.New(

Tested using the [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) driver.

#### Multistatements parameter

You can use [the multistatement parameter](https://github.com/go-sql-driver/mysql#multistatements) in the connection
string to execute some of the setup statements in one query (instead of one query per statement) for a faster execution.


```go
testfixtures.New(
...
testfixtures.Dialect("mysql"), // or "mariadb"
testfixtures.AllowMultipleStatementsInOneQuery(),
)
```

### SQLite

SQLite is also supported. It is recommended to create foreign keys as
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ services:
environment:
PGPASSWORD: postgres
PG_CONN_STRING: host=postgresql user=postgres dbname=testfixtures_test port=5432 sslmode=disable
MYSQL_CONN_STRING: root:mariadb@tcp(mariadb)/testfixtures_test?multiStatements=true
MYSQL_CONN_STRING: root:mariadb@tcp(mariadb)/testfixtures_test
SQLITE_CONN_STRING: testfixtures_test.sqlite3
SQLSERVER_CONN_STRING: server=sqlserver;database=master;user id=sa;password=SQL@1server;encrypt=disable
CRDB_CONN_STRING: host=cockroachdb user=root dbname=defaultdb port=26257 sslmode=disable
Expand Down
29 changes: 26 additions & 3 deletions mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import (
type mySQL struct {
baseHelper

skipResetSequences bool
resetSequencesTo int64
skipResetSequences bool
resetSequencesTo int64
allowMultipleStatementsInOneQuery bool

tables []string
tablesChecksum map[string]int64
Expand Down Expand Up @@ -113,14 +114,36 @@ func (h *mySQL) resetSequences(db *sql.DB) error {
resetSequencesTo = 10000
}

if h.allowMultipleStatementsInOneQuery {
return h.resetSequencesInOneQuery(db, resetSequencesTo)
}
return h.resetSequencesInMultipleQueries(db, resetSequencesTo)

}

func (h *mySQL) resetSequencesInOneQuery(db *sql.DB, resetSequencesTo int64) error {
b := strings.Builder{}
for _, t := range h.tables {
b.WriteString(fmt.Sprintf("ALTER TABLE %s AUTO_INCREMENT = %d;", h.quoteKeyword(t), resetSequencesTo))
b.WriteString(h.makeResetSequenceQuery(t, resetSequencesTo))
}
_, err := db.Exec(b.String())
return err
}

func (h *mySQL) resetSequencesInMultipleQueries(db *sql.DB, resetSequencesTo int64) error {
for _, t := range h.tables {
_, err := db.Exec(h.makeResetSequenceQuery(t, resetSequencesTo))
if err != nil {
return err
}
}
return nil
}

func (h *mySQL) makeResetSequenceQuery(tableName string, resetSequencesTo int64) string {
return fmt.Sprintf("ALTER TABLE %s AUTO_INCREMENT = %d;", h.quoteKeyword(tableName), resetSequencesTo)
}

func (h *mySQL) isTableModified(q queryable, tableName string) (bool, error) {
oldChecksum, found := h.tablesChecksum[tableName]
if !found {
Expand Down
8 changes: 7 additions & 1 deletion mysql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import (

func TestMySQL(t *testing.T) {
db := openDB(t, "mysql", os.Getenv("MYSQL_CONN_STRING"))
loadSchemaInOneQuery(t, db, "testdata/schema/mysql.sql")
loadSchemaInBatchesBySplitter(t, db, "testdata/schema/mysql.sql", []byte(";\n"))
testLoader(t, db, "mysql")
}

func TestMySQLWithMultipleStatementsSupport(t *testing.T) {
db := openDB(t, "mysql", os.Getenv("MYSQL_CONN_STRING")+"?multiStatements=true")
loadSchemaInOneQuery(t, db, "testdata/schema/mysql.sql")
testLoader(t, db, "mysql", AllowMultipleStatementsInOneQuery())
}
17 changes: 17 additions & 0 deletions testfixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,23 @@ func SkipResetSequences() func(*Loader) error {
}
}

// AllowMultipleStatementsInOneQuery is a performance tweak for running some setup statements in one query for better performance.
//
// Your database and connection must be configured to support it: https://github.com/go-sql-driver/mysql?tab=readme-ov-file#multistatements
//
// Only valid for MySQL as it is not enabled by default.
func AllowMultipleStatementsInOneQuery() func(*Loader) error {
return func(l *Loader) error {
switch helper := l.helper.(type) {
case *mySQL:
helper.allowMultipleStatementsInOneQuery = true
default:
return fmt.Errorf("testfixtures: AllowMultipleStatementsInOneQuery is valid for MySQL database")
}
return nil
}
}

// ResetSequencesTo sets the value the sequences will be reset to.
//
// Defaults to 10000.
Expand Down

0 comments on commit 2d3ec07

Please sign in to comment.