Skip to content

Commit 8c56b0a

Browse files
committed
Patch Turso translate_drop_table to use correct db schema for indices
translate_drop_table reads the table's indices via resolver.schema() (always MAIN) but emits Destroy with the resolved database_id. When dropping a TEMP-shadowed table (e.g. permanent t shadowed by temp t), the indices come from MAIN's schema while Destroy opens the cursor on temp's pager. Temp's pager then tries to read a page at MAIN's index root_page, which doesn't exist there: ERROR turso_core::storage::sqlite3_ondisk: short read on page 29 ERROR turso_core::vdbe: page is pinned Repro: testTemporaryTableHasPriorityOverStandardTable. The driver's ALTER emulation issues DROP TABLE on the shadowed name; Turso's drop path picks up MAIN's index 'ia' instead of TEMP's index 'ib'. Fix: read indices via with_schema(database_id, ...). Same pattern as patch #17 for the sqlite_sequence root_page mismatch. Worth reporting upstream — independent of mysql-on-sqlite.
1 parent 42cf49a commit 8c56b0a

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

.github/workflows/phpunit-tests-turso.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,44 @@ jobs:
676676
print('patched join.rs to refuse hash-join in correlated query blocks')
677677
PY_FIX_HASH_JOIN_CORRELATED
678678
679+
# 19. translate_drop_table reads indices from `resolver.schema()`
680+
# (always MAIN) to emit Destroy bytecode, but uses the
681+
# resolved `database_id` for `db:`. When dropping a
682+
# TEMP-shadowed table (perm `t` + temp `t`, DROP resolves to
683+
# temp), the indices come from MAIN's schema while Destroy
684+
# opens the cursor on temp's pager → temp pager reads MAIN's
685+
# index root page, which doesn't exist in temp →
686+
# "short read on page N: page is pinned".
687+
# Repro: testTemporaryTableHasPriorityOverStandardTable —
688+
# during the driver's ALTER emulation, DROP TABLE `t` after
689+
# CREATE TEMPORARY shadow.
690+
# Fix: read indices from with_schema(database_id, ...), same
691+
# pattern as patch #17 for sqlite_sequence.
692+
python3 - <<'PY_FIX_DROP_INDICES'
693+
p = 'core/translate/schema.rs'
694+
s = open(p).read()
695+
old = (
696+
" // 2. Destroy the indices within a loop\n"
697+
" let indices = resolver.schema().get_indices(tbl_name.name.as_str());\n"
698+
" for index in indices {\n"
699+
)
700+
new = (
701+
" // 2. Destroy the indices within a loop\n"
702+
" // Use the schema for the SAME database the cursor will open in —\n"
703+
" // when dropping a TEMP-shadowed table, the table's indices live in\n"
704+
" // temp's schema, not main's. Reading from main here would emit\n"
705+
" // Destroy with main's index root_page on temp's pager, which then\n"
706+
" // tries to read a page that doesn't exist in temp → short read.\n"
707+
" let indices: Vec<_> = resolver.with_schema(database_id, |s| {\n"
708+
" s.get_indices(tbl_name.name.as_str()).cloned().collect()\n"
709+
" });\n"
710+
" for index in indices {\n"
711+
)
712+
assert old in s, 'translate_drop_table get_indices block not found'
713+
open(p, 'w').write(s.replace(old, new, 1))
714+
print('patched translate_drop_table to read indices from correct database schema')
715+
PY_FIX_DROP_INDICES
716+
679717
echo '--- Patched stub! macro ---'
680718
sed -n '/macro_rules! stub/,/^}$/p' sqlite3/src/lib.rs
681719

0 commit comments

Comments
 (0)