Skip to main content

cratestack_sql/values/
projection.rs

1/// Result of a `.select(...)`-projected read. Holds the model with
2/// only the selected columns populated — non-selected fields carry
3/// their type's `Default::default()` value (`""` for `String`, `0`
4/// for integers, `None` for `Option<T>`, etc.).
5///
6/// **Caller responsibility:** check [`Self::is_selected`] before
7/// reading a field if you need to distinguish "real zero-valued DB
8/// row" from "the runtime didn't fetch this column". For typical use
9/// — fetch one or two specific columns for a route that needs only
10/// those — just read the fields you asked for and don't read the
11/// others.
12///
13/// **Compile-time constraint:** every model field type must impl
14/// `Default`. The codegen emits a `#[derive(Default)]` on the model
15/// struct; any field type that doesn't satisfy `Default` (typically a
16/// `Json<MyCustomType>` where `MyCustomType` doesn't derive Default)
17/// becomes a compile error at the `include_server_schema!` /
18/// `include_embedded_schema!` boundary. Wrap the offending field in
19/// `Option` or derive `Default` on the custom struct.
20#[derive(Debug, Clone, PartialEq)]
21pub struct Projection<T> {
22    pub value: T,
23    pub selected: Vec<&'static str>,
24}
25
26impl<T> Projection<T> {
27    /// Consume the projection and return the underlying model. The
28    /// selection metadata is dropped — only do this when you already
29    /// know which fields you asked for.
30    pub fn into_inner(self) -> T {
31        self.value
32    }
33
34    /// Was this SQL column populated by the runtime? Pass the column's
35    /// SQL name (the `sql_name` from `ModelColumn`, typically the
36    /// snake_case form). Reading the corresponding Rust field is
37    /// only meaningful when this returns `true`.
38    pub fn is_selected(&self, column: &str) -> bool {
39        self.selected.iter().any(|name| *name == column)
40    }
41}