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