diff --git a/.changeset/big-plants-joke.md b/.changeset/big-plants-joke.md new file mode 100644 index 0000000..b434e65 --- /dev/null +++ b/.changeset/big-plants-joke.md @@ -0,0 +1,5 @@ +--- +'@powersync/mysql-zongji': patch +--- + +Fix decoding varchar and string values with utf8mb3 and utf8mb4 charsets. diff --git a/lib/common.js b/lib/common.js index 6b4dbe2..f8bf0de 100644 --- a/lib/common.js +++ b/lib/common.js @@ -443,6 +443,18 @@ exports.readMysqlValue = function ( } else if (defPrefix === 'varbin') { result = parser.parseBuffer(size); } else { + if (column.charset !== null) { + switch (column.charset) { + // Javascript UTF8 always allows up to 4 bytes per character + case 'utf8mb3': + case 'utf8mb4': + column.charset = 'utf8'; + break; + } + + parser._encoding = column.charset; + } + result = parser.parseString(size); } break; diff --git a/test/types.js b/test/types.js index 8f18323..599d5d9 100644 --- a/test/types.js +++ b/test/types.js @@ -68,32 +68,24 @@ function defineTypeTest(name, fields, testRows, customTest) { } }; - expectEvents( - test, - eventLog, - [ - expectedWrite - ], - testRows.length, - () => { - test.equal(errorLog.length, 0); + expectEvents(test, eventLog, [expectedWrite], testRows.length, () => { + test.equal(errorLog.length, 0); - const binlogRows = eventLog.reduce((prev, curr) => { - if (curr.getTypeName() === 'WriteRows') { - prev = prev.concat(curr.rows); - } - return prev; - }, []); - - if (customTest) { - customTest.bind(selectResult)(test, { rows: binlogRows }); - } else { - assert.deepEqual(selectResult, binlogRows); + const binlogRows = eventLog.reduce((prev, curr) => { + if (curr.getTypeName() === 'WriteRows') { + prev = prev.concat(curr.rows); } + return prev; + }, []); - test.end(); + if (customTest) { + customTest.bind(selectResult)(test, { rows: binlogRows }); + } else { + assert.deepEqual(selectResult, binlogRows); } - ); + + test.end(); + }); }); }); }); @@ -293,3 +285,12 @@ defineTypeTest( [null, null, null, null] ] ); + +defineTypeTest( + 'charsets', + ['CHAR COLLATE latin1_general_ci', 'VARCHAR(15) COLLATE latin1_general_ci', 'TEXT COLLATE latin1_general_ci'], + [ + ["'ascii only'", "'ascii only'", "'ascii only'"], + ["'João'", "'João'", "'João'"] + ] +);