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