lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

authored_draft_row.rs (2949B)


      1 //! Bound result columns before SQLx materializes a stored authored revision.
      2 //! Invalid nullable metadata uses a noncanonical one-byte sentinel, never NULL:
      3 //! corruption must not turn into an accepted missing operation or scope.
      4 
      5 use radroots_storage::{Error, authored_draft::AuthoredDraftRevision};
      6 use sqlx::{Executor, Sqlite, sqlite::SqliteRow};
      7 
      8 macro_rules! select {
      9     ($suffix:literal) => {
     10         concat!(
     11             "SELECT
     12              CASE WHEN typeof(draft_id) = 'blob' AND octet_length(draft_id) = 16 THEN draft_id END AS draft_id,
     13              CASE WHEN typeof(revision) = 'integer' THEN revision END AS revision,
     14              CASE WHEN typeof(author) = 'blob' AND octet_length(author) = 32 THEN author END AS author,
     15              CASE WHEN typeof(stage) = 'integer' THEN stage END AS stage,
     16              CASE WHEN operation_id IS NULL OR (typeof(operation_id) = 'blob' AND octet_length(operation_id) = 16)
     17                   THEN operation_id ELSE X'00' END AS operation_id,
     18              CASE WHEN typeof(payload_sha256) = 'blob' AND octet_length(payload_sha256) = 32 THEN payload_sha256 END AS payload_sha256,
     19              CASE WHEN typeof(created_at_unix_ms) = 'integer' THEN created_at_unix_ms END AS created_at_unix_ms,
     20              CASE WHEN typeof(updated_at_unix_ms) = 'integer' THEN updated_at_unix_ms END AS updated_at_unix_ms,
     21              CASE WHEN typeof(snapshot) = 'blob' AND octet_length(snapshot) BETWEEN 1 AND 16777216 THEN snapshot END AS snapshot,
     22              CASE WHEN typeof(payload_schema) = 'text' AND octet_length(payload_schema) <= 128 THEN payload_schema END AS payload_schema,
     23              CASE WHEN payload_scope IS NULL OR (typeof(payload_scope) = 'blob' AND octet_length(payload_scope) = 32)
     24                   THEN payload_scope ELSE X'00' END AS payload_scope
     25              FROM radroots_runtime_authored_draft_revisions ",
     26             $suffix
     27         )
     28     };
     29 }
     30 
     31 const HEAD: &str = select!(
     32     "WHERE draft_id = ? AND ? IS NULL ORDER BY radroots_runtime_authored_draft_revisions.revision DESC LIMIT 1"
     33 );
     34 const REVISION: &str = select!("WHERE draft_id = ? AND revision = ?");
     35 
     36 pub(super) async fn load<'e>(
     37     executor: impl Executor<'e, Database = Sqlite>,
     38     key: &[u8; 16],
     39     revision: Option<AuthoredDraftRevision>,
     40 ) -> Result<Option<SqliteRow>, Error> {
     41     let selected = if revision.is_some() { REVISION } else { HEAD };
     42     let revision = revision
     43         .map(|value| super::i64_from_u64(value.get()))
     44         .transpose()?;
     45     // Both alternatives are closed compile-time SQL above. Every data value is
     46     // bound separately; this private helper accepts no caller-supplied SQL.
     47     sqlx::query(sqlx::AssertSqlSafe(selected))
     48         .bind(key.as_slice())
     49         .bind(revision)
     50         .fetch_optional(executor)
     51         .await
     52         .map_err(super::map_backend)
     53 }
     54 
     55 #[cfg(test)]
     56 #[cfg_attr(coverage_nightly, coverage(off))]
     57 #[path = "authored_draft_row_tests.rs"]
     58 mod tests;