Mercurial > pub > bltoolkit
comparison Source/Data/Linq/Builder/CountBuilder.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.Linq.Expressions; | |
3 | |
4 namespace BLToolkit.Data.Linq.Builder | |
5 { | |
6 using BLToolkit.Linq; | |
7 using Data.Sql; | |
8 | |
9 class CountBuilder : MethodCallBuilder | |
10 { | |
11 public static string[] MethodNames = new[] { "Count", "LongCount" }; | |
12 | |
13 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
14 { | |
15 return methodCall.IsQueryable(MethodNames); | |
16 } | |
17 | |
18 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
19 { | |
20 var returnType = methodCall.Method.ReturnType; | |
21 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); | |
22 | |
23 if (sequence.SqlQuery != buildInfo.SqlQuery) | |
24 { | |
25 if (sequence is JoinBuilder.GroupJoinSubQueryContext) | |
26 { | |
27 var ctx = new CountContext(buildInfo.Parent, sequence, returnType) | |
28 { | |
29 SqlQuery = ((JoinBuilder.GroupJoinSubQueryContext)sequence).GetCounter(methodCall) | |
30 }; | |
31 | |
32 ctx.Sql = ctx.SqlQuery; | |
33 ctx.FieldIndex = ctx.SqlQuery.Select.Add(SqlFunction.CreateCount(returnType, ctx.SqlQuery), "cnt"); | |
34 | |
35 return ctx; | |
36 } | |
37 | |
38 if (sequence is GroupByBuilder.GroupByContext) | |
39 { | |
40 return new CountContext(buildInfo.Parent, sequence, returnType) | |
41 { | |
42 Sql = SqlFunction.CreateCount(returnType, sequence.SqlQuery), | |
43 FieldIndex = -1 | |
44 }; | |
45 } | |
46 } | |
47 | |
48 if (sequence.SqlQuery.Select.IsDistinct || | |
49 sequence.SqlQuery.Select.TakeValue != null || | |
50 sequence.SqlQuery.Select.SkipValue != null || | |
51 !sequence.SqlQuery.GroupBy.IsEmpty) | |
52 { | |
53 sequence.ConvertToIndex(null, 0, ConvertFlags.Key); | |
54 sequence = new SubQueryContext(sequence); | |
55 } | |
56 | |
57 if (sequence.SqlQuery.OrderBy.Items.Count > 0) | |
58 { | |
59 if (sequence.SqlQuery.Select.TakeValue == null && sequence.SqlQuery.Select.SkipValue == null) | |
60 sequence.SqlQuery.OrderBy.Items.Clear(); | |
61 else | |
62 sequence = new SubQueryContext(sequence); | |
63 } | |
64 | |
65 var context = new CountContext(buildInfo.Parent, sequence, returnType); | |
66 | |
67 context.Sql = context.SqlQuery; | |
68 context.FieldIndex = context.SqlQuery.Select.Add(SqlFunction.CreateCount(returnType, context.SqlQuery), "cnt"); | |
69 | |
70 return context; | |
71 } | |
72 | |
73 protected override SequenceConvertInfo Convert( | |
74 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) | |
75 { | |
76 return null; | |
77 } | |
78 | |
79 internal class CountContext : SequenceContextBase | |
80 { | |
81 public CountContext(IBuildContext parent, IBuildContext sequence, Type returnType) | |
82 : base(parent, sequence, null) | |
83 { | |
84 _returnType = returnType; | |
85 } | |
86 | |
87 readonly Type _returnType; | |
88 private SqlInfo[] _index; | |
89 | |
90 public int FieldIndex; | |
91 public ISqlExpression Sql; | |
92 | |
93 public override void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter) | |
94 { | |
95 var expr = Builder.BuildSql(_returnType, FieldIndex); | |
96 var mapper = Builder.BuildMapper<object>(expr); | |
97 | |
98 query.SetElementQuery(mapper.Compile()); | |
99 } | |
100 | |
101 public override Expression BuildExpression(Expression expression, int level) | |
102 { | |
103 return Builder.BuildSql(_returnType, ConvertToIndex(expression, level, ConvertFlags.Field)[0].Index); | |
104 } | |
105 | |
106 public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags) | |
107 { | |
108 switch (flags) | |
109 { | |
110 case ConvertFlags.Field : return new[] { new SqlInfo { Query = Parent.SqlQuery, Sql = Sql } }; | |
111 } | |
112 | |
113 throw new InvalidOperationException(); | |
114 } | |
115 | |
116 public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags) | |
117 { | |
118 switch (flags) | |
119 { | |
120 case ConvertFlags.Field : | |
121 return _index ?? (_index = new[] | |
122 { | |
123 new SqlInfo { Query = Parent.SqlQuery, Index = Parent.SqlQuery.Select.Add(Sql), Sql = Sql, } | |
124 }); | |
125 } | |
126 | |
127 throw new InvalidOperationException(); | |
128 } | |
129 | |
130 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag) | |
131 { | |
132 switch (requestFlag) | |
133 { | |
134 case RequestFor.Expression : return IsExpressionResult.True; | |
135 } | |
136 | |
137 return IsExpressionResult.False; | |
138 } | |
139 | |
140 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo) | |
141 { | |
142 return Sequence.GetContext(expression, level, buildInfo); | |
143 } | |
144 | |
145 public override ISqlExpression GetSubQuery(IBuildContext context) | |
146 { | |
147 var query = context.SqlQuery; | |
148 | |
149 if (query == SqlQuery) | |
150 { | |
151 var col = query.Select.Columns[query.Select.Columns.Count - 1]; | |
152 | |
153 query.Select.Columns.RemoveAt(query.Select.Columns.Count - 1); | |
154 | |
155 return col.Expression; | |
156 } | |
157 | |
158 return null; | |
159 } | |
160 } | |
161 } | |
162 } |