Rename Value -> DbValue

This commit is contained in:
Eric Eastwood
2026-06-23 21:20:45 -05:00
parent f42ba674b6
commit c21dbbdc1f
3 changed files with 46 additions and 46 deletions
+28 -28
View File
@@ -95,7 +95,7 @@ pub trait Transaction: Send {
/// Each pool maps the values its database driver hands back into this common
/// set, so callers can work with one representation regardless of engine.
#[derive(Debug, Clone, PartialEq)]
pub enum Value {
pub enum DbValue {
/// A SQL `NULL`.
Null,
Bool(bool),
@@ -107,24 +107,24 @@ pub enum Value {
/// A row of data returned from the database by a query.
///
/// Each pool converts the cells its database driver hands back into the
/// engine-agnostic [`Value`] representation, so a row is simply a list of them.
/// engine-agnostic [`DbValue`] representation, so a row is simply a list of them.
/// Values are pulled out by their numeric index with [`RowExt::try_get`].
pub type Row = Vec<Value>;
pub type Row = Vec<DbValue>;
/// Extension methods for reading typed values out of a [`Row`].
///
/// Modelled after [`tokio_postgres::Row`]'s `try_get`: [`try_get`](Self::try_get)
/// converts the [`Value`] at a given index into the requested type via
/// [`FromValue`] (our analogue of `tokio-postgres`'s `FromSql`).
/// converts the [`DbValue`] at a given index into the requested type via
/// [`FromDbValue`] (our analogue of `tokio-postgres`'s `FromSql`).
pub trait RowExt {
/// Deserializes a value from the row, specified by its numeric index,
/// returning an error if the index is out of bounds or the value cannot be
/// converted into `T`.
fn try_get<T: FromValue>(&self, index: usize) -> Result<T, anyhow::Error>;
fn try_get<T: FromDbValue>(&self, index: usize) -> Result<T, anyhow::Error>;
}
impl RowExt for Row {
fn try_get<T: FromValue>(&self, index: usize) -> Result<T, anyhow::Error> {
fn try_get<T: FromDbValue>(&self, index: usize) -> Result<T, anyhow::Error> {
let value = self.get(index).cloned().ok_or_else(|| {
anyhow::anyhow!(
"tried to get column {index} but the row only has {} column(s)",
@@ -136,56 +136,56 @@ impl RowExt for Row {
}
}
/// Converts a backend-agnostic [`Value`] into a concrete Rust type, analogous to
/// Converts a backend-agnostic [`DbValue`] into a concrete Rust type, analogous to
/// `tokio-postgres`'s `FromSql`.
pub trait FromValue: Sized {
fn from_value(value: Value) -> Result<Self, anyhow::Error>;
pub trait FromDbValue: Sized {
fn from_value(value: DbValue) -> Result<Self, anyhow::Error>;
}
impl FromValue for bool {
fn from_value(value: Value) -> Result<Self, anyhow::Error> {
impl FromDbValue for bool {
fn from_value(value: DbValue) -> Result<Self, anyhow::Error> {
match value {
Value::Bool(b) => Ok(b),
DbValue::Bool(b) => Ok(b),
// SQLite has no native boolean type and stores them as integers.
Value::Int(i) => Ok(i != 0),
DbValue::Int(i) => Ok(i != 0),
other => anyhow::bail!("cannot read {other:?} as bool"),
}
}
}
impl FromValue for i64 {
fn from_value(value: Value) -> Result<Self, anyhow::Error> {
impl FromDbValue for i64 {
fn from_value(value: DbValue) -> Result<Self, anyhow::Error> {
match value {
Value::Int(i) => Ok(i),
Value::Bool(b) => Ok(b as i64),
DbValue::Int(i) => Ok(i),
DbValue::Bool(b) => Ok(b as i64),
other => anyhow::bail!("cannot read {other:?} as i64"),
}
}
}
impl FromValue for f64 {
fn from_value(value: Value) -> Result<Self, anyhow::Error> {
impl FromDbValue for f64 {
fn from_value(value: DbValue) -> Result<Self, anyhow::Error> {
match value {
Value::Float(f) => Ok(f),
Value::Int(i) => Ok(i as f64),
DbValue::Float(f) => Ok(f),
DbValue::Int(i) => Ok(i as f64),
other => anyhow::bail!("cannot read {other:?} as f64"),
}
}
}
impl FromValue for String {
fn from_value(value: Value) -> Result<Self, anyhow::Error> {
impl FromDbValue for String {
fn from_value(value: DbValue) -> Result<Self, anyhow::Error> {
match value {
Value::Text(s) => Ok(s),
DbValue::Text(s) => Ok(s),
other => anyhow::bail!("cannot read {other:?} as String"),
}
}
}
impl<T: FromValue> FromValue for Option<T> {
fn from_value(value: Value) -> Result<Self, anyhow::Error> {
impl<T: FromDbValue> FromDbValue for Option<T> {
fn from_value(value: DbValue) -> Result<Self, anyhow::Error> {
match value {
Value::Null => Ok(None),
DbValue::Null => Ok(None),
other => Ok(Some(T::from_value(other)?)),
}
}
+9 -9
View File
@@ -31,7 +31,7 @@ use pyo3::{
};
use crate::deferred::run_python_awaitable;
use crate::storage::db::{DatabasePool, Row, Transaction, Value};
use crate::storage::db::{DatabasePool, DbValue, Row, Transaction};
/// The database engines we support in the Python side of Synapse
#[derive(Copy, Clone, Debug)]
@@ -276,7 +276,7 @@ impl Transaction for LoggingTransactionWrapper {
self.execute(py, sql, args.as_any())?;
// Pull the rows back out, converting each cell from its Python type
// into the engine-agnostic `Value` representation as we go.
// into the engine-agnostic `DbValue` representation as we go.
let rows_py = self
.logging_transaction_py
.bind(py)
@@ -298,23 +298,23 @@ impl Transaction for LoggingTransactionWrapper {
}
}
/// Convert a single cell from a Python row into a backend-agnostic [`Value`] by
/// Convert a single cell from a Python row into a backend-agnostic [`DbValue`] by
/// inspecting its Python type (the pyo3 equivalent of `isinstance` checks).
fn py_cell_to_value(cell: &Bound<'_, PyAny>) -> PyResult<Value> {
fn py_cell_to_value(cell: &Bound<'_, PyAny>) -> PyResult<DbValue> {
// `None` maps to SQL `NULL`.
if cell.is_none() {
return Ok(Value::Null);
return Ok(DbValue::Null);
}
// A `bool` *is* an `int` in SQLite, so ensure we try `bool` first.
if let Ok(b) = cell.cast::<PyBool>() {
Ok(Value::Bool(b.extract()?))
Ok(DbValue::Bool(b.extract()?))
} else if let Ok(i) = cell.cast::<PyInt>() {
Ok(Value::Int(i.extract()?))
Ok(DbValue::Int(i.extract()?))
} else if let Ok(f) = cell.cast::<PyFloat>() {
Ok(Value::Float(f.extract()?))
Ok(DbValue::Float(f.extract()?))
} else if let Ok(s) = cell.cast::<PyString>() {
Ok(Value::Text(s.to_string()))
Ok(DbValue::Text(s.to_string()))
} else {
Err(PyTypeError::new_err(format!(
"unsupported column type {} returned from the database",
+9 -9
View File
@@ -22,7 +22,7 @@ use bb8_postgres::PostgresConnectionManager;
use futures::future::BoxFuture;
use postgres_native_tls::MakeTlsConnector;
use crate::storage::db::{DatabasePool, Row, Transaction, Value};
use crate::storage::db::{DatabasePool, DbValue, Row, Transaction};
/// Native Rust database access backed by `tokio-postgres` (for use in synapse-rust-apps)
pub struct RustDatabasePool {
@@ -119,25 +119,25 @@ fn tokio_row_to_row(row: &tokio_postgres::Row) -> Result<Row, anyhow::Error> {
.collect()
}
/// Convert a single cell of a [`tokio_postgres::Row`] into a [`Value`].
/// Convert a single cell of a [`tokio_postgres::Row`] into a [`DbValue`].
///
/// Dispatch on the column's Postgres type, leaning on `tokio-postgres`'s own
/// `FromSql` impls to read the cell. Everything is read as `Option<_>` so a SQL
/// `NULL` becomes `Value::Null`.
fn tokio_cell_to_value(row: &tokio_postgres::Row, index: usize) -> Result<Value, anyhow::Error> {
/// `NULL` becomes `DbValue::Null`.
fn tokio_cell_to_value(row: &tokio_postgres::Row, index: usize) -> Result<DbValue, anyhow::Error> {
if let Ok(value) = row.try_get::<_, Option<bool>>(index) {
Ok(value.map_or(Value::Null, Value::Bool))
Ok(value.map_or(DbValue::Null, DbValue::Bool))
} else if let Ok(value) = row.try_get::<_, Option<i64>>(index) {
Ok(value.map_or(Value::Null, Value::Int))
Ok(value.map_or(DbValue::Null, DbValue::Int))
} else if let Ok(value) = row.try_get::<_, Option<f64>>(index) {
Ok(value.map_or(Value::Null, Value::Float))
Ok(value.map_or(DbValue::Null, DbValue::Float))
} else if let Ok(value) = row.try_get::<_, Option<String>>(index) {
Ok(value.map_or(Value::Null, Value::Text))
Ok(value.map_or(DbValue::Null, DbValue::Text))
} else {
let ty = row.columns()[index].type_();
anyhow::bail!(
"Unsupported `tokio-postgres` type {} encountered when trying to convert it \
to our generic database `Value` type. You probably just need to implement it in `tokio_cell_to_value(...)`.",
to our generic database `DbValue` type. You probably just need to implement it in `tokio_cell_to_value(...)`.",
ty
)
}