The database layer

A model your application can use.

Asqueel is a Python database layer. A configuration recipe describes tables, relationships and calculated columns. A live `db` object makes that model available to queries and business logic.

Available now: PostgreSQL and SQLite. Coming soon: MySQL and Microsoft SQL Server (MSSQL).

Start with a recipe

The recipe declares the logical structure. Asqueel resolves it into table and column objects. Building those objects does not open a database connection or create tables.

from asqueel import AsqueelDb
from invoicing import Invoicing

db = AsqueelDb(Invoicing)
invoice = db.table('invc.invoice')

Invoicing is the model used throughout the course. It contains customers, products, invoices, invoice rows and notes. Explore the recipe →

Describe a relationship once

A relation belongs to the model. Queries can follow that relation with an @ path. An alias column can give a frequently used path a name.

tbl.aliasColumn(
    'customer_name',
    relation_path='@customer_id.account_name',
)

Now every query on this table can refer to $customer_name. The compiler resolves the relation and generates the join. Follow the relations →

Keep calculations close to the data

A formula column describes a calculated value using SQL. It is queryable by name without adding a stored column.

tbl.formulaColumn(
    'line_total',
    sql_formula='$quantity * $unit_price',
    dtype='N',
)

The course also covers correlated subqueries and aggregations over related rows. These examples use the development API described in the compatibility notes.

Inspect a query before executing it

SQL remains the expression language. Asqueel resolves model references; values are passed separately.

query = invoice.query(
    columns='$inv_number, $customer_name, $total',
    where='$total >= :minimum',
    minimum=100,
    order_by='$inv_number',
)
print(query.sqltext)  # Compile without opening a connection.
rows = query.fetch()  # Execute against the database.

Fetched rows are mutable NamedList objects with access by name or position. Use dict(row) when you need a dictionary. Choose a fetch terminal →

Use the same model for business logic

Table objects expose writes and can carry application behavior. The course follows what happens before and after an insert, update or delete: field triggers, table hooks and relation actions.

Transactions are explicit. db.commit() saves a unit of work. db.rollback() discards it. Understand the write cycle →

Choose the right boundary

Concern Responsibility
Tables, relations, formulas and query expressions Asqueel
Synchronous reads, writes and transaction control Asqueel
Comparing and applying physical schema changes Asqueel Migration
Authentication, requests and application delivery Your application
Rendering a user interface Your UI framework

The model can carry external metadata through grammar extensions. That does not imply a UI renderer or an authorization system. See the full course →