Skip to content

Commit d03addf

Browse files
View primary keys must be FilterableValues
1 parent 5384635 commit d03addf

6 files changed

Lines changed: 57 additions & 2 deletions

File tree

crates/bindings-macro/src/view.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ pub(crate) fn view_impl(args: ViewArgs, original_function: &ItemFn) -> syn::Resu
293293
quote! {
294294
const _: () = {
295295
fn _assert_view_primary_key_column #lt_params (__row: &#row_ty) #lt_where_clause {
296-
let _ = &__row.#primary_key;
296+
fn _assert_view_primary_key_column_type<T: spacetimedb::ViewPrimaryKeyColumn>(_: &T) {}
297+
_assert_view_primary_key_column_type(&__row.#primary_key);
297298
}
298299
};
299300
}

crates/bindings/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ pub use spacetimedb_lib::ScheduleAt;
4949
pub use spacetimedb_lib::TimeDuration;
5050
pub use spacetimedb_lib::Timestamp;
5151
pub use spacetimedb_lib::Uuid;
52+
#[doc(hidden)]
53+
pub use spacetimedb_lib::ViewPrimaryKeyColumn;
5254
pub use spacetimedb_primitives::TableId;
5355
pub use sys::Errno;
5456
pub use table::{

crates/bindings/tests/ui/views.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,4 +215,20 @@ fn view_primary_key_uses_canonical_name(_: &ViewContext) -> Vec<CustomAccessorVi
215215
vec![]
216216
}
217217

218+
#[derive(SpacetimeType)]
219+
struct NonFilterableViewPrimaryKey {
220+
value: u32,
221+
}
222+
223+
#[derive(SpacetimeType)]
224+
struct NonFilterableViewPrimaryKeyRow {
225+
identity: NonFilterableViewPrimaryKey,
226+
}
227+
228+
/// The declared view primary key column type must be filterable.
229+
#[view(accessor = view_primary_key_non_filterable_column, public, primary_key = identity)]
230+
fn view_primary_key_non_filterable_column(_: &ViewContext) -> Vec<NonFilterableViewPrimaryKeyRow> {
231+
vec![]
232+
}
233+
218234
fn main() {}

crates/bindings/tests/ui/views.stderr

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,3 +477,29 @@ error[E0609]: no field `identity` on type `&CustomAccessorViewRow`
477477
| ^^^^^^^^ unknown field
478478
|
479479
= note: available field is: `renamed_identity`
480+
481+
error[E0277]: `&'a NonFilterableViewPrimaryKey` cannot appear as an argument to an index filtering operation
482+
--> tests/ui/views.rs:229:1
483+
|
484+
229 | #[view(accessor = view_primary_key_non_filterable_column, public, primary_key = identity)]
485+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ should be an integer type, `bool`, `String`, `&str`, `Identity`, `Uuid`, `Timestamp`, `ConnectionId`, `Hash` or a no-payload enum which derives `SpacetimeType`, not `&'a NonFilterableViewPrimaryKey`
486+
|
487+
= help: the trait `for<'a> FilterableValue` is not implemented for `&'a NonFilterableViewPrimaryKey`
488+
= note: The allowed set of types are limited to integers, bool, strings, `Identity`, `Uuid`, `Timestamp`, `ConnectionId`, `Hash` and no-payload enums which derive `SpacetimeType`,
489+
= help: the following other types implement trait `FilterableValue`:
490+
&ConnectionId
491+
&FunctionVisibility
492+
&Lifecycle
493+
&TableAccess
494+
&TableType
495+
&bool
496+
&ethnum::int::I256
497+
&ethnum::uint::U256
498+
and $N others
499+
= note: required for `NonFilterableViewPrimaryKey` to implement `ViewPrimaryKeyColumn`
500+
note: required by a bound in `_::_assert_view_primary_key_column::_assert_view_primary_key_column_type`
501+
--> tests/ui/views.rs:229:1
502+
|
503+
229 | #[view(accessor = view_primary_key_non_filterable_column, public, primary_key = identity)]
504+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `_assert_view_primary_key_column_type`
505+
= note: this error originates in the attribute macro `view` (in Nightly builds, run with -Z macro-backtrace for more info)

crates/lib/src/filterable_value.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,16 @@ impl_filterable_value! {
118118
// &[u8] => Vec<u8>,
119119
}
120120

121+
/// Marker trait for column types supported as procedural view primary keys.
122+
#[doc(hidden)]
123+
#[diagnostic::on_unimplemented(
124+
message = "view primary key column type `{Self}` is not supported",
125+
label = "view primary key columns must use an index-filterable key type",
126+
note = "view primary keys must be integer, bool, string, Identity, Uuid, Timestamp, ConnectionId, Hash, or a no-payload enum which derives SpacetimeType"
127+
)]
128+
pub trait ViewPrimaryKeyColumn {}
129+
impl<T> ViewPrimaryKeyColumn for T where for<'a> &'a T: FilterableValue<Column = T> {}
130+
121131
pub enum TermBound<T> {
122132
Single(ops::Bound<T>),
123133
Range(ops::Bound<T>, ops::Bound<T>),

crates/lib/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub use connection_id::ConnectionId;
3535
pub use direct_index_key::{assert_column_type_valid_for_direct_index, DirectIndexKey};
3636
#[doc(hidden)]
3737
pub use filterable_value::Private;
38-
pub use filterable_value::{FilterableValue, IndexScanRangeBoundsTerminator, TermBound};
38+
pub use filterable_value::{FilterableValue, IndexScanRangeBoundsTerminator, TermBound, ViewPrimaryKeyColumn};
3939
pub use identity::Identity;
4040
pub use scheduler::ScheduleAt;
4141
pub use spacetimedb_sats::hash::{self, hash_bytes, Hash};

0 commit comments

Comments
 (0)