From 2f76a22e219ad280393cb8a09fb6b2e4b21a6d4f Mon Sep 17 00:00:00 2001
From: 2881099 <2881099@qq.com>
Date: Mon, 25 Jul 2022 22:12:25 +0800
Subject: [PATCH] fix WithTempQuery 05
---
FreeSql.DbContext/FreeSql.DbContext.xml | 9 --
.../Curd/SqlServerSelectWithTempQueryTest.cs | 115 ++++++++++++++++--
FreeSql/Internal/CommonExpression.cs | 31 +++--
.../SelectProvider/Select1Provider.cs | 3 +-
.../SelectProvider/SelectGroupingProvider.cs | 61 +++++++---
5 files changed, 177 insertions(+), 42 deletions(-)
diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index 26522f10..537315e2 100644
--- a/FreeSql.DbContext/FreeSql.DbContext.xml
+++ b/FreeSql.DbContext/FreeSql.DbContext.xml
@@ -800,14 +800,5 @@
-
-
- 批量注入 Repository,可以参考代码自行调整
-
-
-
-
-
-
diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs
index 2d2502d1..8e435295 100644
--- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs
+++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectWithTempQueryTest.cs
@@ -174,6 +174,57 @@ WHERE (a.[rownum] = 1)";
Assert.Equal(list04[1].Id, 4);
Assert.Equal(list04[2].rownum, 1);
Assert.Equal(list04[2].Id, 5);
+
+
+ var sql05 = fsql.Select()
+ .Where(a => a.Id > 0)
+ .WithTempQuery(a => new
+ {
+ a.Id,
+ a.Nickname
+ })
+ .GroupBy(a => new { a.Nickname })
+ .WithTempQuery(a => new
+ {
+ a.Key,
+ sum1 = a.Sum(a.Value.Id),
+ cou1 = a.Count()
+ })
+ .ToSql();
+ var assertSql05 = @"SELECT *
+FROM (
+ SELECT a.[Nickname], sum(a.[Id]) [sum1], count(1) [cou1]
+ FROM (
+ SELECT a.[Id], a.[Nickname]
+ FROM [TwoTablePartitionBy_User] a
+ WHERE (a.[Id] > 0) ) a
+ GROUP BY a.[Nickname] ) a";
+ Assert.Equal(assertSql05, sql05);
+ var list05 = fsql.Select()
+ .Where(a => a.Id > 0)
+ .WithTempQuery(a => new
+ {
+ a.Id,
+ a.Nickname
+ })
+ .GroupBy(a => new { a.Nickname })
+ .WithTempQuery(a => new
+ {
+ a.Key,
+ sum1 = a.Sum(a.Value.Id),
+ cou1 = a.Count()
+ })
+ .ToList();
+ Assert.Equal(3, list05.Count);
+ Assert.Equal("name01", list05[0].Key.Nickname);
+ Assert.Equal(6, list05[0].sum1);
+ Assert.Equal(3, list05[0].cou1);
+ Assert.Equal("name02", list05[1].Key.Nickname);
+ Assert.Equal(4, list05[1].sum1);
+ Assert.Equal(1, list05[1].cou1);
+ Assert.Equal("name03", list05[2].Key.Nickname);
+ Assert.Equal(11, list05[2].sum1);
+ Assert.Equal(2, list05[2].cou1);
}
class SingleTablePartitionBy_User
{
@@ -527,7 +578,8 @@ FROM (
SELECT a.[Id], a.[Nickname], row_number() over( partition by a.[Nickname] order by a.[Id]) [rownum]
FROM [TwoTablePartitionBy_User] a ) a
WHERE (a.[rownum] = 1) ) a
-INNER JOIN (SELECT a.[UserId], a.[Remark]
+INNER JOIN (
+ SELECT a.[UserId], a.[Remark]
FROM [TwoTablePartitionBy_UserExt] a) b ON a.[Id] = b.[UserId]
WHERE ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02'))";
Assert.Equal(sql07, assertSql07);
@@ -567,7 +619,8 @@ WHERE ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02'))";
FROM (
SELECT a.[Id], a.[Nickname], row_number() over( partition by a.[Nickname] order by a.[Id]) [rownum]
FROM [TwoTablePartitionBy_User] a ) a
-INNER JOIN (SELECT a.[UserId], a.[Remark]
+INNER JOIN (
+ SELECT a.[UserId], a.[Remark]
FROM [TwoTablePartitionBy_UserExt] a
WHERE (a.[UserId] > 0)) b ON a.[Id] = b.[UserId]
WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02'))";
@@ -599,7 +652,7 @@ WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02
rownum = SqlExt.RowNumber().Over().PartitionBy(a.Nickname).OrderBy(a.Id).ToValue()
})
.Where(a => a.rownum == 1)
- .FromQuery(fsql.Select().Where(b => b.UserId > 0).GroupBy(b => new { b.UserId, b.Remark }).WithTempQuery(b => b.Key))
+ .FromQuery(fsql.Select().Where(b => b.UserId > 0).WithTempQuery(b => new { b.UserId, b.Remark }))
.InnerJoin((a, b) => a.user.Id == b.UserId)
.Where((a, b) => a.user.Nickname == "name03" || a.user.Nickname == "name02")
.ToSql((a, b) => new TwoTablePartitionBy_UserDto());
@@ -607,10 +660,10 @@ WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02
FROM (
SELECT a.[Id], a.[Nickname], row_number() over( partition by a.[Nickname] order by a.[Id]) [rownum]
FROM [TwoTablePartitionBy_User] a ) a
-INNER JOIN ( SELECT a.[UserId], a.[Remark]
+INNER JOIN (
+ SELECT a.[UserId], a.[Remark]
FROM [TwoTablePartitionBy_UserExt] a
- WHERE (a.[UserId] > 0)
- GROUP BY a.[UserId], a.[Remark] ) b ON a.[Id] = b.[UserId]
+ WHERE (a.[UserId] > 0) ) b ON a.[Id] = b.[UserId]
WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02'))";
Assert.Equal(sql09, assertSql09);
var list09 = fsql.Select()
@@ -620,7 +673,7 @@ WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02
rownum = SqlExt.RowNumber().Over().PartitionBy(a.Nickname).OrderBy(a.Id).ToValue()
})
.Where(a => a.rownum == 1)
- .FromQuery(fsql.Select().Where(b => b.UserId > 0).GroupBy(b => new { b.UserId, b.Remark }).WithTempQuery(b => b.Key))
+ .FromQuery(fsql.Select().Where(b => b.UserId > 0).WithTempQuery(b => new { b.UserId, b.Remark }))
.InnerJoin((a, b) => a.user.Id == b.UserId)
.Where((a, b) => a.user.Nickname == "name03" || a.user.Nickname == "name02")
.ToList();
@@ -633,6 +686,48 @@ WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02
Assert.Equal(list09[1].remark, "remark05");
+ var sql091 = fsql.Select()
+ .WithTempQuery(a => new
+ {
+ user = a,
+ rownum = SqlExt.RowNumber().Over().PartitionBy(a.Nickname).OrderBy(a.Id).ToValue()
+ })
+ .Where(a => a.rownum == 1)
+ .FromQuery(fsql.Select().Where(b => b.UserId > 0).GroupBy(b => new { b.UserId, b.Remark }).WithTempQuery(b => b.Key))
+ .InnerJoin((a, b) => a.user.Id == b.UserId)
+ .Where((a, b) => a.user.Nickname == "name03" || a.user.Nickname == "name02")
+ .ToSql((a, b) => new TwoTablePartitionBy_UserDto());
+ var assertSql091 = @"SELECT a.[rownum] as1, b.[Remark] as2
+FROM (
+ SELECT a.[Id], a.[Nickname], row_number() over( partition by a.[Nickname] order by a.[Id]) [rownum]
+ FROM [TwoTablePartitionBy_User] a ) a
+INNER JOIN (
+ SELECT a.[UserId], a.[Remark]
+ FROM [TwoTablePartitionBy_UserExt] a
+ WHERE (a.[UserId] > 0)
+ GROUP BY a.[UserId], a.[Remark] ) b ON a.[Id] = b.[UserId]
+WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02'))";
+ Assert.Equal(sql091, assertSql091);
+ var list091 = fsql.Select()
+ .WithTempQuery(a => new
+ {
+ user = a,
+ rownum = SqlExt.RowNumber().Over().PartitionBy(a.Nickname).OrderBy(a.Id).ToValue()
+ })
+ .Where(a => a.rownum == 1)
+ .FromQuery(fsql.Select().Where(b => b.UserId > 0).GroupBy(b => new { b.UserId, b.Remark }).WithTempQuery(b => b.Key))
+ .InnerJoin((a, b) => a.user.Id == b.UserId)
+ .Where((a, b) => a.user.Nickname == "name03" || a.user.Nickname == "name02")
+ .ToList();
+ Assert.Equal(list091.Count, 2);
+ Assert.Equal(list091[0].rownum, 1);
+ Assert.Equal(list091[0].Id, 0);
+ Assert.Equal(list091[0].remark, "remark04");
+ Assert.Equal(list091[1].rownum, 1);
+ Assert.Equal(list091[1].Id, 0);
+ Assert.Equal(list091[1].remark, "remark05");
+
+
var sql10 = fsql.Select()
.WithTempQuery(a => new
{
@@ -648,7 +743,8 @@ WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02
FROM (
SELECT a.[Id], a.[Nickname], row_number() over( partition by a.[Nickname] order by a.[Id]) [rownum]
FROM [TwoTablePartitionBy_User] a ) a
-INNER JOIN ( SELECT a.[UserId], a.[Remark], sum(a.[UserId]) [rownum]
+INNER JOIN (
+ SELECT a.[UserId], a.[Remark], sum(a.[UserId]) [rownum]
FROM [TwoTablePartitionBy_UserExt] a
WHERE (a.[UserId] > 0)
GROUP BY a.[UserId], a.[Remark] ) b ON a.[Id] = b.[UserId]
@@ -689,7 +785,8 @@ WHERE (a.[rownum] = 1) AND ((a.[Nickname] = N'name03' OR a.[Nickname] = N'name02
FROM (
SELECT a.[Id], a.[Nickname], row_number() over( partition by a.[Nickname] order by a.[Id]) [rownum]
FROM [TwoTablePartitionBy_User] a ) a
-INNER JOIN ( SELECT a.[UserId] [uid], sum(a.[UserId]) [rownum]
+INNER JOIN (
+ SELECT a.[UserId] [uid], sum(a.[UserId]) [rownum]
FROM [TwoTablePartitionBy_UserExt] a
WHERE (a.[UserId] > 0)
GROUP BY a.[UserId] ) b ON a.[Id] = b.[uid]
diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs
index a42e34bf..c4fb4e72 100644
--- a/FreeSql/Internal/CommonExpression.cs
+++ b/FreeSql/Internal/CommonExpression.cs
@@ -51,14 +51,14 @@ namespace FreeSql.Internal
public bool ReadAnonymousField(List _tables, Func _tableRule, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Select0Provider select,
BaseDiyMemberExpression diymemexp, List whereGlobalFilter, List findIncludeMany, List findSubSelectMany, bool isAllDtoMap)
{
- void LocalSetFieldAlias(ref int localIndex)
+ void LocalSetFieldAlias(ref int localIndex, bool isdiymemexp)
{
if (localIndex >= 0)
{
parent.DbNestedField = $"as{++localIndex}";
field.Append(_common.FieldAsAlias(parent.DbNestedField));
}
- else if (diymemexp?.ParseExpMapResult != null)
+ else if (isdiymemexp && diymemexp?.ParseExpMapResult != null)
parent.DbNestedField = diymemexp.ParseExpMapResult.DbNestedField;
else if (string.IsNullOrEmpty(parent.CsName) == false)
{
@@ -77,7 +77,7 @@ namespace FreeSql.Internal
case ExpressionType.NegateChecked:
parent.DbField = $"-({ExpressionLambdaToSql((exp as UnaryExpression)?.Operand, getTSC())})";
field.Append(", ").Append(parent.DbField);
- LocalSetFieldAlias(ref index);
+ LocalSetFieldAlias(ref index, false);
if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
case ExpressionType.Convert: return ReadAnonymousField(_tables, _tableRule, field, parent, ref index, (exp as UnaryExpression)?.Operand, select, diymemexp, whereGlobalFilter, findIncludeMany, findSubSelectMany, isAllDtoMap);
@@ -96,7 +96,7 @@ namespace FreeSql.Internal
else
parent.DbField = _common.FormatSql("{0}", constExp?.Value);
field.Append(", ").Append(parent.DbField);
- LocalSetFieldAlias(ref index);
+ LocalSetFieldAlias(ref index, false);
if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
case ExpressionType.Conditional:
@@ -125,7 +125,7 @@ namespace FreeSql.Internal
else
parent.DbField = ExpressionLambdaToSql(exp, getTSC());
field.Append(", ").Append(parent.DbField);
- LocalSetFieldAlias(ref index);
+ LocalSetFieldAlias(ref index, false);
if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
case ExpressionType.Parameter:
@@ -273,7 +273,7 @@ namespace FreeSql.Internal
if (findcol != null) pdbfield = _common.RereadColumn(findcol, pdbfield);
}
field.Append(", ").Append(pdbfield);
- LocalSetFieldAlias(ref index);
+ LocalSetFieldAlias(ref index, true);
return false;
}
return false;
@@ -486,7 +486,7 @@ namespace FreeSql.Internal
}
parent.DbField = $"({ExpressionLambdaToSql(exp, getTSC())})";
field.Append(", ").Append(parent.DbField);
- LocalSetFieldAlias(ref index);
+ LocalSetFieldAlias(ref index, false);
if (parent.CsType == null && exp.Type.IsValueType) parent.CsType = exp.Type;
return false;
}
@@ -2178,6 +2178,23 @@ namespace FreeSql.Internal
}
return null;
}
+ public class ReplaceVisitor : ExpressionVisitor
+ {
+ private Expression _oldexp;
+ private Expression _newexp;
+ public Expression Modify(Expression find, Expression oldexp, Expression newexp)
+ {
+ this._oldexp = oldexp;
+ this._newexp = newexp;
+ return Visit(find);
+ }
+ protected override Expression VisitMember(MemberExpression node)
+ {
+ if (node.Expression == _oldexp)
+ return Expression.Property(_newexp, node.Member.Name);
+ return base.VisitMember(node);
+ }
+ }
public class ReplaceParameterVisitor : ExpressionVisitor
{
private Expression _replaceExp;
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs
index 87a14edd..0d8cb161 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs
@@ -141,11 +141,12 @@ namespace FreeSql.Internal.CommonProvider
{
sql2 = select2sp._tableRule(select2sp._tables[0].Table.Type, null);
if (sql2.StartsWith("(") && sql2.EndsWith(")")) sql2 = sql2.Substring(1, sql2.Length - 2);
+ if (sql2.StartsWith(" \r\n")) sql2 = sql2.Substring(3);
}
if (string.IsNullOrWhiteSpace(sql2))
sql2 = select2?.ToSql("*");
}
- return ret.WithSql(null, sql2);
+ return ret.WithSql(null, $" \r\n{sql2}");
}
public ISelectGrouping GroupBy(Expression> columns)
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs
index 0cb9b7c0..a68ea8c7 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs
@@ -38,7 +38,8 @@ namespace FreeSql.Internal.CommonProvider
ParseExpMapResult = _map;
return _map.DbField;
}
- var parentName = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression)?.Member.Name;
+ var firstMember = ((members.FirstOrDefault() as MemberExpression)?.Expression as MemberExpression);
+ var parentName = firstMember?.Member.Name;
switch (parentName)
{
case "Key":
@@ -51,29 +52,57 @@ namespace FreeSql.Internal.CommonProvider
ParseExpMapResult = read;
return read.DbField;
case "Value":
- var tb = _tables.First();
+ var curtables = _tables;
+ SelectTableInfo curtable = null;
var foridx = 0;
- if (members.Length > 1)
+ if (_select._diymemexpWithTempQuery != null && _select._diymemexpWithTempQuery is Select0Provider.WithTempQueryParser tempQueryParser)
{
- var mem0 = (members.FirstOrDefault() as MemberExpression);
- var mem0Name = mem0?.Member.Name;
- if (mem0Name?.StartsWith("Item") == true && int.TryParse(mem0Name.Substring(4), out var tryitemidx))
+ if (_select._tables.Count == 1)
+ curtable = _select._tables[0];
+ else
{
- if (tryitemidx == 1) foridx++;
- else
+ curtables = _select._tables;
+ LocalValueInitData();
+ }
+ if (tempQueryParser._outsideTable.Contains(curtable))
+ {
+ for (var a = 0; a < members.Length; a++)
+ members[a] = new CommonExpression.ReplaceVisitor().Modify(members[a], firstMember, curtable.Parameter);
+ var ret = _select._diymemexpWithTempQuery.ParseExp(members);
+ ParseExpMapResult = _select._diymemexpWithTempQuery.ParseExpMapResult;
+ return ret;
+ }
+ }
+ else
+ {
+ LocalValueInitData();
+ }
+
+ void LocalValueInitData()
+ {
+ curtable = curtables.First();
+ if (members.Length > 1)
+ {
+ var mem0 = (members.FirstOrDefault() as MemberExpression);
+ var mem0Name = mem0?.Member.Name;
+ if (mem0Name?.StartsWith("Item") == true && int.TryParse(mem0Name.Substring(4), out var tryitemidx))
{
- //var alias = $"SP10{(char)(96 + tryitemidx)}";
- var tmptb = _tables.Where((a, idx) => //a.AliasInit == alias &&
- a.Table.Type == mem0.Type && idx == tryitemidx - 1).FirstOrDefault();
- if (tmptb != null)
+ if (tryitemidx == 1) foridx++;
+ else
{
- tb = tmptb;
- foridx++;
+ //var alias = $"SP10{(char)(96 + tryitemidx)}";
+ var tmptb = curtables.Where((a, idx) => //a.AliasInit == alias &&
+ a.Table.Type == mem0.Type && idx == tryitemidx - 1).FirstOrDefault();
+ if (tmptb != null)
+ {
+ curtable = tmptb;
+ foridx++;
+ }
}
}
}
}
- var parmExp = Expression.Parameter(tb.Table.Type, tb.Alias);
+ var parmExp = Expression.Parameter(curtable.Table.Type, curtable.Alias);
Expression retExp = parmExp;
for (var a = foridx; a < members.Length; a++)
{
@@ -205,7 +234,7 @@ namespace FreeSql.Internal.CommonProvider
var ret = (_orm as BaseDbProvider).CreateSelectProvider(null) as Select1Provider;
if (ret._tables[0].Table == null) ret._tables[0].Table = TableInfo.GetDefaultTable(typeof(TDto));
var parser = new Select0Provider.WithTempQueryParser(_select, this, selector, ret._tables[0]);
- var sql = this.ToSql(parser._insideSelectList[0].InsideField);
+ var sql = $"\r\n{this.ToSql(parser._insideSelectList[0].InsideField)}";
ret.WithSql(sql);
ret._diymemexpWithTempQuery = parser;
return ret;