Exercise 2: Three Small Inserts Landing on the Same Page — Possible Solution ==================================================================== THE TEST ------------------------------ table = HeapTable(hf, Schema([('n', 'TEXT')])) ids = [table.insert([f"x{i}"]) for i in range(3)] RESULT ------------------------------ ids -> [(0, 0), (0, 1), (0, 2)] All three row IDs share page_num == 0 -- three distinct slots (0, 1, 2) on the SAME page, not three separate pages. WHICH PART OF insert() IS RESPONSIBLE ------------------------------ insert()'s own logic is: n = self.heap_file.num_pages() if n > 0: page = self.heap_file.read_page(n - 1) # the LAST existing page try: slot = page.add_record(record) self.heap_file.write_page(n - 1, page) return (n - 1, slot) except ValueError: pass # full -- fall through to allocating a new one page_num = self.heap_file.allocate_page() ... For the FIRST insert, n (num_pages()) is 0, so the `if n > 0:` branch is skipped entirely -- a new page (page 0) is allocated, and the record goes into it, returning (0, 0). For the SECOND insert, n is now 1 -- the `if n > 0:` branch runs, reading page n-1 = page 0 (the same page the first record went into). Since page 0 still has plenty of room for one more tiny record, page.add_record() succeeds without raising ValueError, and the function returns (0, 1) directly -- the `except ValueError: pass` branch, and the subsequent allocate_page() call, are never reached at all. The THIRD insert follows the exact same path as the second: n is still 1 (no new page was allocated for insert #2), page 0 is read again, and the record fits again, giving (0, 2). WHY THIS WORKS AS AN ANSWER ------------------------------ The specific mechanism responsible is the `if n > 0: ... try: ... except ValueError: pass` structure -- insert() always attempts to reuse the LAST page before ever considering a new one, and only falls through to allocate_page() when that attempt genuinely raises ValueError (meaning the last page really is full, per Chapter 3's own capacity check). This is the direct fix for the wasteful "allocate a new page for every single insert" alternative named in the chapter's own "Where This Connects" table -- reusing existing space is the default behavior, not an afterthought.