internal override SqlSource VisitJoin(SqlJoin join) {
                if (join.JoinType == SqlJoinType.CrossApply) { 
                    // Visit the left side as usual.
                    join.Left = this.VisitSource(join.Left);

                    // Visit the condition as usual.
                    join.Condition = this.VisitExpression(join.Condition);

                    // Visit the right, with the expressionSink set.
                    SelectScope s = expressionSink;

                    expressionSink = new SelectScope();
                    expressionSink.LeftProduction = SqlGatherProducedAliases.Gather(join.Left);
                    join.Right = this.VisitSource(join.Right);

                    // Were liftable expressions found?
                    SqlSource newSource = join;
                    foreach (List<SqlColumn> cols in expressionSink.Lifted) {
                        newSource = PushSourceDown(newSource, cols);
                    }
                    expressionSink = s;
                    return newSource;
                }
                return base.VisitJoin(join);
            }
 internal override SqlSource VisitJoin(SqlJoin join) {
     // block where clauses from being lifted out of the cardinality-dependent 
     // side of an outer join.
     Scope save = this.current;
     try {
         switch (join.JoinType) {
             case SqlJoinType.Cross:
             case SqlJoinType.CrossApply:
             case SqlJoinType.Inner:
                 return base.VisitJoin(join);
             case SqlJoinType.LeftOuter:
             case SqlJoinType.OuterApply: {
                     join.Left = this.VisitSource(join.Left);
                     this.current = null;
                     join.Right = this.VisitSource(join.Right);
                     join.Condition = this.VisitExpression(join.Condition);
                     return join;
                 }
             default:
                 this.current = null;
                 return base.VisitJoin(join);
         }
     }
     finally {
         this.current = save;
     }
 }
            internal override SqlExpression VisitMultiset(SqlSubSelect sms) {
                // allow one big-join per query?
                if ((this.options & Options.EnableBigJoin) != 0 &&
                    !this.hasBigJoin && this.canJoin && this.isTopLevel && this.outerSelect != null
                    && !MultisetChecker.HasMultiset(sms.Select.Selection) 
                    && BigJoinChecker.CanBigJoin(sms.Select)) {

                    sms.Select = this.VisitSelect(sms.Select);

                    SqlAlias alias = new SqlAlias(sms.Select);
                    SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, this.outerSelect.From, alias, null, sms.SourceExpression);
                    this.outerSelect.From = join;
                    this.outerSelect.OrderingType = SqlOrderingType.Always;

                    // make joined expression
                    SqlExpression expr = (SqlExpression)SqlDuplicator.Copy(sms.Select.Selection);

                    // make count expression
                    SqlSelect copySelect = (SqlSelect)SqlDuplicator.Copy(sms.Select);
                    SqlAlias copyAlias = new SqlAlias(copySelect);
                    SqlSelect countSelect = new SqlSelect(sql.Unary(SqlNodeType.Count, null, sms.SourceExpression), copyAlias, sms.SourceExpression);
                    countSelect.OrderingType = SqlOrderingType.Never;
                    SqlExpression count = sql.SubSelect(SqlNodeType.ScalarSubSelect, countSelect);

                    // make joined collection
                    SqlJoinedCollection jc = new SqlJoinedCollection(sms.ClrType, sms.SqlType, expr, count, sms.SourceExpression);
                    this.hasBigJoin = true;
                    return jc;
                }
                else {
                    return QueryExtractor.Extract(sms, this.parentParameters);
                }
            }
 internal override SqlSource VisitJoin(SqlJoin join) {
     this.Visit(join.Left);
     List<SqlOrderExpression> leftOrders = this.orders;
     this.orders = null;
     this.Visit(join.Right);
     this.PrependOrderExpressions(leftOrders);
     return join;
 }
示例#5
0
        public void ExpressionType_ReturnsJoin()
        {
            var table = new SqlTable("dbo.Users", "u");
            var predicate = SqlExpression.Equal("u.Id", 5);
            var expression = new SqlJoin(SqlJoinType.Left, table);

            Assert.Equal(SqlExpressionType.Join, expression.ExpressionType);
        }
示例#6
0
        public void Ctor_WithTableAndPredicate_SetsPropertyValues()
        {
            var table = new SqlTable("dbo.Users", "u");
            var predicate = SqlExpression.Equal("u.Id", 5);
            var expression = new SqlJoin(SqlJoinType.Left, table, predicate);

            Assert.NotNull(expression.Table);
            Assert.Same(table, expression.Table);
            Assert.NotNull(expression.On);
            Assert.NotNull(expression.On.Predicate);
            Assert.Same(predicate, expression.On.Predicate);
            Assert.Equal(SqlJoinType.Left, expression.Type);
        }
			internal override SqlSource VisitJoin(SqlJoin join) {
				if (join.JoinType == SqlJoinType.CrossApply) {
					// Look down the left side to see what table aliases are produced.
					HashSet<SqlAlias> p = SqlGatherProducedAliases.Gather(join.Left);
					// Look down the right side to see what table aliases are consumed.
					HashSet<SqlAlias> c = SqlGatherConsumedAliases.Gather(join.Right);
					// Look at each consumed alias and see if they are mentioned in produced.
                    if (p.Overlaps(c)) {
						Annotations.Add(join, new SqlServerCompatibilityAnnotation(Strings.SourceExpressionAnnotation(join.SourceExpression), SqlProvider.ProviderMode.Sql2000));
						// Can't reduce because this consumed alias is produced on the left.
						return base.VisitJoin(join);
					}

					// Can turn this into a CROSS JOIN
					join.JoinType = SqlJoinType.Cross;
					return VisitJoin(join);
				}
				return base.VisitJoin(join);
			}
 internal override SqlSource VisitJoin(SqlJoin join) {
     SqlSource left = this.VisitSource(join.Left);
     SqlSource right = this.VisitSource(join.Right);
     SqlExpression cond = (SqlExpression)this.Visit(join.Condition);
     return new SqlJoin(join.JoinType, left, right, cond, join.SourceExpression);
 }
示例#9
0
        private SqlSelect VisitDefaultIfEmpty(Expression sequence) {
            SqlSelect select = this.VisitSequence(sequence);
            SqlAlias alias = new SqlAlias(select);
            SqlAliasRef aliasRef = new SqlAliasRef(alias);

            SqlExpression opt = new SqlOptionalValue(
                new SqlColumn(
                    "test",
                    sql.Unary(SqlNodeType.OuterJoinedValue,
                        sql.Value(typeof(int?), this.typeProvider.From(typeof(int)), 1, false, this.dominatingExpression)
                        )
                    ),
                    sql.Unary(SqlNodeType.OuterJoinedValue, aliasRef)
                );
            SqlSelect optSelect = new SqlSelect(opt, alias, this.dominatingExpression);

            alias = new SqlAlias(optSelect);
            aliasRef = new SqlAliasRef(alias);

            SqlExpression litNull = sql.TypedLiteralNull(typeof(string), this.dominatingExpression);
            SqlSelect selNull = new SqlSelect(litNull, null, this.dominatingExpression);
            SqlAlias aliasNull = new SqlAlias(selNull);

            SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, aliasNull, alias, null, this.dominatingExpression);

            return new SqlSelect(aliasRef, join, this.dominatingExpression);
        }
示例#10
0
        private SqlSelect VisitJoin(Expression outerSequence, Expression innerSequence, LambdaExpression outerKeySelector, LambdaExpression innerKeySelector, LambdaExpression resultSelector) {
            SqlSelect outerSelect = this.VisitSequence(outerSequence);
            SqlSelect innerSelect = this.VisitSequence(innerSequence);

            SqlAlias outerAlias = new SqlAlias(outerSelect);
            SqlAliasRef outerRef = new SqlAliasRef(outerAlias);
            SqlAlias innerAlias = new SqlAlias(innerSelect);
            SqlAliasRef innerRef = new SqlAliasRef(innerAlias);

            this.map[outerKeySelector.Parameters[0]] = outerRef;
            SqlExpression outerKey = this.VisitExpression(outerKeySelector.Body);

            this.map[innerKeySelector.Parameters[0]] = innerRef;
            SqlExpression innerKey = this.VisitExpression(innerKeySelector.Body);

            this.map[resultSelector.Parameters[0]] = outerRef;
            this.map[resultSelector.Parameters[1]] = innerRef;
            SqlExpression result = this.VisitExpression(resultSelector.Body);

            SqlExpression condition = sql.Binary(SqlNodeType.EQ, outerKey, innerKey);
            SqlSelect select = null;
            if ((this.converterStrategy & ConverterStrategy.CanUseJoinOn) != 0) {
                SqlJoin join = new SqlJoin(SqlJoinType.Inner, outerAlias, innerAlias, condition, this.dominatingExpression);
                select = new SqlSelect(result, join, this.dominatingExpression);
            } else {
                SqlJoin join = new SqlJoin(SqlJoinType.Cross, outerAlias, innerAlias, null, this.dominatingExpression);
                select = new SqlSelect(result, join, this.dominatingExpression);
                select.Where = condition;
            }
            return select;
        }
示例#11
0
        private SqlSelect VisitSelectMany(Expression sequence, LambdaExpression colSelector, LambdaExpression resultSelector) {
            SqlSelect seqSelect = this.VisitSequence(sequence);
            SqlAlias seqAlias = new SqlAlias(seqSelect);
            SqlAliasRef seqRef = new SqlAliasRef(seqAlias);

            this.map[colSelector.Parameters[0]] = seqRef;

            SqlNode colSelectorNode = this.VisitSequence(colSelector.Body);
            SqlAlias selAlias = new SqlAlias(colSelectorNode);
            SqlAliasRef selRef = new SqlAliasRef(selAlias);
            SqlJoin join = new SqlJoin(SqlJoinType.CrossApply, seqAlias, selAlias, null, this.dominatingExpression);

            SqlExpression projection = selRef;

            if (resultSelector != null) {
                this.map[resultSelector.Parameters[0]] = seqRef;
                this.map[resultSelector.Parameters[1]] = selRef;
                projection = this.VisitExpression(resultSelector.Body);
            }

            return new SqlSelect(projection, join, this.dominatingExpression);
        }
示例#12
0
        private SqlSelect VisitSelect(Expression sequence, LambdaExpression selector) {
            SqlSelect source = this.VisitSequence(sequence);
            SqlAlias alias = new SqlAlias(source);
            SqlAliasRef aref = new SqlAliasRef(alias);

            this.map[selector.Parameters[0]] = aref;
            SqlNode project = this.Visit(selector.Body);

            SqlSelect pselect = project as SqlSelect;
            if (pselect != null) {
                return new SqlSelect(sql.SubSelect(SqlNodeType.Multiset, pselect, selector.Body.Type), alias, this.dominatingExpression);
            }
            else if ((project.NodeType == SqlNodeType.Element || project.NodeType == SqlNodeType.ScalarSubSelect) &&
                     (this.converterStrategy & ConverterStrategy.CanUseOuterApply) != 0) {
                SqlSubSelect sub = (SqlSubSelect)project;
                SqlSelect inner = sub.Select;
                SqlAlias innerAlias = new SqlAlias(inner);
                SqlAliasRef innerRef = new SqlAliasRef(innerAlias);
                if (project.NodeType == SqlNodeType.Element) {
                    inner.Selection = new SqlOptionalValue(
                        new SqlColumn(
                            "test",
                            sql.Unary(
                                SqlNodeType.OuterJoinedValue,
                                sql.Value(typeof(int?), this.typeProvider.From(typeof(int)), 1, false, this.dominatingExpression)
                                )
                            ),
                            sql.Unary(SqlNodeType.OuterJoinedValue, inner.Selection)
                        );
                }
                else {
                    inner.Selection = sql.Unary(SqlNodeType.OuterJoinedValue, inner.Selection);
                }
                SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, alias, innerAlias, null, this.dominatingExpression);
                return new SqlSelect(innerRef, join, this.dominatingExpression);
            }
            else {
                SqlExpression expr = project as SqlExpression;
                if (expr != null) {
                    return new SqlSelect(expr, alias, this.dominatingExpression);
                }
                else {
                    throw Error.BadProjectionInSelect();
                }
            }
        }
示例#13
0
 internal override SqlSource VisitJoin(SqlJoin join) {
     Scope save = this.CurrentScope;
     switch (join.JoinType) {
         case SqlJoinType.CrossApply:
         case SqlJoinType.OuterApply: {
             this.Visit(join.Left);
             Scope tmp = new Scope(join.Left, this.CurrentScope.ContainingScope);
             this.CurrentScope = new Scope(null, tmp);
             this.Visit(join.Right);
             Scope tmp2 = new Scope(join.Right, tmp);
             this.CurrentScope = new Scope(null, tmp2);
             this.Visit(join.Condition);
             break;
         }
         default: {
             this.Visit(join.Left);
             this.Visit(join.Right);
             this.CurrentScope = new Scope(null, new Scope(join.Right, new Scope(join.Left, this.CurrentScope.ContainingScope)));
             this.Visit(join.Condition);
             break;
         }
     }
     this.CurrentScope = save;
     return join;
 }
示例#14
0
 protected virtual SqlExpression VisitJoin(SqlJoin expr)
 {
     return expr;
 }
示例#15
0
 internal virtual SqlSource VisitJoin(SqlJoin join) {
     join.Left = this.VisitSource(join.Left);
     join.Right = this.VisitSource(join.Right);
     join.Condition = this.VisitExpression(join.Condition);
     return join;
 }
示例#16
0
 /// <summary>
 /// Visits the specified <see cref="SqlJoin"/>.
 /// </summary>
 /// <param name="expression">
 /// The expression to visit.
 /// </param>
 public virtual void Visit(SqlJoin expression)
 {
 }
示例#17
0
 public JoinInfo(SqlJoin joinType, ISqlInstruction with, Exp on)
 {
     With = with;
     JoinType = joinType;
     On = on;
 }
示例#18
0
 private SqlQuery Join(SqlJoin join, ISqlInstruction instruction, Exp on)
 {
     joins.Add(new JoinInfo(join, instruction, on));
     return this;
 }
示例#19
0
 internal override SqlSource VisitJoin(SqlJoin join) {
     switch (join.JoinType) {
         case SqlJoinType.CrossApply:
         case SqlJoinType.OuterApply: {
             this.Visit(join.Left);
             if (this.found == null) {
                 this.Visit(join.Right);
             }
             break;
         }
         default: {
             this.Visit(join.Left);
             this.Visit(join.Right);
             break;
         }
     }
     return join;
 }
示例#20
0
 internal override SqlSource VisitJoin(SqlJoin join) {
     base.VisitJoin(join);
     if (join.Condition != null) {
         this.CheckJoinCondition(join.Condition);
     }
     return join;
 }
示例#21
0
            internal override SqlSource VisitJoin(SqlJoin join) {
                if (join.JoinType == SqlJoinType.CrossApply ||
                    join.JoinType == SqlJoinType.OuterApply) {
                    join.Left = this.VisitSource(join.Left);

                    SqlSelect saveSelect = this.currentSelect;
                    try {
                        this.currentSelect = this.GetSourceSelect(join.Left);
                        join.Right = this.VisitSource(join.Right);

                        this.currentSelect = null;
                        join.Condition = this.VisitExpression(join.Condition);

                        return join;
                    }
                    finally {
                        this.currentSelect = saveSelect;
                    }
                }
                else {
                    return base.VisitJoin(join);
                }
            }
 internal override SqlSource VisitJoin(SqlJoin join) {
     this.ReferenceColumns(join.Condition);
     return base.VisitJoin(join);
 }
            protected override SqlExpression VisitJoin(SqlJoin join)
            {
                Visit(join.Left);
                NewLine();
                
                switch (join.JoinType)
                {
                    case SqlJoinType.Cross:
                        _builder.Append("CROSS JOIN ");
                        break;
                    case SqlJoinType.Inner:
                        _builder.Append("INNER JOIN ");
                        break;
                    case SqlJoinType.LeftOuter:
                        _builder.Append("LEFT OUTER JOIN ");
                        break;
                    case SqlJoinType.RightOuter:
                        _builder.Append("RIGHT OUTER JOIN ");
                        break;
                }

                VisitJoinSource(join.Right);

                if (join.Condition != null)
                {
                    _builder.Append(" ON ");
                    Visit(join.Condition);

                    return join;
                }
                
                if (RequiresOnCondition(join.JoinType))
                    _builder.Append(" ON 1 = 1 ");

                return join;
            }
 internal override SqlSource VisitJoin(SqlJoin join) {
     join.Left = this.VisitSource(join.Left);
     join.Right = this.VisitSource(join.Right);
     join.Condition = this.VisitPredicate(join.Condition);
     return join;
 }
示例#25
0
 internal override SqlSource VisitJoin(SqlJoin join) {
     base.VisitJoin(join);
     switch (join.JoinType) {
         case SqlJoinType.Cross:
         case SqlJoinType.Inner:
             // reducing either side would effect cardinality of results
             break;
         case SqlJoinType.LeftOuter:
         case SqlJoinType.CrossApply:
         case SqlJoinType.OuterApply:
             // may reduce to left if no references to the right
             if (this.HasEmptySource(join.Right)) {
                 SqlAlias a = (SqlAlias)join.Right;
                 this.removedMap[a] = a;
                 return join.Left;
             }
             break;
     }
     return join;
 }
示例#26
0
 internal override SqlSource VisitJoin(SqlJoin join) {
     this.Visit(join.Left);
     this.NewLine();
     switch (join.JoinType) {
         case SqlJoinType.CrossApply:
             sb.Append("CROSS APPLY ");
             break;
         case SqlJoinType.Cross:
             sb.Append("CROSS JOIN ");
             break;
         case SqlJoinType.Inner:
             sb.Append("INNER JOIN ");
             break;
         case SqlJoinType.LeftOuter:
             sb.Append("LEFT OUTER JOIN ");
             break;
         case SqlJoinType.OuterApply:
             sb.Append("OUTER APPLY ");
             break;
     }
     SqlJoin rightJoin = join.Right as SqlJoin;
     if (rightJoin == null || 
          (rightJoin.JoinType == SqlJoinType.Cross 
            && join.JoinType != SqlJoinType.CrossApply 
            && join.JoinType != SqlJoinType.OuterApply)) {
         this.Visit(join.Right);
     } else {
         this.VisitJoinSource(join.Right);
     }
     if (join.Condition != null) {
         sb.Append(" ON ");
         this.Visit(join.Condition);
     } else if (this.RequiresOnCondition(join.JoinType)) {
         sb.Append(" ON 1=1 ");
     }
     return join;
 }
示例#27
0
 public SqlQuery Join(SqlQueryBase query, object LocalKey, object OtherKey)
 {
     var join = new SqlJoin { JoinQuery = query, ForeignKey = OtherKey, LocalKey = LocalKey, Parent = this };
     Joins.Add(join);
     return this;
 }