Skip to content

Commit

Permalink
refactor and fix FOR iterator
Browse files Browse the repository at this point in the history
  • Loading branch information
quinchs committed Mar 9, 2024
1 parent 49529e2 commit 4fcd9d5
Show file tree
Hide file tree
Showing 22 changed files with 517 additions and 415 deletions.
46 changes: 46 additions & 0 deletions examples/EdgeDB.Examples.CSharp/Examples/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,52 @@ public async Task ExecuteAsync(EdgeDBClient client)
{
try
{
// depth of 4
var data = new Person[]
{
new Person
{
Email = "[email protected]",
Name = "test1",
},
new Person
{
Email = "[email protected]",
Name = "test2",
BestFriend = new Person
{
Email = "[email protected]",
Name = "test3",
Friends = new List<Person>()
{
new Person()
{
Name = "test4",
Email = "[email protected]",
BestFriend = new Person()
{
Name = "test4.1",
Email = "[email protected]"
}
},
new Person()
{
Name = "test5",
Email = "[email protected]",
BestFriend = new Person()
{
Name = "test5.1",
Email = "[email protected]"
}
}
}
}
}
};

var query = await QueryBuilder.For(data,
x => QueryBuilder.Insert(x)
).CompileAsync(client, true);
await QueryBuilderDemo(client);
}
catch (Exception x)

Check warning on line 83 in examples/EdgeDB.Examples.CSharp/Examples/QueryBuilder.cs

View workflow job for this annotation

GitHub Actions / Run test suite

The variable 'x' is declared but never used

Check warning on line 83 in examples/EdgeDB.Examples.CSharp/Examples/QueryBuilder.cs

View workflow job for this annotation

GitHub Actions / Run test suite

The variable 'x' is declared but never used
Expand Down
2 changes: 2 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/Compiled/CompiledQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public class CompiledQuery(string query, Dictionary<string, object?>? variables)
{
public string Query { get; } = query;

public string Prettied => Prettify();

public IReadOnlyDictionary<string, object?>? Variables { get; }
= variables?.ToImmutableDictionary();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void Reduce(IQueryBuilder builder, QueryWriter writer)
marker.Replace(writer => writer
.AppendSpanned(
ref tokens,
writer => global.Compile(builder, writer, new CompileContext { PreFinalizerModifier = modifier } )
writer => global.Compile(builder, writer, new CompileContext { PreFinalizerModifier = modifier, SchemaInfo = builder.SchemaInfo } )
)
);
}
Expand Down
12 changes: 2 additions & 10 deletions src/EdgeDB.Net.QueryBuilder/Grammar/Terms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,6 @@ public static QueryWriter Assignment(this QueryWriter writer, Value name, Value
public static QueryWriter TypeCast(this QueryWriter writer, Value type)
=> writer.Append("<", type, ">");

public static QueryWriter Variable(this QueryWriter writer, Value type, Value name)
=> writer.Marker(
MarkerType.Variable,
$"variable_{name}",
debug: null,
Value.Of(writer => writer.TypeCast(type).Append(name))
);

public readonly struct FunctionArg
{
public readonly Value Value;
Expand Down Expand Up @@ -173,8 +165,8 @@ public static QueryWriter Function(this QueryWriter writer, string name, params
public static QueryWriter SingleQuoted(this QueryWriter writer, Value value)
=> writer.Append('\'', value, '\'');

public static QueryWriter QueryArgument(this QueryWriter writer, Value type, string name, Deferrable<string>? debug = null)
=> writer.Marker(MarkerType.Variable, name, debug, '<', type, ">$", name);
public static QueryWriter QueryArgument(this QueryWriter writer, Value type, Value name, Deferrable<string>? debug = null)
=> writer.Marker(MarkerType.Variable, $"variable_{name}", debug, '<', type, ">$", name);

public static Value[] Span(this QueryWriter writer, WriterProxy proxy)
{
Expand Down
3 changes: 3 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/Interfaces/IQueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using EdgeDB.Interfaces;
using EdgeDB.Interfaces.Queries;
using EdgeDB.QueryNodes;
using EdgeDB.Schema;
using System.Linq.Expressions;

namespace EdgeDB
Expand Down Expand Up @@ -298,6 +299,8 @@ public interface IQueryBuilder
/// </summary>
internal Dictionary<string, object?> Variables { get; }

internal SchemaInfo? SchemaInfo { get; }

/// <summary>
/// Compiles the current query.
/// </summary>
Expand Down
22 changes: 11 additions & 11 deletions src/EdgeDB.Net.QueryBuilder/JsonVariable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@

namespace EdgeDB
{
public interface IJsonVariable<T> : IJsonVariable
{
Type IJsonVariable.InnerType => typeof(T);
}

/// <summary>
/// Represents an abstracted form of <see cref="JsonCollectionVariable{T}"/>.
/// </summary>
internal interface IJsonVariable
public interface IJsonVariable
{
/// <summary>
/// Gets the depth of the json.
Expand Down Expand Up @@ -46,7 +51,7 @@ internal interface IJsonVariable
/// A class representing a singleton, user defined json variable.
/// </summary>
/// <typeparam name="T">The type that this json variable was initialized with.</typeparam>
public class JsonReferenceVariable<T> : IJsonVariable
public class JsonReferenceVariable<T> : IJsonVariable<T>
{
/// <summary>
/// Gets the value this <see cref="JsonReferenceVariable{T}"/> represents.
Expand Down Expand Up @@ -84,10 +89,6 @@ string IJsonVariable.Name
string IJsonVariable.VariableName
=> VariableName ?? throw new InvalidOperationException("Cannot access variable name until reference variable initializes");

/// <inheritdoc/>
Type IJsonVariable.InnerType
=> typeof(T);

/// <inheritdoc/>
IEnumerable<JObject> IJsonVariable.GetObjectsAtDepth(int targetDepth)
=> Array.Empty<JObject>();
Expand All @@ -97,7 +98,7 @@ IEnumerable<JObject> IJsonVariable.GetObjectsAtDepth(int targetDepth)
/// Represents a json value used within queries.
/// </summary>
/// <typeparam name="T">The inner type that the json value represents.</typeparam>
public class JsonCollectionVariable<T> : IJsonVariable
public class JsonCollectionVariable<T> : IJsonVariable<T>
{
/// <summary>
/// Gets the name of the json variable.
Expand All @@ -108,9 +109,9 @@ public class JsonCollectionVariable<T> : IJsonVariable
/// Gets a mock reference of the json variable.
/// </summary>
/// <remarks>
/// This property can only be accessed within query builder lambda
/// functions. Attempting to access this property outside of a query
/// builder context will result in a <see cref="InvalidOperationException"/>
/// This property can only be accessed within query builder lambda
/// functions. Attempting to access this property outside of a query
/// builder context will result in a <see cref="InvalidOperationException"/>
/// being thrown.
/// </remarks>
public T Value
Expand Down Expand Up @@ -200,7 +201,6 @@ private int CalculateNodeDepth(JObject node, int depth = 0)
}

string IJsonVariable.Name => Name;
Type IJsonVariable.InnerType => typeof(T);
IEnumerable<JObject> IJsonVariable.GetObjectsAtDepth(int targetDepth) => GetObjectsAtDepth(targetDepth);
int IJsonVariable.Depth => CalculateDepth();
string IJsonVariable.VariableName => VariableName;
Expand Down
3 changes: 3 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/QueryBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ internal CompiledQuery CompileInternal(CompileContext? context = null)

internal void CompileInternal(QueryWriter writer, CompileContext? context = null)
{
_schemaInfo ??= context?.SchemaInfo;
context ??= new();

List<IDictionary<string, object?>> parameters = new();
Expand Down Expand Up @@ -579,6 +580,8 @@ async Task<TType> IMultiCardinalityExecutable<TType>.ExecuteRequiredSingleAsync(


#region IQueryBuilder<TType>

SchemaInfo? IQueryBuilder.SchemaInfo => _schemaInfo;
IReadOnlyCollection<QueryNode> IQueryBuilder.Nodes => _nodes;
List<QueryGlobal> IQueryBuilder.Globals => _queryGlobals;
Dictionary<string, object?> IQueryBuilder.Variables => _queryVariables;
Expand Down
2 changes: 2 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/QueryBuilder/CompileContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using EdgeDB.QueryNodes;
using EdgeDB.Schema;

namespace EdgeDB;

Expand All @@ -8,4 +9,5 @@ internal sealed record CompileContext
public bool IncludeAutogeneratedNodes { get; init; } = true;
public Action<QueryNode>? PreFinalizerModifier { get; init; }
public bool Debug { get; init; }
public SchemaInfo? SchemaInfo { get; init; }
}
20 changes: 20 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/QueryBuilder/QueryBuilder.For.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ public static partial class QueryBuilder
public static IMultiCardinalityExecutable<TType> For<TType>(IEnumerable<TType> collection,
Expression<Func<JsonCollectionVariable<TType>, IQueryBuilder>> iterator)
=> new QueryBuilder<TType>().For(collection, iterator);

public static IMultiCardinalityExecutable<TType> For<TType>(
Expression<Func<IEnumerable<TType>>> collection,
Expression<Func<JsonCollectionVariable<TType>, IQueryBuilder>> iterator
) => new QueryBuilder<TType>().For(collection, iterator);

public static IMultiCardinalityExecutable<TType> For<TType>(
Expression<Func<QueryContext, IEnumerable<TType>>> collection,
Expression<Func<JsonCollectionVariable<TType>, IQueryBuilder>> iterator
) => new QueryBuilder<TType>().For(collection, iterator);
}

public partial class QueryBuilder<TType, TContext>
Expand All @@ -27,6 +37,16 @@ public IMultiCardinalityExecutable<TType> For(IEnumerable<TType> collection, Exp
Set = collection
});

return this;
}
public IMultiCardinalityExecutable<TType> For(LambdaExpression collection, Expression<Func<JsonCollectionVariable<TType>, IQueryBuilder>> iterator)
{
AddNode<ForNode>(new ForContext(typeof(TType))
{
Expression = iterator,
SetExpression = collection
});

return this;
}
}
Expand Down
48 changes: 40 additions & 8 deletions src/EdgeDB.Net.QueryBuilder/QueryBuilder/QueryBuilder.Insert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace EdgeDB
{
public static partial class QueryBuilder
{

/// <inheritdoc cref="IQueryBuilder{TType, QueryContext}.Insert(Expression{Func{QueryContext, TType}}, bool)"/>
public static IInsertQuery<TType, QueryContext<TType>> Insert<TType>(Expression<Func<QueryContext<TType>, TType>> value, bool returnInsertedValue)
=> new QueryBuilder<TType>().Insert(value, returnInsertedValue);
Expand All @@ -28,17 +29,51 @@ public static IInsertQuery<TType, QueryContext<TType>> Insert<TType>(TType value
public static IInsertQuery<TType, QueryContext<TType>> Insert<TType>(TType value)
where TType : class
=> new QueryBuilder<TType>().Insert(value, false);

public static IInsertQuery<object, QueryContext<object>> Insert(Type type, IDictionary<string, object?> values)
=> new QueryBuilder<object>().Insert(type, values);

public static IInsertQuery<object, QueryContext<object>> Insert(Type type, IDictionary<string, object?> values, bool returnInsertedValue)
=> new QueryBuilder<object>().Insert(type, values, returnInsertedValue);

public static IInsertQuery<T, QueryContext<T>> Insert<T>(Type type, Expression<Func<T>> shape)
=> new QueryBuilder<T>().Insert(type, shape);

public static IInsertQuery<T, QueryContext<T>> Insert<T>(Type type, Expression<Func<QueryContext, T>> shape)
=> new QueryBuilder<T>().Insert(type, shape);
}

public partial class QueryBuilder<TType, TContext>
{
public IInsertQuery<TType, TContext> Insert(Type type, LambdaExpression expression,
bool returnInsertedValue = true)
{
var insertNode = AddNode<InsertNode>(new InsertContext(type, expression));

if (returnInsertedValue)
{
AddNode<SelectNode>(new SelectContext(type), true, insertNode);
}

return this;
}

public IInsertQuery<TType, TContext> Insert(Type type, IDictionary<string, object?> values, bool returnInsertedValue = true)
{
var insertNode = AddNode<InsertNode>(new InsertContext(type, InsertNode.InsertValue.FromRaw(type, values)));

if (returnInsertedValue)
{
AddNode<SelectNode>(new SelectContext(type), true, insertNode);
}

return this;
}

/// <inheritdoc/>
public IInsertQuery<TType, TContext> Insert(TType value, bool returnInsertedValue = true)
{
var insertNode = AddNode<InsertNode>(new InsertContext(typeof(TType))
{
Value = value,
});
var insertNode = AddNode<InsertNode>(new InsertContext(typeof(TType), value));

if (returnInsertedValue)
{
Expand All @@ -55,10 +90,7 @@ public IInsertQuery<TType, TContext> Insert(TType value)
/// <inheritdoc/>
public IInsertQuery<TType, TContext> Insert(Expression<Func<TContext, TType>> value, bool returnInsertedValue = true)
{
var insertNode = AddNode<InsertNode>(new InsertContext(typeof(TType))
{
Value = value,
});
var insertNode = AddNode<InsertNode>(new InsertContext(typeof(TType), value));

if (returnInsertedValue)
{
Expand Down
9 changes: 9 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/QueryContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ public class QueryContext<TSelf> : IQueryContext
/// </summary>
public TSelf Self { get; } = default!;

/// <summary>
/// References a defined query argument with the given name.
/// </summary>
/// <param name="name">The name of the query argument.</param>
/// <typeparam name="TType">The type of the query argument.</typeparam>
/// <returns>A mock reference to a global with the given <paramref name="name"/>.</returns>
public TType QueryArgument<TType>(string name)
=> default!;

/// <summary>
/// References a defined query global given a name.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/EdgeDB.Net.QueryBuilder/QueryNodes/Contexts/ForContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ internal class ForContext : NodeContext
/// </summary>
public IEnumerable? Set { get; init; }

public LambdaExpression? SetExpression { get; init; }

/// <inheritdoc/>
public ForContext(Type currentType) : base(currentType)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

Expand All @@ -14,11 +15,14 @@ internal class InsertContext : NodeContext
/// <summary>
/// Gets the value that is to be inserted.
/// </summary>
public object? Value { get; init; }
public Union<LambdaExpression, InsertNode.InsertValue, IJsonVariable>? Value { get; init; }

/// <inheritdoc/>
public InsertContext(Type currentType) : base(currentType)
public InsertContext(Type currentType, object? value) : base(currentType)
{
Value = value is not null
? Union<LambdaExpression, InsertNode.InsertValue, IJsonVariable>.From(value, () => InsertNode.InsertValue.FromType(value))
: null;
}
}
}
Loading

0 comments on commit 4fcd9d5

Please sign in to comment.