Skip to content

Commit 6008f71

Browse files
committed
fix: Restore fails with bufio.Scanner: token too long when importing large dump files
1 parent ec3f9b3 commit 6008f71

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

pkg/database/restore.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"fmt"
88
"io"
99
"regexp"
10+
"strings"
1011
)
1112

1213
const (
@@ -31,20 +32,33 @@ func Restore(ctx context.Context, dbconn *Connection, databasesMap map[string]st
3132
if err != nil {
3233
return fmt.Errorf("failed to restore database: %w", err)
3334
}
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
35+
reader := bufio.NewReader(r)
3836
var current string
39-
for scanner.Scan() {
40-
line := scanner.Text()
37+
for {
38+
line, err := reader.ReadString('\n')
39+
if err != nil && err != io.EOF {
40+
_ = tx.Rollback()
41+
return fmt.Errorf("failed to restore database: %w", err)
42+
}
43+
// strip CRLF/newline
44+
line = strings.TrimRight(line, "\r\n")
4145
if line == "" {
46+
if err == io.EOF {
47+
break
48+
}
4249
continue
4350
}
4451
current += line + "\n"
52+
53+
// if the line does not end with a semicolon, keep accumulating
4554
if line[len(line)-1] != ';' {
55+
if err == io.EOF {
56+
// EOF reached but statement not terminated; we'll try to execute below
57+
break
58+
}
4659
continue
4760
}
61+
4862
// if we have the line that sets the database, and we need to replace, replace it
4963
if createRegex.MatchString(current) {
5064
dbName := createRegex.FindStringSubmatch(current)[3]
@@ -64,9 +78,17 @@ func Restore(ctx context.Context, dbconn *Connection, databasesMap map[string]st
6478
return fmt.Errorf("failed to restore database: %w", err)
6579
}
6680
current = ""
81+
82+
if err == io.EOF {
83+
break
84+
}
6785
}
68-
if err := scanner.Err(); err != nil {
69-
return fmt.Errorf("failed to restore database: %w", err)
86+
// if there's any leftover SQL (for example last statement without newline), execute it
87+
if strings.TrimSpace(current) != "" {
88+
if _, err := tx.Exec(current); err != nil {
89+
_ = tx.Rollback()
90+
return fmt.Errorf("failed to restore database: %w", err)
91+
}
7092
}
7193
if err := tx.Commit(); err != nil {
7294
return fmt.Errorf("failed to restore database: %w", err)

0 commit comments

Comments
 (0)