Skip to content

Commit 540dcbf

Browse files
committed
fix(core.utils): treat empty schema_meta as unknown-version for entries rebuild
1 parent 23a69d4 commit 540dcbf

2 files changed

Lines changed: 42 additions & 16 deletions

File tree

cuda_core/cuda/core/utils/_program_cache.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,41 +1089,44 @@ def _connect_and_init(self) -> None:
10891089

10901090
# Detect an existing schema version *before* creating any tables so
10911091
# a structural migration (added columns / renamed indexes) can be
1092-
# handled by dropping the old tables outright.
1092+
# handled by dropping the old tables outright. Two cases yield
1093+
# "version unknown": schema_meta is missing entirely, or schema_meta
1094+
# exists but has no ``schema_version`` row. Both mean we can't trust
1095+
# any pre-existing ``entries`` layout -- CREATE TABLE IF NOT EXISTS
1096+
# would keep it and later reads/writes would fail with
1097+
# OperationalError instead of recovering to an empty cache.
10931098
existing_version = None
1094-
schema_meta_missing = False
1099+
schema_version_known = False
10951100
try:
10961101
row = self._conn.execute(
10971102
"SELECT value FROM schema_meta WHERE key = ?",
10981103
("schema_version",),
10991104
).fetchone()
11001105
if row is not None:
11011106
existing_version = row[0]
1107+
schema_version_known = True
11021108
except self._sqlite3.OperationalError:
11031109
# schema_meta doesn't exist.
1104-
schema_meta_missing = True
1110+
pass
11051111

1106-
# If schema_meta is absent but an ``entries`` table is already
1107-
# present (e.g. the file was produced by a different tool or a
1108-
# pre-schema_meta version of this cache), treat the DB as
1109-
# incompatible: CREATE TABLE IF NOT EXISTS would keep the old
1110-
# ``entries`` layout and later reads/writes would fail with
1111-
# OperationalError instead of recovering to an empty cache.
1112-
entries_present_without_schema_meta = False
1113-
if schema_meta_missing:
1112+
# If the schema_version isn't known but an ``entries`` table exists,
1113+
# the DB came from a different tool or a pre-schema_meta revision;
1114+
# drop and rebuild. If both are present and match, leave in place.
1115+
entries_present_with_unknown_version = False
1116+
if not schema_version_known:
11141117
row = self._conn.execute(
11151118
"SELECT name FROM sqlite_master WHERE type='table' AND name='entries'",
11161119
).fetchone()
1117-
entries_present_without_schema_meta = row is not None
1120+
entries_present_with_unknown_version = row is not None
11181121

11191122
needs_drop = (
1120-
(existing_version is not None and existing_version != _SQLITE_SCHEMA_VERSION)
1121-
or entries_present_without_schema_meta
1123+
(schema_version_known and existing_version != _SQLITE_SCHEMA_VERSION)
1124+
or entries_present_with_unknown_version
11221125
)
11231126
if needs_drop:
11241127
# Drop all cache tables -- ensures structural mismatch (whether
1125-
# a version bump or a foreign ``entries`` layout) can't leave a
1126-
# legacy table in place.
1128+
# a version bump or a foreign/pre-schema_meta ``entries``
1129+
# layout) can't leave a legacy table in place.
11271130
self._conn.execute("DROP TABLE IF EXISTS entries")
11281131
self._conn.execute("DROP TABLE IF EXISTS schema_meta")
11291132

cuda_core/tests/test_program_cache.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,29 @@ def test_sqlite_cache_drops_foreign_entries_table_without_schema_meta(tmp_path):
19351935
assert bytes(cache[b"k"].code) == b"v"
19361936

19371937

1938+
@needs_sqlite3
1939+
def test_sqlite_cache_drops_entries_when_schema_meta_is_empty(tmp_path):
1940+
"""schema_meta exists but has no schema_version row: the cache version
1941+
is unknown, so any pre-existing ``entries`` table is untrusted and must
1942+
be dropped. Otherwise CREATE TABLE IF NOT EXISTS would keep the foreign
1943+
layout and later reads/writes would fail with OperationalError."""
1944+
import sqlite3
1945+
1946+
from cuda.core.utils import SQLiteProgramCache
1947+
1948+
db = tmp_path / "cache.db"
1949+
with sqlite3.connect(db) as conn:
1950+
conn.execute("CREATE TABLE schema_meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)")
1951+
conn.execute("CREATE TABLE entries (id INTEGER PRIMARY KEY, junk TEXT)")
1952+
conn.execute("INSERT INTO entries (id, junk) VALUES (1, 'legacy')")
1953+
conn.commit()
1954+
1955+
with SQLiteProgramCache(db) as cache:
1956+
assert len(cache) == 0
1957+
cache[b"k"] = _fake_object_code(b"v")
1958+
assert bytes(cache[b"k"].code) == b"v"
1959+
1960+
19381961
@needs_sqlite3
19391962
def test_sqlite_cache_schema_version_encodes_key_schema(tmp_path, monkeypatch):
19401963
"""Bumping ``_KEY_SCHEMA_VERSION`` must invalidate existing on-disk

0 commit comments

Comments
 (0)