Database¶
- class nextorm.database.Database[source]¶
Bases:
objectOwns a provider binding, a persistent connection, and entity schema.
The database keeps a single open connection so that in-memory SQLite databases (
":memory:") remain accessible across multiple operations.Call
close()(or use the database as a context manager) to release the connection when done.Parameters¶
- entities:
Explicit list of entity classes to include. When omitted, all
Entitysubclasses registered via_entity_registryare used.
- register(*entity_classes)[source]¶
Add one or more entity classes to this database’s scope.
Entities register themselves globally at import time; call this method to opt specific classes into a database that was constructed with an explicit
entities=[...]list, or to add entities after construction.Calling
register()with an entity that is already registered is a no-op. Each argument must be anEntitysubclass — passing anything else raisesTypeError.Example:
db = Database(entities=[User]) db.register(Post, Comment) # add more after the fact db.bind("sqlite", ":memory:") db.generate_mapping(create_tables=True)
- property entities: dict[str, type[Entity]]¶
Return
{entity_name: entity_class}for all entities in this DB.
- bind(provider, *args, pool_min=0, pool_max=1, pool_timeout=30.0, **kwargs)[source]¶
Bind the database to a named provider.
Parameters¶
- provider:
Registered provider name (
"sqlite","postgres","mariadb").- *args / **kwargs:
Connection arguments forwarded to the provider (e.g. the database path for SQLite, the DSN for PostgreSQL).
- pool_min:
Minimum (pre-created) pool connections.
0means no connections are opened until the first query.- pool_max:
Maximum pool size.
1(the default) keeps the legacy single-persistent-connection behaviour. Values> 1enable true pooling — each operation checks out a connection from the pool and returns it afterwards.- pool_timeout:
Seconds to wait for a free connection before
PoolTimeoutErroris raised.
- close()[source]¶
Close the persistent connection (if open) or all pool connections.
- Return type:
None
- commit()[source]¶
Flush pending changes then commit the current database transaction.
Calls
flush()first so all pending inserts/updates are written, then finalises the underlying connection’s transaction. This mirrors PonyORM’s approach wherecommit()integrates the flush step internally — callers never need to flush manually before committing.- Return type:
None
- rollback()[source]¶
Roll back the current database transaction and clear the session cache.
Discards uncommitted work on the active connection and wipes the identity map of the current
db_session(). When called outside a session the cache-clear step is a no-op.- Return type:
None
- flush()[source]¶
Write all pending dirty and new objects in the current session to the DB.
Iterates the current
db_session()cache and callssave()on every object that has been scheduled for INSERT or marked dirty that belongs to this database. Because NextORM auto-commits per DML statement, eachsaveis independently committed.When called outside a session this is a no-op.
- Return type:
None
- generate_mapping(*, create_tables=False, validate_relations=False)[source]¶
Build the internal schema and optionally create database tables.
Must be called after
bind(). Registers this database instance so that_find_db_for_entity()can locate it.Parameters¶
- create_tables:
When
True, executeCREATE TABLEDDL for every entity in the schema. The connection is kept open so that in-memory SQLite databases (":memory:") remain accessible after the call.- validate_relations:
When
True, every declaredSet[T]relation is checked to have a matchingSingle[T]back-reference on the target entity. Ambiguous cases (multiple candidates with noreverse=) raiseMappingError.
Example:
db = Database(entities=[User, Post]) db.bind("sqlite", ":memory:") db.generate_mapping(create_tables=True)
- property schema: dict[str, Table]¶
Current schema mapping (empty until
generate_mapping()is called).
- migrate()[source]¶
Apply pending schema changes to the live database.
Introspects the current database schema, computes the diff against the entity-derived target schema (built by
generate_mapping()), and executes each pending DDL operation (CREATE TABLE,ALTER TABLE … ADD/DROP COLUMN,CREATE/DROP INDEX, etc.).Returns the list of SQL statements that were executed. An empty list means the database is already up to date.
Raises
RuntimeErrorif the database is not bound to a provider or ifgenerate_mapping()has not been called yet.
- get_ddl()[source]¶
DDL statements from the last
generate_mapping()call.
- select(entity_class)[source]¶
Return a
QuerySetfor entity_class.generate_mapping()must have been called first.
- save(entity)[source]¶
Insert or update entity in the database.
All PK columns are
None→ INSERT (auto-PK written back when single auto PK).At least one PK is set → UPDATE all non-PK columns.
Lifecycle hooks are called around each operation. When a
db_session()is active the entity is registered in its identity map after a successful save.- Parameters:
entity (Entity)
- Return type:
None
- insert(entity)[source]¶
Always INSERT entity, even when its primary key is already set.
Unlike
save(), which uses the PK value to choose between INSERT and UPDATE, this method always performs an INSERT. Use it for:Entities with user-assigned (non-auto) primary keys.
Data loading / migration where you know the row does not yet exist.
Inserting a copy of an entity with a freshly assigned identity.
When the PK is auto-generated (
FieldSpec(primary_key=True, auto=True)):PK is
None→ the database generates one, which is written back.PK is a concrete value → that value is passed in the INSERT, overriding the auto-increment counter (useful for data migration).
Lifecycle hooks
before_insert/after_insertare called.- Parameters:
entity (Entity)
- Return type:
None
- delete_instance(entity)[source]¶
Delete entity from the database and clear its primary key.
Raises
ValueErrorwhen the entity has not been saved (PK isNone).- Parameters:
entity (Entity)
- Return type:
None
- get_connection()[source]¶
Return the raw underlying DBAPI connection.
Use this as an escape hatch when you need provider-specific features not covered by the NextORM API. The returned type depends on the active provider (e.g.
sqlite3.Connectionfor SQLite).Raises
RuntimeErrorwhen the database is not connected.- Return type:
- execute(sql, *args)[source]¶
Execute arbitrary SQL and return the number of affected rows.
args are passed as positional parameters to the DBAPI cursor (i.e. bound as
?or%splaceholders depending on the provider).This is useful for DDL statements or DML that cannot be expressed via the QuerySet API:
db.execute("CREATE INDEX idx_user_email ON user (email)") db.execute("DELETE FROM session WHERE expires_at < ?", cutoff)
- select_raw(sql, *args)[source]¶
Execute a raw SELECT and return the results as a list of dicts.
Column names are taken from the cursor description. Use this when you need a join result or aggregate that doesn’t map to a single entity class:
rows = db.select_raw( "SELECT u.name, COUNT(o.id) AS order_count " 'FROM user u LEFT JOIN "order" o ON o.user_id = u.id ' "GROUP BY u.id" ) for row in rows: print(row["name"], row["order_count"])
- property last_sql: str¶
The last SQL string sent to the database.
Updated after every
_execute,_execute_dml, and_execute_insertcall. Empty string if no query has been executed yet. Useful for debugging:db.select(User).filter(User.age > 18).fetch_all() print(db.last_sql)
- property local_stats: dict[str, QueryStat]¶
Per-database query statistics since the last
clear_local_stats()call.Returns a snapshot copy keyed by SQL string. Each value is a
QueryStatwithcount,sum_time,min_time,max_time, andavg_timeattributes.
- merge_local_stats()[source]¶
Merge per-database stats into the module-level
global_stats.Call this periodically (e.g. at the end of a request) to accumulate statistics across multiple
Databaseinstances.- Return type:
None
Public API summary
|
Bind the database to a named provider. |
Close the connection and clear the provider binding. |
|
Add one or more entity classes to this database's scope. |
|
Build the internal schema and optionally create database tables. |
|
|
Return a |
|
Insert or update entity in the database. |
|
Always INSERT entity, even when its primary key is already set. |
Delete entity from the database and clear its primary key. |
|
Flush pending changes then commit the current database transaction. |
|
Roll back the current database transaction and clear the session cache. |
|
Write all pending dirty and new objects in the current session to the DB. |
|
|
Execute arbitrary SQL and return the number of affected rows. |
|
Execute a raw SELECT and return the results as a list of dicts. |
DDL statements from the last |
|
Apply pending schema changes to the live database. |
|
Close the persistent connection (if open) or all pool connections. |
|
Current schema mapping (empty until |
|
Return |
|
The last SQL string sent to the database. |
|
Per-database query statistics since the last |
|
Reset per-database query statistics. |
|
Merge per-database stats into the module-level |
|
Return the raw underlying DBAPI connection. |