Skip to content

Commit

Permalink
Merge branch 'Async'
Browse files Browse the repository at this point in the history
  • Loading branch information
mattwar committed Sep 7, 2016
2 parents f5835a4 + 7d65bcb commit 7afa129
Show file tree
Hide file tree
Showing 45 changed files with 2,316 additions and 705 deletions.
2 changes: 1 addition & 1 deletion src/IQToolkit.Data.Access/AccessQueryProvider.cs
Expand Up @@ -72,7 +72,7 @@ public Executor(AccessQueryProvider provider)
this.provider = provider;
}

protected override DbCommand GetCommand(QueryCommand query, object[] paramValues)
public override DbCommand GetCommand(QueryCommand query, object[] paramValues)
{
var cmd = (OleDbCommand)this.provider.Connection.CreateCommand();
cmd.CommandText = query.CommandText;
Expand Down
2 changes: 1 addition & 1 deletion src/IQToolkit.Data.Access/OleDbQueryProvider.cs
Expand Up @@ -24,7 +24,7 @@ protected override QueryExecutor CreateExecutor()
return new Executor(this);
}

public new class Executor : DbEntityProvider.Executor
public class Executor : DbEntityProvider.DbQueryExecutor
{
OleDbQueryProvider provider;

Expand Down
4 changes: 2 additions & 2 deletions src/IQToolkit.Data.MySqlClient/MySqlQueryProvider.cs
Expand Up @@ -35,7 +35,7 @@ protected override QueryExecutor CreateExecutor()
return new Executor(this);
}

new class Executor : DbEntityProvider.Executor
class Executor : DbEntityProvider.DbQueryExecutor
{
MySqlQueryProvider provider;

Expand All @@ -45,7 +45,7 @@ public Executor(MySqlQueryProvider provider)
this.provider = provider;
}

protected override bool BufferResultRows
public override bool BufferResultRows
{
get { return true; }
}
Expand Down
4 changes: 2 additions & 2 deletions src/IQToolkit.Data.SQLite/SQLiteQueryProvider.cs
Expand Up @@ -55,7 +55,7 @@ protected override QueryExecutor CreateExecutor()
return new Executor(this);
}

new class Executor : DbEntityProvider.Executor
class Executor : DbEntityProvider.DbQueryExecutor
{
SQLiteQueryProvider provider;

Expand All @@ -65,7 +65,7 @@ public Executor(SQLiteQueryProvider provider)
this.provider = provider;
}

protected override DbCommand GetCommand(QueryCommand query, object[] paramValues)
public override DbCommand GetCommand(QueryCommand query, object[] paramValues)
{
SQLiteCommand cmd;
#if false
Expand Down
6 changes: 3 additions & 3 deletions src/IQToolkit.Data.SqlClient/SqlQueryProvider.cs
Expand Up @@ -61,7 +61,7 @@ protected override QueryExecutor CreateExecutor()
return new Executor(this);
}

new class Executor : DbEntityProvider.Executor
class Executor : DbEntityProvider.DbQueryExecutor
{
SqlQueryProvider provider;

Expand All @@ -71,7 +71,7 @@ public Executor(SqlQueryProvider provider)
this.provider = provider;
}

protected override bool BufferResultRows
public override bool BufferResultRows
{
get { return !this.provider.AllowsMultipleActiveResultSets; }
}
Expand Down Expand Up @@ -144,7 +144,7 @@ private IEnumerable<int> ExecuteBatch(QueryCommand query, IEnumerable<object[]>

this.LogMessage("-- Start SQL Batching --");
this.LogMessage("");
this.LogCommand(query, null);
this.LogCommand(query);

IEnumerator<object[]> en = paramSets.GetEnumerator();
using (en)
Expand Down
2 changes: 1 addition & 1 deletion src/IQToolkit.Data.SqlServerCe/SqlCeQueryProvider.cs
Expand Up @@ -41,7 +41,7 @@ protected override QueryExecutor CreateExecutor()
return new Executor(this);
}

new class Executor : DbEntityProvider.Executor
class Executor : DbEntityProvider.DbQueryExecutor
{
public Executor(SqlCeQueryProvider provider)
: base(provider)
Expand Down
66 changes: 34 additions & 32 deletions src/IQToolkit.Data/Common/ExecutionBuilder.cs
Expand Up @@ -10,6 +10,7 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading;

namespace IQToolkit.Data.Common
{
Expand All @@ -18,16 +19,16 @@ namespace IQToolkit.Data.Common
/// </summary>
public class ExecutionBuilder : DbExpressionVisitor
{
QueryPolicy policy;
QueryLinguist linguist;
Expression executor;
Scope scope;
bool isTop = true;
MemberInfo receivingMember;
int nReaders = 0;
List<ParameterExpression> variables = new List<ParameterExpression>();
List<Expression> initializers = new List<Expression>();
Dictionary<string, Expression> variableMap = new Dictionary<string, Expression>();
private QueryPolicy policy;
private QueryLinguist linguist;
private Expression executor;
private Scope scope;
private bool isTop = true;
private MemberInfo receivingMember;
private int nReaders = 0;
private List<ParameterExpression> variables = new List<ParameterExpression>();
private List<Expression> initializers = new List<Expression>();
private Dictionary<string, Expression> variableMap = new Dictionary<string, Expression>();

private ExecutionBuilder(QueryLinguist linguist, QueryPolicy policy, Expression executor)
{
Expand All @@ -41,7 +42,7 @@ public static Expression Build(QueryLinguist linguist, QueryPolicy policy, Expre
var executor = Expression.Parameter(typeof(QueryExecutor), "executor");
var builder = new ExecutionBuilder(linguist, policy, executor);
builder.variables.Add(executor);
builder.initializers.Add(Expression.Call(Expression.Convert(provider, typeof(ICreateExecutor)), "CreateExecutor", null, null));
builder.initializers.Add(Expression.Call(Expression.Convert(provider, typeof(ICreateExecutor)), nameof(ICreateExecutor.CreateExecutor), null, null));
var result = builder.Build(expression);
return result;
}
Expand Down Expand Up @@ -78,10 +79,10 @@ private static Expression MakeSequence(IList<Expression> expressions)
{
Expression last = expressions[expressions.Count - 1];
expressions = expressions.Select(e => e.Type.IsValueType ? Expression.Convert(e, typeof(object)) : e).ToList();
return Expression.Convert(Expression.Call(typeof(ExecutionBuilder), "Sequence", null, Expression.NewArrayInit(typeof(object), expressions)), last.Type);
return Expression.Convert(Expression.Call(typeof(ExecutionBuilder), nameof(ExecutionBuilder.Sequence), null, Expression.NewArrayInit(typeof(object), expressions)), last.Type);
}

public static object Sequence(params object[] values)
public static object Sequence(params object[] values)
{
return values[values.Length - 1];
}
Expand All @@ -101,7 +102,7 @@ public static object Sequence(params object[] values)

private static Expression MakeAssign(ParameterExpression variable, Expression value)
{
return Expression.Call(typeof(ExecutionBuilder), "Assign", new Type[] { variable.Type }, variable, value);
return Expression.Call(typeof(ExecutionBuilder), nameof(ExecutionBuilder.Assign), new Type[] { variable.Type }, variable, value);
}

public static T Assign<T>(ref T variable, T value)
Expand Down Expand Up @@ -160,7 +161,7 @@ protected override Expression VisitClientJoin(ClientJoinExpression join)
ProjectionExpression newProjection = new ProjectionExpression(join.Projection.Select, constructKVPair);

int iLookup = ++nLookup;
Expression execution = this.ExecuteProjection(newProjection, false);
Expression execution = this.ExecuteProjection(newProjection, okayToDefer: false, isTopLevel: false);

ParameterExpression kvp = Expression.Parameter(constructKVPair.Type, "kvp");

Expand All @@ -171,13 +172,13 @@ protected override Expression VisitClientJoin(ClientJoinExpression join)
Expression.PropertyOrField(kvp, "Value").NotEqual(TypeHelper.GetNullConstant(join.Projection.Projector.Type)),
kvp
);
execution = Expression.Call(typeof(Enumerable), "Where", new Type[] { kvp.Type }, execution, pred);
execution = Expression.Call(typeof(Enumerable), nameof(Enumerable.Where), new Type[] { kvp.Type }, execution, pred);
}

// make lookup
LambdaExpression keySelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Key"), kvp);
LambdaExpression elementSelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Value"), kvp);
Expression toLookup = Expression.Call(typeof(Enumerable), "ToLookup", new Type[] { kvp.Type, outerKey.Type, join.Projection.Projector.Type }, execution, keySelector, elementSelector);
Expression toLookup = Expression.Call(typeof(Enumerable), nameof(Enumerable.ToLookup), new Type[] { kvp.Type, outerKey.Type, join.Projection.Projector.Type }, execution, keySelector, elementSelector);

// 2) agg(lookup[outer])
ParameterExpression lookup = Expression.Parameter(toLookup.Type, "lookup" + iLookup);
Expand All @@ -200,7 +201,7 @@ protected override Expression VisitProjection(ProjectionExpression projection)
if (this.isTop)
{
this.isTop = false;
return this.ExecuteProjection(projection, this.scope != null);
return this.ExecuteProjection(projection, okayToDefer: this.scope != null, isTopLevel: true);
}
else
{
Expand All @@ -217,7 +218,7 @@ protected virtual Expression Parameterize(Expression expression)
return this.linguist.Parameterize(expression);
}

private Expression ExecuteProjection(ProjectionExpression projection, bool okayToDefer)
private Expression ExecuteProjection(ProjectionExpression projection, bool okayToDefer, bool isTopLevel)
{
// parameterize query
projection = (ProjectionExpression)this.Parameterize(projection);
Expand All @@ -233,10 +234,10 @@ private Expression ExecuteProjection(ProjectionExpression projection, bool okayT
QueryCommand command = new QueryCommand(commandText, namedValues.Select(v => new QueryParameter(v.Name, v.Type, v.QueryType)));
Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

return this.ExecuteProjection(projection, okayToDefer, command, values);
return this.ExecuteProjection(projection, okayToDefer, command, values, isTopLevel);
}

private Expression ExecuteProjection(ProjectionExpression projection, bool okayToDefer, QueryCommand command, Expression[] values)
private Expression ExecuteProjection(ProjectionExpression projection, bool okayToDefer, QueryCommand command, Expression[] values, bool isTopLevel)
{
okayToDefer &= (this.receivingMember != null && this.policy.IsDeferLoaded(this.receivingMember));

Expand All @@ -248,9 +249,9 @@ private Expression ExecuteProjection(ProjectionExpression projection, bool okayT

var entity = EntityFinder.Find(projection.Projector);

string methExecute = okayToDefer
? "ExecuteDeferred"
: "Execute";
string methExecute = okayToDefer
? nameof(QueryExecutor.ExecuteDeferred)
: nameof(QueryExecutor.Execute);

// call low-level execute directly on supplied DbQueryProvider
Expression result = Expression.Call(this.executor, methExecute, new Type[] { projector.Body.Type },
Expand All @@ -265,6 +266,7 @@ private Expression ExecuteProjection(ProjectionExpression projection, bool okayT
// apply aggregator
result = DbExpressionReplacer.Replace(projection.Aggregator.Body, projection.Aggregator.Parameters[0], result);
}

return result;
}

Expand All @@ -279,7 +281,7 @@ protected override Expression VisitBatch(BatchExpression batch)
var source = this.Visit(batch.Input);
var op = this.Visit(batch.Operation.Body);
var fn = Expression.Lambda(op, batch.Operation.Parameters[1]);
return Expression.Call(this.GetType(), "Batch", new Type[] {TypeHelper.GetElementType(source.Type), batch.Operation.Body.Type}, source, fn, batch.Stream);
return Expression.Call(typeof(ExecutionBuilder), nameof(ExecutionBuilder.Batch), new Type[] {TypeHelper.GetElementType(source.Type), batch.Operation.Body.Type}, source, fn, batch.Stream);
}
}

Expand All @@ -293,7 +295,7 @@ protected virtual Expression BuildExecuteBatch(BatchExpression batch)
QueryCommand command = new QueryCommand(commandText, namedValues.Select(v => new QueryParameter(v.Name, v.Type, v.QueryType)));
Expression[] values = namedValues.Select(v => Expression.Convert(this.Visit(v.Value), typeof(object))).ToArray();

Expression paramSets = Expression.Call(typeof(Enumerable), "Select", new Type[] { batch.Operation.Parameters[1].Type, typeof(object[]) },
Expression paramSets = Expression.Call(typeof(Enumerable), nameof(Enumerable.Select), new Type[] { batch.Operation.Parameters[1].Type, typeof(object[]) },
batch.Input,
Expression.Lambda(Expression.NewArrayInit(typeof(object), values), new[] { batch.Operation.Parameters[1] })
);
Expand All @@ -312,7 +314,7 @@ protected virtual Expression BuildExecuteBatch(BatchExpression batch)
var entity = EntityFinder.Find(projection.Projector);
command = new QueryCommand(command.CommandText, command.Parameters);

plan = Expression.Call(this.executor, "ExecuteBatch", new Type[] { projector.Body.Type },
plan = Expression.Call(this.executor, nameof(QueryExecutor.ExecuteBatch), new Type[] { projector.Body.Type },
Expression.Constant(command),
paramSets,
projector,
Expand All @@ -323,7 +325,7 @@ protected virtual Expression BuildExecuteBatch(BatchExpression batch)
}
else
{
plan = Expression.Call(this.executor, "ExecuteBatch", null,
plan = Expression.Call(this.executor, nameof(QueryExecutor.ExecuteBatch), null,
Expression.Constant(command),
paramSets,
batch.BatchSize,
Expand Down Expand Up @@ -390,7 +392,7 @@ protected override Expression VisitIf(IFCommand ifx)
ifx.IfFalse != null
? ifx.IfFalse
: ifx.IfTrue.Type == typeof(int)
? (Expression)Expression.Property(this.executor, "RowsAffected")
? (Expression)Expression.Property(this.executor, nameof(QueryExecutor.RowsAffected))
: (Expression)Expression.Constant(TypeHelper.GetDefault(ifx.IfTrue.Type), ifx.IfTrue.Type)
);
return this.Visit(test);
Expand All @@ -400,7 +402,7 @@ protected override Expression VisitFunction(FunctionExpression func)
{
if (this.linguist.Language.IsRowsAffectedExpressions(func))
{
return Expression.Property(this.executor, "RowsAffected");
return Expression.Property(this.executor, nameof(QueryExecutor.RowsAffected));
}
return base.VisitFunction(func);
}
Expand Down Expand Up @@ -478,10 +480,10 @@ protected virtual Expression BuildExecuteCommand(CommandExpression command)
ProjectionExpression projection = ProjectionFinder.FindProjection(expression);
if (projection != null)
{
return this.ExecuteProjection(projection, false, qc, values);
return this.ExecuteProjection(projection, false, qc, values, isTopLevel: true);
}

Expression plan = Expression.Call(this.executor, "ExecuteCommand", null,
var plan = Expression.Call(this.executor, nameof(QueryExecutor.ExecuteCommand), null,
Expression.Constant(qc),
Expression.NewArrayInit(typeof(object), values)
);
Expand Down
25 changes: 13 additions & 12 deletions src/IQToolkit.Data/Common/FieldReader.cs
Expand Up @@ -15,7 +15,7 @@ namespace IQToolkit.Data.Common
{
public abstract class FieldReader
{
TypeCode[] typeCodes;
private TypeCode[] typeCodes;

public FieldReader()
{
Expand Down Expand Up @@ -775,14 +775,6 @@ private TypeCode GetTypeCode(int ordinal)

public static MethodInfo GetReaderMethod(Type type)
{
if (_readerMethods == null)
{
var meths = typeof(FieldReader).GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.Name.StartsWith("Read")).ToList();
_readerMethods = meths.ToDictionary(m => m.ReturnType);
_miReadValue = meths.Single(m => m.Name == "ReadValue");
_miReadNullableValue = meths.Single(m => m.Name == "ReadNullableValue");
}

MethodInfo mi;
_readerMethods.TryGetValue(type, out mi);
if (mi == null)
Expand All @@ -796,12 +788,21 @@ public static MethodInfo GetReaderMethod(Type type)
mi = _miReadValue.MakeGenericMethod(type);
}
}

return mi;
}

static Dictionary<Type, MethodInfo> _readerMethods;
static MethodInfo _miReadValue;
static MethodInfo _miReadNullableValue;
static FieldReader()
{
var meths = typeof(FieldReader).GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(m => m.Name.StartsWith("Read")).ToList();
_readerMethods = meths.ToDictionary(m => m.ReturnType);
_miReadValue = meths.Single(m => m.Name == "ReadValue");
_miReadNullableValue = meths.Single(m => m.Name == "ReadNullableValue");
}

static readonly Dictionary<Type, MethodInfo> _readerMethods;
static readonly MethodInfo _miReadValue;
static readonly MethodInfo _miReadNullableValue;
}
}

Expand Down
33 changes: 2 additions & 31 deletions src/IQToolkit.Data/Common/QueryCommand.cs
Expand Up @@ -10,8 +10,8 @@ namespace IQToolkit.Data.Common
{
public class QueryCommand
{
string commandText;
ReadOnlyCollection<QueryParameter> parameters;
private readonly string commandText;
private readonly ReadOnlyCollection<QueryParameter> parameters;

public QueryCommand(string commandText, IEnumerable<QueryParameter> parameters)
{
Expand All @@ -29,33 +29,4 @@ public ReadOnlyCollection<QueryParameter> Parameters
get { return this.parameters; }
}
}

public class QueryParameter
{
string name;
Type type;
QueryType queryType;

public QueryParameter(string name, Type type, QueryType queryType)
{
this.name = name;
this.type = type;
this.queryType = queryType;
}

public string Name
{
get { return this.name; }
}

public Type Type
{
get { return this.type; }
}

public QueryType QueryType
{
get { return this.queryType; }
}
}
}

0 comments on commit 7afa129

Please sign in to comment.