The database layer
Asqueel supports synchronous PostgreSQL and SQLite access, model declarations, SQL compilation and explicit transaction control. Backend-specific SQL expressions remain backend-specific.
Coming soon: MySQL and Microsoft SQL Server (MSSQL) support in the Asqueel query/runtime layer.
Course compatibility
Verified with the official release: the first ten video lessons and the CLI example were executed in a new virtual environment using Asqueel 0.6.0 and Asqueel Migration 0.3.1, installed from PyPI on 20 October 2026. No source checkout or experimental package was used for this verification.
python -m pip install "asqueel[migration]==0.6.0"
The opening lesson creates a model directly in Python, migrates SQLite in memory, inserts, reads and updates rows, then adds columns with reloadModel(model) and migrates again. It imports a CSV string using products.sql_insert(data, format="csv"). Fourteen checks verify the results, retained rows, an empty final migration plan and absence of model/database files.
The second lesson imports four CSV files with table.sql_insert(source). The file extension identifies the format; the model converts integer keys, dates and Decimal amounts. This raw SQL import skips Python triggers and leaves transaction control to the caller. The result is 30 products, eight customers, twelve invoices and 36 rows. Twenty-one checks verify import counts, dates, every row total, relationship paths, foreign keys and unchanged CSV inputs.
The invoice-row CSV already contains quantity, unit_price and total. Fixture totals are calculated as quantity times unit price, rounded to two decimal places. Importing stores those totals; it does not compute them. If quantity or price changes, the stored total must be updated too.
The third lesson uses relationship paths in where and order_by, including two-hop customer-city filters and descending invoice dates. Fourteen checks compare results with expectations independently derived from the CSVs. Fields used in filtering or sorting need not be selected.
The fourth lesson focuses on a customer-city alias and the calculated amount of an invoice row. It changes a quantity, compares the stored and calculated amounts, then rolls back. No aggregate or best-buyer example is included.
The fifth lesson calculates invoice, customer and product totals. It uses @relation.aggr(...) for sums, counts and averages, then filters products by a named average-price formula. Checks compare results against the CSVs, including inclusive price bounds and null results for unsold products. Mean selling price is the unweighted mean of invoice-row unit prices. In Asqueel 0.6.0, aggr() is a standalone projection; the named formula supports filtering and ordering. SQL ROUND controls displayed precision; SQLite numeric arithmetic is not exact decimal arithmetic.
The sixth lesson focuses on GROUP BY and HAVING. Seven checks compare city totals and counts with independent CSV calculations, verify filtering before and after grouping, and retain the same in-memory connection. It uses ordinary fetch() to display results and writes no report files.
The seventh lesson reuses that report query to compare fetch, fetchAsDict, fetchGrouped, fetchRecord, fetchPkeys, fetchAsJson and iterfetch, then exports CSV and JSON. Fourteen checks cover result shapes, key handling, batch completeness and exact exported data. Only the exported reports are written to disk; the database remains in memory.
The eighth lesson is an optional extension, after GROUP BY: a calculated best-buyer ID starts a weak relation to a customer. Spending is grouped by buyer before sorting: two purchases of six beat one purchase of ten. Checks cover all buyers, names and cities, unsold products, ties, changes and rollback. Lesson nine rebuilds its starting state without this extension.
The ninth lesson focuses on normal writes and transactions, without custom Python hooks. It inserts and commits one invoice row, updates it through the table and a query selection, deletes it, and rolls back to its committed state. Nine checks verify the transaction boundary, key selection, unchanged values and final cleanup. Table update receives a complete physical record and old_record; query update prepares them automatically. Committing an in-memory database does not create a database file.
The tenth lesson attaches Python inserting, updating and updated hooks to invoice rows. These calculate stored totals and validate quantity and price. Direct query(...).sql_update(...) skips the hooks, as does the CSV import's sql_insert path. Thirteen checks cover calculations, direct-SQL differences, validation failures and rollback to every original row. After hooks run before commit; Python side effects are not undone by database rollback.
All ten videos have English narration, captions, chapter controls and playback-speed selection. The narration uses Heart, an AI-generated voice produced with Kokoro. The videos reconstruct executed commands with edited timing. Their SQLite database lasts only as long as the Python connection. The downloads contain commands and, for lessons two through ten, a bootstrap for restarting in a fresh console.
The CLI example separately passes eight checks, including migration, parameterized queries, explicit rollback and rollback when exiting the REPL.
The original 34 screenplays remain archived unchanged. Lessons 11–38 retain the original reading edition and historical verification from the write-cycle course at commit f7208dc; their PostgreSQL scenarios have not been rerun in this release check. This fresh execution covers the ten video lessons and CLI example, not every original scenario.
Migration compatibility
Asqueel 0.6.0 declares asqueel-migration>=0.3.1,<0.4 for its migration extra. The verified installation uses the published Migration 0.3.1. Follow the package dependency constraints when upgrading.
Migration 0.3.0 changed SQLite file layout: attached schemas use <schema>.db next to the main database file. The video lessons use in-memory schemas; the CLI example uses database files.
Boundaries worth knowing
- Model construction and SQL compilation do not create database tables.
- Migration support is different from query/runtime support.
- Transactions are explicit; closing the console does not save pending work.
- Row policies and model metadata are not a complete authorization system.
- Direct SQL, including
sql_insert, bypasses Python write hooks. - SQLite and PostgreSQL have different locking and schema behavior.
Asqueel 0.6.0 on PyPI · Migration 0.3.1 on PyPI · Data-file import documentation