From bcc154ee4337b339af90ba9bec0472eac9846f12 Mon Sep 17 00:00:00 2001 From: 28810 <28810@YEXIANGQIN> Date: Mon, 9 Sep 2019 18:30:55 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=A2=9E=E5=8A=A0=20AsTable=20=E5=A4=9A?= =?UTF-8?q?=E6=AC=A1=EF=BC=8C=E5=8F=AF=E6=9F=A5=E8=AF=A2=E5=88=86=E8=A1=A8?= =?UTF-8?q?=E5=90=8E=E7=9A=84=E5=A4=9A=E4=B8=AA=E5=AD=90=E8=A1=A8=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=EF=BC=8C=E4=BB=A5=20UNION=20ALL=20=E5=BD=A2=E5=BC=8F?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ExpressionTree/GetAllTableRuleTest.cs | 34 ++ .../MySql/MapType/DateTimeOffSetTest.cs | 6 +- .../Sqlite/Curd/SqliteSelectTest.cs | 16 +- FreeSql.Tests/FreeSql.Tests/UnitTest1.cs | 3 + FreeSql/FreeSql.xml | 9 +- FreeSql/Interface/Curd/ISelect/ISelect0.cs | 9 +- .../SelectProvider/Select0Provider.cs | 12 +- FreeSql/Internal/CommonUtils.cs | 31 ++ .../Curd/MySqlSelect.cs | 144 +++---- .../Curd/OracleSelect.cs | 172 +++++---- .../Curd/PostgreSQLSelect.cs | 148 ++++---- .../Curd/SqlServerSelect.cs | 356 +++++++++--------- .../Curd/SqliteSelect.cs | 144 +++---- 13 files changed, 620 insertions(+), 464 deletions(-) create mode 100644 FreeSql.Tests/FreeSql.Tests/ExpressionTree/GetAllTableRuleTest.cs diff --git a/FreeSql.Tests/FreeSql.Tests/ExpressionTree/GetAllTableRuleTest.cs b/FreeSql.Tests/FreeSql.Tests/ExpressionTree/GetAllTableRuleTest.cs new file mode 100644 index 00000000..dcc5f640 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/ExpressionTree/GetAllTableRuleTest.cs @@ -0,0 +1,34 @@ +using FreeSql.DataAnnotations; +using FreeSql; +using System; +using System.Collections.Generic; +using Xunit; +using System.Linq; +using Newtonsoft.Json.Linq; +using NpgsqlTypes; +using Npgsql.LegacyPostgis; +using FreeSql.Internal; +using System.Linq.Expressions; +using FreeSql.Internal.Model; + +namespace FreeSql.ExpressionTree +{ + public class GetAllTableRuleTest + { + + [Fact] + public void Test() + { + //var _tables = new List + //{ + // [0] = new SelectTableInfo { } + //}; + //var tableRuleInvoke = new Func((type, oldname) => + //{ + // return new[] { oldname }; + //}); + + //CommonUtils.GetAllTableRule(_tables, tableRuleInvoke); + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/MapType/DateTimeOffSetTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/MapType/DateTimeOffSetTest.cs index 5f9e4c63..6c17e72d 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/MapType/DateTimeOffSetTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/MapType/DateTimeOffSetTest.cs @@ -13,7 +13,7 @@ namespace FreeSql.Tests.MySqlMapType [Column(MapType = typeof(DateTime))] public DateTimeOffset dtos_to_dt { get; set; } - [Column(MapType = typeof(DateTime))] + [Column(MapType = typeof(DateTime?))] public DateTimeOffset? dtosnullable_to_dt { get; set; } } [Fact] @@ -27,7 +27,7 @@ namespace FreeSql.Tests.MySqlMapType Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.dtos_to_dt.ToString("g"), find.dtos_to_dt.ToString("g")); - Assert.Equal(item.dtosnullable_to_dt.Value.ToString("g"), find.dtosnullable_to_dt.Value.ToString("g")); + Assert.Equal(item.dtosnullable_to_dt, find.dtosnullable_to_dt); //update all item.dtos_to_dt = DateTimeOffset.Now; @@ -36,7 +36,7 @@ namespace FreeSql.Tests.MySqlMapType Assert.NotNull(find); Assert.Equal(item.id, find.id); Assert.Equal(item.dtos_to_dt.ToString("g"), find.dtos_to_dt.ToString("g")); - Assert.Equal(item.dtosnullable_to_dt.Value.ToString("g"), find.dtosnullable_to_dt.Value.ToString("g")); + Assert.Equal(item.dtosnullable_to_dt, find.dtosnullable_to_dt); item.dtosnullable_to_dt = DateTimeOffset.Now; Assert.Equal(1, orm.Update().SetSource(item).ExecuteAffrows()); diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index 45e0f362..22f92795 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -790,10 +790,22 @@ namespace FreeSql.Tests.Sqlite else if (type == typeof(TestTypeInfo)) return oldname + "AsTable2"; return oldname + "AsTable"; }; + Func tableRule2 = (type, oldname) => + { + if (type == typeof(Topic)) return oldname + "Test2"; + else if (type == typeof(TestTypeInfo)) return oldname + "Test2"; + return oldname + "Test2"; + }; + var query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).AsTable(tableRule).AsTable(tableRule2); + var sql = query.ToSql(); + + query = select.AsTable((type, oldname) => "table_1").AsTable((type, oldname) => "table_2").AsTable((type, oldname) => "table_3"); + sql = query.ToSql(a => a.Id); + //����е�������a.Type��a.Type.Parent ���ǵ������� - var query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).AsTable(tableRule); - var sql = query.ToSql().Replace("\r\n", ""); + query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid).AsTable(tableRule); + sql = query.ToSql().Replace("\r\n", ""); Assert.Equal("SELECT a.\"Id\", a.\"Clicks\", a.\"TypeGuid\", a__Type.\"Guid\", a__Type.\"ParentId\", a__Type.\"Name\", a.\"Title\", a.\"CreateTime\" FROM \"tb_topic22AsTable1\" a LEFT JOIN \"TestTypeInfoAsTable2\" a__Type ON a__Type.\"Guid\" = a.\"TypeGuid\"", sql); query = select.LeftJoin(a => a.Type.Guid == a.TypeGuid && a.Type.Name == "xxx").AsTable(tableRule); diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs index a8af4dc3..4f95cf07 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest1.cs @@ -297,6 +297,7 @@ namespace FreeSql.Tests public bool OptionsEntity02 { get; set; } = false; public bool OptionsEntity03 { get; set; } = false; public int OptionsEntity04 { get; set; } + public int? score { get; set; } [Navigate("TbId")] public virtual ICollection Builds { get; set; } @@ -405,6 +406,8 @@ namespace FreeSql.Tests [Fact] public void Test1() { + var testorderbysql = g.mysql.Select().OrderByDescending(a => a.OptionsEntity04 + (a.score ?? 0)).ToSql(); + var testincludeMemberssql1 = g.sqlite.Select().Where(a => a.Templates.Title == "1").ToList(); var testincludeMemberssql2 = g.sqlite.Select().Include(a => a.Templates).ToList(); diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 37ba8ffe..140f0f0d 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -809,7 +809,14 @@ - 设置表名规则,可用于分库/分表,参数1:实体类型;参数2:默认表名;返回值:新表名; + 设置表名规则,可用于分库/分表,参数1:实体类型;参数2:默认表名;返回值:新表名; + 设置后可查询分表后的多个子表记录,以 UNION ALL 形式执行。 + 如:select.AsTable((type, oldname) => "table_1").AsTable((type, oldname) => "table_2").AsTable((type, oldname) => "table_3").ToSql(a => a.Id); + select * from (SELECT a."Id" as1 FROM "table_1" a) ftb + UNION ALL + select * from (SELECT a."Id" as1 FROM "table_2" a) ftb + UNION ALL + select * from (SELECT a."Id" as1 FROM "table_3" a) ftb diff --git a/FreeSql/Interface/Curd/ISelect/ISelect0.cs b/FreeSql/Interface/Curd/ISelect/ISelect0.cs index 09350041..9cef1fde 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect0.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect0.cs @@ -68,7 +68,14 @@ namespace FreeSql Task FirstAsync(); /// - /// 设置表名规则,可用于分库/分表,参数1:实体类型;参数2:默认表名;返回值:新表名; + /// 设置表名规则,可用于分库/分表,参数1:实体类型;参数2:默认表名;返回值:新表名; + /// 设置后可查询分表后的多个子表记录,以 UNION ALL 形式执行。 + /// 如:select.AsTable((type, oldname) => "table_1").AsTable((type, oldname) => "table_2").AsTable((type, oldname) => "table_3").ToSql(a => a.Id); + /// select * from (SELECT a."Id" as1 FROM "table_1" a) ftb + /// UNION ALL + /// select * from (SELECT a."Id" as1 FROM "table_2" a) ftb + /// UNION ALL + /// select * from (SELECT a."Id" as1 FROM "table_3" a) ftb /// /// /// diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 225c04c5..4cc1da5b 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -906,14 +906,16 @@ namespace FreeSql.Internal.CommonProvider return (map, field.ToString()); } - protected string TableRuleInvoke(Type type, string oldname) + protected string[] TableRuleInvoke(Type type, string oldname) { - for (var a = _tableRules.Count - 1; a >= 0; a--) + List newnames = new List(); + foreach (var tr in _tableRules) { - var newname = _tableRules[a]?.Invoke(type, oldname); - if (!string.IsNullOrEmpty(newname)) return newname; + var newname = tr?.Invoke(type, oldname); + if (!string.IsNullOrEmpty(newname)) newnames.Add(newname); } - return oldname; + if (newnames.Any() == false) return new[] { oldname }; + return newnames.Distinct().ToArray(); } public TSelect AsTable(Func tableRule) diff --git a/FreeSql/Internal/CommonUtils.cs b/FreeSql/Internal/CommonUtils.cs index a1bce7e8..034d3e45 100644 --- a/FreeSql/Internal/CommonUtils.cs +++ b/FreeSql/Internal/CommonUtils.cs @@ -363,5 +363,36 @@ namespace FreeSql.Internal } while (initConns.TryTake(out var conn)) pool.Return(conn); } + + public static List> GetAllTableRule(List _tables, Func tableRuleInvoke) + { + var tableRuleSorted = new List<(Type, string[])>(); + var tableRuleDict = new Dictionary(); + foreach(var tb in _tables) + { + if (tb.Type == SelectTableInfoType.Parent) continue; + if (tableRuleDict.ContainsKey(tb.Table.Type)) continue; + var names = tableRuleInvoke(tb.Table.Type, tb.Table.DbName); + tableRuleSorted.Add((tb.Table.Type, names)); + tableRuleDict.Add(tb.Table.Type, true); + } + var tableRules = new List>(); + tableRules.Add(tableRuleSorted.Select(a => (a.Item1, a.Item2.First())).ToDictionary(a => a.Item1, a => a.Item2)); + for (var z = tableRuleSorted.Count - 1; z >=0; z--) + { + var tbrd = tableRuleSorted[z]; + var curpos = tableRules.Count; + for (var a = 1; a < tbrd.Item2.Length; a++) + { + for (var b = 0; b < curpos; b++) + { + var tr = new Dictionary(); + foreach (var oldtd in tableRules[b]) tr.Add(oldtd.Key, tbrd.Item1 == oldtd.Key ? tbrd.Item2[a] : oldtd.Value); + tableRules.Add(tr); + } + } + } + return tableRules; + } } } diff --git a/Providers/FreeSql.Provider.MySql/Curd/MySqlSelect.cs b/Providers/FreeSql.Provider.MySql/Curd/MySqlSelect.cs index 6c5557ba..68cf90b9 100644 --- a/Providers/FreeSql.Provider.MySql/Curd/MySqlSelect.cs +++ b/Providers/FreeSql.Provider.MySql/Curd/MySqlSelect.cs @@ -12,7 +12,7 @@ namespace FreeSql.MySql.Curd class MySqlSelect : FreeSql.Internal.CommonProvider.Select1Provider where T1 : class { - internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) + internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) { if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); @@ -22,85 +22,95 @@ namespace FreeSql.MySql.Curd tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression); var sb = new StringBuilder(); - var sbnav = new StringBuilder(); - sb.Append(_select); - if (_distinct) sb.Append("DISTINCT "); - sb.Append(field).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++) + var tbrules = CommonUtils.GetAllTableRule(_tables, tableRuleInvoke); + var tbrulesGt0 = tbrules.Count > 1; + for (var tbrulesIdx = 0; tbrulesIdx < tbrules.Count; tbrulesIdx++) { - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias); - if (tbsjoin.Length > 0) + if (tbrulesIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n"); + if (tbrulesGt0) sb.Append("select * from ("); + var tbrule = tbrules[tbrulesIdx]; + + var sbnav = new StringBuilder(); + sb.Append(_select); + if (_distinct) sb.Append("DISTINCT "); + sb.Append(field).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++) { - //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 - for (var b = 1; b < tbsfrom.Length; b++) + sb.Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[a].Table.Type])).Append(" ").Append(tbsfrom[a].Alias); + if (tbsjoin.Length > 0) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias); - - if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); - else + //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 + for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); - if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[b].Table.Type])).Append(" ").Append(tbsfrom[b].Alias); + + if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); + else + { + sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); + if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + } } + break; } - break; + else + { + if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); + if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); + if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + } + if (a < tbsfrom.Length - 1) sb.Append(", "); } - else + foreach (var tb in tbsjoin) { - if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); - if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); - if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + 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(tbrule[tb.Table.Type])).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); + if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } - if (a < tbsfrom.Length - 1) sb.Append(", "); - } - foreach (var tb in tbsjoin) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - switch (tb.Type) + if (_join.Length > 0) sb.Append(_join); + + sbnav.Append(_where); + if (!string.IsNullOrEmpty(_tables[0].Cascade)) + sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); + + foreach (var tb in _tables) { - 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; + if (tb.Type == SelectTableInfoType.Parent) continue; + if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) + sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); } - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); - if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); - if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); - } - if (_join.Length > 0) sb.Append(_join); + if (sbnav.Length > 0) + { + sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); + } + if (string.IsNullOrEmpty(_groupby) == false) + { + sb.Append(_groupby); + if (string.IsNullOrEmpty(_having) == false) + sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); + } + sb.Append(_orderby); + if (_skip > 0 || _limit > 0) + sb.Append(" \r\nlimit ").Append(Math.Max(0, _skip)).Append(",").Append(_limit > 0 ? _limit : -1); - sbnav.Append(_where); - if (!string.IsNullOrEmpty(_tables[0].Cascade)) - sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); - - foreach (var tb in _tables) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) - sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + sbnav.Clear(); + if (tbrulesGt0) sb.Append(") ftb"); } - if (sbnav.Length > 0) - { - sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); - } - if (string.IsNullOrEmpty(_groupby) == false) - { - sb.Append(_groupby); - if (string.IsNullOrEmpty(_having) == false) - sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); - } - sb.Append(_orderby); - if (_skip > 0 || _limit > 0) - sb.Append(" \r\nlimit ").Append(Math.Max(0, _skip)).Append(",").Append(_limit > 0 ? _limit : -1); - - sbnav.Clear(); return sb.ToString(); } diff --git a/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs b/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs index 14911f36..a2d6904c 100644 --- a/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs +++ b/Providers/FreeSql.Provider.Oracle/Curd/OracleSelect.cs @@ -12,7 +12,7 @@ namespace FreeSql.Oracle.Curd class OracleSelect : FreeSql.Internal.CommonProvider.Select1Provider where T1 : class { - internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) + internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) { if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); @@ -22,97 +22,107 @@ namespace FreeSql.Oracle.Curd tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression); var sb = new StringBuilder(); - var sbnav = new StringBuilder(); - sb.Append(_select); - if (_distinct) sb.Append("DISTINCT "); - sb.Append(field); - if (string.IsNullOrEmpty(_orderby) && _skip > 0) sb.Append(", ROWNUM AS \"__rownum__\""); - 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++) + var tbrules = CommonUtils.GetAllTableRule(_tables, tableRuleInvoke); + var tbrulesGt0 = tbrules.Count > 1; + for (var tbrulesIdx = 0; tbrulesIdx < tbrules.Count; tbrulesIdx++) { - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, 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(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias); + if (tbrulesIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n"); + if (tbrulesGt0) sb.Append("select * from ("); + var tbrule = tbrules[tbrulesIdx]; - if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); - else + var sbnav = new StringBuilder(); + sb.Append(_select); + if (_distinct) sb.Append("DISTINCT "); + sb.Append(field); + if (string.IsNullOrEmpty(_orderby) && _skip > 0) sb.Append(", ROWNUM AS \"__rownum__\""); + 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(tbrule[tbsfrom[a].Table.Type])).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(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); - if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[b].Table.Type])).Append(" ").Append(tbsfrom[b].Alias); + + if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); + else + { + sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); + if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + } } + break; } - break; + else + { + if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); + if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); + if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + } + 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(tbrule[tb.Table.Type])).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); + if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); + } + if (_join.Length > 0) sb.Append(_join); + + sbnav.Append(_where); + if (!string.IsNullOrEmpty(_tables[0].Cascade)) + sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); + + foreach (var tb in _tables) + { + if (tb.Type == SelectTableInfoType.Parent) continue; + if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) + sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + } + if (string.IsNullOrEmpty(_orderby) && (_skip > 0 || _limit > 0)) + sbnav.Append(" AND ROWNUM < ").Append(_skip + _limit + 1); + if (sbnav.Length > 0) + sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); + if (string.IsNullOrEmpty(_groupby) == false) + { + sb.Append(_groupby); + if (string.IsNullOrEmpty(_having) == false) + sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); + } + sb.Append(_orderby); + + if (string.IsNullOrEmpty(_orderby)) + { + if (_skip > 0) + sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE t.\"__rownum__\" > ").Append(_skip); } else { - if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); - if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); - if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + if (_skip > 0 && _limit > 0) sb.Insert(0, "SELECT t.* FROM (SELECT rt.*, ROWNUM AS \"__rownum__\" FROM (").Append(") rt WHERE ROWNUM < ").Append(_skip + _limit + 1).Append(") t WHERE t.\"__rownum__\" > ").Append(_skip); + else if (_skip > 0) sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE ROWNUM > ").Append(_skip); + else if (_limit > 0) sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE ROWNUM < ").Append(_limit + 1); } - 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(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); - if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); - if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); - } - if (_join.Length > 0) sb.Append(_join); - sbnav.Append(_where); - if (!string.IsNullOrEmpty(_tables[0].Cascade)) - sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); - - foreach (var tb in _tables) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) - sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + sbnav.Clear(); + if (tbrulesGt0) sb.Append(") ftb"); } - if (string.IsNullOrEmpty(_orderby) && (_skip > 0 || _limit > 0)) - sbnav.Append(" AND ROWNUM < ").Append(_skip + _limit + 1); - if (sbnav.Length > 0) - sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); - if (string.IsNullOrEmpty(_groupby) == false) - { - sb.Append(_groupby); - if (string.IsNullOrEmpty(_having) == false) - sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); - } - sb.Append(_orderby); - - if (string.IsNullOrEmpty(_orderby)) - { - if (_skip > 0) - sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE t.\"__rownum__\" > ").Append(_skip); - } - else - { - if (_skip > 0 && _limit > 0) sb.Insert(0, "SELECT t.* FROM (SELECT rt.*, ROWNUM AS \"__rownum__\" FROM (").Append(") rt WHERE ROWNUM < ").Append(_skip + _limit + 1).Append(") t WHERE t.\"__rownum__\" > ").Append(_skip); - else if (_skip > 0) sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE ROWNUM > ").Append(_skip); - else if (_limit > 0) sb.Insert(0, "SELECT t.* FROM (").Append(") t WHERE ROWNUM < ").Append(_limit + 1); - } - - sbnav.Clear(); return sb.ToString(); } diff --git a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLSelect.cs b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLSelect.cs index 21d9eca8..77672c61 100644 --- a/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLSelect.cs +++ b/Providers/FreeSql.Provider.PostgreSQL/Curd/PostgreSQLSelect.cs @@ -12,7 +12,7 @@ namespace FreeSql.PostgreSQL.Curd class PostgreSQLSelect : FreeSql.Internal.CommonProvider.Select1Provider where T1 : class { - internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) + internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) { if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); @@ -22,87 +22,97 @@ namespace FreeSql.PostgreSQL.Curd tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression); var sb = new StringBuilder(); - var sbnav = new StringBuilder(); - sb.Append(_select); - if (_distinct) sb.Append("DISTINCT "); - sb.Append(field).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++) + var tbrules = CommonUtils.GetAllTableRule(_tables, tableRuleInvoke); + var tbrulesGt0 = tbrules.Count > 1; + for (var tbrulesIdx = 0; tbrulesIdx < tbrules.Count; tbrulesIdx++) { - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias); - if (tbsjoin.Length > 0) + if (tbrulesIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n"); + if (tbrulesGt0) sb.Append("select * from ("); + var tbrule = tbrules[tbrulesIdx]; + + var sbnav = new StringBuilder(); + sb.Append(_select); + if (_distinct) sb.Append("DISTINCT "); + sb.Append(field).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++) { - //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 - for (var b = 1; b < tbsfrom.Length; b++) + sb.Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[a].Table.Type])).Append(" ").Append(tbsfrom[a].Alias); + if (tbsjoin.Length > 0) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias); - - if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); - else + //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 + for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); - if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[b].Table.Type])).Append(" ").Append(tbsfrom[b].Alias); + + if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); + else + { + sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); + if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + } } + break; } - break; + else + { + if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); + if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); + if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + } + if (a < tbsfrom.Length - 1) sb.Append(", "); } - else + foreach (var tb in tbsjoin) { - if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); - if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); - if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + 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(tbrule[tb.Table.Type])).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); + if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } - if (a < tbsfrom.Length - 1) sb.Append(", "); - } - foreach (var tb in tbsjoin) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - switch (tb.Type) + if (_join.Length > 0) sb.Append(_join); + + sbnav.Append(_where); + if (!string.IsNullOrEmpty(_tables[0].Cascade)) + sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); + + foreach (var tb in _tables) { - 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; + if (tb.Type == SelectTableInfoType.Parent) continue; + if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) + sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); } - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); - if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); - if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); - } - if (_join.Length > 0) sb.Append(_join); + if (sbnav.Length > 0) + { + sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); + } + if (string.IsNullOrEmpty(_groupby) == false) + { + sb.Append(_groupby); + if (string.IsNullOrEmpty(_having) == false) + sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); + } + sb.Append(_orderby); + if (_limit > 0) + sb.Append(" \r\nlimit ").Append(_limit); + if (_skip > 0) + sb.Append(" \r\noffset ").Append(_skip); - sbnav.Append(_where); - if (!string.IsNullOrEmpty(_tables[0].Cascade)) - sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); - - foreach (var tb in _tables) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) - sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + sbnav.Clear(); + if (tbrulesGt0) sb.Append(") ftb"); } - if (sbnav.Length > 0) - { - sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); - } - if (string.IsNullOrEmpty(_groupby) == false) - { - sb.Append(_groupby); - if (string.IsNullOrEmpty(_having) == false) - sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); - } - sb.Append(_orderby); - if (_limit > 0) - sb.Append(" \r\nlimit ").Append(_limit); - if (_skip > 0) - sb.Append(" \r\noffset ").Append(_skip); - - sbnav.Clear(); return sb.ToString(); } diff --git a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs index 4228689a..620bc333 100644 --- a/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs +++ b/Providers/FreeSql.Provider.SqlServer/Curd/SqlServerSelect.cs @@ -12,13 +12,13 @@ namespace FreeSql.SqlServer.Curd class SqlServerSelect : FreeSql.Internal.CommonProvider.Select1Provider where T1 : class { - internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) + internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) => (_commonUtils as SqlServerUtils).IsSelectRowNumber ? ToSqlStaticRowNumber(_commonUtils, _commonExpression, _select, _distinct, field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, tableRuleInvoke, _whereCascadeExpression, _orm) : ToSqlStaticOffsetFetchNext(_commonUtils, _commonExpression, _select, _distinct, field, _join, _where, _groupby, _having, _orderby, _skip, _limit, _tables, tableRuleInvoke, _whereCascadeExpression, _orm); #region SqlServer 2005 row_number - internal static string ToSqlStaticRowNumber(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) + internal static string ToSqlStaticRowNumber(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) { if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); @@ -28,104 +28,114 @@ namespace FreeSql.SqlServer.Curd tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression); var sb = new StringBuilder(); - var sbnav = new StringBuilder(); - sb.Append(_select); - if (_distinct) sb.Append("DISTINCT "); - if (_limit > 0) sb.Append("TOP ").Append(_skip + _limit).Append(" "); - sb.Append(field); - if (_skip > 0) + var tbrules = CommonUtils.GetAllTableRule(_tables, tableRuleInvoke); + var tbrulesGt0 = tbrules.Count > 1; + for (var tbrulesIdx = 0; tbrulesIdx < tbrules.Count; tbrulesIdx++) { - if (string.IsNullOrEmpty(_orderby)) + if (tbrulesIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n"); + if (tbrulesGt0) sb.Append("select * from ("); + var tbrule = tbrules[tbrulesIdx]; + + var sbnav = new StringBuilder(); + sb.Append(_select); + if (_distinct) sb.Append("DISTINCT "); + if (_limit > 0) sb.Append("TOP ").Append(_skip + _limit).Append(" "); + sb.Append(field); + if (_skip > 0) { - 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(", ROW_NUMBER() OVER(").Append(_orderby).Append(") AS __rownum__"); - } - 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(tableRuleInvoke(tbsfrom[a].Table.Type, 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++) + if (string.IsNullOrEmpty(_orderby)) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias); - - if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); - else - { - sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); - if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); - } + 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)); } - break; + sb.Append(", ROW_NUMBER() OVER(").Append(_orderby).Append(") AS __rownum__"); } + 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(tbrule[tbsfrom[a].Table.Type])).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(tbrule[tbsfrom[b].Table.Type])).Append(" ").Append(tbsfrom[b].Alias); + + if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); + else + { + sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); + if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + } + } + break; + } + else + { + if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); + if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); + if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + } + 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(tbrule[tb.Table.Type])).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); + if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); + } + if (_join.Length > 0) sb.Append(_join); + + sbnav.Append(_where); + if (!string.IsNullOrEmpty(_tables[0].Cascade)) + sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); + + foreach (var tb in _tables) + { + if (tb.Type == SelectTableInfoType.Parent) continue; + if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) + sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + } + if (sbnav.Length > 0) + { + sb.Append(" \r\nWHERE ").Append(sbnav.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) + sb.Append(_orderby); else - { - if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); - if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); - if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); - } - 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(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); - if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); - if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); - } - if (_join.Length > 0) sb.Append(_join); + sb.Insert(0, "WITH t AS ( ").Append(" ) SELECT t.* FROM t where __rownum__ > ").Append(_skip); - sbnav.Append(_where); - if (!string.IsNullOrEmpty(_tables[0].Cascade)) - sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); - - foreach (var tb in _tables) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) - sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + sbnav.Clear(); + if (tbrulesGt0) sb.Append(") ftb"); } - if (sbnav.Length > 0) - { - sb.Append(" \r\nWHERE ").Append(sbnav.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) - sb.Append(_orderby); - else - sb.Insert(0, "WITH t AS ( ").Append(" ) SELECT t.* FROM t where __rownum__ > ").Append(_skip); - - sbnav.Clear(); return sb.ToString(); } #endregion #region SqlServer 2012+ offset feach next - internal static string ToSqlStaticOffsetFetchNext(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) + internal static string ToSqlStaticOffsetFetchNext(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) { if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); @@ -135,99 +145,109 @@ namespace FreeSql.SqlServer.Curd tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression); var sb = new StringBuilder(); - var sbnav = new StringBuilder(); - sb.Append(_select); - if (_distinct) sb.Append("DISTINCT "); - 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++) + var tbrules = CommonUtils.GetAllTableRule(_tables, tableRuleInvoke); + var tbrulesGt0 = tbrules.Count > 1; + for (var tbrulesIdx = 0; tbrulesIdx < tbrules.Count; tbrulesIdx++) { - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias); - if (tbsjoin.Length > 0) + if (tbrulesIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n"); + if (tbrulesGt0) sb.Append("select * from ("); + var tbrule = tbrules[tbrulesIdx]; + + var sbnav = new StringBuilder(); + sb.Append(_select); + if (_distinct) sb.Append("DISTINCT "); + 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++) { - //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 - for (var b = 1; b < tbsfrom.Length; b++) + sb.Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[a].Table.Type])).Append(" ").Append(tbsfrom[a].Alias); + if (tbsjoin.Length > 0) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias); - - if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); - else + //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 + for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); - if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[b].Table.Type])).Append(" ").Append(tbsfrom[b].Alias); + + if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); + else + { + sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); + if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + } } + break; } - break; + else + { + if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); + if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); + if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + } + 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(tbrule[tb.Table.Type])).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); + if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); + } + if (_join.Length > 0) sb.Append(_join); + + sbnav.Append(_where); + if (!string.IsNullOrEmpty(_tables[0].Cascade)) + sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); + + foreach (var tb in _tables) + { + if (tb.Type == SelectTableInfoType.Parent) continue; + if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) + sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + } + if (sbnav.Length > 0) + { + sb.Append(" \r\nWHERE ").Append(sbnav.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 { - if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); - if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); - if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + sb.Append(_orderby); } - 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(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); - if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); - if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); - } - if (_join.Length > 0) sb.Append(_join); - sbnav.Append(_where); - if (!string.IsNullOrEmpty(_tables[0].Cascade)) - sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); - - foreach (var tb in _tables) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) - sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + sbnav.Clear(); + if (tbrulesGt0) sb.Append(") ftb"); } - if (sbnav.Length > 0) - { - sb.Append(" \r\nWHERE ").Append(sbnav.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); - } - - sbnav.Clear(); return sb.ToString(); } #endregion diff --git a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteSelect.cs b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteSelect.cs index 20b2e833..463c593f 100644 --- a/Providers/FreeSql.Provider.Sqlite/Curd/SqliteSelect.cs +++ b/Providers/FreeSql.Provider.Sqlite/Curd/SqliteSelect.cs @@ -12,7 +12,7 @@ namespace FreeSql.Sqlite.Curd class SqliteSelect : FreeSql.Internal.CommonProvider.Select1Provider where T1 : class { - internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) + internal static string ToSqlStatic(CommonUtils _commonUtils, CommonExpression _commonExpression, string _select, bool _distinct, string field, StringBuilder _join, StringBuilder _where, string _groupby, string _having, string _orderby, int _skip, int _limit, List _tables, Func tableRuleInvoke, List _whereCascadeExpression, IFreeSql _orm) { if (_orm.CodeFirst.IsAutoSyncStructure) _orm.CodeFirst.SyncStructure(_tables.Select(a => a.Table.Type).ToArray()); @@ -22,85 +22,95 @@ namespace FreeSql.Sqlite.Curd tb.Cascade = _commonExpression.GetWhereCascadeSql(tb, _whereCascadeExpression); var sb = new StringBuilder(); - var sbnav = new StringBuilder(); - sb.Append(_select); - if (_distinct) sb.Append("DISTINCT "); - sb.Append(field).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++) + var tbrules = CommonUtils.GetAllTableRule(_tables, tableRuleInvoke); + var tbrulesGt0 = tbrules.Count > 1; + for (var tbrulesIdx = 0; tbrulesIdx < tbrules.Count; tbrulesIdx++) { - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[a].Table.Type, tbsfrom[a].Table.DbName))).Append(" ").Append(tbsfrom[a].Alias); - if (tbsjoin.Length > 0) + if (tbrulesIdx > 0) sb.Append(" \r\n\r\nUNION ALL\r\n\r\n"); + if (tbrulesGt0) sb.Append("select * from ("); + var tbrule = tbrules[tbrulesIdx]; + + var sbnav = new StringBuilder(); + sb.Append(_select); + if (_distinct) sb.Append("DISTINCT "); + sb.Append(field).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++) { - //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 - for (var b = 1; b < tbsfrom.Length; b++) + sb.Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[a].Table.Type])).Append(" ").Append(tbsfrom[a].Alias); + if (tbsjoin.Length > 0) { - sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tbsfrom[b].Table.Type, tbsfrom[b].Table.DbName))).Append(" ").Append(tbsfrom[b].Alias); - - if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); - else + //如果存在 join 查询,则处理 from t1, t2 改为 from t1 inner join t2 on 1 = 1 + for (var b = 1; b < tbsfrom.Length; b++) { - sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); - if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + sb.Append(" \r\nLEFT JOIN ").Append(_commonUtils.QuoteSqlName(tbrule[tbsfrom[b].Table.Type])).Append(" ").Append(tbsfrom[b].Alias); + + if (string.IsNullOrEmpty(tbsfrom[b].NavigateCondition) && string.IsNullOrEmpty(tbsfrom[b].On) && string.IsNullOrEmpty(tbsfrom[b].Cascade)) sb.Append(" ON 1 = 1"); + else + { + sb.Append(" ON ").Append(tbsfrom[b].NavigateCondition ?? tbsfrom[b].On); + if (string.IsNullOrEmpty(tbsfrom[b].Cascade) == false) sb.Append(" AND (").Append(tbsfrom[b].Cascade).Append(")"); + } } + break; } - break; + else + { + if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); + if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); + if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + } + if (a < tbsfrom.Length - 1) sb.Append(", "); } - else + foreach (var tb in tbsjoin) { - if (!string.IsNullOrEmpty(tbsfrom[a].NavigateCondition)) sbnav.Append(" AND (").Append(tbsfrom[a].NavigateCondition).Append(")"); - if (!string.IsNullOrEmpty(tbsfrom[a].On)) sbnav.Append(" AND (").Append(tbsfrom[a].On).Append(")"); - if (a > 0 && !string.IsNullOrEmpty(tbsfrom[a].Cascade)) sbnav.Append(" AND (").Append(tbsfrom[a].Cascade).Append(")"); + 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(tbrule[tb.Table.Type])).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); + if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); + if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); } - if (a < tbsfrom.Length - 1) sb.Append(", "); - } - foreach (var tb in tbsjoin) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - switch (tb.Type) + if (_join.Length > 0) sb.Append(_join); + + sbnav.Append(_where); + if (!string.IsNullOrEmpty(_tables[0].Cascade)) + sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); + + foreach (var tb in _tables) { - 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; + if (tb.Type == SelectTableInfoType.Parent) continue; + if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) + sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); } - sb.Append(_commonUtils.QuoteSqlName(tableRuleInvoke(tb.Table.Type, tb.Table.DbName))).Append(" ").Append(tb.Alias).Append(" ON ").Append(tb.On ?? tb.NavigateCondition); - if (!string.IsNullOrEmpty(tb.Cascade)) sb.Append(" AND (").Append(tb.Cascade).Append(")"); - if (!string.IsNullOrEmpty(tb.On) && !string.IsNullOrEmpty(tb.NavigateCondition)) sbnav.Append(" AND (").Append(tb.NavigateCondition).Append(")"); - } - if (_join.Length > 0) sb.Append(_join); + if (sbnav.Length > 0) + { + sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); + } + if (string.IsNullOrEmpty(_groupby) == false) + { + sb.Append(_groupby); + if (string.IsNullOrEmpty(_having) == false) + sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); + } + sb.Append(_orderby); + if (_skip > 0 || _limit > 0) + sb.Append(" \r\nlimit ").Append(Math.Max(0, _skip)).Append(",").Append(_limit > 0 ? _limit : -1); - sbnav.Append(_where); - if (!string.IsNullOrEmpty(_tables[0].Cascade)) - sbnav.Append(" AND (").Append(_tables[0].Cascade).Append(")"); - - foreach (var tb in _tables) - { - if (tb.Type == SelectTableInfoType.Parent) continue; - if (string.IsNullOrEmpty(tb.Table.SelectFilter) == false) - sbnav.Append(" AND (").Append(tb.Table.SelectFilter.Replace("a.", $"{tb.Alias}.")).Append(")"); + sbnav.Clear(); + if (tbrulesGt0) sb.Append(") ftb"); } - if (sbnav.Length > 0) - { - sb.Append(" \r\nWHERE ").Append(sbnav.Remove(0, 5)); - } - if (string.IsNullOrEmpty(_groupby) == false) - { - sb.Append(_groupby); - if (string.IsNullOrEmpty(_having) == false) - sb.Append(" \r\nHAVING ").Append(_having.Substring(5)); - } - sb.Append(_orderby); - if (_skip > 0 || _limit > 0) - sb.Append(" \r\nlimit ").Append(Math.Max(0, _skip)).Append(",").Append(_limit > 0 ? _limit : -1); - - sbnav.Clear(); return sb.ToString(); }