Skip to content

Commit 32b9918

Browse files
committed
Reorganize code in SqlCompiler.Helpers.cs
1 parent d2703e1 commit 32b9918

File tree

1 file changed

+159
-127
lines changed

1 file changed

+159
-127
lines changed

Orm/Xtensive.Orm/Orm/Providers/SqlCompiler.Helpers.cs

Lines changed: 159 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)