query-x
A powerful Rust library for parsing HTTP query parameters into structured queries with support for both traditional and advanced similarity-based filtering, plus optional SQL generation.
Features
- ๐ Dual URL Support: Handle both traditional (
?name=john
) and advanced (?name=contains:john
) query parameters - ๐ฏ Advanced Filtering: Support for contains, starts-with, ends-with, between, greater, lesser, and more
- ๐ Roundtrip Conversion: Convert between HTTP queries and structured objects seamlessly
- ๐๏ธ SQL Generation: Optional SQL query generation with parameter binding (feature-gated)
- ๐ก๏ธ Type Safety: Full Rust type safety with comprehensive error handling
- โก Zero Dependencies: Minimal dependencies for core functionality
- ๐งช Well Tested: Comprehensive test suite with 150+ tests
Quick Start
Add this to your Cargo.toml
:
[]
= "0.3.0"
# Optional: Enable SQL generation (enabled by default)
# query-x = { version = "0.3.0", default-features = false }
Basic Usage
Traditional Query Parameters
use Query;
// Parse traditional HTTP query parameters
let query = from_http?;
// Access parameters
let name_param = query.parameters.0.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.0.get.unwrap;
assert_eq!;
assert_eq!;
let age_param = query.parameters.0.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.0.get.unwrap;
assert_eq!;
assert_eq!;
// Advanced parameters
let age_param = query.parameters.0.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 sort_fields = new;
sort_fields
.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.sort_fields.ascending;
// Access the underlying IndexMap for complex operations
let param_map = query.parameters.inner;
let sort_map = query.sort_fields.inner;
// Iterate over all parameters
for in param_map
// Perform bulk operations
let param_map_mut = query.parameters.inner_mut;
param_map_mut.insert;
Backward Compatibility
The library maintains full backward compatibility with tuple access:
use Query;
let query = from_http?;
let param = query.parameters.inner.get.unwrap;
// Old tuple access still works
assert_eq!;
assert_eq!;
// New semantic access also works
assert_eq!;
assert_eq!;
// Both return the same data
assert_eq!;
assert_eq!;
Similarity Types
The library supports various similarity types for advanced filtering:
Similarity | Description | Example | SQL 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 Generation (Optional)
Enable the sql
feature (enabled by default) to generate SQL queries:
use Query;
let query = from_http?;
// Generate SQL with parameter placeholders
let sql = query.to_sql;
// Result: "WHERE name LIKE ? AND age BETWEEN ? AND ? ORDER BY date_created DESC LIMIT ? OFFSET ?"
// Use with your database driver
// let stmt = conn.prepare(&format!("SELECT * FROM users {}", sql))?;
// let rows = stmt.query(["%john%", "20", "30", "10", "0"])?;
SQL Examples
// 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 ?"
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.0.get.unwrap;
assert_eq!; // Automatically decoded
let email_param = query.parameters.0.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 SQL 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 SQL 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 SQL 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: includes SQL generation
= "0.3.0"
# Without SQL generation (smaller binary)
= { = "0.3.0", = false }
# With specific features
= { = "0.3.0", = ["sql"] }
API Reference
Core Types
Query
: Main query structure containing parameters, sorting, and paginationParameters
: Collection of query parameters with builder methodsSortFields
: Collection of sort fields with builder methodsParameter
: Type alias for(Similarity, Vec<String>)
with trait methodsParameterGet
: Trait providing semantic access to parameter dataSimilarity
: Enum defining comparison types (equals, contains, between, etc.)SortOrder
: Sort direction (ascending, descending)
Key Methods
Query Methods
Query::from_http()
: Parse HTTP query string into Query structQuery::to_http()
: Convert Query struct back to HTTP query stringQuery::to_sql()
: Generate SQL query with parameter placeholders (feature-gated)Query::init()
: Create Query with custom parameters, sort fields, limit, and offset
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
SortFields Methods
SortFields::new()
: Create new SortFields collectionSortFields::ascending()
,SortFields::descending()
: Builder methods for adding sort fieldsSortFields::inner()
: Get immutable reference to underlying IndexMapSortFields::inner_mut()
: Get mutable reference to underlying IndexMapSortFields::keep()
: Filter sort fields to keep only specified keysSortFields::remove()
: Remove specified sort fields
Parameter Access Methods
Parameter::similarity()
: Get reference to similarity typeParameter::values()
: Get reference to parameter values
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