From be84f6dbd62ce9c344e41156463b11d13a307bb4 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Thu, 21 Feb 2019 14:30:51 +0800 Subject: [PATCH] add sqlserver2012+ offset fetch next --- FreeSql/SqlServer/Curd/SqlServerSelect.cs | 79 ++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/FreeSql/SqlServer/Curd/SqlServerSelect.cs b/FreeSql/SqlServer/Curd/SqlServerSelect.cs index 658ae0ea..31dd47c8 100644 --- a/FreeSql/SqlServer/Curd/SqlServerSelect.cs +++ b/FreeSql/SqlServer/Curd/SqlServerSelect.cs @@ -10,7 +10,11 @@ namespace FreeSql.SqlServer.Curd { class SqlServerSelect : FreeSql.Internal.CommonProvider.Select1Provider where T1 : class { - internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, IFreeSql _orm) { + internal static string ToSqlStatic(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, IFreeSql _orm) + => ToSqlStaticRowNumber(_commonUtils, _select, field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, _orm); + + #region SqlServer 2005 row_number + internal static string ToSqlStaticRowNumber(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, IFreeSql _orm) { if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); @@ -80,6 +84,79 @@ namespace FreeSql.SqlServer.Curd { return sb.ToString(); } + #endregion + + #region SqlServer 2012+ offset feach next + internal static string ToSqlStaticOffsetFetchNext(CommonUtils _commonUtils, string _select, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, IFreeSql _orm) { + if (_orm.CodeFirst.IsAutoSyncStructure) + _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); + + var sb = new StringBuilder(); + sb.Append(_select); + if (_skip <= 0 && _limit > 0) sb.Append("TOP ").Append(_limit).Append(" "); + sb.Append(field); + sb.Append(" \r\nFROM "); + var tbsjoin = _tables.Where(a => a.Type != SelectTableInfoType.From).ToArray(); + var tbsfrom = _tables.Where(a => a.Type == SelectTableInfoType.From).ToArray(); + for (var a = 0; a < tbsfrom.Length; a++) { + sb.Append(_commonUtils.QuoteSqlName(tbsfrom[a].Table.DbName)).Append(" ").Append(tbsfrom[a].Alias); + if (tbsjoin.Length > 0) { + //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 + for (var b = 1; b < tbsfrom.Length; b++) + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbsfrom[b].Table.DbName)).Append(" ").Append(tbsfrom[b].Alias).Append(" ON 1 = 1"); + break; + } + if (a < tbsfrom.Length - 1) sb.Append(", "); + } + foreach (var tb in tbsjoin) { + if (tb.Type == SelectTableInfoType.Parent) continue; + switch (tb.Type) { + case SelectTableInfoType.LeftJoin: + sb.Append(" \r\nLEFT JOIN "); + break; + case SelectTableInfoType.InnerJoin: + sb.Append(" \r\nINNER JOIN "); + break; + case SelectTableInfoType.RightJoin: + sb.Append(" \r\nRIGHT JOIN "); + break; + } + sb.Append(_commonUtils.QuoteSqlName(tb.Table.DbName)).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On); + } + if (_join.Length > 0) sb.Append(_join); + + var sbqf = new StringBuilder(); + foreach (var tb in _tables) { + if (tb.Type == SelectTableInfoType.Parent) continue; + if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) + sbqf.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + } + if (_where.Length > 0) { + sb.Append(" \r\nWHERE ").Append(_where.ToString().Substring(5)); + if (sbqf.Length > 0) sb.Append(sbqf.ToString()); + } else { + if (sbqf.Length > 0) sb.Append(" \r\nWHERE ").Append(sbqf.Remove(0, 5)); + } + if (string.IsNullOrEmpty(_groupby) == false) { + sb.Append(_groupby); + if (string.IsNullOrEmpty(_having) == false) + sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); + } + if (_skip > 0) { + if (string.IsNullOrEmpty(_orderby)) { + var pktb = _tables.Where(a => a.Table.Primarys.Any()).FirstOrDefault(); + if (pktb != null) _orderby = string.Concat(" \r\nORDER BY ", pktb.Alias, ".", _commonUtils.QuoteSqlName(pktb?.Table.Primarys.First().Attribute.Name)); + else _orderby = string.Concat(" \r\nORDER BY ", _tables.First().Alias, ".", _commonUtils.QuoteSqlName(_tables.First().Table.Columns.First().Value.Attribute.Name)); + } + sb.Append(_orderby).Append($" \r\nOFFSET {_skip} ROW"); + if (_limit > 0) sb.Append($" \r\nFETCH NEXT {_limit} ROW ONLY"); + } else { + sb.Append(_orderby); + } + + return sb.ToString(); + } + #endregion public SqlServerSelect(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) : base(orm, commonUtils, commonExpression, dywhere) { } public override ISelect From(Expression, T2, T3, ISelectFromExpression>> exp) { this.InternalFrom(exp?.Body); var ret = new SqlServerSelect(_orm, _commonUtils, _commonExpression, null); SqlServerSelect.CopyData(this, ret); return ret; }