Repository navigation
Releases: hare-orm/hare-orm
Releases · hare-orm/hare-orm
Release list
hare-orm 0.12.0
Breaking changes
VersionedModel.idandOutboxEvent.idrequire UUID7, including values passed through filters and
relations. Generate these identifiers withUuid7.new; putVersionedModelfirst when combining it
with a base model declaring anidfield.makemigrations --renamerefuses an answer that renames nothing instead of writing a migration
that removes and recreates the object. Correct the names before generating the migration.
Added
UUIDField(version=...)restricts UUID values to the declared version.HareDTOsupportsextra_fields,computedandrelated_values;pydantic_model_creator()supports
extra_fieldsandrelated_values, including declarations on nested related models.- Model-specific
Tenancy.scope(...)works with tenant schemas and row-level security policies. - Migration safety checks report a required field added without a Python or database default.
Fixed
- Subquery membership handles NULL values and wrapped model keys consistently. Filters through
relations bind each subquery's current slice when reusing a plan. Count, existence and set operations
preserve joins and distinct columns introduced by ordering; grouped summaries expand composite keys.
Recursive queries declared before initialization are validated when their calls are replayed. - Composite relation aliases retain key operations, and their null lookups require boolean values.
Existence checks reject inflated aggregates used by HAVING. Explicit bulk update returning is
refused before SQL on databases without RETURNING. - Iterators and cursors preserve duplicate rows, keyless queries, unordered distinct values and
database-specific annotations. Bounds use the stored field representation, including Float32,
enum labels, JSON and explicit NULL ordering around NaN. - Sliced prefetches preserve partial field masks, composite keys, joins, duplicate rows and connection
routing. Nested prefetches keep the required keys on intermediate models selected byonly()and
report missing keys on partial instances withQueryError. - Query annotations remain distinct from similarly named relation paths and internal columns,
including case differences and long identifiers. Grouping, set operations, generic relation types,
negated relation filters,latest()/earliest()andin_bulk()retain their query semantics. RETURNINGreads keyless models and converted keys correctly; old values retain their aliases.
Bulk conflict reporting accounts for prepared defaults, tenant values and encrypted lookup keys.- Generated fields retain their output field's conversion and comparison rules. Window defaults,
duration expressions and literals in write expressions retain their declared field semantics.
Functions unavailable on the selected dialect and JSON aggregates of unsupported nested field types
are refused before SQL. - Tenant scope caches follow live model changes and stay isolated between application contexts.
- Pydantic extra fields and related values respect
includeandexclude, including nested schemas.
Request query declarations accept structurally compatible Meta options without requiring exact types. - Migration serialization preserves import aliases in copied functions, decorators, defaults and
annotations, including lambda scopes. Schema checks preserve distinct Unicode names on SQLite;
tenant migrations retain one-shot target iterables. - Rollback restores write-generated instance state; a cancelled
BEGINcannot leave a reusable
connection in an unfinished transaction. Removing an outbox wakeup's last subscription closes its
listener on the loop that opened it. - Connection setup translates configuration failures; schema drift checks preserve non-PK identity
targets, and generated typing stubs preserve shadowed imports and nested literal types.
hare-orm 0.11.0
Breaking changes
bulk_create(ignore_conflicts=True)returns the objects it inserted, and only they are marked saved;
objects whose keys the database generates needon_conflict=[...].JSONField(field_type=...), YAML configuration files andFaker()need thepydantic,yamland
fakerextras.- A transaction of
postgresql+asyncpgrefuses a statement from another event loop, and an in-memory
SQLite database refuses another event loop - both withConfigurationError. bulk_update()of a sliced queryset, or one ofdistinct(*fields), raisesQueryError, asupdate()
does; it wrote objects outside the slice.- A constraint or index condition, a policy or a
GeneratedFieldreading a related model is refused when
the model is bound (ConfigurationError), not by its migration. - A
FloatFieldfilter byNaNon SQLite raisesValidationError- SQLite bound it asNULL.
Added
- Outbox:
ChangeCapture(extend_many=...)andChangeCapture.replace(),OutboxEvent.enqueue_many(),
topic patterns andexclude_topicsofOutboxRelay,WebhookDeliveryof subscribers (target,
allows_url,result_field,signature_header). - A
Qas a value inannotate(),alias(),values(),values_list()andupdate()(ConditionValue). - The pytest plugin's
hare_app_dbandhare_app_transactional_dbfor the application under test. VersionedModel.get_last_visible_version_or_exception(),Uuid7,ClickhouseRequestQuery,
Field.get_json_value(),prefetch_related(None).
Changed
- The ids of
VersionedModelandOutboxEventare version 7 UUIDs;ListenNotifyWakeupsends oneNOTIFY
per topic and transaction; a PostgreSQL test database is dropped with its sessions.
Fixed
- Migrations of outbox models, of a parameterized
field_typeand of an expression index over a foreign
key;makemigrationswithoutasyncpg; the change events of every field type; the pure wheel; the
validators of aUUIDFieldgiven text; the JSON of a pydantic schema with NaN or infinity; the count,
exists()and offset page of a request query that prefetches,Exists()of a queryset that prefetches. - ClickHouse: the first
atomic()of a process on a connection withtransactions=true, and
autonomous()with an option, which ran without a transaction; the Keeper migration lock of a database
named with/; the key series of a database named as the prefix of another one, and a test database's
series left in the Keeper; abloom_filterindex written without its argument reported as drift. - Change capture: a write inside an open transaction whose event failed kept its row;
InProcessWakeup
signalled from a thread with an event loop of its own. bulk_create(ignore_conflicts=True)matching rows by a mapping's key order (hstore, jsonb).inspectdband drift: SQLiteDATETIME/DOUBLE/FLOATcolumns and index order; a PostgreSQLIN
check overvarcharand a sequence shared by tables.- A configuration, or a section of it, that isn't a mapping raises
ConfigurationError, notTypeError;
thetransactionsoption of the application integrations is checked.
hare-orm 0.10.0
Breaking changes
DecimalFieldis refused on SQLite.Avg,StdDevandVariancereturn what the database computes (Decimalon PostgreSQL).- Settings written in code are no longer checked.
MEMORY_SQLITE/init_memory_sqlite()areMEMORY_DATABASE/init_memory_database().Ordermoved tohare.sql.order; the dialect API moved one database's SQL and features into its dialect.get_model()takes one"app.Model"label instead of(app_label, model_name).
Added
Meta.api_getterof request queries, rollback of migrations,<Model>Updatesand more types for
mypy andhare stubs,CHECKof enum fields, narrowing checks ofAlterField.- Every API taking a model takes its
"app.Model"label too.
Fixed
- Bugs of writes, queries, migrations, inspectdb and ClickHouse found by an audit and a bug hunt.
hare-orm 0.9.0
The first public release of hare-orm - an async Python ORM for PostgreSQL, SQLite and ClickHouse. It
brings the whole code base over from the project's earlier private development: hare-orm began as a
fork of Tortoise ORM and carries an adapted copy of
PyPika's query builder (see NOTICE), and most of both
has since been rewritten. Every entry below is new in this release.
It runs on CPython 3.12, 3.13 and 3.14, with PostgreSQL 14 and newer, SQLite 3.35.5 and newer and
ClickHouse 25.8 and newer - see Installation.
Wheels with the Rust extension are built for Linux (glibc and musl), macOS and Windows.
Added
- Models -
Modelclasses with typed fields, relations andMetaoptions: foreign keys,
one-to-one and many-to-many relations (through models included), generic relations made of real
foreign keys, composite primary keys everywhere - as foreign-key targets too - and models without
a primary key; validators,db_defaultand generated columns, encrypted fields with blind indexes
and sensitive fields hidden from errors and logs; models built at runtime from a table - see
Field types,
Relations and
Meta options. - Queries - a lazy
QuerySetwith Django-style lookups across relations,Q/Fexpressions,
annotations, aggregation (grouping sets included), window functions,Case/When,
Subquery/Exists/OuterReference, set operations, CTEs and recursive queries over a tree,
keyset pagination,values()/values_list(),select_related()/prefetch_related()with
filters, bulk create and update, upserts,MERGE,select_for_update(), raw SQL through
RawSQLTermand the query builder - and an error instead of an aggregate a to-many JOIN would
silently inflate - see QuerySet methods,
Filters and
Expressions. - Statement plans - a query of a shape seen before runs on the SQL built for the first one,
binding only its own values; repeatedget(), filters, writes and instance saves skip building
SQL altogether - see Query plan cache. - The schema in
Meta- constraints (EXCLUDEincluded), partial and expression indexes,
triggers, views and materialized views, database functions, sequences, row level security
policies, grants, table partitioning and per-database table options, created and changed by
migrations - see Constraints and triggers,
Indexes and
Schema objects. - Behavior declared in
Meta- soft delete with restore, versioned rows, multi-tenancy by column,
by schema or by row level security, optimistic locking, dirty-field tracking and change capture
into a transactional outbox - see Soft delete,
Versioned models and
Multi-tenancy. - Migrations - migrations detected from the changes to the models, written as files or run
without them, squashed, checked for operations that lock a busy table (zero-downtime rules),
compared with the live database (hare drift) and generated from an existing one
(hare inspectdb); thehareCLI with its plugin commands - see
Migrations,
Operations and
CLI. - Connections and transactions - pools with health checks, nested transactions with savepoints,
isolation levels, read-only transactions and statement timeouts,on_commit()/on_rollback()
callbacks, read replicas and routers with read-your-writes, several databases, distributed
transactions by two-phase commit, PgBouncer in transaction mode - see
Transactions and
Multiple databases. - Pluggable dialects - SQLite, PostgreSQL and ClickHouse are dialects built on the public
hare.dialectsAPI a third-party package uses; a database lacking a feature raises a clear error
before any SQL is sent instead of returning a wrong result - see
Dialects and features and
Writing a dialect. - PostgreSQL - a Rust driver (
rust_pg), the default forpostgresql://URLs, decoding rows and
converting values in Rust, and theasyncpgdriver; arrays, ranges, hstore, ltree, network and
native enum types, the GIN/GiST/BRIN/Bloom/Hash/SP-GiST index family, trigram search and
LISTEN/NOTIFY- see PostgreSQL fields and
LISTEN/NOTIFY. - SQLite - through
aiosqlite, with exact decimals, regular expressions and the date, text and
math functions SQLite lacks registered on the connection, attached databases standing for
schemas - see SQLite: what runs differently. - ClickHouse - over HTTP (
clickhouse-connect) and the native protocol (clickhouse-driver):
MergeTree engines and their table options, clusters withDistributedtables, dictionaries,
projections,ARRAY JOIN,ASOF JOIN,LIMIT BYand ClickHouse's own aggregates and types - see
ClickHouse models and
ClickHouse: what runs differently. - Search and geodata - full-text search (PostgreSQL, SQLite FTS5), vector search (pgvector,
sqlite-vec) and GIS (PostGIS, SpatiaLite, ClickHouse geometry types) - see
Full-text search,
Vector search and
GIS. - Integrations - request queries turning HTTP parameters into a validated, paginated query;
Litestar, FastAPI and Robyn integrations; Pydantic schemas of models; a transactional outbox with
Kafka, RabbitMQ, Redis Streams, webhook and taskiq deliveries - see
Request queries,
Web frameworks and
Outbox. - Observability - observers of queries and writes, OpenTelemetry spans and metrics, SQL comment
tags, a repeated-query (N+1) detector and pool health - see
Observers and
OpenTelemetry. - Testing and type checking - a pytest plugin with isolated test databases, factories and
query-count assertions; a mypy plugin rejecting misspelled filters and typing the rows of
values(), and stubs for pyright - see Test setup and
Type checking. - Documentation in English and Russian, and benchmarks against SQLAlchemy, Tortoise ORM,
yara-orm and Django - see Benchmarks.