Struct mz_adapter::catalog::ConnCatalog

source ·
pub struct ConnCatalog<'a> {
    state: Cow<'a, CatalogState>,
    unresolvable_ids: BTreeSet<CatalogItemId>,
    conn_id: ConnectionId,
    cluster: String,
    database: Option<DatabaseId>,
    search_path: Vec<(ResolvedDatabaseSpecifier, SchemaSpecifier)>,
    role_id: RoleId,
    prepared_statements: Option<&'a BTreeMap<String, PreparedStatement>>,
    notices_tx: UnboundedSender<AdapterNotice>,
}

Fields§

§state: Cow<'a, CatalogState>§unresolvable_ids: BTreeSet<CatalogItemId>

Because we don’t have any way of removing items from the catalog temporarily, we allow the ConnCatalog to pretend that a set of items don’t exist during resolution.

This feature is necessary to allow re-planning of statements, which is either incredibly useful or required when altering item definitions.

Note that uses of this field should be used by short-lived catalogs.

§conn_id: ConnectionId§cluster: String§database: Option<DatabaseId>§search_path: Vec<(ResolvedDatabaseSpecifier, SchemaSpecifier)>§role_id: RoleId§prepared_statements: Option<&'a BTreeMap<String, PreparedStatement>>§notices_tx: UnboundedSender<AdapterNotice>

Implementations§

source§

impl ConnCatalog<'_>

source

pub fn conn_id(&self) -> &ConnectionId

source

pub fn state(&self) -> &CatalogState

source

pub fn mark_id_unresolvable_for_replanning(&mut self, id: CatalogItemId)

Prevent planning from resolving item with the provided ID. Instead, return an error as if the item did not exist.

This feature is meant exclusively to permit re-planning statements during update operations and should not be used otherwise given its extremely “powerful” semantics.

§Panics

If the catalog’s role ID is not MZ_SYSTEM_ROLE_ID.

source

pub fn effective_search_path( &self, include_temp_schema: bool, ) -> Vec<(ResolvedDatabaseSpecifier, SchemaSpecifier)>

Returns the schemas:

  • mz_catalog
  • pg_catalog
  • temp (if requested)
  • all schemas from the session’s search_path var that exist
source§

impl ConnCatalog<'_>

Trait Implementations§

source§

impl ConnectionResolver for ConnCatalog<'_>

source§

impl<'a> Debug for ConnCatalog<'a>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl ExprHumanizer for ConnCatalog<'_>

source§

fn humanize_id(&self, id: GlobalId) -> Option<String>

Attempts to return a human-readable string for the relation identified by id.
source§

fn humanize_id_unqualified(&self, id: GlobalId) -> Option<String>

Same as above, but without qualifications, e.g., only foo for materialize.public.foo.
source§

fn humanize_id_parts(&self, id: GlobalId) -> Option<Vec<String>>

Like Self::humanize_id, but returns the constituent parts of the name as individual elements.
source§

fn humanize_scalar_type(&self, typ: &ScalarType) -> String

Returns a human-readable name for the specified scalar type.
source§

fn column_names_for_id(&self, id: GlobalId) -> Option<Vec<String>>

Returns a vector of column names for the relation identified by id.
source§

fn humanize_column(&self, id: GlobalId, column: usize) -> Option<String>

Returns the #column name for the relation identified by id.
source§

fn id_exists(&self, id: GlobalId) -> bool

Returns whether the specified id exists.
source§

fn humanize_column_type(&self, typ: &ColumnType) -> String

Returns a human-readable name for the specified column type.
source§

impl SessionCatalog for ConnCatalog<'_>

source§

fn minimal_qualification( &self, qualified_name: &QualifiedItemName, ) -> PartialItemName

Returns a PartialItemName with the minimum amount of qualifiers to unambiguously resolve the object.

source§

fn active_role_id(&self) -> &RoleId

Returns the id of the role that is issuing the query.
source§

fn get_prepared_statement_desc(&self, name: &str) -> Option<&StatementDesc>

Returns the descriptor of the named prepared statement on the session, or None if the prepared statement does not exist.
source§

fn active_database(&self) -> Option<&DatabaseId>

Returns the database to use if one is not explicitly specified.
source§

fn active_cluster(&self) -> &str

Returns the cluster to use if one is not explicitly specified.
source§

fn search_path(&self) -> &[(ResolvedDatabaseSpecifier, SchemaSpecifier)]

Returns the resolved search paths for the current user. (Invalid search paths are skipped.)
source§

fn resolve_database( &self, database_name: &str, ) -> Result<&dyn CatalogDatabase, SqlCatalogError>

Resolves the named database. Read more
source§

fn get_database(&self, id: &DatabaseId) -> &dyn CatalogDatabase

Gets a database by its ID. Read more
source§

fn get_databases(&self) -> Vec<&dyn CatalogDatabase>

Gets all databases.
source§

fn resolve_schema( &self, database_name: Option<&str>, schema_name: &str, ) -> Result<&dyn CatalogSchema, SqlCatalogError>

Resolves a partially-specified schema name. Read more
source§

fn resolve_schema_in_database( &self, database_spec: &ResolvedDatabaseSpecifier, schema_name: &str, ) -> Result<&dyn CatalogSchema, SqlCatalogError>

Resolves a schema name within a specified database. Read more
source§

fn get_schema( &self, database_spec: &ResolvedDatabaseSpecifier, schema_spec: &SchemaSpecifier, ) -> &dyn CatalogSchema

Gets a schema by its ID. Read more
source§

fn get_schemas(&self) -> Vec<&dyn CatalogSchema>

Gets all schemas.
source§

fn get_mz_internal_schema_id(&self) -> SchemaId

Gets the mz_internal schema id.
source§

fn get_mz_unsafe_schema_id(&self) -> SchemaId

Gets the mz_unsafe schema id.
source§

fn is_system_schema_specifier(&self, schema: SchemaSpecifier) -> bool

Returns true if schema is an internal system schema, false otherwise
source§

fn resolve_role( &self, role_name: &str, ) -> Result<&dyn CatalogRole, SqlCatalogError>

Resolves the named role.
source§

fn resolve_network_policy( &self, policy_name: &str, ) -> Result<&dyn CatalogNetworkPolicy, SqlCatalogError>

Resolves the named network policy.
source§

fn try_get_role(&self, id: &RoleId) -> Option<&dyn CatalogRole>

Gets a role by its ID.
source§

fn get_role(&self, id: &RoleId) -> &dyn CatalogRole

Gets a role by its ID. Read more
source§

fn get_roles(&self) -> Vec<&dyn CatalogRole>

Gets all roles.
source§

fn mz_system_role_id(&self) -> RoleId

Gets the id of the mz_system role.
source§

fn collect_role_membership(&self, id: &RoleId) -> BTreeSet<RoleId>

Collects all role IDs that id is transitively a member of.
source§

fn get_network_policy(&self, id: &NetworkPolicyId) -> &dyn CatalogNetworkPolicy

Resolves the named cluster. Gets a network_policy by its ID. Read more
source§

fn get_network_policies(&self) -> Vec<&dyn CatalogNetworkPolicy>

Gets all roles.
source§

fn resolve_cluster( &self, cluster_name: Option<&str>, ) -> Result<&dyn CatalogCluster<'_>, SqlCatalogError>

If the provided name is None, resolves the currently active cluster.
source§

fn resolve_cluster_replica( &self, cluster_replica_name: &QualifiedReplica, ) -> Result<&dyn CatalogClusterReplica<'_>, SqlCatalogError>

Resolves the named cluster replica.
source§

fn resolve_item( &self, name: &PartialItemName, ) -> Result<&dyn CatalogItem, SqlCatalogError>

Resolves a partially-specified item name, that is NOT a function or type. (For resolving functions or types, please use SessionCatalog::resolve_function or SessionCatalog::resolve_type.) Read more
source§

fn resolve_function( &self, name: &PartialItemName, ) -> Result<&dyn CatalogItem, SqlCatalogError>

Performs the same operation as SessionCatalog::resolve_item but for functions within the catalog.
source§

fn resolve_type( &self, name: &PartialItemName, ) -> Result<&dyn CatalogItem, SqlCatalogError>

Performs the same operation as SessionCatalog::resolve_item but for types within the catalog.
source§

fn get_system_type(&self, name: &str) -> &dyn CatalogItem

Gets a type named name from exactly one of the system schemas. Read more
source§

fn try_get_item(&self, id: &CatalogItemId) -> Option<&dyn CatalogItem>

Gets an item by its ID.
source§

fn try_get_item_by_global_id( &self, id: &GlobalId, ) -> Option<Box<dyn CatalogCollectionItem>>

Tries to get an item by a GlobalId, returning None if the GlobalId does not exist. Read more
source§

fn get_item(&self, id: &CatalogItemId) -> &dyn CatalogItem

Gets an item by its ID. Read more
source§

fn get_item_by_global_id(&self, id: &GlobalId) -> Box<dyn CatalogCollectionItem>

Gets an item by a GlobalId. Read more
source§

fn get_items(&self) -> Vec<&dyn CatalogItem>

Gets all items.
source§

fn get_item_by_name( &self, name: &QualifiedItemName, ) -> Option<&dyn SqlCatalogItem>

Looks up an item by its name.
source§

fn get_type_by_name( &self, name: &QualifiedItemName, ) -> Option<&dyn SqlCatalogItem>

Looks up a type by its name.
source§

fn get_cluster(&self, id: ClusterId) -> &dyn CatalogCluster<'_>

Gets a cluster by ID.
source§

fn get_clusters(&self) -> Vec<&dyn CatalogCluster<'_>>

Gets all clusters.
source§

fn get_cluster_replica( &self, cluster_id: ClusterId, replica_id: ReplicaId, ) -> &dyn CatalogClusterReplica<'_>

Gets a cluster replica by ID.
source§

fn get_cluster_replicas(&self) -> Vec<&dyn CatalogClusterReplica<'_>>

Gets all cluster replicas.
source§

fn get_system_privileges(&self) -> &PrivilegeMap

Gets all system privileges.
source§

fn get_default_privileges( &self, ) -> Vec<(&DefaultPrivilegeObject, Vec<&DefaultPrivilegeAclItem>)>

Gets all default privileges.
source§

fn find_available_name(&self, name: QualifiedItemName) -> QualifiedItemName

Finds a name like name that is not already in use. Read more
source§

fn resolve_full_name(&self, name: &QualifiedItemName) -> FullItemName

Returns a fully qualified human readable name from fully qualified non-human readable name
source§

fn resolve_full_schema_name(&self, name: &QualifiedSchemaName) -> FullSchemaName

Returns a fully qualified human readable schema name from fully qualified non-human readable schema name
source§

fn resolve_item_id(&self, global_id: &GlobalId) -> CatalogItemId

Returns the CatalogItemId for from a GlobalId.
source§

fn resolve_global_id( &self, item_id: &CatalogItemId, version: RelationVersionSelector, ) -> GlobalId

Returns the GlobalId for the specificed Catalog Item, at the specified version.
source§

fn config(&self) -> &CatalogConfig

Returns the configuration of the catalog.
source§

fn now(&self) -> EpochMillis

Returns the number of milliseconds since the system epoch. For normal use this means the Unix epoch. This can safely be mocked in tests and start at 0.
Returns the set of supported AWS PrivateLink availability zone ids.
source§

fn system_vars(&self) -> &SystemVars

Returns system vars
source§

fn system_vars_mut(&mut self) -> &mut SystemVars

Returns mutable system vars Read more
source§

fn get_owner_id(&self, id: &ObjectId) -> Option<RoleId>

Returns the RoleId of the owner of an object by its ID.
source§

fn get_privileges(&self, id: &SystemObjectId) -> Option<&PrivilegeMap>

Returns the PrivilegeMap of the object.
source§

fn object_dependents(&self, ids: &Vec<ObjectId>) -> Vec<ObjectId>

Returns all the IDs of all objects that depend on ids, including ids themselves. Read more
source§

fn item_dependents(&self, id: CatalogItemId) -> Vec<ObjectId>

Returns all the IDs of all objects that depend on id, including id themselves. Read more
source§

fn all_object_privileges(&self, object_type: SystemObjectType) -> AclMode

Returns all possible privileges associated with an object type.
source§

fn get_object_type(&self, object_id: &ObjectId) -> ObjectType

Returns the object type of object_id.
source§

fn get_system_object_type(&self, id: &SystemObjectId) -> SystemObjectType

Returns the system object type of id.
source§

fn add_notice(&self, notice: PlanNotice)

Adds a PlanNotice that will be displayed to the user if the plan successfully executes.
source§

fn get_item_comments( &self, id: &CatalogItemId, ) -> Option<&BTreeMap<Option<usize>, String>>

Returns the associated comments for the given id
source§

fn is_cluster_size_cc(&self, size: &str) -> bool

Reports whether the specified cluster size is a modern “cc” size rather than a legacy T-shirt size.
source§

fn active_database_name(&self) -> Option<&str>

Returns the database to use if one is not explicitly specified.
source§

fn resolve_item_or_type( &self, name: &PartialItemName, ) -> Result<&dyn CatalogItem, CatalogError>

Resolves name to a type or item, preferring the type if both exist.

Auto Trait Implementations§

§

impl<'a> Freeze for ConnCatalog<'a>

§

impl<'a> !RefUnwindSafe for ConnCatalog<'a>

§

impl<'a> Send for ConnCatalog<'a>

§

impl<'a> Sync for ConnCatalog<'a>

§

impl<'a> Unpin for ConnCatalog<'a>

§

impl<'a> !UnwindSafe for ConnCatalog<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> AsAny for T
where T: Any,

source§

fn as_any(&self) -> &(dyn Any + 'static)

source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T, U> CastInto<U> for T
where U: CastFrom<T>,

source§

fn cast_into(self) -> U

Performs the cast.
source§

impl<T> Conv for T

source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
source§

impl<T> FmtForward for T

source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T> FutureExt for T

source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> IntoRequest<T> for T

source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
source§

impl<T, U> OverrideFrom<Option<&T>> for U
where U: OverrideFrom<T>,

source§

fn override_from(self, layer: &Option<&T>) -> U

Override the configuration represented by Self with values from the given layer.
source§

impl<T> Pipe for T
where T: ?Sized,

source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
source§

impl<T> Pointable for T

source§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<P, R> ProtoType<R> for P
where R: RustType<P>,

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<'a, S, T> Semigroup<&'a S> for T
where T: Semigroup<S>,

source§

fn plus_equals(&mut self, rhs: &&'a S)

The method of std::ops::AddAssign, for types that do not implement AddAssign.
source§

impl<T> Tap for T

source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
source§

impl<T> TryConv for T

source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

source§

fn vzip(self) -> V

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more