@@ -20,8 +20,8 @@ use spacetimedb_datastore::traits::IsolationLevel;
2020use spacetimedb_expr:: statement:: Statement ;
2121use spacetimedb_lib:: identity:: AuthCtx ;
2222use spacetimedb_lib:: metrics:: ExecutionMetrics ;
23+ use spacetimedb_lib:: Timestamp ;
2324use spacetimedb_lib:: { AlgebraicType , ProductType , ProductValue } ;
24- use spacetimedb_lib:: { Identity , Timestamp } ;
2525use spacetimedb_query:: { compile_sql_stmt, execute_dml_stmt, execute_select_stmt} ;
2626use spacetimedb_schema:: relation:: FieldName ;
2727use spacetimedb_vm:: eval:: run_ast;
@@ -192,51 +192,26 @@ pub async fn run(
192192 auth : AuthCtx ,
193193 subs : Option < & ModuleSubscriptions > ,
194194 module : Option < & ModuleHost > ,
195- caller_identity : Identity ,
196195 head : & mut Vec < ( Box < str > , AlgebraicType ) > ,
197196) -> Result < SqlResult , DBError > {
197+ let module = module
198+ . as_ref ( )
199+ . ok_or_else ( || anyhow ! ( "Cannot execute views without module context" ) ) ?;
200+
201+ let mut metrics = ExecutionMetrics :: default ( ) ;
202+
198203 // We parse the sql statement in a mutable transaction.
199204 // If it turns out to be a query, we downgrade the tx.
200- let ( mut tx, stmt) = db. with_auto_rollback ( db. begin_mut_tx ( IsolationLevel :: Serializable , Workload :: Sql ) , |tx| {
205+ let ( tx, stmt) = db. with_auto_rollback ( db. begin_mut_tx ( IsolationLevel :: Serializable , Workload :: Sql ) , |tx| {
201206 compile_sql_stmt ( sql_text, & SchemaViewer :: new ( tx, & auth) , & auth)
202207 } ) ?;
203208
204- let mut metrics = ExecutionMetrics :: default ( ) ;
205-
206- for ( view_name, args) in stmt. views ( ) {
207- let ( is_materialized, args) = tx
208- . is_materialized ( view_name, args, caller_identity)
209- . map_err ( |e| DBError :: Other ( anyhow ! ( "Failed to check memoized view: {e}" ) ) ) ?;
210-
211- // Skip if already memoized
212- if is_materialized {
213- continue ;
214- }
215-
216- let module = module
217- . as_ref ( )
218- . ok_or_else ( || anyhow ! ( "Cannot execute view `{view_name}` without module context" ) ) ?;
219-
220- let res = module
221- . call_view (
222- tx,
223- view_name,
224- crate :: host:: FunctionArgs :: Bsatn ( args) ,
225- caller_identity,
226- None ,
227- )
228- . await
229- . map_err ( |e| DBError :: Other ( anyhow ! ( "Failed to execute view `{view_name}`: {e}" ) ) ) ?;
230-
231- tx = res. tx ;
232- }
233-
234209 match stmt {
235210 Statement :: Select ( stmt) => {
236- // Materialize views before we downgrade to a read-only transaction
237- tx . materialize_views ( & stmt , auth . caller ) ? ;
238-
239- let ( tx_data , tx_metrics_mut , tx ) = tx . commit_downgrade ( Workload :: Sql ) ;
211+ // Materialize views and downgrade to a read-only transaction
212+ let ( tx_data , tx_metrics_mut , tx ) = module
213+ . materialize_views_and_downgrade_tx ( tx , & stmt , auth . caller , Workload :: Sql )
214+ . await ? ;
240215
241216 let ( tx_offset_send, tx_offset) = oneshot:: channel ( ) ;
242217 // Release the tx on drop, so that we record metrics
@@ -398,7 +373,6 @@ pub(crate) mod tests {
398373 AuthCtx :: for_testing ( ) ,
399374 Some ( & subs) ,
400375 None ,
401- Identity :: ZERO ,
402376 & mut vec ! [ ] ,
403377 ) )
404378 . map ( |x| x. rows )
@@ -551,7 +525,7 @@ pub(crate) mod tests {
551525 expected : impl IntoIterator < Item = ProductValue > ,
552526 ) {
553527 assert_eq ! (
554- run( db, sql, * auth, None , None , Identity :: ZERO , & mut vec![ ] )
528+ run( db, sql, * auth, None , None , & mut vec![ ] )
555529 . await
556530 . unwrap( )
557531 . rows
@@ -1506,9 +1480,7 @@ pub(crate) mod tests {
15061480
15071481 let rt = db. runtime ( ) . expect ( "runtime should be there" ) ;
15081482
1509- let run = |db, sql, auth, subs, mut tmp_vec| {
1510- rt. block_on ( run ( db, sql, auth, subs, None , Identity :: ZERO , & mut tmp_vec) )
1511- } ;
1483+ let run = |db, sql, auth, subs, mut tmp_vec| rt. block_on ( run ( db, sql, auth, subs, None , & mut tmp_vec) ) ;
15121484 // No row limit, both queries pass.
15131485 assert ! ( run( & db, "SELECT * FROM T" , internal_auth, None , tmp_vec. clone( ) ) . is_ok( ) ) ;
15141486 assert ! ( run( & db, "SELECT * FROM T" , external_auth, None , tmp_vec. clone( ) ) . is_ok( ) ) ;
@@ -1558,9 +1530,7 @@ pub(crate) mod tests {
15581530 let internal_auth = AuthCtx :: new ( server, server) ;
15591531
15601532 let tmp_vec = Vec :: new ( ) ;
1561- let run = |db, sql, auth, subs, mut tmp_vec| async move {
1562- run ( db, sql, auth, subs, None , Identity :: ZERO , & mut tmp_vec) . await
1563- } ;
1533+ let run = |db, sql, auth, subs, mut tmp_vec| async move { run ( db, sql, auth, subs, None , & mut tmp_vec) . await } ;
15641534
15651535 let check = |db, sql, auth, metrics : ExecutionMetrics | {
15661536 let result = rt. block_on ( run ( db, sql, auth, None , tmp_vec. clone ( ) ) ) ?;
0 commit comments