You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,167 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="BasicCellRelation.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.Bharani1729
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Mapping.ViewGeneration.Structures;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Data.Common.Utils;
|
||||
using System.Data.Metadata.Edm;
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
|
||||
using BasicSchemaConstraints = SchemaConstraints<BasicKeyConstraint>;
|
||||
|
||||
// This class represents a relation signature that lists all scalar
|
||||
// slots for the join tree in cell query (before projection)
|
||||
internal class BasicCellRelation : CellRelation
|
||||
{
|
||||
|
||||
#region Constructor
|
||||
// effects: Creates a basic cell relation for query
|
||||
internal BasicCellRelation(CellQuery cellQuery, ViewCellRelation viewCellRelation,
|
||||
IEnumerable<MemberProjectedSlot> slots)
|
||||
: base(viewCellRelation.CellNumber)
|
||||
{
|
||||
m_cellQuery = cellQuery;
|
||||
m_slots = new List<MemberProjectedSlot>(slots);
|
||||
Debug.Assert(m_slots.Count > 0, "Cell relation with not even an exent?");
|
||||
m_viewCellRelation = viewCellRelation;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private CellQuery m_cellQuery;
|
||||
private List<MemberProjectedSlot> m_slots;
|
||||
private ViewCellRelation m_viewCellRelation; // The viewcellrelation
|
||||
// corresponding to this basiccellrelation
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
internal ViewCellRelation ViewCellRelation
|
||||
{
|
||||
get { return m_viewCellRelation; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Key Constraints Methods
|
||||
// effects: Modifies constraints to contain the key constraints that
|
||||
// are present in this relation
|
||||
internal void PopulateKeyConstraints(BasicSchemaConstraints constraints)
|
||||
{
|
||||
Debug.Assert(this == m_cellQuery.BasicCellRelation, "Cellquery does not point to the correct BasicCellRelation?");
|
||||
Debug.Assert(m_cellQuery.Extent is EntitySet || m_cellQuery.Extent is AssociationSet,
|
||||
"Top level extents handled is currently entityset or association set");
|
||||
if (m_cellQuery.Extent is EntitySet)
|
||||
{
|
||||
PopulateKeyConstraintsForEntitySet(constraints);
|
||||
}
|
||||
else
|
||||
{
|
||||
PopulateKeyConstraintsForRelationshipSet(constraints);
|
||||
}
|
||||
}
|
||||
|
||||
// requires: this to correspond to a cell relation for an entityset (m_cellQuery.Extent)
|
||||
// effects: Adds any key constraints present in this to constraints
|
||||
private void PopulateKeyConstraintsForEntitySet(BasicSchemaConstraints constraints)
|
||||
{
|
||||
MemberPath prefix = new MemberPath(m_cellQuery.Extent);
|
||||
EntityType entityType = (EntityType)m_cellQuery.Extent.ElementType;
|
||||
|
||||
// Get all the keys for the entity type and create the key constraints
|
||||
List<ExtentKey> keys = ExtentKey.GetKeysForEntityType(prefix, entityType);
|
||||
AddKeyConstraints(keys, constraints);
|
||||
}
|
||||
|
||||
// requires: this to correspond to a cell relation for an association set (m_cellQuery.Extent)
|
||||
// effects: Adds any key constraints present in this relation in
|
||||
// constraints
|
||||
private void PopulateKeyConstraintsForRelationshipSet(BasicSchemaConstraints constraints)
|
||||
{
|
||||
AssociationSet relationshipSet = m_cellQuery.Extent as AssociationSet;
|
||||
// Gather all members of all keys
|
||||
// CHANGE_[....]_FEATURE_KEYS: assume that an Entity has exactly one key. Otherwise we
|
||||
// have to take a cross-product of all keys
|
||||
|
||||
// Keep track of all the key members for the association in a set
|
||||
// so that if no end corresponds to a key, we use all the members
|
||||
// to form the key
|
||||
Set<MemberPath> associationKeyMembers = new Set<MemberPath>(MemberPath.EqualityComparer);
|
||||
bool hasAnEndThatFormsKey = false;
|
||||
|
||||
// Determine the keys of each end. If the end forms a key, add it
|
||||
// as a key to the set
|
||||
|
||||
foreach (AssociationSetEnd end in relationshipSet.AssociationSetEnds)
|
||||
{
|
||||
AssociationEndMember endMember = end.CorrespondingAssociationEndMember;
|
||||
|
||||
MemberPath prefix = new MemberPath(relationshipSet, endMember);
|
||||
List<ExtentKey> keys = ExtentKey.GetKeysForEntityType(prefix, end.EntitySet.ElementType);
|
||||
Debug.Assert(keys.Count > 0, "No keys for entity?");
|
||||
Debug.Assert(keys.Count == 1, "Currently, we only support primary keys");
|
||||
|
||||
if (MetadataHelper.DoesEndFormKey(relationshipSet, endMember))
|
||||
{
|
||||
// This end has is a key end
|
||||
AddKeyConstraints(keys, constraints);
|
||||
hasAnEndThatFormsKey = true;
|
||||
}
|
||||
// Add the members of the (only) key to associationKey
|
||||
associationKeyMembers.AddRange(keys[0].KeyFields);
|
||||
}
|
||||
// If an end forms a key then that key implies the full key
|
||||
if (false == hasAnEndThatFormsKey)
|
||||
{
|
||||
// No end is a key -- take all the end members and make a key
|
||||
// based on that
|
||||
ExtentKey key = new ExtentKey(associationKeyMembers);
|
||||
ExtentKey[] keys = new ExtentKey[] { key };
|
||||
AddKeyConstraints(keys, constraints);
|
||||
}
|
||||
}
|
||||
|
||||
// effects: Given keys for this relation, adds one key constraint for
|
||||
// each key present in keys
|
||||
private void AddKeyConstraints(IEnumerable<ExtentKey> keys, BasicSchemaConstraints constraints)
|
||||
{
|
||||
foreach (ExtentKey key in keys)
|
||||
{
|
||||
// If the key is being projected, only then do we add the key constraint
|
||||
|
||||
List<MemberProjectedSlot> keySlots = MemberProjectedSlot.GetSlots(m_slots, key.KeyFields);
|
||||
if (keySlots != null)
|
||||
{
|
||||
BasicKeyConstraint keyConstraint = new BasicKeyConstraint(this, keySlots);
|
||||
constraints.Add(keyConstraint);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Comparer/String Methods
|
||||
protected override int GetHash()
|
||||
{
|
||||
// Note: Using CLR-Hashcode
|
||||
return m_cellQuery.GetHashCode();
|
||||
// We need not hash the slots, etc - cellQuery should give us enough
|
||||
// differentiation and land the relation into the same bucket
|
||||
}
|
||||
|
||||
internal override void ToCompactString(StringBuilder builder)
|
||||
{
|
||||
builder.Append("BasicRel: ");
|
||||
// Just print the extent name from slot 0
|
||||
StringUtil.FormatStringBuilder(builder, "{0}", m_slots[0]);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="BasicKeyConstraint.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
using System.Data.Mapping.ViewGeneration.Structures;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
|
||||
using BasicSchemaConstraints = SchemaConstraints<BasicKeyConstraint>;
|
||||
|
||||
// Class representing a key constraint on the basic cell relations
|
||||
internal class BasicKeyConstraint : KeyConstraint<BasicCellRelation, MemberProjectedSlot>
|
||||
{
|
||||
|
||||
#region Constructor
|
||||
// Constructs a key constraint for the given relation and keyslots
|
||||
internal BasicKeyConstraint(BasicCellRelation relation, IEnumerable<MemberProjectedSlot> keySlots)
|
||||
: base(relation, keySlots, ProjectedSlot.EqualityComparer)
|
||||
{ }
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
// effects: Propagates this constraint from the basic cell relation
|
||||
// to the corresponding view cell relation and returns the new constraint
|
||||
// If all the key slots are not being projected, returns null
|
||||
internal ViewKeyConstraint Propagate()
|
||||
{
|
||||
ViewCellRelation viewCellRelation = CellRelation.ViewCellRelation;
|
||||
// If all slots appear in the projection, propagate key constraint
|
||||
List<ViewCellSlot> viewSlots = new List<ViewCellSlot>();
|
||||
foreach (MemberProjectedSlot keySlot in KeySlots)
|
||||
{
|
||||
ViewCellSlot viewCellSlot = viewCellRelation.LookupViewSlot(keySlot);
|
||||
if (viewCellSlot == null)
|
||||
{
|
||||
// Slot is missing -- no key constraint on the view relation
|
||||
return null;
|
||||
}
|
||||
viewSlots.Add(viewCellSlot);
|
||||
}
|
||||
|
||||
// Create a key on view relation
|
||||
ViewKeyConstraint viewKeyConstraint = new ViewKeyConstraint(viewCellRelation, viewSlots);
|
||||
return viewKeyConstraint;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="CellRelation.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
using System.Data.Common.Utils;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
// Abstract class representing a relation signature for a cell query
|
||||
internal abstract class CellRelation : InternalBase
|
||||
{
|
||||
|
||||
#region Constructor
|
||||
// effects: Given a cell number (for debugging purposes), creates a
|
||||
// cell relation
|
||||
protected CellRelation(int cellNumber)
|
||||
{
|
||||
m_cellNumber = cellNumber;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
internal int m_cellNumber; // The number of the cell for which this
|
||||
// relation was made (for debugging)
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
internal int CellNumber
|
||||
{
|
||||
get { return m_cellNumber; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected abstract int GetHash();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ConstraintBase.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner srimand
|
||||
// @backupOwner cmeek
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Data.Common.Utils;
|
||||
using System.Data.Common.Utils.Boolean;
|
||||
using System.Data.Mapping.ViewGeneration.Structures;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
|
||||
using WrapperBoolExpr = BoolExpr<LeftCellWrapper>;
|
||||
using WrapperTreeExpr = TreeExpr<LeftCellWrapper>;
|
||||
using WrapperAndExpr = AndExpr<LeftCellWrapper>;
|
||||
using WrapperOrExpr = OrExpr<LeftCellWrapper>;
|
||||
using WrapperNotExpr = NotExpr<LeftCellWrapper>;
|
||||
using WrapperTermExpr = TermExpr<LeftCellWrapper>;
|
||||
using WrapperTrueExpr = TrueExpr<LeftCellWrapper>;
|
||||
using WrapperFalseExpr = FalseExpr<LeftCellWrapper>;
|
||||
|
||||
// A superclass for constraint errors. It also contains useful constraint
|
||||
// checking methods
|
||||
internal abstract class ConstraintBase : InternalBase
|
||||
{
|
||||
|
||||
#region Methods
|
||||
// effects: Returns an error log record with this constraint's information
|
||||
internal abstract ErrorLog.Record GetErrorRecord();
|
||||
#endregion
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,106 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ExtentKey.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
using System.Data.Common.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Data.Metadata.Edm;
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Structures
|
||||
{
|
||||
|
||||
// This class represents the key of constraint on values that a relation slot may have
|
||||
internal class ExtentKey : InternalBase
|
||||
{
|
||||
|
||||
#region Constructors
|
||||
// effects: Creates a key object for an extent (present in each MemberPath)
|
||||
// with the fields corresponding to keyFields
|
||||
internal ExtentKey(IEnumerable<MemberPath> keyFields)
|
||||
{
|
||||
m_keyFields = new List<MemberPath>(keyFields);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
// All the key fields in an entity set
|
||||
private List<MemberPath> m_keyFields;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
internal IEnumerable<MemberPath> KeyFields
|
||||
{
|
||||
get { return m_keyFields; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
// effects: Determines all the keys (unique and primary for
|
||||
// entityType) for entityType and returns a key. "prefix" gives the
|
||||
// path of the extent or end of a relationship in a relationship set
|
||||
// -- prefix is prepended to the entity's key fields to get the full memberpath
|
||||
internal static List<ExtentKey> GetKeysForEntityType(MemberPath prefix, EntityType entityType)
|
||||
{
|
||||
// CHANGE_[....]_MULTIPLE_KEYS: currently there is a single key only. Need to support
|
||||
// keys inside complex types + unique keys
|
||||
ExtentKey key = GetPrimaryKeyForEntityType(prefix, entityType);
|
||||
|
||||
List<ExtentKey> keys = new List<ExtentKey>();
|
||||
keys.Add(key);
|
||||
return keys;
|
||||
}
|
||||
|
||||
// effects: Returns the key for entityType prefixed with prefix (for
|
||||
// its memberPath)
|
||||
internal static ExtentKey GetPrimaryKeyForEntityType(MemberPath prefix, EntityType entityType)
|
||||
{
|
||||
List<MemberPath> keyFields = new List<MemberPath>();
|
||||
foreach (EdmMember keyMember in entityType.KeyMembers)
|
||||
{
|
||||
Debug.Assert(keyMember != null, "Bogus key member in metadata");
|
||||
keyFields.Add(new MemberPath(prefix, keyMember));
|
||||
}
|
||||
|
||||
// Just have one key for now
|
||||
ExtentKey key = new ExtentKey(keyFields);
|
||||
return key;
|
||||
}
|
||||
|
||||
// effects: Returns a key correspnding to all the fields in different
|
||||
// ends of relationtype prefixed with "prefix"
|
||||
internal static ExtentKey GetKeyForRelationType(MemberPath prefix, AssociationType relationType)
|
||||
{
|
||||
List<MemberPath> keyFields = new List<MemberPath>();
|
||||
|
||||
foreach (AssociationEndMember endMember in relationType.AssociationEndMembers)
|
||||
{
|
||||
MemberPath endPrefix = new MemberPath(prefix, endMember);
|
||||
EntityType entityType = MetadataHelper.GetEntityTypeForEnd(endMember);
|
||||
ExtentKey primaryKey = GetPrimaryKeyForEntityType(endPrefix, entityType);
|
||||
keyFields.AddRange(primaryKey.KeyFields);
|
||||
}
|
||||
ExtentKey key = new ExtentKey(keyFields);
|
||||
return key;
|
||||
}
|
||||
|
||||
internal string ToUserString()
|
||||
{
|
||||
string result = StringUtil.ToCommaSeparatedStringSorted(m_keyFields);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal override void ToCompactString(StringBuilder builder)
|
||||
{
|
||||
StringUtil.ToCommaSeparatedStringSorted(builder, m_keyFields);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,61 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="KeyConstraint.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Data.Common.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
// Class representing a key constraint for particular cellrelation
|
||||
internal class KeyConstraint<TCellRelation, TSlot> : InternalBase
|
||||
where TCellRelation : CellRelation
|
||||
{
|
||||
|
||||
#region Constructor
|
||||
// Constructs a key constraint for the given relation and keyslots
|
||||
// with comparer being the comparison operator for comparing various
|
||||
// keyslots in Implies, etc
|
||||
internal KeyConstraint(TCellRelation relation, IEnumerable<TSlot> keySlots, IEqualityComparer<TSlot> comparer)
|
||||
{
|
||||
m_relation = relation;
|
||||
m_keySlots = new Set<TSlot>(keySlots, comparer).MakeReadOnly();
|
||||
Debug.Assert(m_keySlots.Count > 0, "Key constraint being created without any keyslots?");
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private TCellRelation m_relation;
|
||||
private Set<TSlot> m_keySlots;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
protected TCellRelation CellRelation
|
||||
{
|
||||
get { return m_relation; }
|
||||
}
|
||||
|
||||
protected Set<TSlot> KeySlots
|
||||
{
|
||||
get { return m_keySlots; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
internal override void ToCompactString(StringBuilder builder)
|
||||
{
|
||||
StringUtil.FormatStringBuilder(builder, "Key (V{0}) - ", m_relation.CellNumber);
|
||||
StringUtil.ToSeparatedStringSorted(builder, KeySlots, ", ");
|
||||
// The slots contain the name of the relation: So we skip
|
||||
// printing the CellRelation
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,70 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="SchemaConstraints.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
|
||||
using System.Data.Common.Utils;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// A class representing a set of constraints. It uses generic parameters
|
||||
/// so that we can get strong typing and avoid downcasts
|
||||
/// </summary>
|
||||
internal class SchemaConstraints<TKeyConstraint> : InternalBase
|
||||
where TKeyConstraint : InternalBase
|
||||
{
|
||||
|
||||
#region Constructor
|
||||
// effects: Creates an empty set of constraints
|
||||
internal SchemaConstraints()
|
||||
{
|
||||
m_keyConstraints = new List<TKeyConstraint>();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
// Use different lists so we can enumerate the right kind of constraints
|
||||
private List<TKeyConstraint> m_keyConstraints;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
internal IEnumerable<TKeyConstraint> KeyConstraints
|
||||
{
|
||||
get { return m_keyConstraints; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
// effects: Adds a key constraint to this
|
||||
internal void Add(TKeyConstraint constraint)
|
||||
{
|
||||
EntityUtil.CheckArgumentNull(constraint, "constraint");
|
||||
m_keyConstraints.Add(constraint);
|
||||
}
|
||||
|
||||
// effects: Converts constraints to human-readable strings and adds them to builder
|
||||
private static void ConstraintsToBuilder<Constraint>(IEnumerable<Constraint> constraints, StringBuilder builder)
|
||||
where Constraint : InternalBase
|
||||
{
|
||||
foreach (Constraint constraint in constraints)
|
||||
{
|
||||
constraint.ToCompactString(builder);
|
||||
builder.Append(Environment.NewLine);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void ToCompactString(StringBuilder builder)
|
||||
{
|
||||
ConstraintsToBuilder(m_keyConstraints, builder);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,95 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ViewCellRelation.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Mapping.ViewGeneration.Structures;
|
||||
using System.Text;
|
||||
using System.Data.Common.Utils;
|
||||
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a relation signature that lists all projected
|
||||
/// slots of two cell queries in a cell after projection. So if
|
||||
/// SPerson1.Disc is present in the cellquery (and part of the where
|
||||
/// clause) but not in the projected slots, it is missing from a ViewCellRelation
|
||||
/// </summary>
|
||||
internal class ViewCellRelation : CellRelation
|
||||
{
|
||||
|
||||
#region Constructor
|
||||
// effects: Creates a view cell relation for "cell" with the
|
||||
// projected slots given by slots -- cellNumber is the number of the
|
||||
// cell for debugging purposes
|
||||
// Also creates the BasicCellRelations for the left and right cell queries
|
||||
internal ViewCellRelation(Cell cell, List<ViewCellSlot> slots, int cellNumber)
|
||||
: base(cellNumber)
|
||||
{
|
||||
m_cell = cell;
|
||||
m_slots = slots;
|
||||
// We create the basiccellrelations passing this to it so that we have
|
||||
// a reference from the basiccellrelations to this
|
||||
m_cell.CQuery.CreateBasicCellRelation(this);
|
||||
m_cell.SQuery.CreateBasicCellRelation(this);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private Cell m_cell; // The cell for which this relation exists
|
||||
private List<ViewCellSlot> m_slots; // Slots projected from both cell queries
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
internal Cell Cell
|
||||
{
|
||||
get { return m_cell; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Methods
|
||||
// requires: slot corresponds to a slot in the corresponding
|
||||
// BasicCellRelation
|
||||
// effects: Given a slot in the corresponding basicCellRelation,
|
||||
// looks up the slot in this viewcellrelation and returns it. Returns
|
||||
// null if it does not find the slot in the left or right side of the viewrelation
|
||||
internal ViewCellSlot LookupViewSlot(MemberProjectedSlot slot)
|
||||
{
|
||||
// CHANGE_[....]_IMPROVE: We could have a dictionary to speed this up
|
||||
foreach (ViewCellSlot viewSlot in m_slots)
|
||||
{
|
||||
// If the left or right slots are equal, return the viewSlot
|
||||
if (ProjectedSlot.EqualityComparer.Equals(slot, viewSlot.CSlot) ||
|
||||
ProjectedSlot.EqualityComparer.Equals(slot, viewSlot.SSlot))
|
||||
{
|
||||
return viewSlot;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override int GetHash()
|
||||
{
|
||||
// Note: Using CLR-Hashcode
|
||||
return m_cell.GetHashCode();
|
||||
// We need not hash the slots, etc - cell should give us enough
|
||||
// differentiation and land the relation into the same bucket
|
||||
}
|
||||
|
||||
internal override void ToCompactString(StringBuilder builder)
|
||||
{
|
||||
builder.Append("ViewRel[");
|
||||
m_cell.ToCompactString(builder);
|
||||
// StringUtil.ToSeparatedStringSorted(builder, m_slots, ", ");
|
||||
builder.Append(']');
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,148 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ViewCellSlot.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common.CommandTrees;
|
||||
using System.Data.Common.Utils;
|
||||
using System.Data.Mapping.ViewGeneration.Structures;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Represents a slot that is projected by C and S queries in a cell.
|
||||
/// </summary>
|
||||
internal class ViewCellSlot : ProjectedSlot
|
||||
{
|
||||
#region Constructor
|
||||
// effects:
|
||||
/// <summary>
|
||||
/// Creates a view cell slot that corresponds to <paramref name="slotNum"/> in some cell. The <paramref name="cSlot"/> and <paramref name="sSlot"/> represent the
|
||||
/// slots in the left and right queries of the view cell.
|
||||
/// </summary>
|
||||
internal ViewCellSlot(int slotNum, MemberProjectedSlot cSlot, MemberProjectedSlot sSlot)
|
||||
{
|
||||
m_slotNum = slotNum;
|
||||
m_cSlot = cSlot;
|
||||
m_sSlot = sSlot;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Fields
|
||||
private readonly int m_slotNum;
|
||||
private readonly MemberProjectedSlot m_cSlot;
|
||||
private readonly MemberProjectedSlot m_sSlot;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// Returns the slot corresponding to the left cellquery.
|
||||
/// </summary>
|
||||
internal MemberProjectedSlot CSlot
|
||||
{
|
||||
get { return m_cSlot; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the slot corresponding to the right cellquery.
|
||||
/// </summary>
|
||||
internal MemberProjectedSlot SSlot
|
||||
{
|
||||
get { return m_sSlot; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Comparer/String Methods
|
||||
protected override bool IsEqualTo(ProjectedSlot right)
|
||||
{
|
||||
ViewCellSlot rightSlot = right as ViewCellSlot;
|
||||
if (rightSlot == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return m_slotNum == rightSlot.m_slotNum &&
|
||||
MemberProjectedSlot.EqualityComparer.Equals(m_cSlot, rightSlot.m_cSlot) &&
|
||||
MemberProjectedSlot.EqualityComparer.Equals(m_sSlot, rightSlot.m_sSlot);
|
||||
}
|
||||
|
||||
protected override int GetHash()
|
||||
{
|
||||
return MemberProjectedSlot.EqualityComparer.GetHashCode(m_cSlot) ^
|
||||
MemberProjectedSlot.EqualityComparer.GetHashCode(m_sSlot) ^
|
||||
m_slotNum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Given a list of <paramref name="slots"/>, converts the left/right slots (if left is true/false) to a human-readable string.
|
||||
/// </summary>
|
||||
internal static string SlotsToUserString(IEnumerable<ViewCellSlot> slots, bool isFromCside)
|
||||
{
|
||||
StringBuilder builder = new StringBuilder();
|
||||
bool first = true;
|
||||
foreach (ViewCellSlot slot in slots)
|
||||
{
|
||||
if (false == first)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
builder.Append(SlotToUserString(slot, isFromCside));
|
||||
first = false;
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
internal static string SlotToUserString(ViewCellSlot slot, bool isFromCside)
|
||||
{
|
||||
MemberProjectedSlot actualSlot = isFromCside ? slot.CSlot : slot.SSlot;
|
||||
string result = StringUtil.FormatInvariant("{0}", actualSlot);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not supported in this class.
|
||||
/// </summary>
|
||||
internal override string GetCqlFieldAlias(MemberPath outputMember)
|
||||
{
|
||||
Debug.Fail("Should not be called.");
|
||||
return null; // To keep the compiler happy
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not supported in this class.
|
||||
/// </summary>
|
||||
internal override StringBuilder AsEsql(StringBuilder builder, MemberPath outputMember, string blockAlias, int indentLevel)
|
||||
{
|
||||
Debug.Fail("Should not be called.");
|
||||
return null; // To keep the compiler happy
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Not supported in this class.
|
||||
/// </summary>
|
||||
internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember)
|
||||
{
|
||||
Debug.Fail("Should not be called.");
|
||||
return null;
|
||||
}
|
||||
|
||||
internal override void ToCompactString(StringBuilder builder)
|
||||
{
|
||||
builder.Append('<');
|
||||
StringUtil.FormatStringBuilder(builder, "{0}", m_slotNum);
|
||||
builder.Append(':');
|
||||
m_cSlot.ToCompactString(builder);
|
||||
builder.Append('-');
|
||||
m_sSlot.ToCompactString(builder);
|
||||
builder.Append('>');
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
@@ -0,0 +1,191 @@
|
||||
//---------------------------------------------------------------------
|
||||
// <copyright file="ViewKeyConstraint.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//
|
||||
// @owner [....]
|
||||
// @backupOwner [....]
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
namespace System.Data.Mapping.ViewGeneration.Validation
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Data.Common.Utils;
|
||||
using System.Data.Entity;
|
||||
using System.Data.Mapping.ViewGeneration.Structures;
|
||||
using System.Data.Mapping.ViewGeneration.Utils;
|
||||
using System.Data.Metadata.Edm;
|
||||
using System.Text;
|
||||
|
||||
// Class representing a key constraint on the view cell relations
|
||||
internal class ViewKeyConstraint : KeyConstraint<ViewCellRelation, ViewCellSlot>
|
||||
{
|
||||
|
||||
|
||||
#region Constructor
|
||||
// effects: Constructs a key constraint for the given relation and keyslots
|
||||
internal ViewKeyConstraint(ViewCellRelation relation, IEnumerable<ViewCellSlot> keySlots) :
|
||||
base(relation, keySlots, ProjectedSlot.EqualityComparer)
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
// effects: Returns the cell corresponding to this constraint
|
||||
internal Cell Cell
|
||||
{
|
||||
get { return CellRelation.Cell; }
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
internal bool Implies(ViewKeyConstraint second)
|
||||
{
|
||||
if (false == Object.ReferenceEquals(CellRelation, second.CellRelation))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Check if the slots in this key are a subset of slots in
|
||||
// second. If it is a key in this e.g., <A.pid> then <A.pid,
|
||||
// A.foo> is certainly a key as well
|
||||
|
||||
if (KeySlots.IsSubsetOf(second.KeySlots))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now check for subsetting taking referential constraints into account
|
||||
// Check that each slot in KeySlots can be found in second.KeySlots if we take
|
||||
// slot equivalence into account
|
||||
|
||||
Set<ViewCellSlot> secondKeySlots = new Set<ViewCellSlot>(second.KeySlots);
|
||||
|
||||
foreach (ViewCellSlot firstSlot in KeySlots)
|
||||
{
|
||||
bool found = false; // Need to find a match for firstSlot
|
||||
|
||||
foreach (ViewCellSlot secondSlot in secondKeySlots)
|
||||
{
|
||||
if (ProjectedSlot.EqualityComparer.Equals(firstSlot.SSlot, secondSlot.SSlot))
|
||||
{
|
||||
// S-side is the same. Check if C-side is the same as well. If so, remove it
|
||||
// from secondKeySlots
|
||||
// We have to check for C-side equivalence in terms of actual equality
|
||||
// and equivalence via ref constraints. The former is needed since the
|
||||
// S-side key slots would typically be mapped to the same C-side slot.
|
||||
// The latter is needed since the same S-side key slot could be mapped
|
||||
// into two slots on the C-side that are connected via a ref constraint
|
||||
MemberPath path1 = firstSlot.CSlot.MemberPath;
|
||||
MemberPath path2 = secondSlot.CSlot.MemberPath;
|
||||
if (MemberPath.EqualityComparer.Equals(path1, path2) || path1.IsEquivalentViaRefConstraint(path2))
|
||||
{
|
||||
secondKeySlots.Remove(secondSlot);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found == false)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The subsetting holds when referential constraints are taken into account
|
||||
return true;
|
||||
}
|
||||
|
||||
// effects: Given the fact that rightKeyConstraint is not implied by a
|
||||
// leftSide key constraint, return a useful error message -- some S
|
||||
// was not implied by the C key constraints
|
||||
internal static ErrorLog.Record GetErrorRecord(ViewKeyConstraint rightKeyConstraint)
|
||||
{
|
||||
List<ViewCellSlot> keySlots = new List<ViewCellSlot>(rightKeyConstraint.KeySlots);
|
||||
EntitySetBase table = keySlots[0].SSlot.MemberPath.Extent;
|
||||
EntitySetBase cSet = keySlots[0].CSlot.MemberPath.Extent;
|
||||
|
||||
MemberPath tablePrefix = new MemberPath(table);
|
||||
MemberPath cSetPrefix = new MemberPath(cSet);
|
||||
|
||||
ExtentKey tableKey = ExtentKey.GetPrimaryKeyForEntityType(tablePrefix, (EntityType)table.ElementType);
|
||||
ExtentKey cSetKey = null;
|
||||
if (cSet is EntitySet)
|
||||
{
|
||||
cSetKey = ExtentKey.GetPrimaryKeyForEntityType(cSetPrefix, (EntityType)cSet.ElementType);
|
||||
}
|
||||
else
|
||||
{
|
||||
cSetKey = ExtentKey.GetKeyForRelationType(cSetPrefix, (AssociationType)cSet.ElementType);
|
||||
}
|
||||
|
||||
string message = Strings.ViewGen_KeyConstraint_Violation(
|
||||
table.Name,
|
||||
ViewCellSlot.SlotsToUserString(rightKeyConstraint.KeySlots, false /*isFromCside*/),
|
||||
tableKey.ToUserString(),
|
||||
cSet.Name,
|
||||
ViewCellSlot.SlotsToUserString(rightKeyConstraint.KeySlots, true /*isFromCside*/),
|
||||
cSetKey.ToUserString());
|
||||
|
||||
string debugMessage = StringUtil.FormatInvariant("PROBLEM: Not implied {0}", rightKeyConstraint);
|
||||
return new ErrorLog.Record(true, ViewGenErrorCode.KeyConstraintViolation, message, rightKeyConstraint.CellRelation.Cell, debugMessage);
|
||||
}
|
||||
|
||||
// effects: Given the fact that none of the rightKeyConstraint are not implied by a
|
||||
// leftSide key constraint, return a useful error message (used for
|
||||
// the Update requirement
|
||||
internal static ErrorLog.Record GetErrorRecord(IEnumerable<ViewKeyConstraint> rightKeyConstraints)
|
||||
{
|
||||
ViewKeyConstraint rightKeyConstraint = null;
|
||||
StringBuilder keyBuilder = new StringBuilder();
|
||||
bool isFirst = true;
|
||||
foreach (ViewKeyConstraint rightConstraint in rightKeyConstraints)
|
||||
{
|
||||
string keyMsg = ViewCellSlot.SlotsToUserString(rightConstraint.KeySlots, true /*isFromCside*/);
|
||||
if (isFirst == false)
|
||||
{
|
||||
keyBuilder.Append("; ");
|
||||
}
|
||||
isFirst = false;
|
||||
keyBuilder.Append(keyMsg);
|
||||
rightKeyConstraint = rightConstraint;
|
||||
}
|
||||
|
||||
List<ViewCellSlot> keySlots = new List<ViewCellSlot>(rightKeyConstraint.KeySlots);
|
||||
EntitySetBase table = keySlots[0].SSlot.MemberPath.Extent;
|
||||
EntitySetBase cSet = keySlots[0].CSlot.MemberPath.Extent;
|
||||
|
||||
MemberPath tablePrefix = new MemberPath(table);
|
||||
ExtentKey tableKey = ExtentKey.GetPrimaryKeyForEntityType(tablePrefix, (EntityType)table.ElementType);
|
||||
|
||||
string message;
|
||||
if (cSet is EntitySet)
|
||||
{
|
||||
message = System.Data.Entity.Strings.ViewGen_KeyConstraint_Update_Violation_EntitySet(keyBuilder.ToString(), cSet.Name,
|
||||
tableKey.ToUserString(), table.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
//For a 1:* or 0..1:* association, the * side has to be mapped to the
|
||||
//key properties of the table. Fior this specific case, we give out a specific message
|
||||
//that is specific for this case.
|
||||
AssociationSet associationSet = (AssociationSet)cSet;
|
||||
AssociationEndMember endMember = Helper.GetEndThatShouldBeMappedToKey(associationSet.ElementType);
|
||||
if(endMember != null)
|
||||
{
|
||||
message = System.Data.Entity.Strings.ViewGen_AssociationEndShouldBeMappedToKey(endMember.Name,
|
||||
table.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
message = System.Data.Entity.Strings.ViewGen_KeyConstraint_Update_Violation_AssociationSet(cSet.Name,
|
||||
tableKey.ToUserString(), table.Name);
|
||||
}
|
||||
}
|
||||
|
||||
string debugMessage = StringUtil.FormatInvariant("PROBLEM: Not implied {0}", rightKeyConstraint);
|
||||
return new ErrorLog.Record(true, ViewGenErrorCode.KeyConstraintUpdateViolation, message, rightKeyConstraint.CellRelation.Cell, debugMessage);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user