|
//---------------------------------------------------------------------
// <copyright file="CaseCqlBlock.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
// @owner Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
using System.Data.Mapping.ViewGeneration.Structures;
using System.Text;
using System.Collections.Generic;
using System.Data.Common.CommandTrees;
using System.Data.Common.CommandTrees.ExpressionBuilder;
using System.Data.Common.Utils;
using System.Diagnostics;
namespace System.Data.Mapping.ViewGeneration.CqlGeneration
{
/// <summary>
/// A class to capture cql blocks responsible for case statements generating multiconstants, i.e., complex types, entities, discriminators, etc.
/// </summary>
internal sealed class CaseCqlBlock : CqlBlock
{
#region Constructors
/// <summary>
/// Creates a <see cref="CqlBlock"/> containing the case statememt for the <paramref name="caseSlot"/> and projecting other slots as is from its child (input). CqlBlock with SELECT (slots),
/// </summary>
/// <param name="caseSlot">indicates which slot in <paramref name="slots"/> corresponds to the case statement being generated by this block</param>
internal CaseCqlBlock(SlotInfo[] slots, int caseSlot, CqlBlock child, BoolExpression whereClause, CqlIdentifiers identifiers, int blockAliasNum)
: base(slots, new List<CqlBlock>(new CqlBlock[] { child }), whereClause, identifiers, blockAliasNum)
{
m_caseSlotInfo = slots[caseSlot];
}
#endregion
#region Fields
private readonly SlotInfo m_caseSlotInfo;
#endregion
#region Methods
internal override StringBuilder AsEsql(StringBuilder builder, bool isTopLevel, int indentLevel)
{
// The SELECT part
StringUtil.IndentNewLine(builder, indentLevel);
builder.Append("SELECT ");
if (isTopLevel)
{
builder.Append("VALUE ");
}
Debug.Assert(m_caseSlotInfo.OutputMember != null, "We only construct member slots, not boolean slots.");
builder.Append("-- Constructing ").Append(m_caseSlotInfo.OutputMember.LeafName);
Debug.Assert(Children.Count == 1, "CaseCqlBlock can have exactly one child.");
CqlBlock childBlock = Children[0];
base.GenerateProjectionEsql(builder, childBlock.CqlAlias, true, indentLevel, isTopLevel);
// The FROM part: FROM (ChildView) AS AliasName
builder.Append("FROM (");
childBlock.AsEsql(builder, false, indentLevel + 1);
StringUtil.IndentNewLine(builder, indentLevel);
builder.Append(") AS ").Append(childBlock.CqlAlias);
// Get the WHERE part only when the expression is not simply TRUE.
if (false == BoolExpression.EqualityComparer.Equals(this.WhereClause, BoolExpression.True))
{
StringUtil.IndentNewLine(builder, indentLevel);
builder.Append("WHERE ");
this.WhereClause.AsEsql(builder, childBlock.CqlAlias);
}
return builder;
}
internal override DbExpression AsCqt(bool isTopLevel)
{
Debug.Assert(m_caseSlotInfo.OutputMember != null, "We only construct real slots not boolean slots");
// The FROM part: FROM (childBlock)
Debug.Assert(Children.Count == 1, "CaseCqlBlock can have exactly one child.");
CqlBlock childBlock = this.Children[0];
DbExpression cqt = childBlock.AsCqt(false);
// Get the WHERE part only when the expression is not simply TRUE.
if (!BoolExpression.EqualityComparer.Equals(this.WhereClause, BoolExpression.True))
{
cqt = cqt.Where(row => this.WhereClause.AsCqt(row));
}
// The SELECT part.
return cqt.Select(row => GenerateProjectionCqt(row, isTopLevel));
}
#endregion
}
}
|