Last active
September 28, 2016 12:42
-
-
Save tomaka/67b54450a2ea11cf2f894d3fedcf7247 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
macro_rules! query { | |
($db:ident, $query:expr, [$($param:expr),*], {$($out_field:ident: $ty:ty),+ }) => ({ | |
#[derive(Debug, Clone)] | |
#[allow(non_snake_case)] | |
struct Output { | |
$( | |
$out_field: $ty, | |
)+ | |
} | |
let stmt = $db.prepare_cached($query).unwrap(); | |
let rows = stmt.query(&[$($param),*]).unwrap(); | |
rows.into_iter() | |
.map(|row| { | |
Output { | |
$( | |
$out_field: match row.get_opt(stmt.columns().iter().position(|c| c.name() == stringify!($out_field)).expect(&format!("no field named {}", stringify!($out_field)))) { | |
Some(Ok(f)) => f, | |
Some(Err(err)) => panic!("Error while executing {:?}: {:?}", $query, err), | |
None => panic!("Index doesn't reference a column"), | |
} | |
),+ | |
} | |
}) | |
.collect::<Vec<_>>() | |
}); | |
} | |
macro_rules! query_single { | |
($db:ident, $query:expr, [$($param:expr),*], {$($out_field:ident:$ty:ty),+ }) => ({ | |
query!($db, $query, [$($param),*], {$($out_field:$ty),+}).into_iter().next() | |
}); | |
} | |
macro_rules! query_one_field { | |
($db:ident, $query:expr, [$($param:expr),*]) => ({ | |
let stmt = match $db.prepare_cached($query) { | |
Ok(stmt) => stmt, | |
Err(err) => panic!("Error while executing {:?}: {:?}", $query, err) | |
}; | |
let rows = stmt.query(&[$($param),*]).unwrap(); | |
rows.into_iter() | |
.map(|row| match row.get_opt(0) { | |
Some(Ok(v)) => v, | |
Some(Err(err)) => panic!("Error while reading result of {:?}: {:?}", $query, err), | |
None => panic!("No column in the query output") | |
}) | |
.collect::<Vec<_>>() | |
}); | |
} | |
macro_rules! query_single_one_field { | |
($db:ident, $query:expr, [$($param:expr),*]) => ({ | |
query_one_field!($db, $query, [$($param),*]).into_iter().next() | |
}); | |
} | |
// Example usages: | |
let user: Option<_> = query_single!(database, r#" | |
SELECT name, email FROM users WHERE id = $1 LIMIT 1 | |
"#, [&id], { name: Option<String>, email: String }); | |
let user = match user { Some(u) => u, None => return err_404!("User doesn't exist") }; | |
println!("user's email: ", user.email); | |
let users = query!(database, r#"SELECT id FROM users"#, [], { id: i32 }); | |
for user in users { | |
let id = user.id; | |
} | |
let email: Option<String> = query_single_one_field!(database, r#"SELECT email FROM users WHERE id = $1"#, [&id]); | |
let emails: Vec<String> = query_single_one_field!(database, r#"SELECT email FROM users"#, []); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment