pub struct SessionImpl {Show 13 fields
env: FrontendEnv,
auth_context: Arc<AuthContext>,
user_authenticator: UserAuthenticator,
config_map: Arc<RwLock<SessionConfig>>,
notices: RwLock<Vec<String>>,
id: (i32, i32),
peer_addr: AddressRef,
txn: Arc<Mutex<State>>,
current_query_cancel_flag: Mutex<Option<ShutdownSender>>,
exec_context: Mutex<Option<Weak<ExecContext>>>,
last_idle_instant: Arc<Mutex<Option<Instant>>>,
cursor_manager: Arc<CursorManager>,
temporary_source_manager: Arc<Mutex<TemporarySourceManager>>,
}
Fields§
§env: FrontendEnv
§auth_context: Arc<AuthContext>
§user_authenticator: UserAuthenticator
Used for user authentication.
config_map: Arc<RwLock<SessionConfig>>
Stores the value of configurations.
notices: RwLock<Vec<String>>
buffer the Notices to users,
id: (i32, i32)
Identified by process_id
, secret_key
. Corresponds to SessionManager
.
peer_addr: AddressRef
Client address
txn: Arc<Mutex<State>>
Transaction state.
TODO: get rid of the Mutex
here as a workaround if the Send
requirement of
async functions, there should actually be no contention.
current_query_cancel_flag: Mutex<Option<ShutdownSender>>
Query cancel flag. This flag is set only when current query is executed in local mode, and used to cancel local query.
exec_context: Mutex<Option<Weak<ExecContext>>>
execution context represents the lifetime of a running SQL in the current session
last_idle_instant: Arc<Mutex<Option<Instant>>>
Last idle instant
cursor_manager: Arc<CursorManager>
§temporary_source_manager: Arc<Mutex<TemporarySourceManager>>
temporary sources for the current session
Implementations§
source§impl SessionImpl
impl SessionImpl
sourcepub fn check_privileges(&self, items: &[ObjectCheckItem]) -> Result<(), RwError>
pub fn check_privileges(&self, items: &[ObjectCheckItem]) -> Result<(), RwError>
Check whether the user of the current session has privileges in items
.
sourcepub fn is_super_user(&self) -> bool
pub fn is_super_user(&self) -> bool
Returns true
if the user of the current session is a super user.
sourcepub fn check_privilege_for_drop_alter(
&self,
schema_name: &str,
relation: &impl OwnedByUserCatalog,
) -> Result<(), RwError>
pub fn check_privilege_for_drop_alter( &self, schema_name: &str, relation: &impl OwnedByUserCatalog, ) -> Result<(), RwError>
Check whether the user of the current session has the privilege to drop or alter the
relation relation
in the schema with name schema_name
.
Note that the right to drop or alter in PostgreSQL is special and not covered by the general
GRANT
s.
The right to drop an object, or to alter its definition in any way, is not treated as a grantable privilege; it is inherent in the owner, and cannot be granted or revoked.
Reference: https://www.postgresql.org/docs/current/sql-grant.html
sourcepub fn check_privilege_for_drop_alter_db_schema(
&self,
db_schema: &impl OwnedByUserCatalog,
) -> Result<(), RwError>
pub fn check_privilege_for_drop_alter_db_schema( &self, db_schema: &impl OwnedByUserCatalog, ) -> Result<(), RwError>
Check whether the user of the current session has the privilege to drop or alter the
db_schema
, which is either a database or schema.
Only the owner of the database, or a superuser, can drop a database.
Reference: https://www.postgresql.org/docs/current/manage-ag-dropdb.html
A schema can only be dropped by its owner or a superuser.
Reference: https://www.postgresql.org/docs/current/sql-dropschema.html
source§impl SessionImpl
impl SessionImpl
sourcepub fn txn_begin_implicit(&self) -> ImplicitAutoCommitGuard
pub fn txn_begin_implicit(&self) -> ImplicitAutoCommitGuard
Starts an implicit transaction if there’s no explicit transaction in progress. Called at the beginning of handling each statement.
Returns a guard that auto commits the implicit transaction when dropped.
sourcepub fn txn_begin_explicit(&self, access_mode: AccessMode)
pub fn txn_begin_explicit(&self, access_mode: AccessMode)
Starts an explicit transaction with the specified access mode from START TRANSACTION
.
sourcepub fn txn_commit_explicit(&self)
pub fn txn_commit_explicit(&self)
Commits an explicit transaction.
sourcepub fn txn_rollback_explicit(&self)
pub fn txn_rollback_explicit(&self)
Rollbacks an explicit transaction.
pub fn get_pinned_snapshot(&self) -> Option<ReadSnapshot>
sourcepub fn unpin_snapshot(&self)
pub fn unpin_snapshot(&self)
Unpin snapshot by replacing the snapshot with None.
sourcepub fn pinned_snapshot(&self) -> ReadSnapshot
pub fn pinned_snapshot(&self) -> ReadSnapshot
Acquires and pins a snapshot for the current transaction.
If a snapshot is already acquired, returns it directly.
source§impl SessionImpl
impl SessionImpl
sourcepub fn txn_write_guard(&self) -> Result<WriteGuard, RwError>
pub fn txn_write_guard(&self) -> Result<WriteGuard, RwError>
Returns a WriteGuard
, or an error if write operations are not permitted in the current
transaction.
sourcepub fn catalog_writer(&self) -> Result<&dyn CatalogWriter, RwError>
pub fn catalog_writer(&self) -> Result<&dyn CatalogWriter, RwError>
Returns the catalog writer, if write operations are permitted in the current transaction.
sourcepub fn user_info_writer(&self) -> Result<&dyn UserInfoWriter, RwError>
pub fn user_info_writer(&self) -> Result<&dyn UserInfoWriter, RwError>
Returns the user info writer, if write operations are permitted in the current transaction.
source§impl SessionImpl
impl SessionImpl
pub fn new( env: FrontendEnv, auth_context: Arc<AuthContext>, user_authenticator: UserAuthenticator, id: SessionId, peer_addr: AddressRef, session_config: SessionConfig, ) -> Self
pub fn env(&self) -> &FrontendEnv
pub fn auth_context(&self) -> Arc<AuthContext>
pub fn database(&self) -> &str
pub fn user_name(&self) -> &str
pub fn user_id(&self) -> u32
pub fn config(&self) -> RwLockReadGuard<'_, SessionConfig>
pub fn set_config(&self, key: &str, value: String) -> Result<String, RwError>
pub fn set_config_report( &self, key: &str, value: Option<String>, reporter: impl ConfigReporter, ) -> Result<String, RwError>
pub fn session_id(&self) -> SessionId
pub fn running_sql(&self) -> Option<Arc<str>>
pub fn get_cursor_manager(&self) -> Arc<CursorManager>
pub fn peer_addr(&self) -> &Address
pub fn elapse_since_running_sql(&self) -> Option<u128>
pub fn elapse_since_last_idle_instant(&self) -> Option<u128>
pub fn check_relation_name_duplicated( &self, name: ObjectName, stmt_type: StatementType, if_not_exists: bool, ) -> Result<Either<(), RwPgResponse>, CheckRelationError>
pub fn check_secret_name_duplicated( &self, name: ObjectName, ) -> Result<(), RwError>
pub fn check_connection_name_duplicated( &self, name: ObjectName, ) -> Result<(), RwError>
sourcepub fn get_database_and_schema_id_for_create(
&self,
schema_name: Option<String>,
) -> Result<(u32, u32), RwError>
pub fn get_database_and_schema_id_for_create( &self, schema_name: Option<String>, ) -> Result<(u32, u32), RwError>
Also check if the user has the privilege to create in the schema.
pub fn get_connection_by_name( &self, schema_name: Option<String>, connection_name: &str, ) -> Result<Arc<ConnectionCatalog>, RwError>
pub fn get_subscription_by_schema_id_name( &self, schema_id: u32, subscription_name: &str, ) -> Result<Arc<SubscriptionCatalog>, RwError>
pub fn get_subscription_by_name( &self, schema_name: Option<String>, subscription_name: &str, ) -> Result<Arc<SubscriptionCatalog>, RwError>
pub fn get_table_by_id( &self, table_id: &TableId, ) -> Result<Arc<TableCatalog>, RwError>
pub fn get_table_by_name( &self, table_name: &str, db_id: u32, schema_id: u32, ) -> Result<Arc<TableCatalog>, RwError>
pub fn get_secret_by_name( &self, schema_name: Option<String>, secret_name: &str, ) -> Result<Arc<SecretCatalog>, RwError>
pub fn list_change_log_epochs( &self, table_id: u32, min_epoch: u64, max_count: u32, ) -> Result<Vec<u64>, RwError>
pub fn clear_cancel_query_flag(&self)
pub fn reset_cancel_query_flag(&self) -> ShutdownToken
fn clear_notices(&self)
pub fn cancel_current_query(&self)
pub fn cancel_current_creating_job(&self)
sourcepub async fn run_statement(
self: Arc<Self>,
sql: Arc<str>,
formats: Vec<Format>,
) -> Result<PgResponse<PgResponseStream>, BoxedError>
pub async fn run_statement( self: Arc<Self>, sql: Arc<str>, formats: Vec<Format>, ) -> Result<PgResponse<PgResponseStream>, BoxedError>
This function only used for test now. Maybe we can remove it in the future.
pub fn notice_to_user(&self, str: impl Into<String>)
pub fn is_barrier_read(&self) -> bool
pub fn statement_timeout(&self) -> Duration
pub fn create_temporary_source(&self, source: SourceCatalog)
pub fn get_temporary_source(&self, name: &str) -> Option<SourceCatalog>
pub fn drop_temporary_source(&self, name: &str)
pub fn temporary_source_manager(&self) -> TemporarySourceManager
pub async fn check_cluster_limits(&self) -> Result<(), RwError>
Trait Implementations§
source§impl Session for SessionImpl
impl Session for SessionImpl
source§async fn run_one_query(
self: Arc<Self>,
stmt: Statement,
format: Format,
) -> Result<PgResponse<PgResponseStream>, BoxedError>
async fn run_one_query( self: Arc<Self>, stmt: Statement, format: Format, ) -> Result<PgResponse<PgResponseStream>, BoxedError>
A copy of run_statement
but exclude the parser part so each run must be at most one
statement. The str sql use the to_string
of AST. Consider Reuse later.
source§fn init_exec_context(&self, sql: Arc<str>) -> ExecContextGuard
fn init_exec_context(&self, sql: Arc<str>) -> ExecContextGuard
Init and return an ExecContextGuard
which could be used as a guard to represent the execution flow.
source§fn check_idle_in_transaction_timeout(&self) -> PsqlResult<()>
fn check_idle_in_transaction_timeout(&self) -> PsqlResult<()>
Check whether idle transaction timeout.
If yes, unpin snapshot and return an IdleInTxnTimeout
error.
type Portal = Portal
type PreparedStatement = PrepareStatement
type ValuesStream = PgResponseStream
fn user_authenticator(&self) -> &UserAuthenticator
fn id(&self) -> SessionId
async fn parse( self: Arc<Self>, statement: Option<Statement>, params_types: Vec<Option<DataType>>, ) -> Result<PrepareStatement, BoxedError>
fn bind( self: Arc<Self>, prepare_statement: PrepareStatement, params: Vec<Option<Bytes>>, param_formats: Vec<Format>, result_formats: Vec<Format>, ) -> Result<Portal, BoxedError>
async fn execute( self: Arc<Self>, portal: Portal, ) -> Result<PgResponse<PgResponseStream>, BoxedError>
fn describe_statement( self: Arc<Self>, prepare_statement: PrepareStatement, ) -> Result<(Vec<DataType>, Vec<PgFieldDescriptor>), BoxedError>
fn describe_portal( self: Arc<Self>, portal: Portal, ) -> Result<Vec<PgFieldDescriptor>, BoxedError>
fn set_config(&self, key: &str, value: String) -> Result<String, BoxedError>
source§fn take_notices(self: Arc<Self>) -> Vec<String>
fn take_notices(self: Arc<Self>) -> Vec<String>
fn transaction_status(&self) -> TransactionStatus
Auto Trait Implementations§
impl !Freeze for SessionImpl
impl !RefUnwindSafe for SessionImpl
impl Send for SessionImpl
impl Sync for SessionImpl
impl Unpin for SessionImpl
impl !UnwindSafe for SessionImpl
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Conv for T
impl<T> Conv for T
§impl<Choices> CoproductSubsetter<CNil, HNil> for Choices
impl<Choices> CoproductSubsetter<CNil, HNil> for Choices
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self>
fn with_context(self, otel_cx: Context) -> WithContext<Self>
§fn with_current_context(self) -> WithContext<Self>
fn with_current_context(self) -> WithContext<Self>
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoEither for T
impl<T> IntoEither for T
source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left
is true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self
into a Left
variant of Either<Self, Self>
if into_left(&self)
returns true
.
Converts self
into a Right
variant of Either<Self, Self>
otherwise. Read moresource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T
in a tonic::Request
§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
type Err = Infallible
fn into_result(self) -> Result<T, <T as IntoResult<T>>::Err>
§impl<T, U, I> LiftInto<U, I> for Twhere
U: LiftFrom<T, I>,
impl<T, U, I> LiftInto<U, I> for Twhere
U: LiftFrom<T, I>,
source§impl<M> MetricVecRelabelExt for M
impl<M> MetricVecRelabelExt for M
source§fn relabel(
self,
metric_level: MetricLevel,
relabel_threshold: MetricLevel,
) -> RelabeledMetricVec<M>
fn relabel( self, metric_level: MetricLevel, relabel_threshold: MetricLevel, ) -> RelabeledMetricVec<M>
RelabeledMetricVec::with_metric_level
.source§fn relabel_n(
self,
metric_level: MetricLevel,
relabel_threshold: MetricLevel,
relabel_num: usize,
) -> RelabeledMetricVec<M>
fn relabel_n( self, metric_level: MetricLevel, relabel_threshold: MetricLevel, relabel_num: usize, ) -> RelabeledMetricVec<M>
RelabeledMetricVec::with_metric_level_relabel_n
.source§fn relabel_debug_1(
self,
relabel_threshold: MetricLevel,
) -> RelabeledMetricVec<M>
fn relabel_debug_1( self, relabel_threshold: MetricLevel, ) -> RelabeledMetricVec<M>
RelabeledMetricVec::with_metric_level_relabel_n
with metric_level
set to
MetricLevel::Debug
and relabel_num
set to 1.§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<Source> Sculptor<HNil, HNil> for Source
impl<Source> Sculptor<HNil, HNil> for Source
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.