@@ -8,9 +8,11 @@ import (
88 "fmt"
99 "io"
1010 nurl "net/url"
11+ "strconv"
1112
1213 "github.com/golang-migrate/migrate/v4"
1314 "github.com/golang-migrate/migrate/v4/database"
15+ "github.com/golang-migrate/migrate/v4/database/multistmt"
1416 "github.com/hashicorp/go-multierror"
1517 _ "github.com/nakagami/firebirdsql"
1618 "go.uber.org/atomic"
@@ -22,15 +24,22 @@ func init() {
2224 database .Register ("firebirdsql" , & db )
2325}
2426
25- var DefaultMigrationsTable = "schema_migrations"
27+ var (
28+ multiStmtDelimiter = []byte (";" )
29+
30+ DefaultMigrationsTable = "schema_migrations"
31+ DefaultMultiStatementMaxSize = 10 * 1 << 20 // 10 MB
32+ )
2633
2734var (
2835 ErrNilConfig = fmt .Errorf ("no config" )
2936)
3037
3138type Config struct {
32- DatabaseName string
33- MigrationsTable string
39+ DatabaseName string
40+ MigrationsTable string
41+ MultiStatementEnabled bool
42+ MultiStatementMaxSize int
3443}
3544
3645type Firebird struct {
@@ -85,9 +94,30 @@ func (f *Firebird) Open(dsn string) (database.Driver, error) {
8594 return nil , err
8695 }
8796
97+ multiStatementMaxSize := DefaultMultiStatementMaxSize
98+ if s := purl .Query ().Get ("x-multi-statement-max-size" ); len (s ) > 0 {
99+ multiStatementMaxSize , err = strconv .Atoi (s )
100+ if err != nil {
101+ return nil , err
102+ }
103+ if multiStatementMaxSize <= 0 {
104+ multiStatementMaxSize = DefaultMultiStatementMaxSize
105+ }
106+ }
107+
108+ multiStatementEnabled := false
109+ if s := purl .Query ().Get ("x-multi-statement" ); len (s ) > 0 {
110+ multiStatementEnabled , err = strconv .ParseBool (s )
111+ if err != nil {
112+ return nil , fmt .Errorf ("unable to parse option x-multi-statement: %w" , err )
113+ }
114+ }
115+
88116 px , err := WithInstance (db , & Config {
89- MigrationsTable : purl .Query ().Get ("x-migrations-table" ),
90- DatabaseName : purl .Path ,
117+ MigrationsTable : purl .Query ().Get ("x-migrations-table" ),
118+ DatabaseName : purl .Path ,
119+ MultiStatementEnabled : multiStatementEnabled ,
120+ MultiStatementMaxSize : multiStatementMaxSize ,
91121 })
92122
93123 if err != nil {
@@ -121,6 +151,24 @@ func (f *Firebird) Unlock() error {
121151}
122152
123153func (f * Firebird ) Run (migration io.Reader ) error {
154+ if f .config .MultiStatementEnabled {
155+ var err error
156+
157+ if e := multistmt .Parse (migration , multiStmtDelimiter , f .config .MultiStatementMaxSize , func (m []byte ) bool {
158+ if len (m ) == 0 {
159+ return true
160+ }
161+ if _ , err = f .conn .ExecContext (context .Background (), string (m )); err != nil {
162+ return false // stop parsing on error
163+ }
164+ return true // continue parsing
165+ }); e != nil {
166+ return & database.Error {OrigErr : e , Err : "error parsing multi-statement migration" }
167+ }
168+ if err != nil {
169+ return & database.Error {OrigErr : err , Err : "error executing multi-statement migration" }
170+ }
171+ }
124172 migr , err := io .ReadAll (migration )
125173 if err != nil {
126174 return err
0 commit comments