From e60ef4b0a19e7765f5b84c2aaf9cbbe6bedaab45 Mon Sep 17 00:00:00 2001 From: rekhoff Date: Tue, 2 Dec 2025 11:53:08 -0800 Subject: [PATCH 1/5] First pass on implementing Transactions for Procedures --- crates/bindings-csharp/BSATN.Codegen/Type.cs | 25 ++ crates/bindings-csharp/Codegen/Module.cs | 317 ++++++++++++++++-- crates/bindings-csharp/Runtime/Exceptions.cs | 19 ++ .../bindings-csharp/Runtime/Internal/FFI.cs | 84 +++-- .../Runtime/Internal/IProcedure.cs | 6 + .../Runtime/Internal/Module.cs | 31 ++ .../Runtime/Internal/Procedure.cs | 136 ++++++++ crates/bindings-csharp/Runtime/bindings.c | 10 + .../examples~/regression-tests/server/Lib.cs | 78 ++++- 9 files changed, 646 insertions(+), 60 deletions(-) create mode 100644 crates/bindings-csharp/Runtime/Internal/Procedure.cs diff --git a/crates/bindings-csharp/BSATN.Codegen/Type.cs b/crates/bindings-csharp/BSATN.Codegen/Type.cs index 4bfbf45ec7e..56c4af41f07 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Type.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Type.cs @@ -44,6 +44,11 @@ public abstract record TypeUse(string Name, string BSATNName) /// public static string BsatnFieldSuffix => $"{BSATN_FIELD_SUFFIX}"; + /// + /// Indicates whether this type represents a void return. + /// + public virtual bool IsVoid => false; + /// /// Parse a type use for a member. /// @@ -53,6 +58,11 @@ public abstract record TypeUse(string Name, string BSATNName) /// public static TypeUse Parse(ISymbol member, ITypeSymbol typeSymbol, DiagReporter diag) { + if (typeSymbol.SpecialType == SpecialType.System_Void) + { + return new VoidUse("void", "SpacetimeDB.BSATN.Unit"); + } + var type = SymbolToName(typeSymbol); string typeInfo; @@ -194,6 +204,21 @@ public override string GetHashCodeStatement(string inVar, string outVar, int lev $"var {outVar} = {inVar} == null ? 0 : {inVar}.GetHashCode();"; } +public sealed record VoidUse(string Type, string TypeInfo) : TypeUse(Type, TypeInfo) +{ + public override bool IsVoid => true; + + public override string EqualsStatement( + string inVar1, + string inVar2, + string outVar, + int level = 0 + ) => $"var {outVar} = true;"; + + public override string GetHashCodeStatement(string inVar, string outVar, int level = 0) => + $"var {outVar} = 0;"; +} + /// /// A use of an array type. /// diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 1049a10668a..79617a0646e 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1232,33 +1232,63 @@ public string GenerateClass() { var invocationArgs = Args.Length == 0 ? "" : ", " + string.Join(", ", Args.Select(a => a.Name)); + var invocation = $"{FullName}((SpacetimeDB.ProcedureContext)ctx{invocationArgs})"; - var invokeBody = HasWrongSignature - ? "throw new System.InvalidOperationException(\"Invalid procedure signature.\");" - : $$""" - var result = {{FullName}}((SpacetimeDB.ProcedureContext)ctx{{invocationArgs}}); - using var output = new MemoryStream(); - using var writer = new BinaryWriter(output); - new {{ReturnType.BSATNName}}().Write(writer, result); - return output.ToArray(); - """; + string[] bodyLines; - return $$""" - class {{Name}} : SpacetimeDB.Internal.IProcedure { - {{MemberDeclaration.GenerateBsatnFields(Accessibility.Private, Args)}} + if (HasWrongSignature) + { + bodyLines = new[] + { + "throw new System.InvalidOperationException(\"Invalid procedure signature.\");", + }; + } + else if (ReturnType.IsVoid) + { + bodyLines = new[] + { + $"{invocation};", + "return System.Array.Empty();", + }; + } + else + { + var serializer = $"new {ReturnType.BSATNName}()"; + bodyLines = new[] + { + $"var result = {invocation};", + "using var output = new MemoryStream();", + "using var writer = new BinaryWriter(output);", + $"{serializer}.Write(writer, result);", + "return output.ToArray();", + }; + } + + var invokeBody = string.Join("\n", bodyLines.Select(line => $" {line}")); + var paramReads = Args.Length == 0 + ? string.Empty + : string.Join( + "\n", + Args.Select(a => + $" var {a.Name} = {a.Name}{TypeUse.BsatnFieldSuffix}.Read(reader);" + ) + ) + "\n"; + var returnTypeExpr = ReturnType.IsVoid + ? "SpacetimeDB.BSATN.AlgebraicType.Unit" + : $"new {ReturnType.BSATNName}().GetAlgebraicType(registrar)"; + + return $$$""" + class {{{Name}}} : SpacetimeDB.Internal.IProcedure { + {{{MemberDeclaration.GenerateBsatnFields(Accessibility.Private, Args)}}} public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( - nameof({{Name}}), - [{{MemberDeclaration.GenerateDefs(Args)}}], - new {{ReturnType.BSATNName}}().GetAlgebraicType(registrar) + nameof({{{Name}}}), + [{{{MemberDeclaration.GenerateDefs(Args)}}}], + {{{returnTypeExpr}}} ); public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { - {{string.Join( - "\n", - Args.Select(a => $"var {a.Name} = {a.Name}{TypeUse.BsatnFieldSuffix}.Read(reader);") - )}} - {{invokeBody}} + {{{paramReads}}}{{{invokeBody}}} } } """; @@ -1591,6 +1621,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) // This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. // We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. #pragma warning disable CS0436 + #pragma warning disable STDB_UNSTABLE using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; @@ -1607,20 +1638,22 @@ public sealed record ReducerContext : DbContext, Internal.IReducerContext // We need this property to be non-static for parity with client SDK. public Identity Identity => Internal.IReducerContext.GetIdentity(); - internal ReducerContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time) { + internal ReducerContext(Identity identity, ConnectionId? connectionId, Random random, + Timestamp time, AuthCtx? senderAuth = null) + { Sender = identity; ConnectionId = connectionId; Rng = random; Timestamp = time; - SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, identity); + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); } } - public sealed record ProcedureContext : Internal.IProcedureContext { + public sealed record ProcedureContext : Internal.IInternalProcedureContext { public readonly Identity Sender; public readonly ConnectionId? ConnectionId; public readonly Random Rng; - public readonly Timestamp Timestamp; + public Timestamp Timestamp { get; private set; } public readonly AuthCtx SenderAuth; // We need this property to be non-static for parity with client SDK. @@ -1633,6 +1666,237 @@ internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random Timestamp = time; SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, identity); } + + private Internal.TransactionOffset? pendingTxOffset; + + public bool TryTakeTransactionOffset(out Internal.TransactionOffset offset) + { + if (pendingTxOffset is { } value) + { + pendingTxOffset = null; + offset = value; + return true; + } + offset = default; + return false; + } + + public void SetTransactionOffset(Internal.TransactionOffset offset) => + pendingTxOffset = offset; + + [Experimental("STDB_UNSTABLE")] + public sealed record TxContext(Local Db, ReducerContext Reducer) : DbContext(Db) + { + public Identity Sender => Reducer.Sender; + public ConnectionId? ConnectionId => Reducer.ConnectionId; + public Timestamp Timestamp => Reducer.Timestamp; + public Random Rng => Reducer.Rng; + public AuthCtx SenderAuth => Reducer.SenderAuth; + } + + private sealed class AbortGuard : IDisposable + { + private readonly Action abort; + private bool disarmed; + public AbortGuard(Action abort) => this.abort = abort; + public void Disarm() => disarmed = true; + public void Dispose() { if (!disarmed) abort(); } + } + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body) + where TError : Exception + { + try + { + var result = RunWithRetry(body); + return result.IsSuccess + ? TxOutcome.Success(result.Value!) + : TxOutcome.Failure(result.Error!); + } + catch (Exception ex) + { + return TxOutcome.Failure(ex); + } + } + + [Experimental("STDB_UNSTABLE")] + public T WithTx(Func body) + { + var outcome = TryWithTx(ctx => + TxResult.Success(body(ctx))); + if (outcome.IsSuccess) return outcome.Value!; + throw outcome.Error!; + } + + [Experimental("STDB_UNSTABLE")] + public readonly record struct TxOutcome(bool IsSuccess, T? Value, Exception? Error) + { + public static TxOutcome Success(T value) => new(true, value, null); + public static TxOutcome Failure(Exception error) => new(false, default, error); + + public TxOutcome Map(Func mapper) => + IsSuccess ? TxOutcome.Success(mapper(Value!)) : TxOutcome.Failure(Error!); + } + + private TxResult RunWithRetry( + Func> body) + where TError : Exception + { + var result = RunOnce(body); + + bool retry() + { + result = RunOnce(body); + return true; + } + + if (!SpacetimeDB.Internal.Procedure.CommitMutTxWithRetry(retry)) + { + SpacetimeDB.Internal.Procedure.AbortMutTx(); + } + + if (TryTakeTransactionOffset(out var offset)) + { + SpacetimeDB.Internal.Module.RecordProcedureTxOffset(offset); + } + return result; + } + + [Experimental("STDB_UNSTABLE")] + public async Task WithTxAsync(Func> body) + { + var outcome = await TryWithTxAsync(async ctx => + TxResult.Success(await body(ctx).ConfigureAwait(false))).ConfigureAwait(false); + if (outcome.IsSuccess) return outcome.Value!; + throw outcome.Error!; + } + + public async Task> TryWithTxAsync( + Func>> body) + where TError : Exception + { + try + { + return (await RunWithRetryAsync(body).ConfigureAwait(false)).Match( + onSuccess: TxOutcome.Success, + onError: TxOutcome.Failure); + } + catch (Exception ex) + { + return TxOutcome.Failure(ex); + } + } + + [Experimental("STDB_UNSTABLE")] + public readonly record struct TxResult + where TError : Exception + { + public bool IsSuccess { get; } + public TSuccess? Value { get; } + public TError? Error { get; } + + private TxResult(bool isSuccess, TSuccess? value, TError? error) + { + IsSuccess = isSuccess; + Value = value; + Error = error; + } + + public static TxResult Success(TSuccess value) => + new(true, value, default); + + public static TxResult Failure(TError error) => + new(false, default, error); + + public TResult Match( + Func onSuccess, + Func onError) + { + if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess)); + if (onError is null) throw new ArgumentNullException(nameof(onError)); + return IsSuccess ? onSuccess(Value!) : onError(Error!); + } + } + + private async Task> RunWithRetryAsync( + Func>> body) + where TError : Exception + { + var result = await RunOnceAsync(body).ConfigureAwait(false); + + async Task Retry() + { + result = await RunOnceAsync(body).ConfigureAwait(false); + return true; + } + + if (!await SpacetimeDB.Internal.Procedure.CommitMutTxWithRetryAsync(Retry).ConfigureAwait(false)) + { + await SpacetimeDB.Internal.Procedure.AbortMutTxAsync().ConfigureAwait(false); + } + if (TryTakeTransactionOffset(out var offset)) { + SpacetimeDB.Internal.Module.RecordProcedureTxOffset(offset); + } + + return result; + } + + private async Task> RunOnceAsync( + Func>> body) + where TError : Exception + { + var micros = SpacetimeDB.Internal.Procedure.StartMutTx(); + await using var guard = new AsyncAbortGuard(SpacetimeDB.Internal.Procedure.AbortMutTxAsync); + var txCtx = MakeTxContext(micros); + var output = await body(txCtx).ConfigureAwait(false); + await guard.DisarmAsync().ConfigureAwait(false); + return output; + } + + private sealed class AsyncAbortGuard : IAsyncDisposable + { + private readonly Func abort; + private bool disarmed; + public AsyncAbortGuard(Func abort) => this.abort = abort; + public Task DisarmAsync() { disarmed = true; return Task.CompletedTask; } + public async ValueTask DisposeAsync() + { + if (!disarmed) await abort().ConfigureAwait(false); + } + } + + private bool RetryOnce( + Func> body, + out TxResult result) + where TError : Exception + { + result = RunOnce(body); + return true; + } + + private TxResult RunOnce( + Func> body) + where TError : Exception + { + var micros = SpacetimeDB.Internal.Procedure.StartMutTx(); + using var guard = new AbortGuard(SpacetimeDB.Internal.Procedure.AbortMutTx); + var txCtx = MakeTxContext(micros); + var output = body(txCtx); + guard.Disarm(); + return output; + } + + private TxContext MakeTxContext(long micros) + { + var txTimestamp = new Timestamp(micros); + Timestamp = txTimestamp; + var reducerCtx = new ReducerContext( + Sender, ConnectionId, new Random(unchecked((int)micros)), + txTimestamp, SenderAuth); + return new TxContext(new Local(), reducerCtx); + } } public sealed record ViewContext : DbContext, Internal.IViewContext @@ -1805,6 +2069,10 @@ SpacetimeDB.Internal.BytesSink result_sink args, result_sink ); + + [UnmanagedCallersOnly(EntryPoint = "__take_procedure_tx_offset__")] + public static byte __take_procedure_tx_offset__(ulong* offset) => + SpacetimeDB.Internal.Module.__take_procedure_tx_offset__(out *offset) ? (byte)1 : (byte)0; [UnmanagedCallersOnly(EntryPoint = "__call_view__")] public static SpacetimeDB.Internal.Errno __call_view__( @@ -1838,6 +2106,7 @@ SpacetimeDB.Internal.BytesSink sink #endif } + #pragma warning restore STDB_UNSTABLE #pragma warning restore CS0436 """ ); diff --git a/crates/bindings-csharp/Runtime/Exceptions.cs b/crates/bindings-csharp/Runtime/Exceptions.cs index 1488b00d91f..e6cd7ceacbf 100644 --- a/crates/bindings-csharp/Runtime/Exceptions.cs +++ b/crates/bindings-csharp/Runtime/Exceptions.cs @@ -77,6 +77,25 @@ public class AutoIncOverflowException : StdbException public override string Message => "The auto-increment sequence overflowed"; } +public class TransactionWouldBlockException : StdbException { + public override string Message => "Attempted operation while another transaction is open"; +} + +public class TransactionNotAnonymousException : StdbException +{ + public override string Message => "The transaction is not anonymous"; +} + +public class TransactionIsReadOnlyException : StdbException +{ + public override string Message => "The transaction is read-only"; +} + +public class TransactionIsMutableException : StdbException { + public override string Message => + "ABI call can only be made while inside a read-only transaction"; +} + public class UnknownException : StdbException { private readonly Errno code; diff --git a/crates/bindings-csharp/Runtime/Internal/FFI.cs b/crates/bindings-csharp/Runtime/Internal/FFI.cs index 1f63e70135a..a5e3b1e612b 100644 --- a/crates/bindings-csharp/Runtime/Internal/FFI.cs +++ b/crates/bindings-csharp/Runtime/Internal/FFI.cs @@ -37,6 +37,10 @@ public enum Errno : short INDEX_NOT_UNIQUE = 14, NO_SUCH_ROW = 15, AUTO_INC_OVERFLOW = 16, + WOULD_BLOCK_TRANSACTION = 17, + TRANSACTION_NOT_ANONYMOUS = 18, + TRANSACTION_IS_READ_ONLY = 19, + TRANSACTION_IS_MUT = 20, } #pragma warning disable IDE1006 // Naming Styles - Not applicable to FFI stuff. @@ -68,6 +72,14 @@ internal static partial class FFI "bindings" #endif ; + + const string StdbNamespace10_3 = +#if EXPERIMENTAL_WASM_AOT + "spacetime_10.3" +#else + "bindings" +#endif + ; [NativeMarshalling(typeof(Marshaller))] public struct CheckedStatus @@ -86,30 +98,45 @@ internal static class Marshaller { public static CheckedStatus ConvertToManaged(Errno status) { - if (status == 0) - { - return default; - } - throw status switch - { - Errno.NOT_IN_TRANSACTION => new NotInTransactionException(), - Errno.BSATN_DECODE_ERROR => new BsatnDecodeException(), - Errno.NO_SUCH_TABLE => new NoSuchTableException(), - Errno.NO_SUCH_INDEX => new NoSuchIndexException(), - Errno.NO_SUCH_ITER => new NoSuchIterException(), - Errno.NO_SUCH_CONSOLE_TIMER => new NoSuchLogStopwatch(), - Errno.NO_SUCH_BYTES => new NoSuchBytesException(), - Errno.NO_SPACE => new NoSpaceException(), - Errno.BUFFER_TOO_SMALL => new BufferTooSmallException(), - Errno.UNIQUE_ALREADY_EXISTS => new UniqueConstraintViolationException(), - Errno.SCHEDULE_AT_DELAY_TOO_LONG => new ScheduleAtDelayTooLongException(), - Errno.INDEX_NOT_UNIQUE => new IndexNotUniqueException(), - Errno.NO_SUCH_ROW => new NoSuchRowException(), - Errno.AUTO_INC_OVERFLOW => new AutoIncOverflowException(), - _ => new UnknownException(status), - }; + ErrnoHelpers.ThrowIfError(status); + return default; + } + } + } + + internal static class ErrnoHelpers + { + public static void ThrowIfError(Errno status) + { + if (status == Errno.OK) + { + return; } + + throw ToException(status); } + + public static Exception ToException(Errno status) => status switch + { + Errno.NOT_IN_TRANSACTION => new NotInTransactionException(), + Errno.BSATN_DECODE_ERROR => new BsatnDecodeException(), + Errno.NO_SUCH_TABLE => new NoSuchTableException(), + Errno.NO_SUCH_INDEX => new NoSuchIndexException(), + Errno.NO_SUCH_ITER => new NoSuchIterException(), + Errno.NO_SUCH_CONSOLE_TIMER => new NoSuchLogStopwatch(), + Errno.NO_SUCH_BYTES => new NoSuchBytesException(), + Errno.NO_SPACE => new NoSpaceException(), + Errno.BUFFER_TOO_SMALL => new BufferTooSmallException(), + Errno.UNIQUE_ALREADY_EXISTS => new UniqueConstraintViolationException(), + Errno.INDEX_NOT_UNIQUE => new IndexNotUniqueException(), + Errno.NO_SUCH_ROW => new NoSuchRowException(), + Errno.AUTO_INC_OVERFLOW => new AutoIncOverflowException(), + Errno.WOULD_BLOCK_TRANSACTION => new TransactionWouldBlockException(), + Errno.TRANSACTION_NOT_ANONYMOUS => new TransactionNotAnonymousException(), + Errno.TRANSACTION_IS_READ_ONLY => new TransactionIsReadOnlyException(), + Errno.TRANSACTION_IS_MUT => new TransactionIsMutableException(), + _ => new UnknownException(status), + }; } [StructLayout(LayoutKind.Sequential)] @@ -318,4 +345,17 @@ uint args_len [DllImport(StdbNamespace10_2)] public static extern Errno get_jwt(ref ConnectionId connectionId, out BytesSource source); + + [LibraryImport(StdbNamespace10_3, EntryPoint = "procedure_start_mut_tx")] + public static partial Errno procedure_start_mut_tx(out long micros); + + [LibraryImport(StdbNamespace10_3, EntryPoint = "procedure_commit_mut_tx")] + public static partial CheckedStatus procedure_commit_mut_tx(); + + [LibraryImport(StdbNamespace10_3, EntryPoint = "procedure_abort_mut_tx")] + public static partial CheckedStatus procedure_abort_mut_tx(); + + [LibraryImport(StdbNamespace10_3, EntryPoint = "__take_procedure_tx_offset__")] + [return: MarshalAs(UnmanagedType.I1)] + public static partial bool take_procedure_tx_offset(out ulong offset); } diff --git a/crates/bindings-csharp/Runtime/Internal/IProcedure.cs b/crates/bindings-csharp/Runtime/Internal/IProcedure.cs index ba7e6f13540..f5cd96d81c9 100644 --- a/crates/bindings-csharp/Runtime/Internal/IProcedure.cs +++ b/crates/bindings-csharp/Runtime/Internal/IProcedure.cs @@ -32,3 +32,9 @@ public static void VolatileNonatomicScheduleImmediate(string name, MemoryStream ); } } + +public interface IInternalProcedureContext : IProcedureContext +{ + bool TryTakeTransactionOffset(out TransactionOffset offset); + void SetTransactionOffset(TransactionOffset offset); +} diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 46157d9308b..274a87c3fdf 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -65,6 +65,7 @@ public static class Module private static readonly List> viewDefs = []; private static readonly List viewDispatchers = []; private static readonly List anonymousViewDispatchers = []; + private static TransactionOffset? lastProcedureTxOffset; private static Func< Identity, @@ -180,6 +181,16 @@ public static void RegisterClientVisibilityFilter(Filter rlsFilter) } } + public static void RecordProcedureTxOffset(TransactionOffset offset) => + lastProcedureTxOffset = offset; + + public static TransactionOffset? TakeProcedureTxOffset() + { + var tmp = lastProcedureTxOffset; + lastProcedureTxOffset = null; + return tmp; + } + public static void RegisterTableDefaultValue(string table, ushort colId, byte[] value) => moduleDef.RegisterTableDefaultValue(table, colId, value); @@ -347,12 +358,20 @@ BytesSink resultSink using var stream = new MemoryStream(args.Consume()); using var reader = new BinaryReader(stream); + using var scope = Procedure.PushContext(ctx); var bytes = procedures[(int)id].Invoke(reader, ctx); if (stream.Position != stream.Length) { throw new Exception("Unrecognised extra bytes in the procedure arguments"); } resultSink.Write(bytes); + if (ctx is IInternalProcedureContext internalCtx) + { + if (internalCtx.TryTakeTransactionOffset(out var offset)) + { + RecordProcedureTxOffset(offset); + } + } return Errno.OK; } catch (Exception e) @@ -362,6 +381,18 @@ BytesSink resultSink return Errno.HOST_CALL_FAILURE; } } + + public static bool __take_procedure_tx_offset__(out ulong offset) + { + if (TakeProcedureTxOffset() is { } tx) + { + offset = tx.Value; + return true; + } + + offset = 0; + return false; + } public static Errno __call_view__( uint id, diff --git a/crates/bindings-csharp/Runtime/Internal/Procedure.cs b/crates/bindings-csharp/Runtime/Internal/Procedure.cs new file mode 100644 index 00000000000..f82a3bcbc8b --- /dev/null +++ b/crates/bindings-csharp/Runtime/Internal/Procedure.cs @@ -0,0 +1,136 @@ +using System.Threading; + +namespace SpacetimeDB.Internal; + +public static class Procedure +{ + private static readonly AsyncLocal current = new(); + + private readonly struct ContextScope : IDisposable + { + private readonly IInternalProcedureContext? previous; + + public ContextScope(IInternalProcedureContext? next) + { + previous = current.Value; + current.Value = next; + } + + public void Dispose() => current.Value = previous; + } + + internal static IDisposable PushContext(IProcedureContext ctx) => + new ContextScope(ctx as IInternalProcedureContext); + + private static IInternalProcedureContext RequireContext() => + current.Value ?? throw new InvalidOperationException( + "Transaction syscalls require a procedure context." + ); + + public static long StartMutTx() + { + var status = FFI.procedure_start_mut_tx(out var micros); + FFI.ErrnoHelpers.ThrowIfError(status); + return micros; + } + + public static void CommitMutTx() + { + FFI.procedure_commit_mut_tx(); // throws on error + if (RequireContext() is IInternalProcedureContext ctx && + TryTakeOffsetFromHost(out var offset)) + { + ctx.SetTransactionOffset(offset); + Module.RecordProcedureTxOffset(offset); + } + } + + public static void AbortMutTx() + { + FFI.procedure_abort_mut_tx(); // throws on error + if (RequireContext() is IInternalProcedureContext ctx && + TryTakeOffsetFromHost(out var offset)) + { + ctx.SetTransactionOffset(offset); + Module.RecordProcedureTxOffset(offset); + } + } + + private static bool TryTakeOffsetFromHost(out TransactionOffset offset) + { + if (FFI.take_procedure_tx_offset(out var rawOffset)) + { + offset = TransactionOffset.FromRaw(unchecked((long)rawOffset)); + return true; + } + + offset = default; + return false; + } + + public static bool CommitMutTxWithRetry(Func retryBody) + { + try + { + CommitMutTx(); + return true; + } + catch (TransactionNotAnonymousException) + { + // reducer misuse, abort immediately + return false; + } + catch (StdbException) + { + if (retryBody()) { + CommitMutTx(); + return true; + } + return false; + } + } + + public static async Task CommitMutTxWithRetryAsync(Func> retryBody) + { + try + { + await CommitMutTxAsync().ConfigureAwait(false); + return true; + } + catch (TransactionNotAnonymousException) + { + return false; + } + catch (StdbException) + { + if (await retryBody().ConfigureAwait(false)) + { + await CommitMutTxAsync().ConfigureAwait(false); + return true; + } + return false; + } + } + + public static Task CommitMutTxAsync() + { + CommitMutTx(); // existing sync path + return Task.CompletedTask; + } + + public static Task AbortMutTxAsync() + { + AbortMutTx(); // existing sync path + return Task.CompletedTask; + } +} + +public readonly struct TransactionOffset +{ + public ulong Value { get; } + + private TransactionOffset(ulong value) => Value = value; + + public static TransactionOffset FromRaw(long raw) => + new(unchecked((ulong)raw)); +} diff --git a/crates/bindings-csharp/Runtime/bindings.c b/crates/bindings-csharp/Runtime/bindings.c index be12f438959..0a42a6d64ea 100644 --- a/crates/bindings-csharp/Runtime/bindings.c +++ b/crates/bindings-csharp/Runtime/bindings.c @@ -1,6 +1,7 @@ #include // #include // #include +#include #include #include @@ -108,6 +109,12 @@ IMPORT(int16_t, bytes_source_remaining_length, (BytesSource source, uint32_t* ou IMPORT(int16_t, get_jwt, (const uint8_t* connection_id_ptr, BytesSource* bytes_ptr), (connection_id_ptr, bytes_ptr)); #undef SPACETIME_MODULE_VERSION +#define SPACETIME_MODULE_VERSION "spacetime_10.3" +IMPORT(uint16_t, procedure_start_mut_tx, (int64_t* micros), (micros)); +IMPORT(uint16_t, procedure_commit_mut_tx, (void), ()); +IMPORT(uint16_t, procedure_abort_mut_tx, (void), ()); +#undef SPACETIME_MODULE_VERSION + #ifndef EXPERIMENTAL_WASM_AOT static MonoClass* ffi_class; @@ -170,6 +177,9 @@ EXPORT(int16_t, __call_procedure__, &conn_id_0, &conn_id_1, ×tamp, &args, &result_sink); +EXPORT(bool, __take_procedure_tx_offset__, + (uint64_t* offset), offset); + EXPORT(int16_t, __call_view__, (uint32_t id, uint64_t sender_0, uint64_t sender_1, uint64_t sender_2, uint64_t sender_3, diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs index b6f0294a454..bd5fbca25c0 100644 --- a/sdks/csharp/examples~/regression-tests/server/Lib.cs +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -36,7 +36,7 @@ public partial class MyTable public static partial class Module { - [SpacetimeDB.Table(Name = "ExampleData", Public = true)] + [SpacetimeDB.Table(Name = "example_data", Public = true)] public partial struct ExampleData { [SpacetimeDB.PrimaryKey] @@ -46,7 +46,7 @@ public partial struct ExampleData public uint Indexed; } - [SpacetimeDB.Table(Name = "Player", Public = true)] + [SpacetimeDB.Table(Name = "player", Public = true)] public partial struct Player { [SpacetimeDB.PrimaryKey] @@ -59,7 +59,7 @@ public partial struct Player public string Name; } - [SpacetimeDB.Table(Name = "PlayerLevel", Public = true)] + [SpacetimeDB.Table(Name = "player_level", Public = true)] public partial struct PlayerLevel { [SpacetimeDB.Unique] @@ -79,20 +79,20 @@ public partial struct PlayerAndLevel } // At-most-one row: return T? - [SpacetimeDB.View(Name = "MyPlayer", Public = true)] + [SpacetimeDB.View(Name = "my_player", Public = true)] public static Player? MyPlayer(ViewContext ctx) { - return ctx.Db.Player.Identity.Find(ctx.Sender) as Player?; + return ctx.Db.player.Identity.Find(ctx.Sender) as Player?; } // Multiple rows: return a list - [SpacetimeDB.View(Name = "PlayersForLevel", Public = true)] + [SpacetimeDB.View(Name = "players_for_level", Public = true)] public static List PlayersForLevel(AnonymousViewContext ctx) { var rows = new List(); - foreach (var player in ctx.Db.PlayerLevel.Level.Filter(1)) + foreach (var player in ctx.Db.player_level.Level.Filter(1)) { - if (ctx.Db.Player.Id.Find(player.PlayerId) is Player p) + if (ctx.Db.player.Id.Find(player.PlayerId) is Player p) { var row = new PlayerAndLevel { @@ -110,13 +110,14 @@ public static List PlayersForLevel(AnonymousViewContext ctx) [SpacetimeDB.Reducer] public static void Delete(ReducerContext ctx, uint id) { - ctx.Db.ExampleData.Id.Delete(id); + LogStopwatch sw = new("Delete"); + ctx.Db.example_data.Id.Delete(id); } [SpacetimeDB.Reducer] public static void Add(ReducerContext ctx, uint id, uint indexed) { - ctx.Db.ExampleData.Insert(new ExampleData { Id = id, Indexed = indexed }); + ctx.Db.example_data.Insert(new ExampleData { Id = id, Indexed = indexed }); } [SpacetimeDB.Reducer] @@ -130,16 +131,16 @@ public static void ClientConnected(ReducerContext ctx) { Log.Info($"Connect {ctx.Sender}"); - if (ctx.Db.Player.Identity.Find(ctx.Sender) is Player player) + if (ctx.Db.player.Identity.Find(ctx.Sender) is Player player) { // We are not logging player login status, so do nothing } else { // Lets setup a new player with a level of 1 - ctx.Db.Player.Insert(new Player { Identity = ctx.Sender, Name = "NewPlayer" }); - var playerId = (ctx.Db.Player.Identity.Find(ctx.Sender)!).Value.Id; - ctx.Db.PlayerLevel.Insert(new PlayerLevel { PlayerId = playerId, Level = 1 }); + ctx.Db.player.Insert(new Player { Identity = ctx.Sender, Name = "NewPlayer" }); + var playerId = (ctx.Db.player.Identity.Find(ctx.Sender)!).Value.Id; + ctx.Db.player_level.Insert(new PlayerLevel { PlayerId = playerId, Level = 1 }); } } @@ -172,4 +173,53 @@ public static SpacetimeDB.Unit WillPanic(ProcedureContext ctx) { throw new InvalidOperationException("This procedure is expected to panic"); } + +#pragma warning disable STDB_UNSTABLE + [SpacetimeDB.Procedure] + public static void InsertWithTxCommit(ProcedureContext ctx) + { + ctx.WithTx(tx => + { + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct(a: 42, b: "magic") + }); + return 0; // discard result + }); + + AssertRowCount(ctx, 1); + } + + [SpacetimeDB.Procedure] + public static void InsertWithTxRollback(ProcedureContext ctx) + { + var _ = ctx.TryWithTx(tx => + { + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct(a: 42, b: "magic") + }); + + return SpacetimeDB.ProcedureContext.TxResult.Failure( + new InvalidOperationException("rollback")); + }); + + AssertRowCount(ctx, 0); + } + + private static void AssertRowCount(ProcedureContext ctx, ulong expected) + { + ctx.WithTx(tx => + { + ulong actual = tx.Db.my_table.Count; + if (actual != expected) + { + throw new InvalidOperationException( + $"Expected {expected} MyTable rows but found {actual}." + ); + } + return 0; + }); + } +#pragma warning restore STDB_UNSTABLE } From 3132d1fe97a57c7323e1c9645d6b8ff00ed7c568 Mon Sep 17 00:00:00 2001 From: rekhoff Date: Wed, 3 Dec 2025 17:41:20 -0800 Subject: [PATCH 2/5] Added a TxContext and pulled out ProcedureContext to the Runtime --- crates/bindings-csharp/Codegen/Module.cs | 449 +++++++----------- .../Runtime/Internal/IProcedure.cs | 2 + .../Runtime/Internal/Module.cs | 11 +- .../Runtime/Internal/Procedure.cs | 14 +- .../Runtime/Internal/TxContext.cs | 30 ++ .../Runtime/ProcedureContext.cs | 286 +++++++++++ 6 files changed, 495 insertions(+), 297 deletions(-) create mode 100644 crates/bindings-csharp/Runtime/Internal/TxContext.cs create mode 100644 crates/bindings-csharp/Runtime/ProcedureContext.cs diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 79617a0646e..bc31b94c6bf 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1190,6 +1190,9 @@ record ProcedureDeclaration public readonly Scope Scope; private readonly bool HasWrongSignature; public readonly TypeUse ReturnType; + private readonly IMethodSymbol _methodSymbol; + private readonly ITypeSymbol _returnTypeSymbol; + private readonly DiagReporter _diag; public ProcedureDeclaration(GeneratorAttributeSyntaxContext context, DiagReporter diag) { @@ -1197,6 +1200,10 @@ public ProcedureDeclaration(GeneratorAttributeSyntaxContext context, DiagReporte var method = (IMethodSymbol)context.TargetSymbol; var attr = context.Attributes.Single().ParseAs(); + _methodSymbol = method; + _returnTypeSymbol = method.ReturnType; + _diag = diag; + if ( method.Parameters.FirstOrDefault()?.Type is not INamedTypeSymbol { Name: "ProcedureContext" } @@ -1234,6 +1241,12 @@ public string GenerateClass() Args.Length == 0 ? "" : ", " + string.Join(", ", Args.Select(a => a.Name)); var invocation = $"{FullName}((SpacetimeDB.ProcedureContext)ctx{invocationArgs})"; + var hasTxOutcome = TryGetTxOutcomeType(out var txOutcomePayload); + var hasTxResult = TryGetTxResultTypes(out var txResultPayload, out _); + var hasTxWrapper = hasTxOutcome || hasTxResult; + var txPayload = hasTxOutcome ? txOutcomePayload : txResultPayload; + var txPayloadIsUnit = hasTxWrapper && txPayload.BSATNName == "SpacetimeDB.BSATN.Unit"; + string[] bodyLines; if (HasWrongSignature) @@ -1243,6 +1256,30 @@ public string GenerateClass() "throw new System.InvalidOperationException(\"Invalid procedure signature.\");", }; } + else if (hasTxWrapper) + { + var successLines = txPayloadIsUnit + ? new[] { "return System.Array.Empty();" } + : new[] + { + "using var output = new MemoryStream();", + "using var writer = new BinaryWriter(output);", + "__txReturnRW.Write(writer, outcome.Value!);", + "return output.ToArray();", + }; + + bodyLines = + new[] + { + $"var outcome = {invocation};", + "if (!outcome.IsSuccess)", + "{", + " throw outcome.Error ?? new System.InvalidOperationException(\"Transaction failed.\");", + "}", + } + .Concat(successLines) + .ToArray(); + } else if (ReturnType.IsVoid) { bodyLines = new[] @@ -1268,30 +1305,46 @@ public string GenerateClass() var paramReads = Args.Length == 0 ? string.Empty : string.Join( - "\n", - Args.Select(a => - $" var {a.Name} = {a.Name}{TypeUse.BsatnFieldSuffix}.Read(reader);" - ) - ) + "\n"; - var returnTypeExpr = ReturnType.IsVoid - ? "SpacetimeDB.BSATN.AlgebraicType.Unit" - : $"new {ReturnType.BSATNName}().GetAlgebraicType(registrar)"; + "\n", + Args.Select(a => + $" var {a.Name} = {a.Name}{TypeUse.BsatnFieldSuffix}.Read(reader);" + ) + ) + "\n"; - return $$$""" - class {{{Name}}} : SpacetimeDB.Internal.IProcedure { - {{{MemberDeclaration.GenerateBsatnFields(Accessibility.Private, Args)}}} + var returnTypeExpr = hasTxWrapper + ? ( + txPayloadIsUnit + ? "SpacetimeDB.BSATN.AlgebraicType.Unit" + : $"new {txPayload.BSATNName}().GetAlgebraicType(registrar)" + ) + : ( + ReturnType.IsVoid + ? "SpacetimeDB.BSATN.AlgebraicType.Unit" + : $"new {ReturnType.BSATNName}().GetAlgebraicType(registrar)" + ); - public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( - nameof({{{Name}}}), - [{{{MemberDeclaration.GenerateDefs(Args)}}}], - {{{returnTypeExpr}}} - ); + var classFields = MemberDeclaration.GenerateBsatnFields(Accessibility.Private, Args); + if (hasTxWrapper && !txPayloadIsUnit) + { + classFields += + $"\n private {txPayload.BSATNName} __txReturnRW = new {txPayload.BSATNName}();"; + } - public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { - {{{paramReads}}}{{{invokeBody}}} - } - } - """; + return $$$""" + class {{{Name}}} : SpacetimeDB.Internal.IProcedure { + {{{classFields}}} + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof({{{Name}}}), + [{{{MemberDeclaration.GenerateDefs(Args)}}}], + {{{returnTypeExpr}}} + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + {{{paramReads}}}{{{invokeBody}}} + } + } + """; } public Scope.Extensions GenerateSchedule() @@ -1322,6 +1375,46 @@ public Scope.Extensions GenerateSchedule() return extensions; } + + private bool TryGetTxOutcomeType(out TypeUse payloadType) + { + if ( + _returnTypeSymbol is INamedTypeSymbol + { + Name: "TxOutcome", + ContainingType: { Name: "ProcedureContext" } + } named && + named.TypeArguments.Length == 1 + ) + { + payloadType = TypeUse.Parse(_methodSymbol, named.TypeArguments[0], _diag); + return true; + } + + payloadType = default!; + return false; + } + + private bool TryGetTxResultTypes(out TypeUse payloadType, out TypeUse errorType) + { + if ( + _returnTypeSymbol is INamedTypeSymbol + { + Name: "TxResult", + ContainingType: { Name: "ProcedureContext" } + } named && + named.TypeArguments.Length == 2 + ) + { + payloadType = TypeUse.Parse(_methodSymbol, named.TypeArguments[0], _diag); + errorType = TypeUse.Parse(_methodSymbol, named.TypeArguments[1], _diag); + return true; + } + + payloadType = default!; + errorType = default!; + return false; + } } record ClientVisibilityFilterDeclaration @@ -1626,6 +1719,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context) using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + using Internal = SpacetimeDB.Internal; + using TxContext = SpacetimeDB.Internal.TxContext; namespace SpacetimeDB { public sealed record ReducerContext : DbContext, Internal.IReducerContext { @@ -1649,280 +1744,60 @@ internal ReducerContext(Identity identity, ConnectionId? connectionId, Random ra } } - public sealed record ProcedureContext : Internal.IInternalProcedureContext { - public readonly Identity Sender; - public readonly ConnectionId? ConnectionId; - public readonly Random Rng; - public Timestamp Timestamp { get; private set; } - public readonly AuthCtx SenderAuth; - - // We need this property to be non-static for parity with client SDK. - public Identity Identity => Internal.IProcedureContext.GetIdentity(); - - internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time) { - Sender = identity; - ConnectionId = connectionId; - Rng = random; - Timestamp = time; - SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, identity); - } - - private Internal.TransactionOffset? pendingTxOffset; - - public bool TryTakeTransactionOffset(out Internal.TransactionOffset offset) - { - if (pendingTxOffset is { } value) - { - pendingTxOffset = null; - offset = value; - return true; - } - offset = default; - return false; - } - - public void SetTransactionOffset(Internal.TransactionOffset offset) => - pendingTxOffset = offset; - - [Experimental("STDB_UNSTABLE")] - public sealed record TxContext(Local Db, ReducerContext Reducer) : DbContext(Db) - { - public Identity Sender => Reducer.Sender; - public ConnectionId? ConnectionId => Reducer.ConnectionId; - public Timestamp Timestamp => Reducer.Timestamp; - public Random Rng => Reducer.Rng; - public AuthCtx SenderAuth => Reducer.SenderAuth; - } - - private sealed class AbortGuard : IDisposable - { - private readonly Action abort; - private bool disarmed; - public AbortGuard(Action abort) => this.abort = abort; - public void Disarm() => disarmed = true; - public void Dispose() { if (!disarmed) abort(); } - } - - [Experimental("STDB_UNSTABLE")] - public TxOutcome TryWithTx( - Func> body) - where TError : Exception - { - try - { - var result = RunWithRetry(body); - return result.IsSuccess - ? TxOutcome.Success(result.Value!) - : TxOutcome.Failure(result.Error!); - } - catch (Exception ex) - { - return TxOutcome.Failure(ex); - } - } - - [Experimental("STDB_UNSTABLE")] - public T WithTx(Func body) - { - var outcome = TryWithTx(ctx => - TxResult.Success(body(ctx))); - if (outcome.IsSuccess) return outcome.Value!; - throw outcome.Error!; - } - + public sealed class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { + private readonly Local _db = new(); + + internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time) + : base(identity, connectionId, random, time) {} + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext(Internal.TxContext inner) => + _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + [Experimental("STDB_UNSTABLE")] - public readonly record struct TxOutcome(bool IsSuccess, T? Value, Exception? Error) - { - public static TxOutcome Success(T value) => new(true, value, null); - public static TxOutcome Failure(Exception error) => new(false, default, error); - - public TxOutcome Map(Func mapper) => - IsSuccess ? TxOutcome.Success(mapper(Value!)) : TxOutcome.Failure(Error!); - } - - private TxResult RunWithRetry( - Func> body) - where TError : Exception - { - var result = RunOnce(body); - - bool retry() - { - result = RunOnce(body); - return true; - } - - if (!SpacetimeDB.Internal.Procedure.CommitMutTxWithRetry(retry)) - { - SpacetimeDB.Internal.Procedure.AbortMutTx(); - } - - if (TryTakeTransactionOffset(out var offset)) - { - SpacetimeDB.Internal.Module.RecordProcedureTxOffset(offset); - } - return result; - } + public Local Db => _db; [Experimental("STDB_UNSTABLE")] - public async Task WithTxAsync(Func> body) - { - var outcome = await TryWithTxAsync(async ctx => - TxResult.Success(await body(ctx).ConfigureAwait(false))).ConfigureAwait(false); - if (outcome.IsSuccess) return outcome.Value!; - throw outcome.Error!; - } - - public async Task> TryWithTxAsync( - Func>> body) - where TError : Exception - { - try - { - return (await RunWithRetryAsync(body).ConfigureAwait(false)).Match( - onSuccess: TxOutcome.Success, - onError: TxOutcome.Failure); - } - catch (Exception ex) - { - return TxOutcome.Failure(ex); - } - } + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); [Experimental("STDB_UNSTABLE")] - public readonly record struct TxResult - where TError : Exception - { - public bool IsSuccess { get; } - public TSuccess? Value { get; } - public TError? Error { get; } - - private TxResult(bool isSuccess, TSuccess? value, TError? error) - { - IsSuccess = isSuccess; - Value = value; - Error = error; - } - - public static TxResult Success(TSuccess value) => - new(true, value, default); - - public static TxResult Failure(TError error) => - new(false, default, error); - - public TResult Match( - Func onSuccess, - Func onError) - { - if (onSuccess is null) throw new ArgumentNullException(nameof(onSuccess)); - if (onError is null) throw new ArgumentNullException(nameof(onError)); - return IsSuccess ? onSuccess(Value!) : onError(Error!); - } - } - - private async Task> RunWithRetryAsync( - Func>> body) - where TError : Exception - { - var result = await RunOnceAsync(body).ConfigureAwait(false); - - async Task Retry() - { - result = await RunOnceAsync(body).ConfigureAwait(false); - return true; - } - - if (!await SpacetimeDB.Internal.Procedure.CommitMutTxWithRetryAsync(Retry).ConfigureAwait(false)) - { - await SpacetimeDB.Internal.Procedure.AbortMutTxAsync().ConfigureAwait(false); - } - if (TryTakeTransactionOffset(out var offset)) { - SpacetimeDB.Internal.Module.RecordProcedureTxOffset(offset); - } - - return result; - } - - private async Task> RunOnceAsync( - Func>> body) - where TError : Exception - { - var micros = SpacetimeDB.Internal.Procedure.StartMutTx(); - await using var guard = new AsyncAbortGuard(SpacetimeDB.Internal.Procedure.AbortMutTxAsync); - var txCtx = MakeTxContext(micros); - var output = await body(txCtx).ConfigureAwait(false); - await guard.DisarmAsync().ConfigureAwait(false); - return output; - } - - private sealed class AsyncAbortGuard : IAsyncDisposable - { - private readonly Func abort; - private bool disarmed; - public AsyncAbortGuard(Func abort) => this.abort = abort; - public Task DisarmAsync() { disarmed = true; return Task.CompletedTask; } - public async ValueTask DisposeAsync() - { - if (!disarmed) await abort().ConfigureAwait(false); - } - } - - private bool RetryOnce( - Func> body, - out TxResult result) - where TError : Exception - { - result = RunOnce(body); - return true; - } - - private TxResult RunOnce( - Func> body) - where TError : Exception - { - var micros = SpacetimeDB.Internal.Procedure.StartMutTx(); - using var guard = new AbortGuard(SpacetimeDB.Internal.Procedure.AbortMutTx); - var txCtx = MakeTxContext(micros); - var output = body(txCtx); - guard.Disarm(); - return output; - } - - private TxContext MakeTxContext(long micros) - { - var txTimestamp = new Timestamp(micros); - Timestamp = txTimestamp; - var reducerCtx = new ReducerContext( - Sender, ConnectionId, new Random(unchecked((int)micros)), - txTimestamp, SenderAuth); - return new TxContext(new Local(), reducerCtx); - } + public TxOutcome TryWithTx( + Func> body) + where TError : Exception => + base.TryWithTx(tx => body((ProcedureTxContext)tx)); + } + + [Experimental("STDB_UNSTABLE")] + public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { + internal ProcedureTxContext(Internal.TxContext inner) : base(inner) {} + + public new Local Db => (Local)base.Db; + } + + public sealed class Local : global::SpacetimeDB.LocalBase { + {{string.Join("\n", tableAccessors.Select(v => v.getter))}} + } + + public sealed class LocalReadOnly : global::SpacetimeDB.LocalReadOnlyBase { + {{string.Join("\n", readOnlyAccessors.Select(v => v.readOnlyGetter))}} } - public sealed record ViewContext : DbContext, Internal.IViewContext + public sealed record ViewContext : DbContext, Internal.IViewContext { public Identity Sender { get; } - - internal ViewContext(Identity sender, Internal.LocalReadOnly db) - : base(db) - { - Sender = sender; - } + internal ViewContext(Identity sender, LocalReadOnly db) : base(db) => Sender = sender; } - public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext - { - internal AnonymousViewContext(Internal.LocalReadOnly db) - : base(db) { } + public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext { + internal AnonymousViewContext(LocalReadOnly db) : base(db) { } } + } - namespace Internal.TableHandles { - {{string.Join("\n", tableAccessors.Select(v => v.tableAccessor))}} - } - - public sealed class Local { - {{string.Join("\n", tableAccessors.Select(v => v.getter))}} - } + namespace SpacetimeDB.Internal.TableHandles { + {{string.Join("\n", tableAccessors.Select(v => v.tableAccessor))}} } {{string.Join("\n", @@ -1938,12 +1813,6 @@ namespace SpacetimeDB.Internal.ViewHandles { {{string.Join("\n", readOnlyAccessors.Array.Select(v => v.readOnlyAccessor))}} } - namespace SpacetimeDB.Internal { - public sealed partial class LocalReadOnly { - {{string.Join("\n", readOnlyAccessors.Select(v => v.readOnlyGetter))}} - } - } - static class ModuleRegistration { {{string.Join("\n", addReducers.Select(r => r.Class))}} @@ -1962,8 +1831,8 @@ public static List ToListOrEmpty(T? value) where T : struct #endif public static void Main() { SpacetimeDB.Internal.Module.SetReducerContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time)); - SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.Internal.LocalReadOnly())); - SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly())); + SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.LocalReadOnly())); + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.LocalReadOnly())); SpacetimeDB.Internal.Module.SetProcedureContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time)); var __memoryStream = new MemoryStream(); var __writer = new BinaryWriter(__memoryStream); diff --git a/crates/bindings-csharp/Runtime/Internal/IProcedure.cs b/crates/bindings-csharp/Runtime/Internal/IProcedure.cs index f5cd96d81c9..7b055c65048 100644 --- a/crates/bindings-csharp/Runtime/Internal/IProcedure.cs +++ b/crates/bindings-csharp/Runtime/Internal/IProcedure.cs @@ -37,4 +37,6 @@ public interface IInternalProcedureContext : IProcedureContext { bool TryTakeTransactionOffset(out TransactionOffset offset); void SetTransactionOffset(TransactionOffset offset); + TxContext EnterTxContext(long timestampMicros); + void ExitTxContext(); } diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index 274a87c3fdf..b2937db24ed 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -442,11 +442,20 @@ public static Errno __call_view_anon__(uint id, BytesSource args, BytesSink rows } } +/// +/// Read-write database access for procedure contexts. +/// The code generator will extend this partial class with table accessors. +/// +public partial class Local +{ + // Intentionally empty – generated code adds table handles here. +} + /// /// Read-only database access for view contexts. /// The code generator will extend this partial class to add table accessors. /// -public sealed partial class LocalReadOnly +public partial class LocalReadOnly { // This class is intentionally empty - the code generator will add // read-only table accessors for each table in the module. diff --git a/crates/bindings-csharp/Runtime/Internal/Procedure.cs b/crates/bindings-csharp/Runtime/Internal/Procedure.cs index f82a3bcbc8b..a11b7ff96ab 100644 --- a/crates/bindings-csharp/Runtime/Internal/Procedure.cs +++ b/crates/bindings-csharp/Runtime/Internal/Procedure.cs @@ -1,5 +1,3 @@ -using System.Threading; - namespace SpacetimeDB.Internal; public static class Procedure @@ -31,14 +29,17 @@ public static long StartMutTx() { var status = FFI.procedure_start_mut_tx(out var micros); FFI.ErrnoHelpers.ThrowIfError(status); + var ctx = RequireContext(); + ctx.EnterTxContext(micros); return micros; } public static void CommitMutTx() { FFI.procedure_commit_mut_tx(); // throws on error - if (RequireContext() is IInternalProcedureContext ctx && - TryTakeOffsetFromHost(out var offset)) + var ctx = RequireContext(); + ctx.ExitTxContext(); + if (TryTakeOffsetFromHost(out var offset)) { ctx.SetTransactionOffset(offset); Module.RecordProcedureTxOffset(offset); @@ -48,8 +49,9 @@ public static void CommitMutTx() public static void AbortMutTx() { FFI.procedure_abort_mut_tx(); // throws on error - if (RequireContext() is IInternalProcedureContext ctx && - TryTakeOffsetFromHost(out var offset)) + var ctx = RequireContext(); + ctx.ExitTxContext(); + if (TryTakeOffsetFromHost(out var offset)) { ctx.SetTransactionOffset(offset); Module.RecordProcedureTxOffset(offset); diff --git a/crates/bindings-csharp/Runtime/Internal/TxContext.cs b/crates/bindings-csharp/Runtime/Internal/TxContext.cs new file mode 100644 index 00000000000..db2589ee0cd --- /dev/null +++ b/crates/bindings-csharp/Runtime/Internal/TxContext.cs @@ -0,0 +1,30 @@ +namespace SpacetimeDB.Internal; + +public sealed class TxContext +{ + public TxContext( + Local db, + Identity sender, + ConnectionId? connectionId, + Timestamp timestamp, + AuthCtx senderAuth, + Random rng) + { + Db = db; + Sender = sender; + ConnectionId = connectionId; + Timestamp = timestamp; + SenderAuth = senderAuth; + Rng = rng; + } + + public Local Db { get; } + public Identity Sender { get; } + public ConnectionId? ConnectionId { get; } + public Timestamp Timestamp { get; } + public AuthCtx SenderAuth { get; } + public Random Rng { get; } + + public TxContext WithTimestamp(Timestamp ts) => + new(Db, Sender, ConnectionId, ts, SenderAuth, Rng); +} \ No newline at end of file diff --git a/crates/bindings-csharp/Runtime/ProcedureContext.cs b/crates/bindings-csharp/Runtime/ProcedureContext.cs new file mode 100644 index 00000000000..e9d6c006d44 --- /dev/null +++ b/crates/bindings-csharp/Runtime/ProcedureContext.cs @@ -0,0 +1,286 @@ +namespace SpacetimeDB; + +using System.Diagnostics.CodeAnalysis; + +#pragma warning disable STDB_UNSTABLE +public abstract class ProcedureContextBase : Internal.IInternalProcedureContext +{ + protected ProcedureContextBase( + Identity sender, + ConnectionId? connectionId, + Random random, + Timestamp time) + { + Sender = sender; + ConnectionId = connectionId; + Rng = random; + Timestamp = time; + SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, sender); + } + + public Identity Identity => Internal.IProcedureContext.GetIdentity(); + public Identity Sender { get; } + public ConnectionId? ConnectionId { get; } + public Random Rng { get; } + public Timestamp Timestamp { get; private set; } + public AuthCtx SenderAuth { get; } + + private Internal.TransactionOffset? pendingTxOffset; + private Internal.TxContext? txContext; + private ProcedureTxContextBase? cachedUserTxContext; + + protected abstract ProcedureTxContextBase CreateTxContext(Internal.TxContext inner); + protected internal abstract LocalBase CreateLocal(); + + private protected ProcedureTxContextBase RequireTxContext() + { + var inner = txContext ?? throw new InvalidOperationException("Transaction context was not initialised."); + cachedUserTxContext ??= CreateTxContext(inner); + cachedUserTxContext.Refresh(inner); + return cachedUserTxContext; + } + + public Internal.TxContext EnterTxContext(long timestampMicros) + { + var timestamp = new Timestamp(timestampMicros); + Timestamp = timestamp; + txContext = txContext?.WithTimestamp(timestamp) + ?? new Internal.TxContext(CreateLocal(), Sender, ConnectionId, timestamp, SenderAuth, Rng); + return txContext; + } + + public void ExitTxContext() => txContext = null; + + public void SetTransactionOffset(Internal.TransactionOffset offset) => + pendingTxOffset = offset; + + public bool TryTakeTransactionOffset(out Internal.TransactionOffset offset) + { + if (pendingTxOffset is { } value) + { + pendingTxOffset = null; + offset = value; + return true; + } + + offset = default; + return false; + } + + public readonly struct TxOutcome + { + public TxOutcome(bool isSuccess, TResult? value, Exception? error) + { + IsSuccess = isSuccess; + Value = value; + Error = error; + } + + public bool IsSuccess { get; } + public TResult? Value { get; } + public Exception? Error { get; } + + public static TxOutcome Success(TResult value) => + new(true, value, null); + + public static TxOutcome Failure(Exception error) => + new(false, default, error); + + public TResult UnwrapOrThrow() => + IsSuccess ? Value! : throw (Error ?? new InvalidOperationException("Transaction failed without an error object.")); + + public TResult UnwrapOrThrow(Func fallbackFactory) => + IsSuccess ? Value! : throw (Error ?? fallbackFactory()); + } + + public readonly struct TxResult + where TError : Exception + { + public TxResult(bool isSuccess, TResult? value, TError? error) + { + IsSuccess = isSuccess; + Value = value; + Error = error; + } + + public bool IsSuccess { get; } + public TResult? Value { get; } + public TError? Error { get; } + + public static TxResult Success(TResult value) => + new(true, value, null); + + public static TxResult Failure(TError error) => + new(false, default, error); + + public TResult UnwrapOrThrow() + { + if (IsSuccess) + { + return Value!; + } + + if (Error is not null) + { + throw Error; + } + + throw new InvalidOperationException("Transaction failed without an error object."); + } + } + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + TryWithTx(tx => TxResult.Success(body(tx))).UnwrapOrThrow(); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body) + where TError : Exception + { + try + { + var result = RunWithRetry(body); + return result.IsSuccess + ? TxOutcome.Success(result.Value!) + : TxOutcome.Failure(result.Error!); + } + catch (Exception ex) + { + return TxOutcome.Failure(ex); + } + } + + private TxResult RunWithRetry( + Func> body) + where TError : Exception + { + var result = RunOnce(body); + if (!result.IsSuccess) + { + return result; + } + + bool Retry() + { + result = RunOnce(body); + return result.IsSuccess; + } + + if (!SpacetimeDB.Internal.Procedure.CommitMutTxWithRetry(Retry)) + { + return result; + } + + if (TryTakeTransactionOffset(out var offset)) + { + SetTransactionOffset(offset); + SpacetimeDB.Internal.Module.RecordProcedureTxOffset(offset); + } + + return result; + } + + private TxResult RunOnce( + Func> body) + where TError : Exception + { + _ = SpacetimeDB.Internal.Procedure.StartMutTx(); + using var guard = new AbortGuard(SpacetimeDB.Internal.Procedure.AbortMutTx); + var txCtx = RequireTxContext(); + var result = body(txCtx); + if (result.IsSuccess) + { + guard.Disarm(); + return result; + } + + SpacetimeDB.Internal.Procedure.AbortMutTx(); + guard.Disarm(); + return result; + } + + private sealed class AbortGuard : IDisposable + { + private readonly Action abort; + private bool disarmed; + + public AbortGuard(Action abort) => this.abort = abort; + + public void Disarm() => disarmed = true; + + public void Dispose() + { + if (!disarmed) + { + abort(); + } + } + } +} + +public abstract class ProcedureTxContextBase +{ + protected ProcedureTxContextBase(Internal.TxContext inner) + { + Inner = inner; + } + + internal Internal.TxContext Inner { get; private set; } + + internal void Refresh(Internal.TxContext inner) => Inner = inner; + + public LocalBase Db => (LocalBase)Inner.Db; + public Identity Sender => Inner.Sender; + public ConnectionId? ConnectionId => Inner.ConnectionId; + public Timestamp Timestamp => Inner.Timestamp; + public AuthCtx SenderAuth => Inner.SenderAuth; + public Random Rng => Inner.Rng; +} + +public abstract class LocalBase : Internal.Local +{ +} + +public abstract class LocalReadOnlyBase : Internal.LocalReadOnly +{ +} + +public sealed class ProcedureContext : ProcedureContextBase +{ + private readonly Local _db = new(); + + public ProcedureContext( + Identity sender, + ConnectionId? connectionId, + Random random, + Timestamp timestamp) + : base(sender, connectionId, random, timestamp) + { + } + + protected internal override LocalBase CreateLocal() => _db; + protected override ProcedureTxContextBase CreateTxContext(Internal.TxContext inner) => + _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; +} + +public sealed class ProcedureTxContext : ProcedureTxContextBase +{ + internal ProcedureTxContext(Internal.TxContext inner) + : base(inner) + { + } + + public new Local Db => (Local)base.Db; +} + +public sealed class Local : LocalBase +{ +} + +public sealed class LocalReadOnly : LocalReadOnlyBase +{ +} +#pragma warning restore STDB_UNSTABLE \ No newline at end of file From 758bd23e0984bf1bc98ddbc3308374924ec8d489 Mon Sep 17 00:00:00 2001 From: rekhoff Date: Thu, 4 Dec 2025 08:55:10 -0800 Subject: [PATCH 3/5] Updated C# formatting and snapshots --- .../BSATN.Codegen/BSATN.Codegen.csproj | 2 - crates/bindings-csharp/BSATN.Codegen/Diag.cs | 99 +- crates/bindings-csharp/BSATN.Codegen/Type.cs | 4 +- .../BSATN.Runtime.Tests.csproj | 8 +- .../BSATN.Runtime.Tests/Tests.cs | 29 +- .../BSATN.Runtime/BSATN.Runtime.csproj | 14 +- .../BSATN.Runtime/BSATN/I256.cs | 1 - .../BSATN.Runtime/BSATN/Runtime.cs | 5 +- .../bindings-csharp/BSATN.Runtime/Builtins.cs | 46 +- .../Codegen.Tests/Codegen.Tests.csproj | 2 - .../fixtures/client/client.csproj | 2 - .../Codegen.Tests/fixtures/diag/diag.csproj | 2 - .../diag/snapshots/Module#FFI.verified.cs | 1792 ++++++++-------- .../fixtures/server/server.csproj | 2 - .../server/snapshots/Module#FFI.verified.cs | 1843 ++++++++--------- crates/bindings-csharp/Codegen/Codegen.csproj | 7 +- crates/bindings-csharp/Codegen/Diag.cs | 343 ++- crates/bindings-csharp/Codegen/Module.cs | 98 +- .../Runtime.Tests/Runtime.Tests.csproj | 6 +- crates/bindings-csharp/Runtime/Exceptions.cs | 6 +- .../bindings-csharp/Runtime/Internal/FFI.cs | 53 +- .../Runtime/Internal/ITable.cs | 16 +- .../Runtime/Internal/Module.cs | 2 +- .../Runtime/Internal/Procedure.cs | 17 +- .../Runtime/Internal/TxContext.cs | 5 +- .../Runtime/ProcedureContext.cs | 130 +- crates/bindings-csharp/Runtime/Runtime.csproj | 14 +- .../Runtime/build/SpacetimeDB.Runtime.props | 2 - .../Runtime/build/SpacetimeDB.Runtime.targets | 43 +- .../examples~/regression-tests/server/Lib.cs | 4 +- 30 files changed, 2277 insertions(+), 2320 deletions(-) diff --git a/crates/bindings-csharp/BSATN.Codegen/BSATN.Codegen.csproj b/crates/bindings-csharp/BSATN.Codegen/BSATN.Codegen.csproj index 0884890a939..f3aea963486 100644 --- a/crates/bindings-csharp/BSATN.Codegen/BSATN.Codegen.csproj +++ b/crates/bindings-csharp/BSATN.Codegen/BSATN.Codegen.csproj @@ -1,5 +1,4 @@ - SpacetimeDB.BSATN.Codegen 1.11.0 @@ -27,5 +26,4 @@ - diff --git a/crates/bindings-csharp/BSATN.Codegen/Diag.cs b/crates/bindings-csharp/BSATN.Codegen/Diag.cs index 2ae3b2513ba..53d0d7f2432 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Diag.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Diag.cs @@ -134,61 +134,55 @@ internal static class ErrorDescriptor ISymbol member, ITypeSymbol type, Exception e - )> UnsupportedType = - new( - group, - "Unsupported type", - ctx => $"BSATN implementation for {ctx.type} is not found: {ctx.e.Message}", - ctx => ctx.member - ); + )> UnsupportedType = new( + group, + "Unsupported type", + ctx => $"BSATN implementation for {ctx.type} is not found: {ctx.e.Message}", + ctx => ctx.member + ); public static readonly ErrorDescriptor<( EqualsValueClauseSyntax equalsValue, EnumMemberDeclarationSyntax enumMember, EnumDeclarationSyntax @enum - )> EnumWithExplicitValues = - new( - group, - "[SpacetimeDB.Type] enums cannot have explicit values", - ctx => - $"{ctx.@enum.Identifier}.{ctx.enumMember.Identifier} has an explicit value {ctx.equalsValue.Value} which is not allowed in SpacetimeDB enums.", - ctx => ctx.equalsValue - ); + )> EnumWithExplicitValues = new( + group, + "[SpacetimeDB.Type] enums cannot have explicit values", + ctx => + $"{ctx.@enum.Identifier}.{ctx.enumMember.Identifier} has an explicit value {ctx.equalsValue.Value} which is not allowed in SpacetimeDB enums.", + ctx => ctx.equalsValue + ); - public static readonly ErrorDescriptor EnumTooManyVariants = - new( - group, - "[SpacetimeDB.Type] enums are limited to 256 variants", - @enum => - $"{@enum.Identifier} has {@enum.Members.Count} variants which is more than the allowed 256 variants for SpacetimeDB enums.", - @enum => @enum.Members[256] - ); + public static readonly ErrorDescriptor EnumTooManyVariants = new( + group, + "[SpacetimeDB.Type] enums are limited to 256 variants", + @enum => + $"{@enum.Identifier} has {@enum.Members.Count} variants which is more than the allowed 256 variants for SpacetimeDB enums.", + @enum => @enum.Members[256] + ); - public static readonly ErrorDescriptor TaggedEnumInlineTuple = - new( - group, - "Tagged enum variants must be declared with inline tuples", - baseType => - $"{baseType} does not have the expected format SpacetimeDB.TaggedEnum<(TVariant1 v1, ..., TVariantN vN)>.", - baseType => baseType - ); + public static readonly ErrorDescriptor TaggedEnumInlineTuple = new( + group, + "Tagged enum variants must be declared with inline tuples", + baseType => + $"{baseType} does not have the expected format SpacetimeDB.TaggedEnum<(TVariant1 v1, ..., TVariantN vN)>.", + baseType => baseType + ); - public static readonly ErrorDescriptor TaggedEnumField = - new( - group, - "Tagged enums cannot have instance fields", - field => - $"{field.Name} is an instance field, which are not permitted inside SpacetimeDB tagged enums.", - field => field - ); + public static readonly ErrorDescriptor TaggedEnumField = new( + group, + "Tagged enums cannot have instance fields", + field => + $"{field.Name} is an instance field, which are not permitted inside SpacetimeDB tagged enums.", + field => field + ); - public static readonly ErrorDescriptor TypeParams = - new( - group, - "Type parameters are not yet supported", - typeParams => $"Type parameters {typeParams} are not supported in SpacetimeDB types.", - typeParams => typeParams - ); + public static readonly ErrorDescriptor TypeParams = new( + group, + "Type parameters are not yet supported", + typeParams => $"Type parameters {typeParams} are not supported in SpacetimeDB types.", + typeParams => typeParams + ); } // This class is used to collect diagnostics during parsing and return them as a combined result. @@ -214,13 +208,12 @@ public void Report(ErrorDescriptor descriptor, TContext ctx) private DiagReporter() { } - private static readonly ErrorDescriptor<(Location location, Exception e)> InternalError = - new( - new("STDBINT", "SpacetimeDB.Internal"), - "Internal SpacetimeDB codegen error", - ctx => $"An internal error occurred during codegen: {ctx.e.Message}", - ctx => ctx.location - ); + private static readonly ErrorDescriptor<(Location location, Exception e)> InternalError = new( + new("STDBINT", "SpacetimeDB.Internal"), + "Internal SpacetimeDB codegen error", + ctx => $"An internal error occurred during codegen: {ctx.e.Message}", + ctx => ctx.location + ); public static ParseResult With(Location location, Func build) where T : IEquatable diff --git a/crates/bindings-csharp/BSATN.Codegen/Type.cs b/crates/bindings-csharp/BSATN.Codegen/Type.cs index 56c4af41f07..9d8ad56f26f 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Type.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Type.cs @@ -516,7 +516,7 @@ public sealed record {{m.Name}}({{m.Type.Name}} {{m.Name}}_) : {{ShortName}} public override string ToString() => $"{{m.Name}}({ SpacetimeDB.BSATN.StringUtil.GenericToString({{m.Name}}_) })"; } - + """ ) ) @@ -659,7 +659,7 @@ public override int GetHashCode() { {{getHashCode}} } - + """ ); diff --git a/crates/bindings-csharp/BSATN.Runtime.Tests/BSATN.Runtime.Tests.csproj b/crates/bindings-csharp/BSATN.Runtime.Tests/BSATN.Runtime.Tests.csproj index 5bb0e2c30a6..b4bdf12f40e 100644 --- a/crates/bindings-csharp/BSATN.Runtime.Tests/BSATN.Runtime.Tests.csproj +++ b/crates/bindings-csharp/BSATN.Runtime.Tests/BSATN.Runtime.Tests.csproj @@ -1,5 +1,4 @@ - false true @@ -20,7 +19,10 @@ - + - diff --git a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs index c22879a596c..bee26979774 100644 --- a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs +++ b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs @@ -137,8 +137,8 @@ public static void IdentityLengthCheck() public static void NonHexStrings() { // n.b. 32 chars long - Assert.ThrowsAny( - () => ConnectionId.FromHexString("these are not hex characters....") + Assert.ThrowsAny(() => + ConnectionId.FromHexString("these are not hex characters....") ); } @@ -626,7 +626,6 @@ public static void GeneratedNestedListRoundTrip() .Select(list => new ContainsNestedList(list)); #pragma warning restore CS8620 // Argument cannot be used for parameter due to differences in the nullability of reference types. - static readonly Gen<(ContainsNestedList e1, ContainsNestedList e2)> GenTwoContainsNestedList = Gen.Select(GenContainsNestedList, GenContainsNestedList, (e1, e2) => (e1, e2)); @@ -797,26 +796,22 @@ public static void GeneratedToString() ); Assert.Equal( "ContainsList { TheList = [ X(1), Y(\"hi\"), W(BasicDataRecord { X = 1, Y = \"hi\", Z = null, W = null }) ] }", - new ContainsList( - [ - new BasicEnum.X(1), - new BasicEnum.Y("hi"), - new BasicEnum.W(new BasicDataRecord((1, "hi", null, null))), - ] - ).ToString() + new ContainsList([ + new BasicEnum.X(1), + new BasicEnum.Y("hi"), + new BasicEnum.W(new BasicDataRecord((1, "hi", null, null))), + ]).ToString() ); #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Equal( "ContainsNestedList { TheList = [ [ [ X(1), null ], null ], null ] }", - new ContainsNestedList( + new ContainsNestedList([ [ - [ - [new BasicEnum.X(1), null], - null, - ], + [new BasicEnum.X(1), null], null, - ] - ).ToString() + ], + null, + ]).ToString() ); #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN.Runtime.csproj b/crates/bindings-csharp/BSATN.Runtime/BSATN.Runtime.csproj index b781668147d..c12bad75129 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN.Runtime.csproj +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN.Runtime.csproj @@ -1,5 +1,4 @@ - SpacetimeDB.BSATN.Runtime 1.11.0 @@ -18,18 +17,25 @@ - + - + - diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/I256.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/I256.cs index b217944f3bd..f4bdd40cf32 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/I256.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/I256.cs @@ -97,7 +97,6 @@ public int CompareTo(I256 value) } /// - public static bool IsNegative(I256 value) => (long)value._upper.Upper < 0; private BigInteger AsBigInt() => diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs index 9a7a617a2ab..bde8ac8bbd7 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs @@ -577,8 +577,9 @@ public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // reduce amount of noisy compilation errors when a used type is not supported by BSATN. public readonly struct Unsupported : IReadWrite { - private static readonly NotSupportedException Exception = - new($"Type {typeof(T)} is not supported by BSATN."); + private static readonly NotSupportedException Exception = new( + $"Type {typeof(T)} is not supported by BSATN." + ); public T Read(BinaryReader reader) => throw Exception; diff --git a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs index a3478d18023..d2ba774bd1c 100644 --- a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs +++ b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs @@ -191,12 +191,10 @@ public void Write(BinaryWriter writer, ConnectionId value) => // --- customized --- public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. - new AlgebraicType.Product( - [ - // Using this specific name here is important. - new("__connection_id__", new AlgebraicType.U128(default)), - ] - ); + new AlgebraicType.Product([ + // Using this specific name here is important. + new("__connection_id__", new AlgebraicType.U128(default)), + ]); // --- / customized --- } @@ -283,12 +281,10 @@ public void Write(BinaryWriter writer, Identity value) => // --- customized --- public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. - new AlgebraicType.Product( - [ - // Using this specific name here is important. - new("__identity__", new AlgebraicType.U256(default)), - ] - ); + new AlgebraicType.Product([ + // Using this specific name here is important. + new("__identity__", new AlgebraicType.U256(default)), + ]); // --- / customized --- } @@ -414,9 +410,10 @@ public void Write(BinaryWriter writer, Timestamp value) public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. new AlgebraicType.Product( - // Using this specific name here is important. - [new("__timestamp_micros_since_unix_epoch__", new AlgebraicType.I64(default))] - ); + // Using this specific name here is important. + [ + new("__timestamp_micros_since_unix_epoch__", new AlgebraicType.I64(default)), + ]); // --- / customized --- } } @@ -516,9 +513,10 @@ public void Write(BinaryWriter writer, TimeDuration value) public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. new AlgebraicType.Product( - // Using this specific name here is important. - [new("__time_duration_micros__", new AlgebraicType.I64(default))] - ); + // Using this specific name here is important. + [ + new("__time_duration_micros__", new AlgebraicType.I64(default)), + ]); // --- / customized --- } } @@ -595,13 +593,11 @@ public void Write(BinaryWriter writer, ScheduleAt value) // --- customized --- public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Sum directly, not a Ref, because this is a special type. - new AlgebraicType.Sum( - [ - // Using these specific names here is important. - new("Interval", Interval.GetAlgebraicType(registrar)), - new("Time", Time.GetAlgebraicType(registrar)), - ] - ); + new AlgebraicType.Sum([ + // Using these specific names here is important. + new("Interval", Interval.GetAlgebraicType(registrar)), + new("Time", Time.GetAlgebraicType(registrar)), + ]); // --- / customized --- } } diff --git a/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj b/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj index 5f02268f537..50adc298107 100644 --- a/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj +++ b/crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj @@ -1,5 +1,4 @@ - false true @@ -32,5 +31,4 @@ - diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/client/client.csproj b/crates/bindings-csharp/Codegen.Tests/fixtures/client/client.csproj index 8f25982a1d2..3867044feac 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/client/client.csproj +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/client/client.csproj @@ -1,5 +1,4 @@  - @@ -10,5 +9,4 @@ - diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/diag.csproj b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/diag.csproj index 426f04d2bc6..66830dc463c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/diag.csproj +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/diag.csproj @@ -1,5 +1,4 @@  - net8.0 enable @@ -9,5 +8,4 @@ - diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs index 42936be56cd..dccfa6caedc 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/diag/snapshots/Module#FFI.verified.cs @@ -5,10 +5,13 @@ // This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. // We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. #pragma warning disable CS0436 +#pragma warning disable STDB_UNSTABLE using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Internal = SpacetimeDB.Internal; +using TxContext = SpacetimeDB.Internal.TxContext; namespace SpacetimeDB { @@ -27,27 +30,21 @@ internal ReducerContext( Identity identity, ConnectionId? connectionId, Random random, - Timestamp time + Timestamp time, + AuthCtx? senderAuth = null ) { Sender = identity; ConnectionId = connectionId; Rng = random; Timestamp = time; - SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, identity); + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); } } - public sealed record ProcedureContext : Internal.IProcedureContext + public sealed class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { - public readonly Identity Sender; - public readonly ConnectionId? ConnectionId; - public readonly Random Rng; - public readonly Timestamp Timestamp; - public readonly AuthCtx SenderAuth; - - // We need this property to be non-static for parity with client SDK. - public Identity Identity => Internal.IProcedureContext.GetIdentity(); + private readonly Local _db = new(); internal ProcedureContext( Identity identity, @@ -55,1004 +52,1041 @@ internal ProcedureContext( Random random, Timestamp time ) - { - Sender = identity; - ConnectionId = connectionId; - Rng = random; - Timestamp = time; - SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, identity); - } + : base(identity, connectionId, random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + + [Experimental("STDB_UNSTABLE")] + public Local Db => _db; + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((ProcedureTxContext)tx)); + } + + [Experimental("STDB_UNSTABLE")] + public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase + { + internal ProcedureTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + public sealed class Local : global::SpacetimeDB.LocalBase + { + public global::SpacetimeDB.Internal.TableHandles.Player Player => new(); + public global::SpacetimeDB.Internal.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestDuplicateTableName TestDuplicateTableName => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestIndexIssues TestIndexIssues => new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Internal.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => + new(); + } + + public sealed class LocalReadOnly : global::SpacetimeDB.LocalReadOnlyBase + { + public global::SpacetimeDB.Internal.ViewHandles.PlayerReadOnly Player => new(); + public global::SpacetimeDB.Internal.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => + new(); + public global::SpacetimeDB.Internal.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => + new(); } - public sealed record ViewContext : DbContext, Internal.IViewContext + public sealed record ViewContext : DbContext, Internal.IViewContext { public Identity Sender { get; } - internal ViewContext(Identity sender, Internal.LocalReadOnly db) - : base(db) - { - Sender = sender; - } + internal ViewContext(Identity sender, LocalReadOnly db) + : base(db) => Sender = sender; } public sealed record AnonymousViewContext - : DbContext, + : DbContext, Internal.IAnonymousViewContext { - internal AnonymousViewContext(Internal.LocalReadOnly db) + internal AnonymousViewContext(LocalReadOnly db) : base(db) { } } +} - namespace Internal.TableHandles +namespace SpacetimeDB.Internal.TableHandles +{ + public readonly struct Player : global::SpacetimeDB.Internal.ITableView { - public readonly struct Player - : global::SpacetimeDB.Internal.ITableView + static global::Player global::SpacetimeDB.Internal.ITableView< + Player, + global::Player + >.ReadGenFields(System.IO.BinaryReader reader, global::Player row) { - static global::Player global::SpacetimeDB.Internal.ITableView< - Player, - global::Player - >.ReadGenFields(System.IO.BinaryReader reader, global::Player row) - { - return row; - } + return row; + } - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< - Player, - global::Player - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(Player), - ProductTypeRef: (uint) - new global::Player.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: - [ - new( - Name: null, - AccessorName: "Identity", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - Player, - global::Player - >.MakeUniqueConstraint(0) - ], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + Player, + global::Player + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(Player), + ProductTypeRef: (uint)new global::Player.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + Name: null, + AccessorName: "Identity", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + Player, + global::Player + >.MakeUniqueConstraint(0) + ], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); - public ulong Count => - global::SpacetimeDB.Internal.ITableView.DoCount(); + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView.DoIter(); + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); - public global::Player Insert(global::Player row) => - global::SpacetimeDB.Internal.ITableView.DoInsert(row); + public global::Player Insert(global::Player row) => + global::SpacetimeDB.Internal.ITableView.DoInsert(row); - public bool Delete(global::Player row) => - global::SpacetimeDB.Internal.ITableView.DoDelete(row); + public bool Delete(global::Player row) => + global::SpacetimeDB.Internal.ITableView.DoDelete(row); - public sealed class IdentityUniqueIndex - : UniqueIndex< - Player, - global::Player, - SpacetimeDB.Identity, - SpacetimeDB.Identity.BSATN - > - { - internal IdentityUniqueIndex() - : base("Player_Identity_idx_btree") { } + public sealed class IdentityUniqueIndex + : UniqueIndex + { + internal IdentityUniqueIndex() + : base("Player_Identity_idx_btree") { } - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::Player? Find(SpacetimeDB.Identity key) => - DoFilter(key).Cast().SingleOrDefault(); + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Player? Find(SpacetimeDB.Identity key) => + DoFilter(key).Cast().SingleOrDefault(); - public global::Player Update(global::Player row) => DoUpdate(row); - } + public global::Player Update(global::Player row) => DoUpdate(row); + } - public IdentityUniqueIndex Identity => new(); + public IdentityUniqueIndex Identity => new(); + } + + public readonly struct TestAutoIncNotInteger + : global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + > + { + static global::TestAutoIncNotInteger global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.ReadGenFields(System.IO.BinaryReader reader, global::TestAutoIncNotInteger row) + { + if (row.AutoIncField == default) + { + row.AutoIncField = global::TestAutoIncNotInteger.BSATN.AutoIncFieldRW.Read(reader); + } + if (row.IdentityField == default) + { + row.IdentityField = global::TestAutoIncNotInteger.BSATN.IdentityFieldRW.Read( + reader + ); + } + return row; } - public readonly struct TestAutoIncNotInteger - : global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestAutoIncNotInteger), + ProductTypeRef: (uint) + new global::TestAutoIncNotInteger.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + Name: null, + AccessorName: "IdentityField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.MakeUniqueConstraint(1) + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.MakeSequence(0), + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.MakeSequence(1) + ], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestAutoIncNotInteger, global::TestAutoIncNotInteger - > - { - static global::TestAutoIncNotInteger global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestAutoIncNotInteger, global::TestAutoIncNotInteger - >.ReadGenFields(System.IO.BinaryReader reader, global::TestAutoIncNotInteger row) - { - if (row.AutoIncField == default) - { - row.AutoIncField = global::TestAutoIncNotInteger.BSATN.AutoIncFieldRW.Read( - reader - ); - } - if (row.IdentityField == default) - { - row.IdentityField = global::TestAutoIncNotInteger.BSATN.IdentityFieldRW.Read( - reader - ); - } - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestAutoIncNotInteger Insert(global::TestAutoIncNotInteger row) => + global::SpacetimeDB.Internal.ITableView< TestAutoIncNotInteger, global::TestAutoIncNotInteger - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestAutoIncNotInteger), - ProductTypeRef: (uint) - new global::TestAutoIncNotInteger.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: - [ - new( - Name: null, - AccessorName: "IdentityField", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger - >.MakeUniqueConstraint(1) - ], - Sequences: - [ - global::SpacetimeDB.Internal.ITableView< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger - >.MakeSequence(0), - global::SpacetimeDB.Internal.ITableView< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger - >.MakeSequence(1) - ], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoInsert(row); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger - >.DoIter(); - - public global::TestAutoIncNotInteger Insert(global::TestAutoIncNotInteger row) => - global::SpacetimeDB.Internal.ITableView< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger - >.DoInsert(row); - - public bool Delete(global::TestAutoIncNotInteger row) => - global::SpacetimeDB.Internal.ITableView< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger - >.DoDelete(row); - - public sealed class IdentityFieldUniqueIndex - : UniqueIndex< - TestAutoIncNotInteger, - global::TestAutoIncNotInteger, - string, - SpacetimeDB.BSATN.String - > - { - internal IdentityFieldUniqueIndex() - : base("TestAutoIncNotInteger_IdentityField_idx_btree") { } + public bool Delete(global::TestAutoIncNotInteger row) => + global::SpacetimeDB.Internal.ITableView< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger + >.DoDelete(row); + + public sealed class IdentityFieldUniqueIndex + : UniqueIndex< + TestAutoIncNotInteger, + global::TestAutoIncNotInteger, + string, + SpacetimeDB.BSATN.String + > + { + internal IdentityFieldUniqueIndex() + : base("TestAutoIncNotInteger_IdentityField_idx_btree") { } - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::TestAutoIncNotInteger? Find(string key) => - DoFilter(key).Cast().SingleOrDefault(); + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestAutoIncNotInteger? Find(string key) => + DoFilter(key).Cast().SingleOrDefault(); - public global::TestAutoIncNotInteger Update(global::TestAutoIncNotInteger row) => - DoUpdate(row); - } + public global::TestAutoIncNotInteger Update(global::TestAutoIncNotInteger row) => + DoUpdate(row); + } + + public IdentityFieldUniqueIndex IdentityField => new(); + } - public IdentityFieldUniqueIndex IdentityField => new(); + public readonly struct TestDefaultFieldValues + : global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + > + { + static global::TestDefaultFieldValues global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.ReadGenFields(System.IO.BinaryReader reader, global::TestDefaultFieldValues row) + { + return row; } - public readonly struct TestDefaultFieldValues - : global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestDefaultFieldValues), + ProductTypeRef: (uint) + new global::TestDefaultFieldValues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + Name: null, + AccessorName: "UniqueField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.MakeUniqueConstraint(0) + ], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestDefaultFieldValues, global::TestDefaultFieldValues - > - { - static global::TestDefaultFieldValues global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestDefaultFieldValues, global::TestDefaultFieldValues - >.ReadGenFields(System.IO.BinaryReader reader, global::TestDefaultFieldValues row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestDefaultFieldValues Insert(global::TestDefaultFieldValues row) => + global::SpacetimeDB.Internal.ITableView< TestDefaultFieldValues, global::TestDefaultFieldValues - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestDefaultFieldValues), - ProductTypeRef: (uint) - new global::TestDefaultFieldValues.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: - [ - new( - Name: null, - AccessorName: "UniqueField", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - TestDefaultFieldValues, - global::TestDefaultFieldValues - >.MakeUniqueConstraint(0) - ], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoInsert(row); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestDefaultFieldValues, - global::TestDefaultFieldValues - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestDefaultFieldValues, - global::TestDefaultFieldValues - >.DoIter(); - - public global::TestDefaultFieldValues Insert(global::TestDefaultFieldValues row) => - global::SpacetimeDB.Internal.ITableView< - TestDefaultFieldValues, - global::TestDefaultFieldValues - >.DoInsert(row); - - public bool Delete(global::TestDefaultFieldValues row) => - global::SpacetimeDB.Internal.ITableView< - TestDefaultFieldValues, - global::TestDefaultFieldValues - >.DoDelete(row); - } - - public readonly struct TestDuplicateTableName - : global::SpacetimeDB.Internal.ITableView< + public bool Delete(global::TestDefaultFieldValues row) => + global::SpacetimeDB.Internal.ITableView< + TestDefaultFieldValues, + global::TestDefaultFieldValues + >.DoDelete(row); + } + + public readonly struct TestDuplicateTableName + : global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + > + { + static global::TestDuplicateTableName global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.ReadGenFields(System.IO.BinaryReader reader, global::TestDuplicateTableName row) + { + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestDuplicateTableName), + ProductTypeRef: (uint) + new global::TestDuplicateTableName.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestDuplicateTableName, global::TestDuplicateTableName - > - { - static global::TestDuplicateTableName global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestDuplicateTableName, global::TestDuplicateTableName - >.ReadGenFields(System.IO.BinaryReader reader, global::TestDuplicateTableName row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestDuplicateTableName Insert(global::TestDuplicateTableName row) => + global::SpacetimeDB.Internal.ITableView< TestDuplicateTableName, global::TestDuplicateTableName - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestDuplicateTableName), - ProductTypeRef: (uint) - new global::TestDuplicateTableName.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: [], - Constraints: [], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoInsert(row); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestDuplicateTableName, - global::TestDuplicateTableName - >.DoCount(); + public bool Delete(global::TestDuplicateTableName row) => + global::SpacetimeDB.Internal.ITableView< + TestDuplicateTableName, + global::TestDuplicateTableName + >.DoDelete(row); + } - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestDuplicateTableName, - global::TestDuplicateTableName - >.DoIter(); + public readonly struct TestIndexIssues + : global::SpacetimeDB.Internal.ITableView + { + static global::TestIndexIssues global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.ReadGenFields(System.IO.BinaryReader reader, global::TestIndexIssues row) + { + return row; + } - public global::TestDuplicateTableName Insert(global::TestDuplicateTableName row) => - global::SpacetimeDB.Internal.ITableView< - TestDuplicateTableName, - global::TestDuplicateTableName - >.DoInsert(row); + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestIndexIssues), + ProductTypeRef: (uint) + new global::TestIndexIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + Name: null, + AccessorName: "TestIndexWithoutColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) + ), + new( + Name: null, + AccessorName: "TestIndexWithEmptyColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) + ), + new( + Name: null, + AccessorName: "TestUnknownColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) + ), + new( + Name: null, + AccessorName: "TestUnexpectedColumns", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ) + ], + Constraints: [], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); - public bool Delete(global::TestDuplicateTableName row) => - global::SpacetimeDB.Internal.ITableView< - TestDuplicateTableName, - global::TestDuplicateTableName - >.DoDelete(row); - } + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.DoCount(); - public readonly struct TestIndexIssues - : global::SpacetimeDB.Internal.ITableView - { - static global::TestIndexIssues global::SpacetimeDB.Internal.ITableView< + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestIndexIssues, global::TestIndexIssues - >.ReadGenFields(System.IO.BinaryReader reader, global::TestIndexIssues row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestIndexIssues Insert(global::TestIndexIssues row) => + global::SpacetimeDB.Internal.ITableView< TestIndexIssues, global::TestIndexIssues - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestIndexIssues), - ProductTypeRef: (uint) - new global::TestIndexIssues.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: - [ - new( - Name: null, - AccessorName: "TestIndexWithoutColumns", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) - ), - new( - Name: null, - AccessorName: "TestIndexWithEmptyColumns", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) - ), - new( - Name: null, - AccessorName: "TestUnknownColumns", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([]) - ), - new( - Name: null, - AccessorName: "TestUnexpectedColumns", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) - ], - Constraints: [], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private + >.DoInsert(row); + + public bool Delete(global::TestIndexIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestIndexIssues, + global::TestIndexIssues + >.DoDelete(row); + + public sealed class TestIndexWithoutColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + "TestIndexIssues__idx_btree" + ) { } + + public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); + + public sealed class TestIndexWithEmptyColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + "TestIndexIssues__idx_btree" + ) { } + + public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); + + public sealed class TestUnknownColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + "TestIndexIssues__idx_btree" + ) { } + + public TestUnknownColumnsIndex TestUnknownColumns => new(); + + public sealed class TestUnexpectedColumnsIndex() + : SpacetimeDB.Internal.IndexBase( + "TestIndexIssues_SelfIndexingColumn_idx_btree" + ) + { + public IEnumerable Filter(int SelfIndexingColumn) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) ); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestIndexIssues, - global::TestIndexIssues - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestIndexIssues, - global::TestIndexIssues - >.DoIter(); - - public global::TestIndexIssues Insert(global::TestIndexIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestIndexIssues, - global::TestIndexIssues - >.DoInsert(row); - - public bool Delete(global::TestIndexIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestIndexIssues, - global::TestIndexIssues - >.DoDelete(row); - - public sealed class TestIndexWithoutColumnsIndex() - : SpacetimeDB.Internal.IndexBase( - "TestIndexIssues__idx_btree" - ) { } - - public TestIndexWithoutColumnsIndex TestIndexWithoutColumns => new(); - - public sealed class TestIndexWithEmptyColumnsIndex() - : SpacetimeDB.Internal.IndexBase( - "TestIndexIssues__idx_btree" - ) { } - - public TestIndexWithEmptyColumnsIndex TestIndexWithEmptyColumns => new(); - - public sealed class TestUnknownColumnsIndex() - : SpacetimeDB.Internal.IndexBase( - "TestIndexIssues__idx_btree" - ) { } - - public TestUnknownColumnsIndex TestUnknownColumns => new(); - - public sealed class TestUnexpectedColumnsIndex() - : SpacetimeDB.Internal.IndexBase( - "TestIndexIssues_SelfIndexingColumn_idx_btree" - ) - { - public IEnumerable Filter(int SelfIndexingColumn) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds( - SelfIndexingColumn - ) - ); - - public ulong Delete(int SelfIndexingColumn) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds( - SelfIndexingColumn - ) - ); - - public IEnumerable Filter(Bound SelfIndexingColumn) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds( - SelfIndexingColumn - ) - ); - - public ulong Delete(Bound SelfIndexingColumn) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds( - SelfIndexingColumn - ) - ); - } + public ulong Delete(int SelfIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); - public TestUnexpectedColumnsIndex TestUnexpectedColumns => new(); + public IEnumerable Filter(Bound SelfIndexingColumn) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); + + public ulong Delete(Bound SelfIndexingColumn) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + SelfIndexingColumn + ) + ); } - public readonly struct TestScheduleWithMissingScheduleAtField - : global::SpacetimeDB.Internal.ITableView< - TestScheduleWithMissingScheduleAtField, - global::TestScheduleIssues - > + public TestUnexpectedColumnsIndex TestUnexpectedColumns => new(); + } + + public readonly struct TestScheduleWithMissingScheduleAtField + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + > + { + static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) { - static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestScheduleWithMissingScheduleAtField), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithMissingScheduleAtField, global::TestScheduleIssues - >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) - { - return row; - } + >.DoCount(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithMissingScheduleAtField, global::TestScheduleIssues - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestScheduleWithMissingScheduleAtField), - ProductTypeRef: (uint) - new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: [], - Constraints: [], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoIter(); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithMissingScheduleAtField, - global::TestScheduleIssues - >.DoCount(); + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.DoInsert(row); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithMissingScheduleAtField, - global::TestScheduleIssues - >.DoIter(); + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithMissingScheduleAtField, + global::TestScheduleIssues + >.DoDelete(row); + } - public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithMissingScheduleAtField, - global::TestScheduleIssues - >.DoInsert(row); + public readonly struct TestScheduleWithoutPrimaryKey + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + > + { + static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) + { + return row; + } - public bool Delete(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithMissingScheduleAtField, + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestScheduleWithoutPrimaryKey), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + Schedule: global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, global::TestScheduleIssues - >.DoDelete(row); - } + >.MakeSchedule("DummyScheduledReducer", 3), + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); - public readonly struct TestScheduleWithoutPrimaryKey - : global::SpacetimeDB.Internal.ITableView< + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithoutPrimaryKey, global::TestScheduleIssues - > - { - static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithoutPrimaryKey, global::TestScheduleIssues - >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithoutPrimaryKey, global::TestScheduleIssues - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestScheduleWithoutPrimaryKey), - ProductTypeRef: (uint) - new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: [], - Constraints: [], - Sequences: [], - Schedule: global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutPrimaryKey, - global::TestScheduleIssues - >.MakeSchedule("DummyScheduledReducer", 3), - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); - - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutPrimaryKey, - global::TestScheduleIssues - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutPrimaryKey, - global::TestScheduleIssues - >.DoIter(); + >.DoInsert(row); - public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutPrimaryKey, - global::TestScheduleIssues - >.DoInsert(row); + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutPrimaryKey, + global::TestScheduleIssues + >.DoDelete(row); + } - public bool Delete(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutPrimaryKey, - global::TestScheduleIssues - >.DoDelete(row); + public readonly struct TestScheduleWithoutScheduleAt + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + > + { + static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) + { + return row; } - public readonly struct TestScheduleWithoutScheduleAt - : global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestScheduleWithoutScheduleAt), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + Name: null, + AccessorName: "IdCorrectType", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.MakeUniqueConstraint(1) + ], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithoutScheduleAt, global::TestScheduleIssues - > - { - static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithoutScheduleAt, global::TestScheduleIssues - >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithoutScheduleAt, global::TestScheduleIssues - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestScheduleWithoutScheduleAt), - ProductTypeRef: (uint) - new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [1], - Indexes: - [ - new( - Name: null, - AccessorName: "IdCorrectType", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutScheduleAt, - global::TestScheduleIssues - >.MakeUniqueConstraint(1) - ], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); - - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutScheduleAt, - global::TestScheduleIssues - >.DoCount(); + >.DoInsert(row); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutScheduleAt, - global::TestScheduleIssues - >.DoIter(); + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues + >.DoDelete(row); - public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutScheduleAt, - global::TestScheduleIssues - >.DoInsert(row); + public sealed class IdCorrectTypeUniqueIndex + : UniqueIndex< + TestScheduleWithoutScheduleAt, + global::TestScheduleIssues, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdCorrectTypeUniqueIndex() + : base("TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree") { } - public bool Delete(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithoutScheduleAt, - global::TestScheduleIssues - >.DoDelete(row); - - public sealed class IdCorrectTypeUniqueIndex - : UniqueIndex< - TestScheduleWithoutScheduleAt, - global::TestScheduleIssues, - int, - SpacetimeDB.BSATN.I32 - > - { - internal IdCorrectTypeUniqueIndex() - : base("TestScheduleWithoutScheduleAt_IdCorrectType_idx_btree") { } + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestScheduleIssues? Find(int key) => + DoFilter(key).Cast().SingleOrDefault(); - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::TestScheduleIssues? Find(int key) => - DoFilter(key).Cast().SingleOrDefault(); + public global::TestScheduleIssues Update(global::TestScheduleIssues row) => + DoUpdate(row); + } - public global::TestScheduleIssues Update(global::TestScheduleIssues row) => - DoUpdate(row); - } + public IdCorrectTypeUniqueIndex IdCorrectType => new(); + } - public IdCorrectTypeUniqueIndex IdCorrectType => new(); + public readonly struct TestScheduleWithWrongPrimaryKeyType + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + > + { + static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) + { + return row; } - public readonly struct TestScheduleWithWrongPrimaryKeyType - : global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestScheduleWithWrongPrimaryKeyType), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + Name: null, + AccessorName: "IdWrongType", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.MakeUniqueConstraint(0) + ], + Sequences: [], + Schedule: global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.MakeSchedule("DummyScheduledReducer", 3), + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongPrimaryKeyType, global::TestScheduleIssues - > - { - static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongPrimaryKeyType, global::TestScheduleIssues - >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongPrimaryKeyType, global::TestScheduleIssues - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestScheduleWithWrongPrimaryKeyType), - ProductTypeRef: (uint) - new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [0], - Indexes: - [ - new( - Name: null, - AccessorName: "IdWrongType", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongPrimaryKeyType, - global::TestScheduleIssues - >.MakeUniqueConstraint(0) - ], - Sequences: [], - Schedule: global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongPrimaryKeyType, - global::TestScheduleIssues - >.MakeSchedule("DummyScheduledReducer", 3), - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoInsert(row); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongPrimaryKeyType, - global::TestScheduleIssues - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongPrimaryKeyType, - global::TestScheduleIssues - >.DoIter(); - - public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongPrimaryKeyType, - global::TestScheduleIssues - >.DoInsert(row); + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues + >.DoDelete(row); - public bool Delete(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongPrimaryKeyType, - global::TestScheduleIssues - >.DoDelete(row); + public sealed class IdWrongTypeUniqueIndex + : UniqueIndex< + TestScheduleWithWrongPrimaryKeyType, + global::TestScheduleIssues, + string, + SpacetimeDB.BSATN.String + > + { + internal IdWrongTypeUniqueIndex() + : base("TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree") { } - public sealed class IdWrongTypeUniqueIndex - : UniqueIndex< - TestScheduleWithWrongPrimaryKeyType, - global::TestScheduleIssues, - string, - SpacetimeDB.BSATN.String - > - { - internal IdWrongTypeUniqueIndex() - : base("TestScheduleWithWrongPrimaryKeyType_IdWrongType_idx_btree") { } + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestScheduleIssues? Find(string key) => + DoFilter(key).Cast().SingleOrDefault(); - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::TestScheduleIssues? Find(string key) => - DoFilter(key).Cast().SingleOrDefault(); + public global::TestScheduleIssues Update(global::TestScheduleIssues row) => + DoUpdate(row); + } - public global::TestScheduleIssues Update(global::TestScheduleIssues row) => - DoUpdate(row); - } + public IdWrongTypeUniqueIndex IdWrongType => new(); + } - public IdWrongTypeUniqueIndex IdWrongType => new(); + public readonly struct TestScheduleWithWrongScheduleAtType + : global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + > + { + static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) + { + return row; } - public readonly struct TestScheduleWithWrongScheduleAtType - : global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestScheduleWithWrongScheduleAtType), + ProductTypeRef: (uint) + new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + Name: null, + AccessorName: "IdCorrectType", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.MakeUniqueConstraint(1) + ], + Sequences: [], + Schedule: global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.MakeSchedule("DummyScheduledReducer", 2), + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongScheduleAtType, global::TestScheduleIssues - > - { - static global::TestScheduleIssues global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongScheduleAtType, global::TestScheduleIssues - >.ReadGenFields(System.IO.BinaryReader reader, global::TestScheduleIssues row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< TestScheduleWithWrongScheduleAtType, global::TestScheduleIssues - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestScheduleWithWrongScheduleAtType), - ProductTypeRef: (uint) - new global::TestScheduleIssues.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [1], - Indexes: - [ - new( - Name: null, - AccessorName: "IdCorrectType", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongScheduleAtType, - global::TestScheduleIssues - >.MakeUniqueConstraint(1) - ], - Sequences: [], - Schedule: global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongScheduleAtType, - global::TestScheduleIssues - >.MakeSchedule("DummyScheduledReducer", 2), - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); - - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongScheduleAtType, - global::TestScheduleIssues - >.DoCount(); + >.DoInsert(row); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongScheduleAtType, - global::TestScheduleIssues - >.DoIter(); - - public global::TestScheduleIssues Insert(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongScheduleAtType, - global::TestScheduleIssues - >.DoInsert(row); + public bool Delete(global::TestScheduleIssues row) => + global::SpacetimeDB.Internal.ITableView< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues + >.DoDelete(row); - public bool Delete(global::TestScheduleIssues row) => - global::SpacetimeDB.Internal.ITableView< - TestScheduleWithWrongScheduleAtType, - global::TestScheduleIssues - >.DoDelete(row); + public sealed class IdCorrectTypeUniqueIndex + : UniqueIndex< + TestScheduleWithWrongScheduleAtType, + global::TestScheduleIssues, + int, + SpacetimeDB.BSATN.I32 + > + { + internal IdCorrectTypeUniqueIndex() + : base("TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree") { } - public sealed class IdCorrectTypeUniqueIndex - : UniqueIndex< - TestScheduleWithWrongScheduleAtType, - global::TestScheduleIssues, - int, - SpacetimeDB.BSATN.I32 - > - { - internal IdCorrectTypeUniqueIndex() - : base("TestScheduleWithWrongScheduleAtType_IdCorrectType_idx_btree") { } + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestScheduleIssues? Find(int key) => + DoFilter(key).Cast().SingleOrDefault(); - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::TestScheduleIssues? Find(int key) => - DoFilter(key).Cast().SingleOrDefault(); + public global::TestScheduleIssues Update(global::TestScheduleIssues row) => + DoUpdate(row); + } - public global::TestScheduleIssues Update(global::TestScheduleIssues row) => - DoUpdate(row); - } + public IdCorrectTypeUniqueIndex IdCorrectType => new(); + } - public IdCorrectTypeUniqueIndex IdCorrectType => new(); + public readonly struct TestUniqueNotEquatable + : global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + > + { + static global::TestUniqueNotEquatable global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.ReadGenFields(System.IO.BinaryReader reader, global::TestUniqueNotEquatable row) + { + return row; } - public readonly struct TestUniqueNotEquatable - : global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(TestUniqueNotEquatable), + ProductTypeRef: (uint) + new global::TestUniqueNotEquatable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + Name: null, + AccessorName: "UniqueField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + Name: null, + AccessorName: "PrimaryKeyField", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.MakeUniqueConstraint(0), + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.MakeUniqueConstraint(1) + ], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< TestUniqueNotEquatable, global::TestUniqueNotEquatable - > - { - static global::TestUniqueNotEquatable global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< TestUniqueNotEquatable, global::TestUniqueNotEquatable - >.ReadGenFields(System.IO.BinaryReader reader, global::TestUniqueNotEquatable row) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::TestUniqueNotEquatable Insert(global::TestUniqueNotEquatable row) => + global::SpacetimeDB.Internal.ITableView< TestUniqueNotEquatable, global::TestUniqueNotEquatable - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(TestUniqueNotEquatable), - ProductTypeRef: (uint) - new global::TestUniqueNotEquatable.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [1], - Indexes: - [ - new( - Name: null, - AccessorName: "UniqueField", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ), - new( - Name: null, - AccessorName: "PrimaryKeyField", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - TestUniqueNotEquatable, - global::TestUniqueNotEquatable - >.MakeUniqueConstraint(0), - global::SpacetimeDB.Internal.ITableView< - TestUniqueNotEquatable, - global::TestUniqueNotEquatable - >.MakeUniqueConstraint(1) - ], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoInsert(row); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - TestUniqueNotEquatable, - global::TestUniqueNotEquatable - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - TestUniqueNotEquatable, - global::TestUniqueNotEquatable - >.DoIter(); - - public global::TestUniqueNotEquatable Insert(global::TestUniqueNotEquatable row) => - global::SpacetimeDB.Internal.ITableView< - TestUniqueNotEquatable, - global::TestUniqueNotEquatable - >.DoInsert(row); - - public bool Delete(global::TestUniqueNotEquatable row) => - global::SpacetimeDB.Internal.ITableView< - TestUniqueNotEquatable, - global::TestUniqueNotEquatable - >.DoDelete(row); - - public sealed class PrimaryKeyFieldUniqueIndex - : UniqueIndex< - TestUniqueNotEquatable, - global::TestUniqueNotEquatable, - TestEnumWithExplicitValues, - SpacetimeDB.BSATN.Enum - > - { - internal PrimaryKeyFieldUniqueIndex() - : base("TestUniqueNotEquatable_PrimaryKeyField_idx_btree") { } + public bool Delete(global::TestUniqueNotEquatable row) => + global::SpacetimeDB.Internal.ITableView< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable + >.DoDelete(row); - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::TestUniqueNotEquatable? Find(TestEnumWithExplicitValues key) => - DoFilter(key).Cast().SingleOrDefault(); + public sealed class PrimaryKeyFieldUniqueIndex + : UniqueIndex< + TestUniqueNotEquatable, + global::TestUniqueNotEquatable, + TestEnumWithExplicitValues, + SpacetimeDB.BSATN.Enum + > + { + internal PrimaryKeyFieldUniqueIndex() + : base("TestUniqueNotEquatable_PrimaryKeyField_idx_btree") { } - public global::TestUniqueNotEquatable Update(global::TestUniqueNotEquatable row) => - DoUpdate(row); - } + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::TestUniqueNotEquatable? Find(TestEnumWithExplicitValues key) => + DoFilter(key).Cast().SingleOrDefault(); - public PrimaryKeyFieldUniqueIndex PrimaryKeyField => new(); + public global::TestUniqueNotEquatable Update(global::TestUniqueNotEquatable row) => + DoUpdate(row); } - } - public sealed class Local - { - public global::SpacetimeDB.Internal.TableHandles.Player Player => new(); - public global::SpacetimeDB.Internal.TableHandles.TestAutoIncNotInteger TestAutoIncNotInteger => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestDefaultFieldValues TestDefaultFieldValues => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestDuplicateTableName TestDuplicateTableName => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestIndexIssues TestIndexIssues => new(); - public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithMissingScheduleAtField TestScheduleWithMissingScheduleAtField => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutPrimaryKey TestScheduleWithoutPrimaryKey => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithoutScheduleAt TestScheduleWithoutScheduleAt => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongPrimaryKeyType TestScheduleWithWrongPrimaryKeyType => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestScheduleWithWrongScheduleAtType TestScheduleWithWrongScheduleAtType => - new(); - public global::SpacetimeDB.Internal.TableHandles.TestUniqueNotEquatable TestUniqueNotEquatable => - new(); + public PrimaryKeyFieldUniqueIndex PrimaryKeyField => new(); } } @@ -1715,34 +1749,6 @@ internal PrimaryKeyFieldIndex() } } -namespace SpacetimeDB.Internal -{ - public sealed partial class LocalReadOnly - { - public global::SpacetimeDB.Internal.ViewHandles.PlayerReadOnly Player => new(); - public global::SpacetimeDB.Internal.ViewHandles.TestAutoIncNotIntegerReadOnly TestAutoIncNotInteger => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestDefaultFieldValuesReadOnly TestDefaultFieldValues => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestDuplicateTableNameReadOnly TestDuplicateTableName => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestIndexIssuesReadOnly TestIndexIssues => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithMissingScheduleAtFieldReadOnly TestScheduleWithMissingScheduleAtField => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutPrimaryKeyReadOnly TestScheduleWithoutPrimaryKey => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithoutScheduleAtReadOnly TestScheduleWithoutScheduleAt => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongPrimaryKeyTypeReadOnly TestScheduleWithWrongPrimaryKeyType => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestScheduleWithWrongScheduleAtTypeReadOnly TestScheduleWithWrongScheduleAtType => - new(); - public global::SpacetimeDB.Internal.ViewHandles.TestUniqueNotEquatableReadOnly TestUniqueNotEquatable => - new(); - } -} - static class ModuleRegistration { class __ReducerWithReservedPrefix : SpacetimeDB.Internal.IReducer @@ -1872,13 +1878,10 @@ public static void Main() new SpacetimeDB.ReducerContext(identity, connectionId, random, time) ); SpacetimeDB.Internal.Module.SetViewContextConstructor( - identity => new SpacetimeDB.ViewContext( - identity, - new SpacetimeDB.Internal.LocalReadOnly() - ) + identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.LocalReadOnly()) ); SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor( - () => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + () => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.LocalReadOnly()) ); SpacetimeDB.Internal.Module.SetProcedureContextConstructor( (identity, connectionId, random, time) => @@ -2225,6 +2228,10 @@ SpacetimeDB.Internal.BytesSink result_sink result_sink ); + [UnmanagedCallersOnly(EntryPoint = "__take_procedure_tx_offset__")] + public static byte __take_procedure_tx_offset__(ulong* offset) => + SpacetimeDB.Internal.Module.__take_procedure_tx_offset__(out *offset) ? (byte)1 : (byte)0; + [UnmanagedCallersOnly(EntryPoint = "__call_view__")] public static SpacetimeDB.Internal.Errno __call_view__( uint id, @@ -2254,4 +2261,5 @@ SpacetimeDB.Internal.BytesSink sink #endif } +#pragma warning restore STDB_UNSTABLE #pragma warning restore CS0436 diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/server.csproj b/crates/bindings-csharp/Codegen.Tests/fixtures/server/server.csproj index 426f04d2bc6..66830dc463c 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/server.csproj +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/server.csproj @@ -1,5 +1,4 @@  - net8.0 enable @@ -9,5 +8,4 @@ - 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 c69d4a151d3..0668b3d1281 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 @@ -5,10 +5,13 @@ // This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. // We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. #pragma warning disable CS0436 +#pragma warning disable STDB_UNSTABLE using System.Diagnostics.CodeAnalysis; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using Internal = SpacetimeDB.Internal; +using TxContext = SpacetimeDB.Internal.TxContext; namespace SpacetimeDB { @@ -27,27 +30,21 @@ internal ReducerContext( Identity identity, ConnectionId? connectionId, Random random, - Timestamp time + Timestamp time, + AuthCtx? senderAuth = null ) { Sender = identity; ConnectionId = connectionId; Rng = random; Timestamp = time; - SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, identity); + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); } } - public sealed record ProcedureContext : Internal.IProcedureContext + public sealed class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { - public readonly Identity Sender; - public readonly ConnectionId? ConnectionId; - public readonly Random Rng; - public readonly Timestamp Timestamp; - public readonly AuthCtx SenderAuth; - - // We need this property to be non-static for parity with client SDK. - public Identity Identity => Internal.IProcedureContext.GetIdentity(); + private readonly Local _db = new(); internal ProcedureContext( Identity identity, @@ -55,1029 +52,1007 @@ internal ProcedureContext( Random random, Timestamp time ) - { - Sender = identity; - ConnectionId = connectionId; - Rng = random; - Timestamp = time; - SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, identity); - } + : base(identity, connectionId, random, time) { } + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext( + Internal.TxContext inner + ) => _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + + [Experimental("STDB_UNSTABLE")] + public Local Db => _db; + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body + ) + where TError : Exception => base.TryWithTx(tx => body((ProcedureTxContext)tx)); + } + + [Experimental("STDB_UNSTABLE")] + public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase + { + internal ProcedureTxContext(Internal.TxContext inner) + : base(inner) { } + + public new Local Db => (Local)base.Db; + } + + public sealed class Local : global::SpacetimeDB.LocalBase + { + internal global::SpacetimeDB.Internal.TableHandles.BTreeMultiColumn BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Internal.TableHandles.BTreeViews BTreeViews => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable1 MultiTable1 => new(); + public global::SpacetimeDB.Internal.TableHandles.MultiTable2 MultiTable2 => new(); + public global::SpacetimeDB.Internal.TableHandles.PrivateTable PrivateTable => new(); + public global::SpacetimeDB.Internal.TableHandles.PublicTable PublicTable => new(); + internal global::SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Internal.TableHandles.SendMessageTimer SendMessageTimer => new(); } - public sealed record ViewContext : DbContext, Internal.IViewContext + public sealed class LocalReadOnly : global::SpacetimeDB.LocalReadOnlyBase + { + internal global::SpacetimeDB.Internal.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => + new(); + internal global::SpacetimeDB.Internal.ViewHandles.BTreeViewsReadOnly BTreeViews => new(); + public global::SpacetimeDB.Internal.ViewHandles.MultiTable1ReadOnly MultiTable1 => new(); + public global::SpacetimeDB.Internal.ViewHandles.MultiTable2ReadOnly MultiTable2 => new(); + public global::SpacetimeDB.Internal.ViewHandles.PrivateTableReadOnly PrivateTable => new(); + public global::SpacetimeDB.Internal.ViewHandles.PublicTableReadOnly PublicTable => new(); + internal global::SpacetimeDB.Internal.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => + new(); + public global::SpacetimeDB.Internal.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => + new(); + } + + public sealed record ViewContext : DbContext, Internal.IViewContext { public Identity Sender { get; } - internal ViewContext(Identity sender, Internal.LocalReadOnly db) - : base(db) - { - Sender = sender; - } + internal ViewContext(Identity sender, LocalReadOnly db) + : base(db) => Sender = sender; } public sealed record AnonymousViewContext - : DbContext, + : DbContext, Internal.IAnonymousViewContext { - internal AnonymousViewContext(Internal.LocalReadOnly db) + internal AnonymousViewContext(LocalReadOnly db) : base(db) { } } +} - namespace Internal.TableHandles +namespace SpacetimeDB.Internal.TableHandles +{ + internal readonly struct BTreeMultiColumn + : global::SpacetimeDB.Internal.ITableView { - internal readonly struct BTreeMultiColumn - : global::SpacetimeDB.Internal.ITableView + static global::BTreeMultiColumn global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.ReadGenFields(System.IO.BinaryReader reader, global::BTreeMultiColumn row) { - static global::BTreeMultiColumn global::SpacetimeDB.Internal.ITableView< + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(BTreeMultiColumn), + ProductTypeRef: (uint) + new global::BTreeMultiColumn.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + Name: null, + AccessorName: "Location", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0, 1, 2]) + ) + ], + Constraints: [], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< BTreeMultiColumn, global::BTreeMultiColumn - >.ReadGenFields(System.IO.BinaryReader reader, global::BTreeMultiColumn row) - { - return row; - } + >.DoCount(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< BTreeMultiColumn, global::BTreeMultiColumn - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(BTreeMultiColumn), - ProductTypeRef: (uint) - new global::BTreeMultiColumn.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: - [ - new( - Name: null, - AccessorName: "Location", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0, 1, 2]) - ) - ], - Constraints: [], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoIter(); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - BTreeMultiColumn, - global::BTreeMultiColumn - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - BTreeMultiColumn, - global::BTreeMultiColumn - >.DoIter(); - - public global::BTreeMultiColumn Insert(global::BTreeMultiColumn row) => - global::SpacetimeDB.Internal.ITableView< - BTreeMultiColumn, - global::BTreeMultiColumn - >.DoInsert(row); - - public bool Delete(global::BTreeMultiColumn row) => - global::SpacetimeDB.Internal.ITableView< - BTreeMultiColumn, - global::BTreeMultiColumn - >.DoDelete(row); - - internal sealed class LocationIndex() - : SpacetimeDB.Internal.IndexBase( - "BTreeMultiColumn_X_Y_Z_idx_btree" - ) - { - public IEnumerable Filter(uint X) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public ulong Delete(uint X) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public IEnumerable Filter(Bound X) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public ulong Delete(Bound X) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public IEnumerable Filter((uint X, uint Y) f) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public ulong Delete((uint X, uint Y) f) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public IEnumerable Filter((uint X, Bound Y) f) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public ulong Delete((uint X, Bound Y) f) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public IEnumerable Filter((uint X, uint Y, uint Z) f) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public ulong Delete((uint X, uint Y, uint Z) f) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public IEnumerable Filter( - (uint X, uint Y, Bound Z) f - ) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public ulong Delete((uint X, uint Y, Bound Z) f) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - } + public global::BTreeMultiColumn Insert(global::BTreeMultiColumn row) => + global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.DoInsert(row); - internal LocationIndex Location => new(); - } + public bool Delete(global::BTreeMultiColumn row) => + global::SpacetimeDB.Internal.ITableView< + BTreeMultiColumn, + global::BTreeMultiColumn + >.DoDelete(row); - internal readonly struct BTreeViews - : global::SpacetimeDB.Internal.ITableView + internal sealed class LocationIndex() + : SpacetimeDB.Internal.IndexBase( + "BTreeMultiColumn_X_Y_Z_idx_btree" + ) { - static global::BTreeViews global::SpacetimeDB.Internal.ITableView< - BTreeViews, - global::BTreeViews - >.ReadGenFields(System.IO.BinaryReader reader, global::BTreeViews row) - { - return row; - } + public IEnumerable Filter(uint X) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< - BTreeViews, - global::BTreeViews - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(BTreeViews), - ProductTypeRef: (uint) - new global::BTreeViews.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [0], - Indexes: - [ - new( - Name: null, - AccessorName: "Id", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ), - new( - Name: null, - AccessorName: "Location", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1, 2]) - ), - new( - Name: null, - AccessorName: "Faction", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([3]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - BTreeViews, - global::BTreeViews - >.MakeUniqueConstraint(0) - ], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private + public ulong Delete(uint X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter(Bound X) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public ulong Delete(Bound X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter((uint X, uint Y) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, uint Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public IEnumerable Filter((uint X, Bound Y) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + + public ulong Delete((uint X, Bound Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) ); - public ulong Count => - global::SpacetimeDB.Internal.ITableView.DoCount(); + public IEnumerable Filter((uint X, uint Y, uint Z) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView.DoIter(); + public ulong Delete((uint X, uint Y, uint Z) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); - public global::BTreeViews Insert(global::BTreeViews row) => - global::SpacetimeDB.Internal.ITableView.DoInsert( - row + public IEnumerable Filter( + (uint X, uint Y, Bound Z) f + ) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) ); - public bool Delete(global::BTreeViews row) => - global::SpacetimeDB.Internal.ITableView.DoDelete( - row + public ulong Delete((uint X, uint Y, Bound Z) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) ); + } - internal sealed class IdUniqueIndex - : UniqueIndex< - BTreeViews, - global::BTreeViews, - SpacetimeDB.Identity, - SpacetimeDB.Identity.BSATN - > - { - internal IdUniqueIndex() - : base("BTreeViews_Id_idx_btree") { } + internal LocationIndex Location => new(); + } - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::BTreeViews? Find(SpacetimeDB.Identity key) => - DoFilter(key).Cast().SingleOrDefault(); + internal readonly struct BTreeViews + : global::SpacetimeDB.Internal.ITableView + { + static global::BTreeViews global::SpacetimeDB.Internal.ITableView< + BTreeViews, + global::BTreeViews + >.ReadGenFields(System.IO.BinaryReader reader, global::BTreeViews row) + { + return row; + } - public global::BTreeViews Update(global::BTreeViews row) => DoUpdate(row); - } + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + BTreeViews, + global::BTreeViews + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(BTreeViews), + ProductTypeRef: (uint) + new global::BTreeViews.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + Name: null, + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + Name: null, + AccessorName: "Location", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1, 2]) + ), + new( + Name: null, + AccessorName: "Faction", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([3]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + BTreeViews, + global::BTreeViews + >.MakeUniqueConstraint(0) + ], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); - internal IdUniqueIndex Id => new(); + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); - internal sealed class LocationIndex() - : SpacetimeDB.Internal.IndexBase("BTreeViews_X_Y_idx_btree") - { - public IEnumerable Filter(uint X) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public ulong Delete(uint X) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public IEnumerable Filter(Bound X) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public ulong Delete(Bound X) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds(X) - ); - - public IEnumerable Filter((uint X, uint Y) f) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public ulong Delete((uint X, uint Y) f) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public IEnumerable Filter((uint X, Bound Y) f) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - - public ulong Delete((uint X, Bound Y) f) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds< - uint, - SpacetimeDB.BSATN.U32, - uint, - SpacetimeDB.BSATN.U32 - >(f) - ); - } + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); - internal LocationIndex Location => new(); + public global::BTreeViews Insert(global::BTreeViews row) => + global::SpacetimeDB.Internal.ITableView.DoInsert(row); - internal sealed class FactionIndex() - : SpacetimeDB.Internal.IndexBase("BTreeViews_Faction_idx_btree") - { - public IEnumerable Filter(string Faction) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds( - Faction - ) - ); - - public ulong Delete(string Faction) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds( - Faction - ) - ); - - public IEnumerable Filter(Bound Faction) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds( - Faction - ) - ); - - public ulong Delete(Bound Faction) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds( - Faction - ) - ); - } + public bool Delete(global::BTreeViews row) => + global::SpacetimeDB.Internal.ITableView.DoDelete(row); - internal FactionIndex Faction => new(); + internal sealed class IdUniqueIndex + : UniqueIndex< + BTreeViews, + global::BTreeViews, + SpacetimeDB.Identity, + SpacetimeDB.Identity.BSATN + > + { + internal IdUniqueIndex() + : base("BTreeViews_Id_idx_btree") { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::BTreeViews? Find(SpacetimeDB.Identity key) => + DoFilter(key).Cast().SingleOrDefault(); + + public global::BTreeViews Update(global::BTreeViews row) => DoUpdate(row); } - public readonly struct MultiTable1 - : global::SpacetimeDB.Internal.ITableView + internal IdUniqueIndex Id => new(); + + internal sealed class LocationIndex() + : SpacetimeDB.Internal.IndexBase("BTreeViews_X_Y_idx_btree") { - static global::MultiTableRow global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.ReadGenFields(System.IO.BinaryReader reader, global::MultiTableRow row) - { - if (row.Foo == default) - { - row.Foo = global::MultiTableRow.BSATN.FooRW.Read(reader); - } - return row; - } + public IEnumerable Filter(uint X) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public ulong Delete(uint X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter(Bound X) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(X)); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(MultiTable1), - ProductTypeRef: (uint) - new global::MultiTableRow.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [1], - Indexes: - [ - new( - Name: null, - AccessorName: "Foo", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ), - new( - Name: null, - AccessorName: "Name", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.MakeUniqueConstraint(1) - ], - Sequences: - [ - global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.MakeSequence(1) - ], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Public + public ulong Delete(Bound X) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(X)); + + public IEnumerable Filter((uint X, uint Y) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) ); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.DoIter(); - - public global::MultiTableRow Insert(global::MultiTableRow row) => - global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.DoInsert(row); - - public bool Delete(global::MultiTableRow row) => - global::SpacetimeDB.Internal.ITableView< - MultiTable1, - global::MultiTableRow - >.DoDelete(row); - - public sealed class FooUniqueIndex - : UniqueIndex - { - internal FooUniqueIndex() - : base("MultiTable1_Foo_idx_btree") { } + public ulong Delete((uint X, uint Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::MultiTableRow? Find(uint key) => - DoFilter(key).Cast().SingleOrDefault(); + public IEnumerable Filter((uint X, Bound Y) f) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); - public global::MultiTableRow Update(global::MultiTableRow row) => DoUpdate(row); - } + public ulong Delete((uint X, Bound Y) f) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds< + uint, + SpacetimeDB.BSATN.U32, + uint, + SpacetimeDB.BSATN.U32 + >(f) + ); + } - public FooUniqueIndex Foo => new(); + internal LocationIndex Location => new(); - public sealed class NameIndex() - : SpacetimeDB.Internal.IndexBase( - "MultiTable1_Name_idx_btree" - ) - { - public IEnumerable Filter(string Name) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds( - Name - ) - ); - - public ulong Delete(string Name) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds( - Name - ) - ); - - public IEnumerable Filter(Bound Name) => - DoFilter( - new SpacetimeDB.Internal.BTreeIndexBounds( - Name - ) - ); - - public ulong Delete(Bound Name) => - DoDelete( - new SpacetimeDB.Internal.BTreeIndexBounds( - Name - ) - ); - } + internal sealed class FactionIndex() + : SpacetimeDB.Internal.IndexBase("BTreeViews_Faction_idx_btree") + { + public IEnumerable Filter(string Faction) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); - public NameIndex Name => new(); + public ulong Delete(string Faction) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); + + public IEnumerable Filter(Bound Faction) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); + + public ulong Delete(Bound Faction) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Faction + ) + ); } - public readonly struct MultiTable2 - : global::SpacetimeDB.Internal.ITableView + internal FactionIndex Faction => new(); + } + + public readonly struct MultiTable1 + : global::SpacetimeDB.Internal.ITableView + { + static global::MultiTableRow global::SpacetimeDB.Internal.ITableView< + MultiTable1, + global::MultiTableRow + >.ReadGenFields(System.IO.BinaryReader reader, global::MultiTableRow row) { - static global::MultiTableRow global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.ReadGenFields(System.IO.BinaryReader reader, global::MultiTableRow row) + if (row.Foo == default) { - if (row.Foo == default) - { - row.Foo = global::MultiTableRow.BSATN.FooRW.Read(reader); - } - return row; + row.Foo = global::MultiTableRow.BSATN.FooRW.Read(reader); } + return row; + } - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(MultiTable2), - ProductTypeRef: (uint) - new global::MultiTableRow.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: - [ - new( - Name: null, - AccessorName: "Bar", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([2]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.MakeUniqueConstraint(2) - ], - Sequences: - [ - global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.MakeSequence(1) - ], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + MultiTable1, + global::MultiTableRow + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(MultiTable1), + ProductTypeRef: (uint) + new global::MultiTableRow.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [1], + Indexes: + [ + new( + Name: null, + AccessorName: "Foo", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ), + new( + Name: null, + AccessorName: "Name", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable1, + global::MultiTableRow + >.MakeUniqueConstraint(1) + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable1, + global::MultiTableRow + >.MakeSequence(1) + ], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public + ); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.DoIter(); - - public global::MultiTableRow Insert(global::MultiTableRow row) => - global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.DoInsert(row); - - public bool Delete(global::MultiTableRow row) => - global::SpacetimeDB.Internal.ITableView< - MultiTable2, - global::MultiTableRow - >.DoDelete(row); - - public sealed class BarUniqueIndex - : UniqueIndex - { - internal BarUniqueIndex() - : base("MultiTable2_Bar_idx_btree") { } + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::MultiTableRow? Find(uint key) => - DoFilter(key).Cast().SingleOrDefault(); + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); - public global::MultiTableRow Update(global::MultiTableRow row) => DoUpdate(row); - } + public global::MultiTableRow Insert(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoInsert( + row + ); - public BarUniqueIndex Bar => new(); + public bool Delete(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoDelete( + row + ); + + public sealed class FooUniqueIndex + : UniqueIndex + { + internal FooUniqueIndex() + : base("MultiTable1_Foo_idx_btree") { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::MultiTableRow? Find(uint key) => + DoFilter(key).Cast().SingleOrDefault(); + + public global::MultiTableRow Update(global::MultiTableRow row) => DoUpdate(row); } - public readonly struct PrivateTable - : global::SpacetimeDB.Internal.ITableView + public FooUniqueIndex Foo => new(); + + public sealed class NameIndex() + : SpacetimeDB.Internal.IndexBase("MultiTable1_Name_idx_btree") { - static global::PrivateTable global::SpacetimeDB.Internal.ITableView< - PrivateTable, - global::PrivateTable - >.ReadGenFields(System.IO.BinaryReader reader, global::PrivateTable row) - { - return row; - } + public IEnumerable Filter(string Name) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) + ); + + public ulong Delete(string Name) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) + ); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< - PrivateTable, - global::PrivateTable - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(PrivateTable), - ProductTypeRef: (uint) - new global::PrivateTable.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [], - Indexes: [], - Constraints: [], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private + public IEnumerable Filter(Bound Name) => + DoFilter( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) ); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - PrivateTable, - global::PrivateTable - >.DoCount(); - - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - PrivateTable, - global::PrivateTable - >.DoIter(); - - public global::PrivateTable Insert(global::PrivateTable row) => - global::SpacetimeDB.Internal.ITableView< - PrivateTable, - global::PrivateTable - >.DoInsert(row); - - public bool Delete(global::PrivateTable row) => - global::SpacetimeDB.Internal.ITableView< - PrivateTable, - global::PrivateTable - >.DoDelete(row); + public ulong Delete(Bound Name) => + DoDelete( + new SpacetimeDB.Internal.BTreeIndexBounds( + Name + ) + ); } - public readonly struct PublicTable - : global::SpacetimeDB.Internal.ITableView + public NameIndex Name => new(); + } + + public readonly struct MultiTable2 + : global::SpacetimeDB.Internal.ITableView + { + static global::MultiTableRow global::SpacetimeDB.Internal.ITableView< + MultiTable2, + global::MultiTableRow + >.ReadGenFields(System.IO.BinaryReader reader, global::MultiTableRow row) { - static global::PublicTable global::SpacetimeDB.Internal.ITableView< - PublicTable, - global::PublicTable - >.ReadGenFields(System.IO.BinaryReader reader, global::PublicTable row) + if (row.Foo == default) { - if (row.Id == default) - { - row.Id = global::PublicTable.BSATN.IdRW.Read(reader); - } - return row; + row.Foo = global::MultiTableRow.BSATN.FooRW.Read(reader); } + return row; + } - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< - PublicTable, - global::PublicTable - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(PublicTable), - ProductTypeRef: (uint) - new global::PublicTable.BSATN().GetAlgebraicType(registrar).Ref_, - PrimaryKey: [0], - Indexes: - [ - new( - Name: null, - AccessorName: "Id", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - PublicTable, - global::PublicTable - >.MakeUniqueConstraint(0) - ], - Sequences: - [ - global::SpacetimeDB.Internal.ITableView< - PublicTable, - global::PublicTable - >.MakeSequence(0) - ], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Public - ); + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + MultiTable2, + global::MultiTableRow + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(MultiTable2), + ProductTypeRef: (uint) + new global::MultiTableRow.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: + [ + new( + Name: null, + AccessorName: "Bar", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([2]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable2, + global::MultiTableRow + >.MakeUniqueConstraint(2) + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + MultiTable2, + global::MultiTableRow + >.MakeSequence(1) + ], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); - public ulong Count => - global::SpacetimeDB.Internal.ITableView.DoCount(); + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView.DoIter(); + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); - public global::PublicTable Insert(global::PublicTable row) => - global::SpacetimeDB.Internal.ITableView.DoInsert( - row - ); + public global::MultiTableRow Insert(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoInsert( + row + ); - public bool Delete(global::PublicTable row) => - global::SpacetimeDB.Internal.ITableView.DoDelete( - row - ); + public bool Delete(global::MultiTableRow row) => + global::SpacetimeDB.Internal.ITableView.DoDelete( + row + ); - public sealed class IdUniqueIndex - : UniqueIndex - { - internal IdUniqueIndex() - : base("PublicTable_Id_idx_btree") { } + public sealed class BarUniqueIndex + : UniqueIndex + { + internal BarUniqueIndex() + : base("MultiTable2_Bar_idx_btree") { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::MultiTableRow? Find(uint key) => + DoFilter(key).Cast().SingleOrDefault(); + + public global::MultiTableRow Update(global::MultiTableRow row) => DoUpdate(row); + } - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::PublicTable? Find(int key) => - DoFilter(key).Cast().SingleOrDefault(); + public BarUniqueIndex Bar => new(); + } - public global::PublicTable Update(global::PublicTable row) => DoUpdate(row); + public readonly struct PrivateTable + : global::SpacetimeDB.Internal.ITableView + { + static global::PrivateTable global::SpacetimeDB.Internal.ITableView< + PrivateTable, + global::PrivateTable + >.ReadGenFields(System.IO.BinaryReader reader, global::PrivateTable row) + { + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + PrivateTable, + global::PrivateTable + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(PrivateTable), + ProductTypeRef: (uint) + new global::PrivateTable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [], + Constraints: [], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::PrivateTable Insert(global::PrivateTable row) => + global::SpacetimeDB.Internal.ITableView.DoInsert( + row + ); + + public bool Delete(global::PrivateTable row) => + global::SpacetimeDB.Internal.ITableView.DoDelete( + row + ); + } + + public readonly struct PublicTable + : global::SpacetimeDB.Internal.ITableView + { + static global::PublicTable global::SpacetimeDB.Internal.ITableView< + PublicTable, + global::PublicTable + >.ReadGenFields(System.IO.BinaryReader reader, global::PublicTable row) + { + if (row.Id == default) + { + row.Id = global::PublicTable.BSATN.IdRW.Read(reader); } + return row; + } - public IdUniqueIndex Id => new(); + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + PublicTable, + global::PublicTable + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(PublicTable), + ProductTypeRef: (uint) + new global::PublicTable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + Name: null, + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + PublicTable, + global::PublicTable + >.MakeUniqueConstraint(0) + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + PublicTable, + global::PublicTable + >.MakeSequence(0) + ], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView.DoIter(); + + public global::PublicTable Insert(global::PublicTable row) => + global::SpacetimeDB.Internal.ITableView.DoInsert(row); + + public bool Delete(global::PublicTable row) => + global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public sealed class IdUniqueIndex + : UniqueIndex + { + internal IdUniqueIndex() + : base("PublicTable_Id_idx_btree") { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::PublicTable? Find(int key) => + DoFilter(key).Cast().SingleOrDefault(); + + public global::PublicTable Update(global::PublicTable row) => DoUpdate(row); + } + + public IdUniqueIndex Id => new(); + } + + internal readonly struct RegressionMultipleUniqueIndexesHadSameName + : global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + > + { + static global::RegressionMultipleUniqueIndexesHadSameName global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.ReadGenFields( + System.IO.BinaryReader reader, + global::RegressionMultipleUniqueIndexesHadSameName row + ) + { + return row; } - internal readonly struct RegressionMultipleUniqueIndexesHadSameName - : global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(RegressionMultipleUniqueIndexesHadSameName), + ProductTypeRef: (uint) + new global::RegressionMultipleUniqueIndexesHadSameName.BSATN() + .GetAlgebraicType(registrar) + .Ref_, + PrimaryKey: [], + Indexes: + [ + new( + Name: null, + AccessorName: "Unique1", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ), + new( + Name: null, + AccessorName: "Unique2", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.MakeUniqueConstraint(0), + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.MakeUniqueConstraint(1) + ], + Sequences: [], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); + + public ulong Count => + global::SpacetimeDB.Internal.ITableView< RegressionMultipleUniqueIndexesHadSameName, global::RegressionMultipleUniqueIndexesHadSameName - > - { - static global::RegressionMultipleUniqueIndexesHadSameName global::SpacetimeDB.Internal.ITableView< + >.DoCount(); + + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< RegressionMultipleUniqueIndexesHadSameName, global::RegressionMultipleUniqueIndexesHadSameName - >.ReadGenFields( - System.IO.BinaryReader reader, - global::RegressionMultipleUniqueIndexesHadSameName row - ) - { - return row; - } + >.DoIter(); - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + public global::RegressionMultipleUniqueIndexesHadSameName Insert( + global::RegressionMultipleUniqueIndexesHadSameName row + ) => + global::SpacetimeDB.Internal.ITableView< RegressionMultipleUniqueIndexesHadSameName, global::RegressionMultipleUniqueIndexesHadSameName - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(RegressionMultipleUniqueIndexesHadSameName), - ProductTypeRef: (uint) - new global::RegressionMultipleUniqueIndexesHadSameName.BSATN() - .GetAlgebraicType(registrar) - .Ref_, - PrimaryKey: [], - Indexes: - [ - new( - Name: null, - AccessorName: "Unique1", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ), - new( - Name: null, - AccessorName: "Unique2", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName - >.MakeUniqueConstraint(0), - global::SpacetimeDB.Internal.ITableView< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName - >.MakeUniqueConstraint(1) - ], - Sequences: [], - Schedule: null, - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); + >.DoInsert(row); - public ulong Count => - global::SpacetimeDB.Internal.ITableView< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName - >.DoCount(); + public bool Delete(global::RegressionMultipleUniqueIndexesHadSameName row) => + global::SpacetimeDB.Internal.ITableView< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName + >.DoDelete(row); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName - >.DoIter(); + internal sealed class Unique1UniqueIndex + : UniqueIndex< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal Unique1UniqueIndex() + : base("RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree") { } - public global::RegressionMultipleUniqueIndexesHadSameName Insert( + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => + DoFilter(key) + .Cast() + .SingleOrDefault(); + + public global::RegressionMultipleUniqueIndexesHadSameName Update( global::RegressionMultipleUniqueIndexesHadSameName row - ) => - global::SpacetimeDB.Internal.ITableView< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName - >.DoInsert(row); - - public bool Delete(global::RegressionMultipleUniqueIndexesHadSameName row) => - global::SpacetimeDB.Internal.ITableView< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName - >.DoDelete(row); - - internal sealed class Unique1UniqueIndex - : UniqueIndex< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName, - uint, - SpacetimeDB.BSATN.U32 - > - { - internal Unique1UniqueIndex() - : base("RegressionMultipleUniqueIndexesHadSameName_Unique1_idx_btree") { } - - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => - DoFilter(key) - .Cast() - .SingleOrDefault(); - - public global::RegressionMultipleUniqueIndexesHadSameName Update( - global::RegressionMultipleUniqueIndexesHadSameName row - ) => DoUpdate(row); - } + ) => DoUpdate(row); + } - internal Unique1UniqueIndex Unique1 => new(); + internal Unique1UniqueIndex Unique1 => new(); - internal sealed class Unique2UniqueIndex - : UniqueIndex< - RegressionMultipleUniqueIndexesHadSameName, - global::RegressionMultipleUniqueIndexesHadSameName, - uint, - SpacetimeDB.BSATN.U32 - > - { - internal Unique2UniqueIndex() - : base("RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree") { } - - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => - DoFilter(key) - .Cast() - .SingleOrDefault(); - - public global::RegressionMultipleUniqueIndexesHadSameName Update( - global::RegressionMultipleUniqueIndexesHadSameName row - ) => DoUpdate(row); - } + internal sealed class Unique2UniqueIndex + : UniqueIndex< + RegressionMultipleUniqueIndexesHadSameName, + global::RegressionMultipleUniqueIndexesHadSameName, + uint, + SpacetimeDB.BSATN.U32 + > + { + internal Unique2UniqueIndex() + : base("RegressionMultipleUniqueIndexesHadSameName_Unique2_idx_btree") { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::RegressionMultipleUniqueIndexesHadSameName? Find(uint key) => + DoFilter(key) + .Cast() + .SingleOrDefault(); - internal Unique2UniqueIndex Unique2 => new(); + public global::RegressionMultipleUniqueIndexesHadSameName Update( + global::RegressionMultipleUniqueIndexesHadSameName row + ) => DoUpdate(row); } - public readonly struct SendMessageTimer - : global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - > + internal Unique2UniqueIndex Unique2 => new(); + } + + public readonly struct SendMessageTimer + : global::SpacetimeDB.Internal.ITableView + { + static global::Timers.SendMessageTimer global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.ReadGenFields(System.IO.BinaryReader reader, global::Timers.SendMessageTimer row) { - static global::Timers.SendMessageTimer global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - >.ReadGenFields(System.IO.BinaryReader reader, global::Timers.SendMessageTimer row) + if (row.ScheduledId == default) { - if (row.ScheduledId == default) - { - row.ScheduledId = global::Timers.SendMessageTimer.BSATN.ScheduledIdRW.Read( - reader - ); - } - return row; + row.ScheduledId = global::Timers.SendMessageTimer.BSATN.ScheduledIdRW.Read(reader); } + return row; + } - static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => - new( - Name: nameof(SendMessageTimer), - ProductTypeRef: (uint) - new global::Timers.SendMessageTimer.BSATN() - .GetAlgebraicType(registrar) - .Ref_, - PrimaryKey: [0], - Indexes: - [ - new( - Name: null, - AccessorName: "ScheduledId", - Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) - ) - ], - Constraints: - [ - global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - >.MakeUniqueConstraint(0) - ], - Sequences: - [ - global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - >.MakeSequence(0) - ], - Schedule: global::SpacetimeDB.Internal.ITableView< + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + new( + Name: nameof(SendMessageTimer), + ProductTypeRef: (uint) + new global::Timers.SendMessageTimer.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: + [ + new( + Name: null, + AccessorName: "ScheduledId", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) + ) + ], + Constraints: + [ + global::SpacetimeDB.Internal.ITableView< SendMessageTimer, global::Timers.SendMessageTimer - >.MakeSchedule("SendScheduledMessage", 1), - TableType: SpacetimeDB.Internal.TableType.User, - TableAccess: SpacetimeDB.Internal.TableAccess.Private - ); - - public ulong Count => - global::SpacetimeDB.Internal.ITableView< + >.MakeUniqueConstraint(0) + ], + Sequences: + [ + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.MakeSequence(0) + ], + Schedule: global::SpacetimeDB.Internal.ITableView< SendMessageTimer, global::Timers.SendMessageTimer - >.DoCount(); + >.MakeSchedule("SendScheduledMessage", 1), + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Private + ); - public IEnumerable Iter() => - global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - >.DoIter(); + public ulong Count => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoCount(); - public global::Timers.SendMessageTimer Insert(global::Timers.SendMessageTimer row) => - global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - >.DoInsert(row); + public IEnumerable Iter() => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoIter(); - public bool Delete(global::Timers.SendMessageTimer row) => - global::SpacetimeDB.Internal.ITableView< - SendMessageTimer, - global::Timers.SendMessageTimer - >.DoDelete(row); + public global::Timers.SendMessageTimer Insert(global::Timers.SendMessageTimer row) => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoInsert(row); - public sealed class ScheduledIdUniqueIndex - : UniqueIndex< - SendMessageTimer, - global::Timers.SendMessageTimer, - ulong, - SpacetimeDB.BSATN.U64 - > - { - internal ScheduledIdUniqueIndex() - : base("SendMessageTimer_ScheduledId_idx_btree") { } - - // Important: don't move this to the base class. - // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based - // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. - public global::Timers.SendMessageTimer? Find(ulong key) => - DoFilter(key).Cast().SingleOrDefault(); - - public global::Timers.SendMessageTimer Update( - global::Timers.SendMessageTimer row - ) => DoUpdate(row); - } + public bool Delete(global::Timers.SendMessageTimer row) => + global::SpacetimeDB.Internal.ITableView< + SendMessageTimer, + global::Timers.SendMessageTimer + >.DoDelete(row); - public ScheduledIdUniqueIndex ScheduledId => new(); + public sealed class ScheduledIdUniqueIndex + : UniqueIndex< + SendMessageTimer, + global::Timers.SendMessageTimer, + ulong, + SpacetimeDB.BSATN.U64 + > + { + internal ScheduledIdUniqueIndex() + : base("SendMessageTimer_ScheduledId_idx_btree") { } + + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Timers.SendMessageTimer? Find(ulong key) => + DoFilter(key).Cast().SingleOrDefault(); + + public global::Timers.SendMessageTimer Update(global::Timers.SendMessageTimer row) => + DoUpdate(row); } - } - public sealed class Local - { - internal global::SpacetimeDB.Internal.TableHandles.BTreeMultiColumn BTreeMultiColumn => - new(); - internal global::SpacetimeDB.Internal.TableHandles.BTreeViews BTreeViews => new(); - public global::SpacetimeDB.Internal.TableHandles.MultiTable1 MultiTable1 => new(); - public global::SpacetimeDB.Internal.TableHandles.MultiTable2 MultiTable2 => new(); - public global::SpacetimeDB.Internal.TableHandles.PrivateTable PrivateTable => new(); - public global::SpacetimeDB.Internal.TableHandles.PublicTable PublicTable => new(); - internal global::SpacetimeDB.Internal.TableHandles.RegressionMultipleUniqueIndexesHadSameName RegressionMultipleUniqueIndexesHadSameName => - new(); - public global::SpacetimeDB.Internal.TableHandles.SendMessageTimer SendMessageTimer => new(); + public ScheduledIdUniqueIndex ScheduledId => new(); } } @@ -1533,24 +1508,6 @@ internal ScheduledIdIndex() } } -namespace SpacetimeDB.Internal -{ - public sealed partial class LocalReadOnly - { - internal global::SpacetimeDB.Internal.ViewHandles.BTreeMultiColumnReadOnly BTreeMultiColumn => - new(); - internal global::SpacetimeDB.Internal.ViewHandles.BTreeViewsReadOnly BTreeViews => new(); - public global::SpacetimeDB.Internal.ViewHandles.MultiTable1ReadOnly MultiTable1 => new(); - public global::SpacetimeDB.Internal.ViewHandles.MultiTable2ReadOnly MultiTable2 => new(); - public global::SpacetimeDB.Internal.ViewHandles.PrivateTableReadOnly PrivateTable => new(); - public global::SpacetimeDB.Internal.ViewHandles.PublicTableReadOnly PublicTable => new(); - internal global::SpacetimeDB.Internal.ViewHandles.RegressionMultipleUniqueIndexesHadSameNameReadOnly RegressionMultipleUniqueIndexesHadSameName => - new(); - public global::SpacetimeDB.Internal.ViewHandles.SendMessageTimerReadOnly SendMessageTimer => - new(); - } -} - static class ModuleRegistration { class Init : SpacetimeDB.Internal.IReducer @@ -1665,13 +1622,10 @@ public static void Main() new SpacetimeDB.ReducerContext(identity, connectionId, random, time) ); SpacetimeDB.Internal.Module.SetViewContextConstructor( - identity => new SpacetimeDB.ViewContext( - identity, - new SpacetimeDB.Internal.LocalReadOnly() - ) + identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.LocalReadOnly()) ); SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor( - () => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.Internal.LocalReadOnly()) + () => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.LocalReadOnly()) ); SpacetimeDB.Internal.Module.SetProcedureContextConstructor( (identity, connectionId, random, time) => @@ -1788,6 +1742,10 @@ SpacetimeDB.Internal.BytesSink result_sink result_sink ); + [UnmanagedCallersOnly(EntryPoint = "__take_procedure_tx_offset__")] + public static byte __take_procedure_tx_offset__(ulong* offset) => + SpacetimeDB.Internal.Module.__take_procedure_tx_offset__(out *offset) ? (byte)1 : (byte)0; + [UnmanagedCallersOnly(EntryPoint = "__call_view__")] public static SpacetimeDB.Internal.Errno __call_view__( uint id, @@ -1817,4 +1775,5 @@ SpacetimeDB.Internal.BytesSink sink #endif } +#pragma warning restore STDB_UNSTABLE #pragma warning restore CS0436 diff --git a/crates/bindings-csharp/Codegen/Codegen.csproj b/crates/bindings-csharp/Codegen/Codegen.csproj index 3f1036e6ff2..7bf172ed0d0 100644 --- a/crates/bindings-csharp/Codegen/Codegen.csproj +++ b/crates/bindings-csharp/Codegen/Codegen.csproj @@ -1,5 +1,4 @@ - SpacetimeDB.Codegen 1.11.0 @@ -42,7 +41,9 @@ - + - diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index 6b87a4028b0..e96a4b4e25d 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -7,161 +7,149 @@ internal static class ErrorDescriptor { private static readonly ErrorDescriptorGroup group = new("STDB", "SpacetimeDB"); - public static readonly ErrorDescriptor ReducerReturnType = - new( - group, - "[SpacetimeDB.Reducer] methods must return void", - method => - $"Reducer method {method.Identifier} returns {method.ReturnType} instead of void.", - method => method.ReturnType - ); - - public static readonly ErrorDescriptor AutoIncNotInteger = - new( - group, - "AutoInc fields must be of integer type", - field => - $"Field {field.Name} is marked as AutoInc but it has a non-integer type {field.Type}.", - field => field - ); - - public static readonly ErrorDescriptor UniqueNotEquatable = - new( - group, - "Unique fields must be equatable", - field => - $"Field {field.Name} is marked as Unique but it has a type {field.Type} which is not an equatable primitive.", - field => field - ); - - public static readonly ErrorDescriptor EmptyIndexColumns = - new( - group, - "Index attribute must specify Columns", - _ => $"Index attribute doesn't specify columns.", - attr => attr - ); - - public static readonly ErrorDescriptor InvalidTableVisibility = - new( - group, - "Table row visibility must be public or internal", - table => $"Table {table.Identifier} and its parent types must be public or internal.", - table => table.Identifier - ); - - public static readonly ErrorDescriptor TableTaggedEnum = - new( - group, - "Tables cannot be tagged enums", - table => $"Table {table.Identifier} is a tagged enum, which is not allowed.", - table => table.BaseList! - ); + public static readonly ErrorDescriptor ReducerReturnType = new( + group, + "[SpacetimeDB.Reducer] methods must return void", + method => + $"Reducer method {method.Identifier} returns {method.ReturnType} instead of void.", + method => method.ReturnType + ); + + public static readonly ErrorDescriptor AutoIncNotInteger = new( + group, + "AutoInc fields must be of integer type", + field => + $"Field {field.Name} is marked as AutoInc but it has a non-integer type {field.Type}.", + field => field + ); + + public static readonly ErrorDescriptor UniqueNotEquatable = new( + group, + "Unique fields must be equatable", + field => + $"Field {field.Name} is marked as Unique but it has a type {field.Type} which is not an equatable primitive.", + field => field + ); + + public static readonly ErrorDescriptor EmptyIndexColumns = new( + group, + "Index attribute must specify Columns", + _ => $"Index attribute doesn't specify columns.", + attr => attr + ); + + public static readonly ErrorDescriptor InvalidTableVisibility = new( + group, + "Table row visibility must be public or internal", + table => $"Table {table.Identifier} and its parent types must be public or internal.", + table => table.Identifier + ); + + public static readonly ErrorDescriptor TableTaggedEnum = new( + group, + "Tables cannot be tagged enums", + table => $"Table {table.Identifier} is a tagged enum, which is not allowed.", + table => table.BaseList! + ); public static readonly ErrorDescriptor<( string kind, string exportName, IEnumerable fullNames - )> DuplicateExport = - new( - group, - "Duplicate exports", - ctx => - $"{ctx.kind} with the same export name {ctx.exportName} is registered in multiple places: {string.Join(", ", ctx.fullNames)}", - ctx => Location.None - ); - - public static readonly ErrorDescriptor ReducerContextParam = - new( - group, - "Reducers must have a first argument of type ReducerContext", - method => - $"Reducer method {method.Identifier} does not have a ReducerContext parameter.", - method => method.ParameterList - ); - - public static readonly ErrorDescriptor ProcedureContextParam = - new( - group, - "Procedures must have a first argument of type ProcedureContext", - method => - $"Procedure method {method.Identifier} does not have a ProcedureContext parameter.", - method => method.ParameterList - ); + )> DuplicateExport = new( + group, + "Duplicate exports", + ctx => + $"{ctx.kind} with the same export name {ctx.exportName} is registered in multiple places: {string.Join(", ", ctx.fullNames)}", + ctx => Location.None + ); + + public static readonly ErrorDescriptor ReducerContextParam = new( + group, + "Reducers must have a first argument of type ReducerContext", + method => $"Reducer method {method.Identifier} does not have a ReducerContext parameter.", + method => method.ParameterList + ); + + public static readonly ErrorDescriptor ProcedureContextParam = new( + group, + "Procedures must have a first argument of type ProcedureContext", + method => + $"Procedure method {method.Identifier} does not have a ProcedureContext parameter.", + method => method.ParameterList + ); public static readonly ErrorDescriptor<( MethodDeclarationSyntax method, string prefix - )> ReducerReservedPrefix = - new( - group, - "Reducer method has a reserved name prefix", - ctx => - $"Reducer method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", - ctx => ctx.method.Identifier - ); + )> ReducerReservedPrefix = new( + group, + "Reducer method has a reserved name prefix", + ctx => + $"Reducer method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", + ctx => ctx.method.Identifier + ); public static readonly ErrorDescriptor<( MethodDeclarationSyntax method, string prefix - )> ProcedureReservedPrefix = - new( - group, - "Procedure method has a reserved name prefix", - ctx => - $"Procedure method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", - ctx => ctx.method.Identifier - ); + )> ProcedureReservedPrefix = new( + group, + "Procedure method has a reserved name prefix", + ctx => + $"Procedure method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", + ctx => ctx.method.Identifier + ); public static readonly UnusedErrorDescriptor IncompatibleTableSchedule = new(group); public static readonly ErrorDescriptor<( ReducerKind kind, IEnumerable fullNames - )> DuplicateSpecialReducer = - new( - group, - "Multiple reducers of the same kind", - ctx => - $"Several reducers are assigned to the same lifecycle kind {ctx.kind}: {string.Join(", ", ctx.fullNames)}", - ctx => Location.None - ); + )> DuplicateSpecialReducer = new( + group, + "Multiple reducers of the same kind", + ctx => + $"Several reducers are assigned to the same lifecycle kind {ctx.kind}: {string.Join(", ", ctx.fullNames)}", + ctx => Location.None + ); public static readonly ErrorDescriptor<( AttributeData attr, string message - )> InvalidScheduledDeclaration = - new(group, "Invalid scheduled table declaration", ctx => $"{ctx.message}", ctx => ctx.attr); - - public static readonly ErrorDescriptor UnexpectedIndexColumns = - new( - group, - "Index attribute on a field must not specify Columns", - _ => - $"Index attribute on a field applies directly to that field, so it doesn't accept the Columns parameter.", - attr => attr - ); + )> InvalidScheduledDeclaration = new( + group, + "Invalid scheduled table declaration", + ctx => $"{ctx.message}", + ctx => ctx.attr + ); + + public static readonly ErrorDescriptor UnexpectedIndexColumns = new( + group, + "Index attribute on a field must not specify Columns", + _ => + $"Index attribute on a field applies directly to that field, so it doesn't accept the Columns parameter.", + attr => attr + ); public static readonly ErrorDescriptor<( AttributeData attr, string columnName, string typeName - )> UnknownColumn = - new( - group, - "Unknown column", - ctx => $"Could not find the specified column {ctx.columnName} in {ctx.typeName}.", - ctx => ctx.attr - ); - - public static readonly ErrorDescriptor ClientVisibilityNotFilter = - new( - group, - "ClientVisibilityFilters must be Filters", - field => - $"Field {field.Name} is marked as ClientVisibilityFilter but it has type {field.Type} which is not SpacetimeDB.Filter", - field => field - ); + )> UnknownColumn = new( + group, + "Unknown column", + ctx => $"Could not find the specified column {ctx.columnName} in {ctx.typeName}.", + ctx => ctx.attr + ); + + public static readonly ErrorDescriptor ClientVisibilityNotFilter = new( + group, + "ClientVisibilityFilters must be Filters", + field => + $"Field {field.Name} is marked as ClientVisibilityFilter but it has type {field.Type} which is not SpacetimeDB.Filter", + field => field + ); public static readonly ErrorDescriptor ClientVisibilityNotPublicStaticReadonly = new( @@ -181,62 +169,55 @@ string typeName field => field ); - public static readonly ErrorDescriptor InvalidDefaultValueType = - new( - group, - "Invalid Default Value Type", - field => $"Default value for field {field.Name} cannot be converted to provided type", - field => field - ); - - public static readonly ErrorDescriptor InvalidDefaultValueFormat = - new( - group, - "Invalid Default Value Format", - field => $"Default value for field {field.Name} has invalid format for provided type ", - field => field - ); - public static readonly ErrorDescriptor ViewContextParam = - new( - group, - "Views must start with ViewContext or AnonymousViewContext", - method => - $"View method {method.Identifier} must have a first parameter of type ViewContext or AnonymousViewContext.", - method => method.ParameterList - ); - - public static readonly ErrorDescriptor ViewMustHaveName = - new( - group, - "Views must have an explicit name.", - method => $"View '{method.Identifier}' must have an explicit name.", - method => method - ); - public static readonly ErrorDescriptor ViewInvalidReturn = - new( - group, - "Views must return Vec or Option", - method => $"View '{method.Identifier}' must return Vec or Option.", - method => method - ); + public static readonly ErrorDescriptor InvalidDefaultValueType = new( + group, + "Invalid Default Value Type", + field => $"Default value for field {field.Name} cannot be converted to provided type", + field => field + ); + + public static readonly ErrorDescriptor InvalidDefaultValueFormat = new( + group, + "Invalid Default Value Format", + field => $"Default value for field {field.Name} has invalid format for provided type ", + field => field + ); + public static readonly ErrorDescriptor ViewContextParam = new( + group, + "Views must start with ViewContext or AnonymousViewContext", + method => + $"View method {method.Identifier} must have a first parameter of type ViewContext or AnonymousViewContext.", + method => method.ParameterList + ); + + public static readonly ErrorDescriptor ViewMustHaveName = new( + group, + "Views must have an explicit name.", + method => $"View '{method.Identifier}' must have an explicit name.", + method => method + ); + public static readonly ErrorDescriptor ViewInvalidReturn = new( + group, + "Views must return Vec or Option", + method => $"View '{method.Identifier}' must return Vec or Option.", + method => method + ); // TODO: Remove once Views support Private: Views must be Public currently - public static readonly ErrorDescriptor ViewMustBePublic = - new( - group, - "Views must be public", - method => - $"View '{method.Identifier}' must have Public = true. Views are always public in SpacetimeDB.", - method => method - ); + public static readonly ErrorDescriptor ViewMustBePublic = new( + group, + "Views must be public", + method => + $"View '{method.Identifier}' must have Public = true. Views are always public in SpacetimeDB.", + method => method + ); // TODO: Remove once Views support arguments: Views must have no arguments beyond the context. - public static readonly ErrorDescriptor ViewArgsUnsupported = - new( - group, - "Views must have no arguments beyond the context.", - method => - $"View '{method.Identifier}' must have no arguments beyond the context. This is a temporary limitation.", - method => method - ); + public static readonly ErrorDescriptor ViewArgsUnsupported = new( + group, + "Views must have no arguments beyond the context.", + method => + $"View '{method.Identifier}' must have no arguments beyond the context. This is a temporary limitation.", + method => method + ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index bc31b94c6bf..03dea0e4c93 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -557,7 +557,7 @@ public ulong Delete({{argsScalar}}) => public ulong Delete({{argsBounds}}) => DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds<{{types}}>({{argName}})); - + """; } @@ -1268,25 +1268,20 @@ public string GenerateClass() "return output.ToArray();", }; - bodyLines = - new[] - { - $"var outcome = {invocation};", - "if (!outcome.IsSuccess)", - "{", - " throw outcome.Error ?? new System.InvalidOperationException(\"Transaction failed.\");", - "}", - } + bodyLines = new[] + { + $"var outcome = {invocation};", + "if (!outcome.IsSuccess)", + "{", + " throw outcome.Error ?? new System.InvalidOperationException(\"Transaction failed.\");", + "}", + } .Concat(successLines) .ToArray(); } else if (ReturnType.IsVoid) { - bodyLines = new[] - { - $"{invocation};", - "return System.Array.Empty();", - }; + bodyLines = new[] { $"{invocation};", "return System.Array.Empty();" }; } else { @@ -1302,14 +1297,15 @@ public string GenerateClass() } var invokeBody = string.Join("\n", bodyLines.Select(line => $" {line}")); - var paramReads = Args.Length == 0 - ? string.Empty - : string.Join( - "\n", - Args.Select(a => - $" var {a.Name} = {a.Name}{TypeUse.BsatnFieldSuffix}.Read(reader);" - ) - ) + "\n"; + var paramReads = + Args.Length == 0 + ? string.Empty + : string.Join( + "\n", + Args.Select(a => + $" var {a.Name} = {a.Name}{TypeUse.BsatnFieldSuffix}.Read(reader);" + ) + ) + "\n"; var returnTypeExpr = hasTxWrapper ? ( @@ -1331,20 +1327,20 @@ public string GenerateClass() } return $$$""" - class {{{Name}}} : SpacetimeDB.Internal.IProcedure { - {{{classFields}}} - - public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( - nameof({{{Name}}}), - [{{{MemberDeclaration.GenerateDefs(Args)}}}], - {{{returnTypeExpr}}} - ); - - public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { - {{{paramReads}}}{{{invokeBody}}} - } - } - """; + class {{{Name}}} : SpacetimeDB.Internal.IProcedure { + {{{classFields}}} + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof({{{Name}}}), + [{{{MemberDeclaration.GenerateDefs(Args)}}}], + {{{returnTypeExpr}}} + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + {{{paramReads}}}{{{invokeBody}}} + } + } + """; } public Scope.Extensions GenerateSchedule() @@ -1375,16 +1371,17 @@ public Scope.Extensions GenerateSchedule() return extensions; } - + private bool TryGetTxOutcomeType(out TypeUse payloadType) { if ( - _returnTypeSymbol is INamedTypeSymbol - { - Name: "TxOutcome", - ContainingType: { Name: "ProcedureContext" } - } named && - named.TypeArguments.Length == 1 + _returnTypeSymbol + is INamedTypeSymbol + { + Name: "TxOutcome", + ContainingType: { Name: "ProcedureContext" } + } named + && named.TypeArguments.Length == 1 ) { payloadType = TypeUse.Parse(_methodSymbol, named.TypeArguments[0], _diag); @@ -1398,12 +1395,13 @@ _returnTypeSymbol is INamedTypeSymbol private bool TryGetTxResultTypes(out TypeUse payloadType, out TypeUse errorType) { if ( - _returnTypeSymbol is INamedTypeSymbol - { - Name: "TxResult", - ContainingType: { Name: "ProcedureContext" } - } named && - named.TypeArguments.Length == 2 + _returnTypeSymbol + is INamedTypeSymbol + { + Name: "TxResult", + ContainingType: { Name: "ProcedureContext" } + } named + && named.TypeArguments.Length == 2 ) { payloadType = TypeUse.Parse(_methodSymbol, named.TypeArguments[0], _diag); diff --git a/crates/bindings-csharp/Runtime.Tests/Runtime.Tests.csproj b/crates/bindings-csharp/Runtime.Tests/Runtime.Tests.csproj index d5cb92f3a77..139122ac391 100644 --- a/crates/bindings-csharp/Runtime.Tests/Runtime.Tests.csproj +++ b/crates/bindings-csharp/Runtime.Tests/Runtime.Tests.csproj @@ -1,5 +1,4 @@ - net8.0 enable @@ -20,8 +19,7 @@ - - + + - diff --git a/crates/bindings-csharp/Runtime/Exceptions.cs b/crates/bindings-csharp/Runtime/Exceptions.cs index e6cd7ceacbf..a7a3cf8b09d 100644 --- a/crates/bindings-csharp/Runtime/Exceptions.cs +++ b/crates/bindings-csharp/Runtime/Exceptions.cs @@ -77,7 +77,8 @@ public class AutoIncOverflowException : StdbException public override string Message => "The auto-increment sequence overflowed"; } -public class TransactionWouldBlockException : StdbException { +public class TransactionWouldBlockException : StdbException +{ public override string Message => "Attempted operation while another transaction is open"; } @@ -91,7 +92,8 @@ public class TransactionIsReadOnlyException : StdbException public override string Message => "The transaction is read-only"; } -public class TransactionIsMutableException : StdbException { +public class TransactionIsMutableException : StdbException +{ public override string Message => "ABI call can only be made while inside a read-only transaction"; } diff --git a/crates/bindings-csharp/Runtime/Internal/FFI.cs b/crates/bindings-csharp/Runtime/Internal/FFI.cs index a5e3b1e612b..7407d867ef8 100644 --- a/crates/bindings-csharp/Runtime/Internal/FFI.cs +++ b/crates/bindings-csharp/Runtime/Internal/FFI.cs @@ -40,7 +40,7 @@ public enum Errno : short WOULD_BLOCK_TRANSACTION = 17, TRANSACTION_NOT_ANONYMOUS = 18, TRANSACTION_IS_READ_ONLY = 19, - TRANSACTION_IS_MUT = 20, + TRANSACTION_IS_MUT = 20, } #pragma warning disable IDE1006 // Naming Styles - Not applicable to FFI stuff. @@ -72,7 +72,7 @@ internal static partial class FFI "bindings" #endif ; - + const string StdbNamespace10_3 = #if EXPERIMENTAL_WASM_AOT "spacetime_10.3" @@ -103,7 +103,7 @@ public static CheckedStatus ConvertToManaged(Errno status) } } } - + internal static class ErrnoHelpers { public static void ThrowIfError(Errno status) @@ -116,27 +116,28 @@ public static void ThrowIfError(Errno status) throw ToException(status); } - public static Exception ToException(Errno status) => status switch - { - Errno.NOT_IN_TRANSACTION => new NotInTransactionException(), - Errno.BSATN_DECODE_ERROR => new BsatnDecodeException(), - Errno.NO_SUCH_TABLE => new NoSuchTableException(), - Errno.NO_SUCH_INDEX => new NoSuchIndexException(), - Errno.NO_SUCH_ITER => new NoSuchIterException(), - Errno.NO_SUCH_CONSOLE_TIMER => new NoSuchLogStopwatch(), - Errno.NO_SUCH_BYTES => new NoSuchBytesException(), - Errno.NO_SPACE => new NoSpaceException(), - Errno.BUFFER_TOO_SMALL => new BufferTooSmallException(), - Errno.UNIQUE_ALREADY_EXISTS => new UniqueConstraintViolationException(), - Errno.INDEX_NOT_UNIQUE => new IndexNotUniqueException(), - Errno.NO_SUCH_ROW => new NoSuchRowException(), - Errno.AUTO_INC_OVERFLOW => new AutoIncOverflowException(), - Errno.WOULD_BLOCK_TRANSACTION => new TransactionWouldBlockException(), - Errno.TRANSACTION_NOT_ANONYMOUS => new TransactionNotAnonymousException(), - Errno.TRANSACTION_IS_READ_ONLY => new TransactionIsReadOnlyException(), - Errno.TRANSACTION_IS_MUT => new TransactionIsMutableException(), - _ => new UnknownException(status), - }; + public static Exception ToException(Errno status) => + status switch + { + Errno.NOT_IN_TRANSACTION => new NotInTransactionException(), + Errno.BSATN_DECODE_ERROR => new BsatnDecodeException(), + Errno.NO_SUCH_TABLE => new NoSuchTableException(), + Errno.NO_SUCH_INDEX => new NoSuchIndexException(), + Errno.NO_SUCH_ITER => new NoSuchIterException(), + Errno.NO_SUCH_CONSOLE_TIMER => new NoSuchLogStopwatch(), + Errno.NO_SUCH_BYTES => new NoSuchBytesException(), + Errno.NO_SPACE => new NoSpaceException(), + Errno.BUFFER_TOO_SMALL => new BufferTooSmallException(), + Errno.UNIQUE_ALREADY_EXISTS => new UniqueConstraintViolationException(), + Errno.INDEX_NOT_UNIQUE => new IndexNotUniqueException(), + Errno.NO_SUCH_ROW => new NoSuchRowException(), + Errno.AUTO_INC_OVERFLOW => new AutoIncOverflowException(), + Errno.WOULD_BLOCK_TRANSACTION => new TransactionWouldBlockException(), + Errno.TRANSACTION_NOT_ANONYMOUS => new TransactionNotAnonymousException(), + Errno.TRANSACTION_IS_READ_ONLY => new TransactionIsReadOnlyException(), + Errno.TRANSACTION_IS_MUT => new TransactionIsMutableException(), + _ => new UnknownException(status), + }; } [StructLayout(LayoutKind.Sequential)] @@ -345,7 +346,7 @@ uint args_len [DllImport(StdbNamespace10_2)] public static extern Errno get_jwt(ref ConnectionId connectionId, out BytesSource source); - + [LibraryImport(StdbNamespace10_3, EntryPoint = "procedure_start_mut_tx")] public static partial Errno procedure_start_mut_tx(out long micros); @@ -354,7 +355,7 @@ uint args_len [LibraryImport(StdbNamespace10_3, EntryPoint = "procedure_abort_mut_tx")] public static partial CheckedStatus procedure_abort_mut_tx(); - + [LibraryImport(StdbNamespace10_3, EntryPoint = "__take_procedure_tx_offset__")] [return: MarshalAs(UnmanagedType.I1)] public static partial bool take_procedure_tx_offset(out ulong offset); diff --git a/crates/bindings-csharp/Runtime/Internal/ITable.cs b/crates/bindings-csharp/Runtime/Internal/ITable.cs index 575c3a9fc10..146358b4243 100644 --- a/crates/bindings-csharp/Runtime/Internal/ITable.cs +++ b/crates/bindings-csharp/Runtime/Internal/ITable.cs @@ -34,8 +34,7 @@ public bool MoveNext() // Iterator advanced and may also be `EXHAUSTED`. // When `OK`, we'll need to advance the iterator in the next call to `MoveNext`. // In both cases, copy over the row data to `Current` from the scratch `buffer`. - case Errno.EXHAUSTED - or Errno.OK: + case Errno.EXHAUSTED or Errno.OK: Current = new byte[buffer_len]; Array.Copy(buffer, 0, Current, 0, buffer_len); return buffer_len != 0; @@ -112,13 +111,12 @@ protected override void IterStart(out FFI.RowIter handle) => private static readonly string tableName = typeof(View).Name; // Note: this must be Lazy to ensure that we don't try to get the tableId during startup, before the module is initialized. - private static readonly Lazy tableId_ = - new(() => - { - var name_bytes = System.Text.Encoding.UTF8.GetBytes(tableName); - FFI.table_id_from_name(name_bytes, (uint)name_bytes.Length, out var out_); - return out_; - }); + private static readonly Lazy tableId_ = new(() => + { + var name_bytes = System.Text.Encoding.UTF8.GetBytes(tableName); + FFI.table_id_from_name(name_bytes, (uint)name_bytes.Length, out var out_); + return out_; + }); internal static FFI.TableId tableId => tableId_.Value; diff --git a/crates/bindings-csharp/Runtime/Internal/Module.cs b/crates/bindings-csharp/Runtime/Internal/Module.cs index b2937db24ed..9f43c463b5a 100644 --- a/crates/bindings-csharp/Runtime/Internal/Module.cs +++ b/crates/bindings-csharp/Runtime/Internal/Module.cs @@ -381,7 +381,7 @@ BytesSink resultSink return Errno.HOST_CALL_FAILURE; } } - + public static bool __take_procedure_tx_offset__(out ulong offset) { if (TakeProcedureTxOffset() is { } tx) diff --git a/crates/bindings-csharp/Runtime/Internal/Procedure.cs b/crates/bindings-csharp/Runtime/Internal/Procedure.cs index a11b7ff96ab..37cfd487f5b 100644 --- a/crates/bindings-csharp/Runtime/Internal/Procedure.cs +++ b/crates/bindings-csharp/Runtime/Internal/Procedure.cs @@ -21,9 +21,8 @@ internal static IDisposable PushContext(IProcedureContext ctx) => new ContextScope(ctx as IInternalProcedureContext); private static IInternalProcedureContext RequireContext() => - current.Value ?? throw new InvalidOperationException( - "Transaction syscalls require a procedure context." - ); + current.Value + ?? throw new InvalidOperationException("Transaction syscalls require a procedure context."); public static long StartMutTx() { @@ -45,7 +44,7 @@ public static void CommitMutTx() Module.RecordProcedureTxOffset(offset); } } - + public static void AbortMutTx() { FFI.procedure_abort_mut_tx(); // throws on error @@ -84,14 +83,16 @@ public static bool CommitMutTxWithRetry(Func retryBody) } catch (StdbException) { - if (retryBody()) { + Log.Warn("Committing anonymous transaction failed; retrying once."); + if (retryBody()) + { CommitMutTx(); return true; } return false; } } - + public static async Task CommitMutTxWithRetryAsync(Func> retryBody) { try @@ -105,6 +106,7 @@ public static async Task CommitMutTxWithRetryAsync(Func> retryB } catch (StdbException) { + Log.Warn("Committing anonymous transaction failed; retrying once."); if (await retryBody().ConfigureAwait(false)) { await CommitMutTxAsync().ConfigureAwait(false); @@ -133,6 +135,5 @@ public readonly struct TransactionOffset private TransactionOffset(ulong value) => Value = value; - public static TransactionOffset FromRaw(long raw) => - new(unchecked((ulong)raw)); + public static TransactionOffset FromRaw(long raw) => new(unchecked((ulong)raw)); } diff --git a/crates/bindings-csharp/Runtime/Internal/TxContext.cs b/crates/bindings-csharp/Runtime/Internal/TxContext.cs index db2589ee0cd..25bf7674edd 100644 --- a/crates/bindings-csharp/Runtime/Internal/TxContext.cs +++ b/crates/bindings-csharp/Runtime/Internal/TxContext.cs @@ -8,7 +8,8 @@ public TxContext( ConnectionId? connectionId, Timestamp timestamp, AuthCtx senderAuth, - Random rng) + Random rng + ) { Db = db; Sender = sender; @@ -27,4 +28,4 @@ public TxContext( public TxContext WithTimestamp(Timestamp ts) => new(Db, Sender, ConnectionId, ts, SenderAuth, Rng); -} \ No newline at end of file +} diff --git a/crates/bindings-csharp/Runtime/ProcedureContext.cs b/crates/bindings-csharp/Runtime/ProcedureContext.cs index e9d6c006d44..11fe27743b2 100644 --- a/crates/bindings-csharp/Runtime/ProcedureContext.cs +++ b/crates/bindings-csharp/Runtime/ProcedureContext.cs @@ -9,7 +9,8 @@ protected ProcedureContextBase( Identity sender, ConnectionId? connectionId, Random random, - Timestamp time) + Timestamp time + ) { Sender = sender; ConnectionId = connectionId; @@ -34,7 +35,9 @@ protected ProcedureContextBase( private protected ProcedureTxContextBase RequireTxContext() { - var inner = txContext ?? throw new InvalidOperationException("Transaction context was not initialised."); + var inner = + txContext + ?? throw new InvalidOperationException("Transaction context was not initialised."); cachedUserTxContext ??= CreateTxContext(inner); cachedUserTxContext.Refresh(inner); return cachedUserTxContext; @@ -44,15 +47,22 @@ public Internal.TxContext EnterTxContext(long timestampMicros) { var timestamp = new Timestamp(timestampMicros); Timestamp = timestamp; - txContext = txContext?.WithTimestamp(timestamp) - ?? new Internal.TxContext(CreateLocal(), Sender, ConnectionId, timestamp, SenderAuth, Rng); + txContext = + txContext?.WithTimestamp(timestamp) + ?? new Internal.TxContext( + CreateLocal(), + Sender, + ConnectionId, + timestamp, + SenderAuth, + Rng + ); return txContext; } public void ExitTxContext() => txContext = null; - public void SetTransactionOffset(Internal.TransactionOffset offset) => - pendingTxOffset = offset; + public void SetTransactionOffset(Internal.TransactionOffset offset) => pendingTxOffset = offset; public bool TryTakeTransactionOffset(out Internal.TransactionOffset offset) { @@ -75,24 +85,27 @@ public TxOutcome(bool isSuccess, TResult? value, Exception? error) Value = value; Error = error; } - + public bool IsSuccess { get; } public TResult? Value { get; } public Exception? Error { get; } - - public static TxOutcome Success(TResult value) => - new(true, value, null); - - public static TxOutcome Failure(Exception error) => - new(false, default, error); - + + public static TxOutcome Success(TResult value) => new(true, value, null); + + public static TxOutcome Failure(Exception error) => new(false, default, error); + public TResult UnwrapOrThrow() => - IsSuccess ? Value! : throw (Error ?? new InvalidOperationException("Transaction failed without an error object.")); - + IsSuccess + ? Value! + : throw ( + Error + ?? new InvalidOperationException("Transaction failed without an error object.") + ); + public TResult UnwrapOrThrow(Func fallbackFactory) => IsSuccess ? Value! : throw (Error ?? fallbackFactory()); } - + public readonly struct TxResult where TError : Exception { @@ -102,40 +115,39 @@ public TxResult(bool isSuccess, TResult? value, TError? error) Value = value; Error = error; } - + public bool IsSuccess { get; } public TResult? Value { get; } public TError? Error { get; } - - public static TxResult Success(TResult value) => - new(true, value, null); - - public static TxResult Failure(TError error) => - new(false, default, error); - + + public static TxResult Success(TResult value) => new(true, value, null); + + public static TxResult Failure(TError error) => new(false, default, error); + public TResult UnwrapOrThrow() { if (IsSuccess) { return Value!; } - + if (Error is not null) { throw Error; } - + throw new InvalidOperationException("Transaction failed without an error object."); } } - + [Experimental("STDB_UNSTABLE")] public TResult WithTx(Func body) => TryWithTx(tx => TxResult.Success(body(tx))).UnwrapOrThrow(); - + [Experimental("STDB_UNSTABLE")] public TxOutcome TryWithTx( - Func> body) + Func> body + ) where TError : Exception { try @@ -150,9 +162,10 @@ public TxOutcome TryWithTx( return TxOutcome.Failure(ex); } } - + private TxResult RunWithRetry( - Func> body) + Func> body + ) where TError : Exception { var result = RunOnce(body); @@ -160,29 +173,30 @@ private TxResult RunWithRetry( { return result; } - + bool Retry() { result = RunOnce(body); return result.IsSuccess; } - + if (!SpacetimeDB.Internal.Procedure.CommitMutTxWithRetry(Retry)) { return result; } - + if (TryTakeTransactionOffset(out var offset)) { SetTransactionOffset(offset); SpacetimeDB.Internal.Module.RecordProcedureTxOffset(offset); } - + return result; } - + private TxResult RunOnce( - Func> body) + Func> body + ) where TError : Exception { _ = SpacetimeDB.Internal.Procedure.StartMutTx(); @@ -194,21 +208,21 @@ private TxResult RunOnce( guard.Disarm(); return result; } - + SpacetimeDB.Internal.Procedure.AbortMutTx(); guard.Disarm(); return result; } - + private sealed class AbortGuard : IDisposable { private readonly Action abort; private bool disarmed; - + public AbortGuard(Action abort) => this.abort = abort; - + public void Disarm() => disarmed = true; - + public void Dispose() { if (!disarmed) @@ -238,13 +252,9 @@ protected ProcedureTxContextBase(Internal.TxContext inner) public Random Rng => Inner.Rng; } -public abstract class LocalBase : Internal.Local -{ -} +public abstract class LocalBase : Internal.Local { } -public abstract class LocalReadOnlyBase : Internal.LocalReadOnly -{ -} +public abstract class LocalReadOnlyBase : Internal.LocalReadOnly { } public sealed class ProcedureContext : ProcedureContextBase { @@ -254,12 +264,12 @@ public ProcedureContext( Identity sender, ConnectionId? connectionId, Random random, - Timestamp timestamp) - : base(sender, connectionId, random, timestamp) - { - } + Timestamp timestamp + ) + : base(sender, connectionId, random, timestamp) { } protected internal override LocalBase CreateLocal() => _db; + protected override ProcedureTxContextBase CreateTxContext(Internal.TxContext inner) => _cached ??= new ProcedureTxContext(inner); @@ -269,18 +279,12 @@ protected override ProcedureTxContextBase CreateTxContext(Internal.TxContext inn public sealed class ProcedureTxContext : ProcedureTxContextBase { internal ProcedureTxContext(Internal.TxContext inner) - : base(inner) - { - } + : base(inner) { } public new Local Db => (Local)base.Db; } -public sealed class Local : LocalBase -{ -} +public sealed class Local : LocalBase { } -public sealed class LocalReadOnly : LocalReadOnlyBase -{ -} -#pragma warning restore STDB_UNSTABLE \ No newline at end of file +public sealed class LocalReadOnly : LocalReadOnlyBase { } +#pragma warning restore STDB_UNSTABLE diff --git a/crates/bindings-csharp/Runtime/Runtime.csproj b/crates/bindings-csharp/Runtime/Runtime.csproj index 3a8d576f39c..41eda180cd5 100644 --- a/crates/bindings-csharp/Runtime/Runtime.csproj +++ b/crates/bindings-csharp/Runtime/Runtime.csproj @@ -1,5 +1,4 @@ - SpacetimeDB.Runtime 1.11.0 @@ -19,7 +18,11 @@ - + @@ -31,12 +34,15 @@ - + - diff --git a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props index 58ccaa0de6e..eabfed55468 100644 --- a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props +++ b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.props @@ -1,5 +1,4 @@ - true full @@ -25,5 +24,4 @@ false - diff --git a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets index 780d6f19f43..1acb0d21c26 100644 --- a/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets +++ b/crates/bindings-csharp/Runtime/build/SpacetimeDB.Runtime.targets @@ -1,5 +1,4 @@ - @@ -24,8 +23,15 @@ - - + + @@ -45,8 +51,14 @@ $([System.IO.Path]::Combine($(IntermediateOutputPath), "wasi-sdk.$(WasiSdkVersion).tar.gz")) - x86_64 - arm64 + x86_64 + arm64 windows linux @@ -62,15 +74,22 @@ + SourceUrl="$(WasiSdkUrl)" + DestinationFolder="$(IntermediateOutputPath)" + DestinationFileName="$([System.IO.Path]::GetFileName('$(WasiSdkDownloadTempFile)'))" + Condition="!Exists('$(WasiClang)')" + /> - + - + - diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs index bd5fbca25c0..474a125ffe4 100644 --- a/sdks/csharp/examples~/regression-tests/server/Lib.cs +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -173,7 +173,7 @@ public static SpacetimeDB.Unit WillPanic(ProcedureContext ctx) { throw new InvalidOperationException("This procedure is expected to panic"); } - + #pragma warning disable STDB_UNSTABLE [SpacetimeDB.Procedure] public static void InsertWithTxCommit(ProcedureContext ctx) @@ -211,7 +211,7 @@ private static void AssertRowCount(ProcedureContext ctx, ulong expected) { ctx.WithTx(tx => { - ulong actual = tx.Db.my_table.Count; + var actual = tx.Db.my_table.Count; if (actual != expected) { throw new InvalidOperationException( From 14d310bb2a9e6a64571dabb8e4b343f86b21ac0a Mon Sep 17 00:00:00 2001 From: rekhoff Date: Thu, 4 Dec 2025 09:23:44 -0800 Subject: [PATCH 4/5] More lint updates --- crates/bindings-csharp/BSATN.Codegen/Diag.cs | 99 ++--- crates/bindings-csharp/BSATN.Codegen/Type.cs | 4 +- .../BSATN.Runtime.Tests/Tests.cs | 60 ++- .../BSATN.Runtime/BSATN/AlgebraicType.cs | 12 +- .../BSATN.Runtime/BSATN/Runtime.cs | 5 +- .../bindings-csharp/BSATN.Runtime/Builtins.cs | 48 +-- crates/bindings-csharp/Codegen/Diag.cs | 343 +++++++++--------- crates/bindings-csharp/Codegen/Module.cs | 20 +- .../Runtime/Internal/ITable.cs | 16 +- .../Runtime/Internal/TxContext.cs | 38 +- .../Runtime/ProcedureContext.cs | 91 ++--- modules/benchmarks-cs/circles.cs | 9 +- modules/benchmarks-cs/ia_loop.cs | 15 +- modules/benchmarks-cs/lib.cs | 3 +- modules/benchmarks-cs/synthetic.cs | 7 +- modules/module-test-cs/Lib.cs | 4 +- modules/sdk-test-connect-disconnect-cs/Lib.cs | 4 +- modules/sdk-test-cs/Lib.cs | 4 +- .../regression-tests/client/Program.cs | 117 ++++-- 19 files changed, 455 insertions(+), 444 deletions(-) diff --git a/crates/bindings-csharp/BSATN.Codegen/Diag.cs b/crates/bindings-csharp/BSATN.Codegen/Diag.cs index 53d0d7f2432..2ae3b2513ba 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Diag.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Diag.cs @@ -134,55 +134,61 @@ internal static class ErrorDescriptor ISymbol member, ITypeSymbol type, Exception e - )> UnsupportedType = new( - group, - "Unsupported type", - ctx => $"BSATN implementation for {ctx.type} is not found: {ctx.e.Message}", - ctx => ctx.member - ); + )> UnsupportedType = + new( + group, + "Unsupported type", + ctx => $"BSATN implementation for {ctx.type} is not found: {ctx.e.Message}", + ctx => ctx.member + ); public static readonly ErrorDescriptor<( EqualsValueClauseSyntax equalsValue, EnumMemberDeclarationSyntax enumMember, EnumDeclarationSyntax @enum - )> EnumWithExplicitValues = new( - group, - "[SpacetimeDB.Type] enums cannot have explicit values", - ctx => - $"{ctx.@enum.Identifier}.{ctx.enumMember.Identifier} has an explicit value {ctx.equalsValue.Value} which is not allowed in SpacetimeDB enums.", - ctx => ctx.equalsValue - ); + )> EnumWithExplicitValues = + new( + group, + "[SpacetimeDB.Type] enums cannot have explicit values", + ctx => + $"{ctx.@enum.Identifier}.{ctx.enumMember.Identifier} has an explicit value {ctx.equalsValue.Value} which is not allowed in SpacetimeDB enums.", + ctx => ctx.equalsValue + ); - public static readonly ErrorDescriptor EnumTooManyVariants = new( - group, - "[SpacetimeDB.Type] enums are limited to 256 variants", - @enum => - $"{@enum.Identifier} has {@enum.Members.Count} variants which is more than the allowed 256 variants for SpacetimeDB enums.", - @enum => @enum.Members[256] - ); + public static readonly ErrorDescriptor EnumTooManyVariants = + new( + group, + "[SpacetimeDB.Type] enums are limited to 256 variants", + @enum => + $"{@enum.Identifier} has {@enum.Members.Count} variants which is more than the allowed 256 variants for SpacetimeDB enums.", + @enum => @enum.Members[256] + ); - public static readonly ErrorDescriptor TaggedEnumInlineTuple = new( - group, - "Tagged enum variants must be declared with inline tuples", - baseType => - $"{baseType} does not have the expected format SpacetimeDB.TaggedEnum<(TVariant1 v1, ..., TVariantN vN)>.", - baseType => baseType - ); + public static readonly ErrorDescriptor TaggedEnumInlineTuple = + new( + group, + "Tagged enum variants must be declared with inline tuples", + baseType => + $"{baseType} does not have the expected format SpacetimeDB.TaggedEnum<(TVariant1 v1, ..., TVariantN vN)>.", + baseType => baseType + ); - public static readonly ErrorDescriptor TaggedEnumField = new( - group, - "Tagged enums cannot have instance fields", - field => - $"{field.Name} is an instance field, which are not permitted inside SpacetimeDB tagged enums.", - field => field - ); + public static readonly ErrorDescriptor TaggedEnumField = + new( + group, + "Tagged enums cannot have instance fields", + field => + $"{field.Name} is an instance field, which are not permitted inside SpacetimeDB tagged enums.", + field => field + ); - public static readonly ErrorDescriptor TypeParams = new( - group, - "Type parameters are not yet supported", - typeParams => $"Type parameters {typeParams} are not supported in SpacetimeDB types.", - typeParams => typeParams - ); + public static readonly ErrorDescriptor TypeParams = + new( + group, + "Type parameters are not yet supported", + typeParams => $"Type parameters {typeParams} are not supported in SpacetimeDB types.", + typeParams => typeParams + ); } // This class is used to collect diagnostics during parsing and return them as a combined result. @@ -208,12 +214,13 @@ public void Report(ErrorDescriptor descriptor, TContext ctx) private DiagReporter() { } - private static readonly ErrorDescriptor<(Location location, Exception e)> InternalError = new( - new("STDBINT", "SpacetimeDB.Internal"), - "Internal SpacetimeDB codegen error", - ctx => $"An internal error occurred during codegen: {ctx.e.Message}", - ctx => ctx.location - ); + private static readonly ErrorDescriptor<(Location location, Exception e)> InternalError = + new( + new("STDBINT", "SpacetimeDB.Internal"), + "Internal SpacetimeDB codegen error", + ctx => $"An internal error occurred during codegen: {ctx.e.Message}", + ctx => ctx.location + ); public static ParseResult With(Location location, Func build) where T : IEquatable diff --git a/crates/bindings-csharp/BSATN.Codegen/Type.cs b/crates/bindings-csharp/BSATN.Codegen/Type.cs index 9d8ad56f26f..56c4af41f07 100644 --- a/crates/bindings-csharp/BSATN.Codegen/Type.cs +++ b/crates/bindings-csharp/BSATN.Codegen/Type.cs @@ -516,7 +516,7 @@ public sealed record {{m.Name}}({{m.Type.Name}} {{m.Name}}_) : {{ShortName}} public override string ToString() => $"{{m.Name}}({ SpacetimeDB.BSATN.StringUtil.GenericToString({{m.Name}}_) })"; } - + """ ) ) @@ -659,7 +659,7 @@ public override int GetHashCode() { {{getHashCode}} } - + """ ); diff --git a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs index bee26979774..c3e26ddb09b 100644 --- a/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs +++ b/crates/bindings-csharp/BSATN.Runtime.Tests/Tests.cs @@ -137,8 +137,8 @@ public static void IdentityLengthCheck() public static void NonHexStrings() { // n.b. 32 chars long - Assert.ThrowsAny(() => - ConnectionId.FromHexString("these are not hex characters....") + Assert.ThrowsAny( + () => ConnectionId.FromHexString("these are not hex characters....") ); } @@ -246,20 +246,12 @@ public BasicDataClass((int x, string y, int? z, string? w) data) } [Type] - public partial struct BasicDataStruct + public partial struct BasicDataStruct((int x, string y, int? z, string? w) data) { - public int X; - public string Y; - public int? Z; - public string? W; - - public BasicDataStruct((int x, string y, int? z, string? w) data) - { - X = data.x; - Y = data.y; - Z = data.z; - W = data.w; - } + public int X = data.x; + public string Y = data.y; + public int? Z = data.z; + public string? W = data.w; } [Type] @@ -315,12 +307,12 @@ public void Add(bool collides) } } - public double CollisionFraction + public readonly double CollisionFraction { get => (double)Collisions / (double)Comparisons; } - public void AssertCollisionsLessThan(double fraction) + public readonly void AssertCollisionsLessThan(double fraction) { Assert.True( CollisionFraction < fraction, @@ -629,14 +621,10 @@ public static void GeneratedNestedListRoundTrip() static readonly Gen<(ContainsNestedList e1, ContainsNestedList e2)> GenTwoContainsNestedList = Gen.Select(GenContainsNestedList, GenContainsNestedList, (e1, e2) => (e1, e2)); - class EnumerableEqualityComparer : EqualityComparer> + class EnumerableEqualityComparer(EqualityComparer equalityComparer) + : EqualityComparer> { - private readonly EqualityComparer EqualityComparer; - - public EnumerableEqualityComparer(EqualityComparer equalityComparer) - { - EqualityComparer = equalityComparer; - } + private readonly EqualityComparer EqualityComparer = equalityComparer; public override bool Equals(IEnumerable? x, IEnumerable? y) => x == null ? y == null : (y == null ? false : x.SequenceEqual(y, EqualityComparer)); @@ -796,22 +784,26 @@ public static void GeneratedToString() ); Assert.Equal( "ContainsList { TheList = [ X(1), Y(\"hi\"), W(BasicDataRecord { X = 1, Y = \"hi\", Z = null, W = null }) ] }", - new ContainsList([ - new BasicEnum.X(1), - new BasicEnum.Y("hi"), - new BasicEnum.W(new BasicDataRecord((1, "hi", null, null))), - ]).ToString() + new ContainsList( + [ + new BasicEnum.X(1), + new BasicEnum.Y("hi"), + new BasicEnum.W(new BasicDataRecord((1, "hi", null, null))), + ] + ).ToString() ); #pragma warning disable CS8625 // Cannot convert null literal to non-nullable reference type. Assert.Equal( "ContainsNestedList { TheList = [ [ [ X(1), null ], null ], null ] }", - new ContainsNestedList([ + new ContainsNestedList( [ - [new BasicEnum.X(1), null], + [ + [new BasicEnum.X(1), null], + null, + ], null, - ], - null, - ]).ToString() + ] + ).ToString() ); #pragma warning restore CS8625 // Cannot convert null literal to non-nullable reference type. } diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs index 603feae5c78..602afa7af5f 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/AlgebraicType.cs @@ -6,17 +6,11 @@ public interface ITypeRegistrar } [SpacetimeDB.Type] -public partial struct AggregateElement +public partial struct AggregateElement(string name, AlgebraicType algebraicType) { - public string? Name; + public string? Name = name; - public AlgebraicType AlgebraicType; - - public AggregateElement(string name, AlgebraicType algebraicType) - { - Name = name; - AlgebraicType = algebraicType; - } + public AlgebraicType AlgebraicType = algebraicType; } [SpacetimeDB.Type] diff --git a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs index bde8ac8bbd7..9a7a617a2ab 100644 --- a/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs +++ b/crates/bindings-csharp/BSATN.Runtime/BSATN/Runtime.cs @@ -577,9 +577,8 @@ public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // reduce amount of noisy compilation errors when a used type is not supported by BSATN. public readonly struct Unsupported : IReadWrite { - private static readonly NotSupportedException Exception = new( - $"Type {typeof(T)} is not supported by BSATN." - ); + private static readonly NotSupportedException Exception = + new($"Type {typeof(T)} is not supported by BSATN."); public T Read(BinaryReader reader) => throw Exception; diff --git a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs index d2ba774bd1c..8a8aa783a5c 100644 --- a/crates/bindings-csharp/BSATN.Runtime/Builtins.cs +++ b/crates/bindings-csharp/BSATN.Runtime/Builtins.cs @@ -191,10 +191,12 @@ public void Write(BinaryWriter writer, ConnectionId value) => // --- customized --- public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. - new AlgebraicType.Product([ - // Using this specific name here is important. - new("__connection_id__", new AlgebraicType.U128(default)), - ]); + new AlgebraicType.Product( + [ + // Using this specific name here is important. + new("__connection_id__", new AlgebraicType.U128(default)), + ] + ); // --- / customized --- } @@ -281,10 +283,12 @@ public void Write(BinaryWriter writer, Identity value) => // --- customized --- public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. - new AlgebraicType.Product([ - // Using this specific name here is important. - new("__identity__", new AlgebraicType.U256(default)), - ]); + new AlgebraicType.Product( + [ + // Using this specific name here is important. + new("__identity__", new AlgebraicType.U256(default)), + ] + ); // --- / customized --- } @@ -361,7 +365,7 @@ public readonly TimeDuration TimeDurationSince(Timestamp earlier) => public static Timestamp operator -(Timestamp point, TimeDuration interval) => new Timestamp(checked(point.MicrosecondsSinceUnixEpoch - interval.Microseconds)); - public int CompareTo(Timestamp that) + public readonly int CompareTo(Timestamp that) { return this.MicrosecondsSinceUnixEpoch.CompareTo(that.MicrosecondsSinceUnixEpoch); } @@ -410,10 +414,9 @@ public void Write(BinaryWriter writer, Timestamp value) public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. new AlgebraicType.Product( - // Using this specific name here is important. - [ - new("__timestamp_micros_since_unix_epoch__", new AlgebraicType.I64(default)), - ]); + // Using this specific name here is important. + [new("__timestamp_micros_since_unix_epoch__", new AlgebraicType.I64(default))] + ); // --- / customized --- } } @@ -513,10 +516,9 @@ public void Write(BinaryWriter writer, TimeDuration value) public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Product directly, not a Ref, because this is a special type. new AlgebraicType.Product( - // Using this specific name here is important. - [ - new("__time_duration_micros__", new AlgebraicType.I64(default)), - ]); + // Using this specific name here is important. + [new("__time_duration_micros__", new AlgebraicType.I64(default))] + ); // --- / customized --- } } @@ -593,11 +595,13 @@ public void Write(BinaryWriter writer, ScheduleAt value) // --- customized --- public AlgebraicType GetAlgebraicType(ITypeRegistrar registrar) => // Return a Sum directly, not a Ref, because this is a special type. - new AlgebraicType.Sum([ - // Using these specific names here is important. - new("Interval", Interval.GetAlgebraicType(registrar)), - new("Time", Time.GetAlgebraicType(registrar)), - ]); + new AlgebraicType.Sum( + [ + // Using these specific names here is important. + new("Interval", Interval.GetAlgebraicType(registrar)), + new("Time", Time.GetAlgebraicType(registrar)), + ] + ); // --- / customized --- } } diff --git a/crates/bindings-csharp/Codegen/Diag.cs b/crates/bindings-csharp/Codegen/Diag.cs index e96a4b4e25d..6b87a4028b0 100644 --- a/crates/bindings-csharp/Codegen/Diag.cs +++ b/crates/bindings-csharp/Codegen/Diag.cs @@ -7,149 +7,161 @@ internal static class ErrorDescriptor { private static readonly ErrorDescriptorGroup group = new("STDB", "SpacetimeDB"); - public static readonly ErrorDescriptor ReducerReturnType = new( - group, - "[SpacetimeDB.Reducer] methods must return void", - method => - $"Reducer method {method.Identifier} returns {method.ReturnType} instead of void.", - method => method.ReturnType - ); - - public static readonly ErrorDescriptor AutoIncNotInteger = new( - group, - "AutoInc fields must be of integer type", - field => - $"Field {field.Name} is marked as AutoInc but it has a non-integer type {field.Type}.", - field => field - ); - - public static readonly ErrorDescriptor UniqueNotEquatable = new( - group, - "Unique fields must be equatable", - field => - $"Field {field.Name} is marked as Unique but it has a type {field.Type} which is not an equatable primitive.", - field => field - ); - - public static readonly ErrorDescriptor EmptyIndexColumns = new( - group, - "Index attribute must specify Columns", - _ => $"Index attribute doesn't specify columns.", - attr => attr - ); - - public static readonly ErrorDescriptor InvalidTableVisibility = new( - group, - "Table row visibility must be public or internal", - table => $"Table {table.Identifier} and its parent types must be public or internal.", - table => table.Identifier - ); - - public static readonly ErrorDescriptor TableTaggedEnum = new( - group, - "Tables cannot be tagged enums", - table => $"Table {table.Identifier} is a tagged enum, which is not allowed.", - table => table.BaseList! - ); + public static readonly ErrorDescriptor ReducerReturnType = + new( + group, + "[SpacetimeDB.Reducer] methods must return void", + method => + $"Reducer method {method.Identifier} returns {method.ReturnType} instead of void.", + method => method.ReturnType + ); + + public static readonly ErrorDescriptor AutoIncNotInteger = + new( + group, + "AutoInc fields must be of integer type", + field => + $"Field {field.Name} is marked as AutoInc but it has a non-integer type {field.Type}.", + field => field + ); + + public static readonly ErrorDescriptor UniqueNotEquatable = + new( + group, + "Unique fields must be equatable", + field => + $"Field {field.Name} is marked as Unique but it has a type {field.Type} which is not an equatable primitive.", + field => field + ); + + public static readonly ErrorDescriptor EmptyIndexColumns = + new( + group, + "Index attribute must specify Columns", + _ => $"Index attribute doesn't specify columns.", + attr => attr + ); + + public static readonly ErrorDescriptor InvalidTableVisibility = + new( + group, + "Table row visibility must be public or internal", + table => $"Table {table.Identifier} and its parent types must be public or internal.", + table => table.Identifier + ); + + public static readonly ErrorDescriptor TableTaggedEnum = + new( + group, + "Tables cannot be tagged enums", + table => $"Table {table.Identifier} is a tagged enum, which is not allowed.", + table => table.BaseList! + ); public static readonly ErrorDescriptor<( string kind, string exportName, IEnumerable fullNames - )> DuplicateExport = new( - group, - "Duplicate exports", - ctx => - $"{ctx.kind} with the same export name {ctx.exportName} is registered in multiple places: {string.Join(", ", ctx.fullNames)}", - ctx => Location.None - ); - - public static readonly ErrorDescriptor ReducerContextParam = new( - group, - "Reducers must have a first argument of type ReducerContext", - method => $"Reducer method {method.Identifier} does not have a ReducerContext parameter.", - method => method.ParameterList - ); - - public static readonly ErrorDescriptor ProcedureContextParam = new( - group, - "Procedures must have a first argument of type ProcedureContext", - method => - $"Procedure method {method.Identifier} does not have a ProcedureContext parameter.", - method => method.ParameterList - ); + )> DuplicateExport = + new( + group, + "Duplicate exports", + ctx => + $"{ctx.kind} with the same export name {ctx.exportName} is registered in multiple places: {string.Join(", ", ctx.fullNames)}", + ctx => Location.None + ); + + public static readonly ErrorDescriptor ReducerContextParam = + new( + group, + "Reducers must have a first argument of type ReducerContext", + method => + $"Reducer method {method.Identifier} does not have a ReducerContext parameter.", + method => method.ParameterList + ); + + public static readonly ErrorDescriptor ProcedureContextParam = + new( + group, + "Procedures must have a first argument of type ProcedureContext", + method => + $"Procedure method {method.Identifier} does not have a ProcedureContext parameter.", + method => method.ParameterList + ); public static readonly ErrorDescriptor<( MethodDeclarationSyntax method, string prefix - )> ReducerReservedPrefix = new( - group, - "Reducer method has a reserved name prefix", - ctx => - $"Reducer method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", - ctx => ctx.method.Identifier - ); + )> ReducerReservedPrefix = + new( + group, + "Reducer method has a reserved name prefix", + ctx => + $"Reducer method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", + ctx => ctx.method.Identifier + ); public static readonly ErrorDescriptor<( MethodDeclarationSyntax method, string prefix - )> ProcedureReservedPrefix = new( - group, - "Procedure method has a reserved name prefix", - ctx => - $"Procedure method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", - ctx => ctx.method.Identifier - ); + )> ProcedureReservedPrefix = + new( + group, + "Procedure method has a reserved name prefix", + ctx => + $"Procedure method {ctx.method.Identifier} starts with '{ctx.prefix}', which is a reserved prefix.", + ctx => ctx.method.Identifier + ); public static readonly UnusedErrorDescriptor IncompatibleTableSchedule = new(group); public static readonly ErrorDescriptor<( ReducerKind kind, IEnumerable fullNames - )> DuplicateSpecialReducer = new( - group, - "Multiple reducers of the same kind", - ctx => - $"Several reducers are assigned to the same lifecycle kind {ctx.kind}: {string.Join(", ", ctx.fullNames)}", - ctx => Location.None - ); + )> DuplicateSpecialReducer = + new( + group, + "Multiple reducers of the same kind", + ctx => + $"Several reducers are assigned to the same lifecycle kind {ctx.kind}: {string.Join(", ", ctx.fullNames)}", + ctx => Location.None + ); public static readonly ErrorDescriptor<( AttributeData attr, string message - )> InvalidScheduledDeclaration = new( - group, - "Invalid scheduled table declaration", - ctx => $"{ctx.message}", - ctx => ctx.attr - ); - - public static readonly ErrorDescriptor UnexpectedIndexColumns = new( - group, - "Index attribute on a field must not specify Columns", - _ => - $"Index attribute on a field applies directly to that field, so it doesn't accept the Columns parameter.", - attr => attr - ); + )> InvalidScheduledDeclaration = + new(group, "Invalid scheduled table declaration", ctx => $"{ctx.message}", ctx => ctx.attr); + + public static readonly ErrorDescriptor UnexpectedIndexColumns = + new( + group, + "Index attribute on a field must not specify Columns", + _ => + $"Index attribute on a field applies directly to that field, so it doesn't accept the Columns parameter.", + attr => attr + ); public static readonly ErrorDescriptor<( AttributeData attr, string columnName, string typeName - )> UnknownColumn = new( - group, - "Unknown column", - ctx => $"Could not find the specified column {ctx.columnName} in {ctx.typeName}.", - ctx => ctx.attr - ); - - public static readonly ErrorDescriptor ClientVisibilityNotFilter = new( - group, - "ClientVisibilityFilters must be Filters", - field => - $"Field {field.Name} is marked as ClientVisibilityFilter but it has type {field.Type} which is not SpacetimeDB.Filter", - field => field - ); + )> UnknownColumn = + new( + group, + "Unknown column", + ctx => $"Could not find the specified column {ctx.columnName} in {ctx.typeName}.", + ctx => ctx.attr + ); + + public static readonly ErrorDescriptor ClientVisibilityNotFilter = + new( + group, + "ClientVisibilityFilters must be Filters", + field => + $"Field {field.Name} is marked as ClientVisibilityFilter but it has type {field.Type} which is not SpacetimeDB.Filter", + field => field + ); public static readonly ErrorDescriptor ClientVisibilityNotPublicStaticReadonly = new( @@ -169,55 +181,62 @@ string typeName field => field ); - public static readonly ErrorDescriptor InvalidDefaultValueType = new( - group, - "Invalid Default Value Type", - field => $"Default value for field {field.Name} cannot be converted to provided type", - field => field - ); - - public static readonly ErrorDescriptor InvalidDefaultValueFormat = new( - group, - "Invalid Default Value Format", - field => $"Default value for field {field.Name} has invalid format for provided type ", - field => field - ); - public static readonly ErrorDescriptor ViewContextParam = new( - group, - "Views must start with ViewContext or AnonymousViewContext", - method => - $"View method {method.Identifier} must have a first parameter of type ViewContext or AnonymousViewContext.", - method => method.ParameterList - ); - - public static readonly ErrorDescriptor ViewMustHaveName = new( - group, - "Views must have an explicit name.", - method => $"View '{method.Identifier}' must have an explicit name.", - method => method - ); - public static readonly ErrorDescriptor ViewInvalidReturn = new( - group, - "Views must return Vec or Option", - method => $"View '{method.Identifier}' must return Vec or Option.", - method => method - ); + public static readonly ErrorDescriptor InvalidDefaultValueType = + new( + group, + "Invalid Default Value Type", + field => $"Default value for field {field.Name} cannot be converted to provided type", + field => field + ); + + public static readonly ErrorDescriptor InvalidDefaultValueFormat = + new( + group, + "Invalid Default Value Format", + field => $"Default value for field {field.Name} has invalid format for provided type ", + field => field + ); + public static readonly ErrorDescriptor ViewContextParam = + new( + group, + "Views must start with ViewContext or AnonymousViewContext", + method => + $"View method {method.Identifier} must have a first parameter of type ViewContext or AnonymousViewContext.", + method => method.ParameterList + ); + + public static readonly ErrorDescriptor ViewMustHaveName = + new( + group, + "Views must have an explicit name.", + method => $"View '{method.Identifier}' must have an explicit name.", + method => method + ); + public static readonly ErrorDescriptor ViewInvalidReturn = + new( + group, + "Views must return Vec or Option", + method => $"View '{method.Identifier}' must return Vec or Option.", + method => method + ); // TODO: Remove once Views support Private: Views must be Public currently - public static readonly ErrorDescriptor ViewMustBePublic = new( - group, - "Views must be public", - method => - $"View '{method.Identifier}' must have Public = true. Views are always public in SpacetimeDB.", - method => method - ); + public static readonly ErrorDescriptor ViewMustBePublic = + new( + group, + "Views must be public", + method => + $"View '{method.Identifier}' must have Public = true. Views are always public in SpacetimeDB.", + method => method + ); // TODO: Remove once Views support arguments: Views must have no arguments beyond the context. - public static readonly ErrorDescriptor ViewArgsUnsupported = new( - group, - "Views must have no arguments beyond the context.", - method => - $"View '{method.Identifier}' must have no arguments beyond the context. This is a temporary limitation.", - method => method - ); + public static readonly ErrorDescriptor ViewArgsUnsupported = + new( + group, + "Views must have no arguments beyond the context.", + method => + $"View '{method.Identifier}' must have no arguments beyond the context. This is a temporary limitation.", + method => method + ); } diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index 03dea0e4c93..b10817e0aab 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -557,7 +557,7 @@ public ulong Delete({{argsScalar}}) => public ulong Delete({{argsBounds}}) => DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds<{{types}}>({{argName}})); - + """; } @@ -1798,7 +1798,7 @@ namespace SpacetimeDB.Internal.TableHandles { {{string.Join("\n", tableAccessors.Select(v => v.tableAccessor))}} } - {{string.Join("\n", + {{string.Join("\n", views.Array.Where(v => !v.IsAnonymous) .Select((v, i) => v.GenerateDispatcherClass((uint)i)) .Concat( @@ -1851,7 +1851,7 @@ public static void Main() { // IMPORTANT: The order in which we register views matters. // It must correspond to the order in which we call `GenerateDispatcherClass`. // See the comment on `GenerateDispatcherClass` for more explanation. - {{string.Join("\n", + {{string.Join("\n", views.Array.Where(v => !v.IsAnonymous) .Select(v => $"SpacetimeDB.Internal.Module.RegisterView<{v.Name}ViewDispatcher>();") .Concat( @@ -1870,14 +1870,14 @@ public static void Main() { )}} {{string.Join( "\n", - columnDefaultValues.Select(d => + columnDefaultValues.Select(d => "{\n" - +$"var value = new {d.BSATNTypeName}();\n" - +"__memoryStream.Position = 0;\n" - +"__memoryStream.SetLength(0);\n" - +$"value.Write(__writer, {d.value});\n" - +"var array = __memoryStream.ToArray();\n" - +$"SpacetimeDB.Internal.Module.RegisterTableDefaultValue(\"{d.tableName}\", {d.columnId}, array);" + + $"var value = new {d.BSATNTypeName}();\n" + + "__memoryStream.Position = 0;\n" + + "__memoryStream.SetLength(0);\n" + + $"value.Write(__writer, {d.value});\n" + + "var array = __memoryStream.ToArray();\n" + + $"SpacetimeDB.Internal.Module.RegisterTableDefaultValue(\"{d.tableName}\", {d.columnId}, array);" + "\n}\n") )}} } diff --git a/crates/bindings-csharp/Runtime/Internal/ITable.cs b/crates/bindings-csharp/Runtime/Internal/ITable.cs index 146358b4243..575c3a9fc10 100644 --- a/crates/bindings-csharp/Runtime/Internal/ITable.cs +++ b/crates/bindings-csharp/Runtime/Internal/ITable.cs @@ -34,7 +34,8 @@ public bool MoveNext() // Iterator advanced and may also be `EXHAUSTED`. // When `OK`, we'll need to advance the iterator in the next call to `MoveNext`. // In both cases, copy over the row data to `Current` from the scratch `buffer`. - case Errno.EXHAUSTED or Errno.OK: + case Errno.EXHAUSTED + or Errno.OK: Current = new byte[buffer_len]; Array.Copy(buffer, 0, Current, 0, buffer_len); return buffer_len != 0; @@ -111,12 +112,13 @@ protected override void IterStart(out FFI.RowIter handle) => private static readonly string tableName = typeof(View).Name; // Note: this must be Lazy to ensure that we don't try to get the tableId during startup, before the module is initialized. - private static readonly Lazy tableId_ = new(() => - { - var name_bytes = System.Text.Encoding.UTF8.GetBytes(tableName); - FFI.table_id_from_name(name_bytes, (uint)name_bytes.Length, out var out_); - return out_; - }); + private static readonly Lazy tableId_ = + new(() => + { + var name_bytes = System.Text.Encoding.UTF8.GetBytes(tableName); + FFI.table_id_from_name(name_bytes, (uint)name_bytes.Length, out var out_); + return out_; + }); internal static FFI.TableId tableId => tableId_.Value; diff --git a/crates/bindings-csharp/Runtime/Internal/TxContext.cs b/crates/bindings-csharp/Runtime/Internal/TxContext.cs index 25bf7674edd..d5bea2febd9 100644 --- a/crates/bindings-csharp/Runtime/Internal/TxContext.cs +++ b/crates/bindings-csharp/Runtime/Internal/TxContext.cs @@ -1,30 +1,20 @@ namespace SpacetimeDB.Internal; -public sealed class TxContext +public sealed class TxContext( + Local db, + Identity sender, + ConnectionId? connectionId, + Timestamp timestamp, + AuthCtx senderAuth, + Random rng +) { - public TxContext( - Local db, - Identity sender, - ConnectionId? connectionId, - Timestamp timestamp, - AuthCtx senderAuth, - Random rng - ) - { - Db = db; - Sender = sender; - ConnectionId = connectionId; - Timestamp = timestamp; - SenderAuth = senderAuth; - Rng = rng; - } - - public Local Db { get; } - public Identity Sender { get; } - public ConnectionId? ConnectionId { get; } - public Timestamp Timestamp { get; } - public AuthCtx SenderAuth { get; } - public Random Rng { get; } + public Local Db { get; } = db; + public Identity Sender { get; } = sender; + public ConnectionId? ConnectionId { get; } = connectionId; + public Timestamp Timestamp { get; } = timestamp; + public AuthCtx SenderAuth { get; } = senderAuth; + public Random Rng { get; } = rng; public TxContext WithTimestamp(Timestamp ts) => new(Db, Sender, ConnectionId, ts, SenderAuth, Rng); diff --git a/crates/bindings-csharp/Runtime/ProcedureContext.cs b/crates/bindings-csharp/Runtime/ProcedureContext.cs index 11fe27743b2..8c78a427f35 100644 --- a/crates/bindings-csharp/Runtime/ProcedureContext.cs +++ b/crates/bindings-csharp/Runtime/ProcedureContext.cs @@ -3,28 +3,19 @@ namespace SpacetimeDB; using System.Diagnostics.CodeAnalysis; #pragma warning disable STDB_UNSTABLE -public abstract class ProcedureContextBase : Internal.IInternalProcedureContext +public abstract class ProcedureContextBase( + Identity sender, + ConnectionId? connectionId, + Random random, + Timestamp time +) : Internal.IInternalProcedureContext { - protected ProcedureContextBase( - Identity sender, - ConnectionId? connectionId, - Random random, - Timestamp time - ) - { - Sender = sender; - ConnectionId = connectionId; - Rng = random; - Timestamp = time; - SenderAuth = AuthCtx.BuildFromSystemTables(connectionId, sender); - } - public Identity Identity => Internal.IProcedureContext.GetIdentity(); - public Identity Sender { get; } - public ConnectionId? ConnectionId { get; } - public Random Rng { get; } - public Timestamp Timestamp { get; private set; } - public AuthCtx SenderAuth { get; } + public Identity Sender { get; } = sender; + public ConnectionId? ConnectionId { get; } = connectionId; + public Random Rng { get; } = random; + public Timestamp Timestamp { get; private set; } = time; + public AuthCtx SenderAuth { get; } = AuthCtx.BuildFromSystemTables(connectionId, sender); private Internal.TransactionOffset? pendingTxOffset; private Internal.TxContext? txContext; @@ -77,18 +68,11 @@ public bool TryTakeTransactionOffset(out Internal.TransactionOffset offset) return false; } - public readonly struct TxOutcome + public readonly struct TxOutcome(bool isSuccess, TResult? value, Exception? error) { - public TxOutcome(bool isSuccess, TResult? value, Exception? error) - { - IsSuccess = isSuccess; - Value = value; - Error = error; - } - - public bool IsSuccess { get; } - public TResult? Value { get; } - public Exception? Error { get; } + public bool IsSuccess { get; } = isSuccess; + public TResult? Value { get; } = value; + public Exception? Error { get; } = error; public static TxOutcome Success(TResult value) => new(true, value, null); @@ -106,19 +90,12 @@ public TResult UnwrapOrThrow(Func fallbackFactory) => IsSuccess ? Value! : throw (Error ?? fallbackFactory()); } - public readonly struct TxResult + public readonly struct TxResult(bool isSuccess, TResult? value, TError? error) where TError : Exception { - public TxResult(bool isSuccess, TResult? value, TError? error) - { - IsSuccess = isSuccess; - Value = value; - Error = error; - } - - public bool IsSuccess { get; } - public TResult? Value { get; } - public TError? Error { get; } + public bool IsSuccess { get; } = isSuccess; + public TResult? Value { get; } = value; + public TError? Error { get; } = error; public static TxResult Success(TResult value) => new(true, value, null); @@ -214,13 +191,11 @@ Func> body return result; } - private sealed class AbortGuard : IDisposable + private sealed class AbortGuard(Action abort) : IDisposable { - private readonly Action abort; + private readonly Action abort = abort; private bool disarmed; - public AbortGuard(Action abort) => this.abort = abort; - public void Disarm() => disarmed = true; public void Dispose() @@ -233,14 +208,9 @@ public void Dispose() } } -public abstract class ProcedureTxContextBase +public abstract class ProcedureTxContextBase(Internal.TxContext inner) { - protected ProcedureTxContextBase(Internal.TxContext inner) - { - Inner = inner; - } - - internal Internal.TxContext Inner { get; private set; } + internal Internal.TxContext Inner { get; private set; } = inner; internal void Refresh(Internal.TxContext inner) => Inner = inner; @@ -256,18 +226,15 @@ public abstract class LocalBase : Internal.Local { } public abstract class LocalReadOnlyBase : Internal.LocalReadOnly { } -public sealed class ProcedureContext : ProcedureContextBase +public sealed class ProcedureContext( + Identity sender, + ConnectionId? connectionId, + Random random, + Timestamp timestamp +) : ProcedureContextBase(sender, connectionId, random, timestamp) { private readonly Local _db = new(); - public ProcedureContext( - Identity sender, - ConnectionId? connectionId, - Random random, - Timestamp timestamp - ) - : base(sender, connectionId, random, timestamp) { } - protected internal override LocalBase CreateLocal() => _db; protected override ProcedureTxContextBase CreateTxContext(Internal.TxContext inner) => diff --git a/modules/benchmarks-cs/circles.cs b/modules/benchmarks-cs/circles.cs index d369427e551..e818f166511 100644 --- a/modules/benchmarks-cs/circles.cs +++ b/modules/benchmarks-cs/circles.cs @@ -1,6 +1,5 @@ -using SpacetimeDB; - namespace Benchmarks; +using SpacetimeDB; public static partial class circles { @@ -48,9 +47,9 @@ public static float MassToRadius(uint mass) public static bool IsOverlapping(Entity entity1, Entity entity2) { - float entity1_radius = MassToRadius(entity1.mass); - float entity2_radius = MassToRadius(entity2.mass); - float distance = (float) + var entity1_radius = MassToRadius(entity1.mass); + var entity2_radius = MassToRadius(entity2.mass); + var distance = (float) Math.Sqrt( Math.Pow(entity1.position.x - entity2.position.x, 2) + Math.Pow(entity1.position.y - entity2.position.y, 2) diff --git a/modules/benchmarks-cs/ia_loop.cs b/modules/benchmarks-cs/ia_loop.cs index 8e8abe8c167..7a473e3f9fd 100644 --- a/modules/benchmarks-cs/ia_loop.cs +++ b/modules/benchmarks-cs/ia_loop.cs @@ -1,6 +1,5 @@ -using SpacetimeDB; - namespace Benchmarks; +using SpacetimeDB; public static partial class ia_loop { @@ -196,7 +195,7 @@ public static void insert_world(ReducerContext ctx, ulong players) { for (ulong i = 0; i < players; i++) { - ulong next_action_timestamp = + var next_action_timestamp = (i & 2) == 2 ? MomentMilliseconds() + 2000 : MomentMilliseconds(); ctx.Db.game_enemy_ai_agent_state.Insert( @@ -234,7 +233,7 @@ ulong num_players { List result = new(4); - for (ulong id = entity_id; id < num_players; id++) + for (var id = entity_id; id < num_players; id++) { foreach ( GameLiveTargetableState t in ctx.Db.game_live_targetable_state.quad.Filter((long)id) @@ -259,7 +258,7 @@ public static void MoveAgent( ulong current_time_ms ) { - ulong entity_id = agent.entity_id; + var entity_id = agent.entity_id; GameEnemyState enemy = ctx.Db.game_enemy_state.entity_id.Find(entity_id) @@ -277,7 +276,7 @@ ulong current_time_ms GameTargetableState targetable = ctx.Db.game_targetable_state.entity_id.Find(entity_id) ?? throw new Exception("GameTargetableState Entity ID not found"); - int new_hash = targetable.quad.GetHashCode(); + var new_hash = targetable.quad.GetHashCode(); targetable.quad = new_hash; ctx.Db.game_targetable_state.entity_id.Update(targetable); @@ -306,7 +305,7 @@ public static void AgentLoop( ulong current_time_ms ) { - ulong entity_id = agent.entity_id; + var entity_id = agent.entity_id; GameMobileEntityState? coordinates = ctx.Db.game_mobile_entity_state.entity_id.Find(entity_id) @@ -329,7 +328,7 @@ ulong current_time_ms public static void game_loop_enemy_ia(ReducerContext ctx, ulong players) { uint count = 0; - ulong current_time_ms = MomentMilliseconds(); + var current_time_ms = MomentMilliseconds(); foreach (GameEnemyAiAgentState agent in ctx.Db.game_enemy_ai_agent_state.Iter()) { diff --git a/modules/benchmarks-cs/lib.cs b/modules/benchmarks-cs/lib.cs index c72027d57cf..9b5784e4713 100644 --- a/modules/benchmarks-cs/lib.cs +++ b/modules/benchmarks-cs/lib.cs @@ -1,6 +1,5 @@ -using System.Runtime.CompilerServices; - namespace Benchmarks; +using System.Runtime.CompilerServices; public static class Bench { diff --git a/modules/benchmarks-cs/synthetic.cs b/modules/benchmarks-cs/synthetic.cs index cf888fd7a56..ae6ce6c64c5 100644 --- a/modules/benchmarks-cs/synthetic.cs +++ b/modules/benchmarks-cs/synthetic.cs @@ -1,6 +1,5 @@ -using SpacetimeDB; - namespace Benchmarks; +using SpacetimeDB; public static partial class synthetic { @@ -250,7 +249,7 @@ List people [SpacetimeDB.Reducer] public static void update_bulk_unique_0_u32_u64_u64(ReducerContext ctx, uint row_count) { - int hit = 0; + var hit = 0; foreach ( unique_0_u32_u64_u64_t loc in ctx.Db.unique_0_u32_u64_u64.Iter().Take((int)row_count) ) @@ -545,7 +544,7 @@ string _arg32 [SpacetimeDB.Reducer] public static void print_many_things(ReducerContext ctx, uint n) { - for (int i = 0; i < n; i++) + for (var i = 0; i < n; i++) { Log.Info("hello again!"); } diff --git a/modules/module-test-cs/Lib.cs b/modules/module-test-cs/Lib.cs index 1889f75bf2e..59227ed29fc 100644 --- a/modules/module-test-cs/Lib.cs +++ b/modules/module-test-cs/Lib.cs @@ -382,7 +382,7 @@ public static void add_player(ReducerContext ctx, string name) [Reducer] public static void delete_player(ReducerContext ctx, ulong id) { - bool deleted = ctx.Db.test_e.id.Delete(id); + var deleted = ctx.Db.test_e.id.Delete(id); if (!deleted) { throw new Exception($"No TestE row with id {id}"); @@ -429,7 +429,7 @@ public static void query_private(ReducerContext ctx) public static void test_btree_index_args(ReducerContext ctx) { // Testing various acceptable index filter argument types. - string s = "String"; + var s = "String"; var _1 = ctx.Db.test_e.name.Filter(s); var _2 = ctx.Db.test_e.name.Filter("str"); diff --git a/modules/sdk-test-connect-disconnect-cs/Lib.cs b/modules/sdk-test-connect-disconnect-cs/Lib.cs index 79af81d8cc4..40cc3532cb6 100644 --- a/modules/sdk-test-connect-disconnect-cs/Lib.cs +++ b/modules/sdk-test-connect-disconnect-cs/Lib.cs @@ -19,12 +19,12 @@ static partial class Module [SpacetimeDB.Reducer(ReducerKind.ClientConnected)] public static void identity_connected(ReducerContext ctx) { - ctx.Db.connected.Insert(new Connected { identity = ctx.Sender}); + ctx.Db.connected.Insert(new Connected { identity = ctx.Sender }); } [SpacetimeDB.Reducer(ReducerKind.ClientDisconnected)] public static void identity_disconnected(ReducerContext ctx) { - ctx.Db.disconnected.Insert(new Disconnected { identity = ctx.Sender}); + ctx.Db.disconnected.Insert(new Disconnected { identity = ctx.Sender }); } } diff --git a/modules/sdk-test-cs/Lib.cs b/modules/sdk-test-cs/Lib.cs index b17daa81ad4..84525e2b413 100644 --- a/modules/sdk-test-cs/Lib.cs +++ b/modules/sdk-test-cs/Lib.cs @@ -2010,9 +2010,9 @@ public partial struct ScheduledTable [SpacetimeDB.Reducer] public static void send_scheduled_message(ReducerContext ctx, ScheduledTable arg) { - ulong id = arg.scheduled_id; + var id = arg.scheduled_id; SpacetimeDB.ScheduleAt scheduleAt = arg.scheduled_at; - string text = arg.text; + var text = arg.text; } [SpacetimeDB.Table(Name = "indexed_table")] diff --git a/sdks/csharp/examples~/regression-tests/client/Program.cs b/sdks/csharp/examples~/regression-tests/client/Program.cs index 9b9f6d15b19..b530c1a4cd6 100644 --- a/sdks/csharp/examples~/regression-tests/client/Program.cs +++ b/sdks/csharp/examples~/regression-tests/client/Program.cs @@ -2,9 +2,11 @@ /// To run these, run a local SpacetimeDB via `spacetime start`, /// then in a separate terminal run `tools~/run-regression-tests.sh PATH_TO_SPACETIMEDB_REPO_CHECKOUT`. /// This is done on CI in .github/workflows/test.yml. - +using System; using System.Diagnostics; +using System.Linq; using System.Runtime.CompilerServices; +using System.Threading; using SpacetimeDB; using SpacetimeDB.Types; @@ -14,25 +16,30 @@ DbConnection ConnectToDB() { DbConnection? conn = null; - conn = DbConnection.Builder() + conn = DbConnection + .Builder() .WithUri(HOST) .WithModuleName(DBNAME) .OnConnect(OnConnected) - .OnConnectError((err) => - { - throw err; - }) - .OnDisconnect((conn, err) => - { - if (err != null) + .OnConnectError( + (err) => { throw err; } - else + ) + .OnDisconnect( + (conn, err) => { - throw new Exception("Unexpected disconnect"); + if (err != null) + { + throw err; + } + else + { + throw new Exception("Unexpected disconnect"); + } } - }) + ) .Build(); return conn; } @@ -46,11 +53,17 @@ void OnConnected(DbConnection conn, Identity identity, string authToken) Log.Debug($"Connected to {DBNAME} on {HOST}"); handle = conn.SubscriptionBuilder() .OnApplied(OnSubscriptionApplied) - .OnError((ctx, err) => - { - throw err; - }) - .Subscribe(["SELECT * FROM ExampleData", "SELECT * FROM MyPlayer", "SELECT * FROM PlayersForLevel"]); + .OnError( + (ctx, err) => + { + throw err; + } + ) + .Subscribe([ + "SELECT * FROM ExampleData", + "SELECT * FROM MyPlayer", + "SELECT * FROM PlayersForLevel", + ]); conn.Reducers.OnAdd += (ReducerEventContext ctx, uint id, uint indexed) => { @@ -127,30 +140,46 @@ void OnSubscriptionApplied(SubscriptionEventContext context) // Now unsubscribe and check that the unsubscribe is actually applied. Log.Debug("Calling Unsubscribe"); waiting++; - handle?.UnsubscribeThen((ctx) => - { - Log.Debug("Received Unsubscribe"); - ValidateBTreeIndexes(ctx); - waiting--; - }); - + handle?.UnsubscribeThen( + (ctx) => + { + Log.Debug("Received Unsubscribe"); + ValidateBTreeIndexes(ctx); + waiting--; + } + ); // Views test Log.Debug("Checking Views are populated"); Debug.Assert(context.Db.MyPlayer != null, "context.Db.MyPlayer != null"); Debug.Assert(context.Db.PlayersForLevel != null, "context.Db.PlayersForLevel != null"); - Debug.Assert(context.Db.MyPlayer.Count > 0, $"context.Db.MyPlayer.Count = {context.Db.MyPlayer.Count}"); - Debug.Assert(context.Db.PlayersForLevel.Count > 0, $"context.Db.PlayersForLevel.Count = {context.Db.PlayersForLevel.Count}"); + Debug.Assert( + context.Db.MyPlayer.Count > 0, + $"context.Db.MyPlayer.Count = {context.Db.MyPlayer.Count}" + ); + Debug.Assert( + context.Db.PlayersForLevel.Count > 0, + $"context.Db.PlayersForLevel.Count = {context.Db.PlayersForLevel.Count}" + ); Log.Debug("Calling Iter on View"); var viewIterRows = context.Db.MyPlayer.Iter(); - var expectedPlayer = new Player { Id = 1, Identity = context.Identity!.Value, Name = "NewPlayer" }; - Log.Debug("MyPlayer Iter count: " + (viewIterRows != null ? viewIterRows.Count().ToString() : "null")); + var expectedPlayer = new Player + { + Id = 1, + Identity = context.Identity!.Value, + Name = "NewPlayer", + }; + Log.Debug( + "MyPlayer Iter count: " + (viewIterRows != null ? viewIterRows.Count().ToString() : "null") + ); Debug.Assert(viewIterRows != null && viewIterRows.Any()); - Log.Debug("Validating View row data " + - $"Id={expectedPlayer.Id}, Identity={expectedPlayer.Identity}, Name={expectedPlayer.Name} => " + - $"Id={viewIterRows.First().Id}, Identity={viewIterRows.First().Identity}, Name={viewIterRows.First().Name}"); + Log.Debug( + "Validating View row data " + + $"Id={expectedPlayer.Id}, Identity={expectedPlayer.Identity}, Name={expectedPlayer.Name} => " + + $"Id={viewIterRows.First().Id}, Identity={viewIterRows.First().Identity}, Name={viewIterRows.First().Name}" + ); Debug.Assert(viewIterRows.First().Equals(expectedPlayer)); Log.Debug("Calling RemoteQuery on View"); @@ -165,18 +194,30 @@ void OnSubscriptionApplied(SubscriptionEventContext context) Id = 1, Identity = context.Identity!.Value, Name = "NewPlayer", - Level = 1 + Level = 1, }; - Log.Debug("PlayersForLevel Iter count: " + (anonViewIterRows != null ? anonViewIterRows.Count().ToString() : "null")); + Log.Debug( + "PlayersForLevel Iter count: " + + (anonViewIterRows != null ? anonViewIterRows.Count().ToString() : "null") + ); Debug.Assert(anonViewIterRows != null && anonViewIterRows.Any()); - Log.Debug("Validating Anonymous View row data " + - $"Id={expectedPlayerAndLevel.Id}, Identity={expectedPlayerAndLevel.Identity}, Name={expectedPlayerAndLevel.Name}, Level={expectedPlayerAndLevel.Level} => " + - $"Id={anonViewIterRows.First().Id}, Identity={anonViewIterRows.First().Identity}, Name={anonViewIterRows.First().Name}, Level={anonViewIterRows.First().Level}"); + Log.Debug( + "Validating Anonymous View row data " + + $"Id={expectedPlayerAndLevel.Id}, Identity={expectedPlayerAndLevel.Identity}, Name={expectedPlayerAndLevel.Name}, Level={expectedPlayerAndLevel.Level} => " + + $"Id={anonViewIterRows.First().Id}, Identity={anonViewIterRows.First().Identity}, Name={anonViewIterRows.First().Name}, Level={anonViewIterRows.First().Level}" + ); Debug.Assert(anonViewIterRows.First().Equals(expectedPlayerAndLevel)); Log.Debug("Calling RemoteQuery on Anonymous View"); var anonViewRemoteQueryRows = context.Db.PlayersForLevel.RemoteQuery("WHERE Level = 1"); - Log.Debug("PlayersForLevel RemoteQuery count: " + (anonViewRemoteQueryRows != null ? anonViewRemoteQueryRows.Result.Length.ToString() : "null")); + Log.Debug( + "PlayersForLevel RemoteQuery count: " + + ( + anonViewRemoteQueryRows != null + ? anonViewRemoteQueryRows.Result.Length.ToString() + : "null" + ) + ); Debug.Assert(anonViewRemoteQueryRows != null && anonViewRemoteQueryRows.Result.Length > 0); Debug.Assert(anonViewRemoteQueryRows.Result.First().Equals(expectedPlayerAndLevel)); } @@ -201,4 +242,4 @@ void OnSubscriptionApplied(SubscriptionEventContext context) } } Log.Info("Success"); -Environment.Exit(0); \ No newline at end of file +Environment.Exit(0); From b9aafff687a6ca0a35ffd9f7269626f02de26a9a Mon Sep 17 00:00:00 2001 From: rekhoff Date: Tue, 9 Dec 2025 17:26:54 -0800 Subject: [PATCH 5/5] First pass on adding additional transaction tests --- crates/bindings-csharp/Codegen/Module.cs | 2 +- .../Runtime/ProcedureContext.cs | 2 +- crates/codegen/src/csharp.rs | 6 +- .../regression-tests/client/Program.cs | 269 ++++- .../AuthenticationCapabilities.g.cs | 65 ++ .../Procedures/DanglingTxWarning.g.cs | 64 + .../Procedures/DocumentationGapChecks.g.cs | 84 ++ .../Procedures/InsertWithTxCommit.g.cs | 64 + .../Procedures/InsertWithTxPanic.g.cs | 64 + .../Procedures/InsertWithTxRetry.g.cs | 64 + .../Procedures/InsertWithTxRollback.g.cs | 64 + .../Procedures/SleepUntilTimestampUpdate.g.cs | 77 ++ .../Procedures/SubscriptionEventOffset.g.cs | 65 ++ .../Procedures/TimestampCapabilities.g.cs | 65 ++ .../Procedures/TxContextCapabilities.g.cs | 65 ++ .../module_bindings/SpacetimeDBClient.g.cs | 13 +- .../module_bindings/Tables/ExampleData.g.cs | 2 +- .../module_bindings/Tables/MyPlayer.g.cs | 2 +- .../client/module_bindings/Tables/Player.g.cs | 2 +- .../module_bindings/Tables/PlayerLevel.g.cs | 2 +- ...rsForLevel.g.cs => PlayersAtLevelOne.g.cs} | 8 +- .../module_bindings/Tables/RetryLog.g.cs | 39 + .../client/module_bindings/Types/MyTable.g.cs | 12 + .../module_bindings/Types/RetryLog.g.cs | 34 + .../Module.PlayerAndLevel.cs | 107 ++ .../SpacetimeDB.Codegen.Type/ReturnEnum.cs | 68 ++ .../SpacetimeDB.Codegen.Type/ReturnStruct.cs | 90 ++ .../SpacetimeDB.Codegen.Module/FFI.cs | 1037 +++++++++++++++++ .../SpacetimeDB.Codegen.Module/Module.Add.cs | 14 + .../Module.AuthenticationCapabilities.cs | 13 + .../Module.ClientConnected.cs | 13 + .../Module.DanglingTxWarning.cs | 13 + .../Module.Delete.cs | 13 + .../Module.DocumentationGapChecks.cs | 14 + .../Module.ExampleData.cs | 91 ++ .../Module.InsertWithTxCommit.cs | 13 + .../Module.InsertWithTxPanic.cs | 13 + .../Module.InsertWithTxRetry.cs | 13 + .../Module.InsertWithTxRollback.cs | 13 + .../Module.MyTable.cs | 83 ++ .../Module.Player.cs | 99 ++ .../Module.PlayerLevel.cs | 91 ++ .../Module.RetryLog.cs | 92 ++ .../Module.ReturnEnumA.cs | 13 + .../Module.ReturnEnumB.cs | 13 + .../Module.ReturnPrimitive.cs | 14 + .../Module.ReturnStructProcedure.cs | 14 + .../Module.SleepUntilTimestampUpdate.cs | 13 + .../Module.SubscriptionEventOffset.cs | 13 + .../Module.ThrowError.cs | 13 + .../Module.TimestampCapabilities.cs | 13 + .../Module.TxContextCapabilities.cs | 13 + .../Module.WillPanic.cs | 13 + .../SpacetimeDB.Codegen.Module/MyTable.cs | 82 ++ .../SpacetimeDB.Codegen.Module/RetryLog.cs | 82 ++ .../examples~/regression-tests/server/Lib.cs | 389 ++++++- sdks/csharp/src/Event.cs | 2 +- 57 files changed, 3663 insertions(+), 48 deletions(-) create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/AuthenticationCapabilities.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DanglingTxWarning.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DocumentationGapChecks.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxCommit.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxPanic.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRetry.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRollback.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SleepUntilTimestampUpdate.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SubscriptionEventOffset.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TimestampCapabilities.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TxContextCapabilities.g.cs rename sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/{PlayersForLevel.g.cs => PlayersAtLevelOne.g.cs} (57%) create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/RetryLog.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/client/module_bindings/Types/RetryLog.g.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/Module.PlayerAndLevel.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnEnum.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnStruct.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Add.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.AuthenticationCapabilities.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ClientConnected.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DanglingTxWarning.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Delete.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DocumentationGapChecks.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ExampleData.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxCommit.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxPanic.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRetry.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRollback.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.MyTable.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Player.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.PlayerLevel.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.RetryLog.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumA.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumB.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnPrimitive.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnStructProcedure.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SleepUntilTimestampUpdate.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SubscriptionEventOffset.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ThrowError.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TimestampCapabilities.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TxContextCapabilities.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.WillPanic.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/MyTable.cs create mode 100644 sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/RetryLog.cs diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index b10817e0aab..ab08c207e9c 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -1742,7 +1742,7 @@ internal ReducerContext(Identity identity, ConnectionId? connectionId, Random ra } } - public sealed class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { + public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { private readonly Local _db = new(); internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time) diff --git a/crates/bindings-csharp/Runtime/ProcedureContext.cs b/crates/bindings-csharp/Runtime/ProcedureContext.cs index 8c78a427f35..b3949a20127 100644 --- a/crates/bindings-csharp/Runtime/ProcedureContext.cs +++ b/crates/bindings-csharp/Runtime/ProcedureContext.cs @@ -226,7 +226,7 @@ public abstract class LocalBase : Internal.Local { } public abstract class LocalReadOnlyBase : Internal.LocalReadOnly { } -public sealed class ProcedureContext( +public sealed partial class ProcedureContext( Identity sender, ConnectionId? connectionId, Random random, diff --git a/crates/codegen/src/csharp.rs b/crates/codegen/src/csharp.rs index c07265a6d69..cbafac497ab 100644 --- a/crates/codegen/src/csharp.rs +++ b/crates/codegen/src/csharp.rs @@ -355,7 +355,7 @@ const REDUCER_EVENTS: &str = r#" /// /// The procedure event that caused this callback to run. /// - public readonly ProcedureEvent Event; + public ProcedureEvent Event { get; } /// /// Access to tables in the client cache, which stores a read-only replica of the remote database state. @@ -422,10 +422,10 @@ const REDUCER_EVENTS: &str = r#" remove => Reducers.InternalOnUnhandledReducerError -= value; } - internal ProcedureEventContext(DbConnection conn, ProcedureEvent Event) + internal ProcedureEventContext(DbConnection conn, ProcedureEvent procedureEvent) { this.conn = conn; - this.Event = Event; + Event = procedureEvent; } } diff --git a/sdks/csharp/examples~/regression-tests/client/Program.cs b/sdks/csharp/examples~/regression-tests/client/Program.cs index b530c1a4cd6..83bd56a80a2 100644 --- a/sdks/csharp/examples~/regression-tests/client/Program.cs +++ b/sdks/csharp/examples~/regression-tests/client/Program.cs @@ -60,9 +60,9 @@ void OnConnected(DbConnection conn, Identity identity, string authToken) } ) .Subscribe([ - "SELECT * FROM ExampleData", - "SELECT * FROM MyPlayer", - "SELECT * FROM PlayersForLevel", + "SELECT * FROM example_data", + "SELECT * FROM my_player", + "SELECT * FROM players_at_level_one", ]); conn.Reducers.OnAdd += (ReducerEventContext ctx, uint id, uint indexed) => @@ -150,19 +150,18 @@ void OnSubscriptionApplied(SubscriptionEventContext context) ); // Views test - Log.Debug("Checking Views are populated"); Debug.Assert(context.Db.MyPlayer != null, "context.Db.MyPlayer != null"); - Debug.Assert(context.Db.PlayersForLevel != null, "context.Db.PlayersForLevel != null"); + Debug.Assert(context.Db.PlayersAtLevelOne != null, "context.Db.PlayersAtLevelOne != null"); Debug.Assert( context.Db.MyPlayer.Count > 0, $"context.Db.MyPlayer.Count = {context.Db.MyPlayer.Count}" ); Debug.Assert( - context.Db.PlayersForLevel.Count > 0, - $"context.Db.PlayersForLevel.Count = {context.Db.PlayersForLevel.Count}" + context.Db.PlayersAtLevelOne.Count > 0, + $"context.Db.PlayersAtLevelOne.Count = {context.Db.PlayersAtLevelOne.Count}" ); - + Log.Debug("Calling Iter on View"); var viewIterRows = context.Db.MyPlayer.Iter(); var expectedPlayer = new Player @@ -181,14 +180,14 @@ void OnSubscriptionApplied(SubscriptionEventContext context) + $"Id={viewIterRows.First().Id}, Identity={viewIterRows.First().Identity}, Name={viewIterRows.First().Name}" ); Debug.Assert(viewIterRows.First().Equals(expectedPlayer)); - + Log.Debug("Calling RemoteQuery on View"); var viewRemoteQueryRows = context.Db.MyPlayer.RemoteQuery("WHERE Id > 0"); Debug.Assert(viewRemoteQueryRows != null && viewRemoteQueryRows.Result.Length > 0); Debug.Assert(viewRemoteQueryRows.Result.First().Equals(expectedPlayer)); - + Log.Debug("Calling Iter on Anonymous View"); - var anonViewIterRows = context.Db.PlayersForLevel.Iter(); + var anonViewIterRows = context.Db.PlayersAtLevelOne.Iter(); var expectedPlayerAndLevel = new PlayerAndLevel { Id = 1, @@ -197,21 +196,22 @@ void OnSubscriptionApplied(SubscriptionEventContext context) Level = 1, }; Log.Debug( - "PlayersForLevel Iter count: " + "PlayersAtLevelOne Iter count: " + (anonViewIterRows != null ? anonViewIterRows.Count().ToString() : "null") ); Debug.Assert(anonViewIterRows != null && anonViewIterRows.Any()); Log.Debug( "Validating Anonymous View row data " + $"Id={expectedPlayerAndLevel.Id}, Identity={expectedPlayerAndLevel.Identity}, Name={expectedPlayerAndLevel.Name}, Level={expectedPlayerAndLevel.Level} => " - + $"Id={anonViewIterRows.First().Id}, Identity={anonViewIterRows.First().Identity}, Name={anonViewIterRows.First().Name}, Level={anonViewIterRows.First().Level}" + + $"Id={anonViewIterRows.First().Id}, Identity={anonViewIterRows.First().Identity}, Name={anonViewIterRows.First().Name}, Level={anonViewIterRows.First().Level} => " + //+ $"PlayerId={anonViewIterRows.First().PlayerId}, Level={anonViewIterRows.First().Level}" ); Debug.Assert(anonViewIterRows.First().Equals(expectedPlayerAndLevel)); - + Log.Debug("Calling RemoteQuery on Anonymous View"); - var anonViewRemoteQueryRows = context.Db.PlayersForLevel.RemoteQuery("WHERE Level = 1"); + var anonViewRemoteQueryRows = context.Db.PlayersAtLevelOne.RemoteQuery("WHERE Level = 1"); Log.Debug( - "PlayersForLevel RemoteQuery count: " + "PlayersAtLevelOne RemoteQuery count: " + ( anonViewRemoteQueryRows != null ? anonViewRemoteQueryRows.Result.Length.ToString() @@ -220,6 +220,243 @@ void OnSubscriptionApplied(SubscriptionEventContext context) ); Debug.Assert(anonViewRemoteQueryRows != null && anonViewRemoteQueryRows.Result.Length > 0); Debug.Assert(anonViewRemoteQueryRows.Result.First().Equals(expectedPlayerAndLevel)); + + // Procedures tests + + Log.Debug("Calling InsertWithTxCommit"); + waiting++; + context.Procedures.InsertWithTxCommit((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "InsertWithTxCommit should succeed"); + Debug.Assert(context.Db.MyTable.Count == 1, $"MyTable should have one row after commit, but had {context.Db.MyTable.Count}"); + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling InsertWithTxRollback"); + waiting++; + context.Procedures.InsertWithTxRollback((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(!result.IsSuccess, "InsertWithTxRollback should fail"); + Debug.Assert(result.Error is InvalidOperationException ioe && ioe.Message == "rollback", $"Expected error to be InvalidOperationException with message 'rollback' but got {result.Error}"); + Debug.Assert(context.Db.MyTable.Count == 0, "MyTable should remain empty after rollback"); + // No tx-offset assertion because ProcedureEvent doesn’t expose one yet. + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling InsertWithTxRetry"); + waiting++; + context.Procedures.InsertWithTxRetry((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "InsertWithTxRetry should succeed after retry"); + // For Unit return types, you don't need to check result.Value + } + catch (Exception ex) + { + Log.Exception(ex); + throw; + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling InsertWithTxPanic"); + waiting++; + context.Procedures.InsertWithTxPanic((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "InsertWithTxPanic should succeed (exception is caught)"); + Debug.Assert(context.Db.MyTable.Count == 0, "MyTable should remain empty after exception abort"); + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling DanglingTxWarning"); + waiting++; + context.Procedures.DanglingTxWarning((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "DanglingTxWarning should succeed"); + Debug.Assert(context.Db.MyTable.Count == 0, "MyTable should remain empty after dangling tx auto-abort"); + // Note: We can't easily assert on the warning log from client-side, + // but the server-side AssertRowCount verifies the auto-abort behavior + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling TxContextCapabilities"); + waiting++; + context.Procedures.TxContextCapabilities((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "TxContextCapabilities should succeed"); + Debug.Assert(result.Value != null && result.Value.A == 1, $"Expected count 1, got {result.Value.A}"); + Debug.Assert(result.Value.B.StartsWith("sender:"), $"Expected sender info, got {result.Value.B}"); + Debug.Assert(context.Db.MyTable.Count == 1, "MyTable should have one row after TxContext test"); + + // Verify the inserted row has the expected data + var row = context.Db.MyTable.Iter().FirstOrDefault(); + Debug.Assert(row is not null, "Should have a row in MyTable"); + Debug.Assert(row.Field.A == 200, $"Expected field.A == 200, got {row.Field.A}"); + Debug.Assert(row.Field.B == "tx-test", $"Expected field.B == 'tx-test', got {row.Field.B}"); + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling TimestampCapabilities"); + waiting++; + context.Procedures.TimestampCapabilities((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "TimestampCapabilities should succeed"); + Debug.Assert(result.Value != null && result.Value.A > 0, "Should return a valid timestamp-derived value"); + Debug.Assert(result.Value.B.Contains(":"), "Should return formatted timestamp string"); + Debug.Assert(context.Db.MyTable.Count == 2, "MyTable should have two rows after timestamp test"); + + // Verify the inserted row has timestamp information + var rows = context.Db.MyTable.Iter().ToList(); + Debug.Assert(rows.Count == 2, "Should have exactly 2 rows"); + + var timestampRow = rows.FirstOrDefault(r => r.Field.B.StartsWith("timestamp:")); + Debug.Assert(timestampRow is not null, "Should have a row with timestamp data"); + Debug.Assert(timestampRow.Field.B.StartsWith("timestamp:"), "Timestamp row should have correct format"); + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling AuthenticationCapabilities"); + waiting++; + context.Procedures.AuthenticationCapabilities((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "AuthenticationCapabilities should succeed"); + Debug.Assert(result.Value != null, "Should return a valid sender-derived value"); + Debug.Assert(result.Value.B.Contains("jwt:") || result.Value.B == "no-jwt", $"Should return JWT info, got {result.Value.B}"); + Debug.Assert(context.Db.MyTable.Count == 3, "MyTable should have three rows after auth test"); + + // Verify the inserted row has authentication information + var rows = context.Db.MyTable.Iter().ToList(); + Debug.Assert(rows.Count == 3, "Should have exactly 3 rows"); + + var authRow = rows.FirstOrDefault(r => r.Field.B.StartsWith("auth:")); + Debug.Assert(authRow is not null, "Should have a row with auth data"); + Debug.Assert(authRow.Field.B.Contains("sender:"), "Auth row should contain sender info"); + Debug.Assert(authRow.Field.B.Contains("conn:"), "Auth row should contain connection info"); + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling SubscriptionEventOffset"); + waiting++; + context.Procedures.SubscriptionEventOffset((IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "SubscriptionEventOffset should succeed"); + Debug.Assert(result.Value != null && result.Value.A == 999, $"Expected A == 999, got {result.Value.A}"); + Debug.Assert(result.Value.B.StartsWith("committed:"), $"Expected committed timestamp, got {result.Value.B}"); + Debug.Assert(context.Db.MyTable.Count == 4, "MyTable should have four rows after offset test"); + + // Verify the inserted row has the expected offset test data + var rows = context.Db.MyTable.Iter().ToList(); + Debug.Assert(rows.Count == 4, "Should have exactly 4 rows"); + + var offsetRow = rows.FirstOrDefault(r => r.Field.B.StartsWith("offset-test:")); + Debug.Assert(offsetRow is not null, "Should have a row with offset-test data"); + Debug.Assert(offsetRow.Field.A == 999, "Offset test row should have A == 999"); + + // Note: Transaction offset information may not be directly accessible in ProcedureEvent yet, + // but this test verifies that the transaction was committed and subscription events were generated + // The presence of the new row in the subscription confirms the transaction offset was processed + } + finally + { + waiting--; + } + }); + + Log.Debug("Calling DocumentationGapChecks with valid parameters"); + waiting++; + context.Procedures.DocumentationGapChecks(42, "test-input", (IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(result.IsSuccess, "DocumentationGapChecks should succeed with valid parameters"); + + // Expected: inputValue * 2 + inputText.Length = 42 * 2 + 10 = 94 + var expectedValue = 42u * 2 + (uint)"test-input".Length; // 84 + 10 = 94 + Debug.Assert(result.Value != null && result.Value.A == expectedValue, $"Expected A == {expectedValue}, got {result.Value.A}"); + Debug.Assert(result.Value.B.StartsWith("success:"), $"Expected success message, got {result.Value.B}"); + Debug.Assert(result.Value.B.Contains("test-input"), "Result should contain input text"); + + Debug.Assert(context.Db.MyTable.Count == 5, "MyTable should have five rows after documentation gap test"); + + // Verify the inserted row has the expected documentation gap test data + var rows = context.Db.MyTable.Iter().ToList(); + var docGapRow = rows.FirstOrDefault(r => r.Field.B.StartsWith("doc-gap:")); + Debug.Assert(docGapRow is not null, "Should have a row with doc-gap data"); + Debug.Assert(docGapRow.Field.A == expectedValue, $"Doc gap row should have A == {expectedValue}"); + Debug.Assert(docGapRow.Field.B.Contains("test-input"), "Doc gap row should contain input text"); + } + finally + { + waiting--; + } + }); + + // Test error handling with invalid parameters + Log.Debug("Calling DocumentationGapChecks with invalid parameters (should fail)"); + waiting++; + context.Procedures.DocumentationGapChecks(0, "", (IProcedureEventContext ctx, ProcedureCallbackResult result) => + { + try + { + Debug.Assert(!result.IsSuccess, "DocumentationGapChecks should fail with invalid parameters"); + Debug.Assert(result.Error is ArgumentException, $"Expected ArgumentException, got {result.Error?.GetType()}"); + + // Table count should remain the same since the procedure failed + Debug.Assert(context.Db.MyTable.Count == 5, "MyTable count should remain 5 after failed call"); + } + finally + { + waiting--; + } + }); } System.AppDomain.CurrentDomain.UnhandledException += (sender, args) => diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/AuthenticationCapabilities.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/AuthenticationCapabilities.g.cs new file mode 100644 index 00000000000..5ac94eec7ce --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/AuthenticationCapabilities.g.cs @@ -0,0 +1,65 @@ +// 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 RemoteProcedures : RemoteBase + { + public void AuthenticationCapabilities(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalAuthenticationCapabilities((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalAuthenticationCapabilities(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.AuthenticationCapabilitiesArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class AuthenticationCapabilities + { + [DataMember(Name = "Value")] + public SpacetimeDB.Types.ReturnStruct Value; + + public AuthenticationCapabilities(SpacetimeDB.Types.ReturnStruct Value) + { + this.Value = Value; + } + + public AuthenticationCapabilities() + { + this.Value = new(); + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class AuthenticationCapabilitiesArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "AuthenticationCapabilities"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DanglingTxWarning.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DanglingTxWarning.g.cs new file mode 100644 index 00000000000..45f97316046 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DanglingTxWarning.g.cs @@ -0,0 +1,64 @@ +// 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 RemoteProcedures : RemoteBase + { + public void DanglingTxWarning(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalDanglingTxWarning((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalDanglingTxWarning(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.DanglingTxWarningArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class DanglingTxWarning + { + [DataMember(Name = "Value")] + public SpacetimeDB.Unit Value; + + public DanglingTxWarning(SpacetimeDB.Unit Value) + { + this.Value = Value; + } + + public DanglingTxWarning() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class DanglingTxWarningArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "DanglingTxWarning"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DocumentationGapChecks.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DocumentationGapChecks.g.cs new file mode 100644 index 00000000000..53be2ac06dc --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/DocumentationGapChecks.g.cs @@ -0,0 +1,84 @@ +// 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 RemoteProcedures : RemoteBase + { + public void DocumentationGapChecks(uint inputValue, string inputText, ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalDocumentationGapChecks(inputValue, inputText, (ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalDocumentationGapChecks(uint inputValue, string inputText, ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.DocumentationGapChecksArgs(inputValue, inputText), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class DocumentationGapChecks + { + [DataMember(Name = "Value")] + public SpacetimeDB.Types.ReturnStruct Value; + + public DocumentationGapChecks(SpacetimeDB.Types.ReturnStruct Value) + { + this.Value = Value; + } + + public DocumentationGapChecks() + { + this.Value = new(); + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class DocumentationGapChecksArgs : Procedure, IProcedureArgs + { + [DataMember(Name = "inputValue")] + public uint InputValue; + [DataMember(Name = "inputText")] + public string InputText; + + public DocumentationGapChecksArgs( + uint InputValue, + string InputText + ) + { + this.InputValue = InputValue; + this.InputText = InputText; + } + + public DocumentationGapChecksArgs() + { + this.InputText = ""; + } + + string IProcedureArgs.ProcedureName => "DocumentationGapChecks"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxCommit.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxCommit.g.cs new file mode 100644 index 00000000000..0840ae041e8 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxCommit.g.cs @@ -0,0 +1,64 @@ +// 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 RemoteProcedures : RemoteBase + { + public void InsertWithTxCommit(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalInsertWithTxCommit((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalInsertWithTxCommit(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.InsertWithTxCommitArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxCommit + { + [DataMember(Name = "Value")] + public SpacetimeDB.Unit Value; + + public InsertWithTxCommit(SpacetimeDB.Unit Value) + { + this.Value = Value; + } + + public InsertWithTxCommit() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxCommitArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "InsertWithTxCommit"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxPanic.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxPanic.g.cs new file mode 100644 index 00000000000..fe19b50b6f4 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxPanic.g.cs @@ -0,0 +1,64 @@ +// 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 RemoteProcedures : RemoteBase + { + public void InsertWithTxPanic(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalInsertWithTxPanic((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalInsertWithTxPanic(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.InsertWithTxPanicArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxPanic + { + [DataMember(Name = "Value")] + public SpacetimeDB.Unit Value; + + public InsertWithTxPanic(SpacetimeDB.Unit Value) + { + this.Value = Value; + } + + public InsertWithTxPanic() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxPanicArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "InsertWithTxPanic"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRetry.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRetry.g.cs new file mode 100644 index 00000000000..347fc22de61 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRetry.g.cs @@ -0,0 +1,64 @@ +// 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 RemoteProcedures : RemoteBase + { + public void InsertWithTxRetry(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalInsertWithTxRetry((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalInsertWithTxRetry(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.InsertWithTxRetryArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxRetry + { + [DataMember(Name = "Value")] + public uint Value; + + public InsertWithTxRetry(uint Value) + { + this.Value = Value; + } + + public InsertWithTxRetry() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxRetryArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "InsertWithTxRetry"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRollback.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRollback.g.cs new file mode 100644 index 00000000000..d8d374bc264 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/InsertWithTxRollback.g.cs @@ -0,0 +1,64 @@ +// 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 RemoteProcedures : RemoteBase + { + public void InsertWithTxRollback(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalInsertWithTxRollback((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalInsertWithTxRollback(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.InsertWithTxRollbackArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxRollback + { + [DataMember(Name = "Value")] + public SpacetimeDB.Unit Value; + + public InsertWithTxRollback(SpacetimeDB.Unit Value) + { + this.Value = Value; + } + + public InsertWithTxRollback() + { + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class InsertWithTxRollbackArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "InsertWithTxRollback"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SleepUntilTimestampUpdate.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SleepUntilTimestampUpdate.g.cs new file mode 100644 index 00000000000..e1051b77205 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SleepUntilTimestampUpdate.g.cs @@ -0,0 +1,77 @@ +// 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 RemoteProcedures : RemoteBase + { + public void SleepUntilTimestampUpdate(uint sleepMillis, ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalSleepUntilTimestampUpdate(sleepMillis, (ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalSleepUntilTimestampUpdate(uint sleepMillis, ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.SleepUntilTimestampUpdateArgs(sleepMillis), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SleepUntilTimestampUpdate + { + [DataMember(Name = "Value")] + public SpacetimeDB.Types.ReturnStruct Value; + + public SleepUntilTimestampUpdate(SpacetimeDB.Types.ReturnStruct Value) + { + this.Value = Value; + } + + public SleepUntilTimestampUpdate() + { + this.Value = new(); + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SleepUntilTimestampUpdateArgs : Procedure, IProcedureArgs + { + [DataMember(Name = "sleepMillis")] + public uint SleepMillis; + + public SleepUntilTimestampUpdateArgs(uint SleepMillis) + { + this.SleepMillis = SleepMillis; + } + + public SleepUntilTimestampUpdateArgs() + { + } + + string IProcedureArgs.ProcedureName => "SleepUntilTimestampUpdate"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SubscriptionEventOffset.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SubscriptionEventOffset.g.cs new file mode 100644 index 00000000000..be718da9ac7 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/SubscriptionEventOffset.g.cs @@ -0,0 +1,65 @@ +// 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 RemoteProcedures : RemoteBase + { + public void SubscriptionEventOffset(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalSubscriptionEventOffset((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalSubscriptionEventOffset(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.SubscriptionEventOffsetArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscriptionEventOffset + { + [DataMember(Name = "Value")] + public SpacetimeDB.Types.ReturnStruct Value; + + public SubscriptionEventOffset(SpacetimeDB.Types.ReturnStruct Value) + { + this.Value = Value; + } + + public SubscriptionEventOffset() + { + this.Value = new(); + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class SubscriptionEventOffsetArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "SubscriptionEventOffset"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TimestampCapabilities.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TimestampCapabilities.g.cs new file mode 100644 index 00000000000..3c054920e80 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TimestampCapabilities.g.cs @@ -0,0 +1,65 @@ +// 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 RemoteProcedures : RemoteBase + { + public void TimestampCapabilities(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalTimestampCapabilities((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalTimestampCapabilities(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.TimestampCapabilitiesArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TimestampCapabilities + { + [DataMember(Name = "Value")] + public SpacetimeDB.Types.ReturnStruct Value; + + public TimestampCapabilities(SpacetimeDB.Types.ReturnStruct Value) + { + this.Value = Value; + } + + public TimestampCapabilities() + { + this.Value = new(); + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TimestampCapabilitiesArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "TimestampCapabilities"; + } + + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TxContextCapabilities.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TxContextCapabilities.g.cs new file mode 100644 index 00000000000..8b60bef209e --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Procedures/TxContextCapabilities.g.cs @@ -0,0 +1,65 @@ +// 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 RemoteProcedures : RemoteBase + { + public void TxContextCapabilities(ProcedureCallback callback) + { + // Convert the clean callback to the wrapper callback + InternalTxContextCapabilities((ctx, result) => + { + if (result.IsSuccess && result.Value != null) + { + callback(ctx, ProcedureCallbackResult.Success(result.Value.Value)); + } + else + { + callback(ctx, ProcedureCallbackResult.Failure(result.Error!)); + } + }); + } + + private void InternalTxContextCapabilities(ProcedureCallback callback) + { + conn.InternalCallProcedure(new Procedure.TxContextCapabilitiesArgs(), callback); + } + + } + + public abstract partial class Procedure + { + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TxContextCapabilities + { + [DataMember(Name = "Value")] + public SpacetimeDB.Types.ReturnStruct Value; + + public TxContextCapabilities(SpacetimeDB.Types.ReturnStruct Value) + { + this.Value = Value; + } + + public TxContextCapabilities() + { + this.Value = new(); + } + } + [SpacetimeDB.Type] + [DataContract] + public sealed partial class TxContextCapabilitiesArgs : Procedure, IProcedureArgs + { + string IProcedureArgs.ProcedureName => "TxContextCapabilities"; + } + + } +} 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 8b3eecc9d4d..dfa92ec5ca8 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 1.9.0 (commit 6b66e0ec5ff6837618bf774e62b5844e8bcccd22). +// This was generated using spacetimedb cli version 1.11.0 (commit 14d310bb2a9e6a64571dabb8e4b343f86b21ac0a). #nullable enable @@ -30,10 +30,11 @@ public RemoteTables(DbConnection conn) { AddTable(ExampleData = new(conn)); AddTable(MyPlayer = new(conn)); + AddTable(MyTable = new(conn)); AddTable(Player = new(conn)); AddTable(PlayerLevel = new(conn)); - AddTable(PlayersForLevel = new(conn)); - AddTable(MyTable = new(conn)); + AddTable(PlayersAtLevelOne = new(conn)); + AddTable(RetryLog = new(conn)); } } @@ -381,7 +382,7 @@ public sealed class ProcedureEventContext : IProcedureEventContext, IRemoteDbCon /// /// The procedure event that caused this callback to run. /// - public readonly ProcedureEvent Event; + public ProcedureEvent Event { get; } /// /// Access to tables in the client cache, which stores a read-only replica of the remote database state. @@ -450,10 +451,10 @@ public event Action? OnUnhandledReducerError remove => Reducers.InternalOnUnhandledReducerError -= value; } - internal ProcedureEventContext(DbConnection conn, ProcedureEvent Event) + internal ProcedureEventContext(DbConnection conn, ProcedureEvent procedureEvent) { this.conn = conn; - this.Event = Event; + Event = procedureEvent; } } diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs index ac26997f2f5..f46d19756a2 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/ExampleData.g.cs @@ -15,7 +15,7 @@ public sealed partial class RemoteTables { public sealed class ExampleDataHandle : RemoteTableHandle { - protected override string RemoteTableName => "ExampleData"; + protected override string RemoteTableName => "example_data"; public sealed class IdUniqueIndex : UniqueIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/MyPlayer.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/MyPlayer.g.cs index 86292847f92..199a1dfba7f 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/MyPlayer.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/MyPlayer.g.cs @@ -15,7 +15,7 @@ public sealed partial class RemoteTables { public sealed class MyPlayerHandle : RemoteTableHandle { - protected override string RemoteTableName => "MyPlayer"; + protected override string RemoteTableName => "my_player"; internal MyPlayerHandle(DbConnection conn) : base(conn) { diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/Player.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/Player.g.cs index 7cc2b9b3316..ce769f4e611 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/Player.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/Player.g.cs @@ -15,7 +15,7 @@ public sealed partial class RemoteTables { public sealed class PlayerHandle : RemoteTableHandle { - protected override string RemoteTableName => "Player"; + protected override string RemoteTableName => "player"; public sealed class IdUniqueIndex : UniqueIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayerLevel.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayerLevel.g.cs index 01e5169593a..e4da71c07ca 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayerLevel.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayerLevel.g.cs @@ -15,7 +15,7 @@ public sealed partial class RemoteTables { public sealed class PlayerLevelHandle : RemoteTableHandle { - protected override string RemoteTableName => "PlayerLevel"; + protected override string RemoteTableName => "player_level"; public sealed class LevelIndex : BTreeIndexBase { diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayersForLevel.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayersAtLevelOne.g.cs similarity index 57% rename from sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayersForLevel.g.cs rename to sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayersAtLevelOne.g.cs index 5758613ad31..56b58ad0a6c 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayersForLevel.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/PlayersAtLevelOne.g.cs @@ -13,15 +13,15 @@ namespace SpacetimeDB.Types { public sealed partial class RemoteTables { - public sealed class PlayersForLevelHandle : RemoteTableHandle + public sealed class PlayersAtLevelOneHandle : RemoteTableHandle { - protected override string RemoteTableName => "PlayersForLevel"; + protected override string RemoteTableName => "players_at_level_one"; - internal PlayersForLevelHandle(DbConnection conn) : base(conn) + internal PlayersAtLevelOneHandle(DbConnection conn) : base(conn) { } } - public readonly PlayersForLevelHandle PlayersForLevel; + public readonly PlayersAtLevelOneHandle PlayersAtLevelOne; } } diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/RetryLog.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/RetryLog.g.cs new file mode 100644 index 00000000000..f67e0bea4b2 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Tables/RetryLog.g.cs @@ -0,0 +1,39 @@ +// 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 RetryLogHandle : RemoteTableHandle + { + protected override string RemoteTableName => "retry_log"; + + public sealed class IdUniqueIndex : UniqueIndexBase + { + protected override uint GetKey(RetryLog row) => row.Id; + + public IdUniqueIndex(RetryLogHandle table) : base(table) { } + } + + public readonly IdUniqueIndex Id; + + internal RetryLogHandle(DbConnection conn) : base(conn) + { + Id = new(this); + } + + protected override object GetPrimaryKey(RetryLog row) => row.Id; + } + + public readonly RetryLogHandle RetryLog; + } +} diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/MyTable.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/MyTable.g.cs index 5fe3407eadc..9e720eb8469 100644 --- a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/MyTable.g.cs +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/MyTable.g.cs @@ -13,5 +13,17 @@ namespace SpacetimeDB.Types [DataContract] public sealed partial class MyTable { + [DataMember(Name = "Field")] + public ReturnStruct Field; + + public MyTable(ReturnStruct Field) + { + this.Field = Field; + } + + public MyTable() + { + this.Field = new(); + } } } diff --git a/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/RetryLog.g.cs b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/RetryLog.g.cs new file mode 100644 index 00000000000..a7a2faef743 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/client/module_bindings/Types/RetryLog.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 RetryLog + { + [DataMember(Name = "Id")] + public uint Id; + [DataMember(Name = "Attempts")] + public uint Attempts; + + public RetryLog( + uint Id, + uint Attempts + ) + { + this.Id = Id; + this.Attempts = Attempts; + } + + public RetryLog() + { + } + } +} diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/Module.PlayerAndLevel.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/Module.PlayerAndLevel.cs new file mode 100644 index 00000000000..3850813b365 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/Module.PlayerAndLevel.cs @@ -0,0 +1,107 @@ +// +#nullable enable + +partial class Module { +partial struct PlayerAndLevel : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + Id = BSATN.IdRW.Read(reader); + Identity = BSATN.IdentityRW.Read(reader); + Name = BSATN.NameRW.Read(reader); + Level = BSATN.LevelRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) { + BSATN.IdRW.Write(writer, Id); + BSATN.IdentityRW.Write(writer, Identity); + BSATN.NameRW.Write(writer, Name); + BSATN.LevelRW.Write(writer, Level); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"PlayerAndLevel {{ Id = {SpacetimeDB.BSATN.StringUtil.GenericToString(Id)}, Identity = {SpacetimeDB.BSATN.StringUtil.GenericToString(Identity)}, Name = {SpacetimeDB.BSATN.StringUtil.GenericToString(Name)}, Level = {SpacetimeDB.BSATN.StringUtil.GenericToString(Level)} }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U64 IdRW = new(); + internal static readonly SpacetimeDB.Identity.BSATN IdentityRW = new(); + internal static readonly SpacetimeDB.BSATN.String NameRW = new(); + internal static readonly SpacetimeDB.BSATN.U64 LevelRW = new(); + + public Module.PlayerAndLevel Read(System.IO.BinaryReader reader) { + var ___result = new Module.PlayerAndLevel(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Module.PlayerAndLevel value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + new("Id", IdRW.GetAlgebraicType(registrar)), + new("Identity", IdentityRW.GetAlgebraicType(registrar)), + new("Name", NameRW.GetAlgebraicType(registrar)), + new("Level", LevelRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashId = Id.GetHashCode(); +var ___hashIdentity = Identity.GetHashCode(); +var ___hashName = Name == null ? 0 : Name.GetHashCode(); +var ___hashLevel = Level.GetHashCode(); +return ___hashId ^ + ___hashIdentity ^ + ___hashName ^ + ___hashLevel; + } + +#nullable enable + public bool Equals(Module.PlayerAndLevel that) + { + + var ___eqId = this.Id.Equals(that.Id); +var ___eqIdentity = this.Identity.Equals(that.Identity); +var ___eqName = this.Name == null ? that.Name == null : this.Name.Equals(that.Name); +var ___eqLevel = this.Level.Equals(that.Level); + return ___eqId && + ___eqIdentity && + ___eqName && + ___eqLevel; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as Module.PlayerAndLevel?; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (Module.PlayerAndLevel this_, Module.PlayerAndLevel that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (Module.PlayerAndLevel this_, Module.PlayerAndLevel that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // PlayerAndLevel +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnEnum.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnEnum.cs new file mode 100644 index 00000000000..c0be7c689e0 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnEnum.cs @@ -0,0 +1,68 @@ +// +#nullable enable + +partial record ReturnEnum : System.IEquatable { + + public sealed record A(uint A_) : ReturnEnum + { + public override string ToString() => + $"A({ SpacetimeDB.BSATN.StringUtil.GenericToString(A_) })"; + } + + public sealed record B(string B_) : ReturnEnum + { + public override string ToString() => + $"B({ SpacetimeDB.BSATN.StringUtil.GenericToString(B_) })"; + } + + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U32 ARW = new(); + internal static readonly SpacetimeDB.BSATN.String BRW = new(); + + public ReturnEnum Read(System.IO.BinaryReader reader) { + return reader.ReadByte() switch { + 0 => new A(ARW.Read(reader)), + 1 => new B(BRW.Read(reader)), + _ => throw new System.InvalidOperationException("Invalid tag value, this state should be unreachable.") + }; + } + + public void Write(System.IO.BinaryWriter writer, ReturnEnum value) { + switch (value) { + case A(var inner): + writer.Write((byte)0); + ARW.Write(writer, inner); + break; + case B(var inner): + writer.Write((byte)1); + BRW.Write(writer, inner); + break; + } + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Sum(new SpacetimeDB.BSATN.AggregateElement[] { + new("A", ARW.GetAlgebraicType(registrar)), + new("B", BRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + switch (this) { + case A(var inner): + var ___hashA = inner.GetHashCode(); + return ___hashA; + case B(var inner): + var ___hashB = inner == null ? 0 : inner.GetHashCode(); + return ___hashB; + default: + return 0; + } + } + +} // ReturnEnum diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnStruct.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnStruct.cs new file mode 100644 index 00000000000..e87eeaf0aed --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.BSATN.Codegen/SpacetimeDB.Codegen.Type/ReturnStruct.cs @@ -0,0 +1,90 @@ +// +#nullable enable + +partial class ReturnStruct : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + A = BSATN.ARW.Read(reader); + B = BSATN.BRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) { + BSATN.ARW.Write(writer, A); + BSATN.BRW.Write(writer, B); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"ReturnStruct {{ A = {SpacetimeDB.BSATN.StringUtil.GenericToString(A)}, B = {SpacetimeDB.BSATN.StringUtil.GenericToString(B)} }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U32 ARW = new(); + internal static readonly SpacetimeDB.BSATN.String BRW = new(); + + public ReturnStruct Read(System.IO.BinaryReader reader) { + var ___result = new ReturnStruct(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, ReturnStruct value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + new("A", ARW.GetAlgebraicType(registrar)), + new("B", BRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashA = A.GetHashCode(); +var ___hashB = B == null ? 0 : B.GetHashCode(); +return ___hashA ^ + ___hashB; + } + +#nullable enable + public bool Equals(ReturnStruct? that) + { + if (((object?)that) == null) { return false; } + + var ___eqA = this.A.Equals(that.A); +var ___eqB = this.B == null ? that.B == null : this.B.Equals(that.B); + return ___eqA && + ___eqB; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as ReturnStruct; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (ReturnStruct? this_, ReturnStruct? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (ReturnStruct? this_, ReturnStruct? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // ReturnStruct diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs new file mode 100644 index 00000000000..0eb7b97016d --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/FFI.cs @@ -0,0 +1,1037 @@ +// +#nullable enable +// The runtime already defines SpacetimeDB.Internal.LocalReadOnly in Runtime\Internal\Module.cs as an empty partial type. +// This is needed so every module build doesn't generate a full LocalReadOnly type, but just adds on to the existing. +// We extend it here with generated table accessors, and just need to suppress the duplicate-type warning. +#pragma warning disable CS0436 +#pragma warning disable STDB_UNSTABLE + +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal = SpacetimeDB.Internal; +using TxContext = SpacetimeDB.Internal.TxContext; + +namespace SpacetimeDB { + public sealed record ReducerContext : DbContext, Internal.IReducerContext { + public readonly Identity Sender; + public readonly ConnectionId? ConnectionId; + public readonly Random Rng; + public readonly Timestamp Timestamp; + public readonly AuthCtx SenderAuth; + + // We need this property to be non-static for parity with client SDK. + public Identity Identity => Internal.IReducerContext.GetIdentity(); + + internal ReducerContext(Identity identity, ConnectionId? connectionId, Random random, + Timestamp time, AuthCtx? senderAuth = null) + { + Sender = identity; + ConnectionId = connectionId; + Rng = random; + Timestamp = time; + SenderAuth = senderAuth ?? AuthCtx.BuildFromSystemTables(connectionId, identity); + } + } + + public sealed partial class ProcedureContext : global::SpacetimeDB.ProcedureContextBase { + private readonly Local _db = new(); + + internal ProcedureContext(Identity identity, ConnectionId? connectionId, Random random, Timestamp time) + : base(identity, connectionId, random, time) {} + + protected override global::SpacetimeDB.LocalBase CreateLocal() => _db; + protected override global::SpacetimeDB.ProcedureTxContextBase CreateTxContext(Internal.TxContext inner) => + _cached ??= new ProcedureTxContext(inner); + + private ProcedureTxContext? _cached; + + [Experimental("STDB_UNSTABLE")] + public Local Db => _db; + + [Experimental("STDB_UNSTABLE")] + public TResult WithTx(Func body) => + base.WithTx(tx => body((ProcedureTxContext)tx)); + + [Experimental("STDB_UNSTABLE")] + public TxOutcome TryWithTx( + Func> body) + where TError : Exception => + base.TryWithTx(tx => body((ProcedureTxContext)tx)); + } + + [Experimental("STDB_UNSTABLE")] + public sealed class ProcedureTxContext : global::SpacetimeDB.ProcedureTxContextBase { + internal ProcedureTxContext(Internal.TxContext inner) : base(inner) {} + + public new Local Db => (Local)base.Db; + } + + public sealed class Local : global::SpacetimeDB.LocalBase { + public global::SpacetimeDB.Internal.TableHandles.example_data example_data => new(); +public global::SpacetimeDB.Internal.TableHandles.my_table my_table => new(); +public global::SpacetimeDB.Internal.TableHandles.player player => new(); +public global::SpacetimeDB.Internal.TableHandles.player_level player_level => new(); +public global::SpacetimeDB.Internal.TableHandles.retry_log retry_log => new(); + } + + public sealed class LocalReadOnly : global::SpacetimeDB.LocalReadOnlyBase { + public global::SpacetimeDB.Internal.ViewHandles.example_dataReadOnly example_data => new(); +public global::SpacetimeDB.Internal.ViewHandles.my_tableReadOnly my_table => new(); +public global::SpacetimeDB.Internal.ViewHandles.player_levelReadOnly player_level => new(); +public global::SpacetimeDB.Internal.ViewHandles.playerReadOnly player => new(); +public global::SpacetimeDB.Internal.ViewHandles.retry_logReadOnly retry_log => new(); + } + + public sealed record ViewContext : DbContext, Internal.IViewContext + { + public Identity Sender { get; } + internal ViewContext(Identity sender, LocalReadOnly db) : base(db) => Sender = sender; + } + + public sealed record AnonymousViewContext : DbContext, Internal.IAnonymousViewContext { + internal AnonymousViewContext(LocalReadOnly db) : base(db) { } + } +} + +namespace SpacetimeDB.Internal.TableHandles { + public readonly struct example_data : global::SpacetimeDB.Internal.ITableView { + static global::Module.ExampleData global::SpacetimeDB.Internal.ITableView.ReadGenFields(System.IO.BinaryReader reader, global::Module.ExampleData row) { + + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + Name: nameof(example_data), + ProductTypeRef: (uint) new global::Module.ExampleData.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: [ + new( + Name: null, + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) +), +new( + Name: null, + AccessorName: "Indexed", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) +) + ], + Constraints: [ + global::SpacetimeDB.Internal.ITableView.MakeUniqueConstraint(0) +], + Sequences: [ + +], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public + ); + + public ulong Count => global::SpacetimeDB.Internal.ITableView.DoCount(); + public IEnumerable Iter() => global::SpacetimeDB.Internal.ITableView.DoIter(); + public global::Module.ExampleData Insert(global::Module.ExampleData row) => global::SpacetimeDB.Internal.ITableView.DoInsert(row); + public bool Delete(global::Module.ExampleData row) => global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public sealed class IdUniqueIndex : UniqueIndex { + internal IdUniqueIndex() : base("example_data_Id_idx_btree") {} + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Module.ExampleData? Find(uint key) => DoFilter(key).Cast().SingleOrDefault(); + public global::Module.ExampleData Update(global::Module.ExampleData row) => DoUpdate(row); +} +public IdUniqueIndex Id => new(); + public sealed class IndexedIndex() : SpacetimeDB.Internal.IndexBase("example_data_Indexed_idx_btree") { + public IEnumerable Filter(uint Indexed) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(Indexed)); + + public ulong Delete(uint Indexed) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(Indexed)); + + public IEnumerable Filter(Bound Indexed) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(Indexed)); + + public ulong Delete(Bound Indexed) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(Indexed)); + +} + public IndexedIndex Indexed => new(); + +} +public readonly struct my_table : global::SpacetimeDB.Internal.ITableView { + static global::Module.MyTable global::SpacetimeDB.Internal.ITableView.ReadGenFields(System.IO.BinaryReader reader, global::Module.MyTable row) { + + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + Name: nameof(my_table), + ProductTypeRef: (uint) new global::Module.MyTable.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [ + + ], + Constraints: [ + +], + Sequences: [ + +], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public + ); + + public ulong Count => global::SpacetimeDB.Internal.ITableView.DoCount(); + public IEnumerable Iter() => global::SpacetimeDB.Internal.ITableView.DoIter(); + public global::Module.MyTable Insert(global::Module.MyTable row) => global::SpacetimeDB.Internal.ITableView.DoInsert(row); + public bool Delete(global::Module.MyTable row) => global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + +} +public readonly struct player : global::SpacetimeDB.Internal.ITableView { + static global::Module.Player global::SpacetimeDB.Internal.ITableView.ReadGenFields(System.IO.BinaryReader reader, global::Module.Player row) { + if (row.Id == default) +{ + row.Id = global::Module.Player.BSATN.IdRW.Read(reader); +} + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + Name: nameof(player), + ProductTypeRef: (uint) new global::Module.Player.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: [ + new( + Name: null, + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) +), +new( + Name: null, + AccessorName: "Identity", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) +) + ], + Constraints: [ + global::SpacetimeDB.Internal.ITableView.MakeUniqueConstraint(0), +global::SpacetimeDB.Internal.ITableView.MakeUniqueConstraint(1) +], + Sequences: [ + global::SpacetimeDB.Internal.ITableView.MakeSequence(0) +], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public + ); + + public ulong Count => global::SpacetimeDB.Internal.ITableView.DoCount(); + public IEnumerable Iter() => global::SpacetimeDB.Internal.ITableView.DoIter(); + public global::Module.Player Insert(global::Module.Player row) => global::SpacetimeDB.Internal.ITableView.DoInsert(row); + public bool Delete(global::Module.Player row) => global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public sealed class IdUniqueIndex : UniqueIndex { + internal IdUniqueIndex() : base("player_Id_idx_btree") {} + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Module.Player? Find(ulong key) => DoFilter(key).Cast().SingleOrDefault(); + public global::Module.Player Update(global::Module.Player row) => DoUpdate(row); +} +public IdUniqueIndex Id => new(); +public sealed class IdentityUniqueIndex : UniqueIndex { + internal IdentityUniqueIndex() : base("player_Identity_idx_btree") {} + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Module.Player? Find(SpacetimeDB.Identity key) => DoFilter(key).Cast().SingleOrDefault(); + public global::Module.Player Update(global::Module.Player row) => DoUpdate(row); +} +public IdentityUniqueIndex Identity => new(); +} +public readonly struct player_level : global::SpacetimeDB.Internal.ITableView { + static global::Module.PlayerLevel global::SpacetimeDB.Internal.ITableView.ReadGenFields(System.IO.BinaryReader reader, global::Module.PlayerLevel row) { + + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + Name: nameof(player_level), + ProductTypeRef: (uint) new global::Module.PlayerLevel.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [], + Indexes: [ + new( + Name: null, + AccessorName: "PlayerId", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) +), +new( + Name: null, + AccessorName: "Level", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([1]) +) + ], + Constraints: [ + global::SpacetimeDB.Internal.ITableView.MakeUniqueConstraint(0) +], + Sequences: [ + +], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public + ); + + public ulong Count => global::SpacetimeDB.Internal.ITableView.DoCount(); + public IEnumerable Iter() => global::SpacetimeDB.Internal.ITableView.DoIter(); + public global::Module.PlayerLevel Insert(global::Module.PlayerLevel row) => global::SpacetimeDB.Internal.ITableView.DoInsert(row); + public bool Delete(global::Module.PlayerLevel row) => global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public sealed class PlayerIdUniqueIndex : UniqueIndex { + internal PlayerIdUniqueIndex() : base("player_level_PlayerId_idx_btree") {} + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Module.PlayerLevel? Find(ulong key) => DoFilter(key).Cast().SingleOrDefault(); + public global::Module.PlayerLevel Update(global::Module.PlayerLevel row) => DoUpdate(row); +} +public PlayerIdUniqueIndex PlayerId => new(); + public sealed class LevelIndex() : SpacetimeDB.Internal.IndexBase("player_level_Level_idx_btree") { + public IEnumerable Filter(ulong Level) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(Level)); + + public ulong Delete(ulong Level) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(Level)); + + public IEnumerable Filter(Bound Level) => + DoFilter(new SpacetimeDB.Internal.BTreeIndexBounds(Level)); + + public ulong Delete(Bound Level) => + DoDelete(new SpacetimeDB.Internal.BTreeIndexBounds(Level)); + +} + public LevelIndex Level => new(); + +} +public readonly struct retry_log : global::SpacetimeDB.Internal.ITableView { + static global::Module.RetryLog global::SpacetimeDB.Internal.ITableView.ReadGenFields(System.IO.BinaryReader reader, global::Module.RetryLog row) { + + return row; + } + + static SpacetimeDB.Internal.RawTableDefV9 global::SpacetimeDB.Internal.ITableView.MakeTableDesc(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + Name: nameof(retry_log), + ProductTypeRef: (uint) new global::Module.RetryLog.BSATN().GetAlgebraicType(registrar).Ref_, + PrimaryKey: [0], + Indexes: [ + new( + Name: null, + AccessorName: "Id", + Algorithm: new SpacetimeDB.Internal.RawIndexAlgorithm.BTree([0]) +) + ], + Constraints: [ + global::SpacetimeDB.Internal.ITableView.MakeUniqueConstraint(0) +], + Sequences: [ + +], + Schedule: null, + TableType: SpacetimeDB.Internal.TableType.User, + TableAccess: SpacetimeDB.Internal.TableAccess.Public + ); + + public ulong Count => global::SpacetimeDB.Internal.ITableView.DoCount(); + public IEnumerable Iter() => global::SpacetimeDB.Internal.ITableView.DoIter(); + public global::Module.RetryLog Insert(global::Module.RetryLog row) => global::SpacetimeDB.Internal.ITableView.DoInsert(row); + public bool Delete(global::Module.RetryLog row) => global::SpacetimeDB.Internal.ITableView.DoDelete(row); + + public sealed class IdUniqueIndex : UniqueIndex { + internal IdUniqueIndex() : base("retry_log_Id_idx_btree") {} + // Important: don't move this to the base class. + // C# generics don't play well with nullable types and can't accept both struct-type-based and class-type-based + // `globalName` in one generic definition, leading to buggy `Row?` expansion for either one or another. + public global::Module.RetryLog? Find(uint key) => DoFilter(key).Cast().SingleOrDefault(); + public global::Module.RetryLog Update(global::Module.RetryLog row) => DoUpdate(row); +} +public IdUniqueIndex Id => new(); +} +} + +sealed class my_playerViewDispatcher : global::SpacetimeDB.Internal.IView { + + + public SpacetimeDB.Internal.RawViewDefV9 MakeViewDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) + => new global::SpacetimeDB.Internal.RawViewDefV9( + Name: "my_player", + Index: 0, + IsPublic: true, + IsAnonymous: false, + Params: [], + ReturnType: new SpacetimeDB.BSATN.ValueOption().GetAlgebraicType(registrar) +); + + public byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IViewContext ctx + ) { + try { + + var returnValue = Module.MyPlayer((SpacetimeDB.ViewContext)ctx); + var listSerializer = SpacetimeDB.BSATN.ValueOption.GetListSerializer(); + var listValue = ModuleRegistration.ToListOrEmpty(returnValue); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + listSerializer.Write(writer, listValue); + return output.ToArray(); + } catch (System.Exception e) { + global::SpacetimeDB.Log.Error("Error in view 'my_player': " + e); + throw; + } + } +} +sealed class players_at_level_oneViewDispatcher : global::SpacetimeDB.Internal.IAnonymousView { + + + public SpacetimeDB.Internal.RawViewDefV9 MakeAnonymousViewDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) + => new global::SpacetimeDB.Internal.RawViewDefV9( + Name: "players_at_level_one", + Index: 0, + IsPublic: true, + IsAnonymous: true, + Params: [], + ReturnType: new SpacetimeDB.BSATN.List().GetAlgebraicType(registrar) +); + + public byte[] Invoke( + System.IO.BinaryReader reader, + global::SpacetimeDB.Internal.IAnonymousViewContext ctx + ) { + try { + + var returnValue = Module.PlayersAtLevelOne((SpacetimeDB.AnonymousViewContext)ctx); + SpacetimeDB.BSATN.List returnRW = new(); + using var output = new System.IO.MemoryStream(); + using var writer = new System.IO.BinaryWriter(output); + returnRW.Write(writer, returnValue); + return output.ToArray(); + } catch (System.Exception e) { + global::SpacetimeDB.Log.Error("Error in view 'players_at_level_one': " + e); + throw; + } + } +} + +namespace SpacetimeDB.Internal.ViewHandles { + public sealed class example_dataReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView +{ + internal example_dataReadOnly() : base("example_data") { } + + public ulong Count => DoCount(); + + public sealed class IdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Internal.ViewHandles.example_dataReadOnly, + global::Module.ExampleData, + uint, + SpacetimeDB.BSATN.U32> +{ + internal IdIndex() : base("example_data_Id_idx_btree") { } + + public global::Module.ExampleData? Find(uint key) => FindSingle(key); +} + +public IdIndex Id => new(); +public sealed class IndexedIndex +: global::SpacetimeDB.Internal.ReadOnlyIndexBase +{ +internal IndexedIndex() : base("example_data_Indexed_idx_btree") {} +public IEnumerable Filter(uint Indexed) => + DoFilter(new global::SpacetimeDB.Internal.BTreeIndexBounds(Indexed)); + +public IEnumerable Filter(global::SpacetimeDB.Internal.Bound Indexed) => + DoFilter(new global::SpacetimeDB.Internal.BTreeIndexBounds(Indexed)); +} +public IndexedIndex Indexed => new(); +} +public sealed class my_tableReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView +{ + internal my_tableReadOnly() : base("my_table") { } + + public ulong Count => DoCount(); + + +} +public sealed class player_levelReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView +{ + internal player_levelReadOnly() : base("player_level") { } + + public ulong Count => DoCount(); + + public sealed class PlayerIdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Internal.ViewHandles.player_levelReadOnly, + global::Module.PlayerLevel, + ulong, + SpacetimeDB.BSATN.U64> +{ + internal PlayerIdIndex() : base("player_level_PlayerId_idx_btree") { } + + public global::Module.PlayerLevel? Find(ulong key) => FindSingle(key); +} + +public PlayerIdIndex PlayerId => new(); +public sealed class LevelIndex +: global::SpacetimeDB.Internal.ReadOnlyIndexBase +{ +internal LevelIndex() : base("player_level_Level_idx_btree") {} +public IEnumerable Filter(ulong Level) => + DoFilter(new global::SpacetimeDB.Internal.BTreeIndexBounds(Level)); + +public IEnumerable Filter(global::SpacetimeDB.Internal.Bound Level) => + DoFilter(new global::SpacetimeDB.Internal.BTreeIndexBounds(Level)); +} +public LevelIndex Level => new(); +} +public sealed class playerReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView +{ + internal playerReadOnly() : base("player") { } + + public ulong Count => DoCount(); + + public sealed class IdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Internal.ViewHandles.playerReadOnly, + global::Module.Player, + ulong, + SpacetimeDB.BSATN.U64> +{ + internal IdIndex() : base("player_Id_idx_btree") { } + + public global::Module.Player? Find(ulong key) => FindSingle(key); +} + +public IdIndex Id => new(); +public sealed class IdentityIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Internal.ViewHandles.playerReadOnly, + global::Module.Player, + SpacetimeDB.Identity, + SpacetimeDB.Identity.BSATN> +{ + internal IdentityIndex() : base("player_Identity_idx_btree") { } + + public global::Module.Player? Find(SpacetimeDB.Identity key) => FindSingle(key); +} + +public IdentityIndex Identity => new(); +} +public sealed class retry_logReadOnly + : global::SpacetimeDB.Internal.ReadOnlyTableView +{ + internal retry_logReadOnly() : base("retry_log") { } + + public ulong Count => DoCount(); + + public sealed class IdIndex + : global::SpacetimeDB.Internal.ReadOnlyUniqueIndex< + global::SpacetimeDB.Internal.ViewHandles.retry_logReadOnly, + global::Module.RetryLog, + uint, + SpacetimeDB.BSATN.U32> +{ + internal IdIndex() : base("retry_log_Id_idx_btree") { } + + public global::Module.RetryLog? Find(uint key) => FindSingle(key); +} + +public IdIndex Id => new(); +} +} + +static class ModuleRegistration { + class Add: SpacetimeDB.Internal.IReducer { + private static readonly SpacetimeDB.BSATN.U32 idRW = new(); + private static readonly SpacetimeDB.BSATN.U32 indexedRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + nameof(Add), + [new("id", idRW.GetAlgebraicType(registrar)), + new("indexed", indexedRW.GetAlgebraicType(registrar))], + null + ); + + public void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) { + Module.Add((SpacetimeDB.ReducerContext)ctx, idRW.Read(reader), indexedRW.Read(reader)); + } +} +class ClientConnected: SpacetimeDB.Internal.IReducer { + + + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + nameof(ClientConnected), + [], + SpacetimeDB.Internal.Lifecycle.OnConnect + ); + + public void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) { + Module.ClientConnected((SpacetimeDB.ReducerContext)ctx); + } +} +class Delete: SpacetimeDB.Internal.IReducer { + private static readonly SpacetimeDB.BSATN.U32 idRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + nameof(Delete), + [new("id", idRW.GetAlgebraicType(registrar))], + null + ); + + public void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) { + Module.Delete((SpacetimeDB.ReducerContext)ctx, idRW.Read(reader)); + } +} +class ThrowError: SpacetimeDB.Internal.IReducer { + private static readonly SpacetimeDB.BSATN.String errorRW = new(); + + public SpacetimeDB.Internal.RawReducerDefV9 MakeReducerDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new ( + nameof(ThrowError), + [new("error", errorRW.GetAlgebraicType(registrar))], + null + ); + + public void Invoke(BinaryReader reader, SpacetimeDB.Internal.IReducerContext ctx) { + Module.ThrowError((SpacetimeDB.ReducerContext)ctx, errorRW.Read(reader)); + } +} + + class AuthenticationCapabilities : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(AuthenticationCapabilities), + [], + new ReturnStruct.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var result = Module.AuthenticationCapabilities((SpacetimeDB.ProcedureContext)ctx); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnStruct.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class DanglingTxWarning : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(DanglingTxWarning), + [], + SpacetimeDB.BSATN.AlgebraicType.Unit + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + Module.DanglingTxWarning((SpacetimeDB.ProcedureContext)ctx); + return System.Array.Empty(); + } +} +class DocumentationGapChecks : SpacetimeDB.Internal.IProcedure { + private static readonly SpacetimeDB.BSATN.U32 inputValueRW = new(); + private static readonly SpacetimeDB.BSATN.String inputTextRW = new(); + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(DocumentationGapChecks), + [new("inputValue", inputValueRW.GetAlgebraicType(registrar)), + new("inputText", inputTextRW.GetAlgebraicType(registrar))], + new ReturnStruct.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var inputValue = inputValueRW.Read(reader); + var inputText = inputTextRW.Read(reader); + var result = Module.DocumentationGapChecks((SpacetimeDB.ProcedureContext)ctx, inputValue, inputText); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnStruct.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class InsertWithTxCommit : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(InsertWithTxCommit), + [], + SpacetimeDB.BSATN.AlgebraicType.Unit + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + Module.InsertWithTxCommit((SpacetimeDB.ProcedureContext)ctx); + return System.Array.Empty(); + } +} +class InsertWithTxPanic : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(InsertWithTxPanic), + [], + SpacetimeDB.BSATN.AlgebraicType.Unit + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + Module.InsertWithTxPanic((SpacetimeDB.ProcedureContext)ctx); + return System.Array.Empty(); + } +} +class InsertWithTxRetry : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(InsertWithTxRetry), + [], + new SpacetimeDB.BSATN.U32().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var result = Module.InsertWithTxRetry((SpacetimeDB.ProcedureContext)ctx); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new SpacetimeDB.BSATN.U32().Write(writer, result); + return output.ToArray(); + } +} +class InsertWithTxRollback : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(InsertWithTxRollback), + [], + SpacetimeDB.BSATN.AlgebraicType.Unit + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + Module.InsertWithTxRollback((SpacetimeDB.ProcedureContext)ctx); + return System.Array.Empty(); + } +} +class ReturnEnumA : SpacetimeDB.Internal.IProcedure { + private static readonly SpacetimeDB.BSATN.U32 aRW = new(); + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(ReturnEnumA), + [new("a", aRW.GetAlgebraicType(registrar))], + new ReturnEnum.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var a = aRW.Read(reader); + var result = Module.ReturnEnumA((SpacetimeDB.ProcedureContext)ctx, a); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnEnum.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class ReturnEnumB : SpacetimeDB.Internal.IProcedure { + private static readonly SpacetimeDB.BSATN.String bRW = new(); + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(ReturnEnumB), + [new("b", bRW.GetAlgebraicType(registrar))], + new ReturnEnum.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var b = bRW.Read(reader); + var result = Module.ReturnEnumB((SpacetimeDB.ProcedureContext)ctx, b); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnEnum.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class ReturnPrimitive : SpacetimeDB.Internal.IProcedure { + private static readonly SpacetimeDB.BSATN.U32 lhsRW = new(); + private static readonly SpacetimeDB.BSATN.U32 rhsRW = new(); + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(ReturnPrimitive), + [new("lhs", lhsRW.GetAlgebraicType(registrar)), + new("rhs", rhsRW.GetAlgebraicType(registrar))], + new SpacetimeDB.BSATN.U32().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var lhs = lhsRW.Read(reader); + var rhs = rhsRW.Read(reader); + var result = Module.ReturnPrimitive((SpacetimeDB.ProcedureContext)ctx, lhs, rhs); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new SpacetimeDB.BSATN.U32().Write(writer, result); + return output.ToArray(); + } +} +class ReturnStructProcedure : SpacetimeDB.Internal.IProcedure { + private static readonly SpacetimeDB.BSATN.U32 aRW = new(); + private static readonly SpacetimeDB.BSATN.String bRW = new(); + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(ReturnStructProcedure), + [new("a", aRW.GetAlgebraicType(registrar)), + new("b", bRW.GetAlgebraicType(registrar))], + new ReturnStruct.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var a = aRW.Read(reader); + var b = bRW.Read(reader); + var result = Module.ReturnStructProcedure((SpacetimeDB.ProcedureContext)ctx, a, b); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnStruct.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class SleepUntilTimestampUpdate : SpacetimeDB.Internal.IProcedure { + private static readonly SpacetimeDB.BSATN.U32 sleepMillisRW = new(); + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(SleepUntilTimestampUpdate), + [new("sleepMillis", sleepMillisRW.GetAlgebraicType(registrar))], + new ReturnStruct.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var sleepMillis = sleepMillisRW.Read(reader); + var result = Module.SleepUntilTimestampUpdate((SpacetimeDB.ProcedureContext)ctx, sleepMillis); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnStruct.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class SubscriptionEventOffset : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(SubscriptionEventOffset), + [], + new ReturnStruct.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var result = Module.SubscriptionEventOffset((SpacetimeDB.ProcedureContext)ctx); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnStruct.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class TimestampCapabilities : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(TimestampCapabilities), + [], + new ReturnStruct.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var result = Module.TimestampCapabilities((SpacetimeDB.ProcedureContext)ctx); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnStruct.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class TxContextCapabilities : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(TxContextCapabilities), + [], + new ReturnStruct.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var result = Module.TxContextCapabilities((SpacetimeDB.ProcedureContext)ctx); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new ReturnStruct.BSATN().Write(writer, result); + return output.ToArray(); + } +} +class WillPanic : SpacetimeDB.Internal.IProcedure { + + + public SpacetimeDB.Internal.RawProcedureDefV9 MakeProcedureDef(SpacetimeDB.BSATN.ITypeRegistrar registrar) => new( + nameof(WillPanic), + [], + new SpacetimeDB.Unit.BSATN().GetAlgebraicType(registrar) + ); + + public byte[] Invoke(BinaryReader reader, SpacetimeDB.Internal.IProcedureContext ctx) { + var result = Module.WillPanic((SpacetimeDB.ProcedureContext)ctx); + using var output = new MemoryStream(); + using var writer = new BinaryWriter(output); + new SpacetimeDB.Unit.BSATN().Write(writer, result); + return output.ToArray(); + } +} + + public static List ToListOrEmpty(T? value) where T : struct + => value is null ? new List() : new List { value.Value }; + +#if EXPERIMENTAL_WASM_AOT + // In AOT mode we're building a library. + // Main method won't be called automatically, so we need to export it as a preinit function. + [UnmanagedCallersOnly(EntryPoint = "__preinit__10_init_csharp")] +#else + // Prevent trimming of FFI exports that are invoked from C and not visible to C# trimmer. + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(SpacetimeDB.Internal.Module))] +#endif + public static void Main() { + SpacetimeDB.Internal.Module.SetReducerContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ReducerContext(identity, connectionId, random, time)); + SpacetimeDB.Internal.Module.SetViewContextConstructor(identity => new SpacetimeDB.ViewContext(identity, new SpacetimeDB.LocalReadOnly())); + SpacetimeDB.Internal.Module.SetAnonymousViewContextConstructor(() => new SpacetimeDB.AnonymousViewContext(new SpacetimeDB.LocalReadOnly())); + SpacetimeDB.Internal.Module.SetProcedureContextConstructor((identity, connectionId, random, time) => new SpacetimeDB.ProcedureContext(identity, connectionId, random, time)); + var __memoryStream = new MemoryStream(); + var __writer = new BinaryWriter(__memoryStream); + + SpacetimeDB.Internal.Module.RegisterReducer(); +SpacetimeDB.Internal.Module.RegisterReducer(); +SpacetimeDB.Internal.Module.RegisterReducer(); +SpacetimeDB.Internal.Module.RegisterReducer(); + SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); +SpacetimeDB.Internal.Module.RegisterProcedure(); + + // IMPORTANT: The order in which we register views matters. + // It must correspond to the order in which we call `GenerateDispatcherClass`. + // See the comment on `GenerateDispatcherClass` for more explanation. + SpacetimeDB.Internal.Module.RegisterView(); +SpacetimeDB.Internal.Module.RegisterAnonymousView(); + + SpacetimeDB.Internal.Module.RegisterTable(); +SpacetimeDB.Internal.Module.RegisterTable(); +SpacetimeDB.Internal.Module.RegisterTable(); +SpacetimeDB.Internal.Module.RegisterTable(); +SpacetimeDB.Internal.Module.RegisterTable(); + + + } + +// Exports only work from the main assembly, so we need to generate forwarding methods. +#if EXPERIMENTAL_WASM_AOT + [UnmanagedCallersOnly(EntryPoint = "__describe_module__")] + public static void __describe_module__(SpacetimeDB.Internal.BytesSink d) => SpacetimeDB.Internal.Module.__describe_module__(d); + + [UnmanagedCallersOnly(EntryPoint = "__call_reducer__")] + public static SpacetimeDB.Internal.Errno __call_reducer__( + uint id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink error + ) => SpacetimeDB.Internal.Module.__call_reducer__( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + error + ); + + [UnmanagedCallersOnly(EntryPoint = "__call_procedure__")] + public static SpacetimeDB.Internal.Errno __call_procedure__( + uint id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + ulong conn_id_0, + ulong conn_id_1, + SpacetimeDB.Timestamp timestamp, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink result_sink + ) => SpacetimeDB.Internal.Module.__call_procedure__( + id, + sender_0, + sender_1, + sender_2, + sender_3, + conn_id_0, + conn_id_1, + timestamp, + args, + result_sink + ); + + [UnmanagedCallersOnly(EntryPoint = "__take_procedure_tx_offset__")] + public static byte __take_procedure_tx_offset__(ulong* offset) => + SpacetimeDB.Internal.Module.__take_procedure_tx_offset__(out *offset) ? (byte)1 : (byte)0; + + [UnmanagedCallersOnly(EntryPoint = "__call_view__")] + public static SpacetimeDB.Internal.Errno __call_view__( + uint id, + ulong sender_0, + ulong sender_1, + ulong sender_2, + ulong sender_3, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => SpacetimeDB.Internal.Module.__call_view__( + id, + sender_0, + sender_1, + sender_2, + sender_3, + args, + sink + ); + + [UnmanagedCallersOnly(EntryPoint = "__call_view_anon__")] + public static SpacetimeDB.Internal.Errno __call_view_anon__( + uint id, + SpacetimeDB.Internal.BytesSource args, + SpacetimeDB.Internal.BytesSink sink + ) => SpacetimeDB.Internal.Module.__call_view_anon__( + id, + args, + sink + ); +#endif +} + +#pragma warning restore STDB_UNSTABLE +#pragma warning restore CS0436 \ No newline at end of file diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Add.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Add.cs new file mode 100644 index 00000000000..b3f546d3985 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Add.cs @@ -0,0 +1,14 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateAdd(uint id, uint indexed) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.U32().Write(writer, id); +new SpacetimeDB.BSATN.U32().Write(writer, indexed); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof(Add), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.AuthenticationCapabilities.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.AuthenticationCapabilities.cs new file mode 100644 index 00000000000..a95faa4b343 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.AuthenticationCapabilities.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateAuthenticationCapabilities() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(AuthenticationCapabilities), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ClientConnected.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ClientConnected.cs new file mode 100644 index 00000000000..cd736a2e538 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ClientConnected.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateClientConnected() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof(ClientConnected), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DanglingTxWarning.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DanglingTxWarning.cs new file mode 100644 index 00000000000..c3b7cc6e668 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DanglingTxWarning.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateDanglingTxWarning() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(DanglingTxWarning), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Delete.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Delete.cs new file mode 100644 index 00000000000..abeba0fdd12 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Delete.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateDelete(uint id) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.U32().Write(writer, id); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof(Delete), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DocumentationGapChecks.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DocumentationGapChecks.cs new file mode 100644 index 00000000000..28e9e7a9c65 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.DocumentationGapChecks.cs @@ -0,0 +1,14 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateDocumentationGapChecks(uint inputValue, string inputText) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.U32().Write(writer, inputValue); +new SpacetimeDB.BSATN.String().Write(writer, inputText); + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(DocumentationGapChecks), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ExampleData.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ExampleData.cs new file mode 100644 index 00000000000..ca23e53d626 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ExampleData.cs @@ -0,0 +1,91 @@ +// +#nullable enable + +partial class Module { +partial struct ExampleData : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + Id = BSATN.IdRW.Read(reader); + Indexed = BSATN.IndexedRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) { + BSATN.IdRW.Write(writer, Id); + BSATN.IndexedRW.Write(writer, Indexed); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"ExampleData {{ Id = {SpacetimeDB.BSATN.StringUtil.GenericToString(Id)}, Indexed = {SpacetimeDB.BSATN.StringUtil.GenericToString(Indexed)} }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U32 IdRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 IndexedRW = new(); + + public Module.ExampleData Read(System.IO.BinaryReader reader) { + var ___result = new Module.ExampleData(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Module.ExampleData value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + new("Id", IdRW.GetAlgebraicType(registrar)), + new("Indexed", IndexedRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashId = Id.GetHashCode(); +var ___hashIndexed = Indexed.GetHashCode(); +return ___hashId ^ + ___hashIndexed; + } + +#nullable enable + public bool Equals(Module.ExampleData that) + { + + var ___eqId = this.Id.Equals(that.Id); +var ___eqIndexed = this.Indexed.Equals(that.Indexed); + return ___eqId && + ___eqIndexed; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as Module.ExampleData?; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (Module.ExampleData this_, Module.ExampleData that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (Module.ExampleData this_, Module.ExampleData that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // ExampleData +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxCommit.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxCommit.cs new file mode 100644 index 00000000000..c9da768ddc4 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxCommit.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateInsertWithTxCommit() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(InsertWithTxCommit), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxPanic.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxPanic.cs new file mode 100644 index 00000000000..7c7b16f608b --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxPanic.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateInsertWithTxPanic() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(InsertWithTxPanic), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRetry.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRetry.cs new file mode 100644 index 00000000000..27cc2018533 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRetry.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateInsertWithTxRetry() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(InsertWithTxRetry), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRollback.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRollback.cs new file mode 100644 index 00000000000..297f759eeb0 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.InsertWithTxRollback.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateInsertWithTxRollback() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(InsertWithTxRollback), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.MyTable.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.MyTable.cs new file mode 100644 index 00000000000..730a7f13ed4 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.MyTable.cs @@ -0,0 +1,83 @@ +// +#nullable enable + +partial class Module { +partial struct MyTable : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + Field = BSATN.FieldRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) { + BSATN.FieldRW.Write(writer, Field); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"MyTable {{ Field = {SpacetimeDB.BSATN.StringUtil.GenericToString(Field)} }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly ReturnStruct.BSATN FieldRW = new(); + + public Module.MyTable Read(System.IO.BinaryReader reader) { + var ___result = new Module.MyTable(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Module.MyTable value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + new("Field", FieldRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashField = Field == null ? 0 : Field.GetHashCode(); +return ___hashField; + } + +#nullable enable + public bool Equals(Module.MyTable that) + { + + var ___eqField = this.Field == null ? that.Field == null : this.Field.Equals(that.Field); + return ___eqField; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as Module.MyTable?; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (Module.MyTable this_, Module.MyTable that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (Module.MyTable this_, Module.MyTable that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // MyTable +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Player.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Player.cs new file mode 100644 index 00000000000..bd88b36ae1c --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.Player.cs @@ -0,0 +1,99 @@ +// +#nullable enable + +partial class Module { +partial struct Player : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + Id = BSATN.IdRW.Read(reader); + Identity = BSATN.IdentityRW.Read(reader); + Name = BSATN.NameRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) { + BSATN.IdRW.Write(writer, Id); + BSATN.IdentityRW.Write(writer, Identity); + BSATN.NameRW.Write(writer, Name); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"Player {{ Id = {SpacetimeDB.BSATN.StringUtil.GenericToString(Id)}, Identity = {SpacetimeDB.BSATN.StringUtil.GenericToString(Identity)}, Name = {SpacetimeDB.BSATN.StringUtil.GenericToString(Name)} }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U64 IdRW = new(); + internal static readonly SpacetimeDB.Identity.BSATN IdentityRW = new(); + internal static readonly SpacetimeDB.BSATN.String NameRW = new(); + + public Module.Player Read(System.IO.BinaryReader reader) { + var ___result = new Module.Player(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Module.Player value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + new("Id", IdRW.GetAlgebraicType(registrar)), + new("Identity", IdentityRW.GetAlgebraicType(registrar)), + new("Name", NameRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashId = Id.GetHashCode(); +var ___hashIdentity = Identity.GetHashCode(); +var ___hashName = Name == null ? 0 : Name.GetHashCode(); +return ___hashId ^ + ___hashIdentity ^ + ___hashName; + } + +#nullable enable + public bool Equals(Module.Player that) + { + + var ___eqId = this.Id.Equals(that.Id); +var ___eqIdentity = this.Identity.Equals(that.Identity); +var ___eqName = this.Name == null ? that.Name == null : this.Name.Equals(that.Name); + return ___eqId && + ___eqIdentity && + ___eqName; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as Module.Player?; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (Module.Player this_, Module.Player that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (Module.Player this_, Module.Player that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // Player +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.PlayerLevel.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.PlayerLevel.cs new file mode 100644 index 00000000000..5e4665b7b69 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.PlayerLevel.cs @@ -0,0 +1,91 @@ +// +#nullable enable + +partial class Module { +partial struct PlayerLevel : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + PlayerId = BSATN.PlayerIdRW.Read(reader); + Level = BSATN.LevelRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) { + BSATN.PlayerIdRW.Write(writer, PlayerId); + BSATN.LevelRW.Write(writer, Level); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"PlayerLevel {{ PlayerId = {SpacetimeDB.BSATN.StringUtil.GenericToString(PlayerId)}, Level = {SpacetimeDB.BSATN.StringUtil.GenericToString(Level)} }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U64 PlayerIdRW = new(); + internal static readonly SpacetimeDB.BSATN.U64 LevelRW = new(); + + public Module.PlayerLevel Read(System.IO.BinaryReader reader) { + var ___result = new Module.PlayerLevel(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Module.PlayerLevel value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + new("PlayerId", PlayerIdRW.GetAlgebraicType(registrar)), + new("Level", LevelRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashPlayerId = PlayerId.GetHashCode(); +var ___hashLevel = Level.GetHashCode(); +return ___hashPlayerId ^ + ___hashLevel; + } + +#nullable enable + public bool Equals(Module.PlayerLevel that) + { + + var ___eqPlayerId = this.PlayerId.Equals(that.PlayerId); +var ___eqLevel = this.Level.Equals(that.Level); + return ___eqPlayerId && + ___eqLevel; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as Module.PlayerLevel?; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (Module.PlayerLevel this_, Module.PlayerLevel that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (Module.PlayerLevel this_, Module.PlayerLevel that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // PlayerLevel +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.RetryLog.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.RetryLog.cs new file mode 100644 index 00000000000..b12cc944082 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.RetryLog.cs @@ -0,0 +1,92 @@ +// +#nullable enable + +partial class Module { +partial class RetryLog : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + Id = BSATN.IdRW.Read(reader); + Attempts = BSATN.AttemptsRW.Read(reader); + } + + public void WriteFields(System.IO.BinaryWriter writer) { + BSATN.IdRW.Write(writer, Id); + BSATN.AttemptsRW.Write(writer, Attempts); + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"RetryLog {{ Id = {SpacetimeDB.BSATN.StringUtil.GenericToString(Id)}, Attempts = {SpacetimeDB.BSATN.StringUtil.GenericToString(Attempts)} }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + internal static readonly SpacetimeDB.BSATN.U32 IdRW = new(); + internal static readonly SpacetimeDB.BSATN.U32 AttemptsRW = new(); + + public Module.RetryLog Read(System.IO.BinaryReader reader) { + var ___result = new Module.RetryLog(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, Module.RetryLog value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + new("Id", IdRW.GetAlgebraicType(registrar)), + new("Attempts", AttemptsRW.GetAlgebraicType(registrar)) + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + var ___hashId = Id.GetHashCode(); +var ___hashAttempts = Attempts.GetHashCode(); +return ___hashId ^ + ___hashAttempts; + } + +#nullable enable + public bool Equals(Module.RetryLog? that) + { + if (((object?)that) == null) { return false; } + + var ___eqId = this.Id.Equals(that.Id); +var ___eqAttempts = this.Attempts.Equals(that.Attempts); + return ___eqId && + ___eqAttempts; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as Module.RetryLog; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (Module.RetryLog? this_, Module.RetryLog? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (Module.RetryLog? this_, Module.RetryLog? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // RetryLog +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumA.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumA.cs new file mode 100644 index 00000000000..ea805990c03 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumA.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateReturnEnumA(uint a) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.U32().Write(writer, a); + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(ReturnEnumA), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumB.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumB.cs new file mode 100644 index 00000000000..315effef0ad --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnEnumB.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateReturnEnumB(string b) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.String().Write(writer, b); + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(ReturnEnumB), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnPrimitive.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnPrimitive.cs new file mode 100644 index 00000000000..ffb306d2e1f --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnPrimitive.cs @@ -0,0 +1,14 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateReturnPrimitive(uint lhs, uint rhs) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.U32().Write(writer, lhs); +new SpacetimeDB.BSATN.U32().Write(writer, rhs); + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(ReturnPrimitive), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnStructProcedure.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnStructProcedure.cs new file mode 100644 index 00000000000..217cce2ecbe --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ReturnStructProcedure.cs @@ -0,0 +1,14 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateReturnStructProcedure(uint a, string b) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.U32().Write(writer, a); +new SpacetimeDB.BSATN.String().Write(writer, b); + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(ReturnStructProcedure), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SleepUntilTimestampUpdate.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SleepUntilTimestampUpdate.cs new file mode 100644 index 00000000000..1fd9dc01db1 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SleepUntilTimestampUpdate.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateSleepUntilTimestampUpdate(uint sleepMillis) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.U32().Write(writer, sleepMillis); + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(SleepUntilTimestampUpdate), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SubscriptionEventOffset.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SubscriptionEventOffset.cs new file mode 100644 index 00000000000..de12452a850 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.SubscriptionEventOffset.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateSubscriptionEventOffset() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(SubscriptionEventOffset), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ThrowError.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ThrowError.cs new file mode 100644 index 00000000000..c784c1c8971 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.ThrowError.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateThrowError(string error) { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + new SpacetimeDB.BSATN.String().Write(writer, error); + SpacetimeDB.Internal.IReducer.VolatileNonatomicScheduleImmediate(nameof(ThrowError), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TimestampCapabilities.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TimestampCapabilities.cs new file mode 100644 index 00000000000..769fba6cb09 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TimestampCapabilities.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateTimestampCapabilities() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(TimestampCapabilities), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TxContextCapabilities.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TxContextCapabilities.cs new file mode 100644 index 00000000000..b5c22c054c0 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.TxContextCapabilities.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateTxContextCapabilities() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(TxContextCapabilities), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.WillPanic.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.WillPanic.cs new file mode 100644 index 00000000000..ea1c3002c26 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/Module.WillPanic.cs @@ -0,0 +1,13 @@ +// +#nullable enable + +partial class Module { + +[System.Diagnostics.CodeAnalysis.Experimental("STDB_UNSTABLE")] +public static void VolatileNonatomicScheduleImmediateWillPanic() { + using var stream = new MemoryStream(); + using var writer = new BinaryWriter(stream); + + SpacetimeDB.Internal.IProcedure.VolatileNonatomicScheduleImmediate(nameof(WillPanic), stream); +} +} // Module diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/MyTable.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/MyTable.cs new file mode 100644 index 00000000000..894fc1f0929 --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/MyTable.cs @@ -0,0 +1,82 @@ +// +#nullable enable + +partial class MyTable : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + + } + + public void WriteFields(System.IO.BinaryWriter writer) { + + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"MyTable {{ }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + + + public MyTable Read(System.IO.BinaryReader reader) { + var ___result = new MyTable(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, MyTable value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + +return 0; + } + +#nullable enable + public bool Equals(MyTable? that) + { + if (((object?)that) == null) { return false; } + + + return true; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as MyTable; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (MyTable? this_, MyTable? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (MyTable? this_, MyTable? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // MyTable diff --git a/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/RetryLog.cs b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/RetryLog.cs new file mode 100644 index 00000000000..249f75b19ee --- /dev/null +++ b/sdks/csharp/examples~/regression-tests/server/Generated/SpacetimeDB.Codegen/SpacetimeDB.Codegen.Module/RetryLog.cs @@ -0,0 +1,82 @@ +// +#nullable enable + +partial class RetryLog : System.IEquatable, SpacetimeDB.BSATN.IStructuralReadWrite { + + public void ReadFields(System.IO.BinaryReader reader) { + + } + + public void WriteFields(System.IO.BinaryWriter writer) { + + } + + object SpacetimeDB.BSATN.IStructuralReadWrite.GetSerializer() { + return new BSATN(); + } + public override string ToString() => + $"RetryLog {{ }}"; + public readonly partial struct BSATN : SpacetimeDB.BSATN.IReadWrite + { + + + public RetryLog Read(System.IO.BinaryReader reader) { + var ___result = new RetryLog(); + ___result.ReadFields(reader); + return ___result; + } + + public void Write(System.IO.BinaryWriter writer, RetryLog value) { + value.WriteFields(writer); + } + + public SpacetimeDB.BSATN.AlgebraicType.Ref GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + registrar.RegisterType(_ => new SpacetimeDB.BSATN.AlgebraicType.Product(new SpacetimeDB.BSATN.AggregateElement[] { + + })); + + SpacetimeDB.BSATN.AlgebraicType SpacetimeDB.BSATN.IReadWrite.GetAlgebraicType(SpacetimeDB.BSATN.ITypeRegistrar registrar) => + GetAlgebraicType(registrar); + } + + public override int GetHashCode() + { + +return 0; + } + +#nullable enable + public bool Equals(RetryLog? that) + { + if (((object?)that) == null) { return false; } + + + return true; + } + + public override bool Equals(object? that) { + if (that == null) { + return false; + } + var that_ = that as RetryLog; + if (((object?)that_) == null) { + return false; + } + return Equals(that_); + } + + public static bool operator == (RetryLog? this_, RetryLog? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return object.Equals(this_, that); + } + return this_.Equals(that); + } + + public static bool operator != (RetryLog? this_, RetryLog? that) { + if (((object?)this_) == null || ((object?)that) == null) { + return !object.Equals(this_, that); + } + return !this_.Equals(that); + } +#nullable restore +} // RetryLog diff --git a/sdks/csharp/examples~/regression-tests/server/Lib.cs b/sdks/csharp/examples~/regression-tests/server/Lib.cs index 474a125ffe4..325172d51da 100644 --- a/sdks/csharp/examples~/regression-tests/server/Lib.cs +++ b/sdks/csharp/examples~/regression-tests/server/Lib.cs @@ -1,6 +1,7 @@ // Server module for regression tests. // Everything we're testing for happens SDK-side so this module is very uninteresting. +using System.Diagnostics; using SpacetimeDB; [SpacetimeDB.Type] @@ -28,14 +29,13 @@ public partial record ReturnEnum : SpacetimeDB.TaggedEnum<( string B )>; -[SpacetimeDB.Table(Name = "my_table", Public = true)] -public partial class MyTable -{ - public ReturnStruct Field { get; set; } = new(0, string.Empty); -} - public static partial class Module { + [SpacetimeDB.Table(Name = "my_table", Public = true)] + public partial struct MyTable + { + public ReturnStruct Field; + } [SpacetimeDB.Table(Name = "example_data", Public = true)] public partial struct ExampleData { @@ -86,8 +86,8 @@ public partial struct PlayerAndLevel } // Multiple rows: return a list - [SpacetimeDB.View(Name = "players_for_level", Public = true)] - public static List PlayersForLevel(AnonymousViewContext ctx) + [SpacetimeDB.View(Name = "players_at_level_one", Public = true)] + public static List PlayersAtLevelOne(AnonymousViewContext ctx) { var rows = new List(); foreach (var player in ctx.Db.player_level.Level.Filter(1)) @@ -182,9 +182,9 @@ public static void InsertWithTxCommit(ProcedureContext ctx) { tx.Db.my_table.Insert(new MyTable { - Field = new ReturnStruct(a: 42, b: "magic") + Field = new ReturnStruct(a: 42, b: "magic"), }); - return 0; // discard result + return 0; // return value ignored by WithTx }); AssertRowCount(ctx, 1); @@ -193,17 +193,18 @@ public static void InsertWithTxCommit(ProcedureContext ctx) [SpacetimeDB.Procedure] public static void InsertWithTxRollback(ProcedureContext ctx) { - var _ = ctx.TryWithTx(tx => + var outcome = ctx.TryWithTx(tx => { tx.Db.my_table.Insert(new MyTable { Field = new ReturnStruct(a: 42, b: "magic") }); - return SpacetimeDB.ProcedureContext.TxResult.Failure( + return ProcedureContext.TxResult.Failure( new InvalidOperationException("rollback")); }); + Debug.Assert(!outcome.IsSuccess, "TryWithTxAsync should report failure"); AssertRowCount(ctx, 0); } @@ -221,5 +222,369 @@ private static void AssertRowCount(ProcedureContext ctx, ulong expected) return 0; }); } + + [SpacetimeDB.Table(Name = "retry_log", Public = true)] + public partial class RetryLog + { + [SpacetimeDB.PrimaryKey] + public uint Id; + public uint Attempts; + } + + [SpacetimeDB.Procedure] + public static uint InsertWithTxRetry(ProcedureContext ctx) + { + const uint key = 1; + + var outcome = ctx.TryWithTx(tx => + { + var existing = tx.Db.retry_log.Id.Find(key); + + if (existing is null) + { + tx.Db.retry_log.Insert(new RetryLog { Id = key, Attempts = 1 }); + return ProcedureContext.TxResult.Failure(new Exception("conflict")); + } + + // Use the unique index Update method + var newAttempts = existing.Attempts + 1; + tx.Db.retry_log.Id.Update(new RetryLog { Id = key, Attempts = newAttempts }); + return ProcedureContext.TxResult.Success(newAttempts); + }); + + if (!outcome.IsSuccess) + { + throw outcome.Error ?? new InvalidOperationException("Retry failed without an error"); + } + + // Verify final state + var finalAttempts = ctx.WithTx(tx => + { + var final = tx.Db.retry_log.Id.Find(key); + return final?.Attempts ?? 0u; + }); + + return finalAttempts; + } + + [SpacetimeDB.Procedure] + public static void InsertWithTxPanic(ProcedureContext ctx) + { + try + { + ctx.WithTx(tx => + { + // Insert a row + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct(a: 99, b: "panic-test") + }); + + // Throw an exception to abort the transaction + throw new InvalidOperationException("panic abort"); + }); + } + catch (InvalidOperationException ex) when (ex.Message == "panic abort") + { + // Expected exception - transaction should be aborted + } + + // Verify no rows were inserted due to the exception + AssertRowCount(ctx, 0); + } + + [SpacetimeDB.Procedure] + public static void DanglingTxWarning(ProcedureContext ctx) + { + // This test demonstrates transaction cleanup when an unhandled exception occurs + // during transaction processing, which should trigger auto-abort behavior + + bool exceptionCaught = false; + + try + { + ctx.WithTx(tx => + { + // Insert a row + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct(a: 123, b: "dangling") + }); + + // Simulate an unexpected system exception that might leave transaction in limbo + // This should trigger the transaction cleanup/auto-abort mechanisms + throw new SystemException("Simulated system failure during transaction"); + }); + } + catch (SystemException) + { + exceptionCaught = true; + } + + // Verify the exception was caught and no rows were persisted + if (!exceptionCaught) + { + throw new InvalidOperationException("Expected SystemException was not thrown"); + } + + // Verify no rows were persisted due to transaction abort + AssertRowCount(ctx, 0); + } + + [SpacetimeDB.Procedure] + public static ReturnStruct TxContextCapabilities(ProcedureContext ctx) + { + var result = ctx.WithTx(tx => + { + // Test 1: Verify transaction context has database access + var initialCount = tx.Db.my_table.Count; + + // Test 2: Insert data and verify it's visible within the same transaction + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct(a: 200, b: "tx-test") + }); + + var countAfterInsert = tx.Db.my_table.Count; + if (countAfterInsert != initialCount + 1) + { + throw new InvalidOperationException($"Expected count {initialCount + 1}, got {countAfterInsert}"); + } + + // Test 3: Verify transaction context properties are accessible + // (These should match the procedure context properties) + var txSender = tx.Sender; + var txTimestamp = tx.Timestamp; + + if (txSender != ctx.Sender) + { + throw new InvalidOperationException("Transaction sender should match procedure sender"); + } + + // Test 4: Return data from within transaction + return new ReturnStruct(a: (uint)countAfterInsert, b: $"sender:{txSender}"); + }); + + // Verify the row was committed + AssertRowCount(ctx, 1); + + return result; + } + + [SpacetimeDB.Procedure] + public static ReturnStruct TimestampCapabilities(ProcedureContext ctx) + { + // Test 1: Verify timestamp is accessible from procedure context + var procedureTimestamp = ctx.Timestamp; + + var result = ctx.WithTx(tx => + { + // Test 2: Verify timestamp is accessible from transaction context + var txTimestamp = tx.Timestamp; + + // Test 3: Timestamps should be consistent within the same procedure call + if (txTimestamp != procedureTimestamp) + { + throw new InvalidOperationException( + $"Transaction timestamp {txTimestamp} should match procedure timestamp {procedureTimestamp}"); + } + + // Test 4: Insert data with timestamp information + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct( + a: (uint)(txTimestamp.MicrosecondsSinceUnixEpoch % uint.MaxValue), + b: $"timestamp:{txTimestamp.MicrosecondsSinceUnixEpoch}") + }); + + return new ReturnStruct( + a: (uint)(txTimestamp.MicrosecondsSinceUnixEpoch % uint.MaxValue), + b: txTimestamp.ToString()); + }); + + // Test 5: Verify timestamp is still accessible after transaction + var postTxTimestamp = ctx.Timestamp; + if (postTxTimestamp != procedureTimestamp) + { + throw new InvalidOperationException( + $"Post-transaction timestamp {postTxTimestamp} should match original timestamp {procedureTimestamp}"); + } + + return result; + } + + [SpacetimeDB.Procedure] + public static ReturnStruct SleepUntilTimestampUpdate(ProcedureContext ctx, uint sleepMillis) + { + var beforeTimestamp = ctx.Timestamp; + + // Since we can't actually sleep in a procedure, we'll simulate the concept + // by creating a target timestamp and demonstrating timestamp arithmetic + var targetMicros = beforeTimestamp.MicrosecondsSinceUnixEpoch + (sleepMillis * 1000); + var targetTime = new SpacetimeDB.Timestamp(targetMicros); + + // Get the current timestamp again (this will be very close to beforeTimestamp) + var afterTimestamp = ctx.Timestamp; + var elapsedMicros = afterTimestamp.MicrosecondsSinceUnixEpoch - beforeTimestamp.MicrosecondsSinceUnixEpoch; + + return ctx.WithTx(tx => { + tx.Db.my_table.Insert(new MyTable { + Field = new ReturnStruct( + a: (uint)(elapsedMicros / 1000), // Convert back to milliseconds + b: $"target:{targetTime.MicrosecondsSinceUnixEpoch}:actual:{afterTimestamp.MicrosecondsSinceUnixEpoch}" + ) + }); + return new ReturnStruct( + a: (uint)(elapsedMicros / 1000), // Convert back to milliseconds + b: $"simulated-sleep:{sleepMillis}ms" + ); + }); + } + + [SpacetimeDB.Procedure] + public static ReturnStruct AuthenticationCapabilities(ProcedureContext ctx) + { + // Test 1: Verify authentication context is accessible from procedure context + var procAuth = ctx.SenderAuth; + var procSender = ctx.Sender; + var procConnectionId = ctx.ConnectionId; + + var result = ctx.WithTx(tx => + { + // Test 2: Verify authentication context is accessible from transaction context + var txAuth = tx.SenderAuth; + var txSender = tx.Sender; + var txConnectionId = tx.ConnectionId; + + // Test 3: Authentication contexts should be consistent + if (txSender != procSender) + { + throw new InvalidOperationException( + $"Transaction sender {txSender} should match procedure sender {procSender}"); + } + + if (txConnectionId != procConnectionId) + { + throw new InvalidOperationException( + $"Transaction connectionId {txConnectionId} should match procedure connectionId {procConnectionId}"); + } + + // Test 4: Insert data with authentication information + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct( + a: (uint)(txSender.GetHashCode() & 0xFF), + b: $"auth:sender:{txSender}:conn:{txConnectionId}") + }); + + // Test 5: Check JWT claims (if available) + var jwtInfo = "no-jwt"; + try + { + var jwt = txAuth.Jwt; + if (jwt != null) + { + jwtInfo = $"jwt:present:identity:{jwt.Identity}"; + } + } + catch + { + // JWT may not be available in test environment + jwtInfo = "jwt:unavailable"; + } + + return new ReturnStruct( + a: (uint)(txSender.GetHashCode() & 0xFF), + b: jwtInfo); + }); + + return result; + } + + [SpacetimeDB.Procedure] + public static ReturnStruct SubscriptionEventOffset(ProcedureContext ctx) + { + // This procedure tests that subscription events carry transaction offset information + // We'll insert data and return information that helps verify the transaction offset + + var result = ctx.WithTx(tx => + { + // Insert a row that will trigger subscription events + var testData = new MyTable + { + Field = new ReturnStruct( + a: 999, // Use a distinctive value to identify this test + b: $"offset-test:{tx.Timestamp.MicrosecondsSinceUnixEpoch}") + }; + + tx.Db.my_table.Insert(testData); + + // Return data that can be used to correlate with subscription events + return new ReturnStruct( + a: 999, + b: $"committed:{tx.Timestamp.MicrosecondsSinceUnixEpoch}"); + }); + + // At this point, the transaction should be committed and subscription events + // should be generated with the transaction offset information + + return result; + } + + [SpacetimeDB.Procedure] + public static ReturnStruct DocumentationGapChecks(ProcedureContext ctx, uint inputValue, string inputText) + { + // This procedure tests various documentation gaps and edge cases + // Test 1: Parameter handling - procedures can accept multiple parameters + if (inputValue == 0) + { + throw new ArgumentException("inputValue cannot be zero"); + } + + if (string.IsNullOrEmpty(inputText)) + { + throw new ArgumentException("inputText cannot be null or empty"); + } + + var result = ctx.WithTx(tx => + { + // Test 2: Multiple database operations in single transaction + var count = tx.Db.my_table.Count; + + // Test 3: Conditional logic based on database state + if (count > 10) + { + // Don't insert if too many rows + return new ReturnStruct( + a: (uint)count, + b: $"skipped:too-many-rows:{count}"); + } + + // Test 4: Complex data manipulation + var processedValue = inputValue * 2 + (uint)inputText.Length; + + tx.Db.my_table.Insert(new MyTable + { + Field = new ReturnStruct( + a: processedValue, + b: $"doc-gap:{inputText}:processed:{processedValue}") + }); + + // Test 5: Return computed results + return new ReturnStruct( + a: processedValue, + b: $"success:input:{inputText}:result:{processedValue}"); + }); + + // Test 6: Post-transaction validation + var finalCount = ctx.WithTx(tx => tx.Db.my_table.Count); + + if (finalCount <= 0) + { + throw new InvalidOperationException("Expected at least one row after transaction"); + } + + return result; + } #pragma warning restore STDB_UNSTABLE } diff --git a/sdks/csharp/src/Event.cs b/sdks/csharp/src/Event.cs index 60cba010195..47b4de3178d 100644 --- a/sdks/csharp/src/Event.cs +++ b/sdks/csharp/src/Event.cs @@ -26,7 +26,7 @@ public interface IErrorContext public interface IProcedureEventContext { - + public ProcedureEvent Event { get; } } // The following underscores are needed to work around c#'s unified type-and-function // namespace.