diff Source/Data/Linq/Builder/IntersectBuilder.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/Data/Linq/Builder/IntersectBuilder.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,56 @@
+using System;
+using System.Linq.Expressions;
+
+namespace BLToolkit.Data.Linq.Builder
+{
+	using BLToolkit.Linq;
+	using Data.Sql;
+
+	class IntersectBuilder : MethodCallBuilder
+	{
+		protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
+		{
+			return methodCall.Arguments.Count == 2 && methodCall.IsQueryable("Except", "Intersect");
+		}
+
+		protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
+		{
+			var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
+			var query    = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery()));
+			var except   = query.SqlQuery;
+
+			sequence = new SubQueryContext(sequence);
+
+			var sql = sequence.SqlQuery;
+
+			except.ParentSql = sql;
+
+			if (methodCall.Method.Name == "Except")
+				sql.Where.Not.Exists(except);
+			else
+				sql.Where.Exists(except);
+
+			var keys1 = sequence.ConvertToSql(null, 0, ConvertFlags.Key);
+			var keys2 = query.   ConvertToSql(null, 0, ConvertFlags.Key);
+
+			if (keys1.Length != keys2.Length)
+				throw new InvalidOperationException();
+
+			for (var i = 0; i < keys1.Length; i++)
+			{
+				except.Where
+					.Expr(keys1[i].Sql)
+					.Equal
+					.Expr(keys2[i].Sql);
+			}
+
+			return sequence;
+		}
+
+		protected override SequenceConvertInfo Convert(
+			ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
+		{
+			return null;
+		}
+	}
+}