Exercise 2: A Crash Before the FIRST of Two Index Updates — Possible Solution ==================================================================== THE TEST ------------------------------ db3 = Database(tmp3) db3.create_table('accounts', [('id','INTEGER'),('name','TEXT'),('balance','INTEGER')]) db3.create_index('accounts', 'id') db3.create_index('accounts', 'name') db3.insert('accounts', [1, 'Alice', 500]) schema4, table4 = db3.tables['accounts'] table4.insert([2, 'Bob', 300]) # crash simulated BEFORE the index-update # loop in Database.insert() ever starts scanned2 = list(table4.scan()) by_id = db3.select('accounts', where=('id', '=', 2)) by_name = db3.select('accounts', where=('name', '=', 'Bob')) RESULT ------------------------------ a real scan finds both rows: [[1, 'Alice', 500], [2, 'Bob', 300]] WHERE id = 2 -> [] WHERE name = 'Bob' -> [] Both queries return empty. Row 2 is genuinely present in the table, but neither of its two indexes has any record of it. WHY BOTH INDEXES FAIL, NOT JUST ONE ------------------------------ Database.insert()'s own index-update step is a single Python for loop: for (t_name, col_name), root in list(self.indexes.items()): if t_name == table_name: ... self.indexes[(t_name, col_name)] = btree_insert(root, values[idx], location) Calling table.insert() directly (as this test does, simulating the crash) skips Database.insert() -- and therefore this ENTIRE loop -- completely. It isn't that the loop ran partway and stopped after updating the id index but before reaching the name index; it's that the loop never started running at all. Whether a table has one index or ten, an interruption at this exact point (between the row being physically written and Database.insert()'s own second step beginning) leaves every single one of them stale simultaneously. WHY THIS IS A MORE DANGEROUS VERSION OF FINDING 1 ------------------------------ Chapter 1's own main demonstration used a table with only one index, which could make the bug look like a narrow, one-index edge case. This exercise makes clear it isn't: the number of indexes on a table has no bearing on how many of them break, because the underlying problem was never "one index update failed" -- it's that atomicity was never guaranteed for the multi-step insert operation as a whole. A table with five indexes crashing at this exact point would leave all five silently wrong, all at once, for exactly the same reason. WHY THIS WORKS AS AN ANSWER ------------------------------ Extending the original one-index scenario to two indexes and verifying both fail identically confirms the bug is structural (a property of WHERE the interruption happens relative to the whole operation) rather than something specific to a single index's own implementation -- ruling out a narrower, less useful explanation for what Finding 1 actually demonstrated.