587 lines
16 KiB
C#
587 lines
16 KiB
C#
|
//---------------------------------------------------------------------
|
||
|
// <copyright file="QueryExpr.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
//
|
||
|
// @owner [....]
|
||
|
// @backupOwner [....]
|
||
|
//---------------------------------------------------------------------
|
||
|
|
||
|
namespace System.Data.Common.EntitySql.AST
|
||
|
{
|
||
|
using System;
|
||
|
using System.Globalization;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents select kind (value,row).
|
||
|
/// </summary>
|
||
|
internal enum SelectKind
|
||
|
{
|
||
|
Value,
|
||
|
Row
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents join kind (cross,inner,leftouter,rightouter).
|
||
|
/// </summary>
|
||
|
internal enum JoinKind
|
||
|
{
|
||
|
Cross,
|
||
|
Inner,
|
||
|
LeftOuter,
|
||
|
FullOuter,
|
||
|
RightOuter
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents order kind (none=asc,asc,desc).
|
||
|
/// </summary>
|
||
|
internal enum OrderKind
|
||
|
{
|
||
|
None,
|
||
|
Asc,
|
||
|
Desc
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents distinct kind (none=all,all,distinct).
|
||
|
/// </summary>
|
||
|
internal enum DistinctKind
|
||
|
{
|
||
|
None,
|
||
|
All,
|
||
|
Distinct
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents apply kind (cross,outer).
|
||
|
/// </summary>
|
||
|
internal enum ApplyKind
|
||
|
{
|
||
|
Cross,
|
||
|
Outer
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents a query expression ast node.
|
||
|
/// </summary>
|
||
|
internal sealed class QueryExpr : Node
|
||
|
{
|
||
|
private readonly SelectClause _selectClause;
|
||
|
private readonly FromClause _fromClause;
|
||
|
private readonly Node _whereClause;
|
||
|
private readonly GroupByClause _groupByClause;
|
||
|
private readonly HavingClause _havingClause;
|
||
|
private readonly OrderByClause _orderByClause;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes a query expression ast node.
|
||
|
/// </summary>
|
||
|
/// <param name="selectClause">select clause</param>
|
||
|
/// <param name="fromClause">from clasuse</param>
|
||
|
/// <param name="whereClause">optional where clause</param>
|
||
|
/// <param name="groupByClause">optional group by clause</param>
|
||
|
/// <param name="havingClause">optional having clause</param>
|
||
|
/// <param name="orderByClause">optional order by clause</param>
|
||
|
internal QueryExpr(SelectClause selectClause,
|
||
|
FromClause fromClause,
|
||
|
Node whereClause,
|
||
|
GroupByClause groupByClause,
|
||
|
HavingClause havingClause,
|
||
|
OrderByClause orderByClause)
|
||
|
{
|
||
|
_selectClause = selectClause;
|
||
|
_fromClause = fromClause;
|
||
|
_whereClause = whereClause;
|
||
|
_groupByClause = groupByClause;
|
||
|
_havingClause = havingClause;
|
||
|
_orderByClause = orderByClause;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns select clause.
|
||
|
/// </summary>
|
||
|
internal SelectClause SelectClause
|
||
|
{
|
||
|
get { return _selectClause; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns from clause.
|
||
|
/// </summary>
|
||
|
internal FromClause FromClause
|
||
|
{
|
||
|
get { return _fromClause; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns optional where clause (expr).
|
||
|
/// </summary>
|
||
|
internal Node WhereClause
|
||
|
{
|
||
|
get { return _whereClause; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns optional group by clause.
|
||
|
/// </summary>
|
||
|
internal GroupByClause GroupByClause
|
||
|
{
|
||
|
get { return _groupByClause; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns optional having clause (expr).
|
||
|
/// </summary>
|
||
|
internal HavingClause HavingClause
|
||
|
{
|
||
|
get { return _havingClause; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns optional order by clause.
|
||
|
/// </summary>
|
||
|
internal OrderByClause OrderByClause
|
||
|
{
|
||
|
get { return _orderByClause; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns true if method calls are present.
|
||
|
/// </summary>
|
||
|
internal bool HasMethodCall
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return _selectClause.HasMethodCall ||
|
||
|
(null != _havingClause && _havingClause.HasMethodCall) ||
|
||
|
(null != _orderByClause && _orderByClause.HasMethodCall);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents select clause.
|
||
|
/// </summary>
|
||
|
internal sealed class SelectClause : Node
|
||
|
{
|
||
|
private readonly NodeList<AliasedExpr> _selectClauseItems;
|
||
|
private readonly SelectKind _selectKind;
|
||
|
private readonly DistinctKind _distinctKind;
|
||
|
private readonly Node _topExpr;
|
||
|
private readonly uint _methodCallCount;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initialize SelectKind.SelectRow clause.
|
||
|
/// </summary>
|
||
|
internal SelectClause(NodeList<AliasedExpr> items, SelectKind selectKind, DistinctKind distinctKind, Node topExpr, uint methodCallCount)
|
||
|
{
|
||
|
_selectKind = selectKind;
|
||
|
_selectClauseItems = items;
|
||
|
_distinctKind = distinctKind;
|
||
|
_topExpr = topExpr;
|
||
|
_methodCallCount = methodCallCount;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Projection list.
|
||
|
/// </summary>
|
||
|
internal NodeList<AliasedExpr> Items
|
||
|
{
|
||
|
get { return _selectClauseItems; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Select kind (row or value).
|
||
|
/// </summary>
|
||
|
internal SelectKind SelectKind
|
||
|
{
|
||
|
get { return _selectKind; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Distinct kind (none,all,distinct).
|
||
|
/// </summary>
|
||
|
internal DistinctKind DistinctKind
|
||
|
{
|
||
|
get { return _distinctKind; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Optional top expression.
|
||
|
/// </summary>
|
||
|
internal Node TopExpr
|
||
|
{
|
||
|
get { return _topExpr; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// True if select list has method calls.
|
||
|
/// </summary>
|
||
|
internal bool HasMethodCall
|
||
|
{
|
||
|
get { return (_methodCallCount > 0); }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents from clause.
|
||
|
/// </summary>
|
||
|
internal sealed class FromClause : Node
|
||
|
{
|
||
|
private readonly NodeList<FromClauseItem> _fromClauseItems;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes from clause.
|
||
|
/// </summary>
|
||
|
internal FromClause(NodeList<FromClauseItem> fromClauseItems)
|
||
|
{
|
||
|
_fromClauseItems = fromClauseItems;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// List of from clause items.
|
||
|
/// </summary>
|
||
|
internal NodeList<FromClauseItem> FromClauseItems
|
||
|
{
|
||
|
get { return _fromClauseItems; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// From clause item kind.
|
||
|
/// </summary>
|
||
|
internal enum FromClauseItemKind
|
||
|
{
|
||
|
AliasedFromClause,
|
||
|
JoinFromClause,
|
||
|
ApplyFromClause
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents single from clause item.
|
||
|
/// </summary>
|
||
|
internal sealed class FromClauseItem : Node
|
||
|
{
|
||
|
private readonly Node _fromClauseItemExpr;
|
||
|
private readonly FromClauseItemKind _fromClauseItemKind;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes as 'simple' aliased expression.
|
||
|
/// </summary>
|
||
|
internal FromClauseItem(AliasedExpr aliasExpr)
|
||
|
{
|
||
|
_fromClauseItemExpr = aliasExpr;
|
||
|
_fromClauseItemKind = FromClauseItemKind.AliasedFromClause;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes as join clause item.
|
||
|
/// </summary>
|
||
|
internal FromClauseItem(JoinClauseItem joinClauseItem)
|
||
|
{
|
||
|
_fromClauseItemExpr = joinClauseItem;
|
||
|
_fromClauseItemKind = FromClauseItemKind.JoinFromClause;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes as apply clause item.
|
||
|
/// </summary>
|
||
|
internal FromClauseItem(ApplyClauseItem applyClauseItem)
|
||
|
{
|
||
|
_fromClauseItemExpr = applyClauseItem;
|
||
|
_fromClauseItemKind = FromClauseItemKind.ApplyFromClause;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// From clause item expression.
|
||
|
/// </summary>
|
||
|
internal Node FromExpr
|
||
|
{
|
||
|
get { return _fromClauseItemExpr; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// From clause item kind (alias,join,apply).
|
||
|
/// </summary>
|
||
|
internal FromClauseItemKind FromClauseItemKind
|
||
|
{
|
||
|
get { return _fromClauseItemKind; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents group by clause.
|
||
|
/// </summary>
|
||
|
internal sealed class GroupByClause : Node
|
||
|
{
|
||
|
private readonly NodeList<AliasedExpr> _groupItems;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes GROUP BY clause
|
||
|
/// </summary>
|
||
|
internal GroupByClause(NodeList<AliasedExpr> groupItems)
|
||
|
{
|
||
|
_groupItems = groupItems;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Group items.
|
||
|
/// </summary>
|
||
|
internal NodeList<AliasedExpr> GroupItems
|
||
|
{
|
||
|
get { return _groupItems; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents having clause.
|
||
|
/// </summary>
|
||
|
internal sealed class HavingClause : Node
|
||
|
{
|
||
|
private readonly Node _havingExpr;
|
||
|
private readonly uint _methodCallCount;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes having clause.
|
||
|
/// </summary>
|
||
|
internal HavingClause(Node havingExpr, uint methodCallCounter)
|
||
|
{
|
||
|
_havingExpr = havingExpr;
|
||
|
_methodCallCount = methodCallCounter;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns having inner expression.
|
||
|
/// </summary>
|
||
|
internal Node HavingPredicate
|
||
|
{
|
||
|
get { return _havingExpr; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// True if predicate has method calls.
|
||
|
/// </summary>
|
||
|
internal bool HasMethodCall
|
||
|
{
|
||
|
get { return (_methodCallCount > 0); }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents order by clause.
|
||
|
/// </summary>
|
||
|
internal sealed class OrderByClause : Node
|
||
|
{
|
||
|
private readonly NodeList<OrderByClauseItem> _orderByClauseItem;
|
||
|
private readonly Node _skipExpr;
|
||
|
private readonly Node _limitExpr;
|
||
|
private readonly uint _methodCallCount;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes order by clause.
|
||
|
/// </summary>
|
||
|
internal OrderByClause(NodeList<OrderByClauseItem> orderByClauseItem, Node skipExpr, Node limitExpr, uint methodCallCount)
|
||
|
{
|
||
|
_orderByClauseItem = orderByClauseItem;
|
||
|
_skipExpr = skipExpr;
|
||
|
_limitExpr = limitExpr;
|
||
|
_methodCallCount = methodCallCount;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns order by clause items.
|
||
|
/// </summary>
|
||
|
internal NodeList<OrderByClauseItem> OrderByClauseItem
|
||
|
{
|
||
|
get { return _orderByClauseItem; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns skip sub clause ast node.
|
||
|
/// </summary>
|
||
|
internal Node SkipSubClause
|
||
|
{
|
||
|
get { return _skipExpr; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns limit sub-clause ast node.
|
||
|
/// </summary>
|
||
|
internal Node LimitSubClause
|
||
|
{
|
||
|
get { return _limitExpr; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// True if order by has method calls.
|
||
|
/// </summary>
|
||
|
internal bool HasMethodCall
|
||
|
{
|
||
|
get { return (_methodCallCount > 0); }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents a order by clause item.
|
||
|
/// </summary>
|
||
|
internal sealed class OrderByClauseItem : Node
|
||
|
{
|
||
|
private readonly Node _orderExpr;
|
||
|
private readonly OrderKind _orderKind;
|
||
|
private readonly Identifier _optCollationIdentifier;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes non-collated order by clause item.
|
||
|
/// </summary>
|
||
|
internal OrderByClauseItem(Node orderExpr, OrderKind orderKind)
|
||
|
: this(orderExpr, orderKind, null)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes collated order by clause item.
|
||
|
/// </summary>
|
||
|
/// <param name="optCollationIdentifier">optional Collation identifier</param>
|
||
|
internal OrderByClauseItem(Node orderExpr, OrderKind orderKind, Identifier optCollationIdentifier)
|
||
|
{
|
||
|
_orderExpr = orderExpr;
|
||
|
_orderKind = orderKind;
|
||
|
_optCollationIdentifier = optCollationIdentifier;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Oeturns order expression.
|
||
|
/// </summary>
|
||
|
internal Node OrderExpr
|
||
|
{
|
||
|
get { return _orderExpr; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns order kind (none,asc,desc).
|
||
|
/// </summary>
|
||
|
internal OrderKind OrderKind
|
||
|
{
|
||
|
get { return _orderKind; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns collattion identifier if one exists.
|
||
|
/// </summary>
|
||
|
internal Identifier Collation
|
||
|
{
|
||
|
get { return _optCollationIdentifier; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents join clause item.
|
||
|
/// </summary>
|
||
|
internal sealed class JoinClauseItem : Node
|
||
|
{
|
||
|
private readonly FromClauseItem _joinLeft;
|
||
|
private readonly FromClauseItem _joinRight;
|
||
|
private JoinKind _joinKind;
|
||
|
private readonly Node _onExpr;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes join clause item without ON expression.
|
||
|
/// </summary>
|
||
|
internal JoinClauseItem(FromClauseItem joinLeft, FromClauseItem joinRight, JoinKind joinKind)
|
||
|
: this(joinLeft, joinRight, joinKind, null)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes join clause item with ON expression.
|
||
|
/// </summary>
|
||
|
internal JoinClauseItem(FromClauseItem joinLeft, FromClauseItem joinRight, JoinKind joinKind, Node onExpr)
|
||
|
{
|
||
|
_joinLeft = joinLeft;
|
||
|
_joinRight = joinRight;
|
||
|
_joinKind = joinKind;
|
||
|
_onExpr = onExpr;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns join left expression.
|
||
|
/// </summary>
|
||
|
internal FromClauseItem LeftExpr
|
||
|
{
|
||
|
get { return _joinLeft; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns join right expression.
|
||
|
/// </summary>
|
||
|
internal FromClauseItem RightExpr
|
||
|
{
|
||
|
get { return _joinRight; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Join kind (cross, inner, full, left outer,right outer).
|
||
|
/// </summary>
|
||
|
internal JoinKind JoinKind
|
||
|
{
|
||
|
get { return _joinKind; }
|
||
|
set { _joinKind = value; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns join on expression.
|
||
|
/// </summary>
|
||
|
internal Node OnExpr
|
||
|
{
|
||
|
get { return _onExpr; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Represents apply expression.
|
||
|
/// </summary>
|
||
|
internal sealed class ApplyClauseItem : Node
|
||
|
{
|
||
|
private readonly FromClauseItem _applyLeft;
|
||
|
private readonly FromClauseItem _applyRight;
|
||
|
private readonly ApplyKind _applyKind;
|
||
|
|
||
|
/// <summary>
|
||
|
/// Initializes apply clause item.
|
||
|
/// </summary>
|
||
|
internal ApplyClauseItem(FromClauseItem applyLeft, FromClauseItem applyRight, ApplyKind applyKind)
|
||
|
{
|
||
|
_applyLeft = applyLeft;
|
||
|
_applyRight = applyRight;
|
||
|
_applyKind = applyKind;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns apply left expression.
|
||
|
/// </summary>
|
||
|
internal FromClauseItem LeftExpr
|
||
|
{
|
||
|
get { return _applyLeft; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns apply right expression.
|
||
|
/// </summary>
|
||
|
internal FromClauseItem RightExpr
|
||
|
{
|
||
|
get { return _applyRight; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns apply kind (cross,outer).
|
||
|
/// </summary>
|
||
|
internal ApplyKind ApplyKind
|
||
|
{
|
||
|
get { return _applyKind; }
|
||
|
}
|
||
|
}
|
||
|
}
|