"""Original offline fixture: SQLite projection + compact UTF-8 JSON sizes. No Cloudflare connection; budgets are ours, not a D1 wire-size emulator. Run with Python 3 standard library: python3 d1-byte-budget-lab.py """ import json import platform import sqlite3 def encoded(rows): return json.dumps(rows, ensure_ascii=False, separators=(",", ":")).encode("utf-8") def database(mixed): db = sqlite3.connect(":memory:") db.row_factory = sqlite3.Row db.execute("CREATE TABLE reports(id INTEGER PRIMARY KEY, title TEXT, body TEXT)") db.executemany("INSERT INTO reports VALUES(?,?,?)", ( (i, f"보고서 {i}", "가" * (300_000 if mixed and i <= 60 else 300)) for i in range(1, 101))) return db def read(db, columns, after=0, count=100): # Only these internal column sets are allowed. User input never becomes SQL. assert columns in ("id,title,body", "id,title") return [dict(r) for r in db.execute( f"SELECT {columns} FROM reports WHERE id > ? ORDER BY id LIMIT ?", (after, count))] def local_retry(db, after, count, budget): attempts = [] while True: rows = read(db, "id,title,body", after, count) size = len(encoded(rows)) attempts.append({"limit": count, "rows": len(rows), "jsonBytes": size}) if size <= budget: return {"status": "ok", "ids": [r["id"] for r in rows], "nextAfter": rows[-1]["id"] if rows else after, "attempts": attempts} if count == 1: return {"status": "needs-projection-or-separate-path", "ids": [], "nextAfter": after, "attempts": attempts} # Failed requests never advance the boundary. This fixture reads static data. count = max(1, count // 2) def main(): small, mixed = database(False), database(True) sizes = {"small100": len(encoded(read(small, "id,title,body"))), "mixed100": len(encoded(read(mixed, "id,title,body"))), "projected100": len(encoded(read(mixed, "id,title")))} assert sizes["small100"] < 1_000_000 assert sizes["mixed100"] > 50_000_000 assert sizes["projected100"] < 10_000 recovered = local_retry(mixed, 0, 100, 4_000_000) assert recovered["ids"] == [1, 2, 3] and recovered["nextAfter"] == 3 following = local_retry(mixed, recovered["nextAfter"], 3, 4_000_000) assert following["ids"] == [4, 5, 6] blocked = local_retry(mixed, 0, 1, 512_000) assert blocked["nextAfter"] == 0 and blocked["ids"] == [] assert blocked["status"] == "needs-projection-or-separate-path" assert local_retry(mixed, 100, 3, 4_000_000)["ids"] == [] bound = (4_000_000 - 100_000) // 1_000_000 assert bound == 3 text = "가" * 300_000 assert len(text) == 300_000 and len(text.encode("utf-8")) == 900_000 print(json.dumps({"environment": {"python": platform.python_version(), "sqlite": sqlite3.sqlite_version}, "scope": "Synthetic local SQLite and Python JSON only; no D1 remote request or 50 MB enforcement test", "encoding": "compact JSON ensure_ascii=False, UTF-8; array only, no D1 metadata", "sizes": sizes, "recovered": recovered, "following": following, "singleRowBlocked": blocked, "assumedBoundRows": bound, "assertions": "passed"}, ensure_ascii=False, indent=2)) small.close() mixed.close() if __name__ == "__main__": main()