Skip to content

Replay WAL in the object's database context - #618

Merged
wudidapaopao merged 1 commit into
mainfrom
fix/durable-wal-replay-db-context
Jul 28, 2026
Merged

Replay WAL in the object's database context#618
wudidapaopao merged 1 commit into
mainfrom
fix/durable-wal-replay-db-context

Conversation

@ShawnChen-Sirius

@ShawnChen-Sirius ShawnChen-Sirius commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

What

Restore the object's database as the current database before replaying the write-ahead log in chdb.durable.

The bug

WAL replay ran with default as the current database. A durable object sets its own database (the manifest's db) as current, and callers write with unqualified table names against it. On reopen, those logged statements replayed into default instead — so the tables were invisible to the caller and dropped by the next BACKUP DATABASE {db} checkpoint. Net effect: committed writes silently lost after a crash/reopen, whenever the caller used unqualified names (the natural style once you've set a database).

The fix

USE {db} before replay (one line in _restore), plus a note in the WAL usage rules.

Test

Adds a regression test. Every existing durable test qualifies its table names (mem.t), so none exercised the replay database context; the new test uses an unqualified name and reopens. Without the fix it fails with UNKNOWN_TABLE; with it, the full suite passes (verified locally and against MinIO).

Context

Found while building a memory backend on chdb.durable (auxten/clickmem#7), whose tables are unqualified — this fix is a correctness prerequisite for that use.

Note

Replay WAL in the object's database context and quote database identifiers

  • Adds _quote_ident helper in object.py to backtick-quote ClickHouse identifiers, allowing database names containing hyphens or other special characters in DDL statements.
  • Issues a USE <db> statement before WAL replay in DurableObject._restore so unqualified table references in WAL entries replay against the object's own database instead of default.
  • Applies _quote_ident consistently in open, _restore, and checkpoint for CREATE DATABASE and BACKUP DATABASE statements.
  • Behavioral Change: WAL replay now executes in the object's database context; previously unqualified statements would silently target default.

Macroscope summarized 9cd8e66.

@ShawnChen-Sirius
ShawnChen-Sirius requested a review from Copilot July 27, 2026 04:40
@ShawnChen-Sirius

Copy link
Copy Markdown
Contributor Author

@chibugai please review it.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Fixes chdb.durable crash/reopen correctness by ensuring WAL replay runs with the durable object’s manifest database set as the session’s current database, so unqualified table names during replay target the intended database (instead of default).

Changes:

  • Set the session database via USE {db} before replaying WAL segments during _restore.
  • Document WAL replay semantics for unqualified table names vs. cross-database statements.
  • Add a regression test that writes unqualified statements after USE, flushes (WAL-only), reopens, and asserts data is restored into the manifest DB.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
chdb/durable/object.py Sets current DB before WAL replay to ensure unqualified statements replay into the object’s manifest database.
chdb/durable/wal.py Documents that WAL replay uses the manifest DB as the current database; cross-DB statements must be qualified.
tests/test_durable.py Adds regression coverage for WAL replay with unqualified table names after USE and reopen.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread chdb/durable/object.py Outdated
WAL replay ran with `default` as the current database, so any statement
written with an unqualified table name (after the caller set its database
with `USE`) silently replayed into the wrong database — invisible to the
caller and dropped by the next `BACKUP DATABASE {db}` checkpoint, i.e.
committed writes lost after a crash/reopen.

Restore the object's database (the manifest's `db`) as the current
database before replay, and document the guarantee in the WAL usage
notes. Add a regression test: every other durable test qualifies table
names (mem.t), so none of them exercised the replay database context.

Also backtick-quote the database identifier in every DDL/USE statement
(CREATE/RESTORE/BACKUP/USE DATABASE), so a name needing quotes (e.g. one
with '-') is valid and can't break out of the statement; the durable
package quotes locally rather than importing clickhouse_connect. Covered
by a round-trip test on a hyphenated database name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ShawnChen-Sirius
ShawnChen-Sirius force-pushed the fix/durable-wal-replay-db-context branch from 95a62e8 to 9cd8e66 Compare July 28, 2026 00:37
@ShawnChen-Sirius

Copy link
Copy Markdown
Contributor Author

@wudidapaopao please review it.

@wudidapaopao wudidapaopao left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@wudidapaopao
wudidapaopao merged commit 8a3f56a into main Jul 28, 2026
9 checks passed
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.

3 participants