Skip to content

Commit

Permalink
fix: support enum columns for mysqlsh copy-instance utility (#350)
Browse files Browse the repository at this point in the history
* test: add enum column to mysqlsh copy-instance test
* test: add UUID column
* test: uuid and enum
* fix: convert enum ordinal to string for duckdb insert
  • Loading branch information
fanyang01 authored Jan 7, 2025
1 parent 0ba0b75 commit 052e742
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 9 deletions.
36 changes: 28 additions & 8 deletions .github/workflows/mysql-copy-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,22 @@ jobs:
- name: Setup test data in source MySQL
run: |
mysqlsh -hlocalhost -P13306 -uroot -proot --sql -e "
mysqlsh -hlocalhost -P13306 -uroot -proot --sql <<'EOF'
CREATE DATABASE testdb;
USE testdb;
-- Normal table, which should be copied to MyDuck via duckdb's csv import
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100)
name VARCHAR(100),
status ENUM('active', 'inactive', 'pending') DEFAULT 'pending'
);
INSERT INTO users (name) VALUES ('test1'), ('test2'), ('test3');
INSERT INTO users (name, status) VALUES
('test1', 'active'),
('test2', 'inactive'),
('test3', 'pending');
-- Make a gap in the id sequence
INSERT INTO users VALUES (100, 'test100');
INSERT INTO users (name) VALUES ('test101');
INSERT INTO users VALUES (100, 'test100', 'active');
INSERT INTO users (name, status) VALUES ('test101', 'inactive');
-- A table with non-default starting auto_increment value
CREATE TABLE items (
Expand All @@ -66,7 +71,22 @@ jobs:
) AUTO_INCREMENT=1000;
INSERT INTO items (v, name) VALUES (1, 'item1'), (2, 'item2'), (3, 'item3');
"
-- Table with UUID primary key
-- For such tables, MySQL Shell generates nontrivial LOAD DATA statements
-- to copy the data to MyDuck: LOAD DATA ... (@id, title, created_at) SET id = FROM_BASE64(@id),
-- which can only be executed by the go-mysql-server framework for now.
CREATE TABLE documents (
id BINARY(16) PRIMARY KEY,
title VARCHAR(200),
status ENUM('draft', 'published', 'archived') DEFAULT 'draft',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
INSERT INTO documents (id, title, status) VALUES
(UUID_TO_BIN(UUID()), 'Document 1', 'published'),
(UUID_TO_BIN(UUID()), 'Document 2', 'draft');
EOF
- name: Build and start MyDuck Server
run: |
Expand All @@ -85,7 +105,7 @@ jobs:
--users false --ignore-version true
# Verify the data was copied
for table in users items; do
for table in users items documents; do
mysqlsh -hlocalhost -P13306 -uroot -proot --sql -e "
SELECT * FROM testdb.$table ORDER BY id;
" | tee source_data_$table.tsv
Expand All @@ -96,4 +116,4 @@ jobs:
diff source_data_$table.tsv copied_data_$table.tsv
done
21 changes: 20 additions & 1 deletion catalog/inserter.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type rowInserter struct {
stmt *stdsql.Stmt
err error
flushSQL string
enums []int
}

var _ sql.RowInserter = &rowInserter{}
Expand Down Expand Up @@ -75,9 +76,15 @@ func (ri *rowInserter) init(ctx *sql.Context) {
}
insert.WriteString(" INTO ")
insert.WriteString(ConnectIdentifiersANSI(ri.db, ri.table))
insert.WriteString(" SELECT * FROM ")
insert.WriteString(" FROM ")
insert.WriteString(QuoteIdentifierANSI(ri.tmpTable))
ri.flushSQL = insert.String()

for i, col := range ri.schema {
if _, ok := col.Type.(sql.EnumType); ok {
ri.enums = append(ri.enums, i)
}
}
}

func (ri *rowInserter) StatementBegin(ctx *sql.Context) {
Expand Down Expand Up @@ -106,6 +113,18 @@ func (ri *rowInserter) Insert(ctx *sql.Context, row sql.Row) error {
if ri.err != nil {
return ri.err
}

// For enum columns, we have to convert the enum ordinal to the enum string.
for _, i := range ri.enums {
if idx, ok := row[i].(uint16); ok {
if s, ok := ri.schema[i].Type.(sql.EnumType).At(int(idx)); ok {
row[i] = s
} else {
return fmt.Errorf("invalid enum value %d for column %s", idx, ri.schema[i].Name)
}
}
}

if _, err := ri.stmt.ExecContext(ctx, row...); err != nil {
ri.err = err
return err
Expand Down

0 comments on commit 052e742

Please sign in to comment.