| Crates.io | mik-sql |
| lib.rs | mik-sql |
| version | 0.1.2 |
| created_at | 2025-12-28 07:43:32.537978+00 |
| updated_at | 2026-01-02 21:39:55.229969+00 |
| description | SQL query builder with Mongo-style filters - sql_read!, sql_create!, sql_update!, sql_delete! |
| homepage | |
| repository | https://github.com/dufeut/mik-sdk |
| max_upload_size | |
| id | 2008347 |
| size | 391,911 |
SQL query builder with Mongo-style filter operators and cursor pagination.
v0.1.x - Published and usable, but evolving. The API may change between minor versions.
$eq, $in, $between, $like, etc.$1) and SQLite (?1)use mik_sql::prelude::*;
// SELECT with filters
let (sql, params) = sql_read!(users {
select: [id, name, email],
filter: { active: true, role: "admin" },
order: name,
limit: 10,
});
// → "SELECT id, name, email FROM users WHERE active = $1 AND role = $2 ORDER BY name LIMIT 10"
// INSERT with returning
let (sql, params) = sql_create!(users {
name: str(name),
email: str(email),
returning: [id],
});
// → "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id"
// UPDATE with filter
let (sql, params) = sql_update!(users {
set: { name: str(new_name) },
filter: { id: int(user_id) },
});
// → "UPDATE users SET name = $1 WHERE id = $2"
// DELETE with filter
let (sql, params) = sql_delete!(users {
filter: { id: int(user_id) },
});
// → "DELETE FROM users WHERE id = $1"
| Operator | SQL | Example |
|---|---|---|
$eq |
= |
status: { $eq: "active" } |
$ne |
!= |
status: { $ne: "deleted" } |
$gt |
> |
age: { $gt: 18 } |
$gte |
>= |
age: { $gte: 21 } |
$lt |
< |
price: { $lt: 100 } |
$lte |
<= |
price: { $lte: 50 } |
$in |
IN (...) |
status: { $in: ["a", "b"] } |
$nin |
NOT IN |
status: { $nin: ["x"] } |
$like |
LIKE |
name: { $like: "%test%" } |
$ilike |
ILIKE |
name: { $ilike: "%TEST%" } |
$starts_with |
LIKE x || '%' |
name: { $starts_with: "John" } |
$ends_with |
LIKE '%' || x |
email: { $ends_with: "@example.com" } |
$contains |
LIKE '%' || x || '%' |
bio: { $contains: "rust" } |
$between |
BETWEEN |
age: { $between: [18, 65] } |
// AND (implicit)
filter: { active: true, role: "admin" }
// OR
filter: { $or: { status: "pending", status: "review" } }
// NOT
filter: { $not: { deleted: true } }
// Combined
filter: {
$and: {
active: true,
$or: { role: "admin", role: "moderator" }
}
}
use mik_sql::prelude::*;
// Query with cursor
let (sql, params) = sql_read!(posts {
select: [id, title, created_at],
filter: { published: true },
order: [-created_at, -id], // - prefix = DESC
after: req.query("after"), // cursor from query string
limit: 20,
});
// Build cursor for next page
let next_cursor = Cursor::new()
.string("created_at", &last_item.created_at)
.int("id", last_item.id)
.encode();
// → "eyJjcmVhdGVkX2F0IjoiMjAyNS0wMS0xNSIsImlkIjoxMjN9"
Add sqlite as first parameter:
let (sql, params) = sql_read!(sqlite, users {
select: [id, name],
filter: { active: true },
});
// → "SELECT id, name FROM users WHERE active = ?1"
use mik_sql::{postgres, Operator, Value, SortDir};
let result = postgres("users")
.fields(&["id", "name", "email"])
.filter("active", Operator::Eq, Value::Bool(true))
.filter("role", Operator::In, Value::Array(vec![
Value::String("admin".into()),
Value::String("mod".into()),
]))
.sort("created_at", SortDir::Desc)
.limit(20)
.build();
println!("{}", result.sql);
// → SELECT id, name, email FROM users WHERE active = $1 AND role IN ($2, $3) ORDER BY created_at DESC LIMIT 20
Licensed under MIT license. See LICENSE-MIT.