1 //---------------------------------------------------------------------
2 // <copyright file="RewritingProcessor.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
11 using System.Diagnostics;
12 using System.Collections.Generic;
15 namespace System.Data.Mapping.ViewGeneration.QueryRewriting
17 internal abstract class TileProcessor<T_Tile>
19 internal abstract bool IsEmpty(T_Tile tile);
20 internal abstract T_Tile Union(T_Tile a, T_Tile b);
21 internal abstract T_Tile Join(T_Tile a, T_Tile b);
22 internal abstract T_Tile AntiSemiJoin(T_Tile a, T_Tile b);
24 internal abstract T_Tile GetArg1(T_Tile tile);
25 internal abstract T_Tile GetArg2(T_Tile tile);
26 internal abstract TileOpKind GetOpKind(T_Tile tile);
29 internal class RewritingProcessor<T_Tile> : TileProcessor<T_Tile> where T_Tile : class
31 public double PERMUTE_FRACTION = 0.0;
32 public int MIN_PERMUTATIONS = 0;
33 public int MAX_PERMUTATIONS = 0;
34 public bool REORDER_VIEWS = false;
36 private int m_numSATChecks;
37 private int m_numIntersection;
38 private int m_numDifference;
39 private int m_numUnion;
41 private int m_numErrors;
43 private TileProcessor<T_Tile> m_tileProcessor;
45 public RewritingProcessor(TileProcessor<T_Tile> tileProcessor)
47 m_tileProcessor = tileProcessor;
50 internal TileProcessor<T_Tile> TileProcessor
52 get { return m_tileProcessor; }
55 public void GetStatistics(out int numSATChecks, out int numIntersection, out int numUnion, out int numDifference, out int numErrors)
57 numSATChecks = m_numSATChecks;
58 numIntersection = m_numIntersection;
59 numUnion = m_numUnion;
60 numDifference = m_numDifference;
61 numErrors = m_numErrors;
64 public void PrintStatistics()
66 Console.WriteLine("{0} containment checks, {4} set operations ({1} intersections + {2} unions + {3} differences)",
67 m_numSATChecks, m_numIntersection, m_numUnion, m_numDifference,
68 m_numIntersection + m_numUnion + m_numDifference);
69 Console.WriteLine("{0} errors", m_numErrors);
72 internal override T_Tile GetArg1(T_Tile tile)
74 return m_tileProcessor.GetArg1(tile);
77 internal override T_Tile GetArg2(T_Tile tile)
79 return m_tileProcessor.GetArg2(tile);
82 internal override TileOpKind GetOpKind(T_Tile tile)
84 return m_tileProcessor.GetOpKind(tile);
87 internal override bool IsEmpty(T_Tile a)
90 return m_tileProcessor.IsEmpty(a);
93 public bool IsDisjointFrom(T_Tile a, T_Tile b)
95 return m_tileProcessor.IsEmpty(Join(a, b));
98 internal bool IsContainedIn(T_Tile a, T_Tile b)
100 T_Tile difference = AntiSemiJoin(a, b);
101 return IsEmpty(difference);
104 internal bool IsEquivalentTo(T_Tile a, T_Tile b)
106 bool aInB = IsContainedIn(a, b);
107 bool bInA = IsContainedIn(b, a);
111 internal override T_Tile Union(T_Tile a, T_Tile b)
114 return m_tileProcessor.Union(a, b);
117 internal override T_Tile Join(T_Tile a, T_Tile b)
124 return m_tileProcessor.Join(a, b);
127 internal override T_Tile AntiSemiJoin(T_Tile a, T_Tile b)
130 return m_tileProcessor.AntiSemiJoin(a, b);
133 public void AddError()
138 public int CountOperators(T_Tile query)
143 if (GetOpKind(query) != TileOpKind.Named)
146 count += CountOperators(GetArg1(query));
147 count += CountOperators(GetArg2(query));
153 public int CountViews(T_Tile query)
155 HashSet<T_Tile> views = new HashSet<T_Tile>();
156 GatherViews(query, views);
160 public void GatherViews(T_Tile rewriting, HashSet<T_Tile> views)
162 if (rewriting != null)
164 if (GetOpKind(rewriting) == TileOpKind.Named)
166 views.Add(rewriting);
170 GatherViews(GetArg1(rewriting), views);
171 GatherViews(GetArg2(rewriting), views);
176 public static IEnumerable<T> AllButOne<T>(IEnumerable<T> list, int toSkipPosition)
178 int valuePosition = 0;
179 foreach (T value in list)
181 if (valuePosition++ != toSkipPosition)
188 public static IEnumerable<T> Concat<T>(T value, IEnumerable<T> rest)
191 foreach (T restValue in rest)
193 yield return restValue;
197 public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> list)
199 IEnumerable<T> rest = null;
200 int valuePosition = 0;
201 foreach (T value in list)
203 rest = AllButOne<T>(list, valuePosition++);
204 foreach (IEnumerable<T> restPermutation in Permute<T>(rest))
206 yield return Concat<T>(value, restPermutation);
211 yield return list; // list is empty enumeration
215 static Random rnd = new Random(1507);
216 public static List<T> RandomPermutation<T>(IEnumerable<T> input)
218 List<T> output = new List<T>(input);
219 for (int i = 0; i < output.Count; i++)
221 int j = rnd.Next(output.Count);
223 output[i] = output[j];
229 public static IEnumerable<T> Reverse<T>(IEnumerable<T> input, HashSet<T> filter)
231 List<T> output = new List<T>(input);
233 foreach (T t in output)
235 if (filter.Contains(t))
242 public bool RewriteQuery(T_Tile toFill, T_Tile toAvoid, IEnumerable<T_Tile> views, out T_Tile rewriting)
244 if (RewriteQueryOnce(toFill, toAvoid, views, out rewriting))
246 HashSet<T_Tile> usedViews = new HashSet<T_Tile>();
247 GatherViews(rewriting, usedViews);
248 int opCount = CountOperators(rewriting);
250 // try several permutations of views, pick one with fewer operators
252 int permuteTries = 0;
253 int numPermutations = Math.Min(MAX_PERMUTATIONS, Math.Max(MIN_PERMUTATIONS, (int)(usedViews.Count * PERMUTE_FRACTION)));
254 while (permuteTries++ < numPermutations)
256 IEnumerable<T_Tile> permutedViews;
257 if (permuteTries == 1)
259 permutedViews = Reverse(views, usedViews);
263 permutedViews = RandomPermutation(usedViews); // Tradeoff: views vs. usedViews!
265 bool succeeded = RewriteQueryOnce(toFill, toAvoid, permutedViews, out newRewriting);
266 Debug.Assert(succeeded);
267 int newOpCount = CountOperators(newRewriting);
268 if (newOpCount < opCount)
270 opCount = newOpCount;
271 rewriting = newRewriting;
273 HashSet<T_Tile> newUsedViews = new HashSet<T_Tile>();
274 GatherViews(newRewriting, newUsedViews);
275 usedViews = newUsedViews; // can only be fewer!
282 public bool RewriteQueryOnce(T_Tile toFill, T_Tile toAvoid, IEnumerable<T_Tile> views, out T_Tile rewriting)
284 List<T_Tile> viewList = new List<T_Tile>(views);
285 return RewritingPass<T_Tile>.RewriteQuery(toFill, toAvoid, out rewriting, viewList, this);