Skip to content

Read and write batch and checkpoint files as UTF-8 - #2434

Merged
rolandwalker merged 1 commit into
dbcli:mainfrom
Alpenj:fix-utf8-batch-checkpoint
Nov 14, 2026
Merged

rolandwalker merged 1 commit into
dbcli:mainfrom
Alpenj:fix-utf8-batch-checkpoint

Conversation

@Alpenj

@Alpenj Alpenj commented Nov 14, 2026

Copy link
Copy Markdown
Contributor

Description

On Windows, --batch and --checkpoint do not agree on the file encoding:

  • --batch files are opened with click.open_file(path), so they are read with the locale encoding (the ANSI code page on Windows, such as cp1252 or cp949).
  • The --checkpoint file is written with click.open_file(path, mode='a') (locale encoding) in run_query(), but replay_checkpoint_file() reads it back with encoding='utf-8'.

So on Windows, a UTF-8 batch file with any non-ASCII text fails to load or is read garbled, a statement with a character outside the code page cannot be written to the checkpoint, and --resume cannot read back a checkpoint that holds a non-ASCII statement. On Linux and macOS the locale encoding is usually UTF-8, so the problem does not show there.

Reproduction with the same open() calls, Python 3.14 on Windows with the cp949 code page:

locale encoding: cp949
batch read: UnicodeDecodeError 'cp949' codec can't decode byte 0xe2 in position 16: illegal multibyte sequence
checkpoint write: UnicodeEncodeError 'cp949' codec can't encode character '\u2728' in position 15: illegal multibyte sequence
checkpoint replay: UnicodeDecodeError 'utf-8' codec can't decode byte 0xc7 in position 23: invalid continuation byte

(The batch file is select 'Łukasz ✨';. The last line is a Korean statement written to the checkpoint with the locale encoding and read back as UTF-8, as --resume does.)

This change:

  • reads --batch files as UTF-8. Standard input (--batch -) is left as before, so click still picks the console encoding.
  • writes the --checkpoint file as UTF-8, which matches how replay_checkpoint_file() reads it.

Tests:

  • test_main_batch_without_progress_bar_reads_utf8_batch_and_checkpoint and test_main_batch_with_progress_bar_reads_utf8_batch use a UTF-8 batch file with Łukasz ✨.
  • test_run_query_writes_checkpoint_as_utf8 checks that the checkpoint is written as UTF-8.
  • The click.open_file fakes in test_main_modes_batch.py now accept keyword arguments.

On Windows 11 (cp949), Python 3.14, uv run pytest mycli_test/pytests/test_main_modes_batch.py mycli_test/pytests/test_client_query.py: before the fix, the 3 new tests fail (3 failed, 74 passed, 6 skipped); with the fix, 77 passed, 6 skipped.

Checklist

  • I added this contribution to the changelog.md file.
  • I added my name to the mycli/AUTHORS.txt file (or it's already there).
  • To lint and format the code, I ran
    uv run ruff check && uv run ruff format && uv run mypy --install-types .
    ruff check and ruff format --check pass. mypy on the changed files reports the same 4 errors before and after the change; they are Windows-only (pwd and os.getuid are missing there) and in other files.

--batch files were read with the locale encoding, and the
--checkpoint file was written with the locale encoding but read
back as UTF-8. On Windows, non-ASCII batch files failed to load
and --resume could not read the checkpoint. Read batch files as
UTF-8 (standard input is unchanged) and write the checkpoint as
UTF-8.
@rolandwalker

Copy link
Copy Markdown
Contributor

Hi! Thanks! We love better Windows support!

@rolandwalker
rolandwalker merged commit 93abdf3 into dbcli:main Nov 14, 2026
13 checks passed
@rolandwalker

Copy link
Copy Markdown
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants