Module Defined Views
The shipping continues! This time we have Module Defined Views or just "views". Views are a simple, but incredibly expressive way to define custom and intricate read permissioning for your tables.
Views, which are inspired by a similar concept from SQL, are virtual tables that are defined by new "view functions" in your module and derived from other tables or parameters.
Views are defined by read-only procedural, functions in the language of your module. This function returns data derived from your database tables. You can then query and subscribe to this view as you would any normal database table and it will be updated automatically in realtime.
Here's a look at the syntax for defining a view in the various module languages:
Rust
Declare with #[view]. First argument is a view context (&ViewContext or &AnonymousViewContext). Return Option<T> (0–1 row) or Vec<T> (many rows).
#[view(name = my_player, public)]
fn my_player(ctx: &ViewContext) -> Option<Player> {
ctx.db.player().identity().find(ctx.sender)
}
#[view(name = players_for_level, public)]
fn players_for_level(ctx: &AnonymousViewContext) -> Vec<Player> {
ctx.db
.player_level()
.level()
.filter(2u64) // players for level 2
.map(|player| {
ctx.db
.player()
.id()
.find(player.player_id)
})
.collect()
} Notes
- A
nameis required. - Only the context parameter is allowed; no extra args (yet).
- The context provides a read-only view of the database
- Mutations are not allowed
- Full table scans are not allowed
C#
Use [SpacetimeDB.View] with ViewContext or AnonymousViewContext. Return a single row as T? or many rows as List<T> / T[].
[SpacetimeDB.View(Name = "my_player", Public = true)]
public static Player? MyPlayer(ViewContext ctx) =>
ctx.Db.Player.Identity.Find(ctx.Sender) as Player;
[SpacetimeDB.View(Name = "players_for_level", Public = true)]
public static List<Player> PlayerLocations(AnonymousViewContext ctx) {
var rows = new List<Player>();
foreach (var player in ctx.Db.PlayerLevel.Level.Filter(2))
{
if (ctx.Db.Player.Id.Find(player.PlayerId) is Player p)
{
rows.Add(p);
}
}
return rows;
} TypeScript
Register with schema.view(...) or schema.anonymousView(...). Use t.option(row) for 0–1 row or t.array(row) for many rows.
spacetimedb.view(
{ name: 'my_player', public: true },
t.option(players.row()),
(ctx) => {
return ctx.db.players.identity.find(ctx.sender) ?? null;
}
);
spacetimedb.anonymousView(
{ name: 'players_for_level', public: true },
t.option(players.row()),
(ctx) => {
const out = [];
for (const pl of ctx.db.playerLevels.level.find(2)) {
const p = ctx.db.players.id.find(pl.player_id);
if (p) out.push(p);
}
return out;
}
); Row-level security rules
Currently procedurally defined view functions are limited to index probing tables so that we can efficiently compute the real-time delta for procedural functions. However, we also plan to shortly add the ability to return typed queries from view functions which will allow you to define performant, incrementally evaluated queries which execute full tables scans.
This functionality will make views strictly more expressive and powerful than the existing unstable RLS (row-level security) rules API that we introduced earlier this year. As such we will be deprecating the RLS API in favor of the view API. Here is an idea (not final API) of what that might look like in TypeScript
spacetimedb.view(
{ name: 'high_level_players', public: true },
t.query(players.row()),
(ctx) => {
return ctx.from(ctx.db.player).where(player => gt(player.level, 50))
}
); What's Changed
- Add typescript quickstart smoketest by @coolreader18 in https://github.com/clockworklabs/SpacetimeDB/pull/3463
- CI - Move the Package job to ubuntu-latest by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3553
- CI - Fix NuGet smoketest dependencies by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3557
- Fix Nix build by not using Git in Cargo build scripts by @gefjon in https://github.com/clockworklabs/SpacetimeDB/pull/3551
- Use production API key by @JulienLavocat in https://github.com/clockworklabs/SpacetimeDB/pull/3560
- Bump versions to 1.7.0 by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3550
- Generate client bindings for views by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/3564
- Add proper V8 sys module versioning by @coolreader18 in https://github.com/clockworklabs/SpacetimeDB/pull/3527
- Set default server to
localin replication smoketests by @gefjon in https://github.com/clockworklabs/SpacetimeDB/pull/3562 - View resolution in sql by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/3570
- [teams 1/5] Reset database by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/3496
- Fix some annoyances with the smoketests by @coolreader18 in https://github.com/clockworklabs/SpacetimeDB/pull/3556
- Add view handling to query engine and planner by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/3578
- CI - Fix the merge queue by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3571
- Revert "[teams 1/5] Reset database (#3496)" by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3580
- Decrement view subscriber count on disconnect by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/3547
- Update C# client-api bindings by @gefjon in https://github.com/clockworklabs/SpacetimeDB/pull/3537
- Views: Host interface for WASM modules by @Shubham8287 in https://github.com/clockworklabs/SpacetimeDB/pull/3548
- Fix for multi-column indexes in typescript modules by @jsdt in https://github.com/clockworklabs/SpacetimeDB/pull/3589
- smoketests: Adjust enable replication tests by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/3590
Dockerfilefails more cleanly if.gitis a submodule by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3591- fix: view index by @Shubham8287 in https://github.com/clockworklabs/SpacetimeDB/pull/3596
- remove module watcher from subscription by @Shubham8287 in https://github.com/clockworklabs/SpacetimeDB/pull/3602
- Fix issue with row id for non primary key tables by @aasoni in https://github.com/clockworklabs/SpacetimeDB/pull/3603
- Typescript views by @coolreader18 in https://github.com/clockworklabs/SpacetimeDB/pull/3584
- CI - Make Internal Tests less brittle by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3536
- Materialize views on subscribe by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/3599
- Refactor module instance code by @coolreader18 in https://github.com/clockworklabs/SpacetimeDB/pull/3605
- commitlog,durability: Support preallocation of disk space by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/3437
- Add Rust client SDK bindings for calling procedures by @gefjon in https://github.com/clockworklabs/SpacetimeDB/pull/3532
- Add comment about public API key use on Docusaurus by @JulienLavocat in https://github.com/clockworklabs/SpacetimeDB/pull/3567
- Views: fix table schema creation from system table. by @Shubham8287 in https://github.com/clockworklabs/SpacetimeDB/pull/3615
- Disable parameterized views in rust by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/3629
- CI - Fix format strings by @bfops in https://github.com/clockworklabs/SpacetimeDB/pull/3627
- Atomic view update by @joshua-spacetime in https://github.com/clockworklabs/SpacetimeDB/pull/3624
- Disconnect clients when updating RLS rules by @mamcx in https://github.com/clockworklabs/SpacetimeDB/pull/3574
- [teams 1/5] Reset database by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/3611
- SQL smoketests for views by @Shubham8287 in https://github.com/clockworklabs/SpacetimeDB/pull/3616
- [teams 2/5] client-api: Add
parentparameter to publish endpoint by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/3519 - [teams 3/5] API authorization, CLI, smoketests by @kim in https://github.com/clockworklabs/SpacetimeDB/pull/3523
- C# bindings for views by @rekhoff in https://github.com/clockworklabs/SpacetimeDB/pull/3585
Full Changelog: https://github.com/clockworklabs/SpacetimeDB/compare/v1.7.0...v1.8.0
