🦀 🦀 query() - Database Query Function in Rust

Rust Documentation

🦀 query() - Database Query Function in Rust

"We don't bow to any king" - Database Edition

The query() function in TuskLang Rust provides ultra-fast, zero-copy database operations with compile-time safety and built-in protection against SQL injection. Say goodbye to ORM complexity and hello to raw power with type safety.

🚀 Basic Syntax

use tusklang_rust::{query, QueryBuilder, DatabaseConnection};

// Simple query with zero-copy parsing let users: Vec<User> = query!("SELECT * FROM users")?;

// Parameterized query (SQL injection protection) let user: Option<User> = query!( "SELECT * FROM users WHERE id = ?", user_id ).first()?;

// Multiple parameters with type safety let results: Vec<Order> = query!( "SELECT * FROM orders WHERE user_id = ? AND status = ?", user_id, "completed" )?;

🎯 SELECT Queries

use tusklang_rust::{query, QueryResult};

// Basic SELECT with automatic deserialization #[derive(Debug, Deserialize)] struct User { id: i32, name: String, email: String, active: bool, }

let all_users: Vec<User> = query!("SELECT * FROM users")?;

// SELECT with conditions let active_users: Vec<User> = query!( "SELECT * FROM users WHERE active = ?", true )?;

// Complex SELECT with joins #[derive(Debug, Deserialize)] struct OrderWithDetails { id: i32, total: f64, customer_name: String, product_name: String, }

let orders: Vec<OrderWithDetails> = query!(r#" SELECT o.id, o.total, u.name as customer_name, p.name as product_name FROM orders o JOIN users u ON o.user_id = u.id JOIN products p ON o.product_id = p.id WHERE o.created_at > ? ORDER BY o.created_at DESC LIMIT 100 "#, last_week)?;

// Single row with Option let user: Option<User> = query!( "SELECT * FROM users WHERE email = ?", email ).first()?;

// Single value extraction let count: i64 = query!( "SELECT COUNT(*) as total FROM users" ).value("total")?;

⚡ INSERT Queries

use tusklang_rust::{query, InsertResult};

// Basic INSERT with automatic parameter binding let insert_result: InsertResult = query!( "INSERT INTO users (name, email, created_at) VALUES (?, ?, ?)", name, email, chrono::Utc::now() )?;

// Get insert ID let user_id: i64 = query!( "INSERT INTO users (name, email) VALUES (?, ?)", name, email ).insert_id()?;

// Batch insert with iterator let users_data = vec![ ("John", "john@example.com"), ("Jane", "jane@example.com"), ("Bob", "bob@example.com"), ];

for (name, email) in users_data { query!( "INSERT INTO users (name, email) VALUES (?, ?)", name, email )?; }

// Insert with ON DUPLICATE KEY UPDATE query!( "INSERT INTO settings (user_id, key, value) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE value = VALUES(value)", user_id, setting_key, setting_value )?;

🔄 UPDATE Queries

use tusklang_rust::{query, UpdateResult};

// Basic UPDATE with affected rows let update_result: UpdateResult = query!( "UPDATE users SET last_login = ? WHERE id = ?", chrono::Utc::now(), user_id )?;

println!("Affected rows: {}", update_result.affected_rows());

// Update multiple fields query!( "UPDATE products SET name = ?, price = ?, updated_at = ? WHERE id = ?", name, price, chrono::Utc::now(), product_id )?;

// Conditional update query!( "UPDATE orders SET status = ? WHERE id = ? AND status = ?", "shipped", order_id, "pending" )?;

// Increment value query!( "UPDATE users SET login_count = login_count + 1 WHERE id = ?", user_id )?;

🗑️ DELETE Queries

use tusklang_rust::{query, DeleteResult};

// Basic DELETE with affected rows let delete_result: DeleteResult = query!( "DELETE FROM users WHERE id = ?", user_id )?;

println!("Deleted rows: {}", delete_result.affected_rows());

// Delete with condition query!( "DELETE FROM sessions WHERE expires_at < ?", chrono::Utc::now() )?;

// Soft delete query!( "UPDATE users SET deleted_at = ? WHERE id = ?", chrono::Utc::now(), user_id )?;

// Delete with JOIN query!(r#" DELETE orders FROM orders JOIN users ON orders.user_id = users.id WHERE users.inactive = 1 "#)?;

🔒 Transactions

use tusklang_rust::{transaction, Transaction};

// Basic transaction with automatic rollback let result: Result<(), Box<dyn std::error::Error>> = transaction(|tx| { // Deduct from account query!( "UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, from_id ).execute_on(tx)?; // Add to account query!( "UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, to_id ).execute_on(tx)?; // Log transaction query!( "INSERT INTO transactions (from_id, to_id, amount) VALUES (?, ?, ?)", from_id, to_id, amount ).execute_on(tx)?; Ok(()) });

// Manual transaction control let mut tx = db.begin_transaction()?;

match (|| -> Result<(), Box<dyn std::error::Error>> { // Multiple queries query!( "INSERT INTO orders (user_id, total) VALUES (?, ?)", user_id, total ).execute_on(&mut tx)?; let order_id = tx.last_insert_id()?; for item in items { query!( "INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)", order_id, item.product_id, item.quantity ).execute_on(&mut tx)?; } tx.commit()?; Ok(()) })() { Ok(_) => println!("Transaction successful"), Err(e) => { tx.rollback()?; return Err(e); } }

🎯 Prepared Statements

use tusklang_rust::{prepare, PreparedStatement};

// Prepare once, execute many let mut stmt = prepare!( "INSERT INTO logs (level, message, created_at) VALUES (?, ?, ?)" )?;

for entry in log_entries { stmt.execute(&[&entry.level, &entry.message, &chrono::Utc::now()])?; }

stmt.close()?;

// Named parameters with struct #[derive(Debug)] struct UserQuery { min_age: i32, max_age: i32, status: String, }

let mut stmt = prepare!( "SELECT * FROM users WHERE age BETWEEN :min_age AND :max_age AND status = :status" )?;

let query_params = UserQuery { min_age: 18, max_age: 65, status: "active".to_string(), };

let results: Vec<User> = stmt.execute_named(&query_params)?;

🔧 Query Builder Integration

use tusklang_rust::{QueryBuilder, Condition};

// Build query dynamically with type safety let mut builder = QueryBuilder::new("SELECT * FROM products"); let mut conditions = Vec::new(); let mut params = Vec::new();

if let Some(search_name) = search_name { conditions.push("name LIKE ?"); params.push(format!("%{}%", search_name)); }

if let Some(min_price) = min_price { conditions.push("price >= ?"); params.push(min_price); }

if let Some(category_id) = category_id { conditions.push("category_id = ?"); params.push(category_id); }

if !conditions.is_empty() { builder = builder.where_clause(&conditions.join(" AND ")); }

let results: Vec<Product> = builder.execute(&params)?;

📊 Result Processing

use tusklang_rust::{query, QueryResult};

// Get all results with automatic deserialization let users: Vec<User> = query!("SELECT * FROM users").all()?;

// Get first result let first_user: Option<User> = query!( "SELECT * FROM users ORDER BY created_at" ).first()?;

// Get single column let emails: Vec<String> = query!( "SELECT email FROM users" ).column("email")?;

// Get key-value pairs let user_names: HashMap<i32, String> = query!( "SELECT id, name FROM users" ).pairs("id", "name")?;

// Custom result processing with iterator query!("SELECT * FROM orders").each(|row: Order| { process_order(row); })?;

// Map results with functional programming let totals: Vec<f64> = query!("SELECT * FROM orders") .map(|order: Order| order.total)?;

⚡ Advanced Features

use tusklang_rust::{query, QueryOptions};

// Query with timeout let results: Vec<User> = query!( "SELECT * FROM large_table" ).with_options(QueryOptions { timeout: Some(Duration::from_secs(5)), ..Default::default() })?;

// Read from replica let users: Vec<User> = query!( "SELECT * FROM users" ).with_options(QueryOptions { connection: Some("read_replica".to_string()), ..Default::default() })?;

// Query profiling let profile_result = query!( "SELECT * FROM complex_view" ).with_options(QueryOptions { profile: true, ..Default::default() })?;

println!("Query time: {:?}", profile_result.profile.time); println!("Rows returned: {}", profile_result.profile.rows);

// Streaming results for large datasets query!("SELECT * FROM huge_table") .with_options(QueryOptions { stream: true, chunk_size: Some(1000), ..Default::default() }) .stream_chunks(|chunk: Vec<User>| { process_chunk(chunk); })?;

🛡️ Error Handling

use tusklang_rust::{query, QueryError, DatabaseError};

// Basic error handling with custom types #[derive(Debug, thiserror::Error)] enum AppError { #[error("Database query failed: {0}")] QueryError(#[from] QueryError), #[error("User not found: {0}")] UserNotFound(i32), }

let result: Result<Option<User>, AppError> = (|| { let user = query!( "SELECT * FROM users WHERE id = ?", user_id ).first()?; Ok(user) })();

match result { Ok(Some(user)) => println!("Found user: {:?}", user), Ok(None) => Err(AppError::UserNotFound(user_id))?, Err(e) => { log::error!("Query failed: {:?}", e); return Err(e); } }

// Check query success with result types let update_result = query!( "UPDATE users SET active = ? WHERE id = ?", false, user_id )?;

if update_result.affected_rows() > 0 { log::info!("User deactivated: {}", user_id); } else { log::warn!("No user found to deactivate: {}", user_id); }

// Handle deadlocks with retry logic fn retry_on_deadlock<F, T>(mut f: F, max_retries: u32) -> Result<T, Box<dyn std::error::Error>> where F: FnMut() -> Result<T, QueryError>, { let mut attempts = 0; loop { match f() { Ok(result) => return Ok(result), Err(e) => { if e.is_deadlock() && attempts < max_retries { attempts += 1; std::thread::sleep(Duration::from_millis(100 * attempts)); } else { return Err(e.into()); } } } } }

🚀 Query Caching

use tusklang_rust::{query, cache::QueryCache};
use std::collections::HashMap;

// Cache query results with TTL struct CachedQuery { cache: QueryCache, }

impl CachedQuery { fn cached_query<T>( &self, sql: &str, params: &[&dyn std::any::Any], ttl: Duration, ) -> Result<T, Box<dyn std::error::Error>> where T: for<'de> Deserialize<'de> + Clone + Send + Sync + 'static, { let cache_key = format!("query:{}", md5::compute(sql)); if let Some(cached) = self.cache.get::<T>(&cache_key)? { return Ok(cached); } let result: T = query!(sql, params)?; self.cache.set(&cache_key, &result, ttl)?; Ok(result) } fn update_user(&self, id: i32, data: UserUpdate) -> Result<(), Box<dyn std::error::Error>> { query!( "UPDATE users SET ? WHERE id = ?", data, id )?; // Clear related caches let cache_key = format!("query:{}", md5::compute("SELECT * FROM users WHERE id = ?")); self.cache.delete(&cache_key)?; self.cache.flush_tag("users")?; Ok(()) } }

🌐 Database Agnostic

use tusklang_rust::{query, DatabaseType};

// Works with different databases automatically // MySQL let users: Vec<User> = query!("SELECT * FROM users LIMIT ?", 10)?;

// PostgreSQL let users: Vec<User> = query!("SELECT * FROM users LIMIT $1", 10)?;

// SQLite let users: Vec<User> = query!("SELECT * FROM users LIMIT ?", 10)?;

// SQL Server let users: Vec<User> = query!("SELECT TOP (?) * FROM users", 10)?;

// Use database abstraction with type safety let users: Vec<User> = QueryBuilder::new("users") .select("*") .limit(10) .execute()?;

⚡ Performance Tips

use tusklang_rust::{query, ExplainResult};

// Use EXPLAIN to analyze queries let explain: ExplainResult = query!( "EXPLAIN SELECT * FROM orders WHERE user_id = ?", user_id )?;

println!("Query plan: {:?}", explain.plan);

// Batch operations with connection pooling let pool = ConnectionPool::new(10)?;

pool.batch(|conn| { for item in items { query!( "INSERT INTO items (name, price) VALUES (?, ?)", item.name, item.price ).execute_on(conn)?; } Ok(()) })?;

// Use indexes effectively // Create index query!("CREATE INDEX idx_user_email ON users(email)")?;

// Query will use index automatically let user: Option<User> = query!( "SELECT * FROM users WHERE email = ?", email ).first()?;

🎯 Best Practices

1. Always use parameterized queries - Zero SQL injection risk with compile-time safety 2. Use transactions for related operations - ACID compliance with automatic rollback 3. Handle errors with proper types - Leverage Rust's Result type for safety 4. Cache when appropriate - Built-in caching with TTL and tag invalidation 5. Profile slow queries - Automatic query profiling and analysis 6. Use indexes effectively - Query optimizer automatically selects best indexes 7. Limit result sets - Streaming support for large datasets 8. Use connection pooling - Automatic connection management and reuse

🔗 Related Functions

- prepare!() - Prepared statements with compile-time safety - transaction!() - Transaction management with automatic rollback - db!() - Database connection with connection pooling - schema!() - Schema builder with migrations - migrate!() - Database migrations with versioning

🚀 Performance Benchmarks

use tusklang_rust::{query, benchmark};

// Benchmark query performance let benchmark_result = benchmark!( "SELECT * FROM users WHERE email = ?", &["test@example.com"] )?;

println!("Average time: {:?}", benchmark_result.average_time); println!("Throughput: {} queries/sec", benchmark_result.throughput);

TuskLang Rust: Where zero-copy meets zero-compromise. Your database operations will never be the same.