From 193ddfd670c28e9e3bf436daa0d87b751cc65c0a Mon Sep 17 00:00:00 2001 From: james gilles Date: Tue, 28 Apr 2026 17:04:28 -0400 Subject: [PATCH] WIP: Start SDK tests for delete_all_by_eq_bsatn (#2164) # Description of Changes This API used to be unimplemented and the SDK tests did not exercise it. Now it is implemented but while playing with blackholio I noticed the C# implementation was wrong. For now I am going to fix blackholio by avoiding use of this API for now, but we should also correct the implementation and test it. # API and ABI breaking changes None # Expected complexity level and risk 0 # Testing Working on adding tests. If someone is more familiar with the SDK tests I would appreciate help amending them. Co-authored-by: clockwork-labs-bot --- .../Runtime/Internal/ITable.cs | 2 +- modules/sdk-test/src/lib.rs | 199 ++++++++++-------- 2 files changed, 108 insertions(+), 93 deletions(-) diff --git a/crates/bindings-csharp/Runtime/Internal/ITable.cs b/crates/bindings-csharp/Runtime/Internal/ITable.cs index 5dbf91d79..5294ce0e7 100644 --- a/crates/bindings-csharp/Runtime/Internal/ITable.cs +++ b/crates/bindings-csharp/Runtime/Internal/ITable.cs @@ -189,7 +189,7 @@ public interface ITableView using var stream = new MemoryStream(); using var writer = new BinaryWriter(stream); // `datastore_delete_all_by_eq_bsatn` expects an array-like BSATN. - // Write a length of 1 without actually wrapping the `row` into array + // Write a length of 1 without actually wrapping the `row` into an array // (annoyingly, that would require passing `TRW` through a bunch of APIs). writer.Write(1U); row.WriteFields(writer); diff --git a/modules/sdk-test/src/lib.rs b/modules/sdk-test/src/lib.rs index 2b4a78f9a..54f8b22b6 100644 --- a/modules/sdk-test/src/lib.rs +++ b/modules/sdk-test/src/lib.rs @@ -205,6 +205,21 @@ macro_rules! define_tables { define_tables!(@impl_ops $name { $($($ops)*)? } $($field_name $ty,)*); }; + // Define a reducer for tables which deletes a row by equality on all columns. + (@impl_ops $name:ident + { delete_all $delete:ident + $(, $($ops:tt)* )? } + $($field_name:ident $ty:ty),* $(,)*) => { + paste::paste! { + #[spacetimedb::reducer] + pub fn $delete (ctx: &ReducerContext, $($field_name : $ty,)*) { + ctx.db.[<$name:snake>]().delete($name { $($field_name,)* }); + } + } + + define_tables!(@impl_ops $name { $($($ops)*)? } $($field_name $ty,)*); + }; + // Define a reducer for tables with a primary key field, // which uses `update` to update by that primary key field. (@impl_ops $name:ident @@ -276,89 +291,89 @@ macro_rules! define_tables { // Tables holding a single value. define_tables! { - OneU8 { insert insert_one_u8 } n u8; - OneU16 { insert insert_one_u16 } n u16; - OneU32 { insert insert_one_u32 } n u32; - OneU64 { insert insert_one_u64 } n u64; - OneU128 { insert insert_one_u128 } n u128; - OneU256 { insert insert_one_u256 } n u256; + OneU8 { insert insert_one_u8, delete_all delete_all_one_u8 } n u8; + OneU16 { insert insert_one_u16, delete_all delete_all_one_u16 } n u16; + OneU32 { insert insert_one_u32, delete_all delete_all_one_u32 } n u32; + OneU64 { insert insert_one_u64, delete_all delete_all_one_u64 } n u64; + OneU128 { insert insert_one_u128, delete_all delete_all_one_u128 } n u128; + OneU256 { insert insert_one_u256, delete_all delete_all_one_u256 } n u256; - OneI8 { insert insert_one_i8 } n i8; - OneI16 { insert insert_one_i16 } n i16; - OneI32 { insert insert_one_i32 } n i32; - OneI64 { insert insert_one_i64 } n i64; - OneI128 { insert insert_one_i128 } n i128; - OneI256 { insert insert_one_i256 } n i256; + OneI8 { insert insert_one_i8, delete_all delete_all_one_i8 } n i8; + OneI16 { insert insert_one_i16, delete_all delete_all_one_i16 } n i16; + OneI32 { insert insert_one_i32, delete_all delete_all_one_i32 } n i32; + OneI64 { insert insert_one_i64, delete_all delete_all_one_i64 } n i64; + OneI128 { insert insert_one_i128, delete_all delete_all_one_i128 } n i128; + OneI256 { insert insert_one_i256, delete_all delete_all_one_i256 } n i256; - OneBool { insert insert_one_bool } b bool; + OneBool { insert insert_one_bool, delete_all delete_all_one_bool } b bool; - OneF32 { insert insert_one_f32 } f f32; - OneF64 { insert insert_one_f64 } f f64; + OneF32 { insert insert_one_f32, delete_all delete_all_one_f32 } f f32; + OneF64 { insert insert_one_f64, delete_all delete_all_one_f64 } f f64; - OneString { insert insert_one_string } s String; + OneString { insert insert_one_string, delete_all delete_all_one_string } s String; - OneIdentity { insert insert_one_identity } i Identity; + OneIdentity { insert insert_one_identity, delete_all delete_all_one_identity } i Identity; OneConnectionId { insert insert_one_connection_id} a ConnectionId; - OneUuid { insert insert_one_uuid } u Uuid; + OneUuid { insert insert_one_uuid, delete_all delete_all_one_uuid } u Uuid; - OneTimestamp { insert insert_one_timestamp } t Timestamp; + OneTimestamp { insert insert_one_timestamp, delete_all delete_all_one_timestamp } t Timestamp; - OneSimpleEnum { insert insert_one_simple_enum } e SimpleEnum; - OneEnumWithPayload { insert insert_one_enum_with_payload } e EnumWithPayload; + OneSimpleEnum { insert insert_one_simple_enum, delete_all delete_all_one_simple_enum } e SimpleEnum; + OneEnumWithPayload { insert insert_one_enum_with_payload, delete_all delete_all_one_enum_with_payload } e EnumWithPayload; - OneUnitStruct { insert insert_one_unit_struct } s UnitStruct; - OneByteStruct { insert insert_one_byte_struct } s ByteStruct; - OneEveryPrimitiveStruct { insert insert_one_every_primitive_struct } s EveryPrimitiveStruct; - OneEveryVecStruct { insert insert_one_every_vec_struct } s EveryVecStruct; + OneUnitStruct { insert insert_one_unit_struct, delete_all delete_all_one_unit_struct } s UnitStruct; + OneByteStruct { insert insert_one_byte_struct, delete_all delete_all_one_byte_struct } s ByteStruct; + OneEveryPrimitiveStruct { insert insert_one_every_primitive_struct, delete_all delete_all_one_every_primitive_struct } s EveryPrimitiveStruct; + OneEveryVecStruct { insert insert_one_every_vec_struct, delete_all delete_all_one_every_vec_struct } s EveryVecStruct; } // Tables holding a Vec of various types. define_tables! { - VecU8 { insert insert_vec_u8 } n Vec; - VecU16 { insert insert_vec_u16 } n Vec; - VecU32 { insert insert_vec_u32 } n Vec; - VecU64 { insert insert_vec_u64 } n Vec; - VecU128 { insert insert_vec_u128 } n Vec; - VecU256 { insert insert_vec_u256 } n Vec; + VecU8 { insert insert_vec_u8, delete_all delete_all_vec_u8 } n Vec; + VecU16 { insert insert_vec_u16, delete_all delete_all_vec_u16 } n Vec; + VecU32 { insert insert_vec_u32, delete_all delete_all_vec_u32 } n Vec; + VecU64 { insert insert_vec_u64, delete_all delete_all_vec_u64 } n Vec; + VecU128 { insert insert_vec_u128, delete_all delete_all_vec_u128 } n Vec; + VecU256 { insert insert_vec_u256, delete_all delete_all_vec_u256 } n Vec; - VecI8 { insert insert_vec_i8 } n Vec; - VecI16 { insert insert_vec_i16 } n Vec; - VecI32 { insert insert_vec_i32 } n Vec; - VecI64 { insert insert_vec_i64 } n Vec; - VecI128 { insert insert_vec_i128 } n Vec; - VecI256 { insert insert_vec_i256 } n Vec; + VecI8 { insert insert_vec_i8, delete_all delete_all_vec_i8 } n Vec; + VecI16 { insert insert_vec_i16, delete_all delete_all_vec_i16 } n Vec; + VecI32 { insert insert_vec_i32, delete_all delete_all_vec_i32 } n Vec; + VecI64 { insert insert_vec_i64, delete_all delete_all_vec_i64 } n Vec; + VecI128 { insert insert_vec_i128, delete_all delete_all_vec_i128 } n Vec; + VecI256 { insert insert_vec_i256, delete_all delete_all_vec_i256 } n Vec; - VecBool { insert insert_vec_bool } b Vec; + VecBool { insert insert_vec_bool, delete_all delete_all_vec_bool } b Vec; - VecF32 { insert insert_vec_f32 } f Vec; - VecF64 { insert insert_vec_f64 } f Vec; + VecF32 { insert insert_vec_f32, delete_all delete_all_vec_f32 } f Vec; + VecF64 { insert insert_vec_f64, delete_all delete_all_vec_f64 } f Vec; - VecString { insert insert_vec_string } s Vec; + VecString { insert insert_vec_string, delete_all delete_all_vec_string } s Vec; - VecIdentity { insert insert_vec_identity } i Vec; + VecIdentity { insert insert_vec_identity, delete_all delete_all_vec_identity } i Vec; VecConnectionId { insert insert_vec_connection_id} a Vec; - VecUuid { insert insert_vec_uuid } u Vec; + VecUuid { insert insert_vec_uuid, delete_all delete_all_vec_uuid } u Vec; - VecTimestamp { insert insert_vec_timestamp } t Vec; + VecTimestamp { insert insert_vec_timestamp, delete_all delete_all_vec_timestamp } t Vec; - VecSimpleEnum { insert insert_vec_simple_enum } e Vec; - VecEnumWithPayload { insert insert_vec_enum_with_payload } e Vec; + VecSimpleEnum { insert insert_vec_simple_enum, delete_all delete_all_vec_simple_enum } e Vec; + VecEnumWithPayload { insert insert_vec_enum_with_payload, delete_all delete_all_vec_enum_with_payload } e Vec; - VecUnitStruct { insert insert_vec_unit_struct } s Vec; - VecByteStruct { insert insert_vec_byte_struct } s Vec; - VecEveryPrimitiveStruct { insert insert_vec_every_primitive_struct } s Vec; - VecEveryVecStruct { insert insert_vec_every_vec_struct } s Vec; + VecUnitStruct { insert insert_vec_unit_struct, delete_all delete_all_vec_unit_struct } s Vec; + VecByteStruct { insert insert_vec_byte_struct, delete_all delete_all_vec_byte_struct } s Vec; + VecEveryPrimitiveStruct { insert insert_vec_every_primitive_struct, delete_all delete_all_vec_every_primitive_struct } s Vec; + VecEveryVecStruct { insert insert_vec_every_vec_struct, delete_all delete_all_vec_every_vec_struct } s Vec; } // Tables holding an Option of various types. define_tables! { - OptionI32 { insert insert_option_i32 } n Option; - OptionString { insert insert_option_string } s Option; - OptionIdentity { insert insert_option_identity } i Option; - OptionUuid { insert insert_option_uuid } u Option; - OptionSimpleEnum { insert insert_option_simple_enum } e Option; - OptionEveryPrimitiveStruct { insert insert_option_every_primitive_struct } s Option; - OptionVecOptionI32 { insert insert_option_vec_option_i32 } v Option>>; + OptionI32 { insert insert_option_i32, delete_all delete_all_option_i32 } n Option; + OptionString { insert insert_option_string, delete_all delete_all_option_string } s Option; + OptionIdentity { insert insert_option_identity, delete_all delete_all_option_identity } i Option; + OptionUuid { insert insert_option_uuid, delete_all delete_all_option_uuid } u Option; + OptionSimpleEnum { insert insert_option_simple_enum, delete_all delete_all_option_simple_enum } e Option; + OptionEveryPrimitiveStruct { insert insert_option_every_primitive_struct, delete_all delete_all_option_every_primitive_struct } s Option; + OptionVecOptionI32 { insert insert_option_vec_option_i32, delete_all delete_all_option_vec_option_i32 } v Option>>; } // Tables holding a Result of various types. @@ -375,106 +390,106 @@ define_tables! { // This allows us to test delete events, and the semantically correct absence of update events. define_tables! { UniqueU8 { - insert_or_panic insert_unique_u8, + insert_or_panic insert_unique_u8, delete_all delete_all_unique_u8, update_non_pk_by update_unique_u8 = update_by_n(n), delete_by delete_unique_u8 = delete_by_n(n: u8), } #[unique] n u8, data i32; UniqueU16 { - insert_or_panic insert_unique_u16, + insert_or_panic insert_unique_u16, delete_all delete_all_unique_u16, update_non_pk_by update_unique_u16 = update_by_n(n), delete_by delete_unique_u16 = delete_by_n(n: u16), } #[unique] n u16, data i32; UniqueU32 { - insert_or_panic insert_unique_u32, + insert_or_panic insert_unique_u32, delete_all delete_all_unique_u32, update_non_pk_by update_unique_u32 = update_by_n(n), delete_by delete_unique_u32 = delete_by_n(n: u32), } #[unique] n u32, data i32; UniqueU64 { - insert_or_panic insert_unique_u64, + insert_or_panic insert_unique_u64, delete_all delete_all_unique_u64, update_non_pk_by update_unique_u64 = update_by_n(n), delete_by delete_unique_u64 = delete_by_n(n: u64), } #[unique] n u64, data i32; UniqueU128 { - insert_or_panic insert_unique_u128, + insert_or_panic insert_unique_u128, delete_all delete_all_unique_u128, update_non_pk_by update_unique_u128 = update_by_n(n), delete_by delete_unique_u128 = delete_by_n(n: u128), } #[unique] n u128, data i32; UniqueU256 { - insert_or_panic insert_unique_u256, + insert_or_panic insert_unique_u256, delete_all delete_all_unique_u256, update_non_pk_by update_unique_u256 = update_by_n(n), delete_by delete_unique_u256 = delete_by_n(n: u256), } #[unique] n u256, data i32; UniqueI8 { - insert_or_panic insert_unique_i8, + insert_or_panic insert_unique_i8, delete_all delete_all_unique_i8, update_non_pk_by update_unique_i8 = update_by_n(n), delete_by delete_unique_i8 = delete_by_n(n: i8), } #[unique] n i8, data i32; UniqueI16 { - insert_or_panic insert_unique_i16, + insert_or_panic insert_unique_i16, delete_all delete_all_unique_i16, update_non_pk_by update_unique_i16 = update_by_n(n), delete_by delete_unique_i16 = delete_by_n(n: i16), } #[unique] n i16, data i32; UniqueI32 { - insert_or_panic insert_unique_i32, + insert_or_panic insert_unique_i32, delete_all delete_all_unique_i32, update_non_pk_by update_unique_i32 = update_by_n(n), delete_by delete_unique_i32 = delete_by_n(n: i32), } #[unique] n i32, data i32; UniqueI64 { - insert_or_panic insert_unique_i64, + insert_or_panic insert_unique_i64, delete_all delete_all_unique_i64, update_non_pk_by update_unique_i64 = update_by_n(n), delete_by delete_unique_i64 = delete_by_n(n: i64), } #[unique] n i64, data i32; UniqueI128 { - insert_or_panic insert_unique_i128, + insert_or_panic insert_unique_i128, delete_all delete_all_unique_i128, update_non_pk_by update_unique_i128 = update_by_n(n), delete_by delete_unique_i128 = delete_by_n(n: i128), } #[unique] n i128, data i32; UniqueI256 { - insert_or_panic insert_unique_i256, + insert_or_panic insert_unique_i256, delete_all delete_all_unique_i256, update_non_pk_by update_unique_i256 = update_by_n(n), delete_by delete_unique_i256 = delete_by_n(n: i256), } #[unique] n i256, data i32; UniqueBool { - insert_or_panic insert_unique_bool, + insert_or_panic insert_unique_bool, delete_all delete_all_unique_bool, update_non_pk_by update_unique_bool = update_by_b(b), delete_by delete_unique_bool = delete_by_b(b: bool), } #[unique] b bool, data i32; UniqueString { - insert_or_panic insert_unique_string, + insert_or_panic insert_unique_string, delete_all delete_all_unique_string, update_non_pk_by update_unique_string = update_by_s(s), delete_by delete_unique_string = delete_by_s(s: String), } #[unique] s String, data i32; UniqueIdentity { - insert_or_panic insert_unique_identity, + insert_or_panic insert_unique_identity, delete_all delete_all_unique_identity, update_non_pk_by update_unique_identity = update_by_i(i), delete_by delete_unique_identity = delete_by_i(i: Identity), } #[unique] i Identity, data i32; UniqueConnectionId { - insert_or_panic insert_unique_connection_id, + insert_or_panic insert_unique_connection_id, delete_all delete_all_unique_connection_id, update_non_pk_by update_unique_connection_id = update_by_a(a), delete_by delete_unique_connection_id = delete_by_a(a: ConnectionId), } #[unique] a ConnectionId, data i32; UniqueUuid { - insert_or_panic insert_unique_uuid, + insert_or_panic insert_unique_uuid, delete_all delete_all_unique_uuid, update_non_pk_by update_unique_uuid = update_by_u(u), delete_by delete_unique_uuid = delete_by_u(u: Uuid), } #[unique] u Uuid, data i32; @@ -484,109 +499,109 @@ define_tables! { // This allows us to test update and delete events. define_tables! { PkU8 { - insert_or_panic insert_pk_u8, + insert_or_panic insert_pk_u8, delete_all delete_all_pk_u8, update_by update_pk_u8 = update_by_n(n), delete_by delete_pk_u8 = delete_by_n(n: u8), } #[primary_key] n u8, data i32; PkU16 { - insert_or_panic insert_pk_u16, + insert_or_panic insert_pk_u16, delete_all delete_all_pk_u16, update_by update_pk_u16 = update_by_n(n), delete_by delete_pk_u16 = delete_by_n(n: u16), } #[primary_key] n u16, data i32; PkU32 { - insert_or_panic insert_pk_u32, + insert_or_panic insert_pk_u32, delete_all delete_all_pk_u32, update_by update_pk_u32 = update_by_n(n), delete_by delete_pk_u32 = delete_by_n(n: u32), } #[primary_key] n u32, data i32; PkU32Two { - insert_or_panic insert_pk_u32_two, + insert_or_panic insert_pk_u32_two, delete_all delete_all_pk_u32_two, update_by update_pk_u32_two = update_by_n(n), delete_by delete_pk_u32_two = delete_by_n(n: u32), } #[primary_key] n u32, data i32; PkU64 { - insert_or_panic insert_pk_u64, + insert_or_panic insert_pk_u64, delete_all delete_all_pk_u64, update_by update_pk_u64 = update_by_n(n), delete_by delete_pk_u64 = delete_by_n(n: u64), } #[primary_key] n u64, data i32; PkU128 { - insert_or_panic insert_pk_u128, + insert_or_panic insert_pk_u128, delete_all delete_all_pk_u128, update_by update_pk_u128 = update_by_n(n), delete_by delete_pk_u128 = delete_by_n(n: u128), } #[primary_key] n u128, data i32; PkU256 { - insert_or_panic insert_pk_u256, + insert_or_panic insert_pk_u256, delete_all delete_all_pk_u256, update_by update_pk_u256 = update_by_n(n), delete_by delete_pk_u256 = delete_by_n(n: u256), } #[primary_key] n u256, data i32; PkI8 { - insert_or_panic insert_pk_i8, + insert_or_panic insert_pk_i8, delete_all delete_all_pk_i8, update_by update_pk_i8 = update_by_n(n), delete_by delete_pk_i8 = delete_by_n(n: i8), } #[primary_key] n i8, data i32; PkI16 { - insert_or_panic insert_pk_i16, + insert_or_panic insert_pk_i16, delete_all delete_all_pk_i16, update_by update_pk_i16 = update_by_n(n), delete_by delete_pk_i16 = delete_by_n(n: i16), } #[primary_key] n i16, data i32; PkI32 { - insert_or_panic insert_pk_i32, + insert_or_panic insert_pk_i32, delete_all delete_all_pk_i32, update_by update_pk_i32 = update_by_n(n), delete_by delete_pk_i32 = delete_by_n(n: i32), } #[primary_key] n i32, data i32; PkI64 { - insert_or_panic insert_pk_i64, + insert_or_panic insert_pk_i64, delete_all delete_all_pk_i64, update_by update_pk_i64 = update_by_n(n), delete_by delete_pk_i64 = delete_by_n(n: i64), } #[primary_key] n i64, data i32; PkI128 { - insert_or_panic insert_pk_i128, + insert_or_panic insert_pk_i128, delete_all delete_all_pk_i128, update_by update_pk_i128 = update_by_n(n), delete_by delete_pk_i128 = delete_by_n(n: i128), } #[primary_key] n i128, data i32; PkI256 { - insert_or_panic insert_pk_i256, + insert_or_panic insert_pk_i256, delete_all delete_all_pk_i256, update_by update_pk_i256 = update_by_n(n), delete_by delete_pk_i256 = delete_by_n(n: i256), } #[primary_key] n i256, data i32; PkBool { - insert_or_panic insert_pk_bool, + insert_or_panic insert_pk_bool, delete_all delete_all_pk_bool, update_by update_pk_bool = update_by_b(b), delete_by delete_pk_bool = delete_by_b(b: bool), } #[primary_key] b bool, data i32; PkString { - insert_or_panic insert_pk_string, + insert_or_panic insert_pk_string, delete_all delete_all_pk_string, update_by update_pk_string = update_by_s(s), delete_by delete_pk_string = delete_by_s(s: String), } #[primary_key] s String, data i32; PkIdentity { - insert_or_panic insert_pk_identity, + insert_or_panic insert_pk_identity, delete_all delete_all_pk_identity, update_by update_pk_identity = update_by_i(i), delete_by delete_pk_identity = delete_by_i(i: Identity), } #[primary_key] i Identity, data i32; PkConnectionId { - insert_or_panic insert_pk_connection_id, + insert_or_panic insert_pk_connection_id, delete_all delete_all_pk_connection_id, update_by update_pk_connection_id = update_by_a(a), delete_by delete_pk_connection_id = delete_by_a(a: ConnectionId), } #[primary_key] a ConnectionId, data i32; PkUuid { - insert_or_panic insert_pk_uuid, + insert_or_panic insert_pk_uuid, delete_all delete_all_pk_uuid, update_by update_pk_uuid = update_by_u(u), delete_by delete_pk_uuid = delete_by_u(u: Uuid), } #[primary_key] u Uuid, data i32;