Skip to main content

nodedb_physical/physical_plan/document/
row_source.rs

1// SPDX-License-Identifier: Apache-2.0
2
3//! The relation a Control-Plane-orchestrated `INSERT ... SELECT`, `MERGE`, or
4//! `UPDATE ... FROM` reads its source rows from.
5
6use nodedb_types::QualifiedCollection;
7
8use crate::physical_plan::PhysicalPlan;
9
10/// Source relation of an orchestrated copy or join write.
11#[derive(
12    Debug,
13    Clone,
14    PartialEq,
15    serde::Serialize,
16    serde::Deserialize,
17    zerompk::ToMessagePack,
18    zerompk::FromMessagePack,
19)]
20pub enum RowSource {
21    /// A plain document scan, read page by page through
22    /// `DocumentOp::MaterializeScan`. The B-tree key cursor is stable under
23    /// concurrent writes, so the read has no row-count bound. The Control
24    /// Plane applies the WHERE filter, the offset, the limit, and the column
25    /// map to each page.
26    DocumentPages(DocumentPageSource),
27    /// Any other SELECT, lowered by the normal plan converter and read once
28    /// through the Data Plane dispatch funnel. It has exactly SELECT
29    /// semantics: engine, filters, ordering, distinct, windows, joins, `AS
30    /// OF`, and read policies all come from the normal pipeline, under the
31    /// normal result-byte budget.
32    Query(QuerySource),
33}
34
35/// A plain document scan source, read page by page.
36#[derive(
37    Debug,
38    Clone,
39    PartialEq,
40    serde::Serialize,
41    serde::Deserialize,
42    zerompk::ToMessagePack,
43    zerompk::FromMessagePack,
44)]
45pub struct DocumentPageSource {
46    pub collection: QualifiedCollection,
47    /// Serialized `Vec<ScanFilter>`: the WHERE clause, ANDed with the
48    /// collection's read policy by the RLS pass.
49    pub filters: Vec<u8>,
50    /// `FOR SYSTEM_TIME AS OF` cut, in epoch milliseconds. `None` reads the
51    /// current version.
52    pub system_as_of_ms: Option<i64>,
53    /// Matching rows skipped before the first row is read.
54    pub offset: usize,
55    /// Matching rows read after the offset. `None` reads every matching row.
56    pub limit: Option<usize>,
57    /// zerompk `Vec<ComputedColumn>`: one entry per target column, its alias
58    /// the target column and its expression the source-row expression.
59    /// Empty passes each source row through unchanged.
60    pub column_map: Vec<u8>,
61}
62
63/// A source SELECT read once as a whole relation.
64#[derive(
65    Debug,
66    Clone,
67    PartialEq,
68    serde::Serialize,
69    serde::Deserialize,
70    zerompk::ToMessagePack,
71    zerompk::FromMessagePack,
72)]
73pub struct QuerySource {
74    /// The lowered SELECT.
75    pub plan: Box<PhysicalPlan>,
76    /// zerompk `Vec<ComputedColumn>` that renames each output column to the
77    /// target column it writes. Empty passes each output row through
78    /// unchanged.
79    pub column_map: Vec<u8>,
80}
81
82impl RowSource {
83    /// A page source that reads every current row of `collection` unchanged.
84    pub fn whole_collection(collection: QualifiedCollection) -> Self {
85        RowSource::DocumentPages(DocumentPageSource {
86            collection,
87            filters: Vec::new(),
88            system_as_of_ms: None,
89            offset: 0,
90            limit: None,
91            column_map: Vec::new(),
92        })
93    }
94
95    /// The collection a page source scans. `None` for a query source, whose
96    /// collections are the ones its plan reads.
97    pub fn paged_collection(&self) -> Option<&QualifiedCollection> {
98        match self {
99            RowSource::DocumentPages(page) => Some(&page.collection),
100            RowSource::Query(_) => None,
101        }
102    }
103
104    /// The plan a query source runs. `None` for a page source.
105    pub fn query_plan(&self) -> Option<&PhysicalPlan> {
106        match self {
107            RowSource::DocumentPages(_) => None,
108            RowSource::Query(query) => Some(&query.plan),
109        }
110    }
111
112    /// A short label for logs and error messages: the paged collection, or
113    /// the primary collection of the query plan.
114    pub fn label(&self) -> &str {
115        match self {
116            RowSource::DocumentPages(page) => page.collection.as_str(),
117            RowSource::Query(query) => query.plan.collection().unwrap_or("<query>"),
118        }
119    }
120}