Skip to content

Commit bd983a3

Browse files
committed
Added Function support to InMemoryAdapter
1 parent 83a51ed commit bd983a3

5 files changed

Lines changed: 172 additions & 9 deletions

File tree

Simple.Data.Ado/DataReaderEnumerable.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ private void ExecuteReader()
139139
{
140140
try
141141
{
142+
_command.WriteTrace();
142143
_command.Connection.OpenIfClosed();
143144
_reader = _command.ExecuteReader();
144145
CreateIndexIfNecessary();

Simple.Data.Ado/QueryBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ private void InferWithType(WithClause withClause)
133133
var objectReference = withClause.ObjectReference;
134134
while (!ReferenceEquals(objectReference.GetOwner(), null))
135135
{
136-
var fromTable = _schema.FindTable(objectReference.GetName());
137-
var toTable = _schema.FindTable(objectReference.GetOwner().GetName());
136+
var toTable = _schema.FindTable(objectReference.GetName());
137+
var fromTable = _schema.FindTable(objectReference.GetOwner().GetName());
138138
if (_schema.GetRelationType(fromTable.ActualName, toTable.ActualName) == RelationType.OneToMany)
139139
{
140140
withClause.Type = WithType.Many;

Simple.Data.InMemoryTest/InMemoryTests.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,23 @@ public void TestJoin()
285285
Assert.AreEqual(1, customers.Count);
286286
}
287287

288+
[Test]
289+
public void TestJoinConfig()
290+
{
291+
var adapter = new InMemoryAdapter();
292+
adapter.Join.Master("Customer", "ID").Detail("Order", "CustomerID");
293+
Database.UseMockAdapter(adapter);
294+
var db = Database.Open();
295+
db.Customer.Insert(ID: 1, Name: "NASA");
296+
db.Customer.Insert(ID: 2, Name: "ACME");
297+
db.Order.Insert(ID: 1, CustomerID: 1, Date: new DateTime(1997, 1, 12));
298+
db.Order.Insert(ID: 2, CustomerID: 2, Date: new DateTime(2001, 1, 1));
299+
300+
var customers = db.Customer.FindAll(db.Customer.Order.Date < new DateTime(1999, 12, 31)).ToList();
301+
Assert.IsNotNull(customers);
302+
Assert.AreEqual(1, customers.Count);
303+
}
304+
288305
/// <summary>
289306
///A test for Find
290307
///</summary>
@@ -542,5 +559,57 @@ public void InsertAndGetWithTransactionShouldWork()
542559
Assert.AreEqual("Alice", record.Name);
543560
}
544561
}
562+
563+
[Test]
564+
public void ProcedureShouldWork()
565+
{
566+
var adapter = new InMemoryAdapter();
567+
adapter.AddFunction("Test", () => new Dictionary<string,object> { { "Foo", "Bar"}});
568+
Database.UseMockAdapter(adapter);
569+
var db = Database.Open();
570+
foreach (var row in db.Test())
571+
{
572+
Assert.AreEqual("Bar", row.Foo);
573+
}
574+
}
575+
576+
[Test]
577+
public void ProcedureWithParametersShouldWork()
578+
{
579+
var adapter = new InMemoryAdapter();
580+
adapter.AddFunction<string,object,IDictionary<string,object>>("Test", (key, value) => new Dictionary<string, object> { { key, value } });
581+
Database.UseMockAdapter(adapter);
582+
var db = Database.Open();
583+
foreach (var row in db.Test("Foo", "Bar"))
584+
{
585+
Assert.AreEqual("Bar", row.Foo);
586+
}
587+
}
588+
589+
[Test]
590+
public void ProcedureReturningArrayShouldWork()
591+
{
592+
var adapter = new InMemoryAdapter();
593+
adapter.AddFunction("Test", () => new[] { new Dictionary<string, object> { { "Foo", "Bar" } } });
594+
Database.UseMockAdapter(adapter);
595+
var db = Database.Open();
596+
foreach (var row in db.Test())
597+
{
598+
Assert.AreEqual("Bar", row.Foo);
599+
}
600+
}
601+
602+
[Test]
603+
public void ProcedureWithParametersReturningArrayShouldWork()
604+
{
605+
var adapter = new InMemoryAdapter();
606+
adapter.AddFunction<string, object, IDictionary<string, object>[]>("Test", (key, value) => new IDictionary<string, object>[] {new Dictionary<string, object> { { key, value } }});
607+
Database.UseMockAdapter(adapter);
608+
var db = Database.Open();
609+
foreach (var row in db.Test("Foo", "Bar"))
610+
{
611+
Assert.AreEqual("Bar", row.Foo);
612+
}
613+
}
545614
}
546615
}

Simple.Data/InMemoryAdapter.cs

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@
66
using System.Linq;
77
using QueryPolyfills;
88

9-
public partial class InMemoryAdapter : Adapter
9+
public partial class InMemoryAdapter : Adapter, IAdapterWithFunctions
1010
{
1111
private readonly Dictionary<string, string> _autoIncrementColumns = new Dictionary<string, string>();
1212
private readonly Dictionary<string, string[]> _keyColumns = new Dictionary<string, string[]>();
1313

1414
private readonly Dictionary<string, List<IDictionary<string, object>>> _tables =
1515
new Dictionary<string, List<IDictionary<string, object>>>();
1616

17-
private readonly ICollection<Join> _joins = new Collection<Join>();
17+
private readonly Dictionary<string, Delegate> _functions = new Dictionary<string, Delegate>();
18+
19+
private readonly ICollection<JoinInfo> _joins = new Collection<JoinInfo>();
1820

1921
private List<IDictionary<string, object>> GetTable(string tableName)
2022
{
@@ -208,12 +210,17 @@ public void SetKeyColumns(string tableName, params string[] columnNames)
208210
/// <param name="detailPropertyName">The name to give the collection property in the master object</param>
209211
public void ConfigureJoin(string masterTableName, string masterKey, string masterPropertyName, string detailTableName, string detailKey, string detailPropertyName)
210212
{
211-
var join = new Join(masterTableName, masterKey, masterPropertyName, detailTableName, detailKey,
213+
var join = new JoinInfo(masterTableName, masterKey, masterPropertyName, detailTableName, detailKey,
212214
detailPropertyName);
213215
_joins.Add(join);
214216
}
215217

216-
public class Join
218+
public JoinConfig Join
219+
{
220+
get { return new JoinConfig(_joins);}
221+
}
222+
223+
internal class JoinInfo
217224
{
218225
private readonly string _masterTableName;
219226
private readonly string _masterKey;
@@ -222,7 +229,7 @@ public class Join
222229
private readonly string _detailKey;
223230
private readonly string _detailPropertyName;
224231

225-
public Join(string masterTableName, string masterKey, string masterPropertyName, string detailTableName, string detailKey, string detailPropertyName)
232+
public JoinInfo(string masterTableName, string masterKey, string masterPropertyName, string detailTableName, string detailKey, string detailPropertyName)
226233
{
227234
_masterTableName = masterTableName;
228235
_masterKey = masterKey;
@@ -282,5 +289,91 @@ public IDictionary<string, object> Get(string tableName, IAdapterTransaction tra
282289
{
283290
return Get(tableName, parameterValues);
284291
}
292+
293+
public class JoinConfig
294+
{
295+
private readonly ICollection<JoinInfo> _joins;
296+
private JoinInfo _joinInfo;
297+
298+
internal JoinConfig(ICollection<JoinInfo> joins)
299+
{
300+
_joins = joins;
301+
_joinInfo = new JoinInfo(null,null,null,null,null,null);
302+
}
303+
304+
public JoinConfig Master(string tableName, string keyName, string propertyNameInDetailRecords = null)
305+
{
306+
if (_joins.Contains(_joinInfo)) _joins.Remove(_joinInfo);
307+
_joinInfo = new JoinInfo(tableName, keyName, propertyNameInDetailRecords ?? tableName, _joinInfo.DetailTableName,
308+
_joinInfo.DetailKey, _joinInfo.DetailPropertyName);
309+
_joins.Add(_joinInfo);
310+
return this;
311+
}
312+
313+
314+
public JoinConfig Detail(string tableName, string keyName, string propertyNameInMasterRecords = null)
315+
{
316+
if (_joins.Contains(_joinInfo)) _joins.Remove(_joinInfo);
317+
_joinInfo = new JoinInfo(_joinInfo.MasterTableName, _joinInfo.MasterKey, _joinInfo.MasterPropertyName,
318+
tableName, keyName,
319+
propertyNameInMasterRecords ?? tableName);
320+
_joins.Add(_joinInfo);
321+
return this;
322+
}
323+
}
324+
325+
public void AddFunction<TResult>(string functionName, Func<TResult> function)
326+
{
327+
_functions.Add(functionName, function);
328+
}
329+
330+
public void AddFunction<T,TResult>(string functionName, Func<T,TResult> function)
331+
{
332+
_functions.Add(functionName, function);
333+
}
334+
335+
public void AddFunction<T1,T2,TResult>(string functionName, Func<T1,T2,TResult> function)
336+
{
337+
_functions.Add(functionName, function);
338+
}
339+
340+
public void AddFunction<T1,T2,T3,TResult>(string functionName, Func<T1,T2,T3,TResult> function)
341+
{
342+
_functions.Add(functionName, function);
343+
}
344+
345+
public void AddFunction<T1, T2, T3, T4, TResult>(string functionName, Func<T1, T2, T3, T4, TResult> function)
346+
{
347+
_functions.Add(functionName, function);
348+
}
349+
350+
public void AddDelegate(string functionName, Delegate function)
351+
{
352+
_functions.Add(functionName, function);
353+
}
354+
355+
public bool IsValidFunction(string functionName)
356+
{
357+
return _functions.ContainsKey(functionName);
358+
}
359+
360+
public IEnumerable<IEnumerable<IEnumerable<KeyValuePair<string, object>>>> Execute(string functionName, IDictionary<string, object> parameters)
361+
{
362+
if (!_functions.ContainsKey(functionName)) throw new InvalidOperationException("No function found with that name.");
363+
var obj = _functions[functionName].DynamicInvoke(parameters.Values.ToArray());
364+
365+
var dict = obj as IDictionary<string, object>;
366+
if (dict != null) return new List<IEnumerable<IDictionary<string, object>>> { new List<IDictionary<string, object>> { dict } };
367+
368+
var list = obj as IEnumerable<IDictionary<string, object>>;
369+
if (list != null) return new List<IEnumerable<IDictionary<string, object>>> { list };
370+
371+
return obj as IEnumerable<IEnumerable<IDictionary<string, object>>>;
372+
}
373+
374+
public IEnumerable<IEnumerable<IEnumerable<KeyValuePair<string, object>>>> Execute(string functionName, IDictionary<string, object> parameters, IAdapterTransaction transaction)
375+
{
376+
return Execute(functionName, parameters);
377+
}
285378
}
286379
}

Simple.Data/SimpleQuery.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ public SimpleQuery OuterJoin(ObjectReference objectReference, out dynamic queryO
427427
public SimpleQuery On(SimpleExpression joinExpression)
428428
{
429429
if (_tempJoinWaitingForOn == null)
430-
throw new InvalidOperationException("Call to On must be preceded by call to Join.");
430+
throw new InvalidOperationException("Call to On must be preceded by call to JoinInfo.");
431431
return AddNewJoin(new JoinClause(_tempJoinWaitingForOn.Table, _tempJoinWaitingForOn.JoinType, joinExpression));
432432
}
433433

@@ -474,7 +474,7 @@ private SimpleQuery ParseJoin(InvokeMemberBinder binder, object[] args)
474474
private SimpleQuery ParseOn(InvokeMemberBinder binder, IEnumerable<object> args)
475475
{
476476
if (_tempJoinWaitingForOn == null)
477-
throw new InvalidOperationException("Call to On must be preceded by call to Join.");
477+
throw new InvalidOperationException("Call to On must be preceded by call to JoinInfo.");
478478
var joinExpression = ExpressionHelper.CriteriaDictionaryToExpression(_tempJoinWaitingForOn.Table,
479479
binder.NamedArgumentsToDictionary(args));
480480
return AddNewJoin(new JoinClause(_tempJoinWaitingForOn.Table, _tempJoinWaitingForOn.JoinType, joinExpression));

0 commit comments

Comments
 (0)