mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-06-19 12:28:15 +08:00
- 增加 SqlExt 常用开窗函数的自定义表达式解析;
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
using FreeSql.DataAnnotations;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
[ExpressionCall]
|
||||
@ -39,4 +40,67 @@ public static class FreeSqlGlobalExpressionCallExtensions
|
||||
expContext.Value.Result = $"{expContext.Value.ParsedContent["that"]} >= {expContext.Value.ParsedContent["start"]} and {expContext.Value.ParsedContent["that"]} < {expContext.Value.ParsedContent["end"]}";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FreeSql
|
||||
{
|
||||
[ExpressionCall]
|
||||
public static class SqlExt
|
||||
{
|
||||
public static ThreadLocal<ExpressionCallContext> expContext = new ThreadLocal<ExpressionCallContext>();
|
||||
static ThreadLocal<StringBuilder> expSb = new ThreadLocal<StringBuilder>();
|
||||
static ThreadLocal<bool> expSbIsOrderBy = new ThreadLocal<bool>();
|
||||
|
||||
public static ISqlOver<long> Rank() => Over<long>("RANK()");
|
||||
public static ISqlOver<long> DenseRank() => Over<long>("DENSE_RANK()");
|
||||
public static ISqlOver<long> Count() => Over<long>("COUNT()");
|
||||
public static ISqlOver<decimal> Sum(object column) => Over<decimal>($"Sum({expContext.Value.ParsedContent["column"]})");
|
||||
public static ISqlOver<decimal> Avg() => Over<decimal>($"AVG({expContext.Value.ParsedContent["column"]})");
|
||||
public static ISqlOver<T> Max<T>(T column) => Over<T>($"MAX({expContext.Value.ParsedContent["column"]})");
|
||||
public static ISqlOver<T> Min<T>(T column) => Over<T>($"MIN({expContext.Value.ParsedContent["column"]})");
|
||||
public static ISqlOver<long> RowNumber() => Over<long>("ROW_NUMBER()");
|
||||
|
||||
#region .. over([partition by ..] order by ...)
|
||||
static ISqlOver<TValue> Over<TValue>(string sqlFunc)
|
||||
{
|
||||
expSb.Value = new StringBuilder();
|
||||
expSbIsOrderBy.Value = false;
|
||||
expSb.Value.Append($"{sqlFunc} ");
|
||||
return null;
|
||||
}
|
||||
public static ISqlOver<TValue> Over<TValue>(this ISqlOver<TValue> that)
|
||||
{
|
||||
expSb.Value.Append("OVER(");
|
||||
return that;
|
||||
}
|
||||
public static ISqlOver<TValue> PartitionBy<TValue>(this ISqlOver<TValue> that, object column)
|
||||
{
|
||||
expSb.Value.Append("PARTITION BY ").Append(expContext.Value.ParsedContent["column"]).Append(",");
|
||||
return that;
|
||||
}
|
||||
public static ISqlOver<TValue> OrderBy<TValue>(this ISqlOver<TValue> that, object column) => OrderBy(that, false);
|
||||
public static ISqlOver<TValue> OrderByDescending<TValue>(this ISqlOver<TValue> that, object column) => OrderBy(that, true);
|
||||
static ISqlOver<TValue> OrderBy<TValue>(this ISqlOver<TValue> that, bool isDesc)
|
||||
{
|
||||
var sb = expSb.Value;
|
||||
if (expSbIsOrderBy.Value == false)
|
||||
{
|
||||
sb.Append("ORDER BY ");
|
||||
expSbIsOrderBy.Value = true;
|
||||
}
|
||||
sb.Append(expContext.Value.ParsedContent["column"]);
|
||||
if (isDesc) sb.Append(" desc");
|
||||
sb.Append(",");
|
||||
return that;
|
||||
}
|
||||
public static TValue ToValue<TValue>(this ISqlOver<TValue> that)
|
||||
{
|
||||
var sb = expSb.Value.ToString().TrimEnd(',');
|
||||
expSb.Value.Clear();
|
||||
expContext.Value.Result = $"{sb})";
|
||||
return default;
|
||||
}
|
||||
public interface ISqlOver<TValue> { }
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -627,8 +627,11 @@ namespace FreeSql.Internal
|
||||
};
|
||||
var exp3MethodParams = exp3.Method.GetParameters();
|
||||
var dbParamsIndex = tsc.dbParams?.Count;
|
||||
ecc.RawExpression.Add(exp3MethodParams[0].Name, exp3.Arguments[0]);
|
||||
ecc.ParsedContent.Add(exp3MethodParams[0].Name, exp3MethodParams[0].GetCustomAttributes(typeof(RawValueAttribute), true).Any() ? null : ExpressionLambdaToSql(exp3.Arguments[0], tsc));
|
||||
if (exp3MethodParams.Any())
|
||||
{
|
||||
ecc.RawExpression.Add(exp3MethodParams[0].Name, exp3.Arguments[0]);
|
||||
ecc.ParsedContent.Add(exp3MethodParams[0].Name, exp3MethodParams[0].GetCustomAttributes(typeof(RawValueAttribute), true).Any() ? null : ExpressionLambdaToSql(exp3.Arguments[0], tsc));
|
||||
}
|
||||
if (tsc.dbParams?.Count > dbParamsIndex) ecc.DbParameter = tsc.dbParams.Last();
|
||||
List<DbParameter> oldDbParams = tsc.SetDbParamsReturnOld(null);
|
||||
for (var a = 1; a < exp3.Arguments.Count; a++)
|
||||
@ -646,7 +649,20 @@ namespace FreeSql.Internal
|
||||
{
|
||||
var eccContent = ecc.ParsedContent[exp3MethodParams[a].Name];
|
||||
if (eccContent == null)
|
||||
exp3InvokeParams[a] = Expression.Lambda(exp3.Arguments[a]).Compile().DynamicInvoke();
|
||||
{
|
||||
var isdyInvoke = true;
|
||||
if (exp3.Arguments[a].NodeType == ExpressionType.Call) //判断如果参数也是标记 ExpressionCall
|
||||
{
|
||||
var exp3ArgsACallExp = exp3.Arguments[a] as MethodCallExpression;
|
||||
if (exp3ArgsACallExp.Object == null && (
|
||||
_dicTypeExistsExpressionCallAttribute.GetOrAdd(exp3ArgsACallExp.Method.DeclaringType, dttp => dttp.GetCustomAttributes(typeof(ExpressionCallAttribute), true).Any()) ||
|
||||
exp3ArgsACallExp.Method.GetCustomAttributes(typeof(ExpressionCallAttribute), true).Any()
|
||||
))
|
||||
isdyInvoke = false;
|
||||
}
|
||||
if (isdyInvoke)
|
||||
exp3InvokeParams[a] = Expression.Lambda(exp3.Arguments[a]).Compile().DynamicInvoke();
|
||||
}
|
||||
else if (exp3.Arguments[a].IsParameter())
|
||||
exp3InvokeParams[a] = exp3.Arguments[a].Type.CreateInstanceGetDefaultValue();
|
||||
else
|
||||
@ -668,7 +684,7 @@ namespace FreeSql.Internal
|
||||
{
|
||||
var sqlRet = exp3.Method.Invoke(null, exp3InvokeParams);
|
||||
if (string.IsNullOrEmpty(ecc.Result) && sqlRet is string) ecc.Result = string.Concat(sqlRet);
|
||||
if (string.IsNullOrEmpty(ecc.Result)) ecc.Result = ecc.ParsedContent[exp3MethodParams[0].Name];
|
||||
if (string.IsNullOrEmpty(ecc.Result) && exp3MethodParams.Any()) ecc.Result = ecc.ParsedContent[exp3MethodParams[0].Name];
|
||||
if (ecc.UserParameters?.Any() == true) tsc.dbParams?.AddRange(ecc.UserParameters);
|
||||
return ecc.Result;
|
||||
}
|
||||
|
Reference in New Issue
Block a user