@@ -8,9 +8,12 @@ import (
88 "fmt"
99 "io"
1010 nurl "net/url"
11+ "strconv"
12+ "strings"
1113
1214 "github.com/golang-migrate/migrate/v4"
1315 "github.com/golang-migrate/migrate/v4/database"
16+ "github.com/golang-migrate/migrate/v4/database/multistmt"
1417 "github.com/hashicorp/go-multierror"
1518 _ "github.com/nakagami/firebirdsql"
1619 "go.uber.org/atomic"
@@ -22,15 +25,22 @@ func init() {
2225 database .Register ("firebirdsql" , & db )
2326}
2427
25- var DefaultMigrationsTable = "schema_migrations"
28+ var (
29+ multiStmtDelimiter = []byte (";" )
30+
31+ DefaultMigrationsTable = "schema_migrations"
32+ DefaultMultiStatementMaxSize = 10 * 1 << 20 // 10 MB
33+ )
2634
2735var (
2836 ErrNilConfig = fmt .Errorf ("no config" )
2937)
3038
3139type Config struct {
32- DatabaseName string
33- MigrationsTable string
40+ DatabaseName string
41+ MigrationsTable string
42+ MultiStatementEnabled bool
43+ MultiStatementMaxSize int
3444}
3545
3646type Firebird struct {
@@ -85,9 +95,30 @@ func (f *Firebird) Open(dsn string) (database.Driver, error) {
8595 return nil , err
8696 }
8797
98+ multiStatementMaxSize := DefaultMultiStatementMaxSize
99+ if s := purl .Query ().Get ("x-multi-statement-max-size" ); len (s ) > 0 {
100+ multiStatementMaxSize , err = strconv .Atoi (s )
101+ if err != nil {
102+ return nil , err
103+ }
104+ if multiStatementMaxSize <= 0 {
105+ multiStatementMaxSize = DefaultMultiStatementMaxSize
106+ }
107+ }
108+
109+ multiStatementEnabled := false
110+ if s := purl .Query ().Get ("x-multi-statement" ); len (s ) > 0 {
111+ multiStatementEnabled , err = strconv .ParseBool (s )
112+ if err != nil {
113+ return nil , fmt .Errorf ("unable to parse option x-multi-statement: %w" , err )
114+ }
115+ }
116+
88117 px , err := WithInstance (db , & Config {
89- MigrationsTable : purl .Query ().Get ("x-migrations-table" ),
90- DatabaseName : purl .Path ,
118+ MigrationsTable : purl .Query ().Get ("x-migrations-table" ),
119+ DatabaseName : purl .Path ,
120+ MultiStatementEnabled : multiStatementEnabled ,
121+ MultiStatementMaxSize : multiStatementMaxSize ,
91122 })
92123
93124 if err != nil {
@@ -121,6 +152,26 @@ func (f *Firebird) Unlock() error {
121152}
122153
123154func (f * Firebird ) Run (migration io.Reader ) error {
155+ if f .config .MultiStatementEnabled {
156+ var err error
157+
158+ if e := multistmt .Parse (migration , multiStmtDelimiter , f .config .MultiStatementMaxSize , func (m []byte ) bool {
159+ query := strings .TrimSpace (string (m ))
160+ if len (query ) == 0 {
161+ return true
162+ }
163+ if _ , err = f .conn .ExecContext (context .Background (), query ); err != nil {
164+ return false // stop parsing on error
165+ }
166+ return true // continue parsing
167+ }); e != nil {
168+ return & database.Error {OrigErr : e , Err : "error parsing multi-statement migration" }
169+ }
170+ if err != nil {
171+ return & database.Error {OrigErr : err , Err : "error executing multi-statement migration" }
172+ }
173+ return nil
174+ }
124175 migr , err := io .ReadAll (migration )
125176 if err != nil {
126177 return err
0 commit comments