//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Data.Common.CommandTrees; using System.Data.Common.CommandTrees.ExpressionBuilder; using System.Data.Common.Utils; using System.Data.Mapping.ViewGeneration.Structures; using System.Text; using System.Diagnostics; namespace System.Data.Mapping.ViewGeneration.CqlGeneration { /// /// A class that keeps track of slot information in a . /// internal sealed class SlotInfo : InternalBase { #region Constructor /// /// Creates a for a X with information about whether this slot is needed by X's parent /// (), whether X projects it () along with the slot value () and /// the output member path ( (for regular/non-boolean slots) for the slot. /// internal SlotInfo(bool isRequiredByParent, bool isProjected, ProjectedSlot slotValue, MemberPath outputMember) : this(isRequiredByParent, isProjected, slotValue, outputMember, false /* enforceNotNull */) { } /// /// Creates a for a X with information about whether this slot is needed by X's parent /// (), whether X projects it () along with the slot value () and /// the output member path ( (for regular/non-boolean slots) for the slot. /// /// We need to ensure that _from variables are never null since view generation uses 2-valued boolean logic. /// If =true, the generated Cql adds a condition (AND NOT NULL). /// This flag is used only for boolean slots. internal SlotInfo(bool isRequiredByParent, bool isProjected, ProjectedSlot slotValue, MemberPath outputMember, bool enforceNotNull) { m_isRequiredByParent = isRequiredByParent; m_isProjected = isProjected; m_slotValue = slotValue; m_outputMember = outputMember; m_enforceNotNull = enforceNotNull; Debug.Assert(false == m_isRequiredByParent || m_slotValue != null, "Required slots cannot be null"); Debug.Assert(m_slotValue is QualifiedSlot || (m_slotValue == null && m_outputMember == null) || // unused boolean slot (m_slotValue is BooleanProjectedSlot) == (m_outputMember == null), "If slot is boolean slot, there is no member path for it and vice-versa"); } #endregion #region Fields /// /// If slot is required by the parent. Can be reset to false in method. /// private bool m_isRequiredByParent; /// /// If the node is capable of projecting this slot. /// private readonly bool m_isProjected; /// /// The slot represented by this . /// private readonly ProjectedSlot m_slotValue; /// /// The output member path of this slot. /// private readonly MemberPath m_outputMember; /// /// Whether to add AND NOT NULL to Cql. /// private readonly bool m_enforceNotNull; #endregion #region Properties /// /// Returns true iff this slot is required by the 's parent. /// Can be reset to false by calling method. /// internal bool IsRequiredByParent { get { return m_isRequiredByParent; } } /// /// Returns true iff this slot is projected by this . /// internal bool IsProjected { get { return m_isProjected; } } /// /// Returns the output memberpath of this slot /// internal MemberPath OutputMember { get { return m_outputMember; } } /// /// Returns the slot value corresponfing to this object. /// internal ProjectedSlot SlotValue { get { return m_slotValue; } } /// /// Returns the Cql alias for this slot, e.g., "CPerson1_Pid", "_from0", etc /// internal string CqlFieldAlias { get { return m_slotValue != null ? m_slotValue.GetCqlFieldAlias(m_outputMember) : null; } } /// /// Returns true if Cql generated for the slot needs to have an extra AND IS NOT NULL condition. /// internal bool IsEnforcedNotNull { get { return m_enforceNotNull; } } #endregion #region Methods /// /// Sets the to false. /// Note we don't have a setter because we don't want people to set this field to true after the object has been created. /// internal void ResetIsRequiredByParent() { m_isRequiredByParent = false; } /// /// Generates eSQL representation of the slot. For different slots, the result is different, e.g., "_from0", "CPerson1.pid", "TREAT(....)". /// internal StringBuilder AsEsql(StringBuilder builder, string blockAlias, int indentLevel) { if (m_enforceNotNull) { builder.Append('('); m_slotValue.AsEsql(builder, m_outputMember, blockAlias, indentLevel); builder.Append(" AND "); m_slotValue.AsEsql(builder, m_outputMember, blockAlias, indentLevel); builder.Append(" IS NOT NULL)"); } else { m_slotValue.AsEsql(builder, m_outputMember, blockAlias, indentLevel); } return builder; } /// /// Generates CQT representation of the slot. /// internal DbExpression AsCqt(DbExpression row) { DbExpression cqt = m_slotValue.AsCqt(row, m_outputMember); if (m_enforceNotNull) { cqt = cqt.And(cqt.IsNull().Not()); } return cqt; } internal override void ToCompactString(StringBuilder builder) { if (m_slotValue != null) { builder.Append(CqlFieldAlias); } } #endregion } }