//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.CommandTrees; using System.Data.Common.Utils; using System.Collections.Generic; using System.Text; using System.Diagnostics; using System.Linq; namespace System.Data.Mapping.ViewGeneration.Structures { using DomainConstraint = System.Data.Common.Utils.Boolean.DomainConstraint; using DomainVariable = System.Data.Common.Utils.Boolean.DomainVariable; using DomainBoolExpr = System.Data.Common.Utils.Boolean.BoolExpr>; using DomainNotExpr = System.Data.Common.Utils.Boolean.NotExpr >; using DomainTermExpr = System.Data.Common.Utils.Boolean.TermExpr>; /// /// A class that ties up all the literals in boolean expressions. /// Conditions represented by s need to be synchronized with s, /// which may be modified upon calling . This is what the method is used for. /// internal abstract class BoolLiteral : InternalBase { #region Fields internal static readonly IEqualityComparer EqualityComparer = new BoolLiteralComparer(); internal static readonly IEqualityComparer EqualityIdentifierComparer = new IdentifierComparer(); #endregion #region Static MakeTermExpression methods /// /// Creates a term expression of the form: " in with all possible values being ". /// internal static DomainTermExpr MakeTermExpression(BoolLiteral literal, IEnumerable domain, IEnumerable range) { Set domainSet = new Set(domain, Constant.EqualityComparer); Set rangeSet = new Set(range, Constant.EqualityComparer); return MakeTermExpression(literal, domainSet, rangeSet); } /// /// Creates a term expression of the form: " in with all possible values being ". /// internal static DomainTermExpr MakeTermExpression(BoolLiteral literal, Set domain, Set range) { domain.MakeReadOnly(); range.MakeReadOnly(); DomainVariable variable = new DomainVariable(literal, domain, EqualityIdentifierComparer); DomainConstraint constraint = new DomainConstraint(variable, range); DomainTermExpr result = new DomainTermExpr(EqualityComparer.Default, constraint); return result; } #endregion #region Virtual methods /// /// Fixes the range of the literal using the new values provided in and returns a boolean expression corresponding to the new value. /// internal abstract DomainBoolExpr FixRange(Set range, MemberDomainMap memberDomainMap); internal abstract DomainBoolExpr GetDomainBoolExpression(MemberDomainMap domainMap); /// /// See . /// internal abstract BoolLiteral RemapBool(Dictionary remap); /// /// See . /// /// /// internal abstract void GetRequiredSlots(MemberProjectionIndex projectedSlotMap, bool[] requiredSlots); /// /// See . /// internal abstract StringBuilder AsEsql(StringBuilder builder, string blockAlias, bool skipIsNotNull); /// /// See . /// internal abstract DbExpression AsCqt(DbExpression row, bool skipIsNotNull); internal abstract StringBuilder AsUserString(StringBuilder builder, string blockAlias, bool skipIsNotNull); internal abstract StringBuilder AsNegatedUserString(StringBuilder builder, string blockAlias, bool skipIsNotNull); /// /// Checks if the identifier in this is the same as the one in . /// protected virtual bool IsIdentifierEqualTo(BoolLiteral right) { return IsEqualTo(right); } protected abstract bool IsEqualTo(BoolLiteral right); /// /// Get the hash code based on the identifier. /// protected virtual int GetIdentifierHash() { return GetHashCode(); } #endregion #region Comparer class /// /// This class compares boolean expressions. /// private sealed class BoolLiteralComparer : IEqualityComparer { public bool Equals(BoolLiteral left, BoolLiteral right) { // Quick check with references if (object.ReferenceEquals(left, right)) { // Gets the Null and Undefined case as well return true; } // One of them is non-null at least if (left == null || right == null) { return false; } // Both are non-null at this point return left.IsEqualTo(right); } public int GetHashCode(BoolLiteral literal) { return literal.GetHashCode(); } } #endregion #region Identifier Comparer class /// /// This class compares just the identifier in boolean expressions. /// private sealed class IdentifierComparer : IEqualityComparer { public bool Equals(BoolLiteral left, BoolLiteral right) { // Quick check with references if (object.ReferenceEquals(left, right)) { // Gets the Null and Undefined case as well return true; } // One of them is non-null at least if (left == null || right == null) { return false; } // Both are non-null at this point return left.IsIdentifierEqualTo(right); } public int GetHashCode(BoolLiteral literal) { return literal.GetIdentifierHash(); } } #endregion } internal abstract class TrueFalseLiteral : BoolLiteral { internal override DomainBoolExpr GetDomainBoolExpression(MemberDomainMap domainMap) { // Essentially say that the variable can take values true or false and here its value is only true IEnumerable actualValues = new Constant[] { new ScalarConstant(true) }; IEnumerable possibleValues = new Constant[] { new ScalarConstant(true), new ScalarConstant(false) }; Set variableDomain = new Set(possibleValues, Constant.EqualityComparer).MakeReadOnly(); Set thisDomain = new Set(actualValues, Constant.EqualityComparer).MakeReadOnly(); DomainTermExpr result = MakeTermExpression(this, variableDomain, thisDomain); return result; } internal override DomainBoolExpr FixRange(Set range, MemberDomainMap memberDomainMap) { Debug.Assert(range.Count == 1, "For BoolLiterals, there should be precisely one value - true or false"); ScalarConstant scalar = (ScalarConstant)range.First(); DomainBoolExpr expr = GetDomainBoolExpression(memberDomainMap); if ((bool)scalar.Value == false) { // The range of the variable was "inverted". Return a NOT of // the expression expr = new DomainNotExpr(expr); } return expr; } } }