Skip to content

Commit ec000bc

Browse files
committed
add test and rowexec/binlog impl
1 parent d7ee834 commit ec000bc

18 files changed

+1362
-485
lines changed

enginetest/enginetests.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,12 @@ func TestLoadDataFailing(t *testing.T, harness Harness) {
11001100
}
11011101
}
11021102

1103+
func TestBinlog(t *testing.T, harness Harness) {
1104+
for _, script := range queries.BinlogScripts {
1105+
TestScript(t, harness, script)
1106+
}
1107+
}
1108+
11031109
func TestSelectIntoFile(t *testing.T, harness Harness) {
11041110
harness.Setup(setup.MydbData, setup.MytableData, setup.EmptytableData, setup.NiltableData)
11051111
e := mustNewEngine(t, harness)

enginetest/memory_engine_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,10 @@ func TestLoadDataFailing(t *testing.T) {
607607
enginetest.TestLoadDataFailing(t, enginetest.NewDefaultMemoryHarness())
608608
}
609609

610+
func TestBinlog(t *testing.T) {
611+
enginetest.TestBinlog(t, enginetest.NewDefaultMemoryHarness())
612+
}
613+
610614
func TestSelectIntoFile(t *testing.T) {
611615
enginetest.TestSelectIntoFile(t, enginetest.NewDefaultMemoryHarness())
612616
}
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// Copyright 2025 Dolthub, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package queries
16+
17+
import (
18+
"os"
19+
"strings"
20+
21+
"github.com/dolthub/go-mysql-server/sql"
22+
)
23+
24+
var (
25+
binlogInsertStmts = readBinlogTestFile("./testdata/binlog_insert.txt")
26+
binlogUpdateStmts = readBinlogTestFile("./testdata/binlog_update.txt")
27+
binlogDeleteStmts = readBinlogTestFile("./testdata/binlog_delete.txt")
28+
binlogFormatDescStmts = readBinlogTestFile("./testdata/binlog_format_desc.txt")
29+
binlogTransactionMultiOps = readBinlogTestFile("./testdata/binlog_transaction_multi_ops.txt")
30+
binlogNoFormatDescStmts = readBinlogTestFile("./testdata/binlog_no_format_desc.txt")
31+
)
32+
33+
// BinlogScripts contains test cases for the BINLOG statement. Test data is generated from real MariaDB binlog events by
34+
// running `bats binlog_maker.bats` in enginetest/testdata.
35+
// To add tests: add a @test to binlog_maker.bats, generate the .dat file, then add a test case here.
36+
var BinlogScripts = []ScriptTest{
37+
{
38+
Name: "BINLOG requires FORMAT_DESCRIPTION_EVENT first",
39+
SetUpScript: []string{
40+
"CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50), email VARCHAR(100))",
41+
},
42+
Assertions: []ScriptTestAssertion{
43+
{Query: binlogNoFormatDescStmts[0], ExpectedErr: sql.ErrNoFormatDescriptionEventBeforeBinlogStatement},
44+
},
45+
},
46+
{
47+
Name: "BINLOG with simple INSERT",
48+
SetUpScript: []string{
49+
"CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50), email VARCHAR(100))",
50+
},
51+
Assertions: []ScriptTestAssertion{
52+
{Query: binlogInsertStmts[0], Expected: []sql.Row{}},
53+
{Query: binlogInsertStmts[1], Expected: []sql.Row{}},
54+
{Query: binlogInsertStmts[2], Expected: []sql.Row{}},
55+
{
56+
Query: "SELECT * FROM users ORDER BY id",
57+
Expected: []sql.Row{
58+
{1, "Alice", "[email protected]"},
59+
{2, "Bob", "[email protected]"},
60+
},
61+
},
62+
},
63+
},
64+
{
65+
Name: "BINLOG with UPDATE",
66+
SetUpScript: []string{
67+
"CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50), email VARCHAR(100))",
68+
"INSERT INTO users VALUES (1, 'Alice', '[email protected]')",
69+
"INSERT INTO users VALUES (2, 'Bob', '[email protected]')",
70+
},
71+
Assertions: []ScriptTestAssertion{
72+
{Query: binlogUpdateStmts[0], Expected: []sql.Row{}},
73+
{Query: binlogUpdateStmts[1], Expected: []sql.Row{}},
74+
{
75+
Query: "SELECT name FROM users WHERE id = 1",
76+
Expected: []sql.Row{
77+
{"Alice Smith"},
78+
},
79+
},
80+
},
81+
},
82+
{
83+
Name: "BINLOG with DELETE",
84+
SetUpScript: []string{
85+
"CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(50), email VARCHAR(100))",
86+
"INSERT INTO users VALUES (1, 'Alice', '[email protected]')",
87+
"INSERT INTO users VALUES (2, 'Bob', '[email protected]')",
88+
},
89+
Assertions: []ScriptTestAssertion{
90+
{Query: binlogDeleteStmts[0], Expected: []sql.Row{}},
91+
{Query: binlogDeleteStmts[1], Expected: []sql.Row{}},
92+
{
93+
Query: "SELECT COUNT(*) FROM users",
94+
Expected: []sql.Row{
95+
{1},
96+
},
97+
},
98+
{
99+
Query: "SELECT id FROM users",
100+
Expected: []sql.Row{
101+
{1},
102+
},
103+
},
104+
},
105+
},
106+
{
107+
Name: "BINLOG with FORMAT_DESCRIPTION only",
108+
Assertions: []ScriptTestAssertion{
109+
{Query: binlogFormatDescStmts[0], Expected: []sql.Row{}},
110+
},
111+
},
112+
{
113+
Name: "BINLOG transaction with multiple INSERT UPDATE DELETE",
114+
SetUpScript: []string{
115+
"CREATE TABLE multi_op_test (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100), value DECIMAL(10,2), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)",
116+
},
117+
Assertions: []ScriptTestAssertion{
118+
{Query: binlogTransactionMultiOps[0], Expected: []sql.Row{}},
119+
{Query: binlogTransactionMultiOps[1], Expected: []sql.Row{}},
120+
{Query: binlogTransactionMultiOps[2], Expected: []sql.Row{}},
121+
{Query: binlogTransactionMultiOps[3], Expected: []sql.Row{}},
122+
{Query: binlogTransactionMultiOps[4], Expected: []sql.Row{}},
123+
{Query: binlogTransactionMultiOps[5], Expected: []sql.Row{}},
124+
{
125+
Query: "SELECT COUNT(*) FROM multi_op_test",
126+
Expected: []sql.Row{
127+
{2},
128+
},
129+
},
130+
{
131+
Query: "SELECT value FROM multi_op_test WHERE id = 1",
132+
Expected: []sql.Row{
133+
{"109.99"},
134+
},
135+
},
136+
},
137+
},
138+
{
139+
Name: "BINLOG with invalid base64",
140+
Assertions: []ScriptTestAssertion{
141+
{
142+
Query: "BINLOG 'not-valid-base64!!!'",
143+
ExpectedErr: sql.ErrBase64DecodeError,
144+
},
145+
},
146+
},
147+
}
148+
149+
// readBinlogTestFile reads BINLOG statements from a testdata file. The file is pre-filtered by binlog_maker.bats to
150+
// contain only BINLOG statements.
151+
func readBinlogTestFile(path string) []string {
152+
data, err := os.ReadFile(path)
153+
if err != nil {
154+
return nil
155+
}
156+
157+
content := strings.TrimSpace(string(data))
158+
if content == "" {
159+
return nil
160+
}
161+
162+
return strings.Split(content, "BINLOG '")
163+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
BINLOG '
2+
q9X/aA8BAAAA/AAAAAABAAAAAAQAMTAuMTEuMTMtTWFyaWFEQi0wdWJ1bnR1MC4yNC4wNC4xLWxv
3+
ZwAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA
4+
CgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
5+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
6+
AAAAAAAAAAAEEwQADQgICAoKCgE1OrWh
7+
'/*!*/;
8+
BINLOG '
9+
q9X/aBMBAAAANgAAAO0BAAAAABIAAAAAAAEABG15ZGIABXVzZXJzAAMDDw8EMgBkAAa3E3Ct
10+
q9X/aBkBAAAAOgAAACcCAAAAABIAAAAAAAEAAwf4AgAAAANCb2IPYm9iQGV4YW1wbGUuY29tJ0mO
11+
iA==
12+
'/*!*/;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
BINLOG '
2+
q9X/aA8BAAAA/AAAAAABAAAAAAQAMTAuMTEuMTMtTWFyaWFEQi0wdWJ1bnR1MC4yNC4wNC4xLWxv
3+
ZwAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA
4+
CgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
5+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
6+
AAAAAAAAAAAEEwQADQgICAoKCgE1OrWh
7+
'/*!*/;
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
BINLOG '
2+
qtX/aA8BAAAA/AAAAAABAAAAAAQAMTAuMTEuMTMtTWFyaWFEQi0wdWJ1bnR1MC4yNC4wNC4xLWxv
3+
ZwAAAAAAAAAAAAAAAACq1f9oEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA
4+
CgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
5+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
6+
AAAAAAAAAAAEEwQADQgICAoKCgEl17yE
7+
'/*!*/;
8+
BINLOG '
9+
q9X/aBMBAAAANgAAANEDAAAAABIAAAAAAAEABG15ZGIABXVzZXJzAAMDDw8EMgBkAAbaolFI
10+
q9X/aBcBAAAAPgAAAA8EAAAAABIAAAAAAAEAAwf4AQAAAAVBbGljZRFhbGljZUBleGFtcGxlLmNv
11+
bRQK09I=
12+
'/*!*/;
13+
BINLOG '
14+
q9X/aBMBAAAANgAAANsEAAAAABIAAAAAAAEABG15ZGIABXVzZXJzAAMDDw8EMgBkAAayBNYS
15+
q9X/aBcBAAAAOgAAABUFAAAAABIAAAAAAAEAAwf4AgAAAANCb2IPYm9iQGV4YW1wbGUuY29t8VcU
16+
wg==
17+
'/*!*/;

0 commit comments

Comments
 (0)