# sqlx-record Values Skill Guide to Value types and database binding. ## Triggers - "value type", "sql value" - "bind value", "query parameter" - "type conversion" ## Value Enum ```rust pub enum Value { // Integers Int8(i8), Uint8(u8), Int16(i16), Uint16(u16), Int32(i32), Uint32(u32), Int64(i64), Uint64(u64), // Other primitives String(String), Bool(bool), VecU8(Vec), // Special types Uuid(uuid::Uuid), NaiveDate(NaiveDate), NaiveDateTime(NaiveDateTime), } ``` ## Auto-Conversions (From trait) ```rust // Strings Value::from("hello") // String Value::from("hello".to_string()) // String // Integers Value::from(42i32) // Int32 Value::from(42i64) // Int64 Value::from(&42i32) // Int32 (from reference) Value::from(&42i64) // Int64 (from reference) // Boolean Value::from(true) // Bool Value::from(&true) // Bool (from reference) // UUID Value::from(uuid::Uuid::new_v4()) // Uuid Value::from(&some_uuid) // Uuid (from reference) // Dates Value::from(NaiveDate::from_ymd(2024, 1, 15)) // NaiveDate Value::from(NaiveDateTime::new(...)) // NaiveDateTime ``` ## values! Macro ```rust // Empty values![] // Single value (auto-converts) values!["hello"] values![42] values![true] // Multiple values values!["name", 30, true, uuid] // With explicit types values![ Value::String("test".into()), Value::Int32(42), Value::Bool(true) ] ``` ## Database-Specific Handling ### Unsigned Integers | Type | MySQL | PostgreSQL | SQLite | |------|-------|------------|--------| | Uint8 | Native u8 | Cast to i16 | Cast to i16 | | Uint16 | Native u16 | Cast to i32 | Cast to i32 | | Uint32 | Native u32 | Cast to i64 | Cast to i64 | | Uint64 | Native u64 | Cast to i64* | Cast to i64* | *Note: Uint64 values > i64::MAX will overflow when cast. ### UUID Storage | Database | Type | Notes | |----------|------|-------| | MySQL | BINARY(16) | Stored as bytes | | PostgreSQL | UUID | Native type | | SQLite | BLOB | Stored as bytes | ### JSON Storage | Database | Type | |----------|------| | MySQL | JSON | | PostgreSQL | JSONB | | SQLite | TEXT | ## Bind Functions ### bind_values Bind values to a raw Query: ```rust use sqlx_record::prelude::*; let query = sqlx::query("SELECT * FROM users WHERE name = ? AND age > ?"); let query = bind_values(query, &values!["Alice", 18]); let rows = query.fetch_all(&pool).await?; ``` ### bind_as_values Bind values to a typed QueryAs: ```rust let query = sqlx::query_as::<_, User>("SELECT * FROM users WHERE id = ?"); let query = bind_as_values(query, &values![user_id]); let user = query.fetch_optional(&pool).await?; ``` ### bind_scalar_values Bind values to a scalar QueryScalar: ```rust let query = sqlx::query_scalar("SELECT COUNT(*) FROM users WHERE active = ?"); let query = bind_scalar_values(query, &values![true]); let count: i64 = query.fetch_one(&pool).await?; ``` ## BindValues Trait Extension trait for fluent binding: ```rust use sqlx_record::prelude::BindValues; let users = sqlx::query_as::<_, User>("SELECT * FROM users WHERE role = ?") .bind_values(&values!["admin"]) .fetch_all(&pool) .await?; ``` ## Placeholder Function Database-specific placeholder generation: ```rust use sqlx_record::prelude::placeholder; let ph1 = placeholder(1); let ph2 = placeholder(2); // MySQL/SQLite: "?", "?" // PostgreSQL: "$1", "$2" let sql = format!("SELECT * FROM users WHERE id = {} AND role = {}", ph1, ph2); ``` ## With Filters Filters automatically use Value internally: ```rust // These are equivalent: filters![("name", "Alice")] filters![("name", Value::String("Alice".into()))] // Values are extracted for binding: let (where_clause, values) = Filter::build_where_clause(&filters); // values: Vec ``` ## Custom Queries with Values ```rust use sqlx_record::prelude::*; async fn complex_query(pool: &Pool, status: &str, min_age: i32) -> Result> { let values = values![status, min_age]; let sql = format!( "SELECT * FROM users WHERE status = {} AND age >= {} ORDER BY name", placeholder(1), placeholder(2) ); let query = sqlx::query_as::<_, User>(&sql); let query = bind_as_values(query, &values); query.fetch_all(pool).await } ``` ## Updater Enum For more complex update patterns: ```rust pub enum Updater<'a> { Set(&'a str, Value), // SET field = value Increment(&'a str, Value), // SET field = field + value Decrement(&'a str, Value), // SET field = field - value } ``` ## Type Helpers ### query_fields Extract field names from aliased field list: ```rust let fields = vec!["id", "name as user_name", "email"]; let result = query_fields(fields); // "id, name, email" ``` ## Common Patterns ### Dynamic WHERE Clause ```rust fn build_query(filters: &[(&str, Value)]) -> (String, Vec) { let mut conditions = Vec::new(); let mut values = Vec::new(); for (i, (field, value)) in filters.iter().enumerate() { conditions.push(format!("{} = {}", field, placeholder(i + 1))); values.push(value.clone()); } let where_clause = if conditions.is_empty() { String::new() } else { format!("WHERE {}", conditions.join(" AND ")) }; (where_clause, values) } ``` ### Batch Insert Values ```rust fn batch_values(users: &[User]) -> Vec { users.iter().flat_map(|u| { vec![ Value::Uuid(u.id), Value::String(u.name.clone()), Value::String(u.email.clone()), ] }).collect() } ```