Skip to content

Commit 1582b86

Browse files
committed
feat: Add multistmt support to firebird driver
1 parent 2788339 commit 1582b86

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

database/firebird/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
| URL Query | WithInstance Config | Description |
66
|------------|---------------------|-------------|
77
| `x-migrations-table` | `MigrationsTable` | Name of the migrations table |
8+
| `x-multi-statement` | `MultiStatementEnabled` | Enable multi-statement execution (default: false) |
9+
| `x-multi-statement-max-size` | `MultiStatementMaxSize` | Maximum size of single statement in bytes (default: 10MB) |
810
| `auth_plugin_name` | | Authentication plugin name. Srp256/Srp/Legacy_Auth are available. (default is Srp) |
911
| `column_name_to_lower` | | Force column name to lower. (default is false) |
1012
| `role` | | Role name |
1113
| `tzname` | | Time Zone name. (For Firebird 4.0+) |
12-
| `wire_crypt` | | Enable wire data encryption or not. For Firebird 3.0+ (default is true) |
14+
| `wire_crypt` | | Enable wire data encryption or not. For Firebird 3.0+ (default is true) |

database/firebird/firebird.go

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2734
var (
2835
ErrNilConfig = fmt.Errorf("no config")
2936
)
3037

3138
type Config struct {
32-
DatabaseName string
33-
MigrationsTable string
39+
DatabaseName string
40+
MigrationsTable string
41+
MultiStatementEnabled bool
42+
MultiStatementMaxSize int
3443
}
3544

3645
type 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

123153
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+
}
124172
migr, err := io.ReadAll(migration)
125173
if err != nil {
126174
return err

0 commit comments

Comments
 (0)