| Crates.io | reinhardt-db |
| lib.rs | reinhardt-db |
| version | 0.1.0-alpha.1 |
| created_at | 2026-01-23 05:17:09.644943+00 |
| updated_at | 2026-01-23 05:17:09.644943+00 |
| description | Django-style database layer for Reinhardt framework |
| homepage | |
| repository | https://github.com/kent8192/reinhardt-rs |
| max_upload_size | |
| id | 2063491 |
| size | 3,716,787 |
Django-style database layer for Reinhardt framework
reinhardt-db provides a comprehensive database layer for Reinhardt applications, inspired by Django's ORM with powerful features for database abstraction, object-relational mapping, migrations, and connection pooling.
This crate provides a comprehensive database layer organized into multiple modules to deliver a unified database experience.
This crate provides the following modules:
ORM: Object-Relational Mapping system
Migrations: Schema migration system
MigrationStateLoader): Django-style state reconstruction
ProjectState by replaying migration historyPool: Connection pool management
Hybrid: Hybrid database support
Associations: Relationship management
Advanced Query Optimization
Enhanced Transaction Management
Database Replication and Routing
The reinhardt-db crate is organized into three logical layers:
High-level APIs for everyday database operations:
orm module: High-level ORM API
migrations module: Schema migration system
Low-level database connectivity and connection management:
backends module: Low-level database drivers
pool module: Connection pooling implementation
backends_pool module: Pool backend abstractions for DI
Key difference: Use pool module for direct pool management. Use backends_pool module when integrating with dependency injection systems.
Advanced features for specific use cases:
associations module: Relationship management
hybrid module: Hybrid properties
contenttypes module: Generic relations
nosql module: NoSQL database support
Add this to your Cargo.toml:
[dependencies]
reinhardt-db = "0.1.0-alpha.1"
Enable specific features based on your needs:
[dependencies]
reinhardt-db = { version = "0.1.0-alpha.1", features = ["postgres", "orm", "migrations"] }
Available features:
database (default): Low-level database layerbackends (default): Backend implementationspool (default): Connection poolingorm (default): ORM functionalitymigrations (default): Migration systemhybrid (default): Multi-database supportassociations (default): Relationship managementpostgres: PostgreSQL supportsqlite: SQLite supportmysql: MySQL supportall-databases: All database backendsuse reinhardt::prelude::*;
use serde::{Serialize, Deserialize};
use chrono::{DateTime, Utc};
#[derive(Serialize, Deserialize)]
#[model(app_label = "myapp", table_name = "users")]
pub struct User {
/// Primary key
#[field(primary_key = true)]
pub id: i64,
/// Username (max 50 characters, unique)
#[field(max_length = 50, unique = true)]
pub username: String,
/// Email address (max 254 characters)
#[field(max_length = 254)]
pub email: String,
/// User's age
pub age: i32,
/// Account creation timestamp (auto-populated on insert)
#[field(auto_now_add = true)]
pub created_at: DateTime<Utc>,
/// Last update timestamp (auto-updated on save)
#[field(auto_now = true)]
pub updated_at: DateTime<Utc>,
}
Field Attributes:
#[field(primary_key = true)] - Primary key#[field(max_length = N)] - Maximum length for strings#[field(unique = true)] - Unique constraint#[field(auto_now_add = true)] - Auto-populate on creation#[field(auto_now = true)] - Auto-update on save#[field(null = true)] - Allow NULL values#[field(default = value)] - Default value#[field(foreign_key = "ModelType")] - Foreign key relationshipFor a complete list of field attributes, see the Field Attributes Guide.
Note: The #[model(...)] attribute macro automatically generates:
Model trait implementationUser::field_username(), User::field_email(), etc.)use reinhardt::db::{QuerySet, Model};
// Get all users
let users = User::objects().all().await?;
// Filter users
let adults = User::objects()
.filter("age__gte", 18)
.order_by("-created_at")
.all()
.await?;
// Get a single user
let user = User::objects()
.filter("username", "john")
.first()
.await?;
use reinhardt::db::{Migration, CreateModel, AddField};
// Create a new migration
let migration = Migration::new("0001_initial")
.add_operation(CreateModel {
name: "User",
fields: vec![
("id", "AutoField"),
("username", "CharField(max_length=50)"),
("email", "EmailField"),
],
});
// Apply migration
migration.apply(db).await?;
use reinhardt::db::Pool;
// Create a connection pool
let pool = Pool::new("postgres://user:pass@localhost/db")
.max_connections(10)
.build()
.await?;
// Get a connection
let conn = pool.get().await?;
`reinhardt-db` is organized into the following modules:
`orm` - Object-Relational Mapping system`migrations` - Schema migration system`pool` - Connection pooling`backends` - Database drivers (PostgreSQL, MySQL, SQLite)`backends-pool` - DI-aware pool abstractions`associations` - Relationship management (ForeignKey, ManyToMany, etc.)`hybrid` - Hybrid properties and multi-database support`contenttypes` - Generic relations (polymorphic)`nosql` - NoSQL database support (MongoDB)use reinhardt::db::orm::{Model, QuerySet};
use reinhardt::db::migrations::Migration;
use reinhardt::db::pool::ConnectionPool;
Database-related tests require Docker for TestContainers integration:
# Verify Docker is running
docker version
docker ps
CRITICAL: This project uses Docker for TestContainers integration, NOT Podman.
DOCKER_HOST environment variable points to Docker socket:
unix:///var/run/docker.sock or not setunix:///.../podman/... (will cause container startup failures)If both Docker and Podman are installed:
.testcontainers.properties to force Docker usage (already configured in project root)DOCKER_HOST is not set to Podman socket# Run all database tests (requires Docker)
cargo test --package reinhardt-db --all-features
# Run tests for specific module
cargo test --package reinhardt-orm --all-features
cargo test --package reinhardt-migrations --all-features
# Run with PostgreSQL container (TestContainers automatically starts PostgreSQL)
cargo test --package reinhardt-orm --test orm_integration_tests
Database tests automatically use TestContainers to:
Standard Fixtures from reinhardt-test are available:
use reinhardt::test::fixtures::postgres_container;
use rstest::*;
#[rstest]
#[tokio::test]
async fn test_with_database(
#[future] postgres_container: (ContainerAsync<GenericImage>, Arc<PgPool>, u16, String),
) {
let (_container, pool, _port, _database_url) = postgres_container.await;
// Use pool for database operations
let result = sqlx::query("SELECT 1").fetch_one(pool.as_ref()).await;
assert!(result.is_ok());
// Container is automatically cleaned up when dropped
}
For comprehensive testing standards, see:
"Cannot connect to Docker daemon" or "IncompleteMessage" errors:
# 1. Check Docker is running
docker ps
# 2. Check DOCKER_HOST environment variable
echo $DOCKER_HOST
# 3. If DOCKER_HOST points to Podman, unset it
unset DOCKER_HOST
# 4. Verify .testcontainers.properties exists in project root
cat .testcontainers.properties
AssociationProxy<S, A, T>)new(): Create a new association proxy with custom getter functionsget(): Retrieve the target attribute through the associationAssociationCollection<S, C, T>)new(): Create a new association collection proxy with custom getter functionsget_all(): Get all target attributes from the collectioncount(): Count the number of items in the collectionis_empty(): Check if the collection is emptyForeignKey - Many-to-one relationships with cascade actions
OneToOne - Unique one-to-one relationships
OneToMany - One-to-many relationships (reverse side of ForeignKey)
ManyToMany - Many-to-many relationships through junction tables
PolymorphicAssociation - Polymorphic one-to-many relationships
PolymorphicManyToMany - Polymorphic many-to-many relationships
Define behavior when parent objects are deleted:
Optimize how related objects are loaded:
LazyLoader - Load related objects only when accessed (default)
EagerLoader - Load related objects immediately with parent
SelectInLoader - Use SELECT IN strategy for collections
JoinedLoader - Use SQL JOIN for single query loading
SubqueryLoader - Use subquery for complex filtering
Automatic reverse accessor generation - Related models get automatic reverse accessors
Custom naming - Override default reverse accessor names with related_name
Singular forms - Generate singular accessor names for one-to-one relationships
ContentType::new() - Create a new content typeContentType::with_id() - Set content type IDnatural_key() - Get (app_label, model) tuple for natural keyqualified_name() - Get fully qualified name (e.g., "blog.Post")Serialize, Deserialize, PartialEq, Eq, Hash, Cloneregister() - Register a new content type with automatic ID assignmentget() - Get content type by app label and model nameget_by_id() - Get content type by IDget_or_create() - Get existing or create new content typeall() - List all registered content typesclear() - Clear registry (mainly for testing)RwLock for concurrent accessonce_cell::Lazy for initializationnew() - Create empty generic foreign keyset() - Set content type and object IDget_content_type() - Retrieve associated content typeis_set() - Check if both content type and object ID are setclear() - Clear content type and object IDDefault, Serialize, Deserialize, CloneAPP_LABEL - Associated constant for app labelMODEL_NAME - Associated constant for model nameContentTypeRegistry:
get_typed<M: ModelType>() - Type-safe getget_or_create_typed<M: ModelType>() - Type-safe get or createregister_typed<M: ModelType>() - Type-safe registerGenericForeignKey:
set_typed<M: ModelType>() - Type-safe set with model typeGenericRelatable Trait - Trait for models that can be targets of generic relations
get_content_type() - Get content type for the modelget_object_id() - Get object ID for the instanceGenericRelationQuery - Helper for building generic relation queries
new() - Create query for specific content typeadd_object() - Add object ID to queryto_sql() - Generate SQL query for fetching related objectsContentTypePersistence - Database-backed content type storage
new() - Create persistence backend with database URLfrom_pool() - Create from existing connection poolcreate_table() - Automatic table creation with indexesget(), get_by_id() - Retrieve content types from databaseget_or_create() - Get existing or create new content type in databasesave(), delete() - Persist and remove content typesload_all() - Load all content types from databaseexists() - Check content type existenceMulti-Database Support
MultiDbContentTypeManager - Manage content types across multiple databasesadd_database() - Register new database connectionssearch_all_databases() - Find content types across all databaseslist_databases() - Get all registered database namesGenericForeignKey Constraints
validate_content_type() - Verify content type exists in databaseget_validated_content_type() - Retrieve validated content type from databaseContentTypeQuery - ORM-style query builder for content types
new() - Create query builder from connection poolfilter_app_label(), filter_model(), filter_id() - Filter by fieldsorder_by_app_label(), order_by_model(), order_by_id() - Sortingorder_by_*_desc() - Descending order variantslimit(), offset() - Pagination supportall() - Execute query and get all resultsfirst() - Get first resultcount() - Count matching recordsexists() - Check if any records matchContentTypeTransaction - Transaction-aware content type operations
new() - Create transaction context
query() - Get query builder for transaction
create() - Create content type within transaction
delete() - Delete content type within transaction
Full ACID transaction support for content type operations
HybridProperty::new() - Create a property with instance-level behaviorget() - Get the value for an instancewith_expression() - Add SQL expression generation capabilityexpression() - Get the SQL expression stringHybridProperty<T, R>HybridMethod::new() - Create a method with instance-level behaviorcall() - Call the method for an instance with argumentswith_expression() - Add SQL expression generation capabilityexpression() - Get the SQL expression string with argumentsHybridMethod<T, A, R>new() - Create a SQL expression from a stringconcat() - Generate CONCAT expressionslower() - Generate LOWER expressions for case-insensitive operationsupper() - Generate UPPER expressions for case-insensitive operationscoalesce() - Generate COALESCE expressions for NULL handlingSqlExpression, String, and &strto_sql() - Convert to SQL string representationnew() - Create a comparator with an expressioneq(), ne() - Equality and inequality comparisonslt(), le(), gt(), ge() - Ordering comparisonsget_instance() - Get instance-level valueget_expression() - Get SQL expression (optional)set_instance() - Set instance-level value (optional)new() - Create an overridable property with custom implementationget(), set() - Instance-level getters and settersexpression() - SQL expression supporthybrid_property! macro: Convenience macro for defining hybrid properties
Migration Operations: Comprehensive set of operations for schema changes
CreateModel, DeleteModel, RenameModelAddField, RemoveField, AlterField, RenameFieldRunSQL, RunCode (Rust equivalent of Django's RunPython)CreateExtension, DropExtension, CreateCollationState Management: Track schema state across migrations
ProjectState: Maintains complete database schema stateModelState: Represents individual model definitionsFieldState: Tracks field configurationsAutodetection: Automatically detect schema changes
MigrationAutodetector: Detects differences between statesMigration Execution
MigrationExecutor: Apply migrations to SQLite databasesDatabaseMigrationExecutor: Multi-database support (PostgreSQL, MySQL, SQLite)Migration Management
MigrationLoader: Load migrations from diskMigrationWriter: Generate Rust migration filesCLI Commands
makemigrations: Generate migrations from model changes
migrate: Apply migrations to database
Migration State Management
MigrationStateLoader: Django-style state reconstruction from migration history
ProjectState by replaying applied migrations in topological orderDatabase Backend Support
Dependency Injection Integration
MigrationService: DI-compatible service for migrationsMigrationConfig: Configuration managementInteractive Mode: Guided migration creation
Conflict Resolution: Automatic handling of migration conflicts
Migration Testing: Built-in tools for testing migrations
Performance Profiling: Measure migration execution time and identify bottlenecks
Document Databases: MongoDB (✅), CouchDB (planned)
Key-Value Stores: Redis (planned), DynamoDB (planned)
Column-Family Stores: Cassandra (planned)
Graph Databases: Neo4j (planned)
Zero-Cost Abstractions: Uses generics to minimize runtime overhead
Type-Safe API: Compile-time guarantees for database operations
Transaction Support: Multi-document ACID transactions (MongoDB with replica set)
ConnectionPool::new_postgres() - Create PostgreSQL connection poolConnectionPool::new_mysql() - Create MySQL connection poolConnectionPool::new_sqlite() - Create SQLite connection poolmax_connections - Maximum number of connectionsmin_connections - Minimum idle connections to maintainmax_size - Overall pool size limitmin_idle - Optional minimum idle connectionsconnection_timeout - Timeout for creating new connectionsacquire_timeout - Timeout for acquiring from poolidle_timeout - Optional timeout for idle connectionsmax_lifetime - Optional maximum connection lifetimetest_before_acquire - Validate connections before usePoolOptions for ergonomic configuration with method chainingConnectionAcquired - Connection checked out from poolConnectionReturned - Connection returned to poolConnectionCreated - New connection establishedConnectionClosed - Connection terminatedConnectionTestFailed - Health check failureConnectionInvalidated - Hard invalidation (connection unusable)ConnectionSoftInvalidated - Soft invalidation (can complete current operation)ConnectionReset - Connection resetPoolEventListener traitEventLogger for simple event logginginvalidate() - connection immediately unusablesoft_invalidate() - can complete current operationreset()PoolManager for managing multiple named pools
add_pool() - Register a named poolget_pool() - Retrieve pool by name with type safetyremove_pool() - Unregister a poolDatabaseService for DI frameworksDatabaseUrl wrapper for type-safe URLsMySqlPool, PostgresPool, SqlitePool typesPoolClosed - Pool has been closedTimeout - Operation timeoutPoolExhausted - Max connections reachedInvalidConnection - Connection validation failedDatabase - sqlx database errorsConfig - Configuration validation errorsConnection - Connection-specific errorsPoolNotFound - Named pool not foundPoolResult<T> type aliasLicensed under either of Apache License, Version 2.0 or MIT license at your option.