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;
		}
		internal override SqlExpression VisitMultiset(SqlSubSelect sms)
		{
			// allow one big-join per query?
			if((this.options & SqlMultiplexerOptionType.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;
			}
			return QueryExtractor.Extract(sms, this.parentParameters);
		}
		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 SqlSource VisitJoin(SqlJoin join)
		{
			SqlScope save = this.CurrentScope;
			switch(join.JoinType)
			{
				case SqlJoinType.CrossApply:
				case SqlJoinType.OuterApply:
				{
					this.Visit(join.Left);
					SqlScope tmp = new SqlScope(join.Left, this.CurrentScope.ContainingScope);
					this.CurrentScope = new SqlScope(null, tmp);
					this.Visit(join.Right);
					SqlScope tmp2 = new SqlScope(join.Right, tmp);
					this.CurrentScope = new SqlScope(null, tmp2);
					this.Visit(join.Condition);
					break;
				}
				default:
				{
					this.Visit(join.Left);
					this.Visit(join.Right);
					this.CurrentScope = new SqlScope(null, new SqlScope(join.Right, new SqlScope(join.Left, this.CurrentScope.ContainingScope)));
					this.Visit(join.Condition);
					break;
				}
			}
			this.CurrentScope = save;
			return join;
		}
		internal override SqlSource VisitJoin(SqlJoin join)
		{
			base.VisitJoin(@join);
			if(@join.Condition != null)
			{
				this.CheckJoinCondition(@join.Condition);
			}
			return @join;
		}
		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;
		}
			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 CompatibilityAnnotation(Strings.SourceExpressionAnnotation(join.SourceExpression), _providerModesWithIncompatibilities));
						// 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);
			}
Exemple #8
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;
		}
		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;
						_removedMap[a] = a;
						return @join.Left;
					}
					break;
			}
			return @join;
		}
		internal override SqlSource VisitJoin(SqlJoin join)
		{
			@join.Condition = this.VisitExpression(@join.Condition);
			@join.Right = this.VisitSource(@join.Right);
			@join.Left = this.VisitSource(@join.Left);
			return @join;
		}
		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);
		}
Exemple #12
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;
 }
		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",
					_nodeFactory.Unary(SqlNodeType.OuterJoinedValue,
						_nodeFactory.Value(typeof(int?), _typeProvider.From(typeof(int)), 1, false, _dominatingExpression)
						)
					),
					_nodeFactory.Unary(SqlNodeType.OuterJoinedValue, aliasRef)
				);
			SqlSelect optSelect = new SqlSelect(opt, alias, _dominatingExpression);

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

			SqlExpression litNull = _nodeFactory.TypedLiteralNull(typeof(string), _dominatingExpression);
			SqlSelect selNull = new SqlSelect(litNull, null, _dominatingExpression);
			SqlAlias aliasNull = new SqlAlias(selNull);

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

			return new SqlSelect(aliasRef, join, _dominatingExpression);
		}
		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);

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

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

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

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

			_parameterExpressionToSqlExpression[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, _dominatingExpression);

			SqlExpression projection = selRef;

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

			return new SqlSelect(projection, join, _dominatingExpression);
		}
		private SqlSelect VisitSelect(Expression sequence, LambdaExpression selector)
		{
			SqlSelect source = this.VisitSequence(sequence);
			SqlAlias alias = new SqlAlias(source);
			SqlAliasRef aref = new SqlAliasRef(alias);

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

			SqlSelect pselect = project as SqlSelect;
			if(pselect != null)
			{
				return new SqlSelect(_nodeFactory.SubSelect(SqlNodeType.Multiset, pselect, selector.Body.Type), alias, _dominatingExpression);
			}
			else if((project.NodeType == SqlNodeType.Element || project.NodeType == SqlNodeType.ScalarSubSelect) &&
					 (_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",
							_nodeFactory.Unary(
								SqlNodeType.OuterJoinedValue,
								_nodeFactory.Value(typeof(int?), _typeProvider.From(typeof(int)), 1, false, _dominatingExpression)
								)
							),
							_nodeFactory.Unary(SqlNodeType.OuterJoinedValue, inner.Selection)
						);
				}
				else
				{
					inner.Selection = _nodeFactory.Unary(SqlNodeType.OuterJoinedValue, inner.Selection);
				}
				SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, alias, innerAlias, null, _dominatingExpression);
				return new SqlSelect(innerRef, join, _dominatingExpression);
			}
			else
			{
				SqlExpression expr = project as SqlExpression;
				if(expr != null)
				{
					return new SqlSelect(expr, alias, _dominatingExpression);
				}
				else
				{
					throw Error.BadProjectionInSelect();
				}
			}
		}
		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);
		}
		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);
		}
		internal override SqlSource VisitJoin(SqlJoin join)
		{
			this.Visit(@join.Left);
			this.NewLine();
			switch(@join.JoinType)
			{
				case SqlJoinType.CrossApply:
					_commandStringBuilder.Append("CROSS APPLY ");
					break;
				case SqlJoinType.Cross:
					_commandStringBuilder.Append("CROSS JOIN ");
					break;
				case SqlJoinType.Inner:
					_commandStringBuilder.Append("INNER JOIN ");
					break;
				case SqlJoinType.LeftOuter:
					_commandStringBuilder.Append("LEFT OUTER JOIN ");
					break;
				case SqlJoinType.OuterApply:
					_commandStringBuilder.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)
			{
				_commandStringBuilder.Append(" ON ");
				this.Visit(@join.Condition);
			}
			else if(this.RequiresOnCondition(@join.JoinType))
			{
				_commandStringBuilder.Append(" ON 1=1 ");
			}
			return @join;
		}