Skip to content

Commit 5631ee9

Browse files
committed
Added support for Length function
1 parent 7a2332c commit 5631ee9

7 files changed

Lines changed: 127 additions & 48 deletions

File tree

Simple.Data.UnitTest/DictionaryQueryRunnerTest.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,29 @@ public void SelectShouldRestrictColumnList()
9393
Assert.AreEqual("David", actual[3]["Name"]);
9494
}
9595

96+
[Test]
97+
public void SelectLengthShouldUseLengthFunction()
98+
{
99+
var tableRef = new ObjectReference("FooTable");
100+
var function = new FunctionReference("Length", new ObjectReference("Name", tableRef)).As("NameLength");
101+
var selectClause = new SelectClause(new SimpleReference[] { new ObjectReference("Name", tableRef), function });
102+
var runner = new DictionaryQueryRunner(SelectSource(), selectClause);
103+
var actual = runner.Run().ToList();
104+
Assert.AreEqual(4, actual.Count);
105+
Assert.AreEqual(2, actual[0].Count);
106+
Assert.AreEqual("Alice", actual[0]["Name"]);
107+
Assert.AreEqual(5, actual[0]["NameLength"]);
108+
Assert.AreEqual(2, actual[1].Count);
109+
Assert.AreEqual("Bob", actual[1]["Name"]);
110+
Assert.AreEqual(3, actual[1]["NameLength"]);
111+
Assert.AreEqual(2, actual[2].Count);
112+
Assert.AreEqual("Charlie", actual[2]["Name"]);
113+
Assert.AreEqual(7, actual[2]["NameLength"]);
114+
Assert.AreEqual(2, actual[3].Count);
115+
Assert.AreEqual("David", actual[3]["Name"]);
116+
Assert.AreEqual(5, actual[3]["NameLength"]);
117+
}
118+
96119
#region Distinct sources
97120

98121
private static IEnumerable<IDictionary<string, object>> DuplicatingSource()

Simple.Data/FunctionReference.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ public string Alias
5555
get { return _alias; }
5656
}
5757

58+
/// <summary>
59+
/// Gets the name of the referenced object.
60+
/// </summary>
61+
/// <returns>The name.</returns>
62+
public string GetAliasOrName()
63+
{
64+
return _alias ?? _name;
65+
}
66+
5867
public bool IsAggregate
5968
{
6069
get { return _isAggregate; }

Simple.Data/ObjectReference.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public ObjectReference GetTop()
5959

6060
protected internal override DataStrategy FindDataStrategyInHierarchy()
6161
{
62-
return _dataStrategy ?? (_owner == null ? null : _owner.FindDataStrategyInHierarchy());
62+
return _dataStrategy ?? (ReferenceEquals(_owner, null) ? null : _owner.FindDataStrategyInHierarchy());
6363
}
6464

6565
/// <summary>
@@ -71,6 +71,15 @@ public string GetName()
7171
return _name;
7272
}
7373

74+
/// <summary>
75+
/// Gets the name of the referenced object.
76+
/// </summary>
77+
/// <returns>The name.</returns>
78+
public string GetAliasOrName()
79+
{
80+
return _alias ?? _name;
81+
}
82+
7483
public ObjectReference As(string alias)
7584
{
7685
return new ObjectReference(_name, _owner, _dataStrategy, alias);

Simple.Data/QueryPolyfills/DictionaryQueryRunner.cs

Lines changed: 0 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
namespace Simple.Data.QueryPolyfills
22
{
33
using System;
4-
using System.Collections.Concurrent;
54
using System.Collections.Generic;
65
using System.Linq;
76

@@ -59,50 +58,4 @@ public IEnumerable<IDictionary<string, object>> Run()
5958
return source;
6059
}
6160
}
62-
63-
class SelectClauseHandler
64-
{
65-
private readonly IList<SimpleReference> _references;
66-
private readonly IList<ObjectReference> _objectReferences;
67-
private Func<int, IDictionary<string, object>> _creator;
68-
69-
public SelectClauseHandler(SelectClause clause)
70-
{
71-
_references = clause.Columns.ToList();
72-
_objectReferences = _references.Select(r => r as ObjectReference).ToList();
73-
}
74-
75-
public IEnumerable<IDictionary<string,object>> Run(IEnumerable<IDictionary<string,object>> source)
76-
{
77-
return source.Select(Run);
78-
}
79-
80-
private IDictionary<string,object> Run(IDictionary<string,object> source)
81-
{
82-
if (_creator == null) _creator = CreateCreator(source);
83-
var target = _creator(_references.Count);
84-
for (int i = 0; i < _objectReferences.Count; i++)
85-
{
86-
if (!ReferenceEquals(_objectReferences[i], null))
87-
{
88-
var name = _objectReferences[i].GetName();
89-
target[name] = source[name];
90-
}
91-
}
92-
return target;
93-
}
94-
95-
private Func<int, IDictionary<string, object>> CreateCreator(IDictionary<string,object> source)
96-
{
97-
var dictionary = source as Dictionary<string, object>;
98-
if (dictionary != null) return cap => new Dictionary<string, object>(cap, dictionary.Comparer);
99-
var sortedDictionary = source as SortedDictionary<string, object>;
100-
if (sortedDictionary != null) return cap => new SortedDictionary<string, object>(sortedDictionary.Comparer);
101-
var concurrentDictionary = source as ConcurrentDictionary<string, object>;
102-
if (concurrentDictionary != null) return cap => new ConcurrentDictionary<string, object>();
103-
104-
var type = source.GetType();
105-
return cap => (IDictionary<string, object>) Activator.CreateInstance(type);
106-
}
107-
}
10861
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
namespace Simple.Data.QueryPolyfills
2+
{
3+
using System;
4+
using System.Collections.Concurrent;
5+
using System.Collections.Generic;
6+
using System.Linq;
7+
8+
class SelectClauseHandler
9+
{
10+
private readonly IList<SimpleReference> _references;
11+
private readonly IList<ObjectReference> _objectReferences;
12+
private readonly IList<FunctionReference> _functionReferences;
13+
private Func<int, IDictionary<string, object>> _creator;
14+
15+
public SelectClauseHandler(SelectClause clause)
16+
{
17+
_references = clause.Columns.ToList();
18+
_objectReferences = _references.Select(r => r as ObjectReference).ToList();
19+
_functionReferences = _references.Select(r => r as FunctionReference).ToList();
20+
}
21+
22+
public IEnumerable<IDictionary<string,object>> Run(IEnumerable<IDictionary<string,object>> source)
23+
{
24+
return source.Select(Run);
25+
}
26+
27+
private IDictionary<string,object> Run(IDictionary<string,object> source)
28+
{
29+
if (_creator == null) _creator = CreateCreator(source);
30+
var target = _creator(_references.Count);
31+
for (int i = 0; i < _references.Count; i++)
32+
{
33+
bool _ = TryCopyAsObjectReference(_objectReferences[i], source, target)
34+
|| TryCopyAsFunctionReference(_functionReferences[i], source, target);
35+
}
36+
return target;
37+
}
38+
39+
private static bool TryCopyAsObjectReference(ObjectReference reference, IDictionary<string, object> source, IDictionary<string, object> target)
40+
{
41+
if (reference.IsNull()) return false;
42+
target[reference.GetAliasOrName()] = source[reference.GetName()];
43+
return true;
44+
}
45+
46+
private static bool TryCopyAsFunctionReference(FunctionReference reference, IDictionary<string, object> source, IDictionary<string, object> target)
47+
{
48+
if (reference.IsNull()) return false;
49+
var argument = (ObjectReference) reference.Argument;
50+
target[reference.GetAliasOrName()] = ApplyFunction(reference, source[argument.GetName()]);
51+
return true;
52+
}
53+
54+
private static object ApplyFunction(FunctionReference function, object value)
55+
{
56+
if (function.Name.Equals("length", StringComparison.OrdinalIgnoreCase))
57+
{
58+
return value == null ? 0 : value.ToString().Length;
59+
}
60+
return value;
61+
}
62+
63+
private Func<int, IDictionary<string, object>> CreateCreator(IDictionary<string, object> source)
64+
{
65+
var dictionary = source as Dictionary<string, object>;
66+
if (dictionary != null) return cap => new Dictionary<string, object>(cap, dictionary.Comparer);
67+
var sortedDictionary = source as SortedDictionary<string, object>;
68+
if (sortedDictionary != null) return cap => new SortedDictionary<string, object>(sortedDictionary.Comparer);
69+
var concurrentDictionary = source as ConcurrentDictionary<string, object>;
70+
if (concurrentDictionary != null) return cap => new ConcurrentDictionary<string, object>();
71+
72+
var type = source.GetType();
73+
return cap => (IDictionary<string, object>) Activator.CreateInstance(type);
74+
}
75+
}
76+
}

Simple.Data/Simple.Data.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
<Compile Include="OrderByClause.cs" />
9999
<Compile Include="OrderByDirection.cs" />
100100
<Compile Include="Promise.cs" />
101+
<Compile Include="QueryPolyfills\SelectClauseHandler.cs" />
101102
<Compile Include="Range.cs" />
102103
<Compile Include="Range1.cs" />
103104
<Compile Include="SelectClause.cs" />

Simple.Data/SimpleReference.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,12 @@ protected internal virtual DataStrategy FindDataStrategyInHierarchy()
99
return null;
1010
}
1111
}
12+
13+
public static class SimpleReferenceEx
14+
{
15+
public static bool IsNull(this SimpleReference reference)
16+
{
17+
return ReferenceEquals(reference, null);
18+
}
19+
}
1220
}

0 commit comments

Comments
 (0)