Skip to content

Commit 304fbed

Browse files
authored
Merge pull request #486 from n2em/bugfix/restore/token-too-long
fix: Restore fails with bufio.Scanner: token too long when importing large dump files
2 parents 3330987 + fd1bca4 commit 304fbed

File tree

1 file changed

+30
-13
lines changed

1 file changed

+30
-13
lines changed

pkg/database/restore.go

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ import (
77
"fmt"
88
"io"
99
"regexp"
10-
)
11-
12-
const (
13-
// used to define default max buffer size Scanner, counter part of dump
14-
defaultMaxAllowedPacket = 4194304
10+
"strings"
1511
)
1612

1713
var (
@@ -31,20 +27,33 @@ func Restore(ctx context.Context, dbconn *Connection, databasesMap map[string]st
3127
if err != nil {
3228
return fmt.Errorf("failed to restore database: %w", err)
3329
}
34-
scanBuf := []byte{}
35-
scanner := bufio.NewScanner(r)
36-
// increase the buffer size
37-
scanner.Buffer(scanBuf, defaultMaxAllowedPacket) //TODO should be a configurable option like with dump
30+
reader := bufio.NewReader(r)
3831
var current string
39-
for scanner.Scan() {
40-
line := scanner.Text()
32+
for {
33+
line, err := reader.ReadString('\n')
34+
if err != nil && err != io.EOF {
35+
_ = tx.Rollback()
36+
return fmt.Errorf("failed to restore database: %w", err)
37+
}
38+
// strip CRLF/newline
39+
line = strings.TrimRight(line, "\r\n")
4140
if line == "" {
41+
if err == io.EOF {
42+
break
43+
}
4244
continue
4345
}
4446
current += line + "\n"
47+
48+
// if the line does not end with a semicolon, keep accumulating
4549
if line[len(line)-1] != ';' {
50+
if err == io.EOF {
51+
// EOF reached but statement not terminated; we'll try to execute below
52+
break
53+
}
4654
continue
4755
}
56+
4857
// if we have the line that sets the database, and we need to replace, replace it
4958
if createRegex.MatchString(current) {
5059
dbName := createRegex.FindStringSubmatch(current)[3]
@@ -64,9 +73,17 @@ func Restore(ctx context.Context, dbconn *Connection, databasesMap map[string]st
6473
return fmt.Errorf("failed to restore database: %w", err)
6574
}
6675
current = ""
76+
77+
if err == io.EOF {
78+
break
79+
}
6780
}
68-
if err := scanner.Err(); err != nil {
69-
return fmt.Errorf("failed to restore database: %w", err)
81+
// if there's any leftover SQL (for example last statement without newline), execute it
82+
if strings.TrimSpace(current) != "" {
83+
if _, err := tx.Exec(current); err != nil {
84+
_ = tx.Rollback()
85+
return fmt.Errorf("failed to restore database: %w", err)
86+
}
7087
}
7188
if err := tx.Commit(); err != nil {
7289
return fmt.Errorf("failed to restore database: %w", err)

0 commit comments

Comments
 (0)