kitx 0.0.15

A lightweight wrapper for database operations based on sqlx, enabling fast CRUD operations.
Documentation
kitx-0.0.15 has been yanked.

πŸ› οΈ Kitx - A Fast CRUD Toolkit Based on Rust's Sqlx

🌐 English | δΈ­ζ–‡

A lightweight CRUD toolkit built on top of sqlx::QueryBuilder

Use it just like you'd use Sqlx β€” flexible, simple, and without extra overhead!
Supports: SQLite, MySQL/MariaDB, and PostgreSQL


🌟 Key Features

  1. Native Sqlx Usage Style
    Core queries are built with a thin wrapper around sqlx::QueryBuilder, ensuring type safety and protection against SQL injection. Easily compose raw SQL fragments for complex query scenarios.

  2. Simplified Entity Model Macros
    Depends only on the FieldAccess trait (besides sqlx). No heavy derive macros needed β€” minimal configuration and boilerplate. Comes with utility functions to parse entity models.

  3. Reduced Field Binding Effort
    Eliminates repetitive .bind(x).bind(y)... calls. Many operations require no manual binding of field values!

  4. Built-in Common Operations
    Provides ready-to-use methods for Insert, Update, Upsert, Delete, Select, including regular pagination and cursor-based pagination β€” covering most real-world use cases.


πŸš€ Why Choose Kitx? See It in Action!

/// Fetch all records β€” So easy?
async fn test_find_all() {
    let qb = Select::<Article>::select_default().from_default().inner();
    
    init_pool().await;
    let list = fetch_all::<Article>(qb).await.unwrap();  
    dbg!(&list);
}
/// Not an ORM, but still very convenient.
/// Note: Foreign key relationships must be handled manually.
async fn test_update_one() {
    let mut entity = Article::new(110, "test_title_", None);
    entity.content = Some("test_content".to_string());
    entity.id = 1;

    let key = PrimaryKey::Single("id", true);
    let qb = Update::one(&entity, &key, true).unwrap();

    init_pool().await;
    let result = execute(qb).await.unwrap(); 
    println!("Updated {} rows.", result.rows_affected());
}
/// Nested subquery example
async fn test_nested_subquery() {
    let avg_views_subquery = Subquery::<Article>::select(|b| {
        b.push("AVG(views)");
    })
    .from_default()
    .where_(|b| {
        b.push("id > ").push_bind(3.into());
    });

    let qb = Select::<Article>::select_default()
        .from_default()
        .where_(move |b| {
            b.push("views < ");
            avg_views_subquery.append_to(b);
        })
        .order_by("id DESC")
        .inner();

    init_pool().await;
    let result = fetch_all::<Article>(qb).await.unwrap();
    dbg!(&result);
}

πŸ“¦ Getting Started

1. Add Dependency

[dependencies]

kitx = "0.0.15"

Or, if you're targeting a specific database (recommended for better compile-time performance):

# For PostgreSQL

kitx = { version = "0.0.15", features = ["postgres"] }



# For MySQL

kitx = { version = "0.0.15", features = ["mysql"] }



# For SQLite

kitx = { version = "0.0.15", features = ["sqlite"] }

All three databases are supported by default, but enabling only the required feature improves compilation speed.


2. Usage Guide

use kitx::prelude::{*, postgres::*};

async fn test_find_all() {
    let qb = Select::<Article>::select_default().from_default().inner();
    
    init_pool().await;
    let list = fetch_all::<Article>(qb).await.unwrap();

    // ...
}

For more examples, check the integration tests under each database-specific module.


πŸ’‘ Note:

Kitx works by breaking down SQL statements into keyword-based segments (e.g., "SELECT {} FROM {} WHERE {}") and using entity model data to auto-fill placeholders. When automatic filling isn't sufficient, you can fall back to manual construction via closures (fn(QueryBuilder)), allowing aliases, joins, nested conditions, etc.

Methods named one or many that operate directly on entity models do not support custom SQL fragments. These require a strict naming convention: the database table name (snake_case) must correspond to the struct name (camelCase).

All methods are thoroughly unit-tested to ensure reliability.


βœ… Simple. Safe. Expressive.
Build powerful database interactions β€” without leaving the comfort of Sqlx.