diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs index b88ae42dcb4..43662c057a0 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs @@ -39,6 +39,7 @@ Unit F64 )> { public static readonly AlgebraicType Unit = new Product([]); + public const string QueryBuilderProductTypeTag = "__query__"; // Special AlgebraicType that can be recognised by the SpacetimeDB `generate` CLI as an Option. internal static AlgebraicType MakeOption(AlgebraicType someType) => @@ -47,4 +48,8 @@ internal static AlgebraicType MakeOption(AlgebraicType someType) => // Special AlgebraicType that can be recognised by the SpacetimeDB `generate` CLI as a Result. internal static AlgebraicType MakeResult(AlgebraicType okType, AlgebraicType errType) => new Sum([new("ok", okType), new("err", errType)]); + + // Special AlgebraicType that can be recognised by the SpacetimeDB `generate` CLI as Query. + public static AlgebraicType MakeQueryBuilderProductType(Ref rowProductTypeRef) => + new Product([new(QueryBuilderProductTypeTag, rowProductTypeRef)]); } diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index c519fb9d7e0..260b42c3098 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -1636,10 +1636,9 @@ SpacetimeDB.BSATN.ITypeRegistrar registrar IsPublic: true, IsAnonymous: false, Params: [], - ReturnType: new SpacetimeDB.BSATN.ValueOption< - PublicTable, - PublicTable.BSATN - >().GetAlgebraicType(registrar) + ReturnType: global::SpacetimeDB.BSATN.AlgebraicType.MakeQueryBuilderProductType( + new PublicTable.BSATN().GetAlgebraicType(registrar) + ) ); public byte[] Invoke( diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index e9c0d0522e5..111503f0472 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1122,6 +1122,7 @@ record ViewDeclaration public readonly bool IsPublic; public readonly bool ReturnsQuery; public readonly TypeUse ReturnType; + public readonly TypeUse? QueryRowType; public readonly EquatableArray Parameters; public readonly Scope Scope; @@ -1186,15 +1187,12 @@ method.ReturnType is INamedTypeSymbol { ReturnsQuery = true; var rowType = TypeUse.Parse(method, queryRowType, diag); - var optType = queryRowType.IsValueType - ? "SpacetimeDB.BSATN.ValueOption" - : "SpacetimeDB.BSATN.RefOption"; - var opt = $"{optType}<{rowType.Name}, {rowType.BSATNName}>"; - // Match Rust semantics: Query is described as a nullable row (T?). - ReturnType = new ReferenceUse(opt, opt); + QueryRowType = rowType; + ReturnType = rowType; } else { + QueryRowType = null; ReturnType = TypeUse.Parse(method, method.ReturnType, diag); } Scope = new Scope(methodSyntax.Parent as MemberDeclarationSyntax); @@ -1211,9 +1209,10 @@ method.ReturnType is INamedTypeSymbol diag.Report(ErrorDescriptor.ViewContextParam, methodSyntax); } - // Validate return type: must be List or T? + // Validate return type: must be List, T?, or IQuery. if ( - !ReturnType.BSATNName.Contains("SpacetimeDB.BSATN.ValueOption") + !ReturnsQuery + && !ReturnType.BSATNName.Contains("SpacetimeDB.BSATN.ValueOption") && !ReturnType.BSATNName.Contains("SpacetimeDB.BSATN.RefOption") && !ReturnType.BSATNName.Contains("SpacetimeDB.BSATN.List") ) @@ -1229,17 +1228,22 @@ method.ReturnType is INamedTypeSymbol ); } - public string GenerateViewDef(uint Index) => - $$$""" + public string GenerateViewDef(uint Index) + { + var returnTypeExpr = ReturnsQuery + ? $"global::SpacetimeDB.BSATN.AlgebraicType.MakeQueryBuilderProductType(new {QueryRowType!.BSATNName}().GetAlgebraicType(registrar))" + : $"new {ReturnType.BSATNName}().GetAlgebraicType(registrar)"; + return $$$""" new global::SpacetimeDB.Internal.RawViewDefV10( SourceName: "{{{Name}}}", Index: {{{Index}}}, IsPublic: {{{IsPublic.ToString().ToLower()}}}, IsAnonymous: {{{IsAnonymous.ToString().ToLower()}}}, Params: [{{{MemberDeclaration.GenerateDefs(Parameters)}}}], - ReturnType: new {{{ReturnType.BSATNName}}}().GetAlgebraicType(registrar) + ReturnType: {{{returnTypeExpr}}} ); """; + } /// /// Generates the class responsible for evaluating a view. diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index e449f703181..76907815898 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -653,6 +653,13 @@ impl Lang for Csharp<'_> { } } } + for (columns, constraints) in schema.backcompat_column_constraints() { + if constraints.has_indexed() || constraints.has_unique() || constraints.has_primary_key() { + for col_pos in columns.iter() { + ix_col_positions.insert(col_pos.idx()); + } + } + } writeln!(output, "public sealed class {cols_owner_name}Cols"); indented_block(&mut output, |output| { diff --git a/modules/sdk-test-view-pk-cs/.gitignore b/modules/sdk-test-view-pk-cs/.gitignore new file mode 100644 index 00000000000..1746e3269ed --- /dev/null +++ b/modules/sdk-test-view-pk-cs/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/modules/sdk-test-view-pk-cs/Lib.cs b/modules/sdk-test-view-pk-cs/Lib.cs new file mode 100644 index 00000000000..5fa58de076b --- /dev/null +++ b/modules/sdk-test-view-pk-cs/Lib.cs @@ -0,0 +1,92 @@ +namespace SpacetimeDB.Sdk.Test.ViewPk; + +using SpacetimeDB; + +public static partial class Module +{ + [SpacetimeDB.Table(Accessor = "view_pk_player", Public = true)] + public partial struct ViewPkPlayer + { + [SpacetimeDB.PrimaryKey] + public ulong id; + public string name; + } + + [SpacetimeDB.Table(Accessor = "view_pk_membership", Public = true)] + public partial struct ViewPkMembership + { + [SpacetimeDB.PrimaryKey] + public ulong id; + + [SpacetimeDB.Index.BTree] + public ulong player_id; + } + + [SpacetimeDB.Table(Accessor = "view_pk_membership_secondary", Public = true)] + public partial struct ViewPkMembershipSecondary + { + [SpacetimeDB.PrimaryKey] + public ulong id; + + [SpacetimeDB.Index.BTree] + public ulong player_id; + } + + [SpacetimeDB.Reducer] + public static void insert_view_pk_player(ReducerContext ctx, ulong id, string name) + { + ctx.Db.view_pk_player.Insert(new ViewPkPlayer { id = id, name = name }); + } + + [SpacetimeDB.Reducer] + public static void update_view_pk_player(ReducerContext ctx, ulong id, string name) + { + ctx.Db.view_pk_player.id.Update(new ViewPkPlayer { id = id, name = name }); + } + + [SpacetimeDB.Reducer] + public static void insert_view_pk_membership(ReducerContext ctx, ulong id, ulong player_id) + { + ctx.Db.view_pk_membership.Insert(new ViewPkMembership { id = id, player_id = player_id }); + } + + [SpacetimeDB.Reducer] + public static void insert_view_pk_membership_secondary( + ReducerContext ctx, + ulong id, + ulong player_id + ) + { + ctx.Db.view_pk_membership_secondary.Insert( + new ViewPkMembershipSecondary { id = id, player_id = player_id } + ); + } + + [SpacetimeDB.View(Accessor = "all_view_pk_players", Public = true)] + public static IQuery all_view_pk_players(ViewContext ctx) + { + return ctx.From.view_pk_player(); + } + + [SpacetimeDB.View(Accessor = "sender_view_pk_players_a", Public = true)] + public static IQuery sender_view_pk_players_a(ViewContext ctx) + { + return ctx + .From.view_pk_membership() + .RightSemijoin( + ctx.From.view_pk_player(), + (membership, player) => membership.player_id.Eq(player.id) + ); + } + + [SpacetimeDB.View(Accessor = "sender_view_pk_players_b", Public = true)] + public static IQuery sender_view_pk_players_b(ViewContext ctx) + { + return ctx + .From.view_pk_membership_secondary() + .RightSemijoin( + ctx.From.view_pk_player(), + (membership, player) => membership.player_id.Eq(player.id) + ); + } +} diff --git a/modules/sdk-test-view-pk-cs/README.md b/modules/sdk-test-view-pk-cs/README.md new file mode 100644 index 00000000000..a62bd410bfe --- /dev/null +++ b/modules/sdk-test-view-pk-cs/README.md @@ -0,0 +1,8 @@ +# `sdk-test-view-pk-cs` *C#* test + +See the [sdk-test-view-pk README](../sdk-test-view-pk/README.md) for more details. + +> **WARNING**: This C# source code is manually derived from `../sdk-test-view-pk/src/lib.rs` +> and is supposed to be functionally equivalent. +> Do not add new types or functionality here that are not present in the *Rust* version, +> because they're compared against each other. diff --git a/modules/sdk-test-view-pk-cs/sdk-test-view-pk-cs.csproj b/modules/sdk-test-view-pk-cs/sdk-test-view-pk-cs.csproj new file mode 100644 index 00000000000..d4caede5ffa --- /dev/null +++ b/modules/sdk-test-view-pk-cs/sdk-test-view-pk-cs.csproj @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/sdks/csharp/examples~/regression-tests/client/Program.cs b/sdks/csharp/examples~/regression-tests/client/Program.cs index dda45f13468..edc89983e83 100644 --- a/sdks/csharp/examples~/regression-tests/client/Program.cs +++ b/sdks/csharp/examples~/regression-tests/client/Program.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Threading; +using RegressionTests.Shared; using SpacetimeDB; using SpacetimeDB.Types; @@ -19,46 +20,19 @@ const string EXPECTED_TEST_EVENT_NAME = "hello"; const ulong EXPECTED_TEST_EVENT_VALUE = 42; -DbConnection ConnectToDB() -{ - DbConnection? conn = null; - conn = DbConnection - .Builder() - .WithUri(HOST) - .WithDatabaseName(DBNAME) - .OnConnect(OnConnected) - .OnConnectError( - (err) => - { - throw err; - } - ) - .OnDisconnect( - (conn, err) => - { - if (err != null) - { - throw err; - } - else - { - throw new Exception("Unexpected disconnect"); - } - } - ) - .Build(); - return conn; -} - +DbConnection db = null!; uint waiting = 0; -var applied = false; -SubscriptionHandle? handle = null; +var runComplete = false; +SubscriptionHandle? mainHandle = null; uint testEventInsertCount = 0; +long viewPkIdCounter = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() * 10; + +ulong NextViewPkId() => (ulong)Interlocked.Increment(ref viewPkIdCounter); void OnConnected(DbConnection conn, Identity identity, string authToken) { Log.Debug($"Connected to {DBNAME} on {HOST}"); - handle = conn.SubscriptionBuilder() + mainHandle = conn.SubscriptionBuilder() .OnApplied(OnSubscriptionApplied) .OnError( (ctx, err) => @@ -285,6 +259,34 @@ string name "Event table iterator should remain empty after noop" ); }; + + conn.Reducers.OnInsertViewPkPlayer += (ctx, _, _) => + { + Log.Info("Got InsertViewPkPlayer callback"); + waiting--; + ValidateCommittedReducer("InsertViewPkPlayer", ctx); + }; + + conn.Reducers.OnUpdateViewPkPlayer += (ctx, _, _) => + { + Log.Info("Got UpdateViewPkPlayer callback"); + waiting--; + ValidateCommittedReducer("UpdateViewPkPlayer", ctx); + }; + + conn.Reducers.OnInsertViewPkMembership += (ctx, _, _) => + { + Log.Info("Got InsertViewPkMembership callback"); + waiting--; + ValidateCommittedReducer("InsertViewPkMembership", ctx); + }; + + conn.Reducers.OnInsertViewPkMembershipSecondary += (ctx, _, _) => + { + Log.Info("Got InsertViewPkMembershipSecondary callback"); + waiting--; + ValidateCommittedReducer("InsertViewPkMembershipSecondary", ctx); + }; } const uint MAX_ID = 10; @@ -541,10 +543,282 @@ void ValidateSemijoinSubscriptions(IRemoteDbContext conn, Identity identity) Debug.Assert(levels[0].Level == 1, $"Expected player_level.Level == 1, got {levels[0].Level}"); } -void OnSubscriptionApplied(SubscriptionEventContext context) +void ValidateCommittedReducer(string reducerName, ReducerEventContext ctx) +{ + switch (ctx.Event.Status) + { + case Status.Committed: + return; + case Status.Failed(var reason): + throw new Exception($"{reducerName} should commit, got failure: {reason}"); + case Status.OutOfEnergy(var _): + throw new Exception($"{reducerName} ran out of energy"); + default: + throw new Exception($"{reducerName} returned unexpected status: {ctx.Event.Status}"); + } +} + +void ExpectSingleViewPkPlayerUpdate( + string testName, + ref bool sawUpdate, + ulong expectedId, + string expectedOldName, + string expectedNewName, + ViewPkPlayer oldRow, + ViewPkPlayer newRow +) +{ + Debug.Assert(!sawUpdate, $"Expected exactly one OnUpdate callback for {testName}"); + Debug.Assert(oldRow.Id == expectedId, $"Expected oldRow.Id={expectedId}, got {oldRow.Id}"); + Debug.Assert( + oldRow.Name == expectedOldName, + $"Expected oldRow.Name={expectedOldName}, got {oldRow.Name}" + ); + Debug.Assert(newRow.Id == expectedId, $"Expected newRow.Id={expectedId}, got {newRow.Id}"); + Debug.Assert( + newRow.Name == expectedNewName, + $"Expected newRow.Name={expectedNewName}, got {newRow.Name}" + ); + sawUpdate = true; +} + +/// Subscribe to a query builder view whose underlying table has a primary key. +/// Ensures the C# SDK emits an `OnUpdate` callback and that the client receives the correct old and new rows. +/// +/// Test: +/// 1. Subscribe to: SELECT * FROM all_view_pk_players +/// 2. Insert row: (id=1, name="before") +/// 3. Update row: (id=1, name="after") +/// +/// Expect: +/// - `OnUpdate` is called for PK=1 +/// - `oldRow` should be the "before" value +/// - `newRow` should be the "after" value +void ExecViewPkOnUpdate() +{ + const string testName = "view-pk-on-update"; + var playerId = NextViewPkId(); + const string before = "before"; + const string after = "after"; + bool sawUpdate = false; + SubscriptionHandle? phaseHandle = null; + + Log.Debug($"Starting {testName}"); + phaseHandle = db + .SubscriptionBuilder() + .OnApplied(ctx => + { + void OnAllViewPkPlayersUpdate(EventContext _, ViewPkPlayer oldRow, ViewPkPlayer newRow) + { + ctx.Db.AllViewPkPlayers.OnUpdate -= OnAllViewPkPlayersUpdate; + ExpectSingleViewPkPlayerUpdate( + testName, + ref sawUpdate, + playerId, + before, + after, + oldRow, + newRow + ); + + waiting++; + phaseHandle?.UnsubscribeThen(_ => + { + Debug.Assert(sawUpdate, $"Expected an OnUpdate callback for {testName}"); + ExecViewPkJoinQueryBuilder(); + waiting--; + }); + } + + ctx.Db.AllViewPkPlayers.OnUpdate += OnAllViewPkPlayersUpdate; + + waiting++; + ctx.Reducers.InsertViewPkPlayer(playerId, before); + + waiting++; + ctx.Reducers.UpdateViewPkPlayer(playerId, after); + }) + .OnError((_, err) => + { + throw err; + }) + .AddQuery(q => q.From.AllViewPkPlayers()) + .Subscribe(); +} + +/// Subscribe to a right semijoin whose rhs is a view with primary key. +/// +/// Ensures: +/// 1. A semijoin subscription involving a view is valid +/// 2. The C# SDK emits an `OnUpdate` callback and that the client receives the correct old and new rows +/// +/// Query: +/// SELECT player.* +/// FROM view_pk_membership membership +/// JOIN all_view_pk_players player ON membership.player_id = player.id +/// +/// Test: +/// 1. Insert player row (id=1, "before"). +/// 2. Insert membership row referencing player_id=1, allowing the semijoin match. +/// 3. Update player row to (id=1, "after"). +/// +/// Expect: +/// - `OnUpdate` is called for player PK=1 +/// - `oldRow` should be the "before" value +/// - `newRow` should be the "after" value +void ExecViewPkJoinQueryBuilder() { - applied = true; + const string testName = "view-pk-join-query-builder"; + var playerId = NextViewPkId(); + var membershipId = NextViewPkId(); + const string before = "before"; + const string after = "after"; + bool sawUpdate = false; + SubscriptionHandle? phaseHandle = null; + + Log.Debug($"Starting {testName}"); + phaseHandle = db + .SubscriptionBuilder() + .OnApplied(ctx => + { + void OnAllViewPkPlayersUpdate(EventContext _, ViewPkPlayer oldRow, ViewPkPlayer newRow) + { + ctx.Db.AllViewPkPlayers.OnUpdate -= OnAllViewPkPlayersUpdate; + ExpectSingleViewPkPlayerUpdate( + testName, + ref sawUpdate, + playerId, + before, + after, + oldRow, + newRow + ); + waiting++; + phaseHandle?.UnsubscribeThen(_ => + { + Debug.Assert(sawUpdate, $"Expected an OnUpdate callback for {testName}"); + ExecViewPkSemijoinTwoSenderViewsQueryBuilder(); + waiting--; + }); + } + + ctx.Db.AllViewPkPlayers.OnUpdate += OnAllViewPkPlayersUpdate; + + waiting++; + ctx.Reducers.InsertViewPkPlayer(playerId, before); + + waiting++; + ctx.Reducers.InsertViewPkMembership(membershipId, playerId); + + waiting++; + ctx.Reducers.UpdateViewPkPlayer(playerId, after); + }) + .OnError((_, err) => + { + throw err; + }) + .AddQuery(q => + q.From.ViewPkMembership().RightSemijoin( + q.From.AllViewPkPlayers(), + (membership, player) => membership.PlayerId.Eq(player.Id) + ) + ) + .Subscribe(); +} + +/// Subscribe to a semijoin between two views with primary keys. +/// +/// Ensures: +/// 1. A semijoin subscription involving a view is valid +/// 2. The C# SDK emits an `OnUpdate` callback and that the client receives the correct old and new rows +/// +/// Query: +/// SELECT b.* +/// FROM sender_view_pk_players_a a +/// JOIN sender_view_pk_players_b b ON a.id = b.id +/// +/// Test: +/// 1. Insert player row (id=1, "before"). +/// 2. Insert membership for sender view A. +/// 3. Insert membership for sender view B. +/// 4. Update player row to (id=1, "after"). +/// +/// Expect: +/// - `OnUpdate` is called for player PK=1 +/// - `oldRow` should be the "before" value +/// - `newRow` should be the "after" value +void ExecViewPkSemijoinTwoSenderViewsQueryBuilder() +{ + const string testName = "view-pk-semijoin-two-sender-views-query-builder"; + var playerId = NextViewPkId(); + var membershipAId = NextViewPkId(); + var membershipBId = NextViewPkId(); + const string before = "before"; + const string after = "after"; + bool sawUpdate = false; + SubscriptionHandle? phaseHandle = null; + + Log.Debug($"Starting {testName}"); + phaseHandle = db + .SubscriptionBuilder() + .OnApplied(ctx => + { + void OnSenderViewPkPlayersBUpdate( + EventContext _, + ViewPkPlayer oldRow, + ViewPkPlayer newRow + ) + { + ctx.Db.SenderViewPkPlayersB.OnUpdate -= OnSenderViewPkPlayersBUpdate; + ExpectSingleViewPkPlayerUpdate( + testName, + ref sawUpdate, + playerId, + before, + after, + oldRow, + newRow + ); + + waiting++; + phaseHandle?.UnsubscribeThen(_ => + { + Debug.Assert(sawUpdate, $"Expected an OnUpdate callback for {testName}"); + runComplete = true; + waiting--; + }); + } + + ctx.Db.SenderViewPkPlayersB.OnUpdate += OnSenderViewPkPlayersBUpdate; + + waiting++; + ctx.Reducers.InsertViewPkPlayer(playerId, before); + + waiting++; + ctx.Reducers.InsertViewPkMembership(membershipAId, playerId); + + waiting++; + ctx.Reducers.InsertViewPkMembershipSecondary(membershipBId, playerId); + + waiting++; + ctx.Reducers.UpdateViewPkPlayer(playerId, after); + }) + .OnError((_, err) => + { + throw err; + }) + .AddQuery(q => + q.From.SenderViewPkPlayersA().RightSemijoin( + q.From.SenderViewPkPlayersB(), + (lhsView, rhsView) => lhsView.Id.Eq(rhsView.Id) + ) + ) + .Subscribe(); +} + +void OnSubscriptionApplied(SubscriptionEventContext context) +{ ValidateWhereSubscription(context); ValidateWhereTestViews(context); ValidateSemijoinSubscriptions(context, context.Identity!.Value); @@ -1119,34 +1393,20 @@ ProcedureCallbackResult> result // Now unsubscribe and check that the unsubscribing is actually applied. Log.Debug("Calling Unsubscribe"); waiting++; - handle?.UnsubscribeThen( + mainHandle?.UnsubscribeThen( (ctx) => { Log.Debug("Received Unsubscribe"); ValidateBTreeIndexes(ctx); + ExecViewPkOnUpdate(); waiting--; } ); } -System.AppDomain.CurrentDomain.UnhandledException += (sender, args) => -{ - Log.Exception($"Unhandled exception: {sender} {args}"); - Environment.Exit(1); -}; -var db = ConnectToDB(); -Log.Info("Starting timer"); +RegressionTestHarness.RegisterUnhandledExceptionExitHandler(); +db = RegressionTestHarness.ConnectToDatabase(HOST, DBNAME, OnConnected); const int TIMEOUT = 20; // seconds; -var start = DateTime.Now; -while (!applied || waiting > 0) -{ - db.FrameTick(); - Thread.Sleep(100); - if ((DateTime.Now - start).Seconds > TIMEOUT) - { - Log.Error($"Timeout, all events should have elapsed in {TIMEOUT} seconds!"); - Environment.Exit(1); - } -} +RegressionTestHarness.FrameTickUntilComplete(db, () => runComplete && waiting == 0, TIMEOUT); Log.Info("Success"); Environment.Exit(0); diff --git a/sdks/csharp/examples~/regression-tests/client/client.csproj b/sdks/csharp/examples~/regression-tests/client/client.csproj index c76a780a74d..540e15ad427 100644 --- a/sdks/csharp/examples~/regression-tests/client/client.csproj +++ b/sdks/csharp/examples~/regression-tests/client/client.csproj @@ -12,4 +12,8 @@ + + + + diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkMembership.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkMembership.g.cs new file mode 100644 index 00000000000..3b09c569584 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkMembership.g.cs @@ -0,0 +1,73 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void InsertViewPkMembershipHandler(ReducerEventContext ctx, ulong id, ulong playerId); + public event InsertViewPkMembershipHandler? OnInsertViewPkMembership; + + public void InsertViewPkMembership(ulong id, ulong playerId) + { + conn.InternalCallReducer(new Reducer.InsertViewPkMembership(id, playerId)); + } + + public bool InvokeInsertViewPkMembership(ReducerEventContext ctx, Reducer.InsertViewPkMembership args) + { + if (OnInsertViewPkMembership == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnInsertViewPkMembership( + ctx, + args.Id, + args.PlayerId + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertViewPkMembership : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "player_id")] + public ulong PlayerId; + + public InsertViewPkMembership( + ulong Id, + ulong PlayerId + ) + { + this.Id = Id; + this.PlayerId = PlayerId; + } + + public InsertViewPkMembership() + { + } + + string IReducerArgs.ReducerName => "insert_view_pk_membership"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkMembershipSecondary.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkMembershipSecondary.g.cs new file mode 100644 index 00000000000..4742217d359 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkMembershipSecondary.g.cs @@ -0,0 +1,73 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void InsertViewPkMembershipSecondaryHandler(ReducerEventContext ctx, ulong id, ulong playerId); + public event InsertViewPkMembershipSecondaryHandler? OnInsertViewPkMembershipSecondary; + + public void InsertViewPkMembershipSecondary(ulong id, ulong playerId) + { + conn.InternalCallReducer(new Reducer.InsertViewPkMembershipSecondary(id, playerId)); + } + + public bool InvokeInsertViewPkMembershipSecondary(ReducerEventContext ctx, Reducer.InsertViewPkMembershipSecondary args) + { + if (OnInsertViewPkMembershipSecondary == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnInsertViewPkMembershipSecondary( + ctx, + args.Id, + args.PlayerId + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertViewPkMembershipSecondary : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "player_id")] + public ulong PlayerId; + + public InsertViewPkMembershipSecondary( + ulong Id, + ulong PlayerId + ) + { + this.Id = Id; + this.PlayerId = PlayerId; + } + + public InsertViewPkMembershipSecondary() + { + } + + string IReducerArgs.ReducerName => "insert_view_pk_membership_secondary"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkPlayer.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkPlayer.g.cs new file mode 100644 index 00000000000..75146b10f70 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/InsertViewPkPlayer.g.cs @@ -0,0 +1,74 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void InsertViewPkPlayerHandler(ReducerEventContext ctx, ulong id, string name); + public event InsertViewPkPlayerHandler? OnInsertViewPkPlayer; + + public void InsertViewPkPlayer(ulong id, string name) + { + conn.InternalCallReducer(new Reducer.InsertViewPkPlayer(id, name)); + } + + public bool InvokeInsertViewPkPlayer(ReducerEventContext ctx, Reducer.InsertViewPkPlayer args) + { + if (OnInsertViewPkPlayer == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnInsertViewPkPlayer( + ctx, + args.Id, + args.Name + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertViewPkPlayer : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "name")] + public string Name; + + public InsertViewPkPlayer( + ulong Id, + string Name + ) + { + this.Id = Id; + this.Name = Name; + } + + public InsertViewPkPlayer() + { + this.Name = ""; + } + + string IReducerArgs.ReducerName => "insert_view_pk_player"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/UpdateViewPkPlayer.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/UpdateViewPkPlayer.g.cs new file mode 100644 index 00000000000..1649aed0401 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Reducers/UpdateViewPkPlayer.g.cs @@ -0,0 +1,74 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteReducers : RemoteBase + { + public delegate void UpdateViewPkPlayerHandler(ReducerEventContext ctx, ulong id, string name); + public event UpdateViewPkPlayerHandler? OnUpdateViewPkPlayer; + + public void UpdateViewPkPlayer(ulong id, string name) + { + conn.InternalCallReducer(new Reducer.UpdateViewPkPlayer(id, name)); + } + + public bool InvokeUpdateViewPkPlayer(ReducerEventContext ctx, Reducer.UpdateViewPkPlayer args) + { + if (OnUpdateViewPkPlayer == null) + { + if (InternalOnUnhandledReducerError != null) + { + switch (ctx.Event.Status) + { + case Status.Failed(var reason): InternalOnUnhandledReducerError(ctx, new Exception(reason)); break; + case Status.OutOfEnergy(var _): InternalOnUnhandledReducerError(ctx, new Exception("out of energy")); break; + } + } + return false; + } + OnUpdateViewPkPlayer( + ctx, + args.Id, + args.Name + ); + return true; + } + } + + public abstract partial class Reducer + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class UpdateViewPkPlayer : Reducer, IReducerArgs + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "name")] + public string Name; + + public UpdateViewPkPlayer( + ulong Id, + string Name + ) + { + this.Id = Id; + this.Name = Name; + } + + public UpdateViewPkPlayer() + { + this.Name = ""; + } + + string IReducerArgs.ReducerName => "update_view_pk_player"; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs index e6d99f9b15b..480000e349d 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 6a6b5a6616f0578aa641bc0689691f953b13feb8). +// This was generated using spacetimedb cli version 2.0.4 (commit 589c48dc67d151edb98f2e4a5245a7b4fac70767). #nullable enable @@ -29,6 +29,7 @@ public RemoteTables(DbConnection conn) { AddTable(Admins = new(conn)); AddTable(Account = new(conn)); + AddTable(AllViewPkPlayers = new(conn)); AddTable(ExampleData = new(conn)); AddTable(FindWhereTest = new(conn)); AddTable(MyAccount = new(conn)); @@ -48,12 +49,17 @@ public RemoteTables(DbConnection conn) AddTable(ScoresPlayer123 = new(conn)); AddTable(ScoresPlayer123Level5 = new(conn)); AddTable(ScoresPlayer123Range = new(conn)); + AddTable(SenderViewPkPlayersA = new(conn)); + AddTable(SenderViewPkPlayersB = new(conn)); AddTable(TestEvent = new(conn)); AddTable(User = new(conn)); AddTable(UsersAge1865 = new(conn)); AddTable(UsersAge18Plus = new(conn)); AddTable(UsersAgeUnder18 = new(conn)); AddTable(UsersNamedAlice = new(conn)); + AddTable(ViewPkMembership = new(conn)); + AddTable(ViewPkMembershipSecondary = new(conn)); + AddTable(ViewPkPlayer = new(conn)); AddTable(WhereTest = new(conn)); AddTable(WhereTestQuery = new(conn)); AddTable(WhereTestView = new(conn)); @@ -555,6 +561,7 @@ public sealed class QueryBuilder { new QueryBuilder().From.Admins().ToSql(), new QueryBuilder().From.Account().ToSql(), + new QueryBuilder().From.AllViewPkPlayers().ToSql(), new QueryBuilder().From.ExampleData().ToSql(), new QueryBuilder().From.FindWhereTest().ToSql(), new QueryBuilder().From.MyAccount().ToSql(), @@ -574,12 +581,17 @@ public sealed class QueryBuilder new QueryBuilder().From.ScoresPlayer123().ToSql(), new QueryBuilder().From.ScoresPlayer123Level5().ToSql(), new QueryBuilder().From.ScoresPlayer123Range().ToSql(), + new QueryBuilder().From.SenderViewPkPlayersA().ToSql(), + new QueryBuilder().From.SenderViewPkPlayersB().ToSql(), new QueryBuilder().From.TestEvent().ToSql(), new QueryBuilder().From.User().ToSql(), new QueryBuilder().From.UsersAge1865().ToSql(), new QueryBuilder().From.UsersAge18Plus().ToSql(), new QueryBuilder().From.UsersAgeUnder18().ToSql(), new QueryBuilder().From.UsersNamedAlice().ToSql(), + new QueryBuilder().From.ViewPkMembership().ToSql(), + new QueryBuilder().From.ViewPkMembershipSecondary().ToSql(), + new QueryBuilder().From.ViewPkPlayer().ToSql(), new QueryBuilder().From.WhereTest().ToSql(), new QueryBuilder().From.WhereTestQuery().ToSql(), new QueryBuilder().From.WhereTestView().ToSql(), @@ -591,6 +603,7 @@ public sealed class From { public global::SpacetimeDB.Table Admins() => new("admins", new AdminsCols("admins"), new AdminsIxCols("admins")); public global::SpacetimeDB.Table Account() => new("account", new AccountCols("account"), new AccountIxCols("account")); + public global::SpacetimeDB.Table AllViewPkPlayers() => new("all_view_pk_players", new AllViewPkPlayersCols("all_view_pk_players"), new AllViewPkPlayersIxCols("all_view_pk_players")); public global::SpacetimeDB.Table ExampleData() => new("example_data", new ExampleDataCols("example_data"), new ExampleDataIxCols("example_data")); public global::SpacetimeDB.Table FindWhereTest() => new("find_where_test", new FindWhereTestCols("find_where_test"), new FindWhereTestIxCols("find_where_test")); public global::SpacetimeDB.Table MyAccount() => new("my_account", new MyAccountCols("my_account"), new MyAccountIxCols("my_account")); @@ -610,12 +623,17 @@ public sealed class From public global::SpacetimeDB.Table ScoresPlayer123() => new("scores_player_123", new ScoresPlayer123Cols("scores_player_123"), new ScoresPlayer123IxCols("scores_player_123")); public global::SpacetimeDB.Table ScoresPlayer123Level5() => new("scores_player_123_level_5", new ScoresPlayer123Level5Cols("scores_player_123_level_5"), new ScoresPlayer123Level5IxCols("scores_player_123_level_5")); public global::SpacetimeDB.Table ScoresPlayer123Range() => new("scores_player_123_range", new ScoresPlayer123RangeCols("scores_player_123_range"), new ScoresPlayer123RangeIxCols("scores_player_123_range")); + public global::SpacetimeDB.Table SenderViewPkPlayersA() => new("sender_view_pk_players_a", new SenderViewPkPlayersACols("sender_view_pk_players_a"), new SenderViewPkPlayersAIxCols("sender_view_pk_players_a")); + public global::SpacetimeDB.Table SenderViewPkPlayersB() => new("sender_view_pk_players_b", new SenderViewPkPlayersBCols("sender_view_pk_players_b"), new SenderViewPkPlayersBIxCols("sender_view_pk_players_b")); public global::SpacetimeDB.Table TestEvent() => new("test_event", new TestEventCols("test_event"), new TestEventIxCols("test_event")); public global::SpacetimeDB.Table User() => new("user", new UserCols("user"), new UserIxCols("user")); public global::SpacetimeDB.Table UsersAge1865() => new("users_age_18_65", new UsersAge1865Cols("users_age_18_65"), new UsersAge1865IxCols("users_age_18_65")); public global::SpacetimeDB.Table UsersAge18Plus() => new("users_age_18_plus", new UsersAge18PlusCols("users_age_18_plus"), new UsersAge18PlusIxCols("users_age_18_plus")); public global::SpacetimeDB.Table UsersAgeUnder18() => new("users_age_under_18", new UsersAgeUnder18Cols("users_age_under_18"), new UsersAgeUnder18IxCols("users_age_under_18")); public global::SpacetimeDB.Table UsersNamedAlice() => new("users_named_alice", new UsersNamedAliceCols("users_named_alice"), new UsersNamedAliceIxCols("users_named_alice")); + public global::SpacetimeDB.Table ViewPkMembership() => new("view_pk_membership", new ViewPkMembershipCols("view_pk_membership"), new ViewPkMembershipIxCols("view_pk_membership")); + public global::SpacetimeDB.Table ViewPkMembershipSecondary() => new("view_pk_membership_secondary", new ViewPkMembershipSecondaryCols("view_pk_membership_secondary"), new ViewPkMembershipSecondaryIxCols("view_pk_membership_secondary")); + public global::SpacetimeDB.Table ViewPkPlayer() => new("view_pk_player", new ViewPkPlayerCols("view_pk_player"), new ViewPkPlayerIxCols("view_pk_player")); public global::SpacetimeDB.Table WhereTest() => new("where_test", new WhereTestCols("where_test"), new WhereTestIxCols("where_test")); public global::SpacetimeDB.Table WhereTestQuery() => new("where_test_query", new WhereTestQueryCols("where_test_query"), new WhereTestQueryIxCols("where_test_query")); public global::SpacetimeDB.Table WhereTestView() => new("where_test_view", new WhereTestViewCols("where_test_view"), new WhereTestViewIxCols("where_test_view")); @@ -707,10 +725,14 @@ protected override bool Dispatch(IReducerEventContext context, Reducer reducer) Reducer.InsertNullStringIntoNonNullable args => Reducers.InvokeInsertNullStringIntoNonNullable(eventContext, args), Reducer.InsertNullStringIntoNullable args => Reducers.InvokeInsertNullStringIntoNullable(eventContext, args), Reducer.InsertResult args => Reducers.InvokeInsertResult(eventContext, args), + Reducer.InsertViewPkMembership args => Reducers.InvokeInsertViewPkMembership(eventContext, args), + Reducer.InsertViewPkMembershipSecondary args => Reducers.InvokeInsertViewPkMembershipSecondary(eventContext, args), + Reducer.InsertViewPkPlayer args => Reducers.InvokeInsertViewPkPlayer(eventContext, args), Reducer.InsertWhereTest args => Reducers.InvokeInsertWhereTest(eventContext, args), Reducer.Noop args => Reducers.InvokeNoop(eventContext, args), Reducer.SetNullableVec args => Reducers.InvokeSetNullableVec(eventContext, args), Reducer.ThrowError args => Reducers.InvokeThrowError(eventContext, args), + Reducer.UpdateViewPkPlayer args => Reducers.InvokeUpdateViewPkPlayer(eventContext, args), Reducer.UpdateWhereTest args => Reducers.InvokeUpdateWhereTest(eventContext, args), _ => throw new ArgumentOutOfRangeException("Reducer", $"Unknown reducer {reducer}") }; diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/AllViewPkPlayers.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/AllViewPkPlayers.g.cs new file mode 100644 index 00000000000..98b348c7f09 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/AllViewPkPlayers.g.cs @@ -0,0 +1,51 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class AllViewPkPlayersHandle : RemoteTableHandle + { + protected override string RemoteTableName => "all_view_pk_players"; + + internal AllViewPkPlayersHandle(DbConnection conn) : base(conn) + { + } + + protected override object GetPrimaryKey(ViewPkPlayer row) => row.Id; + } + + public readonly AllViewPkPlayersHandle AllViewPkPlayers; + } + + public sealed class AllViewPkPlayersCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Name { get; } + + public AllViewPkPlayersCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Name = new global::SpacetimeDB.Col(tableName, "name"); + } + } + + public sealed class AllViewPkPlayersIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public AllViewPkPlayersIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/SenderViewPkPlayersA.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/SenderViewPkPlayersA.g.cs new file mode 100644 index 00000000000..bc23d9e62ef --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/SenderViewPkPlayersA.g.cs @@ -0,0 +1,51 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class SenderViewPkPlayersAHandle : RemoteTableHandle + { + protected override string RemoteTableName => "sender_view_pk_players_a"; + + internal SenderViewPkPlayersAHandle(DbConnection conn) : base(conn) + { + } + + protected override object GetPrimaryKey(ViewPkPlayer row) => row.Id; + } + + public readonly SenderViewPkPlayersAHandle SenderViewPkPlayersA; + } + + public sealed class SenderViewPkPlayersACols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Name { get; } + + public SenderViewPkPlayersACols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Name = new global::SpacetimeDB.Col(tableName, "name"); + } + } + + public sealed class SenderViewPkPlayersAIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public SenderViewPkPlayersAIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/SenderViewPkPlayersB.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/SenderViewPkPlayersB.g.cs new file mode 100644 index 00000000000..214837f8276 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/SenderViewPkPlayersB.g.cs @@ -0,0 +1,51 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class SenderViewPkPlayersBHandle : RemoteTableHandle + { + protected override string RemoteTableName => "sender_view_pk_players_b"; + + internal SenderViewPkPlayersBHandle(DbConnection conn) : base(conn) + { + } + + protected override object GetPrimaryKey(ViewPkPlayer row) => row.Id; + } + + public readonly SenderViewPkPlayersBHandle SenderViewPkPlayersB; + } + + public sealed class SenderViewPkPlayersBCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Name { get; } + + public SenderViewPkPlayersBCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Name = new global::SpacetimeDB.Col(tableName, "name"); + } + } + + public sealed class SenderViewPkPlayersBIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public SenderViewPkPlayersBIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkMembership.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkMembership.g.cs new file mode 100644 index 00000000000..8c0339e7b86 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkMembership.g.cs @@ -0,0 +1,73 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class ViewPkMembershipHandle : RemoteTableHandle + { + protected override string RemoteTableName => "view_pk_membership"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override ulong GetKey(ViewPkMembership row) => row.Id; + + public IdUniqueIndex(ViewPkMembershipHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + public sealed class PlayerIdIndex : BTreeIndexBase + { + protected override ulong GetKey(ViewPkMembership row) => row.PlayerId; + + public PlayerIdIndex(ViewPkMembershipHandle table) : base(table) { } + } + + public readonly PlayerIdIndex PlayerId; + + internal ViewPkMembershipHandle(DbConnection conn) : base(conn) + { + Id = new(this); + PlayerId = new(this); + } + + protected override object GetPrimaryKey(ViewPkMembership row) => row.Id; + } + + public readonly ViewPkMembershipHandle ViewPkMembership; + } + + public sealed class ViewPkMembershipCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col PlayerId { get; } + + public ViewPkMembershipCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + PlayerId = new global::SpacetimeDB.Col(tableName, "player_id"); + } + } + + public sealed class ViewPkMembershipIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + public global::SpacetimeDB.IxCol PlayerId { get; } + + public ViewPkMembershipIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + PlayerId = new global::SpacetimeDB.IxCol(tableName, "player_id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkMembershipSecondary.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkMembershipSecondary.g.cs new file mode 100644 index 00000000000..ec4bf1ff25a --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkMembershipSecondary.g.cs @@ -0,0 +1,73 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class ViewPkMembershipSecondaryHandle : RemoteTableHandle + { + protected override string RemoteTableName => "view_pk_membership_secondary"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override ulong GetKey(ViewPkMembershipSecondary row) => row.Id; + + public IdUniqueIndex(ViewPkMembershipSecondaryHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + public sealed class PlayerIdIndex : BTreeIndexBase + { + protected override ulong GetKey(ViewPkMembershipSecondary row) => row.PlayerId; + + public PlayerIdIndex(ViewPkMembershipSecondaryHandle table) : base(table) { } + } + + public readonly PlayerIdIndex PlayerId; + + internal ViewPkMembershipSecondaryHandle(DbConnection conn) : base(conn) + { + Id = new(this); + PlayerId = new(this); + } + + protected override object GetPrimaryKey(ViewPkMembershipSecondary row) => row.Id; + } + + public readonly ViewPkMembershipSecondaryHandle ViewPkMembershipSecondary; + } + + public sealed class ViewPkMembershipSecondaryCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col PlayerId { get; } + + public ViewPkMembershipSecondaryCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + PlayerId = new global::SpacetimeDB.Col(tableName, "player_id"); + } + } + + public sealed class ViewPkMembershipSecondaryIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + public global::SpacetimeDB.IxCol PlayerId { get; } + + public ViewPkMembershipSecondaryIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + PlayerId = new global::SpacetimeDB.IxCol(tableName, "player_id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkPlayer.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkPlayer.g.cs new file mode 100644 index 00000000000..f420e3e2586 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ViewPkPlayer.g.cs @@ -0,0 +1,61 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using SpacetimeDB.BSATN; +using SpacetimeDB.ClientApi; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + public sealed partial class RemoteTables + { + public sealed class ViewPkPlayerHandle : RemoteTableHandle + { + protected override string RemoteTableName => "view_pk_player"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override ulong GetKey(ViewPkPlayer row) => row.Id; + + public IdUniqueIndex(ViewPkPlayerHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal ViewPkPlayerHandle(DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(ViewPkPlayer row) => row.Id; + } + + public readonly ViewPkPlayerHandle ViewPkPlayer; + } + + public sealed class ViewPkPlayerCols + { + public global::SpacetimeDB.Col Id { get; } + public global::SpacetimeDB.Col Name { get; } + + public ViewPkPlayerCols(string tableName) + { + Id = new global::SpacetimeDB.Col(tableName, "id"); + Name = new global::SpacetimeDB.Col(tableName, "name"); + } + } + + public sealed class ViewPkPlayerIxCols + { + public global::SpacetimeDB.IxCol Id { get; } + + public ViewPkPlayerIxCols(string tableName) + { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/WhereTestQuery.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/WhereTestQuery.g.cs index 8e039b09042..6ebbfe7db97 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/WhereTestQuery.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/WhereTestQuery.g.cs @@ -20,6 +20,8 @@ public sealed class WhereTestQueryHandle : RemoteTableHandle row.Id; } public readonly WhereTestQueryHandle WhereTestQuery; @@ -41,9 +43,11 @@ public WhereTestQueryCols(string tableName) public sealed class WhereTestQueryIxCols { + public global::SpacetimeDB.IxCol Id { get; } public WhereTestQueryIxCols(string tableName) { + Id = new global::SpacetimeDB.IxCol(tableName, "id"); } } } diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkMembership.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkMembership.g.cs new file mode 100644 index 00000000000..330ba5af904 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkMembership.g.cs @@ -0,0 +1,34 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ViewPkMembership + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "player_id")] + public ulong PlayerId; + + public ViewPkMembership( + ulong Id, + ulong PlayerId + ) + { + this.Id = Id; + this.PlayerId = PlayerId; + } + + public ViewPkMembership() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkMembershipSecondary.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkMembershipSecondary.g.cs new file mode 100644 index 00000000000..aec64d3466b --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkMembershipSecondary.g.cs @@ -0,0 +1,34 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ViewPkMembershipSecondary + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "player_id")] + public ulong PlayerId; + + public ViewPkMembershipSecondary( + ulong Id, + ulong PlayerId + ) + { + this.Id = Id; + this.PlayerId = PlayerId; + } + + public ViewPkMembershipSecondary() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkPlayer.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkPlayer.g.cs new file mode 100644 index 00000000000..b3b1da245ca --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/ViewPkPlayer.g.cs @@ -0,0 +1,35 @@ +// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE +// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. + +#nullable enable + +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; + +namespace SpacetimeDB.Types +{ + [SpacetimeDB.Type] + [DataContract] + public sealed partial class ViewPkPlayer + { + [DataMember(Name = "id")] + public ulong Id; + [DataMember(Name = "name")] + public string Name; + + public ViewPkPlayer( + ulong Id, + string Name + ) + { + this.Id = Id; + this.Name = Name; + } + + public ViewPkPlayer() + { + this.Name = ""; + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/Program.cs b/sdks/csharp/examples~/regression-tests/procedure-client/Program.cs index 95e1a0f6508..8997f596354 100644 --- a/sdks/csharp/examples~/regression-tests/procedure-client/Program.cs +++ b/sdks/csharp/examples~/regression-tests/procedure-client/Program.cs @@ -5,38 +5,13 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using RegressionTests.Shared; using SpacetimeDB; using SpacetimeDB.Types; const string HOST = "http://localhost:3000"; const string DBNAME = "procedure-tests"; -DbConnection ConnectToDB() -{ - DbConnection? conn = null; - conn = DbConnection.Builder() - .WithUri(HOST) - .WithDatabaseName(DBNAME) - .OnConnect(OnConnected) - .OnConnectError((err) => - { - throw err; - }) - .OnDisconnect((conn, err) => - { - if (err != null) - { - throw err; - } - else - { - throw new Exception("Unexpected disconnect"); - } - }) - .Build(); - return conn; -} - uint waiting = 0; bool applied = false; @@ -201,24 +176,9 @@ void OnSubscriptionApplied(SubscriptionEventContext context) }); } -System.AppDomain.CurrentDomain.UnhandledException += (sender, args) => -{ - Log.Exception($"Unhandled exception: {sender} {args}"); - Environment.Exit(1); -}; -var db = ConnectToDB(); -Log.Info("Starting timer"); +RegressionTestHarness.RegisterUnhandledExceptionExitHandler(); +var db = RegressionTestHarness.ConnectToDatabase(HOST, DBNAME, OnConnected); const int TIMEOUT = 20; // seconds; -var start = DateTime.Now; -while (!applied || waiting > 0) -{ - db.FrameTick(); - Thread.Sleep(100); - if ((DateTime.Now - start).Seconds > TIMEOUT) - { - Log.Error($"Timeout, all events should have elapsed in {TIMEOUT} seconds!"); - Environment.Exit(1); - } -} +RegressionTestHarness.FrameTickUntilComplete(db, () => applied && waiting == 0, TIMEOUT); Log.Info("Success"); Environment.Exit(0); diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/client.csproj b/sdks/csharp/examples~/regression-tests/procedure-client/client.csproj index 590940fbcb0..04759b33920 100644 --- a/sdks/csharp/examples~/regression-tests/procedure-client/client.csproj +++ b/sdks/csharp/examples~/regression-tests/procedure-client/client.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs index 59344f7ba69..948b4e405d7 100644 --- a/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs +++ b/sdks/csharp/examples~/regression-tests/procedure-client/module_bindings/SpacetimeDBClient.g.cs @@ -1,7 +1,7 @@ // THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE // WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD. -// This was generated using spacetimedb cli version 2.0.0 (commit 9e0e81a6aaec6bf3619cfb9f7916743d86ab7ffc). +// This was generated using spacetimedb cli version 2.0.4 (commit dfc726be29516b8cdecc651f5c9705026a624a04). #nullable enable diff --git a/sdks/csharp/examples~/regression-tests/republishing/client/Program.cs b/sdks/csharp/examples~/regression-tests/republishing/client/Program.cs index 52931e7bf7d..e8493cee87f 100644 --- a/sdks/csharp/examples~/regression-tests/republishing/client/Program.cs +++ b/sdks/csharp/examples~/regression-tests/republishing/client/Program.cs @@ -5,38 +5,13 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using RegressionTests.Shared; using SpacetimeDB; using SpacetimeDB.Types; const string HOST = "http://localhost:3000"; const string DBNAME = "republish-test"; -DbConnection ConnectToDB() -{ - DbConnection? conn = null; - conn = DbConnection.Builder() - .WithUri(HOST) - .WithDatabaseName(DBNAME) - .OnConnect(OnConnected) - .OnConnectError((err) => - { - throw err; - }) - .OnDisconnect((conn, err) => - { - if (err != null) - { - throw err; - } - else - { - throw new Exception("Unexpected disconnect"); - } - }) - .Build(); - return conn; -} - uint waiting = 0; bool applied = false; SubscriptionHandle? handle = null; @@ -128,24 +103,9 @@ void OnSubscriptionApplied(SubscriptionEventContext context) Log.Info("Evaluation of ExampleData in republishing test completed."); } -System.AppDomain.CurrentDomain.UnhandledException += (sender, args) => -{ - Log.Exception($"Unhandled exception: {sender} {args}"); - Environment.Exit(1); -}; -var db = ConnectToDB(); -Log.Info("Starting timer"); +RegressionTestHarness.RegisterUnhandledExceptionExitHandler(); +var db = RegressionTestHarness.ConnectToDatabase(HOST, DBNAME, OnConnected); const int TIMEOUT = 20; // seconds; -var start = DateTime.Now; -while (!applied || waiting > 0) -{ - db.FrameTick(); - Thread.Sleep(100); - if ((DateTime.Now - start).Seconds > TIMEOUT) - { - Log.Error($"Timeout, all events should have elapsed in {TIMEOUT} seconds!"); - Environment.Exit(1); - } -} +RegressionTestHarness.FrameTickUntilComplete(db, () => applied && waiting == 0, TIMEOUT); Log.Info("Success"); Environment.Exit(0); diff --git a/sdks/csharp/examples~/regression-tests/republishing/client/client.csproj b/sdks/csharp/examples~/regression-tests/republishing/client/client.csproj index 759ea6f4a26..9c07c1d1c1b 100644 --- a/sdks/csharp/examples~/regression-tests/republishing/client/client.csproj +++ b/sdks/csharp/examples~/regression-tests/republishing/client/client.csproj @@ -11,4 +11,8 @@ + + + + diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs index 67f57eef047..39b1a881efe 100644 --- a/sdks/csharp/examples~/regression-tests/server/Lib.cs +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -169,6 +169,35 @@ public partial struct NullStringNullable public string? Name; } + [SpacetimeDB.Table(Accessor = "view_pk_player", Public = true)] + public partial struct ViewPkPlayer + { + [SpacetimeDB.PrimaryKey] + public ulong Id; + + public string Name; + } + + [SpacetimeDB.Table(Accessor = "view_pk_membership", Public = true)] + public partial struct ViewPkMembership + { + [SpacetimeDB.PrimaryKey] + public ulong Id; + + [SpacetimeDB.Index.BTree] + public ulong PlayerId; + } + + [SpacetimeDB.Table(Accessor = "view_pk_membership_secondary", Public = true)] + public partial struct ViewPkMembershipSecondary + { + [SpacetimeDB.PrimaryKey] + public ulong Id; + + [SpacetimeDB.Index.BTree] + public ulong PlayerId; + } + // At-most-one row: return T? [SpacetimeDB.View(Accessor = "my_player", Public = true)] public static Player? MyPlayer(ViewContext ctx) @@ -335,6 +364,34 @@ public static List NullableVecView(AnonymousViewContext ctx) return rows; } + [SpacetimeDB.View(Accessor = "all_view_pk_players", Public = true)] + public static IQuery AllViewPkPlayers(ViewContext ctx) + { + return ctx.From.view_pk_player(); + } + + [SpacetimeDB.View(Accessor = "sender_view_pk_players_a", Public = true)] + public static IQuery SenderViewPkPlayersA(ViewContext ctx) + { + return ctx + .From.view_pk_membership() + .RightSemijoin( + ctx.From.view_pk_player(), + (membership, player) => membership.PlayerId.Eq(player.Id) + ); + } + + [SpacetimeDB.View(Accessor = "sender_view_pk_players_b", Public = true)] + public static IQuery SenderViewPkPlayersB(ViewContext ctx) + { + return ctx + .From.view_pk_membership_secondary() + .RightSemijoin( + ctx.From.view_pk_player(), + (membership, player) => membership.PlayerId.Eq(player.Id) + ); + } + [SpacetimeDB.Reducer] public static void Delete(ReducerContext ctx, uint id) { @@ -424,6 +481,36 @@ public static void UpdateWhereTest(ReducerContext ctx, uint id, uint value, stri ); } + [SpacetimeDB.Reducer] + public static void InsertViewPkPlayer(ReducerContext ctx, ulong id, string name) + { + ctx.Db.view_pk_player.Insert(new ViewPkPlayer { Id = id, Name = name }); + } + + [SpacetimeDB.Reducer] + public static void UpdateViewPkPlayer(ReducerContext ctx, ulong id, string name) + { + ctx.Db.view_pk_player.Id.Update(new ViewPkPlayer { Id = id, Name = name }); + } + + [SpacetimeDB.Reducer] + public static void InsertViewPkMembership(ReducerContext ctx, ulong id, ulong playerId) + { + ctx.Db.view_pk_membership.Insert(new ViewPkMembership { Id = id, PlayerId = playerId }); + } + + [SpacetimeDB.Reducer] + public static void InsertViewPkMembershipSecondary( + ReducerContext ctx, + ulong id, + ulong playerId + ) + { + ctx.Db.view_pk_membership_secondary.Insert( + new ViewPkMembershipSecondary { Id = id, PlayerId = playerId } + ); + } + [Reducer(ReducerKind.ClientConnected)] public static void ClientConnected(ReducerContext ctx) { diff --git a/sdks/csharp/examples~/regression-tests/shared/RegressionTestHarness.cs b/sdks/csharp/examples~/regression-tests/shared/RegressionTestHarness.cs new file mode 100644 index 00000000000..986c042e226 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/shared/RegressionTestHarness.cs @@ -0,0 +1,92 @@ +using System.Threading; +using SpacetimeDB; +using SpacetimeDB.Types; + +namespace RegressionTests.Shared; + +internal static class RegressionTestHarness +{ + public static void RegisterUnhandledExceptionExitHandler() + { + AppDomain.CurrentDomain.UnhandledException += (_, eventArgs) => + { + Log.Exception($"Unhandled exception: {eventArgs.ExceptionObject}"); + Environment.Exit(1); + }; + } + + public static DbConnection ConnectToDatabase( + string host, + string databaseName, + DbConnectionBuilder.ConnectCallback onConnect, + Action? onConnectError = null, + Action? onDisconnect = null + ) + { + return DbConnection + .Builder() + .WithUri(host) + .WithDatabaseName(databaseName) + .OnConnect(onConnect) + .OnConnectError(err => + { + if (onConnectError != null) + { + onConnectError(err); + return; + } + + throw err; + }) + .OnDisconnect((_, err) => + { + if (onDisconnect != null) + { + onDisconnect(err); + return; + } + + if (err != null) + { + throw err; + } + + throw new Exception("Unexpected disconnect"); + }) + .Build(); + } + + public static void FrameTickUntilComplete( + DbConnection conn, + Func isComplete, + int timeoutSeconds, + int sleepMilliseconds = 100, + bool logStart = true + ) + { + if (logStart) + { + Log.Info("Starting timer"); + } + + var deadline = DateTime.UtcNow.AddSeconds(timeoutSeconds); + while (!isComplete()) + { + conn.FrameTick(); + Thread.Sleep(sleepMilliseconds); + if (DateTime.UtcNow > deadline) + { + Log.Error($"Timeout, all events should have elapsed in {timeoutSeconds} seconds!"); + Environment.Exit(1); + } + } + } + + public static void Require(bool condition, string message) + { + if (!condition) + { + throw new Exception(message); + } + } +} diff --git a/sdks/csharp/tools~/run-regression-tests.sh b/sdks/csharp/tools~/run-regression-tests.sh index fdd7733bf65..847409c9c32 100644 --- a/sdks/csharp/tools~/run-regression-tests.sh +++ b/sdks/csharp/tools~/run-regression-tests.sh @@ -31,7 +31,6 @@ rm -rf "$SDK_PATH/examples~/regression-tests/procedure-client/module_bindings"/* # Publish module for procedure tests cargo run --manifest-path "$STDB_PATH/crates/cli/Cargo.toml" -- publish -c -y --server local -p "$STDB_PATH/modules/sdk-test-procedure" procedure-tests - # Run client for btree test cd "$SDK_PATH/examples~/regression-tests/client" && dotnet run -c Debug diff --git a/sdks/rust/tests/test.rs b/sdks/rust/tests/test.rs index ed623c7d36f..02f0357a524 100644 --- a/sdks/rust/tests/test.rs +++ b/sdks/rust/tests/test.rs @@ -528,3 +528,4 @@ macro_rules! view_pk_tests { } view_pk_tests!(rust_view_pk, ""); +view_pk_tests!(csharp_view_pk, "-cs");