@@ -24,8 +24,7 @@ partial class SqlCompiler
2424 protected SqlProvider CreateProvider ( SqlSelect statement ,
2525 CompilableProvider origin , params ExecutableProvider [ ] sources )
2626 {
27- var extraBindings = ( IEnumerable < QueryParameterBinding > ) null ;
28- return CreateProvider ( statement , extraBindings , origin , sources ) ;
27+ return CreateProvider ( statement , ( IEnumerable < QueryParameterBinding > ) null , origin , sources ) ;
2928 }
3029
3130 protected SqlProvider CreateProvider ( SqlSelect statement , QueryParameterBinding extraBinding ,
@@ -41,20 +40,23 @@ protected SqlProvider CreateProvider(SqlSelect statement, IEnumerable<QueryParam
4140 var sqlSources = sources . OfType < SqlProvider > ( ) ;
4241
4342 var parameterBindings = sqlSources . SelectMany ( p => p . Request . ParameterBindings ) ;
44- if ( extraBindings != null )
43+ if ( extraBindings != null ) {
4544 parameterBindings = parameterBindings . Concat ( extraBindings ) ;
45+ }
4646
47- bool allowBatching = sqlSources
47+ var allowBatching = sqlSources
4848 . Aggregate ( true , ( current , provider ) =>
4949 current && provider . Request . CheckOptions ( QueryRequestOptions . AllowOptimization ) ) ;
5050 var tupleDescriptor = origin . Header . TupleDescriptor ;
5151
5252 var options = QueryRequestOptions . Empty ;
53- if ( allowBatching )
53+ if ( allowBatching ) {
5454 options |= QueryRequestOptions . AllowOptimization ;
55+ }
5556
56- if ( statement . Columns . Count < origin . Header . TupleDescriptor . Count )
57+ if ( statement . Columns . Count < origin . Header . TupleDescriptor . Count ) {
5758 tupleDescriptor = origin . Header . TupleDescriptor . Head ( statement . Columns . Count ) ;
59+ }
5860
5961 var request = CreateQueryRequest ( Driver , statement , parameterBindings , tupleDescriptor , options ) ;
6062
@@ -121,11 +123,15 @@ protected SqlExpression ExtractColumnExpression(SqlColumn column)
121123 }
122124 }
123125 }
124- else
126+ else {
125127 expression = column ;
128+ }
129+
126130 var columnRef = expression as SqlColumnRef ;
127- if ( ! columnRef . IsNullReference ( ) )
131+ if ( ! columnRef . IsNullReference ( ) ) {
128132 expression = columnRef . SqlColumn ;
133+ }
134+
129135 return expression ;
130136 }
131137
@@ -139,8 +145,9 @@ protected void AddInlinableColumn(IInlinableProvider provider, Column column,
139145 stubColumnMap . Add ( columnStub , columnExpression ) ;
140146 resultQuery . Columns . Add ( columnStub ) ;
141147 }
142- else
148+ else {
143149 resultQuery . Columns . Add ( columnRef ) ;
150+ }
144151 }
145152
146153 protected SqlExpression GetBooleanColumnExpression ( SqlExpression originalExpression )
@@ -150,187 +157,212 @@ protected SqlExpression GetBooleanColumnExpression(SqlExpression originalExpress
150157 : booleanExpressionConverter . BooleanToInt ( originalExpression ) ;
151158 }
152159
153- protected QueryRequest CreateQueryRequest ( StorageDriver driver , SqlSelect statement , IEnumerable < QueryParameterBinding > parameterBindings ,
160+ protected QueryRequest CreateQueryRequest ( StorageDriver driver , SqlSelect statement ,
161+ IEnumerable < QueryParameterBinding > parameterBindings ,
154162 TupleDescriptor tupleDescriptor , QueryRequestOptions options )
155163 {
156- if ( Handlers . Domain . Configuration . ShareStorageSchemaOverNodes )
164+ if ( Handlers . Domain . Configuration . ShareStorageSchemaOverNodes ) {
157165 return new QueryRequest ( driver , statement , parameterBindings , tupleDescriptor , options , NodeConfiguration ) ;
166+ }
167+
158168 return new QueryRequest ( driver , statement , parameterBindings , tupleDescriptor , options ) ;
159169 }
160170
161171 private static bool IsCalculatedColumn ( SqlColumn column )
162172 {
163- if ( column is SqlUserColumn )
173+ if ( column is SqlUserColumn ) {
164174 return true ;
175+ }
165176 var cRef = column as SqlColumnRef ;
166- if ( ! ReferenceEquals ( null , cRef ) )
167- return cRef . SqlColumn is SqlUserColumn ;
168- return false ;
177+ return cRef ? . SqlColumn is SqlUserColumn ;
169178 }
170179
171180 private static bool IsColumnStub ( SqlColumn column )
172181 {
173- if ( column is SqlColumnStub )
182+ if ( column is SqlColumnStub ) {
174183 return true ;
184+ }
185+
175186 var cRef = column as SqlColumnRef ;
176- if ( ! ReferenceEquals ( null , cRef ) )
177- return cRef . SqlColumn is SqlColumnStub ;
178- return false ;
187+ return cRef ? . SqlColumn is SqlColumnStub ;
179188 }
180189
181190 private static SqlColumnStub ExtractColumnStub ( SqlColumn column )
182191 {
183- var columnStub = column as SqlColumnStub ;
184- if ( ! ReferenceEquals ( null , columnStub ) )
185- return columnStub ;
186- var columnRef = column as SqlColumnRef ;
187- if ( ! ReferenceEquals ( null , columnRef ) )
188- return ( SqlColumnStub ) columnRef . SqlColumn ;
189- return ( SqlColumnStub ) column ;
192+ switch ( column ) {
193+ case SqlColumnStub columnStub :
194+ return columnStub ;
195+ case SqlColumnRef columnRef :
196+ return ( SqlColumnStub ) columnRef . SqlColumn ;
197+ default :
198+ return ( SqlColumnStub ) column ;
199+ }
190200 }
191201
192202 private static SqlUserColumn ExtractUserColumn ( SqlColumn column )
193203 {
194- var userColumn = column as SqlUserColumn ;
195- if ( ! ReferenceEquals ( null , userColumn ) )
196- return userColumn ;
197- var columnRef = column as SqlColumnRef ;
198- if ( ! ReferenceEquals ( null , columnRef ) )
199- return ( SqlUserColumn ) columnRef . SqlColumn ;
200- return ( SqlUserColumn ) column ;
204+ switch ( column ) {
205+ case SqlUserColumn userColumn :
206+ return userColumn ;
207+ case SqlColumnRef columnRef :
208+ return ( SqlUserColumn ) columnRef . SqlColumn ;
209+ default :
210+ return ( SqlUserColumn ) column ;
211+ }
201212 }
202213
203214 private static bool ShouldUseQueryReference ( CompilableProvider origin , SqlProvider compiledSource )
204215 {
205216 var sourceSelect = compiledSource . Request . Statement ;
206- if ( sourceSelect . From == null )
217+ if ( sourceSelect . From == null ) {
207218 return false ;
219+ }
208220
209- var calculatedColumnIndexes = sourceSelect . Columns
210- . Select ( ( c , i ) => IsCalculatedColumn ( c ) ? i : - 1 )
211- . Where ( i => i >= 0 )
212- . ToList ( ) ;
221+ var columnIndex = 0 ;
222+ var rowNumberIsUsed = false ;
223+ var calculatedColumnIndexes = new List < int > ( 8 ) ;
224+ foreach ( var column in sourceSelect . Columns ) {
225+ if ( IsCalculatedColumn ( column ) ) {
226+ calculatedColumnIndexes . Add ( columnIndex ) ;
227+ rowNumberIsUsed = rowNumberIsUsed || ExtractUserColumn ( column ) . Expression is SqlRowNumber ;
228+ }
229+ columnIndex ++ ;
230+ }
213231 var containsCalculatedColumns = calculatedColumnIndexes . Count > 0 ;
214- var rowNumberIsUsed = calculatedColumnIndexes . Count > 0 && sourceSelect . Columns
215- . Select ( ( c , i ) => new { c , i } )
216- . Any ( a => calculatedColumnIndexes . Contains ( a . i ) && ExtractUserColumn ( a . c ) . Expression is SqlRowNumber ) ;
217- var pagingIsUsed = ! sourceSelect . Limit . IsNullReference ( ) || ! sourceSelect . Offset . IsNullReference ( ) || rowNumberIsUsed ;
232+ var pagingIsUsed = rowNumberIsUsed
233+ || ! sourceSelect . Limit . IsNullReference ( ) || ! sourceSelect . Offset . IsNullReference ( ) ;
218234 var groupByIsUsed = sourceSelect . GroupBy . Count > 0 ;
219235 var distinctIsUsed = sourceSelect . Distinct ;
220236 var filterIsUsed = ! sourceSelect . Where . IsNullReference ( ) ;
221237
222- if ( origin . Type == ProviderType . Filter ) {
223- var filterProvider = ( FilterProvider ) origin ;
224- var usedColumnIndexes = new TupleAccessGatherer ( ) . Gather ( filterProvider . Predicate . Body ) ;
225- return pagingIsUsed || usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) ;
226- }
227-
228- if ( origin . Type == ProviderType . Select )
229- return distinctIsUsed ;
230-
231- if ( origin . Type == ProviderType . RowNumber ) {
232- var usedColumnIndexes = origin . Header . Order . Select ( o => o . Key ) ;
233- return pagingIsUsed || groupByIsUsed || distinctIsUsed || usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) ;
234- }
235-
236- if ( origin . Type == ProviderType . Calculate ) {
237- var calculateProvider = ( CalculateProvider ) origin ;
238- var columnGatherer = new TupleAccessGatherer ( ) ;
239- var usedColumnIndexes = new List < int > ( ) ;
240- foreach ( var column in calculateProvider . CalculatedColumns )
241- usedColumnIndexes . AddRange (
242- columnGatherer . Gather ( column . Expression . Body , column . Expression . Parameters [ 0 ] ) ) ;
243-
244- return usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) ;
245- }
238+ switch ( origin . Type ) {
239+ case ProviderType . Filter : {
240+ var filterProvider = ( FilterProvider ) origin ;
241+ var usedColumnIndexes = new TupleAccessGatherer ( ) . Gather ( filterProvider . Predicate . Body ) ;
242+ return pagingIsUsed || usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) ;
243+ }
244+ case ProviderType . Select :
245+ return distinctIsUsed ;
246+ case ProviderType . RowNumber : {
247+ var usedColumnIndexes = origin . Header . Order . Select ( o => o . Key ) ;
248+ return pagingIsUsed || groupByIsUsed || distinctIsUsed
249+ || usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) ;
250+ }
251+ case ProviderType . Calculate : {
252+ var calculateProvider = ( CalculateProvider ) origin ;
253+ var columnGatherer = new TupleAccessGatherer ( ) ;
254+ var usedColumnIndexes = new List < int > ( ) ;
255+ foreach ( var column in calculateProvider . CalculatedColumns ) {
256+ usedColumnIndexes . AddRange (
257+ columnGatherer . Gather ( column . Expression . Body , column . Expression . Parameters [ 0 ] ) ) ;
258+ }
246259
247- if ( origin . Type == ProviderType . Aggregate ) {
248- var aggregateProvider = ( AggregateProvider ) origin ;
249- var columnGatherer = new TupleAccessGatherer ( ) ;
250- var usedColumnIndexes = ( aggregateProvider . AggregateColumns ?? Enumerable . Empty < AggregateColumn > ( ) )
251- . Select ( ac => ac . SourceIndex )
252- . Concat ( aggregateProvider . GroupColumnIndexes )
253- . ToList ( ) ;
260+ return usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) ;
261+ }
262+ case ProviderType . Aggregate : {
263+ var aggregateProvider = ( AggregateProvider ) origin ;
264+ var usedColumnIndexes = ( aggregateProvider . AggregateColumns ?? Enumerable . Empty < AggregateColumn > ( ) )
265+ . Select ( ac => ac . SourceIndex )
266+ . Concat ( aggregateProvider . GroupColumnIndexes ) ;
267+
268+ return pagingIsUsed || distinctIsUsed || groupByIsUsed
269+ || usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) ;
270+ }
271+ case ProviderType . Take :
272+ case ProviderType . Skip :
273+ case ProviderType . Paging : {
274+ return distinctIsUsed || pagingIsUsed || groupByIsUsed
275+ || ( origin . Sources [ 0 ] is SortProvider sortProvider &&
276+ sortProvider . Header . Order . Select ( order => order . Key ) . Any ( calculatedColumnIndexes . Contains ) ) ;
277+ }
278+ case ProviderType . Apply :
279+ return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed ;
280+ case ProviderType . Join : {
281+ var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed ;
282+ if ( shouldUseQueryReference ) {
283+ return true ;
284+ }
254285
255- return usedColumnIndexes . Any ( calculatedColumnIndexes . Contains ) || pagingIsUsed || distinctIsUsed || groupByIsUsed ;
256- }
286+ var joinProvider = ( JoinProvider ) origin ;
287+ var isRight = joinProvider . Right == compiledSource . Origin ;
288+ var indexes = joinProvider . EqualIndexes . Select ( p => isRight ? p . Second : p . First ) ;
289+ return ( joinProvider . JoinType == JoinType . LeftOuter && filterIsUsed && isRight )
290+ || ( containsCalculatedColumns && indexes . Any ( calculatedColumnIndexes . Contains ) ) ;
291+ }
292+ case ProviderType . PredicateJoin : {
293+ var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed ;
294+ if ( shouldUseQueryReference ) {
295+ return true ;
296+ }
257297
258- if ( origin . Type . In ( ProviderType . Take , ProviderType . Skip , ProviderType . Paging ) ) {
259- var sortProvider = origin . Sources [ 0 ] as SortProvider ;
260- var orderingOverCalculatedColumn = sortProvider != null &&
261- sortProvider . Header . Order
298+ var joinProvider = ( PredicateJoinProvider ) origin ;
299+ var isRight = joinProvider . Right == compiledSource . Origin ;
300+ var indexes = new TupleAccessGatherer ( )
301+ . Gather ( joinProvider . Predicate . Body , joinProvider . Predicate . Parameters [ isRight ? 1 : 0 ] ) ;
302+ return ( joinProvider . JoinType == JoinType . LeftOuter && filterIsUsed && isRight )
303+ || ( containsCalculatedColumns && indexes . Any ( calculatedColumnIndexes . Contains ) ) ;
304+ }
305+ case ProviderType . Sort when distinctIsUsed :
306+ return true ;
307+ case ProviderType . Sort : {
308+ var orderingOverCalculatedColumn = origin . Header . Order
262309 . Select ( order => order . Key )
263310 . Any ( calculatedColumnIndexes . Contains ) ;
264- return distinctIsUsed || pagingIsUsed || groupByIsUsed || orderingOverCalculatedColumn ;
265- }
266-
267- if ( origin . Type == ProviderType . Apply )
268- return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed ;
269-
270- if ( origin . Type == ProviderType . Join ) {
271- var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed ;
272- if ( shouldUseQueryReference )
273- return true ;
274- var joinProvider = ( JoinProvider ) origin ;
275- var isRight = joinProvider . Right == compiledSource . Origin ;
276- var indexes = joinProvider . EqualIndexes . Select ( p => isRight ? p . Second : p . First ) ;
277- return ( joinProvider . JoinType == JoinType . LeftOuter && filterIsUsed && isRight )
278- || ( containsCalculatedColumns && indexes . Any ( calculatedColumnIndexes . Contains ) ) ;
279- }
280-
281- if ( origin . Type == ProviderType . PredicateJoin ) {
282- var shouldUseQueryReference = distinctIsUsed || pagingIsUsed || groupByIsUsed ;
283- if ( shouldUseQueryReference )
284- return true ;
285- var joinProvider = ( PredicateJoinProvider ) origin ;
286- var isRight = joinProvider . Right == compiledSource . Origin ;
287- var indexes = new TupleAccessGatherer ( ) . Gather ( joinProvider . Predicate . Body , joinProvider . Predicate . Parameters [ isRight ? 1 : 0 ] ) ;
288- return ( joinProvider . JoinType == JoinType . LeftOuter && filterIsUsed && isRight )
289- || ( containsCalculatedColumns && indexes . Any ( calculatedColumnIndexes . Contains ) ) ;
290- }
291-
292- if ( origin . Type == ProviderType . Sort ) {
293- if ( distinctIsUsed )
294- return true ;
295- var orderingOverCalculatedColumn = origin . Header . Order
296- . Select ( order => order . Key )
297- . Any ( calculatedColumnIndexes . Contains ) ;
298- return orderingOverCalculatedColumn ;
311+ return orderingOverCalculatedColumn ;
312+ }
313+ default :
314+ return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed ;
299315 }
300-
301- return containsCalculatedColumns || distinctIsUsed || pagingIsUsed || groupByIsUsed ;
302316 }
303317
304318 private SqlExpression GetOrderByExpression ( SqlExpression expression , SortProvider provider , int index )
305319 {
306- if ( provider . Header . Columns . Count <= index )
320+ var columns = provider . Header . Columns ;
321+ if ( columns . Count <= index ) {
307322 return expression ;
323+ }
308324
309- if ( providerInfo . Supports ( ProviderFeatures . DateTimeEmulation ) && provider . Header . Columns [ index ] . Type == typeof ( DateTime ) )
325+ var columnType = columns [ index ] . Type ;
326+ if ( providerInfo . Supports ( ProviderFeatures . DateTimeEmulation ) && columnType == typeof ( DateTime ) ) {
310327 return SqlDml . Cast ( expression , SqlType . DateTime ) ;
311- if ( providerInfo . Supports ( ProviderFeatures . DateTimeOffsetEmulation ) && provider . Header . Columns [ index ] . Type == typeof ( DateTimeOffset ) )
328+ }
329+
330+ if ( providerInfo . Supports ( ProviderFeatures . DateTimeOffsetEmulation ) && columnType == typeof ( DateTimeOffset ) ) {
312331 return SqlDml . Cast ( expression , SqlType . DateTimeOffset ) ;
332+ }
333+
313334 return expression ;
314335 }
315336
316- private SqlExpression GetJoinExpression ( SqlExpression leftExpression , SqlExpression rightExpression , JoinProvider provider , int index )
337+ private SqlExpression GetJoinExpression ( SqlExpression leftExpression , SqlExpression rightExpression ,
338+ JoinProvider provider , int index )
317339 {
318340 if ( provider . EqualColumns . Length > index ) {
319- if ( providerInfo . Supports ( ProviderFeatures . DateTimeEmulation ) )
320- {
321- if ( provider . EqualColumns [ index ] . First . Type == typeof ( DateTime ) )
341+ Pair < Column > columnPair ;
342+ if ( providerInfo . Supports ( ProviderFeatures . DateTimeEmulation ) ) {
343+ columnPair = provider . EqualColumns [ index ] ;
344+ if ( columnPair . First . Type == typeof ( DateTime ) ) {
322345 leftExpression = SqlDml . Cast ( leftExpression , SqlType . DateTime ) ;
323- if ( provider . EqualColumns [ index ] . Second . Type == typeof ( DateTime ) )
346+ }
347+
348+ if ( columnPair . Second . Type == typeof ( DateTime ) ) {
324349 rightExpression = SqlDml . Cast ( rightExpression , SqlType . DateTime ) ;
350+ }
325351 }
352+
326353 if ( providerInfo . Supports ( ProviderFeatures . DateTimeOffsetEmulation ) ) {
327- if ( provider . EqualColumns [ index ] . First . Type == typeof ( DateTimeOffset ) )
354+ columnPair = provider . EqualColumns [ index ] ;
355+ if ( columnPair . First . Type == typeof ( DateTimeOffset ) ) {
328356 leftExpression = SqlDml . Cast ( leftExpression , SqlType . DateTimeOffset ) ;
329- if ( provider . EqualColumns [ index ] . Second . Type == typeof ( DateTimeOffset ) )
357+ }
358+
359+ if ( columnPair . Second . Type == typeof ( DateTimeOffset ) ) {
330360 rightExpression = SqlDml . Cast ( rightExpression , SqlType . DateTimeOffset ) ;
361+ }
331362 }
332363 }
333- return leftExpression == rightExpression ;
364+
365+ return leftExpression == rightExpression ;
334366 }
335367
336368 public SqlExpression GetOuterExpression ( ApplyParameter parameter , int columnIndex )
0 commit comments