1use sofie_core::{ColumnReader, Result, SqlType, SqlValue, Uuid};
2
3use crate::{Db, Decoding, Dialect, RowSink};
4
5const MAX_RESERVED_ROWS: usize = 1000;
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
9pub enum Reach {
10 All,
11 AllAs(Uuid),
13 OwnedBy(Uuid),
14}
15
16impl Reach {
17 pub(crate) const fn owner(self) -> Option<Uuid> {
18 match self {
19 Self::All | Self::AllAs(_) => None,
20 Self::OwnedBy(owner) => Some(owner),
21 }
22 }
23
24 #[must_use]
25 pub const fn actor(self) -> Option<Uuid> {
26 match self {
27 Self::All => None,
28 Self::AllAs(actor) | Self::OwnedBy(actor) => Some(actor),
29 }
30 }
31}
32
33#[derive(Clone)]
35pub struct Read {
36 pub(crate) db: Db,
37 reach: Reach,
38}
39
40impl Read {
41 #[must_use]
42 pub fn within(db: &Db, reach: Reach) -> Self {
43 Self {
44 db: db.clone(),
45 reach,
46 }
47 }
48
49 pub(crate) fn owner(&self) -> Option<Uuid> {
50 self.reach.owner()
51 }
52
53 pub(crate) fn actor(&self) -> Option<Uuid> {
54 self.reach.actor()
55 }
56
57 pub(crate) fn across_owners(&self) -> Self {
58 let reach = self.reach.actor().map_or(Reach::All, Reach::AllAs);
59 Self::within(&self.db, reach)
60 }
61
62 pub(crate) fn dialect(&self) -> &dyn Dialect {
63 self.db.driver().dialect()
64 }
65
66 pub(crate) async fn decoded<T: Send>(
68 &self,
69 sql: &str,
70 params: &[SqlValue],
71 expected_rows: usize,
72 expects: Vec<Option<SqlType>>,
73 decode: impl FnMut(&mut dyn ColumnReader) -> Result<T> + Send,
74 ) -> Result<Vec<T>> {
75 let mut rows = Decoding::new(expects, decode);
76 rows.reserve(expected_rows.min(MAX_RESERVED_ROWS));
77 self.query(sql, params, &mut rows).await?;
78 Ok(rows.into_decoded())
79 }
80
81 async fn query(&self, sql: &str, params: &[SqlValue], rows: &mut dyn RowSink) -> Result<()> {
82 #[cfg(feature = "etag")]
83 if crate::read_versions::tracking() {
84 let mut fingerprinted = crate::read_versions::Fingerprinted::new(rows);
85 self.db
86 .driver()
87 .query(sql, params, &mut fingerprinted)
88 .await?;
89 fingerprinted.record();
90 return Ok(());
91 }
92 self.db.driver().query(sql, params, rows).await
93 }
94}