/mcs/class/referencesource/System.Data.Linq/SqlClient/Common/SqlFactory.cs
C# | 612 lines | 483 code | 92 blank | 37 comment | 101 complexity | c9ebfd3d63cd761b2dd19c9490bb8de2 MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, Unlicense, Apache-2.0
- 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;
- /// <summary>
- /// Factory class produces SqlNodes. Smarts about type system mappings should go
- /// here and not in the individual SqlNodes.
- /// </summary>
- 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 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));
- }
- /// <summary>
- /// Non-internal string length. This should only be used when translating an explicit call by the
- /// user to String.Length.
- /// </summary>
- internal SqlExpression LEN(SqlExpression expr) {
- return FunctionCall(typeof(int), "LEN", new SqlExpression[] { expr }, expr.SourceExpression);
- }
- /// <summary>
- /// 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.
- /// </summary>
- internal SqlExpression DATALENGTH(SqlExpression expr) {
- return FunctionCall(typeof(int), "DATALENGTH", new SqlExpression[] { expr }, expr.SourceExpression);
- }
- /// <summary>
- /// 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.
- /// </summary>
- 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 static bool IsSqlDateTimeType(SqlExpression exp) {
- SqlDbType sqlDbType = ((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType;
- return (sqlDbType == SqlDbType.DateTime || sqlDbType == SqlDbType.SmallDateTime);
- }
- internal static bool IsSqlDateType(SqlExpression exp) {
- return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.Date);
- }
- internal static bool IsSqlTimeType(SqlExpression exp) {
- return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.Time);
- }
- internal static bool IsSqlDateTimeOffsetType(SqlExpression exp) {
- return (((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType == SqlDbType.DateTimeOffset);
- }
- internal static bool IsSqlHighPrecisionDateTimeType(SqlExpression exp) {
- SqlDbType sqlDbType = ((SqlTypeSystem.SqlType)(exp.SqlType)).SqlDbType;
- return (sqlDbType == SqlDbType.Time || sqlDbType == SqlDbType.DateTime2 || sqlDbType == SqlDbType.DateTimeOffset);
- }
- internal SqlExpression Value(Type clrType, ProviderType sqlType, object value, bool isClientSpecified, Expression sourceExpression) {
- if (typeof(Type).IsAssignableFrom(clrType) && value != null) {
- MetaType typeOf = this.model.GetMetaType((Type)value);
- return StaticType(typeOf, sourceExpression);
- }
- return new SqlValue(clrType, sqlType, value, isClientSpecified, sourceExpression);
- }
- /// <summary>
- /// Return a node representing typeof(typeOf)
- /// </summary>
- 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(List<SqlOrderExpression> orderBy, 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()) {
- // DevDiv 201730 - Do not ignore nullability of bool type
- clrType = expression.ClrType.Equals(typeof(bool?)) ? typeof(bool?) : 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 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<SqlExpression> 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);
- }
- /// <summary>
- /// Construct either a SqlClientCase or a SqlSimpleCase depending on whether the individual cases
- /// are client-aided or not.
- /// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
- internal SqlExpression Case(Type clrType, SqlExpression discriminator, List<SqlExpression> matches, List<SqlExpression> values, Expression sourceExpression) {
- if (values.Count == 0) {
- throw Error.EmptyCaseNotSupported();
- }
- bool anyClient = false;
- foreach (SqlExpression value in values) {
- anyClient |= value.IsClientAidedExpression();
- }
- if (anyClient) {
- List<SqlClientWhen> whens = new List<SqlClientWhen>();
- 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<SqlWhen> whens = new List<SqlWhen>();
- 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<SqlTypeCaseWhen> whens, Expression sourceExpression) {
- return new SqlTypeCase(clrType, typeProvider.From(clrType), rowType, discriminator, whens, sourceExpression);
- }
- internal SqlNew New(MetaType type, ConstructorInfo cons, IEnumerable<SqlExpression> args, IEnumerable<MemberInfo> argMembers, IEnumerable<SqlMemberAssign> 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<SqlExpression> 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<SqlExpression> args, Expression source) {
- return new SqlFunctionCall(clrType, sqlType, name, args, source);
- }
- internal SqlTableValuedFunctionCall TableValuedFunctionCall(MetaType rowType, Type clrType, string name, IEnumerable<SqlExpression> 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);
- }
- }
- internal SqlJoin MakeJoin(SqlJoinType joinType, SqlSource location, SqlAlias alias, SqlExpression condition, Expression source) {
- // if the new item is on the right side of some outer join then fixup the projection to reflect that it can possibly be null
- if (joinType == SqlJoinType.LeftOuter) {
- SqlSelect sel = alias.Node as SqlSelect;
- if (sel != null && sel.Selection != null && sel.Selection.NodeType != SqlNodeType.OptionalValue) {
- // replace selection w/ optional + outer-joined-value
- sel.Selection = new SqlOptionalValue(
- new SqlColumn(
- "test",
- this.Unary(SqlNodeType.OuterJoinedValue,
- this.Value(typeof(int?), this.typeProvider.From(typeof(int)), 1, false, source))
- ),
- sel.Selection
- );
- }
- }
- return new SqlJoin(joinType, location, alias, condition, source);
- }
- }
- }