Skip to content

Commit

Permalink
Fix nullable value types in codec visitor (#76)
Browse files Browse the repository at this point in the history
  • Loading branch information
quinchs authored Jan 25, 2024
1 parent 6e67a61 commit bd3d774
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 1 deletion.
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;
}
}
33 changes: 32 additions & 1 deletion src/EdgeDB.Net.Driver/Binary/Codecs/Visitors/TypeVisitor.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using EdgeDB.Binary.Builders.Wrappers;
using EdgeDB.DataTypes;
using EdgeDB.Utils;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -239,8 +240,26 @@ private Type GetContextualTypeForComplexCodec(IComplexCodec codec, TypeVisitorCo
return context.Type;
}

private record TypeVisitorContext(Type Type)
private record TypeVisitorContext
{
private readonly Type _type;

public Type Type
{
get => _type;
init
{
// remove the wrapper if ones present
var temp = value;
while (IWrapper.TryGetWrapper(temp, out var wrapper))
{
temp = wrapper.GetInnerType(temp);
}

_type = temp;
}
}

public bool IsDynamicResult
=> Type == typeof(object);

Expand All @@ -252,6 +271,18 @@ public bool IsDynamicResult

public string FormattedDepth
=> "".PadRight(Depth, '>') + (Depth > 0 ? " " : "");

public TypeVisitorContext(Type type)
{
// remove the wrapper if ones present
var temp = type;
while (IWrapper.TryGetWrapper(temp, out var wrapper))
{
temp = wrapper.GetInnerType(temp);
}

_type = temp;
}
}

}
142 changes: 142 additions & 0 deletions tests/EdgeDB.Tests.Integration/QueryTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,148 @@ public async Task TestTypelessRange() =>

#region Object types

public class ScalarContainer
{
public short? A { get; set; }
public int? B { get; set; }
public long? C { get; set; }
public string? D { get; set; }
public bool? E { get; set; }
public float? F { get; set; }
public double? G { get; set; }
public BigInteger? H { get; set; }
public decimal? I { get; set; }
public Guid? J { get; set; }
public Json? K { get; set; }
public EdgeDB.DataTypes.DateTime? L { get; set; }
public DataTypes.LocalDateTime? M { get; set; }
public DataTypes.LocalDate? N { get; set; }
public DataTypes.LocalTime? O { get; set; }
public DataTypes.Duration? P { get; set; }
public DataTypes.RelativeDuration? Q { get; set; }
public DataTypes.DateDuration? R { get; set; }
public byte[]? S { get; set; }

}

[TestMethod]
public async Task TestNullableScalars()
{
var j = Guid.NewGuid();
var k = new Json("{\"Test\": \"Value\"}");
var l = new DataTypes.DateTime(DateTime.Now);
var m = new LocalDateTime(DateTime.Now);
var n = new LocalDate(DateOnly.FromDateTime(DateTime.Now));
var o = new LocalTime(TimeOnly.FromDateTime(DateTime.Now));
var p = new Duration(TimeSpan.FromSeconds(23));
var q = new RelativeDuration(TimeSpan.FromMilliseconds(255));
var r = new DateDuration(TimeSpan.FromDays(2));
var s = new byte[] {1, 2, 3, 4, 5};

var result = await _client.QueryRequiredSingleAsync<ScalarContainer>(
"""
WITH
container := (INSERT tests::ScalarContainer {
a := 5,
b := 7,
c := 299,
d := 'ABC',
e := true,
f := 221.5,
g := 2999.999,
h := 19248124,
i := <decimal>23.2,
j := <uuid>$j,
k := <json>$k,
l := <datetime>$l,
m := <cal::local_datetime>$m,
n := <cal::local_date>$n,
o := <cal::local_time>$o,
p := <duration>$p,
q := <cal::relative_duration>$q,
r := <cal::date_duration>$r,
s := <bytes>$s
})
SELECT container {
a,
b,
c,
d,
e,
f,
g,
h,
i,
j,
k,
l,
m,
n,
o,
p,
q,
r,
s
}
""", new
{
j,
k,
l,
m,
n,
o,
p,
q,
r,
s
});

#region Null checks

Assert.IsNotNull(result.A);
Assert.IsNotNull(result.B);
Assert.IsNotNull(result.C);
Assert.IsNotNull(result.D);
Assert.IsNotNull(result.E);
Assert.IsNotNull(result.F);
Assert.IsNotNull(result.G);
Assert.IsNotNull(result.H);
Assert.IsNotNull(result.I);
Assert.IsNotNull(result.J);
Assert.IsNotNull(result.K);
Assert.IsNotNull(result.L);
Assert.IsNotNull(result.M);
Assert.IsNotNull(result.N);
Assert.IsNotNull(result.O);
Assert.IsNotNull(result.P);
Assert.IsNotNull(result.Q);
Assert.IsNotNull(result.R);
Assert.IsNotNull(result.S);

#endregion

Assert.AreEqual(5, result.A.Value);
Assert.AreEqual(7, result.B.Value);
Assert.AreEqual(299, result.C.Value);
Assert.AreEqual("ABC", result.D);
Assert.AreEqual(true, result.E.Value);
Assert.AreEqual(221.5f, result.F.Value);
Assert.AreEqual(2999.999, result.G.Value);
Assert.AreEqual(19248124, result.H.Value);
Assert.AreEqual((decimal)23.2, result.I.Value);
Assert.AreEqual(j, result.J.Value);
Assert.AreEqual(k, result.K.Value);
Assert.AreEqual(l, result.L.Value);
Assert.AreEqual(m, result.M.Value);
Assert.AreEqual(n, result.N.Value);
Assert.AreEqual(o, result.O.Value);
Assert.AreEqual(p, result.P.Value);
Assert.AreEqual(q, result.Q.Value);
Assert.AreEqual(r, result.R.Value);
Assert.IsTrue(s.SequenceEqual(result.S));
}

public class A
{
public B? PropA { get; set; }
Expand Down

0 comments on commit bd3d774

Please sign in to comment.