Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mysql): make multistatements parameter optional #249

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading