@@ -56,11 +56,9 @@ use mz_license_keys::ValidatedLicenseKey;
5656use mz_ore:: metrics:: MetricsRegistry ;
5757use mz_ore:: now:: { EpochMillis , NowFn , SYSTEM_TIME } ;
5858use mz_ore:: result:: ResultExt as _;
59- use mz_ore:: soft_assert_or_log;
6059use mz_persist_client:: PersistClient ;
6160use mz_repr:: adt:: mz_acl_item:: { AclMode , PrivilegeMap } ;
6261use mz_repr:: explain:: ExprHumanizer ;
63- use mz_repr:: namespaces:: MZ_TEMP_SCHEMA ;
6462use mz_repr:: network_policy_id:: NetworkPolicyId ;
6563use mz_repr:: optimize:: OptimizerFeatures ;
6664use mz_repr:: role_id:: RoleId ;
@@ -1164,75 +1162,42 @@ impl Catalog {
11641162 self . state . try_get_role_auth_by_id ( id)
11651163 }
11661164
1167- /// Creates a new schema in the `Catalog` for temporary items
1168- /// indicated by the TEMPORARY or TEMP keywords.
1169- pub fn create_temporary_schema (
1170- & mut self ,
1171- conn_id : & ConnectionId ,
1172- owner_id : RoleId ,
1173- ) -> Result < ( ) , Error > {
1174- self . state . create_temporary_schema ( conn_id, owner_id)
1165+ /// Registers the connection's temporary namespace: the `uuid` <->
1166+ /// `conn_id` mapping used to stamp and apply durable temporary items
1167+ /// owned by the session. The `mz_temp` schema itself materializes when
1168+ /// the first temporary item is applied.
1169+ ///
1170+ /// The coordinator calls this at a session's first temporary-item
1171+ /// creation, strictly before the transaction that persists the item, and
1172+ /// guards on [`CatalogState::has_temporary_namespace`], so registering
1173+ /// an already-registered namespace is a bug.
1174+ pub fn register_temporary_namespace ( & mut self , conn_id : & ConnectionId , uuid : Uuid ) {
1175+ self . state
1176+ . temporary_namespaces
1177+ . register ( conn_id. clone ( ) , uuid) ;
11751178 }
11761179
11771180 fn item_exists_in_temp_schemas ( & self , conn_id : & ConnectionId , item_name : & str ) -> bool {
1178- // Temporary schemas are created lazily, so it's valid for one to not exist yet.
1181+ // A temporary namespace is registered at the connection's first
1182+ // temporary-item creation, so it's valid for one to not exist yet.
11791183 self . state
1180- . temporary_schemas
1181- . get ( conn_id)
1184+ . temporary_namespaces
1185+ . schema ( conn_id)
11821186 . map ( |schema| schema. items . contains_key ( item_name) )
11831187 . unwrap_or ( false )
11841188 }
11851189
1186- /// Drops schema for connection if it exists. Returns an error if it exists and has items.
1187- /// Returns Ok if conn_id's temp schema does not exist.
1188- pub fn drop_temporary_schema ( & mut self , conn_id : & ConnectionId ) -> Result < ( ) , Error > {
1189- let Some ( schema) = self . state . temporary_schemas . remove ( conn_id) else {
1190- return Ok ( ( ) ) ;
1191- } ;
1192- if !schema. items . is_empty ( ) {
1193- return Err ( Error :: new ( ErrorKind :: SchemaNotEmpty ( MZ_TEMP_SCHEMA . into ( ) ) ) ) ;
1194- }
1195- Ok ( ( ) )
1196- }
1197-
1198- /// Registers the session as an ephemeral owner: the `uuid` <-> `conn_id`
1199- /// mapping used to stamp and apply durable temporary items owned by the
1200- /// session.
1201- ///
1202- /// The coordinator calls this at a session's first temporary-item
1203- /// creation, strictly before the transaction that persists the item, and
1204- /// guards on [`CatalogState::is_ephemeral_owner`], so registering an
1205- /// already-registered connection is a bug.
1206- pub fn register_ephemeral_owner ( & mut self , uuid : Uuid , conn_id : ConnectionId ) {
1207- let prev = self
1208- . state
1209- . ephemeral_owner_conns_by_uuid
1210- . insert ( uuid, conn_id. clone ( ) ) ;
1211- soft_assert_or_log ! (
1212- prev. is_none( ) ,
1213- "duplicate ephemeral owner registration for {uuid}"
1214- ) ;
1215- self . state
1216- . ephemeral_owner_uuids_by_conn
1217- . insert ( conn_id, uuid) ;
1218- }
1219-
1220- /// Removes the ephemeral-owner registration for `conn_id`.
1190+ /// Removes the connection's temporary namespace, if it has one. Returns
1191+ /// Ok if none exists.
12211192 ///
1222- /// Callers guard on [`CatalogState::is_ephemeral_owner`], so
1223- /// unregistering an unregistered connection is a bug. They must also
1224- /// only do this after the transaction dropping the session's temporary
1225- /// items has been applied, since applying an ephemeral item update
1226- /// resolves the owning connection through this mapping.
1227- pub fn unregister_ephemeral_owner ( & mut self , conn_id : & ConnectionId ) {
1228- let uuid = self . state . ephemeral_owner_uuids_by_conn . remove ( conn_id) ;
1229- soft_assert_or_log ! (
1230- uuid. is_some( ) ,
1231- "no ephemeral owner registration for {conn_id}"
1232- ) ;
1233- if let Some ( uuid) = uuid {
1234- self . state . ephemeral_owner_conns_by_uuid . remove ( & uuid) ;
1235- }
1193+ /// Callers must only do this after the transaction dropping the
1194+ /// session's temporary items has been applied, since applying an
1195+ /// ephemeral item update resolves the owning connection through the
1196+ /// namespace. If the schema still contains items (the drop transaction
1197+ /// failed, e.g. because this process is being fenced out), this returns
1198+ /// an error and leaves the namespace fully in place.
1199+ pub fn drop_temporary_namespace ( & mut self , conn_id : & ConnectionId ) -> Result < ( ) , Error > {
1200+ self . state . temporary_namespaces . unregister ( conn_id)
12361201 }
12371202
12381203 pub ( crate ) fn object_dependents (
@@ -2077,7 +2042,7 @@ impl SessionCatalog for ConnCatalog<'_> {
20772042 self . state
20782043 . ambient_schemas_by_id
20792044 . values ( )
2080- . chain ( self . state . temporary_schemas . values ( ) )
2045+ . chain ( self . state . temporary_namespaces . schemas ( ) )
20812046 . map ( |schema| schema as & dyn CatalogSchema ) ,
20822047 )
20832048 . collect ( )
@@ -2811,6 +2776,10 @@ mod tests {
28112776 ]
28122777 ) ;
28132778
2779+ // A session's temporary namespace is registered at its first
2780+ // temporary-item creation, so until then `mz_temp` drops out of
2781+ // the resolved search path and temporary resolution comes only
2782+ // from the implicit leading temporary schema.
28142783 let mut session = Session :: dummy ( ) ;
28152784 session
28162785 . vars_mut ( )
@@ -2822,25 +2791,14 @@ mod tests {
28222791 )
28232792 . expect ( "failed to set search_path" ) ;
28242793 let conn_catalog = catalog. for_session ( & session) ;
2825- assert_ne ! (
2826- conn_catalog. effective_search_path( false ) ,
2827- conn_catalog. search_path
2828- ) ;
2829- assert_ne ! (
2830- conn_catalog. effective_search_path( true ) ,
2831- conn_catalog. search_path
2832- ) ;
2794+ assert_eq ! ( conn_catalog. search_path, vec![ ] ) ;
28332795 assert_eq ! (
28342796 conn_catalog. effective_search_path( false ) ,
2835- vec![
2836- mz_catalog_schema. clone( ) ,
2837- pg_catalog_schema. clone( ) ,
2838- mz_temp_schema. clone( )
2839- ]
2797+ vec![ mz_catalog_schema. clone( ) , pg_catalog_schema. clone( ) ]
28402798 ) ;
28412799 assert_eq ! (
28422800 conn_catalog. effective_search_path( true ) ,
2843- vec![ mz_catalog_schema , pg_catalog_schema , mz_temp_schema ]
2801+ vec![ mz_temp_schema , mz_catalog_schema , pg_catalog_schema ]
28442802 ) ;
28452803 catalog. expire ( ) . await ;
28462804 } )
0 commit comments