Skip to main content

icydb_core/db/session/
mod.rs

1//! Module: session
2//! Responsibility: user-facing query/write execution facade over db executors.
3//! Does not own: planning semantics, cursor validation rules, or storage mutation protocol.
4//! Boundary: converts fluent/query intent calls into executor operations and response DTOs.
5
6mod accepted_schema;
7mod bounded_cache;
8mod catalog;
9mod integrity;
10mod query;
11mod read_set;
12mod request;
13mod response;
14mod resumable_job;
15#[cfg(feature = "sql")]
16mod sql;
17mod write;
18
19#[cfg(all(test, feature = "sql", feature = "diagnostics"))]
20mod tests;
21
22use crate::metrics::sink::with_metrics_sink;
23use crate::{
24    db::{Db, StoreRegistry},
25    metrics::sink::MetricsSink,
26    traits::CanisterKind,
27};
28use std::thread::LocalKey;
29
30pub(in crate::db) use accepted_schema::AcceptedSchemaCatalogContext;
31#[cfg(all(test, feature = "sql", feature = "diagnostics"))]
32pub(in crate::db) use accepted_schema::{
33    AcceptedSchemaRuntimeBuildCounts, accepted_schema_runtime_build_counts_for_tests,
34    reset_accepted_schema_runtime_build_counts_for_tests,
35};
36#[cfg(all(feature = "sql", feature = "diagnostics"))]
37pub use query::{
38    DirectDataRowAttribution, GroupedCountAttribution, GroupedExecutionAttribution,
39    KernelRowAttribution, ScalarAggregateAttribution,
40};
41#[doc(hidden)]
42pub use query::{
43    MAX_TYPED_EXACT_KEY_BATCH_INPUT_BYTES, MAX_TYPED_EXACT_KEY_BATCH_ITEMS,
44    MAX_TYPED_EXACT_KEY_BATCH_RESULT_BYTES, MAX_TYPED_EXACT_KEY_BATCH_STORED_BYTES,
45};
46pub use request::RequestExecutionRoot;
47pub(in crate::db) use request::RequestExecutionScope;
48pub(in crate::db) use response::finalize_structural_grouped_projection_result;
49pub(in crate::db) use response::grouped_cursor_from_bytes;
50#[cfg(all(feature = "sql", feature = "diagnostics"))]
51pub use sql::{
52    SqlCompileAttribution, SqlExecutionAttribution, SqlHybridCoveringAttribution,
53    SqlOutputBlobAttribution, SqlPureCoveringAttribution, SqlQueryCacheAttribution,
54    SqlQueryExecutionAttribution,
55};
56#[cfg(feature = "sql")]
57pub use sql::{
58    SqlConstraintValidationPage, SqlConstraintValidationRevisionStatus,
59    SqlConstraintValidationState, SqlDdlExecutionStatus, SqlDdlMutationKind,
60    SqlDdlPreparationReport, SqlIntegrityError, SqlStatementDispatch, SqlStatementResult,
61    SqlStatementShellSurface, SqlStatementSurface, TrustedResumableUpdateContinuation,
62    TrustedResumableUpdatePhase, TrustedResumableUpdateReceipt,
63    TrustedResumableUpdateRestartReason, sql_statement_dispatch, sql_statement_entity_name,
64    sql_statement_shell_surface, sql_statement_surface,
65};
66#[cfg(feature = "sql")]
67pub(in crate::db::session) use write::{
68    AcceptedStructuralMutation, AcceptedStructuralMutationTarget,
69    structural_data_key_from_runtime_values,
70};
71
72///
73/// DbSession
74///
75/// Session-scoped database handle with policy (debug, metrics) and execution routing.
76///
77
78pub struct DbSession<C: CanisterKind> {
79    db: Db<C>,
80    debug: bool,
81    metrics: Option<&'static dyn MetricsSink>,
82}
83
84impl<C: CanisterKind> DbSession<C> {
85    /// Construct one session facade over a sealed runtime store registry.
86    #[must_use]
87    pub fn new(
88        store: &'static LocalKey<StoreRegistry>,
89        request_root: &RequestExecutionRoot,
90    ) -> Self {
91        Self {
92            db: Db::new(store, request_root.scope()),
93            debug: false,
94            metrics: None,
95        }
96    }
97
98    /// Construct a session from the active synchronous request scope.
99    ///
100    /// Generated zero-argument `db!()` wiring uses this entry. `None` means
101    /// that the caller did not establish a request execution boundary.
102    #[doc(hidden)]
103    #[must_use]
104    pub fn __new_from_current_request(store: &'static LocalKey<StoreRegistry>) -> Option<Self> {
105        request::current_request_scope().map(|scope| Self {
106            db: Db::new(store, scope),
107            debug: false,
108            metrics: None,
109        })
110    }
111
112    /// Enable debug execution behavior where supported by executors.
113    #[must_use]
114    pub const fn debug(mut self) -> Self {
115        self.debug = true;
116        self
117    }
118
119    /// Attach one metrics sink for all session-executed operations.
120    #[must_use]
121    pub const fn metrics_sink(mut self, sink: &'static dyn MetricsSink) -> Self {
122        self.metrics = Some(sink);
123        self
124    }
125
126    fn with_metrics<T>(&self, f: impl FnOnce() -> T) -> T {
127        if let Some(sink) = self.metrics {
128            with_metrics_sink(sink, f)
129        } else {
130            f()
131        }
132    }
133}