Skip to content

Commit

Permalink
Merge branch 'dev' into feat/querybuilder-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
quinchs committed Jan 25, 2024
2 parents 5090201 + 2179dea commit 6760edf
Show file tree
Hide file tree
Showing 29 changed files with 668 additions and 237 deletions.
2 changes: 1 addition & 1 deletion EdgeDB.Net.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VersionPrefix>1.3.0</VersionPrefix>
<VersionPrefix>1.3.1</VersionPrefix>
<LangVersion>latest</LangVersion>
<Authors>EdgeDB.Net Contributors</Authors>
<PackageTags>edgedb;db;database</PackageTags>
Expand Down
26 changes: 26 additions & 0 deletions dbschema/migrations/00013.edgeql
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
CREATE MIGRATION m1xgcfneyhgejgvqtk3e46njjnngnxdwqeq3jh5idjfjhjxppfv5ya
ONTO m1qobo3k5z5dg56j3vymsaktqjnff5uv4ndpytjpqfwkda7lxinllq
{
CREATE MODULE tests IF NOT EXISTS;
CREATE TYPE tests::ScalarContainer {
CREATE PROPERTY a: std::int16;
CREATE PROPERTY b: std::int32;
CREATE PROPERTY c: std::int64;
CREATE PROPERTY d: std::str;
CREATE PROPERTY e: std::bool;
CREATE PROPERTY f: std::float32;
CREATE PROPERTY g: std::float64;
CREATE PROPERTY h: std::bigint;
CREATE PROPERTY i: std::decimal;
CREATE PROPERTY j: std::uuid;
CREATE PROPERTY k: std::json;
CREATE PROPERTY l: std::datetime;
CREATE PROPERTY m: cal::local_datetime;
CREATE PROPERTY n: cal::local_date;
CREATE PROPERTY o: cal::local_time;
CREATE PROPERTY p: std::duration;
CREATE PROPERTY q: cal::relative_duration;
CREATE PROPERTY r: cal::date_duration;
CREATE PROPERTY s: std::bytes;
};
};
23 changes: 23 additions & 0 deletions dbschema/tests.esdl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module tests {
type ScalarContainer {
a: int16;
b: int32;
c: int64;
d: str;
e: bool;
f: float32;
g: float64;
h: bigint;
i: decimal;
j: uuid;
k: json;
l: datetime;
m: cal::local_datetime;
n: cal::local_date;
o: cal::local_time;
p: duration;
q: cal::relative_duration;
r: cal::date_duration;
s: bytes;
}
}
18 changes: 11 additions & 7 deletions src/EdgeDB.Net.Driver/Binary/Builders/ObjectBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using EdgeDB.Binary.Codecs;
using EdgeDB.DataTypes;
using EdgeDB.Utils;
using Microsoft.Extensions.Logging;
using System.Collections;
using System.Collections.Concurrent;
Expand All @@ -12,7 +13,8 @@ internal sealed class ObjectBuilder
private static readonly ConcurrentDictionary<Type, (int Version, ICodec Codec)> _codecVisitorStateTable = new();
private static readonly object _visitorLock = new();

public static PreheatedCodec PreheatCodec<T>(EdgeDBBinaryClient client, ICodec codec)
public static async Task<PreheatedCodec> PreheatCodecAsync<T>(EdgeDBBinaryClient client, ICodec codec,
CancellationToken token)
{
// if the codec has been visited before and we have the most up-to-date version, return it.
if (
Expand All @@ -28,17 +30,18 @@ public static PreheatedCodec PreheatCodec<T>(EdgeDBBinaryClient client, ICodec c

var visitor = new TypeVisitor(client);
visitor.SetTargetType(typeof(T));
visitor.Visit(ref codec);
var reference = new Ref<ICodec>(codec);
await visitor.VisitAsync(reference, token);

if (typeof(T) != typeof(object))
_codecVisitorStateTable[typeof(T)] = (version, codec);
_codecVisitorStateTable[typeof(T)] = (version, reference.Value);

if (client.Logger.IsEnabled(LogLevel.Debug))
{
client.Logger.ObjectDeserializationPrep(CodecFormatter.Format(codec).ToString());
client.Logger.ObjectDeserializationPrep(CodecFormatter.Format(reference.Value).ToString());
}

return new PreheatedCodec(codec);
return new PreheatedCodec(reference.Value);
}

public static T? BuildResult<T>(EdgeDBBinaryClient client, in PreheatedCodec preheated,
Expand All @@ -54,8 +57,9 @@ public static PreheatedCodec PreheatCodec<T>(EdgeDBBinaryClient client, ICodec c
return (T?)ConvertTo(typeof(T), value);
}

public static T? BuildResult<T>(EdgeDBBinaryClient client, ICodec codec, in ReadOnlyMemory<byte> data)
=> BuildResult<T>(client, PreheatCodec<T>(client, codec), data);
public static async Task<T?> BuildResultAsync<T>(
EdgeDBBinaryClient client, ICodec codec, ReadOnlyMemory<byte> data, CancellationToken token)
=> BuildResult<T>(client, await PreheatCodecAsync<T>(client, codec, token), data);

public static object? ConvertTo(Type type, object? value)
{
Expand Down
12 changes: 12 additions & 0 deletions src/EdgeDB.Net.Driver/Binary/Codecs/ArgumentCodecContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace EdgeDB.Binary.Codecs;

internal sealed class ArgumentCodecContext : CodecContext
{
public readonly ICodec[] Codecs;

public ArgumentCodecContext(ICodec[] codecs, EdgeDBBinaryClient client)
: base(client)
{
Codecs = codecs;
}
}
14 changes: 12 additions & 2 deletions src/EdgeDB.Net.Driver/Binary/Codecs/ArrayCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,25 @@
namespace EdgeDB.Binary.Codecs;

internal sealed class ArrayCodec<T>
: BaseCodec<T?[]>, IWrappingCodec, ICacheableCodec
: BaseCodec<T?[]>, IWrappingCodec, ICacheableCodec, ICompiledCodec
{
public static readonly byte[] EMPTY_ARRAY = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};

public Type CompiledFrom { get; }
public CompilableWrappingCodec Template { get; }

internal ICodec<T> InnerCodec;

public ArrayCodec(in Guid id, ICodec<T> innerCodec, CodecMetadata? metadata = null)
public ArrayCodec(
in Guid id,
Type compiledFrom,
CompilableWrappingCodec template,
ICodec<T> innerCodec,
CodecMetadata? metadata = null)
: base(in id, metadata)
{
CompiledFrom = compiledFrom;
Template = template;
InnerCodec = innerCodec;
}

Expand Down
2 changes: 1 addition & 1 deletion src/EdgeDB.Net.Driver/Binary/Codecs/CodecContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace EdgeDB.Binary.Codecs;

internal sealed class CodecContext
internal class CodecContext
{
public CodecContext(EdgeDBBinaryClient client)
{
Expand Down
39 changes: 39 additions & 0 deletions src/EdgeDB.Net.Driver/Binary/Codecs/CodecFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,45 @@ namespace EdgeDB.Binary.Codecs;

internal static class CodecFormatter
{
public static StringBuilder FormatCodecAsTree(ICodec codec)
{
var sb = new StringBuilder();

AppendCodecToTree(sb, codec, 0);

return sb;
}


private const int CODEC_TREE_SPACING = 2;
private static void AppendCodecToTree(StringBuilder tree, ICodec codec, int depth, string? prefix = null)
{
tree.AppendLine("".PadLeft(depth) + $"{prefix} {codec}");

if (codec is IMultiWrappingCodec multiwrap)
{
for (int i = 0; i != multiwrap.InnerCodecs.Length; i++)
{
var innerCodec = multiwrap.InnerCodecs[i];
AppendCodecToTree(
tree,
innerCodec,
depth + CODEC_TREE_SPACING,
i == multiwrap.InnerCodecs.Length - 1 ? "\u2514" : "\u251c"
);
}
}
else if (codec is IWrappingCodec wrapping)
{
AppendCodecToTree(
tree,
wrapping.InnerCodec,
depth + CODEC_TREE_SPACING,
"\u2514"
);
}
}

public static StringBuilder Format(ICodec codec, int spacing = 2)
{
StringBuilder sb = new();
Expand Down
12 changes: 8 additions & 4 deletions src/EdgeDB.Net.Driver/Binary/Codecs/CompilableCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ void ICodec.Serialize(ref PacketWriter writer, object? value, CodecContext conte
object? ICodec.Deserialize(ref PacketReader reader, CodecContext context) => throw new NotSupportedException();

// to avoid state changes to this compilable, pass in the inner codec post-walk.
public ICodec Compile(IProtocolProvider provider, Type type, ICodec? innerCodec = null)
public ICompiledCodec Compile(IProtocolProvider provider, Type type, ICodec? innerCodec = null)
{
innerCodec ??= InnerCodec;

Expand All @@ -41,15 +41,19 @@ public ICodec Compile(IProtocolProvider provider, Type type, ICodec? innerCodec

return CodecBuilder.GetProviderCache(provider).CompiledCodecCache.GetOrAdd(cacheKey, k =>
{
var codec = (ICodec)Activator.CreateInstance(genType, Id, innerCodec, Metadata)!;
var codec = (ICompiledCodec)Activator.CreateInstance(
genType,
Id, type, this, innerCodec, Metadata
)!;
if (codec is IComplexCodec complex)
{
complex.BuildRuntimeCodecs(provider);
}
return codec;
});
}) as ICompiledCodec
?? throw new InvalidOperationException("Codec that was returned from the cache was not a compiled codec, this shouldn't happen");
}

public Type GetInnerType()
Expand All @@ -58,5 +62,5 @@ public Type GetInnerType()
: InnerCodec.ConverterType;

public override string ToString()
=> $"compilable({_rootCodecType.Name})";
=> $"compilable({InnerCodec})";
}
4 changes: 2 additions & 2 deletions src/EdgeDB.Net.Driver/Binary/Codecs/Impl/BaseArgumentCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ protected BaseArgumentCodec(in Guid id, CodecMetadata? metadata)
{
}

public abstract void SerializeArguments(ref PacketWriter writer, T? value, CodecContext context);
public abstract void SerializeArguments(ref PacketWriter writer, T? value, ArgumentCodecContext context);

void IArgumentCodec.SerializeArguments(ref PacketWriter writer, object? value, CodecContext context)
void IArgumentCodec.SerializeArguments(ref PacketWriter writer, object? value, ArgumentCodecContext context)
=> SerializeArguments(ref writer, (T?)value, context);
}
4 changes: 2 additions & 2 deletions src/EdgeDB.Net.Driver/Binary/Codecs/Impl/IArgumentCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ namespace EdgeDB.Binary.Codecs;

internal interface IArgumentCodec<T> : IArgumentCodec, ICodec<T>
{
void SerializeArguments(ref PacketWriter writer, T? value, CodecContext context);
void SerializeArguments(ref PacketWriter writer, T? value, ArgumentCodecContext context);
}

internal interface IArgumentCodec
{
void SerializeArguments(ref PacketWriter writer, object? value, CodecContext context);
void SerializeArguments(ref PacketWriter writer, object? value, ArgumentCodecContext context);
}
7 changes: 7 additions & 0 deletions src/EdgeDB.Net.Driver/Binary/Codecs/Impl/ICompiledCodec.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace EdgeDB.Binary.Codecs;

internal interface ICompiledCodec : ICodec, IWrappingCodec
{
Type CompiledFrom { get; }
CompilableWrappingCodec Template { get; }
}
24 changes: 21 additions & 3 deletions src/EdgeDB.Net.Driver/Binary/Codecs/MultiRangeCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,32 @@

namespace EdgeDB.Binary.Codecs;

internal sealed class MultiRangeCodec<T> : BaseCodec<MultiRange<T>>, IWrappingCodec, ICacheableCodec
internal sealed class MultiRangeCodec<T>
: BaseCodec<MultiRange<T>>, IWrappingCodec, ICacheableCodec, ICompiledCodec
where T : struct
{
public Type CompiledFrom { get; }
public CompilableWrappingCodec Template { get; }

private RangeCodec<T> _rangeCodec;

public MultiRangeCodec(in Guid id, ICodec<T> rangeInnerCodec, CodecMetadata? metadata) : base(in id, metadata)
public MultiRangeCodec(
in Guid id,
Type compiledFrom,
CompilableWrappingCodec template,
ICodec<T> rangeInnerCodec,
CodecMetadata? metadata
) : base(in id, metadata)
{
_rangeCodec = new RangeCodec<T>(in id, rangeInnerCodec, metadata);
CompiledFrom = compiledFrom;
Template = template;
_rangeCodec = new RangeCodec<T>(
in id,
compiledFrom,
template,
rangeInnerCodec,
metadata
);
}

public override void Serialize(ref PacketWriter writer, MultiRange<T> value, CodecContext context)
Expand Down
2 changes: 1 addition & 1 deletion src/EdgeDB.Net.Driver/Binary/Codecs/NullCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public NullCodec() { }

public NullCodec(CodecMetadata? metadata = null) { } // used in generic codec construction

public void SerializeArguments(ref PacketWriter writer, object? value, CodecContext context) { }
public void SerializeArguments(ref PacketWriter writer, object? value, ArgumentCodecContext context) { }

public Guid Id
=> Guid.Empty;
Expand Down
21 changes: 9 additions & 12 deletions src/EdgeDB.Net.Driver/Binary/Codecs/ObjectCodec.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public EdgeDBTypeDeserializeInfo Deserializer
reader.Position = enumerator.Reader.Position;
}
}

public override string ToString()
=> $"object ({TargetType.Name})";
}

internal class ObjectCodec
Expand Down Expand Up @@ -109,10 +112,13 @@ public TypeInitializedObjectCodec GetOrCreateTypeCodec(Type type)
}
}

public override void SerializeArguments(ref PacketWriter writer, object? value, CodecContext context)
=> Serialize(ref writer, value, context);
public override void SerializeArguments(ref PacketWriter writer, object? value, ArgumentCodecContext context)
=> Serialize(ref writer, value, context.Codecs, context);

public override void Serialize(ref PacketWriter writer, object? value, CodecContext context)
=> Serialize(ref writer, value, InnerCodecs, context);

private void Serialize(ref PacketWriter writer, object? value, ICodec[] codecs, CodecContext context)
{
object?[]? values = null;

Expand All @@ -128,9 +134,6 @@ public override void Serialize(ref PacketWriter writer, object? value, CodecCont

writer.Write(values.Length);

// TODO: maybe cache the visited codecs based on the 'value'.
var visitor = context.CreateTypeVisitor();

for (var i = 0; i != values.Length; i++)
{
var element = values[i];
Expand All @@ -156,17 +159,11 @@ public override void Serialize(ref PacketWriter writer, object? value, CodecCont
}
else
{
var innerCodec = InnerCodecs[i];
var innerCodec = codecs[i];

// special case for enums
if (element.GetType().IsEnum && innerCodec is TextCodec)
element = element.ToString();
else
{
visitor.SetTargetType(element.GetType());
visitor.Visit(ref innerCodec);
visitor.Reset();
}

writer.WriteToWithInt32Length((ref PacketWriter innerWriter) =>
innerCodec.Serialize(ref innerWriter, element, context));
Expand Down
Loading

0 comments on commit 6760edf

Please sign in to comment.