Permalink
Browse files

With differentiates master and detail relationships

  • Loading branch information...
markrendle committed Jan 27, 2012
1 parent 712aab4 commit 3aee86bec3abb47bb613993da2bd86b9c264992a
@@ -38,31 +38,7 @@ IEnumerator IEnumerable.GetEnumerator()
private IEnumerable<IDictionary<string,object>> CreateObjectGraphs()
{
- var load = new Dictionary<IDictionary<string,object>,IDictionary<string, HashSet<IDictionary<string, object>>>>(new DictionaryEqualityComparer());
-
- foreach (var dict in _source)
- {
- IDictionary<string, HashSet<IDictionary<string, object>>> children;
-
- var main = new SubDictionary<string, object>(dict, s => !s.StartsWith("__with__"));
- if (!load.TryGetValue(main, out children))
- {
- children = new Dictionary<string, HashSet<IDictionary<string, object>>>();
- load.Add(main, children);
- }
-
- foreach (var tuple in ExtractObjects(dict))
- {
- if (children.ContainsKey(tuple.Item1))
- {
- children[tuple.Item1].Add(tuple.Item2);
- }
- else
- {
- children.Add(tuple.Item1, new HashSet<IDictionary<string, object>>(new DictionaryEqualityComparer()) {tuple.Item2});
- }
- }
- }
+ var load = BuildLoadDictionary();
IDictionary<string,int> index = null;
foreach (var kvp in load)
@@ -74,128 +50,94 @@ IEnumerator IEnumerable.GetEnumerator()
var row = new OptimizedDictionary<string, object>(index, kvp.Key.Values);
foreach (var sub in kvp.Value)
{
- if (sub.Value.Count == 1)
+ if (sub.Value.Single != null)
{
- kvp.Key[sub.Key] = sub.Value.Single();
+ row[sub.Key] = sub.Value.Single;
}
- else
+ else if (sub.Value.Collection != null)
{
- kvp.Key[sub.Key] = sub.Value.ToList();
+ row[sub.Key] = sub.Value.Collection.ToList();
}
}
- yield return kvp.Key;
+ yield return row;
}
}
- private IEnumerable<Tuple<string,Dictionary<string,object>>> ExtractObjects(IDictionary<string,object> source)
- {
- var names =
- source.Keys.Where(k => k.StartsWith("__with__")).Select(
- k => k.Split(new[] {"__"}, StringSplitOptions.RemoveEmptyEntries)[1]).ToList();
-
- return from name in names
- let pattern = "__with__" + name + "__"
- select Tuple.Create(name, source.Where(kvp => kvp.Key.StartsWith(pattern))
- .ToDictionary(kvp => kvp.Key.Replace(pattern, ""), kvp => kvp.Value));
- }
- }
-
- internal class SubDictionary<TKey,TValue> : IDictionary<TKey,TValue>
- {
- private readonly IDictionary<TKey, TValue> _super;
- private readonly Func<TKey, bool> _keyFilter;
-
- private IEnumerable<KeyValuePair<TKey, TValue>> Filter()
- {
- return _super.Where(kvp => _keyFilter(kvp.Key));
- }
-
- public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
- {
- return Filter().GetEnumerator();
- }
-
- public void Add(KeyValuePair<TKey, TValue> item)
- {
- _super.Add(item);
- }
-
- public void Clear()
- {
- _super.Clear();
- }
-
- public bool Contains(KeyValuePair<TKey, TValue> item)
- {
- return _super.Contains(item);
- }
-
- public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
- {
- Filter().ToArray().CopyTo(array, arrayIndex);
- }
-
- public bool Remove(KeyValuePair<TKey, TValue> item)
+ private Dictionary<IDictionary<string, object>, IDictionary<string, WithContainer>> BuildLoadDictionary()
{
- return _super.Remove(item);
- }
+ var load =
+ new Dictionary<IDictionary<string, object>, IDictionary<string, WithContainer>>(
+ new DictionaryEqualityComparer());
- public int Count
- {
- get { return Filter().Count(); }
- }
+ foreach (var dict in _source)
+ {
+ IDictionary<string, WithContainer> withContainers;
- public bool IsReadOnly
- {
- get { return _super.IsReadOnly; }
- }
+ var main = new SubDictionary<string, object>(dict, s => !s.StartsWith("__with"));
+ if (!load.TryGetValue(main, out withContainers))
+ {
+ withContainers = new Dictionary<string, WithContainer>();
+ load.Add(main, withContainers);
+ foreach (var tuple in ExtractSingleObjects(dict))
+ {
+ var withContainer = new WithContainer();
+ withContainer.SetSingle(tuple.Item2);
+ withContainers.Add(tuple.Item1, withContainer);
+ }
+ }
- public bool ContainsKey(TKey key)
- {
- return _keyFilter(key) && _super.ContainsKey(key);
+ foreach (var tuple in ExtractCollectionObjects(dict))
+ {
+ if (!withContainers.ContainsKey(tuple.Item1))
+ {
+ withContainers.Add(tuple.Item1, new WithContainer());
+ }
+ withContainers[tuple.Item1].AddToCollection(tuple.Item2);
+ }
+ }
+ return load;
}
- public void Add(TKey key, TValue value)
+ private class WithContainer
{
- _super.Add(key, value);
- }
+ public HashSet<IDictionary<string, object>> Collection { get; private set; }
- public bool Remove(TKey key)
- {
- return _super.Remove(key);
- }
+ public IDictionary<string, object> Single { get; private set; }
- public bool TryGetValue(TKey key, out TValue value)
- {
- return _super.TryGetValue(key, out value);
- }
+ public void AddToCollection(IDictionary<string,object> row)
+ {
+ if (Collection == null) Collection = new HashSet<IDictionary<string, object>>(new DictionaryEqualityComparer());
+ Collection.Add(row);
+ }
- public TValue this[TKey key]
- {
- get { return _super[key]; }
- set { _super[key] = value; }
+ public void SetSingle(IDictionary<string,object> row)
+ {
+ Single = row;
+ }
}
- public ICollection<TKey> Keys
+ private IEnumerable<Tuple<string,Dictionary<string,object>>> ExtractSingleObjects(IDictionary<string,object> source)
{
- get { return _super.Keys.Where(_keyFilter).ToList().AsReadOnly(); }
- }
+ var names =
+ source.Keys.Where(k => k.StartsWith("__with1__")).Select(
+ k => k.Split(new[] {"__"}, StringSplitOptions.RemoveEmptyEntries)[1]).Distinct().ToList();
- public ICollection<TValue> Values
- {
- get { return Filter().Select(kvp => kvp.Value).ToList().AsReadOnly(); }
+ return from name in names
+ let pattern = "__with1__" + name + "__"
+ select Tuple.Create(name, source.Where(kvp => kvp.Key.StartsWith(pattern))
+ .ToDictionary(kvp => kvp.Key.Replace(pattern, ""), kvp => kvp.Value, HomogenizedEqualityComparer.DefaultInstance));
}
-
- public SubDictionary(IDictionary<TKey, TValue> super, Func<TKey,bool> keyFilter)
+ private IEnumerable<Tuple<string,Dictionary<string,object>>> ExtractCollectionObjects(IDictionary<string,object> source)
{
- _super = super;
- _keyFilter = keyFilter;
- }
+ var names =
+ source.Keys.Where(k => k.StartsWith("__withn__")).Select(
+ k => k.Split(new[] {"__"}, StringSplitOptions.RemoveEmptyEntries)[1]).Distinct().ToList();
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
+ return from name in names
+ let pattern = "__withn__" + name + "__"
+ select Tuple.Create(name, source.Where(kvp => kvp.Key.StartsWith(pattern))
+ .ToDictionary(kvp => kvp.Key.Replace(pattern, ""), kvp => kvp.Value, HomogenizedEqualityComparer.DefaultInstance));
}
}
}
@@ -67,6 +67,18 @@ private void SetQueryContext(SimpleQuery query)
_columns = _table.Columns.Select(c => ObjectReference.FromStrings(_table.ActualName, c.ActualName)).ToArray();
}
+ HandleWithClauses();
+
+ _whereCriteria = _query.Clauses.OfType<WhereClause>().Aggregate(SimpleExpression.Empty,
+ (seed, where) => seed && where.Criteria);
+ _havingCriteria = _query.Clauses.OfType<HavingClause>().Aggregate(SimpleExpression.Empty,
+ (seed, having) => seed && having.Criteria);
+
+ _commandBuilder.SetText(GetSelectClause(_tableName));
+ }
+
+ private void HandleWithClauses()
+ {
var withClauses = _query.Clauses.OfType<WithClause>().ToList();
if (withClauses.Count > 0)
{
@@ -78,20 +90,24 @@ private void SetQueryContext(SimpleQuery query)
_columns.Concat(
_schema.FindTable(withClause.ObjectReference.GetName()).Columns.Select(
c => new ObjectReference(c.ActualName, withClause.ObjectReference)))
- .ToArray();
+ .ToArray();
}
}
_columns =
- _columns.OfType<ObjectReference>().Select(
- c => _schema.FindTable(c.GetOwner().GetName()) == _table ? c : c.As(string.Format("__with__{0}__{1}", c.GetOwner().GetAliasOrName(), c.GetName()))).ToArray();
+ _columns.OfType<ObjectReference>()
+ .Select(c => _schema.FindTable(c.GetOwner().GetName()) == _table ? c : AddWithAlias(c))
+ .ToArray();
}
+ }
- _whereCriteria = _query.Clauses.OfType<WhereClause>().Aggregate(SimpleExpression.Empty,
- (seed, where) => seed && where.Criteria);
- _havingCriteria = _query.Clauses.OfType<HavingClause>().Aggregate(SimpleExpression.Empty,
- (seed, having) => seed && having.Criteria);
-
- _commandBuilder.SetText(GetSelectClause(_tableName));
+ private ObjectReference AddWithAlias(ObjectReference c)
+ {
+ var relationType = _schema.GetRelationType(c.GetOwner().GetOwner().GetName(), c.GetOwner().GetName());
+ if (relationType == RelationType.None) throw new InvalidOperationException("No Join found");
+ return c.As(string.Format("__with{0}__{1}__{2}",
+ relationType == RelationType.OneToMany
+ ? "n"
+ : "1", c.GetOwner().GetAliasOrName(), c.GetName()));
}
private void HandleJoins()
@@ -115,5 +115,21 @@ public ObjectName BuildObjectName(String text)
if (schemaDotTable.Length != 2) throw new InvalidOperationException("Could not parse table name.");
return new ObjectName(schemaDotTable[0], schemaDotTable[1]);
}
+
+ public RelationType GetRelationType(string fromTableName, string toTableName)
+ {
+ var fromTable = FindTable(fromTableName);
+
+ if (fromTable.GetMaster(toTableName) != null) return RelationType.ManyToOne;
+ if (fromTable.GetDetail(toTableName) != null) return RelationType.OneToMany;
+ return RelationType.None;
+ }
+ }
+
+ public enum RelationType
+ {
+ None,
+ OneToMany,
+ ManyToOne
}
}
@@ -135,6 +135,7 @@
<Compile Include="Schema\TableJoin.cs" />
<Compile Include="Schema\TableType.cs" />
<Compile Include="ObjectName.cs" />
+ <Compile Include="SubDictionary.cs" />
<Compile Include="TraceHelper.cs" />
<Compile Include="TupleExtensions.cs" />
<Compile Include="TypeHelper.cs" />
Oops, something went wrong.

0 comments on commit 3aee86b

Please sign in to comment.