mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 18:52:50 +08:00
- 优化 AsTreeCte 对 MySql 5.6 的兼容;#536
This commit is contained in:
parent
cf60f26759
commit
bbc4f91d9b
@ -509,14 +509,5 @@
|
|||||||
<param name="that"></param>
|
<param name="that"></param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
<member name="M:Microsoft.Extensions.DependencyInjection.FreeSqlRepositoryDependencyInjection.AddFreeRepository(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Action{FreeSql.FluentDataFilter},System.Reflection.Assembly[])">
|
|
||||||
<summary>
|
|
||||||
批量注入 Repository,可以参考代码自行调整
|
|
||||||
</summary>
|
|
||||||
<param name="services"></param>
|
|
||||||
<param name="globalDataFilter"></param>
|
|
||||||
<param name="assemblies"></param>
|
|
||||||
<returns></returns>
|
|
||||||
</member>
|
|
||||||
</members>
|
</members>
|
||||||
</doc>
|
</doc>
|
||||||
|
@ -1989,43 +1989,49 @@ WHERE ((b.`IsFinished` OR a.`TaskType` = 3) AND b.`EnabledMark` = 1)", groupsql1
|
|||||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||||
|
|
||||||
//t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte().OrderBy(a => a.Code).ToTreeList();
|
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte().OrderBy(a => a.Code).ToTreeList();
|
||||||
//Assert.Single(t3);
|
Assert.Single(t3);
|
||||||
//Assert.Equal("100000", t3[0].Code);
|
Assert.Equal("100000", t3[0].Code);
|
||||||
//Assert.Single(t3[0].Childs);
|
Assert.Single(t3[0].Childs);
|
||||||
//Assert.Equal("110000", t3[0].Childs[0].Code);
|
Assert.Equal("110000", t3[0].Childs[0].Code);
|
||||||
//Assert.Equal(2, t3[0].Childs[0].Childs.Count);
|
Assert.Equal(2, t3[0].Childs[0].Childs.Count);
|
||||||
//Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||||
//Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||||
|
|
||||||
//t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte().OrderBy(a => a.Code).ToList();
|
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte().OrderBy(a => a.Code).ToList();
|
||||||
//Assert.Equal(4, t3.Count);
|
Assert.Equal(4, t3.Count);
|
||||||
//Assert.Equal("100000", t3[0].Code);
|
Assert.Equal("100000", t3[0].Code);
|
||||||
//Assert.Equal("110000", t3[1].Code);
|
Assert.Equal("110000", t3[1].Code);
|
||||||
//Assert.Equal("110100", t3[2].Code);
|
Assert.Equal("110100", t3[2].Code);
|
||||||
//Assert.Equal("110101", t3[3].Code);
|
Assert.Equal("110101", t3[3].Code);
|
||||||
|
|
||||||
//t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsTreeCte().OrderBy(a => a.Code).ToList();
|
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsTreeCte().OrderBy(a => a.Code).ToList();
|
||||||
//Assert.Equal(3, t3.Count);
|
Assert.Equal(3, t3.Count);
|
||||||
//Assert.Equal("110000", t3[0].Code);
|
Assert.Equal("110000", t3[0].Code);
|
||||||
//Assert.Equal("110100", t3[1].Code);
|
Assert.Equal("110100", t3[1].Code);
|
||||||
//Assert.Equal("110101", t3[2].Code);
|
Assert.Equal("110101", t3[2].Code);
|
||||||
|
|
||||||
//var select = fsql.Select<VM_District_Child>()
|
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "东城区").AsTreeCte(up: true).ToList();
|
||||||
// .Where(a => a.Name == "中国")
|
Assert.Equal(3, t4.Count);
|
||||||
// .AsTreeCte()
|
Assert.Equal("110101", t4[0].Code);
|
||||||
// //.OrderBy("a.cte_level desc") //递归层级
|
Assert.Equal("110000", t4[1].Code);
|
||||||
// ;
|
Assert.Equal("100000", t4[2].Code);
|
||||||
//// var list = select.ToList(); //自己调试看查到的数据
|
|
||||||
//select.ToUpdate().Set(a => a.testint, 855).ExecuteAffrows();
|
|
||||||
//Assert.Equal(855, fsql.Select<VM_District_Child>()
|
|
||||||
// .Where(a => a.Name == "中国")
|
|
||||||
// .AsTreeCte().Distinct().First(a => a.testint));
|
|
||||||
|
|
||||||
//Assert.Equal(4, select.ToDelete().ExecuteAffrows());
|
var select = fsql.Select<VM_District_Child>()
|
||||||
//Assert.False(fsql.Select<VM_District_Child>()
|
.Where(a => a.Name == "中国")
|
||||||
// .Where(a => a.Name == "中国")
|
.AsTreeCte()
|
||||||
// .AsTreeCte().Any());
|
//.OrderBy("a.cte_level desc") //递归层级
|
||||||
|
;
|
||||||
|
// var list = select.ToList(); //自己调试看查到的数据
|
||||||
|
select.ToUpdate().Set(a => a.testint, 855).ExecuteAffrows();
|
||||||
|
Assert.Equal(855, fsql.Select<VM_District_Child>()
|
||||||
|
.Where(a => a.Name == "中国")
|
||||||
|
.AsTreeCte().Distinct().First(a => a.testint));
|
||||||
|
|
||||||
|
Assert.Equal(4, select.ToDelete().ExecuteAffrows());
|
||||||
|
Assert.False(fsql.Select<VM_District_Child>()
|
||||||
|
.Where(a => a.Name == "中国")
|
||||||
|
.AsTreeCte().Any());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Table(Name = "D_District")]
|
[Table(Name = "D_District")]
|
||||||
|
@ -30,7 +30,7 @@ namespace FreeSql.Tests
|
|||||||
});
|
});
|
||||||
Assert.Equal(id, item2.xxx);
|
Assert.Equal(id, item2.xxx);
|
||||||
|
|
||||||
fsql.Delete<ts_iif>().Where("1=1").ExecuteAffrows();
|
fsql.Delete<ts_iif_topic>().Where("1=1").ExecuteAffrows();
|
||||||
fsql.Delete<ts_iif_type>().Where("1=1").ExecuteAffrows();
|
fsql.Delete<ts_iif_type>().Where("1=1").ExecuteAffrows();
|
||||||
var typeid = Guid.NewGuid();
|
var typeid = Guid.NewGuid();
|
||||||
fsql.Insert(new ts_iif_type { id = typeid, name = "type001" }).ExecuteAffrows();
|
fsql.Insert(new ts_iif_type { id = typeid, name = "type001" }).ExecuteAffrows();
|
||||||
|
@ -9,7 +9,7 @@ public class g
|
|||||||
{
|
{
|
||||||
|
|
||||||
static Lazy<IFreeSql> mysqlLazy = new Lazy<IFreeSql>(() => new FreeSql.FreeSqlBuilder()
|
static Lazy<IFreeSql> mysqlLazy = new Lazy<IFreeSql>(() => new FreeSql.FreeSqlBuilder()
|
||||||
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=5")
|
.UseConnectionString(FreeSql.DataType.MySql, "Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;Max pool size=5;Allow User Variables=True")
|
||||||
//.UseConnectionFactory(FreeSql.DataType.MySql, () => new MySql.Data.MySqlClient.MySqlConnection("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;"))
|
//.UseConnectionFactory(FreeSql.DataType.MySql, () => new MySql.Data.MySqlClient.MySqlConnection("Data Source=127.0.0.1;Port=3306;User ID=root;Password=root;Initial Catalog=cccddd;Charset=utf8;SslMode=none;"))
|
||||||
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=192.168.164.10;Port=33061;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10")
|
//.UseConnectionString(FreeSql.DataType.MySql, "Data Source=192.168.164.10;Port=33061;User ID=root;Password=root;Initial Catalog=cccddd_mysqlconnector;Charset=utf8;SslMode=none;Max pool size=10")
|
||||||
.UseAutoSyncStructure(true)
|
.UseAutoSyncStructure(true)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
using FreeSql;
|
using FreeSql;
|
||||||
using FreeSql.DataAnnotations;
|
using FreeSql.DataAnnotations;
|
||||||
using FreeSql.Internal.CommonProvider;
|
using FreeSql.Internal.CommonProvider;
|
||||||
|
using FreeSql.Internal.ObjectPool;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
@ -378,10 +379,12 @@ public static partial class FreeSqlGlobalExtensions
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region AsTreeCte(..) 递归查询
|
#region AsTreeCte(..) 递归查询
|
||||||
|
static ConcurrentDictionary<string, string> _dicMySqlVersion = new ConcurrentDictionary<string, string>();
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用递归 CTE 查询树型的所有子记录,或者所有父记录。<para></para>
|
/// 使用递归 CTE 查询树型的所有子记录,或者所有父记录。<para></para>
|
||||||
/// 通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、Firebird、达梦、人大金仓、翰高<para></para>
|
/// 通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、Firebird、达梦、人大金仓、翰高<para></para>
|
||||||
/// 返回隐藏字段:.ToList(a => new { item = a, level = "a.cte_level", path = "a.cte_path" })
|
/// 返回隐藏字段:.ToList(a => new { item = a, level = "a.cte_level", path = "a.cte_path" })<para></para>
|
||||||
|
/// * v2.0.0 兼容 MySql5.6 向上或向下查询,但不支持 pathSelector/pathSeparator 详细:https://github.com/dotnetcore/FreeSql/issues/536
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T1"></typeparam>
|
/// <typeparam name="T1"></typeparam>
|
||||||
/// <param name="that"></param>
|
/// <param name="that"></param>
|
||||||
@ -409,6 +412,69 @@ public static partial class FreeSqlGlobalExtensions
|
|||||||
var cteName = "as_tree_cte";
|
var cteName = "as_tree_cte";
|
||||||
if (select._orm.CodeFirst.IsSyncStructureToLower) cteName = cteName.ToLower();
|
if (select._orm.CodeFirst.IsSyncStructureToLower) cteName = cteName.ToLower();
|
||||||
if (select._orm.CodeFirst.IsSyncStructureToUpper) cteName = cteName.ToUpper();
|
if (select._orm.CodeFirst.IsSyncStructureToUpper) cteName = cteName.ToUpper();
|
||||||
|
|
||||||
|
switch (select._orm.Ado.DataType) //MySql5.6
|
||||||
|
{
|
||||||
|
case DataType.MySql:
|
||||||
|
case DataType.OdbcMySql:
|
||||||
|
var mysqlConnectionString = select._orm.Ado?.ConnectionString ?? select._connection?.ConnectionString ?? "";
|
||||||
|
if (_dicMySqlVersion.TryGetValue(mysqlConnectionString, out var mysqlVersion) == false)
|
||||||
|
{
|
||||||
|
if (select._orm.Ado?.ConnectionString != null)
|
||||||
|
{
|
||||||
|
using (var mysqlconn = select._orm.Ado.MasterPool.Get())
|
||||||
|
mysqlVersion = mysqlconn.Value.ServerVersion;
|
||||||
|
}
|
||||||
|
else if (select._connection != null)
|
||||||
|
{
|
||||||
|
var isclosed = select._connection.State != ConnectionState.Open;
|
||||||
|
if (isclosed) select._connection.Open();
|
||||||
|
mysqlVersion = select._connection.ServerVersion;
|
||||||
|
if (isclosed) select._connection.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (int.TryParse((mysqlVersion ?? "").Split('.')[0], out var mysqlVersionFirst) && mysqlVersionFirst < 8)
|
||||||
|
{
|
||||||
|
if (tbref.Columns.Count > 1) throw new ArgumentException($"{tb.Type.FullName} 是父子关系,但是 MySql 8.0 以下版本中不支持组合多主键");
|
||||||
|
var mysql56Sql = "";
|
||||||
|
if (up == false)
|
||||||
|
{
|
||||||
|
mysql56Sql = $@"SELECT cte_tbc.cte_level, {select.GetAllFieldExpressionTreeLevel2().Field}
|
||||||
|
FROM (
|
||||||
|
SELECT @cte_ids as cte_ids, (
|
||||||
|
SELECT @cte_ids := group_concat({select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)})
|
||||||
|
FROM {select._commonUtils.QuoteSqlName(tb.DbName)}
|
||||||
|
WHERE find_in_set({select._commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name)}, @cte_ids)
|
||||||
|
) as cte_cids, @cte_level := @cte_idcte_levels + 1 as cte_level
|
||||||
|
FROM {select._commonUtils.QuoteSqlName(tb.DbName)}, (
|
||||||
|
SELECT @cte_ids := a.{select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)}, @cte_idcte_levels := 0
|
||||||
|
FROM {select._commonUtils.QuoteSqlName(tb.DbName)} a
|
||||||
|
WHERE 1=1{select._where}
|
||||||
|
LIMIT 1) cte_tbb
|
||||||
|
WHERE @cte_ids IS NOT NULL
|
||||||
|
) cte_tbc, {select._commonUtils.QuoteSqlName(tb.DbName)} a
|
||||||
|
WHERE find_in_set(a.{select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)}, cte_tbc.cte_ids)";
|
||||||
|
select.WithSql(mysql56Sql).OrderBy("a.cte_level DESC");
|
||||||
|
select._where.Clear();
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
mysql56Sql = $@"SELECT cte_tbc.cte_level, {select.GetAllFieldExpressionTreeLevel2().Field}
|
||||||
|
FROM (
|
||||||
|
SELECT @cte_pid as cte_id, (SELECT @cte_pid := {select._commonUtils.QuoteSqlName(tbref.RefColumns[0].Attribute.Name)} FROM {select._commonUtils.QuoteSqlName(tb.DbName)} WHERE {select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)} = cte_id) as cte_pid, @cte_level := @cte_level + 1 as cte_level
|
||||||
|
FROM {select._commonUtils.QuoteSqlName(tb.DbName)}, (
|
||||||
|
SELECT @cte_pid := a.{select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)}, @cte_level := 0
|
||||||
|
FROM {select._commonUtils.QuoteSqlName(tb.DbName)} a
|
||||||
|
WHERE 1=1{select._where}
|
||||||
|
LIMIT 1) cte_tbb
|
||||||
|
) cte_tbc
|
||||||
|
JOIN {select._commonUtils.QuoteSqlName(tb.DbName)} a ON cte_tbc.cte_id = a.{select._commonUtils.QuoteSqlName(tbref.Columns[0].Attribute.Name)}";
|
||||||
|
select.WithSql(mysql56Sql).OrderBy("a.cte_level");
|
||||||
|
select._where.Clear();
|
||||||
|
return select;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
var sql1ctePath = "";
|
var sql1ctePath = "";
|
||||||
if (pathSelector != null)
|
if (pathSelector != null)
|
||||||
{
|
{
|
||||||
|
@ -4369,7 +4369,8 @@
|
|||||||
<summary>
|
<summary>
|
||||||
使用递归 CTE 查询树型的所有子记录,或者所有父记录。<para></para>
|
使用递归 CTE 查询树型的所有子记录,或者所有父记录。<para></para>
|
||||||
通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、Firebird、达梦、人大金仓、翰高<para></para>
|
通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、Firebird、达梦、人大金仓、翰高<para></para>
|
||||||
返回隐藏字段:.ToList(a => new { item = a, level = "a.cte_level", path = "a.cte_path" })
|
返回隐藏字段:.ToList(a => new { item = a, level = "a.cte_level", path = "a.cte_path" })<para></para>
|
||||||
|
* v2.0.0 兼容 MySql5.6 向上或向下查询,但不支持 pathSelector/pathSeparator 详细:https://github.com/dotnetcore/FreeSql/issues/536
|
||||||
</summary>
|
</summary>
|
||||||
<typeparam name="T1"></typeparam>
|
<typeparam name="T1"></typeparam>
|
||||||
<param name="that"></param>
|
<param name="that"></param>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user