@@ -8,9 +8,11 @@ import (
8
8
"fmt"
9
9
"io"
10
10
nurl "net/url"
11
+ "strconv"
11
12
12
13
"github.com/golang-migrate/migrate/v4"
13
14
"github.com/golang-migrate/migrate/v4/database"
15
+ "github.com/golang-migrate/migrate/v4/database/multistmt"
14
16
"github.com/hashicorp/go-multierror"
15
17
_ "github.com/nakagami/firebirdsql"
16
18
"go.uber.org/atomic"
@@ -22,15 +24,22 @@ func init() {
22
24
database .Register ("firebirdsql" , & db )
23
25
}
24
26
25
- var DefaultMigrationsTable = "schema_migrations"
27
+ var (
28
+ multiStmtDelimiter = []byte (";" )
29
+
30
+ DefaultMigrationsTable = "schema_migrations"
31
+ DefaultMultiStatementMaxSize = 10 * 1 << 20 // 10 MB
32
+ )
26
33
27
34
var (
28
35
ErrNilConfig = fmt .Errorf ("no config" )
29
36
)
30
37
31
38
type Config struct {
32
- DatabaseName string
33
- MigrationsTable string
39
+ DatabaseName string
40
+ MigrationsTable string
41
+ MultiStatementEnabled bool
42
+ MultiStatementMaxSize int
34
43
}
35
44
36
45
type Firebird struct {
@@ -85,9 +94,30 @@ func (f *Firebird) Open(dsn string) (database.Driver, error) {
85
94
return nil , err
86
95
}
87
96
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
+
88
116
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 ,
91
121
})
92
122
93
123
if err != nil {
@@ -121,6 +151,24 @@ func (f *Firebird) Unlock() error {
121
151
}
122
152
123
153
func (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
+ }
124
172
migr , err := io .ReadAll (migration )
125
173
if err != nil {
126
174
return err
0 commit comments