|
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq.Expressions;
using System.Diagnostics;
using System.Data;
namespace System.Data.Linq.SqlClient {
using System.Data.Linq.Mapping;
using System.Data.Linq.Provider;
using System.Diagnostics.CodeAnalysis;
internal enum SqlNodeType {
Add,
Alias,
AliasRef,
And,
Assign,
Avg,
Between,
BitAnd,
BitNot,
BitOr,
BitXor,
Block,
ClientArray,
ClientCase,
ClientParameter,
ClientQuery,
ClrLength,
Coalesce,
Column,
ColumnRef,
Concat,
Convert,
Count,
Delete,
DiscriminatedType,
DiscriminatorOf,
Div,
DoNotVisit,
Element,
ExprSet,
EQ,
EQ2V,
Exists,
FunctionCall,
In,
IncludeScope,
IsNotNull,
IsNull,
LE,
Lift,
Link,
Like,
LongCount,
LT,
GE,
Grouping,
GT,
Insert,
Join,
JoinedCollection,
Max,
MethodCall,
Member,
MemberAssign,
Min,
Mod,
Mul,
Multiset,
NE,
NE2V,
Negate,
New,
Not,
Not2V,
Nop,
Or,
OptionalValue,
OuterJoinedValue,
Parameter,
Property,
Row,
RowNumber,
ScalarSubSelect,
SearchedCase,
Select,
SharedExpression,
SharedExpressionRef,
SimpleCase,
SimpleExpression,
Stddev,
StoredProcedureCall,
Sub,
Sum,
Table,
TableValuedFunctionCall,
Treat,
TypeCase,
Union,
Update,
UserColumn,
UserQuery,
UserRow,
Variable,
Value,
ValueOf
}
[System.Diagnostics.DebuggerDisplay("text = {Text}, \r\nsource = {SourceExpression}")]
internal abstract class SqlNode {
private SqlNodeType nodeType;
private Expression sourceExpression;
internal SqlNode(SqlNodeType nodeType, Expression sourceExpression) {
this.nodeType = nodeType;
this.sourceExpression = sourceExpression;
}
internal Expression SourceExpression {
get { return this.sourceExpression; }
}
internal void ClearSourceExpression() {
this.sourceExpression = null;
}
internal SqlNodeType NodeType {
get { return this.nodeType; }
}
#if DEBUG
private static DbFormatter formatter;
internal static DbFormatter Formatter {
get { return formatter; }
set { formatter = value; }
}
internal string Text {
get {
if (Formatter == null)
return "SqlNode.Formatter is not assigned";
return SqlNode.Formatter.Format(this, true);
}
}
#endif
}
internal abstract class SqlExpression : SqlNode {
private Type clrType;
internal SqlExpression(SqlNodeType nodeType, Type clrType, Expression sourceExpression)
: base(nodeType, sourceExpression) {
this.clrType = clrType;
}
internal Type ClrType {
get { return this.clrType; }
}
// note: changing the CLR type of a node is potentially dangerous
internal void SetClrType(Type type) {
this.clrType = type;
}
internal abstract ProviderType SqlType { get; }
/// <summary>
/// Drill down looking for a constant root expression, returning true if found.
/// </summary>
internal bool IsConstantColumn {
get {
if (this.NodeType == SqlNodeType.Column) {
SqlColumn col = (SqlColumn)this;
if (col.Expression != null) {
return col.Expression.IsConstantColumn;
}
}
else if (this.NodeType == SqlNodeType.ColumnRef) {
return ((SqlColumnRef)this).Column.IsConstantColumn;
}
else if (this.NodeType == SqlNodeType.OptionalValue) {
return ((SqlOptionalValue)this).Value.IsConstantColumn;
}
else if (this.NodeType == SqlNodeType.Value ||
this.NodeType == SqlNodeType.Parameter) {
return true;
}
return false;
}
}
}
/// <summary>
/// A SqlExpression with a simple implementation of ClrType and SqlType.
/// </summary>
internal abstract class SqlSimpleTypeExpression : SqlExpression {
private ProviderType sqlType;
internal SqlSimpleTypeExpression(SqlNodeType nodeType, Type clrType, ProviderType sqlType, Expression sourceExpression)
: base(nodeType, clrType, sourceExpression) {
this.sqlType = sqlType;
}
internal override ProviderType SqlType {
get { return this.sqlType; }
}
internal void SetSqlType(ProviderType type) {
this.sqlType = type;
}
}
internal class SqlDiscriminatorOf : SqlSimpleTypeExpression {
SqlExpression obj;
internal SqlDiscriminatorOf(SqlExpression obj, Type clrType, ProviderType sqlType, Expression sourceExpression)
: base(SqlNodeType.DiscriminatorOf, clrType, sqlType, sourceExpression) {
this.obj = obj;
}
internal SqlExpression Object {
get { return this.obj; }
set { this.obj = value; }
}
}
/// <summary>
/// Represents a dynamic CLR type that is chosen based on a discriminator expression.
/// </summary>
internal class SqlDiscriminatedType : SqlExpression {
private ProviderType sqlType;
private SqlExpression discriminator;
private MetaType targetType;
internal SqlDiscriminatedType(ProviderType sqlType, SqlExpression discriminator, MetaType targetType, Expression sourceExpression)
: base(SqlNodeType.DiscriminatedType,
typeof(Type),
sourceExpression) {
if (discriminator == null)
throw Error.ArgumentNull("discriminator");
this.discriminator = discriminator;
this.targetType = targetType;
this.sqlType = sqlType;
}
internal override ProviderType SqlType {
get { return this.sqlType; }
}
internal SqlExpression Discriminator {
get { return this.discriminator; }
set { this.discriminator = value; }
}
internal MetaType TargetType {
get { return this.targetType; }
}
}
internal abstract class SqlStatement : SqlNode {
internal SqlStatement(SqlNodeType nodeType, Expression sourceExpression)
: base(nodeType, sourceExpression) {
}
}
internal abstract class SqlSource : SqlNode {
internal SqlSource(SqlNodeType nt, Expression sourceExpression)
: base(nt, sourceExpression) {
}
}
internal class SqlSelect : SqlStatement {
private SqlExpression top;
private bool isPercent;
private bool isDistinct;
private SqlExpression selection;
private SqlRow row;
private SqlSource from;
private SqlExpression where;
private List<SqlExpression> groupBy;
private SqlExpression having;
private List<SqlOrderExpression> orderBy;
private SqlOrderingType orderingType;
private bool squelch;
internal SqlSelect(SqlExpression selection, SqlSource from, Expression sourceExpression)
: base(SqlNodeType.Select, sourceExpression) {
this.Row = new SqlRow(sourceExpression);
this.Selection = selection;
this.From = from;
this.groupBy = new List<SqlExpression>();
this.orderBy = new List<SqlOrderExpression>();
this.orderingType = SqlOrderingType.Default;
}
internal SqlExpression Top {
get { return this.top; }
set { this.top = value; }
}
internal bool IsPercent {
get { return this.isPercent; }
set { this.isPercent = value; }
}
internal bool IsDistinct {
get { return this.isDistinct; }
set { this.isDistinct = value; }
}
internal SqlExpression Selection {
get { return this.selection; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.selection = value;
}
}
internal SqlRow Row {
get { return this.row; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.row = value;
}
}
internal SqlSource From {
get { return this.from; }
set { this.from = value; }
}
internal SqlExpression Where {
get { return this.where; }
set {
if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) {
throw Error.ArgumentWrongType("value", "bool", value.ClrType);
}
this.where = value;
}
}
internal List<SqlExpression> GroupBy {
get { return this.groupBy; }
}
internal SqlExpression Having {
get { return this.having; }
set {
if (value != null && TypeSystem.GetNonNullableType(value.ClrType) != typeof(bool)) {
throw Error.ArgumentWrongType("value", "bool", value.ClrType);
}
this.having = value;
}
}
internal List<SqlOrderExpression> OrderBy {
get { return this.orderBy; }
}
internal SqlOrderingType OrderingType {
get { return this.orderingType; }
set { this.orderingType = value; }
}
internal bool DoNotOutput {
get { return this.squelch; }
set { this.squelch = value; }
}
}
internal enum SqlOrderingType {
Default,
Never,
Blocked,
Always
}
internal class SqlTable : SqlNode {
private MetaTable table;
private MetaType rowType;
private ProviderType sqlRowType;
private List<SqlColumn> columns;
internal SqlTable(MetaTable table, MetaType rowType, ProviderType sqlRowType, Expression sourceExpression)
: base(SqlNodeType.Table, sourceExpression) {
this.table = table;
this.rowType = rowType;
this.sqlRowType = sqlRowType;
this.columns = new List<SqlColumn>();
}
internal MetaTable MetaTable {
get { return this.table; }
}
internal string Name {
get { return this.table.TableName; }
}
internal List<SqlColumn> Columns {
get { return this.columns; }
}
internal MetaType RowType {
get { return this.rowType; }
}
internal ProviderType SqlRowType {
get { return this.sqlRowType; }
}
internal SqlColumn Find(string columnName) {
foreach (SqlColumn c in this.Columns) {
if (c.Name == columnName)
return c;
}
return null;
}
}
internal class SqlUserQuery : SqlNode {
private string queryText;
private SqlExpression projection;
private List<SqlExpression> args;
private List<SqlUserColumn> columns;
internal SqlUserQuery(SqlNodeType nt, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)
: base(nt, source) {
this.Projection = projection;
this.args = (args != null) ? new List<SqlExpression>(args) : new List<SqlExpression>();
this.columns = new List<SqlUserColumn>();
}
internal SqlUserQuery(string queryText, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)
: base(SqlNodeType.UserQuery, source) {
this.queryText = queryText;
this.Projection = projection;
this.args = (args != null) ? new List<SqlExpression>(args) : new List<SqlExpression>();
this.columns = new List<SqlUserColumn>();
}
internal string QueryText {
get { return this.queryText; }
}
internal SqlExpression Projection {
get { return this.projection; }
set {
if (this.projection != null && this.projection.ClrType != value.ClrType)
throw Error.ArgumentWrongType("value", this.projection.ClrType, value.ClrType);
this.projection = value;
}
}
internal List<SqlExpression> Arguments {
get { return this.args; }
}
internal List<SqlUserColumn> Columns {
get { return this.columns; }
}
internal SqlUserColumn Find(string name) {
foreach (SqlUserColumn c in this.Columns) {
if (c.Name == name)
return c;
}
return null;
}
}
internal class SqlStoredProcedureCall : SqlUserQuery {
private MetaFunction function;
internal SqlStoredProcedureCall(MetaFunction function, SqlExpression projection, IEnumerable<SqlExpression> args, Expression source)
: base(SqlNodeType.StoredProcedureCall, projection, args, source) {
if (function == null)
throw Error.ArgumentNull("function");
this.function = function;
}
internal MetaFunction Function {
get { return this.function; }
}
}
internal class SqlUserRow : SqlSimpleTypeExpression {
private SqlUserQuery query;
private MetaType rowType;
internal SqlUserRow(MetaType rowType, ProviderType sqlType, SqlUserQuery query, Expression source)
: base(SqlNodeType.UserRow, rowType.Type, sqlType, source) {
this.Query = query;
this.rowType = rowType;
}
internal MetaType RowType {
get { return this.rowType; }
}
internal SqlUserQuery Query {
get { return this.query; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (value.Projection != null && value.Projection.ClrType != this.ClrType)
throw Error.ArgumentWrongType("value", this.ClrType, value.Projection.ClrType);
this.query = value;
}
}
}
internal class SqlUserColumn : SqlSimpleTypeExpression {
private SqlUserQuery query;
private string name;
private bool isRequired;
internal SqlUserColumn(Type clrType, ProviderType sqlType, SqlUserQuery query, string name, bool isRequired, Expression source)
: base(SqlNodeType.UserColumn, clrType, sqlType, source) {
this.Query = query;
this.name = name;
this.isRequired = isRequired;
}
internal SqlUserQuery Query {
get { return this.query; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.query != null && this.query != value)
throw Error.ArgumentWrongValue("value");
this.query = value;
}
}
internal string Name {
get { return this.name; }
}
internal bool IsRequired {
get { return this.isRequired; }
}
}
internal class SqlAlias : SqlSource {
private string name;
private SqlNode node;
internal SqlAlias(SqlNode node)
: base(SqlNodeType.Alias, node.SourceExpression) {
this.Node = node;
}
internal string Name {
get { return this.name; }
set { this.name = value; }
}
internal SqlNode Node {
get { return this.node; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (!(value is SqlExpression || value is SqlSelect || value is SqlTable || value is SqlUnion))
throw Error.UnexpectedNode(value.NodeType);
this.node = value;
}
}
}
internal class SqlAliasRef : SqlExpression {
private SqlAlias alias;
internal SqlAliasRef(SqlAlias alias)
: base(SqlNodeType.AliasRef, GetClrType(alias.Node), alias.SourceExpression) {
if (alias == null)
throw Error.ArgumentNull("alias");
this.alias = alias;
}
internal SqlAlias Alias {
get { return this.alias; }
}
internal override ProviderType SqlType {
get { return GetSqlType(this.alias.Node); }
}
private static Type GetClrType(SqlNode node) {
SqlTableValuedFunctionCall tvf = node as SqlTableValuedFunctionCall;
if (tvf != null)
return tvf.RowType.Type;
SqlExpression exp = node as SqlExpression;
if (exp != null) {
if (TypeSystem.IsSequenceType(exp.ClrType))
return TypeSystem.GetElementType(exp.ClrType);
return exp.ClrType;
}
SqlSelect sel = node as SqlSelect;
if (sel != null)
return sel.Selection.ClrType;
SqlTable tab = node as SqlTable;
if (tab != null)
return tab.RowType.Type;
SqlUnion su = node as SqlUnion;
if (su != null)
return su.GetClrType();
throw Error.UnexpectedNode(node.NodeType);
}
private static ProviderType GetSqlType(SqlNode node) {
SqlExpression exp = node as SqlExpression;
if (exp != null)
return exp.SqlType;
SqlSelect sel = node as SqlSelect;
if (sel != null)
return sel.Selection.SqlType;
SqlTable tab = node as SqlTable;
if (tab != null)
return tab.SqlRowType;
SqlUnion su = node as SqlUnion;
if (su != null)
return su.GetSqlType();
throw Error.UnexpectedNode(node.NodeType);
}
}
internal class SqlJoin : SqlSource {
private SqlJoinType joinType;
private SqlSource left;
private SqlSource right;
private SqlExpression condition;
internal SqlJoin(SqlJoinType type, SqlSource left, SqlSource right, SqlExpression cond, Expression sourceExpression)
: base(SqlNodeType.Join, sourceExpression) {
this.JoinType = type;
this.Left = left;
this.Right = right;
this.Condition = cond;
}
internal SqlJoinType JoinType {
get { return this.joinType; }
set { this.joinType = value; }
}
internal SqlSource Left {
get { return this.left; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.left = value;
}
}
internal SqlSource Right {
get { return this.right; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.right = value;
}
}
internal SqlExpression Condition {
get { return this.condition; }
set { this.condition = value; }
}
}
internal enum SqlJoinType {
Cross,
Inner,
LeftOuter,
CrossApply,
OuterApply
}
internal class SqlUnion : SqlNode {
private SqlNode left;
private SqlNode right;
private bool all;
internal SqlUnion(SqlNode left, SqlNode right, bool all)
: base(SqlNodeType.Union, right.SourceExpression) {
this.Left = left;
this.Right = right;
this.All = all;
}
internal SqlNode Left {
get { return this.left; }
set {
Validate(value);
this.left = value;
}
}
internal SqlNode Right {
get { return this.right; }
set {
Validate(value);
this.right = value;
}
}
internal bool All {
get { return this.all; }
set { this.all = value; }
}
[SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
private void Validate(SqlNode node) {
if (node == null)
throw Error.ArgumentNull("node");
if (!(node is SqlExpression || node is SqlSelect || node is SqlUnion))
throw Error.UnexpectedNode(node.NodeType);
}
internal Type GetClrType() {
SqlExpression exp = this.Left as SqlExpression;
if (exp != null)
return exp.ClrType;
SqlSelect sel = this.Left as SqlSelect;
if (sel != null)
return sel.Selection.ClrType;
throw Error.CouldNotGetClrType();
}
internal ProviderType GetSqlType() {
SqlExpression exp = this.Left as SqlExpression;
if (exp != null)
return exp.SqlType;
SqlSelect sel = this.Left as SqlSelect;
if (sel != null)
return sel.Selection.SqlType;
throw Error.CouldNotGetSqlType();
}
}
internal class SqlNop : SqlSimpleTypeExpression {
internal SqlNop(Type clrType, ProviderType sqlType, Expression sourceExpression)
: base(SqlNodeType.Nop, clrType, sqlType, sourceExpression) {
}
}
internal class SqlLift : SqlExpression {
internal SqlExpression liftedExpression;
internal SqlLift(Type type, SqlExpression liftedExpression, Expression sourceExpression)
: base(SqlNodeType.Lift, type, sourceExpression) {
if (liftedExpression == null)
throw Error.ArgumentNull("liftedExpression");
this.liftedExpression = liftedExpression;
}
internal SqlExpression Expression {
get { return this.liftedExpression; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.liftedExpression = value;
}
}
internal override ProviderType SqlType {
get { return this.liftedExpression.SqlType; }
}
}
internal enum SqlOrderType {
Ascending,
Descending
}
internal class SqlOrderExpression : IEquatable<SqlOrderExpression> {
private SqlOrderType orderType;
private SqlExpression expression;
internal SqlOrderExpression(SqlOrderType type, SqlExpression expr) {
this.OrderType = type;
this.Expression = expr;
}
internal SqlOrderType OrderType {
get { return this.orderType; }
set { this.orderType = value; }
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.expression != null && !this.expression.ClrType.IsAssignableFrom(value.ClrType))
throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
this.expression = value;
}
}
public override bool Equals(object obj) {
if (this.EqualsTo(obj as SqlOrderExpression))
return true;
return base.Equals(obj);
}
public bool Equals(SqlOrderExpression other) {
if (this.EqualsTo(other))
return true;
return base.Equals(other);
}
private bool EqualsTo(SqlOrderExpression other) {
if (other == null)
return false;
if (object.ReferenceEquals(this, other))
return true;
if (this.OrderType != other.OrderType)
return false;
if (!this.Expression.SqlType.Equals(other.Expression.SqlType))
return false;
SqlColumn col1 = SqlOrderExpression.UnwrapColumn(this.Expression);
SqlColumn col2 = SqlOrderExpression.UnwrapColumn(other.Expression);
if (col1 == null || col2 == null)
return false;
return col1 == col2;
}
public override int GetHashCode() {
SqlColumn col = SqlOrderExpression.UnwrapColumn(this.Expression);
if (col != null)
return col.GetHashCode();
return base.GetHashCode();
}
private static SqlColumn UnwrapColumn(SqlExpression expr) {
System.Diagnostics.Debug.Assert(expr != null);
SqlUnary exprAsUnary = expr as SqlUnary;
if (exprAsUnary != null) {
expr = exprAsUnary.Operand;
}
SqlColumn exprAsColumn = expr as SqlColumn;
if (exprAsColumn != null) {
return exprAsColumn;
}
SqlColumnRef exprAsColumnRef = expr as SqlColumnRef;
if (exprAsColumnRef != null) {
return exprAsColumnRef.GetRootColumn();
}
//
// For all other types return null to revert to default behavior for Equals()
// and GetHashCode()
//
return null;
}
}
internal class SqlRowNumber : SqlSimpleTypeExpression {
private List<SqlOrderExpression> orderBy;
internal List<SqlOrderExpression> OrderBy {
get { return orderBy; }
}
internal SqlRowNumber(Type clrType, ProviderType sqlType, List<SqlOrderExpression> orderByList, Expression sourceExpression)
: base(SqlNodeType.RowNumber, clrType, sqlType, sourceExpression) {
if (orderByList == null) {
throw Error.ArgumentNull("orderByList");
}
this.orderBy = orderByList;
}
}
internal class SqlUnary : SqlSimpleTypeExpression {
private SqlExpression operand;
private MethodInfo method;
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, Expression sourceExpression)
: this(nt, clrType, sqlType, expr, null, sourceExpression) {
}
internal SqlUnary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression expr, MethodInfo method, Expression sourceExpression)
: base(nt, clrType, sqlType, sourceExpression) {
switch (nt) {
case SqlNodeType.Not:
case SqlNodeType.Not2V:
case SqlNodeType.Negate:
case SqlNodeType.BitNot:
case SqlNodeType.IsNull:
case SqlNodeType.IsNotNull:
case SqlNodeType.Count:
case SqlNodeType.LongCount:
case SqlNodeType.Max:
case SqlNodeType.Min:
case SqlNodeType.Sum:
case SqlNodeType.Avg:
case SqlNodeType.Stddev:
case SqlNodeType.Convert:
case SqlNodeType.ValueOf:
case SqlNodeType.Treat:
case SqlNodeType.OuterJoinedValue:
case SqlNodeType.ClrLength:
break;
default:
throw Error.UnexpectedNode(nt);
}
this.Operand = expr;
this.method = method;
}
internal SqlExpression Operand {
get { return this.operand; }
set {
if (value == null && (this.NodeType != SqlNodeType.Count && this.NodeType != SqlNodeType.LongCount))
throw Error.ArgumentNull("value");
this.operand = value;
}
}
internal MethodInfo Method {
get { return this.method; }
}
}
internal class SqlBinary : SqlSimpleTypeExpression {
private SqlExpression left;
private SqlExpression right;
private MethodInfo method;
[SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right)
: this(nt, clrType, sqlType, left, right, null) {
}
internal SqlBinary(SqlNodeType nt, Type clrType, ProviderType sqlType, SqlExpression left, SqlExpression right, MethodInfo method)
: base(nt, clrType, sqlType, right.SourceExpression) {
switch (nt) {
case SqlNodeType.Add:
case SqlNodeType.Sub:
case SqlNodeType.Mul:
case SqlNodeType.Div:
case SqlNodeType.Mod:
case SqlNodeType.BitAnd:
case SqlNodeType.BitOr:
case SqlNodeType.BitXor:
case SqlNodeType.And:
case SqlNodeType.Or:
case SqlNodeType.GE:
case SqlNodeType.GT:
case SqlNodeType.LE:
case SqlNodeType.LT:
case SqlNodeType.EQ:
case SqlNodeType.NE:
case SqlNodeType.EQ2V:
case SqlNodeType.NE2V:
case SqlNodeType.Concat:
case SqlNodeType.Coalesce:
break;
default:
throw Error.UnexpectedNode(nt);
}
this.Left = left;
this.Right = right;
this.method = method;
}
internal SqlExpression Left {
get { return this.left; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.left = value;
}
}
internal SqlExpression Right {
get { return this.right; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.right = value;
}
}
internal MethodInfo Method {
get { return this.method; }
}
}
internal class SqlBetween : SqlSimpleTypeExpression {
SqlExpression expression;
SqlExpression start;
SqlExpression end;
internal SqlBetween(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression start, SqlExpression end, Expression source)
: base(SqlNodeType.Between, clrType, sqlType, source) {
this.expression = expr;
this.start = start;
this.end = end;
}
internal SqlExpression Expression {
get { return this.expression; }
set { this.expression = value; }
}
internal SqlExpression Start {
get { return this.start; }
set { this.start = value; }
}
internal SqlExpression End {
get { return this.end; }
set { this.end = value; }
}
}
internal class SqlIn : SqlSimpleTypeExpression {
private SqlExpression expression;
private List<SqlExpression> values;
internal SqlIn(Type clrType, ProviderType sqlType, SqlExpression expression, IEnumerable<SqlExpression> values, Expression sourceExpression)
:base(SqlNodeType.In, clrType, sqlType, sourceExpression) {
this.expression = expression;
this.values = values != null ? new List<SqlExpression>(values) : new List<SqlExpression>(0);
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null) {
throw Error.ArgumentNull("value");
}
this.expression = value;
}
}
internal List<SqlExpression> Values {
get { return this.values; }
}
}
internal class SqlLike : SqlSimpleTypeExpression {
private SqlExpression expression;
private SqlExpression pattern;
private SqlExpression escape;
internal SqlLike(Type clrType, ProviderType sqlType, SqlExpression expr, SqlExpression pattern, SqlExpression escape, Expression source)
: base(SqlNodeType.Like, clrType, sqlType, source) {
if (expr == null)
throw Error.ArgumentNull("expr");
if (pattern == null)
throw Error.ArgumentNull("pattern");
this.Expression = expr;
this.Pattern = pattern;
this.Escape = escape;
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (value.ClrType != typeof(string))
throw Error.ArgumentWrongType("value", "string", value.ClrType);
this.expression = value;
}
}
internal SqlExpression Pattern {
get { return this.pattern; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (value.ClrType != typeof(string))
throw Error.ArgumentWrongType("value", "string", value.ClrType);
this.pattern = value;
}
}
internal SqlExpression Escape {
get { return this.escape; }
set {
if (value != null && value.ClrType != typeof(string))
throw Error.ArgumentWrongType("value", "string", value.ClrType);
this.escape = value;
}
}
}
internal class SqlWhen {
private SqlExpression matchExpression;
private SqlExpression valueExpression;
internal SqlWhen(SqlExpression match, SqlExpression value) {
// 'match' may be null when this when represents the ELSE condition.
if (value == null)
throw Error.ArgumentNull("value");
this.Match = match;
this.Value = value;
}
internal SqlExpression Match {
get { return this.matchExpression; }
set {
if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType
// Exception: bool types, because predicates can have type bool or bool?
&& !TypeSystem.GetNonNullableType(this.matchExpression.ClrType).Equals(typeof(bool))
&& !TypeSystem.GetNonNullableType(value.ClrType).Equals(typeof(bool)))
throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
this.matchExpression = value;
}
}
internal SqlExpression Value {
get { return this.valueExpression; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.valueExpression != null && !this.valueExpression.ClrType.IsAssignableFrom(value.ClrType))
throw Error.ArgumentWrongType("value", this.valueExpression.ClrType, value.ClrType);
this.valueExpression = value;
}
}
}
/*
* Searched CASE function:
* CASE
* WHEN BooleanExpression THEN resultExpression
* [ ...n ]
* [
* ELSE elseResultExpression
* ]
* END
*/
internal class SqlSearchedCase : SqlExpression {
private List<SqlWhen> whens;
private SqlExpression @else;
internal SqlSearchedCase(Type clrType, IEnumerable<SqlWhen> whens, SqlExpression @else, Expression sourceExpression)
: base(SqlNodeType.SearchedCase, clrType, sourceExpression) {
if (whens == null)
throw Error.ArgumentNull("whens");
this.whens = new List<SqlWhen>(whens);
if (this.whens.Count == 0)
throw Error.ArgumentOutOfRange("whens");
this.Else = @else;
}
internal List<SqlWhen> Whens {
get { return this.whens; }
}
internal SqlExpression Else {
get { return this.@else; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.@else != null && !this.@else.ClrType.IsAssignableFrom(value.ClrType))
throw Error.ArgumentWrongType("value", this.@else.ClrType, value.ClrType);
this.@else = value;
}
}
internal override ProviderType SqlType {
get { return this.whens[0].Value.SqlType; }
}
}
/*
* Simple CASE function:
* CASE inputExpression
* WHEN whenExpression THEN resultExpression
* [ ...n ]
* [
* ELSE elseResultExpression
* ]
* END
*/
internal class SqlSimpleCase : SqlExpression {
private SqlExpression expression;
private List<SqlWhen> whens = new List<SqlWhen>();
internal SqlSimpleCase(Type clrType, SqlExpression expr, IEnumerable<SqlWhen> whens, Expression sourceExpression)
: base(SqlNodeType.SimpleCase, clrType, sourceExpression) {
this.Expression = expr;
if (whens == null)
throw Error.ArgumentNull("whens");
this.whens.AddRange(whens);
if (this.whens.Count == 0)
throw Error.ArgumentOutOfRange("whens");
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.expression != null && this.expression.ClrType != value.ClrType)
throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
this.expression = value;
}
}
internal List<SqlWhen> Whens {
get { return this.whens; }
}
internal override ProviderType SqlType {
get { return this.whens[0].Value.SqlType; }
}
}
/// <summary>
/// A case statement that must be evaluated on the client. For example, a case statement
/// that contains values of LINK, Element, or Multi-set are not directly handleable by
/// SQL.
///
/// CASE inputExpression
/// WHEN whenExpression THEN resultExpression
/// [ ...n ]
/// END
/// </summary>
internal class SqlClientCase : SqlExpression {
private SqlExpression expression;
private List<SqlClientWhen> whens = new List<SqlClientWhen>();
internal SqlClientCase(Type clrType, SqlExpression expr, IEnumerable<SqlClientWhen> whens, Expression sourceExpression)
: base(SqlNodeType.ClientCase, clrType, sourceExpression) {
this.Expression = expr;
if (whens == null)
throw Error.ArgumentNull("whens");
this.whens.AddRange(whens);
if (this.whens.Count == 0)
throw Error.ArgumentOutOfRange("whens");
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.expression != null && this.expression.ClrType != value.ClrType)
throw Error.ArgumentWrongType("value", this.expression.ClrType, value.ClrType);
this.expression = value;
}
}
internal List<SqlClientWhen> Whens {
get { return this.whens; }
}
internal override ProviderType SqlType {
get { return this.whens[0].Value.SqlType; }
}
}
/// <summary>
/// A single WHEN clause for ClientCase.
/// </summary>
internal class SqlClientWhen {
private SqlExpression matchExpression;
private SqlExpression matchValue;
internal SqlClientWhen(SqlExpression match, SqlExpression value) {
// 'match' may be null when this when represents the ELSE condition.
if (value == null)
throw Error.ArgumentNull("value");
this.Match = match;
this.Value = value;
}
internal SqlExpression Match {
get { return this.matchExpression; }
set {
if (this.matchExpression != null && value != null && this.matchExpression.ClrType != value.ClrType)
throw Error.ArgumentWrongType("value", this.matchExpression.ClrType, value.ClrType);
this.matchExpression = value;
}
}
internal SqlExpression Value {
get { return this.matchValue; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.matchValue != null && this.matchValue.ClrType != value.ClrType)
throw Error.ArgumentWrongType("value", this.matchValue.ClrType, value.ClrType);
this.matchValue = value;
}
}
}
/// <summary>
/// Represents the construction of an object in abstract 'super sql'.
/// The type may be polymorphic. A discriminator field is used to determine
/// which type in a hierarchy should be instantiated.
/// In the common degenerate case where the inheritance hierarchy is 1-deep
/// the discriminator will be a constant SqlValue and there will be one
/// type-case-when corresponding to that type.
/// </summary>
internal class SqlTypeCase : SqlExpression {
private MetaType rowType;
private SqlExpression discriminator;
private List<SqlTypeCaseWhen> whens = new List<SqlTypeCaseWhen>();
ProviderType sqlType;
internal SqlTypeCase(Type clrType, ProviderType sqlType, MetaType rowType, SqlExpression discriminator, IEnumerable<SqlTypeCaseWhen> whens, Expression sourceExpression)
: base(SqlNodeType.TypeCase, clrType, sourceExpression) {
this.Discriminator = discriminator;
if (whens == null)
throw Error.ArgumentNull("whens");
this.whens.AddRange(whens);
if (this.whens.Count == 0)
throw Error.ArgumentOutOfRange("whens");
this.sqlType = sqlType;
this.rowType = rowType;
}
internal SqlExpression Discriminator {
get { return this.discriminator; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.discriminator != null && this.discriminator.ClrType != value.ClrType)
throw Error.ArgumentWrongType("value", this.discriminator.ClrType, value.ClrType);
this.discriminator = value;
}
}
internal List<SqlTypeCaseWhen> Whens {
get { return this.whens; }
}
internal override ProviderType SqlType {
get { return sqlType; }
}
internal MetaType RowType {
get { return this.rowType; }
}
}
/// <summary>
/// Represents one choice of object instantiation type in a type case.
/// When 'match' is the same as type case Discriminator then the corresponding
/// type binding is the one used for instantiation.
/// </summary>
internal class SqlTypeCaseWhen {
private SqlExpression match;
private SqlExpression @new;
internal SqlTypeCaseWhen(SqlExpression match, SqlExpression typeBinding) {
this.Match = match;
this.TypeBinding = typeBinding;
}
internal SqlExpression Match {
get { return this.match; }
set {
if (this.match != null && value != null && this.match.ClrType != value.ClrType)
throw Error.ArgumentWrongType("value", this.match.ClrType, value.ClrType);
this.match = value;
}
}
internal SqlExpression TypeBinding {
get { return this.@new; }
set { this.@new = value; }
}
}
internal class SqlValue : SqlSimpleTypeExpression {
private object value;
private bool isClient;
internal SqlValue(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression)
: base(SqlNodeType.Value, clrType, sqlType, sourceExpression) {
this.value = value;
this.isClient = isClientSpecified;
}
internal object Value {
get { return this.value; }
}
internal bool IsClientSpecified {
get { return this.isClient; }
}
}
internal class SqlParameter : SqlSimpleTypeExpression {
private string name;
private System.Data.ParameterDirection direction;
internal SqlParameter(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)
: base(SqlNodeType.Parameter, clrType, sqlType, sourceExpression) {
if (name == null)
throw Error.ArgumentNull("name");
if (typeof(Type).IsAssignableFrom(clrType))
throw Error.ArgumentWrongValue("clrType");
this.name = name;
this.direction = System.Data.ParameterDirection.Input;
}
internal string Name {
get { return this.name; }
}
internal System.Data.ParameterDirection Direction {
get { return this.direction; }
set { this.direction = value; }
}
}
internal class SqlVariable : SqlSimpleTypeExpression {
private string name;
internal SqlVariable(Type clrType, ProviderType sqlType, string name, Expression sourceExpression)
: base(SqlNodeType.Variable, clrType, sqlType, sourceExpression) {
if (name == null)
throw Error.ArgumentNull("name");
this.name = name;
}
internal string Name {
get { return this.name; }
}
}
internal class SqlMember : SqlSimpleTypeExpression {
private SqlExpression expression;
private MemberInfo member;
internal SqlMember(Type clrType, ProviderType sqlType, SqlExpression expr, MemberInfo member)
: base(SqlNodeType.Member, clrType, sqlType, expr.SourceExpression) {
this.member = member;
this.Expression = expr;
}
internal MemberInfo Member {
get { return this.member; }
}
internal SqlExpression Expression {
get {
return this.expression;
}
set {
if (value == null)
throw Error.ArgumentNull("value");
if (!this.member.ReflectedType.IsAssignableFrom(value.ClrType) &&
!value.ClrType.IsAssignableFrom(this.member.ReflectedType))
throw Error.MemberAccessIllegal(this.member, this.member.ReflectedType, value.ClrType);
this.expression = value;
}
}
}
internal class SqlColumn : SqlExpression {
private SqlAlias alias;
private string name;
private int ordinal;
private MetaDataMember member;
private SqlExpression expression;
private ProviderType sqlType;
internal SqlColumn(Type clrType, ProviderType sqlType, string name, MetaDataMember member, SqlExpression expr, Expression sourceExpression)
: base(SqlNodeType.Column, clrType, sourceExpression) {
if (typeof(Type).IsAssignableFrom(clrType))
throw Error.ArgumentWrongValue("clrType");
this.Name = name;
this.member = member;
this.Expression = expr;
this.Ordinal = -1;
if (sqlType == null)
throw Error.ArgumentNull("sqlType");
this.sqlType = sqlType;
System.Diagnostics.Debug.Assert(sqlType.CanBeColumn);
}
internal SqlColumn(string name, SqlExpression expr)
: this(expr.ClrType, expr.SqlType, name, null, expr, expr.SourceExpression) {
System.Diagnostics.Debug.Assert(expr != null);
}
internal SqlAlias Alias {
get { return this.alias; }
set { this.alias = value; }
}
internal string Name {
get { return this.name; }
set { this.name = value; }
}
internal int Ordinal {
get { return this.ordinal; }
set { this.ordinal = value; }
}
internal MetaDataMember MetaMember {
get { return this.member; }
}
/// <summary>
/// Set the column's Expression. This can change the type of the column.
/// </summary>
internal SqlExpression Expression {
get {
return this.expression;
}
set {
if (value != null) {
if (!this.ClrType.IsAssignableFrom(value.ClrType))
throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
SqlColumnRef cref = value as SqlColumnRef;
if (cref != null && cref.Column == this)
throw Error.ColumnCannotReferToItself();
}
this.expression = value;
}
}
internal override ProviderType SqlType {
get {
if (this.expression != null)
return this.expression.SqlType;
return this.sqlType;
}
}
}
internal class SqlColumnRef : SqlExpression {
private SqlColumn column;
internal SqlColumnRef(SqlColumn col)
: base(SqlNodeType.ColumnRef, col.ClrType, col.SourceExpression) {
this.column = col;
}
internal SqlColumn Column {
get { return this.column; }
}
internal override ProviderType SqlType {
get { return this.column.SqlType; }
}
public override bool Equals(object obj) {
SqlColumnRef cref = obj as SqlColumnRef;
return cref != null && cref.Column == this.column;
}
public override int GetHashCode() {
return this.column.GetHashCode();
}
internal SqlColumn GetRootColumn() {
SqlColumn c = this.column;
while (c.Expression != null && c.Expression.NodeType == SqlNodeType.ColumnRef) {
c = ((SqlColumnRef)c.Expression).Column;
}
return c;
}
}
internal class SqlRow : SqlNode {
private List<SqlColumn> columns;
internal SqlRow(Expression sourceExpression)
: base(SqlNodeType.Row, sourceExpression) {
this.columns = new List<SqlColumn>();
}
internal List<SqlColumn> Columns {
get { return this.columns; }
}
internal SqlColumn Find(string name) {
foreach (SqlColumn c in this.columns) {
if (name == c.Name)
return c;
}
return null;
}
}
internal class SqlMemberAssign : SqlNode {
private MemberInfo member;
private SqlExpression expression;
internal SqlMemberAssign(MemberInfo member, SqlExpression expr)
: base(SqlNodeType.MemberAssign, expr.SourceExpression) {
if (member == null)
throw Error.ArgumentNull("member");
this.member = member;
this.Expression = expr;
}
internal MemberInfo Member {
get { return this.member; }
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.expression = value;
}
}
}
internal class SqlGrouping : SqlSimpleTypeExpression {
private SqlExpression key;
private SqlExpression group;
internal SqlGrouping(Type clrType, ProviderType sqlType, SqlExpression key, SqlExpression group, Expression sourceExpression)
: base(SqlNodeType.Grouping, clrType, sqlType, sourceExpression) {
if (key == null) throw Error.ArgumentNull("key");
if (group == null) throw Error.ArgumentNull("group");
this.key = key;
this.group = group;
}
internal SqlExpression Key {
get { return this.key; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (!this.key.ClrType.IsAssignableFrom(value.ClrType)
&& !value.ClrType.IsAssignableFrom(this.key.ClrType))
throw Error.ArgumentWrongType("value", this.key.ClrType, value.ClrType);
this.key = value;
}
}
internal SqlExpression Group {
get { return this.group; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (value.ClrType != this.group.ClrType)
throw Error.ArgumentWrongType("value", this.group.ClrType, value.ClrType);
this.group = value;
}
}
}
internal class SqlNew : SqlSimpleTypeExpression {
private MetaType metaType;
private ConstructorInfo constructor;
private List<SqlExpression> args;
private List<MemberInfo> argMembers;
private List<SqlMemberAssign> members;
internal SqlNew(MetaType metaType, ProviderType sqlType, ConstructorInfo cons, IEnumerable<SqlExpression> args, IEnumerable<MemberInfo> argMembers, IEnumerable<SqlMemberAssign> members, Expression sourceExpression)
: base(SqlNodeType.New, metaType.Type, sqlType, sourceExpression) {
this.metaType = metaType;
if (cons == null && metaType.Type.IsClass) { // structs do not need to have a constructor
throw Error.ArgumentNull("cons");
}
this.constructor = cons;
this.args = new List<SqlExpression>();
this.argMembers = new List<MemberInfo>();
this.members = new List<SqlMemberAssign>();
if (args != null) {
this.args.AddRange(args);
}
if (argMembers != null) {
this.argMembers.AddRange(argMembers);
}
if (members != null) {
this.members.AddRange(members);
}
}
internal MetaType MetaType {
get { return this.metaType; }
}
internal ConstructorInfo Constructor {
get { return this.constructor; }
}
internal List<SqlExpression> Args {
get { return this.args; }
}
internal List<MemberInfo> ArgMembers {
get { return this.argMembers; }
}
internal List<SqlMemberAssign> Members {
get { return this.members; }
}
internal SqlExpression Find(MemberInfo mi) {
for (int i = 0, n = this.argMembers.Count; i < n; i++) {
MemberInfo argmi = this.argMembers[i];
if (argmi.Name == mi.Name) {
return this.args[i];
}
}
foreach (SqlMemberAssign ma in this.Members) {
if (ma.Member.Name == mi.Name) {
return ma.Expression;
}
}
return null;
}
}
internal class SqlMethodCall : SqlSimpleTypeExpression {
private MethodInfo method;
private SqlExpression obj;
private List<SqlExpression> arguments;
internal SqlMethodCall(Type clrType, ProviderType sqlType, MethodInfo method, SqlExpression obj, IEnumerable<SqlExpression> args, Expression sourceExpression)
: base(SqlNodeType.MethodCall, clrType, sqlType, sourceExpression) {
if (method == null)
throw Error.ArgumentNull("method");
this.method = method;
this.Object = obj;
this.arguments = new List<SqlExpression>();
if (args != null)
this.arguments.AddRange(args);
}
internal MethodInfo Method {
get { return this.method; }
}
internal SqlExpression Object {
get { return this.obj; }
set {
if (value == null && !this.method.IsStatic)
throw Error.ArgumentNull("value");
if (value != null && !this.method.DeclaringType.IsAssignableFrom(value.ClrType))
throw Error.ArgumentWrongType("value", this.method.DeclaringType, value.ClrType);
this.obj = value;
}
}
internal List<SqlExpression> Arguments {
get { return this.arguments; }
}
}
internal class SqlIncludeScope : SqlNode {
SqlNode child;
internal SqlIncludeScope(SqlNode child, Expression sourceExpression)
: base(SqlNodeType.IncludeScope, sourceExpression) {
this.child = child;
}
internal SqlNode Child {
get {return this.child;}
set {this.child = value;}
}
}
internal class SqlClientArray : SqlSimpleTypeExpression {
private List<SqlExpression> expressions;
internal SqlClientArray(Type clrType, ProviderType sqlType, SqlExpression[ ] exprs, Expression sourceExpression)
: base(SqlNodeType.ClientArray, clrType, sqlType, sourceExpression) {
this.expressions = new List<SqlExpression>();
if (exprs != null)
this.Expressions.AddRange(exprs);
}
internal List<SqlExpression> Expressions {
get { return this.expressions; }
}
}
internal class SqlLink : SqlSimpleTypeExpression {
private MetaType rowType;
private SqlExpression expression;
private MetaDataMember member;
private List<SqlExpression> keyExpressions;
private SqlExpression expansion;
private object id;
internal SqlLink(object id, MetaType rowType, Type clrType, ProviderType sqlType, SqlExpression expression, MetaDataMember member, IEnumerable<SqlExpression> keyExpressions, SqlExpression expansion, Expression sourceExpression)
: base(SqlNodeType.Link, clrType, sqlType, sourceExpression) {
this.id = id;
this.rowType = rowType;
this.expansion = expansion;
this.expression = expression;
this.member = member;
this.keyExpressions = new List<SqlExpression>();
if (keyExpressions != null)
this.keyExpressions.AddRange(keyExpressions);
}
internal MetaType RowType {
get { return this.rowType; }
}
internal SqlExpression Expansion {
get { return this.expansion; }
set { this.expansion = value; }
}
internal SqlExpression Expression {
get { return this.expression; }
set { this.expression = value; }
}
internal MetaDataMember Member {
get { return this.member; }
}
internal List<SqlExpression> KeyExpressions {
get { return this.keyExpressions; }
}
internal object Id {
get { return this.id; }
}
}
internal class SqlExprSet : SqlExpression {
private List<SqlExpression> expressions;
internal SqlExprSet(Type clrType, IEnumerable <SqlExpression> exprs, Expression sourceExpression)
: base(SqlNodeType.ExprSet, clrType, sourceExpression) {
this.expressions = new List<SqlExpression>(exprs);
}
internal List<SqlExpression> Expressions {
get { return this.expressions; }
}
/// <summary>
/// Get the first non-set expression of the set by drilling
/// down the left expressions.
/// </summary>
internal SqlExpression GetFirstExpression() {
SqlExpression expr = expressions[0];
while (expr is SqlExprSet) {
expr = ((SqlExprSet)expr).Expressions[0];
}
return expr;
}
internal override ProviderType SqlType {
get { return this.expressions[0].SqlType; }
}
}
internal class SqlSubSelect : SqlSimpleTypeExpression {
private SqlSelect select;
internal SqlSubSelect(SqlNodeType nt , Type clrType, ProviderType sqlType , SqlSelect select)
: base(nt, clrType, sqlType, select.SourceExpression) {
switch (nt) {
case SqlNodeType.Multiset:
case SqlNodeType.ScalarSubSelect:
case SqlNodeType.Element:
case SqlNodeType.Exists:
break;
default:
throw Error.UnexpectedNode(nt);
}
this.Select = select;
}
internal SqlSelect Select {
get { return this.select; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.select = value;
}
}
}
internal class SqlClientQuery : SqlSimpleTypeExpression {
private SqlSubSelect query;
private List<SqlExpression> arguments;
private List<SqlParameter> parameters;
int ordinal;
internal SqlClientQuery(SqlSubSelect subquery)
: base(SqlNodeType.ClientQuery, subquery.ClrType, subquery.SqlType, subquery.SourceExpression) {
this.query = subquery;
this.arguments = new List<SqlExpression>();
this.parameters = new List<SqlParameter>();
}
internal SqlSubSelect Query {
get { return this.query; }
set {
if (value == null || (this.query != null && this.query.ClrType != value.ClrType))
throw Error.ArgumentWrongType(value, this.query.ClrType, value.ClrType);
this.query = value;
}
}
internal List<SqlExpression> Arguments {
get { return this.arguments; }
}
internal List<SqlParameter> Parameters {
get { return this.parameters; }
}
internal int Ordinal {
get { return this.ordinal; }
set { this.ordinal = value; }
}
}
internal class SqlJoinedCollection : SqlSimpleTypeExpression {
private SqlExpression expression;
private SqlExpression count;
internal SqlJoinedCollection(Type clrType, ProviderType sqlType, SqlExpression expression, SqlExpression count, Expression sourceExpression)
: base(SqlNodeType.JoinedCollection, clrType, sqlType, sourceExpression) {
this.expression = expression;
this.count = count;
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null || this.expression != null && this.expression.ClrType != value.ClrType)
throw Error.ArgumentWrongType(value, this.expression.ClrType, value.ClrType);
this.expression = value;
}
}
internal SqlExpression Count {
get { return this.count; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (value.ClrType != typeof(int))
throw Error.ArgumentWrongType(value, typeof(int), value.ClrType);
this.count = value;
}
}
}
internal class SqlUpdate : SqlStatement {
private SqlSelect select;
private List<SqlAssign> assignments;
internal SqlUpdate(SqlSelect select, IEnumerable<SqlAssign> assignments, Expression sourceExpression)
: base(SqlNodeType.Update, sourceExpression) {
this.Select = select;
this.assignments = new List<SqlAssign>(assignments);
}
internal SqlSelect Select {
get { return this.select; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.select = value;
}
}
internal List<SqlAssign> Assignments {
get { return this.assignments; }
}
}
internal class SqlInsert : SqlStatement {
private SqlTable table;
private SqlRow row;
private SqlExpression expression;
private SqlColumn outputKey;
private bool outputToLocal;
internal SqlInsert(SqlTable table, SqlExpression expr, Expression sourceExpression)
: base(SqlNodeType.Insert, sourceExpression) {
this.Table = table;
this.Expression = expr;
this.Row = new SqlRow(sourceExpression);
}
internal SqlTable Table {
get { return this.table; }
set {
if (value == null)
throw Error.ArgumentNull("null");
this.table = value;
}
}
internal SqlRow Row {
get { return this.row; }
set { this.row = value; }
}
internal SqlExpression Expression {
get { return this.expression; }
set {
if (value == null)
throw Error.ArgumentNull("null");
if (!this.table.RowType.Type.IsAssignableFrom(value.ClrType))
throw Error.ArgumentWrongType("value", this.table.RowType, value.ClrType);
this.expression = value;
}
}
internal SqlColumn OutputKey {
get { return this.outputKey; }
set { this.outputKey = value; }
}
internal bool OutputToLocal {
get { return this.outputToLocal; }
set { this.outputToLocal = value; }
}
}
internal class SqlDelete : SqlStatement {
private SqlSelect select;
internal SqlDelete(SqlSelect select, Expression sourceExpression)
: base(SqlNodeType.Delete, sourceExpression) {
this.Select = select;
}
internal SqlSelect Select {
get { return this.select; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.select = value;
}
}
}
internal class SqlBlock : SqlStatement {
private List<SqlStatement> statements;
internal SqlBlock(Expression sourceExpression)
: base(SqlNodeType.Block, sourceExpression) {
this.statements = new List<SqlStatement>();
}
internal List<SqlStatement> Statements {
get { return this.statements; }
}
}
internal class SqlAssign : SqlStatement {
private SqlExpression leftValue;
private SqlExpression rightValue;
internal SqlAssign(SqlExpression lValue, SqlExpression rValue, Expression sourceExpression)
: base(SqlNodeType.Assign, sourceExpression) {
this.LValue = lValue;
this.RValue = rValue;
}
internal SqlExpression LValue {
get { return this.leftValue; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.rightValue != null && !value.ClrType.IsAssignableFrom(this.rightValue.ClrType))
throw Error.ArgumentWrongType("value", this.rightValue.ClrType, value.ClrType);
this.leftValue = value;
}
}
internal SqlExpression RValue {
get { return this.rightValue; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (this.leftValue != null && !this.leftValue.ClrType.IsAssignableFrom(value.ClrType))
throw Error.ArgumentWrongType("value", this.leftValue.ClrType, value.ClrType);
this.rightValue = value;
}
}
}
internal class SqlDoNotVisitExpression : SqlExpression {
private SqlExpression expression;
internal SqlDoNotVisitExpression(SqlExpression expr)
: base(SqlNodeType.DoNotVisit, expr.ClrType, expr.SourceExpression) {
if (expr == null)
throw Error.ArgumentNull("expr");
this.expression = expr;
}
internal SqlExpression Expression {
get { return this.expression; }
}
internal override ProviderType SqlType {
get { return this.expression.SqlType; }
}
}
internal class SqlOptionalValue : SqlSimpleTypeExpression {
private SqlExpression hasValue;
private SqlExpression expressionValue;
internal SqlOptionalValue( SqlExpression hasValue, SqlExpression value)
: base(SqlNodeType.OptionalValue, value.ClrType, value.SqlType, value.SourceExpression) {
this.HasValue = hasValue;
this.Value = value;
}
internal SqlExpression HasValue {
get { return this.hasValue; }
set {
if (value == null)
throw Error.ArgumentNull("value");
this.hasValue = value;
}
}
internal SqlExpression Value {
get { return this.expressionValue; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (value.ClrType != this.ClrType)
throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
this.expressionValue = value;
}
}
}
internal class SqlFunctionCall : SqlSimpleTypeExpression {
private string name;
private List<SqlExpression> arguments;
internal SqlFunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression > args , Expression source)
: this(SqlNodeType.FunctionCall, clrType , sqlType, name, args, source) {
}
internal SqlFunctionCall(SqlNodeType nodeType, Type clrType, ProviderType sqlType, string name , IEnumerable <SqlExpression> args , Expression source)
: base(nodeType, clrType, sqlType, source) {
this.name = name;
this.arguments = new List<SqlExpression>(args);
}
internal string Name {
get { return this.name; }
}
internal List<SqlExpression> Arguments {
get { return this.arguments; }
}
}
/// <summary>
/// This class is used to represent a table value function. It inherits normal function
/// call functionality, and adds TVF specific members.
/// </summary>
internal class SqlTableValuedFunctionCall : SqlFunctionCall {
private MetaType rowType;
private List<SqlColumn> columns;
internal SqlTableValuedFunctionCall(MetaType rowType, Type clrType, ProviderType sqlType, string name, IEnumerable <SqlExpression > args , Expression source)
: base(SqlNodeType.TableValuedFunctionCall, clrType , sqlType, name, args, source) {
this.rowType = rowType;
this.columns = new List<SqlColumn>();
}
internal MetaType RowType {
get { return this.rowType; }
}
internal List<SqlColumn> Columns {
get { return this.columns; }
}
internal SqlColumn Find(string name) {
foreach (SqlColumn c in this.Columns) {
if (c.Name == name)
return c;
}
return null;
}
}
internal class SqlSharedExpression : SqlExpression {
private SqlExpression expr;
internal SqlSharedExpression(SqlExpression expr)
: base(SqlNodeType.SharedExpression, expr.ClrType, expr.SourceExpression) {
this.expr = expr;
}
internal SqlExpression Expression {
get { return this.expr; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (!this.ClrType.IsAssignableFrom(value.ClrType)
&& !value.ClrType.IsAssignableFrom(this.ClrType))
throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
this.expr = value;
}
}
internal override ProviderType SqlType {
get { return this.expr.SqlType; }
}
}
internal class SqlSharedExpressionRef : SqlExpression {
private SqlSharedExpression expr;
internal SqlSharedExpressionRef(SqlSharedExpression expr)
: base(SqlNodeType.SharedExpressionRef, expr.ClrType, expr.SourceExpression) {
this.expr = expr;
}
internal SqlSharedExpression SharedExpression {
get { return this.expr; }
}
internal override ProviderType SqlType {
get { return this.expr.SqlType; }
}
}
internal class SqlSimpleExpression : SqlExpression {
private SqlExpression expr;
internal SqlSimpleExpression(SqlExpression expr)
: base(SqlNodeType.SimpleExpression, expr.ClrType, expr.SourceExpression) {
this.expr = expr;
}
internal SqlExpression Expression {
get { return this.expr; }
set {
if (value == null)
throw Error.ArgumentNull("value");
if (!TypeSystem.GetNonNullableType(this.ClrType).IsAssignableFrom(TypeSystem.GetNonNullableType(value.ClrType)))
throw Error.ArgumentWrongType("value", this.ClrType, value.ClrType);
this.expr = value;
}
}
internal override ProviderType SqlType {
get { return this.expr.SqlType; }
}
}
internal class SqlClientParameter : SqlSimpleTypeExpression {
// Expression<Func<object[], T>>
LambdaExpression accessor;
internal SqlClientParameter(Type clrType, ProviderType sqlType, LambdaExpression accessor, Expression sourceExpression):
base(SqlNodeType.ClientParameter, clrType, sqlType, sourceExpression) {
this.accessor = accessor;
}
internal LambdaExpression Accessor {
get { return this.accessor; }
}
}
}
|