Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / Map / ViewGeneration / Structures / OpCellTreeNode.cs / 2 / OpCellTreeNode.cs
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System.Data.Common.Utils;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Mapping.ViewGeneration.CqlGeneration;
using System.Data.Mapping.ViewGeneration.QueryRewriting;
using System.Text;
using System.Linq;
using System.Diagnostics;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping.ViewGeneration.Structures {
using AttributeSet = Set;
// This class represents th intermediate nodes in the tree (non-leaf nodes)
internal class OpCellTreeNode : CellTreeNode {
#region Constructors
// effects: Creates a node with operation opType and no children
internal OpCellTreeNode(CellNormalizer normalizer, CellTreeOpType opType)
: base(normalizer) {
m_opType = opType;
m_attrs = new AttributeSet(MemberPath.EqualityComparer);
m_children = new List();
}
internal OpCellTreeNode(CellNormalizer normalizer, CellTreeOpType opType, params CellTreeNode[] children)
: this(normalizer, opType, (IEnumerable)children) { }
// effects: Given a sequence of children node and the opType, creates
// an OpCellTreeNode and returns it
internal OpCellTreeNode(CellNormalizer normalizer, CellTreeOpType opType, IEnumerable children)
: this(normalizer, opType) {
// Add the children one by one so that we can get the attrs etc fixed
foreach (CellTreeNode child in children) {
Add(child);
}
}
#endregion
#region Fields
private Set m_attrs; // attributes from whole subtree below
private List m_children;
private CellTreeOpType m_opType;
private FragmentQuery m_leftFragmentQuery;
private FragmentQuery m_rightFragmentQuery;
#endregion
#region Properties
// effects: See CellTreeNode.OpType
internal override CellTreeOpType OpType { get { return m_opType; } }
// fragment query superseeds SelectionDomain
internal override FragmentQuery LeftFragmentQuery
{
get
{
if (m_leftFragmentQuery == null)
{
Debug.Assert(Children.Count > 0);
FragmentQuery leftFragmentQuery = Children[0].LeftFragmentQuery;
FragmentQueryProcessor leftQP = CellNormalizer.LeftFragmentQP;
for (int i = 1; i < Children.Count; i++)
{
FragmentQuery nextLeftQuery = Children[i].LeftFragmentQuery;
switch (OpType)
{
case CellTreeOpType.IJ:
leftFragmentQuery = leftQP.Intersect(leftFragmentQuery, nextLeftQuery);
break;
case CellTreeOpType.LOJ:
// Left outer join means keeping the domain of the leftmost child
break;
case CellTreeOpType.LASJ:
// not used in basic view generation but current validation calls Simplify, so add this for debugging
leftFragmentQuery = leftQP.Difference(leftFragmentQuery, nextLeftQuery);
break;
default:
// All other operators (Union, FOJ) require union of the domains
leftFragmentQuery = leftQP.Union(leftFragmentQuery, nextLeftQuery);
break;
}
}
m_leftFragmentQuery = leftFragmentQuery;
}
return m_leftFragmentQuery;
}
}
internal override FragmentQuery RightFragmentQuery
{
get
{
if (m_rightFragmentQuery == null)
{
Debug.Assert(Children.Count > 0);
FragmentQuery rightFragmentQuery = Children[0].RightFragmentQuery;
FragmentQueryProcessor rightQP = CellNormalizer.RightFragmentQP;
for (int i = 1; i < Children.Count; i++)
{
FragmentQuery nextRightQuery = Children[i].RightFragmentQuery;
switch (OpType)
{
case CellTreeOpType.IJ:
rightFragmentQuery = rightQP.Intersect(rightFragmentQuery, nextRightQuery);
break;
case CellTreeOpType.LOJ:
// Left outer join means keeping the domain of the leftmost child
break;
case CellTreeOpType.LASJ:
// not used in basic view generation but current validation calls Simplify, so add this for debugging
rightFragmentQuery = rightQP.Difference(rightFragmentQuery, nextRightQuery);
break;
default:
// All other operators (Union, FOJ) require union of the domains
rightFragmentQuery = rightQP.Union(rightFragmentQuery, nextRightQuery);
break;
}
}
m_rightFragmentQuery = rightFragmentQuery;
}
return m_rightFragmentQuery;
}
}
// effects: See CellTreeNode.RightDomainMap
internal override MemberDomainMap RightDomainMap {
get {
// Get the information from one of the children
Debug.Assert(m_children[0].RightDomainMap != null, "EdmMember domain map missing");
return m_children[0].RightDomainMap;
}
}
// effects: See CellTreeNode.Attributes
internal override Set Attributes { get { return m_attrs; } }
// effects: See CellTreeNode.Children
internal override List Children { get { return m_children; } }
internal override int NumProjectedSlots {
get {
// All children have the same number of slots
Debug.Assert(m_children.Count > 1, "No children for op node?");
return m_children[0].NumProjectedSlots;
}
}
internal override int NumBoolSlots {
get {
Debug.Assert(m_children.Count > 1, "No children for op node?");
return m_children[0].NumBoolSlots;
}
}
#endregion
#region Methods
internal override TOutput Accept(SimpleCellTreeVisitor visitor, TInput param) {
return visitor.VisitOpNode(this, param);
}
internal override TOutput Accept(CellTreeVisitor visitor, TInput param) {
switch (OpType) {
case CellTreeOpType.IJ:
return visitor.VisitInnerJoin(this, param);
case CellTreeOpType.LOJ:
return visitor.VisitLeftOuterJoin(this, param);
case CellTreeOpType.Union:
return visitor.VisitUnion(this, param);
case CellTreeOpType.FOJ:
return visitor.VisitFullOuterJoin(this, param);
case CellTreeOpType.LASJ:
return visitor.VisitLeftAntiSemiJoin(this, param);
default:
Debug.Fail("Unexpected optype: " + OpType);
// To satsfy the compiler
return visitor.VisitInnerJoin(this, param);
}
}
// effects: Add child to the end of the current children list
// while ensuring the constants and attributes of the child are
// propagated into this (i.e., unioned)
internal void Add(CellTreeNode child) {
Insert(m_children.Count, child);
}
// effects: Add child at the beginning of the current children list
// while ensuring the constants and attributes of the child are
// propagated into this (i.e., unioned)
internal void AddFirst(CellTreeNode child) {
Insert(0, child);
}
// effects: Inserts child at "index" while ensuring the constants
// and attributes of the child are propagated into this
private void Insert(int index, CellTreeNode child) {
m_attrs.Unite(child.Attributes);
m_children.Insert(index, child);
// reset fragmentQuery so it's recomputed when property FragmentQuery is accessed
m_leftFragmentQuery = null;
m_rightFragmentQuery = null;
}
// effects: Given the required slots by the parent,
// generates a CqlBlock tree for the tree rooted below node
internal override CqlBlock ToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum,
ref List withStatements)
{
// Dispatch depending on whether we have a union node or join node
CqlBlock result;
if (OpType == CellTreeOpType.Union) {
result = UnionToCqlBlock(requiredSlots, identifiers, ref blockAliasNum, ref withStatements);
} else {
result = JoinToCqlBlock(requiredSlots, identifiers, ref blockAliasNum, ref withStatements);
}
return result;
}
internal override bool IsProjectedSlot(int slot) {
// If any childtree projects it, return true
foreach (CellTreeNode childNode in Children) {
if (childNode.IsProjectedSlot(slot)) {
return true;
}
}
return false;
}
#endregion
#region Union CqlBLock Methods
// requires: node corresponds to a Union node
// effects: Given a union node and the slots required by the parent,
// generates a CqlBlock for the subtree rooted at node
private CqlBlock UnionToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List withStatements)
{
Debug.Assert(OpType == CellTreeOpType.Union);
List children = new List();
List aliasedSlotsForAddedByChildren = new List();
int totalSlots = requiredSlots.Length;
foreach (CellTreeNode child in Children) {
// Unlike Join, we pass the requiredSlots from the parent as the requirement
// CqlBlock childBlock = child.ToCqlBlock(requiredSlots, identifiers, ref blockAliasNum);
bool[] childProjectedSlots = child.GetProjectedSlots();
AndWith(childProjectedSlots, requiredSlots);
CqlBlock childBlock = child.ToCqlBlock(childProjectedSlots, identifiers, ref blockAliasNum, ref withStatements);
for (int aliasedSlotNumber = childProjectedSlots.Length; aliasedSlotNumber < childBlock.Slots.Count; aliasedSlotNumber++)
{
SlotInfo slotInfo = childBlock.Slots[aliasedSlotNumber];
aliasedSlotsForAddedByChildren.Add(new AliasedSlot(childBlock, slotInfo.SlotValue, slotInfo.MemberPath, aliasedSlotNumber));
}
// if required, but not projected, add NULL
SlotInfo[] paddedSlotInfo = new SlotInfo[childBlock.Slots.Count];
ReadOnlyCollection childSlotInfo = childBlock.Slots;
for (int slotNum = 0; slotNum < totalSlots; slotNum++)
{
if (requiredSlots[slotNum] && !childProjectedSlots[slotNum])
{
if (IsBoolSlot(slotNum))
{
paddedSlotInfo[slotNum] = new SlotInfo(true /* is required */, true /* is projected */,
new BooleanProjectedSlot(BoolExpression.False, identifiers, SlotToBoolIndex(slotNum)), null /* member path*/);
}
else
{
// NULL as projected slot
paddedSlotInfo[slotNum] = new SlotInfo(true /* is required */, true /* is projected */,
new ConstantSlot(CellConstant.Null), childSlotInfo[slotNum].MemberPath);
}
}
else
{
paddedSlotInfo[slotNum] = childSlotInfo[slotNum];
}
}
//Add the slots that were added by children
//for (int slotNum = totalSlots; slotNum < childBlock.Slots.Count; slotNum++)
//{
// paddedSlotInfo[slotNum] = childSlotInfo[slotNum];
//}
childBlock.Slots = new ReadOnlyCollection(paddedSlotInfo);
children.Add(childBlock);
Debug.Assert(totalSlots == child.NumBoolSlots + child.NumProjectedSlots,
"Number of required slots is different from what each node in the tree has?");
}
//We need to add the slots added by each child unformly for others( as nulls)
//since this is a union operation
if (aliasedSlotsForAddedByChildren.Count != 0)
{
foreach (CqlBlock childBlock in children)
{
SlotInfo[] childSlots = new SlotInfo[totalSlots + aliasedSlotsForAddedByChildren.Count];
childBlock.Slots.CopyTo(childSlots,0);
int index = totalSlots;
foreach (AliasedSlot aliasedSlot in aliasedSlotsForAddedByChildren)
{
if (aliasedSlot.Block.Equals(childBlock))
{
childSlots[index] = new SlotInfo(true /* is required */, true /* is projected */,
aliasedSlot.InnerSlot, aliasedSlot.MemberPath);
}
else
{
childSlots[index] = new SlotInfo(true /* is required */, true /* is projected */,
new ConstantSlot(CellConstant.Null), aliasedSlot.MemberPath);
}
//move on to the next slot added by children.
index++;
}
childBlock.Slots = new ReadOnlyCollection(childSlots);
}
}
// Create the slotInfos and then Union CqlBlock
SlotInfo[] slotInfos = new SlotInfo[totalSlots + aliasedSlotsForAddedByChildren.Count];
// We pick the slot references from the first child, just as convention
// In a union, values come from both sides
CqlBlock firstChild = children[0];
for (int slotNum = 0; slotNum < totalSlots; slotNum++) {
ProjectedSlot slot = firstChild.ProjectedSlot(slotNum);
MemberPath memberPath = GetMemberPath(slotNum);
// A required slot is somehow projected by a child in Union
// -- so set isProjected to be the same as isRequired
bool isRequired = requiredSlots[slotNum];
SlotInfo slotInfo = new SlotInfo(isRequired, isRequired, slot, memberPath);
slotInfos[slotNum] = slotInfo;
}
for (int i = 0, slotNum = totalSlots; slotNum < totalSlots + aliasedSlotsForAddedByChildren.Count; slotNum++, i++)
{
slotInfos[slotNum] = new SlotInfo(true, true, aliasedSlotsForAddedByChildren[i], aliasedSlotsForAddedByChildren[i].MemberPath);
}
CqlBlock block = new UnionCqlBlock(slotInfos, children, identifiers, ++blockAliasNum);
return block;
}
private static void AndWith(bool[] boolArray, bool[] another)
{
Debug.Assert(boolArray.Length == another.Length);
for (int i = 0; i < boolArray.Length; i++)
{
boolArray[i] &= another[i];
}
}
#endregion
#region Join CqlBLock Methods
// requires: node corresponds to an IJ, LOJ, FOJ node
// effects: Given a union node and the slots required by the parent,
// generates a CqlBlock for the subtree rooted at node
private CqlBlock JoinToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List withStatements)
{
int totalSlots = requiredSlots.Length;
Debug.Assert(OpType == CellTreeOpType.IJ ||
OpType == CellTreeOpType.LOJ ||
OpType == CellTreeOpType.FOJ, "Only these join operations handled");
List children = new List();
List aliasedSlotsForAddedByChildren = new List();
// First get the children nodes (FROM part)
foreach (CellTreeNode child in Children) {
// Determine the slots that are projected by this child.
// These are the required slots as well - unlike Union, we do
// not need the child to project any extra nulls
bool[] childProjectedSlots = child.GetProjectedSlots();
AndWith(childProjectedSlots, requiredSlots);
//List subAddedSlotsByChild = new List();
CqlBlock childBlock = child.ToCqlBlock(childProjectedSlots, identifiers, ref blockAliasNum, ref withStatements);
//addedSlotsByChild.AddRange(subAddedSlotsByChild);
children.Add(childBlock);
//foreach (SlotInfo slotInfo in subAddedSlotsByChild)
for(int aliasedSlotNumber = childProjectedSlots.Length; aliasedSlotNumber < childBlock.Slots.Count;aliasedSlotNumber++)
{
SlotInfo slotInfo = childBlock.Slots[aliasedSlotNumber];
aliasedSlotsForAddedByChildren.Add(new AliasedSlot(childBlock, slotInfo.SlotValue, slotInfo.MemberPath, aliasedSlotNumber));
}
Debug.Assert(totalSlots == child.NumBoolSlots + child.NumProjectedSlots,
"Number of required slots is different from what each node in the tree has?");
}
// Now get the slots that are projected out by this node (SELECT part)
SlotInfo[] slotInfos = new SlotInfo[totalSlots + aliasedSlotsForAddedByChildren.Count];
for (int slotNum = 0; slotNum < totalSlots; slotNum++)
{
// Note: this call could create a CaseStatementSlot (i.e., slotInfo.SlotValue is CaseStatementSlot)
// which uses "from" booleans that need to be projected by children
SlotInfo slotInfo = GetJoinSlotInfo(OpType, requiredSlots[slotNum], children, slotNum, identifiers);
slotInfos[slotNum] = slotInfo;
}
for (int i = 0, slotNum = totalSlots; slotNum < totalSlots + aliasedSlotsForAddedByChildren.Count; slotNum++, i++)
{
slotInfos[slotNum] = new SlotInfo(true, true, aliasedSlotsForAddedByChildren[i], aliasedSlotsForAddedByChildren[i].MemberPath);
}
// Generate the ON conditions: For each child, generate an ON
// clause with the 0th child on the key fields
List onClauses = new List();
for (int i = 1; i < children.Count; i++) {
CqlBlock child = children[i];
JoinCqlBlock.OnClause onClause = new JoinCqlBlock.OnClause();
foreach (int keySlotNum in KeySlots) {
SlotInfo slotInfo = slotInfos[keySlotNum];
Debug.Assert(child.IsProjected(keySlotNum), "Key is not in child");
Debug.Assert(children[0].IsProjected(keySlotNum), "Key is not in 0th child");
AliasedSlot first = new AliasedSlot(children[0], slotInfo.SlotValue,
slotInfo.MemberPath, keySlotNum);
AliasedSlot second = new AliasedSlot(child, slotInfo.SlotValue, slotInfo.MemberPath,
keySlotNum);
onClause.Add(first, second);
}
onClauses.Add(onClause);
}
CqlBlock result = new JoinCqlBlock(OpType, slotInfos, children, onClauses, identifiers, ++blockAliasNum);
return result;
}
// effects: Generates a SlotInfo object for a slot of a join node. It
// uses the type of the join operation (opType), whether the slot is
// required by the parent or not (isRequiredSlot), the children of
// this node (children) and the number of the slotNum
private SlotInfo GetJoinSlotInfo(CellTreeOpType opType, bool isRequiredSlot,
List children, int slotNum, CqlIdentifiers identifiers) {
if (false == isRequiredSlot) {
// The slot will not be used. So we can set the projected slot to be null
SlotInfo unrequiredSlotInfo = new SlotInfo(false, false, null, GetMemberPath(slotNum));
return unrequiredSlotInfo;
}
// For a required slot, determine the child who is contributing to this value
int childDefiningSlot = -1;
CaseStatement caseForOuterJoins = null;
for (int childNum = 0; childNum < children.Count; childNum++) {
CqlBlock child = children[childNum];
if (false == child.IsProjected(slotNum)) {
continue;
}
// For keys, we can pick any child block. So the first
// one that we find is fine as well
if (IsKeySlot(slotNum)) {
childDefiningSlot = childNum;
break;
} else if (opType == CellTreeOpType.IJ) {
// For Inner Joins, most of the time, the entries will be
// the same in all the children. However, in some cases,
// we will end up with NULL in one child and an actual
// value in another -- we should pick up the actual value in that case
childDefiningSlot = GetInnerJoinChildForSlot(children, slotNum);
break;
} else {
// For LOJs, we generate a case statement if more than
// one child generates the value - until then we do not
// create the caseForOuterJoins object
if (childDefiningSlot != -1) {
// We really need a case statement now
// We have the value being generated by another child
// We need to fetch the variable from the appropriate child
Debug.Assert(false == IsBoolSlot(slotNum), "Boolean slots cannot come from two children");
if (caseForOuterJoins == null) {
MemberPath outputMember = GetMemberPath(slotNum);
caseForOuterJoins = new CaseStatement(outputMember);
// Add the child that we had not added in the first shot
AddCaseForOuterJoins(caseForOuterJoins, children[childDefiningSlot], slotNum, identifiers);
}
AddCaseForOuterJoins(caseForOuterJoins, child, slotNum, identifiers);
}
childDefiningSlot = childNum;
}
}
MemberPath memberPath = GetMemberPath(slotNum);
ProjectedSlot slot = null;
// Generate the slot value -- case statement slot, or an aliased slot
// or null or false. If case statement slot has nothing, treat it as null/empty
if (caseForOuterJoins != null && (caseForOuterJoins.Clauses.Count > 0 || caseForOuterJoins.ElseValue != null)) {
caseForOuterJoins.Simplify();
slot = new CaseStatementSlot(caseForOuterJoins, null);
} else if (childDefiningSlot >= 0) {
slot = new AliasedSlot(children[childDefiningSlot],
children[childDefiningSlot].ProjectedSlot(slotNum), memberPath, slotNum);
} else {
// need to produce output slot, but don't have a value
// output NULL for fields or False for bools
if (IsBoolSlot(slotNum)) {
slot = new BooleanProjectedSlot(BoolExpression.False, identifiers, SlotToBoolIndex(slotNum));
} else {
slot = new ConstantSlot(CellConstantDomain.GetDefaultValueForMemberPath(memberPath, GetLeaves(), CellNormalizer.Config));
}
}
// We need to ensure that _from variables are never null since
// view generation uses 2-valued boolean logic.
// They can become null in outer joins. We compensate for it by
// adding AND NOT NULL condition on boolean slots coming from outer joins.
bool enforceNotNull = IsBoolSlot(slotNum) &&
((opType == CellTreeOpType.LOJ && childDefiningSlot > 0) ||
opType == CellTreeOpType.FOJ);
// We set isProjected to be true since we have come up with some value for it
SlotInfo slotInfo = new SlotInfo(true, true, slot, memberPath, enforceNotNull);
return slotInfo;
}
// requires: children to be a list of nodes that are children of an
// Inner Join node. slotNum does not correspond to the key slot
// effects: Determines the child number from which the slot should be
// picked up.
private static int GetInnerJoinChildForSlot(List children, int slotNum) {
// Picks the child with the non-constant slot first. If none, picks a non-null constant slot.
// If not een that, picks any one
int result = -1;
for (int i = 0; i < children.Count; i++) {
CqlBlock child = children[i];
if (false == child.IsProjected(slotNum)) {
continue;
}
ProjectedSlot slot = child.ProjectedSlot(slotNum);
ConstantSlot constantSlot = slot as ConstantSlot;
JoinTreeSlot joinSlot = slot as JoinTreeSlot;
if (joinSlot != null) { // Pick the non-constant slot
result = i;
} else if (constantSlot != null && constantSlot.CellConstant.IsNull()) {
if (result == -1) { // In case, all are null
result = i;
}
} else {
// Just pick anything
result = i;
}
}
return result;
}
// requires: caseForOuterJoins corresponds the slot "slotNum"
// effects: Adds a WhenThen corresponding to child to caseForOuterJoins.
private void AddCaseForOuterJoins(CaseStatement caseForOuterJoins, CqlBlock child, int slotNum, CqlIdentifiers identifiers) {
// Determine the cells that the slot comes from
// and make an OR expression, e.g., WHEN _from0 or _from2 or ... THEN child[slotNum]
ProjectedSlot childSlot = child.ProjectedSlot(slotNum);
ConstantSlot constantSlot = childSlot as ConstantSlot;
if (constantSlot != null && constantSlot.CellConstant.IsNull()) {
// NULL being generated by a child - don't need to project
return;
}
BoolExpression originBool = BoolExpression.False;
for (int i = 0; i < NumBoolSlots; i++) {
int boolSlotNum = BoolIndexToSlot(i);
if (child.IsProjected(boolSlotNum)) {
// OR it to the expression
QualifiedCellIdBoolean boolExpr = new QualifiedCellIdBoolean(child, identifiers, i);
originBool = BoolExpression.CreateOr(originBool, BoolExpression.CreateLiteral(boolExpr, RightDomainMap));
}
}
// Make an aliased slot corresponding to child[slotNum] for the THEN
MemberPath outputMember = GetMemberPath(slotNum);
AliasedSlot slot = new AliasedSlot(child, childSlot, outputMember, slotNum);
caseForOuterJoins.AddWhenThen(originBool, slot);
}
#endregion
#region String methods
// effects: Given an optype, returns a SQL-acceptable string
// corresponding to the op
internal static string OpToCql(CellTreeOpType opType) {
switch (opType) {
case CellTreeOpType.FOJ: return "FULL OUTER JOIN";
case CellTreeOpType.IJ: return "INNER JOIN";
//case CellTreeOpType.LASJ: return "LEFT ANTISEMIJOIN";
case CellTreeOpType.LOJ: return "LEFT OUTER JOIN";
case CellTreeOpType.Union: return "UNION ALL";
}
Debug.Fail("Unknown operator");
return null;
}
internal override void ToCompactString(StringBuilder stringBuilder) {
// Debug.Assert(m_children.Count > 1, "Tree not flattened?");
stringBuilder.Append("(");
for (int i = 0; i < m_children.Count; i++) {
CellTreeNode child = m_children[i];
child.ToCompactString(stringBuilder);
if (i != m_children.Count - 1) {
StringUtil.FormatStringBuilder(stringBuilder, " {0} ", OpType);
}
}
stringBuilder.Append(")");
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//----------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// @owner [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System.Data.Common.Utils;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Mapping.ViewGeneration.CqlGeneration;
using System.Data.Mapping.ViewGeneration.QueryRewriting;
using System.Text;
using System.Linq;
using System.Diagnostics;
using System.Data.Metadata.Edm;
namespace System.Data.Mapping.ViewGeneration.Structures {
using AttributeSet = Set;
// This class represents th intermediate nodes in the tree (non-leaf nodes)
internal class OpCellTreeNode : CellTreeNode {
#region Constructors
// effects: Creates a node with operation opType and no children
internal OpCellTreeNode(CellNormalizer normalizer, CellTreeOpType opType)
: base(normalizer) {
m_opType = opType;
m_attrs = new AttributeSet(MemberPath.EqualityComparer);
m_children = new List();
}
internal OpCellTreeNode(CellNormalizer normalizer, CellTreeOpType opType, params CellTreeNode[] children)
: this(normalizer, opType, (IEnumerable)children) { }
// effects: Given a sequence of children node and the opType, creates
// an OpCellTreeNode and returns it
internal OpCellTreeNode(CellNormalizer normalizer, CellTreeOpType opType, IEnumerable children)
: this(normalizer, opType) {
// Add the children one by one so that we can get the attrs etc fixed
foreach (CellTreeNode child in children) {
Add(child);
}
}
#endregion
#region Fields
private Set m_attrs; // attributes from whole subtree below
private List m_children;
private CellTreeOpType m_opType;
private FragmentQuery m_leftFragmentQuery;
private FragmentQuery m_rightFragmentQuery;
#endregion
#region Properties
// effects: See CellTreeNode.OpType
internal override CellTreeOpType OpType { get { return m_opType; } }
// fragment query superseeds SelectionDomain
internal override FragmentQuery LeftFragmentQuery
{
get
{
if (m_leftFragmentQuery == null)
{
Debug.Assert(Children.Count > 0);
FragmentQuery leftFragmentQuery = Children[0].LeftFragmentQuery;
FragmentQueryProcessor leftQP = CellNormalizer.LeftFragmentQP;
for (int i = 1; i < Children.Count; i++)
{
FragmentQuery nextLeftQuery = Children[i].LeftFragmentQuery;
switch (OpType)
{
case CellTreeOpType.IJ:
leftFragmentQuery = leftQP.Intersect(leftFragmentQuery, nextLeftQuery);
break;
case CellTreeOpType.LOJ:
// Left outer join means keeping the domain of the leftmost child
break;
case CellTreeOpType.LASJ:
// not used in basic view generation but current validation calls Simplify, so add this for debugging
leftFragmentQuery = leftQP.Difference(leftFragmentQuery, nextLeftQuery);
break;
default:
// All other operators (Union, FOJ) require union of the domains
leftFragmentQuery = leftQP.Union(leftFragmentQuery, nextLeftQuery);
break;
}
}
m_leftFragmentQuery = leftFragmentQuery;
}
return m_leftFragmentQuery;
}
}
internal override FragmentQuery RightFragmentQuery
{
get
{
if (m_rightFragmentQuery == null)
{
Debug.Assert(Children.Count > 0);
FragmentQuery rightFragmentQuery = Children[0].RightFragmentQuery;
FragmentQueryProcessor rightQP = CellNormalizer.RightFragmentQP;
for (int i = 1; i < Children.Count; i++)
{
FragmentQuery nextRightQuery = Children[i].RightFragmentQuery;
switch (OpType)
{
case CellTreeOpType.IJ:
rightFragmentQuery = rightQP.Intersect(rightFragmentQuery, nextRightQuery);
break;
case CellTreeOpType.LOJ:
// Left outer join means keeping the domain of the leftmost child
break;
case CellTreeOpType.LASJ:
// not used in basic view generation but current validation calls Simplify, so add this for debugging
rightFragmentQuery = rightQP.Difference(rightFragmentQuery, nextRightQuery);
break;
default:
// All other operators (Union, FOJ) require union of the domains
rightFragmentQuery = rightQP.Union(rightFragmentQuery, nextRightQuery);
break;
}
}
m_rightFragmentQuery = rightFragmentQuery;
}
return m_rightFragmentQuery;
}
}
// effects: See CellTreeNode.RightDomainMap
internal override MemberDomainMap RightDomainMap {
get {
// Get the information from one of the children
Debug.Assert(m_children[0].RightDomainMap != null, "EdmMember domain map missing");
return m_children[0].RightDomainMap;
}
}
// effects: See CellTreeNode.Attributes
internal override Set Attributes { get { return m_attrs; } }
// effects: See CellTreeNode.Children
internal override List Children { get { return m_children; } }
internal override int NumProjectedSlots {
get {
// All children have the same number of slots
Debug.Assert(m_children.Count > 1, "No children for op node?");
return m_children[0].NumProjectedSlots;
}
}
internal override int NumBoolSlots {
get {
Debug.Assert(m_children.Count > 1, "No children for op node?");
return m_children[0].NumBoolSlots;
}
}
#endregion
#region Methods
internal override TOutput Accept(SimpleCellTreeVisitor visitor, TInput param) {
return visitor.VisitOpNode(this, param);
}
internal override TOutput Accept(CellTreeVisitor visitor, TInput param) {
switch (OpType) {
case CellTreeOpType.IJ:
return visitor.VisitInnerJoin(this, param);
case CellTreeOpType.LOJ:
return visitor.VisitLeftOuterJoin(this, param);
case CellTreeOpType.Union:
return visitor.VisitUnion(this, param);
case CellTreeOpType.FOJ:
return visitor.VisitFullOuterJoin(this, param);
case CellTreeOpType.LASJ:
return visitor.VisitLeftAntiSemiJoin(this, param);
default:
Debug.Fail("Unexpected optype: " + OpType);
// To satsfy the compiler
return visitor.VisitInnerJoin(this, param);
}
}
// effects: Add child to the end of the current children list
// while ensuring the constants and attributes of the child are
// propagated into this (i.e., unioned)
internal void Add(CellTreeNode child) {
Insert(m_children.Count, child);
}
// effects: Add child at the beginning of the current children list
// while ensuring the constants and attributes of the child are
// propagated into this (i.e., unioned)
internal void AddFirst(CellTreeNode child) {
Insert(0, child);
}
// effects: Inserts child at "index" while ensuring the constants
// and attributes of the child are propagated into this
private void Insert(int index, CellTreeNode child) {
m_attrs.Unite(child.Attributes);
m_children.Insert(index, child);
// reset fragmentQuery so it's recomputed when property FragmentQuery is accessed
m_leftFragmentQuery = null;
m_rightFragmentQuery = null;
}
// effects: Given the required slots by the parent,
// generates a CqlBlock tree for the tree rooted below node
internal override CqlBlock ToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum,
ref List withStatements)
{
// Dispatch depending on whether we have a union node or join node
CqlBlock result;
if (OpType == CellTreeOpType.Union) {
result = UnionToCqlBlock(requiredSlots, identifiers, ref blockAliasNum, ref withStatements);
} else {
result = JoinToCqlBlock(requiredSlots, identifiers, ref blockAliasNum, ref withStatements);
}
return result;
}
internal override bool IsProjectedSlot(int slot) {
// If any childtree projects it, return true
foreach (CellTreeNode childNode in Children) {
if (childNode.IsProjectedSlot(slot)) {
return true;
}
}
return false;
}
#endregion
#region Union CqlBLock Methods
// requires: node corresponds to a Union node
// effects: Given a union node and the slots required by the parent,
// generates a CqlBlock for the subtree rooted at node
private CqlBlock UnionToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List withStatements)
{
Debug.Assert(OpType == CellTreeOpType.Union);
List children = new List();
List aliasedSlotsForAddedByChildren = new List();
int totalSlots = requiredSlots.Length;
foreach (CellTreeNode child in Children) {
// Unlike Join, we pass the requiredSlots from the parent as the requirement
// CqlBlock childBlock = child.ToCqlBlock(requiredSlots, identifiers, ref blockAliasNum);
bool[] childProjectedSlots = child.GetProjectedSlots();
AndWith(childProjectedSlots, requiredSlots);
CqlBlock childBlock = child.ToCqlBlock(childProjectedSlots, identifiers, ref blockAliasNum, ref withStatements);
for (int aliasedSlotNumber = childProjectedSlots.Length; aliasedSlotNumber < childBlock.Slots.Count; aliasedSlotNumber++)
{
SlotInfo slotInfo = childBlock.Slots[aliasedSlotNumber];
aliasedSlotsForAddedByChildren.Add(new AliasedSlot(childBlock, slotInfo.SlotValue, slotInfo.MemberPath, aliasedSlotNumber));
}
// if required, but not projected, add NULL
SlotInfo[] paddedSlotInfo = new SlotInfo[childBlock.Slots.Count];
ReadOnlyCollection childSlotInfo = childBlock.Slots;
for (int slotNum = 0; slotNum < totalSlots; slotNum++)
{
if (requiredSlots[slotNum] && !childProjectedSlots[slotNum])
{
if (IsBoolSlot(slotNum))
{
paddedSlotInfo[slotNum] = new SlotInfo(true /* is required */, true /* is projected */,
new BooleanProjectedSlot(BoolExpression.False, identifiers, SlotToBoolIndex(slotNum)), null /* member path*/);
}
else
{
// NULL as projected slot
paddedSlotInfo[slotNum] = new SlotInfo(true /* is required */, true /* is projected */,
new ConstantSlot(CellConstant.Null), childSlotInfo[slotNum].MemberPath);
}
}
else
{
paddedSlotInfo[slotNum] = childSlotInfo[slotNum];
}
}
//Add the slots that were added by children
//for (int slotNum = totalSlots; slotNum < childBlock.Slots.Count; slotNum++)
//{
// paddedSlotInfo[slotNum] = childSlotInfo[slotNum];
//}
childBlock.Slots = new ReadOnlyCollection(paddedSlotInfo);
children.Add(childBlock);
Debug.Assert(totalSlots == child.NumBoolSlots + child.NumProjectedSlots,
"Number of required slots is different from what each node in the tree has?");
}
//We need to add the slots added by each child unformly for others( as nulls)
//since this is a union operation
if (aliasedSlotsForAddedByChildren.Count != 0)
{
foreach (CqlBlock childBlock in children)
{
SlotInfo[] childSlots = new SlotInfo[totalSlots + aliasedSlotsForAddedByChildren.Count];
childBlock.Slots.CopyTo(childSlots,0);
int index = totalSlots;
foreach (AliasedSlot aliasedSlot in aliasedSlotsForAddedByChildren)
{
if (aliasedSlot.Block.Equals(childBlock))
{
childSlots[index] = new SlotInfo(true /* is required */, true /* is projected */,
aliasedSlot.InnerSlot, aliasedSlot.MemberPath);
}
else
{
childSlots[index] = new SlotInfo(true /* is required */, true /* is projected */,
new ConstantSlot(CellConstant.Null), aliasedSlot.MemberPath);
}
//move on to the next slot added by children.
index++;
}
childBlock.Slots = new ReadOnlyCollection(childSlots);
}
}
// Create the slotInfos and then Union CqlBlock
SlotInfo[] slotInfos = new SlotInfo[totalSlots + aliasedSlotsForAddedByChildren.Count];
// We pick the slot references from the first child, just as convention
// In a union, values come from both sides
CqlBlock firstChild = children[0];
for (int slotNum = 0; slotNum < totalSlots; slotNum++) {
ProjectedSlot slot = firstChild.ProjectedSlot(slotNum);
MemberPath memberPath = GetMemberPath(slotNum);
// A required slot is somehow projected by a child in Union
// -- so set isProjected to be the same as isRequired
bool isRequired = requiredSlots[slotNum];
SlotInfo slotInfo = new SlotInfo(isRequired, isRequired, slot, memberPath);
slotInfos[slotNum] = slotInfo;
}
for (int i = 0, slotNum = totalSlots; slotNum < totalSlots + aliasedSlotsForAddedByChildren.Count; slotNum++, i++)
{
slotInfos[slotNum] = new SlotInfo(true, true, aliasedSlotsForAddedByChildren[i], aliasedSlotsForAddedByChildren[i].MemberPath);
}
CqlBlock block = new UnionCqlBlock(slotInfos, children, identifiers, ++blockAliasNum);
return block;
}
private static void AndWith(bool[] boolArray, bool[] another)
{
Debug.Assert(boolArray.Length == another.Length);
for (int i = 0; i < boolArray.Length; i++)
{
boolArray[i] &= another[i];
}
}
#endregion
#region Join CqlBLock Methods
// requires: node corresponds to an IJ, LOJ, FOJ node
// effects: Given a union node and the slots required by the parent,
// generates a CqlBlock for the subtree rooted at node
private CqlBlock JoinToCqlBlock(bool[] requiredSlots, CqlIdentifiers identifiers, ref int blockAliasNum, ref List withStatements)
{
int totalSlots = requiredSlots.Length;
Debug.Assert(OpType == CellTreeOpType.IJ ||
OpType == CellTreeOpType.LOJ ||
OpType == CellTreeOpType.FOJ, "Only these join operations handled");
List children = new List();
List aliasedSlotsForAddedByChildren = new List();
// First get the children nodes (FROM part)
foreach (CellTreeNode child in Children) {
// Determine the slots that are projected by this child.
// These are the required slots as well - unlike Union, we do
// not need the child to project any extra nulls
bool[] childProjectedSlots = child.GetProjectedSlots();
AndWith(childProjectedSlots, requiredSlots);
//List subAddedSlotsByChild = new List();
CqlBlock childBlock = child.ToCqlBlock(childProjectedSlots, identifiers, ref blockAliasNum, ref withStatements);
//addedSlotsByChild.AddRange(subAddedSlotsByChild);
children.Add(childBlock);
//foreach (SlotInfo slotInfo in subAddedSlotsByChild)
for(int aliasedSlotNumber = childProjectedSlots.Length; aliasedSlotNumber < childBlock.Slots.Count;aliasedSlotNumber++)
{
SlotInfo slotInfo = childBlock.Slots[aliasedSlotNumber];
aliasedSlotsForAddedByChildren.Add(new AliasedSlot(childBlock, slotInfo.SlotValue, slotInfo.MemberPath, aliasedSlotNumber));
}
Debug.Assert(totalSlots == child.NumBoolSlots + child.NumProjectedSlots,
"Number of required slots is different from what each node in the tree has?");
}
// Now get the slots that are projected out by this node (SELECT part)
SlotInfo[] slotInfos = new SlotInfo[totalSlots + aliasedSlotsForAddedByChildren.Count];
for (int slotNum = 0; slotNum < totalSlots; slotNum++)
{
// Note: this call could create a CaseStatementSlot (i.e., slotInfo.SlotValue is CaseStatementSlot)
// which uses "from" booleans that need to be projected by children
SlotInfo slotInfo = GetJoinSlotInfo(OpType, requiredSlots[slotNum], children, slotNum, identifiers);
slotInfos[slotNum] = slotInfo;
}
for (int i = 0, slotNum = totalSlots; slotNum < totalSlots + aliasedSlotsForAddedByChildren.Count; slotNum++, i++)
{
slotInfos[slotNum] = new SlotInfo(true, true, aliasedSlotsForAddedByChildren[i], aliasedSlotsForAddedByChildren[i].MemberPath);
}
// Generate the ON conditions: For each child, generate an ON
// clause with the 0th child on the key fields
List onClauses = new List();
for (int i = 1; i < children.Count; i++) {
CqlBlock child = children[i];
JoinCqlBlock.OnClause onClause = new JoinCqlBlock.OnClause();
foreach (int keySlotNum in KeySlots) {
SlotInfo slotInfo = slotInfos[keySlotNum];
Debug.Assert(child.IsProjected(keySlotNum), "Key is not in child");
Debug.Assert(children[0].IsProjected(keySlotNum), "Key is not in 0th child");
AliasedSlot first = new AliasedSlot(children[0], slotInfo.SlotValue,
slotInfo.MemberPath, keySlotNum);
AliasedSlot second = new AliasedSlot(child, slotInfo.SlotValue, slotInfo.MemberPath,
keySlotNum);
onClause.Add(first, second);
}
onClauses.Add(onClause);
}
CqlBlock result = new JoinCqlBlock(OpType, slotInfos, children, onClauses, identifiers, ++blockAliasNum);
return result;
}
// effects: Generates a SlotInfo object for a slot of a join node. It
// uses the type of the join operation (opType), whether the slot is
// required by the parent or not (isRequiredSlot), the children of
// this node (children) and the number of the slotNum
private SlotInfo GetJoinSlotInfo(CellTreeOpType opType, bool isRequiredSlot,
List children, int slotNum, CqlIdentifiers identifiers) {
if (false == isRequiredSlot) {
// The slot will not be used. So we can set the projected slot to be null
SlotInfo unrequiredSlotInfo = new SlotInfo(false, false, null, GetMemberPath(slotNum));
return unrequiredSlotInfo;
}
// For a required slot, determine the child who is contributing to this value
int childDefiningSlot = -1;
CaseStatement caseForOuterJoins = null;
for (int childNum = 0; childNum < children.Count; childNum++) {
CqlBlock child = children[childNum];
if (false == child.IsProjected(slotNum)) {
continue;
}
// For keys, we can pick any child block. So the first
// one that we find is fine as well
if (IsKeySlot(slotNum)) {
childDefiningSlot = childNum;
break;
} else if (opType == CellTreeOpType.IJ) {
// For Inner Joins, most of the time, the entries will be
// the same in all the children. However, in some cases,
// we will end up with NULL in one child and an actual
// value in another -- we should pick up the actual value in that case
childDefiningSlot = GetInnerJoinChildForSlot(children, slotNum);
break;
} else {
// For LOJs, we generate a case statement if more than
// one child generates the value - until then we do not
// create the caseForOuterJoins object
if (childDefiningSlot != -1) {
// We really need a case statement now
// We have the value being generated by another child
// We need to fetch the variable from the appropriate child
Debug.Assert(false == IsBoolSlot(slotNum), "Boolean slots cannot come from two children");
if (caseForOuterJoins == null) {
MemberPath outputMember = GetMemberPath(slotNum);
caseForOuterJoins = new CaseStatement(outputMember);
// Add the child that we had not added in the first shot
AddCaseForOuterJoins(caseForOuterJoins, children[childDefiningSlot], slotNum, identifiers);
}
AddCaseForOuterJoins(caseForOuterJoins, child, slotNum, identifiers);
}
childDefiningSlot = childNum;
}
}
MemberPath memberPath = GetMemberPath(slotNum);
ProjectedSlot slot = null;
// Generate the slot value -- case statement slot, or an aliased slot
// or null or false. If case statement slot has nothing, treat it as null/empty
if (caseForOuterJoins != null && (caseForOuterJoins.Clauses.Count > 0 || caseForOuterJoins.ElseValue != null)) {
caseForOuterJoins.Simplify();
slot = new CaseStatementSlot(caseForOuterJoins, null);
} else if (childDefiningSlot >= 0) {
slot = new AliasedSlot(children[childDefiningSlot],
children[childDefiningSlot].ProjectedSlot(slotNum), memberPath, slotNum);
} else {
// need to produce output slot, but don't have a value
// output NULL for fields or False for bools
if (IsBoolSlot(slotNum)) {
slot = new BooleanProjectedSlot(BoolExpression.False, identifiers, SlotToBoolIndex(slotNum));
} else {
slot = new ConstantSlot(CellConstantDomain.GetDefaultValueForMemberPath(memberPath, GetLeaves(), CellNormalizer.Config));
}
}
// We need to ensure that _from variables are never null since
// view generation uses 2-valued boolean logic.
// They can become null in outer joins. We compensate for it by
// adding AND NOT NULL condition on boolean slots coming from outer joins.
bool enforceNotNull = IsBoolSlot(slotNum) &&
((opType == CellTreeOpType.LOJ && childDefiningSlot > 0) ||
opType == CellTreeOpType.FOJ);
// We set isProjected to be true since we have come up with some value for it
SlotInfo slotInfo = new SlotInfo(true, true, slot, memberPath, enforceNotNull);
return slotInfo;
}
// requires: children to be a list of nodes that are children of an
// Inner Join node. slotNum does not correspond to the key slot
// effects: Determines the child number from which the slot should be
// picked up.
private static int GetInnerJoinChildForSlot(List children, int slotNum) {
// Picks the child with the non-constant slot first. If none, picks a non-null constant slot.
// If not een that, picks any one
int result = -1;
for (int i = 0; i < children.Count; i++) {
CqlBlock child = children[i];
if (false == child.IsProjected(slotNum)) {
continue;
}
ProjectedSlot slot = child.ProjectedSlot(slotNum);
ConstantSlot constantSlot = slot as ConstantSlot;
JoinTreeSlot joinSlot = slot as JoinTreeSlot;
if (joinSlot != null) { // Pick the non-constant slot
result = i;
} else if (constantSlot != null && constantSlot.CellConstant.IsNull()) {
if (result == -1) { // In case, all are null
result = i;
}
} else {
// Just pick anything
result = i;
}
}
return result;
}
// requires: caseForOuterJoins corresponds the slot "slotNum"
// effects: Adds a WhenThen corresponding to child to caseForOuterJoins.
private void AddCaseForOuterJoins(CaseStatement caseForOuterJoins, CqlBlock child, int slotNum, CqlIdentifiers identifiers) {
// Determine the cells that the slot comes from
// and make an OR expression, e.g., WHEN _from0 or _from2 or ... THEN child[slotNum]
ProjectedSlot childSlot = child.ProjectedSlot(slotNum);
ConstantSlot constantSlot = childSlot as ConstantSlot;
if (constantSlot != null && constantSlot.CellConstant.IsNull()) {
// NULL being generated by a child - don't need to project
return;
}
BoolExpression originBool = BoolExpression.False;
for (int i = 0; i < NumBoolSlots; i++) {
int boolSlotNum = BoolIndexToSlot(i);
if (child.IsProjected(boolSlotNum)) {
// OR it to the expression
QualifiedCellIdBoolean boolExpr = new QualifiedCellIdBoolean(child, identifiers, i);
originBool = BoolExpression.CreateOr(originBool, BoolExpression.CreateLiteral(boolExpr, RightDomainMap));
}
}
// Make an aliased slot corresponding to child[slotNum] for the THEN
MemberPath outputMember = GetMemberPath(slotNum);
AliasedSlot slot = new AliasedSlot(child, childSlot, outputMember, slotNum);
caseForOuterJoins.AddWhenThen(originBool, slot);
}
#endregion
#region String methods
// effects: Given an optype, returns a SQL-acceptable string
// corresponding to the op
internal static string OpToCql(CellTreeOpType opType) {
switch (opType) {
case CellTreeOpType.FOJ: return "FULL OUTER JOIN";
case CellTreeOpType.IJ: return "INNER JOIN";
//case CellTreeOpType.LASJ: return "LEFT ANTISEMIJOIN";
case CellTreeOpType.LOJ: return "LEFT OUTER JOIN";
case CellTreeOpType.Union: return "UNION ALL";
}
Debug.Fail("Unknown operator");
return null;
}
internal override void ToCompactString(StringBuilder stringBuilder) {
// Debug.Assert(m_children.Count > 1, "Tree not flattened?");
stringBuilder.Append("(");
for (int i = 0; i < m_children.Count; i++) {
CellTreeNode child = m_children[i];
child.ToCompactString(stringBuilder);
if (i != m_children.Count - 1) {
StringUtil.FormatStringBuilder(stringBuilder, " {0} ", OpType);
}
}
stringBuilder.Append(")");
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FontInfo.cs
- RawUIStateInputReport.cs
- XPathChildIterator.cs
- AmbiguousMatchException.cs
- ListenerConnectionDemuxer.cs
- OutOfMemoryException.cs
- ProcessHostMapPath.cs
- ListDictionaryInternal.cs
- BindingsSection.cs
- ConnectorDragDropGlyph.cs
- ExtensionFile.cs
- TransformConverter.cs
- DocumentPage.cs
- MediaEntryAttribute.cs
- ThreadAbortException.cs
- PieceDirectory.cs
- Content.cs
- DoubleStorage.cs
- WebPartManagerInternals.cs
- QuaternionIndependentAnimationStorage.cs
- PagerSettings.cs
- CultureInfo.cs
- Model3DCollection.cs
- PrinterUnitConvert.cs
- ThicknessKeyFrameCollection.cs
- LinkUtilities.cs
- StorageComplexTypeMapping.cs
- PersistChildrenAttribute.cs
- LocationEnvironment.cs
- CounterCreationData.cs
- AppSecurityManager.cs
- PostBackOptions.cs
- Win32.cs
- AccessDataSource.cs
- UrlAuthFailureHandler.cs
- StackSpiller.Generated.cs
- KeyValueConfigurationCollection.cs
- Int32EqualityComparer.cs
- HttpPostedFile.cs
- SoapReflector.cs
- InkCollectionBehavior.cs
- _TimerThread.cs
- HasCopySemanticsAttribute.cs
- XmlObjectSerializer.cs
- ContextMenuAutomationPeer.cs
- SmiConnection.cs
- TextTreeExtractElementUndoUnit.cs
- StretchValidation.cs
- TextContainerChangedEventArgs.cs
- RectIndependentAnimationStorage.cs
- AsyncOperationManager.cs
- EventDriven.cs
- TablePattern.cs
- ChangeBlockUndoRecord.cs
- JoinGraph.cs
- ArgumentOutOfRangeException.cs
- DynamicUpdateCommand.cs
- OutKeywords.cs
- WrappedIUnknown.cs
- HtmlElementCollection.cs
- ButtonPopupAdapter.cs
- EntityViewGenerator.cs
- TypeBuilder.cs
- _TransmitFileOverlappedAsyncResult.cs
- ActivityDesignerAccessibleObject.cs
- ParentUndoUnit.cs
- XslAst.cs
- ObjectStateFormatter.cs
- XmlExtensionFunction.cs
- ToolstripProfessionalRenderer.cs
- DbProviderFactory.cs
- ThreadAttributes.cs
- ZoneButton.cs
- CaseCqlBlock.cs
- ProcessProtocolHandler.cs
- XmlDataProvider.cs
- _IPv6Address.cs
- Mouse.cs
- EmptyEnumerable.cs
- ChangePasswordDesigner.cs
- FontStretchConverter.cs
- ConfigDefinitionUpdates.cs
- SynchronizationContext.cs
- DataGridState.cs
- Padding.cs
- TypeNameConverter.cs
- OleDbEnumerator.cs
- SectionXmlInfo.cs
- COM2FontConverter.cs
- TypeSystem.cs
- TTSEngineTypes.cs
- Double.cs
- Registry.cs
- ArrayElementGridEntry.cs
- Attributes.cs
- PointKeyFrameCollection.cs
- SoapRpcMethodAttribute.cs
- InputProcessorProfilesLoader.cs
- OracleConnectionStringBuilder.cs
- TransactionOptions.cs