Skip to content

Commit 2be0e15

Browse files
authored
fix: enable the replication of MySQL's TRUNCATE statement (#275)
* test: add TestTruncateTable * Implement sql.TruncateableTable
1 parent 2950610 commit 2be0e15

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

backend/executor.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ func (b *DuckBuilder) Build(ctx *sql.Context, root sql.Node, r sql.Row) (sql.Row
7171
switch n.(type) {
7272
case *plan.CreateDB, *plan.DropDB, *plan.DropTable, *plan.RenameTable,
7373
*plan.CreateTable, *plan.AddColumn, *plan.RenameColumn, *plan.DropColumn, *plan.ModifyColumn,
74+
*plan.Truncate,
7475
*plan.CreateIndex, *plan.DropIndex, *plan.AlterIndex, *plan.ShowIndexes,
7576
*plan.ShowTables, *plan.ShowCreateTable, *plan.ShowColumns,
7677
*plan.ShowBinlogs, *plan.ShowBinlogStatus, *plan.ShowWarnings,

binlogreplication/binlog_replication_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,31 @@ func TestCharsetsAndCollations(t *testing.T) {
506506
require.NoError(t, rows.Close())
507507
}
508508

509+
// TestTruncateTable tests that TRUNCATE TABLE is correctly replicated.
510+
func TestTruncateTable(t *testing.T) {
511+
defer teardown(t)
512+
startSqlServersWithSystemVars(t, duckReplicaSystemVars)
513+
startReplicationAndCreateTestDb(t, mySqlPort)
514+
515+
// Create a table and insert some data
516+
primaryDatabase.MustExec("create table t (pk int primary key);")
517+
primaryDatabase.MustExec("insert into t values (1), (2), (3);")
518+
519+
// Verify the data on the replica
520+
waitForReplicaToCatchUp(t)
521+
requireReplicaResults(t, "select * from db01.t order by pk;", [][]any{{"1"}, {"2"}, {"3"}})
522+
523+
// TRUNCATE TABLE and verify the replica
524+
primaryDatabase.MustExec("truncate table t;")
525+
waitForReplicaToCatchUp(t)
526+
requireReplicaResults(t, "select * from db01.t;", [][]any{})
527+
528+
// Insert some new data and verify the replica
529+
primaryDatabase.MustExec("insert into t values (4), (5), (6);")
530+
waitForReplicaToCatchUp(t)
531+
requireReplicaResults(t, "select * from db01.t order by pk;", [][]any{{"4"}, {"5"}, {"6"}})
532+
}
533+
509534
//
510535
// Test Helper Functions
511536
//

catalog/table.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ var _ sql.IndexAddressableTable = (*Table)(nil)
4848
var _ sql.InsertableTable = (*Table)(nil)
4949
var _ sql.UpdatableTable = (*Table)(nil)
5050
var _ sql.DeletableTable = (*Table)(nil)
51+
var _ sql.TruncateableTable = (*Table)(nil)
5152
var _ sql.ReplaceableTable = (*Table)(nil)
5253
var _ sql.CommentedTable = (*Table)(nil)
5354

@@ -333,6 +334,16 @@ func (t *Table) Deleter(*sql.Context) sql.RowDeleter {
333334
return nil
334335
}
335336

337+
// Truncate implements sql.TruncateableTable.
338+
func (t *Table) Truncate(ctx *sql.Context) (int, error) {
339+
result, err := adapter.ExecCatalog(ctx, `TRUNCATE TABLE `+FullTableName(t.db.catalog, t.db.name, t.name))
340+
if err != nil {
341+
return 0, err
342+
}
343+
affected, err := result.RowsAffected()
344+
return int(affected), err
345+
}
346+
336347
// Replacer implements sql.ReplaceableTable.
337348
func (t *Table) Replacer(*sql.Context) sql.RowReplacer {
338349
hasKey := len(t.schema.PkOrdinals) > 0 || !sql.IsKeyless(t.schema.Schema)

0 commit comments

Comments
 (0)