internal SelectExpression(LambdaExpression projection, FromExpression from, WhereExpression where, string alias, bool isProjection, Expression take, OrderByClause orderBy)
			: base(CompleteExpressionType.Select, typeof(IEnumerable<>).MakeGenericType(projection.ReturnType))
		{
			this.Projection = projection;
			this.Alias = alias;
			this.From = from;
			this.Where = where;
			this.Take = take;
			this.OrderBy = orderBy;
			this.IsProjection = isProjection;

			var ce = ColumnExtractor.ExtractColumns(this, projection);
			this._Columns = ce.Columns.ToList();
			this._Assignments = ce.Assignments.ToList();
		}
		protected virtual Expression VisitWhere(WhereExpression where)
		{
			this.Write(".Where(");
			this.WriteLine(Indentation.Inner);
			this.Visit(where.Predicate);
			this.WriteLine(Indentation.Outer);
			this.Write(")");
			return where;
		}
		internal WhereExpression(Expression predicate, WhereExpression previousWhere)
			: base(CompleteExpressionType.Where, typeof(bool))
		{
			if (predicate == null) throw new ArgumentNullException("predicate");
			if (predicate.Type != typeof(bool))
				throw new ArgumentException("'predicate' must return a bool.", "predicate");

			if (previousWhere != null)
			{
				predicate =
					Expression.AndAlso(
						predicate,
						previousWhere.Predicate);
			}

			this.Predicate = predicate;
		}
		protected virtual Expression VisitWhere(WhereExpression where)
		{
			var predicate = this.Visit(where.Predicate);
			if (predicate == where.Predicate)
				return where;
			return CompleteExpression.Where(predicate);
		}
		protected override Expression VisitWhere(WhereExpression where)
		{
			sb.Append("where ");

			if (where.Predicate is BinaryExpression)
				this.Visit(where.Predicate);
			else if (where.Predicate.NodeType == ExpressionType.Constant)
			{
				var value = (bool)((where.Predicate as ConstantExpression).Value);
				if (value)
					sb.Append("1 = 1");
				else
					sb.Append("0 = 1");
			}
			else if (where.Predicate is ConditionalExpression)
			{
				this.Visit(where.Predicate);
				sb.Append(" = 1");
			}
			else
				throw new NotSupportedException("Not sure yet what to do here. ");

			this.AppendNewLine(Indentation.Same);
			return where;
		}
		public static WhereExpression Where(Expression predicate, WhereExpression previousWhere = null)
		{
			return new WhereExpression(predicate, previousWhere);
		}
		public static SelectExpression Select(string alias, LambdaExpression projection, FromExpression from, OrderByClause orderBy, WhereExpression where = null, bool isProjection = true, Expression take = null)
		{
			return new SelectExpression(projection, from, where, alias, isProjection, take, orderBy);
		}