1- use serde_json:: json;
1+ use serde_json:: { json, Value } ;
22use spacetimedb_smoketests:: { require_dotnet, require_pnpm, Smoketest } ;
33
44const TS_VIEWS_SUBSCRIBE_MODULE : & str = r#"import { schema, t, table } from "spacetimedb/server";
@@ -77,6 +77,30 @@ public static partial class Module
7777}
7878"# ;
7979
80+ fn project_inserts_and_deletes_for_view ( events : Vec < Value > , view_name : & str ) -> Vec < Value > {
81+ events
82+ . into_iter ( )
83+ . map ( |event| {
84+ json ! ( {
85+ view_name: {
86+ "deletes" : event[ view_name] [ "deletes" ]
87+ . as_array( )
88+ . unwrap( )
89+ . iter( )
90+ . map( |row| json!( { "name" : row[ "name" ] } ) )
91+ . collect:: <Vec <_>>( ) ,
92+ "inserts" : event[ view_name] [ "inserts" ]
93+ . as_array( )
94+ . unwrap( )
95+ . iter( )
96+ . map( |row| json!( { "name" : row[ "name" ] } ) )
97+ . collect:: <Vec <_>>( )
98+ }
99+ } )
100+ } )
101+ . collect ( )
102+ }
103+
80104/// Tests that views populate the st_view_* system tables
81105#[ test]
82106fn test_st_view_tables ( ) {
@@ -404,24 +428,7 @@ fn test_subscribing_with_different_identities() {
404428 test. call ( "insert_player" , & [ "Bob" ] ) . unwrap ( ) ;
405429 let events = sub. collect ( ) . unwrap ( ) ;
406430
407- let projection: Vec < serde_json:: Value > = events
408- . into_iter ( )
409- . map ( |event| {
410- let deletes = event[ "my_player" ] [ "deletes" ]
411- . as_array ( )
412- . unwrap ( )
413- . iter ( )
414- . map ( |row| json ! ( { "name" : row[ "name" ] } ) )
415- . collect :: < Vec < _ > > ( ) ;
416- let inserts = event[ "my_player" ] [ "inserts" ]
417- . as_array ( )
418- . unwrap ( )
419- . iter ( )
420- . map ( |row| json ! ( { "name" : row[ "name" ] } ) )
421- . collect :: < Vec < _ > > ( ) ;
422- json ! ( { "my_player" : { "deletes" : deletes, "inserts" : inserts} } )
423- } )
424- . collect ( ) ;
431+ let projection = project_inserts_and_deletes_for_view ( events, "my_player" ) ;
425432
426433 assert_eq ! (
427434 serde_json:: json!( projection) ,
@@ -500,26 +507,7 @@ fn test_procedure_triggers_subscription_updates() {
500507 let sub = test. subscribe_background ( & [ "select * from my_player" ] , 1 ) . unwrap ( ) ;
501508 test. call ( "insert_player_proc" , & [ "Alice" ] ) . unwrap ( ) ;
502509 let events = sub. collect ( ) . unwrap ( ) ;
503-
504- let projection: Vec < serde_json:: Value > = events
505- . into_iter ( )
506- . map ( |event| {
507- let deletes = event[ "my_player" ] [ "deletes" ]
508- . as_array ( )
509- . unwrap ( )
510- . iter ( )
511- . map ( |row| json ! ( { "name" : row[ "name" ] } ) )
512- . collect :: < Vec < _ > > ( ) ;
513- let inserts = event[ "my_player" ] [ "inserts" ]
514- . as_array ( )
515- . unwrap ( )
516- . iter ( )
517- . map ( |row| json ! ( { "name" : row[ "name" ] } ) )
518- . collect :: < Vec < _ > > ( ) ;
519- json ! ( { "my_player" : { "deletes" : deletes, "inserts" : inserts} } )
520- } )
521- . collect ( ) ;
522-
510+ let projection = project_inserts_and_deletes_for_view ( events, "my_player" ) ;
523511 assert_eq ! (
524512 serde_json:: json!( projection) ,
525513 serde_json:: json!( [
@@ -543,24 +531,7 @@ fn test_typescript_procedure_triggers_subscription_updates() {
543531 test. call ( "insert_player_proc" , & [ "Alice" ] ) . unwrap ( ) ;
544532 let events = sub. collect ( ) . unwrap ( ) ;
545533
546- let projection: Vec < serde_json:: Value > = events
547- . into_iter ( )
548- . map ( |event| {
549- let deletes = event[ "my_player" ] [ "deletes" ]
550- . as_array ( )
551- . unwrap ( )
552- . iter ( )
553- . map ( |row| json ! ( { "name" : row[ "name" ] } ) )
554- . collect :: < Vec < _ > > ( ) ;
555- let inserts = event[ "my_player" ] [ "inserts" ]
556- . as_array ( )
557- . unwrap ( )
558- . iter ( )
559- . map ( |row| json ! ( { "name" : row[ "name" ] } ) )
560- . collect :: < Vec < _ > > ( ) ;
561- json ! ( { "my_player" : { "deletes" : deletes, "inserts" : inserts} } )
562- } )
563- . collect ( ) ;
534+ let projection = project_inserts_and_deletes_for_view ( events, "my_player" ) ;
564535
565536 assert_eq ! (
566537 serde_json:: json!( projection) ,
@@ -609,3 +580,80 @@ fn test_csharp_query_builder_view_query() {
609580 1 | true"# ,
610581 ) ;
611582}
583+
584+ #[ test]
585+ fn test_subscribe_join_with_view_on_primary_key_col ( ) {
586+ let test = Smoketest :: builder ( ) . precompiled_module ( "views-subscribe" ) . build ( ) ;
587+
588+ test. call ( "insert_player_proc" , & [ "Alice" ] ) . unwrap ( ) ;
589+
590+ let query =
591+ "SELECT all_players.* FROM player_state JOIN all_players ON player_state.identity = all_players.identity" ;
592+ let events = test. subscribe ( & [ query] , 0 ) . unwrap ( ) ;
593+ let projection = project_inserts_and_deletes_for_view ( events, "all_players" ) ;
594+
595+ assert_eq ! (
596+ serde_json:: json!( projection) ,
597+ serde_json:: json!( [
598+ { "all_players" : { "deletes" : [ ] , "inserts" : [ { "name" : "Alice" } ] } }
599+ ] )
600+ ) ;
601+ }
602+
603+ #[ test]
604+ fn test_subscribe_join_two_views_on_primary_key_col ( ) {
605+ let test = Smoketest :: builder ( ) . precompiled_module ( "views-query" ) . build ( ) ;
606+
607+ let query = "SELECT online_users.* \
608+ FROM online_users \
609+ JOIN users_whos_age_is_known \
610+ ON online_users.identity = users_whos_age_is_known.identity";
611+ let events = test. subscribe ( & [ query] , 0 ) . unwrap ( ) ;
612+ let projection = project_inserts_and_deletes_for_view ( events, "online_users" ) ;
613+
614+ assert_eq ! (
615+ serde_json:: json!( projection) ,
616+ serde_json:: json!( [
617+ { "online_users" : { "deletes" : [ ] , "inserts" : [ { "name" : "Alice" } ] } }
618+ ] )
619+ ) ;
620+ }
621+
622+ #[ test]
623+ fn test_subscribe_join_with_anonymous_view_on_primary_key_col ( ) {
624+ let test = Smoketest :: builder ( ) . precompiled_module ( "views-query" ) . build ( ) ;
625+
626+ let query = "SELECT anonymous_adult_people.* \
627+ FROM person \
628+ JOIN anonymous_adult_people \
629+ ON person.identity = anonymous_adult_people.identity \
630+ WHERE anonymous_adult_people.identity = 1";
631+ let events = test. subscribe ( & [ query] , 0 ) . unwrap ( ) ;
632+ let projection = project_inserts_and_deletes_for_view ( events, "anonymous_adult_people" ) ;
633+
634+ assert_eq ! (
635+ serde_json:: json!( projection) ,
636+ serde_json:: json!( [
637+ { "anonymous_adult_people" : { "deletes" : [ ] , "inserts" : [ { "name" : "Alice" } ] } }
638+ ] )
639+ ) ;
640+ }
641+
642+ #[ test]
643+ fn test_subscribe_join_two_sender_views_with_filters_on_both_sides ( ) {
644+ let test = Smoketest :: builder ( ) . precompiled_module ( "views-query" ) . build ( ) ;
645+
646+ let query = "SELECT online_users_identity_1.* \
647+ FROM online_users_identity_1 \
648+ JOIN users_whos_age_is_known_identity_1 \
649+ ON online_users_identity_1.identity = users_whos_age_is_known_identity_1.identity";
650+ let events = test. subscribe ( & [ query] , 0 ) . unwrap ( ) ;
651+ let projection = project_inserts_and_deletes_for_view ( events, "online_users_identity_1" ) ;
652+
653+ assert_eq ! (
654+ serde_json:: json!( projection) ,
655+ serde_json:: json!( [
656+ { "online_users_identity_1" : { "deletes" : [ ] , "inserts" : [ { "name" : "Alice" } ] } }
657+ ] )
658+ ) ;
659+ }
0 commit comments