diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 9289b03..2d9cef6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,23 +20,32 @@ maturin develop # compile Rust + install in dev mode
```
### Run Tests
-
+
```bash
# Rust unit tests (no DB needed)
cargo test
-
+
# Python unit tests (no DB needed)
python test.py
-
+
# Integration tests (SQLite)
python test.py --integration
-
+
# All tests
python test.py --all
```
-
+
+### Run Benchmarks
+
+To measure the performance of the query compiler:
+
+```bash
+cd ryx-query && cargo bench
+```
+
### Type Check
+
```bash
mypy ryx/
```
diff --git a/README.md b/README.md
index 25722f0..20e5791 100644
--- a/README.md
+++ b/README.md
@@ -75,10 +75,20 @@ async with ryx.transaction():
| **Backends** | All | All | **PG · MySQL · SQLite** |
| **Migrations** | Built-in | Alembic | **Built-in** |
-## Performance
+## Architecture
+
+
+
+
+
+Your Python queries are compiled to SQL in Rust, executed by sqlx, and decoded back — all without blocking the Python event loop.
+Since v0.1.3, the query engine has been extracted into a standalone crate `ryx-query`. This decouples the SQL compilation logic from the PyO3 bindings, enabling extreme performance and independent testing.
+
+## Performance
+
Benchmark of 1 000 rows on SQLite (lower is better):
-
+
| Operation | Ryx ORM | SQLAlchemy ORM | SQLAlchemy Core | Ryx raw |
|-----------|--------:|---------------:|----------------:|--------:|
| **bulk_create** | 0.0074 s | 0.1696 s | 0.0022 s | 0.0011 s |
@@ -86,59 +96,13 @@ Benchmark of 1 000 rows on SQLite (lower is better):
| **bulk_delete** | 0.0005 s | 0.0012 s | 0.0009 s | 0.0004 s |
| **filter + order + limit** | 0.0009 s | 0.0019 s | 0.0008 s | 0.0004 s |
| **aggregate** | 0.0002 s | 0.0015 s | 0.0005 s | 0.0001 s |
-
+
Ryx ORM is **16× faster** than SQLAlchemy ORM on bulk inserts and **2× faster** on deletes — while keeping the same Django-style API. The raw SQL layer (`raw_execute` / `raw_fetch`) gives you near-C speed when you need it.
+**Internal Compilation Speed**: Our query compiler is blindingly fast, with simple lookups compiled in **~248ns** and complex query trees in **~1µs**.
+
Run the benchmark yourself:
-```bash
-uv add sqlalchemy[asyncio] aiosqlite
-uv run python examples/13_benchmark_sqlalchemy.py
-```
-
-## Quick Start
-
-```bash
-pip install maturin
-maturin develop # compile Rust + install
-```
-
-```python
-import asyncio, ryx
-from ryx import Model, CharField
-
-class Article(Model):
- title = CharField(max_length=200)
-
-async def main():
- await ryx.setup("sqlite:///app.db")
- await ryx.migrate([Article])
- await Article.objects.create(title="Hello Ryx")
- print(await Article.objects.all())
-
-asyncio.run(main())
-```
-
-## Key Features
-
-- **30+ field types** — from `AutoField` to `JSONField`, with validation built in
-- **Q objects** — complex `AND` / `OR` / `NOT` expressions with nesting
-- **Aggregations** — `Count`, `Sum`, `Avg`, `Min`, `Max` with `GROUP BY` and `HAVING`
-- **Relationships** — `ForeignKey`, `OneToOneField`, `ManyToManyField` with `select_related` / `prefetch_related`
-- **Transactions** — async context managers with nested savepoints
-- **Signals** — `pre_save`, `post_save`, `pre_delete`, `post_delete` and more
-- **Migrations** — autodetect schema changes, generate and apply
-- **Validation** — field-level + model-level, collects all errors before raising
-- **Sync/async bridge** — use from sync or async code seamlessly
-- **CLI** — `python -m ryx migrate`, `makemigrations`, `shell`, `inspectdb`
-
-## Architecture
-
-
-
-
-
-Your Python queries are compiled to SQL in Rust, executed by sqlx, and decoded back — all without blocking the Python event loop.
## Documentation
diff --git a/docs/doc/internals/architecture.mdx b/docs/doc/internals/architecture.mdx
index a2d2471..0a8e9c2 100644
--- a/docs/doc/internals/architecture.mdx
+++ b/docs/doc/internals/architecture.mdx
@@ -7,7 +7,7 @@ sidebar_position: 2
Ryx is built in three layers, each with a clear responsibility.
## Layer Diagram
-
+
```
┌──────────────────────────────────────────────────────────┐
│ Python Layer (ryx/) │
@@ -17,8 +17,11 @@ Ryx is built in three layers, each with a clear responsibility.
│ PyO3 Boundary (src/lib.rs) │
│ QueryBuilder · TransactionHandle · Type Bridge · Async │
├──────────────────────────────────────────────────────────┤
-│ Rust Core (src/) │
-│ AST · Q-Trees · SQL Compiler · Executor · Pool · Tx │
+│ Modular Query Engine (ryx-query crate) │
+│ AST · Q-Trees · SQL Compiler · Lookup Registry │
+├──────────────────────────────────────────────────────────┤
+│ Rust Core (src/) │
+│ Executor · Pool · Transaction Logic │
├──────────────────────────────────────────────────────────┤
│ sqlx 0.8.6 + tokio 1.40 │
│ AnyPool · Async Drivers · Transactions │
@@ -27,6 +30,7 @@ Ryx is built in three layers, each with a clear responsibility.
└──────────────────────────────────────────────────────────┘
```
+
## Query Execution Flow
```
diff --git a/docs/doc/internals/query-compiler.mdx b/docs/doc/internals/query-compiler.mdx
index 8905064..2c86595 100644
--- a/docs/doc/internals/query-compiler.mdx
+++ b/docs/doc/internals/query-compiler.mdx
@@ -3,11 +3,13 @@ sidebar_position: 4
---
# Query Compiler
+
+The heart of Ryx — transforms Python query expressions into optimized SQL.
-The heart of Ryx — transforms Python query expressions into optimized SQL.
-
+Since v0.1.3, the compiler resides in the standalone `ryx-query` crate, decoupled from the Python bindings for maximum performance and testability.
+
## Pipeline
-
+
```
Python QuerySet methods
│
@@ -15,26 +17,27 @@ Python QuerySet methods
QueryNode (Rust AST)
│
▼
-compiler::compile()
+ryx_query::compiler::compile()
│
▼
CompiledQuery { sql: String, values: Vec }
```
-
+
## AST Types
-
+
### QueryNode
-
+
The root of every query:
-
+
```rust
pub struct QueryNode {
- pub operation: QueryOperation, // Select, Aggregate, Count, Delete, Update, Insert
pub table: String,
- pub columns: Vec,
+ pub backend: Backend, // DB backend for SQL generation
+ pub operation: QueryOperation, // Select, Aggregate, Count, Delete, Update, Insert
pub filters: Vec,
- pub q_tree: Option,
+ pub q_filter: Option,
pub joins: Vec,
+ pub annotations: Vec,
pub group_by: Vec,
pub having: Vec,
pub order_by: Vec,
@@ -43,20 +46,20 @@ pub struct QueryNode {
pub distinct: bool,
}
```
-
+
### QNode — Boolean Expression Tree
-
+
```rust
pub enum QNode {
Leaf { field: String, lookup: String, value: SqlValue, negated: bool },
- And { left: Box, right: Box },
- Or { left: Box, right: Box },
- Not { inner: Box },
+ And(Vec),
+ Or(Vec),
+ Not(Box),
}
```
-
+
### SqlValue — Type-Safe Values
-
+
```rust
pub enum SqlValue {
Null,
@@ -64,27 +67,25 @@ pub enum SqlValue {
Int(i64),
Float(f64),
Text(String),
- Bytes(Vec),
- Date(chrono::NaiveDate),
- Time(chrono::NaiveTime),
- DateTime(chrono::NaiveDateTime),
- Json(serde_json::Value),
+ List(Vec),
}
```
-
+
### JoinClause
-
+
```rust
-pub enum JoinKind { Inner, LeftOuter, RightOuter, FullOuter, Cross }
-
+pub enum JoinKind { Inner, LeftOuter, RightOuter, FullOuter, CrossJoin }
+
pub struct JoinClause {
- pub table: String,
- pub condition: String,
pub kind: JoinKind,
+ pub table: String,
pub alias: Option,
+ pub on_left: String,
+ pub on_right: String,
}
```
+
## Compilation Process
1. **SELECT clause** — `columns` or `*`