query-lite
A convenient SQL query builder for rusqlite that makes it easy to build type-safe SQLite queries with parameter binding. Parse HTTP query parameters, build queries programmatically, or combine both approaches to create secure, parameterized SQL queries.
Why query-lite?
Building SQL queries manually is error-prone and tedious. query-lite provides a type-safe, builder-pattern API that:
- ✅ Prevents SQL Injection: All queries use parameterized placeholders
- ✅ Type-Safe: Compile-time guarantees for query structure
- ✅ Easy to Use: Builder pattern with fluent API
- ✅ rusqlite Ready: Direct integration with rusqlite's
ToSqltrait - ✅ Flexible: Build queries programmatically or parse from HTTP
Example
use ;
use Connection;
// Build a query
let mut params = new;
params
.contains
.between
.greater;
let mut order = new;
order.descending;
let query = init;
// Generate SQL
let sql = query.to_sql;
// "WHERE name LIKE ? AND age BETWEEN ? AND ? AND price > ? ORDER BY date_created DESC LIMIT ? OFFSET ?"
// Get values for rusqlite
let values = query.to_values;
// Use with rusqlite
let conn = open?;
let mut stmt = conn.prepare?;
let params: = values
.iter
.map
.collect;
let rows = stmt.query?;
Features
- 🗄️ SQL Query Builder: Build type-safe SQLite queries with automatic parameter binding for rusqlite
- 🔒 SQL Injection Safe: All queries use parameterized placeholders - never string concatenation
- 🎯 Rich Filtering: Support for equals, contains, starts-with, ends-with, between, greater, lesser, and more
- 📊 Sorting & Pagination: Built-in support for ORDER BY, LIMIT, and OFFSET clauses
- 🔍 HTTP Query Parsing: Optional support for parsing HTTP query parameters into SQL queries
- 🛡️ Type Safety: Full Rust type safety with comprehensive error handling
- ⚡ Zero-Copy Values: Direct integration with rusqlite's
ToSqltrait for efficient parameter binding - 🧪 Well Tested: Comprehensive test suite with 240+ tests
Quick Start
Add this to your Cargo.toml:
[]
# SQL query builder (default - includes SQL generation)
= "0.11.0"
# With HTTP query parameter parsing (optional)
= { = "0.11.0", = ["http"] }
Basic Usage
Building SQL Queries Programmatically
The primary use case is building SQL queries for rusqlite:
use ;
use Connection;
Parsing HTTP Query Parameters (Optional)
If you enable the http feature, you can also parse HTTP query strings:
use Query;
use Connection;
Traditional Query Parameters
use Query;
// Parse traditional HTTP query parameters
let query = from_http?;
// Access parameters
let name_param = query.parameters.inner.get.unwrap;
assert_eq!;
assert_eq!;
// Convert back to HTTP
let http_string = query.to_http;
// Result: "name=equals:john&age=equals:25&city=equals:london&limit=50&offset=0"
Advanced Similarity-based Parameters
use Query;
// Parse advanced query parameters
let query = from_http?;
// Access parameters with different similarity types
let name_param = query.parameters.inner.get.unwrap;
assert_eq!;
assert_eq!;
let age_param = query.parameters.inner.get.unwrap;
assert_eq!;
assert_eq!;
Mixed Traditional and Advanced
use Query;
// Mix traditional and advanced parameters
let query = from_http?;
// Traditional parameters (repeated values)
let name_param = query.parameters.inner.get.unwrap;
assert_eq!;
assert_eq!;
// Advanced parameters
let age_param = query.parameters.inner.get.unwrap;
assert_eq!;
assert_eq!;
Programmatic Query Building
You can also build queries programmatically using the builder pattern:
use ;
// Build parameters using the builder pattern
let mut parameters = new;
parameters
.equals
.contains
.between
.greater;
// Build sort fields using the builder pattern
let mut order = new;
order
.descending
.ascending;
// Create the query
let query = init;
// Convert to HTTP string
let http_string = query.to_http;
// Result: "name=equals:john,jane&description=contains:rust&age=between:18,65&price=greater:100&order=date_created:desc,name:asc&limit=25&offset=0"
Enhanced Parameter Access
The library provides multiple ways to access parameter data for different use cases:
Semantic Access (Recommended)
use Query;
let query = from_http?;
// Access parameters using semantic methods
let name_param = query.parameters.inner.get.unwrap;
assert_eq!;
assert_eq!;
let age_param = query.parameters.inner.get.unwrap;
assert_eq!;
assert_eq!;
Direct Collection Access
For advanced operations, you can access the underlying collections directly:
use Query;
let mut query = new;
query.parameters.equals;
query.order.ascending;
// Access the underlying IndexMap for complex operations
let param_map = query.parameters.inner;
let order_map = query.order.inner;
// Iterate over all parameters
for in param_map
// Perform bulk operations
let param_map_mut = query.parameters.inner_mut;
param_map_mut.insert;
Parameter Access
The library provides semantic access methods for parameter data:
use Query;
let query = from_http?;
let param = query.parameters.inner.get.unwrap;
// Use semantic access methods
assert_eq!;
assert_eq!;
// Create parameters using the init method
let new_param = init;
Similarity Types
The library supports various similarity types for advanced filtering:
| Similarity | Description | Example | SQLite Equivalent |
|---|---|---|---|
equals |
Exact match | name=equals:john |
name = ? |
contains |
Substring match | name=contains:john |
name LIKE ? |
starts-with |
Prefix match | name=starts-with:john |
name LIKE ? |
ends-with |
Suffix match | name=ends-with:john |
name LIKE ? |
between |
Range match | age=between:20,30 |
age BETWEEN ? AND ? |
greater |
Greater than | price=greater:100 |
price > ? |
lesser |
Less than | price=lesser:100 |
price < ? |
greater-or-equal |
Greater or equal | price=greater-or-equal:100 |
price >= ? |
lesser-or-equal |
Less or equal | price=lesser-or-equal:100 |
price <= ? |
Multiple Values
// Multiple values for equals (IN clause)
"?name=equals:john,jane,bob"
// → name IN ('john', 'jane', 'bob')
// Multiple ranges for between
"?age=between:18,25,30,40,50,65"
// → (age BETWEEN 18 AND 25) OR (age BETWEEN 30 AND 40) OR (age BETWEEN 50 AND 65)
// Note: Odd values (65) are ignored
Sorting and Pagination
use Query;
let query = from_http?;
// Access sorting
assert_eq!;
assert_eq!;
assert_eq!;
// Access pagination
assert_eq!;
assert_eq!;
SQL Query Building
The core feature of query-lite is building SQL queries for rusqlite. All queries use parameterized placeholders to prevent SQL injection:
use Query;
let query = from_http?;
// Generate SQLite-compatible SQL with parameter placeholders
let sql = query.to_sql;
// Result: "WHERE name LIKE ? AND age BETWEEN ? AND ? ORDER BY date_created DESC LIMIT ? OFFSET ?"
// Get parameter values separately for more control
let param_values = query.parameter_values;
let pagination_values = query.pagination_values;
let total_params = query.total_parameters;
// Use with SQLite
// let stmt = conn.prepare(&format!("SELECT * FROM users {}", sql))?;
// let rows = stmt.query(param_values)?;
Advanced SQLite Clause Management
Version 0.8.0 introduces improved SQLite clause methods that return Option<String> for better semantic clarity:
use Query;
let query = from_http?;
// Get WHERE clause (returns None if no conditions)
match query.where_clause
// Get ORDER BY clause (returns None if no sorting)
match query.order_clause
// Build custom SQL with explicit handling
let sql = match ;
Advanced SQLite Value Management
Version 0.6.0 introduces simplified SQLite value methods:
use Query;
let query = from_http?;
// Get only parameter values (without pagination)
let param_values = query.parameter_values;
// Result: [sql::Value::Text("%john%"), sql::Value::Text("20"), sql::Value::Text("30"), sql::Value::Text("100")]
// Get only order values (without pagination)
let param_values = query.parameter_values;
// Result: [sql::Value::Text("%john%"), sql::Value::Text("20"), sql::Value::Text("30"), sql::Value::Text("100")]
// Get only pagination values
let pagination_values = query.pagination_values;
// Result: [sql::Value::Integer(50), sql::Value::Integer(0)]
// Get total parameter count
let total_params = query.total_parameters;
// Result: 6 (4 parameter values + 2 pagination values)
// Combine for complete SQL execution
let all_values = .concat;
// Use with SQLite
// let stmt = conn.prepare(&format!("SELECT * FROM users {}", query.to_sql()))?;
// let rows = stmt.query(all_values)?;
This granular approach allows for:
- Separate Parameter Handling: Process parameter values and pagination values independently
- Custom Value Processing: Apply different logic to parameters vs pagination
- Performance Optimization: Avoid unnecessary value processing when only certain parts are needed
- Debugging: Easily inspect parameter counts and values for troubleshooting
SQLite Examples
The generated SQL uses SQLite syntax with ? parameter placeholders:
// Traditional parameters
"?name=john&name=jane&age=25"
// → "WHERE name IN (?, ?) AND age = ? LIMIT ? OFFSET ?"
// Advanced parameters
"?name=contains:john&age=between:20,30&price=greater:100"
// → "WHERE name LIKE ? AND age BETWEEN ? AND ? AND price > ? LIMIT ? OFFSET ?"
// Complex mixed query
"?name=john&name=jane&age=contains:25&price=greater:100&order=date_created:desc&limit=20"
// → "WHERE name IN (?, ?) AND age LIKE ? AND price > ? ORDER BY date_created DESC LIMIT ? OFFSET ?"
rusqlite Integration
The sql::Value type (which is rusqlite::types::Value) implements rusqlite::types::ToSql, allowing direct parameter binding to rusqlite queries:
use Query;
use Connection;
URL Encoding Support
The library automatically handles URL encoding and decoding:
use Query;
// URL encoded parameters
let query = from_http?;
let name_param = query.parameters.inner.get.unwrap;
assert_eq!; // Automatically decoded
let email_param = query.parameters.inner.get.unwrap;
assert_eq!; // Automatically decoded
Query Manipulation
use Query;
let query = from_http?;
// Keep only specific parameters
let filtered_params = query.parameters.keep;
let filtered_query = init;
// Result: Only name and age parameters remain
// Remove specific parameters
let filtered_params = query.parameters.remove;
let filtered_query = init;
// Result: email parameter is removed, name and age remain
Error Handling
use ;
match from_http
Real-world Examples
E-commerce Product Search
use Query;
// Complex product search with multiple filters
let query = from_http?;
// Generate SQLite query for product search
let sql = query.to_sql;
// "WHERE category = ? AND brand IN (?, ?) AND price BETWEEN ? AND ? AND rating >= ? ORDER BY price ASC LIMIT ? OFFSET ?"
User Management System
use Query;
// User filtering and management
let query = from_http?;
// Generate SQLite query for user query
let sql = query.to_sql;
// "WHERE name LIKE ? AND age > ? AND status = ? AND role IN (?, ?) ORDER BY created_at DESC LIMIT ? OFFSET ?"
Content Management
use Query;
// Content filtering with date ranges
let query = from_http?;
// Generate SQLite query for content query
let sql = query.to_sql;
// "WHERE title LIKE ? AND tags IN (?, ?) AND date BETWEEN ? AND ? AND published = ? ORDER BY date DESC LIMIT ? OFFSET ?"
Feature Flags
The library supports feature flags for optional functionality:
[]
# Default: SQL query builder (includes SQL generation)
= "0.11.0"
# With HTTP query parameter parsing (optional)
= { = "0.11.0", = ["http"] }
Feature Details
sql(default): Enables SQL query generation methods (to_sql(),where_clause(),order_clause(), etc.) and re-exportsrusqlite::types::Valueassql::Value. Thesql::Valuetype implementsrusqlite::types::ToSql, allowing direct parameter binding to rusqlite queries.http(optional): Enables HTTP query string parsing and generation methods (from_http(),to_http()).
API Reference
Core Types
Query: Main query structure containing parameters, sorting, and paginationParameters: Collection of query parameters with builder methodsParameter: Struct containing similarity and values with semantic access methods (fields are private)Order: Collection of sort fields with builder methodsSimilarity: Enum defining comparison types (equals, contains, between, etc.)SortDirection: Sort direction (ascending, descending)
Key Methods
Query Methods
Query::new(): Create a new Query with default values (empty parameters, empty order, limit=50, offset=0)Query::init(): Create Query with custom parameters, order, limit, and offsetQuery::to_sql(): Generate SQLite-compatible query with parameter placeholders (default feature)Query::from_http(): Parse HTTP query string into Query struct (requireshttpfeature)Query::to_http(): Convert Query struct back to HTTP query string (requireshttpfeature)Query::where_clause(): Get WHERE clause as Option (feature-gated)Query::order_clause(): Get ORDER BY clause as Option (feature-gated)Query::to_values(): Get all SQLite values (parameters + pagination) (feature-gated)Query::parameter_values(): Get SQLite values for parameters only (feature-gated)Query::pagination_values(): Get SQLite values for pagination only (feature-gated)Query::total_parameters(): Get total number of SQLite parameter values (feature-gated)
Parameters Methods
Parameters::new(): Create new Parameters collectionParameters::equals(),Parameters::contains(), etc.: Builder methods for adding parametersParameters::inner(): Get immutable reference to underlying IndexMapParameters::inner_mut(): Get mutable reference to underlying IndexMapParameters::keep(): Filter parameters to keep only specified keysParameters::remove(): Remove specified parameters
Parameter Methods
Parameter::init(): Create a new Parameter with similarity and valuesParameter::similarity(): Get reference to similarity typeParameter::values(): Get reference to parameter valuesParameter::values_mut(): Get mutable reference to parameter values
Order Methods
Order::new(): Create new Order collectionOrder::ascending(),Order::descending(): Builder methods for adding sort fieldsOrder::inner(): Get immutable reference to underlying IndexMapOrder::inner_mut(): Get mutable reference to underlying IndexMapOrder::keep(): Filter sort fields to keep only specified keysOrder::remove(): Remove specified sort fields
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
License
This project is licensed under either of
- Apache License, Version 2.0, (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Changelog
See CHANGELOG.md for a detailed list of changes.
Made with ❤️ in Rust