Exemplo n.º 1
0
        /// <summary>
        /// 为指定的原始查询生成指定分页效果的新查询。
        /// </summary>
        /// <param name="raw">原始查询</param>
        /// <param name="pagingInfo">分页信息。</param>
        /// <returns></returns>
        protected override ISqlSelect ModifyToPagingTree(SqlSelect raw, PagingInfo pagingInfo)
        {
            if (PagingInfo.IsNullOrEmpty(pagingInfo))
            {
                throw new ArgumentNullException("pagingInfo");
            }
            if (!raw.HasOrdered())
            {
                throw new InvalidProgramException("必须排序后才能使用分页功能。");
            }

            var pageNumber = pagingInfo.PageNumber;
            var pageSize   = pagingInfo.PageSize;

            var res = MakePagingTree(raw, pageNumber, pageSize);

            return(res);
        }
Exemplo n.º 2
0
        /// <summary>
        /// 使用 ROWNUM 来进行分页。
        /// </summary>
        /// <param name="raw">The raw.</param>
        /// <param name="pagingInfo">The paging information.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">pagingInfo</exception>
        /// <exception cref="System.InvalidProgramException">必须排序后才能使用分页功能。</exception>
        protected override ISqlSelect ModifyToPagingTree(SqlSelect raw, PagingInfo pagingInfo)
        {
            if (PagingInfo.IsNullOrEmpty(pagingInfo))
            {
                throw new ArgumentNullException("pagingInfo");
            }
            if (!raw.HasOrdered())
            {
                throw new InvalidProgramException("必须排序后才能使用分页功能。");
            }

            var startRow = pagingInfo.PageSize * (pagingInfo.PageNumber - 1) + 1;
            var endRow   = startRow + pagingInfo.PageSize - 1;

            var res = MakePagingTree(raw, startRow, endRow);

            return(res);
        }
Exemplo n.º 3
0
        /// <summary>
        /// 为指定的原始查询生成指定分页效果的新查询。
        /// </summary>
        /// <param name="raw">原始查询</param>
        /// <param name="pagingInfo">分页信息。</param>
        /// <returns></returns>
        private ISqlSelect ModifyToPagingTreeWithNotIn(SqlSelect raw, PagingInfo pagingInfo)
        {
            if (PagingInfo.IsNullOrEmpty(pagingInfo))
            {
                throw new ArgumentNullException("pagingInfo");
            }
            if (!raw.HasOrdered())
            {
                throw new InvalidProgramException("必须排序后才能使用分页功能。");
            }

            //如果是第一页,则只需要使用 TOP 语句即可。
            if (pagingInfo.PageNumber == 1)
            {
                return(new SqlSelect
                {
                    Selection = new SqlNodeList
                    {
                        new SqlLiteral {
                            FormattedSql = "TOP " + pagingInfo.PageSize + " "
                        },
                        raw.Selection ?? SqlSelectAll.Default
                    },
                    From = raw.From,
                    Where = raw.Where,
                    OrderBy = raw.OrderBy
                });
            }

            /*********************** 代码块解释 *********************************
             *
             * 转换方案:
             *
             * SELECT *
             * FROM ASN
             * WHERE ASN.Id > 0
             * ORDER BY ASN.AsnCode ASC
             *
             * 转换分页后:
             *
             * SELECT TOP 10 *
             * FROM ASN
             * WHERE ASN.Id > 0 AND ASN.Id NOT IN(
             *     SELECT TOP 20 Id
             *     FROM ASN
             *     WHERE ASN.Id > 0
             *     ORDER BY ASN.AsnCode ASC
             * )
             * ORDER BY ASN.AsnCode ASC
             *
             **********************************************************************/

            //先要找到主表的 PK,分页时需要使用此主键列来生成分页 Sql。
            //这里约定 Id 为主键列名。
            var finder   = new FirstTableFinder();
            var pkTable  = finder.Find(raw.From);
            var pkColumn = new SqlColumn {
                Table = pkTable, ColumnName = EntityConvention.IdColumnName
            };

            //先生成内部的 Select
            var excludeSelect = new SqlSelect
            {
                Selection = new SqlNodeList
                {
                    new SqlLiteral {
                        FormattedSql = "TOP " + (pagingInfo.PageNumber - 1) * pagingInfo.PageSize + " "
                    },
                    pkColumn
                },
                From    = raw.From,
                Where   = raw.Where,
                OrderBy = raw.OrderBy,
            };

            var res = new SqlSelect
            {
                Selection = new SqlNodeList
                {
                    new SqlLiteral {
                        FormattedSql = "TOP " + pagingInfo.PageSize + " "
                    },
                    raw.Selection ?? SqlSelectAll.Default
                },
                From    = raw.From,
                OrderBy = raw.OrderBy,
            };

            var newWhere = new SqlColumnConstraint
            {
                Column   = pkColumn,
                Operator = SqlColumnConstraintOperator.NotIn,
                Value    = excludeSelect
            };

            if (raw.Where != null)
            {
                res.Where = new SqlBinaryConstraint
                {
                    Left     = raw.Where,
                    Opeartor = SqlBinaryConstraintType.And,
                    Right    = newWhere
                };
            }
            else
            {
                res.Where = newWhere;
            }

            return(res);
        }
Exemplo n.º 4
0
        /// <summary>
        /// 为指定的原始查询生成指定分页效果的新查询。
        /// </summary>
        /// <param name="raw">原始查询</param>
        /// <param name="pagingInfo">分页信息。</param>
        /// <returns></returns>
        protected ISqlSelect ModifyToPagingTreeWithRowNumberOver(SqlSelect raw, PagingInfo pagingInfo)
        {
            if (PagingInfo.IsNullOrEmpty(pagingInfo))
            {
                throw new ArgumentNullException("pagingInfo");
            }
            if (!raw.HasOrdered())
            {
                throw new InvalidProgramException("必须排序后才能使用分页功能。");
            }

            //如果是第一页,则只需要使用 TOP 语句即可。
            if (pagingInfo.PageNumber == 1)
            {
                return(new SqlSelect
                {
                    Selection = new SqlNodeList
                    {
                        new SqlLiteral {
                            FormattedSql = "TOP " + pagingInfo.PageSize + " "
                        },
                        raw.Selection ?? SqlSelectAll.Default
                    },
                    From = raw.From,
                    Where = raw.Where,
                    OrderBy = raw.OrderBy
                });
            }

            /*********************** 代码块解释 *********************************
             *
             * 转换方案:
             *
             * SELECT *
             * FROM ASN
             * WHERE ASN.Id > 0
             * ORDER BY ASN.AsnCode ASC
             *
             * 转换分页后:
             *
             *      SELECT * FROM
             *      (
             *          SELECT A.*, ROW_NUMBER() OVER (order by  Id)_rowNumber
             *          FROM  A
             *      ) T
             *      WHERE _rowNumber between 1 and 10
             **********************************************************************/

            var newRaw = new SqlSelect
            {
                Selection = new SqlNodeList()
                {
                    new SqlLiteral {
                        FormattedSql = "ROW_NUMBER() OVER ("
                    },
                    raw.OrderBy,
                    new SqlLiteral {
                        FormattedSql = ")_rowNumber,"
                    },
                    raw.Selection ?? SqlSelectAll.Default
                },
                From       = raw.From,
                Where      = raw.Where,
                IsDistinct = raw.IsDistinct,
                IsCounting = raw.IsCounting,
            };
            var startRow = pagingInfo.PageSize * (pagingInfo.PageNumber - 1) + 1;
            var endRow   = startRow + pagingInfo.PageSize - 1;

            var res = MakePagingTree(newRaw, startRow, endRow);

            return(res);
        }
Exemplo n.º 5
0
        /// <summary>
        /// 为指定的原始查询生成指定分页效果的新查询。
        /// </summary>
        /// <param name="raw">原始查询</param>
        /// <param name="pagingInfo">分页信息。</param>
        /// <returns></returns>
        private ISqlSelect ModifyToPagingTree_With_RowNumber(SqlSelect raw, PagingInfo pagingInfo)
        {
            /*********************** 代码块解释 *********************************
             *
             * 转换方案:
             * 使用 ROW_NUMBER() 函数。(此函数 SqlServer、Oracle 都可使用。)
             *
             * SELECT *
             * FROM ASN
             * WHERE ASN.Id > 0
             * ORDER BY ASN.AsnCode ASC
             *
             * 转换分页后:
             *
             * SELECT * FROM
             * (
             *     SELECT A.*, ROW_NUMBER() OVER (order by  Id) _RowNumber
             *     FROM  A
             * ) T
             * WHERE _RowNumber BETWEEN 1 AND 10
             **********************************************************************/

            var finder  = new FirstTableFinder();
            var pkTable = finder.Find(raw.From);

            //在 Sql 分页的算法中,必须排序后才能使用分页功能,所以如果给定的 sql 中没有排序语句的话,则尝试使用任意表的一个默认的字段(Id)来进行排序。
            var orderBy = raw.OrderBy;

            if (!raw.HasOrdered())
            {
                if (SqlServerSqlGeneratorConfiguration.DefaultPagingSqlOrderbyColumn == null)
                {
                    throw new InvalidProgramException("必须提供排序语句后,才能使用分页功能。");
                }

                orderBy = new SqlOrderByList
                {
                    new SqlOrderBy
                    {
                        Column = new SqlColumn
                        {
                            Table      = pkTable,
                            ColumnName = SqlServerSqlGeneratorConfiguration.DefaultPagingSqlOrderbyColumn
                        }
                    }
                };
            }

            var newRaw = new SqlSelect
            {
                Selection = new SqlNodeList()
                {
                    raw.Selection ?? new SqlSelectAll()
                    {
                        Table = pkTable
                    },
                    new SqlLiteral {
                        FormattedSql = ", ROW_NUMBER() OVER ("
                    },
                    orderBy,
                    new SqlLiteral {
                        FormattedSql = ") _RowNumber "
                    }
                },
                From       = raw.From,
                Where      = raw.Where,
                IsDistinct = raw.IsDistinct,
                IsCounting = raw.IsCounting
            };
            var startRow = pagingInfo.PageSize * (pagingInfo.PageNumber - 1) + 1;
            var endRow   = startRow + pagingInfo.PageSize - 1;

            var res = new SqlNodeList
            {
                new SqlLiteral(
                    @"SELECT * FROM
("),
                newRaw,
                new SqlLiteral(
                    @")T WHERE _RowNumber BETWEEN " + startRow + @" AND " + endRow)
            };

            return(res);
        }
Exemplo n.º 6
0
        /// <summary>
        /// 为指定的原始查询生成指定分页效果的新查询。
        /// </summary>
        /// <param name="raw">原始查询</param>
        /// <param name="pkColumn">需要指定主键列</param>
        /// <param name="pagingInfo">分页信息。</param>
        /// <returns></returns>
        public virtual SqlSelect ModifyToPagingTree(SqlSelect raw, SqlColumn pkColumn, PagingInfo pagingInfo)
        {
            if (PagingInfo.IsNullOrEmpty(pagingInfo))
            {
                throw new ArgumentNullException("pagingInfo");
            }
            if (!raw.HasOrdered())
            {
                throw new InvalidProgramException("必须排序后才能使用分页功能。");
            }

            //如果是第一页,则只需要使用 TOP 语句即可。
            if (pagingInfo.PageNumber == 1)
            {
                raw.Top = pagingInfo.PageSize;
                return(raw);
            }

            /*********************** 代码块解释 *********************************
             *
             * 转换方案:
             *
             * SELECT *
             * FROM ASN
             * WHERE ASN.Id > 0
             * ORDER BY ASN.AsnCode ASC
             *
             * SELECT TOP 10 *
             * FROM ASN
             * WHERE ASN.Id > 0 AND ASN.Id NOT IN(
             *     SELECT TOP 20 Id
             *     FROM ASN
             *     WHERE ASN.Id > 0
             *     ORDER BY ASN.AsnCode ASC
             * )
             * ORDER BY ASN.AsnCode ASC
             *
             **********************************************************************/

            var excludeSelect = new SqlSelect
            {
                Top       = (pagingInfo.PageNumber - 1) * pagingInfo.PageSize,
                Selection = pkColumn,
                From      = raw.From,
                Where     = raw.Where,
                OrderBy   = raw.OrderBy,
            };

            var res = new SqlSelect
            {
                Top       = pagingInfo.PageSize,
                Selection = raw.Selection,
                From      = raw.From,
                OrderBy   = raw.OrderBy,
            };

            var newWhere = new SqlColumnConstraint
            {
                Column   = pkColumn,
                Operator = SqlColumnConstraintOperator.NotIn,
                Value    = excludeSelect
            };

            if (raw.Where != null)
            {
                res.Where = new SqlBinaryConstraint
                {
                    Left     = raw.Where,
                    Opeartor = SqlBinaryConstraintType.And,
                    Right    = newWhere
                };
            }
            else
            {
                res.Where = newWhere;
            }

            return(res);
        }
Exemplo n.º 7
0
        /// <summary>
        /// 为指定的原始查询生成指定分页效果的新查询。
        /// </summary>
        /// <param name="raw">原始查询</param>
        /// <param name="pagingInfo">分页信息。</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">pagingInfo</exception>
        /// <exception cref="System.InvalidProgramException">必须排序后才能使用分页功能。</exception>
        protected virtual ISqlSelect ModifyToPagingTree(SqlSelect raw, PagingInfo pagingInfo)
        {
            if (PagingInfo.IsNullOrEmpty(pagingInfo))
            {
                throw new ArgumentNullException("pagingInfo");
            }
            if (!raw.HasOrdered())
            {
                throw new InvalidProgramException("必须排序后才能使用分页功能。");
            }

            /*********************** 代码块解释 *********************************
             *
             * 使用 ROW_NUMBER() 函数,此函数 SqlServer、Oracle 都可使用。
             * 注意,这个方法只支持不太复杂 SQL 的转换。
             *
             * 源格式:
             * select ...... from ...... order by xxxx asc, yyyy desc
             * 不限于以上格式,只要满足没有复杂的嵌套查询,最外层是一个 Select 和 From 语句即可。
             *
             * 目标格式:
             * select * from (select ......, row_number() over(order by xxxx asc, yyyy desc) _rowNumber from ......) x where x._rowNumber<10 and x._rowNumber>5;
             **********************************************************************/

            var startRow = pagingInfo.PageSize * (pagingInfo.PageNumber - 1) + 1;
            var endRow   = startRow + pagingInfo.PageSize - 1;

            var innerSelect = new SqlSelect();
            var selection   = new SqlArray();

            if (raw.Selection != null)
            {
                selection.Items.Add(raw.Selection);
            }
            selection.Items.Add(new SqlNodeList
            {
                new SqlLiteral {
                    FormattedSql = "row_number() over ("
                },
                raw.OrderBy,
                new SqlLiteral {
                    FormattedSql = ") _rowNumber"
                }
            });
            innerSelect.Selection = selection;

            var subSelect = new SqlSubSelect
            {
                Select = innerSelect,
                Alias  = "x"
            };
            var rowNumberColumn = new SqlTree.SqlColumn
            {
                Table      = subSelect,
                ColumnName = "_rowNumber"
            };
            var pagingSelect = new SqlSelect();

            pagingSelect.From  = subSelect;
            pagingSelect.Where = new SqlTree.SqlBinaryConstraint
            {
                Left = new SqlTree.SqlColumnConstraint
                {
                    Column   = rowNumberColumn,
                    Operator = SqlColumnConstraintOperator.GreaterEqual,
                    Value    = startRow
                },
                Opeartor = SqlBinaryConstraintType.And,
                Right    = new SqlTree.SqlColumnConstraint
                {
                    Column   = rowNumberColumn,
                    Operator = SqlColumnConstraintOperator.LessEqual,
                    Value    = endRow
                }
            };

            return(pagingSelect);
        }