166 lines
3.9 KiB
Markdown
166 lines
3.9 KiB
Markdown
# sqlx-record Skill
|
|
|
|
Expert guidance for using the sqlx-record Rust library.
|
|
|
|
## Triggers
|
|
- "create entity", "define entity", "entity struct"
|
|
- "sqlx record", "sqlx-record"
|
|
- "crud operations", "database entity"
|
|
- "audit trail", "change tracking"
|
|
- "lookup table", "lookup options"
|
|
|
|
## Overview
|
|
|
|
sqlx-record provides derive macros for automatic CRUD operations and audit trails for SQL entities. It supports MySQL, PostgreSQL, and SQLite.
|
|
|
|
## Quick Reference
|
|
|
|
### Entity Definition
|
|
```rust
|
|
use sqlx_record::prelude::*;
|
|
use sqlx::FromRow;
|
|
|
|
#[derive(Entity, FromRow)]
|
|
#[table_name = "users"]
|
|
struct User {
|
|
#[primary_key]
|
|
id: Uuid,
|
|
|
|
#[rename("user_name")] // Maps to different DB column
|
|
name: String,
|
|
|
|
#[version] // Auto-increment on updates
|
|
version: u32,
|
|
|
|
#[field_type("TEXT")] // SQLx type hint
|
|
bio: Option<String>,
|
|
}
|
|
```
|
|
|
|
### CRUD Operations
|
|
```rust
|
|
// Insert
|
|
let user = User { id: new_uuid(), name: "Alice".into(), version: 0 };
|
|
user.insert(&pool).await?;
|
|
|
|
// Get
|
|
let user = User::get_by_id(&pool, &id).await?;
|
|
let users = User::get_by_ids(&pool, &ids).await?;
|
|
|
|
// Find with filters
|
|
let users = User::find(&pool, filters![("is_active", true)], None).await?;
|
|
let user = User::find_one(&pool, filters![("email", email)], None).await?;
|
|
|
|
// Find with ordering and pagination
|
|
let page = User::find_ordered_with_limit(
|
|
&pool,
|
|
filters![("role", "admin")],
|
|
None,
|
|
vec![("created_at", false)], // DESC
|
|
Some((0, 10)) // offset, limit
|
|
).await?;
|
|
|
|
// Count
|
|
let count = User::count(&pool, filters![("is_active", true)], None).await?;
|
|
|
|
// Update
|
|
User::update_by_id(&pool, &id, User::update_form().with_name("Bob")).await?;
|
|
```
|
|
|
|
### Filter System
|
|
```rust
|
|
// Simple equality
|
|
filters![("field", value)]
|
|
|
|
// Multiple conditions (AND)
|
|
filters![("active", true), ("role", "admin")]
|
|
|
|
// OR conditions
|
|
filter_or![("status", "active"), ("status", "pending")]
|
|
|
|
// Operators
|
|
"age".gt(18) // >
|
|
"age".ge(18) // >=
|
|
"age".lt(65) // <
|
|
"age".le(65) // <=
|
|
"name".eq("Bob") // =
|
|
"name".ne("Bob") // !=
|
|
|
|
// Other filters
|
|
Filter::Like("name", "%alice%".into())
|
|
Filter::In("status", vec!["active".into(), "pending".into()])
|
|
Filter::IsNull("deleted_at")
|
|
Filter::IsNotNull("email")
|
|
```
|
|
|
|
### Lookup Tables
|
|
```rust
|
|
// With database entity
|
|
lookup_table!(OrderStatus, "pending", "shipped", "delivered");
|
|
// Generates: struct OrderStatus, enum OrderStatusCode, constants
|
|
|
|
// Without database entity
|
|
lookup_options!(PaymentMethod, "credit-card", "paypal", "bank-transfer");
|
|
// Generates: enum PaymentMethodCode, struct PaymentMethod (constants only)
|
|
|
|
// Usage
|
|
let status = OrderStatus::PENDING; // "pending"
|
|
let code = OrderStatusCode::try_from("pending")?; // OrderStatusCode::Pending
|
|
```
|
|
|
|
### Time-Ordered UUIDs
|
|
```rust
|
|
let id = new_uuid(); // Timestamp prefix for better indexing
|
|
```
|
|
|
|
## Feature Flags
|
|
|
|
```toml
|
|
[dependencies]
|
|
sqlx-record = { version = "0.2", features = ["mysql", "derive"] }
|
|
# Database: "mysql", "postgres", or "sqlite" (pick one)
|
|
# Optional: "derive", "static-validation"
|
|
```
|
|
|
|
## Advanced Updates (UpdateExpr)
|
|
|
|
```rust
|
|
use sqlx_record::prelude::UpdateExpr;
|
|
|
|
// Arithmetic: score = score + 10
|
|
User::update_by_id(&pool, &id,
|
|
User::update_form().eval_score(UpdateExpr::Add(10.into()))
|
|
).await?;
|
|
|
|
// CASE/WHEN
|
|
User::update_by_id(&pool, &id,
|
|
User::update_form().eval_tier(UpdateExpr::Case {
|
|
branches: vec![("score".gt(100), "gold".into())],
|
|
default: "bronze".into(),
|
|
})
|
|
).await?;
|
|
|
|
// Raw SQL escape hatch
|
|
User::update_by_id(&pool, &id,
|
|
User::update_form().raw("computed", "COALESCE(a, 0) + b")
|
|
).await?;
|
|
```
|
|
|
|
## ConnProvider (Flexible Connections)
|
|
|
|
```rust
|
|
use sqlx_record::ConnProvider;
|
|
|
|
// Borrowed or owned pool connections
|
|
let conn = ConnProvider::Borrowed(&pool);
|
|
let users = User::find(&*conn, filters![], None).await?;
|
|
```
|
|
|
|
## Database Differences
|
|
|
|
| Feature | MySQL | PostgreSQL | SQLite |
|
|
|---------|-------|------------|--------|
|
|
| Placeholder | `?` | `$1, $2` | `?` |
|
|
| Table quote | `` ` `` | `"` | `"` |
|
|
| Index hints | Supported | N/A | N/A |
|