diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index a0d9c7bb..18d240a7 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,12 +17,12 @@ jobs: with: dotnet-version: 6.0.x - # - uses: edgedb/setup-edgedb@v1.2.2 - # with: - # server-version: stable - # instance-name: EdgeDB_Dotnet_Test + - uses: edgedb/setup-edgedb@v1 + with: + server-version: stable + instance-name: edgedb_dotnet_tests - # - run: edgedb instance list + - run: edgedb instance list - name: Restore dependencies run: dotnet restore @@ -33,5 +33,5 @@ jobs: - name: Unit test run: dotnet test ./tests/EdgeDB.Tests.Unit --no-build --verbosity normal - # - name: Integration Tests - # run: dotnet test ./tests/EdgeDB.Tests.Integration --no-build --verbosity normal + - name: Integration Tests + run: dotnet test ./tests/EdgeDB.Tests.Integration --no-build --verbosity diag diff --git a/.gitignore b/.gitignore index 2c69ae7b..ab85d255 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,10 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore +# test coverage +tests/EdgeDB.Tests.Integration/coveragereports +CoverageReport + # User-specific files *.rsuser *.suo diff --git a/EdgeDB.Net.sln b/EdgeDB.Net.sln index 0e0e480a..9074979f 100644 --- a/EdgeDB.Net.sln +++ b/EdgeDB.Net.sln @@ -5,12 +5,10 @@ VisualStudioVersion = 17.1.31903.286 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Net.Driver", "src\EdgeDB.Net.Driver\EdgeDB.Net.Driver.csproj", "{0C1C6233-388F-4FAE-955B-F0A6D33D44C9}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Examples.ExampleApp", "examples\EdgeDB.Examples.ExampleApp\EdgeDB.Examples.ExampleApp.csproj", "{B85156A1-66B3-46F1-B238-19B96C4C7729}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Examples.CSharp", "examples\EdgeDB.Examples.CSharp\EdgeDB.Examples.CSharp.csproj", "{B85156A1-66B3-46F1-B238-19B96C4C7729}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Tests.Unit", "tests\EdgeDB.Tests.Unit\EdgeDB.Tests.Unit.csproj", "{CD4A4B5D-4B67-4E64-A13B-3F7BF770B056}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Net.QueryBuilder", "src\EdgeDB.Net.QueryBuilder\EdgeDB.Net.QueryBuilder.csproj", "{4CC2101C-D0AB-4F08-A0FD-205F96958196}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{025AAADF-16AF-4367-9C3D-9E60EDED832F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{E6B9FABC-241B-4561-9A94-E67B6BE380E2}" @@ -29,13 +27,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Tests.Benchmarks", " EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.BinaryDebugger", "tools\EdgeDB.BinaryDebugger\EdgeDB.BinaryDebugger.csproj", "{3A4AAAA0-9948-43D3-B838-8EFAC130240C}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Experiments", "Experiments", "{49B6FB80-A675-4ECA-802C-2337A4F37566}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Serializer.Experiments", "experiments\EdgeDB.Serializer.Experiments\EdgeDB.Serializer.Experiments.csproj", "{6FA68DEA-D398-4A5B-8025-5F15C728F04C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EdgeDB.Examples.ExampleTODOApi", "examples\EdgeDB.Examples.ExampleTODOApi\EdgeDB.Examples.ExampleTODOApi.csproj", "{E38429C6-53A5-4311-8189-1F78238666DC}" EndProject -Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "EdgeDB.Example.FSharp", "examples\EdgeDB.Example.FSharp\EdgeDB.Example.FSharp.fsproj", "{F25AA805-163F-46B4-942E-B1A5EBE8383C}" +Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "EdgeDB.Examples.FSharp", "examples\EdgeDB.Examples.FSharp\EdgeDB.Examples.FSharp.fsproj", "{F25AA805-163F-46B4-942E-B1A5EBE8383C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -55,10 +49,6 @@ Global {CD4A4B5D-4B67-4E64-A13B-3F7BF770B056}.Debug|Any CPU.Build.0 = Debug|Any CPU {CD4A4B5D-4B67-4E64-A13B-3F7BF770B056}.Release|Any CPU.ActiveCfg = Release|Any CPU {CD4A4B5D-4B67-4E64-A13B-3F7BF770B056}.Release|Any CPU.Build.0 = Release|Any CPU - {4CC2101C-D0AB-4F08-A0FD-205F96958196}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4CC2101C-D0AB-4F08-A0FD-205F96958196}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4CC2101C-D0AB-4F08-A0FD-205F96958196}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4CC2101C-D0AB-4F08-A0FD-205F96958196}.Release|Any CPU.Build.0 = Release|Any CPU {1557B745-EB4F-449A-9BE7-180C8990AD47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1557B745-EB4F-449A-9BE7-180C8990AD47}.Debug|Any CPU.Build.0 = Debug|Any CPU {1557B745-EB4F-449A-9BE7-180C8990AD47}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -79,10 +69,6 @@ Global {3A4AAAA0-9948-43D3-B838-8EFAC130240C}.Debug|Any CPU.Build.0 = Debug|Any CPU {3A4AAAA0-9948-43D3-B838-8EFAC130240C}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A4AAAA0-9948-43D3-B838-8EFAC130240C}.Release|Any CPU.Build.0 = Release|Any CPU - {6FA68DEA-D398-4A5B-8025-5F15C728F04C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6FA68DEA-D398-4A5B-8025-5F15C728F04C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6FA68DEA-D398-4A5B-8025-5F15C728F04C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6FA68DEA-D398-4A5B-8025-5F15C728F04C}.Release|Any CPU.Build.0 = Release|Any CPU {E38429C6-53A5-4311-8189-1F78238666DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E38429C6-53A5-4311-8189-1F78238666DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {E38429C6-53A5-4311-8189-1F78238666DC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -99,13 +85,11 @@ Global {0C1C6233-388F-4FAE-955B-F0A6D33D44C9} = {025AAADF-16AF-4367-9C3D-9E60EDED832F} {B85156A1-66B3-46F1-B238-19B96C4C7729} = {6FC214F5-C912-4D99-91B1-3E9F52A4E11B} {CD4A4B5D-4B67-4E64-A13B-3F7BF770B056} = {E6B9FABC-241B-4561-9A94-E67B6BE380E2} - {4CC2101C-D0AB-4F08-A0FD-205F96958196} = {025AAADF-16AF-4367-9C3D-9E60EDED832F} {1557B745-EB4F-449A-9BE7-180C8990AD47} = {67ED9EF0-7828-44C0-8CB0-DEBD69EC94CA} {74DB9D5E-9BA9-4282-90EA-2F7BDC4C4FBD} = {67ED9EF0-7828-44C0-8CB0-DEBD69EC94CA} {C189294A-4990-4A06-B120-A0AF03A798C6} = {E6B9FABC-241B-4561-9A94-E67B6BE380E2} {5FFD1E88-614D-409B-8420-F9571AC7CA60} = {E6B9FABC-241B-4561-9A94-E67B6BE380E2} {3A4AAAA0-9948-43D3-B838-8EFAC130240C} = {67ED9EF0-7828-44C0-8CB0-DEBD69EC94CA} - {6FA68DEA-D398-4A5B-8025-5F15C728F04C} = {49B6FB80-A675-4ECA-802C-2337A4F37566} {E38429C6-53A5-4311-8189-1F78238666DC} = {6FC214F5-C912-4D99-91B1-3E9F52A4E11B} {F25AA805-163F-46B4-942E-B1A5EBE8383C} = {6FC214F5-C912-4D99-91B1-3E9F52A4E11B} EndGlobalSection diff --git a/EdgeDB.Net.targets b/EdgeDB.Net.targets index b705df19..f4de332a 100644 --- a/EdgeDB.Net.targets +++ b/EdgeDB.Net.targets @@ -1,6 +1,6 @@ - 0.3.3 + 1.0.0 latest EdgeDB.Net Contributors edgedb;db;database diff --git a/dbschema/default.esdl b/dbschema/default.esdl index e440bc13..8a518d0b 100644 --- a/dbschema/default.esdl +++ b/dbschema/default.esdl @@ -39,4 +39,12 @@ module default { type OtherThing extending AbstractThing { required property attribute -> str; } + + # for type converter example + type UserWithSnowflakeId { + required property user_id -> str { + constraint exclusive; + } + required property username -> str; + } } diff --git a/dbschema/migrations/00010.edgeql b/dbschema/migrations/00010.edgeql new file mode 100644 index 00000000..387dcf79 --- /dev/null +++ b/dbschema/migrations/00010.edgeql @@ -0,0 +1,8 @@ +CREATE MIGRATION m1wuplszy5bldaagiqypo6nsdwikppnvhtmkosmksmkl3eipujwloq + ONTO m1yp62tfavybznmg6ywpi7xkbf77ue7ezaubpye7btyv2pco4okf7q +{ + CREATE TYPE default::UserWithSnowflakeId { + CREATE REQUIRED PROPERTY user_id -> std::str; + CREATE REQUIRED PROPERTY username -> std::str; + }; +}; diff --git a/dbschema/migrations/00011.edgeql b/dbschema/migrations/00011.edgeql new file mode 100644 index 00000000..84d8fc0c --- /dev/null +++ b/dbschema/migrations/00011.edgeql @@ -0,0 +1,9 @@ +CREATE MIGRATION m1cpqrhf5f5vdvux4bsgtljnq2sicll7vz4sfmjmztr5ilwgymzc5a + ONTO m1wuplszy5bldaagiqypo6nsdwikppnvhtmkosmksmkl3eipujwloq +{ + ALTER TYPE default::UserWithSnowflakeId { + ALTER PROPERTY user_id { + CREATE CONSTRAINT std::exclusive; + }; + }; +}; diff --git a/examples/EdgeDB.Examples.ExampleApp/EdgeDB.Examples.ExampleApp.csproj b/examples/EdgeDB.Examples.CSharp/EdgeDB.Examples.CSharp.csproj similarity index 89% rename from examples/EdgeDB.Examples.ExampleApp/EdgeDB.Examples.ExampleApp.csproj rename to examples/EdgeDB.Examples.CSharp/EdgeDB.Examples.CSharp.csproj index 24dbf600..2bd25a18 100644 --- a/examples/EdgeDB.Examples.ExampleApp/EdgeDB.Examples.ExampleApp.csproj +++ b/examples/EdgeDB.Examples.CSharp/EdgeDB.Examples.CSharp.csproj @@ -18,7 +18,6 @@ - diff --git a/examples/EdgeDB.Examples.ExampleApp/ExampleRunner.cs b/examples/EdgeDB.Examples.CSharp/ExampleRunner.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/ExampleRunner.cs rename to examples/EdgeDB.Examples.CSharp/ExampleRunner.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/AbstractTypes.cs b/examples/EdgeDB.Examples.CSharp/Examples/AbstractTypes.cs similarity index 97% rename from examples/EdgeDB.Examples.ExampleApp/Examples/AbstractTypes.cs rename to examples/EdgeDB.Examples.CSharp/Examples/AbstractTypes.cs index 29688fd7..520cae12 100644 --- a/examples/EdgeDB.Examples.ExampleApp/Examples/AbstractTypes.cs +++ b/examples/EdgeDB.Examples.CSharp/Examples/AbstractTypes.cs @@ -1,4 +1,5 @@ -using Microsoft.Extensions.Logging; +using EdgeDB.State; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/BasicQueryFunctions.cs b/examples/EdgeDB.Examples.CSharp/Examples/BasicQueryFunctions.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/Examples/BasicQueryFunctions.cs rename to examples/EdgeDB.Examples.CSharp/Examples/BasicQueryFunctions.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/CancelQueries.cs b/examples/EdgeDB.Examples.CSharp/Examples/CancelQueries.cs similarity index 70% rename from examples/EdgeDB.Examples.ExampleApp/Examples/CancelQueries.cs rename to examples/EdgeDB.Examples.CSharp/Examples/CancelQueries.cs index a7a0a447..3217210c 100644 --- a/examples/EdgeDB.Examples.ExampleApp/Examples/CancelQueries.cs +++ b/examples/EdgeDB.Examples.CSharp/Examples/CancelQueries.cs @@ -13,18 +13,16 @@ internal class CancelQueries : IExample public async Task ExecuteAsync(EdgeDBClient client) { - await using var singleClient = await client.GetOrCreateClientAsync(); - var tokenSource = new CancellationTokenSource(); tokenSource.CancelAfter(TimeSpan.FromTicks(5)); try { - await singleClient.QueryRequiredSingleAsync("select \"Hello, World\"", token: tokenSource.Token); + await client.QueryRequiredSingleAsync("select \"Hello, World\"", token: tokenSource.Token); } catch (OperationCanceledException) { - Logger!.LogInformation("Got task cancelled exception, client is connected? {Conn}", singleClient.IsConnected); + Logger!.LogInformation("Got task cancelled exception"); } } } diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/CustomDeserializer.cs b/examples/EdgeDB.Examples.CSharp/Examples/CustomDeserializer.cs similarity index 94% rename from examples/EdgeDB.Examples.ExampleApp/Examples/CustomDeserializer.cs rename to examples/EdgeDB.Examples.CSharp/Examples/CustomDeserializer.cs index e86470a8..c4c3a934 100644 --- a/examples/EdgeDB.Examples.ExampleApp/Examples/CustomDeserializer.cs +++ b/examples/EdgeDB.Examples.CSharp/Examples/CustomDeserializer.cs @@ -1,4 +1,5 @@ -using EdgeDB.Serializer; +using EdgeDB.Binary; +using EdgeDB.Binary.Builders; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -78,8 +79,10 @@ public async Task ExecuteAsync(EdgeDBClient client) }); // Define a custom creator for the 'PersonImmutable' type - TypeBuilder.AddOrUpdateTypeFactory(data => + TypeBuilder.AddOrUpdateTypeFactory((ref ObjectEnumerator enumerator) => { + var data = (IDictionary)enumerator.ToDynamic()!; + Logger?.LogInformation("Custom factory was called"); return new PersonImpl { diff --git a/examples/EdgeDB.Examples.CSharp/Examples/CustomTypeConverters.cs b/examples/EdgeDB.Examples.CSharp/Examples/CustomTypeConverters.cs new file mode 100644 index 00000000..9bbe1dc8 --- /dev/null +++ b/examples/EdgeDB.Examples.CSharp/Examples/CustomTypeConverters.cs @@ -0,0 +1,44 @@ +using EdgeDB.TypeConverters; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.ExampleApp.Examples +{ + internal class CustomTypeConverters : IExample + { + public ILogger? Logger { get; set; } + + public class UserWithSnowflakeId + { + public ulong UserId { get; set; } + public string? Username { get; set; } + } + + public class UlongTypeConverter : EdgeDBTypeConverter + { + public override ulong ConvertFrom(string? value) + { + if (value is null) + return 0; + + return ulong.Parse(value); + } + + public override string? ConvertTo(ulong value) + { + return value.ToString(); + } + } + + public async Task ExecuteAsync(EdgeDBClient client) + { + var user = await client.QueryAsync("with u := (insert UserWithSnowflakeId { user_id := \"841451783728529451\", username := \"example\" } unless conflict on .user_id else (select UserWithSnowflakeId)) select u { user_id, username }"); + + Logger!.LogInformation("User with snowflake id: {@User}", user); + } + } +} diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/DumpAndRestore.cs b/examples/EdgeDB.Examples.CSharp/Examples/DumpAndRestore.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/Examples/DumpAndRestore.cs rename to examples/EdgeDB.Examples.CSharp/Examples/DumpAndRestore.cs diff --git a/examples/EdgeDB.Examples.CSharp/Examples/GlobalsAndConfig.cs b/examples/EdgeDB.Examples.CSharp/Examples/GlobalsAndConfig.cs new file mode 100644 index 00000000..e156c2dd --- /dev/null +++ b/examples/EdgeDB.Examples.CSharp/Examples/GlobalsAndConfig.cs @@ -0,0 +1,27 @@ +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.ExampleApp.Examples +{ + internal class GlobalsAndConfig : IExample + { + public ILogger? Logger { get; set; } + + public async Task ExecuteAsync(EdgeDBClient baseClient) + { + var client = baseClient + .WithConfig(conf => conf.AllowDMLInFunctions = true) + .WithGlobals(new Dictionary + { + { "current_user_id", Guid.NewGuid() } + }); + + var result = await client.QueryRequiredSingleAsync("select global current_user_id"); + Logger!.LogInformation("CurrentUserId: {@Id}", result); + } + } +} diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/JsonResults.cs b/examples/EdgeDB.Examples.CSharp/Examples/JsonResults.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/Examples/JsonResults.cs rename to examples/EdgeDB.Examples.CSharp/Examples/JsonResults.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/LinksExample.cs b/examples/EdgeDB.Examples.CSharp/Examples/LinksExample.cs similarity index 97% rename from examples/EdgeDB.Examples.ExampleApp/Examples/LinksExample.cs rename to examples/EdgeDB.Examples.CSharp/Examples/LinksExample.cs index 4c4d2cee..feba5deb 100644 --- a/examples/EdgeDB.Examples.ExampleApp/Examples/LinksExample.cs +++ b/examples/EdgeDB.Examples.CSharp/Examples/LinksExample.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; @@ -51,11 +51,10 @@ public async Task ExecuteAsync(EdgeDBClient client) var selectMovieQuery = "select Movie {title, year, director: {name, email}, actors: {name, email}} filter .title = 'Inception'"; await client.ExecuteAsync(createMovieQuery).ConfigureAwait(false); - - + // select it var movie = await client.QueryRequiredSingleAsync(selectMovieQuery).ConfigureAwait(false); - + Logger?.LogInformation("Movie: {@Movie}", movie); } } diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/QueryResults.cs b/examples/EdgeDB.Examples.CSharp/Examples/QueryResults.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/Examples/QueryResults.cs rename to examples/EdgeDB.Examples.CSharp/Examples/QueryResults.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/Range.cs b/examples/EdgeDB.Examples.CSharp/Examples/Range.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/Examples/Range.cs rename to examples/EdgeDB.Examples.CSharp/Examples/Range.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/Records.cs b/examples/EdgeDB.Examples.CSharp/Examples/Records.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/Examples/Records.cs rename to examples/EdgeDB.Examples.CSharp/Examples/Records.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/Transactions.cs b/examples/EdgeDB.Examples.CSharp/Examples/Transactions.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/Examples/Transactions.cs rename to examples/EdgeDB.Examples.CSharp/Examples/Transactions.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/IExample.cs b/examples/EdgeDB.Examples.CSharp/IExample.cs similarity index 100% rename from examples/EdgeDB.Examples.ExampleApp/IExample.cs rename to examples/EdgeDB.Examples.CSharp/IExample.cs diff --git a/examples/EdgeDB.Examples.ExampleApp/Program.cs b/examples/EdgeDB.Examples.CSharp/Program.cs similarity index 83% rename from examples/EdgeDB.Examples.ExampleApp/Program.cs rename to examples/EdgeDB.Examples.CSharp/Program.cs index e8f593a1..adedbdb9 100644 --- a/examples/EdgeDB.Examples.ExampleApp/Program.cs +++ b/examples/EdgeDB.Examples.CSharp/Program.cs @@ -1,4 +1,4 @@ -using EdgeDB; +using EdgeDB; using EdgeDB.ExampleApp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -20,7 +20,10 @@ loggingBuilder.AddSerilog(dispose: true); }); - services.AddEdgeDB(); + services.AddEdgeDB(configure: config => + { + config.SchemaNamingStrategy = INamingStrategy.SnakeCaseNamingStrategy; + }); services.AddSingleton(); }).Build(); diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/Globals.cs b/examples/EdgeDB.Examples.ExampleApp/Examples/Globals.cs deleted file mode 100644 index 6c7ec873..00000000 --- a/examples/EdgeDB.Examples.ExampleApp/Examples/Globals.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB.ExampleApp.Examples -{ - internal class Globals : IExample - { - public ILogger? Logger { get; set; } - - public async Task ExecuteAsync(EdgeDBClient client) - { - // get or create a client singleton with the state configuring delegate. - // Note: the set state we define here is only for that instances default lifetime. - // When the client is returned to the pool, the state is reset. - await using var clientInstance = await client.GetOrCreateClientAsync(state => - { - state.WithGlobals(new Dictionary - { - {"current_user_id", Guid.NewGuid() } - }); - }); - - // select out the global - var result = await clientInstance.QuerySingleAsync("select global current_user_id"); - - Logger?.LogInformation("Selected Global: {@Global}", result); - } - } -} diff --git a/examples/EdgeDB.Examples.ExampleApp/Examples/Reconnection.cs b/examples/EdgeDB.Examples.ExampleApp/Examples/Reconnection.cs deleted file mode 100644 index 8bc080bd..00000000 --- a/examples/EdgeDB.Examples.ExampleApp/Examples/Reconnection.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB.ExampleApp.Examples -{ - internal class Reconnection : IExample - { - public ILogger? Logger { get; set; } - - public async Task ExecuteAsync(EdgeDBClient client) - { - // reconnect a single client - await using (var singleClinet = await client.GetOrCreateClientAsync().ConfigureAwait(false)) - { - await singleClinet.ReconnectAsync(); - - Logger!.LogInformation("Reconnected client is connected: {Connected}", singleClinet.IsConnected); - } - - Logger!.LogInformation("Current clients before disconnect: {Clients}", client.ConnectedClients); - - // disconnect all clients - await client.DisconnectAllAsync(); - - Logger!.LogInformation("Current clients after disconnect: {Clients}", client.ConnectedClients); - } - } -} diff --git a/examples/EdgeDB.Example.FSharp/EdgeDB.Example.FSharp.fsproj b/examples/EdgeDB.Examples.FSharp/EdgeDB.Examples.FSharp.fsproj similarity index 100% rename from examples/EdgeDB.Example.FSharp/EdgeDB.Example.FSharp.fsproj rename to examples/EdgeDB.Examples.FSharp/EdgeDB.Examples.FSharp.fsproj diff --git a/examples/EdgeDB.Example.FSharp/Program.fs b/examples/EdgeDB.Examples.FSharp/Program.fs similarity index 89% rename from examples/EdgeDB.Example.FSharp/Program.fs rename to examples/EdgeDB.Examples.FSharp/Program.fs index 5d4da196..1e5aa5b0 100644 --- a/examples/EdgeDB.Example.FSharp/Program.fs +++ b/examples/EdgeDB.Examples.FSharp/Program.fs @@ -2,7 +2,7 @@ open EdgeDB type Person = { Name: string; - Email: option; + Email: ValueOption; } let client = new EdgeDBClient() diff --git a/experiments/EdgeDB.Serializer.Experiments/DummyPacket.cs b/experiments/EdgeDB.Serializer.Experiments/DummyPacket.cs deleted file mode 100644 index c71bbacb..00000000 --- a/experiments/EdgeDB.Serializer.Experiments/DummyPacket.cs +++ /dev/null @@ -1,43 +0,0 @@ -using EdgeDB.Binary; -using EdgeDB.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, Pack = 0)] - public readonly unsafe struct DummyPacket - { - [MarshalAs(UnmanagedType.I1)] - public readonly ServerMessageType Type; - - [MarshalAs(UnmanagedType.U4)] - public readonly uint Length; - - [MarshalAs(UnmanagedType.U4)] - public readonly uint NameLength; - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] - public readonly byte* NameValue; - - public readonly uint ValueLength; - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] - public readonly byte* ValueValue; - - //public readonly Bytes Name; - //public readonly Bytes Value; - - - } - - [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public unsafe readonly ref struct Bytes - { - public readonly uint Length; - [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] - public readonly byte* Data; - } -} diff --git a/experiments/EdgeDB.Serializer.Experiments/EdgeDB.Serializer.Experiments.csproj b/experiments/EdgeDB.Serializer.Experiments/EdgeDB.Serializer.Experiments.csproj deleted file mode 100644 index ed275497..00000000 --- a/experiments/EdgeDB.Serializer.Experiments/EdgeDB.Serializer.Experiments.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - Exe - net6.0 - enable - enable - true - - - - - - - diff --git a/experiments/EdgeDB.Serializer.Experiments/Program.cs b/experiments/EdgeDB.Serializer.Experiments/Program.cs deleted file mode 100644 index c85f1b4b..00000000 --- a/experiments/EdgeDB.Serializer.Experiments/Program.cs +++ /dev/null @@ -1,17 +0,0 @@ -using EdgeDB; -using EdgeDB.Models; -using EdgeDB.Utils; -using System.Text; - - -var packet = EdgeDB.Utils.HexConverter.FromHex("4B000000C6-000000D-73797374656D5F636F6E666967000000AD00000071F2F5594609176568E2521789EE64F97F0200000000000000000000000000000100020000000000000000000000000000010E01F2F5594609176568E2521789EE64F97F00020000000141000000026964000000000000410000001473657373696F6E5F69646C655F74696D656F75740001000000340000000200000B8600000010172097A439F411E9B1899321EB2F4B97000040490000001000000000039387000000000000000000"); - - -unsafe -{ - fixed (byte* ptr = packet) - { - var p = (DummyPacket*)ptr; - - } -} \ No newline at end of file diff --git a/experiments/EdgeDB.Serializer.Experiments/Serializer.cs b/experiments/EdgeDB.Serializer.Experiments/Serializer.cs deleted file mode 100644 index c9561be7..00000000 --- a/experiments/EdgeDB.Serializer.Experiments/Serializer.cs +++ /dev/null @@ -1,23 +0,0 @@ -using EdgeDB.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - internal unsafe class Serializer - { - //public static ServerMessageType* Deserialize() - //{ - // var packet = new DummyPacket(); - - // var addr = &packet; - - // var p = (ServerMessageType*)addr; - - // return p; - //} - } -} diff --git a/src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBDeserializerAttribute.cs b/src/EdgeDB.Net.Driver/Attributes/EdgeDBDeserializerAttribute.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBDeserializerAttribute.cs rename to src/EdgeDB.Net.Driver/Attributes/EdgeDBDeserializerAttribute.cs diff --git a/src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBIgnoreAttribute.cs b/src/EdgeDB.Net.Driver/Attributes/EdgeDBIgnoreAttribute.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBIgnoreAttribute.cs rename to src/EdgeDB.Net.Driver/Attributes/EdgeDBIgnoreAttribute.cs diff --git a/src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBPropertyAttribute.cs b/src/EdgeDB.Net.Driver/Attributes/EdgeDBPropertyAttribute.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBPropertyAttribute.cs rename to src/EdgeDB.Net.Driver/Attributes/EdgeDBPropertyAttribute.cs diff --git a/src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBTypeAttribute.cs b/src/EdgeDB.Net.Driver/Attributes/EdgeDBTypeAttribute.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Serializer/Attributes/EdgeDBTypeAttribute.cs rename to src/EdgeDB.Net.Driver/Attributes/EdgeDBTypeAttribute.cs diff --git a/src/EdgeDB.Net.Driver/Attributes/EdgeDBTypeConverterAttribute.cs b/src/EdgeDB.Net.Driver/Attributes/EdgeDBTypeConverterAttribute.cs new file mode 100644 index 00000000..ece86e06 --- /dev/null +++ b/src/EdgeDB.Net.Driver/Attributes/EdgeDBTypeConverterAttribute.cs @@ -0,0 +1,43 @@ +using EdgeDB.TypeConverters; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB +{ + /// + /// Marks the current property to be deserialized/serialized with a specific + /// . + /// + [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] + public class EdgeDBTypeConverterAttribute : Attribute + { + internal IEdgeDBTypeConverter Converter; + + /// + /// Initializes the with the + /// specified . + /// + /// The type of the converter. + /// + /// is not a valid + /// . + /// + public EdgeDBTypeConverterAttribute(Type converterType) + { + if (converterType.GetInterface(nameof(IEdgeDBTypeConverter)) is null) + { + throw new ArgumentException("Converter type must implement IEdgeDBTypeConverter"); + } + + if (converterType.IsAbstract || converterType.IsInterface) + { + throw new ArgumentException("Converter type must be a concrete type"); + } + + Converter = (IEdgeDBTypeConverter)Activator.CreateInstance(converterType)!; + } + } +} diff --git a/src/EdgeDB.Net.Driver/Serializer/CodecBuilder.cs b/src/EdgeDB.Net.Driver/Binary/Builders/CodecBuilder.cs similarity index 55% rename from src/EdgeDB.Net.Driver/Serializer/CodecBuilder.cs rename to src/EdgeDB.Net.Driver/Binary/Builders/CodecBuilder.cs index 39dbda78..fbb52367 100644 --- a/src/EdgeDB.Net.Driver/Serializer/CodecBuilder.cs +++ b/src/EdgeDB.Net.Driver/Binary/Builders/CodecBuilder.cs @@ -1,5 +1,4 @@ -using EdgeDB.Binary; -using EdgeDB.Codecs; +using EdgeDB.Binary.Codecs; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -8,9 +7,9 @@ using System.Text; using System.Threading.Tasks; -namespace EdgeDB +namespace EdgeDB.Binary { - internal class CodecInfo + internal sealed class CodecInfo { public Guid Id { get; } public ICodec Codec { get; } @@ -22,7 +21,7 @@ public CodecInfo(Guid id, ICodec codec) } } - internal class CodecBuilder + internal sealed class CodecBuilder { public static readonly Guid NullCodec = Guid.Empty; public static readonly Guid InvalidCodec = Guid.Parse("ffffffffffffffffffffffffffffffff"); @@ -75,82 +74,30 @@ public static ICodec BuildCodec(Guid id, ref PacketReader reader) { var typeDescriptor = ITypeDescriptor.GetDescriptor(ref reader); - var codec = GetScalarCodec(typeDescriptor.Id); + if (!_codecCache.TryGetValue(typeDescriptor.Id, out var codec)) + codec = GetScalarCodec(typeDescriptor.Id); if (codec is not null) codecs.Add(codec); else { - // create codec based on type descriptor - switch (typeDescriptor) + codec = typeDescriptor switch { - case EnumerationTypeDescriptor enumeration: - { - // decode as string like - codecs.Add(new Text()); - } - break; - case ObjectShapeDescriptor shapeDescriptor: - { - var codecArguments = shapeDescriptor.Shapes.Select(x => (x.Name, codecs[x.TypePos])); - codec = new Codecs.Object(codecArguments.Select(x => x.Item2).ToArray(), codecArguments.Select(x => x.Name).ToArray()); - codecs.Add(codec); - } - break; - case TupleTypeDescriptor tuple: - { - codec = new Codecs.Tuple(tuple.ElementTypeDescriptorsIndex.Select(x => codecs[x]).ToArray()); - codecs.Add(codec); - } - break; - case NamedTupleTypeDescriptor namedTuple: - { - // TODO: better datatype than an object? - var codecArguments = namedTuple.Elements.Select(x => (x.Name, codecs[x.TypePos])); - codec = new Codecs.Object(codecArguments.Select(x => x.Item2).ToArray(), codecArguments.Select(x => x.Name).ToArray()); - codecs.Add(codec); - } - break; - case ArrayTypeDescriptor array: - { - var innerCodec = codecs[array.TypePos]; - - // create the array codec with reflection - var codecType = typeof(Array<>).MakeGenericType(innerCodec.ConverterType); - codec = (ICodec)Activator.CreateInstance(codecType, innerCodec)!; - codecs.Add(codec); - } - break; - case SetDescriptor set: - { - var innerCodec = codecs[set.TypePos]; - - var codecType = typeof(Set<>).MakeGenericType(innerCodec.ConverterType); - codec = (ICodec)Activator.CreateInstance(codecType, innerCodec)!; - codecs.Add(codec); - } - break; - case InputShapeDescriptor inputShape: - { - var codecArguments = inputShape.Shapes.Select(x => codecs[x.TypePos]); - codec = new Codecs.SparceObject(codecArguments.ToArray(), inputShape.Shapes); - codecs.Add(codec); - } - break; - case RangeTypeDescriptor rangeType: - { - var innerCodec = codecs[rangeType.TypePos]; - codec = (ICodec)Activator.CreateInstance(typeof(RangeCodec<>).MakeGenericType(innerCodec.ConverterType), innerCodec)!; - codecs.Add(codec); - } - break; - case BaseScalarTypeDescriptor scalar: - { - throw new MissingCodecException($"Could not find the scalar type {scalar.Id}. Please file a bug report with your query that caused this error."); - } - default: - break; - } + EnumerationTypeDescriptor enumeration => new Text(), + NamedTupleTypeDescriptor namedTuple => new Binary.Codecs.Object(namedTuple, codecs), + BaseScalarTypeDescriptor scalar => throw new MissingCodecException($"Could not find the scalar type {scalar.Id}. Please file a bug report with your query that caused this error."), + ObjectShapeDescriptor @object => new Binary.Codecs.Object(@object, codecs), + InputShapeDescriptor input => new SparceObject(input, codecs), + TupleTypeDescriptor tuple => new Binary.Codecs.Tuple(tuple.ElementTypeDescriptorsIndex.Select(x => codecs[x]).ToArray()), + RangeTypeDescriptor range => (ICodec)Activator.CreateInstance(typeof(RangeCodec<>).MakeGenericType(codecs[range.TypePos].ConverterType), codecs[range.TypePos])!, + ArrayTypeDescriptor array => (ICodec)Activator.CreateInstance(typeof(Array<>).MakeGenericType(codecs[array.TypePos].ConverterType), codecs[array.TypePos])!, + SetTypeDescriptor set => (ICodec)Activator.CreateInstance(typeof(Set<>).MakeGenericType(codecs[set.TypePos].ConverterType), codecs[set.TypePos])!, + _ => throw new MissingCodecException($"Could not find a type descriptor with type {typeDescriptor.Id:X2}. Please file a bug report with your query that caused this error.") + }; + + codecs.Add(codec); + + _codecCache[typeDescriptor.Id] = codec; } } @@ -194,7 +141,7 @@ private static ulong CalculateKnuthHash(string content) { new Guid("00000000-0000-0000-0000-000000000105"), typeof(Integer64) }, { new Guid("00000000-0000-0000-0000-000000000106"), typeof(Float32) }, { new Guid("00000000-0000-0000-0000-000000000107"), typeof(Float64) }, - { new Guid("00000000-0000-0000-0000-000000000108"), typeof(Codecs.Decimal) }, + { new Guid("00000000-0000-0000-0000-000000000108"), typeof(Binary.Codecs.Decimal) }, { new Guid("00000000-0000-0000-0000-000000000109"), typeof(Bool) }, { new Guid("00000000-0000-0000-0000-00000000010A"), typeof(Datetime) }, { new Guid("00000000-0000-0000-0000-00000000010B"), typeof(LocalDateTime) }, diff --git a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/ObjectBuilder.cs b/src/EdgeDB.Net.Driver/Binary/Builders/ObjectBuilder.cs similarity index 71% rename from src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/ObjectBuilder.cs rename to src/EdgeDB.Net.Driver/Binary/Builders/ObjectBuilder.cs index ee6be0fa..311e1341 100644 --- a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/ObjectBuilder.cs +++ b/src/EdgeDB.Net.Driver/Binary/Builders/ObjectBuilder.cs @@ -1,18 +1,23 @@ +using EdgeDB.Binary.Packets; +using EdgeDB.Binary.Codecs; using EdgeDB.DataTypes; -using EdgeDB.Serializer; using System.Collections; using System.Collections.Concurrent; using System.Reflection; using System.Runtime.CompilerServices; -namespace EdgeDB +namespace EdgeDB.Binary { - internal class ObjectBuilder + internal sealed class ObjectBuilder { - public static TType? BuildResult(object? value) + public static TType? BuildResult(ICodec codec, ref Data data) { - if (value is IDictionary raw) - return (TType?)TypeBuilder.BuildObject(typeof(TType), raw); + if (codec is Binary.Codecs.Object objectCodec) + { + return (TType?)TypeBuilder.BuildObject(typeof(TType), objectCodec, ref data); + } + + var value = codec.Deserialize(data.PayloadBuffer); return (TType?)ConvertTo(typeof(TType), value); } @@ -42,8 +47,8 @@ internal class ObjectBuilder } // check for edgeql types - if (TypeBuilder.IsValidObjectType(type) && value is IDictionary dict) - return TypeBuilder.BuildObject(type, dict); + //if (TypeBuilder.IsValidObjectType(type) && value is IDictionary dict) + // return TypeBuilder.BuildObject(type, dict); // check for tuple if(value is TransientTuple tuple && type.GetInterface("ITuple") != null) @@ -62,6 +67,19 @@ internal class ObjectBuilder return Activator.CreateInstance(type, new object?[] { innerValue }); } + if (type.IsFSharpValueOption()) + { + // is the value null? + if (value is null) + { + return type.GetProperty("ValueNone", BindingFlags.Static | BindingFlags.Public)!.GetValue(null); + } + + var newValueSome = type.GetMethod("NewValueSome", BindingFlags.Static | BindingFlags.Public)!; + var innerValue = ConvertTo(type.GenericTypeArguments[0], value); + return newValueSome.Invoke(null, new object?[] { innerValue }); + } + try { return Convert.ChangeType(value, type); @@ -86,12 +104,14 @@ internal class ObjectBuilder foreach (var val in (IEnumerable)value) { - if (val is IDictionary raw) - { - converted.Add(strongInnerType is not null ? TypeBuilder.BuildObject(strongInnerType, raw) : val); - } - else - converted.Add(strongInnerType is not null ? ConvertTo(strongInnerType, val) : val); + converted.Add(strongInnerType is not null ? ConvertTo(strongInnerType, val) : val); + + //if (val is IDictionary raw) + //{ + // converted.Add(strongInnerType is not null ? TypeBuilder.BuildObject(strongInnerType, raw) : val); + //} + //else + } diff --git a/src/EdgeDB.Net.Driver/Binary/Builders/ObjectEnumerator.cs b/src/EdgeDB.Net.Driver/Binary/Builders/ObjectEnumerator.cs new file mode 100644 index 00000000..d625893a --- /dev/null +++ b/src/EdgeDB.Net.Driver/Binary/Builders/ObjectEnumerator.cs @@ -0,0 +1,85 @@ +using EdgeDB.Binary.Codecs; +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Dynamic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.Binary.Builders +{ + /// + /// Represents an enumerator for creating objects. + /// + public ref struct ObjectEnumerator + { + private readonly string[] _names; + private readonly ICodec[] _codecs; + private readonly int _numElements; + internal PacketReader Reader; + private int _pos; + + internal ObjectEnumerator(ref Span data, int position, string[] names, ICodec[] codecs) + { + Reader = new PacketReader(ref data, position); + _names = names; + _codecs = codecs; + _pos = 0; + + _numElements = Reader.ReadInt32(); + } + + /// + /// Converts this to a object. + /// + /// A object. + public object? ToDynamic() + { + var data = new ExpandoObject(); + + while (Next(out var name, out var value)) + data.TryAdd(name, value); + + return data; + } + + /// + /// Reads the next property within this enumerator. + /// + /// The name of the property. + /// The value of the property. + /// + /// if a property was read successfully; otherwise . + /// + public bool Next([NotNullWhen(true)] out string? name, out object? value) + { + if (_pos >= _numElements || Reader.Empty) + { + name = null; + value = null; + return false; + } + + Reader.Skip(4); + + var length = Reader.ReadInt32(); + + if (length == -1) + { + name = _names[_pos]; + value = null; + _pos++; + return true; + } + + Reader.ReadBytes(length, out var buff); + + var innerReader = new PacketReader(ref buff); + name = _names[_pos]; + value = _codecs[_pos].Deserialize(ref innerReader); + _pos++; + return true; + } + } +} diff --git a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/TypeBuilder.cs b/src/EdgeDB.Net.Driver/Binary/Builders/TypeBuilder.cs similarity index 52% rename from src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/TypeBuilder.cs rename to src/EdgeDB.Net.Driver/Binary/Builders/TypeBuilder.cs index 3ef52db5..b358d307 100644 --- a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/TypeBuilder.cs +++ b/src/EdgeDB.Net.Driver/Binary/Builders/TypeBuilder.cs @@ -1,10 +1,15 @@ +using EdgeDB.Binary.Packets; +using EdgeDB.Binary.Codecs; using System.Collections; using System.Collections.Concurrent; using System.Diagnostics.CodeAnalysis; +using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; +using EdgeDB.Binary.Builders; +using EdgeDB.TypeConverters; -namespace EdgeDB.Serializer +namespace EdgeDB.Binary { /// /// Represents the class used to build types from edgedb query results. @@ -12,16 +17,19 @@ namespace EdgeDB.Serializer public static class TypeBuilder { /// - /// Gets or sets the naming strategy used when mapping type names returned - /// from EdgeDB to C# classes. + /// Gets or sets the naming strategy used for deserialization of edgeql property names to dotnet property names. /// /// + /// All dotnet types passed to the type builder will have their properties converted to the edgeql version + /// using this naming strategy, the naming convention of the dotnet type will be preserved. + /// + /// /// If the naming strategy doesn't find a match, the - /// will be used. + /// will be used. /// - public static INamingStrategy NamingStrategy { get; set; } - - private readonly static ConcurrentDictionary _typeInfo = new(); + public static INamingStrategy SchemaNamingStrategy { get; set; } + + internal readonly static ConcurrentDictionary TypeInfo = new(); internal static readonly INamingStrategy AttributeNamingStrategy; private readonly static List _scannedAssemblies; @@ -29,7 +37,7 @@ static TypeBuilder() { _scannedAssemblies = new(); AttributeNamingStrategy = INamingStrategy.AttributeNamingStrategy; - NamingStrategy ??= INamingStrategy.SnakeCaseNamingStrategy; + SchemaNamingStrategy ??= INamingStrategy.DefaultNamingStrategy; } /// @@ -41,23 +49,25 @@ static TypeBuilder() public static void AddOrUpdateTypeBuilder( Action> builder) { - object Factory(IDictionary raw) + object Factory(ref ObjectEnumerator enumerator) { var instance = Activator.CreateInstance(); if (instance is null) throw new TargetInvocationException($"Cannot create an instance of {typeof(TType).Name}", null); - builder(instance, raw); + var dynamicData = enumerator.ToDynamic(); + + builder(instance, (IDictionary)dynamicData!); return instance; } var inst = new TypeDeserializeInfo(typeof(TType), Factory); - _typeInfo.AddOrUpdate(typeof(TType), inst, (_, _) => inst); + TypeInfo.AddOrUpdate(typeof(TType), inst, (_, _) => inst); - if (!_typeInfo.ContainsKey(typeof(TType))) + if (!TypeInfo.ContainsKey(typeof(TType))) ScanAssemblyForTypes(typeof(TType).Assembly); } @@ -70,16 +80,11 @@ object Factory(IDictionary raw) public static void AddOrUpdateTypeFactory( TypeDeserializerFactory factory) { - object Factory(IDictionary data) => factory(data) ?? - throw new TargetInvocationException( - $"Cannot create an instance of {typeof(TType).Name}", - null); - - if(_typeInfo.TryGetValue(typeof(TType), out var info)) - info.UpdateFactory(Factory); + if(TypeInfo.TryGetValue(typeof(TType), out var info)) + info.UpdateFactory(factory); else { - _typeInfo.TryAdd(typeof(TType), new(typeof(TType), Factory)); + TypeInfo.TryAdd(typeof(TType), new(typeof(TType), factory)); ScanAssemblyForTypes(typeof(TType).Assembly); } } @@ -94,31 +99,48 @@ object Factory(IDictionary data) => factory(data) ?? public static bool TryRemoveTypeFactory([MaybeNullWhen(false)]out TypeDeserializerFactory factory) { factory = null; - var result = _typeInfo.TryRemove(typeof(TType), out var info); + var result = TypeInfo.TryRemove(typeof(TType), out var info); if (result && info is not null) factory = info; return result; } #region Type helpers - internal static object? BuildObject(Type type, IDictionary raw) + internal static object? BuildObject(Type type, Binary.Codecs.Object codec, ref Data data) { if (!IsValidObjectType(type)) throw new InvalidOperationException($"Cannot deserialize data to {type.Name}"); + + if (!TypeInfo.TryGetValue(type, out TypeDeserializeInfo? info)) + { + info = TypeInfo.AddOrUpdate(type, new TypeDeserializeInfo(type), (_, v) => v); + ScanAssemblyForTypes(type.Assembly); + } + + codec.Initialize(type); + + var reader = new PacketReader(data.PayloadBuffer); + return codec.Deserialize(ref reader); + } - if (!_typeInfo.TryGetValue(type, out TypeDeserializeInfo? info)) + internal static TypeDeserializerFactory GetDeserializationFactory(Type type) + { + if (!IsValidObjectType(type)) + throw new InvalidOperationException($"Cannot deserialize data to {type.Name}"); + + if (!TypeInfo.TryGetValue(type, out var info)) { - info = _typeInfo.AddOrUpdate(type, new TypeDeserializeInfo(type), (_, v) => v); + info = TypeInfo.AddOrUpdate(type, new TypeDeserializeInfo(type), (_, v) => v); ScanAssemblyForTypes(type.Assembly); } - return info.Deserialize(raw); + return info.Factory; } internal static bool IsValidObjectType(Type type) { // check if we know already how to build this type - if (_typeInfo.ContainsKey(type)) + if (TypeInfo.ContainsKey(type)) return true; // check constructor for builder @@ -171,14 +193,6 @@ internal static bool TryGetCustomBuilder(this Type objectType, out MethodInfo? i info = method; return method is not null; } - - internal static IEnumerable GetPropertyMap(this Type objectType) - { - return objectType.GetProperties().Where(x => - x.CanWrite && - x.GetCustomAttribute() == null && - x.SetMethod != null); - } #endregion #region Assembly @@ -198,8 +212,8 @@ internal static void ScanAssemblyForTypes(Assembly assembly) foreach (var type in types) { var info = new TypeDeserializeInfo(type); - _typeInfo.TryAdd(type, info); - foreach (var parentType in _typeInfo.Where(x => (x.Key.IsInterface || x.Key.IsAbstract) && x.Key != type && type.IsAssignableTo(x.Key))) + TypeInfo.TryAdd(type, info); + foreach (var parentType in TypeInfo.Where(x => (x.Key.IsInterface || x.Key.IsAbstract) && x.Key != type && type.IsAssignableTo(x.Key))) parentType.Value.AddOrUpdateChildren(info); } @@ -216,7 +230,7 @@ internal static void ScanAssemblyForTypes(Assembly assembly) private static void ScanForAbstractTypes(Assembly assembly) { // look for any types that inherit already defined abstract types - foreach (var abstractType in _typeInfo.Where(x => x.Value.IsAbtractType)) + foreach (var abstractType in TypeInfo.Where(x => x.Value.IsAbtractType)) { var childTypes = assembly.DefinedTypes.Where(x => (x.IsSubclassOf(abstractType.Key) || x.ImplementedInterfaces.Contains(abstractType.Key) || x.IsAssignableTo(abstractType.Key))); abstractType.Value.AddOrUpdateChildren(childTypes.Select(x => new TypeDeserializeInfo(x))); @@ -225,24 +239,38 @@ private static void ScanForAbstractTypes(Assembly assembly) #endregion } - public delegate object TypeDeserializerFactory(IDictionary args); + /// + /// A method that will create a object from a . + /// + /// The enumerator containing the property values. + /// + /// An instance of an object that represents the data read from the . + /// + public delegate object? TypeDeserializerFactory(ref ObjectEnumerator enumerator); - internal class TypeDeserializeInfo + internal sealed class TypeDeserializeInfo { public string EdgeDBTypeName { get; } public bool IsAbtractType => _type.IsAbstract || _type.IsInterface; - public Dictionary Children { get; } = new(); + public TypeDeserializerFactory Factory => _factory; + public Dictionary Children { get; } = new(); + private readonly Type _type; + private EdgeDBPropertyInfo[]? _properties; + private Dictionary? _propertyIndexTable; private TypeDeserializerFactory _factory; + internal readonly Dictionary PropertyMap; + private readonly ObjectActivator? _typeActivator; - public TypeDeserializeInfo(Type type) { _type = type; + _typeActivator = CreateActivator(); + PropertyMap = GetPropertyMap(type); _factory = CreateDefaultFactory(); EdgeDBTypeName = _type.GetCustomAttribute()?.Name ?? _type.Name; } @@ -250,10 +278,26 @@ public TypeDeserializeInfo(Type type) public TypeDeserializeInfo(Type type, TypeDeserializerFactory factory) { _type = type; + _typeActivator = CreateActivator(); _factory = factory; + PropertyMap = GetPropertyMap(type); EdgeDBTypeName = _type.GetCustomAttribute()?.Name ?? _type.Name; } + private ObjectActivator? CreateActivator() + { + if (IsAbtractType) + return null; + + // get an empty constructor + var ctor = _type.GetConstructor(Type.EmptyTypes) ?? _type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, Type.EmptyTypes); + + if (ctor == null) + return null; + + return Expression.Lambda(Expression.New(ctor)).Compile(); + } + public void AddOrUpdateChildren(TypeDeserializeInfo child) => Children[child._type] = child; @@ -271,35 +315,48 @@ public void UpdateFactory(TypeDeserializerFactory factory) private TypeDeserializerFactory CreateDefaultFactory() { if (_type == typeof(object)) - return (data) => data; + return (ref ObjectEnumerator enumerator) => enumerator.ToDynamic(); + + if(_properties is null || _propertyIndexTable is null) + throw new NullReferenceException("Properties cannot be null"); // if type is anon type or record, or has a constructor with all properties if (_type.IsRecord() || _type.GetCustomAttribute() != null || - _type.GetConstructor(_type.GetProperties().Select(x => x.PropertyType).ToArray()) != null) + _type.GetConstructor(_properties.Select(x => x.Type).ToArray()) != null) { - var props = _type.GetProperties(); - return (data) => + return (ref ObjectEnumerator enumerator) => { - object?[] ctorParams = new object[props.Length]; - for (int i = 0; i != ctorParams.Length; i++) - { - var prop = props[i]; + //var data = (IDictionary)enumerator.ToDynamic()!; + var ctorParams = new object?[_properties.Length]; + var reverseIndexer = new FastInverseIndexer(_properties.Length); - if (!data.TryGetValue(TypeBuilder.NamingStrategy.GetName(prop), out var value)) + while(enumerator.Next(out var name, out var value)) + { + if (PropertyMap.TryGetValue(name, out var prop)) { - ctorParams[i] = ReflectionUtils.GetDefault(prop.PropertyType); + var index = _propertyIndexTable[prop]; + reverseIndexer.Track(index); + + try + { + ctorParams[index] = prop.ConvertToPropertyType(value); + } + catch(Exception x) + { + throw new NoTypeConverterException($"Cannot assign property {prop.PropertyName} with type {value?.GetType().Name ?? "unknown"}", x); + } } + } - try - { - ctorParams[i] = ObjectBuilder.ConvertTo(prop.PropertyType, value); - } - catch(Exception x) - { - throw new NoTypeConverterException($"Cannot assign property {prop.Name} with type {value?.GetType().Name ?? "unknown"}", x); - } + // fill the missed properties with defaults + var missed = reverseIndexer.GetIndexies(); + for(int i = 0; i != missed.Length; i++) + { + var prop = _properties[missed[i]]; + ctorParams[missed[i]] = ReflectionUtils.GetDefault(prop.Type); } + return Activator.CreateInstance(_type, ctorParams)!; }; } @@ -307,14 +364,14 @@ private TypeDeserializerFactory CreateDefaultFactory() // if type has custom method builder if (_type.TryGetCustomBuilder(out var methodInfo)) { - return (data) => + return (ref ObjectEnumerator enumerator) => { - var instance = Activator.CreateInstance(_type); + var instance = CreateInstance(); if (instance is null) throw new TargetInvocationException($"Cannot create an instance of {_type.Name}", null); - methodInfo!.Invoke(instance, new object[] { data }); + methodInfo!.Invoke(instance, new object?[] { enumerator.ToDynamic() }); return instance; }; @@ -324,16 +381,19 @@ private TypeDeserializerFactory CreateDefaultFactory() var constructor = _type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,null, new Type[] { typeof(IDictionary) }, null); if (constructor?.GetCustomAttribute() is not null) - return (data) => constructor.Invoke(new object?[] { data }) ?? + return (ref ObjectEnumerator enumerator) => constructor.Invoke(new object?[] { enumerator.ToDynamic() }) ?? throw new TargetInvocationException($"Cannot create an instance of {_type.Name}", null); // is it abstract if (IsAbtractType) { - return data => + return (ref ObjectEnumerator enumerator) => { // introspect the type name - var typeName = (string)data["__tname__"]!; + if (!enumerator.Next(out var name, out var value) || name != "__tname__") + throw new ConfigurationException("Type introspection is required for abstract types, this is a bug."); + + var typeName = (string)value!; // remove the modulename typeName = typeName.Split("::").Last(); @@ -346,44 +406,120 @@ private TypeDeserializerFactory CreateDefaultFactory() } // deserialize as child - return info.Deserialize(data); + return info.Deserialize(ref enumerator); }; } - - // fallback to reflection factory - var propertyMap = _type.GetPropertyMap(); - - return data => + + return (ref ObjectEnumerator enumerator) => { - var instance = Activator.CreateInstance(_type, true); + var instance = CreateInstance(); if (instance is null) throw new TargetInvocationException($"Cannot create an instance of {_type.Name}", null); - foreach (var prop in propertyMap) + while(enumerator.Next(out var name, out var value)) { - var foundProperty = data.TryGetValue(TypeBuilder.NamingStrategy.GetName(prop), out object? value) || data.TryGetValue(TypeBuilder.AttributeNamingStrategy.GetName(prop), out value); - - if (!foundProperty || value is null) + if (!PropertyMap.TryGetValue(name, out var prop)) continue; - - try - { - prop.SetValue(instance, ObjectBuilder.ConvertTo(prop.PropertyType, value)); - } - catch(Exception x) - { - throw new NoTypeConverterException($"Cannot assign property {prop.Name} with type {value?.GetType().Name ?? "unknown"}", x); - } + + prop.ConvertAndSetValue(instance, value); } return instance; }; } - public object Deserialize(IDictionary args) - => _factory(args); + private object CreateInstance() + { + if (_typeActivator is null) + throw new InvalidOperationException($"No empty constructor found on type {_type}"); + + return _typeActivator(); + } + + private Dictionary GetPropertyMap(Type objectType) + { + var props = objectType.GetProperties(); + _properties = new EdgeDBPropertyInfo[props.Length]; + _propertyIndexTable = new(_properties.Length); + + var dict = new Dictionary(_properties.Length); + + for (var i = 0; i != _properties.Length; i++) + { + var prop = props[i]; + var edbProp = new EdgeDBPropertyInfo(prop); + _properties[i] = edbProp; + + _propertyIndexTable.Add(_properties[i], i); + + if (prop.GetCustomAttribute() is null) + { + dict.Add(edbProp.EdgeDBName, edbProp); + } + } + + return dict; + } + + public object? Deserialize(ref ObjectEnumerator enumerator) + => _factory(ref enumerator); + + private delegate object ObjectActivator(); public static implicit operator TypeDeserializerFactory(TypeDeserializeInfo info) => info._factory; } + + internal sealed class EdgeDBPropertyInfo + { + public string PropertyName + => _property.Name; + + public string EdgeDBName + => AttributeName ?? TypeBuilder.SchemaNamingStrategy.Convert(_property); + + public string? AttributeName + => _propertyAttribute?.Name; + + public IEdgeDBTypeConverter? CustomConverter + => _typeConverter?.Converter; + + public Type Type + => _property.PropertyType; + + public bool IsIgnored + => _ignore is not null; + + private readonly EdgeDBPropertyAttribute? _propertyAttribute; + private readonly EdgeDBTypeConverterAttribute? _typeConverter; + private readonly EdgeDBIgnoreAttribute? _ignore; + private readonly PropertyInfo _property; + public EdgeDBPropertyInfo(PropertyInfo propInfo) + { + _property = propInfo; + _propertyAttribute = propInfo.GetCustomAttribute(); + _typeConverter = propInfo.GetCustomAttribute(); + _ignore = propInfo.GetCustomAttribute(); + } + + public object? ConvertToPropertyType(object? value) + { + if (value is null) + return ReflectionUtils.GetDefault(Type); + + // check if we can use the custom converter + if (CustomConverter is not null && CustomConverter.CanConvert(Type, value.GetType())) + { + return CustomConverter.ConvertFrom(value); + } + + return ObjectBuilder.ConvertTo(Type, value); + } + + public void ConvertAndSetValue(object instance, object? value) + { + var converted = ConvertToPropertyType(value); + _property.SetValue(instance, converted); + } + } } diff --git a/src/EdgeDB.Net.Driver/Binary/Builders/TypeConverters/EdgeDBTypeConverter.cs b/src/EdgeDB.Net.Driver/Binary/Builders/TypeConverters/EdgeDBTypeConverter.cs new file mode 100644 index 00000000..6357dbf6 --- /dev/null +++ b/src/EdgeDB.Net.Driver/Binary/Builders/TypeConverters/EdgeDBTypeConverter.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.TypeConverters +{ + /// + /// Represents a generic client-side type converter. + /// + /// The client-side type which the converter is responsible for converting. + /// The database-side type which the converter is responsible for converting to. + public abstract class EdgeDBTypeConverter : IEdgeDBTypeConverter + { + /// + /// Converts the given to a . + /// + /// The value to convert to a . + /// + /// An instance of ; or . + /// + public abstract TSource? ConvertFrom(TTarget? value); + + /// + /// Converts the given to a . + /// + /// The value to convert to a . + /// An instance of ; or . + public abstract TTarget? ConvertTo(TSource? value); + + object? IEdgeDBTypeConverter.ConvertFrom(object? value) + => ConvertFrom((TTarget?)value); + object? IEdgeDBTypeConverter.ConvertTo(object? value) + => ConvertTo((TSource?)value); + bool IEdgeDBTypeConverter.CanConvert(System.Type from, System.Type to) + => from == typeof(TSource) && to == typeof(TTarget); + } + + internal interface IEdgeDBTypeConverter + { + object? ConvertFrom(object? value); + object? ConvertTo(object? value); + + bool CanConvert(Type from, Type to); + } +} diff --git a/src/EdgeDB.Net.Driver/ClientPacketDuplexer.cs b/src/EdgeDB.Net.Driver/Binary/ClientPacketDuplexer.cs similarity index 94% rename from src/EdgeDB.Net.Driver/ClientPacketDuplexer.cs rename to src/EdgeDB.Net.Driver/Binary/ClientPacketDuplexer.cs index e946ae0a..337707c2 100644 --- a/src/EdgeDB.Net.Driver/ClientPacketDuplexer.cs +++ b/src/EdgeDB.Net.Driver/Binary/ClientPacketDuplexer.cs @@ -1,15 +1,15 @@ -using EdgeDB.Binary; +using EdgeDB.Binary; using EdgeDB.Binary.Packets; -using EdgeDB.Models; using EdgeDB.Utils; using System.Buffers; using System.Buffers.Binary; using System.Collections.Concurrent; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; -namespace EdgeDB +namespace EdgeDB.Binary { - internal class ClientPacketDuplexer + internal sealed class ClientPacketDuplexer { public const int PACKET_HEADER_SIZE = 5; public bool IsConnected @@ -52,7 +52,7 @@ public ClientPacketDuplexer(EdgeDBBinaryClient client) public async Task ResetAsync() { - if(_readTask != null) + if(_readTask != null && !_readTask.IsCanceled) await _readTask!; _disconnectTokenSource = new(); } @@ -222,15 +222,21 @@ public async ValueTask SendAsync(CancellationToken token = default, params Senda if (_stream == null || !IsConnected) throw new EdgeDBException("Cannot send message to a closed connection"); + + await _stream.WriteAsync(BuildPackets(packets), linkedToken.Token).ConfigureAwait(false); + } + + private ReadOnlyMemory BuildPackets(Sendable[] packets) + { + var size = packets.Sum(x => x.GetSize()); + var writer = new PacketWriter(size); - using var ms = new MemoryStream(); - foreach (var packet in packets) + for (int i = 0; i != packets.Length; i++) { - using var writer = new PacketWriter(ms); - packet.Write(writer, _client); + packets[i].Write(ref writer, _client); } - - await _stream.WriteAsync(ms.ToArray(), linkedToken.Token).ConfigureAwait(false); + + return writer.GetBytes(); } public async Task NextAsync(Predicate? predicate = null, bool alwaysReturnError = true, CancellationToken token = default) diff --git a/src/EdgeDB.Net.Driver/Codecs/Array.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Array.cs similarity index 78% rename from src/EdgeDB.Net.Driver/Codecs/Array.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Array.cs index 09d7b84e..65139e51 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Array.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Array.cs @@ -1,6 +1,6 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Array : ICodec> + internal sealed class Array : ICodec> { public static readonly byte[] EMPTY_ARRAY = new byte[] { @@ -52,7 +52,7 @@ public Array(ICodec innerCodec) return array; } - public void Serialize(PacketWriter writer, IEnumerable? value) + public void Serialize(ref PacketWriter writer, IEnumerable? value) { if(value is null) { @@ -62,35 +62,27 @@ public void Serialize(PacketWriter writer, IEnumerable? value) var elements = value.ToArray(); // convert to array to prevent the reference from changing while we serialize - var elementWriter = new PacketWriter(); + writer.Write(1); // num dimensions + writer.Write(0); // reserved + writer.Write(0); // reserved + // dimension (our length for upper and 1 for lower) + writer.Write(elements.Length); + writer.Write(1); + for(int i = 0; i != elements.Length; i++) { var element = elements[i]; if(element is null) { - elementWriter.Write(-1); + writer.Write(-1); } else { - var subWriter = new PacketWriter(); - _innerCodec.Serialize(subWriter, element); - elementWriter.Write((int)subWriter.Length); - elementWriter.Write(subWriter); + writer.WriteToWithInt32Length((ref PacketWriter innerWriter) => _innerCodec.Serialize(ref innerWriter, element)); } } - - writer.Write(1); // num dimensions - writer.Write(0); // reserved - writer.Write(0); // reserved - - // dimension (our length for upper and 1 for lower) - writer.Write(elements.Length); - writer.Write(1); - - // write our serialized elements - writer.Write(elementWriter); } } } diff --git a/src/EdgeDB.Net.Driver/Codecs/BigInt.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/BigInt.cs similarity index 91% rename from src/EdgeDB.Net.Driver/Codecs/BigInt.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/BigInt.cs index 0a12d9a7..ca984ed0 100644 --- a/src/EdgeDB.Net.Driver/Codecs/BigInt.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/BigInt.cs @@ -1,8 +1,8 @@ -using System.Numerics; +using System.Numerics; -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class BigInt : IScalarCodec + internal sealed class BigInt : IScalarCodec { public static readonly BigInteger Base = 10000; @@ -39,7 +39,7 @@ public BigInteger Deserialize(ref PacketReader reader) return BigInteger.Parse(result); } - public void Serialize(PacketWriter writer, BigInteger value) + public void Serialize(ref PacketWriter writer, BigInteger value) { if(value == 0) { diff --git a/src/EdgeDB.Net.Driver/Codecs/Bool.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Bool.cs similarity index 55% rename from src/EdgeDB.Net.Driver/Codecs/Bool.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Bool.cs index b8a522a9..7cc3b03c 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Bool.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Bool.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Bool : IScalarCodec + internal sealed class Bool : IScalarCodec { public bool Deserialize(ref PacketReader reader) { return reader.ReadBoolean(); } - public void Serialize(PacketWriter writer, bool value) + public void Serialize(ref PacketWriter writer, bool value) { writer.Write(value); } diff --git a/src/EdgeDB.Net.Driver/Codecs/Bytes.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Bytes.cs similarity index 60% rename from src/EdgeDB.Net.Driver/Codecs/Bytes.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Bytes.cs index aebb5835..32f89769 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Bytes.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Bytes.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Bytes : IScalarCodec + internal sealed class Bytes : IScalarCodec { public byte[] Deserialize(ref PacketReader reader) { return reader.ConsumeByteArray(); } - public void Serialize(PacketWriter writer, byte[]? value) + public void Serialize(ref PacketWriter writer, byte[]? value) { if (value is not null) writer.Write(value); diff --git a/src/EdgeDB.Net.Driver/Codecs/Datetime.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Datetime.cs similarity index 73% rename from src/EdgeDB.Net.Driver/Codecs/Datetime.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Datetime.cs index b179a3b8..ece399e9 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Datetime.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Datetime.cs @@ -1,6 +1,6 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Datetime : IScalarCodec // std::datetime + internal sealed class Datetime : IScalarCodec // std::datetime { public static readonly DateTimeOffset EdgedbEpoc = new(2000, 1, 1, 0, 0, 0, TimeSpan.Zero); @@ -11,7 +11,7 @@ public DateTimeOffset Deserialize(ref PacketReader reader) return EdgedbEpoc.AddTicks(val * 10); } - public void Serialize(PacketWriter writer, DateTimeOffset value) + public void Serialize(ref PacketWriter writer, DateTimeOffset value) { var v = (value - EdgedbEpoc).Ticks; @@ -19,7 +19,7 @@ public void Serialize(PacketWriter writer, DateTimeOffset value) } } - internal class LocalDateTime : IScalarCodec // std::local_datetime + internal sealed class LocalDateTime : IScalarCodec // std::local_datetime { public static readonly DateTime EdgedbEpoc = new(2000, 1, 1, 0, 0, 0, DateTimeKind.Unspecified); @@ -30,7 +30,7 @@ public DateTime Deserialize(ref PacketReader reader) return EdgedbEpoc.AddTicks(val * 10); } - public void Serialize(PacketWriter writer, DateTime value) + public void Serialize(ref PacketWriter writer, DateTime value) { var v = (value - EdgedbEpoc).Ticks; @@ -38,11 +38,11 @@ public void Serialize(PacketWriter writer, DateTime value) } } - internal class LocalDate : IScalarCodec + internal sealed class LocalDate : IScalarCodec { public static readonly DateOnly EdgedbEpoc = new(2000, 1, 1); - public void Serialize(PacketWriter writer, DateOnly value) + public void Serialize(ref PacketWriter writer, DateOnly value) { var days = (int)Math.Floor((value.ToDateTime(default) - EdgedbEpoc.ToDateTime(default)).TotalDays); writer.Write(days); @@ -71,13 +71,13 @@ public TimeSpan Deserialize(ref PacketReader reader) return TimeSpan.FromTicks(microseconds * 10); } - public void Serialize(PacketWriter writer, TimeSpan value) + public void Serialize(ref PacketWriter writer, TimeSpan value) { writer.Write(value.Ticks / 10); } } - internal class RelativeDuration : IScalarCodec + internal sealed class RelativeDuration : IScalarCodec { public TimeSpan Deserialize(ref PacketReader reader) { @@ -88,11 +88,11 @@ public TimeSpan Deserialize(ref PacketReader reader) return new TimeSpan(microseconds * 10).Add(TimeSpan.FromDays(days + months * 31)); } - public void Serialize(PacketWriter writer, TimeSpan value) + public void Serialize(ref PacketWriter writer, TimeSpan value) { } } - internal class LocalTime : Duration { } + internal sealed class LocalTime : Duration { } } diff --git a/src/EdgeDB.Net.Driver/Codecs/Decimal.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Decimal.cs similarity index 94% rename from src/EdgeDB.Net.Driver/Codecs/Decimal.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Decimal.cs index 44eaf960..457d8414 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Decimal.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Decimal.cs @@ -1,6 +1,6 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Decimal : IScalarCodec + internal sealed class Decimal : IScalarCodec { public const decimal NBASE = 10000; @@ -51,7 +51,7 @@ public decimal Deserialize(ref PacketReader reader) return decimal.Parse(value); } - public void Serialize(PacketWriter writer, decimal value) + public void Serialize(ref PacketWriter writer, decimal value) { // TODO https://www.edgedb.com/docs/reference/protocol/dataformats#std-decimal throw new NotSupportedException(); diff --git a/src/EdgeDB.Net.Driver/Codecs/Float32.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Float32.cs similarity index 54% rename from src/EdgeDB.Net.Driver/Codecs/Float32.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Float32.cs index b3257a0d..2b5988c0 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Float32.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Float32.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Float32 : IScalarCodec + internal sealed class Float32 : IScalarCodec { public float Deserialize(ref PacketReader reader) { return reader.ReadSingle(); } - public void Serialize(PacketWriter writer, float value) + public void Serialize(ref PacketWriter writer, float value) { writer.Write(value); } diff --git a/src/EdgeDB.Net.Driver/Codecs/Float64.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Float64.cs similarity index 54% rename from src/EdgeDB.Net.Driver/Codecs/Float64.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Float64.cs index 38fe6d8d..faba8021 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Float64.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Float64.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Float64 : IScalarCodec + internal sealed class Float64 : IScalarCodec { public double Deserialize(ref PacketReader reader) { return reader.ReadDouble(); } - public void Serialize(PacketWriter writer, double value) + public void Serialize(ref PacketWriter writer, double value) { writer.Write(value); } diff --git a/src/EdgeDB.Net.Driver/Codecs/ICodec.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/ICodec.cs similarity index 75% rename from src/EdgeDB.Net.Driver/Codecs/ICodec.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/ICodec.cs index 5c97d702..fe61cd83 100644 --- a/src/EdgeDB.Net.Driver/Codecs/ICodec.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/ICodec.cs @@ -1,27 +1,27 @@ -using System.Reflection; +using System.Reflection; -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { internal interface IArgumentCodec : IArgumentCodec, ICodec { - void SerializeArguments(PacketWriter writer, TType? value); + void SerializeArguments(ref PacketWriter writer, TType? value); } internal interface IArgumentCodec { - void SerializeArguments(PacketWriter writer, object? value); + void SerializeArguments(ref PacketWriter writer, object? value); byte[] SerializeArguments(object? value) { - using var writer = new PacketWriter(); - SerializeArguments(writer, value); - return writer.GetBytes(); + var writer = new PacketWriter(); + SerializeArguments(ref writer, value); + return writer.GetBytes().ToArray(); } } internal interface ICodec : ICodec { - void Serialize(PacketWriter writer, TConverter? value); + void Serialize(ref PacketWriter writer, TConverter? value); new TConverter? Deserialize(ref PacketReader reader); @@ -40,16 +40,16 @@ internal interface ICodec : ICodec byte[] Serialize(TConverter? value) { var writer = new PacketWriter(); - Serialize(writer, value); - return writer.GetBytes(); + Serialize(ref writer, value); + return writer.GetBytes().ToArray(); } // ICodec object? ICodec.Deserialize(ref PacketReader reader) => Deserialize(ref reader); - void ICodec.Serialize(PacketWriter writer, object? value) - => Serialize(writer, (TConverter?)value); + void ICodec.Serialize(ref PacketWriter writer, object? value) + => Serialize(ref writer, (TConverter?)value); Type ICodec.ConverterType => typeof(TConverter); @@ -64,7 +64,7 @@ internal interface ICodec Type ConverterType { get; } - void Serialize(PacketWriter writer, object? value); + void Serialize(ref PacketWriter writer, object? value); object? Deserialize(ref PacketReader reader); @@ -83,8 +83,8 @@ internal interface ICodec byte[] Serialize(object? value) { var writer = new PacketWriter(); - Serialize(writer, value); - return writer.GetBytes(); + Serialize(ref writer, value); + return writer.GetBytes().ToArray(); } private static readonly List _codecs; diff --git a/src/EdgeDB.Net.Driver/Codecs/Integer16.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Integer16.cs similarity index 54% rename from src/EdgeDB.Net.Driver/Codecs/Integer16.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Integer16.cs index 50d0f516..c1770341 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Integer16.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Integer16.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Integer16 : IScalarCodec + internal sealed class Integer16 : IScalarCodec { public short Deserialize(ref PacketReader reader) { return reader.ReadInt16(); } - public void Serialize(PacketWriter writer, short value) + public void Serialize(ref PacketWriter writer, short value) { writer.Write(value); } diff --git a/src/EdgeDB.Net.Driver/Codecs/Integer32.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Integer32.cs similarity index 54% rename from src/EdgeDB.Net.Driver/Codecs/Integer32.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Integer32.cs index 61f017c9..aba3b0a4 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Integer32.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Integer32.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Integer32 : IScalarCodec + internal sealed class Integer32 : IScalarCodec { public int Deserialize(ref PacketReader reader) { return reader.ReadInt32(); } - public void Serialize(PacketWriter writer, int value) + public void Serialize(ref PacketWriter writer, int value) { writer.Write(value); } diff --git a/src/EdgeDB.Net.Driver/Codecs/Integer64.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Integer64.cs similarity index 54% rename from src/EdgeDB.Net.Driver/Codecs/Integer64.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Integer64.cs index ae370698..72c2f47d 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Integer64.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Integer64.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Integer64 : IScalarCodec + internal sealed class Integer64 : IScalarCodec { public long Deserialize(ref PacketReader reader) { return reader.ReadInt64(); } - public void Serialize(PacketWriter writer, long value) + public void Serialize(ref PacketWriter writer, long value) { writer.Write(value); } diff --git a/src/EdgeDB.Net.Driver/Codecs/Json.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Json.cs similarity index 70% rename from src/EdgeDB.Net.Driver/Codecs/Json.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Json.cs index 838c5c32..130de4a6 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Json.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Json.cs @@ -1,8 +1,8 @@ -using System.Text; +using System.Text; -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Json : IScalarCodec + internal sealed class Json : IScalarCodec { public DataTypes.Json Deserialize(ref PacketReader reader) { @@ -14,7 +14,7 @@ public DataTypes.Json Deserialize(ref PacketReader reader) return new DataTypes.Json(data); } - public void Serialize(PacketWriter writer, DataTypes.Json value) + public void Serialize(ref PacketWriter writer, DataTypes.Json value) { byte[] jsonData = Encoding.UTF8.GetBytes(value.Value ?? ""); diff --git a/src/EdgeDB.Net.Driver/Codecs/Memory.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Memory.cs similarity index 56% rename from src/EdgeDB.Net.Driver/Codecs/Memory.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Memory.cs index c8c797a9..9b5c1558 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Memory.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Memory.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Memory : IScalarCodec + internal sealed class Memory : IScalarCodec { public DataTypes.Memory Deserialize(ref PacketReader reader) { return new DataTypes.Memory(reader.ReadInt64()); } - public void Serialize(PacketWriter writer, DataTypes.Memory value) + public void Serialize(ref PacketWriter writer, DataTypes.Memory value) { writer.Write(value.TotalBytes); } diff --git a/src/EdgeDB.Net.Driver/Codecs/NullCodec.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/NullCodec.cs similarity index 57% rename from src/EdgeDB.Net.Driver/Codecs/NullCodec.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/NullCodec.cs index 9c155f2d..104b3a17 100644 --- a/src/EdgeDB.Net.Driver/Codecs/NullCodec.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/NullCodec.cs @@ -1,6 +1,6 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class NullCodec : ICodec, IArgumentCodec + internal sealed class NullCodec : ICodec, IArgumentCodec { public Type ConverterType => typeof(object); @@ -11,12 +11,12 @@ public bool CanConvert(Type t) public object? Deserialize(ref PacketReader reader) { return null; } - public void Serialize(PacketWriter writer, object? value) + public void Serialize(ref PacketWriter writer, object? value) { writer.Write(0); } - public void SerializeArguments(PacketWriter writer, object? value) + public void SerializeArguments(ref PacketWriter writer, object? value) { writer.Write(0); } diff --git a/src/EdgeDB.Net.Driver/Binary/Codecs/Object.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Object.cs new file mode 100644 index 00000000..e29c468e --- /dev/null +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Object.cs @@ -0,0 +1,154 @@ +using EdgeDB.Binary; +using EdgeDB.Binary.Builders; +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Dynamic; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace EdgeDB.Binary.Codecs +{ + internal sealed class Object : ICodec, IArgumentCodec + { + private readonly ICodec[] _innerCodecs; + private readonly string[] _propertyNames; + private TypeDeserializerFactory? _factory; + private Type? _targetType; + private bool _initialized; + + internal Object(ObjectShapeDescriptor descriptor, List codecs) + { + _innerCodecs = new ICodec[descriptor.Shapes.Length]; + _propertyNames = new string[descriptor.Shapes.Length]; + + for(int i = 0; i != descriptor.Shapes.Length; i++) + { + var shape = descriptor.Shapes[i]; + _innerCodecs[i] = codecs[shape.TypePos]; + _propertyNames[i] = shape.Name; + } + } + + internal Object(NamedTupleTypeDescriptor descriptor, List codecs) + { + _innerCodecs = new ICodec[descriptor.Elements.Length]; + _propertyNames = new string[descriptor.Elements.Length]; + + for (int i = 0; i != descriptor.Elements.Length; i++) + { + var shape = descriptor.Elements[i]; + _innerCodecs[i] = codecs[shape.TypePos]; + _propertyNames[i] = shape.Name; + } + } + + internal Object(ICodec[] innerCodecs, string[] propertyNames) + { + _innerCodecs = innerCodecs; + _propertyNames = propertyNames; + } + + public void Initialize(Type target) + { + if (_initialized && target == _targetType) + return; + + _targetType = target; + + try + { + _factory = TypeBuilder.GetDeserializationFactory(target); + var deserializerInfo = TypeBuilder.TypeInfo[target]; + + // initialize any other object codecs that are properties + for (int i = 0; i != _innerCodecs.Length; i++) + { + if (_innerCodecs[i] is Object objCodec) + { + if (!deserializerInfo.PropertyMap.TryGetValue(_propertyNames[i], out var propInfo)) + throw new EdgeDBException($"Property {_propertyNames[i]} not found on type {target.Name}"); + + objCodec.Initialize(propInfo.Type); + } + } + + _initialized = true; + } + catch (Exception) when (_targetType == typeof(object)) + { + _factory = (ref ObjectEnumerator enumerator) => enumerator.ToDynamic(); + } + } + + public unsafe object? Deserialize(ref PacketReader reader) + { + if (!_initialized || _factory is null || _targetType is null) + Initialize(typeof(object)); + + // reader is being copied if we just pass it as 'ref reader' to our object enumerator, + // so we need to pass the underlying data as a reference and wrap a new reader ontop. + // This method ensures we're not copying the packet in memory again but the downside is + // our 'reader' variable isn't kept up to data with the reader in the object enumerator. + var enumerator = new ObjectEnumerator(ref reader.Data, reader.Position, _propertyNames, _innerCodecs); + + try + { + return _factory!(ref enumerator); + } + catch(Exception x) + { + throw new EdgeDBException($"Failed to deserialize object to {_targetType}", x); + } + finally + { + // set the readers position to the enumerators' readers position. + reader.Position = enumerator.Reader.Position; + } + } + + public void Serialize(ref PacketWriter writer, object? value) + { + throw new NotImplementedException(); + } + + public void SerializeArguments(ref PacketWriter writer, object? value) + { + object?[]? values = null; + + if (value is IDictionary dict) + values = _propertyNames.Select(x => dict[x]).ToArray(); + else if (value is object?[] arr) + value = arr; + + if (values is null) + { + throw new ArgumentException($"Expected dynamic object or array but got {value?.GetType()?.Name ?? "null"}"); + } + + writer.Write(values.Length); + + for (int i = 0; i != values.Length; i++) + { + var element = values[i]; + var innerCodec = _innerCodecs[i]; + + // reserved + writer.Write(0); + + // encode + if (element is null) + { + writer.Write(-1); + } + else + { + // special case for enums + if (element.GetType().IsEnum && innerCodec is Text) + element = element.ToString(); + + writer.WriteToWithInt32Length((ref PacketWriter innerWriter) => innerCodec.Serialize(ref innerWriter, element)); + } + } + } + } +} diff --git a/src/EdgeDB.Net.Driver/Codecs/RangeCodec.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/RangeCodec.cs similarity index 76% rename from src/EdgeDB.Net.Driver/Codecs/RangeCodec.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/RangeCodec.cs index 33d401cd..ef925ef2 100644 --- a/src/EdgeDB.Net.Driver/Codecs/RangeCodec.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/RangeCodec.cs @@ -1,13 +1,13 @@ -using EdgeDB.DataTypes; +using EdgeDB.DataTypes; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class RangeCodec : ICodec> + internal sealed class RangeCodec : ICodec> where T : struct { private ICodec _innerCodec; @@ -41,7 +41,7 @@ public Range Deserialize(ref PacketReader reader) return new Range(lowerBound, upperBound, (flags & RangeFlags.IncudeLowerBound) != 0, (flags & RangeFlags.IncludeUpperBound) != 0); } - public void Serialize(PacketWriter writer, Range value) + public void Serialize(ref PacketWriter writer, Range value) { var flags = value.IsEmpty ? RangeFlags.Empty @@ -54,18 +54,12 @@ public void Serialize(PacketWriter writer, Range value) if(value.Lower.HasValue) { - var lowerWriter = new PacketWriter(); - _innerCodec.Serialize(value.Lower.Value); - writer.Write((int)lowerWriter.Length); - writer.Write(lowerWriter); + writer.WriteToWithInt32Length((ref PacketWriter innerWriter) => _innerCodec.Serialize(ref innerWriter, value.Lower.Value)); } if (value.Upper.HasValue) { - var upperWriter = new PacketWriter(); - _innerCodec.Serialize(value.Upper.Value); - writer.Write((int)upperWriter.Length); - writer.Write(upperWriter); + writer.WriteToWithInt32Length((ref PacketWriter innerWriter) => _innerCodec.Serialize(ref innerWriter, value.Upper.Value)); } } diff --git a/src/EdgeDB.Net.Driver/Codecs/Set.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Set.cs similarity index 84% rename from src/EdgeDB.Net.Driver/Codecs/Set.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Set.cs index 78c808d0..50071259 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Set.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Set.cs @@ -1,6 +1,6 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Set : ICodec> + internal sealed class Set : ICodec> { private readonly ICodec _innerCodec; @@ -12,16 +12,16 @@ public Set(ICodec innerCodec) public IEnumerable? Deserialize(ref PacketReader reader) { if (_innerCodec is Array) - return DecodeSetOfArrays(reader); - else return DecodeSet(reader); + return DecodeSetOfArrays(ref reader); + else return DecodeSet(ref reader); } - public void Serialize(PacketWriter writer, IEnumerable? value) + public void Serialize(ref PacketWriter writer, IEnumerable? value) { throw new NotImplementedException(); } - private IEnumerable? DecodeSetOfArrays(PacketReader reader) + private IEnumerable? DecodeSetOfArrays(ref PacketReader reader) { var dimensions = reader.ReadInt32(); @@ -64,7 +64,7 @@ public void Serialize(PacketWriter writer, IEnumerable? value) return result; } - private IEnumerable? DecodeSet(PacketReader reader) + private IEnumerable? DecodeSet(ref PacketReader reader) { var dimensions = reader.ReadInt32(); diff --git a/src/EdgeDB.Net.Driver/Codecs/Shared/Dimension.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Shared/Dimension.cs similarity index 81% rename from src/EdgeDB.Net.Driver/Codecs/Shared/Dimension.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Shared/Dimension.cs index 5491b5b5..611f1777 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Shared/Dimension.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Shared/Dimension.cs @@ -1,4 +1,4 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { internal readonly struct Dimension { diff --git a/src/EdgeDB.Net.Driver/Codecs/Shared/Element.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Shared/Element.cs similarity index 85% rename from src/EdgeDB.Net.Driver/Codecs/Shared/Element.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Shared/Element.cs index 453ed5fa..69e3552e 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Shared/Element.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Shared/Element.cs @@ -1,4 +1,4 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { internal readonly struct Element { diff --git a/src/EdgeDB.Net.Driver/Codecs/Shared/NumericSign.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Shared/NumericSign.cs similarity index 83% rename from src/EdgeDB.Net.Driver/Codecs/Shared/NumericSign.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Shared/NumericSign.cs index 3fdceee2..f1a28b68 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Shared/NumericSign.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Shared/NumericSign.cs @@ -1,4 +1,4 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { internal enum NumericSign : ushort { diff --git a/src/EdgeDB.Net.Driver/Codecs/SparceObject.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/SparceObject.cs similarity index 70% rename from src/EdgeDB.Net.Driver/Codecs/SparceObject.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/SparceObject.cs index 55e21d6f..7fb360bb 100644 --- a/src/EdgeDB.Net.Driver/Codecs/SparceObject.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/SparceObject.cs @@ -1,4 +1,4 @@ -using EdgeDB.Binary; +using EdgeDB.Binary; using System; using System.Collections.Generic; using System.Dynamic; @@ -6,17 +6,24 @@ using System.Text; using System.Threading.Tasks; -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class SparceObject : ICodec + internal sealed class SparceObject : ICodec { private readonly ICodec[] _innerCodecs; - private readonly List _fieldNames; + private readonly string[] _fieldNames; - internal SparceObject(ICodec[] innerCodecs, ShapeElement[] shape) + internal SparceObject(InputShapeDescriptor descriptor, List codecs) { - _innerCodecs = innerCodecs; - _fieldNames = shape.Select(x => x.Name).ToList(); + _innerCodecs = new ICodec[descriptor.Shapes.Length]; + _fieldNames = new string[descriptor.Shapes.Length]; + + for (int i = 0; i != descriptor.Shapes.Length; i++) + { + var shape = descriptor.Shapes[i]; + _innerCodecs[i] = codecs[shape.TypePos]; + _fieldNames[i] = shape.Name; + } } public object? Deserialize(ref PacketReader reader) @@ -56,7 +63,7 @@ internal SparceObject(ICodec[] innerCodecs, ShapeElement[] shape) return data; } - public void Serialize(PacketWriter writer, object? value) + public void Serialize(ref PacketWriter writer, object? value) { if (value is not IDictionary dict) throw new InvalidOperationException($"Cannot serialize {value?.GetType() ?? Type.Missing} as a sparce object."); @@ -71,7 +78,7 @@ public void Serialize(PacketWriter writer, object? value) foreach(var element in dict) { - var index = _fieldNames.IndexOf(element.Key); + var index = Array.IndexOf(_fieldNames, element.Key); if (index == -1) throw new MissingCodecException($"No serializer found for field {element.Key}"); @@ -82,13 +89,9 @@ public void Serialize(PacketWriter writer, object? value) writer.Write(-1); else { - using var subWriter = new PacketWriter(); var codec = _innerCodecs[index]; - codec.Serialize(subWriter, element.Value); - writer.Write((int)subWriter.Length); - writer.Write(subWriter); + writer.WriteToWithInt32Length((ref PacketWriter innerWriter) => codec.Serialize(ref innerWriter, element.Value)); } - } } } diff --git a/src/EdgeDB.Net.Driver/Codecs/Text.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Text.cs similarity index 56% rename from src/EdgeDB.Net.Driver/Codecs/Text.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Text.cs index 603134b9..fa03a224 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Text.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Text.cs @@ -1,15 +1,16 @@ -using System.Text; +using EdgeDB.Binary; +using System.Text; -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Text : IScalarCodec + internal sealed class Text : IScalarCodec { public string Deserialize(ref PacketReader reader) { return reader.ConsumeString(); } - public void Serialize(PacketWriter writer, string? value) + public void Serialize(ref PacketWriter writer, string? value) { if (value is not null) writer.Write(Encoding.UTF8.GetBytes(value)); diff --git a/src/EdgeDB.Net.Driver/Codecs/Tuple.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/Tuple.cs similarity index 87% rename from src/EdgeDB.Net.Driver/Codecs/Tuple.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/Tuple.cs index feb33fd0..0b74ffcb 100644 --- a/src/EdgeDB.Net.Driver/Codecs/Tuple.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/Tuple.cs @@ -1,9 +1,10 @@ -using EdgeDB.DataTypes; +using EdgeDB.Binary; +using EdgeDB.DataTypes; using System.Runtime.CompilerServices; -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class Tuple : ICodec + internal sealed class Tuple : ICodec { private readonly ICodec[] _innerCodecs; @@ -47,7 +48,7 @@ public TransientTuple Deserialize(ref PacketReader reader) return new TransientTuple(_innerCodecs.Select(x => x.ConverterType).ToArray(), values); } - public void Serialize(PacketWriter writer, TransientTuple value) + public void Serialize(ref PacketWriter writer, TransientTuple value) { throw new NotSupportedException("Tuples cannot be passed in query arguments"); } diff --git a/src/EdgeDB.Net.Driver/Codecs/UUID.cs b/src/EdgeDB.Net.Driver/Binary/Codecs/UUID.cs similarity index 55% rename from src/EdgeDB.Net.Driver/Codecs/UUID.cs rename to src/EdgeDB.Net.Driver/Binary/Codecs/UUID.cs index d5a9f277..111774ff 100644 --- a/src/EdgeDB.Net.Driver/Codecs/UUID.cs +++ b/src/EdgeDB.Net.Driver/Binary/Codecs/UUID.cs @@ -1,13 +1,13 @@ -namespace EdgeDB.Codecs +namespace EdgeDB.Binary.Codecs { - internal class UUID : IScalarCodec + internal sealed class UUID : IScalarCodec { public Guid Deserialize(ref PacketReader reader) { return reader.ReadGuid(); } - public void Serialize(PacketWriter writer, Guid value) + public void Serialize(ref PacketWriter writer, Guid value) { writer.Write(value); } diff --git a/src/EdgeDB.Net.Driver/Models/Shared/Annotation.cs b/src/EdgeDB.Net.Driver/Binary/Common/Annotation.cs similarity index 85% rename from src/EdgeDB.Net.Driver/Models/Shared/Annotation.cs rename to src/EdgeDB.Net.Driver/Binary/Common/Annotation.cs index afb53905..1f18bb66 100644 --- a/src/EdgeDB.Net.Driver/Models/Shared/Annotation.cs +++ b/src/EdgeDB.Net.Driver/Binary/Common/Annotation.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,6 +11,8 @@ namespace EdgeDB.Binary /// public readonly struct Annotation { + internal int Size => Encoding.UTF8.GetByteCount(Name) + Encoding.UTF8.GetByteCount(Value); + /// /// Gets the name of this annotation. /// diff --git a/src/EdgeDB.Net.Driver/Models/Shared/ConnectionParam.cs b/src/EdgeDB.Net.Driver/Binary/Common/ConnectionParam.cs similarity index 65% rename from src/EdgeDB.Net.Driver/Models/Shared/ConnectionParam.cs rename to src/EdgeDB.Net.Driver/Binary/Common/ConnectionParam.cs index e5dd701b..5dc14606 100644 --- a/src/EdgeDB.Net.Driver/Models/Shared/ConnectionParam.cs +++ b/src/EdgeDB.Net.Driver/Binary/Common/ConnectionParam.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -8,11 +9,14 @@ namespace EdgeDB.Binary { internal readonly struct ConnectionParam { + public int Size + => BinaryUtils.SizeOfString(Name) + BinaryUtils.SizeOfString(Value); + public string Name { get; init; } public string Value { get; init; } - public void Write(PacketWriter writer) + public void Write(ref PacketWriter writer) { writer.Write(Name); writer.Write(Value); diff --git a/src/EdgeDB.Net.Driver/Models/Shared/KeyValue.cs b/src/EdgeDB.Net.Driver/Binary/Common/KeyValue.cs similarity index 91% rename from src/EdgeDB.Net.Driver/Models/Shared/KeyValue.cs rename to src/EdgeDB.Net.Driver/Binary/Common/KeyValue.cs index d9ace42a..80f1a30e 100644 --- a/src/EdgeDB.Net.Driver/Models/Shared/KeyValue.cs +++ b/src/EdgeDB.Net.Driver/Binary/Common/KeyValue.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -32,5 +32,8 @@ internal KeyValue(ushort code, byte[] value) /// public override string ToString() => Encoding.UTF8.GetString(Value); + + internal int ToInt() + => int.Parse(ToString()); } } diff --git a/src/EdgeDB.Net.Driver/Models/Shared/MessageSeverity.cs b/src/EdgeDB.Net.Driver/Binary/Common/MessageSeverity.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/MessageSeverity.cs rename to src/EdgeDB.Net.Driver/Binary/Common/MessageSeverity.cs diff --git a/src/EdgeDB.Net.Driver/Models/Shared/ProtocolExtension.cs b/src/EdgeDB.Net.Driver/Binary/Common/ProtocolExtension.cs similarity index 81% rename from src/EdgeDB.Net.Driver/Models/Shared/ProtocolExtension.cs rename to src/EdgeDB.Net.Driver/Binary/Common/ProtocolExtension.cs index ba387951..887c6cd0 100644 --- a/src/EdgeDB.Net.Driver/Models/Shared/ProtocolExtension.cs +++ b/src/EdgeDB.Net.Driver/Binary/Common/ProtocolExtension.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -12,6 +12,9 @@ namespace EdgeDB.Binary /// public readonly struct ProtocolExtension { + internal int Size + => Encoding.UTF8.GetByteCount(Name) + _annotations.Sum(x => x.Size); + /// /// Gets the name of the protocol extension. /// @@ -30,9 +33,10 @@ internal ProtocolExtension(ref PacketReader reader) _annotations = reader.ReadAnnotations(); } - internal void Write(PacketWriter writer) + internal void Write(ref PacketWriter writer) { writer.Write(Name); + writer.Write(_annotations); } } } diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/ArrayTypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/ArrayTypeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/ArrayTypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/ArrayTypeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/BaseScalarTypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/BaseScalarTypeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/BaseScalarTypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/BaseScalarTypeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/DescriptorType.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/DescriptorType.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/DescriptorType.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/DescriptorType.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/EnumerationTypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/EnumerationTypeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/EnumerationTypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/EnumerationTypeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/ITypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/ITypeDescriptor.cs similarity index 95% rename from src/EdgeDB.Net.Driver/Models/Descriptors/ITypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/ITypeDescriptor.cs index 4bc23e22..2f3460ac 100644 --- a/src/EdgeDB.Net.Driver/Models/Descriptors/ITypeDescriptor.cs +++ b/src/EdgeDB.Net.Driver/Binary/Descriptors/ITypeDescriptor.cs @@ -24,7 +24,7 @@ public static ITypeDescriptor GetDescriptor(ref PacketReader reader) DescriptorType.ObjectShapeDescriptor => new ObjectShapeDescriptor(id, ref reader), DescriptorType.ScalarTypeDescriptor => new ScalarTypeDescriptor(id, ref reader), DescriptorType.ScalarTypeNameAnnotation => new ScalarTypeNameAnnotation(id, ref reader), - DescriptorType.SetDescriptor => new SetDescriptor(id, ref reader), + DescriptorType.SetDescriptor => new SetTypeDescriptor(id, ref reader), DescriptorType.TupleTypeDescriptor => new TupleTypeDescriptor(id, ref reader), DescriptorType.InputShapeDescriptor => new InputShapeDescriptor(id, ref reader), DescriptorType.RangeTypeDescriptor => new RangeTypeDescriptor(id, ref reader), diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/InputShapeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/InputShapeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/InputShapeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/InputShapeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/NamedTupleTypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/NamedTupleTypeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/NamedTupleTypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/NamedTupleTypeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/ObjectShapeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/ObjectShapeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/ObjectShapeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/ObjectShapeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/RangeTypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/RangeTypeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/RangeTypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/RangeTypeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/ScalarTypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/ScalarTypeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/ScalarTypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/ScalarTypeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/ScalarTypeNameAnnotation.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/ScalarTypeNameAnnotation.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/ScalarTypeNameAnnotation.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/ScalarTypeNameAnnotation.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/SetDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/SetDescriptor.cs similarity index 70% rename from src/EdgeDB.Net.Driver/Models/Descriptors/SetDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/SetDescriptor.cs index 1d5f2f07..2a036ae7 100644 --- a/src/EdgeDB.Net.Driver/Models/Descriptors/SetDescriptor.cs +++ b/src/EdgeDB.Net.Driver/Binary/Descriptors/SetDescriptor.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,13 +6,13 @@ namespace EdgeDB.Binary { - internal readonly struct SetDescriptor : ITypeDescriptor + internal readonly struct SetTypeDescriptor : ITypeDescriptor { public readonly Guid Id; public readonly ushort TypePos; - public SetDescriptor(Guid id, ref PacketReader reader) + public SetTypeDescriptor(Guid id, ref PacketReader reader) { Id = id; TypePos = reader.ReadUInt16(); diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/TupleTypeDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/TupleTypeDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/TupleTypeDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/TupleTypeDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Models/Descriptors/TypeAnnotationDescriptor.cs b/src/EdgeDB.Net.Driver/Binary/Descriptors/TypeAnnotationDescriptor.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Descriptors/TypeAnnotationDescriptor.cs rename to src/EdgeDB.Net.Driver/Binary/Descriptors/TypeAnnotationDescriptor.cs diff --git a/src/EdgeDB.Net.Driver/Serializer/Dumps/DumpReader.cs b/src/EdgeDB.Net.Driver/Binary/Dumps/DumpReader.cs similarity index 97% rename from src/EdgeDB.Net.Driver/Serializer/Dumps/DumpReader.cs rename to src/EdgeDB.Net.Driver/Binary/Dumps/DumpReader.cs index 77ed14bb..81794511 100644 --- a/src/EdgeDB.Net.Driver/Serializer/Dumps/DumpReader.cs +++ b/src/EdgeDB.Net.Driver/Binary/Dumps/DumpReader.cs @@ -1,12 +1,11 @@ -using EdgeDB.Binary; +using EdgeDB.Binary; using EdgeDB.Binary.Packets; -using EdgeDB.Models; using EdgeDB.Utils; using System.Security.Cryptography; namespace EdgeDB.Dumps { - internal class DumpReader + internal sealed class DumpReader { public static (Restore Restore, IEnumerable Blocks) ReadDatabaseDump(Stream stream) { diff --git a/src/EdgeDB.Net.Driver/Serializer/Dumps/DumpWriter.cs b/src/EdgeDB.Net.Driver/Binary/Dumps/DumpWriter.cs similarity index 61% rename from src/EdgeDB.Net.Driver/Serializer/Dumps/DumpWriter.cs rename to src/EdgeDB.Net.Driver/Binary/Dumps/DumpWriter.cs index 3272c03e..737ea8b1 100644 --- a/src/EdgeDB.Net.Driver/Serializer/Dumps/DumpWriter.cs +++ b/src/EdgeDB.Net.Driver/Binary/Dumps/DumpWriter.cs @@ -1,9 +1,9 @@ -using EdgeDB.Binary.Packets; -using EdgeDB.Models; +using EdgeDB.Binary; +using EdgeDB.Binary.Packets; namespace EdgeDB.Dumps { - internal class DumpWriter : IDisposable + internal ref struct DumpWriter { public const long DumpVersion = 1; public const int FileFormatLength = 17; @@ -26,12 +26,12 @@ internal class DumpWriter : IDisposable private static byte[] Version => BitConverter.GetBytes((long)1).Reverse().ToArray(); - private readonly Stream _stream; + public ReadOnlyMemory Data => _writer.GetBytes(); + private readonly PacketWriter _writer; - public DumpWriter(Stream output) + public DumpWriter() { - _stream = output; - _writer = new PacketWriter(_stream); + _writer = new PacketWriter(); _writer.Write(FileFormat); _writer.Write(Version); @@ -43,20 +43,19 @@ public void WriteDumpHeader(DumpHeader header) _writer.Write(header.Hash.ToArray()); _writer.Write(header.Length); _writer.Write(header.Raw); - - _writer.Flush(); } - public void WriteDumpBlock(DumpBlock block) + public void WriteDumpBlocks(List blocks) { - _writer.Write('D'); - _writer.Write(block.HashBuffer); - _writer.Write(block.Length); - _writer.Write(block.Raw); - - _writer.Flush(); + for(int i = 0; i != blocks.Count; i++) + { + var block = blocks[i]; + + _writer.Write('D'); + _writer.Write(block.HashBuffer); + _writer.Write(block.Length); + _writer.Write(block.Raw); + } } - - public void Dispose() => _writer.Dispose(); } } diff --git a/src/EdgeDB.Net.Driver/Binary/PacketReader.cs b/src/EdgeDB.Net.Driver/Binary/PacketReader.cs new file mode 100644 index 00000000..12ea5603 --- /dev/null +++ b/src/EdgeDB.Net.Driver/Binary/PacketReader.cs @@ -0,0 +1,172 @@ +using EdgeDB.Utils; +using System.Buffers.Binary; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; + +namespace EdgeDB.Binary +{ + internal unsafe ref struct PacketReader + { + public bool Empty + => Position >= Data.Length || Data.IsEmpty; + + internal Span Data; + internal int Position; + + public PacketReader(Span bytes, int position = 0) + { + Data = bytes; + Position = position; + } + + public PacketReader(ref Span bytes, int position = 0) + { + Data = bytes; + Position = position; + } + + #region Unmanaged basic reads & endianness correction + private T UnsafeReadAs() + where T : unmanaged + { + var ret = Unsafe.Read(Unsafe.AsPointer(ref Data[Position])); + + BinaryUtils.CorrectEndianness(ref ret); + Position += sizeof(T); + return ret; + } + + public bool ReadBoolean() + => ReadByte() > 0; + + public byte ReadByte() + => UnsafeReadAs(); + + public char ReadChar() + => UnsafeReadAs(); + + public double ReadDouble() + => UnsafeReadAs(); + + public float ReadSingle() + => UnsafeReadAs(); + + public ulong ReadUInt64() + => UnsafeReadAs(); + + public long ReadInt64() + => UnsafeReadAs(); + + public uint ReadUInt32() + => UnsafeReadAs(); + + public int ReadInt32() + => UnsafeReadAs(); + + public ushort ReadUInt16() + => UnsafeReadAs(); + + public short ReadInt16() + => UnsafeReadAs(); + #endregion + + public void Skip(int count) + { + Position += count; + } + + public byte[] ConsumeByteArray() + { + return Data[Position..].ToArray(); + } + + public string ConsumeString() + { + return Encoding.UTF8.GetString(Data[Position..]); + } + + public Guid ReadGuid() + { + var a = ReadInt32(); + var b = ReadInt16(); + var c = ReadInt16(); + + var buffer = Data[Position..(Position + 8)]; + var guid = new Guid(a, b, c, buffer.ToArray()); + Position += 8; + return guid; + } + + public KeyValue[] ReadKeyValues() + { + var count = ReadUInt16(); + var arr = new KeyValue[count]; + + for (ushort i = 0; i != count; i++) + { + arr[i] = ReadKeyValue(); + } + + return arr; + } + + public KeyValue ReadKeyValue() + { + var code = ReadUInt16(); + var value = ReadByteArray(); + + return new KeyValue(code, value); + } + + public string ReadString() + { + var strLength = (int)ReadUInt32(); + var str = Encoding.UTF8.GetString(Data[Position..(strLength + Position)]); + Position += strLength; + return str; + } + + public Annotation[] ReadAnnotations() + { + var count = ReadUInt16(); + + Annotation[] arr = new Annotation[count]; + + for (ushort i = 0; i != count; i++) + { + arr[i] = ReadAnnotation(); + } + + return arr; + } + + public Annotation ReadAnnotation() + { + var name = ReadString(); + var value = ReadString(); + + return new Annotation(name, value); + } + + public byte[] ReadByteArray() + { + var length = (int)ReadUInt32(); + var buffer = Data[Position..(Position + length)]; + Position += length; + return buffer.ToArray(); + } + + public void ReadBytes(int length, out Span buff) + { + buff = Data[Position..(Position + length)]; + Position += length; + } + + public void Dispose() + { + Data.Clear(); + } + } +} diff --git a/src/EdgeDB.Net.Driver/Serializer/PacketSerializer.cs b/src/EdgeDB.Net.Driver/Binary/PacketSerializer.cs similarity index 96% rename from src/EdgeDB.Net.Driver/Serializer/PacketSerializer.cs rename to src/EdgeDB.Net.Driver/Binary/PacketSerializer.cs index 0ec635cf..6558a261 100644 --- a/src/EdgeDB.Net.Driver/Serializer/PacketSerializer.cs +++ b/src/EdgeDB.Net.Driver/Binary/PacketSerializer.cs @@ -1,14 +1,12 @@ -using EdgeDB.Binary; using EdgeDB.Binary.Packets; -using EdgeDB.Codecs; -using EdgeDB.Models; +using EdgeDB.Binary.Codecs; using System.Collections.Concurrent; using System.Numerics; using System.Reflection; -namespace EdgeDB +namespace EdgeDB.Binary { - internal class PacketSerializer + internal sealed class PacketSerializer { public static string? GetEdgeQLType(Type t) { @@ -103,7 +101,6 @@ internal class PacketSerializer { typeof(DateTime), "local_datetime" }, { typeof(DateTimeOffset), "datetime" }, { typeof(TimeSpan), "duration" }, - { typeof(Sequence), "sequence" }, }; } } diff --git a/src/EdgeDB.Net.Driver/Binary/PacketWriter.cs b/src/EdgeDB.Net.Driver/Binary/PacketWriter.cs new file mode 100644 index 00000000..df059be0 --- /dev/null +++ b/src/EdgeDB.Net.Driver/Binary/PacketWriter.cs @@ -0,0 +1,232 @@ +using EdgeDB.Binary; +using EdgeDB.Utils; +using System; +using System.Buffers; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.Binary +{ + internal unsafe ref struct PacketWriter + { + public long Index + => _trackedPointer - _basePointer; + + internal int Size; + private readonly IMemoryOwner? _memoryOwner; + private readonly bool _isDynamic; + private Memory _rawBuffer; + private byte* _trackedPointer; + private byte* _basePointer; + private MemoryHandle _handle; + + public PacketWriter(int size, bool isDynamic = false) + { + // use shared memory if our size is fixed + if (size > MemoryPool.Shared.MaxBufferSize || isDynamic) + { + _rawBuffer = new Memory(new byte[size]); + _memoryOwner = null; + } + else + { + _memoryOwner = MemoryPool.Shared.Rent(size); + _rawBuffer = _memoryOwner.Memory; + } + + _handle = _rawBuffer.Pin(); + _trackedPointer = (byte*)_handle.Pointer; + _basePointer = (byte*)_handle.Pointer; + Size = size; + _isDynamic = isDynamic; + } + + public PacketWriter() + : this(512, true) + { + + } + + #region Position & conversion + public void SeekToIndex(long index) + => _trackedPointer = _basePointer + index; + + public void Advance(long count) + => _trackedPointer += count; + + public ReadOnlyMemory GetBytes() + => _rawBuffer[..(_isDynamic ? (int)Index : Size)]; + #endregion + + public delegate void WriteAction(ref PacketWriter writer); + public void WriteToWithInt32Length(WriteAction action) + { + var currentIndex = Index; + Advance(sizeof(int)); + action(ref this); + var lastIndex = Index; + SeekToIndex(currentIndex); + Write((int)(lastIndex - currentIndex - sizeof(int))); + SeekToIndex(lastIndex); + } + + #region Very raw memory writing methods for unmanaged + private void Resize(uint target) + { + if(!_isDynamic) + throw new IndexOutOfRangeException("Cannot resize a non-dynamic packet writer"); + + var newSize = + target + Index > 2048 + ? Size + (int)target + 512 + : Size > 2048 ? Size + 2048 : (Size << 1) + (int)target; + + var index = Index; + + var newBuffer = new Memory(new byte[newSize]); + _rawBuffer.CopyTo(newBuffer); + _rawBuffer = newBuffer; + _handle.Dispose(); + _handle = newBuffer.Pin(); + _basePointer = (byte*)_handle.Pointer; + _trackedPointer = _basePointer + index; + + Size = newSize; + } + + private void WriteRaw(void* ptr, uint count) + { + if (Index + count > Size) + Resize(count); + + Unsafe.CopyBlock(_trackedPointer, ptr, count); + _trackedPointer += count; + } + + public void Write(ref PacketWriter value) + { + WriteRaw(value._basePointer, (uint)value.Index); + } + + private void UnsafeWrite(ref T value) + where T : unmanaged + { + var size = sizeof(T); + if (Index + size > Size) + Resize((uint)size); + + BinaryUtils.CorrectEndianness(ref value); + Unsafe.WriteUnaligned(_trackedPointer, value); + _trackedPointer += sizeof(T); + } + + public void Write(T value) + where T : unmanaged + => UnsafeWrite(ref value); + + public void Write(double value) + => UnsafeWrite(ref value); + + public void Write(float value) + => UnsafeWrite(ref value); + + public void Write(ulong value) + => UnsafeWrite(ref value); + + public void Write(long value) + => UnsafeWrite(ref value); + + public void Write(uint value) + => UnsafeWrite(ref value); + + public void Write(int value) + => UnsafeWrite(ref value); + + public void Write(short value) + => UnsafeWrite(ref value); + + public void Write(ushort value) + => UnsafeWrite(ref value); + + public void Write(byte value) + => UnsafeWrite(ref value); + + public void Write(sbyte value) + => UnsafeWrite(ref value); + + public void Write(char value) + => UnsafeWrite(ref value); + + public void Write(bool value) + => UnsafeWrite(ref value); + #endregion + + public void WriteArray(byte[] buffer) + { + Write((uint)buffer.Length); + Write(buffer); + } + + public void WriteArrayWithoutLength(byte[] buffer) + => Write(buffer); + + public void Write(IEnumerable? headers) + { + // write length + Write((ushort)(headers?.Count() ?? 0)); + + if (headers is not null) + { + foreach (var header in headers) + { + Write(header.Name); + Write(header.Value); + } + } + } + + public void Write(KeyValue header) + { + Write(header.Code); + Write(header.Value); + } + + public void Write(Guid value) + { + var bytes = HexConverter.FromHex(value.ToString().Replace("-", "")); + Write(bytes); + } + + public void Write(byte[] array) + { + fixed (byte* ptr = array) + { + WriteRaw(ptr, (uint)array.Length); + } + } + + public void Write(string value) + { + if (value is null) + Write((uint)0); + else + { + var buffer = Encoding.UTF8.GetBytes(value); + Write((uint)buffer.Length); + Write(buffer); + } + } + + public void Dispose() + { + _handle.Dispose(); + _memoryOwner?.Dispose(); + } + } +} diff --git a/src/EdgeDB.Net.Driver/Models/IReceiveable.cs b/src/EdgeDB.Net.Driver/Binary/Packets/IReceiveable.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/IReceiveable.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/IReceiveable.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/AuthStatus.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/AuthStatus.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/AuthStatus.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/AuthStatus.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/AuthenticationStatus.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/AuthenticationStatus.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/AuthenticationStatus.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/AuthenticationStatus.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/CommandComplete.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/CommandComplete.cs similarity index 98% rename from src/EdgeDB.Net.Driver/Models/Receivables/CommandComplete.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/CommandComplete.cs index 994b006b..f6f0e27b 100644 --- a/src/EdgeDB.Net.Driver/Models/Receivables/CommandComplete.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/CommandComplete.cs @@ -1,4 +1,3 @@ -using EdgeDB.Codecs; using System; using System.Collections.Generic; using System.Collections.Immutable; diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/CommandDataDescription.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/CommandDataDescription.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/CommandDataDescription.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/CommandDataDescription.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/Data.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/Data.cs similarity index 84% rename from src/EdgeDB.Net.Driver/Models/Receivables/Data.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/Data.cs index 9e74a2c4..529c5458 100644 --- a/src/EdgeDB.Net.Driver/Models/Receivables/Data.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/Data.cs @@ -1,4 +1,4 @@ -using System.Collections.Immutable; +using System.Collections.Immutable; namespace EdgeDB.Binary.Packets { @@ -19,6 +19,15 @@ public IReadOnlyCollection PayloadData internal readonly byte[] PayloadBuffer; + internal Data(byte[] buff) + { + PayloadBuffer = buff; + } + public Data() + { + PayloadBuffer = new byte[] { }; + } + internal Data(ref PacketReader reader) { // skip arary since its always one, errr should be one diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/DumpBlock.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/DumpBlock.cs similarity index 88% rename from src/EdgeDB.Net.Driver/Models/Receivables/DumpBlock.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/DumpBlock.cs index 0502cc8a..e9b61fea 100644 --- a/src/EdgeDB.Net.Driver/Models/Receivables/DumpBlock.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/DumpBlock.cs @@ -1,4 +1,5 @@ -using System.Collections.Immutable; +using EdgeDB.Utils; +using System.Collections.Immutable; using System.Security.Cryptography; namespace EdgeDB.Binary.Packets @@ -8,6 +9,9 @@ namespace EdgeDB.Binary.Packets /// public readonly struct DumpBlock : IReceiveable { + internal int Size + => sizeof(int) + BinaryUtils.SizeOfByteArray(Raw) + BinaryUtils.SizeOfByteArray(HashBuffer); + /// public ServerMessageType Type => ServerMessageType.DumpBlock; diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/DumpHeader.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/DumpHeader.cs similarity index 99% rename from src/EdgeDB.Net.Driver/Models/Receivables/DumpHeader.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/DumpHeader.cs index 05ae7268..363e8a71 100644 --- a/src/EdgeDB.Net.Driver/Models/Receivables/DumpHeader.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/DumpHeader.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/ErrorResponse.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ErrorResponse.cs similarity index 88% rename from src/EdgeDB.Net.Driver/Models/Receivables/ErrorResponse.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ErrorResponse.cs index 29e0a309..b6713ccc 100644 --- a/src/EdgeDB.Net.Driver/Models/Receivables/ErrorResponse.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ErrorResponse.cs @@ -1,4 +1,3 @@ -using EdgeDB.Models; using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -48,6 +47,12 @@ internal ErrorResponse(ref PacketReader reader) _attributes = reader.ReadKeyValues(); } + internal bool TryGetAttribute(ushort code, out KeyValue value) + { + value = _attributes.FirstOrDefault(x => x.Code == code); + return _attributes.Any(x => x.Code == code); + } + string? IExecuteError.Message => Message; ServerErrorCodes IExecuteError.ErrorCode => ErrorCode; diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/LogMessage.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/LogMessage.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/LogMessage.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/LogMessage.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/ParameterStatus.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ParameterStatus.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/ParameterStatus.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ParameterStatus.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/ReadyForCommand.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ReadyForCommand.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/ReadyForCommand.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ReadyForCommand.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/RestoreReady.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/RestoreReady.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/RestoreReady.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/RestoreReady.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/ServerHandshake.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ServerHandshake.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/ServerHandshake.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ServerHandshake.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/ServerKeyData.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ServerKeyData.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/ServerKeyData.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ServerKeyData.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/ServerMessageType.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ServerMessageType.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/ServerMessageType.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/ServerMessageType.cs diff --git a/src/EdgeDB.Net.Driver/Models/Receivables/StateDataDescription.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Receivables/StateDataDescription.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Receivables/StateDataDescription.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Receivables/StateDataDescription.cs diff --git a/src/EdgeDB.Net.Driver/Binary/Packets/Sendable.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendable.cs new file mode 100644 index 00000000..c0b07f9e --- /dev/null +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendable.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.Binary +{ + internal abstract class Sendable + { + public abstract int Size { get; } + + public abstract ClientMessageTypes Type { get;} + + protected abstract void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client); + + public void Write(ref PacketWriter writer, EdgeDBBinaryClient client) + { + // advance 5 bytes + var start = writer.Index; + writer.Advance(5); + + // write the body of the packet + BuildPacket(ref writer, client); + + // store the index after writing the body + var eofPosition = writer.Index; + + // seek back to the beginning. + writer.SeekToIndex(start); + + // write the type and size + writer.Write((sbyte)Type); + writer.Write((uint)Size + 4); + + // go back to eof + writer.SeekToIndex(eofPosition); + } + + public int GetSize() + => Size + 5; + } +} diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/AuthenticationSASLInitialResponse.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/AuthenticationSASLInitialResponse.cs similarity index 56% rename from src/EdgeDB.Net.Driver/Models/Sendables/AuthenticationSASLInitialResponse.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/AuthenticationSASLInitialResponse.cs index e1676bac..30d43ba9 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/AuthenticationSASLInitialResponse.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/AuthenticationSASLInitialResponse.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,11 +7,14 @@ namespace EdgeDB.Binary.Packets { - internal class AuthenticationSASLInitialResponse : Sendable + internal sealed class AuthenticationSASLInitialResponse : Sendable { public override ClientMessageTypes Type => ClientMessageTypes.AuthenticationSASLInitialResponse; + public override int Size + => BinaryUtils.SizeOfString(Method) + BinaryUtils.SizeOfByteArray(Payload); + public string Method { get; set; } public byte[] Payload { get; set; } @@ -21,10 +25,15 @@ public AuthenticationSASLInitialResponse(byte[] payload,string method) Payload = payload; } - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { writer.Write(Method); writer.WriteArray(Payload); } + + public override string ToString() + { + return $"{Method} {Encoding.UTF8.GetString(Payload)}"; + } } } diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/AuthenticationSASLResponse.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/AuthenticationSASLResponse.cs similarity index 54% rename from src/EdgeDB.Net.Driver/Models/Sendables/AuthenticationSASLResponse.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/AuthenticationSASLResponse.cs index a40a3f5a..1963aa52 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/AuthenticationSASLResponse.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/AuthenticationSASLResponse.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,11 +7,14 @@ namespace EdgeDB.Binary.Packets { - internal class AuthenticationSASLResponse : Sendable + internal sealed class AuthenticationSASLResponse : Sendable { public override ClientMessageTypes Type => ClientMessageTypes.AuthenticationSASLResponse; + public override int Size + => BinaryUtils.SizeOfByteArray(_payload); + private readonly byte[] _payload; public AuthenticationSASLResponse(byte[] payload) @@ -18,9 +22,14 @@ public AuthenticationSASLResponse(byte[] payload) _payload = payload; } - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { writer.WriteArray(_payload); } + + public override string ToString() + { + return Encoding.UTF8.GetString(_payload); + } } } diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/ClientHandshake.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/ClientHandshake.cs similarity index 57% rename from src/EdgeDB.Net.Driver/Models/Sendables/ClientHandshake.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/ClientHandshake.cs index 429f6b21..0c802683 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/ClientHandshake.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/ClientHandshake.cs @@ -1,15 +1,23 @@ -namespace EdgeDB.Binary.Packets +namespace EdgeDB.Binary.Packets { - internal class ClientHandshake : Sendable + internal sealed class ClientHandshake : Sendable { public override ClientMessageTypes Type => ClientMessageTypes.ClientHandshake; + public override int Size + { + get + { + return (sizeof(short) << 2) + ConnectionParameters.Sum(x => x.Size) + Extensions.Sum(x => x.Size); + } + } + public short MajorVersion { get; set; } public short MinorVersion { get; set; } public ConnectionParam[] ConnectionParameters { get; set; } = Array.Empty(); public ProtocolExtension[] Extensions { get; set; } = Array.Empty(); - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { writer.Write(MajorVersion); writer.Write(MinorVersion); @@ -17,13 +25,13 @@ protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient clie writer.Write((ushort)ConnectionParameters.Length); foreach (var param in ConnectionParameters) { - param.Write(writer); + param.Write(ref writer); } - writer.Write(Extensions.Length); + writer.Write((ushort)Extensions.Length); foreach (var extension in Extensions) { - extension.Write(writer); + extension.Write(ref writer); } } } diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/ClientMessageTypes.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/ClientMessageTypes.cs similarity index 88% rename from src/EdgeDB.Net.Driver/Models/Sendables/ClientMessageTypes.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/ClientMessageTypes.cs index ebd3d23a..b793041f 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/ClientMessageTypes.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/ClientMessageTypes.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,7 +6,7 @@ namespace EdgeDB.Binary { - internal enum ClientMessageTypes : sbyte + internal enum ClientMessageTypes : sbyte { AuthenticationSASLInitialResponse = 0x70, AuthenticationSASLResponse = 0x72, diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/Dump.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Dump.cs similarity index 58% rename from src/EdgeDB.Net.Driver/Models/Sendables/Dump.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Dump.cs index a93e2718..a56ae8a8 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/Dump.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Dump.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,14 +7,15 @@ namespace EdgeDB.Binary.Packets { - internal class Dump : Sendable + internal sealed class Dump : Sendable { + public override int Size => BinaryUtils.SizeOfAnnotations(Attributes); public override ClientMessageTypes Type => ClientMessageTypes.Dump; public Annotation[]? Attributes { get; set; } - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { writer.Write(Attributes); } diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/Execute.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Execute.cs similarity index 74% rename from src/EdgeDB.Net.Driver/Models/Sendables/Execute.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Execute.cs index 94784733..372623d0 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/Execute.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Execute.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,8 +7,24 @@ namespace EdgeDB.Binary.Packets { - internal class Execute : Sendable + internal sealed class Execute : Sendable { + public override int Size + { + get + { + return + // Capabilities and implicit limit + annotations (none) + (sizeof(ulong) << 1) + sizeof(ulong) + sizeof(ushort) + + // IOFormat, Cardinality + 3 guids + 50 + + BinaryUtils.SizeOfString(Query) + + BinaryUtils.SizeOfByteArray(StateData) + + Arguments?.Length ?? 4; + + } + } + public override ClientMessageTypes Type => ClientMessageTypes.Execute; @@ -37,7 +54,7 @@ public override ClientMessageTypes Type public byte[]? Arguments { get; set; } - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { if (Query is null) throw new ArgumentException("Command cannot be null"); diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/Parse.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Parse.cs similarity index 79% rename from src/EdgeDB.Net.Driver/Models/Sendables/Parse.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Parse.cs index d1f4b739..8f277cdd 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/Parse.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Parse.cs @@ -1,4 +1,4 @@ -using EdgeDB.Codecs; +using EdgeDB.Utils; using System; using System.Collections.Generic; using System.Linq; @@ -11,8 +11,19 @@ namespace EdgeDB.Binary.Packets /// /// https://www.edgedb.com/docs/reference/protocol/messages#prepare /// - internal class Parse : Sendable + internal sealed class Parse : Sendable { + public override int Size + { + get + { + return (sizeof(ulong) << 1) + sizeof(short) + + 16 + sizeof(ulong) + 2 + + BinaryUtils.SizeOfString(Query) + + BinaryUtils.SizeOfByteArray(StateData); + } + } + public override ClientMessageTypes Type => ClientMessageTypes.Parse; @@ -36,7 +47,7 @@ public override ClientMessageTypes Type public byte[]? StateData { get; set; } - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { if (Query is null) throw new ArgumentException("Command cannot be null"); diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/Restore.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Restore.cs similarity index 62% rename from src/EdgeDB.Net.Driver/Models/Sendables/Restore.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Restore.cs index 6c37c06d..3de31884 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/Restore.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Restore.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,8 +7,11 @@ namespace EdgeDB.Binary.Packets { - internal class Restore : Sendable + internal sealed class Restore : Sendable { + public override int Size + => BinaryUtils.SizeOfAnnotations(Headers) + sizeof(ushort) + BinaryUtils.SizeOfByteArray(HeaderData); + public override ClientMessageTypes Type => ClientMessageTypes.Restore; @@ -17,7 +21,7 @@ public override ClientMessageTypes Type public byte[]? HeaderData { get; set; } - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { writer.Write(Headers); writer.Write(Jobs); diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/RestoreBlock.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/RestoreBlock.cs similarity index 57% rename from src/EdgeDB.Net.Driver/Models/Sendables/RestoreBlock.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/RestoreBlock.cs index a019aa20..80ea0851 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/RestoreBlock.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/RestoreBlock.cs @@ -1,4 +1,5 @@ -using System; +using EdgeDB.Utils; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,14 +7,17 @@ namespace EdgeDB.Binary.Packets { - internal class RestoreBlock : Sendable + internal sealed class RestoreBlock : Sendable { + public override int Size + => BinaryUtils.SizeOfByteArray(BlockData); + public override ClientMessageTypes Type => ClientMessageTypes.RestoreBlock; public byte[]? BlockData { get; set; } - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { writer.WriteArray(BlockData!); } diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/RestoreEOF.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/RestoreEOF.cs similarity index 60% rename from src/EdgeDB.Net.Driver/Models/Sendables/RestoreEOF.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/RestoreEOF.cs index f707ed4e..21ace238 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/RestoreEOF.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/RestoreEOF.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,12 +6,13 @@ namespace EdgeDB.Binary.Packets { - internal class RestoreEOF : Sendable + internal sealed class RestoreEOF : Sendable { + public override int Size => 0; public override ClientMessageTypes Type => ClientMessageTypes.RestoreEOF; - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { // write nothing } diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/Sync.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Sync.cs similarity index 53% rename from src/EdgeDB.Net.Driver/Models/Sendables/Sync.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Sync.cs index 996d3737..76c5c451 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/Sync.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Sync.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,11 +6,12 @@ namespace EdgeDB.Binary.Packets { - internal class Sync : Sendable + internal sealed class Sync : Sendable { + public override int Size => 0; public override ClientMessageTypes Type => ClientMessageTypes.Sync; - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) { } // no data + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { } // no data } } diff --git a/src/EdgeDB.Net.Driver/Models/Sendables/Terminate.cs b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Terminate.cs similarity index 53% rename from src/EdgeDB.Net.Driver/Models/Sendables/Terminate.cs rename to src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Terminate.cs index 8ae3eef5..00619668 100644 --- a/src/EdgeDB.Net.Driver/Models/Sendables/Terminate.cs +++ b/src/EdgeDB.Net.Driver/Binary/Packets/Sendables/Terminate.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,11 +6,12 @@ namespace EdgeDB.Binary.Packets { - internal class Terminate : Sendable + internal sealed class Terminate : Sendable { + public override int Size => 0; public override ClientMessageTypes Type => ClientMessageTypes.Terminate; - protected override void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client) { } // no data + protected override void BuildPacket(ref PacketWriter writer, EdgeDBBinaryClient client) { } // no data } } diff --git a/src/EdgeDB.Net.Driver/ClientPoolHolder.cs b/src/EdgeDB.Net.Driver/ClientPoolHolder.cs new file mode 100644 index 00000000..c118d016 --- /dev/null +++ b/src/EdgeDB.Net.Driver/ClientPoolHolder.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Concurrent; + +namespace EdgeDB +{ + internal sealed class ClientPoolHolder + { + private readonly SemaphoreSlim _resizeWaiter; + private readonly List _handles; + private readonly object _handleCollectionLock; + private SemaphoreSlim _poolClientWaiter; + private int _size; + + public ClientPoolHolder(int initialSize) + { + _size = initialSize; + _poolClientWaiter = new(_size, _size); + _handles = new(); + _resizeWaiter = new(1,1); + _handleCollectionLock = new(); + } + + public async Task ResizeAsync(int newSize) + { + await _resizeWaiter.WaitAsync(); + + try + { + if (_size == newSize) + return; + + _size = newSize; + + _poolClientWaiter = new(_size, _size); + } + finally + { + _resizeWaiter.Release(); + } + } + + public async Task GetPoolHandleAsync(CancellationToken token) + { + // wait for an open handle + var localWaiter = _poolClientWaiter; + await localWaiter.WaitAsync(token).ConfigureAwait(false); + await _resizeWaiter.WaitAsync(token).ConfigureAwait(false); + + try + { + var handle = new PoolHandle(); + handle.SetReleaseAction(() => + { + localWaiter.Release(); + lock (_handleCollectionLock) + { + _handles.Remove(handle); + } + }); + _handles.Add(handle); + return handle; + } + finally + { + _resizeWaiter.Release(); + } + } + + private class PoolHandle : IDisposable + { + public bool HasReleased { get; private set; } + + private readonly object _lock; + private Action _release; + + public PoolHandle() + { + // TODO: resize might have to lock the handle? + _lock = new(); + _release = () => { }; + HasReleased = false; + } + + public void SetReleaseAction(Action newDelegate) + { + lock (_lock) + { + if (HasReleased) + return; + + _release = newDelegate; + } + } + + public void Dispose() + { + lock (_lock) + { + if (!HasReleased) + _release(); + HasReleased = true; + } + } + } + } +} + diff --git a/src/EdgeDB.Net.Driver/Clients/BaseEdgeDBClient.cs b/src/EdgeDB.Net.Driver/Clients/BaseEdgeDBClient.cs index 2bdb0312..e5b29971 100644 --- a/src/EdgeDB.Net.Driver/Clients/BaseEdgeDBClient.cs +++ b/src/EdgeDB.Net.Driver/Clients/BaseEdgeDBClient.cs @@ -1,4 +1,4 @@ -using EdgeDB.DataTypes; +using EdgeDB.DataTypes; using EdgeDB.State; namespace EdgeDB @@ -6,7 +6,7 @@ namespace EdgeDB /// /// Represents a base edgedb client that can interaction with the EdgeDB database. /// - public abstract class BaseEdgeDBClient : IEdgeDBQueryable, IAsyncDisposable + internal abstract class BaseEdgeDBClient : IEdgeDBQueryable, IAsyncDisposable { /// /// Gets whether or not this client has connected to the database and @@ -22,7 +22,7 @@ public abstract class BaseEdgeDBClient : IEdgeDBQueryable, IAsyncDisposable /// /// Gets the clients session. /// - public Session Session { get; protected set; } + internal Session Session { get; set; } internal event Func> OnDisposed { @@ -48,18 +48,29 @@ internal event Func OnConnect internal readonly AsyncEvent> OnConnectInternal = new(); + protected IDisposable ClientPoolHolder; + /// /// Initialized the base client. /// /// The id of this client. - public BaseEdgeDBClient(ulong clientId) + /// The client pool holder for this client. + public BaseEdgeDBClient(ulong clientId, IDisposable clientPoolHolder) { Session = Session.Default; ClientId = clientId; + ClientPoolHolder = clientPoolHolder; + } + + public void AcceptHolder(IDisposable holder) + { + // dispose the old holder + ClientPoolHolder.Dispose(); + ClientPoolHolder = holder; } #region State - public BaseEdgeDBClient WithSession(Session session) + internal BaseEdgeDBClient WithSession(Session session) { Session = session; return this; @@ -155,7 +166,7 @@ public abstract Task> QueryJsonElementsAsync(string qu public virtual async ValueTask DisposeAsync() { bool shouldDispose = true; - + ClientPoolHolder.Dispose(); if (_onDisposed.HasSubscribers) { var results = await _onDisposed.InvokeAsync(this).ConfigureAwait(false); diff --git a/src/EdgeDB.Net.Driver/Clients/EdgeDBBinaryClient.cs b/src/EdgeDB.Net.Driver/Clients/EdgeDBBinaryClient.cs index 08526489..9d052620 100644 --- a/src/EdgeDB.Net.Driver/Clients/EdgeDBBinaryClient.cs +++ b/src/EdgeDB.Net.Driver/Clients/EdgeDBBinaryClient.cs @@ -1,7 +1,6 @@ -using EdgeDB.Binary; +using EdgeDB.Binary; using EdgeDB.Binary.Packets; -using EdgeDB.Codecs; -using EdgeDB.Models; +using EdgeDB.Binary.Codecs; using EdgeDB.Utils; using Microsoft.Extensions.Logging; using System; @@ -19,7 +18,7 @@ namespace EdgeDB /// /// Represents an abstract binary client. /// - public abstract class EdgeDBBinaryClient : BaseEdgeDBClient, ITransactibleClient + internal abstract class EdgeDBBinaryClient : BaseEdgeDBClient, ITransactibleClient { /// /// The major version of the protocol that this client supports. @@ -120,9 +119,10 @@ protected CancellationToken DisconnectCancelToken /// /// The connection details used to connect to the database. /// The configuration for this client. + /// The client pool holder for this client. /// The optional client id of this client. This is used for logging and client pooling. - public EdgeDBBinaryClient(EdgeDBConnection connection, EdgeDBConfig config, ulong? clientId = null) - : base(clientId ?? 0) + public EdgeDBBinaryClient(EdgeDBConnection connection, EdgeDBConfig config, IDisposable clientPoolHolder, ulong? clientId = null) + : base(clientId ?? 0, clientPoolHolder) { Logger = config.Logger ?? Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance; Connection = connection; @@ -130,6 +130,7 @@ public EdgeDBBinaryClient(EdgeDBConnection connection, EdgeDBConfig config, ulon MessageTimeout = TimeSpan.FromMilliseconds(config.MessageTimeout); ConnectionTimeout = TimeSpan.FromMilliseconds(config.ConnectionTimeout); Duplexer = new ClientPacketDuplexer(this); + Duplexer.OnMessage += HandlePayloadAsync; Duplexer.OnDisconnected += HandleDuplexerDisconnectAsync; _stateDescriptorId = CodecBuilder.InvalidCodec; _config = config; @@ -145,11 +146,11 @@ public EdgeDBBinaryClient(EdgeDBConnection connection, EdgeDBConfig config, ulon internal readonly struct RawExecuteResult { public readonly ICodec Deserializer; - public readonly List Data; + public readonly Data[] Data; public RawExecuteResult(ICodec codec, List data) { - Data = data; + Data = data.ToArray(); Deserializer = codec; } } @@ -158,7 +159,7 @@ public RawExecuteResult(ICodec codec, List data) /// The client received an . /// The client received an unexpected message. /// A codec could not be found for the given input arguments or the result. - internal async Task ExecuteInternalAsync(string query, IDictionary? args = null, Cardinality? cardinality = null, + internal async Task ExecuteInternalAsync(string query, IDictionary? args = null, Cardinality? cardinality = null, Capabilities? capabilities = Capabilities.Modifications, IOFormat format = IOFormat.Binary, bool isRetry = false, CancellationToken token = default) { @@ -183,18 +184,15 @@ internal async Task ExecuteInternalAsync(string query, IDictio var cacheKey = CodecBuilder.GetCacheHashKey(query, cardinality ?? Cardinality.Many, format); var serializedState = Session.Serialize(); - - List p = new(); - + if (!CodecBuilder.TryGetCodecs(cacheKey, out var inCodecInfo, out var outCodecInfo)) { bool parseHandlerPredicate(IReceiveable? packet) { - p.Add(packet); switch (packet) { case ErrorResponse err when err.ErrorCode is not ServerErrorCodes.StateMismatchError: - throw new EdgeDBErrorException(err); + throw new EdgeDBErrorException(err, query); case CommandDataDescription descriptor: { outCodecInfo = new(descriptor.OutputTypeDescriptorId, @@ -258,7 +256,7 @@ bool handler(IReceiveable msg) receivedData.Add(data); break; case ErrorResponse err when err.ErrorCode is not ServerErrorCodes.ParameterTypeMismatchError: - throw new EdgeDBErrorException(err); + throw new EdgeDBErrorException(err, query); case ReadyForCommand ready: TransactionState = ready.TransactionState; return true; @@ -284,7 +282,7 @@ bool handler(IReceiveable msg) OutputTypeDescriptorId = outCodecInfo.Id, }, handler, alwaysReturnError: false, token: linkedToken).ConfigureAwait(false); - executeResult.ThrowIfErrrorResponse(); + executeResult.ThrowIfErrrorResponse(query); execResult = new ExecuteResult(true, null, null, query); @@ -302,14 +300,14 @@ bool handler(IReceiveable msg) _semaphore.Release(); released = true; - return await ExecuteInternalAsync(query, args, cardinality, capabilities, format, true, token).ConfigureAwait(false); + return await ExecuteInternalAsync(query, args, cardinality, capabilities, format, true, token).ConfigureAwait(false); } catch (EdgeDBException x) when (x.ShouldRetry && !isRetry) { _semaphore.Release(); released = true; - return await ExecuteInternalAsync(query, args, cardinality, capabilities, format, true, token).ConfigureAwait(false); + return await ExecuteInternalAsync(query, args, cardinality, capabilities, format, true, token).ConfigureAwait(false); } catch (Exception x) { @@ -319,6 +317,9 @@ bool handler(IReceiveable msg) Logger.InternalExecuteFailed(x); + if (x is EdgeDBErrorException) + throw; + throw new EdgeDBException($"Failed to execute query{(isRetry ? " after retrying once" : "")}", x); } finally @@ -337,7 +338,7 @@ bool handler(IReceiveable msg) /// A codec could not be found for the given input arguments or the result. public override async Task ExecuteAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) - => await ExecuteInternalAsync(query, args, Cardinality.Many, capabilities, token: token).ConfigureAwait(false); + => await ExecuteInternalAsync(query, args, Cardinality.Many, capabilities, token: token).ConfigureAwait(false); /// /// A general error occored. @@ -350,16 +351,16 @@ public override async Task ExecuteAsync(string query, IDictionary(query, args, Cardinality.Many, capabilities, token: token); List returnResults = new(); - foreach (var item in result.Data) + for(int i = 0; i != result.Data.Length; i++) { - var obj = ObjectBuilder.BuildResult(result.Deserializer.Deserialize(item.PayloadBuffer)); + var obj = ObjectBuilder.BuildResult(result.Deserializer, ref result.Data[i]); returnResults.Add(obj); } - + return returnResults.ToImmutableArray(); } @@ -375,16 +376,16 @@ public override async Task ExecuteAsync(string query, IDictionary(query, args, Cardinality.AtMostOne, capabilities, token: token); - if (result.Data.Count > 1) + if (result.Data.Length > 1) throw new ResultCardinalityMismatchException(Cardinality.AtMostOne, Cardinality.Many); var queryResult = result.Data.FirstOrDefault(); return queryResult.PayloadBuffer is null ? default - : ObjectBuilder.BuildResult(result.Deserializer.Deserialize(queryResult.PayloadBuffer)); + : ObjectBuilder.BuildResult(result.Deserializer, ref result.Data[0]); } /// @@ -399,16 +400,16 @@ public override async Task ExecuteAsync(string query, IDictionary QueryRequiredSingleAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - var result = await ExecuteInternalAsync(query, args, Cardinality.AtMostOne, capabilities, token: token); + var result = await ExecuteInternalAsync(query, args, Cardinality.AtMostOne, capabilities, token: token); - if (result.Data.Count is > 1 or 0) - throw new ResultCardinalityMismatchException(Cardinality.One, result.Data.Count > 1 ? Cardinality.Many : Cardinality.AtMostOne); + if (result.Data.Length is > 1 or 0) + throw new ResultCardinalityMismatchException(Cardinality.One, result.Data.Length > 1 ? Cardinality.Many : Cardinality.AtMostOne); var queryResult = result.Data.FirstOrDefault(); - + return queryResult.PayloadBuffer is null ? throw new MissingRequiredException() - : ObjectBuilder.BuildResult(result.Deserializer.Deserialize(queryResult.PayloadBuffer))!; + : ObjectBuilder.BuildResult(result.Deserializer, ref result.Data[0])!; } /// @@ -419,9 +420,9 @@ public override async Task QueryRequiredSingleAsync(string que /// A codec could not be found for the given input arguments or the result. public override async Task QueryJsonAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - var result = await ExecuteInternalAsync(query, args, Cardinality.Many, capabilities, IOFormat.Json, token: token); + var result = await ExecuteInternalAsync(query, args, Cardinality.Many, capabilities, IOFormat.Json, token: token); - return result.Data.Count == 1 + return result.Data.Length == 1 ? (string)result.Deserializer.Deserialize(result.Data[0].PayloadBuffer)! : "[]"; } @@ -433,7 +434,7 @@ public override async Task QueryRequiredSingleAsync(string que /// A codec could not be found for the given input arguments or the result. public override async Task> QueryJsonElementsAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - var result = await ExecuteInternalAsync(query, args, Cardinality.AtMostOne, capabilities, IOFormat.Json, token: token); + var result = await ExecuteInternalAsync(query, args, Cardinality.Many, capabilities, IOFormat.JsonElements, token: token); return result.Data.Any() ? result.Data.Select(x => new DataTypes.Json((string?)result.Deserializer.Deserialize(x.PayloadBuffer))).ToImmutableArray() @@ -538,7 +539,7 @@ private async Task StartSASLAuthenticationAsync(AuthenticationStatus authStatus) throw new UnexpectedMessageException(ServerMessageType.Authentication, initialResult.Type); // check the continue - var (FinalMessage, ExpectedSig) = scram.BuildFinalMessage(intiailStatus, Connection.Password!); + var (FinalMessage, ExpectedSig) = scram.BuildFinalMessage(in intiailStatus, Connection.Password!); var finalResult = await Duplexer.DuplexAsync(x => x.Type == ServerMessageType.Authentication, packets: FinalMessage).ConfigureAwait(false); @@ -622,7 +623,7 @@ private void ParseServerSettings(ParameterStatus status) var descriptorId = reader.ReadGuid(); reader.ReadBytes(length, out var typeDesc); - ICodec? codec = CodecBuilder.GetCodec(descriptorId); + var codec = CodecBuilder.GetCodec(descriptorId); if (codec is null) { @@ -634,7 +635,7 @@ private void ParseServerSettings(ParameterStatus status) } // disard length - reader.ReadUInt32(); + reader.Skip(4); var obj = codec.Deserialize(ref reader)!; @@ -664,7 +665,7 @@ private void ParseServerSettings(ParameterStatus status) /// public override async ValueTask ConnectAsync(CancellationToken token = default) { - await _connectSemaphone.WaitAsync(); + await _connectSemaphone.WaitAsync(token); try { @@ -721,9 +722,7 @@ private async Task ConnectInternalAsync(int attempts = 0, CancellationToken toke } Duplexer.Start(stream); - - Duplexer.OnMessage += HandlePayloadAsync; - + // send handshake await Duplexer.SendAsync(new ClientHandshake { @@ -763,7 +762,6 @@ await Duplexer.SendAsync(new ClientHandshake /// A task representing the asynchronous disconnect and reconnection operations. public async Task ReconnectAsync(CancellationToken token = default) { - Duplexer.OnMessage -= HandlePayloadAsync; await DisconnectAsync(token).ConfigureAwait(false); await ConnectAsync(token).ConfigureAwait(false); } @@ -862,16 +860,16 @@ async Task ITransactibleClient.StartTransactionAsync(Isolation isolation, bool r var deferMode = $"{(!deferrable ? "not " : "")}deferrable"; - await ExecuteInternalAsync($"start transaction isolation {isolationMode}, {readMode}, {deferMode}", capabilities: Capabilities.Transaction, token: token).ConfigureAwait(false); + await ExecuteInternalAsync($"start transaction isolation {isolationMode}, {readMode}, {deferMode}", capabilities: Capabilities.Transaction, token: token).ConfigureAwait(false); } /// async Task ITransactibleClient.CommitAsync(CancellationToken token) - => await ExecuteInternalAsync($"commit", capabilities: Capabilities.Transaction, token: token).ConfigureAwait(false); + => await ExecuteInternalAsync($"commit", capabilities: Capabilities.Transaction, token: token).ConfigureAwait(false); /// async Task ITransactibleClient.RollbackAsync(CancellationToken token) - => await ExecuteInternalAsync($"rollback", capabilities: Capabilities.Transaction, token: token).ConfigureAwait(false); + => await ExecuteInternalAsync($"rollback", capabilities: Capabilities.Transaction, token: token).ConfigureAwait(false); /// TransactionState ITransactibleClient.TransactionState => TransactionState; diff --git a/src/EdgeDB.Net.Driver/Clients/EdgeDBHttpClient.cs b/src/EdgeDB.Net.Driver/Clients/EdgeDBHttpClient.cs index e147d8f4..6b86479a 100644 --- a/src/EdgeDB.Net.Driver/Clients/EdgeDBHttpClient.cs +++ b/src/EdgeDB.Net.Driver/Clients/EdgeDBHttpClient.cs @@ -1,5 +1,4 @@ -using EdgeDB.DataTypes; -using EdgeDB.Models; +using EdgeDB.DataTypes; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -18,7 +17,7 @@ namespace EdgeDB /// /// Represents the returned data from a http-based query. /// - public class HttpQueryResult : IExecuteResult + internal sealed class HttpQueryResult : IExecuteResult { /// /// Gets or sets the data returned from the query. @@ -78,7 +77,7 @@ bool IExecuteResult.IsSuccess /// /// Represents a client that can preform queries over HTTP. /// - public sealed class EdgeDBHttpClient : BaseEdgeDBClient + internal sealed class EdgeDBHttpClient : BaseEdgeDBClient { /// /// Fired when a query is executed. @@ -119,9 +118,10 @@ private class QueryPostBody /// /// The connection details used to connect to the database. /// The configuration for this client. + /// The client pool holder for this client. /// The optional client id of this client. This is used for logging and client pooling. - public EdgeDBHttpClient(EdgeDBConnection connection, EdgeDBConfig config, ulong clientId) - : base(clientId) + public EdgeDBHttpClient(EdgeDBConnection connection, EdgeDBConfig config, IDisposable poolHolder, ulong clientId) + : base(clientId, poolHolder) { _logger = config.Logger ?? Microsoft.Extensions.Logging.Abstractions.NullLogger.Instance; _connection = connection; diff --git a/src/EdgeDB.Net.Driver/Clients/EdgeDBTcpClient.cs b/src/EdgeDB.Net.Driver/Clients/EdgeDBTcpClient.cs index 72159f11..ed63b959 100644 --- a/src/EdgeDB.Net.Driver/Clients/EdgeDBTcpClient.cs +++ b/src/EdgeDB.Net.Driver/Clients/EdgeDBTcpClient.cs @@ -1,5 +1,4 @@ -using EdgeDB.Codecs; -using EdgeDB.Models; +using EdgeDB.Binary.Codecs; using EdgeDB.Utils; using Microsoft.Extensions.Logging; using System.Collections.Immutable; @@ -16,7 +15,7 @@ namespace EdgeDB /// /// Represents a TCP client used to interact with EdgeDB. /// - public sealed class EdgeDBTcpClient : EdgeDBBinaryClient + internal sealed class EdgeDBTcpClient : EdgeDBBinaryClient { /// public override bool IsConnected @@ -32,9 +31,10 @@ public override bool IsConnected /// /// The connection details used to connect to the database. /// The configuration for this client. + /// The client pool holder for this client. /// The optional client id of this client. This is used for logging and client pooling. - public EdgeDBTcpClient(EdgeDBConnection connection, EdgeDBConfig config, ulong? clientId = null) - : base(connection, config, clientId) + public EdgeDBTcpClient(EdgeDBConnection connection, EdgeDBConfig config, IDisposable clientPoolHolder, ulong? clientId = null) + : base(connection, config, clientPoolHolder, clientId) { _tcpClient = new(); } @@ -139,4 +139,4 @@ public override async ValueTask DisposeAsync() return shouldDispose; } } -} \ No newline at end of file +} diff --git a/src/EdgeDB.Net.Driver/Clients/IEdgeDBQueryable.cs b/src/EdgeDB.Net.Driver/Clients/IEdgeDBQueryable.cs index 09f87360..6db9c5ed 100644 --- a/src/EdgeDB.Net.Driver/Clients/IEdgeDBQueryable.cs +++ b/src/EdgeDB.Net.Driver/Clients/IEdgeDBQueryable.cs @@ -1,5 +1,4 @@ -using EdgeDB.DataTypes; -using EdgeDB.Models; +using EdgeDB.DataTypes; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/EdgeDB.Net.Driver/Clients/ITransactibleClient.cs b/src/EdgeDB.Net.Driver/Clients/ITransactibleClient.cs index ad3f467c..9d0e0cb5 100644 --- a/src/EdgeDB.Net.Driver/Clients/ITransactibleClient.cs +++ b/src/EdgeDB.Net.Driver/Clients/ITransactibleClient.cs @@ -1,4 +1,3 @@ -using EdgeDB.Models; using System; using System.Collections.Generic; using System.Linq; diff --git a/src/EdgeDB.Net.Driver/Codecs/Object.cs b/src/EdgeDB.Net.Driver/Codecs/Object.cs deleted file mode 100644 index 28b05ec0..00000000 --- a/src/EdgeDB.Net.Driver/Codecs/Object.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Dynamic; - -namespace EdgeDB.Codecs -{ - internal class Object : ICodec, IArgumentCodec - { - private readonly ICodec[] _innerCodecs; - private readonly string[] _propertyNames; - - internal Object(ICodec[] innerCodecs, string[] propertyNames) - { - _innerCodecs = innerCodecs; - _propertyNames = propertyNames; - } - - public object? Deserialize(ref PacketReader reader) - { - var numElements = reader.ReadInt32(); - - if (_innerCodecs.Length != numElements) - { - throw new ArgumentException($"codecs mismatch for tuple: expected {numElements} codecs, got {_innerCodecs.Length} codecs"); - } - - dynamic data = new ExpandoObject(); - var dataDictionary = (IDictionary)data; - - for (int i = 0; i != numElements; i++) - { - // reserved - reader.Skip(4); - var name = _propertyNames[i]; - var length = reader.ReadInt32(); - - if(length is -1) - { - dataDictionary.Add(name, null); - continue; - } - - reader.ReadBytes(length, out var innerData); - - object? value; - - value = _innerCodecs[i].Deserialize(innerData); - - dataDictionary.Add(name, value); - } - - return data; - } - - public void Serialize(PacketWriter writer, object? value) - { - throw new NotImplementedException(); - } - - public void SerializeArguments(PacketWriter writer, object? value) - { - object?[]? values = null; - - if (value is IDictionary dict) - values = _propertyNames.Select(x => dict[x]).ToArray(); - else if (value is object?[] arr) - value = arr; - - if (values is null) - { - throw new ArgumentException($"Expected dynamic object or array but got {value?.GetType()?.Name ?? "null"}"); - } - - using var innerWriter = new PacketWriter(); - for (int i = 0; i != values.Length; i++) - { - var element = values[i]; - var innerCodec = _innerCodecs[i]; - - // reserved - innerWriter.Write(0); - - // encode - if (element is null) - { - innerWriter.Write(-1); - } - else - { - // special case for enums - if (element.GetType().IsEnum && innerCodec is Text) - element = element.ToString(); - - var elementBuff = innerCodec.Serialize(element); - - innerWriter.Write(elementBuff.Length); - innerWriter.Write(elementBuff); - } - } - - writer.Write((int)innerWriter.BaseStream.Length + 4); - writer.Write(values.Length); - writer.Write(innerWriter); - } - } -} diff --git a/src/EdgeDB.Net.Driver/ContractResolvers/EdgeDBContractResolver.cs b/src/EdgeDB.Net.Driver/ContractResolvers/EdgeDBContractResolver.cs index 72c7a15c..45aade40 100644 --- a/src/EdgeDB.Net.Driver/ContractResolvers/EdgeDBContractResolver.cs +++ b/src/EdgeDB.Net.Driver/ContractResolvers/EdgeDBContractResolver.cs @@ -1,11 +1,11 @@ -using System; +using System; using System.Reflection; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace EdgeDB.ContractResolvers { - internal class EdgeDBContractResolver : DefaultContractResolver + internal sealed class EdgeDBContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { diff --git a/src/EdgeDB.Net.Driver/ContractResolvers/RangeConverter.cs b/src/EdgeDB.Net.Driver/ContractResolvers/RangeConverter.cs index 0db98d7f..8ecb58a9 100644 --- a/src/EdgeDB.Net.Driver/ContractResolvers/RangeConverter.cs +++ b/src/EdgeDB.Net.Driver/ContractResolvers/RangeConverter.cs @@ -1,10 +1,10 @@ -using System; +using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace EdgeDB.ContractResolvers { - internal class RangeConverter : JsonConverter + internal sealed class RangeConverter : JsonConverter { public static RangeConverter Instance => new(); diff --git a/src/EdgeDB.Net.Driver/EdgeDBClient.cs b/src/EdgeDB.Net.Driver/EdgeDBClient.cs index 1adbfa3e..b16de07c 100644 --- a/src/EdgeDB.Net.Driver/EdgeDBClient.cs +++ b/src/EdgeDB.Net.Driver/EdgeDBClient.cs @@ -1,5 +1,4 @@ -using EdgeDB.DataTypes; -using EdgeDB.Models; +using EdgeDB.DataTypes; using EdgeDB.State; using System.Collections.Concurrent; using System.Collections.Immutable; @@ -9,7 +8,7 @@ namespace EdgeDB /// /// Represents a client pool used to interact with EdgeDB. /// - public sealed class EdgeDBClient : IEdgeDBQueryable, IAsyncDisposable + public sealed class EdgeDBClient : IEdgeDBQueryable, IAsyncDisposable { /// /// Fired when a client in the client pool executes a query. @@ -23,7 +22,7 @@ public event Func QueryExecuted /// /// Gets all clients within the client pool. /// - public IReadOnlyCollection Clients + internal IReadOnlyCollection Clients => _clients.Values.ToImmutableArray(); /// @@ -48,12 +47,28 @@ public int AvailableClients }); /// - /// Gets the default state that all clients will be initialized with. + /// The containing session-level configuration. /// - /// - /// You can modify this state by calling any of the With... methods on it. - /// - public Session DefaultSession { get; } + public Config Config + => _session.Config; + + /// + /// The default module for this client. + /// + public string Module + => _session.Module; + + /// + /// The module aliases for this client. + /// + public IReadOnlyDictionary Aliases + => _session.Aliases; + + /// + /// The globals for this client. + /// + public IReadOnlyDictionary Globals + => _session.Globals; /// /// Gets the EdgeDB server config. @@ -66,25 +81,26 @@ public int AvailableClients => _edgedbConfig.ToImmutableDictionary(); internal EdgeDBClientType ClientType - => _config.ClientType; + => _poolConfig.ClientType; private readonly AsyncEvent> _queryExecuted = new(); private readonly EdgeDBConnection _connection; - private readonly EdgeDBClientPoolConfig _config; + private readonly EdgeDBClientPoolConfig _poolConfig; private ConcurrentStack _availableClients; private readonly ConcurrentDictionary _clients; - private bool _isInitialized; - private Dictionary _edgedbConfig; - private uint _poolSize; + private readonly Dictionary _edgedbConfig; + private int _poolSize; private readonly object _clientsLock = new(); - private readonly SemaphoreSlim _initSemaphore; private readonly SemaphoreSlim _clientWaitSemaphore; - private readonly Func>? _clientFactory; + private readonly ClientPoolHolder _poolHolder; private ulong _clientIndex; private int _totalClients; + private readonly Session _session; + + #region ctors /// /// Creates a new instance of a EdgeDB client pool allowing you to execute commands. /// @@ -120,51 +136,27 @@ public EdgeDBClient(EdgeDBConnection connection, EdgeDBClientPoolConfig config) if (config.ClientType == EdgeDBClientType.Custom && config.ClientFactory == null) throw new CustomClientException("You must specify a client factory in order to use custom clients"); - DefaultSession = Session.Default; - - _clientFactory = config.ClientFactory; - _config = config; + _poolConfig = config; _clients = new(); _poolSize = config.DefaultPoolSize; _connection = connection; _edgedbConfig = new Dictionary(); - _isInitialized = false; - _initSemaphore = new(1, 1); _availableClients = new(); _clientWaitSemaphore = new(1, 1); + _poolHolder = new(_poolSize); + _session = Session.Default; } - /// - /// Initializes the client pool as well as retrives the server config from edgedb if - /// the clients within the pool support it. - /// - /// A cancellation token used to cancel the asynchronous operation. - public async Task InitializeAsync(CancellationToken token = default) + internal EdgeDBClient(EdgeDBClient other, Session session) + : this(other._connection, other._poolConfig) { - await _initSemaphore.WaitAsync(token).ConfigureAwait(false); - - try - { - if (_isInitialized) - return; - - await using var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); - - if(client is EdgeDBBinaryClient binaryClient) - { - // set the pool size to the recommended - _poolSize = (uint)binaryClient.SuggestedPoolConcurrency; - _edgedbConfig = binaryClient.RawServerConfig; - } - - _isInitialized = true; - } - finally - { - _initSemaphore.Release(); - } + _session = session; + _poolHolder = other._poolHolder; + _poolSize = other._poolSize; } + #endregion + /// /// Disconnects all clients within the client pool. /// @@ -173,7 +165,7 @@ public async Task InitializeAsync(CancellationToken token = default) /// /// A cancellation token used to cancel the asynchronous operation. /// The total number of clients disconnected. - public async Task DisconnectAllAsync(CancellationToken token = default) + internal async Task DisconnectAllAsync(CancellationToken token = default) { await _clientWaitSemaphore.WaitAsync(token).ConfigureAwait(false); @@ -189,13 +181,11 @@ public async Task DisconnectAllAsync(CancellationToken token = default) } } + #region Execute methods /// public async Task ExecuteAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - if (!_isInitialized) - await InitializeAsync(token).ConfigureAwait(false); - await using var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); await client.ExecuteAsync(query, args, capabilities, token).ConfigureAwait(false); } @@ -204,9 +194,6 @@ public async Task ExecuteAsync(string query, IDictionary? args public async Task> QueryAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - if (!_isInitialized) - await InitializeAsync(token).ConfigureAwait(false); - await using var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); return await client.QueryAsync(query, args, capabilities, token).ConfigureAwait(false); } @@ -215,9 +202,6 @@ public async Task ExecuteAsync(string query, IDictionary? args public async Task QuerySingleAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - if (!_isInitialized) - await InitializeAsync(token).ConfigureAwait(false); - await using var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); return await client.QuerySingleAsync(query, args, capabilities, token).ConfigureAwait(false); } @@ -226,33 +210,28 @@ public async Task ExecuteAsync(string query, IDictionary? args public async Task QueryRequiredSingleAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - if (!_isInitialized) - await InitializeAsync(token).ConfigureAwait(false); - await using var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); return await client.QueryRequiredSingleAsync(query, args, capabilities, token).ConfigureAwait(false); } + /// public async Task QueryJsonAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - if (!_isInitialized) - await InitializeAsync(token).ConfigureAwait(false); - await using var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); return await client.QueryJsonAsync(query, args, capabilities, token).ConfigureAwait(false); } + /// public async Task> QueryJsonElementsAsync(string query, IDictionary? args = null, Capabilities? capabilities = Capabilities.Modifications, CancellationToken token = default) { - if (!_isInitialized) - await InitializeAsync(token).ConfigureAwait(false); - await using var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); return await client.QueryJsonElementsAsync(query, args, capabilities, token).ConfigureAwait(false); } + #endregion + #region Client creation /// /// Gets or creates a client in the client pool used to interact with edgedb. /// @@ -271,7 +250,7 @@ public async Task> QueryJsonElementsAsync(string query /// result is a client of type . /// /// The client returned cannot be assigned to . - public async ValueTask GetOrCreateClientAsync(CancellationToken token = default) + internal async ValueTask GetOrCreateClientAsync(CancellationToken token = default) where TClient : BaseEdgeDBClient { var client = await GetOrCreateClientAsync(token); @@ -296,12 +275,17 @@ public async ValueTask GetOrCreateClientAsync(CancellationToke /// A task that represents the asynchonous operation of getting an available client. The tasks /// result is a instance. /// - public async ValueTask GetOrCreateClientAsync(CancellationToken token = default) + internal async Task GetOrCreateClientAsync(CancellationToken token = default) { // try get an available client ready for commands if (_availableClients.TryPop(out var result)) { - return result; + // give a new client pool holder + var holder = await _poolHolder.GetPoolHandleAsync(token); + result.AcceptHolder(holder); + + // return the client with the current session. + return result.WithSession(_session); } if (_totalClients >= _poolSize) @@ -310,13 +294,17 @@ public async ValueTask GetOrCreateClientAsync(CancellationToke try { - return SpinWait.SpinUntil(() => + var client = SpinWait.SpinUntil(() => { token.ThrowIfCancellationRequested(); return _availableClients.TryPop(out result); - }, (int)_config.ConnectionTimeout) + }, (int)_poolConfig.ConnectionTimeout) ? result! - : throw new TimeoutException($"Couldn't find a client after {_config.ConnectionTimeout}ms"); + : throw new TimeoutException($"Couldn't find a client after {_poolConfig.ConnectionTimeout}ms"); + + client.AcceptHolder(await _poolHolder.GetPoolHandleAsync(token).ConfigureAwait(false)); + return client.WithSession(_session); + } finally { @@ -328,7 +316,7 @@ public async ValueTask GetOrCreateClientAsync(CancellationToke // try to get a disconnected client that can be connected again if ((result = _clients.FirstOrDefault(x => !x.Value.IsConnected).Value) != null) { - await result.ConnectAsync(token).ConfigureAwait(false); + result.AcceptHolder(await _poolHolder.GetPoolHandleAsync(token).ConfigureAwait(false)); return result; } @@ -341,120 +329,174 @@ public async ValueTask GetOrCreateClientAsync(CancellationToke } } - /// - /// Gets or creates a client in the client pool used to interact with edgedb. - /// - /// - /// This method can hang if the client pool is full and all connections are in use. - /// It's recommended to use the query methods defined in the class. - ///
- ///
- /// Disposing the returned client with the method - /// will return that client to this client pool. - ///
- /// A delegate to configure the clients state. - /// A cancellation token used to cancel the asynchronous operation. - /// - /// A task that represents the asynchonous operation of getting an available client. The tasks - /// result is a instance. - /// - public async ValueTask GetOrCreateClientAsync(Action stateConfigure, CancellationToken token = default) + private async Task CreateClientAsync(ulong id, CancellationToken token = default) { - var client = await GetOrCreateClientAsync(token).ConfigureAwait(false); - stateConfigure(client.Session); - return client; - } - - private async ValueTask CreateClientAsync(ulong id, CancellationToken token = default) - { - switch (_config.ClientType) + switch (_poolConfig.ClientType) { case EdgeDBClientType.Tcp: { - var client = new EdgeDBTcpClient(_connection, _config, id); + var holder = await _poolHolder.GetPoolHandleAsync(token).ConfigureAwait(false); + var client = new EdgeDBTcpClient(_connection, _poolConfig, holder, id); // clone the default state to prevent modification to our reference to default state - client.WithSession(DefaultSession.Clone()); - - client.OnDisconnect += () => - { - Interlocked.Decrement(ref _totalClients); - RemoveClient(id); - return ValueTask.CompletedTask; - }; - - client.QueryExecuted += (i) => _queryExecuted.InvokeAsync(i); - - await client.ConnectAsync(token).ConfigureAwait(false); + client.WithSession(_session); - client.OnDisposed += (c) => + async ValueTask OnConnect(BaseEdgeDBClient _) { - if(c.IsConnected) - { - // reset state - c.WithSession(DefaultSession.Clone()); - _availableClients.Push(c); - return ValueTask.FromResult(false); - } - return ValueTask.FromResult(_clients.TryRemove(c.ClientId, out _)); - }; - - _clients[id] = client; - - return client; - } - case EdgeDBClientType.Http: - { - var client = new EdgeDBHttpClient(_connection, _config, id); - client.WithSession(DefaultSession.Clone()); + _poolSize = client.SuggestedPoolConcurrency; + await _poolHolder.ResizeAsync(_poolSize).ConfigureAwait(false); + client.OnConnect -= OnConnect; + } + client.OnConnect += OnConnect; + client.QueryExecuted += (i) => _queryExecuted.InvokeAsync(i); client.OnDisposed += (c) => { + // reset state + c.WithSession(Session.Default); _availableClients.Push(c); - c.WithSession(DefaultSession.Clone()); return ValueTask.FromResult(false); }; - client.OnDisconnect += (c) => - { - RemoveClient(c.ClientId); - return ValueTask.CompletedTask; - }; - _clients[id] = client; return client; } - case EdgeDBClientType.Custom when _clientFactory is not null: - { - var client = await _clientFactory(id, _connection, _config).ConfigureAwait(false)!; + //case EdgeDBClientType.Http: + // { + // var client = new EdgeDBHttpClient(_connection, _config, id); + // client.WithSession(DefaultSession.Clone()); + + // client.QueryExecuted += (i) => _queryExecuted.InvokeAsync(i); + + // client.OnDisposed += (c) => + // { + // _availableClients.Push(c); + // c.WithSession(DefaultSession.Clone()); + // return ValueTask.FromResult(false); + // }; + + // client.OnDisconnect += (c) => + // { + // RemoveClient(c.ClientId); + // return ValueTask.CompletedTask; + // }; + + // _clients[id] = client; + + // return client; + // } + //case EdgeDBClientType.Custom when _clientFactory is not null: + // { + // var client = await _clientFactory(id, _connection, _config).ConfigureAwait(false)!; + + // client.WithSession(DefaultSession.Clone()); + + // client.OnDisposed += (c) => + // { + // _availableClients.Push(c); + // c.WithSession(DefaultSession.Clone()); + // return ValueTask.FromResult(false); + // }; + + // client.OnDisconnect += (c) => + // { + // RemoveClient(c.ClientId); + // return ValueTask.CompletedTask; + // }; + + // _clients[id] = client; + + // return client; + // } - client.WithSession(DefaultSession.Clone()); + default: + throw new EdgeDBException($"No client found for type {_poolConfig.ClientType}"); + } + } + #endregion - client.OnDisposed += (c) => - { - _availableClients.Push(c); - c.WithSession(DefaultSession.Clone()); - return ValueTask.FromResult(false); - }; + #region State + /// + /// Creates a new client with the specified . + /// + /// + /// The created client is a 'sub' client of this one, the child client + /// shares the same client pool as this one. + /// + /// A delegate used to modify the config. + /// + /// A new client with the specified config. + /// + public EdgeDBClient WithConfig(Action configDelegate) + { + var props = new ConfigProperties(); + configDelegate(props); + return WithConfig(props.ToConfig(Config)); + } - client.OnDisconnect += (c) => - { - RemoveClient(c.ClientId); - return ValueTask.CompletedTask; - }; + /// + /// Creates a new client with the specified . + /// + /// + /// The created client is a 'sub' client of this one, the child client + /// shares the same client pool as this one. + /// + /// The config for the new client. + /// + /// A new client with the specified config. + /// + public EdgeDBClient WithConfig(Config config) + => new(this, _session.WithConfig(config)); - _clients[id] = client; + /// + /// Creates a new client with the specified Globals. + /// + /// + /// The created client is a 'sub' client of this one, the child client + /// shares the same client pool as this one.
+ /// The newly created client doesn't copy any of the parents globals, this method + /// is settative to the property. + ///
+ /// The globals for the newly create client. + /// + /// A new client with the specified globals. + /// + public EdgeDBClient WithGlobals(Dictionary globals) + => new(this, _session.WithGlobals(globals)); - return client; - } + /// + /// Creates a new client with the specified . + /// + /// + /// The created client is a 'sub' client of this one, the child client + /// shares the same client pool as this one. + /// + /// The module for the new client. + /// + /// A new client with the specified module. + /// + public EdgeDBClient WithModule(string module) + => new(this, _session.WithModule(module)); - default: - throw new EdgeDBException($"No client found for type {_config.ClientType}"); - } - } + /// + /// Creates a new client with the specified . + /// + /// + /// The created client is a 'sub' client of this one, the child client + /// shares the same client pool as this one.
+ /// The newly created client doesn't copy any of the parents aliases, this method + /// is settative to the property. + ///
+ /// The module aliases for the new client. + /// + /// A new client with the specified module aliases. + /// + public EdgeDBClient WithAliases(Dictionary aliases) + => new(this, _session.WithModuleAliases(aliases)); + #endregion private void RemoveClient(ulong id) { diff --git a/src/EdgeDB.Net.Driver/EdgeDBConfig.cs b/src/EdgeDB.Net.Driver/EdgeDBConfig.cs index eb9dfa7d..20dec26a 100644 --- a/src/EdgeDB.Net.Driver/EdgeDBConfig.cs +++ b/src/EdgeDB.Net.Driver/EdgeDBConfig.cs @@ -1,5 +1,6 @@ -using EdgeDB.ContractResolvers; -using EdgeDB.Serializer; +using EdgeDB.Binary; +using EdgeDB.ContractResolvers; +using EdgeDB.State; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using System.Numerics; @@ -9,17 +10,26 @@ namespace EdgeDB /// /// Represents a config for a , extending . /// - public class EdgeDBClientPoolConfig : EdgeDBConfig + public sealed class EdgeDBClientPoolConfig : EdgeDBConfig { /// /// Gets or sets the default client pool size. /// - public uint DefaultPoolSize { get; set; } = 50; + public int DefaultPoolSize + { + get => _poolSize; + set + { + if (value <= 0) + throw new ArgumentOutOfRangeException($"{nameof(DefaultPoolSize)} must be greater than 0"); + _poolSize = value; + } + } /// /// Gets or sets the client type the pool will use. /// - public EdgeDBClientType ClientType { get; set; } + internal EdgeDBClientType ClientType { get; set; } /// /// Gets or sets the client factory to use when adding new clients to the client pool. @@ -27,7 +37,9 @@ public class EdgeDBClientPoolConfig : EdgeDBConfig /// /// The must be to use this property. /// - public Func>? ClientFactory { get; set; } + internal Func>? ClientFactory { get; set; } + + private int _poolSize = 50; } /// @@ -112,15 +124,15 @@ public class EdgeDBConfig public ulong ImplicitLimit { get; set; } /// - /// Gets or sets the default naming strategy for the type builder. + /// Gets or sets the default naming strategy used within the schema. /// /// - /// See + /// By default, the naming convention will not modify property names. /// - public INamingStrategy SerializerNamingStrategy + public INamingStrategy SchemaNamingStrategy { - get => TypeBuilder.NamingStrategy; - set => TypeBuilder.NamingStrategy = value; + get => TypeBuilder.SchemaNamingStrategy; + set => TypeBuilder.SchemaNamingStrategy = value; } } } diff --git a/src/EdgeDB.Net.Driver/EdgeDBConnection.cs b/src/EdgeDB.Net.Driver/EdgeDBConnection.cs index 124669db..8c01e5f5 100644 --- a/src/EdgeDB.Net.Driver/EdgeDBConnection.cs +++ b/src/EdgeDB.Net.Driver/EdgeDBConnection.cs @@ -1,4 +1,4 @@ -using EdgeDB.Utils; +using EdgeDB.Utils; using Newtonsoft.Json; using System.Text.RegularExpressions; using System.Web; @@ -8,7 +8,7 @@ namespace EdgeDB /// /// Represents a class containing information on how to connect to a edgedb instance. /// - public class EdgeDBConnection + public sealed class EdgeDBConnection { private const string EDGEDB_INSTANCE_ENV_NAME = "EDGEDB_INSTANCE"; private const string EDGEDB_DSN_ENV_NAME = "EDGEDB_DSN"; diff --git a/src/EdgeDB.Net.Driver/Extensions/ClientPoolExtensions.cs b/src/EdgeDB.Net.Driver/Extensions/ClientPoolExtensions.cs index 7c43e0ef..3cffa14a 100644 --- a/src/EdgeDB.Net.Driver/Extensions/ClientPoolExtensions.cs +++ b/src/EdgeDB.Net.Driver/Extensions/ClientPoolExtensions.cs @@ -1,5 +1,4 @@ -using EdgeDB.Binary.Packets; -using EdgeDB.Models; +using EdgeDB.Binary.Packets; namespace EdgeDB { @@ -79,53 +78,6 @@ private static async Task GetTransactibleClientAsync(this E return tranactibleClient; } - - #endregion - - #region Dump/Restore - /// - /// Dumps the current database to a stream. - /// - /// The client pool on which to fetch a client from. - /// A token to cancel the operation with. - /// A stream containing the entire dumped database. - /// - /// The client returned from the client pool cannot be used to dump the - /// database. - /// - /// - /// The server sent an error message during the dumping process. - /// - /// The server sent a mismatched packet. - public static async Task DumpDatabaseAsync(this EdgeDBClient pool, CancellationToken token = default) - { - await using var client = await pool.GetOrCreateClientAsync(); - return await client.DumpDatabaseAsync(token).ConfigureAwait(false); - } - - /// - /// Restores the database based on a database dump stream. - /// - /// The client pool on which to fetch a client from. - /// The stream containing the database dump. - /// A token to cancel the operation with. - /// The command complete packet received after restoring the database. - /// - /// The client returned from the client pool cannot be used to dump the - /// database. - /// - /// - /// The server sent an invalid packet or the restore operation couldn't proceed - /// due to the database not being empty. - /// - /// - /// The server sent an error during the restore operation. - /// - public static async Task RestoreDatabaseAsync(this EdgeDBClient pool, Stream stream, CancellationToken token = default) - { - await using var client = await pool.GetOrCreateClientAsync(); - return await client.RestoreDatabaseAsync(stream, token).ConfigureAwait(false); - } #endregion } } diff --git a/src/EdgeDB.Net.Driver/Extensions/EdgeDBClientExtensions.cs b/src/EdgeDB.Net.Driver/Extensions/EdgeDBClientExtensions.cs index b4d90879..1577d43b 100644 --- a/src/EdgeDB.Net.Driver/Extensions/EdgeDBClientExtensions.cs +++ b/src/EdgeDB.Net.Driver/Extensions/EdgeDBClientExtensions.cs @@ -1,10 +1,13 @@ -using EdgeDB.Binary; +using EdgeDB.Binary; using EdgeDB.Binary.Packets; using EdgeDB.Dumps; -using EdgeDB.Models; +using System.Runtime.InteropServices; namespace EdgeDB { + /// + /// A class containing extension methods for edgedb clients. + /// public static class EdgeDBClientExtensions { #region Transactions @@ -112,13 +115,14 @@ internal static async Task TransactionInternalAsync(ITransactibleClient client, /// /// Dumps the current database to a stream. /// - /// The TCP client to preform the transaction with. + /// The client to preform the dump with. /// A token to cancel the operation with. /// A stream containing the entire dumped database. /// The server sent an error message during the dumping process. /// The server sent a mismatched packet. - public static async Task DumpDatabaseAsync(this EdgeDBBinaryClient client, CancellationToken token = default) + public static async Task DumpDatabaseAsync(this EdgeDBClient pool, CancellationToken token = default) { + await using var client = await pool.GetOrCreateClientAsync(token).ConfigureAwait(false); using var cmdLock = await client.AquireCommandLockAsync(token).ConfigureAwait(false); try @@ -127,7 +131,8 @@ internal static async Task TransactionInternalAsync(ITransactibleClient client, token.Register(() => tcs.SetCanceled(token)); var stream = new MemoryStream(); - var writer = new DumpWriter(stream); + List blocks = new(); + var handler = (IReceiveable msg) => { @@ -138,7 +143,7 @@ internal static async Task TransactionInternalAsync(ITransactibleClient client, break; case DumpBlock block: { - writer.WriteDumpBlock(block); + blocks.Add(block); } break; case ErrorResponse error: @@ -166,10 +171,10 @@ internal static async Task TransactionInternalAsync(ITransactibleClient client, throw new UnexpectedMessageException(ServerMessageType.DumpHeader, dump.Type); } - writer.WriteDumpHeader(dumpHeader); - await tcs.Task.ConfigureAwait(false); + WriteDumpDataToStream(stream, ref dumpHeader, blocks); + client.Duplexer.OnMessage -= handler; stream.Position = 0; @@ -181,10 +186,19 @@ internal static async Task TransactionInternalAsync(ITransactibleClient client, } } + private static void WriteDumpDataToStream(Stream stream, ref DumpHeader header, List blocks) + { + var writer = new DumpWriter(); + writer.WriteDumpHeader(header); + writer.WriteDumpBlocks(blocks); + + stream.Write(writer.Data.Span); + } + /// /// Restores the database based on a database dump stream. /// - /// The TCP client to preform the transaction with. + /// The TCP client to preform the restore with. /// The stream containing the database dump. /// A token to cancel the operation with. /// The command complete packet received after restoring the database. @@ -193,8 +207,9 @@ internal static async Task TransactionInternalAsync(ITransactibleClient client, /// due to the database not being empty. /// /// The server sent an error during the restore operation. - public static async Task RestoreDatabaseAsync(this EdgeDBBinaryClient client, Stream stream, CancellationToken token = default) + public static async Task RestoreDatabaseAsync(this EdgeDBClient pool, Stream stream, CancellationToken token = default) { + await using var client = await pool.GetOrCreateClientAsync(token).ConfigureAwait(false); using var cmdLock = await client.AquireCommandLockAsync(token).ConfigureAwait(false); var reader = new DumpReader(); diff --git a/src/EdgeDB.Net.Driver/Extensions/EdgeDBHostingExtensions.cs b/src/EdgeDB.Net.Driver/Extensions/EdgeDBHostingExtensions.cs index 1be9349f..82406a67 100644 --- a/src/EdgeDB.Net.Driver/Extensions/EdgeDBHostingExtensions.cs +++ b/src/EdgeDB.Net.Driver/Extensions/EdgeDBHostingExtensions.cs @@ -1,4 +1,4 @@ -using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; @@ -8,8 +8,22 @@ namespace EdgeDB { + /// + /// A class containing extension methods for DI. + /// public static class EdgeDBHostingExtensions { + /// + /// Adds a singleton to a . + /// + /// The source collection to add a to. + /// An optional connection arguments for the client. + /// + /// An optional configuration delegate for configuring the . + /// + /// + /// The source with added as a singleton. + /// public static IServiceCollection AddEdgeDB(this IServiceCollection collection, EdgeDBConnection? connection = null, Action? configure = null) { diff --git a/src/EdgeDB.Net.Driver/Extensions/LoggerExtensions.cs b/src/EdgeDB.Net.Driver/Extensions/LoggerExtensions.cs index a2c6d235..4483f41e 100644 --- a/src/EdgeDB.Net.Driver/Extensions/LoggerExtensions.cs +++ b/src/EdgeDB.Net.Driver/Extensions/LoggerExtensions.cs @@ -1,5 +1,4 @@ -using EdgeDB.Binary; -using EdgeDB.Models; +using EdgeDB.Binary; using Microsoft.Extensions.Logging; namespace EdgeDB diff --git a/src/EdgeDB.Net.Driver/Extensions/ReceivableExtensions.cs b/src/EdgeDB.Net.Driver/Extensions/ReceivableExtensions.cs index 895265d3..67f578b1 100644 --- a/src/EdgeDB.Net.Driver/Extensions/ReceivableExtensions.cs +++ b/src/EdgeDB.Net.Driver/Extensions/ReceivableExtensions.cs @@ -1,6 +1,5 @@ -using EdgeDB.Binary; +using EdgeDB.Binary; using EdgeDB.Binary.Packets; -using EdgeDB.Models; using System; using System.Collections.Generic; using System.Linq; @@ -11,10 +10,10 @@ namespace EdgeDB { internal static class ReceivableExtensions { - public static void ThrowIfErrrorResponse(this IReceiveable packet) + public static void ThrowIfErrrorResponse(this IReceiveable packet, string? query = null) { if (packet is ErrorResponse err) - throw new EdgeDBErrorException(err); + throw new EdgeDBErrorException(err, query); } public static TPacket ThrowIfErrorOrNot(this IReceiveable packet) diff --git a/src/EdgeDB.Net.Driver/Extensions/TypeExtensions.cs b/src/EdgeDB.Net.Driver/Extensions/TypeExtensions.cs index 19a27dfb..2f239a33 100644 --- a/src/EdgeDB.Net.Driver/Extensions/TypeExtensions.cs +++ b/src/EdgeDB.Net.Driver/Extensions/TypeExtensions.cs @@ -11,7 +11,13 @@ internal static class TypeExtensions public static bool IsRecord(this Type type) => type.GetMethods().Any(m => m.Name == "$"); + public static bool IsFSharpType(this Type type) + => type.Module.Name == "FSharp.Core.dll"; + public static bool IsFSharpOption(this Type type) - => type.Name == "FSharpOption`1" && type.Module.Name == "FSharp.Core.dll"; + => IsFSharpType(type) && type.Name == "FSharpOption`1"; + + public static bool IsFSharpValueOption(this Type type) + => IsFSharpType(type) && type.Name == "FSharpValueOption`1"; } } diff --git a/src/EdgeDB.Net.Driver/Models/Shared/Capabilities.cs b/src/EdgeDB.Net.Driver/Models/Capabilities.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/Capabilities.cs rename to src/EdgeDB.Net.Driver/Models/Capabilities.cs diff --git a/src/EdgeDB.Net.Driver/Models/Shared/Cardinality.cs b/src/EdgeDB.Net.Driver/Models/Cardinality.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/Cardinality.cs rename to src/EdgeDB.Net.Driver/Models/Cardinality.cs diff --git a/src/EdgeDB.Net.Driver/Models/Config.cs b/src/EdgeDB.Net.Driver/Models/Config.cs index 94a6d4c0..e82af65b 100644 --- a/src/EdgeDB.Net.Driver/Models/Config.cs +++ b/src/EdgeDB.Net.Driver/Models/Config.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -6,18 +6,56 @@ namespace EdgeDB.State { + /// + /// Represents a DDL policy. + /// public enum DDLPolicy { + /// + /// Always allow DDL. + /// AlwaysAllow, + + /// + /// Never allow DDL. + /// NeverAllow, } + /// + /// Represents a session-level config. + /// public sealed class Config { + /// + /// Gets the idle transation timeout duration. + /// + /// + /// The default value is 10 seconds. + /// public TimeSpan IdleTransationTimeout { get; init; } + + /// + /// Gets the query execution timeout duration. + /// + /// + /// The default value is zero seconds -- meaning there is no timeout. + /// public TimeSpan QueryExecutionTimeout { get; init; } + + /// + /// Gets whether or not to allow data maniplulations in edgeql functions. + /// public bool AllowDMLInFunctions { get; init; } - public DDLPolicy AllowBareDDL { get; init; } + + /// + /// Gets the data definition policy for this client. + /// + public DDLPolicy DDLPolicy { get; init; } + + /// + /// Gets whether or not to apply the access policy. + /// public bool ApplyAccessPolicies { get; init; } internal Config() @@ -25,7 +63,7 @@ internal Config() IdleTransationTimeout = TimeSpan.FromSeconds(10); QueryExecutionTimeout = TimeSpan.Zero; AllowDMLInFunctions = false; - AllowBareDDL = DDLPolicy.AlwaysAllow; + DDLPolicy = DDLPolicy.NeverAllow; ApplyAccessPolicies = true; } @@ -42,8 +80,7 @@ internal Config() if(AllowDMLInFunctions) dict["allow_dml_in_functions"] = true; - if (AllowBareDDL != DDLPolicy.AlwaysAllow) - dict["allow_bare_ddl"] = AllowBareDDL; + dict["allow_bare_ddl"] = DDLPolicy.ToString(); if (!ApplyAccessPolicies) dict["apply_access_policies"] = false; @@ -54,16 +91,53 @@ internal Config() internal Config Clone() => (Config)MemberwiseClone(); + /// + /// Gets the default config. + /// public static Config Default => new(); } + /// + /// Represents properties used to modify a . + /// public sealed class ConfigProperties { + /// + /// Gets or sets the idle transation timeout duration. + /// public Optional IdleTransationTimeout { get; set; } + + /// + /// Gets or sets the query execution timeout duration. + /// public Optional QueryExecutionTimeout { get; set; } + + /// + /// Gets or sets whether or not to allow data maniplulations in edgeql functions. + /// public Optional AllowDMLInFunctions { get; set; } - public Optional AllowBareDDL { get; set; } + + /// + /// Gets or sets the data definition policy for this client. + /// + public Optional DDLPolicy { get; set; } + + /// + /// Gets or sets whether or not to apply the access policy. + /// public Optional ApplyAccessPolicies { get; set; } + + internal Config ToConfig(Config old) + { + return new Config + { + DDLPolicy = DDLPolicy.GetValueOrDefault(old.DDLPolicy), + AllowDMLInFunctions = AllowDMLInFunctions.GetValueOrDefault(old.AllowDMLInFunctions), + ApplyAccessPolicies = ApplyAccessPolicies.GetValueOrDefault(old.ApplyAccessPolicies), + IdleTransationTimeout = IdleTransationTimeout.GetValueOrDefault(old.IdleTransationTimeout), + QueryExecutionTimeout = QueryExecutionTimeout.GetValueOrDefault(old.QueryExecutionTimeout) + }; + } } } diff --git a/src/EdgeDB.Net.Driver/Models/Shared/ConnectionRetryMode.cs b/src/EdgeDB.Net.Driver/Models/ConnectionRetryMode.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/ConnectionRetryMode.cs rename to src/EdgeDB.Net.Driver/Models/ConnectionRetryMode.cs diff --git a/src/EdgeDB.Net.Driver/Models/DataTypes/Group.cs b/src/EdgeDB.Net.Driver/Models/DataTypes/Group.cs index 31fbe5eb..e5e46d45 100644 --- a/src/EdgeDB.Net.Driver/Models/DataTypes/Group.cs +++ b/src/EdgeDB.Net.Driver/Models/DataTypes/Group.cs @@ -1,5 +1,5 @@ -using EdgeDB.DataTypes; -using EdgeDB.Serializer; +using EdgeDB.Binary.Codecs; +using EdgeDB.DataTypes; using System; using System.Collections; using System.Collections.Generic; @@ -16,7 +16,7 @@ namespace EdgeDB /// /// The type of the key used to group the elements. /// The type of the elements. - public class Group : IGrouping + public sealed class Group : IGrouping { /// /// Gets the key used to group the set of . @@ -34,7 +34,7 @@ public class Group : IGrouping public IReadOnlyCollection Elements { get; } /// - /// Constructs a new grouping + /// Constructs a new grouping. /// /// The key that each element share. /// The property used to group the elements. @@ -54,7 +54,8 @@ internal Group(IDictionary raw) Grouping = ((string[])groupingValue!).ToImmutableArray(); Key = BuildKey((IDictionary)keyValue!); - Elements = ((IDictionary[])elementsValue!).Select(x => (TElement)TypeBuilder.BuildObject(typeof(TElement), x)!).ToImmutableArray(); + throw new NotImplementedException("TODO"); + //Elements = ((IDictionary[])elementsValue!).Select(x => (TElement)TypeBuilder.BuildObject(typeof(TElement), x)!).ToImmutableArray(); } private static TKey BuildKey(IDictionary value) diff --git a/src/EdgeDB.Net.Driver/Models/DataTypes/IQueryResultObject.cs b/src/EdgeDB.Net.Driver/Models/DataTypes/IQueryResultObject.cs deleted file mode 100644 index 3df944de..00000000 --- a/src/EdgeDB.Net.Driver/Models/DataTypes/IQueryResultObject.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace EdgeDB.DataTypes -{ - /// - /// Represents an abstract type result from a query. - /// - public interface IQueryResultObject - { - /// - /// Gets the object id of this result object. - /// - /// The unique id of this object. - public Guid GetObjectId(); - } -} diff --git a/src/EdgeDB.Net.Driver/Models/DataTypes/Memory.cs b/src/EdgeDB.Net.Driver/Models/DataTypes/Memory.cs index 29bb4c9b..9e74042a 100644 --- a/src/EdgeDB.Net.Driver/Models/DataTypes/Memory.cs +++ b/src/EdgeDB.Net.Driver/Models/DataTypes/Memory.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -9,7 +9,7 @@ namespace EdgeDB.DataTypes /// /// Represents the memory type in EdgeDB. /// - public struct Memory + public readonly struct Memory { /// /// Gets the total amount of bytes for this memory object. diff --git a/src/EdgeDB.Net.Driver/Models/DataTypes/Sequence.cs b/src/EdgeDB.Net.Driver/Models/DataTypes/Sequence.cs deleted file mode 100644 index ab085993..00000000 --- a/src/EdgeDB.Net.Driver/Models/DataTypes/Sequence.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - /// - /// Represents a Sequence base type in EdgeDB. - /// - public abstract class Sequence - { - /// - /// Gets the value of the sequence. - /// - public long Value { get; protected set; } - } -} diff --git a/src/EdgeDB.Net.Driver/Models/DataTypes/TransientTuple.cs b/src/EdgeDB.Net.Driver/Models/DataTypes/TransientTuple.cs index b484ea0d..664b8876 100644 --- a/src/EdgeDB.Net.Driver/Models/DataTypes/TransientTuple.cs +++ b/src/EdgeDB.Net.Driver/Models/DataTypes/TransientTuple.cs @@ -1,5 +1,6 @@ -using System; +using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Linq; using System.Runtime.CompilerServices; using System.Text; @@ -7,13 +8,28 @@ namespace EdgeDB.DataTypes { + /// + /// Represents an abstract tuple which is used for deserializing edgedb tuples to dotnet tuples. + /// public readonly struct TransientTuple : ITuple { - private delegate ITuple TupleBuilder(Type[] types, object?[] values); + /// + /// Gets the types within this tuple, following the arity order of the tuple. + /// + public IReadOnlyCollection Types + => _types.ToImmutableArray(); + + /// + /// Gets the values within this tuple, following the arity order of the tuple. + /// + public IReadOnlyCollection Values + => _types.ToImmutableArray(); private readonly Type[] _types; private readonly object?[] _values; + private delegate ITuple TupleBuilder(Type[] types, object?[] values); + private static readonly Type[] _valueTupleTypeMap = new[] { typeof(ValueTuple<>), @@ -38,12 +54,16 @@ namespace EdgeDB.DataTypes typeof(Tuple<,,,,,,,>) }; - public TransientTuple(Type[] types, object?[] values) + internal TransientTuple(Type[] types, object?[] values) { _values = values; _types = types; } + /// + /// Converts this tuple to a with the specific arity. + /// + /// A boxed as a . public ITuple ToValueTuple() { return GenerateTuple((types, values) => @@ -54,6 +74,10 @@ public ITuple ToValueTuple() }); } + /// + /// Converts this tuple to a with the specific arity. + /// + /// A boxed as a . public ITuple ToReferenceTuple() { return GenerateTuple((types, values) => @@ -84,9 +108,24 @@ private ITuple GenerateTuple(TupleBuilder builder, int offset = 0) } - public object? this[int index] - => _values[index]; + /// + /// Gets the value within the tuple at the specified index. + /// + /// + /// The value returned is by-ref and is read-only. + /// + /// The index of the element to return. + /// + /// The value at the specified index. + /// + public ref readonly object? this[int index] + => ref _values[index]; + /// + /// The length of the tuple. + /// public int Length => _values.Length; + + object? ITuple.this[int index] => _values[index]; } } diff --git a/src/EdgeDB.Net.Driver/Models/Shared/ErrorSeverity.cs b/src/EdgeDB.Net.Driver/Models/ErrorSeverity.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/ErrorSeverity.cs rename to src/EdgeDB.Net.Driver/Models/ErrorSeverity.cs diff --git a/src/EdgeDB.Net.Driver/Models/Attributes/ShouldReconnectAttribute.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/Attributes/ShouldReconnectAttribute.cs similarity index 67% rename from src/EdgeDB.Net.Driver/Models/Attributes/ShouldReconnectAttribute.cs rename to src/EdgeDB.Net.Driver/Models/Exceptions/Attributes/ShouldReconnectAttribute.cs index 3d126cab..57b3aab9 100644 --- a/src/EdgeDB.Net.Driver/Models/Attributes/ShouldReconnectAttribute.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/Attributes/ShouldReconnectAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -7,5 +7,5 @@ namespace EdgeDB { [AttributeUsage(AttributeTargets.Field)] - internal class ShouldReconnectAttribute : Attribute { } + internal sealed class ShouldReconnectAttribute : Attribute { } } diff --git a/src/EdgeDB.Net.Driver/Models/Attributes/ShouldRetryAttribute.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/Attributes/ShouldRetryAttribute.cs similarity index 68% rename from src/EdgeDB.Net.Driver/Models/Attributes/ShouldRetryAttribute.cs rename to src/EdgeDB.Net.Driver/Models/Exceptions/Attributes/ShouldRetryAttribute.cs index 2680aa5d..7c66b2e7 100644 --- a/src/EdgeDB.Net.Driver/Models/Attributes/ShouldRetryAttribute.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/Attributes/ShouldRetryAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -7,5 +7,5 @@ namespace EdgeDB { [AttributeUsage(AttributeTargets.Field)] - internal class ShouldRetryAttribute : Attribute { } + internal sealed class ShouldRetryAttribute : Attribute { } } diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/ConfigurationException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/ConfigurationException.cs index 01c2bb90..d5b72c4b 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/ConfigurationException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/ConfigurationException.cs @@ -6,9 +6,22 @@ namespace EdgeDB { - public class ConfigurationException : EdgeDBException + /// + /// Represents a generic configuration error. + /// + public sealed class ConfigurationException : EdgeDBException { + /// + /// Creates a new . + /// + /// The configuration error message. public ConfigurationException(string message) : base(message) { } + + /// + /// Creates a new . + /// + /// The configuration error message. + /// An inner exception. public ConfigurationException(string message, Exception inner) : base(message, inner) { } } } diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedException.cs index e3bfc603..cabbe2d7 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -15,6 +15,12 @@ public sealed class ConnectionFailedException : EdgeDBException /// Gets the number of attempts the client made to reconnect. /// public int Attempts { get; } + + /// + /// Constructs a new with the number + /// of connection attempts made. + /// + /// The number of attempts made to connect. public ConnectionFailedException(int attempts) : base($"The connection failed to be established after {attempts} attempt(s)", false, false) { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedTemporarilyException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedTemporarilyException.cs index 2ceb2536..d02e8783 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedTemporarilyException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/ConnectionFailedTemporarilyException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Net.Sockets; @@ -16,6 +16,11 @@ public sealed class ConnectionFailedTemporarilyException : EdgeDBException /// Gets the socket error that caused the connection to fail. /// public SocketError SocketError { get; } + + /// + /// Constructs a new with the specified socket error. + /// + /// The underlying socket error that caused this exception to be thrown. public ConnectionFailedTemporarilyException(SocketError error) : base("The connection could not be established at this time", true, true) { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/CustomClientException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/CustomClientException.cs index f645daaf..77460800 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/CustomClientException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/CustomClientException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,6 +11,10 @@ namespace EdgeDB /// public sealed class CustomClientException : EdgeDBException { + /// + /// Constructs a new with the specified error message. + /// + /// The error message describing why this exception was thrown. public CustomClientException(string message) : base(message, false, false) { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBErrorException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBErrorException.cs index 64f4141b..224a665c 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBErrorException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBErrorException.cs @@ -1,4 +1,4 @@ -using EdgeDB.Binary.Packets; +using EdgeDB.Binary.Packets; using System; using System.Collections.Generic; using System.Diagnostics; @@ -13,11 +13,44 @@ namespace EdgeDB ///
public sealed class EdgeDBErrorException : EdgeDBException { + private const ushort ERROR_LINE_START = 0xFFF3; + private const ushort ERROR_LINE_END = 0xFFF6; + private const ushort ERROR_UTF16COLUMN_START = 0xFFF5; + private const ushort ERROR_UTF16COLUMN_END = 0xFFF8; + + /// + /// Gets the details related to the error. + /// public string? Details { get; } + + /// + /// Gets the server traceback log for the error. + /// public string? ServerTraceBack { get; } + + /// + /// Gets the hint for the error. + /// public string? Hint { get; } + + /// + /// Gets the raw packet. + /// public ErrorResponse ErrorResponse { get; } + /// + /// Gets the query that caused this error. + /// + public string? Query { get; } + + /// + /// Constructs a new with the specified + /// packet. + /// + /// + /// The packet which + /// caused this exception to be thrown. + /// public EdgeDBErrorException(ErrorResponse error) : base(error.Message, typeof(ServerErrorCodes).GetField(error.ErrorCode.ToString())?.IsDefined(typeof(ShouldRetryAttribute), false) ?? false) { @@ -32,5 +65,68 @@ public EdgeDBErrorException(ErrorResponse error) ErrorResponse = error; } + + /// + /// Constructs a new with the specified + /// packet and query string. + /// + /// + /// The packet which + /// caused this exception to be thrown. + /// + /// The query that caused this error to be thrown. + public EdgeDBErrorException(ErrorResponse error, string? query) + : this(error) + { + Query = query; + } + + /// + /// Prettifies the error if it was a result of a bad query string; otherwise formats it. + /// + /// + public override string ToString() + { + return Prettify() ?? $"{ErrorResponse.ErrorCode}: {ErrorResponse.Message}"; + } + + private string? Prettify() + { + if (Query is null || + !ErrorResponse.TryGetAttribute(ERROR_LINE_START, out var lineStart) || + !ErrorResponse.TryGetAttribute(ERROR_LINE_END, out var lineEnd) || + !ErrorResponse.TryGetAttribute(ERROR_UTF16COLUMN_START, out var columnStart) || + !ErrorResponse.TryGetAttribute(ERROR_UTF16COLUMN_END, out var columnEnd)) + { + return null; + } + + var lines = Query.Split("\n"); + + var lineNoWidth = lineEnd.ToString().Length; + + var errorMessage = $"{ErrorResponse.ErrorCode}: {ErrorResponse.Message}\n"; + + errorMessage += "|".PadLeft(lineNoWidth + 3) + "\n"; + + var lineStartInt = lineStart.ToInt(); + var lineEndInt = lineEnd.ToInt(); + var colStartInt = columnStart.ToInt(); + var colEndInt = columnEnd.ToInt(); + + for (int i = lineStartInt; i < lineEndInt + 1; i++) + { + var line = lines[i - 1]; + var start = i == lineStartInt ? colStartInt : 0; + var end = i == lineEndInt ? colEndInt : line.Length; + errorMessage += $" {i.ToString().PadLeft(lineNoWidth)} | {line}\n"; + errorMessage += $"{"|".PadLeft(lineNoWidth + 3)} {"".PadLeft(end - start, '^').PadLeft(end)}\n"; + } + + if (Hint is not null) + errorMessage += $"Hint: {Hint}"; + + return errorMessage; + } } } diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBException.cs index 90ce74d0..968fbaba 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/EdgeDBException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; @@ -15,18 +15,37 @@ public class EdgeDBException : Exception internal bool ShouldRetry { get; } internal bool ShouldReconnect { get; } + /// + /// Constructs a new . + /// + /// Whether or not this exception is retryable. + /// Whether or not the client who caught this exception should reconnect. public EdgeDBException(bool shouldRetry = false, bool shouldReconnect = false) { ShouldRetry = shouldRetry; ShouldReconnect = shouldReconnect; } + /// + /// Constructs a new with the specified error message. + /// + /// The error message describing why this exception was thrown. + /// Whether or not this exception is retryable. + /// Whether or not the client who caught this exception should reconnect. public EdgeDBException(string? message, bool shouldRetry = false, bool shouldReconnect = false) : base(message) { ShouldRetry = shouldRetry; ShouldReconnect = shouldReconnect; } + /// + /// Constructs a new with the specified error message + /// and inner exception. + /// + /// The error message describing why this exception was thrown. + /// The inner exception. + /// Whether or not this exception is retryable. + /// Whether or not the client who caught this exception should reconnect. public EdgeDBException(string? message, Exception? innerException, bool shouldRetry = false, bool shouldReconnect = false) : base(message, innerException) { ShouldRetry = shouldRetry; diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidConnectionException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidConnectionException.cs index 03cece42..bcb0d849 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidConnectionException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidConnectionException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,6 +11,10 @@ namespace EdgeDB ///
public class InvalidConnectionException : EdgeDBException { + /// + /// Constructs a new with the specified error message. + /// + /// The error message describing why this exception was thrown. public InvalidConnectionException(string message) : base(message, false, false) { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidSignatureException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidSignatureException.cs index ed8b1ec9..9dd0ff14 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidSignatureException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/InvalidSignatureException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,6 +11,9 @@ namespace EdgeDB ///
public class InvalidSignatureException : EdgeDBException { + /// + /// Constructs a new . + /// public InvalidSignatureException() : base("The received signature didn't match the expected one") { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/MissingCodecException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/MissingCodecException.cs index 93f992fb..053000a4 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/MissingCodecException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/MissingCodecException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,6 +12,10 @@ namespace EdgeDB /// public class MissingCodecException : EdgeDBException { + /// + /// Constructs a new with the specified error message. + /// + /// The error message describing why this exception was thrown. public MissingCodecException(string message) : base(message) { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/MissingRequiredException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/MissingRequiredException.cs index a034291b..d9051ca3 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/MissingRequiredException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/MissingRequiredException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,6 +11,9 @@ namespace EdgeDB /// public class MissingRequiredException : EdgeDBException { + /// + /// Constructs a new . + /// public MissingRequiredException() : base("Missing required result from query") { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/NoTypeConverterException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/NoTypeConverterException.cs index c35f2b53..76b61d19 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/NoTypeConverterException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/NoTypeConverterException.cs @@ -11,18 +11,35 @@ namespace EdgeDB /// public class NoTypeConverterException : EdgeDBException { + /// + /// Constructs a new with the target and source types. + /// + /// The target type that was going to be converted to. + /// The source type. public NoTypeConverterException(Type target, Type source) : base($"Could not convert {source.Name} to {target.Name}", false, false) { } + /// + /// Constructs a new with the target and source type, + /// and inner exception. + /// + /// The target type that was going to be converted to. + /// The source type. + /// The inner exception. public NoTypeConverterException(Type target, Type source, Exception inner) : base($"Could not convert {source.Name} to {target.Name}", inner, false, false) { } + /// + /// Constructs a new with the specified error message. + /// + /// The error message describing why this exception was thrown. + /// An optional inner exception. public NoTypeConverterException(string message, Exception? inner = null) : base(message, inner) { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/ResultCardinalityMismatchException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/ResultCardinalityMismatchException.cs index d0e6ec32..77047b2a 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/ResultCardinalityMismatchException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/ResultCardinalityMismatchException.cs @@ -1,4 +1,3 @@ -using EdgeDB.Models; using System; using System.Collections.Generic; using System.Linq; @@ -13,6 +12,11 @@ namespace EdgeDB /// public class ResultCardinalityMismatchException : EdgeDBException { + /// + /// Constructs a new . + /// + /// The expected cardinality. + /// The actual cardinality public ResultCardinalityMismatchException(Cardinality expected, Cardinality actual) : base($"Got mismatch on cardinality of query. Expected \"{expected}\" but got \"{actual}\"") { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/TransactionException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/TransactionException.cs index a8930451..2fff9858 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/TransactionException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/TransactionException.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -11,6 +11,11 @@ namespace EdgeDB /// public class TransactionException : EdgeDBException { + /// + /// Constructs a new with a specified error message. + /// + /// The error message describing why this exception was thrown. + /// An optional inner exception. public TransactionException(string message, Exception? innerException = null) : base(message, innerException, false, false) { diff --git a/src/EdgeDB.Net.Driver/Models/Exceptions/UnexpectedMessageException.cs b/src/EdgeDB.Net.Driver/Models/Exceptions/UnexpectedMessageException.cs index 6caa3f2a..e29967e4 100644 --- a/src/EdgeDB.Net.Driver/Models/Exceptions/UnexpectedMessageException.cs +++ b/src/EdgeDB.Net.Driver/Models/Exceptions/UnexpectedMessageException.cs @@ -1,19 +1,27 @@ -using EdgeDB.Binary; -using EdgeDB.Models; +using EdgeDB.Binary; namespace EdgeDB { /// - /// Represents an exception that occurs when the client receives an unexpected exception. + /// Represents an exception that occurs when the client receives an unexpected message. /// public class UnexpectedMessageException : EdgeDBException { + /// + /// Constructs a new with the message type the client wasn't expecting. + /// + /// The unexcepted message type. public UnexpectedMessageException(ServerMessageType unexpected) : base($"Got unexpected message type {unexpected}") { } + /// + /// Constructs a new with the expected and actual message types. + /// + /// The expected message type. + /// The actual message type. public UnexpectedMessageException(ServerMessageType expected, ServerMessageType actual) : base($"Expected message type {expected} but got {actual}") { diff --git a/src/EdgeDB.Net.Driver/Models/ExecuteResult.cs b/src/EdgeDB.Net.Driver/Models/ExecuteResult.cs index e86aa10a..4b0c3764 100644 --- a/src/EdgeDB.Net.Driver/Models/ExecuteResult.cs +++ b/src/EdgeDB.Net.Driver/Models/ExecuteResult.cs @@ -1,6 +1,6 @@ -using EdgeDB.Binary.Packets; +using EdgeDB.Binary.Packets; -namespace EdgeDB.Models +namespace EdgeDB { /// /// Represents a generic execution result of a command. @@ -57,10 +57,19 @@ public interface IExecuteResult string? ExecutedQuery { get; } } + /// + /// Represents a generic execution error. + /// public interface IExecuteError { + /// + /// Gets the error message. + /// string? Message { get; } + /// + /// Gets the error code. + /// ServerErrorCodes ErrorCode { get; } } } diff --git a/src/EdgeDB.Net.Driver/Models/Shared/IOFormat.cs b/src/EdgeDB.Net.Driver/Models/IOFormat.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/IOFormat.cs rename to src/EdgeDB.Net.Driver/Models/IOFormat.cs diff --git a/src/EdgeDB.Net.Driver/Models/Shared/ISystemProvider.cs b/src/EdgeDB.Net.Driver/Models/ISystemProvider.cs similarity index 95% rename from src/EdgeDB.Net.Driver/Models/Shared/ISystemProvider.cs rename to src/EdgeDB.Net.Driver/Models/ISystemProvider.cs index c76b554c..dbf1b631 100644 --- a/src/EdgeDB.Net.Driver/Models/Shared/ISystemProvider.cs +++ b/src/EdgeDB.Net.Driver/Models/ISystemProvider.cs @@ -19,7 +19,7 @@ internal interface ISystemProvider string? GetEnvVariable(string name); } - internal class DefaultSystemProvider : ISystemProvider + internal sealed class DefaultSystemProvider : ISystemProvider { public char DirectorySeparatorChar => Path.DirectorySeparatorChar; diff --git a/src/EdgeDB.Net.Driver/Models/Shared/Isolation.cs b/src/EdgeDB.Net.Driver/Models/Isolation.cs similarity index 92% rename from src/EdgeDB.Net.Driver/Models/Shared/Isolation.cs rename to src/EdgeDB.Net.Driver/Models/Isolation.cs index 47c7530f..941d6a0d 100644 --- a/src/EdgeDB.Net.Driver/Models/Shared/Isolation.cs +++ b/src/EdgeDB.Net.Driver/Models/Isolation.cs @@ -1,4 +1,4 @@ -namespace EdgeDB +namespace EdgeDB { /// /// An enum representing the transaction mode within a . @@ -20,7 +20,7 @@ public enum Isolation /// before the first query or data-modification statement was executed in /// this transaction. /// - [Obsolete("1.3> no longer supports this", true)] + [Obsolete("EdgeDB 1.3>= no longer supports this", true)] RepeatableRead, } } diff --git a/src/EdgeDB.Net.Driver/Models/Sendable.cs b/src/EdgeDB.Net.Driver/Models/Sendable.cs deleted file mode 100644 index 88de5841..00000000 --- a/src/EdgeDB.Net.Driver/Models/Sendable.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB.Binary -{ - internal abstract class Sendable - { - public abstract ClientMessageTypes Type { get;} - - protected abstract void BuildPacket(PacketWriter writer, EdgeDBBinaryClient client); - - public void Write(PacketWriter writer, EdgeDBBinaryClient client) - { - using var stream = new MemoryStream(); - - BuildPacket(new PacketWriter(stream), client); - - var data = stream.ToArray(); - - writer.Write((sbyte)Type); - var l = stream.Length; - writer.Write((uint)l + 4); - writer.Write(data); - } - } -} diff --git a/src/EdgeDB.Net.Driver/Models/Shared/ServerErrorCodes.cs b/src/EdgeDB.Net.Driver/Models/ServerErrorCodes.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/ServerErrorCodes.cs rename to src/EdgeDB.Net.Driver/Models/ServerErrorCodes.cs diff --git a/src/EdgeDB.Net.Driver/Models/Session.cs b/src/EdgeDB.Net.Driver/Models/Session.cs index 801bf212..3fd2db92 100644 --- a/src/EdgeDB.Net.Driver/Models/Session.cs +++ b/src/EdgeDB.Net.Driver/Models/Session.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; @@ -7,7 +7,7 @@ namespace EdgeDB.State { - public sealed class Session + internal sealed class Session { public string Module { get; init; } public IReadOnlyDictionary Aliases @@ -59,31 +59,48 @@ public Session() public Session WithGlobals(IDictionary globals) { - _globals = globals.ToDictionary(x => x.Key, x => x.Value); - return this; + return new Session() + { + _globals = globals.ToDictionary(x => x.Key, x => x.Value), + _aliases = _aliases, + _config = _config, + Module = Module + }; } public Session WithModuleAliases(IDictionary aliases) { - _aliases = aliases.ToDictionary(x => x.Key, x => x.Value); - return this; + return new Session() + { + _aliases = aliases.ToDictionary(x => x.Key, x => x.Value), + _config = _config, + _globals = _globals, + Module = Module + }; } public Session WithConfig(Config config) { - _config = config; - return this; - } - - internal Session Clone() - => new() + return new Session() { - Aliases = Aliases, - Config = Config.Clone(), - Globals = Globals, + _config = config, + _aliases = _aliases, + _globals = _globals, Module = Module }; + } + public Session WithModule(string module) + { + return new Session() + { + _config = _config, + _aliases = _aliases, + _globals = _globals, + Module = module + }; + } + public static Session Default => new(); } diff --git a/src/EdgeDB.Net.Driver/Models/Shared/TransactionState.cs b/src/EdgeDB.Net.Driver/Models/TransactionState.cs similarity index 100% rename from src/EdgeDB.Net.Driver/Models/Shared/TransactionState.cs rename to src/EdgeDB.Net.Driver/Models/TransactionState.cs diff --git a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/AttributeNamingStrategy.cs b/src/EdgeDB.Net.Driver/NamingStrategies/AttributeNamingStrategy.cs similarity index 56% rename from src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/AttributeNamingStrategy.cs rename to src/EdgeDB.Net.Driver/NamingStrategies/AttributeNamingStrategy.cs index ba8ada9f..81126423 100644 --- a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/AttributeNamingStrategy.cs +++ b/src/EdgeDB.Net.Driver/NamingStrategies/AttributeNamingStrategy.cs @@ -1,17 +1,19 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; -namespace EdgeDB.Serializer +namespace EdgeDB { - public sealed class AttributeNamingStrategy : INamingStrategy + internal sealed class AttributeNamingStrategy : INamingStrategy { - public string GetName(PropertyInfo property) + public string Convert(PropertyInfo property) { return property.GetCustomAttribute()?.Name ?? property.Name; } + + public string Convert(string name) => name; } } diff --git a/src/EdgeDB.Net.Driver/NamingStrategies/CamelCaseNamingStrategy.cs b/src/EdgeDB.Net.Driver/NamingStrategies/CamelCaseNamingStrategy.cs new file mode 100644 index 00000000..f871189e --- /dev/null +++ b/src/EdgeDB.Net.Driver/NamingStrategies/CamelCaseNamingStrategy.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB +{ + internal sealed class CamelCaseNamingStrategy : INamingStrategy + { + public string Convert(PropertyInfo property) + => Convert(property.Name); + + public string Convert(string name) + => $"{char.ToLowerInvariant(name[0])}{name[1..].Replace("_", string.Empty)}"; + } +} diff --git a/src/EdgeDB.Net.Driver/NamingStrategies/DefaultNamingStrategy.cs b/src/EdgeDB.Net.Driver/NamingStrategies/DefaultNamingStrategy.cs new file mode 100644 index 00000000..6bbaeb2f --- /dev/null +++ b/src/EdgeDB.Net.Driver/NamingStrategies/DefaultNamingStrategy.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB +{ + internal sealed class DefaultNamingStrategy : INamingStrategy + { + public string Convert(PropertyInfo property) + => property.Name; + public string Convert(string name) + => name; + } +} diff --git a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/INamingStrategy.cs b/src/EdgeDB.Net.Driver/NamingStrategies/INamingStrategy.cs similarity index 66% rename from src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/INamingStrategy.cs rename to src/EdgeDB.Net.Driver/NamingStrategies/INamingStrategy.cs index 1d0d326c..1eb36922 100644 --- a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/INamingStrategy.cs +++ b/src/EdgeDB.Net.Driver/NamingStrategies/INamingStrategy.cs @@ -1,11 +1,11 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; -namespace EdgeDB.Serializer +namespace EdgeDB { /// /// Represents an abstract naming strategy used to convert property names within @@ -13,6 +13,13 @@ namespace EdgeDB.Serializer /// public interface INamingStrategy { + /// + /// Gets the default naming strategy. This strategy does not modify property + /// names. + /// + public static INamingStrategy DefaultNamingStrategy + => new DefaultNamingStrategy(); + /// /// Gets the attribute-based naming strategy. /// @@ -35,16 +42,23 @@ public static INamingStrategy PascalNamingStrategy /// Gets the 'snake-case' naming strategy. /// /// - /// This is the default naming strategy for the . + /// This is the default naming strategy for the . /// public static INamingStrategy SnakeCaseNamingStrategy => new SnakeCaseNamingStrategy(); /// - /// Gets the name defined in the objects schema given the types property info. + /// Converts the 's name to the desired naming scheme. /// /// The property info of which to convert its name. /// The name defined in the schema. - public string GetName(PropertyInfo property); + public string Convert(PropertyInfo property); + + /// + /// Converts the name to the desired naming scheme. + /// + /// The property name of which to convert its name. + /// The name defined in the schema. + public string Convert(string name); } } diff --git a/src/EdgeDB.Net.Driver/NamingStrategies/PascalNamingStrategy.cs b/src/EdgeDB.Net.Driver/NamingStrategies/PascalNamingStrategy.cs new file mode 100644 index 00000000..13ae3c5a --- /dev/null +++ b/src/EdgeDB.Net.Driver/NamingStrategies/PascalNamingStrategy.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB +{ + internal sealed class PascalNamingStrategy : INamingStrategy + { + public string Convert(PropertyInfo property) + => Convert(property.Name); + + public string Convert(string name) + { + var sample = string.Join("", name.Select(c => Char.IsLetterOrDigit(c) ? c.ToString().ToLower() : "_").ToArray()); + + var arr = sample + .Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries) + .Select(s => $"{s[..1].ToUpper()}{s[1..]}"); + + return string.Join("", arr); + } + } +} diff --git a/src/EdgeDB.Net.Driver/NamingStrategies/SnakeCaseNamingStrategy.cs b/src/EdgeDB.Net.Driver/NamingStrategies/SnakeCaseNamingStrategy.cs new file mode 100644 index 00000000..dbfdd56d --- /dev/null +++ b/src/EdgeDB.Net.Driver/NamingStrategies/SnakeCaseNamingStrategy.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace EdgeDB +{ + internal sealed class SnakeCaseNamingStrategy : INamingStrategy + { + public string Convert(PropertyInfo property) + => Convert(property.Name); + + public string Convert(string name) + { + if (string.IsNullOrWhiteSpace(name)) + { + return name; + } + + var upperCaseLength = name.Where((c, i) => c is >= 'A' and <= 'Z' && i != 0).Count(); + + if (upperCaseLength == 0) + return name.ToLower(); + + var bufferSize = name.Length + upperCaseLength; + Span buffer = stackalloc char[bufferSize]; + var bufferPosition = 0; + var namePosition = 0; + while (bufferPosition < buffer.Length) + { + if (namePosition > 0 && name[namePosition] >= 'A' && name[namePosition] <= 'Z') + { + buffer[bufferPosition] = '_'; + buffer[bufferPosition + 1] = name[namePosition]; + bufferPosition += 2; + namePosition++; + continue; + } + buffer[bufferPosition] = name[namePosition]; + bufferPosition++; + namePosition++; + } + + return new string(buffer).ToLower(); + } + + } +} diff --git a/src/EdgeDB.Net.Driver/Serializer/PacketReader.cs b/src/EdgeDB.Net.Driver/Serializer/PacketReader.cs deleted file mode 100644 index 58a37857..00000000 --- a/src/EdgeDB.Net.Driver/Serializer/PacketReader.cs +++ /dev/null @@ -1,192 +0,0 @@ -using EdgeDB.Binary; -using EdgeDB.Models; -using EdgeDB.Utils; -using System.Buffers.Binary; -using System.Text; - -namespace EdgeDB -{ - internal ref struct PacketReader - { - public bool Empty - => _span.IsEmpty; - - private Span _span; - - public PacketReader(Span bytes) - { - _span = bytes; - } - - public PacketReader(ref Span bytes) - { - _span = bytes; - } - - public void Skip(int count) - { - _span = _span[count..]; - } - - public byte[] ConsumeByteArray() - { - return _span.ToArray(); - } - - public string ConsumeString() - { - return Encoding.UTF8.GetString(_span); - } - - public Guid ReadGuid() - { - var a = ReadInt32(); - var b = ReadInt16(); - var c = ReadInt16(); - - Span buffer = _span[0..8]; - _span = _span[8..]; - return new Guid(a, b, c, buffer.ToArray()); - } - - public bool ReadBoolean() - => ReadByte() > 0; - - public byte ReadByte() - { - var val = _span[0]; - _span = _span[1..]; - return val; - } - - public char ReadChar() - => (char)ReadByte(); - - public double ReadDouble() - { - var value = BinaryPrimitives.ReadDoubleBigEndian(_span); - _span = _span[sizeof(double)..]; - return value; - } - - public KeyValue[] ReadKeyValues() - { - var length = ReadUInt16(); - - KeyValue[] arr = new KeyValue[length]; - - for (ushort i = 0; i != length; i++) - { - arr[i] = ReadKeyValue(); - } - - return arr; - } - - public KeyValue ReadKeyValue() - { - var code = ReadUInt16(); - var value = ReadByteArray(); - - return new KeyValue(code, value); - } - - public float ReadSingle() - { - var value = BinaryPrimitives.ReadSingleBigEndian(_span); - _span = _span[sizeof(float)..]; - return value; - } - - public ulong ReadUInt64() - { - var value = BinaryPrimitives.ReadUInt64BigEndian(_span); - _span = _span[sizeof(ulong)..]; - return value; - } - - public long ReadInt64() - { - var value = BinaryPrimitives.ReadInt64BigEndian(_span); - _span = _span[sizeof(long)..]; - return value; - } - - public uint ReadUInt32() - { - var value = BinaryPrimitives.ReadUInt32BigEndian(_span); - _span = _span[sizeof(uint)..]; - return value; - } - - public int ReadInt32() - { - var value = BinaryPrimitives.ReadInt32BigEndian(_span); - _span = _span[sizeof(int)..]; - return value; - } - - public ushort ReadUInt16() - { - var value = BinaryPrimitives.ReadUInt16BigEndian(_span); - _span = _span[sizeof(ushort)..]; - return value; - } - - public short ReadInt16() - { - var value = BinaryPrimitives.ReadInt16BigEndian(_span); - _span = _span[sizeof(short)..]; - return value; - } - - public string ReadString() - { - var length = (int)ReadUInt32(); - var str = Encoding.UTF8.GetString(_span[0..length]); - _span = _span[length..]; - return str; - } - - public Annotation[] ReadAnnotations() - { - var length = ReadUInt16(); - - Annotation[] arr = new Annotation[length]; - - for (ushort i = 0; i != length; i++) - { - arr[i] = ReadAnnotation(); - } - - return arr; - } - - public Annotation ReadAnnotation() - { - var name = ReadString(); - var value = ReadString(); - - return new Annotation(name, value); - } - - public byte[] ReadByteArray() - { - var length = (int)ReadUInt32(); - var buffer = _span[0..length]; - _span = _span[length..]; - return buffer.ToArray(); - } - - public void ReadBytes(int length, out Span buff) - { - buff = _span[0..length]; - _span = _span[length..]; - } - - public void Dispose() - { - _span.Clear(); - } - } -} diff --git a/src/EdgeDB.Net.Driver/Serializer/PacketWriter.cs b/src/EdgeDB.Net.Driver/Serializer/PacketWriter.cs deleted file mode 100644 index 28d19070..00000000 --- a/src/EdgeDB.Net.Driver/Serializer/PacketWriter.cs +++ /dev/null @@ -1,174 +0,0 @@ -using EdgeDB.Binary; -using EdgeDB.Models; -using EdgeDB.Utils; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Numerics; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - internal unsafe class PacketWriter : BinaryWriter - { - public long Length - => base.OutStream.Length; - - public PacketWriter() - : base(new MemoryStream()) - { - - } - - public PacketWriter(Stream stream) - : base(stream, Encoding.UTF8, true) - { - - } - - public byte[] GetBytes() - { - if (BaseStream is not MemoryStream ms) - throw new InvalidOperationException(); - - ms.Position = 0; - - return ms.ToArray(); - } - - public void Write(IEnumerable? headers) - { - // write length - Write((ushort)(headers?.Count() ?? 0)); - - if(headers is not null) - { - foreach (var header in headers) - { - Write(header.Code); - WriteArray(header.Value); - } - } - } - - public void Write(IEnumerable? headers) - { - // write length - Write((ushort)(headers?.Count() ?? 0)); - - if (headers is not null) - { - foreach (var header in headers) - { - Write(header.Name); - Write(header.Value); - } - } - } - - public void Write(PacketWriter value, int offset = 0) - { - value.BaseStream.Position = offset; - value.BaseStream.CopyTo(base.BaseStream); - } - - public void Write(KeyValue header) - { - Write(header.Code); - Write(header.Value); - } - - public void Write(Guid value) - { - var bytes = HexConverter.FromHex(value.ToString().Replace("-", "")); - Write(bytes); - } - - public override void Write(string value) - { - if (value is null) - Write((uint)0); - else - { - var buffer = Encoding.UTF8.GetBytes(value); - Write((uint)buffer.Length); - Write(buffer); - } - } - - public override void Write(double value) - { - var span = new Span((byte*)&value, sizeof(double)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public override void Write(float value) - { - var span = new Span((byte*)&value, sizeof(float)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public override void Write(uint value) - { - var span = new Span((byte*)&value, sizeof(uint)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public override void Write(int value) - { - var span = new Span((byte*)&value, sizeof(int)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public override void Write(ulong value) - { - var span = new Span((byte*)&value, sizeof(ulong)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public override void Write(long value) - { - var span = new Span((byte*)&value, sizeof(long)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public override void Write(short value) - { - var span = new Span((byte*)&value, sizeof(short)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public override void Write(ushort value) - { - var span = new Span((byte*)&value, sizeof(ushort)); - if (BitConverter.IsLittleEndian) - span.Reverse(); - Write(span); - } - - public void WriteArray(byte[] buffer) - { - Write((uint)buffer.Length); - base.Write(buffer); - } - - public void WriteArrayWithoutLength(byte[] buffer) - => base.Write(buffer); - } -} diff --git a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/CamelCaseNamingStrategy.cs b/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/CamelCaseNamingStrategy.cs deleted file mode 100644 index 31ef7bfe..00000000 --- a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/CamelCaseNamingStrategy.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB.Serializer -{ - public sealed class CamelCaseNamingStrategy : INamingStrategy - { - public string GetName(PropertyInfo property) - { - var name = property.Name; - return $"{char.ToLowerInvariant(name[0])}{name[1..].Replace("_", string.Empty)}"; - } - } -} diff --git a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/PascalNamingStrategy.cs b/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/PascalNamingStrategy.cs deleted file mode 100644 index 2d4e4f57..00000000 --- a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/PascalNamingStrategy.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB.Serializer -{ - public sealed class PascalNamingStrategy : INamingStrategy - { - public string GetName(PropertyInfo property) - { - var str = property.Name; - - string sample = string.Join("", str.Select(c => Char.IsLetterOrDigit(c) ? c.ToString().ToLower() : "_").ToArray()); - - var arr = sample - .Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries) - .Select(s => $"{s.Substring(0, 1).ToUpper()}{s.Substring(1)}"); - - sample = string.Join("", arr); - - return sample; - } - } -} diff --git a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/SnakeCaseNamingStrategy.cs b/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/SnakeCaseNamingStrategy.cs deleted file mode 100644 index b92abed6..00000000 --- a/src/EdgeDB.Net.Driver/Serializer/SchemaTypeBuilders/NamingStrategies/SnakeCaseNamingStrategy.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; - -namespace EdgeDB.Serializer -{ - public sealed class SnakeCaseNamingStrategy : INamingStrategy - { - public string GetName(PropertyInfo property) - { - return Regex.Replace(property.Name, "(? $"_{x.Value}").ToLower(); - } - } -} diff --git a/src/EdgeDB.Net.Driver/Transaction.cs b/src/EdgeDB.Net.Driver/Transaction.cs index 5d05c94c..9639c029 100644 --- a/src/EdgeDB.Net.Driver/Transaction.cs +++ b/src/EdgeDB.Net.Driver/Transaction.cs @@ -1,12 +1,11 @@ -using EdgeDB.DataTypes; -using EdgeDB.Models; +using EdgeDB.DataTypes; namespace EdgeDB { /// /// Represents a transaction within edgedb. /// - public class Transaction : IEdgeDBQueryable + public sealed class Transaction : IEdgeDBQueryable { /// /// Gets the transaction state of this transaction. diff --git a/src/EdgeDB.Net.Driver/Utils/AsyncEvent.cs b/src/EdgeDB.Net.Driver/Utils/AsyncEvent.cs index 6222c10e..0a799201 100644 --- a/src/EdgeDB.Net.Driver/Utils/AsyncEvent.cs +++ b/src/EdgeDB.Net.Driver/Utils/AsyncEvent.cs @@ -1,8 +1,8 @@ -using System.Collections.Concurrent; +using System.Collections.Concurrent; namespace EdgeDB { - internal class AsyncEvent + internal sealed class AsyncEvent where T : class { internal ConcurrentDictionary _subscriptions; diff --git a/src/EdgeDB.Net.Driver/Utils/BinaryUtils.cs b/src/EdgeDB.Net.Driver/Utils/BinaryUtils.cs new file mode 100644 index 00000000..c7621162 --- /dev/null +++ b/src/EdgeDB.Net.Driver/Utils/BinaryUtils.cs @@ -0,0 +1,84 @@ +using EdgeDB.Binary; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.Utils +{ + internal sealed unsafe class BinaryUtils + { + internal static int SizeOfString(string? str) + => str is null ? 4 : Encoding.UTF8.GetByteCount(str) + 4; + internal static int SizeOfByteArray(byte[]? arr) + => arr?.Length + 4 ?? 4; + + internal static int SizeOfAnnotations(Annotation[]? annotations) + => annotations?.Sum(x => x.Size) + 2 ?? 2; + + internal static void CorrectEndianness(ref T value) + where T : unmanaged + { + // return if numeric types are already in big endianness + if (!BitConverter.IsLittleEndian) + return; + + var size = sizeof(T); + + switch (size) + { + case 2: + { + ref var shortValue = ref Unsafe.As(ref value); + + shortValue = (ushort)((shortValue >> 8) + (shortValue << 8)); + } + break; + + case 4: + { + ref var intValue = ref Unsafe.As(ref value); + + var s1 = intValue & 0x00FF00FFu; + var s2 = intValue & 0xFF00FF00u; + intValue = + // rotate right (xx zz) + ((s1 >> 8) | (s1 << (64 - 8))) + + // rotate left (ww yy) + ((s2 << 8) | (s2 >> (32 - 8))); + } + break; + case 8: + { + ref var longValue = ref Unsafe.As(ref value); + + // split to 32 bit for faster thruput + var upper = (uint)longValue; + var upperS1 = upper & 0x00FF00FFu; + var upperS2 = upper & 0xFF00FF00u; + var lower = (uint)(longValue >> 32); + var lowerS1 = lower & 0x00FF00FFu; + var lowerS2 = lower & 0xFF00FF00u; + + longValue = (((ulong)( + // rotate right (xx zz) + ((upperS1 >> 8) | (upperS1 << (64 - 8))) + + // rotate left (ww yy) + ((upperS2 << 8) | (upperS2 >> (32 - 8))) + )) << 32) + ( + // rotate right (xx zz) + ((lowerS1 >> 8) | (lowerS1 << (64 - 8))) + + // rotate left (ww yy) + ((lowerS2 << 8) | (lowerS2 >> (32 - 8))) + ); + } + break; + + default: + return; + } + } + } +} diff --git a/src/EdgeDB.Net.Driver/Utils/FastInverseIndexer.cs b/src/EdgeDB.Net.Driver/Utils/FastInverseIndexer.cs new file mode 100644 index 00000000..3877bdcf --- /dev/null +++ b/src/EdgeDB.Net.Driver/Utils/FastInverseIndexer.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB +{ + internal ref struct FastInverseIndexer + { + private readonly int _bits; + private readonly byte[] _buffer; + private int _tracked; + + public FastInverseIndexer(int count) + { + _tracked = count; + _bits = count; + + // create a span with 'count' bits + // since we're dividing by 8, we can shift the number by 3 and then add one if the frist 3 bits are not zero + var c = count + 0b111; + var t = (count >> 3) + ((count | c) >> 3); + _buffer = new byte[t]; + } + + public void Track(int index) + { + _tracked--; + + if (_tracked < 0) + throw new ArgumentOutOfRangeException(nameof(index), "Too many items tracked!"); + + // get the bit relative to a byte in our span, the and is equivalent to modulus 8 + var b = 1 << (index & 0b111); + + // get the index in our span + var i = index >> 3; + + // OR the bit in + _buffer[i] |= (byte)b; + } + + public int[] GetIndexies() + { + if (_tracked == 0) + return Array.Empty(); + + int[] missed = new int[_tracked]; + int p = 0; + + // iterate over the span + for (int i = 0; i != _buffer.Length; i++) + { + // the byte->bit index + var k = i << 3; + + // inverse the byte at the current index + var b = ~_buffer[i]; + + // iterate over the bits until we've read all 8 or we've read all total bits + for (int j = 0; j != 8 && _bits > k + j; j++) + { + // if the bit is tracked + if ((b & 1) == 1) + { + // add to our missed array + missed[p] = j + k; + p++; + } + + // shift the next bit forwards + b >>= 1; + } + } + + return missed; + } + } +} diff --git a/src/EdgeDB.Net.Driver/Utils/Optional.cs b/src/EdgeDB.Net.Driver/Utils/Optional.cs index 454e439a..50774deb 100644 --- a/src/EdgeDB.Net.Driver/Utils/Optional.cs +++ b/src/EdgeDB.Net.Driver/Utils/Optional.cs @@ -1,11 +1,18 @@ -using System.Diagnostics; +using System.Diagnostics; namespace EdgeDB { //Based on https://github.com/dotnet/coreclr/blob/master/src/mscorlib/src/System/Nullable.cs + /// + /// Represents an optional value type. + /// + /// The type of the optional value. [DebuggerDisplay(@"{DebuggerDisplay,nq}")] public struct Optional { + /// + /// Gets the unspecified value for . + /// public static Optional Unspecified => default; private readonly T? _value; @@ -30,28 +37,67 @@ public Optional(T value) IsSpecified = true; } + /// + /// Gets the value or {}. + /// + /// The value or {}. public T? GetValueOrDefault() => _value; + + /// + /// Gets the value or the provided . + /// + /// + /// The default value of to return if the current + /// does not have a value. + /// + /// The ; or . public T? GetValueOrDefault(T? defaultValue) => IsSpecified ? _value : defaultValue; + /// public override bool Equals(object? other) { if (!IsSpecified) return other == null; if (other == null) return false; return _value?.Equals(other) ?? false; } + + /// public override int GetHashCode() => IsSpecified ? _value!.GetHashCode() : 0; + /// public override string? ToString() => IsSpecified ? _value?.ToString() : null; private string DebuggerDisplay => IsSpecified ? _value?.ToString() ?? "" : ""; public static implicit operator Optional(T value) => new(value); public static explicit operator T?(Optional value) => value.Value; } + + /// + /// Represents an optional value. + /// public static class Optional { + /// + /// Creates an unspecified optional value. + /// + /// The inner type of the optional. + /// A with no value specified. public static Optional Create() => Optional.Unspecified; + + /// + /// Creates an optional value. + /// + /// The inner type of the optional. + /// The value of the . + /// public static Optional Create(T value) => new(value); + /// + /// Converts the to a . + /// + /// The inner type of the optional. + /// The optional to convert. + /// A nullable version of the optional. public static T? ToNullable(this Optional val) where T : struct => val.IsSpecified ? val.Value : null; diff --git a/src/EdgeDB.Net.Driver/Utils/ReflectionUtils.cs b/src/EdgeDB.Net.Driver/Utils/ReflectionUtils.cs index 708500aa..83ac2586 100644 --- a/src/EdgeDB.Net.Driver/Utils/ReflectionUtils.cs +++ b/src/EdgeDB.Net.Driver/Utils/ReflectionUtils.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; @@ -9,7 +9,7 @@ namespace EdgeDB { - internal class ReflectionUtils + internal static class ReflectionUtils { public static bool IsSubclassOfRawGeneric(Type generic, Type? toCheck) { diff --git a/src/EdgeDB.Net.Driver/Utils/Scram.cs b/src/EdgeDB.Net.Driver/Utils/Scram.cs index 038cf78b..b8a58aaf 100644 --- a/src/EdgeDB.Net.Driver/Utils/Scram.cs +++ b/src/EdgeDB.Net.Driver/Utils/Scram.cs @@ -1,14 +1,13 @@ -using EdgeDB.Binary; +using EdgeDB.Binary; using EdgeDB.Binary.Packets; -using EdgeDB.Codecs; -using EdgeDB.Models; +using EdgeDB.Binary.Codecs; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; namespace EdgeDB.Utils { - internal class Scram : IDisposable + internal sealed class Scram : IDisposable { public const int NonceLength = 18; @@ -17,6 +16,11 @@ internal class Scram : IDisposable private static string SanitizeString(string str) => str.Normalize(NormalizationForm.FormKC); + public Scram(byte[]? clientNonce = null) + { + _clientNonce = clientNonce; + } + private static byte[] GenerateNonce() { var bytes = new byte[NonceLength]; @@ -40,7 +44,7 @@ public AuthenticationSASLInitialResponse BuildInitialMessage(string username, st method); } - public (AuthenticationSASLResponse FinalMessage, byte[] ExpectedSig) BuildFinalMessage(AuthenticationStatus status, string password) + public (AuthenticationSASLResponse FinalMessage, byte[] ExpectedSig) BuildFinalMessage(in AuthenticationStatus status, string password) { if (status.AuthStatus != AuthStatus.AuthenticationSASLContinue) throw new ArgumentException($"Expected continuation message for SASL, got {status.AuthStatus}"); @@ -54,8 +58,7 @@ public AuthenticationSASLInitialResponse BuildInitialMessage(string username, st { throw new FormatException("Received malformed scram message"); } - - var serverNonce = Convert.FromBase64String(parsedMessage["r"]); + var salt = Convert.FromBase64String(parsedMessage["s"]); if (!int.TryParse(parsedMessage["i"], out var iterations)) @@ -64,7 +67,7 @@ public AuthenticationSASLInitialResponse BuildInitialMessage(string username, st } // build final - var final = $"c=biws,r={Convert.ToBase64String(serverNonce)}"; + var final = $"c=biws,r={parsedMessage["r"]}"; var authMsg = Encoding.UTF8.GetBytes($"{_rawFirstMessage},{msg},{final}"); var saltedPassword = SaltPassword(SanitizeString(password), salt, iterations); diff --git a/src/EdgeDB.Net.QueryBuilder/AssemblyInfo.cs b/src/EdgeDB.Net.QueryBuilder/AssemblyInfo.cs deleted file mode 100644 index a8ed8186..00000000 --- a/src/EdgeDB.Net.QueryBuilder/AssemblyInfo.cs +++ /dev/null @@ -1,3 +0,0 @@ -using System.Runtime.CompilerServices; - -[assembly: InternalsVisibleTo("EdgeDB.Driver")] diff --git a/src/EdgeDB.Net.QueryBuilder/Attributes/EnumSerializerAttribute.cs b/src/EdgeDB.Net.QueryBuilder/Attributes/EnumSerializerAttribute.cs deleted file mode 100644 index 20687f0b..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Attributes/EnumSerializerAttribute.cs +++ /dev/null @@ -1,30 +0,0 @@ -namespace EdgeDB -{ - [AttributeUsage(AttributeTargets.Enum)] - public class EnumSerializerAttribute : Attribute - { - internal readonly SerializationMethod Method; - - /// - /// Marks this enum to be serialized in a certian way. - /// - /// The serialization method to use when serializing this enum. - public EnumSerializerAttribute(SerializationMethod method) - { - Method = method; - } - } - - public enum SerializationMethod - { - /// - /// Converts the name of the enums value ex: Day to the lowercase representation "day" as a string. - /// - Lower, - - /// - /// Converts the value of the enum to the numeric value. - /// - Numeric, - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Attributes/ParameterMap.cs b/src/EdgeDB.Net.QueryBuilder/Attributes/ParameterMap.cs deleted file mode 100644 index bb841537..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Attributes/ParameterMap.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - [AttributeUsage(AttributeTargets.Method)] - internal class ParameterMap : Attribute - { - internal readonly long Index; - internal readonly string Name; - - public ParameterMap(long index, string name) - { - Index = index; - Name = name; - } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/BuiltQuery.cs b/src/EdgeDB.Net.QueryBuilder/BuiltQuery.cs deleted file mode 100644 index 646fc37a..00000000 --- a/src/EdgeDB.Net.QueryBuilder/BuiltQuery.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Text.RegularExpressions; - -namespace EdgeDB -{ - public sealed class BuiltQuery - { - public string QueryText { get; set; } = ""; - public IEnumerable> Parameters { get; set; } = new Dictionary(); - - public string Prettify() - { - // add newlines - var result = Regex.Replace(QueryText, @"({|\(|\)|}|,)", m => - { - switch (m.Groups[1].Value) - { - case "{" or "(" or ",": - if (m.Groups[1].Value == "{" && QueryText[m.Index + 1] == '}') - return m.Groups[1].Value; - - return $"{m.Groups[1].Value}\n"; - - default: - return $"{((m.Groups[1].Value == "}" && (QueryText[m.Index - 1] == '{' || QueryText[m.Index - 1] == '}')) ? "" : "\n")}{m.Groups[1].Value}{((QueryText.Length != m.Index + 1 && (QueryText[m.Index + 1] != ',')) ? "\n" : "")}"; - } - }).Trim().Replace("\n ", "\n"); - - // clean up newline func - result = Regex.Replace(result, "\n\n", m => "\n"); - - // add indentation - result = Regex.Replace(result, "^", m => - { - int indent = 0; - - foreach (var c in result[..m.Index]) - { - if (c is '(' or '{') - indent++; - if (c is ')' or '}') - indent--; - } - - var next = result.Length != m.Index ? result[m.Index] : '\0'; - - if (next is '}' or ')') - indent--; - - return "".PadLeft(indent * 2); - }, RegexOptions.Multiline); - - return result; - } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/ComputedValue.cs b/src/EdgeDB.Net.QueryBuilder/ComputedValue.cs deleted file mode 100644 index 9f3e39d7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/ComputedValue.cs +++ /dev/null @@ -1,35 +0,0 @@ -namespace EdgeDB -{ - public struct ComputedValue : IComputedValue - { - public TInner? Value { get; } - - internal QueryBuilder? Builder { get; } = null; - - internal ComputedValue(TInner? value) - { - Value = value; - } - - internal ComputedValue(TInner? value, QueryBuilder builder) - : this(value) - { - Builder = builder; - } - - public static implicit operator ComputedValue(TInner? value) - { - return new(value); - } - - object? IComputedValue.Value => Value; - QueryBuilder? IComputedValue.Builder => Builder; - } - - public interface IComputedValue - { - public object? Value { get; } - - internal QueryBuilder? Builder { get; } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/EdgeDB.Net.QueryBuilder.csproj b/src/EdgeDB.Net.QueryBuilder/EdgeDB.Net.QueryBuilder.csproj deleted file mode 100644 index 5a2fb385..00000000 --- a/src/EdgeDB.Net.QueryBuilder/EdgeDB.Net.QueryBuilder.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - EdgeDB.Net.QueryBuilder - EdgeDB - net6.0 - enable - enable - An optional extension to the base driver that allows for query building. - CS1591 - - - - 5 - True - - - - 5 - True - - - - - - - - - True - \ - - - - - - - - diff --git a/src/EdgeDB.Net.QueryBuilder/EdgeQL.cs b/src/EdgeDB.Net.QueryBuilder/EdgeQL.cs deleted file mode 100644 index 74e7be15..00000000 --- a/src/EdgeDB.Net.QueryBuilder/EdgeQL.cs +++ /dev/null @@ -1,21 +0,0 @@ -using EdgeDB.Operators; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - public sealed partial class EdgeQL - { - [EquivalentOperator(typeof(VariablesReference))] - public static object? Var(string name) => default; - - [EquivalentOperator(typeof(VariablesReference))] - public static TType? Var(string name) - { - return QueryBuilder.StaticLiteral(name, QueryExpressionType.Variable).SubQuery(); - } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/EdgeQL.g.cs b/src/EdgeDB.Net.QueryBuilder/EdgeQL.g.cs deleted file mode 100644 index 385fda3e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/EdgeQL.g.cs +++ /dev/null @@ -1,1726 +0,0 @@ -#nullable restore -#pragma warning disable -using EdgeDB.Operators; -using EdgeDB.DataTypes; -using System.Numerics; - -namespace EdgeDB -{ - public sealed partial class EdgeQL - { - #region Generic - - #region Equals - /// - /// A function that represents the EdgeQL version of: ?= - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericEquals))] - public static bool Equals(object? a, object? b) { return default!; } - #endregion - - #region NotEqual - /// - /// A function that represents the EdgeQL version of: ?!= - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericNotEqual))] - public static bool NotEqual(object? a, object? b) { return default!; } - #endregion - - #region LessThan - /// - /// A function that represents the EdgeQL version of: < - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericLessThan))] - public static bool LessThan(object? a, object? b) { return default!; } - #endregion - - #region GreaterThan - /// - /// A function that represents the EdgeQL version of: > - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericGreaterThan))] - public static bool GreaterThan(object? a, object? b) { return default!; } - #endregion - - #region LessThanOrEqual - /// - /// A function that represents the EdgeQL version of: <= - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericLessThanOrEqual))] - public static bool LessThanOrEqual(object? a, object? b) { return default!; } - #endregion - - #region GreaterThanOrEqual - /// - /// A function that represents the EdgeQL version of: >= - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericGreaterThanOrEqual))] - public static bool GreaterThanOrEqual(object? a, object? b) { return default!; } - #endregion - - #region Length - /// - /// A function that represents the EdgeQL version of: len() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericLength))] - public static long Length(object? a) { return default!; } - #endregion - - #region Contains - /// - /// A function that represents the EdgeQL version of: contains(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericContains))] - public static bool Contains(object? source, object? element) { return default!; } - #endregion - - #region Find - /// - /// A function that represents the EdgeQL version of: find(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.GenericFind))] - public static long IndexOf(object? source, object? element) { return default!; } - #endregion - - #endregion Generic - - #region string - - #region Index - /// - /// A function that represents the EdgeQL version of: [] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringIndex))] - public static string? Index(string? a, long b) { return default!; } - #endregion - - #region Slice - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringSlice))] - public static string? Slice(string? str, long startIndex) { return default!; } - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringSlice))] - public static string? Slice(string? str, long startIndex, long endIndex) { return default!; } - #endregion - - #region Concat - /// - /// A function that represents the EdgeQL version of: ++ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringConcat))] - public static string? Concat(string? a, string? b) { return default!; } - #endregion - - #region Like - /// - /// A function that represents the EdgeQL version of: like - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringLike))] - public static bool Like(string? a, string? b) { return default!; } - #endregion - - #region ILike - /// - /// A function that represents the EdgeQL version of: ilike - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringILike))] - public static bool ILike(string? a, string? b) { return default!; } - #endregion - - #region ToString - /// - /// A function that represents the EdgeQL version of: to_str() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringToString))] - public static string? ToString(object? a) { return default!; } - #endregion - - #region Length - /// - /// A function that represents the EdgeQL version of: len() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringLength))] - public static long Length(string? a) { return default!; } - #endregion - - #region Contains - /// - /// A function that represents the EdgeQL version of: contains(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringContains))] - public static bool Contains(string? a, string? b) { return default!; } - /// - /// A function that represents the EdgeQL version of: contains(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringContains))] - public static bool Contains(string? a, char b) { return default!; } - #endregion - - #region Find - /// - /// A function that represents the EdgeQL version of: find(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringFind))] - public static long Find(string? a, string? b) { return default!; } - /// - /// A function that represents the EdgeQL version of: find(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringFind))] - public static long Find(string? a, char b) { return default!; } - #endregion - - #region ToLower - /// - /// A function that represents the EdgeQL version of: str_lower() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringToLower))] - public static string? ToLower(string? a) { return default!; } - #endregion - - #region ToUpper - /// - /// A function that represents the EdgeQL version of: str_upper() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringToUpper))] - public static string? ToUpper(string? a) { return default!; } - #endregion - - #region ToTitle - /// - /// A function that represents the EdgeQL version of: str_title() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringToTitle))] - public static string? ToTitle(string? a) { return default!; } - #endregion - - #region PadLeft - /// - /// A function that represents the EdgeQL version of: str_pad_start(, , {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringPadLeft))] - public static string? PadLeft(string? a, long count) { return default!; } - /// - /// A function that represents the EdgeQL version of: str_pad_start(, , {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringPadLeft))] - public static string? PadLeft(string? a, long count, string? fill) { return default!; } - #endregion - - #region PadRight - /// - /// A function that represents the EdgeQL version of: str_pad_end(, , {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringPadRight))] - public static string? PadRight(string? a, long count) { return default!; } - /// - /// A function that represents the EdgeQL version of: str_pad_end(, , {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringPadRight))] - public static string? PadRight(string? a, long count, string? fill) { return default!; } - #endregion - - #region Trim - /// - /// A function that represents the EdgeQL version of: str_trim(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringTrim))] - public static string? Trim(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: str_trim(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringTrim))] - public static string? Trim(string? a, string? trimCharacters) { return default!; } - #endregion - - #region TrimStart - /// - /// A function that represents the EdgeQL version of: str_trim_start(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringTrimStart))] - public static string? TrimStart(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: str_trim_start(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringTrimStart))] - public static string? TrimStart(string? a, string? trimCharacters) { return default!; } - #endregion - - #region TrimEnd - /// - /// A function that represents the EdgeQL version of: str_trim_end(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringTrimEnd))] - public static string? TrimEnd(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: str_trim_end(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringTrimEnd))] - public static string? TrimEnd(string? a, string? trimCharacters) { return default!; } - #endregion - - #region Repeat - /// - /// A function that represents the EdgeQL version of: str_repeat(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringRepeat))] - public static string? Repeat(string? a, long count) { return default!; } - #endregion - - #region Split - /// - /// A function that represents the EdgeQL version of: str_split(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringSplit))] - public static string?[] Split(string? a, string? delimiter) { return default!; } - /// - /// A function that represents the EdgeQL version of: str_split(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringSplit))] - public static string?[] Split(string? a, char delimiter) { return default!; } - #endregion - - #region Match - /// - /// A function that represents the EdgeQL version of: re_match(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringMatch))] - public static string?[] Match(string? pattern, string? input) { return default!; } - #endregion - - #region MatchAll - /// - /// A function that represents the EdgeQL version of: re_match_all(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringMatchAll))] - public static IEnumerable MatchAll(string? pattern, string? input) { return default!; } - #endregion - - #region Replace - /// - /// A function that represents the EdgeQL version of: re_replace(, , , <flags := {3?}>) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringReplace))] - public static string? Replace(string? pattern, string? substitute, string? input, string? flags) { return default!; } - #endregion - - #region IsMatch - /// - /// A function that represents the EdgeQL version of: re_test(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.StringIsMatch))] - public static bool IsMatch(string? pattern, string? input) { return default!; } - #endregion - - #endregion string - - #region boolean - - #region Or - /// - /// A function that represents the EdgeQL version of: or - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BooleanOr))] - public static bool Or(bool a, bool b) { return default!; } - #endregion - - #region And - /// - /// A function that represents the EdgeQL version of: and - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BooleanAnd))] - public static bool And(bool a, bool b) { return default!; } - #endregion - - #region Not - /// - /// A function that represents the EdgeQL version of: not - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BooleanNot))] - public static bool Not(bool a) { return default!; } - #endregion - - #region All - /// - /// A function that represents the EdgeQL version of: all() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BooleanAll))] - public static bool All(IEnumerable a) { return default!; } - #endregion - - #region Any - /// - /// A function that represents the EdgeQL version of: any() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BooleanAny))] - public static bool Any(IEnumerable a) { return default!; } - #endregion - - #endregion boolean - - #region numbers - - #region Add - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersAdd))] - public static long Add(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersAdd))] - public static short Add(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersAdd))] - public static int Add(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersAdd))] - public static double Add(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersAdd))] - public static float Add(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersAdd))] - public static decimal Add(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersAdd))] - public static byte Add(byte a, byte b) { return default!; } - #endregion - - #region Subtract - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSubtract))] - public static long Subtract(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSubtract))] - public static short Subtract(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSubtract))] - public static int Subtract(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSubtract))] - public static double Subtract(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSubtract))] - public static float Subtract(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSubtract))] - public static decimal Subtract(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSubtract))] - public static byte Subtract(byte a, byte b) { return default!; } - #endregion - - #region Negative - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersNegative))] - public static long Negative(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersNegative))] - public static short Negative(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersNegative))] - public static int Negative(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersNegative))] - public static double Negative(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersNegative))] - public static float Negative(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersNegative))] - public static decimal Negative(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersNegative))] - public static byte Negative(byte a, byte b) { return default!; } - #endregion - - #region Multiply - /// - /// A function that represents the EdgeQL version of: * - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersMultiply))] - public static long Multiply(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: * - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersMultiply))] - public static short Multiply(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: * - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersMultiply))] - public static int Multiply(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: * - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersMultiply))] - public static double Multiply(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: * - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersMultiply))] - public static float Multiply(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: * - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersMultiply))] - public static decimal Multiply(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: * - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersMultiply))] - public static byte Multiply(byte a, byte b) { return default!; } - #endregion - - #region Divide - /// - /// A function that represents the EdgeQL version of: / - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersDivide))] - public static long Divide(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: / - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersDivide))] - public static short Divide(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: / - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersDivide))] - public static int Divide(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: / - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersDivide))] - public static double Divide(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: / - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersDivide))] - public static float Divide(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: / - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersDivide))] - public static decimal Divide(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: / - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersDivide))] - public static byte Divide(byte a, byte b) { return default!; } - #endregion - - #region Floor - /// - /// A function that represents the EdgeQL version of: // - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersFloor))] - public static long Floor(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: // - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersFloor))] - public static short Floor(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: // - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersFloor))] - public static int Floor(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: // - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersFloor))] - public static double Floor(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: // - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersFloor))] - public static float Floor(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: // - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersFloor))] - public static decimal Floor(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: // - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersFloor))] - public static byte Floor(byte a, byte b) { return default!; } - #endregion - - #region Modulo - /// - /// A function that represents the EdgeQL version of: % - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersModulo))] - public static long Modulo(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: % - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersModulo))] - public static short Modulo(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: % - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersModulo))] - public static int Modulo(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: % - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersModulo))] - public static double Modulo(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: % - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersModulo))] - public static float Modulo(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: % - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersModulo))] - public static decimal Modulo(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: % - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersModulo))] - public static byte Modulo(byte a, byte b) { return default!; } - #endregion - - #region Power - /// - /// A function that represents the EdgeQL version of: ^ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersPower))] - public static long Power(long a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: ^ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersPower))] - public static short Power(short a, short b) { return default!; } - /// - /// A function that represents the EdgeQL version of: ^ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersPower))] - public static int Power(int a, int b) { return default!; } - /// - /// A function that represents the EdgeQL version of: ^ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersPower))] - public static double Power(double a, double b) { return default!; } - /// - /// A function that represents the EdgeQL version of: ^ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersPower))] - public static float Power(float a, float b) { return default!; } - /// - /// A function that represents the EdgeQL version of: ^ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersPower))] - public static decimal Power(decimal a, decimal b) { return default!; } - /// - /// A function that represents the EdgeQL version of: ^ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersPower))] - public static byte Power(byte a, byte b) { return default!; } - #endregion - - #region Sum - /// - /// A function that represents the EdgeQL version of: sum() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSum))] - public static long Sum(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: sum() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSum))] - public static long Sum(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: sum() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSum))] - public static decimal Sum(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: sum() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSum))] - public static float Sum(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: sum() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSum))] - public static double Sum(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: sum() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersSum))] - public static BigInteger Sum(IEnumerable a) { return default!; } - #endregion - - #region Round - /// - /// A function that represents the EdgeQL version of: round(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersRound))] - public static long Round(long a) { return default!; } - /// - /// A function that represents the EdgeQL version of: round(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersRound))] - public static long Round(double a) { return default!; } - /// - /// A function that represents the EdgeQL version of: round(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersRound))] - public static long Round(BigInteger a) { return default!; } - /// - /// A function that represents the EdgeQL version of: round(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersRound))] - public static long Round(decimal a) { return default!; } - /// - /// A function that represents the EdgeQL version of: round(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersRound))] - public static long Round(decimal a, long decimalPoint) { return default!; } - #endregion - - #region Random - /// - /// A function that represents the EdgeQL version of: random() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersRandom))] - public static double Random() { return default!; } - #endregion - - #region ToBigInteger - /// - /// A function that represents the EdgeQL version of: to_bigint(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToBigInteger))] - public static BigInteger ToBigInteger(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_bigint(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToBigInteger))] - public static BigInteger ToBigInteger(string? a, string? format) { return default!; } - #endregion - - #region ToDecimal - /// - /// A function that represents the EdgeQL version of: to_decimal(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToDecimal))] - public static decimal ToDecimal(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_decimal(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToDecimal))] - public static decimal ToDecimal(string? a, string? format) { return default!; } - #endregion - - #region ToShort - /// - /// A function that represents the EdgeQL version of: to_int16(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToShort))] - public static short ToShort(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_int16(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToShort))] - public static short ToShort(string? a, string? format) { return default!; } - #endregion - - #region ToInt - /// - /// A function that represents the EdgeQL version of: to_int32(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToInt))] - public static int ToInt(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_int32(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToInt))] - public static int ToInt(string? a, string? format) { return default!; } - #endregion - - #region ToLong - /// - /// A function that represents the EdgeQL version of: to_int64(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToLong))] - public static long ToLong(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_int64(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToLong))] - public static long ToLong(string? a, string? format) { return default!; } - #endregion - - #region ToFloat - /// - /// A function that represents the EdgeQL version of: to_float32(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToFloat))] - public static float ToFloat(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_float32(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToFloat))] - public static float ToFloat(string? a, string? format) { return default!; } - #endregion - - #region ToDouble - /// - /// A function that represents the EdgeQL version of: to_float64(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToDouble))] - public static double ToDouble(string? a) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_float64(, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.NumbersToDouble))] - public static double ToDouble(string? a, string? format) { return default!; } - #endregion - - #endregion numbers - - #region json - - #region Index - /// - /// A function that represents the EdgeQL version of: [] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonIndex))] - public static Json Index(Json a, long index) { return default!; } - #endregion - - #region Slice - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonSlice))] - public static Json Slice(Json a, long b) { return default!; } - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonSlice))] - public static Json Slice(Json a, long b, long c) { return default!; } - #endregion - - #region Concat - /// - /// A function that represents the EdgeQL version of: ++ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonConcat))] - public static Json Concat(Json a, Json b) { return default!; } - #endregion - - #region Index - /// - /// A function that represents the EdgeQL version of: [] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonIndex))] - public static Json Index(Json a, string? b) { return default!; } - #endregion - - #region ToJson - /// - /// A function that represents the EdgeQL version of: to_json() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonToJson))] - public static Json ToJson(string? a) { return default!; } - #endregion - - #region UnpackJsonArray - /// - /// A function that represents the EdgeQL version of: json_array_unpack() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonUnpackJsonArray))] - public static IEnumerable UnpackJsonArray(Json a) { return default!; } - #endregion - - #region JsonGet - /// - /// A function that represents the EdgeQL version of: json_get(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonJsonGet))] - public static Json? JsonGet(Json a, params string[] path) { return default!; } - #endregion - - #region UnpackJsonObject - /// - /// A function that represents the EdgeQL version of: json_object_unpack() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonUnpackJsonObject))] - public static IEnumerable> UnpackJsonObject(Json a) { return default!; } - #endregion - - #region JsonTypeof - /// - /// A function that represents the EdgeQL version of: json_typeof() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.JsonJsonTypeof))] - public static string? JsonTypeof(Json a) { return default!; } - #endregion - - #endregion json - - #region uuid - - #region GenerateGuid - /// - /// A function that represents the EdgeQL version of: uuid_generate_v1mc() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.UuidGenerateGuid))] - public static Guid GenerateGuid() { return default!; } - #endregion - - #endregion uuid - - #region temporal - - #region Add - /// - /// A function that represents the EdgeQL version of: + - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalAdd))] - public static DateTimeOffset Add(DateTimeOffset a, TimeSpan b) { return default!; } - #endregion - - #region Subtract - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalSubtract))] - public static TimeSpan Subtract(TimeSpan a, TimeSpan b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalSubtract))] - public static DateTimeOffset Subtract(DateTimeOffset a, TimeSpan b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalSubtract))] - public static DateTimeOffset Subtract(DateTimeOffset a, DateTimeOffset b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalSubtract))] - public static DateTime Subtract(DateTime a, TimeSpan b) { return default!; } - /// - /// A function that represents the EdgeQL version of: - - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalSubtract))] - public static DateTimeOffset Subtract(DateTime a, DateTime b) { return default!; } - #endregion - - #region GetCurrentDateTime - /// - /// A function that represents the EdgeQL version of: std::datetime_current() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalGetCurrentDateTime))] - public static DateTimeOffset GetCurrentDateTime() { return default!; } - #endregion - - #region GetTransactionDateTime - /// - /// A function that represents the EdgeQL version of: std::datetime_of_transaction() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalGetTransactionDateTime))] - public static DateTimeOffset GetTransactionDateTime() { return default!; } - #endregion - - #region GetStatementDateTime - /// - /// A function that represents the EdgeQL version of: std::datetime_of_statement() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalGetStatementDateTime))] - public static DateTimeOffset GetStatementDateTime() { return default!; } - #endregion - - #region GetDatetimeElement - /// - /// A function that represents the EdgeQL version of: datetime_get(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalGetDatetimeElement))] - public static double GetDatetimeElement(DateTimeOffset a, DateTimeElement b) { return default!; } - #endregion - - #region GetTimespanElement - /// - /// A function that represents the EdgeQL version of: cal::time_get(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalGetTimespanElement))] - public static double GetTimespanElement(TimeSpan a, TimeSpanElement b) { return default!; } - #endregion - - #region GetLocalDateElement - /// - /// A function that represents the EdgeQL version of: cal::date_get(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalGetLocalDateElement))] - public static double GetLocalDateElement(DateTime a, LocalDateElement b) { return default!; } - #endregion - - #region TruncateDateTimeOffset - /// - /// A function that represents the EdgeQL version of: datetime_truncate(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalTruncateDateTimeOffset))] - public static DateTimeOffset TruncateDateTimeOffset(DateTimeOffset a, DateTimeTruncateUnit b) { return default!; } - #endregion - - #region TruncateTimeSpan - /// - /// A function that represents the EdgeQL version of: duration_truncate(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalTruncateTimeSpan))] - public static TimeSpan TruncateTimeSpan(TimeSpan a, DurationTruncateUnit b) { return default!; } - #endregion - - #region ToDateTimeOffset - /// - /// A function that represents the EdgeQL version of: to_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}, {6?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTimeOffset))] - public static DateTimeOffset ToDateTimeOffset(string? a, string? format) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}, {6?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTimeOffset))] - public static DateTimeOffset ToDateTimeOffset(DateTime a, string? timezone) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}, {6?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTimeOffset))] - public static DateTimeOffset ToDateTimeOffset(long year, long month, long day, long hour, long min, long sec, string? timezone) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}, {6?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTimeOffset))] - public static DateTimeOffset ToDateTimeOffset(decimal unixSeconds) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}, {6?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTimeOffset))] - public static DateTimeOffset ToDateTimeOffset(double unixSeconds) { return default!; } - /// - /// A function that represents the EdgeQL version of: to_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}, {6?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTimeOffset))] - public static DateTimeOffset ToDateTimeOffset(long unixSeconds) { return default!; } - #endregion - - #region ToDateTime - /// - /// A function that represents the EdgeQL version of: cal::to_local_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTime))] - public static DateTime ToDateTime(string? a, string? format) { return default!; } - /// - /// A function that represents the EdgeQL version of: cal::to_local_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTime))] - public static DateTime ToDateTime(DateTimeOffset a, string? timezone) { return default!; } - /// - /// A function that represents the EdgeQL version of: cal::to_local_datetime(, {1?}, {2?}, {3?}, {4?}, {5?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToDateTime))] - public static DateTime ToDateTime(long year, long month, long day, long hour, long min, long sec) { return default!; } - #endregion - - #region ToLocalDate - /// - /// A function that represents the EdgeQL version of: cal::to_local_date(, {1?}, {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToLocalDate))] - public static DateTime ToLocalDate(string? a, string? format) { return default!; } - /// - /// A function that represents the EdgeQL version of: cal::to_local_date(, {1?}, {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToLocalDate))] - public static DateTime ToLocalDate(DateTimeOffset a, string? timezone) { return default!; } - /// - /// A function that represents the EdgeQL version of: cal::to_local_date(, {1?}, {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToLocalDate))] - public static DateTime ToLocalDate(long year, long month, long day) { return default!; } - #endregion - - #region ToLocalTime - /// - /// A function that represents the EdgeQL version of: cal::to_local_time(, {1?}, {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToLocalTime))] - public static TimeSpan ToLocalTime(string? a, string? format) { return default!; } - /// - /// A function that represents the EdgeQL version of: cal::to_local_time(, {1?}, {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToLocalTime))] - public static TimeSpan ToLocalTime(DateTimeOffset a, string? timezone) { return default!; } - /// - /// A function that represents the EdgeQL version of: cal::to_local_time(, {1?}, {2?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToLocalTime))] - public static TimeSpan ToLocalTime(long hour, long minute, double second) { return default!; } - #endregion - - #region ToTimeSpan - /// - /// A function that represents the EdgeQL version of: to_duration(<hours := {0?}>, <minutes := {1?}>, <seconds := {2?}> <microseconds := {3?}>) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToTimeSpan))] - public static TimeSpan ToTimeSpan(long? hours = null, long? minutes = null, double? seconds = null, double? microseconds = null) { return default!; } - #endregion - - #region TimeSpanToSeconds - /// - /// A function that represents the EdgeQL version of: std::duration_to_seconds() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalTimeSpanToSeconds))] - public static decimal TimeSpanToSeconds(TimeSpan a) { return default!; } - #endregion - - #region ToRelativeDuration - /// - /// A function that represents the EdgeQL version of: cal::to_relative_duration(<years := {0?}>, <months := {1?}>, <days := {2?}>, <hours := {3?}>, <minutes := {4?}>, <seconds := {5?}>, <microseconds := {6?}>) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TemporalToRelativeDuration))] - public static TimeSpan ToRelativeDuration(long? years = null, long? months = null, long? days = null, long? hours = null, long? minutes = null, long? seconds = null, long? microseconds = null) { return default!; } - #endregion - - #endregion temporal - - #region bytes - - #region Index - /// - /// A function that represents the EdgeQL version of: [] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BytesIndex))] - public static byte[] Index(byte[] a, long index) { return default!; } - #endregion - - #region Slice - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BytesSlice))] - public static byte[] Slice(byte[] a, long startIndex) { return default!; } - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BytesSlice))] - public static byte[] Slice(byte[] a, long startIndex, long endIndex) { return default!; } - #endregion - - #region Concat - /// - /// A function that represents the EdgeQL version of: ++ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BytesConcat))] - public static byte[] Concat(byte[] a, byte[] b) { return default!; } - #endregion - - #region GetBit - /// - /// A function that represents the EdgeQL version of: bytes_get_bit(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.BytesGetBit))] - public static long GetBit(byte[] a, long bitIndex) { return default!; } - #endregion - - #endregion bytes - - #region sequence - - #region IncrementSequence - /// - /// A function that represents the EdgeQL version of: sequence_next(<introspect typeof >) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SequenceIncrementSequence))] - public static long IncrementSequence(long seq) { return default!; } - #endregion - - #region ResetSequence - /// - /// A function that represents the EdgeQL version of: sequence_reset(<introspect typeof >, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SequenceResetSequence))] - public static long ResetSequence(long seq) { return default!; } - /// - /// A function that represents the EdgeQL version of: sequence_reset(<introspect typeof >, {1?}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SequenceResetSequence))] - public static long ResetSequence(long seq, long resetTo) { return default!; } - #endregion - - #endregion sequence - - #region array - - #region Index - /// - /// A function that represents the EdgeQL version of: [] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArrayIndex))] - public static TType Index(IEnumerable a, long index) { return default!; } - #endregion - - #region Slice - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArraySlice))] - public static IEnumerable Slice(IEnumerable a, long startIndex) { return default!; } - /// - /// A function that represents the EdgeQL version of: [:{2?}] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArraySlice))] - public static IEnumerable Slice(IEnumerable a, long startIndex, long endIndex) { return default!; } - #endregion - - #region Concat - /// - /// A function that represents the EdgeQL version of: ++ - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArrayConcat))] - public static IEnumerable Concat(IEnumerable a, IEnumerable b) { return default!; } - #endregion - - #region Aggregate - /// - /// A function that represents the EdgeQL version of: array_agg() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArrayAggregate))] - public static IEnumerable Aggregate(IEnumerable a) { return default!; } - #endregion - - #region IndexOrDefault - /// - /// A function that represents the EdgeQL version of: array_get(, , <default := {2?}>) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArrayIndexOrDefault))] - public static TType? IndexOrDefault(IEnumerable a, long index, TType? defaultValue = default) { return default!; } - #endregion - - #region UnpackArray - /// - /// A function that represents the EdgeQL version of: array_unpack() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArrayUnpackArray))] - public static IEnumerable UnpackArray(IEnumerable a) { return default!; } - #endregion - - #region Join - /// - /// A function that represents the EdgeQL version of: array_join(, ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.ArrayJoin))] - public static string? Join(IEnumerable a, string? delimiter) { return default!; } - #endregion - - #endregion array - - #region sets - - #region Distinct - /// - /// A function that represents the EdgeQL version of: distinct - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsDistinct))] - public static IEnumerable Distinct(IEnumerable a) { return default!; } - #endregion - - #region Contains - /// - /// A function that represents the EdgeQL version of: in - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsContains))] - public static bool Contains(IEnumerable a, TType element) { return default!; } - #endregion - - #region Union - /// - /// A function that represents the EdgeQL version of: union - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsUnion))] - public static IEnumerable Union(IEnumerable a, IEnumerable b) { return default!; } - #endregion - - #region Conditional - /// - /// A function that represents the EdgeQL version of: if else - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsConditional))] - public static TType Conditional(bool condition, TType trueReturn, TType falseReturn) { return default!; } - #endregion - - #region Coalesce - /// - /// A function that represents the EdgeQL version of: ?? - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsCoalesce))] - public static TType Coalesce(TType? a, TType b) { return default!; } - #endregion - - #region Detached - /// - /// A function that represents the EdgeQL version of: detached - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsDetached))] - public static TType Detached(TType a) { return default!; } - #endregion - - #region NotNull - /// - /// A function that represents the EdgeQL version of: exists - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsNotNull))] - public static bool NotNull(TType value) { return default!; } - #endregion - - #region CastIfTypeIs - /// - /// A function that represents the EdgeQL version of: [is ] - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsCastIfTypeIs))] - [ParameterMap(1, "TDesired")] - public static TDesired CastIfTypeIs(object? a) { return default!; } - #endregion - - #region AssertDistinct - /// - /// A function that represents the EdgeQL version of: assert_distinct() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsAssertDistinct))] - public static IEnumerable AssertDistinct(IEnumerable a) { return default!; } - #endregion - - #region AssertSingle - /// - /// A function that represents the EdgeQL version of: assert_single() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsAssertSingle))] - public static TType AssertSingle(IEnumerable a) { return default!; } - #endregion - - #region AssertNotNull - /// - /// A function that represents the EdgeQL version of: assert_exists() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsAssertNotNull))] - public static TType AssertNotNull(TType? a) { return default!; } - #endregion - - #region Count - /// - /// A function that represents the EdgeQL version of: count() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsCount))] - public static long Count(IEnumerable a) { return default!; } - #endregion - - #region Enumerate - /// - /// A function that represents the EdgeQL version of: enumerate() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsEnumerate))] - public static IEnumerable> Enumerate(IEnumerable a) { return default!; } - #endregion - - #region Min - /// - /// A function that represents the EdgeQL version of: min() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsMin))] - public static TType Min(IEnumerable a) { return default!; } - #endregion - - #region Max - /// - /// A function that represents the EdgeQL version of: max() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.SetsMax))] - public static TType Max(IEnumerable a) { return default!; } - #endregion - - #endregion sets - - #region types - - #region Is - /// - /// A function that represents the EdgeQL version of: is - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesIs))] - [ParameterMap(1, "TType")] - public static bool Is(object? a) { return default!; } - #endregion - - #region Is - /// - /// A function that represents the EdgeQL version of: is - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesIs))] - public static bool Is(object? a, Type b) { return default!; } - #endregion - - #region IsNot - /// - /// A function that represents the EdgeQL version of: is not - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesIsNot))] - [ParameterMap(1, "TType")] - public static bool IsNot(object? a) { return default!; } - #endregion - - #region TypeUnion - /// - /// A function that represents the EdgeQL version of: ( | { | :2+}) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesTypeUnion))] - public static Type TypeUnion(Type a, Type b, params Type[] additional) { return default!; } - #endregion - - #region Cast - /// - /// A function that represents the EdgeQL version of: <> - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesCast))] - [ParameterMap(0, "TType")] - public static TType Cast(object? a) { return default!; } - #endregion - - #region GetType - /// - /// A function that represents the EdgeQL version of: introspect (typeof ) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesGetType))] - public static Type GetType(object? a) { return default!; } - #endregion - - #region IsTypeOf - /// - /// A function that represents the EdgeQL version of: is typeof - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesIsTypeOf))] - public static bool IsTypeOf(object? a, object? b) { return default!; } - #endregion - - #region IsNotTypeOf - /// - /// A function that represents the EdgeQL version of: is not typeof - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesIsNotTypeOf))] - public static bool IsNotTypeOf(object? a, object? b) { return default!; } - #endregion - - #region Introspect - /// - /// A function that represents the EdgeQL version of: introspect - /// - [EquivalentOperator(typeof(EdgeDB.Operators.TypesIntrospect))] - public static Type Introspect(Type a) { return default!; } - #endregion - - #endregion types - - #region math - - #region Abs - /// - /// A function that represents the EdgeQL version of: math::abs() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathAbs))] - public static short Abs(short a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::abs() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathAbs))] - public static int Abs(int a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::abs() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathAbs))] - public static long Abs(long a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::abs() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathAbs))] - public static float Abs(float a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::abs() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathAbs))] - public static double Abs(double a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::abs() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathAbs))] - public static decimal Abs(decimal a) { return default!; } - #endregion - - #region Ceil - /// - /// A function that represents the EdgeQL version of: math::ceil() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathCeil))] - public static double Ceil(long a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::ceil() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathCeil))] - public static double Ceil(double a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::ceil() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathCeil))] - public static BigInteger Ceil(BigInteger a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::ceil() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathCeil))] - public static decimal Ceil(decimal a) { return default!; } - #endregion - - #region Floor - /// - /// A function that represents the EdgeQL version of: math::floor() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathFloor))] - public static double Floor(long a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::floor() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathFloor))] - public static double Floor(double a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::floor() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathFloor))] - public static BigInteger Floor(BigInteger a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::floor() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathFloor))] - public static decimal Floor(decimal a) { return default!; } - #endregion - - #region NaturalLog - /// - /// A function that represents the EdgeQL version of: math::ln() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathNaturalLog))] - public static double NaturalLog(long a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::ln() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathNaturalLog))] - public static double NaturalLog(double a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::ln() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathNaturalLog))] - public static decimal NaturalLog(decimal a) { return default!; } - #endregion - - #region Logarithm - /// - /// A function that represents the EdgeQL version of: math::lg() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathLogarithm))] - public static double Logarithm(long a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::lg() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathLogarithm))] - public static double Logarithm(double a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::lg() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathLogarithm))] - public static decimal Logarithm(decimal a) { return default!; } - #endregion - - #region Logarithm - /// - /// A function that represents the EdgeQL version of: math::log( <base := >) - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathLogarithm))] - public static decimal Logarithm(decimal a, decimal numericBase) { return default!; } - #endregion - - #region Mean - /// - /// A function that represents the EdgeQL version of: math::mean() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathMean))] - public static double Mean(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::mean() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathMean))] - public static double Mean(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::mean() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathMean))] - public static decimal Mean(IEnumerable a) { return default!; } - #endregion - - #region StandardDeviation - /// - /// A function that represents the EdgeQL version of: math::stddev() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathStandardDeviation))] - public static double StandardDeviation(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::stddev() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathStandardDeviation))] - public static double StandardDeviation(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::stddev() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathStandardDeviation))] - public static decimal StandardDeviation(IEnumerable a) { return default!; } - #endregion - - #region StandardDeviationPop - /// - /// A function that represents the EdgeQL version of: math::stddev_pop() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathStandardDeviationPop))] - public static double StandardDeviationPop(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::stddev_pop() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathStandardDeviationPop))] - public static double StandardDeviationPop(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::stddev_pop() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathStandardDeviationPop))] - public static decimal StandardDeviationPop(IEnumerable a) { return default!; } - #endregion - - #region Variance - /// - /// A function that represents the EdgeQL version of: math::var() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathVariance))] - public static double Variance(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::var() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathVariance))] - public static double Variance(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::var() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathVariance))] - public static decimal Variance(IEnumerable a) { return default!; } - #endregion - - #region VariancePop - /// - /// A function that represents the EdgeQL version of: math::var_pop() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathVariancePop))] - public static double VariancePop(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::var_pop() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathVariancePop))] - public static double VariancePop(IEnumerable a) { return default!; } - /// - /// A function that represents the EdgeQL version of: math::var_pop() - /// - [EquivalentOperator(typeof(EdgeDB.Operators.MathVariancePop))] - public static decimal VariancePop(IEnumerable a) { return default!; } - #endregion - - #endregion math - - #region links - - #region AddLink - /// - /// A function that represents the EdgeQL version of: += - /// - [EquivalentOperator(typeof(EdgeDB.Operators.LinksAddLink))] - public static TSource AddLink(TSource source, TType element) where TSource : IEnumerable? { return default!; } - #endregion - - #region RemoveLink - /// - /// A function that represents the EdgeQL version of: -= - /// - [EquivalentOperator(typeof(EdgeDB.Operators.LinksRemoveLink))] - public static TSource RemoveLink(TSource source, TType element) where TSource : IEnumerable? { return default!; } - #endregion - - #endregion links - - #region variables - - #endregion variables - - internal static Dictionary FunctionOperators = new() - { - { "String.ToLower", new StringToLower()}, - { "String.ToUpper", new StringToUpper()}, - { "Enumerable.Concat", new SetsUnion()}, - } -; - } -} -#nullable restore -#pragma warning restore diff --git a/src/EdgeDB.Net.QueryBuilder/Exceptions/InvalidQueryOperationException.cs b/src/EdgeDB.Net.QueryBuilder/Exceptions/InvalidQueryOperationException.cs deleted file mode 100644 index 7babf0d7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Exceptions/InvalidQueryOperationException.cs +++ /dev/null @@ -1,26 +0,0 @@ -namespace EdgeDB -{ - /// - /// Thrown when the current method would result in a invalid query being constructed - /// - public class InvalidQueryOperationException : Exception - { - public IReadOnlyCollection ExpressionValidAfter { get; } - public QueryExpressionType Expression { get; } - - public InvalidQueryOperationException(QueryExpressionType expression, string message) - : base(message) - { - Expression = expression; - ExpressionValidAfter = Array.Empty(); - } - - public InvalidQueryOperationException(QueryExpressionType expression, QueryExpressionType[] validAfter) - : base($"Expression {expression} is only valid after {string.Join(", ", validAfter)}") - { - Expression = expression; - ExpressionValidAfter = validAfter; - } - - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Extensions/EdgeDBClientExtensions.cs b/src/EdgeDB.Net.QueryBuilder/Extensions/EdgeDBClientExtensions.cs deleted file mode 100644 index b7a56970..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Extensions/EdgeDBClientExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -using EdgeDB.Models; -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Linq.Expressions; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - public static class EdgeDBClientExtensions - { - //public static Task QueryAsync(this EdgeDBClient client, BuiltQuery query, Cardinality? card = null) - // => client.QueryAsync(query.QueryText, query.Parameters.ToDictionary(x => x.Key, x => x.Value), card); - - //public static Task QueryAsync(this EdgeDBClient client, BuiltQuery query, Cardinality? card = null) - // => client.QueryAsync(query.QueryText, query.Parameters.ToDictionary(x => x.Key, x => x.Value), card); - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Extensions/MemberInfoExtensions.cs b/src/EdgeDB.Net.QueryBuilder/Extensions/MemberInfoExtensions.cs deleted file mode 100644 index 948f1bac..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Extensions/MemberInfoExtensions.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace EdgeDB -{ - internal static class MemberInfoExtensions - { - public static Type? GetMemberType(this MemberInfo info) - { - switch (info.MemberType) - { - case MemberTypes.Field: - return ((FieldInfo)info).FieldType; - case MemberTypes.Property: - return ((PropertyInfo)info).PropertyType; - } - - return null; - } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Aggregate.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Array/Aggregate.g.cs deleted file mode 100644 index 70b6c3ca..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Aggregate.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class ArrayAggregate : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "array_agg({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Concat.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Array/Concat.g.cs deleted file mode 100644 index 180f53d2..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Concat.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class ArrayConcat : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} ++ {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Index.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Array/Index.g.cs deleted file mode 100644 index 800f36f2..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Index.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class ArrayIndex : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Index; - public string EdgeQLOperator => "{0}[{1}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Array/IndexOrDefault.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Array/IndexOrDefault.g.cs deleted file mode 100644 index 202ba760..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Array/IndexOrDefault.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class ArrayIndexOrDefault : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "array_get({0}, {1}, )"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Join.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Array/Join.g.cs deleted file mode 100644 index f7463849..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Join.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class ArrayJoin : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "array_join({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Slice.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Array/Slice.g.cs deleted file mode 100644 index 9db43160..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Array/Slice.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class ArraySlice : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0}[{1}:{2?}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Array/UnpackArray.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Array/UnpackArray.g.cs deleted file mode 100644 index cf5cd877..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Array/UnpackArray.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class ArrayUnpackArray : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "array_unpack({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/All.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/All.g.cs deleted file mode 100644 index d4d9752c..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/All.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BooleanAll : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "all({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/And.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/And.g.cs deleted file mode 100644 index 0090af83..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/And.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BooleanAnd : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.And; - public string EdgeQLOperator => "{0} and {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Any.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Any.g.cs deleted file mode 100644 index c61f301d..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Any.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BooleanAny : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "any({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Not.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Not.g.cs deleted file mode 100644 index 3ac2044a..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Not.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BooleanNot : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Not; - public string EdgeQLOperator => "not {0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Or.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Or.g.cs deleted file mode 100644 index 7d4fe429..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Boolean/Or.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BooleanOr : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Or; - public string EdgeQLOperator => "{0} or {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Concat.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Concat.g.cs deleted file mode 100644 index b4d81513..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Concat.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BytesConcat : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} ++ {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/GetBit.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/GetBit.g.cs deleted file mode 100644 index 014c22f1..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/GetBit.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BytesGetBit : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "bytes_get_bit({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Index.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Index.g.cs deleted file mode 100644 index 24b92805..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Index.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BytesIndex : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Index; - public string EdgeQLOperator => "{0}[{1}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Slice.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Slice.g.cs deleted file mode 100644 index 22c81c13..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Bytes/Slice.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class BytesSlice : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0}[{1}:{2?}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DateTimeElement.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DateTimeElement.g.cs deleted file mode 100644 index d7b927de..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DateTimeElement.g.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace EdgeDB -{ - [EnumSerializerAttribute(SerializationMethod.Lower)] - public enum DateTimeElement - { - EpochSeconds, - Century, - Day, - Decade, - Dow, - Doy, - Hour, - ISODow, - ISOYear, - Microseconds, - Millennium, - Milliseconds, - Minutes, - Month, - Quarter, - Seconds, - Week, - Year - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DateTimeTruncateUnit.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DateTimeTruncateUnit.g.cs deleted file mode 100644 index 90b2004e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DateTimeTruncateUnit.g.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace EdgeDB -{ - [EnumSerializerAttribute(SerializationMethod.Lower)] - public enum DateTimeTruncateUnit - { - Microseconds, - Milliseconds, - seconds, - minutes, - hours, - days, - weeks, - months, - quarters, - years, - decades, - centuries - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DurationTruncateUnit.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DurationTruncateUnit.g.cs deleted file mode 100644 index f84e28f7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/DurationTruncateUnit.g.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace EdgeDB -{ - [EnumSerializerAttribute(SerializationMethod.Lower)] - public enum DurationTruncateUnit - { - Microseconds, - Milliseconds, - Seconds, - Minutes, - Hours - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/LocalDateElement.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Enums/LocalDateElement.g.cs deleted file mode 100644 index d12dd2bc..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/LocalDateElement.g.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace EdgeDB -{ - [EnumSerializerAttribute(SerializationMethod.Lower)] - public enum LocalDateElement - { - Century, - Day, - Decade, - Dow, - Doy, - ISODow, - ISOYear, - Millennium, - Month, - Quarter, - Week, - Year - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/TimeSpanElement.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Enums/TimeSpanElement.g.cs deleted file mode 100644 index b649c46c..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Enums/TimeSpanElement.g.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace EdgeDB -{ - [EnumSerializerAttribute(SerializationMethod.Lower)] - public enum TimeSpanElement - { - MidnightSeconds, - Hour, - Microseconds, - Milliseconds, - Minutes, - Seconds - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/EquivilantOperator.cs b/src/EdgeDB.Net.QueryBuilder/Operators/EquivilantOperator.cs deleted file mode 100644 index 94da7a94..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/EquivilantOperator.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace EdgeDB.Operators -{ - [AttributeUsage(AttributeTargets.Method)] - internal class EquivalentOperator : Attribute - { - public readonly IEdgeQLOperator Operator; - - public EquivalentOperator(Type operatorType) - { - if (!operatorType.GetInterfaces().Contains(typeof(IEdgeQLOperator))) - throw new ArgumentException($"Cannot use {operatorType} as a equivalent operator because it doesn't implement the IEdgeQLOperator interface"); - - Operator = (IEdgeQLOperator)Activator.CreateInstance(operatorType)!; - } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Contains.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Contains.g.cs deleted file mode 100644 index 63e62a30..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Contains.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericContains : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "contains({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Equals.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Equals.g.cs deleted file mode 100644 index 398b4f4c..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Equals.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericEquals : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Equal; - public string EdgeQLOperator => "{0} ?= {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Find.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Find.g.cs deleted file mode 100644 index 86491372..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Find.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericFind : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "find({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/GreaterThan.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/GreaterThan.g.cs deleted file mode 100644 index 70e329f9..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/GreaterThan.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericGreaterThan : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.GreaterThan; - public string EdgeQLOperator => "{0} > {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/GreaterThanOrEqual.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/GreaterThanOrEqual.g.cs deleted file mode 100644 index 00948237..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/GreaterThanOrEqual.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericGreaterThanOrEqual : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.GreaterThanOrEqual; - public string EdgeQLOperator => "{0} >= {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Length.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Length.g.cs deleted file mode 100644 index 9d850c60..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/Length.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericLength : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "len({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/LessThan.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/LessThan.g.cs deleted file mode 100644 index 01a8662e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/LessThan.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericLessThan : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.LessThan; - public string EdgeQLOperator => "{0} < {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/LessThanOrEqual.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/LessThanOrEqual.g.cs deleted file mode 100644 index 85f029d6..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/LessThanOrEqual.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericLessThanOrEqual : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.LessThanOrEqual; - public string EdgeQLOperator => "{0} <= {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/NotEqual.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Generic/NotEqual.g.cs deleted file mode 100644 index bd2c4dd7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Generic/NotEqual.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class GenericNotEqual : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.NotEqual; - public string EdgeQLOperator => "{0} ?!= {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/IEdgeQLOperator.cs b/src/EdgeDB.Net.QueryBuilder/Operators/IEdgeQLOperator.cs deleted file mode 100644 index 16baff97..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/IEdgeQLOperator.cs +++ /dev/null @@ -1,98 +0,0 @@ -using System.Linq.Expressions; -using System.Text.RegularExpressions; - -namespace EdgeDB.Operators -{ - public interface IEdgeQLOperator - { - ExpressionType? ExpressionType { get; } - string EdgeQLOperator { get; } - - string Build(params object[] args) - { - if (Regex.IsMatch(EdgeQLOperator, @".+?\(.*?\)")) - { - // extract arguments - return Regex.Replace(EdgeQLOperator, @"\((.*?)\)", (rootMatch) => - { - var param = string.Join(", ", Regex.Matches(rootMatch.Groups[1].Value, @"<(.*?{(\d|\d\?)+?})>|{(\d|\d\?)+?}").Select(m => - { - if (!m.Groups[1].Success) - { - // value is 3rd group - - if (int.TryParse(m.Groups[3].Value, out var i)) - return $"{args[i]}"; - - if (Regex.IsMatch(m.Groups[3].Value, @"\d\?")) - { - i = int.Parse(Regex.Match(m.Groups[3].Value, @"(\d+)").Groups[1].Value); - - return args.Length > i ? $"{args[i]}" : null; - } - - return null; - } - else - { - // should be group1 {group2} - var name = m.Groups[1].Value; - - // extract the {} param - -#pragma warning disable CS8603 // Possible null reference return. - return Regex.Replace(name, @"{(\d|\d\?|.+?:\d+?\+)+?}", x => - { - if (int.TryParse(x.Groups[1].Value, out var i)) - return $"{args[i]}"; - - if (Regex.IsMatch(x.Groups[1].Value, @"\d\?")) - { - i = int.Parse(Regex.Match(x.Groups[1].Value, @"(\d+)").Groups[1].Value); - - return args.Length > i ? $"{args[i]}" : null; - } - - if (Regex.IsMatch(m.Groups[1].Value, @".+?:\d+?\+")) - { - var split = m.Groups[1].Value.Split(":"); - var indexAfter = int.Parse(Regex.Match(split[1], @"(\d+)").Groups[1].Value); - return $"{(args.Length >= indexAfter ? split[0].Remove(0, 1) : "")}{string.Join(split[0], args.Skip(indexAfter))}"; - } - - return null; - }); -#pragma warning restore CS8603 // Possible null reference return. - - } - }).Where(x => x != null)); - return $"({param})"; - }); - } - else - { - return Regex.Replace(EdgeQLOperator, @"{(\d|\d\?|.+?:\d+?\+)+?}", (m) => - { - if (int.TryParse(m.Groups[1].Value, out var i)) - return $"{args[i]}"; - - if (Regex.IsMatch(m.Groups[1].Value, @"\d\?")) - { - i = int.Parse(Regex.Match(m.Groups[1].Value, @"(\d+)").Groups[1].Value); - - return args.Length < i ? $"{args[i]}" : ""; - } - - if (Regex.IsMatch(m.Groups[1].Value, @".+?:\d+?\+")) - { - var split = m.Groups[1].Value.Split(":"); - var indexAfter = int.Parse(Regex.Match(split[1], @"(\d+)").Groups[1].Value); - return $"{(args.Length >= indexAfter ? split[0].Remove(0, 1) : "")}{string.Join(split[0], args.Skip(indexAfter))}"; - } - - return ""; - }); - } - } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/Concat.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/Concat.g.cs deleted file mode 100644 index a1ec56bf..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/Concat.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonConcat : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} ++ {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/Index.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/Index.g.cs deleted file mode 100644 index 1ed0be7c..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/Index.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonIndex : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0}[{1}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/JsonGet.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/JsonGet.g.cs deleted file mode 100644 index d9ddc74b..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/JsonGet.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonJsonGet : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "json_get({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/JsonTypeof.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/JsonTypeof.g.cs deleted file mode 100644 index 46a6cd62..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/JsonTypeof.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonJsonTypeof : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "json_typeof({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/Slice.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/Slice.g.cs deleted file mode 100644 index 700b9f4c..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/Slice.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonSlice : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0}[{1}:{2?}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/ToJson.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/ToJson.g.cs deleted file mode 100644 index 6023fdbd..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/ToJson.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonToJson : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_json({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/UnpackJsonArray.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/UnpackJsonArray.g.cs deleted file mode 100644 index e42d3d81..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/UnpackJsonArray.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonUnpackJsonArray : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "json_array_unpack({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Json/UnpackJsonObject.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Json/UnpackJsonObject.g.cs deleted file mode 100644 index aedb3aee..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Json/UnpackJsonObject.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class JsonUnpackJsonObject : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "json_object_unpack({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Links/AddLink.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Links/AddLink.g.cs deleted file mode 100644 index df15bc4d..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Links/AddLink.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class LinksAddLink : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "+= {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Links/RemoveLink.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Links/RemoveLink.g.cs deleted file mode 100644 index 1c81b64f..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Links/RemoveLink.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class LinksRemoveLink : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "-= {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Abs.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/Abs.g.cs deleted file mode 100644 index d4c8ff33..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Abs.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathAbs : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::abs({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Ceil.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/Ceil.g.cs deleted file mode 100644 index ef091e83..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Ceil.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathCeil : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::ceil({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Floor.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/Floor.g.cs deleted file mode 100644 index 08a36120..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Floor.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathFloor : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::floor({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Logarithm.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/Logarithm.g.cs deleted file mode 100644 index 157f03ff..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Logarithm.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathLogarithm : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::log({0} )"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Mean.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/Mean.g.cs deleted file mode 100644 index 75759e17..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Mean.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathMean : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::mean({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/NaturalLog.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/NaturalLog.g.cs deleted file mode 100644 index 3699fb4e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/NaturalLog.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathNaturalLog : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::ln({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/StandardDeviation.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/StandardDeviation.g.cs deleted file mode 100644 index 12efaa03..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/StandardDeviation.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathStandardDeviation : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::stddev({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/StandardDeviationPop.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/StandardDeviationPop.g.cs deleted file mode 100644 index fcd0aeeb..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/StandardDeviationPop.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathStandardDeviationPop : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::stddev_pop({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Variance.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/Variance.g.cs deleted file mode 100644 index 1002e2b7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/Variance.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathVariance : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::var({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Math/VariancePop.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Math/VariancePop.g.cs deleted file mode 100644 index e9698312..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Math/VariancePop.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class MathVariancePop : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "math::var_pop({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Add.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Add.g.cs deleted file mode 100644 index cc650c50..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Add.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersAdd : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Add; - public string EdgeQLOperator => "{0} + {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Divide.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Divide.g.cs deleted file mode 100644 index 4bb9974f..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Divide.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersDivide : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Divide; - public string EdgeQLOperator => "{0} / {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Floor.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Floor.g.cs deleted file mode 100644 index b78374d7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Floor.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersFloor : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} // {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Modulo.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Modulo.g.cs deleted file mode 100644 index 3f1fd005..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Modulo.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersModulo : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Modulo; - public string EdgeQLOperator => "{0} % {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Multiply.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Multiply.g.cs deleted file mode 100644 index 7330c65f..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Multiply.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersMultiply : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Multiply; - public string EdgeQLOperator => "{0} * {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Negative.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Negative.g.cs deleted file mode 100644 index 1b786580..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Negative.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersNegative : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Negate; - public string EdgeQLOperator => "-{0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Power.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Power.g.cs deleted file mode 100644 index 3886fd86..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Power.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersPower : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} ^ {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Random.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Random.g.cs deleted file mode 100644 index 60687136..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Random.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersRandom : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "random()"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Round.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Round.g.cs deleted file mode 100644 index 36ebb835..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Round.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersRound : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "round({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Subtract.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Subtract.g.cs deleted file mode 100644 index fa2ded78..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Subtract.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersSubtract : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Subtract; - public string EdgeQLOperator => "{0} - {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Sum.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Sum.g.cs deleted file mode 100644 index fe96b8b9..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/Sum.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersSum : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "sum({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToBigInteger.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToBigInteger.g.cs deleted file mode 100644 index f7f163b7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToBigInteger.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersToBigInteger : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_bigint({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToDecimal.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToDecimal.g.cs deleted file mode 100644 index 5cd0ad1d..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToDecimal.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersToDecimal : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_decimal({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToDouble.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToDouble.g.cs deleted file mode 100644 index 20cbb85f..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToDouble.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersToDouble : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_float64({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToFloat.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToFloat.g.cs deleted file mode 100644 index 0e607d2e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToFloat.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersToFloat : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_float32({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToInt.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToInt.g.cs deleted file mode 100644 index 93943a67..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToInt.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersToInt : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_int32({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToLong.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToLong.g.cs deleted file mode 100644 index ab14c272..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToLong.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersToLong : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_int64({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToShort.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToShort.g.cs deleted file mode 100644 index 3cf7969f..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Numbers/ToShort.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class NumbersToShort : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_int16({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sequence/IncrementSequence.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sequence/IncrementSequence.g.cs deleted file mode 100644 index 9b31ffd3..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sequence/IncrementSequence.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SequenceIncrementSequence : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "sequence_next()"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sequence/ResetSequence.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sequence/ResetSequence.g.cs deleted file mode 100644 index f950f651..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sequence/ResetSequence.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SequenceResetSequence : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "sequence_reset(, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertDistinct.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertDistinct.g.cs deleted file mode 100644 index 3bcb5ed1..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertDistinct.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsAssertDistinct : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "assert_distinct({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertNotNull.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertNotNull.g.cs deleted file mode 100644 index 7cc12942..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertNotNull.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsAssertNotNull : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "assert_exists({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertSingle.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertSingle.g.cs deleted file mode 100644 index 7121d02e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/AssertSingle.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsAssertSingle : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "assert_single({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/CastIfTypeIs.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/CastIfTypeIs.g.cs deleted file mode 100644 index 9364a338..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/CastIfTypeIs.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsCastIfTypeIs : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.TypeIs; - public string EdgeQLOperator => "{0}[is {1}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Coalesce.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Coalesce.g.cs deleted file mode 100644 index 0e08568d..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Coalesce.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsCoalesce : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Coalesce; - public string EdgeQLOperator => "{0} ?? {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Conditional.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Conditional.g.cs deleted file mode 100644 index 31fef010..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Conditional.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsConditional : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Conditional; - public string EdgeQLOperator => "{1} if {0} else {2}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Contains.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Contains.g.cs deleted file mode 100644 index 34c8eb59..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Contains.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsContains : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{1} in {0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Count.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Count.g.cs deleted file mode 100644 index 612171e5..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Count.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsCount : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "count({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Detached.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Detached.g.cs deleted file mode 100644 index da259eb2..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Detached.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsDetached : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "detached {0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Distinct.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Distinct.g.cs deleted file mode 100644 index 262c14d6..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Distinct.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsDistinct : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "distinct {0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Enumerate.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Enumerate.g.cs deleted file mode 100644 index a403cdd6..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Enumerate.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsEnumerate : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "enumerate({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Max.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Max.g.cs deleted file mode 100644 index 1c9bfc10..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Max.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsMax : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "max({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Min.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Min.g.cs deleted file mode 100644 index 6d14dfea..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Min.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsMin : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "min({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/NotNull.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/NotNull.g.cs deleted file mode 100644 index dcb09a2e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/NotNull.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsNotNull : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "exists {0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Union.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Union.g.cs deleted file mode 100644 index 2b932b03..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Sets/Union.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class SetsUnion : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} union {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Concat.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Concat.g.cs deleted file mode 100644 index 4c19cc67..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Concat.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringConcat : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} ++ {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Contains.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Contains.g.cs deleted file mode 100644 index c8d61597..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Contains.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringContains : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "contains({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Find.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Find.g.cs deleted file mode 100644 index 88b95ead..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Find.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringFind : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "find({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/ILike.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/ILike.g.cs deleted file mode 100644 index 3c74fcfc..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/ILike.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringILike : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} ilike {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Index.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Index.g.cs deleted file mode 100644 index 52b4d69b..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Index.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringIndex : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Index; - public string EdgeQLOperator => "{0}[{1}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/IsMatch.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/IsMatch.g.cs deleted file mode 100644 index ec5dd31a..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/IsMatch.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringIsMatch : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "re_test({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Length.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Length.g.cs deleted file mode 100644 index 64f1d590..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Length.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringLength : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "len({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Like.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Like.g.cs deleted file mode 100644 index 8a8093d7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Like.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringLike : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} like {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Match.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Match.g.cs deleted file mode 100644 index 79e1e37b..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Match.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringMatch : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "re_match({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/MatchAll.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/MatchAll.g.cs deleted file mode 100644 index d4971cf9..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/MatchAll.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringMatchAll : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "re_match_all({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/PadLeft.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/PadLeft.g.cs deleted file mode 100644 index 66d5ddb7..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/PadLeft.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringPadLeft : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_pad_start({0}, {1}, {2?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/PadRight.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/PadRight.g.cs deleted file mode 100644 index 158165cd..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/PadRight.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringPadRight : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_pad_end({0}, {1}, {2?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Repeat.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Repeat.g.cs deleted file mode 100644 index 287dbe50..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Repeat.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringRepeat : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_repeat({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Replace.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Replace.g.cs deleted file mode 100644 index dc27d42e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Replace.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringReplace : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "re_replace({0}, {1}, {2}, )"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Slice.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Slice.g.cs deleted file mode 100644 index 31a4cab0..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Slice.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringSlice : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0}[{1}:{2?}]"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Split.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Split.g.cs deleted file mode 100644 index a7a13ffe..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Split.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringSplit : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_split({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToLower.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/ToLower.g.cs deleted file mode 100644 index fc6b4591..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToLower.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringToLower : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_lower({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToString.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/ToString.g.cs deleted file mode 100644 index 927f8014..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToString.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringToString : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_str({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToTitle.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/ToTitle.g.cs deleted file mode 100644 index 2e82f830..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToTitle.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringToTitle : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_title({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToUpper.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/ToUpper.g.cs deleted file mode 100644 index 47e71a65..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/ToUpper.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringToUpper : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_upper({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/Trim.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/Trim.g.cs deleted file mode 100644 index 7d7a4eba..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/Trim.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringTrim : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_trim({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/TrimEnd.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/TrimEnd.g.cs deleted file mode 100644 index c9923612..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/TrimEnd.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringTrimEnd : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_trim_end({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/String/TrimStart.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/String/TrimStart.g.cs deleted file mode 100644 index 52937c4a..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/String/TrimStart.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class StringTrimStart : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "str_trim_start({0}, {1?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/Add.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/Add.g.cs deleted file mode 100644 index f84e245e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/Add.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalAdd : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Add; - public string EdgeQLOperator => "{0} + {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetCurrentDateTime.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetCurrentDateTime.g.cs deleted file mode 100644 index 48e7594e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetCurrentDateTime.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalGetCurrentDateTime : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "std::datetime_current()"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetDatetimeElement.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetDatetimeElement.g.cs deleted file mode 100644 index 118b79c9..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetDatetimeElement.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalGetDatetimeElement : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "datetime_get({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetLocalDateElement.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetLocalDateElement.g.cs deleted file mode 100644 index 659c329c..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetLocalDateElement.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalGetLocalDateElement : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "cal::date_get({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetStatementDateTime.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetStatementDateTime.g.cs deleted file mode 100644 index be41a791..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetStatementDateTime.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalGetStatementDateTime : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "std::datetime_of_statement()"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetTimespanElement.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetTimespanElement.g.cs deleted file mode 100644 index 6c51d01d..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetTimespanElement.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalGetTimespanElement : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "cal::time_get({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetTransactionDateTime.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetTransactionDateTime.g.cs deleted file mode 100644 index ac9a9082..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/GetTransactionDateTime.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalGetTransactionDateTime : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "std::datetime_of_transaction()"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/Subtract.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/Subtract.g.cs deleted file mode 100644 index 348e90d6..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/Subtract.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalSubtract : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Subtract; - public string EdgeQLOperator => "{0} - {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TimeSpanToSeconds.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TimeSpanToSeconds.g.cs deleted file mode 100644 index f0dc4c9e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TimeSpanToSeconds.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalTimeSpanToSeconds : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "std::duration_to_seconds({0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToDateTime.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToDateTime.g.cs deleted file mode 100644 index 32564f84..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToDateTime.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalToDateTime : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "cal::to_local_datetime({0}, {1?}, {2?}, {3?}, {4?}, {5?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToDateTimeOffset.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToDateTimeOffset.g.cs deleted file mode 100644 index 710048bf..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToDateTimeOffset.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalToDateTimeOffset : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_datetime({0}, {1?}, {2?}, {3?}, {4?}, {5?}, {6?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToLocalDate.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToLocalDate.g.cs deleted file mode 100644 index 91e148dc..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToLocalDate.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalToLocalDate : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "cal::to_local_date({0}, {1?}, {2?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToLocalTime.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToLocalTime.g.cs deleted file mode 100644 index 46e33a9e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToLocalTime.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalToLocalTime : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "cal::to_local_time({0}, {1?}, {2?})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToRelativeDuration.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToRelativeDuration.g.cs deleted file mode 100644 index 95646a99..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToRelativeDuration.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalToRelativeDuration : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "cal::to_relative_duration(, , , , , , )"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToTimeSpan.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToTimeSpan.g.cs deleted file mode 100644 index 030cb639..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/ToTimeSpan.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalToTimeSpan : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "to_duration(, , )"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TruncateDateTimeOffset.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TruncateDateTimeOffset.g.cs deleted file mode 100644 index 45e662f3..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TruncateDateTimeOffset.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalTruncateDateTimeOffset : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "datetime_truncate({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TruncateTimeSpan.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TruncateTimeSpan.g.cs deleted file mode 100644 index 23d67cbe..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Temporal/TruncateTimeSpan.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TemporalTruncateTimeSpan : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "duration_truncate({0}, {1})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/Cast.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/Cast.g.cs deleted file mode 100644 index 3a425b08..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/Cast.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesCast : IEdgeQLOperator - { - public ExpressionType? ExpressionType => System.Linq.Expressions.ExpressionType.Convert; - public string EdgeQLOperator => "<{0}>{1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/GetType.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/GetType.g.cs deleted file mode 100644 index 38614f1e..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/GetType.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesGetType : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "introspect (typeof {0})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/Introspect.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/Introspect.g.cs deleted file mode 100644 index fe989ff2..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/Introspect.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesIntrospect : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "introspect {0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/Is.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/Is.g.cs deleted file mode 100644 index 3b7a8e9b..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/Is.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesIs : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} is {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsNot.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsNot.g.cs deleted file mode 100644 index fa377be5..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsNot.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesIsNot : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} is not {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsNotTypeOf.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsNotTypeOf.g.cs deleted file mode 100644 index bed02f6c..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsNotTypeOf.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesIsNotTypeOf : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} is not typeof {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsTypeOf.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsTypeOf.g.cs deleted file mode 100644 index 579cf747..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/IsTypeOf.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesIsTypeOf : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0} is typeof {1}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Types/TypeUnion.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Types/TypeUnion.g.cs deleted file mode 100644 index 61fdedd8..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Types/TypeUnion.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class TypesTypeUnion : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "({0} | {1} { | :2+})"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Uuid/GenerateGuid.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Uuid/GenerateGuid.g.cs deleted file mode 100644 index 8526c883..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Uuid/GenerateGuid.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class UuidGenerateGuid : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "uuid_generate_v1mc()"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/Operators/Variables/Reference.g.cs b/src/EdgeDB.Net.QueryBuilder/Operators/Variables/Reference.g.cs deleted file mode 100644 index 0512bf04..00000000 --- a/src/EdgeDB.Net.QueryBuilder/Operators/Variables/Reference.g.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Linq.Expressions; - -namespace EdgeDB.Operators -{ - internal class VariablesReference : IEdgeQLOperator - { - public ExpressionType? ExpressionType => null; - public string EdgeQLOperator => "{0}"; - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/QueryBuilder.Static.cs b/src/EdgeDB.Net.QueryBuilder/QueryBuilder.Static.cs deleted file mode 100644 index f99828d8..00000000 --- a/src/EdgeDB.Net.QueryBuilder/QueryBuilder.Static.cs +++ /dev/null @@ -1,917 +0,0 @@ -using EdgeDB.DataTypes; -using EdgeDB.Operators; -using System.Collections; -using System.Linq.Expressions; -using System.Reflection; -using System.Text.RegularExpressions; - -namespace EdgeDB -{ - public partial class QueryBuilder - { - private static readonly Dictionary _converters; - private static readonly Dictionary _operators = new(); - - private static readonly Dictionary _reservedPropertiesOperators = new() - { - { "String.Length", new StringLength() }, - }; - - private static readonly Dictionary _reservedFunctionOperators = new(EdgeQL.FunctionOperators) - { - { "ICollection.IndexOf", new GenericFind() }, - { "IEnumerable.IndexOf", new GenericFind() }, - - { "ICollection.Contains", new GenericContains() }, - { "IEnumerable.Contains", new GenericContains() }, - - { "String.get_Chars", new StringIndex() }, - { "Sring.Substring", new StringSlice() }, - }; - - private static readonly Dictionary> _reservedSubQueryFunctions = new() - { - { - "IEnumerable.OrderBy", - (ctx, source, param) => - { - var sourceElement = ConvertExpression(source!, ctx); - return new QueryBuilder(); - } - } - }; - - static QueryBuilder() - { - var types = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.GetInterfaces().Contains(typeof(IEdgeQLOperator))); - - var converters = new Dictionary(); - - foreach (var type in types) - { - var inst = (IEdgeQLOperator)Activator.CreateInstance(type)!; - - if (inst.ExpressionType.HasValue && !converters.ContainsKey(inst.ExpressionType.Value)) - converters.Add(inst.ExpressionType.Value, inst); - } - - // get the funcs - var methods = typeof(EdgeQL).GetMethods(); - - _operators = methods.Select(x => - { - var att = x.GetCustomAttribute(); - return att == null ? ((MethodInfo? Info, IEdgeQLOperator? Operator))(null, null) : ((MethodInfo? Info, IEdgeQLOperator? Operator))(x, att.Operator); - }).Where(x => x.Info != null && x.Operator != null).ToDictionary(x => x.Operator!, x => x.Info!.ReturnType); - - _converters = converters; - } - - public static Type? ReverseLookupFunction(string funcText) - { - // check if its a function - var funcMatch = Regex.Match(funcText, @"^(\w+)\("); - - if (funcMatch.Success) - { - var funcName = funcMatch.Groups[1].Value; - // lookup in our defined ops for this func - return _operators.FirstOrDefault(x => Regex.IsMatch(x.Key.EdgeQLOperator, @"^\w+\(") && x.Key.EdgeQLOperator.StartsWith($"{funcName}(")).Value; - } - return null; - } - - internal static (string Query, Dictionary Arguments) SerializeQueryObject(TType obj, QueryBuilderContext? context = null) - { - var props = typeof(TType).GetProperties().Where(x => x.GetCustomAttribute() == null && x.GetCustomAttribute()?.IsComputed == false); - var propertySet = new List(); - var args = new Dictionary(); - - foreach (var prop in props) - { - var name = GetPropertyName(prop); - var result = SerializeProperty(prop.PropertyType, prop.GetValue(obj), IsLink(prop), context); - - if (!(context?.IncludeEmptySets ?? true) && result.Property == "{}") - continue; - - propertySet.Add($"{name} := {result.Property}"); - args = args.Concat(result.Arguments).ToDictionary(x => x.Key, x => x.Value); // TODO: optimize? - } - - - - return ($"{{ {string.Join(", ", propertySet)} }}", args); - } - - internal static (string Property, Dictionary Arguments) SerializeProperty(TType value, bool isLink, QueryBuilderContext? context = null) - => SerializeProperty(typeof(TType), value, isLink, context); - internal static (string Property, Dictionary Arguments) SerializeProperty(Type type, object? value, bool isLink, QueryBuilderContext? context = null) - { - var args = new Dictionary(); - var queryValue = ""; - var varName = $"p_{Guid.NewGuid().ToString().Replace("-", "")}"; - - if (isLink) - { - // removed with set. - //if (value is ISet set && set.IsSubQuery && set.QueryBuilder is QueryBuilder builder) - //{ - // var result = builder.Build(context?.Enter(x => x.UseDetached = type == set.GetInnerType()) ?? new()); - // args = args.Concat(result.Parameters).ToDictionary(x => x.Key, x => x.Value); - // queryValue = $"({result.QueryText})"; - //} - if (value is IEnumerable enm) - { - List values = new(); - // enumerate object links for mock objects - foreach (var val in enm) - { - if (val is not ISubQueryType sub) - throw new InvalidOperationException($"Expected a sub query for object type, but got {val.GetType()}"); - - values.Add(sub.Builder); - } - - var vals = values.Select(x => - { - args = x.Arguments.Concat(args).ToDictionary(x => x.Key, x => x.Value); - return $"({x})"; - }); - - queryValue = $"{{ {string.Join(", ", vals)} }}"; - } - else if (value is ISubQueryType sub) - { - var result = sub.Builder.Build(context?.Enter(x => x.UseDetached = type == sub.Builder.QuerySelectorType) ?? new()); - args = args.Concat(result.Parameters).ToDictionary(x => x.Key, x => x.Value); - queryValue = $"({result.QueryText})"; - } - else if (value == null) - { - queryValue = "{}"; // TODO: change empty set? - } - else throw new ArgumentException("Unresolved link parser"); - } - else if (value is ISubQueryType sub) - { - var result = sub.Builder.Build(context?.Enter(x => x.UseDetached = sub.Builder.QuerySelectorType == type) ?? new()); - args = args.Concat(result.Parameters).ToDictionary(x => x.Key, x => x.Value); - queryValue = $"({result.QueryText})"; - } - else if (value is IQueryResultObject obj && (context?.IntrospectObjectIds ?? false)) - { - // generate a select query - queryValue = $"(select {GetTypeName(type)} filter .id = \"{obj.GetObjectId()}\")"; - } - else if (value is QueryBuilder builder) - { - var result = builder.Build(context?.Enter(x => x.UseDetached = builder.QuerySelectorType == type) ?? new()); - args = args.Concat(result.Parameters).ToDictionary(x => x.Key, x => x.Value); - queryValue = $"({result.QueryText})"; - } - else if (value == null) - { - queryValue = "{}";// TODO: change empty set? - } - else - { - queryValue = $"<{PacketSerializer.GetEdgeQLType(type)}>${varName}"; - args.Add(varName, value); - } - - return (queryValue, args); - } - - internal static List ParseShapeDefinition(object? shape, Type parentType, bool referenceObject = false) - { - List shapeProps = new(); - - if (shape == null) - return shapeProps; - - // extract all props - var type = shape.GetType(); - - var props = type.GetProperties(); - - foreach (var prop in props) - { - // TODO: - //var isMultiLink = false; //ReflectionUtils.TryGetRawGeneric(typeof(MultiLink<>), parentType, out var multiLink); - - var referenceProp = parentType.GetProperty(prop.Name) ?? parentType.GetProperty(prop.Name); //(isMultiLink ? multiLink!.GenericTypeArguments[0]!.GetProperty(prop.Name) : ; - - if (referenceProp == null) - continue; - - var propName = GetPropertyName(referenceProp); - - if (prop.PropertyType == typeof(bool)) - { - if ((bool)prop.GetValue(shape)!) - shapeProps.Add(propName); - } - else if (prop.PropertyType.IsAssignableTo(typeof(QueryBuilder))) - { - var val = (QueryBuilder)prop.GetValue(shape)!; - - var query = val.Build(new QueryBuilderContext().Enter(x => x.ExplicitShapeDefinition = true)); - - shapeProps.Add($"{propName}:{query.QueryText}"); - } - else - { - // assume anon type - var val = ParseShapeDefinition(prop.GetValue(shape), referenceProp.PropertyType, referenceObject); - shapeProps.Add($"{propName}: {{ {string.Join(", ", val)} }}"); - } - } - - return shapeProps; - } - - internal static List ParseShapeDefinition(LambdaExpression lambda, QueryBuilderContext builderContext) - { - List props = new(); - - var body = lambda.Body; - - if (body is not NewExpression bodyExpression) - throw new ArgumentException($"Cannot infer shape from {body.NodeType}"); - - var type = lambda.Body.Type; - - var anonProperties = type.GetProperties(); - - for (int i = 0; i != anonProperties.Length; i++) - { - var prop = anonProperties[i]; - var param = bodyExpression.Arguments[i]; - - switch (param) - { - case ConstantExpression constant: - // TODO: extend to non booleans in the future? - - if (constant.Value is not bool val) - throw new InvalidDataException($"Expected boolean but got {constant.Type}"); - - if (val) props.Add($"{GetPropertyName(prop)}"); - break; - case MethodCallExpression mce: - // TODO: handle weird method calls - var source = mce.Arguments[0]; - - var exp = ConvertExpression(mce, new QueryContext - { - AllowSubQueryGeneration = true, - BuilderContext = builderContext.Enter(x => x.ExplicitShapeDefinition = true), - }); - - break; - - default: - break; - } - } - - - return props; - } - - internal static List ParseShapeDefinition(QueryBuilderContext context, bool referenceObject = false, params Expression[] shape) - { - List props = new(); - - foreach (var exp in shape) - { - var selector = exp; - - LambdaExpression? lam = null; - - if (selector is LambdaExpression lamd) - { - selector = lamd.Body; - lam = lamd; - - context.ParentQueryTypeName = lamd.Parameters[0].Name; - context.ParentQueryType = lamd.Parameters[0].Type; - - if (lamd.Body.Type.Name.StartsWith("<>f__AnonymousType")) - { - // anon type: parse that - props.AddRange(ParseShapeDefinition(lamd, context)); - continue; - } - } - - if (selector is MemberExpression mbs) - { - List innerExpression = new(); - - void AddExp(MemberExpression m) - { - innerExpression.Add(m); - - if (m.Expression is not null and MemberExpression mb) - AddExp(mb); - } - - AddExp(mbs); - - innerExpression.Reverse(); - - if (mbs.Type.GetCustomAttribute() != null) - { - props.Add($"{mbs.Member.GetCustomAttribute()?.Name ?? mbs.Member.Name}: {{ {string.Join(", ", ParseShapeDefinition(context, referenceObject, new Expression[] { mbs.Expression! }))} }}"); - } - - var name = RecurseNameLookup(mbs); - - if (lam != null) - { - name = referenceObject - ? name[lam.Parameters[0].Name!.Length..] - : name.Substring(lam.Parameters[0].Name!.Length + 1, name.Length - 1 - lam.Parameters[0].Name!.Length); - props.Add(name); - } - } - else if (selector is MethodCallExpression mc) - { - // allow select only - if (mc.Method.Name != "Select") - { - throw new ArgumentException("Only Select method is allowed on property selectors"); - } - - // create a dynamic version of this method - var funcInner = mc.Arguments[1].Type.GenericTypeArguments[0]; - var funcSelect = mc.Arguments[1].Type.GenericTypeArguments[1]; - var method = typeof(QueryBuilder).GetRuntimeMethods().First(x => x.Name == nameof(ParseShapeDefinition)).MakeGenericMethod(funcInner, funcSelect); - - // make the array arg - var arr = Array.CreateInstance(typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(funcInner, funcSelect)), 1); - arr.SetValue(mc.Arguments[1], 0); - - props.Add($"{GetTypeName(funcInner)}: {{ {string.Join(", ", (List)method.Invoke(null, new object[] { referenceObject, arr })!)} }}"); - } - else if (selector is UnaryExpression unary && unary.Type == typeof(object) && unary.Operand is MemberExpression mb && lam != null) - { - var name = RecurseNameLookup(mb); - - name = referenceObject && (!name.Contains(".@")) - ? name[lam.Parameters[0].Name!.Length..] - : name.Substring(lam.Parameters[0].Name!.Length + 1, name.Length - 1 - lam.Parameters[0].Name!.Length); - - props.Add(name); - } - else throw new KeyNotFoundException("Cannot resolve converter"); - } - - return props; - } - - internal static (List Properties, List> Arguments) GetTypePropertyNames(Type t, QueryBuilderContext context, ArgumentAggregationContext? aggregationContext = null) - { - List returnProps = new(); - var props = t.GetProperties().Where(x => x.GetCustomAttribute() == null); - var instance = Activator.CreateInstance(t); - var args = new List>(); - // get inner props on types - foreach (var prop in props) - { - var name = prop.GetCustomAttribute()?.Name ?? prop.Name; - var type = prop.PropertyType; - - if (ReflectionUtils.IsSubclassOfRawGeneric(typeof(ComputedValue<>), type)) - { - if (!context.AllowComputedValues) - continue; - - // its a computed value with a query, expose it - var val = (IComputedValue)prop.GetValue(instance)!; - returnProps.Add($"{name} := ({val.Builder})"); - args = val.Builder!.Arguments; - continue; - } - - if (TryGetEnumerableType(prop.PropertyType, out var i) && i.GetCustomAttribute() != null) - type = i; - - var edgeqlType = type.GetCustomAttribute(); - - if (edgeqlType != null) - { - if (type == t && aggregationContext?.PropertyType == type) - { - continue; - } - - if (context.MaxAggregationDepth.HasValue && context.MaxAggregationDepth.Value == aggregationContext?.Depth) - continue; - - var result = GetTypePropertyNames(type, context, aggregationContext?.Enter(type) ?? new ArgumentAggregationContext(type)); - args.AddRange(result.Arguments); - returnProps.Add($"{name}: {{ {string.Join(", ", result.Properties)} }}"); - } - else - { - returnProps.Add(name); - } - } - - return (returnProps, args); - } - - internal class ArgumentAggregationContext - { - public Type PropertyType { get; } - public ArgumentAggregationContext? Parent { get; private set; } - public int Depth { get; set; } - - public ArgumentAggregationContext(Type propType) - { - PropertyType = propType; - Depth = 0; - } - - public ArgumentAggregationContext Enter(Type propType) - { - return new ArgumentAggregationContext(propType) - { - Parent = this, - Depth = Depth + 1 - }; - } - } - - // TODO: add node checks when in Char context, using int converters while in char context will result in the int being converted to a character. - internal static (string Filter, Dictionary Arguments) ConvertExpression(Expression s, QueryContext context) - { - if (s is MemberInitExpression init) - { - var result = new List<(string Filter, Dictionary Arguments)>(); - foreach (MemberAssignment binding in init.Bindings) - { - var innerContext = context.Enter(binding.Expression, modifier: x => x.BindingType = binding.Member.GetMemberType()); - var value = ConvertExpression(binding.Expression, innerContext); - var name = binding.Member.GetCustomAttribute()?.Name ?? binding.Member.Name; - result.Add(($"{name}{(innerContext.IncludeSetOperand ? " :=" : "")} {value.Filter}", value.Arguments)); - } - - return (string.Join(", ", result.Select(x => x.Filter)), result.SelectMany(x => x.Arguments).ToDictionary(x => x.Key, x => x.Value)); - } - - if (s is BinaryExpression bin) - { - // compute left and right - var left = ConvertExpression(bin.Left, context.Enter(bin.Left)); - var right = ConvertExpression(bin.Right, context.Enter(bin.Right)); - - // reset char context - context.IsCharContext = false; - - // get converter - return _converters.TryGetValue(s.NodeType, out var conv) - ? ((string Filter, Dictionary Arguments))(conv.Build(left.Filter, right.Filter), left.Arguments.Concat(right.Arguments).ToDictionary(x => x.Key, x => x.Value)) - : throw new NotSupportedException($"Couldn't find operator for {s.NodeType}"); - - } - - if (s is UnaryExpression una) - { - // TODO: nullable converts? - - // get the value - var val = ConvertExpression(una.Operand, context); - - // cast only if not char - var edgeqlType = una.Operand.Type == typeof(char) ? "str" : PacketSerializer.GetEdgeQLType(una.Type); - - // set char context - context.IsCharContext = una.Operand.Type == typeof(char); - - return edgeqlType == null - ? throw new NotSupportedException($"No edgeql type map found for type {una.Type}") - : ((string Filter, Dictionary Arguments))($"<{edgeqlType}>{val.Filter}", val.Arguments); - } - - if (s is MethodCallExpression mc) - { - // check for query builder - if (TryResolveQueryBuilder(mc, out var innerBuilder)) - { - var result = innerBuilder!.Build(context.BuilderContext?.Enter(x => - { - x.LimitToOne = !TryGetEnumerableType(context.BindingType ?? mc.Type, out var _); - - }) ?? new()); - - return ($"({result.QueryText})", result.Parameters.ToDictionary(x => x.Key, x => x.Value)); - } - - - List<(string Filter, Dictionary Arguments)>? arguments = new(); - Dictionary parameterMap = new(); - - // check if we have a reserved operator for it - if (_reservedFunctionOperators.TryGetValue($"{mc.Method.DeclaringType!.Name}.{mc.Method.Name}", out IEdgeQLOperator? op) || (mc.Method.DeclaringType?.GetInterfaces().Any(i => _reservedFunctionOperators.TryGetValue($"{i.Name}.{mc.Method.Name}", out op)) ?? false)) - { - // add the object as a param - var objectInst = mc.Object; - if (objectInst == null && !context.AllowStaticOperators) - throw new ArgumentException("Cannot use static methods that require an instance to build"); - else if (objectInst != null) - { - var inst = ConvertExpression(objectInst, context.Enter(objectInst)); - arguments.Add(inst); - } - } - else if (mc.Method.DeclaringType == typeof(EdgeQL)) - { - // get the equivilant operator - op = mc.Method.GetCustomAttribute()?.Operator; - - // check for parameter map - parameterMap = new Dictionary(mc.Method.GetCustomAttributes().ToDictionary(x => x.Index, x => x.Name)); - } - else if (_reservedSubQueryFunctions.TryGetValue($"{mc.Method.DeclaringType!.Name}.{mc.Method.Name}", out var factory)) - { - // get source - var source = mc.Arguments[0]; - var builder = factory(context, source, mc.Arguments.Skip(1).ToArray()); - - var subQuery = builder.Build(context.BuilderContext!); - return (subQuery.QueryText, subQuery.Parameters.ToDictionary(x => x.Key, x => x.Value)); // TODO: dict init - } - - if (op == null) - throw new NotSupportedException($"Couldn't find operator for method {mc.Method}"); - - // parse the arguments - arguments.AddRange(mc.Arguments.SelectMany((x, i) => - { - return x is NewArrayExpression newArr - ? newArr.Expressions.Select((x, i) => ConvertExpression(x, context.Enter(x, i))) - : (IEnumerable<(string Filter, Dictionary Arguments)>)(new (string Filter, Dictionary Arguments)[] { ConvertExpression(x, context.Enter(x)) })!; - })); - - // add our parameter map - if (parameterMap.Any()) - { - var genericMethod = mc.Method.GetGenericMethodDefinition(); - var genericTypeArgs = mc.Method.GetGenericArguments(); - var genericDict = genericMethod.GetGenericArguments().Select((x, i) => new KeyValuePair(x.Name, genericTypeArgs[i])).ToDictionary(x => x.Key, x => x.Value); - foreach (var item in parameterMap) - { - if (genericDict.TryGetValue(item.Value, out var strongType)) - { - // convert the strong type - var typename = PacketSerializer.GetEdgeQLType(strongType) ?? GetTypeName(strongType); - - // insert into arguments - arguments.Insert((int)item.Key, (typename, new())); - } - } - } - - try - { - string builtOperator = op.Build(arguments.Select(x => x.Filter).ToArray()); - - switch (op) - { - case LinksAddLink or LinksRemoveLink: - { - context.IncludeSetOperand = false; - } - break; - case VariablesReference: - { - context.BuilderContext?.AddTrackedVariable(builtOperator); - } - break; - default: - builtOperator = $"({builtOperator})"; - break; - } - - return (builtOperator, arguments.SelectMany(x => x.Arguments).ToDictionary(x => x.Key, x => x.Value)); - } - catch (Exception x) - { - throw new NotSupportedException($"Failed to convert {mc.Method} to a EdgeQL expression", x); - } - } - - if (s is MemberExpression mbs && s.NodeType == ExpressionType.MemberAccess) - { - if (mbs.Expression is ConstantExpression innerConstant) - { - if (IsEdgeQLType(innerConstant.Type)) - { - // assume its a reference to another property and use the self reference context - var name = mbs.Member.GetCustomAttribute()?.Name ?? mbs.Member.Name; - return ($".{name}", new()); - } - - object? value = null; - Dictionary arguments = new(); - - switch (mbs.Member.MemberType) - { - case MemberTypes.Field: - value = ((FieldInfo)mbs.Member).GetValue(innerConstant.Value); - break; - case MemberTypes.Property: - value = ((PropertyInfo)mbs.Member).GetValue(innerConstant.Value); - break; - } - - arguments.Add(mbs.Member.Name, value); - - var edgeqlType = PacketSerializer.GetEdgeQLType(mbs.Type); - - return edgeqlType == null - ? throw new NotSupportedException($"No edgeql type map found for type {mbs.Type}") - : ((string Filter, Dictionary Arguments))($"<{edgeqlType}>${mbs.Member.Name}", arguments); - } - // TODO: optimize this - else if (mbs.Expression is MemberExpression innermbs && _reservedPropertiesOperators.TryGetValue($"{innermbs.Type.Name}.{mbs.Member.Name}", out var op)) - { - // convert the entire expression with the func - var ts = RecurseNameLookup(mbs, true); - if (ts.StartsWith($"{context.ParameterName}.")) - { - return (op.Build(ts.Substring(context.ParameterName!.Length, ts.Length - context.ParameterName.Length)), new()); - } - } - else - { - // check for variable access with recursion - // tostring it and check the starter accesser for our parameter - var ts = RecurseNameLookup(mbs); - if (ts.StartsWith($"{context.ParameterName}.")) - { - return (ts.Substring(context.ParameterName!.Length, ts.Length - context.ParameterName.Length), new()); - } - - if (TryResolveOperator(mbs, out var opr, out var exp) && opr is VariablesReference) - { - if (exp == null || opr == null) - throw new InvalidOperationException("Got faulty operator resolve results"); - - var varName = ConvertExpression(exp, context.Enter(exp)); - - var param = Expression.Parameter(exp.Method.ReturnType, "x"); - var newExp = mbs.Update(param); - var func = Expression.Lambda(newExp, param); - - var accessors = ConvertExpression(func.Body, new QueryContext - { - Body = func.Body, - ParameterName = "x", - ParameterType = exp.Method.ReturnType - }); - - context.BuilderContext?.AddTrackedVariable($"{varName.Filter}{accessors.Filter}"); - - // TODO: optimize dict - return ($"{varName.Filter}{accessors.Filter}", varName.Arguments.Concat(accessors.Arguments).ToDictionary(x => x.Key, x => x.Value)); - } - - throw new NotSupportedException($"Unknown handler for member access: {mbs}"); - } - } - - if (s is ConstantExpression constant && s.NodeType == ExpressionType.Constant) - { - return (ParseArgument(constant.Value, context), new()); - } - - if (s is NewArrayExpression newArr) - { - IEnumerable<(string Filter, Dictionary Arguments)>? values; - // check if its a 'params' array - if (context.ParameterIndex.HasValue && context.Parent?.Body is MethodCallExpression callExpression) - { - var p = callExpression.Method.GetParameters(); - - if (p[context.ParameterIndex.Value].GetCustomAttribute() != null) - { - // return joined by , - values = newArr.Expressions.Select((x, i) => ConvertExpression(x, context.Enter(x, i))); - - return (string.Join(", ", values.Select(x => x.Filter)), values.SelectMany(x => x.Arguments).ToDictionary(x => x.Key, x => x.Value)); - } - } - - // return normal array - values = newArr.Expressions.Select((x, i) => ConvertExpression(x, context.Enter(x, i))); - - return ($"[{string.Join(", ", values.Select(x => x.Filter))}]", values.SelectMany(x => x.Arguments).ToDictionary(x => x.Key, x => x.Value)); - } - - return ("", new()); - } - - internal static bool TryResolveQueryBuilder(MethodCallExpression mc, out QueryBuilder? builder) - { - builder = null; - - if (mc.Object is not MethodCallExpression obj) - return false; - - while (obj is MethodCallExpression innermc && innermc.Object != null && innermc.Object is MethodCallExpression innerInnermc && (!obj?.Type.IsAssignableTo(typeof(QueryBuilder)) ?? true)) - { - obj = innerInnermc; - } - - if (obj?.Type.IsAssignableTo(typeof(QueryBuilder)) ?? false) - { - // execute it - builder = Expression.Lambda>(obj).Compile()(); - return true; - } - - return false; - - } - - internal static bool TryResolveOperator(MemberExpression mc, out IEdgeQLOperator? edgeQLOperator, out MethodCallExpression? expression) - { - edgeQLOperator = null; - expression = null; - - Expression? currentExpression = mc; - - while (currentExpression != null) - { - if (currentExpression is MethodCallExpression mcs && mcs.Method.DeclaringType == typeof(EdgeQL) && mcs.Method.Name == nameof(EdgeQL.Var)) - { - edgeQLOperator = mcs.Method.GetCustomAttribute()!.Operator; - expression = mcs; - return true; - } - - if (currentExpression is MemberExpression mcin) - currentExpression = mcin.Expression; - else - break; - } - - return false; - - } - - internal static string RecurseNameLookup(MemberExpression expression, bool skipStart = false) - { - List tree = new(); - - if (!skipStart) - tree.Add(GetPropertyName(expression.Member)); - - if (expression.Expression is MemberExpression innerExp) - tree.Add(RecurseNameLookup(innerExp)); - if (expression.Expression is ParameterExpression param) - tree.Add(param.Name); - - tree.Reverse(); - return string.Join('.', tree); - } - - internal static string ParseArgument(object? arg, QueryContext context) - { - if (arg is string str) - return context.IsVariableReference ? str : $"\"{str}\""; - - if (arg is char chr) - return $"\"{chr}\""; - - if (context.IsCharContext && arg is int c) - { - return $"\"{char.ConvertFromUtf32(c)}\""; - } - - if (arg is Type t) - { - return PacketSerializer.GetEdgeQLType(t) ?? GetTypeName(t) ?? t.Name; - } - - if (arg != null) - { - var type = arg.GetType(); - - if (type.IsEnum) - { - // check for the serialization method attribute - var att = type.GetCustomAttribute(); - return att != null - ? att.Method switch - { - SerializationMethod.Lower => $"\"{arg.ToString()?.ToLower()}\"", - SerializationMethod.Numeric => Convert.ChangeType(arg, type.BaseType ?? typeof(int)).ToString() ?? "{}", - _ => "{}" - } - : Convert.ChangeType(arg, type.BaseType ?? typeof(int)).ToString() ?? "{}"; - } - } - - - // empy set for null - return arg?.ToString() ?? "{}"; - } - - internal static bool IsEdgeQLType(Type t) - => t.GetCustomAttribute() != null; - - internal static string GetTypeName(Type t) - => t.GetCustomAttribute()?.Name ?? t.Name; - - internal static string GetPropertyName(MemberInfo t) - { - var name = t.GetCustomAttribute()?.Name ?? t.Name; - - //if (ReflectionUtils.IsSubclassOfRawGeneric(typeof(MultiLink<>), t.DeclaringType)) - //{ - // name = $"@{name}"; - //} - - return name; - } - - internal static string GetTypePrefix(Type t) - { - var edgeqlType = PacketSerializer.GetEdgeQLType(t); - - if (edgeqlType == null) - throw new NotSupportedException($"No edgeql type map found for type {t}"); - - return $"<{edgeqlType}>"; - } - - internal static bool TryGetEnumerableType(Type t, out Type type) - { - type = t; - - if (t.Name == typeof(IEnumerable<>).Name) - { - type = t.GenericTypeArguments[0]; - return true; - } - - if (t.GetInterfaces().Any(x => x.Name == typeof(IEnumerable<>).Name)) - { - var i = t.GetInterface(typeof(IEnumerable<>).Name)!; - type = i.GenericTypeArguments[0]; - return true; - } - - return false; - } - - internal static bool IsLink(PropertyInfo? info) - { - if (info == null) - return false; - - return - (info.GetCustomAttribute()?.IsLink ?? false) || - info.PropertyType.GetCustomAttribute() != null || - (TryGetEnumerableType(info.PropertyType, out var inner) && inner.GetCustomAttribute() != null); - } - - internal static Type CreateMockedType(Type mock) - { - //if (mock.IsValueType || mock.IsSealed) - // throw new InvalidOperationException($"Cannot create mocked type from {mock}"); - - //var tb = ReflectionUtils.GetTypeBuilder($"SubQuery{mock.Name}_{Guid.NewGuid().ToString().Replace("-", "")}", - // TypeAttributes.Public | - // TypeAttributes.Class | - // TypeAttributes.AutoClass | - // TypeAttributes.AnsiClass | - // TypeAttributes.BeforeFieldInit | - // TypeAttributes.AutoLayout); - - //tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); - //var get = typeof(ISubQueryType).GetMethod("get_Builder"); - //var set = typeof(ISubQueryType).GetMethod("set_Builder"); - //ReflectionUtils.CreateProperty(tb, "Builder", typeof(QueryBuilder), get, set); - //tb.SetParent(mock); - //tb.AddInterfaceImplementation(typeof(ISubQueryType)); - - //Type objectType = tb.CreateType()!; - - //return objectType; - - throw new NotSupportedException(); - } - } - - public interface ISubQueryType - { - QueryBuilder Builder { get; set; } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/QueryBuilder.cs b/src/EdgeDB.Net.QueryBuilder/QueryBuilder.cs deleted file mode 100644 index 7c4df258..00000000 --- a/src/EdgeDB.Net.QueryBuilder/QueryBuilder.cs +++ /dev/null @@ -1,724 +0,0 @@ -using EdgeDB.DataTypes; -using System.Linq.Expressions; - -namespace EdgeDB -{ - public partial class QueryBuilder - { - internal virtual Type QuerySelectorType => typeof(object); - - internal List QueryNodes = new(); - - internal QueryExpressionType PreviousNodeType - => CurrentRootNode.Children.LastOrDefault().Type; - - internal QueryNode CurrentRootNode - { - get - { - var lastNode = QueryNodes.LastOrDefault(); - - if (lastNode == null) - { - lastNode = new QueryNode() { Type = QueryExpressionType.Start }; - QueryNodes.Add(lastNode); - } - - return lastNode; - } - } - - public List> Arguments { get; set; } = new(); - - #region Static keyword proxies - public static QueryBuilder Select(object shape) => new QueryBuilder().Select(shape); - public static QueryBuilder Select(Expression> selector) => new QueryBuilder().Select(selector); - public static QueryBuilder Select() => new QueryBuilder().Select(); - public static QueryBuilder Select(params Expression>[] properties) => new QueryBuilder().Select(properties); - public static QueryBuilder Select(QueryBuilder value, params Expression>[] shape) => new QueryBuilder().Select(value, shape); - - public static QueryBuilder Insert(TType value) => new QueryBuilder().Insert(value); - public static QueryBuilder Update(TType obj) => new QueryBuilder().Update(obj); - public static QueryBuilder Update(Expression> builder) => new QueryBuilder().Update(builder); - public static QueryBuilder Update(TType? reference, Expression> builder) => new QueryBuilder().Update(reference, builder); - - public static QueryBuilder Delete() => new QueryBuilder().Delete(); - public static QueryBuilder With(string moduleName) => new QueryBuilder().With(moduleName); - public static QueryBuilder With(string name, TType value) => new QueryBuilder().With(name, value); - public static QueryBuilder With(params (string Name, object? Value)[] variables) => new QueryBuilder().With(variables); - - public static QueryBuilder For(Expression, QueryBuilder>> iterator) => new QueryBuilder().For(iterator); - - internal static QueryBuilder StaticLiteral(string query, QueryExpressionType type) => new QueryBuilder().Literal(query, type); - - internal static QueryBuilder StaticLiteral(string query, QueryExpressionType type) => new QueryBuilder().Literal(query, type); - - internal QueryBuilder Literal(string query, QueryExpressionType type) - { - QueryNodes.Add(new QueryNode - { - Query = query, - Type = type, - }); - - return this; - } - - #endregion - - /// - /// Turns this query builder into a edgeql representation. - /// - /// A edgeql query. - public override string? ToString() => Build().QueryText; - - /// - /// Turns this query builder into a edgeql representation where each - /// statement is seperated by newlines. - /// - /// A prettified version of the current query. - public string ToPrettyString() => Build().Prettify(); - - public BuiltQuery Build() => Build(new()); - - internal BuiltQuery Build(QueryBuilderContext config) - { - // reverse for building. - var results = QueryNodes.Reverse().Select(x => x.Build(config)).ToArray(); - return new BuiltQuery - { - Parameters = results.SelectMany(x => x.Parameters), - QueryText = string.Join(" ", results.Select(x => x.QueryText).Reverse()) - }; - } - } - - public class QueryBuilder : QueryBuilder - { - internal override Type QuerySelectorType => typeof(TType); - - public QueryBuilder() : this(null) { } - internal QueryBuilder(List? query = null) - { - QueryNodes = query ?? new List(); - } - - internal QueryBuilder ConvertTo() - => typeof(TTarget) == typeof(TType) ? (this as QueryBuilder)! : new QueryBuilder(QueryNodes); - - public new QueryBuilder Select(object shape) - { - return SelectInternal(context => - { - return context.DontSelectProperties ? null : (ParseShapeDefinition(shape, typeof(TTarget), false), null); - }); - } - - public new QueryBuilder Select(QueryBuilder value, params Expression>[] shape) - { - EnterRootNode(QueryExpressionType.Select, (QueryNode node, ref QueryBuilderContext context) => - { - var innerQuery = value.Build(context); - List parsedShape; - - if (shape.Length > 0) - parsedShape = ParseShapeDefinition(context, shape: shape); - else - { - var result = GetTypePropertyNames(typeof(TTarget), context.Enter(x => - { - x.AllowComputedValues = false; - x.MaxAggregationDepth = 0; - })); - parsedShape = result.Properties; - node.AddArguments(result.Arguments); - } - - node.Query = $"select ({innerQuery.QueryText}){(parsedShape != null && parsedShape.Count != 0 ? $" {{ {string.Join(", ", parsedShape)} }}" : "")}"; - node.AddArguments(innerQuery.Parameters); - }); - - return ConvertTo(); - } - - public new QueryBuilder Select(Expression> selector) - { - EnterRootNode(QueryExpressionType.Select, (QueryNode node, ref QueryBuilderContext context) => - { - var query = ConvertExpression(selector.Body, new QueryContext(selector) { BuilderContext = context }); - node.Query = $"select {query.Filter}"; - node.AddArguments(query.Arguments); - }); - - return typeof(TTarget) == typeof(TType) ? (this as QueryBuilder)! : ConvertTo(); - } - - public new QueryBuilder Select(params Expression>[] shape) - { - return SelectInternal(context => - { - return context.DontSelectProperties ? null : (ParseShapeDefinition(context, shape: shape), null); - }); - } - - public QueryBuilder Select() => Select(); - - public new QueryBuilder Select() - { - return SelectInternal(context => - { - if (context.DontSelectProperties) - { - return null; - } - var result = GetTypePropertyNames(typeof(TTarget), context); - - if (context.IsVariable) - { - result.Properties = new(); - } - - return (result.Properties, result.Arguments); - }); - } - - internal QueryBuilder SelectInternal(Func? Properties, IEnumerable>? Arguments)?> argumentBuilder) - { - EnterRootNode(QueryExpressionType.Select, (QueryNode node, ref QueryBuilderContext context) => - { - var selectArgs = argumentBuilder(context); - - IEnumerable? properties = selectArgs?.Properties; - IEnumerable>? args = selectArgs?.Arguments; - - node.Query = $"{(!context.ExplicitShapeDefinition ? $"select {(context.UseDetached ? "detached " : "")}{GetTypeName(typeof(TTarget))} " : "")}{(properties != null && properties.Any() ? $"{{ {string.Join(", ", properties)} }}" : "")}"; - if (context.LimitToOne || (context.UseDetached && PreviousNodeType != QueryExpressionType.Limit)) - node.AddChild(QueryExpressionType.Limit, (ref QueryBuilderContext _) => new BuiltQuery { QueryText = "limit 1" }); - - if (args != null) - node.AddArguments(args); - }); - return ConvertTo(); - } - - - public QueryBuilder Filter(Expression> filter) - => Filter(filter); - public QueryBuilder Filter(Expression> filter) - { - EnterNode(QueryExpressionType.Filter, (ref QueryBuilderContext builderContext) => - { - var context = new QueryContext(filter) { BuilderContext = builderContext }; - var builtFilter = ConvertExpression(filter.Body, context); - - return new BuiltQuery - { - Parameters = builtFilter.Arguments, - QueryText = $"filter {builtFilter.Filter}" - }; - }); - return ConvertTo(); - } - - public QueryBuilder OrderBy(Expression> selector, NullPlacement? nullPlacement = null) - => OrderByInternal("asc", selector, nullPlacement); - - public QueryBuilder OrderByDescending(Expression> selector, NullPlacement? nullPlacement = null) - => OrderByInternal("desc", selector, nullPlacement); - - internal QueryBuilder OrderByInternal(string direction, Expression> selector, NullPlacement? nullPlacement = null) - { - EnterNode(QueryExpressionType.OrderBy, (ref QueryBuilderContext context) => - { - var builtSelector = ParseShapeDefinition(context, true, selector).FirstOrDefault(); - string orderByExp = ""; - if (CurrentRootNode.Type == QueryExpressionType.OrderBy) - orderByExp += $"then {builtSelector} {direction}"; - else - orderByExp += $"order by {builtSelector} {direction}"; - - if (nullPlacement.HasValue) - orderByExp += $" empty {nullPlacement.Value.ToString().ToLower()}"; - - return new BuiltQuery - { - QueryText = orderByExp - }; - }); - return this; - } - - public QueryBuilder Offset(ulong count) - { - AssertValid(QueryExpressionType.Offset); - EnterNode(QueryExpressionType.Offset, (ref QueryBuilderContext context) => - { - return new BuiltQuery - { - QueryText = $"offset {count}" - }; - }); return this; - } - - public QueryBuilder Limit(ulong count) - { - AssertValid(QueryExpressionType.Limit); - EnterNode(QueryExpressionType.Limit, (ref QueryBuilderContext context) => - { - return new BuiltQuery - { - QueryText = $"limit {count}" - }; - }); - return this; - } - - public QueryBuilder For(Expression, QueryBuilder>> iterator) - { - EnterRootNode(QueryExpressionType.For, (QueryNode node, ref QueryBuilderContext context) => - { - var builder = new QueryBuilder(); - var builtIterator = iterator.Compile()(builder); - - node.Query = $"for {iterator.Parameters[0].Name} in {GetTypeName(typeof(TType))}"; - node.AddChild(QueryExpressionType.Union, (ref QueryBuilderContext innerContext) => - { - var result = builtIterator.Build(innerContext); - result.QueryText = $"union ({result.QueryText})"; - return result; - }); - }); - return this; - } - - public new QueryBuilder Insert(TTarget value) - { - EnterRootNode(QueryExpressionType.Insert, (QueryNode node, ref QueryBuilderContext context) => - { - var obj = SerializeQueryObject(value, context.Enter(x => - { - x.DontSelectProperties = true; - x.IncludeEmptySets = true; - })); - node.Query = $"insert{(context.UseDetached ? " detached" : "")} {GetTypeName(typeof(TTarget))} {obj.Query}"; - node.AddArguments(obj.Arguments); - }); - - return ConvertTo(); - } - - public QueryBuilder UnlessConflictOn(params Expression>[] selectors) - { - EnterNode(QueryExpressionType.UnlessConflictOn, (ref QueryBuilderContext innerContext) => - { - var props = ParseShapeDefinition(innerContext, true, selectors); - - return new BuiltQuery - { - QueryText = props.Count > 1 - ? $"unless conflict on ({string.Join(", ", props)})" - : $"unless conflict on {props[0]}" - }; - }); - - return this; - } - - public new QueryBuilder Update(TTarget obj) - { - EnterRootNode(QueryExpressionType.Update, (QueryNode node, ref QueryBuilderContext context) => - { - node.Query = $"update {GetTypeName(typeof(TTarget))}"; - var serializedObj = SerializeQueryObject(obj, context.Enter(x => x.DontSelectProperties = true)); - node.SetChild(0, QueryExpressionType.Set, (ref QueryBuilderContext innerContext) => - { - return new BuiltQuery - { - QueryText = $"set {serializedObj.Query}", - Parameters = serializedObj.Arguments, - }; - }); - }); - return ConvertTo(); - } - - public new QueryBuilder Update(TTarget? reference, Expression> builder) - { - EnterRootNode(QueryExpressionType.Update, (QueryNode node, ref QueryBuilderContext context) => - { - string? refName = ""; - - switch (reference) - { - case ISubQueryType sub: - if (sub.Builder.CurrentRootNode.Type == QueryExpressionType.Variable) - refName = sub.Builder.ToString(); - else - { - var result = sub.Builder.Build(context); - node.AddArguments(result.Parameters); - refName = $"({result.QueryText})"; - } - break; - case IQueryResultObject obj: - refName = $"(select {GetTypeName(typeof(TTarget))} filter .id = \"{obj.GetObjectId()}\" limit 1)"; - break; - - default: - throw new ArgumentException($"Cannot use {typeof(TTarget)} as a reference, no suitable reference extraction found"); - } - - var serializedObj = ConvertExpression(builder.Body, new QueryContext(builder) { AllowStaticOperators = true, BuilderContext = context.Enter(x => x.DontSelectProperties = true) }); - - node.Query = $"update {refName}"; - node.SetChild(0, QueryExpressionType.Set, (ref QueryBuilderContext innerContext) => - { - return new BuiltQuery - { - QueryText = $"set {{ {serializedObj.Filter} }}", - Parameters = serializedObj.Arguments - }; - }); - }); - - return ConvertTo(); - } - - public new QueryBuilder Update(Expression> builder) - { - EnterRootNode(QueryExpressionType.Update, (QueryNode node, ref QueryBuilderContext context) => - { - var serializedObj = ConvertExpression(builder.Body, new QueryContext(builder) { AllowStaticOperators = true, BuilderContext = context.Enter(x => x.DontSelectProperties = true) }); - - node.Query = $"update {GetTypeName(typeof(TTarget))}"; - - node.SetChild(node.Children.Any() ? 1 : 0, QueryExpressionType.Set, (ref QueryBuilderContext innerContext) => - { - return new BuiltQuery - { - QueryText = $"set {{ {serializedObj.Filter} }}", - Parameters = serializedObj.Arguments - }; - }); - - }); - - return ConvertTo(); - } - - public QueryBuilder Delete() - { - EnterRootNode(QueryExpressionType.Delete, (QueryNode node, ref QueryBuilderContext context) => - { - node.Query = $"delete {GetTypeName(typeof(TType))}"; - }); - return this; - } - - public QueryBuilder With(string moduleName) - { - EnterRootNode(QueryExpressionType.With, (QueryNode node, ref QueryBuilderContext context) => - { - node.Query = $"with module {moduleName}"; - }); - return this; - } - - public new QueryBuilder With(params (string Name, object? Value)[] variables) - { - EnterRootNode(QueryExpressionType.With, (QueryNode node, ref QueryBuilderContext context) => - { - List statements = new(); - - context.IntrospectObjectIds = true; - foreach (var (Name, Value) in variables) - { - var converted = SerializeProperty(Value?.GetType() ?? typeof(object), Value, false, context.Enter(x => - { - x.IsVariable = true; - x.VariableName = Name; - })); - node.AddArguments(converted.Arguments); - - statements.Add($"{Name} := {converted.Property}"); - } - - node.Query = $"with {string.Join(", ", statements)}"; - }); - - return this; - } - - public new QueryBuilder With(string name, TTarget value) - { - if (PreviousNodeType == QueryExpressionType.With) - { - EnterNode(QueryExpressionType.With, (ref QueryBuilderContext context) => - { - context.IntrospectObjectIds = true; - var converted = SerializeProperty(value, false, context); - - return new BuiltQuery - { - QueryText = $", {name} := {converted.Property}", - Parameters = converted.Arguments - }; - }); - } - else - { - EnterRootNode(QueryExpressionType.With, (QueryNode node, ref QueryBuilderContext context) => - { - context.IntrospectObjectIds = true; - var converted = SerializeProperty(value, false, context); - node.AddArguments(converted.Arguments); - node.Query = $"with {name} := {converted.Property}"; - }); - } - - return ConvertTo(); - } - - public QueryBuilder Else() - { - EnterRootNode(QueryExpressionType.Else, (QueryNode node, ref QueryBuilderContext context) => - { - node.Query = "else"; - }); - - return this; - } - - public QueryBuilder Else() - { - EnterRootNode(QueryExpressionType.Else, (QueryNode node, ref QueryBuilderContext context) => - { - node.Query = $"else {GetTypeName(typeof(TTarget))}"; - }); - - return ConvertTo(); - } - - public QueryBuilder Else(QueryBuilder builder) - { - Else(builder as QueryBuilder); - return ConvertTo(); - } - - public QueryBuilder Else(QueryBuilder builder) - { - EnterRootNode(QueryExpressionType.Else, (QueryNode node, ref QueryBuilderContext context) => - { - node.Query = "else"; - - foreach (var childNode in builder.QueryNodes) - { - node.AddChild(node.Type, (ref QueryBuilderContext innerContext) => - { - return childNode.Build(innerContext); - }); - } - }); - - return this; - } - - internal QueryBuilder Literal(string query, QueryExpressionType type) - { - QueryNodes.Add(new QueryNode - { - Query = query, - Type = type - - }); - - return ConvertTo(); - } - - private QueryNode EnterRootNode(QueryExpressionType type, RootNodeBuilder builder) - { - AssertValid(type); - var node = new QueryNode(type, builder); - QueryNodes.Add(node); - return node; - } - - private void EnterNode(QueryExpressionType type, ChildNodeBuilder builder) => CurrentRootNode.AddChild(type, builder); - - private void AssertValid(QueryExpressionType currentExpression) - { - if (_validExpressions.TryGetValue(currentExpression, out var exp) && !exp.Contains(CurrentRootNode.Type)) - { - throw new InvalidQueryOperationException(currentExpression, _validExpressions[currentExpression]); - } - } - - private readonly Dictionary _validExpressions = new() - { - { QueryExpressionType.With, new QueryExpressionType[] { QueryExpressionType.With, QueryExpressionType.Start } }, - { QueryExpressionType.Select, new QueryExpressionType[] { QueryExpressionType.Else, QueryExpressionType.With, QueryExpressionType.Start } }, - { QueryExpressionType.OrderBy, new QueryExpressionType[] { QueryExpressionType.Delete, QueryExpressionType.Filter, QueryExpressionType.Select } }, - { QueryExpressionType.Offset, new QueryExpressionType[] { QueryExpressionType.Delete, QueryExpressionType.OrderBy, QueryExpressionType.Select, QueryExpressionType.Filter } }, - { QueryExpressionType.Limit, new QueryExpressionType[] { QueryExpressionType.Delete, QueryExpressionType.OrderBy, QueryExpressionType.Select, QueryExpressionType.Filter, QueryExpressionType.Offset } }, - { QueryExpressionType.For, new QueryExpressionType[] { QueryExpressionType.Else, QueryExpressionType.With, QueryExpressionType.Start } }, - { QueryExpressionType.Insert, new QueryExpressionType[] { QueryExpressionType.Else, QueryExpressionType.With, QueryExpressionType.Start } }, - { QueryExpressionType.Update, new QueryExpressionType[] { QueryExpressionType.Else, QueryExpressionType.With, QueryExpressionType.Start } }, - { QueryExpressionType.Delete, new QueryExpressionType[] { QueryExpressionType.Else, QueryExpressionType.With, QueryExpressionType.Start } }, - { QueryExpressionType.Transaction, new QueryExpressionType[] { QueryExpressionType.Start } } - }; - - //public static implicit operator Set(QueryBuilder v) => new Set(v); - public static implicit operator ComputedValue(QueryBuilder v) - { - return new ComputedValue(default, v); - } - - public static implicit operator TType(QueryBuilder v) - { - return v.SubQuery(); - } - - //public Set SubQuerySet() - // => (Set)this; - - public TType SubQuery() - { - var obj = (ISubQueryType)Activator.CreateInstance(CreateMockedType(typeof(TType)))!; - obj.Builder = this; - return (TType)obj; - } - } - - internal delegate BuiltQuery ChildNodeBuilder(ref QueryBuilderContext context); - internal delegate void RootNodeBuilder(QueryNode node, ref QueryBuilderContext context); - - - internal class QueryNode - { - public QueryExpressionType Type { get; set; } - public List<(ChildNodeBuilder Builder, QueryExpressionType Type)> Children { get; set; } = new(); - public QueryNode? Parent { get; set; } - public string? Query { get; set; } - public IEnumerable> Arguments { get; set; } = new Dictionary(); - - private readonly object _lock = new(); - - private readonly RootNodeBuilder? _builder; - - public QueryNode() { } - - public QueryNode(QueryExpressionType type, RootNodeBuilder builder) - { - _builder = builder; - Type = type; - } - - public void AddChild(QueryExpressionType type, ChildNodeBuilder builder) - => Children.Add((builder, type)); - public void SetChild(int index, QueryExpressionType type, ChildNodeBuilder builder) - { - if (Children.Count > index) - Children[index] = (builder, type); - else Children.Insert(index, (builder, type)); - } - - public void AddArguments(IEnumerable> args) - { - lock (_lock) - { - Arguments = Arguments.Concat(args); - } - } - - public BuiltQuery Build(QueryBuilderContext config) - { - // remove current arguments incase of building twice - Arguments = new Dictionary(); - - if (_builder != null) - _builder.Invoke(this, ref config); - - var result = $"{Query}"; - - if (Children.Any()) - { - var results = Children.Select(x => x.Builder.Invoke(ref config)).ToArray(); - result += $" {string.Join(" ", results.Select(x => x.QueryText))}"; - AddArguments(results.SelectMany(x => x.Parameters)); - } - - return new BuiltQuery - { - Parameters = Arguments, - QueryText = result - }; - } - } - - public enum QueryExpressionType - { - Start, - Select, - Insert, - Update, - Delete, - With, - For, - Filter, - OrderBy, - Offset, - Limit, - Set, - Transaction, - Union, - UnlessConflictOn, - Rollback, - Commit, - Else, - - // internal - Variable, - } - - public enum IsolationMode - { - /// - /// All statements of the current transaction can only see data changes committed before the first query - /// or data-modification statement was executed in this transaction. If a pattern of reads and writes among - /// concurrent serializable transactions would create a situation which could not have occurred for any serial - /// (one-at-a-time) execution of those transactions, one of them will be rolled back with a serialization_failure error. - /// - Serializable, - /// - /// All statements of the current transaction can only see data committed before the first query or data-modification - /// statement was executed in this transaction. - /// - /// - /// This is the default isolation mode. - /// - RepeatableRead - } - - public enum AccessMode - { - /// - /// Sets the transaction access mode to read/write. - /// - /// - /// This is the default transaction access mode. - /// - ReadWrite, - - /// - /// Sets the transaction access mode to read-only. Any data modifications with insert, update, or delete - /// are disallowed. Schema mutations via DDL are also disallowed. - /// - ReadOnly - } - - public enum NullPlacement - { - First, - Last, - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/QueryBuilderContext.cs b/src/EdgeDB.Net.QueryBuilder/QueryBuilderContext.cs deleted file mode 100644 index dd293969..00000000 --- a/src/EdgeDB.Net.QueryBuilder/QueryBuilderContext.cs +++ /dev/null @@ -1,63 +0,0 @@ -namespace EdgeDB -{ - internal class QueryBuilderContext - { - public bool DontSelectProperties { get; set; } - public bool UseDetached { get; set; } - public bool IntrospectObjectIds { get; set; } - public QueryBuilderContext? Parent { get; set; } - public List TrackedVariables { get; set; } = new(); - public bool IncludeEmptySets { get; set; } = true; - public bool IsVariable { get; set; } - public string? VariableName { get; set; } - public bool AllowComputedValues { get; set; } = true; - public int? MaxAggregationDepth { get; set; } = 10; - public bool LimitToOne { get; set; } - public List TrackedSubQueries { get; set; } = new(); - public bool ExplicitShapeDefinition { get; set; } - - - // sub query type info - public Type? ParentQueryType { get; set; } - public string? ParentQueryTypeName { get; set; } - - public QueryBuilderContext Enter(Action modifier) - { - var context = new QueryBuilderContext - { - Parent = this, - DontSelectProperties = DontSelectProperties, - UseDetached = UseDetached, - IntrospectObjectIds = IntrospectObjectIds, - TrackedVariables = TrackedVariables, - TrackedSubQueries = TrackedSubQueries, - IsVariable = IsVariable, - VariableName = VariableName, - IncludeEmptySets = IncludeEmptySets, - AllowComputedValues = AllowComputedValues, - MaxAggregationDepth = MaxAggregationDepth, - ParentQueryType = ParentQueryType, - ParentQueryTypeName = ParentQueryTypeName, - }; - - modifier(context); - return context; - } - - public void AddTrackedVariable(string var) - { - if (Parent != null) - Parent.AddTrackedVariable(var); - else - TrackedVariables.Add(var); - } - - public void AddTrackedSubQuery(QueryBuilder builder) - { - if (Parent != null) - Parent.AddTrackedSubQuery(builder); - else - TrackedSubQueries.Add(builder); - } - } -} diff --git a/src/EdgeDB.Net.QueryBuilder/QueryContext.cs b/src/EdgeDB.Net.QueryBuilder/QueryContext.cs deleted file mode 100644 index 7380cb75..00000000 --- a/src/EdgeDB.Net.QueryBuilder/QueryContext.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Linq.Expressions; -using System.Reflection; - -namespace EdgeDB -{ - internal class QueryContext - { - public Type? ParameterType { get; set; } - public string? ParameterName { get; set; } - public Expression? Body { get; set; } - public QueryContext? Parent { get; set; } - public int? ParameterIndex { get; set; } - public bool IsCharContext { get; set; } - public bool AllowStaticOperators { get; set; } - public bool IncludeSetOperand { get; set; } = true; - public QueryBuilderContext? BuilderContext { get; set; } - public Type? BindingType { get; set; } - public bool AllowSubQueryGeneration { get; set; } - - public bool IsVariableReference - => Parent?.Body is MethodCallExpression mc && mc.Method.GetCustomAttribute()?.Operator?.GetType() == typeof(Operators.VariablesReference); - - public QueryContext() { } - - public virtual QueryContext Enter(Expression x, int? paramIndex = null, Action? modifier = null) - { - var context = new QueryContext() - { - Body = x, - ParameterName = ParameterName, - ParameterType = ParameterType, - IsCharContext = IsCharContext, - ParameterIndex = paramIndex, - Parent = this, - BuilderContext = BuilderContext, - }; - - modifier?.Invoke(context); - - return context; - } - } - - internal class QueryContext : QueryContext - { - public QueryContext() { } - public QueryContext(Expression> func) : base() - { - Body = func.Body; - ParameterType = func.Parameters[0].Type; - ParameterName = func.Parameters[0].Name; - } - - public QueryContext Enter(Expression x, int? paramIndex = null, Action>? modifier = null) - { - var context = new QueryContext() - { - Body = x, - ParameterName = ParameterName, - ParameterType = ParameterType, - IsCharContext = IsCharContext, - ParameterIndex = paramIndex, - Parent = this - }; - - modifier?.Invoke(context); - - return context; - } - } - - internal class QueryContext : QueryContext - { - public QueryContext() { } - public QueryContext(Expression> func) : base() - { - Body = func.Body; - } - - public QueryContext Enter(Expression x, int? paramIndex = null) - { - return new QueryContext() - { - Body = x, - ParameterName = ParameterName, - ParameterType = ParameterType, - IsCharContext = IsCharContext, - ParameterIndex = paramIndex, - Parent = this - }; - } - } -} diff --git a/tests/EdgeDB.Tests.Benchmarks/DeserializerBenchmarks.cs b/tests/EdgeDB.Tests.Benchmarks/DeserializerBenchmarks.cs index 457ea383..d73f16f9 100644 --- a/tests/EdgeDB.Tests.Benchmarks/DeserializerBenchmarks.cs +++ b/tests/EdgeDB.Tests.Benchmarks/DeserializerBenchmarks.cs @@ -1,6 +1,5 @@ -using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; using EdgeDB.Binary; -using EdgeDB.Models; using EdgeDB.Utils; using System; using System.Collections.Generic; @@ -38,15 +37,16 @@ public class DeserializerBenchmarks static DeserializerBenchmarks() { - ServerHandshake = HexConverter.FromHex("0000000A0000000D0000"); - Authentication1 = HexConverter.FromHex("0000001D0000000A000000010000000D534352414D2D5348412D323536"); - Authentication2 = HexConverter.FromHex("000000600000000B00000054723D435948636F2F333056784F4E6F6E6F7830564262524A2B504642706C55714B3475467358656465443274676A506C7A4E2C733D7A5244694F545130534971734A6877774C71536278673D3D2C693D34303936"); - Authentication3 = HexConverter.FromHex("0000003A0000000C0000002E763D7938654F576867615A5874463477357362336C78713430462B4D7A44744E617061533145712B7875552F453D"); - Authentication4 = HexConverter.FromHex("0000000800000000"); - ServerKeyData = HexConverter.FromHex("000000240000000000000000000000000000000000000000000000000000000000000000"); - ParameterStatus1 = HexConverter.FromHex("000000290000001A7375676765737465645F706F6F6C5F636F6E63757272656E637900000003313030"); - ParameterStatus2 = HexConverter.FromHex("000000C60000000D73797374656D5F636F6E666967000000AD00000071F2F5594609176568E2521789EE64F97F0200000000000000000000000000000100020000000000000000000000000000010E01F2F5594609176568E2521789EE64F97F00020000000141000000026964000000000000410000001473657373696F6E5F69646C655F74696D656F75740001000000340000000200000B8600000010172097A439F411E9B1899321EB2F4B97000040490000001000000000039387000000000000000000"); - ReadyForCommand = HexConverter.FromHex("00000007000049"); + // broken due to proto change. + ServerHandshake = HexConverter.FromHex("0000000D0000"); + Authentication1 = HexConverter.FromHex("0000000A000000010000000D534352414D2D5348412D323536"); + Authentication2 = HexConverter.FromHex("0000000B00000054723D435948636F2F333056784F4E6F6E6F7830564262524A2B504642706C55714B3475467358656465443274676A506C7A4E2C733D7A5244694F545130534971734A6877774C71536278673D3D2C693D34303936"); + Authentication3 = HexConverter.FromHex("0000000C0000002E763D7938654F576867615A5874463477357362336C78713430462B4D7A44744E617061533145712B7875552F453D"); + Authentication4 = HexConverter.FromHex("00000000"); + ServerKeyData = HexConverter.FromHex("0000000000000000000000000000000000000000000000000000000000000000"); + ParameterStatus1 = HexConverter.FromHex("0000001A7375676765737465645F706F6F6C5F636F6E63757272656E637900000003313030"); + ParameterStatus2 = HexConverter.FromHex("0000000D73797374656D5F636F6E666967000000AD00000071F2F5594609176568E2521789EE64F97F0200000000000000000000000000000100020000000000000000000000000000010E01F2F5594609176568E2521789EE64F97F00020000000141000000026964000000000000410000001473657373696F6E5F69646C655F74696D656F75740001000000340000000200000B8600000010172097A439F411E9B1899321EB2F4B97000040490000001000000000039387000000000000000000"); + ReadyForCommand = HexConverter.FromHex("000049"); } [ParamsSource(nameof(ValuesForPacket))] diff --git a/tests/EdgeDB.Tests.Benchmarks/EdgeDB.Tests.Benchmarks.csproj b/tests/EdgeDB.Tests.Benchmarks/EdgeDB.Tests.Benchmarks.csproj index fd44d7c7..8d7b4b6d 100644 --- a/tests/EdgeDB.Tests.Benchmarks/EdgeDB.Tests.Benchmarks.csproj +++ b/tests/EdgeDB.Tests.Benchmarks/EdgeDB.Tests.Benchmarks.csproj @@ -5,6 +5,7 @@ net6.0 enable enable + true diff --git a/tests/EdgeDB.Tests.Benchmarks/MockedEdgeDBClient.cs b/tests/EdgeDB.Tests.Benchmarks/MockedEdgeDBClient.cs index 8ad4d4a2..b2620939 100644 --- a/tests/EdgeDB.Tests.Benchmarks/MockedEdgeDBClient.cs +++ b/tests/EdgeDB.Tests.Benchmarks/MockedEdgeDBClient.cs @@ -1,4 +1,4 @@ -using EdgeDB.DataTypes; +using EdgeDB.DataTypes; using System; using System.Collections.Generic; using System.Linq; @@ -7,12 +7,12 @@ namespace EdgeDB.Tests.Benchmarks { - public class MockedEdgeDBClient : BaseEdgeDBClient + internal class MockedEdgeDBClient : BaseEdgeDBClient { public override bool IsConnected => true; public MockedEdgeDBClient(ulong id) - : base(id) + : base(id, null!) { } diff --git a/tests/EdgeDB.Tests.Benchmarks/PacketWritingBenchmark.cs b/tests/EdgeDB.Tests.Benchmarks/PacketWritingBenchmark.cs new file mode 100644 index 00000000..acfce3df --- /dev/null +++ b/tests/EdgeDB.Tests.Benchmarks/PacketWritingBenchmark.cs @@ -0,0 +1,39 @@ +using BenchmarkDotNet.Attributes; +using EdgeDB.Binary; +using EdgeDB.Binary.Packets; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.Tests.Benchmarks +{ + // commented out because of internalization of sendables. + + //[MemoryDiagnoser] + //public class PacketWritingBenchmark + //{ + // [Benchmark] + // [ArgumentsSource(nameof(Packets))] + // public Memory WritePacket(Sendable packet) + // { + // var p = new PacketWriter(packet.Size + 5); + // packet!.Write(ref p, null!); + // var data = p.GetBytes(); + // p.Dispose(); + // return data; + // } + + // public IEnumerable Packets => new Sendable[] + // { + // new ClientHandshake() + // { + // MajorVersion = 1, + // MinorVersion = 0, + // Extensions = Array.Empty(), + // ConnectionParameters = Array.Empty(), + // } + // }; + //} +} diff --git a/tests/EdgeDB.Tests.Benchmarks/Program.cs b/tests/EdgeDB.Tests.Benchmarks/Program.cs index a83d9560..37f35d59 100644 --- a/tests/EdgeDB.Tests.Benchmarks/Program.cs +++ b/tests/EdgeDB.Tests.Benchmarks/Program.cs @@ -1,34 +1,7 @@ -using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; -using EdgeDB; using EdgeDB.Tests.Benchmarks; -using System.Reflection; -//var asm = typeof(ClientPoolBenchmarks).Assembly; - -//BenchmarkRunner.Run(asm); - -// verify no exceptions -try -{ - var inst = new DeserializerBenchmarks(); - - foreach (var item in inst.ValuesForPacket) - { - inst.Packet = item; - - if (inst.Deserialize() == null) - { - throw new NullReferenceException("Deserialize didn't return packet"); - } - } -} -catch(Exception x) -{ - Console.WriteLine(x); -} BenchmarkRunner.Run(); - - await Task.Delay(-1); diff --git a/tests/EdgeDB.Tests.Benchmarks/TypeBuilderBenchmarks.cs b/tests/EdgeDB.Tests.Benchmarks/TypeBuilderBenchmarks.cs new file mode 100644 index 00000000..770ceebb --- /dev/null +++ b/tests/EdgeDB.Tests.Benchmarks/TypeBuilderBenchmarks.cs @@ -0,0 +1,48 @@ +using BenchmarkDotNet.Attributes; +using EdgeDB.Binary.Packets; +using EdgeDB.Binary.Codecs; +using EdgeDB.Binary; + +namespace EdgeDB.Tests.Benchmarks +{ + [MemoryDiagnoser] + public class TypeBuilderBenchmarks + { + public class Person + { + public string? Name { get; set; } + + public string? Email { get; set; } + } + + internal static Binary.Codecs.Object Codec; + internal static Data Data; + static TypeBuilderBenchmarks() + { + Data = new Data(new byte[] { 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0F, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6C, 0x74, 0x3A, 0x3A, 0x50, 0x65, 0x72, 0x73, 0x6F, 0x6E, 0x00, 0x00, 0x0B, 0x86, 0x00, 0x00, 0x00, 0x10, 0x4D, 0x3A, 0xEC, 0xD0, 0x0A, 0xA1, 0x11, 0xED, 0x87, 0x37, 0xB3, 0xDB, 0x16, 0x26, 0xE0, 0x22, 0x00, 0x00, 0x0B, 0x86, 0x00, 0x00, 0x00, 0x10, 0x97, 0x2B, 0xCF, 0x8A, 0x0A, 0xA8, 0x11, 0xED, 0x93, 0x76, 0xBB, 0xA4, 0xA8, 0xC6, 0xC3, 0xF0, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x0A, 0x4A, 0x6F, 0x68, 0x6E, 0x20, 0x53, 0x6D, 0x69, 0x74, 0x68, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x10, 0x6A, 0x6F, 0x68, 0x6E, 0x40, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x2E, 0x63, 0x6F, 0x6D }); + + Codec = new Binary.Codecs.Object(new ICodec[] + { + new Binary.Codecs.Text(), + new Binary.Codecs.UUID(), + new Binary.Codecs.UUID(), + new Binary.Codecs.Text(), + new Binary.Codecs.Text(), + }, new string[] + { + "__tname__", + "__tid__", + "id", + "name", + "email" + }); + Codec.Initialize(typeof(Person)); + } + + [Benchmark] + public Person? DeserializePersonNew() + { + return (Person?)TypeBuilder.BuildObject(typeof(Person), Codec, ref Data); + } + } +} diff --git a/tests/EdgeDB.Tests.Integration/ClientFixture.cs b/tests/EdgeDB.Tests.Integration/ClientFixture.cs index 8c179724..d174ae22 100644 --- a/tests/EdgeDB.Tests.Integration/ClientFixture.cs +++ b/tests/EdgeDB.Tests.Integration/ClientFixture.cs @@ -1,4 +1,4 @@ -using Newtonsoft.Json; +using Newtonsoft.Json; using System.IO; namespace EdgeDB.Tests.Integration @@ -9,17 +9,10 @@ public class ClientFixture public ClientFixture() { - EdgeDBConnection conn; - try + EdgeDB = new(new EdgeDBClientPoolConfig { - conn = EdgeDBConnection.FromInstanceName("edgedb_dotnet"); - } - catch - { - conn = JsonConvert.DeserializeObject(File.ReadAllText("/home/runner/.config/edgedb/credentials/EdgeDB_Dotnet_Test.json"))!; - } - - EdgeDB = new(conn); + SchemaNamingStrategy = INamingStrategy.SnakeCaseNamingStrategy + }); } } } diff --git a/tests/EdgeDB.Tests.Integration/ClientPoolTests.cs b/tests/EdgeDB.Tests.Integration/ClientPoolTests.cs deleted file mode 100644 index ef8bdf66..00000000 --- a/tests/EdgeDB.Tests.Integration/ClientPoolTests.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Collections.Concurrent; -using System.Diagnostics; -using System.Linq; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace EdgeDB.Tests.Integration -{ - [CollectionDefinition("ClientPoolTest", DisableParallelization = true)] - public class ClientPoolTests : IClassFixture - { - private readonly EdgeDBClient _edgedb; - private readonly ITestOutputHelper _output; - - public ClientPoolTests(ClientFixture clientFixture, ITestOutputHelper output) - { - _edgedb = clientFixture.EdgeDB; - _output = output; - } - - [Fact] - public async Task TestPoolCapability() - { - // create 1000 tasks - var numTasks = 150; - Task[] tasks = new Task[numTasks]; - ConcurrentBag results = new(); - - for (int i = 0; i != numTasks; i++) - { - tasks[i] = Task.Run(async () => - { - results.Add(await _edgedb.QueryRequiredSingleAsync("select \"Hello, Dotnet!\"")); - }); - } - - _output.WriteLine("Starting 150 query test..."); - - Stopwatch sw = Stopwatch.StartNew(); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - sw.Stop(); - - Assert.Equal(150, results.Count); - Assert.All(results, x => Assert.Equal("Hello, Dotnet!", x)); - - _output.WriteLine($"Executed 150 query test in {sw.ElapsedMilliseconds}ms"); - } - - [Fact] - public async Task TestPoolQueryMethods() - { - var jsonResult = await _edgedb.QueryJsonAsync("select {(a := 1), (a := 2)}"); - Assert.Equal("[{\"a\" : 1}, {\"a\" : 2}]", jsonResult); - - var querySingleResult = await _edgedb.QuerySingleAsync("select 123").ConfigureAwait(false); - Assert.Equal(123, querySingleResult); - } - - [Fact] - public async Task TestPoolDisconnects() - { - await using var client = await _edgedb.GetOrCreateClientAsync(); - await client.DisconnectAsync(); // should be removed from the pool - Assert.DoesNotContain(client, _edgedb.Clients); - await client.DisposeAsync(); // should NOT be returned to the pool - Assert.DoesNotContain(client, _edgedb.Clients); - } - - [Fact] - public async Task TestPoolRelease() - { - BaseEdgeDBClient client; - await using (client = await _edgedb.GetOrCreateClientAsync()) - { - await Task.Delay(100); - } - - // client should be back in the pool - Assert.Contains(client, _edgedb.Clients); - } - - [Fact] - public async Task TestPoolTransactions() - { - var result = await _edgedb.TransactionAsync(async (tx) => - { - return await tx.QuerySingleAsync("select \"Transaction within pools\""); - }); - - Assert.Equal("Transaction within pools", result); - } - } -} diff --git a/tests/EdgeDB.Tests.Integration/ClientTests.CustomTypes.cs b/tests/EdgeDB.Tests.Integration/ClientTests.CustomTypes.cs deleted file mode 100644 index 3fe56823..00000000 --- a/tests/EdgeDB.Tests.Integration/ClientTests.CustomTypes.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace EdgeDB.Tests.Integration -{ - public class ClientTestsCustomTypes : IClassFixture - { - private readonly EdgeDBClient _edgedb; - private readonly ITestOutputHelper _output; - - public ClientTestsCustomTypes(ClientFixture clientFixture, ITestOutputHelper output) - { - _edgedb = clientFixture.EdgeDB; - _output = output; - } - - [Fact] - public async Task TypeDeserialize() - { - // insert person if they dont exist - await _edgedb.ExecuteAsync("insert Person { name := \"A random name\", email := \"test@example.com\"} unless conflict on .email"); - - var person = await _edgedb.QueryRequiredSingleAsync("select Person { name, email } filter .email = \"test@example.com\""); - - Assert.Equal("A random name", person.Name); - Assert.Equal("test@example.com", person.Email); - } - - [Fact] - public async Task LocalAbstractTypeDeserialize() - { - // insert person if they dont exist - await _edgedb.ExecuteAsync("insert Person { name := \"A random name\", email := \"test@example.com\"} unless conflict on .email"); - - var person = await _edgedb.QueryRequiredSingleAsync("select Person { name, email } filter .email = \"test@example.com\""); - - Assert.Equal("A random name", person.Name); - Assert.Equal("test@example.com", person.Email); - } - - [Fact] - public async Task SchemaAbstractTypeDeserialize() - { - // insert some types - await _edgedb.ExecuteAsync("insert Thing { name := \"Thing1\", description := \"This is thing one!\" } unless conflict on .name"); - await _edgedb.ExecuteAsync("insert OtherThing { name := \"Thing2\", attribute := \"\" } unless conflict on .name"); - - var abstractSelect = await _edgedb.QueryAsync("select AbstractThing { name, [is Thing].description, [is OtherThing].attribute }"); - - foreach (var result in abstractSelect) - { - if (result is Thing thing) - { - Assert.Equal("Thing1", thing.Name); - Assert.Equal("This is thing one!", thing.Description); - } - else if (result is OtherThing otherThing) - { - Assert.Equal("Thing2", otherThing.Name); - Assert.Equal("", otherThing.Attribute); - } - else - throw new Exception("Unexpected type"); - } - } - - public class Person - { - public string? Name { get; init; } - - public string? Email { get; init; } - } - - public class PersonImpl : AbstractPerson - { - public string? Name { get; init; } - } - - public abstract class AbstractPerson - { - public string? Email { get; init; } - } - - public abstract class AbstractThing - { - public string? Name { get; init; } - } - - public class Thing : AbstractThing - { - public string? Description { get; init; } - } - - public class OtherThing : AbstractThing - { - public string? Attribute { get; init; } - } - } -} diff --git a/tests/EdgeDB.Tests.Integration/ClientTests.cs b/tests/EdgeDB.Tests.Integration/ClientTests.cs index 3e352405..886d1349 100644 --- a/tests/EdgeDB.Tests.Integration/ClientTests.cs +++ b/tests/EdgeDB.Tests.Integration/ClientTests.cs @@ -1,8 +1,9 @@ -using EdgeDB.DataTypes; +using EdgeDB.DataTypes; using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; @@ -21,6 +22,64 @@ public ClientTests(ClientFixture clientFixture, ITestOutputHelper output) _output = output; } + [Fact] + public async Task TestCommandLocks() + { + await using var client = await _edgedb.GetOrCreateClientAsync(); + var timeoutToken = new CancellationTokenSource(); + timeoutToken.CancelAfter(1000); + using var firstLock = await client.AquireCommandLockAsync(timeoutToken.Token); + + await Assert.ThrowsAsync(async () => + { + var secondLock = await client.AquireCommandLockAsync(timeoutToken.Token); + }); + } + + [Fact] + public async Task TestPoolQueryMethods() + { + var jsonResult = await _edgedb.QueryJsonAsync("select {(a := 1), (a := 2)}"); + Assert.Equal("[{\"a\" : 1}, {\"a\" : 2}]", jsonResult); + + var queryJsonElementsResult = await _edgedb.QueryJsonElementsAsync("select {(a := 1), (a := 2)}"); + + Assert.Equal(2, queryJsonElementsResult.Count()); + + Assert.Equal("{\"a\" : 1}", queryJsonElementsResult.First()); + Assert.Equal("{\"a\" : 2}", queryJsonElementsResult.Last()); + + var querySingleResult = await _edgedb.QuerySingleAsync("select 123").ConfigureAwait(false); + Assert.Equal(123, querySingleResult); + + var queryRequiredSingeResult = await _edgedb.QueryRequiredSingleAsync("select 123"); + Assert.Equal(123, queryRequiredSingeResult); + } + + [Fact] + public async Task TestPoolRelease() + { + BaseEdgeDBClient client; + await using (client = await _edgedb.GetOrCreateClientAsync()) + { + await Task.Delay(100); + } + + // client should be back in the pool + Assert.Contains(client, _edgedb.Clients); + } + + [Fact] + public async Task TestPoolTransactions() + { + var result = await _edgedb.TransactionAsync(async (tx) => + { + return await tx.QuerySingleAsync("select \"Transaction within pools\""); + }); + + Assert.Equal("Transaction within pools", result); + } + [Fact] public async Task StandardScalarQueries() { @@ -74,6 +133,21 @@ public async Task SetQueries() Assert.Equal(2, result.Last()); } + [Fact] + public async Task DisconnectAndReconnect() + { + // using raw client for this one, + var client = await _edgedb.GetOrCreateClientAsync(); + + // disconnect should close the underlying connection, and remove alloc'd resources for said connection. + await client.DisconnectAsync(); + + // should run just fine, restarting the underlying connection. + var str = await client.QueryRequiredSingleAsync("select \"Hello, EdgeDB.Net!\""); + + Assert.Equal("Hello, EdgeDB.Net!", str); + } + private async Task TestScalarQuery(string select, TResult expected) { var result = await _edgedb.QuerySingleAsync($"select {select}"); diff --git a/tests/EdgeDB.Tests.Integration/DDLTests.cs b/tests/EdgeDB.Tests.Integration/DDLTests.cs new file mode 100644 index 00000000..d07a2537 --- /dev/null +++ b/tests/EdgeDB.Tests.Integration/DDLTests.cs @@ -0,0 +1,62 @@ +using EdgeDB.State; +using System; +using System.Threading.Tasks; +using Xunit; + +namespace EdgeDB.Tests.Integration +{ + public class DDLTests : IClassFixture + { + private readonly EdgeDBClient _client; + private readonly EdgeDBClient _ddlClient; + + public DDLTests(ClientFixture fixture) + { + _client = fixture.EdgeDB; + _ddlClient = _client.WithConfig(x => x.DDLPolicy = DDLPolicy.AlwaysAllow); + } + + [Fact] + public async Task TestDDLInvalidCapabilitiesAndSessionConfig() + { + await Assert.ThrowsAsync(async () => + { + await _client.ExecuteAsync("CREATE TYPE TestType { CREATE REQUIRED PROPERTY name -> str; }"); + }); + } + + [Fact] + public async Task TestDDLInvalidCapabilitiesAndValidConfig() + { + await Assert.ThrowsAsync(async () => + { + await _ddlClient.ExecuteAsync("CREATE TYPE TestType { CREATE REQUIRED PROPERTY name -> str; }"); + }); + } + + [Fact] + public async Task TestDDLValidConfigAndCapabilities() + { + try + { + await _ddlClient.ExecuteAsync("CREATE TYPE TestType { CREATE REQUIRED PROPERTY name -> str; }", capabilities: Capabilities.All); + + var testResult = await _ddlClient.QueryRequiredSingleAsync("with t := (insert TestType { name := 'test' }) select t { name } limit 1"); + + Assert.NotNull(testResult); + Assert.Equal("test", testResult.Name); + } + finally + { + await _ddlClient.ExecuteAsync("DROP TYPE TestType", capabilities: Capabilities.All); + } + } + + private class TestType + { + [EdgeDBProperty("name")] + public string? Name { get; set; } + } + } +} + diff --git a/tests/EdgeDB.Tests.Integration/ErrorFormatTests.cs b/tests/EdgeDB.Tests.Integration/ErrorFormatTests.cs new file mode 100644 index 00000000..ffda5f63 --- /dev/null +++ b/tests/EdgeDB.Tests.Integration/ErrorFormatTests.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace EdgeDB.Tests.Integration +{ + public class ErrorFormatTests : IClassFixture + { + private readonly EdgeDBClient _client; + + public ErrorFormatTests(ClientFixture fixture) + { + _client = fixture.EdgeDB; + } + + [Fact] + public async Task TestErrorFormat() + { + var exception = await Assert.ThrowsAsync(async () => + { + await _client.QueryAsync("select {\n ver := sys::get_version(),\n unknown := .abc,\n};"); + }); + + Assert.Equal("InvalidReferenceError: object type 'std::FreeObject' has no link or property 'abc'\n |\n 3 | unknown := .abc,\n | ^^^^\n", exception.ToString()); + } + } +} diff --git a/tests/EdgeDB.Tests.Integration/TypeBuilderTests.cs b/tests/EdgeDB.Tests.Integration/TypeBuilderTests.cs new file mode 100644 index 00000000..c978b07b --- /dev/null +++ b/tests/EdgeDB.Tests.Integration/TypeBuilderTests.cs @@ -0,0 +1,222 @@ +using EdgeDB.Binary; +using EdgeDB.Binary.Builders; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace EdgeDB.Tests.Integration +{ + [CollectionDefinition("TypeBuilder", DisableParallelization = true)] + public class TypeBuilderTests : IClassFixture + { + private readonly EdgeDBClient _client; + + public TypeBuilderTests(ClientFixture fixture) + { + _client = fixture.EdgeDB; + } + + private async Task EnsurePersonIsAddedAsync() + { + await _client.ExecuteAsync("insert Person { name := \"A random name\", email := \"test@example.com\"} unless conflict on .email"); + } + + [Fact] + public async Task BasicTypeDeserialize() + { + // insert person if they dont exist + await EnsurePersonIsAddedAsync(); + + var person = await _client.QueryRequiredSingleAsync("select Person { name, email } filter .email = \"test@example.com\""); + + Assert.Equal("A random name", person.Name); + Assert.Equal("test@example.com", person.Email); + } + + [Fact] + public async Task LocalAbstractTypeDeserialize() + { + await EnsurePersonIsAddedAsync(); + + var person = await _client.QueryRequiredSingleAsync("select Person { name, email } filter .email = \"test@example.com\""); + + Assert.Equal("A random name", person.Name); + Assert.Equal("test@example.com", person.Email); + } + + [Fact] + public async Task SchemaAbstractTypeDeserialize() + { + // insert some types + await _client.ExecuteAsync("insert Thing { name := \"Thing1\", description := \"This is thing one!\" } unless conflict on .name"); + await _client.ExecuteAsync("insert OtherThing { name := \"Thing2\", attribute := \"\" } unless conflict on .name"); + + var abstractSelect = await _client.QueryAsync("select AbstractThing { name, [is Thing].description, [is OtherThing].attribute }"); + + foreach (var result in abstractSelect) + { + if (result is Thing thing) + { + Assert.Equal("Thing1", thing.Name); + Assert.Equal("This is thing one!", thing.Description); + } + else if (result is OtherThing otherThing) + { + Assert.Equal("Thing2", otherThing.Name); + Assert.Equal("", otherThing.Attribute); + } + else + throw new Exception("Unexpected type"); + } + } + + [Fact] + public async Task TestConstructorDeserializer() + { + await EnsurePersonIsAddedAsync(); + + var person = await _client.QueryRequiredSingleAsync("select Person { name, email } limit 1"); + + Assert.NotNull(person); + Assert.IsType(person); + Assert.True(person.CustomDeserializerCalled); + } + + [Fact] + public async Task TestCustomMethodDeserializer() + { + await EnsurePersonIsAddedAsync(); + + var person = await _client.QueryRequiredSingleAsync("select Person { name, email } limit 1"); + + Assert.NotNull(person); + Assert.IsType(person); + Assert.True(person.CustomDeserializerCalled); + } + + [Fact] + public async Task TestRecord() + { + await EnsurePersonIsAddedAsync(); + + var person = await _client.QueryRequiredSingleAsync("select Person { name, email } limit 1"); + + Assert.NotNull(person); + Assert.IsType(person); + } + + [Fact] + public async Task TestAddedFactoryBuilder() + { + await EnsurePersonIsAddedAsync(); + + bool customDeserializerCalled = false; + + TypeDeserializerFactory customBuilder = (ref ObjectEnumerator enumerator) => + { + var person = new PersonClass(); + + while(enumerator.Next(out var name, out var value)) + { + switch (name) + { + case "name": + person.Name = (string?)value; + break; + case "email": + person.Email = (string?)value; + break; + } + } + + customDeserializerCalled = true; + + return person; + }; + + TypeBuilder.AddOrUpdateTypeFactory(customBuilder); + + Assert.True(TypeBuilder.TypeInfo.ContainsKey(typeof(PersonClass))); + + var typeInfo = TypeBuilder.TypeInfo[typeof(PersonClass)]; + + Assert.Equal(customBuilder, typeInfo.Factory); + + var person = await _client.QueryAsync("select Person { name, email }"); + + Assert.NotNull(person); + + Assert.True(customDeserializerCalled); + } + + public class PersonClass + { + public string? Name { get; set; } + public string? Email { get; set; } + } + + public class PersonMethodBuilder + { + public string? Name { get; set; } + public string? Email { get; set; } + + public bool CustomDeserializerCalled { get; private set; } + + [EdgeDBDeserializer] + public void Build(IDictionary data) + { + Name = (string?)data["name"]; + Email = (string?)data["email"]; + + CustomDeserializerCalled = true; + } + } + + public class PersonConstructorBuilder + { + public string? Name { get; set; } + public string? Email { get; set; } + + public bool CustomDeserializerCalled { get; } + + [EdgeDBDeserializer] + public PersonConstructorBuilder(IDictionary data) + { + Name = (string?)data["name"]; + Email = (string?)data["email"]; + + CustomDeserializerCalled = true; + } + } + + public record PersonRecord(string Name, string Email); + + public class PersonImpl : AbstractPerson + { + public string? Name { get; init; } + } + + public abstract class AbstractPerson + { + public string? Email { get; init; } + } + + public abstract class AbstractThing + { + public string? Name { get; init; } + } + + public class Thing : AbstractThing + { + public string? Description { get; init; } + } + + public class OtherThing : AbstractThing + { + public string? Attribute { get; init; } + } + } +} diff --git a/tests/EdgeDB.Tests.Unit/ConnectionTests.cs b/tests/EdgeDB.Tests.Unit/ConnectionTests.cs index 785d05cf..33453cf3 100644 --- a/tests/EdgeDB.Tests.Unit/ConnectionTests.cs +++ b/tests/EdgeDB.Tests.Unit/ConnectionTests.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; -namespace EdgeDB.Tests.Unit.Connection +namespace EdgeDB.Tests.Unit { [TestClass] public class ConnectionTests @@ -174,6 +174,14 @@ public void DSNQueryParameterWithUnixSocket() "Cannot use UNIX socket for 'Hostname'"); } + [TestMethod] + public void TestConnectionFormat() + { + var connection = EdgeDBConnection.FromDSN("edgedb://user3:123123@localhost:5555/abcdef"); + + Assert.AreEqual("edgedb://user3:123123@localhost:5555/abcdef", connection.ToString()); + } + private static void Expect(Result result, EdgeDBConnection expected) { Assert.IsNotNull(result.Connection); diff --git a/tests/EdgeDB.Tests.Unit/EdgeDB.Tests.Unit.csproj b/tests/EdgeDB.Tests.Unit/EdgeDB.Tests.Unit.csproj index c5c8ca18..264f2e13 100644 --- a/tests/EdgeDB.Tests.Unit/EdgeDB.Tests.Unit.csproj +++ b/tests/EdgeDB.Tests.Unit/EdgeDB.Tests.Unit.csproj @@ -5,6 +5,8 @@ enable false + + true diff --git a/tests/EdgeDB.Tests.Unit/PacketWriterTests.cs b/tests/EdgeDB.Tests.Unit/PacketWriterTests.cs new file mode 100644 index 00000000..eb8b4ea9 --- /dev/null +++ b/tests/EdgeDB.Tests.Unit/PacketWriterTests.cs @@ -0,0 +1,89 @@ +using EdgeDB.Binary; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Buffers.Binary; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.Tests.Unit +{ + [TestClass] + public class PacketWriterTests + { + private static Dictionary> _endiannessConverters = new() + { + {typeof(int), (byte[] data) => BinaryPrimitives.ReadInt32BigEndian(data)}, + {typeof(uint), (byte[] data) => BinaryPrimitives.ReadUInt32BigEndian(data)}, + {typeof(long), (byte[] data) => BinaryPrimitives.ReadInt64BigEndian(data)}, + {typeof(ulong), (byte[] data) => BinaryPrimitives.ReadUInt64BigEndian(data)}, + {typeof(float), (byte[] data) => BinaryPrimitives.ReadSingleBigEndian(data)}, + {typeof(double), (byte[] data) => BinaryPrimitives.ReadDoubleBigEndian(data)}, + {typeof(short), (byte[] data) => BinaryPrimitives.ReadInt16BigEndian(data)}, + {typeof(ushort), (byte[] data) => BinaryPrimitives.ReadUInt16BigEndian(data)}, + {typeof(byte), (byte[] data) => data[0]}, + {typeof(sbyte), (byte[] data) => (sbyte)data[0]}, + }; + + private static unsafe void TestUnmanagedWrite(T value) + where T : unmanaged + { + var writer = new PacketWriter(sizeof(T)); + writer.Write(value); + Assert.AreEqual(sizeof(T), writer.Index); + + // ensure endianness was correctly accounted for + var data = writer.GetBytes().ToArray(); + Assert.AreEqual(value, _endiannessConverters[typeof(T)](data)); + } + + [TestMethod] + public void TestDynamicSizing() + { + var writer = new PacketWriter(4, true); + writer.Write((ulong)1234); + Assert.AreEqual(16, writer.Size); + } + + [TestMethod] + public void TestByte() + => TestUnmanagedWrite(0x01); + + [TestMethod] + public void TestSByte() + => TestUnmanagedWrite(-1); + + [TestMethod] + public void TestInt16() + => TestUnmanagedWrite((short)1234); + + [TestMethod] + public void TestUInt16() + => TestUnmanagedWrite((ushort)1234); + + [TestMethod] + public void TestInt32() + => TestUnmanagedWrite(1234); + + [TestMethod] + public void TestUInt32() + => TestUnmanagedWrite((uint)1234); + + [TestMethod] + public void TestInt64() + => TestUnmanagedWrite((long)1234); + + [TestMethod] + public void TestUInt64() + => TestUnmanagedWrite((ulong)1234); + + [TestMethod] + public void TestFloat() + => TestUnmanagedWrite((float)1234); + + [TestMethod] + public void TestDouble() + => TestUnmanagedWrite((double)1234); + } +} diff --git a/tests/EdgeDB.Tests.Unit/ProjectPathHashingTest.cs b/tests/EdgeDB.Tests.Unit/ProjectPathHashingTest.cs index df6317b3..5b07c13c 100644 --- a/tests/EdgeDB.Tests.Unit/ProjectPathHashingTest.cs +++ b/tests/EdgeDB.Tests.Unit/ProjectPathHashingTest.cs @@ -9,7 +9,7 @@ using System.Text; using System.Threading.Tasks; -namespace EdgeDB.Tests.Unit.Projects +namespace EdgeDB.Tests.Unit { [TestClass] public class ProjectPathHashingTest diff --git a/tests/EdgeDB.Tests.Unit/SCRAMTests.cs b/tests/EdgeDB.Tests.Unit/SCRAMTests.cs new file mode 100644 index 00000000..292e9fad --- /dev/null +++ b/tests/EdgeDB.Tests.Unit/SCRAMTests.cs @@ -0,0 +1,46 @@ +using EdgeDB.Binary; +using EdgeDB.Binary.Packets; +using EdgeDB.Utils; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace EdgeDB.Tests.Unit +{ + [TestClass] + public class SCRAMTests + { + public const string SCRAM_METHOD = "SCRAM-SHA-256"; + public const string SCRAM_USERNAME = "user"; + public const string SCRAM_PASSWORD = "pencil"; + public const string SCRAM_CLIENT_NONCE = "rOprNGfwEbeRWgbNEkqO"; + public const string SCRAM_SERVER_NONCE = "rOprNGfwEbeRWgbNEkqO%hvYDpWUa2RaTCAfuxFIlj)hNlF$k0"; + public const string SCRAM_SALT = "W22ZaJ0SNY7soEsUEjb6gQ=="; + + [TestMethod] + public void TestSCRAM() + { + var scram = new Scram(Convert.FromBase64String(SCRAM_CLIENT_NONCE)); + + var clientFirst = scram.BuildInitialMessage(SCRAM_USERNAME, SCRAM_METHOD); + Assert.AreEqual($"{SCRAM_METHOD} n,,n={SCRAM_USERNAME},r={SCRAM_CLIENT_NONCE}", clientFirst.ToString()); + + var serverFirst = CreateServerFirstMessage(); + var clientFinal = scram.BuildFinalMessage(in serverFirst, SCRAM_PASSWORD); + + Assert.AreEqual("6rriTRBi23WpRR/wtup+mMhUZUn/dB5nLTJRsjl95G4=", Convert.ToBase64String(clientFinal.ExpectedSig)); + Assert.AreEqual($"c=biws,r={SCRAM_SERVER_NONCE},p=dHzbZapWIk4jUhN+Ute9ytag9zjfMHgsqmmiz7AndVQ=", clientFinal.FinalMessage.ToString()); + } + + private static AuthenticationStatus CreateServerFirstMessage() + { + var inner = Encoding.UTF8.GetBytes($"r={SCRAM_SERVER_NONCE},s={SCRAM_SALT},i=4096"); + var data = new byte[] { 0x00, 0x00, 0x00, 0x0b }.Concat(BitConverter.GetBytes(inner.Length).Reverse()).Concat(inner).ToArray(); + var reader = new PacketReader(data); + return new AuthenticationStatus(ref reader); + } + } +} diff --git a/tests/EdgeDB.Tests.Unit/ScalarCodecsTests.cs b/tests/EdgeDB.Tests.Unit/ScalarCodecsTests.cs index 3a3916da..055b5997 100644 --- a/tests/EdgeDB.Tests.Unit/ScalarCodecsTests.cs +++ b/tests/EdgeDB.Tests.Unit/ScalarCodecsTests.cs @@ -1,9 +1,9 @@ -using EdgeDB.Codecs; +using EdgeDB.Binary.Codecs; using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Linq; -namespace EdgeDB.Tests.Unit.Codecs +namespace EdgeDB.Tests.Unit { [TestClass] public class ScalarCodecsTests diff --git a/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs b/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs index dcd0246b..44bb73e8 100644 --- a/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs +++ b/tools/EdgeDB.BinaryDebugger/DebuggerClient.cs @@ -1,5 +1,4 @@ -using EdgeDB.Binary; -using EdgeDB.Models; +using EdgeDB.Binary; using System; using System.Collections.Generic; using System.Linq; @@ -26,13 +25,12 @@ internal class DebuggerClient : EdgeDBBinaryClient private int _packetLength; private List? _packetBody; - private TcpClient _tcpClient; private NetworkStream? _stream; private SslStream? _secureStream; public DebuggerClient(EdgeDBConnection connection, EdgeDBConfig config, ulong? clientId = null) - : base(connection, config, clientId) + : base(connection, config, null!, clientId) { if (File.Exists("./debug.log")) File.Delete("./debug.log"); diff --git a/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj b/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj index 897e6f52..7935bd1d 100644 --- a/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj +++ b/tools/EdgeDB.DotnetTool/EdgeDB.DotnetTool.csproj @@ -24,7 +24,6 @@ - diff --git a/tools/EdgeDB.DotnetTool/Schemas/ClassBuilder.cs b/tools/EdgeDB.DotnetTool/Schemas/ClassBuilder.cs index 81dfe3f7..6294a216 100644 --- a/tools/EdgeDB.DotnetTool/Schemas/ClassBuilder.cs +++ b/tools/EdgeDB.DotnetTool/Schemas/ClassBuilder.cs @@ -1,4 +1,5 @@ -using System.Globalization; +using EdgeDB.Binary; +using System.Globalization; using System.Text.RegularExpressions; namespace EdgeDB.DotnetTool @@ -141,7 +142,7 @@ public void GenerateType(Type t, string dir, ClassBuilderContext context) { // do a reverse lookup on the root function to see if we can decipher the type computed = Regex.Replace(computed, @"^.+?::", _ => ""); - var returnType = QueryBuilder.ReverseLookupFunction(computed); + var returnType = typeof(object); //QueryBuilder.ReverseLookupFunction(computed); if (returnType != null) type = returnType.FullName;