mirror of
https://github.com/element-hq/synapse.git
synced 2026-09-02 07:03:46 +00:00
Introduce the Python<->Postgres value-mapping layer that the forthcoming Rust DBAPI2 backend will build on, plus the module scaffolding to hang it off (`synapse_rust.database.postgres`). `PgValue` is an owned representation of a bound parameter that implements `tokio_postgres::types::ToSql`, encoding into Postgres' binary wire format according to the column type from the prepared statement (so a single Python `int` becomes INT2/INT4/INT8 as appropriate, with range checks). `PythonPgFromSql` is the decode counterpart, turning a column's wire bytes back into the natural Python object (and SQL NULL into `None`). The two `accepts` lists are kept in sync via tests. The `value` submodule is exposed as `pub` for now so its not-yet-consumed public items don't trip clippy's `dead_code` lint; later changes that wire it into the cursor/connection code tighten that back up. Covers int / float / bool / str / bytes / None; lists and richer types (json, decimal, timestamps) are left to a follow-up. The unit tests exercise the whole mapping without a live Postgres server, including the float4 lossy narrowing, integer width boundaries, the WrongType and out-of-range paths, and the unsupported/non-UTF-8 decode errors. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
100 lines
2.6 KiB
Rust
100 lines
2.6 KiB
Rust
use std::convert::Infallible;
|
|
|
|
use lazy_static::lazy_static;
|
|
use pyo3::prelude::*;
|
|
use pyo3_log::ResetHandle;
|
|
|
|
pub mod acl;
|
|
pub mod canonical_json;
|
|
pub mod deferred;
|
|
pub mod database;
|
|
pub mod duration;
|
|
pub mod errors;
|
|
pub mod events;
|
|
pub mod http;
|
|
pub mod http_client;
|
|
pub mod identifier;
|
|
pub mod json;
|
|
pub mod matrix_const;
|
|
pub mod msc4388_rendezvous;
|
|
pub mod push;
|
|
pub mod rendezvous;
|
|
pub mod room_versions;
|
|
pub mod segmenter;
|
|
pub mod tokio_runtime;
|
|
pub mod types;
|
|
|
|
lazy_static! {
|
|
static ref LOGGING_HANDLE: ResetHandle = pyo3_log::init();
|
|
}
|
|
|
|
/// Returns the hash of all the rust source files at the time it was compiled.
|
|
///
|
|
/// Used by python to detect if the rust library is outdated.
|
|
#[pyfunction]
|
|
fn get_rust_file_digest() -> &'static str {
|
|
env!("SYNAPSE_RUST_DIGEST")
|
|
}
|
|
|
|
/// Returns the `rustc` version used when this native module was built.
|
|
///
|
|
/// This value is embedded at build time, so it can be exported as a prometheus metrics.
|
|
#[pyfunction]
|
|
pub fn get_rustc_version() -> &'static str {
|
|
env!("SYNAPSE_RUSTC_VERSION")
|
|
}
|
|
|
|
/// Formats the sum of two numbers as string.
|
|
#[pyfunction]
|
|
#[pyo3(text_signature = "(a, b, /)")]
|
|
fn sum_as_string(a: usize, b: usize) -> PyResult<String> {
|
|
Ok((a + b).to_string())
|
|
}
|
|
|
|
/// Reset the cached logging configuration of pyo3-log to pick up any changes
|
|
/// in the Python logging configuration.
|
|
///
|
|
#[pyfunction]
|
|
fn reset_logging_config() {
|
|
LOGGING_HANDLE.reset();
|
|
}
|
|
|
|
/// The entry point for defining the Python module.
|
|
#[pymodule]
|
|
fn synapse_rust(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
|
|
m.add_function(wrap_pyfunction!(sum_as_string, m)?)?;
|
|
m.add_function(wrap_pyfunction!(get_rust_file_digest, m)?)?;
|
|
m.add_function(wrap_pyfunction!(get_rustc_version, m)?)?;
|
|
m.add_function(wrap_pyfunction!(reset_logging_config, m)?)?;
|
|
|
|
acl::register_module(py, m)?;
|
|
<<<<<<< HEAD
|
|
deferred::register_module(py, m)?;
|
|
=======
|
|
database::register_module(py, m)?;
|
|
>>>>>>> 64f21f936a (Add Postgres value mapping for the Rust database backend)
|
|
push::register_module(py, m)?;
|
|
events::register_module(py, m)?;
|
|
http_client::register_module(py, m)?;
|
|
rendezvous::register_module(py, m)?;
|
|
msc4388_rendezvous::register_module(py, m)?;
|
|
segmenter::register_module(py, m)?;
|
|
room_versions::register_module(py, m)?;
|
|
types::register_module(py, m)?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub trait UnwrapInfallible<T> {
|
|
fn unwrap_infallible(self) -> T;
|
|
}
|
|
|
|
impl<T> UnwrapInfallible<T> for Result<T, Infallible> {
|
|
fn unwrap_infallible(self) -> T {
|
|
match self {
|
|
Ok(val) => val,
|
|
Err(never) => match never {},
|
|
}
|
|
}
|
|
}
|