@@ -285,7 +285,7 @@ SPACETIMEDB_VIEW(std::vector<PlayerAndLevel>, players_for_level, Public, Anonymo
285285}
286286```
287287
288- Views can return either `std::optional<T>` for at-most-one row or `std::vector<T>` for multiple rows, where `T` can be a table type or any product type.
288+ Views can return `std::optional<T>` for at-most-one row, `std::vector<T>` for multiple rows, or a query-builder type , where `T` can be a table type or any product type.
289289
290290</TabItem>
291291</Tabs>
@@ -895,6 +895,21 @@ fn high_scorers(ctx: &AnonymousViewContext) -> impl Query<Player> {
895895}
896896```
897897
898+ </TabItem>
899+ <TabItem value="cpp" label="C++">
900+
901+ ``` cpp
902+ SPACETIMEDB_VIEW (Query<Player >, high_scorers, Public, AnonymousViewContext ctx) {
903+ return ctx.from[ player]
904+ .where([ ] (const auto& p) {
905+ return p.score.gte(uint64_t(1000));
906+ })
907+ .where([ ] (const auto& p) {
908+ return p.name.ne("BOT");
909+ });
910+ }
911+ ```
912+
898913</TabItem>
899914</Tabs>
900915
@@ -1000,6 +1015,34 @@ fn high_scoring_moderators_declarative(ctx: &AnonymousViewContext) -> impl Query
10001015}
10011016```
10021017
1018+ </TabItem >
1019+ <TabItem value =" cpp " label =" C++ " >
1020+
1021+ ``` cpp
1022+ // Procedural: row-by-row join in module code.
1023+ SPACETIMEDB_VIEW (std::vector<Player >, high_scoring_moderators_procedural, Public, AnonymousViewContext ctx) {
1024+ std::vector<Player > results;
1025+ for (const auto& p : ctx.db[ player_score] .filter(range_from(uint64_t(100)))) {
1026+ if (!ctx.db[ moderator_player_id] .filter(p.id).empty()) {
1027+ results.push_back(p);
1028+ }
1029+ }
1030+ return results;
1031+ }
1032+
1033+ // Query builder: equivalent logic pushed to the query engine.
1034+ // The engine can reorder this join if it decides the smaller side is a better starting point.
1035+ SPACETIMEDB_VIEW(Query<Player >, high_scoring_moderators_declarative, Public, AnonymousViewContext ctx) {
1036+ return ctx.from[ player]
1037+ .where([ ] (const auto& p) {
1038+ return p.score.gte(uint64_t(100));
1039+ })
1040+ .left_semijoin(ctx.from[ moderator] , [ ] (const auto& p, const auto& m) {
1041+ return p.id.eq(m.player_id);
1042+ });
1043+ }
1044+ ```
1045+
10031046</TabItem>
10041047</Tabs>
10051048
@@ -1123,6 +1166,38 @@ fn all_player_levels(ctx: &AnonymousViewContext) -> impl Query<PlayerLevel> {
11231166}
11241167```
11251168
1169+ </TabItem >
1170+ <TabItem value =" cpp " label =" C++ " >
1171+
1172+ ``` cpp
1173+ struct Player {
1174+ uint64_t id;
1175+ std::string name;
1176+ uint64_t score;
1177+ };
1178+ SPACETIMEDB_STRUCT(Player, id, name, score)
1179+ SPACETIMEDB_TABLE(Player, player, Public)
1180+ FIELD_PrimaryKey(player, id)
1181+ FIELD_Index(player, score)
1182+
1183+ struct PlayerLevel {
1184+ uint64_t player_id;
1185+ uint64_t level;
1186+ };
1187+ SPACETIMEDB_STRUCT(PlayerLevel, player_id, level)
1188+ SPACETIMEDB_TABLE(PlayerLevel, player_level, Public)
1189+ FIELD_Unique(player_level, player_id)
1190+ FIELD_Index(player_level, level)
1191+
1192+ SPACETIMEDB_VIEW(Query<Player >, all_players, Public, AnonymousViewContext ctx) {
1193+ return ctx.from[ player] ;
1194+ }
1195+
1196+ SPACETIMEDB_VIEW(Query<PlayerLevel >, all_player_levels, Public, AnonymousViewContext ctx) {
1197+ return ctx.from[ player_level] ;
1198+ }
1199+ ```
1200+
11261201</TabItem>
11271202</Tabs>
11281203
@@ -1184,6 +1259,21 @@ fn high_scorers(ctx: &AnonymousViewContext) -> impl Query<Player> {
11841259}
11851260```
11861261
1262+ </TabItem>
1263+ <TabItem value="cpp" label="C++">
1264+
1265+ ``` cpp
1266+ SPACETIMEDB_VIEW (Query<Player >, high_scorers, Public, AnonymousViewContext ctx) {
1267+ return ctx.from[ player]
1268+ .where([ ] (const auto& p) {
1269+ return p.score.gte(uint64_t(1000));
1270+ })
1271+ .filter([ ] (const auto& p) {
1272+ return p.name.ne("BOT");
1273+ });
1274+ }
1275+ ```
1276+
11871277</TabItem>
11881278</Tabs>
11891279
@@ -1218,6 +1308,15 @@ ctx.from.player().r#where(|p| p.name.eq("ADMIN").or(p.name.eq("BOT")));
12181308ctx . from. player (). r#where (| p | p . name. eq (" BOT" ). not ());
12191309```
12201310
1311+ </TabItem >
1312+ <TabItem value =" cpp " label =" C++ " >
1313+
1314+ ``` cpp
1315+ ctx.from[player].where([](const auto & p) { return p.score.gte(uint64_t(1000)).and_ (p.score.lt(uint64_t(5000))); });
1316+ ctx.from[ player] .where([ ] (const auto& p) { return p.name.eq("ADMIN").or_ (p.name.eq("BOT")); });
1317+ ctx.from[ player] .where([ ] (const auto& p) { return p.name.eq("BOT").not_ (); });
1318+ ```
1319+
12211320</TabItem>
12221321</Tabs>
12231322
@@ -1302,6 +1401,31 @@ fn levels_for_high_scorers(ctx: &AnonymousViewContext) -> impl Query<PlayerLevel
13021401}
13031402```
13041403
1404+ </TabItem >
1405+ <TabItem value =" cpp " label =" C++ " >
1406+
1407+ ``` cpp
1408+ SPACETIMEDB_VIEW (Query<Player >, players_with_levels, Public, AnonymousViewContext ctx) {
1409+ return ctx.from[ player]
1410+ .left_semijoin(ctx.from[ player_level] , [ ] (const auto& p, const auto& pl) {
1411+ return p.id.eq(pl.player_id);
1412+ });
1413+ }
1414+
1415+ SPACETIMEDB_VIEW(Query<PlayerLevel >, levels_for_high_scorers, Public, AnonymousViewContext ctx) {
1416+ return ctx.from[ player]
1417+ .where([ ] (const auto& p) {
1418+ return p.score.gte(uint64_t(1000));
1419+ })
1420+ .right_semijoin(ctx.from[ player_level] , [ ] (const auto& p, const auto& pl) {
1421+ return p.id.eq(pl.player_id);
1422+ })
1423+ .where([ ] (const auto& pl) {
1424+ return pl.level.gte(uint64_t(10));
1425+ });
1426+ }
1427+ ```
1428+
13051429</TabItem>
13061430</Tabs>
13071431
0 commit comments