Skip to content
AITroveRead. Build. Understand.
Make this comfortable

Python SQLite progress handler: interrupt one expensive statement

Last updated: 1 Oct 20265 min read
tutorial
IntermediateBy AITrove Editorial

A progress callback can stop a query after a bounded number of virtual-machine steps.

Download Python source kit

Operation contract

The connection starts with one accepted receipt. A recursive count query exceeds the fixture's forty callback allowance, so the progress handler returns a nonzero result and SQLite interrupts that statement. The handler is removed before a normal query verifies the existing row remains.

Failure boundary

The callback count is a virtual-machine instruction budget, not elapsed time, memory use, or a cross-machine service-level guarantee. Different SQLite builds or query plans may do different work per result. Use a wall-clock deadline and resource policy alongside it for a real request boundary.

Working program

python
import sqlite3

connection = sqlite3.connect(":memory:")
try:
    connection.execute("CREATE TABLE receipts (receipt_id INTEGER PRIMARY KEY)")
    connection.execute("INSERT INTO receipts VALUES (?)", (47,))
    connection.commit()
    callbacks = 0

    def stop_long_query():
        global callbacks
        callbacks += 1
        return int(callbacks >= 40)

    connection.set_progress_handler(stop_long_query, 1)
    try:
        connection.execute("WITH RECURSIVE numbers(value) AS ("
                           "SELECT 1 UNION ALL SELECT value + 1 FROM numbers WHERE value < 100000) "
                           "SELECT sum(value) FROM numbers").fetchone()
    except sqlite3.DatabaseError:
        print("query_interrupted", True)
    finally:
        connection.set_progress_handler(None, 0)
    print("receipt_kept", connection.execute("SELECT receipt_id FROM receipts").fetchone()[0])
finally:
    connection.close()

Output

Output
query_interrupted True
receipt_kept 47

Costs and limits

Invoking Python after every virtual-machine step is deliberately expensive in this small fixture. A production interval should be measured against the accepted query workload, then combined with a deadline.

Common Mistakes

  • Instruction callbacks do not measure wall-clock time.
  • Remove a request-scoped handler before reusing its connection.
  • Catching the interrupt without checking surrounding transaction state can hide a partial workflow.

Connected lessons

Test this contract.

python
sqlite-progress-budget
Storage details