Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DLinq / Dlinq / SqlClient / Common / SqlFactory.cs / 4 / SqlFactory.cs
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Linq.Expressions; using System.Data.Linq; namespace System.Data.Linq.SqlClient { using System.Data.Linq.Mapping; using System.Data.Linq.Provider; using System.Diagnostics.CodeAnalysis; using System.Diagnostics; ////// Factory class produces SqlNodes. Smarts about type system mappings should go /// here and not in the individual SqlNodes. /// internal class SqlFactory { private TypeSystemProvider typeProvider; private MetaModel model; internal TypeSystemProvider TypeProvider { get { return typeProvider; } } internal SqlFactory(TypeSystemProvider typeProvider, MetaModel model) { this.typeProvider = typeProvider; this.model = model; } #region Expression Operators internal SqlExpression CastTo(Type clrType, SqlExpression expr) { return UnaryCast(clrType, typeProvider.From(clrType), expr, expr.SourceExpression); } internal SqlExpression ConvertTo(Type clrType, ProviderType sqlType, SqlExpression expr) { return UnaryConvert(clrType, sqlType, expr, expr.SourceExpression); } internal SqlExpression ConvertTo(Type clrType, SqlExpression expr) { // // In SQL Server 2008, the new TIME data type cannot be converted to BIGINT, or FLOAT, // or a bunch of other SQL types. // if (clrType.IsGenericType && clrType.GetGenericTypeDefinition() == typeof(Nullable<>)) clrType = clrType.GetGenericArguments()[0]; bool isClrTimeSpanType = clrType == typeof(TimeSpan); if (IsSqlTimeType(expr)) { if (isClrTimeSpanType) { // no conversion necessary return expr; } else { expr = ConvertToDateTime(expr); } } return UnaryConvert(clrType, typeProvider.From(clrType), expr, expr.SourceExpression); } internal SqlExpression ConvertToBigint(SqlExpression expr) { return ConvertTo(typeof(long), expr); } internal SqlExpression ConvertToInt(SqlExpression expr) { return ConvertTo(typeof(int), expr); } internal SqlExpression ConvertToDouble(SqlExpression expr) { return ConvertTo(typeof(double), expr); } // If the argument expression has SqlDbType Time, inject a conversion to Double, else return // the expression unchanged. // internal SqlExpression ConvertTimeToDouble(SqlExpression exp) { return IsSqlTimeType(exp) ? ConvertToDouble(exp) : exp; } internal SqlExpression ConvertToBool(SqlExpression expr) { return ConvertTo(typeof(bool), expr); } internal SqlExpression ConvertToDateTime(SqlExpression expr) { return UnaryConvert(typeof(DateTime), typeProvider.From(typeof(DateTime)), expr, expr.SourceExpression); } internal SqlExpression AndAccumulate(SqlExpression left, SqlExpression right) { if (left == null) { return right; } else if (right == null) { return left; } else { return Binary(SqlNodeType.And, left, right); } } internal SqlExpression OrAccumulate(SqlExpression left, SqlExpression right) { if (left == null) { return right; } else if (right == null) { return left; } else { return Binary(SqlNodeType.Or, left, right); } } internal SqlExpression Concat(params SqlExpression[] expressions) { SqlExpression result = expressions[expressions.Length - 1]; for (int i = expressions.Length - 2; i >= 0; i--) { result = Binary(SqlNodeType.Concat, expressions[i], result); } return result; } internal SqlExpression Add(params SqlExpression[] expressions) { SqlExpression sum = expressions[expressions.Length - 1]; for (int i = expressions.Length - 2; i >= 0; i--) { sum = Binary(SqlNodeType.Add, expressions[i], sum); } return sum; } internal SqlExpression Subtract(SqlExpression first, SqlExpression second) { return Binary(SqlNodeType.Sub, first, second); } internal SqlExpression Multiply(params SqlExpression[] expressions) { SqlExpression result = expressions[expressions.Length - 1]; for (int i = expressions.Length - 2; i >= 0; i--) { result = Binary(SqlNodeType.Mul, expressions[i], result); } return result; } internal SqlExpression Divide(SqlExpression first, SqlExpression second) { return Binary(SqlNodeType.Div, first, second); } internal SqlExpression Add(SqlExpression expr, int second) { return Binary(SqlNodeType.Add, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Subtract(SqlExpression expr, int second) { return Binary(SqlNodeType.Sub, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Multiply(SqlExpression expr, long second) { return Binary(SqlNodeType.Mul, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Divide(SqlExpression expr, long second) { return Binary(SqlNodeType.Div, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Mod(SqlExpression expr, long second) { return Binary(SqlNodeType.Mod, expr, ValueFromObject(second, false, expr.SourceExpression)); } ////// Non-internal string length. This should only be used when translating an explicit call by the /// user to String.Length. /// internal SqlExpression LEN(SqlExpression expr) { return FunctionCall(typeof(int), "LEN", new SqlExpression[] { expr }, expr.SourceExpression); } ////// This represents the SQL DATALENGTH function, which is the raw number of bytes in the argument. In the /// case of string types it will count trailing spaces, but doesn't understand unicode. /// internal SqlExpression DATALENGTH(SqlExpression expr) { return FunctionCall(typeof(int), "DATALENGTH", new SqlExpression[] { expr }, expr.SourceExpression); } ////// A unary function that uses DATALENGTH, dividing by two if the string is unicode. This is the internal /// form of String.Length that should always be used. /// internal SqlExpression CLRLENGTH(SqlExpression expr) { return Unary(SqlNodeType.ClrLength, expr); } internal SqlExpression DATEPART(string partName, SqlExpression expr) { return FunctionCall( typeof(int), "DATEPART", new SqlExpression[] { new SqlVariable(typeof(void), null, partName, expr.SourceExpression), expr }, expr.SourceExpression ); } internal SqlExpression DATEADD(string partName, SqlExpression value, SqlExpression expr) { return DATEADD(partName, value, expr, expr.SourceExpression, false); } internal SqlExpression DATEADD(string partName, SqlExpression value, SqlExpression expr, Expression sourceExpression, bool asNullable) { Type returnType = asNullable ? typeof(DateTime?) : typeof(DateTime); return FunctionCall( returnType, "DATEADD", new SqlExpression[] { new SqlVariable(typeof(void), null, partName, sourceExpression), value, expr }, sourceExpression ); } internal SqlExpression DATETIMEOFFSETADD(string partName, SqlExpression value, SqlExpression expr) { return DATETIMEOFFSETADD(partName, value, expr, expr.SourceExpression, false); } internal SqlExpression DATETIMEOFFSETADD(string partName, SqlExpression value, SqlExpression expr, Expression sourceExpression, bool asNullable) { Type returnType = asNullable ? typeof(DateTimeOffset?) : typeof(DateTimeOffset); return FunctionCall( returnType, "DATEADD", new SqlExpression[] { new SqlVariable(typeof(void), null, partName, sourceExpression), value, expr }, sourceExpression ); } #endregion internal SqlExpression AddTimeSpan(SqlExpression dateTime, SqlExpression timeSpan) { return AddTimeSpan(dateTime, timeSpan, false); } internal SqlExpression AddTimeSpan(SqlExpression dateTime, SqlExpression timeSpan, bool asNullable) { Debug.Assert(IsSqlHighPrecisionDateTimeType(timeSpan)); SqlExpression ns = DATEPART("NANOSECOND", timeSpan); SqlExpression ms = DATEPART("MILLISECOND", timeSpan); SqlExpression ss = DATEPART("SECOND", timeSpan); SqlExpression mi = DATEPART("MINUTE", timeSpan); SqlExpression hh = DATEPART("HOUR", timeSpan); SqlExpression result = dateTime; if (IsSqlHighPrecisionDateTimeType(dateTime)) { result = DATEADD("NANOSECOND", ns, result, dateTime.SourceExpression, asNullable); } else { result = DATEADD("MILLISECOND", ms, result, dateTime.SourceExpression, asNullable); } result = DATEADD("SECOND", ss, result, dateTime.SourceExpression, asNullable); result = DATEADD("MINUTE", mi, result, dateTime.SourceExpression, asNullable); result = DATEADD("HOUR", hh, result, dateTime.SourceExpression, asNullable); if (IsSqlDateTimeOffsetType(dateTime)) return ConvertTo(typeof(DateTimeOffset), result); return result; } internal bool IsSqlDateTimeType(SqlExpression exp) { SqlDbType sqlDbType = ((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType; return (sqlDbType == SqlDbType.DateTime || sqlDbType == SqlDbType.SmallDateTime); } internal bool IsSqlDateType(SqlExpression exp) { return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.Date); } internal bool IsSqlTimeType(SqlExpression exp) { return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.Time); } internal bool IsSqlDateTimeOffsetType(SqlExpression exp) { return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.DateTimeOffset); } internal bool IsSqlHighPrecisionDateTimeType(SqlExpression exp) { SqlDbType sqlDbType = ((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType; return (sqlDbType == SqlDbType.Time || sqlDbType == SqlDbType.DateTime2 || sqlDbType == SqlDbType.DateTimeOffset); } ////// Return a node representing obj.GetType() /// internal SqlExpression ObjectType(SqlExpression obj, Expression sourceExpression) { return new SqlObjectType(obj, this.typeProvider.From(typeof(Type)), sourceExpression); } internal SqlExpression Value(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression) { if (typeof(Type).IsAssignableFrom(clrType)) { MetaType typeOf = this.model.GetMetaType((Type)value); return StaticType(typeOf, sourceExpression); } return new SqlValue(clrType, sqlType, value, isClientSpecified, sourceExpression); } ////// Return a node representing typeof(typeOf) /// internal SqlExpression StaticType(MetaType typeOf, Expression sourceExpression) { if (typeOf==null) throw Error.ArgumentNull("typeOf"); if(typeOf.InheritanceCode==null) { // If no inheritance is involved, then there's no discriminator to // make a discriminated type. In this case, just make a literal type. return new SqlValue(typeof(Type), this.typeProvider.From(typeof(Type)), typeOf.Type, false, sourceExpression); } Type type = typeOf.InheritanceCode.GetType(); SqlValue match = new SqlValue(type, this.typeProvider.From(type), typeOf.InheritanceCode, true, sourceExpression); return this.DiscriminatedType(match, typeOf); } internal SqlExpression DiscriminatedType(SqlExpression discriminator, MetaType targetType) { return new SqlDiscriminatedType(typeProvider.From(typeof(Type)), discriminator, targetType, discriminator.SourceExpression); } internal SqlTable Table(MetaTable table, MetaType rowType, Expression sourceExpression) { return new SqlTable(table, rowType, this.typeProvider.GetApplicationType((int)ConverterSpecialTypes.Row), sourceExpression); } internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression) { return Unary(nodeType, expression, expression.SourceExpression); } internal SqlRowNumber RowNumber(ListorderBy, Expression sourceExpression) { return new SqlRowNumber(typeof(long), typeProvider.From(typeof(long)), orderBy, sourceExpression); } internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, Expression sourceExpression) { return Unary(nodeType, expression, null, sourceExpression); } internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, MethodInfo method, Expression sourceExpression) { Type clrType = null; ProviderType sqlType = null; if (nodeType == SqlNodeType.Count) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else if (nodeType == SqlNodeType.LongCount) { clrType = typeof(long); sqlType = typeProvider.From(typeof(long)); } else if (nodeType == SqlNodeType.ClrLength) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else { if (nodeType.IsPredicateUnaryOperator()) { clrType = typeof(bool); } else { clrType = expression.ClrType; } sqlType = typeProvider.PredictTypeForUnary(nodeType, expression.SqlType); } return new SqlUnary(nodeType, clrType, sqlType, expression, method, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlUnary UnaryCast(Type targetClrType, ProviderType targetSqlType, SqlExpression expression, Expression sourceExpression) { return new SqlUnary(SqlNodeType.Cast, targetClrType, targetSqlType, expression, null, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlUnary UnaryConvert(Type targetClrType, ProviderType targetSqlType, SqlExpression expression, Expression sourceExpression) { System.Diagnostics.Debug.Assert(!targetSqlType.IsRuntimeOnlyType, "Attempted coversion to a runtime type: from = " + expression.SqlType.ToQueryString() + "; to = " + targetSqlType.ToQueryString() + "; source = " + sourceExpression.ToString()); return new SqlUnary(SqlNodeType.Convert, targetClrType, targetSqlType, expression, null, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlUnary UnaryValueOf(SqlExpression expression, Expression sourceExpression) { Type valueType = TypeSystem.GetNonNullableType(expression.ClrType); return new SqlUnary(SqlNodeType.ValueOf, valueType, expression.SqlType, expression, null, sourceExpression); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right) { return Binary(nodeType, left, right, null, null); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method) { return Binary(nodeType, left, right, method, null); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, Type clrType) { return Binary(nodeType, left, right, null, clrType); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method, Type clrType) { ProviderType sqlType = null; if (nodeType.IsPredicateBinaryOperator()) { if (clrType == null) { clrType = typeof(bool); } sqlType = typeProvider.From(clrType); } else { ProviderType resultType = this.typeProvider.PredictTypeForBinary(nodeType, left.SqlType, right.SqlType); if (resultType == right.SqlType) { if (clrType == null) { clrType = right.ClrType; } sqlType = right.SqlType; } else if (resultType == left.SqlType) { if (clrType == null) { clrType = left.ClrType; } sqlType = left.SqlType; } else { sqlType = resultType; if (clrType == null) { clrType = resultType.GetClosestRuntimeType(); } } } return new SqlBinary(nodeType, clrType, sqlType, left, right, method); } internal SqlBetween Between(SqlExpression expr, SqlExpression start, SqlExpression end, Expression source) { return new SqlBetween(typeof(bool), typeProvider.From(typeof(bool)), expr, start, end, source); } internal SqlIn In(SqlExpression expr, IEnumerable values, Expression source) { return new SqlIn(typeof(bool), typeProvider.From(typeof(bool)), expr, values, source); } internal SqlLike Like(SqlExpression expr, SqlExpression pattern, SqlExpression escape, Expression source) { SqlLike like = new SqlLike(typeof(bool), typeProvider.From(typeof(bool)), expr, pattern, escape, source); return like; } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlSearchedCase SearchedCase(SqlWhen[] whens, SqlExpression @else, Expression sourceExpression) { return new SqlSearchedCase(whens[0].Value.ClrType, whens, @else, sourceExpression); } /// /// Construct either a SqlClientCase or a SqlSimpleCase depending on whether the individual cases /// are client-aided or not. /// [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlExpression Case(Type clrType, SqlExpression discriminator, Listmatches, List values, Expression sourceExpression) { if (values.Count == 0) { throw Error.EmptyCaseNotSupported(); } bool anyClient = false; foreach (SqlExpression value in values) { anyClient |= value.IsClientAidedExpression(); } if (anyClient) { List whens = new List (); for (int i = 0, c = matches.Count; i < c; ++i) { whens.Add(new SqlClientWhen(matches[i], values[i])); } return new SqlClientCase(clrType, discriminator, whens, sourceExpression); } else { List whens = new List (); for (int i = 0, c = matches.Count; i < c; ++i) { whens.Add(new SqlWhen(matches[i], values[i])); } return new SqlSimpleCase(clrType, discriminator, whens, sourceExpression); } } internal SqlExpression Parameter(object value, Expression source) { System.Diagnostics.Debug.Assert(value != null); Type type = value.GetType(); return Value(type, this.typeProvider.From(value), value, true, source); } internal SqlExpression ValueFromObject(object value, Expression sourceExpression) { return ValueFromObject(value, false, sourceExpression); } internal SqlExpression ValueFromObject(object value, bool isClientSpecified, Expression sourceExpression) { if (value == null) { System.Diagnostics.Debug.Assert(false); throw Error.ArgumentNull("value"); } Type clrType = value.GetType(); return ValueFromObject(value, clrType, isClientSpecified, sourceExpression); } // Override allowing the CLR type of the value to be specified explicitly. internal SqlExpression ValueFromObject(object value, Type clrType, bool isClientSpecified, Expression sourceExpression) { if (clrType == null) { throw Error.ArgumentNull("clrType"); } ProviderType sqlType = (value == null) ? this.typeProvider.From(clrType) : this.typeProvider.From(value); return Value(clrType, sqlType, value, isClientSpecified, sourceExpression); } public SqlExpression TypedLiteralNull(Type type, Expression sourceExpression) { return ValueFromObject(null, type, false, sourceExpression); } internal SqlMember Member(SqlExpression expr, MetaDataMember member) { return new SqlMember(member.Type, this.Default(member), expr, member.Member); } internal SqlMember Member(SqlExpression expr, MemberInfo member) { Type clrType = TypeSystem.GetMemberType(member); MetaType metaType = this.model.GetMetaType(member.DeclaringType); MetaDataMember metaDataMember = metaType.GetDataMember(member); if (metaType != null && metaDataMember != null) { return new SqlMember(clrType, this.Default(metaDataMember), expr, member); } else { return new SqlMember(clrType, this.Default(clrType), expr, member); } } internal SqlExpression TypeCase(Type clrType, MetaType rowType, SqlExpression discriminator, IEnumerable whens, Expression sourceExpression) { return new SqlTypeCase(clrType, typeProvider.From(clrType), rowType, discriminator, whens, sourceExpression); } internal SqlNew New(MetaType type, ConstructorInfo cons, IEnumerable args, IEnumerable argMembers, IEnumerable bindings, Expression sourceExpression) { SqlNew tb = new SqlNew(type, typeProvider.From(type.Type), cons, args, argMembers, bindings, sourceExpression); return tb; } internal SqlMethodCall MethodCall(MethodInfo method, SqlExpression obj, SqlExpression[] args, Expression sourceExpression) { return new SqlMethodCall(method.ReturnType, this.Default(method.ReturnType), method, obj, args, sourceExpression); } internal SqlMethodCall MethodCall(Type returnType, MethodInfo method, SqlExpression obj, SqlExpression[] args, Expression sourceExpression) { return new SqlMethodCall(returnType, this.Default(returnType), method, obj, args, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlExprSet ExprSet(SqlExpression[] exprs, Expression sourceExpression) { return new SqlExprSet(exprs[0].ClrType, exprs, sourceExpression); } internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select) { return this.SubSelect(nt, select, null); } internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select, Type clrType) { ProviderType sqlType = null; switch (nt) { case SqlNodeType.ScalarSubSelect: case SqlNodeType.Element: clrType = select.Selection.ClrType; sqlType = select.Selection.SqlType; break; case SqlNodeType.Multiset: if (clrType == null) { clrType = typeof(List<>).MakeGenericType(select.Selection.ClrType); } sqlType = typeProvider.GetApplicationType((int)ConverterSpecialTypes.Table); break; case SqlNodeType.Exists: clrType = typeof(bool); sqlType = typeProvider.From(typeof(bool)); break; } return new SqlSubSelect(nt, clrType, sqlType, select); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlDoNotVisitExpression DoNotVisitExpression(SqlExpression expr) { return new SqlDoNotVisitExpression(expr); } internal SqlFunctionCall FunctionCall(Type clrType, string name, IEnumerable args, Expression source) { return new SqlFunctionCall(clrType, Default(clrType), name, args, source); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlFunctionCall FunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable args, Expression source) { return new SqlFunctionCall(clrType, sqlType, name, args, source); } internal SqlTableValuedFunctionCall TableValuedFunctionCall(MetaType rowType, Type clrType, string name, IEnumerable args, Expression source) { return new SqlTableValuedFunctionCall(rowType, clrType, Default(clrType), name, args, source); } internal ProviderType Default(Type clrType) { return typeProvider.From(clrType); } internal ProviderType Default(MetaDataMember member) { if(member == null) throw Error.ArgumentNull("member"); if (member.DbType != null) { return this.typeProvider.Parse(member.DbType); } else { return this.typeProvider.From(member.Type); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Linq.Expressions; using System.Data.Linq; namespace System.Data.Linq.SqlClient { using System.Data.Linq.Mapping; using System.Data.Linq.Provider; using System.Diagnostics.CodeAnalysis; using System.Diagnostics; /// /// Factory class produces SqlNodes. Smarts about type system mappings should go /// here and not in the individual SqlNodes. /// internal class SqlFactory { private TypeSystemProvider typeProvider; private MetaModel model; internal TypeSystemProvider TypeProvider { get { return typeProvider; } } internal SqlFactory(TypeSystemProvider typeProvider, MetaModel model) { this.typeProvider = typeProvider; this.model = model; } #region Expression Operators internal SqlExpression CastTo(Type clrType, SqlExpression expr) { return UnaryCast(clrType, typeProvider.From(clrType), expr, expr.SourceExpression); } internal SqlExpression ConvertTo(Type clrType, ProviderType sqlType, SqlExpression expr) { return UnaryConvert(clrType, sqlType, expr, expr.SourceExpression); } internal SqlExpression ConvertTo(Type clrType, SqlExpression expr) { // // In SQL Server 2008, the new TIME data type cannot be converted to BIGINT, or FLOAT, // or a bunch of other SQL types. // if (clrType.IsGenericType && clrType.GetGenericTypeDefinition() == typeof(Nullable<>)) clrType = clrType.GetGenericArguments()[0]; bool isClrTimeSpanType = clrType == typeof(TimeSpan); if (IsSqlTimeType(expr)) { if (isClrTimeSpanType) { // no conversion necessary return expr; } else { expr = ConvertToDateTime(expr); } } return UnaryConvert(clrType, typeProvider.From(clrType), expr, expr.SourceExpression); } internal SqlExpression ConvertToBigint(SqlExpression expr) { return ConvertTo(typeof(long), expr); } internal SqlExpression ConvertToInt(SqlExpression expr) { return ConvertTo(typeof(int), expr); } internal SqlExpression ConvertToDouble(SqlExpression expr) { return ConvertTo(typeof(double), expr); } // If the argument expression has SqlDbType Time, inject a conversion to Double, else return // the expression unchanged. // internal SqlExpression ConvertTimeToDouble(SqlExpression exp) { return IsSqlTimeType(exp) ? ConvertToDouble(exp) : exp; } internal SqlExpression ConvertToBool(SqlExpression expr) { return ConvertTo(typeof(bool), expr); } internal SqlExpression ConvertToDateTime(SqlExpression expr) { return UnaryConvert(typeof(DateTime), typeProvider.From(typeof(DateTime)), expr, expr.SourceExpression); } internal SqlExpression AndAccumulate(SqlExpression left, SqlExpression right) { if (left == null) { return right; } else if (right == null) { return left; } else { return Binary(SqlNodeType.And, left, right); } } internal SqlExpression OrAccumulate(SqlExpression left, SqlExpression right) { if (left == null) { return right; } else if (right == null) { return left; } else { return Binary(SqlNodeType.Or, left, right); } } internal SqlExpression Concat(params SqlExpression[] expressions) { SqlExpression result = expressions[expressions.Length - 1]; for (int i = expressions.Length - 2; i >= 0; i--) { result = Binary(SqlNodeType.Concat, expressions[i], result); } return result; } internal SqlExpression Add(params SqlExpression[] expressions) { SqlExpression sum = expressions[expressions.Length - 1]; for (int i = expressions.Length - 2; i >= 0; i--) { sum = Binary(SqlNodeType.Add, expressions[i], sum); } return sum; } internal SqlExpression Subtract(SqlExpression first, SqlExpression second) { return Binary(SqlNodeType.Sub, first, second); } internal SqlExpression Multiply(params SqlExpression[] expressions) { SqlExpression result = expressions[expressions.Length - 1]; for (int i = expressions.Length - 2; i >= 0; i--) { result = Binary(SqlNodeType.Mul, expressions[i], result); } return result; } internal SqlExpression Divide(SqlExpression first, SqlExpression second) { return Binary(SqlNodeType.Div, first, second); } internal SqlExpression Add(SqlExpression expr, int second) { return Binary(SqlNodeType.Add, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Subtract(SqlExpression expr, int second) { return Binary(SqlNodeType.Sub, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Multiply(SqlExpression expr, long second) { return Binary(SqlNodeType.Mul, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Divide(SqlExpression expr, long second) { return Binary(SqlNodeType.Div, expr, ValueFromObject(second, false, expr.SourceExpression)); } internal SqlExpression Mod(SqlExpression expr, long second) { return Binary(SqlNodeType.Mod, expr, ValueFromObject(second, false, expr.SourceExpression)); } ////// Non-internal string length. This should only be used when translating an explicit call by the /// user to String.Length. /// internal SqlExpression LEN(SqlExpression expr) { return FunctionCall(typeof(int), "LEN", new SqlExpression[] { expr }, expr.SourceExpression); } ////// This represents the SQL DATALENGTH function, which is the raw number of bytes in the argument. In the /// case of string types it will count trailing spaces, but doesn't understand unicode. /// internal SqlExpression DATALENGTH(SqlExpression expr) { return FunctionCall(typeof(int), "DATALENGTH", new SqlExpression[] { expr }, expr.SourceExpression); } ////// A unary function that uses DATALENGTH, dividing by two if the string is unicode. This is the internal /// form of String.Length that should always be used. /// internal SqlExpression CLRLENGTH(SqlExpression expr) { return Unary(SqlNodeType.ClrLength, expr); } internal SqlExpression DATEPART(string partName, SqlExpression expr) { return FunctionCall( typeof(int), "DATEPART", new SqlExpression[] { new SqlVariable(typeof(void), null, partName, expr.SourceExpression), expr }, expr.SourceExpression ); } internal SqlExpression DATEADD(string partName, SqlExpression value, SqlExpression expr) { return DATEADD(partName, value, expr, expr.SourceExpression, false); } internal SqlExpression DATEADD(string partName, SqlExpression value, SqlExpression expr, Expression sourceExpression, bool asNullable) { Type returnType = asNullable ? typeof(DateTime?) : typeof(DateTime); return FunctionCall( returnType, "DATEADD", new SqlExpression[] { new SqlVariable(typeof(void), null, partName, sourceExpression), value, expr }, sourceExpression ); } internal SqlExpression DATETIMEOFFSETADD(string partName, SqlExpression value, SqlExpression expr) { return DATETIMEOFFSETADD(partName, value, expr, expr.SourceExpression, false); } internal SqlExpression DATETIMEOFFSETADD(string partName, SqlExpression value, SqlExpression expr, Expression sourceExpression, bool asNullable) { Type returnType = asNullable ? typeof(DateTimeOffset?) : typeof(DateTimeOffset); return FunctionCall( returnType, "DATEADD", new SqlExpression[] { new SqlVariable(typeof(void), null, partName, sourceExpression), value, expr }, sourceExpression ); } #endregion internal SqlExpression AddTimeSpan(SqlExpression dateTime, SqlExpression timeSpan) { return AddTimeSpan(dateTime, timeSpan, false); } internal SqlExpression AddTimeSpan(SqlExpression dateTime, SqlExpression timeSpan, bool asNullable) { Debug.Assert(IsSqlHighPrecisionDateTimeType(timeSpan)); SqlExpression ns = DATEPART("NANOSECOND", timeSpan); SqlExpression ms = DATEPART("MILLISECOND", timeSpan); SqlExpression ss = DATEPART("SECOND", timeSpan); SqlExpression mi = DATEPART("MINUTE", timeSpan); SqlExpression hh = DATEPART("HOUR", timeSpan); SqlExpression result = dateTime; if (IsSqlHighPrecisionDateTimeType(dateTime)) { result = DATEADD("NANOSECOND", ns, result, dateTime.SourceExpression, asNullable); } else { result = DATEADD("MILLISECOND", ms, result, dateTime.SourceExpression, asNullable); } result = DATEADD("SECOND", ss, result, dateTime.SourceExpression, asNullable); result = DATEADD("MINUTE", mi, result, dateTime.SourceExpression, asNullable); result = DATEADD("HOUR", hh, result, dateTime.SourceExpression, asNullable); if (IsSqlDateTimeOffsetType(dateTime)) return ConvertTo(typeof(DateTimeOffset), result); return result; } internal bool IsSqlDateTimeType(SqlExpression exp) { SqlDbType sqlDbType = ((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType; return (sqlDbType == SqlDbType.DateTime || sqlDbType == SqlDbType.SmallDateTime); } internal bool IsSqlDateType(SqlExpression exp) { return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.Date); } internal bool IsSqlTimeType(SqlExpression exp) { return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.Time); } internal bool IsSqlDateTimeOffsetType(SqlExpression exp) { return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.DateTimeOffset); } internal bool IsSqlHighPrecisionDateTimeType(SqlExpression exp) { SqlDbType sqlDbType = ((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType; return (sqlDbType == SqlDbType.Time || sqlDbType == SqlDbType.DateTime2 || sqlDbType == SqlDbType.DateTimeOffset); } ////// Return a node representing obj.GetType() /// internal SqlExpression ObjectType(SqlExpression obj, Expression sourceExpression) { return new SqlObjectType(obj, this.typeProvider.From(typeof(Type)), sourceExpression); } internal SqlExpression Value(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression) { if (typeof(Type).IsAssignableFrom(clrType)) { MetaType typeOf = this.model.GetMetaType((Type)value); return StaticType(typeOf, sourceExpression); } return new SqlValue(clrType, sqlType, value, isClientSpecified, sourceExpression); } ////// Return a node representing typeof(typeOf) /// internal SqlExpression StaticType(MetaType typeOf, Expression sourceExpression) { if (typeOf==null) throw Error.ArgumentNull("typeOf"); if(typeOf.InheritanceCode==null) { // If no inheritance is involved, then there's no discriminator to // make a discriminated type. In this case, just make a literal type. return new SqlValue(typeof(Type), this.typeProvider.From(typeof(Type)), typeOf.Type, false, sourceExpression); } Type type = typeOf.InheritanceCode.GetType(); SqlValue match = new SqlValue(type, this.typeProvider.From(type), typeOf.InheritanceCode, true, sourceExpression); return this.DiscriminatedType(match, typeOf); } internal SqlExpression DiscriminatedType(SqlExpression discriminator, MetaType targetType) { return new SqlDiscriminatedType(typeProvider.From(typeof(Type)), discriminator, targetType, discriminator.SourceExpression); } internal SqlTable Table(MetaTable table, MetaType rowType, Expression sourceExpression) { return new SqlTable(table, rowType, this.typeProvider.GetApplicationType((int)ConverterSpecialTypes.Row), sourceExpression); } internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression) { return Unary(nodeType, expression, expression.SourceExpression); } internal SqlRowNumber RowNumber(ListorderBy, Expression sourceExpression) { return new SqlRowNumber(typeof(long), typeProvider.From(typeof(long)), orderBy, sourceExpression); } internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, Expression sourceExpression) { return Unary(nodeType, expression, null, sourceExpression); } internal SqlUnary Unary(SqlNodeType nodeType, SqlExpression expression, MethodInfo method, Expression sourceExpression) { Type clrType = null; ProviderType sqlType = null; if (nodeType == SqlNodeType.Count) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else if (nodeType == SqlNodeType.LongCount) { clrType = typeof(long); sqlType = typeProvider.From(typeof(long)); } else if (nodeType == SqlNodeType.ClrLength) { clrType = typeof(int); sqlType = typeProvider.From(typeof(int)); } else { if (nodeType.IsPredicateUnaryOperator()) { clrType = typeof(bool); } else { clrType = expression.ClrType; } sqlType = typeProvider.PredictTypeForUnary(nodeType, expression.SqlType); } return new SqlUnary(nodeType, clrType, sqlType, expression, method, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlUnary UnaryCast(Type targetClrType, ProviderType targetSqlType, SqlExpression expression, Expression sourceExpression) { return new SqlUnary(SqlNodeType.Cast, targetClrType, targetSqlType, expression, null, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlUnary UnaryConvert(Type targetClrType, ProviderType targetSqlType, SqlExpression expression, Expression sourceExpression) { System.Diagnostics.Debug.Assert(!targetSqlType.IsRuntimeOnlyType, "Attempted coversion to a runtime type: from = " + expression.SqlType.ToQueryString() + "; to = " + targetSqlType.ToQueryString() + "; source = " + sourceExpression.ToString()); return new SqlUnary(SqlNodeType.Convert, targetClrType, targetSqlType, expression, null, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlUnary UnaryValueOf(SqlExpression expression, Expression sourceExpression) { Type valueType = TypeSystem.GetNonNullableType(expression.ClrType); return new SqlUnary(SqlNodeType.ValueOf, valueType, expression.SqlType, expression, null, sourceExpression); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right) { return Binary(nodeType, left, right, null, null); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method) { return Binary(nodeType, left, right, method, null); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, Type clrType) { return Binary(nodeType, left, right, null, clrType); } internal SqlBinary Binary(SqlNodeType nodeType, SqlExpression left, SqlExpression right, MethodInfo method, Type clrType) { ProviderType sqlType = null; if (nodeType.IsPredicateBinaryOperator()) { if (clrType == null) { clrType = typeof(bool); } sqlType = typeProvider.From(clrType); } else { ProviderType resultType = this.typeProvider.PredictTypeForBinary(nodeType, left.SqlType, right.SqlType); if (resultType == right.SqlType) { if (clrType == null) { clrType = right.ClrType; } sqlType = right.SqlType; } else if (resultType == left.SqlType) { if (clrType == null) { clrType = left.ClrType; } sqlType = left.SqlType; } else { sqlType = resultType; if (clrType == null) { clrType = resultType.GetClosestRuntimeType(); } } } return new SqlBinary(nodeType, clrType, sqlType, left, right, method); } internal SqlBetween Between(SqlExpression expr, SqlExpression start, SqlExpression end, Expression source) { return new SqlBetween(typeof(bool), typeProvider.From(typeof(bool)), expr, start, end, source); } internal SqlIn In(SqlExpression expr, IEnumerable values, Expression source) { return new SqlIn(typeof(bool), typeProvider.From(typeof(bool)), expr, values, source); } internal SqlLike Like(SqlExpression expr, SqlExpression pattern, SqlExpression escape, Expression source) { SqlLike like = new SqlLike(typeof(bool), typeProvider.From(typeof(bool)), expr, pattern, escape, source); return like; } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlSearchedCase SearchedCase(SqlWhen[] whens, SqlExpression @else, Expression sourceExpression) { return new SqlSearchedCase(whens[0].Value.ClrType, whens, @else, sourceExpression); } /// /// Construct either a SqlClientCase or a SqlSimpleCase depending on whether the individual cases /// are client-aided or not. /// [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlExpression Case(Type clrType, SqlExpression discriminator, Listmatches, List values, Expression sourceExpression) { if (values.Count == 0) { throw Error.EmptyCaseNotSupported(); } bool anyClient = false; foreach (SqlExpression value in values) { anyClient |= value.IsClientAidedExpression(); } if (anyClient) { List whens = new List (); for (int i = 0, c = matches.Count; i < c; ++i) { whens.Add(new SqlClientWhen(matches[i], values[i])); } return new SqlClientCase(clrType, discriminator, whens, sourceExpression); } else { List whens = new List (); for (int i = 0, c = matches.Count; i < c; ++i) { whens.Add(new SqlWhen(matches[i], values[i])); } return new SqlSimpleCase(clrType, discriminator, whens, sourceExpression); } } internal SqlExpression Parameter(object value, Expression source) { System.Diagnostics.Debug.Assert(value != null); Type type = value.GetType(); return Value(type, this.typeProvider.From(value), value, true, source); } internal SqlExpression ValueFromObject(object value, Expression sourceExpression) { return ValueFromObject(value, false, sourceExpression); } internal SqlExpression ValueFromObject(object value, bool isClientSpecified, Expression sourceExpression) { if (value == null) { System.Diagnostics.Debug.Assert(false); throw Error.ArgumentNull("value"); } Type clrType = value.GetType(); return ValueFromObject(value, clrType, isClientSpecified, sourceExpression); } // Override allowing the CLR type of the value to be specified explicitly. internal SqlExpression ValueFromObject(object value, Type clrType, bool isClientSpecified, Expression sourceExpression) { if (clrType == null) { throw Error.ArgumentNull("clrType"); } ProviderType sqlType = (value == null) ? this.typeProvider.From(clrType) : this.typeProvider.From(value); return Value(clrType, sqlType, value, isClientSpecified, sourceExpression); } public SqlExpression TypedLiteralNull(Type type, Expression sourceExpression) { return ValueFromObject(null, type, false, sourceExpression); } internal SqlMember Member(SqlExpression expr, MetaDataMember member) { return new SqlMember(member.Type, this.Default(member), expr, member.Member); } internal SqlMember Member(SqlExpression expr, MemberInfo member) { Type clrType = TypeSystem.GetMemberType(member); MetaType metaType = this.model.GetMetaType(member.DeclaringType); MetaDataMember metaDataMember = metaType.GetDataMember(member); if (metaType != null && metaDataMember != null) { return new SqlMember(clrType, this.Default(metaDataMember), expr, member); } else { return new SqlMember(clrType, this.Default(clrType), expr, member); } } internal SqlExpression TypeCase(Type clrType, MetaType rowType, SqlExpression discriminator, IEnumerable whens, Expression sourceExpression) { return new SqlTypeCase(clrType, typeProvider.From(clrType), rowType, discriminator, whens, sourceExpression); } internal SqlNew New(MetaType type, ConstructorInfo cons, IEnumerable args, IEnumerable argMembers, IEnumerable bindings, Expression sourceExpression) { SqlNew tb = new SqlNew(type, typeProvider.From(type.Type), cons, args, argMembers, bindings, sourceExpression); return tb; } internal SqlMethodCall MethodCall(MethodInfo method, SqlExpression obj, SqlExpression[] args, Expression sourceExpression) { return new SqlMethodCall(method.ReturnType, this.Default(method.ReturnType), method, obj, args, sourceExpression); } internal SqlMethodCall MethodCall(Type returnType, MethodInfo method, SqlExpression obj, SqlExpression[] args, Expression sourceExpression) { return new SqlMethodCall(returnType, this.Default(returnType), method, obj, args, sourceExpression); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlExprSet ExprSet(SqlExpression[] exprs, Expression sourceExpression) { return new SqlExprSet(exprs[0].ClrType, exprs, sourceExpression); } internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select) { return this.SubSelect(nt, select, null); } internal SqlSubSelect SubSelect(SqlNodeType nt, SqlSelect select, Type clrType) { ProviderType sqlType = null; switch (nt) { case SqlNodeType.ScalarSubSelect: case SqlNodeType.Element: clrType = select.Selection.ClrType; sqlType = select.Selection.SqlType; break; case SqlNodeType.Multiset: if (clrType == null) { clrType = typeof(List<>).MakeGenericType(select.Selection.ClrType); } sqlType = typeProvider.GetApplicationType((int)ConverterSpecialTypes.Table); break; case SqlNodeType.Exists: clrType = typeof(bool); sqlType = typeProvider.From(typeof(bool)); break; } return new SqlSubSelect(nt, clrType, sqlType, select); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlDoNotVisitExpression DoNotVisitExpression(SqlExpression expr) { return new SqlDoNotVisitExpression(expr); } internal SqlFunctionCall FunctionCall(Type clrType, string name, IEnumerable args, Expression source) { return new SqlFunctionCall(clrType, Default(clrType), name, args, source); } [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")] internal SqlFunctionCall FunctionCall(Type clrType, ProviderType sqlType, string name, IEnumerable args, Expression source) { return new SqlFunctionCall(clrType, sqlType, name, args, source); } internal SqlTableValuedFunctionCall TableValuedFunctionCall(MetaType rowType, Type clrType, string name, IEnumerable args, Expression source) { return new SqlTableValuedFunctionCall(rowType, clrType, Default(clrType), name, args, source); } internal ProviderType Default(Type clrType) { return typeProvider.From(clrType); } internal ProviderType Default(MetaDataMember member) { if(member == null) throw Error.ArgumentNull("member"); if (member.DbType != null) { return this.typeProvider.Parse(member.DbType); } else { return this.typeProvider.From(member.Type); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- HttpModulesSection.cs
- Nullable.cs
- XpsPackagingException.cs
- SymbolType.cs
- BitmapSizeOptions.cs
- AttributeProviderAttribute.cs
- StyleHelper.cs
- XmlnsDictionary.cs
- TypeUsage.cs
- XmlUtil.cs
- FormatException.cs
- PermissionListSet.cs
- UpDownBase.cs
- DictionaryKeyPropertyAttribute.cs
- BitmapEffect.cs
- PersistenceTypeAttribute.cs
- HMACSHA256.cs
- BitmapCacheBrush.cs
- DesignerSerializationOptionsAttribute.cs
- UriTemplateEquivalenceComparer.cs
- GregorianCalendarHelper.cs
- TableLayoutPanelDesigner.cs
- TextTrailingWordEllipsis.cs
- SafeEventLogWriteHandle.cs
- Animatable.cs
- MetadataItemCollectionFactory.cs
- SystemIPAddressInformation.cs
- PerformanceCounterPermissionAttribute.cs
- AttributeEmitter.cs
- Panel.cs
- DefaultTraceListener.cs
- BroadcastEventHelper.cs
- Pointer.cs
- Point.cs
- FrameworkPropertyMetadata.cs
- RegexCaptureCollection.cs
- ListViewUpdatedEventArgs.cs
- EntityViewGenerationConstants.cs
- TextDecorations.cs
- SpAudioStreamWrapper.cs
- StringOutput.cs
- ApplicationProxyInternal.cs
- OuterGlowBitmapEffect.cs
- XPathNavigatorReader.cs
- PropertyValueChangedEvent.cs
- XmlSerializationGeneratedCode.cs
- RawTextInputReport.cs
- Converter.cs
- SQLCharsStorage.cs
- RuntimeConfigLKG.cs
- PeerNode.cs
- RequiredFieldValidator.cs
- TrackingLocation.cs
- HttpContextServiceHost.cs
- HtmlWindow.cs
- LineGeometry.cs
- Lease.cs
- EntitySqlQueryBuilder.cs
- RegisteredArrayDeclaration.cs
- SyncMethodInvoker.cs
- ExpressionBinding.cs
- ComponentCollection.cs
- AnnouncementInnerClientCD1.cs
- BezierSegment.cs
- WorkflowDesignerMessageFilter.cs
- DataTableTypeConverter.cs
- serverconfig.cs
- EntityParameterCollection.cs
- Form.cs
- GlyphCollection.cs
- UndoManager.cs
- TypedColumnHandler.cs
- PartialCachingAttribute.cs
- GridViewSelectEventArgs.cs
- SQLDateTimeStorage.cs
- MessagePartDescriptionCollection.cs
- SafeThreadHandle.cs
- SByteStorage.cs
- EntityContainer.cs
- DescendentsWalker.cs
- SoapTypeAttribute.cs
- DbSourceCommand.cs
- QuaternionAnimation.cs
- ConfigurationElementCollection.cs
- OleDbCommandBuilder.cs
- StylusPointProperties.cs
- basecomparevalidator.cs
- ZeroOpNode.cs
- TextViewSelectionProcessor.cs
- ListViewEditEventArgs.cs
- AggregateNode.cs
- ServiceDesigner.cs
- ObjectManager.cs
- TableCellCollection.cs
- Int32CollectionConverter.cs
- EventLogPermissionEntry.cs
- AssemblyInfo.cs
- Transactions.cs
- VectorAnimationBase.cs
- UnsafeNativeMethods.cs