Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/big-plants-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@powersync/mysql-zongji': patch
---

Fix decoding varchar and string values with utf8mb3 and utf8mb4 charsets.
12 changes: 12 additions & 0 deletions lib/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this breaks anything, but I'm worried something else might depend on the _encoding being set to something else, and this is only really supposed to change it for the column being read. Can we call parseBuffer(size).toString(column.charset ?? parser._encoding) instead?

}

result = parser.parseString(size);
}
break;
Expand Down
45 changes: 23 additions & 22 deletions test/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
});
});
});
Expand Down Expand Up @@ -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'"]
]
);