mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 10:42:52 +08:00
- 增加 ISelect.AsTreeCte() 递归查询树表(向下或向下);
This commit is contained in:
parent
4cde2a3280
commit
838dd83e47
@ -1754,7 +1754,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1763,18 +1763,42 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -889,7 +889,7 @@ FROM ""TB_TOPIC22"" a", subquery);
|
||||
var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql();
|
||||
Assert.Equal(@"SELECT a.""ID"", a.""CLICKS"", a.""TYPEGUID"", a.""TITLE"", a.""CREATETIME""
|
||||
FROM ""TB_TOPIC22"" a
|
||||
WHERE ((((a.""ID"")::varchar) in (SELECT b.""TITLE""
|
||||
WHERE ((((a.""ID"")::text) in (SELECT b.""TITLE""
|
||||
FROM ""TB_TOPIC22"" b)))", subquery);
|
||||
var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList();
|
||||
}
|
||||
@ -1719,7 +1719,7 @@ WHERE ((((a.""ID"")::varchar) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1728,18 +1728,42 @@ WHERE ((((a.""ID"")::varchar) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -1755,7 +1755,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1764,18 +1764,42 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -985,7 +985,7 @@ FROM ""tb_topic"" a", subquery);
|
||||
var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql();
|
||||
Assert.Equal(@"SELECT a.""id"", a.""clicks"", a.""typeguid"", a.""title"", a.""createtime""
|
||||
FROM ""tb_topic"" a
|
||||
WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
|
||||
WHERE ((((a.""id"")::text) in (SELECT b.""title""
|
||||
FROM ""tb_topic"" b)))", subquery);
|
||||
var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList();
|
||||
}
|
||||
@ -1814,7 +1814,7 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1823,18 +1823,42 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -1705,7 +1705,7 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1714,18 +1714,42 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -1755,7 +1755,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1764,18 +1764,42 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -1755,7 +1755,7 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1764,18 +1764,42 @@ WHERE (((to_char(a.""ID"")) in (SELECT b.""TITLE""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -1002,7 +1002,7 @@ FROM ""tb_topic"" a", subquery);
|
||||
var subquery = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToSql();
|
||||
Assert.Equal(@"SELECT a.""id"", a.""clicks"", a.""typeguid"", a.""title"", a.""createtime""
|
||||
FROM ""tb_topic"" a
|
||||
WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
|
||||
WHERE ((((a.""id"")::text) in (SELECT b.""title""
|
||||
FROM ""tb_topic"" b)))", subquery);
|
||||
var subqueryList = select.Where(a => select.As("b").ToList(b => b.Title).Contains(a.Id.ToString())).ToList();
|
||||
}
|
||||
@ -1830,7 +1830,7 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1839,18 +1839,42 @@ WHERE ((((a.""id"")::varchar) in (SELECT b.""title""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -1786,7 +1786,7 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1795,18 +1795,42 @@ WHERE (((cast(a.[Id] as nvarchar(100))) in (SELECT b.[Title]
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -1904,7 +1904,7 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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.Equal("100000", t3[0].Code);
|
||||
Assert.Single(t3[0].Childs);
|
||||
@ -1913,18 +1913,42 @@ WHERE (((cast(a.""Id"" as character)) in (SELECT b.""Title""
|
||||
Assert.Equal("110100", t3[0].Childs[0].Childs[0].Code);
|
||||
Assert.Equal("110101", t3[0].Childs[0].Childs[1].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsCteTree().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("100000", t3[0].Code);
|
||||
Assert.Equal("110000", t3[1].Code);
|
||||
Assert.Equal("110100", t3[2].Code);
|
||||
Assert.Equal("110101", t3[3].Code);
|
||||
|
||||
t3 = fsql.Select<VM_District_Child>().Where(a => a.Name == "北京").AsCteTree().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("110000", t3[0].Code);
|
||||
Assert.Equal("110100", t3[1].Code);
|
||||
Assert.Equal("110101", t3[2].Code);
|
||||
|
||||
var t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name).OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国", t4[0].path);
|
||||
Assert.Equal("中国 -> 北京", t4[1].path);
|
||||
Assert.Equal("中国 -> 北京 -> 北京市", t4[2].path);
|
||||
Assert.Equal("中国 -> 北京 -> 东城区", t4[3].path);
|
||||
|
||||
t4 = fsql.Select<VM_District_Child>().Where(a => a.Name == "中国").AsTreeCte(a => a.Name + "[" + a.Code + "]").OrderBy(a => a.Code)
|
||||
.ToList(a => new { item = a, level = Convert.ToInt32("a.cte_level"), path = "a.cte_path" });
|
||||
Assert.Equal(4, t4.Count);
|
||||
Assert.Equal("100000", t4[0].item.Code);
|
||||
Assert.Equal("110000", t4[1].item.Code);
|
||||
Assert.Equal("110100", t4[2].item.Code);
|
||||
Assert.Equal("110101", t4[3].item.Code);
|
||||
Assert.Equal("中国[100000]", t4[0].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000]", t4[1].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 北京市[110100]", t4[2].path);
|
||||
Assert.Equal("中国[100000] -> 北京[110000] -> 东城区[110101]", t4[3].path);
|
||||
}
|
||||
|
||||
[Table(Name = "D_District")]
|
||||
|
@ -386,16 +386,24 @@ public static partial class FreeSqlGlobalExtensions
|
||||
#endif
|
||||
#endregion
|
||||
|
||||
#region WhereTree(..) 递归查询
|
||||
#region AsTreeCte(..) 递归查询
|
||||
/// <summary>
|
||||
/// 使用递归 CTE 查询树型的所有子数据。<para></para>
|
||||
/// 通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、达梦、人大金仓
|
||||
/// 使用递归 CTE 查询树型的所有子记录,或者所有父记录。<para></para>
|
||||
/// 通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、达梦、人大金仓<para></para>
|
||||
/// 返回隐藏字段:.ToList(a => new { item = a, level = "a.cte_level", path = "a.cte_path" })
|
||||
/// </summary>
|
||||
/// <typeparam name="T1"></typeparam>
|
||||
/// <param name="that"></param>
|
||||
/// <param name="depth">深度</param>
|
||||
/// <param name="up">false(默认):由父级向子级的递归查询<para></para>true:由子级向父级的递归查询</param>
|
||||
/// <param name="pathSelector">路径内容选择</param>
|
||||
/// <param name="pathSeparator">连接路径内容</param>
|
||||
/// <param name="level">递归层级</param>
|
||||
/// <returns></returns>
|
||||
public static ISelect<T1> AsCteTree<T1>(this ISelect<T1> that, int depth = -1) where T1 : class
|
||||
public static ISelect<T1> AsTreeCte<T1>(this ISelect<T1> that,
|
||||
Expression<Func<T1, string>> pathSelector = null,
|
||||
bool up = false,
|
||||
string pathSeparator = " -> ",
|
||||
int level = -1) where T1 : class
|
||||
{
|
||||
var select = that as Select1Provider<T1>;
|
||||
var tb = select._tables[0].Table;
|
||||
@ -407,24 +415,66 @@ public static partial class FreeSqlGlobalExtensions
|
||||
if (navs.Length != 1) throw new ArgumentException($"{tb.Type.FullName} 不是父子关系,无法使用该功能");
|
||||
var tbref = navs[0];
|
||||
|
||||
var cteName = "as_cte_tree";
|
||||
var cteName = "as_tree_cte";
|
||||
if (select._orm.CodeFirst.IsSyncStructureToLower) cteName = cteName.ToLower();
|
||||
if (select._orm.CodeFirst.IsSyncStructureToUpper) cteName = cteName.ToUpper();
|
||||
var sql1 = select.ToSql($"0 as as_cte_tree_depth, {select.GetAllFieldExpressionTreeLevel2().Field}").Trim();
|
||||
var sql1ctePath = "";
|
||||
if (pathSelector != null)
|
||||
{
|
||||
select._tables[0].Parameter = pathSelector?.Parameters[0];
|
||||
switch (select._orm.Ado.DataType)
|
||||
{
|
||||
case DataType.PostgreSQL:
|
||||
case DataType.OdbcPostgreSQL:
|
||||
case DataType.OdbcKingbaseES:
|
||||
case DataType.ShenTong: //神通测试未通过
|
||||
case DataType.SqlServer:
|
||||
case DataType.OdbcSqlServer:
|
||||
sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, Expression.Call(typeof(Convert).GetMethod("ToString", new Type[] { typeof(string) }), pathSelector?.Body), null, null, null);
|
||||
break;
|
||||
default:
|
||||
sql1ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, pathSelector?.Body, null, null, null);
|
||||
break;
|
||||
}
|
||||
sql1ctePath = $"{sql1ctePath} as cte_path, ";
|
||||
}
|
||||
var sql1 = select.ToSql($"0 as cte_level, {sql1ctePath}{select.GetAllFieldExpressionTreeLevel2().Field}").Trim();
|
||||
|
||||
select._where.Clear();
|
||||
select.As("wct2");
|
||||
var sql2Field = select.GetAllFieldExpressionTreeLevel2().Field;
|
||||
var sql2InnerJoinOn = up == false ?
|
||||
string.Join(" and ", tbref.Columns.Select((a, z) => $"wct2.{select._commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)} = wct1.{select._commonUtils.QuoteSqlName(a.Attribute.Name)}")) :
|
||||
string.Join(" and ", tbref.Columns.Select((a, z) => $"wct2.{select._commonUtils.QuoteSqlName(a.Attribute.Name)} = wct1.{select._commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)}"));
|
||||
|
||||
var sql2ctePath = "";
|
||||
if (pathSelector != null)
|
||||
{
|
||||
select._tables[0].Parameter = pathSelector?.Parameters[0];
|
||||
var wct2ctePath = select._commonExpression.ExpressionWhereLambda(select._tables, pathSelector?.Body, null, null, null);
|
||||
sql2ctePath = select._commonUtils.StringConcat(
|
||||
new string[] {
|
||||
up == false ? "wct1.cte_path" : wct2ctePath,
|
||||
select._commonUtils.FormatSql("{0}", pathSeparator),
|
||||
up == false ? wct2ctePath : "wct1.cte_path"
|
||||
}, new Type[] {
|
||||
typeof(string),
|
||||
typeof(string),
|
||||
typeof(string)
|
||||
});
|
||||
sql2ctePath = $"{sql2ctePath} as cte_path, ";
|
||||
}
|
||||
var sql2 = select
|
||||
.AsAlias((type, old) => type == tb.Type ? old.Replace("wct2", "wct1") : old)
|
||||
.AsTable((type, old) => type == tb.Type ? cteName : old)
|
||||
.InnerJoin($"{select._commonUtils.QuoteSqlName(tb.DbName)} wct2 ON {string.Join(" and ", tbref.Columns.Select((a,z) => $"wct2.{select._commonUtils.QuoteSqlName(tbref.RefColumns[z].Attribute.Name)} = wct1.{select._commonUtils.QuoteSqlName(a.Attribute.Name)}"))}")
|
||||
.ToSql($"wct1.as_cte_tree_depth + 1 as as_cte_tree_depth, {sql2Field}").Trim();
|
||||
.InnerJoin($"{select._commonUtils.QuoteSqlName(tb.DbName)} wct2 ON {sql2InnerJoinOn}")
|
||||
.ToSql($"wct1.cte_level + 1 as cte_level, {sql2ctePath}{sql2Field}").Trim();
|
||||
|
||||
var newSelect = select._orm.Select<T1>()
|
||||
.AsType(tb.Type)
|
||||
.AsTable((type, old) => type == tb.Type ? cteName : old)
|
||||
.WhereIf(depth > 0, $"a.as_cte_tree_depth < {depth + 1}") as Select1Provider<T1>;
|
||||
.WhereIf(level > 0, $"a.cte_level < {level + 1}")
|
||||
.OrderBy(up, "a.cte_level desc") as Select1Provider<T1>;
|
||||
|
||||
var nsselsb = new StringBuilder();
|
||||
if (AdoProvider.IsFromSlave(select._select) == false) nsselsb.Append(" "); //读写分离规则,如果强制读主库,则在前面加个空格
|
||||
@ -447,7 +497,7 @@ public static partial class FreeSqlGlobalExtensions
|
||||
case DataType.OdbcOracle:
|
||||
case DataType.Dameng: //递归 WITH 子句必须具有列别名列表
|
||||
case DataType.OdbcDameng:
|
||||
nsselsb.Append($"(as_cte_tree_depth, {sql2Field.Replace("wct2.", "")})");
|
||||
nsselsb.Append($"(cte_level, {(pathSelector == null ? "" : "cte_path, ")}{sql2Field.Replace("wct2.", "")})");
|
||||
break;
|
||||
}
|
||||
nsselsb.Append(@"
|
||||
|
@ -3653,14 +3653,18 @@
|
||||
<param name="that"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:FreeSqlGlobalExtensions.AsCteTree``1(FreeSql.ISelect{``0},System.Int32)">
|
||||
<member name="M:FreeSqlGlobalExtensions.AsTreeCte``1(FreeSql.ISelect{``0},System.Linq.Expressions.Expression{System.Func{``0,System.String}},System.Boolean,System.String,System.Int32)">
|
||||
<summary>
|
||||
使用递归 CTE 查询树型的所有子数据。<para></para>
|
||||
通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、达梦、人大金仓
|
||||
使用递归 CTE 查询树型的所有子记录,或者所有父记录。<para></para>
|
||||
通过测试的数据库:MySql8.0、SqlServer、PostgreSQL、Oracle、Sqlite、达梦、人大金仓<para></para>
|
||||
返回隐藏字段:.ToList(a => new { item = a, level = "a.cte_level", path = "a.cte_path" })
|
||||
</summary>
|
||||
<typeparam name="T1"></typeparam>
|
||||
<param name="that"></param>
|
||||
<param name="depth">深度</param>
|
||||
<param name="up">false(默认):由父级向子级的递归查询<para></para>true:由子级向父级的递归查询</param>
|
||||
<param name="pathSelector">路径内容选择</param>
|
||||
<param name="pathSeparator">连接路径内容</param>
|
||||
<param name="level">递归层级</param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:System.Linq.Expressions.LambadaExpressionExtensions.And``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}},System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
|
||||
|
@ -37,7 +37,7 @@ namespace FreeSql.Odbc.KingbaseES
|
||||
case "System.Int64": return $"({getExp(operandExp)})::int8";
|
||||
case "System.SByte": return $"({getExp(operandExp)})::int2";
|
||||
case "System.Single": return $"({getExp(operandExp)})::float4";
|
||||
case "System.String": return $"({getExp(operandExp)})::varchar";
|
||||
case "System.String": return $"({getExp(operandExp)})::text";
|
||||
case "System.UInt16": return $"({getExp(operandExp)})::int2";
|
||||
case "System.UInt32": return $"({getExp(operandExp)})::int4";
|
||||
case "System.UInt64": return $"({getExp(operandExp)})::int8";
|
||||
@ -87,7 +87,7 @@ namespace FreeSql.Odbc.KingbaseES
|
||||
if (callExp.Method.DeclaringType.IsNumberType()) return "random()";
|
||||
return null;
|
||||
case "ToString":
|
||||
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? $"({getExp(callExp.Object)})::varchar" : null;
|
||||
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? $"({getExp(callExp.Object)})::text" : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -332,10 +332,10 @@ namespace FreeSql.Odbc.KingbaseES
|
||||
if (exp.Arguments[1].Type == typeof(bool) ||
|
||||
exp.Arguments[1].Type == typeof(StringComparison) && getExp(exp.Arguments[0]).Contains("IgnoreCase")) likeOpt = "ILIKE";
|
||||
}
|
||||
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::varchar || '%')")}";
|
||||
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::varchar)")}";
|
||||
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::text || '%')")}";
|
||||
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::text)")}";
|
||||
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
|
||||
return $"({left}) {likeOpt} ('%' || ({args0Value})::varchar || '%')";
|
||||
return $"({left}) {likeOpt} ('%' || ({args0Value})::text || '%')";
|
||||
case "ToLower": return $"lower({left})";
|
||||
case "ToUpper": return $"upper({left})";
|
||||
case "Substring":
|
||||
@ -378,7 +378,7 @@ namespace FreeSql.Odbc.KingbaseES
|
||||
return left;
|
||||
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||
case "CompareTo": return $"case when {left} = {getExp(exp.Arguments[0])} then 0 when {left} > {getExp(exp.Arguments[0])} then 1 else -1 end";
|
||||
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::varchar)";
|
||||
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::text)";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -573,7 +573,7 @@ namespace FreeSql.Odbc.KingbaseES
|
||||
case "ToInt64": return $"({getExp(exp.Arguments[0])})::int8";
|
||||
case "ToSByte": return $"({getExp(exp.Arguments[0])})::int2";
|
||||
case "ToSingle": return $"({getExp(exp.Arguments[0])})::float4";
|
||||
case "ToString": return $"({getExp(exp.Arguments[0])})::varchar";
|
||||
case "ToString": return $"({getExp(exp.Arguments[0])})::text";
|
||||
case "ToUInt16": return $"({getExp(exp.Arguments[0])})::int2";
|
||||
case "ToUInt32": return $"({getExp(exp.Arguments[0])})::int4";
|
||||
case "ToUInt64": return $"({getExp(exp.Arguments[0])})::int8";
|
||||
|
@ -37,7 +37,7 @@ namespace FreeSql.Odbc.PostgreSQL
|
||||
case "System.Int64": return $"({getExp(operandExp)})::int8";
|
||||
case "System.SByte": return $"({getExp(operandExp)})::int2";
|
||||
case "System.Single": return $"({getExp(operandExp)})::float4";
|
||||
case "System.String": return $"({getExp(operandExp)})::varchar";
|
||||
case "System.String": return $"({getExp(operandExp)})::text";
|
||||
case "System.UInt16": return $"({getExp(operandExp)})::int2";
|
||||
case "System.UInt32": return $"({getExp(operandExp)})::int4";
|
||||
case "System.UInt64": return $"({getExp(operandExp)})::int8";
|
||||
@ -87,7 +87,7 @@ namespace FreeSql.Odbc.PostgreSQL
|
||||
if (callExp.Method.DeclaringType.IsNumberType()) return "random()";
|
||||
return null;
|
||||
case "ToString":
|
||||
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? $"({getExp(callExp.Object)})::varchar" : null;
|
||||
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? $"({getExp(callExp.Object)})::text" : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -354,10 +354,10 @@ namespace FreeSql.Odbc.PostgreSQL
|
||||
if (exp.Arguments[1].Type == typeof(bool) ||
|
||||
exp.Arguments[1].Type == typeof(StringComparison) && getExp(exp.Arguments[0]).Contains("IgnoreCase")) likeOpt = "ILIKE";
|
||||
}
|
||||
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::varchar || '%')")}";
|
||||
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::varchar)")}";
|
||||
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::text || '%')")}";
|
||||
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::text)")}";
|
||||
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
|
||||
return $"({left}) {likeOpt} ('%' || ({args0Value})::varchar || '%')";
|
||||
return $"({left}) {likeOpt} ('%' || ({args0Value})::text || '%')";
|
||||
case "ToLower": return $"lower({left})";
|
||||
case "ToUpper": return $"upper({left})";
|
||||
case "Substring":
|
||||
@ -405,7 +405,7 @@ namespace FreeSql.Odbc.PostgreSQL
|
||||
return left;
|
||||
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||
case "CompareTo": return $"case when {left} = {getExp(exp.Arguments[0])} then 0 when {left} > {getExp(exp.Arguments[0])} then 1 else -1 end";
|
||||
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::varchar)";
|
||||
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::text)";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -598,7 +598,7 @@ namespace FreeSql.Odbc.PostgreSQL
|
||||
case "ToInt64": return $"({getExp(exp.Arguments[0])})::int8";
|
||||
case "ToSByte": return $"({getExp(exp.Arguments[0])})::int2";
|
||||
case "ToSingle": return $"({getExp(exp.Arguments[0])})::float4";
|
||||
case "ToString": return $"({getExp(exp.Arguments[0])})::varchar";
|
||||
case "ToString": return $"({getExp(exp.Arguments[0])})::text";
|
||||
case "ToUInt16": return $"({getExp(exp.Arguments[0])})::int2";
|
||||
case "ToUInt32": return $"({getExp(exp.Arguments[0])})::int4";
|
||||
case "ToUInt64": return $"({getExp(exp.Arguments[0])})::int8";
|
||||
|
@ -73,7 +73,8 @@ namespace FreeSql.Odbc.SqlServer
|
||||
{
|
||||
if (types[a] == typeof(string)) news[a] = objs[a];
|
||||
else if (types[a].NullableTypeOrThis() == typeof(Guid)) news[a] = $"cast({objs[a]} as char(36))";
|
||||
else news[a] = $"cast({objs[a]} as nvarchar)";
|
||||
else if (types[a].IsNumberType()) news[a] = $"cast({objs[a]} as varchar)";
|
||||
else news[a] = $"cast({objs[a]} as nvarchar(max))";
|
||||
}
|
||||
return string.Join(" + ", news);
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace FreeSql.PostgreSQL
|
||||
case "System.Int64": return $"({getExp(operandExp)})::int8";
|
||||
case "System.SByte": return $"({getExp(operandExp)})::int2";
|
||||
case "System.Single": return $"({getExp(operandExp)})::float4";
|
||||
case "System.String": return $"({getExp(operandExp)})::varchar";
|
||||
case "System.String": return $"({getExp(operandExp)})::text";
|
||||
case "System.UInt16": return $"({getExp(operandExp)})::int2";
|
||||
case "System.UInt32": return $"({getExp(operandExp)})::int4";
|
||||
case "System.UInt64": return $"({getExp(operandExp)})::int8";
|
||||
@ -88,7 +88,7 @@ namespace FreeSql.PostgreSQL
|
||||
if (callExp.Method.DeclaringType.IsNumberType()) return "random()";
|
||||
return null;
|
||||
case "ToString":
|
||||
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? $"({getExp(callExp.Object)})::varchar" : null;
|
||||
if (callExp.Object != null) return callExp.Arguments.Count == 0 ? $"({getExp(callExp.Object)})::text" : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ namespace FreeSql.PostgreSQL
|
||||
case "Contains":
|
||||
var json = getExp(callExp.Arguments[argIndex]);
|
||||
if (objType == typeof(JArray))
|
||||
return $"(coalesce({left},'[]') ? ({json})::varchar)";
|
||||
return $"(coalesce({left},'[]') ? ({json})::text)";
|
||||
if (json.StartsWith("'") && json.EndsWith("'"))
|
||||
return $"(coalesce({left},'{{}}') @> {_common.FormatSql("{0}", JToken.Parse(json.Trim('\'')))})";
|
||||
return $"(coalesce({left},'{{}}') @> ({json})::jsonb)";
|
||||
@ -385,10 +385,10 @@ namespace FreeSql.PostgreSQL
|
||||
if (exp.Arguments[1].Type == typeof(bool) ||
|
||||
exp.Arguments[1].Type == typeof(StringComparison) && getExp(exp.Arguments[0]).Contains("IgnoreCase")) likeOpt = "ILIKE";
|
||||
}
|
||||
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::varchar || '%')")}";
|
||||
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::varchar)")}";
|
||||
if (exp.Method.Name == "StartsWith") return $"({left}) {likeOpt} {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(({args0Value})::text || '%')")}";
|
||||
if (exp.Method.Name == "EndsWith") return $"({left}) {likeOpt} {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%' || ({args0Value})::text)")}";
|
||||
if (args0Value.StartsWith("'") && args0Value.EndsWith("'")) return $"({left}) {likeOpt} {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}";
|
||||
return $"({left}) {likeOpt} ('%' || ({args0Value})::varchar || '%')";
|
||||
return $"({left}) {likeOpt} ('%' || ({args0Value})::text || '%')";
|
||||
case "ToLower": return $"lower({left})";
|
||||
case "ToUpper": return $"upper({left})";
|
||||
case "Substring":
|
||||
@ -436,7 +436,7 @@ namespace FreeSql.PostgreSQL
|
||||
return left;
|
||||
case "Replace": return $"replace({left}, {getExp(exp.Arguments[0])}, {getExp(exp.Arguments[1])})";
|
||||
case "CompareTo": return $"case when {left} = {getExp(exp.Arguments[0])} then 0 when {left} > {getExp(exp.Arguments[0])} then 1 else -1 end";
|
||||
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::varchar)";
|
||||
case "Equals": return $"({left} = ({getExp(exp.Arguments[0])})::text)";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -629,7 +629,7 @@ namespace FreeSql.PostgreSQL
|
||||
case "ToInt64": return $"({getExp(exp.Arguments[0])})::int8";
|
||||
case "ToSByte": return $"({getExp(exp.Arguments[0])})::int2";
|
||||
case "ToSingle": return $"({getExp(exp.Arguments[0])})::float4";
|
||||
case "ToString": return $"({getExp(exp.Arguments[0])})::varchar";
|
||||
case "ToString": return $"({getExp(exp.Arguments[0])})::text";
|
||||
case "ToUInt16": return $"({getExp(exp.Arguments[0])})::int2";
|
||||
case "ToUInt32": return $"({getExp(exp.Arguments[0])})::int4";
|
||||
case "ToUInt64": return $"({getExp(exp.Arguments[0])})::int8";
|
||||
|
@ -85,7 +85,8 @@ namespace FreeSql.SqlServer
|
||||
{
|
||||
if (types[a] == typeof(string)) news[a] = objs[a];
|
||||
else if (types[a].NullableTypeOrThis() == typeof(Guid)) news[a] = $"cast({objs[a]} as char(36))";
|
||||
else news[a] = $"cast({objs[a]} as nvarchar)";
|
||||
else if (types[a].IsNumberType()) news[a] = $"cast({objs[a]} as varchar)";
|
||||
else news[a] = $"cast({objs[a]} as nvarchar(max))";
|
||||
}
|
||||
return string.Join(" + ", news);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user