internal WhereClauseLifter(NodeFactory sql)
		{
			this.sql = sql;
			this.aggregateChecker = new SqlAggregateChecker();
			this.rowNumberChecker = new SqlRowNumberChecker();
		}
Example #2
0
		internal override SqlSelect VisitSelect(SqlSelect select)
		{
			bool saveTop = this.topSelect;
			bool savePK = this.addPrimaryKeys;

			SqlSelect saveSelect = this.currentSelect;
			this.currentSelect = select;

			if(select.OrderingType == SqlOrderingType.Always)
			{
				this.addPrimaryKeys = true;
			}

			this.topSelect = false;

			// can't forward ordering information through a group-by
			if(select.GroupBy.Count > 0)
			{
				this.Visit(select.From);
				this.orders = null;
			}
			else
			{
				this.Visit(select.From);
			}

			if(select.OrderBy.Count > 0)
			{
				this.PrependOrderExpressions(select.OrderBy);
			}

			List<SqlOrderExpression> save = this.orders;
			this.orders = null;
			this.rowNumberOrders = save; // lest orders be null when we need info

			/* do all the lower level stuff */
			select.Where = this.VisitExpression(select.Where);
			for(int i = 0, n = select.GroupBy.Count; i < n; i++)
			{
				select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]);
			}
			select.Having = this.VisitExpression(select.Having);
			for(int i = 0, n = select.OrderBy.Count; i < n; i++)
			{
				select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression);
			}
			select.Top = this.VisitExpression(select.Top);
			select.Selection = this.VisitExpression(select.Selection);
			select.Row = (SqlRow)this.Visit(select.Row);

			this.topSelect = saveTop;
			this.addPrimaryKeys = savePK;

			this.orders = save;

			// all ordering is blocked for this layer and above
			if(select.OrderingType == SqlOrderingType.Blocked)
			{
				this.orders = null;
			}

			// rebuild orderby expressions, provided this select doesn't contain a SqlRowNumber
			// otherwise, replace the orderby with a reference to that column
			select.OrderBy.Clear();
			var rowNumberChecker = new SqlRowNumberChecker();

			if(rowNumberChecker.HasRowNumber(select) && rowNumberChecker.RowNumberColumn != null)
			{
				select.Row.Columns.Remove(rowNumberChecker.RowNumberColumn);
				this.PushDown(rowNumberChecker.RowNumberColumn);
				this.Orders.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(rowNumberChecker.RowNumberColumn)));
			}
			if((this.topSelect || select.Top != null) && select.OrderingType != SqlOrderingType.Never && this.orders != null)
			{
				this.orders = new HashSet<SqlOrderExpression>(this.orders).ToList();
				SqlDuplicator dup = new SqlDuplicator(true);
				foreach(SqlOrderExpression sox in this.orders)
				{
					select.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
				}
			}
			this.currentSelect = saveSelect;

			return select;
		}
        internal override SqlSelect VisitSelect(SqlSelect select)
        {
            bool saveTop = this.topSelect;
            bool savePK  = this.addPrimaryKeys;

            SqlSelect saveSelect = this.currentSelect;

            this.currentSelect = select;

            if (select.OrderingType == SqlOrderingType.Always)
            {
                this.addPrimaryKeys = true;
            }

            this.topSelect = false;

            // can't forward ordering information through a group-by
            if (select.GroupBy.Count > 0)
            {
                this.Visit(select.From);
                this.orders = null;
            }
            else
            {
                this.Visit(select.From);
            }

            if (select.OrderBy.Count > 0)
            {
                this.PrependOrderExpressions(select.OrderBy);
            }

            List <SqlOrderExpression> save = this.orders;

            this.orders          = null;
            this.rowNumberOrders = save;             // lest orders be null when we need info

            /* do all the lower level stuff */
            select.Where = this.VisitExpression(select.Where);
            for (int i = 0, n = select.GroupBy.Count; i < n; i++)
            {
                select.GroupBy[i] = this.VisitExpression(select.GroupBy[i]);
            }
            select.Having = this.VisitExpression(select.Having);
            for (int i = 0, n = select.OrderBy.Count; i < n; i++)
            {
                select.OrderBy[i].Expression = this.VisitExpression(select.OrderBy[i].Expression);
            }
            select.Top       = this.VisitExpression(select.Top);
            select.Selection = this.VisitExpression(select.Selection);
            select.Row       = (SqlRow)this.Visit(select.Row);

            this.topSelect      = saveTop;
            this.addPrimaryKeys = savePK;

            this.orders = save;

            // all ordering is blocked for this layer and above
            if (select.OrderingType == SqlOrderingType.Blocked)
            {
                this.orders = null;
            }

            // rebuild orderby expressions, provided this select doesn't contain a SqlRowNumber
            // otherwise, replace the orderby with a reference to that column
            select.OrderBy.Clear();
            var rowNumberChecker = new SqlRowNumberChecker();

            if (rowNumberChecker.HasRowNumber(select) && rowNumberChecker.RowNumberColumn != null)
            {
                select.Row.Columns.Remove(rowNumberChecker.RowNumberColumn);
                this.PushDown(rowNumberChecker.RowNumberColumn);
                this.Orders.Add(new SqlOrderExpression(SqlOrderType.Ascending, new SqlColumnRef(rowNumberChecker.RowNumberColumn)));
            }
            if ((this.topSelect || select.Top != null) && select.OrderingType != SqlOrderingType.Never && this.orders != null)
            {
                this.orders = new HashSet <SqlOrderExpression>(this.orders).ToList();
                SqlDuplicator dup = new SqlDuplicator(true);
                foreach (SqlOrderExpression sox in this.orders)
                {
                    select.OrderBy.Add(new SqlOrderExpression(sox.OrderType, (SqlExpression)dup.Duplicate(sox.Expression)));
                }
            }
            this.currentSelect = saveSelect;

            return(select);
        }