Beispiel #1
0
 internal virtual SqlExpression VisitDiscriminatorOf(SqlDiscriminatorOf dof) {
     dof.Object = this.VisitExpression(dof.Object);
     return dof;
 }
		internal override SqlExpression VisitDiscriminatorOf(SqlDiscriminatorOf dof)
		{
			if(_isDebugMode)
			{
				_commandStringBuilder.Append("DISCO(");
			}
			base.VisitDiscriminatorOf(dof);
			if(_isDebugMode)
			{
				_commandStringBuilder.Append(")");
			}
			return dof;
		}
		/// <summary>
		/// Evaluate the object and extract its discriminator.
		/// </summary>
		internal override SqlExpression VisitDiscriminatorOf(SqlDiscriminatorOf dof) {
			SqlExpression obj = this.FetchExpression(dof.Object); // FetchExpression removes Link.
			// It's valid to unwrap optional and outer-join values here because type case already handles
			// NULL values correctly.
			while (obj.NodeType == SqlNodeType.OptionalValue
				   || obj.NodeType == SqlNodeType.OuterJoinedValue) {
					   if (obj.NodeType == SqlNodeType.OptionalValue) {
						   obj = ((SqlOptionalValue)obj).Value;
					   }
					   else {
						   obj = ((SqlUnary)obj).Operand;
					   }
				   }
			if (obj.NodeType == SqlNodeType.TypeCase) {
				SqlTypeCase tc = (SqlTypeCase)obj;
				// Rewrite a case of discriminators. We can't just reduce to 
				// discriminator (yet) because the ELSE clause needs to be considered.
				// Later in the conversion there is an optimization that will turn the CASE
				// into a simple combination of ANDs and ORs.
				// Also, cannot reduce to IsNull(Discriminator,DefaultDiscriminator) because
				// other unexpected values besides NULL need to be handled.
				List<SqlExpression> matches = new List<SqlExpression>();
				List<SqlExpression> values = new List<SqlExpression>();
				MetaType defaultType = tc.RowType.InheritanceDefault;
				object discriminator = defaultType.InheritanceCode;
				foreach (SqlTypeCaseWhen when in tc.Whens) {
					matches.Add(when.Match);
					if (when.Match == null) {
						SqlExpression @default = sql.Value(discriminator.GetType(), tc.Whens[0].Match.SqlType, defaultType.InheritanceCode, true, tc.SourceExpression);
						values.Add(@default);
					}
					else {
						// Must duplicate so that columnizer doesn't nominate the match as a value.
						values.Add(sql.Value(discriminator.GetType(), when.Match.SqlType, ((SqlValue)when.Match).Value, true, tc.SourceExpression));
					}
				}
				return sql.Case(tc.Discriminator.ClrType, tc.Discriminator, matches, values, tc.SourceExpression);
			} else {
				var mt = this.model.GetMetaType(obj.ClrType).InheritanceRoot;
				if (mt.HasInheritance) {
					return this.VisitExpression(sql.Member(dof.Object, mt.Discriminator.Member));
				}
			}
			return sql.TypedLiteralNull(dof.ClrType, dof.SourceExpression);
		}
		internal override SqlExpression VisitDiscriminatorOf(SqlDiscriminatorOf dof)
		{
			return new SqlDiscriminatorOf(this.VisitExpression(dof.Object), dof.ClrType, dof.SqlType, dof.SourceExpression);
		}
			internal override SqlExpression VisitMethodCall(SqlMethodCall mc)
			{
				mc.Object = this.VisitExpression(mc.Object);
				for(int i = 0, n = mc.Arguments.Count; i < n; i++)
				{
					mc.Arguments[i] = this.VisitExpression(mc.Arguments[i]);
				}
				if(mc.Method.IsStatic)
				{
					if(mc.Method.Name == "Equals" && mc.Arguments.Count == 2)
					{
						return sql.Binary(SqlNodeType.EQ2V, mc.Arguments[0], mc.Arguments[1], mc.Method);
					}
					if(mc.Method.DeclaringType == typeof(string) && mc.Method.Name == "Concat")
					{
						SqlClientArray arr = mc.Arguments[0] as SqlClientArray;
						List<SqlExpression> exprs = null;
						if(arr != null)
						{
							exprs = arr.Expressions;
						}
						else
						{
							exprs = mc.Arguments;
						}
						if(exprs.Count == 0)
						{
							return sql.ValueFromObject("", false, mc.SourceExpression);
						}
						SqlExpression sum;
						if(exprs[0].SqlType.IsString || exprs[0].SqlType.IsChar)
						{
							sum = exprs[0];
						}
						else
						{
							sum = sql.ConvertTo(typeof(string), exprs[0]);
						}
						for(int i = 1; i < exprs.Count; i++)
						{
							if(exprs[i].SqlType.IsString || exprs[i].SqlType.IsChar)
							{
								sum = sql.Concat(sum, exprs[i]);
							}
							else
							{
								sum = sql.Concat(sum, sql.ConvertTo(typeof(string), exprs[i]));
							}
						}
						return sum;
					}
					if(IsVbIIF(mc))
					{
						return TranslateVbIIF(mc);
					}
					switch(mc.Method.Name)
					{
						case "op_Equality":
							return sql.Binary(SqlNodeType.EQ, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_Inequality":
							return sql.Binary(SqlNodeType.NE, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_LessThan":
							return sql.Binary(SqlNodeType.LT, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_LessThanOrEqual":
							return sql.Binary(SqlNodeType.LE, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_GreaterThan":
							return sql.Binary(SqlNodeType.GT, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_GreaterThanOrEqual":
							return sql.Binary(SqlNodeType.GE, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_Multiply":
							return sql.Binary(SqlNodeType.Mul, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_Division":
							return sql.Binary(SqlNodeType.Div, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_Subtraction":
							return sql.Binary(SqlNodeType.Sub, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_Addition":
							return sql.Binary(SqlNodeType.Add, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_Modulus":
							return sql.Binary(SqlNodeType.Mod, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_BitwiseAnd":
							return sql.Binary(SqlNodeType.BitAnd, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_BitwiseOr":
							return sql.Binary(SqlNodeType.BitOr, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_ExclusiveOr":
							return sql.Binary(SqlNodeType.BitXor, mc.Arguments[0], mc.Arguments[1], mc.Method, mc.ClrType);
						case "op_UnaryNegation":
							return sql.Unary(SqlNodeType.Negate, mc.Arguments[0], mc.Method, mc.SourceExpression);
						case "op_OnesComplement":
							return sql.Unary(SqlNodeType.BitNot, mc.Arguments[0], mc.Method, mc.SourceExpression);
						case "op_False":
							return sql.Unary(SqlNodeType.Not, mc.Arguments[0], mc.Method, mc.SourceExpression);
					}
				}
				else
				{
					if(mc.Method.Name == "Equals" && mc.Arguments.Count == 1)
					{
						return sql.Binary(SqlNodeType.EQ, mc.Object, mc.Arguments[0]);
					}
					if(mc.Method.Name == "GetType" && mc.Arguments.Count == 0)
					{
						MetaType mt = TypeSource.GetSourceMetaType(mc.Object, this.model);
						if(mt.HasInheritance)
						{
							Type discriminatorType = mt.Discriminator.Type;
							SqlDiscriminatorOf discriminatorOf = new SqlDiscriminatorOf(mc.Object, discriminatorType, this.sql.TypeProvider.From(discriminatorType), mc.SourceExpression);
							return this.VisitExpression(sql.DiscriminatedType(discriminatorOf, mt));
						}
						return this.VisitExpression(sql.StaticType(mt, mc.SourceExpression));
					}
				}
				return mc;
			}