Skip to main content

RangedIndex

Struct RangedIndex 

Source
pub struct RangedIndex<Tbl: Table, IndexType, Idx: IndexIsRanged> { /* private fields */ }
Expand description

A handle to a B-Tree or Direct index on a table.

To get one of these from a ReducerContext, use:

ctx.db.{table}().{index}()

for a table table and an index index.

Example:

use spacetimedb::{table, RangedIndex, ReducerContext, DbContext};

#[table(accessor = user,
    index(accessor = dogs_and_name, btree(columns = [dogs, name])))]
struct User {
    id: u32,
    name: String,
    /// Number of dogs owned by the user.
    dogs: u64
}

fn demo(ctx: &ReducerContext) {
    let by_dogs_and_name: RangedIndex<_, (u64, String), _> = ctx.db.user().dogs_and_name();
}

For single-column indexes, use the name of the column:

use spacetimedb::{table, RangedIndex, ReducerContext, DbContext};

#[table(accessor = user)]
struct User {
    id: u32,
    username: String,
    #[index(btree)]
    dogs: u64
}

fn demo(ctx: &ReducerContext) {
    let by_dogs: RangedIndex<_, (u64,), _> = ctx.db().user().dogs();
}

Implementations§

Source§

impl<Tbl: Table, IndexType, Idx: IndexIsRanged> RangedIndex<Tbl, IndexType, Idx>

Source

pub fn filter<B, K>( &self, b: B, ) -> impl Iterator<Item = Tbl::Row> + use<B, K, Tbl, IndexType, Idx>
where B: IndexScanRangeBounds<IndexType, K>,

Returns an iterator over all rows in the database state where the indexed column(s) match the bounds b.

This method accepts a variable numbers of arguments using the [IndexScanRangeBounds] trait. This depends on the type of the B-Tree index. b may be:

  • A value for the first indexed column.
  • A range of values for the first indexed column.
  • A tuple of values for any prefix of the indexed columns, optionally terminated by a range for the next.

For example:

use spacetimedb::{table, ReducerContext, RangedIndex};

#[table(accessor = user,
    index(accessor = dogs_and_name, btree(columns = [dogs, name])))]
struct User {
    id: u32,
    name: String,
    dogs: u64
}

fn demo(ctx: &ReducerContext) {
    let by_dogs_and_name: RangedIndex<_, (u64, String), _> = ctx.db.user().dogs_and_name();

    // Find user with exactly 25 dogs.
    for user in by_dogs_and_name.filter(25u64) { // The `u64` is required, see below.
        /* ... */
    }

    // Find user with at least 25 dogs.
    for user in by_dogs_and_name.filter(25u64..) {
        /* ... */
    }

    // Find user with exactly 25 dogs, and a name beginning with "J".
    for user in by_dogs_and_name.filter((25u64, "J".."K")) {
        /* ... */
    }

    // Find user with exactly 25 dogs, and exactly the name "Joseph".
    for user in by_dogs_and_name.filter((25u64, "Joseph")) {
        /* ... */
    }

    // You can also pass arguments by reference if desired.
    for user in by_dogs_and_name.filter((&25u64, &"Joseph".to_string())) {
        /* ... */
    }
}

NOTE: An unfortunate interaction between Rust’s trait solver and integer literal defaulting rules means that you must specify the types of integer literals passed to filter and find methods via the suffix syntax, like 21u32.

If you don’t, you’ll see a compiler error like:

error[E0271]: type mismatch resolving `<i32 as FilterableValue>::Column == u32`
   --> modules/rust-wasm-test/src/lib.rs:356:48
    |
356 |     for person in ctx.db.person().age().filter(21) {
    |                                         ------ ^^ expected `u32`, found `i32`
    |                                         |
    |                                         required by a bound introduced by this call
    |
    = note: required for `i32` to implement `IndexScanRangeBounds<(u32,), SingleBound>`
note: required by a bound in `RangedIndex::<Tbl, IndexType, Idx>::filter`
    |
410 |     pub fn filter<B, K>(&self, b: B) -> impl Iterator<Item = Tbl::Row>
    |            ------ required by a bound in this associated function
411 |     where
412 |         B: IndexScanRangeBounds<IndexType, K>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RangedIndex::<Tbl, IndexType, Idx>::filter`
Source

pub fn delete<B, K>(&self, b: B) -> u64
where B: IndexScanRangeBounds<IndexType, K>,

Deletes all rows in the database state where the indexed column(s) match the bounds b.

This method accepts a variable numbers of arguments using the [IndexScanRangeBounds] trait. This depends on the type of the B-Tree index. b may be:

  • A value for the first indexed column.
  • A range of values for the first indexed column.
  • A tuple of values for any prefix of the indexed columns, optionally terminated by a range for the next.

For example:

use spacetimedb::{table, ReducerContext, RangedIndex};

#[table(accessor = user,
    index(accessor = dogs_and_name, btree(columns = [dogs, name])))]
struct User {
    id: u32,
    name: String,
    dogs: u64
}

fn demo(ctx: &ReducerContext) {
    let by_dogs_and_name: RangedIndex<_, (u64, String), _> = ctx.db.user().dogs_and_name();

    // Delete users with exactly 25 dogs.
    by_dogs_and_name.delete(25u64); // The `u64` is required, see below.

    // Delete users with at least 25 dogs.
    by_dogs_and_name.delete(25u64..);

    // Delete users with exactly 25 dogs, and a name beginning with "J".
    by_dogs_and_name.delete((25u64, "J".."K"));

    // Delete users with exactly 25 dogs, and exactly the name "Joseph".
    by_dogs_and_name.delete((25u64, "Joseph"));

    // You can also pass arguments by reference if desired.
    by_dogs_and_name.delete((&25u64, &"Joseph".to_string()));
}

NOTE: An unfortunate interaction between Rust’s trait solver and integer literal defaulting rules means that you must specify the types of integer literals passed to filter and find methods via the suffix syntax, like 21u32.

If you don’t, you’ll see a compiler error like:

error[E0271]: type mismatch resolving `<i32 as FilterableValue>::Column == u32`
   --> modules/rust-wasm-test/src/lib.rs:356:48
    |
356 |     for person in ctx.db.person().age().filter(21) {
    |                                         ------ ^^ expected `u32`, found `i32`
    |                                         |
    |                                         required by a bound introduced by this call
    |
    = note: required for `i32` to implement `IndexScanRangeBounds<(u32,), SingleBound>`
note: required by a bound in `RangedIndex::<Tbl, IndexType, Idx>::filter`
    |
410 |     pub fn filter<B, K>(&self, b: B) -> impl Iterator<Item = Tbl::Row>
    |            ------ required by a bound in this associated function
411 |     where
412 |         B: IndexScanRangeBounds<IndexType, K>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RangedIndex::<Tbl, IndexType, Idx>::filter`

May panic if deleting any one of the rows would violate a constraint, though at present no such constraints exist.

Auto Trait Implementations§

§

impl<Tbl, IndexType, Idx> Freeze for RangedIndex<Tbl, IndexType, Idx>

§

impl<Tbl, IndexType, Idx> RefUnwindSafe for RangedIndex<Tbl, IndexType, Idx>
where Tbl: RefUnwindSafe, IndexType: RefUnwindSafe, Idx: RefUnwindSafe,

§

impl<Tbl, IndexType, Idx> Send for RangedIndex<Tbl, IndexType, Idx>
where Tbl: Send, IndexType: Send, Idx: Send,

§

impl<Tbl, IndexType, Idx> Sync for RangedIndex<Tbl, IndexType, Idx>
where Tbl: Sync, IndexType: Sync, Idx: Sync,

§

impl<Tbl, IndexType, Idx> Unpin for RangedIndex<Tbl, IndexType, Idx>
where Tbl: Unpin, IndexType: Unpin, Idx: Unpin,

§

impl<Tbl, IndexType, Idx> UnsafeUnpin for RangedIndex<Tbl, IndexType, Idx>

§

impl<Tbl, IndexType, Idx> UnwindSafe for RangedIndex<Tbl, IndexType, Idx>
where Tbl: UnwindSafe, IndexType: UnwindSafe, Idx: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V