You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
WebSocket: TEXT stored in a column declared BLOB is base64-decoded on read #288
On the WebSocket transport with the default websocketBlobFormat (base64-blobs-v1), decodeWebsocketRowsetData base64-decodes every string cell in a column whose declared type contains BLOB. SQLite lets such a column hold TEXT, and those values are base64-decoded too, so the client gets the wrong bytes. What's stored is correct; only the read is wrong.
awaitdb.sql`CREATE TABLE t (id INTEGER PRIMARY KEY, b BLOB)`awaitdb.sql`INSERT INTO t VALUES (1, 'Hello'), (2, X'48656C6C6F'), (3, '48656c6c6f'), (4, 'aGVsbG8=')`awaitdb.sql`SELECT id, typeof(b), hex(b) FROM t`// 1 text 48656C6C6F// 2 blob 48656C6C6F// 3 text 34383635366336633666// 4 text 614756736247383Dawaitdb.sql`SELECT id, b FROM t`// 1 [29, 233, 101] expected the text 'Hello'// 2 [72, 101, 108, 108, 111] correct ("Hello")// 3 [227, 206, 185, 233, 206, 156, 233] expected the text '48656c6c6f'// 4 [104, 101, 108, 108, 111] expected the text 'aGVsbG8=', got the bytes of "hello"
CAST(b AS TEXT), and the same text in a column with no declared BLOB type, read back correctly.
Cause
decodeWebsocketRowsetData in src/drivers/utilities.ts:
With base64-blobs-v1 a BLOB arrives as a base64 string, and nothing marks it apart from a TEXT value: both are strings. The decoder guesses from the column's declared type (metadata.columns[i].type), but SQLite's declared types are only a hint. A BLOB column can hold TEXT, INTEGER or REAL, and a column without BLOB in its type can hold a BLOB (see #281).
Impact
Anyone storing text in a BLOB-declared column sees wrong data. A client that reads a row and writes it back, such as a data editor, would store the wrong bytes.
Activity