pub struct Page<T> {
pub rows: Vec<T>,
pub total: i64,
}
impl<T> Default for Page<T> {
fn default() -> Self {
Self {
rows: Vec::new(),
total: 0,
}
}
}
fn inject_total_count(sql: &str) -> String {
if let Some(idx) = sql.find(" FROM ") {
let mut out = String::with_capacity(sql.len() + 48);
out.push_str(&sql[..idx]);
out.push_str(", COUNT(*) OVER () AS \"__rustango_total\"");
out.push_str(&sql[idx..]);
out
} else {
format!(
"/* rustango: fetch_paginated_on could not splice COUNT(*) OVER () \
into the compiled SELECT — anchor ` FROM ` not found. The query \
below will run unchanged but `total` will be 0. */ {sql}"
)
}
}
pub(super) fn paginated_statement(
d: &dyn crate::sql::Dialect,
select: &crate::core::SelectQuery,
) -> Result<crate::sql::CompiledStatement, crate::sql::SqlError> {
let distinct = match select.distinct {
Some(crate::core::DistinctMode::All) => true,
Some(crate::core::DistinctMode::On(_)) => d.name() == "postgres",
None => false,
};
if select.compound.is_empty() && distinct {
let mut b = crate::sql::writers::Sql::new(d);
crate::sql::writers::write_distinct_with_total(&mut b, select)?;
return Ok(b.finish());
}
if select.compound.is_empty() {
let stmt = d.compile_select(select)?;
return Ok(crate::sql::CompiledStatement {
sql: inject_total_count(&stmt.sql),
params: stmt.params,
});
}
let mut b = crate::sql::writers::Sql::new(d);
crate::sql::writers::write_compound_with_total(&mut b, select)?;
Ok(b.finish())
}