//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Text; using System.Diagnostics; using System.Data.Common; using System.Data.Common.CommandTrees; using System.Data.Common.CommandTrees.ExpressionBuilder; using System.Data.Common.Utils; using System.Data.Mapping.ViewGeneration.CqlGeneration; using System.Data.Mapping.ViewGeneration.Utils; using System.Data.Metadata.Edm; namespace System.Data.Mapping.ViewGeneration.Structures { /// /// A class that denotes a constant value that can be stored in a multiconstant or in a projected slot of a . /// internal sealed class ScalarConstant : Constant { #region Constructor /// /// Creates a scalar constant corresponding to the . /// internal ScalarConstant(object value) { Debug.Assert(value != null, "Scalar const value must not be null."); m_scalar = value; } #endregion #region Fields /// /// The actual value of the scalar. /// private readonly object m_scalar; #endregion #region Properties internal object Value { get { return m_scalar; } } #endregion #region Methods internal override bool IsNull() { return false; } internal override bool IsNotNull() { return false; } internal override bool IsUndefined() { return false; } internal override bool HasNotNull() { return false; } internal override StringBuilder AsEsql(StringBuilder builder, MemberPath outputMember, string blockAlias) { Debug.Assert(outputMember.LeafEdmMember != null, "Constant can't correspond to an empty member path."); TypeUsage modelTypeUsage = Helper.GetModelTypeUsage(outputMember.LeafEdmMember); EdmType modelType = modelTypeUsage.EdmType; // Some built-in constants if (BuiltInTypeKind.PrimitiveType == modelType.BuiltInTypeKind) { PrimitiveTypeKind primitiveTypeKind = ((PrimitiveType)modelType).PrimitiveTypeKind; if (primitiveTypeKind == PrimitiveTypeKind.Boolean) { // This better be a boolean. Else we crash! bool val = (bool)m_scalar; string value = StringUtil.FormatInvariant("{0}", val); builder.Append(value); return builder; } else if (primitiveTypeKind == PrimitiveTypeKind.String) { bool isUnicode; if (!TypeHelpers.TryGetIsUnicode(modelTypeUsage, out isUnicode)) { // If can't determine - use the safest option, assume unicode. isUnicode = true; } if (isUnicode) { builder.Append('N'); } AppendEscapedScalar(builder); return builder; } } else if (BuiltInTypeKind.EnumType == modelType.BuiltInTypeKind) { // Enumerated type - we should be able to cast it EnumMember enumMember = (EnumMember)m_scalar; builder.Append(enumMember.Name); return builder; } // Need to cast builder.Append("CAST("); AppendEscapedScalar(builder); builder.Append(" AS "); CqlWriter.AppendEscapedTypeName(builder, modelType); builder.Append(')'); return builder; } private StringBuilder AppendEscapedScalar(StringBuilder builder) { string value = StringUtil.FormatInvariant("{0}", m_scalar); if (value.Contains("'")) { // Deal with strings with ' by doubling it value = value.Replace("'", "''"); } StringUtil.FormatStringBuilder(builder, "'{0}'", value); return builder; } internal override DbExpression AsCqt(DbExpression row, MemberPath outputMember) { Debug.Assert(outputMember.LeafEdmMember != null, "Constant can't correspond to an empty member path."); TypeUsage modelTypeUsage = Helper.GetModelTypeUsage(outputMember.LeafEdmMember); return modelTypeUsage.Constant(m_scalar); } protected override bool IsEqualTo(Constant right) { ScalarConstant rightScalarConstant = right as ScalarConstant; if (rightScalarConstant == null) { return false; } return ByValueEqualityComparer.Default.Equals(m_scalar, rightScalarConstant.m_scalar); } public override int GetHashCode() { return m_scalar.GetHashCode(); } internal override string ToUserString() { StringBuilder builder = new StringBuilder(); ToCompactString(builder); return builder.ToString(); } internal override void ToCompactString(StringBuilder builder) { EnumMember enumMember = m_scalar as EnumMember; if (enumMember != null) { builder.Append(enumMember.Name); } else { builder.Append(StringUtil.FormatInvariant("'{0}'", m_scalar)); } } #endregion } }