| Crates.io | rust-queries-builder |
| lib.rs | rust-queries-builder |
| version | 1.0.7 |
| created_at | 2025-10-11 20:01:30.342232+00 |
| updated_at | 2025-10-18 14:08:25.542877+00 |
| description | A powerful, type-safe query builder library for Rust that leverages key-paths for SQL-like operations on in-memory collections |
| homepage | |
| repository | https://github.com/codefonsi/rust-queries-builder |
| max_upload_size | |
| id | 1878507 |
| size | 1,334,147 |
A powerful, type-safe query builder library for Rust that leverages key-paths for SQL-like operations on in-memory collections. This library brings the expressiveness of SQL to Rust's collections with compile-time type safety.
🎉 v1.0.0 - Stable Release! Production-ready with all features tested and optimized!
🔐 Universal Lock Support! Works with
std::sync,tokio, andparking_lotlocks (189x lazy speedup) - see lock types guide
🎯 Lock-Aware Queries! SQL syntax on
HashMap<K, Arc<RwLock<V>>>with JOINs and VIEWs - see guide
🎯 v0.5.0 - Extension Trait & Derive Macros! Call
.query()and.lazy_query()directly on containers - see extension guide
⚡ v0.5.0 - Build Optimized! Split into 3 crates - 65% faster builds, 6KB umbrella crate - see build guide
🎨 v0.4.0 - Helper Macros! 12 macros to reduce boilerplate - save 20-45 characters per operation - see macro guide
📦 v0.3.0 - Container Support! Query Vec, HashMap, HashSet, BTreeMap, VecDeque, and more - see container guide
⚡ v0.3.0 - Lazy Evaluation! New
LazyQuerywith deferred execution and early termination - see lazy guide
🚀 v0.2.0 - Performance Optimized! Most operations now work without
Clone- see optimization guide
🔒 Memory Safe! Using
'staticbounds causes 0 memory leaks - verified with tests ✅
💡 New! See how SQL queries map to Rust Query Builder in our SQL Comparison Example - demonstrates 15 SQL patterns side-by-side!
✅ Verified! All query results are exact SQL equivalents - see verification tests (17/17 tests passing)
Clone - details.query() and .lazy_query() directly on containers - details#[derive(QueryBuilder)] - detailsArc<RwLock<T>> and Arc<Mutex<T>> without copying - 5x faster!std::sync, tokio::sync, and parking_lot locksAdd this to your Cargo.toml:
[dependencies]
rust-queries-builder = "1.0.1"
key-paths-derive = "0.5.0"
# Optional: Enable datetime operations with chrono
rust-queries-builder = { version = "1.0.1", features = ["datetime"] }
chrono = "0.4"
# Optional: For async/tokio support
tokio = { version = "1.35", features = ["sync"] }
# Optional: For high-performance parking_lot locks
parking_lot = "0.12"
For faster builds (65% faster) and minimal dependencies:
[dependencies]
rust-queries-core = "1.0.1"
rust-queries-derive = "1.0.1" # Optional, only if using derive macros
key-paths-derive = "0.5.0"
# Optional: Enable datetime operations with chrono
rust-queries-core = { version = "1.0.1", features = ["datetime"] }
chrono = "0.4"
# Optional: For async/tokio support
tokio = { version = "1.35", features = ["sync"] }
# Optional: For high-performance parking_lot locks
parking_lot = "0.12"
⚠️ Important: When using individual crates, import from the correct locations:
use rust_queries_core::{Query, QueryExt}; // ← QueryExt is here!
use rust_queries_derive::QueryBuilder; // ← Derive macros here
See the Individual Crates Guide for complete details.
use rust_queries_builder::QueryExt; // Extension trait
use key_paths_derive::Keypath;
// Note: Clone not required for most operations!
#[derive(Keypath)]
struct Product {
id: u32,
name: String,
price: f64,
category: String,
stock: u32,
}
let products = vec![/* ... */];
// Call .query() directly on Vec!
let query = products.query().where_(Product::price(), |&p| p > 100.0);
let expensive = query.all();
// Or use lazy queries for better performance
let cheap: Vec<_> = products
.lazy_query()
.where_(Product::price(), |&p| p < 50.0)
.collect();
use rust_queries_builder::Query;
use key_paths_derive::Keypath;
#[derive(Keypath)]
struct Product {
id: u32,
name: String,
price: f64,
category: String,
stock: u32,
}
fn main() {
let products = vec![
Product { id: 1, name: "Laptop".to_string(), price: 999.99, category: "Electronics".to_string(), stock: 15 },
Product { id: 2, name: "Mouse".to_string(), price: 29.99, category: "Electronics".to_string(), stock: 50 },
Product { id: 3, name: "Desk".to_string(), price: 299.99, category: "Furniture".to_string(), stock: 10 },
];
// Filter products by category and price
let query = Query::new(&products)
.where_(Product::category(), |cat| cat == "Electronics")
.where_(Product::price(), |&price| price < 100.0);
let affordable_electronics = query.all();
println!("Found {} affordable electronics", affordable_electronics.len());
}
use rust_queries_builder::LazyQuery;
use key_paths_derive::Keypath;
fn main() {
let products = vec![/* ... */];
// Build query (nothing executes yet!)
let query = LazyQuery::new(&products)
.where_(Product::category(), |cat| cat == "Electronics")
.where_(Product::price(), |&price| price < 100.0)
.take_lazy(10); // Will stop after finding 10 items!
// Execute query (lazy evaluation with early termination)
let first_10: Vec<_> = query.collect();
println!("Found {} items (stopped early!)", first_10.len());
// Up to 100x faster for large datasets with take_lazy!
}
where_Filter collections using type-safe key-paths:
let query = Query::new(&products)
.where_(Product::category(), |cat| cat == "Electronics");
let electronics = query.all();
// Multiple conditions
let query2 = Query::new(&products)
.where_(Product::category(), |cat| cat == "Electronics")
.where_(Product::price(), |&price| price > 500.0)
.where_(Product::stock(), |&stock| stock > 0);
let premium_electronics = query2.all();
selectProject specific fields from your data:
// Get all product names
let names: Vec<String> = Query::new(&products)
.select(Product::name());
// Get prices of electronics
let prices: Vec<f64> = Query::new(&products)
.where_(Product::category(), |cat| cat == "Electronics")
.select(Product::price());
Sort results by any field:
// Sort by price (ascending)
let by_price = Query::new(&products)
.order_by_float(Product::price());
// Sort by name (descending)
let by_name_desc = Query::new(&products)
.order_by_desc(Product::name());
// Sort with filtering
let sorted_electronics = Query::new(&products)
.where_(Product::category(), |cat| cat == "Electronics")
.order_by_float(Product::price());
Compute statistics over your data:
let electronics = Query::new(&products)
.where_(Product::category(), |cat| cat == "Electronics");
// Count
let count = electronics.count();
// Sum
let total_value: f64 = electronics.sum(Product::price());
// Average
let avg_price = electronics.avg(Product::price()).unwrap_or(0.0);
// Min and Max
let cheapest = electronics.min_float(Product::price());
let most_expensive = electronics.max_float(Product::price());
group_byGroup data by field values:
use std::collections::HashMap;
// Group products by category
let by_category: HashMap<String, Vec<Product>> = Query::new(&products)
.group_by(Product::category());
// Calculate statistics per group
for (category, items) in &by_category {
let cat_query = Query::new(items);
let avg = cat_query.avg(Product::price()).unwrap_or(0.0);
println!("{}: {} products, avg price ${:.2}", category, items.len(), avg);
}
Limit and skip results for pagination:
// Get first 10 products
let query = Query::new(&products);
let first_page = query.limit(10);
// Get second page (skip 10, take 10)
let query = Query::new(&products);
let second_page = query.skip(10).limit(10);
// Get first matching item
let query = Query::new(&products)
.where_(Product::price(), |&price| price > 1000.0);
let first = query.first();
Combine multiple collections with type-safe joins:
use rust_queries_builder::JoinQuery;
#[derive(Clone, Keypaths)]
struct User {
id: u32,
name: String,
}
#[derive(Clone, Keypaths)]
struct Order {
id: u32,
user_id: u32,
total: f64,
}
let users = vec![
User { id: 1, name: "Alice".to_string() },
User { id: 2, name: "Bob".to_string() },
];
let orders = vec![
Order { id: 101, user_id: 1, total: 99.99 },
Order { id: 102, user_id: 1, total: 149.99 },
Order { id: 103, user_id: 2, total: 199.99 },
];
// Inner join: users with their orders
let user_orders = JoinQuery::new(&users, &orders)
.inner_join(
User::id(),
Order::user_id(),
|user, order| (user.name.clone(), order.total)
);
// Left join: all users, with or without orders
let all_users_orders = JoinQuery::new(&users, &orders)
.left_join(
User::id(),
Order::user_id(),
|user, order| match order {
Some(o) => format!("{} has order totaling ${:.2}", user.name, o.total),
None => format!("{} has no orders", user.name),
}
);
// Join with filter: only high-value orders
let high_value = JoinQuery::new(&users, &orders)
.inner_join_where(
User::id(),
Order::user_id(),
|_user, order| order.total > 100.0,
|user, order| (user.name.clone(), order.total)
);
Query Arc<RwLock<T>> and Arc<Mutex<T>> with full SQL syntax - NO copying required!
use rust_queries_builder::{LockQueryable, LockLazyQueryable};
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
use key_paths_derive::Keypaths;
#[derive(Clone, Keypaths)]
struct Product {
name: String,
price: f64,
category: String,
stock: u32,
}
let products: HashMap<String, Arc<RwLock<Product>>> = /* ... */;
// Full SQL-like syntax on locked data!
let expensive = products
.lock_query()
.where_(Product::category(), |cat| cat == "Electronics")
.where_(Product::price(), |&p| p > 500.0)
.order_by_float_desc(Product::rating())
.limit(10);
// GROUP BY with aggregations
let by_category = products
.lock_query()
.group_by(Product::category());
// Aggregations
let stats = products.lock_query();
let total = stats.sum(Product::price());
let avg = stats.avg(Product::price());
let count = stats.count();
// Lazy with early termination
let first_match: Vec<_> = products
.lock_lazy_query()
.where_(Product::stock(), |&s| s > 20)
.take_lazy(5)
.collect();
Performance: 5.25x faster than copy-based approach!
lock_lazy_query()Works out-of-the-box with Arc<RwLock<T>> and Arc<Mutex<T>>:
use std::sync::{Arc, RwLock};
use std::collections::HashMap;
use rust_queries_builder::LockQueryable;
let products: HashMap<String, Arc<RwLock<Product>>> = /* ... */;
let expensive = products
.lock_query()
.where_(Product::price(), |&p| p > 100.0)
.all();
Native support for tokio::sync::RwLock:
use tokio::sync::RwLock;
use std::sync::Arc;
use rust_queries_builder::{TokioLockQueryExt, TokioLockLazyQueryExt};
// Create extension wrapper
use rust_queries_builder::TokioRwLockWrapper;
let mut products: HashMap<String, TokioRwLockWrapper<Product>> = HashMap::new();
products.insert("p1".to_string(), TokioRwLockWrapper::new(Product {
id: 1,
price: 999.99,
category: "Electronics".to_string(),
}));
// Query asynchronously
async fn query_products(products: &HashMap<String, TokioRwLockWrapper<Product>>) {
let expensive = products
.lock_query() // Direct method call!
.where_(Product::price(), |&p| p > 500.0)
.all();
println!("Found {} expensive products", expensive.len());
}
See the tokio_rwlock_support example for complete async examples.
Support for parking_lot::RwLock and parking_lot::Mutex with better performance:
use parking_lot::RwLock;
use std::sync::Arc;
use std::collections::HashMap;
// Create wrapper for parking_lot locks
#[derive(Clone, Debug)]
pub struct ParkingLotRwLockWrapper<T>(Arc<RwLock<T>>);
impl<T> ParkingLotRwLockWrapper<T> {
pub fn new(value: T) -> Self {
Self(Arc::new(RwLock::new(value)))
}
}
// Implement LockValue trait
use rust_queries_builder::LockValue;
impl<T> LockValue<T> for ParkingLotRwLockWrapper<T> {
fn with_value<F, R>(&self, f: F) -> Option<R>
where
F: FnOnce(&T) -> R,
{
let guard = self.0.read();
Some(f(&*guard))
}
}
// Create extension trait for direct method calls
pub trait ParkingLotQueryExt<V> {
fn lock_query(&self) -> LockQuery<'_, V, ParkingLotRwLockWrapper<V>>;
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotRwLockWrapper<V>, impl Iterator<Item = &ParkingLotRwLockWrapper<V>>>;
}
impl<K, V: 'static> ParkingLotQueryExt<V> for HashMap<K, ParkingLotRwLockWrapper<V>>
where
K: std::hash::Hash + Eq,
{
fn lock_query(&self) -> LockQuery<'_, V, ParkingLotRwLockWrapper<V>> {
let locks: Vec<_> = self.values().collect();
LockQuery::from_locks(locks)
}
fn lock_lazy_query(&self) -> LockLazyQuery<'_, V, ParkingLotRwLockWrapper<V>, impl Iterator<Item = &ParkingLotRwLockWrapper<V>>> {
LockLazyQuery::new(self.values())
}
}
// Now use it!
let products: HashMap<String, ParkingLotRwLockWrapper<Product>> = /* ... */;
let expensive = products
.lock_query() // Direct method call!
.where_(Product::price(), |&p| p > 500.0)
.all();
parking_lot Advantages:
See the parking_lot_support example for complete implementation.
Query by dates, times, weekdays, and business hours with optional chrono support:
use rust_queries_builder::Query;
use chrono::{Utc, Duration};
use key_paths_derive::Keypaths;
#[derive(Keypath)]
struct Event {
id: u32,
title: String,
scheduled_at: DateTime<Utc>,
category: String,
}
let events = vec![/* ... */];
let now = Utc::now();
// Events scheduled in the next 7 days
let upcoming = Query::new(&events)
.where_between(
Event::scheduled_at(),
now,
now + Duration::days(7)
);
// Weekend events
let weekend = Query::new(&events)
.where_weekend(Event::scheduled_at());
// Work events during business hours on weekdays
let work_hours = Query::new(&events)
.where_(Event::category(), |c| c == "Work")
.where_weekday(Event::scheduled_at())
.where_business_hours(Event::scheduled_at());
// Events in December 2024
let december = Query::new(&events)
.where_year(Event::scheduled_at(), 2024)
.where_month(Event::scheduled_at(), 12);
where_after, where_before, where_betweenwhere_year, where_month, where_daywhere_weekend, where_weekday, where_todaywhere_business_hoursSee the DateTime Guide for complete documentation and examples.
// Find top 5 expensive electronics in stock, ordered by rating
let top_electronics = Query::new(&products)
.where_(Product::category(), |cat| cat == "Electronics")
.where_(Product::stock(), |&stock| stock > 0)
.where_(Product::price(), |&price| price > 100.0)
.order_by_float_desc(Product::rating());
for product in top_electronics.iter().take(5) {
println!("{} - ${:.2} - Rating: {:.1}",
product.name, product.price, product.rating);
}
#[derive(Clone, Keypaths)]
struct Product {
id: u32,
name: String,
price: f64,
}
// First join: Orders with Users
let orders_users = JoinQuery::new(&orders, &users)
.inner_join(
Order::user_id(),
User::id(),
|order, user| (order.clone(), user.clone())
);
// Second join: Add Products
let mut complete_orders = Vec::new();
for (order, user) in orders_users {
for product in &products {
if order.product_id == product.id {
complete_orders.push((user.name.clone(), product.name.clone(), order.total));
}
}
}
// Join orders with products, then aggregate by category
let order_products = JoinQuery::new(&orders, &products)
.inner_join(
Order::product_id(),
Product::id(),
|order, product| (product.category.clone(), order.total)
);
let mut category_sales: HashMap<String, f64> = HashMap::new();
for (category, total) in order_products {
*category_sales.entry(category).or_insert(0.0) += total;
}
Basic Operations:
new(data: &[T]) - Create a new querywhere_(path, predicate) - Filter by predicateall() - Get all matching itemsfirst() - Get first matching itemcount() - Count matching itemslimit(n) - Limit resultsskip(n) - Skip results for paginationexists() - Check if any matchOrdering:
order_by(path) - Sort ascendingorder_by_desc(path) - Sort descendingorder_by_float(path) - Sort f64 ascendingorder_by_float_desc(path) - Sort f64 descendingProjection & Grouping:
select(path) - Project fieldgroup_by(path) - Group by fieldAggregations:
sum(path) - Sum numeric fieldavg(path) - Average of f64 fieldmin(path) / max(path) - Min/max of Ord fieldmin_float(path) / max_float(path) - Min/max of f64 fieldDateTime Operations (with datetime feature):
where_after(path, time) - Filter after datetimewhere_before(path, time) - Filter before datetimewhere_between(path, start, end) - Filter within rangewhere_today(path, now) - Filter for todaywhere_year(path, year) - Filter by yearwhere_month(path, month) - Filter by month (1-12)where_day(path, day) - Filter by day (1-31)where_weekend(path) - Filter for weekendswhere_weekday(path) - Filter for weekdayswhere_business_hours(path) - Filter for business hours (9 AM - 5 PM)DateTime Operations (SystemTime, always available):
where_after_systemtime(path, time) - Filter after SystemTimewhere_before_systemtime(path, time) - Filter before SystemTimewhere_between_systemtime(path, start, end) - Filter within rangenew(left, right) - Create a new join queryinner_join(left_key, right_key, mapper) - Inner joinleft_join(left_key, right_key, mapper) - Left joinright_join(left_key, right_key, mapper) - Right joininner_join_where(left_key, right_key, predicate, mapper) - Filtered joincross_join(mapper) - Cartesian product# Advanced query builder example
cargo run --example advanced_query_builder
# Join operations example
cargo run --example join_query_builder
# DateTime operations - filter by dates, times, weekdays (v0.7.0+, requires datetime feature)
cargo run --example datetime_operations --features datetime
# i64 Timestamp aggregators - Unix timestamps in milliseconds (v1.0.5+)
cargo run --example i64_timestamp_aggregators
# Local datetime over UTC epoch - timezone-aware operations (v1.0.5+)
cargo run --example local_datetime_utc_epoch
# Lazy DateTime operations - efficient datetime queries with early termination (v0.7.0+)
cargo run --example lazy_datetime_operations --features datetime --release
# DateTime helper functions - all datetime helpers with SQL equivalents (v0.7.0+)
cargo run --example datetime_helper_functions --features datetime
# Lazy datetime helpers - all helpers with lazy evaluation and performance benchmarks (v0.7.0+)
cargo run --example lazy_datetime_helpers --features datetime --release
# SQL comparison - see how SQL queries map to Rust Query Builder
cargo run --example sql_comparison
# SQL verification - verify exact SQL equivalence (17 tests)
cargo run --example sql_verification
# Documentation examples - verify all doc examples compile and run (10 tests)
cargo run --example doc_examples
# Clone-free operations - demonstrates performance optimization (v0.2.0+)
cargo run --example without_clone
# Memory safety verification - proves 'static doesn't cause memory leaks
cargo run --example memory_safety_verification
# Lazy evaluation - demonstrates deferred execution and early termination
cargo run --example lazy_evaluation
# Container support - demonstrates querying various container types
cargo run --example container_support
# Custom Queryable - implement Queryable for custom containers (7 examples)
cargo run --example custom_queryable
# Arc<RwLock<T>> HashMap - thread-safe shared data with all 17 lazy operations
cargo run --example arc_rwlock_hashmap
# Lock-aware queries - query Arc<RwLock<T>> WITHOUT copying (v0.8.0+, 5x faster!)
cargo run --example lock_aware_queries --release
# SQL-like lock queries - full SQL syntax on locked HashMaps (v0.8.0+)
cargo run --example sql_like_lock_queries --release
# Advanced lock SQL - joins, views, lazy queries on locked data (v0.8.0+)
cargo run --example advanced_lock_sql --release
# Macro helpers - reduce boilerplate with 12 helper macros (30% less code)
cargo run --example macro_helpers
# Extension trait & derive macros - call .query() directly on containers (v0.5.0+)
cargo run --example derive_and_ext
# Individual crates usage - demonstrates using core + derive separately (v0.6.0+)
cargo run --example individual_crates
# Tokio RwLock support - async lock-aware queries (v0.9.0+)
cargo run --example tokio_rwlock_support
# parking_lot support - high-performance locks with queries (v1.0.0+)
cargo run --example parking_lot_support --release
The sql_comparison example demonstrates how traditional SQL queries (like those in HSQLDB) translate to Rust Query Builder:
// SQL: SELECT * FROM employees WHERE department = 'Engineering';
let engineering = Query::new(&employees)
.where_(Employee::department(), |dept| dept == "Engineering")
.all();
// SQL: SELECT AVG(salary) FROM employees WHERE age < 30;
let avg_salary = Query::new(&employees)
.where_(Employee::age(), |&age| age < 30)
.avg(Employee::salary());
// SQL: SELECT * FROM employees ORDER BY salary DESC LIMIT 5;
let top_5 = Query::new(&employees)
.order_by_float_desc(Employee::salary())
.into_iter()
.take(5)
.collect::<Vec<_>>();
The example demonstrates 15 different SQL patterns including SELECT, WHERE, JOIN, GROUP BY, ORDER BY, aggregations, and subqueries.
The query builder uses:
| Operation | Complexity | Memory | Clone Required? |
|---|---|---|---|
where_ / all |
O(n) | Zero extra | ❌ No |
count |
O(n) | Zero extra | ❌ No |
select |
O(n) | Only field copies | ❌ No |
sum / avg |
O(n) | Zero extra | ❌ No |
limit / skip |
O(n) | Zero extra | ❌ No |
order_by* |
O(n log n) | Clones all items | ✅ Yes |
group_by |
O(n) | Clones all items | ✅ Yes |
| Joins | O(n + m) | Zero extra | ❌ No |
Example: Filtering 10,000 employees (1KB each)
Work with Unix timestamps stored as i64 values in milliseconds, compatible with Java's Date.getTime() and JavaScript's Date.getTime(). Supports both positive timestamps (dates after 1970-01-01) and negative timestamps (dates before 1970-01-01):
use rust_queries_builder::{Query, Keypath};
#[derive(Keypath)]
struct Event {
id: u32,
name: String,
created_at: i64, // Unix timestamp in milliseconds
scheduled_at: i64, // Unix timestamp in milliseconds
}
let events = vec![/* ... */];
// Basic timestamp aggregators
let earliest = Query::new(&events).min_timestamp(Event::created_at());
let latest = Query::new(&events).max_timestamp(Event::created_at());
let avg = Query::new(&events).avg_timestamp(Event::created_at());
let total = Query::new(&events).sum_timestamp(Event::created_at());
let count = Query::new(&events).count_timestamp(Event::created_at());
// Time-based filtering (including negative timestamps for pre-epoch dates)
let epoch_start = 0; // 1970-01-01 00:00:00 UTC
let year_2020 = 1577836800000; // 2020-01-01 00:00:00 UTC
// Pre-epoch events (negative timestamps - dates before 1970)
let pre_epoch = Query::new(&events)
.where_before_timestamp(Event::created_at(), epoch_start);
let recent = Query::new(&events)
.where_after_timestamp(Event::created_at(), year_2020);
// Relative time filtering
let last_30_days = Query::new(&events)
.where_last_days_timestamp(Event::created_at(), 30);
let next_7_days = Query::new(&events)
.where_next_days_timestamp(Event::scheduled_at(), 7);
// Time-based ordering
let chronological = Query::new(&events)
.order_by_timestamp(Event::created_at());
let reverse_chronological = Query::new(&events)
.order_by_timestamp_desc(Event::scheduled_at());
// Complex queries
let tech_events = Query::new(&events)
.where_(Event::category(), |cat| cat == "Technology")
.where_last_days_timestamp(Event::created_at(), 365)
.order_by_timestamp(Event::created_at());
Basic Aggregators:
min_timestamp() - Find earliest timestampmax_timestamp() - Find latest timestampavg_timestamp() - Calculate average timestampsum_timestamp() - Sum all timestampscount_timestamp() - Count non-null timestampsTime-based Filtering:
where_after_timestamp() - Filter timestamps after referencewhere_before_timestamp() - Filter timestamps before referencewhere_between_timestamp() - Filter timestamps between two valuesRelative Time Filtering:
where_last_days_timestamp() - Last N days from nowwhere_next_days_timestamp() - Next N days from nowwhere_last_hours_timestamp() - Last N hours from nowwhere_next_hours_timestamp() - Next N hours from nowwhere_last_minutes_timestamp() - Last N minutes from nowwhere_next_minutes_timestamp() - Next N minutes from nowTime-based Ordering:
order_by_timestamp() - Sort by timestamp (oldest first)order_by_timestamp_desc() - Sort by timestamp (newest first)Advanced timezone-aware operations with UTC timestamps interpreted in local timezones:
use rust_queries_builder::{Query, Keypath};
use chrono::{DateTime, Utc, FixedOffset};
#[derive(Keypath)]
struct LocalEvent {
utc_timestamp: i64, // UTC timestamp in milliseconds
local_timezone: String, // Timezone identifier
category: String,
is_business_hours: bool, // Whether event is during local business hours
}
let events = vec![/* ... */];
// Timezone-aware business hours detection
let business_hours = Query::new(&events)
.where_(LocalEvent::is_business_hours(), |&is_business| is_business)
.all();
// Cross-timezone simultaneous events
let same_utc_time = 1704067200000; // 2024-01-01 00:00:00 UTC
let simultaneous = Query::new(&events)
.where_(LocalEvent::utc_timestamp(), move |&ts| ts == same_utc_time)
.all();
// Duration analysis by timezone
for timezone in ["America/New_York", "Europe/London", "Asia/Tokyo"] {
let tz_query = Query::new(&events)
.where_(LocalEvent::local_timezone(), move |tz| tz == timezone);
let avg_duration = tz_query.avg(LocalEvent::duration_minutes()).unwrap_or(0.0);
let total_duration = tz_query.sum(LocalEvent::duration_minutes());
let event_count = tz_query.count();
println!("{}: {} events, avg duration: {:.1} min",
timezone, event_count, avg_duration);
}
This library leverages the key-paths crate to provide type-safe field access. The Keypath derive macro automatically generates accessor methods for your structs:
#[derive(Keypath)]
struct Product {
id: u32,
name: String,
price: f64,
}
// Generated methods:
// - Product::id() -> KeyPaths<Product, u32>
// - Product::name() -> KeyPaths<Product, String>
// - Product::price() -> KeyPaths<Product, f64>
| Feature | std::sync::RwLock | tokio::sync::RwLock | parking_lot::RwLock |
|---|---|---|---|
| Lock Acquisition | Baseline | Async | 10-30% faster |
| Memory Footprint | 64 bytes | 64 bytes | 8 bytes (8x smaller) |
| Poisoning | Yes (Result type) | No | No |
| Fair Unlocking | No | No | Yes |
| Async Support | ❌ | ✅ | ❌ |
| Use Case | General sync | Async/await | High-perf sync |
| Setup Required | None (built-in) | Extension trait | Newtype wrapper |
std::sync::RwLock / Mutex
tokio::sync::RwLock
parking_lot::RwLock / Mutex
What's New:
Breaking Changes: None! v1.0.0 is fully backward compatible with v0.9.0.
Update your Cargo.toml:
# Old (v0.7.0-0.9.0)
rust-queries-builder = "0.9.0"
# New (v1.0.0)
rust-queries-builder = "1.0.1"
All your existing code will work without modification!
If upgrading from v0.8.0 or earlier, you'll gain:
Tokio Support - Add async lock-aware queries:
use rust_queries_builder::TokioRwLockWrapper;
// See examples/tokio_rwlock_support.rs
parking_lot Support - High-performance locks:
// See examples/parking_lot_support.rs for implementation
Better Performance - Lazy queries up to 189x faster
More Examples - Comprehensive guides and patterns
This project is licensed under either of:
at your option.
Contributions are welcome! Please feel free to submit a Pull Request.
Built with rust-key-paths for type-safe field access.