macro_rules! impl_query_exec {
(prepare($this:ident) $prepare:block) => {
pub async fn fetch_all(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<Vec<tokio_postgres::Row>> {
let (sql, params, tag) = $prepare;
match tag {
Some(tag) => conn.query_tagged(tag, &sql, ¶ms).await,
None => conn.query(&sql, ¶ms).await,
}
}
pub async fn fetch_all_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<Vec<T>> {
let rows = $this.fetch_all(conn).await?;
rows.iter().map(T::from_row).collect()
}
pub async fn fetch_one(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<tokio_postgres::Row> {
let (sql, params, tag) = $prepare;
match tag {
Some(tag) => conn.query_one_tagged(tag, &sql, ¶ms).await,
None => conn.query_one(&sql, ¶ms).await,
}
}
pub async fn fetch_one_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<T> {
let row = $this.fetch_one(conn).await?;
T::from_row(&row)
}
pub async fn fetch_opt(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<Option<tokio_postgres::Row>> {
let (sql, params, tag) = $prepare;
match tag {
Some(tag) => conn.query_opt_tagged(tag, &sql, ¶ms).await,
None => conn.query_opt(&sql, ¶ms).await,
}
}
pub async fn fetch_opt_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<Option<T>> {
let row = $this.fetch_opt(conn).await?;
row.as_ref().map(T::from_row).transpose()
}
pub async fn execute(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<u64> {
let (sql, params, tag) = $prepare;
match tag {
Some(tag) => conn.execute_tagged(tag, &sql, ¶ms).await,
None => conn.execute(&sql, ¶ms).await,
}
}
pub async fn stream(&$this, conn: &impl $crate::client::StreamingClient) -> $crate::error::OrmResult<$crate::client::RowStream> {
let (sql, params, tag) = $prepare;
match tag {
Some(tag) => conn.query_stream_tagged(tag, &sql, ¶ms).await,
None => conn.query_stream(&sql, ¶ms).await,
}
}
pub async fn stream_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::StreamingClient) -> $crate::error::OrmResult<super::stream::FromRowStream<T>> {
let stream = $this.stream(conn).await?;
Ok(super::stream::FromRowStream::new(stream))
}
pub async fn fetch_all_tagged(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<Vec<tokio_postgres::Row>> {
let (sql, params, _) = $prepare;
conn.query_tagged(tag, &sql, ¶ms).await
}
pub async fn fetch_all_tagged_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<Vec<T>> {
let rows = $this.fetch_all_tagged(conn, tag).await?;
rows.iter().map(T::from_row).collect()
}
pub async fn fetch_one_tagged(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<tokio_postgres::Row> {
let (sql, params, _) = $prepare;
conn.query_one_tagged(tag, &sql, ¶ms).await
}
pub async fn fetch_one_tagged_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<T> {
let row = $this.fetch_one_tagged(conn, tag).await?;
T::from_row(&row)
}
pub async fn fetch_opt_tagged(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<Option<tokio_postgres::Row>> {
let (sql, params, _) = $prepare;
conn.query_opt_tagged(tag, &sql, ¶ms).await
}
pub async fn fetch_opt_tagged_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<Option<T>> {
let row = $this.fetch_opt_tagged(conn, tag).await?;
row.as_ref().map(T::from_row).transpose()
}
pub async fn execute_tagged(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<u64> {
let (sql, params, _) = $prepare;
conn.execute_tagged(tag, &sql, ¶ms).await
}
pub async fn fetch_one_strict(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<tokio_postgres::Row> {
let (sql, params, tag) = $prepare;
match tag {
Some(tag) => conn.query_one_strict_tagged(tag, &sql, ¶ms).await,
None => conn.query_one_strict(&sql, ¶ms).await,
}
}
pub async fn fetch_one_strict_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<T> {
let row = $this.fetch_one_strict(conn).await?;
T::from_row(&row)
}
pub async fn fetch_one_strict_tagged(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<tokio_postgres::Row> {
let (sql, params, _) = $prepare;
conn.query_one_strict_tagged(tag, &sql, ¶ms).await
}
pub async fn fetch_one_strict_tagged_as<T: $crate::row::FromRow>(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<T> {
let row = $this.fetch_one_strict_tagged(conn, tag).await?;
T::from_row(&row)
}
pub async fn fetch_scalar_one<'__a, T>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<T>
where
T: for<'__b> tokio_postgres::types::FromSql<'__b> + Send + Sync,
{
let row = $this.fetch_one(conn).await?;
row.try_get(0)
.map_err(|e| $crate::error::OrmError::decode("0", e.to_string()))
}
pub async fn fetch_scalar_one_strict<'__a, T>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<T>
where
T: for<'__b> tokio_postgres::types::FromSql<'__b> + Send + Sync,
{
let row = $this.fetch_one_strict(conn).await?;
row.try_get(0)
.map_err(|e| $crate::error::OrmError::decode("0", e.to_string()))
}
pub async fn fetch_scalar_one_strict_tagged<'__a, T>(&$this, conn: &impl $crate::client::GenericClient, tag: &str) -> $crate::error::OrmResult<T>
where
T: for<'__b> tokio_postgres::types::FromSql<'__b> + Send + Sync,
{
let row = $this.fetch_one_strict_tagged(conn, tag).await?;
row.try_get(0)
.map_err(|e| $crate::error::OrmError::decode("0", e.to_string()))
}
pub async fn fetch_scalar_opt<'__a, T>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<Option<T>>
where
T: for<'__b> tokio_postgres::types::FromSql<'__b> + Send + Sync,
{
let row = $this.fetch_opt(conn).await?;
match row {
Some(r) => r.try_get(0).map(Some)
.map_err(|e| $crate::error::OrmError::decode("0", e.to_string())),
None => Ok(None),
}
}
pub async fn fetch_scalar_all<'__a, T>(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<Vec<T>>
where
T: for<'__b> tokio_postgres::types::FromSql<'__b> + Send + Sync,
{
let rows = $this.fetch_all(conn).await?;
rows.iter()
.map(|r| r.try_get(0)
.map_err(|e| $crate::error::OrmError::decode("0", e.to_string())))
.collect()
}
pub async fn exists(&$this, conn: &impl $crate::client::GenericClient) -> $crate::error::OrmResult<bool> {
let (sql, params, tag) = $prepare;
let inner_sql = sql.trim_end();
let inner_sql = inner_sql.strip_suffix(';').unwrap_or(inner_sql).trim_end();
let trimmed = super::strip_sql_prefix(inner_sql);
if !super::starts_with_keyword(trimmed, "SELECT")
&& !super::starts_with_keyword(trimmed, "WITH")
{
return Err($crate::error::OrmError::Validation(
"exists() only works with SELECT statements (including WITH ... SELECT)".to_string(),
));
}
let wrapped_sql = format!("SELECT EXISTS({inner_sql})");
let row = match tag {
Some(tag) => conn.query_one_tagged(tag, &wrapped_sql, ¶ms).await?,
None => conn.query_one(&wrapped_sql, ¶ms).await?,
};
row.try_get(0)
.map_err(|e| $crate::error::OrmError::decode("0", e.to_string()))
}
};
}