protected override Provider VisitJoin(JoinProvider provider) { // split List <int> leftMapping; List <int> rightMapping; SplitMappings(provider, out leftMapping, out rightMapping); leftMapping = Merge(leftMapping, provider.EqualIndexes.Select(p => p.First)); rightMapping = Merge(rightMapping, provider.EqualIndexes.Select(p => p.Second)); var newLeftProvider = provider.Left; var newRightProvider = provider.Right; VisitJoin(ref leftMapping, ref newLeftProvider, ref rightMapping, ref newRightProvider); mappings[provider] = MergeMappings(provider.Left, leftMapping, rightMapping); if (newLeftProvider == provider.Left && newRightProvider == provider.Right) { return(provider); } var newIndexes = new List <Pair <int> >(); foreach (var pair in provider.EqualIndexes) { var newLeftIndex = leftMapping.IndexOf(pair.First); var newRightIndex = rightMapping.IndexOf(pair.Second); newIndexes.Add(new Pair <int>(newLeftIndex, newRightIndex)); } return(new JoinProvider(newLeftProvider, newRightProvider, provider.JoinType, newIndexes.ToArray())); }
protected override Provider VisitJoin(JoinProvider provider) { var left = VisitCompilable(provider.Left); var leftOrder = sortOrder; var right = VisitCompilable(provider.Right); var rightOrder = sortOrder; var result = left == provider.Left && right == provider.Right ? provider : new JoinProvider(left, right, provider.JoinType, provider.EqualIndexes); sortOrder = ComputeBinaryOrder(provider, leftOrder, rightOrder); return(result); }
protected override Provider VisitJoin(JoinProvider provider) { CompilableProvider left; CompilableProvider right; VisitBinaryProvider(provider, out left, out right); if (provider.JoinType == JoinType.LeftOuter) { EnsureAbsenceOfApplyProviderRequiringConversion(); } if (left != provider.Left || right != provider.Right) { return(new JoinProvider(left, right, provider.JoinType, provider.EqualIndexes)); } return(provider); }
private SqlExpression GetJoinExpression(SqlExpression leftExpression, SqlExpression rightExpression, JoinProvider provider, int index) { if (provider.EqualColumns.Length > index) { if (providerInfo.Supports(ProviderFeatures.DateTimeEmulation)) { if (provider.EqualColumns[index].First.Type == typeof(DateTime)) { leftExpression = SqlDml.Cast(leftExpression, SqlType.DateTime); } if (provider.EqualColumns[index].Second.Type == typeof(DateTime)) { rightExpression = SqlDml.Cast(rightExpression, SqlType.DateTime); } } if (providerInfo.Supports(ProviderFeatures.DateTimeOffsetEmulation)) { if (provider.EqualColumns[index].First.Type == typeof(DateTimeOffset)) { leftExpression = SqlDml.Cast(leftExpression, SqlType.DateTimeOffset); } if (provider.EqualColumns[index].Second.Type == typeof(DateTimeOffset)) { rightExpression = SqlDml.Cast(rightExpression, SqlType.DateTimeOffset); } } } return(leftExpression == rightExpression); }
/// <summary> /// Compiles <see cref="JoinProvider"/>. /// </summary> /// <param name="provider">Join provider.</param> protected abstract TResult VisitJoin(JoinProvider provider);
/// <inheritdoc/> protected override SqlProvider VisitJoin(JoinProvider provider) { var left = Compile(provider.Left); var right = Compile(provider.Right); // SQLite does not allow certain join combinations // Any right part of join expression should not be join itself // See IssueA363_WrongInnerJoin for example of such query var strictJoinWorkAround = providerInfo.Supports(ProviderFeatures.StrictJoinSyntax) && right.Request.Statement.From is SqlJoinedTable; var leftShouldUseReference = ShouldUseQueryReference(provider, left); var leftTable = leftShouldUseReference ? left.PermanentReference : left.Request.Statement.From; var leftColumns = leftShouldUseReference ? leftTable.Columns.Cast <SqlColumn>() : left.Request.Statement.Columns; var leftExpressions = leftShouldUseReference ? leftTable.Columns.Cast <SqlExpression>().ToList() : ExtractColumnExpressions(left.Request.Statement); var rightShouldUseReference = strictJoinWorkAround || ShouldUseQueryReference(provider, right); var rightTable = rightShouldUseReference ? right.PermanentReference : right.Request.Statement.From; var rightColumns = rightShouldUseReference ? rightTable.Columns.Cast <SqlColumn>() : right.Request.Statement.Columns; var rightExpressions = rightShouldUseReference ? rightTable.Columns.Cast <SqlExpression>().ToList() : ExtractColumnExpressions(right.Request.Statement); var joinType = provider.JoinType == JoinType.LeftOuter ? SqlJoinType.LeftOuterJoin : SqlJoinType.InnerJoin; SqlExpression joinExpression = null; for (var i = 0; i < provider.EqualIndexes.Count(); ++i) { var leftExpression = leftExpressions[provider.EqualIndexes[i].First]; var rightExpression = rightExpressions[provider.EqualIndexes[i].Second]; joinExpression &= GetJoinExpression(leftExpression, rightExpression, provider, i); } var joinedTable = SqlDml.Join( joinType, leftTable, rightTable, leftColumns.ToList(), rightColumns.ToList(), joinExpression); var query = SqlDml.Select(joinedTable); if (!leftShouldUseReference) { query.Where &= left.Request.Statement.Where; } if (!rightShouldUseReference) { query.Where &= right.Request.Statement.Where; } query.Columns.AddRange(joinedTable.AliasedColumns); return(CreateProvider(query, provider, left, right)); }