Skip to content

Commit

Permalink
cast reduction, fix groups, smart markers, aggregation
Browse files Browse the repository at this point in the history
  • Loading branch information
quinchs committed Mar 13, 2024
1 parent c1eb806 commit 2b25bb2
Show file tree
Hide file tree
Showing 48 changed files with 2,476 additions and 3,646 deletions.
18 changes: 9 additions & 9 deletions examples/EdgeDB.Examples.CSharp/Examples/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
// grouping by expressions
query = QueryBuilder
.Group<Person>()
.Using(person => new {StartsWithVowel = Regex.Matches(person.Name!, "(?i)^[aeiou]")})
.Using(person => new {StartsWithVowel = Regex.IsMatch(person.Name!, "(?i)^[aeiou]")})
.By(ctx => ctx.Using.StartsWithVowel)
.Compile(true);

Expand All @@ -185,7 +185,7 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
People = ctx.SubQuerySingle(QueryBuilder.Select<Person>()),
Groups = ctx.SubQuerySingle(
QueryBuilder
.Group(ctx => ctx.Local<Person>("People"))
.Group(ctx => ctx.Global<Person>("People"))
.Using(person => new {Vowel = Regex.IsMatch(person.Name!, "(?i)^[aeiou]")})
.By(ctx => ctx.Using.Vowel)
)
Expand All @@ -195,7 +195,7 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
{
StartsWithVowel = group.Key,
Count = EdgeQL.Count(group.Elements),
NameLength = EdgeQL.Len(ctx.Ref(group.Elements).Name!)
NameLength = 1//EdgeQL.Len(ctx.Ref(group.Elements).Name!)
})
)
.Compile(true);
Expand All @@ -207,7 +207,7 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
People = ctx.SubQuerySingle(QueryBuilder.Select<Person>()),
Groups = ctx.SubQuerySingle(
QueryBuilder
.Group(ctx => ctx.Local<Person>("People"))
.Group(ctx => ctx.Global<Person>("People"))
.Using(person => new
{
Vowel = Regex.IsMatch(person.Name!, "(?i)^[aeiou]"),
Expand All @@ -217,11 +217,11 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
)
})
.SelectExpression(ctx => ctx.Variables.Groups, shape => shape
.Computeds((ctx, group) => new
.Explicitly((ctx, group) => new
{
StartsWithVowel = group.Key,
group.Key,
Count = EdgeQL.Count(group.Elements),
NameLength = EdgeQL.Len(ctx.Ref(group.Elements).Name!)
MeanNameLength = EdgeQL.Mean(ctx.Aggregate(group.Elements, element => (long)element.Name!.Length))
})
)
.Compile(true);
Expand All @@ -243,12 +243,12 @@ private static async Task QueryBuilderDemo(EdgeDBClient client)
)
})
.SelectExpression(ctx => ctx.Variables.Groups, shape => shape
.Computeds((ctx, group) => new
.Explicitly((ctx, group) => new
{
group.Key,
group.Grouping,
Count = EdgeQL.Count(group.Elements),
NameLength = EdgeQL.Len(ctx.Ref(group.Elements).Name!)
MeanNameLength = EdgeQL.Mean(ctx.Aggregate(group.Elements, element => (long)element.Name!.Length))//NameLength = 1//EdgeQL.Len(ctx.Ref(group.Elements).Name!)
})
)
.OrderBy(x => EdgeQL.ArrayAgg(x.Grouping))
Expand Down
21 changes: 21 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/Attributes/EdgeQLFunctionAttribute.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
namespace EdgeDB;

public sealed class EdgeQLFunctionAttribute(string name, string module, string returns, bool returnsSetOf, bool returnsOptional) : Attribute
{
public readonly string Name = name;
public readonly string Module = module;
public readonly string Returns = returns;
public readonly bool ReturnsSetOf = returnsSetOf;
public readonly bool ReturnsOptional = returnsOptional;

public string GetFormattedReturnType()
{
if (ReturnsSetOf)
return $"set<{Returns}>";

if (ReturnsOptional)
return $"optional {Returns}";

return Returns;
}
}
23 changes: 13 additions & 10 deletions src/EdgeDB.Net.QueryBuilder/Builders/ShapeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,18 +211,14 @@ public ShapeBuilder<T> Exclude<TExcluded>(Expression<Func<T, TExcluded>> selecto
}

public ShapeBuilder<T> Computeds<TAnon>(Expression<Func<T, TAnon>> computedsSelector)
{
var computeds = FlattenAnonymousExpression(SelectedType, computedsSelector);

foreach (var computed in computeds)
SelectedProperties[computed.Key.GetEdgeDBPropertyName()] = new(computed.Key, computed.Value);

return this;
}
=> ComputedsInternal(computedsSelector);

public ShapeBuilder<T> Computeds<TAnon>(Expression<Func<QueryContextSelf<T>, T, TAnon>> computedsSelector)
=> ComputedsInternal(computedsSelector);

internal ShapeBuilder<T> ComputedsInternal(LambdaExpression expression)
{
var computeds = FlattenAnonymousExpression(SelectedType, computedsSelector);
var computeds = FlattenAnonymousExpression(SelectedType, expression);

foreach (var computed in computeds)
SelectedProperties[computed.Key.GetEdgeDBPropertyName()] = new(computed.Key, computed.Value);
Expand All @@ -231,8 +227,15 @@ public ShapeBuilder<T> Computeds<TAnon>(Expression<Func<QueryContextSelf<T>, T,
}

public ShapeBuilder<T> Explicitly<TAnon>(Expression<Func<T, TAnon>> explicitSelector)
=> ExplicitlyInternal(explicitSelector);

public ShapeBuilder<T> Explicitly<TAnon>(Expression<Func<QueryContextSelf<T>, T, TAnon>> explicitSelector)
=> ExplicitlyInternal(explicitSelector);


internal ShapeBuilder<T> ExplicitlyInternal(LambdaExpression expression)
{
var members = FlattenAnonymousExpression(SelectedType, explicitSelector);
var members = FlattenAnonymousExpression(SelectedType, expression);

SelectedProperties.Clear();

Expand Down
99 changes: 69 additions & 30 deletions src/EdgeDB.Net.QueryBuilder/Compiled/DebugCompiledQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,41 +57,76 @@ private static string CreateDebugText(string query, Dictionary<string, object?>
barText.Insert(size - 1, "\u255d"); // corner UL
rowText.Insert(column.Range.Start.Value, barText);

char DrawVert(char prev)
{
return prev switch
{
' ' => '\u2551',
// L: UR -> T: UDR
'\u255a' => '\u2560',
// L: UL -> T: UDL
'\u255d' => '\u2563',
// horizontal -
'\u2550' => '\u256c',
_ => prev
};
}

foreach (var prevRowText in rows)
{
var prevStart = prevRowText[column.Range.Start.Value];

if (prevStart is ' ' or '\u255a')
{
prevRowText.Remove(column.Range.Start.Value, 1);
prevRowText.Insert(column.Range.Start.Value, prevStart == '\u255a' ? '\u2560' : '\u2551');
}
prevRowText.Remove(column.Range.Start.Value, 1);
prevRowText.Insert(column.Range.Start.Value, DrawVert(prevStart));

prevStart = prevRowText[query.Length + 1 + column.Range.Start.Value];

if (prevStart is ' ' or '\u255a')
{
prevRowText.Remove(query.Length + 1 + column.Range.Start.Value, 1);
prevRowText.Insert(query.Length + 1 + column.Range.Start.Value, prevStart == '\u255a' ? '\u2560' : '\u2551');
}
prevRowText.Remove(query.Length + 1 + column.Range.Start.Value, 1);
prevRowText.Insert(query.Length + 1 + column.Range.Start.Value, DrawVert(prevStart));

var prevEnd = prevRowText[column.Range.End.Value - 1];

if (prevEnd is ' ' or '\u255d')
{
prevRowText.Remove(column.Range.End.Value - 1, 1);
prevRowText.Insert(column.Range.End.Value - 1, prevEnd == '\u255d' ? '\u2563' : '\u2551');
}
prevRowText.Remove(column.Range.End.Value - 1, 1);
prevRowText.Insert(column.Range.End.Value - 1, DrawVert(prevEnd));

prevEnd = prevRowText[query.Length + column.Range.End.Value];

if (prevEnd is ' ' or '\u255d')
{
prevRowText.Remove(query.Length + column.Range.End.Value, 1);
prevRowText.Insert(query.Length + column.Range.End.Value, prevEnd == '\u255d' ? '\u2563' : '\u2551');
}
prevRowText.Remove(query.Length + column.Range.End.Value, 1);
prevRowText.Insert(query.Length + column.Range.End.Value, DrawVert(prevEnd));
}

// foreach (var prevRowText in rows)
// {
// var prevStart = prevRowText[column.Range.Start.Value];
//
// if (prevStart is ' ' or '\u255a')
// {
// prevRowText.Remove(column.Range.Start.Value, 1);
// prevRowText.Insert(column.Range.Start.Value, prevStart == '\u255a' ? '\u2560' : '\u2551');
// }
//
// prevStart = prevRowText[query.Length + 1 + column.Range.Start.Value];
//
// if (prevStart is ' ' or '\u255a')
// {
// prevRowText.Remove(query.Length + 1 + column.Range.Start.Value, 1);
// prevRowText.Insert(query.Length + 1 + column.Range.Start.Value, prevStart == '\u255a' ? '\u2560' : '\u2551');
// }
//
// var prevEnd = prevRowText[column.Range.End.Value - 1];
//
// if (prevEnd is ' ' or '\u255d')
// {
// prevRowText.Remove(column.Range.End.Value - 1, 1);
// prevRowText.Insert(column.Range.End.Value - 1, prevEnd == '\u255d' ? '\u2563' : '\u2551');
// }
//
// prevEnd = prevRowText[query.Length + column.Range.End.Value];
//
// if (prevEnd is ' ' or '\u255d')
// {
// prevRowText.Remove(query.Length + column.Range.End.Value, 1);
// prevRowText.Insert(query.Length + column.Range.End.Value, prevEnd == '\u255d' ? '\u2563' : '\u2551');
// }
// }

// desc
var icon = (markerTexts.Count + 1).ToString();
var desc = $"{icon} [{column.Marker.Type}] {column.Name}";
Expand All @@ -100,17 +135,17 @@ private static string CreateDebugText(string query, Dictionary<string, object?>
desc += $": {column.Marker.DebugText.Get()}";


if (desc.Length > size)
if (desc.Length + 2 > size)
{
desc = $"{icon} [{column.Marker.Type}] {column.Name}";
}

if (desc.Length > size)
if (desc.Length + 2 > size)
{
desc = $"{icon} {column.Name}";
}

if (desc.Length >= size)
if (desc.Length + 2 >= size)
{
desc = icon;
}
Expand Down Expand Up @@ -146,14 +181,18 @@ private static string CreateDebugText(string query, Dictionary<string, object?>
{
sb.AppendLine("Markers:");

var markerTypePadding = Enum.GetValues<MarkerType>().Max(x => Enum.GetName(x)!.Length) + 2;
foreach (var (name, value) in markerTexts)
{
var desc = $"{$"[{value.Marker.Type}]".PadRight(markerTypePadding)} {value.Name}";
sb.AppendLine($" {name}. {value.Marker.Type} ({value.Range})");
sb.AppendLine($" - Name: {value.Name}");
sb.AppendLine($" - Position: {value.Marker.Position}, Size: {value.Marker.Size}");
if (value.Marker.Metadata is not null)
sb.AppendLine($" - {value.Marker.Metadata}");
if (value.Marker.DebugText is not null)
desc += $": {value.Marker.DebugText.Get()}";
sb.AppendLine($" - Context: {value.Marker.DebugText.Get()}");


sb.AppendLine($" - {name.PadRight(markerTexts.Count.ToString().Length)} {$"({value.Range})".PadRight(query.Length.ToString().Length*2+4)} {desc}");
sb.AppendLine();
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/EdgeDB.Net.QueryBuilder/EdgeDB.Net.QueryBuilder.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Grammar\Operators\" />
<Folder Include="stdlib\" />
<Folder Include="Translators\Methods\Generated\" />
</ItemGroup>
</Project>
86 changes: 45 additions & 41 deletions src/EdgeDB.Net.QueryBuilder/EdgeQL.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,54 @@
using EdgeDB.Interfaces;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace EdgeDB
{
public sealed partial class EdgeQL
{
private static readonly Dictionary<string, Dictionary<string, List<MethodInfo>>> EdgeQLFunctions;

static EdgeQL()
{
var methods = typeof(EdgeQL).GetMethods();
EdgeQLFunctions = new();

foreach (var method in methods)
{
var edgeqlFuncAttribute = method.GetCustomAttribute<EdgeQLFunctionAttribute>();

if(edgeqlFuncAttribute is null)
continue;

if (!EdgeQLFunctions.TryGetValue(edgeqlFuncAttribute.Module, out var moduleFunctions))
moduleFunctions = EdgeQLFunctions[edgeqlFuncAttribute.Module] = new();

if (!moduleFunctions.TryGetValue(edgeqlFuncAttribute.Name, out var functions))
functions = moduleFunctions[edgeqlFuncAttribute.Name] = new();

functions.Add(method);
}
}

internal static bool TryGetMethods(string name, string module, [MaybeNullWhen(false)] out List<MethodInfo> methods)
{
methods = null;
return EdgeQLFunctions.TryGetValue(module, out var moduleFunctions) && moduleFunctions.TryGetValue(name, out methods);
}

internal static List<MethodInfo> SearchMethods(string name)
{
var result = new List<MethodInfo>();

foreach (var (module, functions) in EdgeQLFunctions)
{
if (functions.TryGetValue(name, out var targetFunctions))
result.AddRange(targetFunctions);
}

return result;
}

public static T Rollup<T>(T value)
=> default!;

Expand All @@ -13,46 +58,5 @@ public static T Cube<T>(T value)
public static JsonReferenceVariable<T> AsJson<T>(T value) => new(value);

public static long Count<TType>(IMultiCardinalityExecutable<TType> a) { return default!; }

// /// <summary>
// /// A function that represents the EdgeQL version of: <code>count(<paramref name="a"/>)</code>
// /// </summary>
//
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksAddLink))]
// public static TType[] AddLink<TType>(IQuery<TType> element)
// => default!;
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksAddLink))]
// public static TType[] AddLinkRef<TType>(TType element)
// => default!;
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksAddLink))]
// public static TSource AddLink<TSource, TType>(TType element)
// where TSource : IEnumerable<TType>
// => default!;
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksAddLink))]
// public static TSource AddLinkRef<TSource, TType>(IQuery<TType> element)
// where TSource : IEnumerable<TType>
// => default!;
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksRemoveLink))]
// public static TType[] RemoveLinkRef<TType>(TType element)
// => default!;
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksRemoveLink))]
// public static TType[] RemoveLink<TType>(IQuery<TType> element)
// => default!;
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksRemoveLink))]
// public static TSource RemoveLinkRef<TSource, TType>(TType element)
// where TSource : IEnumerable<TType>
// => default!;
//
// [EquivalentOperator(typeof(EdgeDB.Operators.LinksRemoveLink))]
// public static TSource RemoveLink<TSource, TType>(IQuery<TType> element)
// where TSource : IEnumerable<TType>
// => default!;
}
}
Loading

0 comments on commit 2b25bb2

Please sign in to comment.