Esempio n. 1
0
        /// <summary>
        /// Renders a SELECT statement which a result-set page
        /// </summary>
        /// <param name="pageIndex">The zero based index of the page to be returned</param>
        /// <param name="pageSize">The size of a page</param>
        /// <param name="totalRowCount">Total number of rows the query would yeild if not paged</param>
        /// <param name="query">Query definition to apply paging on</param>
        /// <returns>Generated SQL statement</returns>
        /// <remarks>
        /// To generate pagination SQL you must supply <paramref name="totalRowCount"/>.
        /// To aquire the total number of rows use the <see cref="RenderRowCount"/> method.
        /// </remarks>
        public virtual string RenderPage(int pageIndex, int pageSize, int totalRowCount, SelectQuery query)
        {
            if (query.OrderByTerms.Count == 0)
            {
                throw new InvalidQueryException("OrderBy must be specified for paging to work.");
            }

            int currentPageSize = pageSize;

            if (pageSize * (pageIndex + 1) > totalRowCount)
            {
                currentPageSize = totalRowCount - pageSize * pageIndex;
            }
            if (currentPageSize < 0)
            {
                currentPageSize = 0;
            }

            SelectQuery baseQuery = query.Clone();

            baseQuery.Top = (pageIndex + 1) * pageSize;
            //baseQuery.Columns.Add(new SelectColumn("*"));
            foreach (OrderByTerm term in baseQuery.OrderByTerms)
            {
                baseQuery.Columns.Add(
                    new SelectColumn(term.Field, term.Table, FormatSortFieldName(term.Field),
                                     SqlAggregationFunction.None));
            }

            string baseSql = RenderSelect(baseQuery);

            SelectQuery reverseQuery = new SelectQuery();

            reverseQuery.Columns.Add(new SelectColumn("*"));
            reverseQuery.Top = currentPageSize;
            reverseQuery.FromClause.BaseTable = FromTerm.SubQuery(baseSql, "r");
            ApplyOrderBy(baseQuery.OrderByTerms, reverseQuery, false, reverseQuery.FromClause.BaseTable);
            string reverseSql = RenderSelect(reverseQuery);

            SelectQuery forwardQuery = new SelectQuery();

            foreach (SelectColumn originalCol in query.Columns)
            {
                FromTerm      forwardTable = FromTerm.TermRef("f");
                SqlExpression expr         = null;
                if (originalCol.ColumnAlias != null)
                {
                    expr = SqlExpression.Field(originalCol.ColumnAlias, forwardTable);
                }
                else if (originalCol.Expression.Type == SqlExpressionType.Field ||
                         originalCol.Expression.Type == SqlExpressionType.Constant)
                {
                    expr = SqlExpression.Field((string)originalCol.Expression.Value, forwardTable);
                }

                if (expr != null)
                {
                    forwardQuery.Columns.Add(new SelectColumn(expr, originalCol.ColumnAlias));
                }
            }

            forwardQuery.FromClause.BaseTable = FromTerm.SubQuery(reverseSql, "f");
            ApplyOrderBy(baseQuery.OrderByTerms, forwardQuery, true, forwardQuery.FromClause.BaseTable);

            return(RenderSelect(forwardQuery));
        }