mirror of
				https://github.com/nsnail/FreeSql.git
				synced 2025-11-04 09:15:27 +08:00 
			
		
		
		
	- 增加 SqlExt.GroupConcat MySql 函数解决;
This commit is contained in:
		@@ -155,6 +155,37 @@ namespace FreeSql.Tests
 | 
				
			|||||||
        [Fact]
 | 
					        [Fact]
 | 
				
			||||||
        public void Test03()
 | 
					        public void Test03()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            var sqlextGroupConcat = g.mysql.Select<Edi, EdiItem>()
 | 
				
			||||||
 | 
					                .InnerJoin((a, b) => b.Id == a.Id)
 | 
				
			||||||
 | 
					                .ToSql((a, b) => new
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Id = a.Id,
 | 
				
			||||||
 | 
					                    EdiId = b.Id,
 | 
				
			||||||
 | 
					                    case1 = SqlExt.Case()
 | 
				
			||||||
 | 
					                        .When(a.Id == 1, 10)
 | 
				
			||||||
 | 
					                        .When(a.Id == 2, 11)
 | 
				
			||||||
 | 
					                        .When(a.Id == 3, 12)
 | 
				
			||||||
 | 
					                        .When(a.Id == 4, 13)
 | 
				
			||||||
 | 
					                        .When(a.Id == 5, SqlExt.Case().When(b.Id == 1, 10000).Else(999).End())
 | 
				
			||||||
 | 
					                        .End(),
 | 
				
			||||||
 | 
					                    groupct1 = SqlExt.GroupConcat(a.Id).Distinct().OrderBy(b.EdiId).Separator("_").ToValue()
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            var sqlextGroupConcatToList = g.mysql.Select<Edi, EdiItem>()
 | 
				
			||||||
 | 
					                .InnerJoin((a, b) => b.Id == a.Id)
 | 
				
			||||||
 | 
					                .ToList((a, b) => new
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    Id = a.Id,
 | 
				
			||||||
 | 
					                    EdiId = b.Id,
 | 
				
			||||||
 | 
					                    case1 = SqlExt.Case()
 | 
				
			||||||
 | 
					                        .When(a.Id == 1, 10)
 | 
				
			||||||
 | 
					                        .When(a.Id == 2, 11)
 | 
				
			||||||
 | 
					                        .When(a.Id == 3, 12)
 | 
				
			||||||
 | 
					                        .When(a.Id == 4, 13)
 | 
				
			||||||
 | 
					                        .When(a.Id == 5, SqlExt.Case().When(b.Id == 1, 10000).Else(999).End())
 | 
				
			||||||
 | 
					                        .End(),
 | 
				
			||||||
 | 
					                    groupct1 = SqlExt.GroupConcat(a.Id).Distinct().OrderBy(b.EdiId).Separator("_").ToValue()
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var sqlextCase = g.sqlserver.Select<Edi, EdiItem>()
 | 
					            var sqlextCase = g.sqlserver.Select<Edi, EdiItem>()
 | 
				
			||||||
                .InnerJoin((a, b) => b.Id == a.Id)
 | 
					                .InnerJoin((a, b) => b.Id == a.Id)
 | 
				
			||||||
                .ToSql((a, b) => new
 | 
					                .ToSql((a, b) => new
 | 
				
			||||||
@@ -167,7 +198,8 @@ namespace FreeSql.Tests
 | 
				
			|||||||
                        .When(a.Id == 3, 12)
 | 
					                        .When(a.Id == 3, 12)
 | 
				
			||||||
                        .When(a.Id == 4, 13)
 | 
					                        .When(a.Id == 4, 13)
 | 
				
			||||||
                        .When(a.Id == 5, SqlExt.Case().When(b.Id == 1, 10000).Else(999).End())
 | 
					                        .When(a.Id == 5, SqlExt.Case().When(b.Id == 1, 10000).Else(999).End())
 | 
				
			||||||
                        .End()
 | 
					                        .End(),
 | 
				
			||||||
 | 
					                    over1 = SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
            var sqlextCaseToList = g.sqlserver.Select<Edi, EdiItem>()
 | 
					            var sqlextCaseToList = g.sqlserver.Select<Edi, EdiItem>()
 | 
				
			||||||
                .InnerJoin((a, b) => b.Id == a.Id)
 | 
					                .InnerJoin((a, b) => b.Id == a.Id)
 | 
				
			||||||
@@ -181,7 +213,8 @@ namespace FreeSql.Tests
 | 
				
			|||||||
                        .When(a.Id == 3, 12)
 | 
					                        .When(a.Id == 3, 12)
 | 
				
			||||||
                        .When(a.Id == 4, 13)
 | 
					                        .When(a.Id == 4, 13)
 | 
				
			||||||
                        .When(a.Id == 5, SqlExt.Case().When(b.Id == 1, 10000).Else(999).End())
 | 
					                        .When(a.Id == 5, SqlExt.Case().When(b.Id == 1, 10000).Else(999).End())
 | 
				
			||||||
                        .End()
 | 
					                        .End(),
 | 
				
			||||||
 | 
					                    over1 = SqlExt.Rank().Over().OrderBy(a.Id).OrderByDescending(b.EdiId).ToValue(),
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
 | 
				
			|||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
using System.Text;
 | 
					using System.Text;
 | 
				
			||||||
using System.Threading;
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					using static FreeSql.SqlExtExtensions;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[ExpressionCall]
 | 
					[ExpressionCall]
 | 
				
			||||||
public static class FreeSqlGlobalExpressionCallExtensions
 | 
					public static class FreeSqlGlobalExpressionCallExtensions
 | 
				
			||||||
@@ -46,99 +47,215 @@ public static class FreeSqlGlobalExpressionCallExtensions
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace FreeSql
 | 
					namespace FreeSql
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    /// <summary>
 | 
				
			||||||
 | 
					    /// SqlExt 是利用自定表达式函数解析功能,解析默认常用的SQL函数,欢迎 PR
 | 
				
			||||||
 | 
					    /// </summary>
 | 
				
			||||||
    [ExpressionCall]
 | 
					    [ExpressionCall]
 | 
				
			||||||
    public static class SqlExt
 | 
					    public static class SqlExt
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        public static ThreadLocal<ExpressionCallContext> expContext = new ThreadLocal<ExpressionCallContext>();
 | 
					        internal static ThreadLocal<ExpressionCallContext> expContext = new ThreadLocal<ExpressionCallContext>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public static ISqlOver<long> Rank() => Over<long>("RANK()");
 | 
					        #region SqlServer/PostgreSQL over
 | 
				
			||||||
        public static ISqlOver<long> DenseRank() => Over<long>("DENSE_RANK()");
 | 
					        /// <summary>
 | 
				
			||||||
        public static ISqlOver<long> Count() => Over<long>("COUNT()");
 | 
					        /// rank() over(order by ...)
 | 
				
			||||||
        public static ISqlOver<decimal> Sum(object column) => Over<decimal>($"Sum({expContext.Value.ParsedContent["column"]})");
 | 
					        /// </summary>
 | 
				
			||||||
        public static ISqlOver<decimal> Avg() => Over<decimal>($"AVG({expContext.Value.ParsedContent["column"]})");
 | 
					        /// <returns></returns>
 | 
				
			||||||
        public static ISqlOver<T> Max<T>(T column) => Over<T>($"MAX({expContext.Value.ParsedContent["column"]})");
 | 
					        public static ISqlOver<long> Rank() => Over<long>("rank()");
 | 
				
			||||||
        public static ISqlOver<T> Min<T>(T column) => Over<T>($"MIN({expContext.Value.ParsedContent["column"]})");
 | 
					        /// <summary>
 | 
				
			||||||
        public static ISqlOver<long> RowNumber() => Over<long>("ROW_NUMBER()");
 | 
					        /// dense_rank() over(order by ...)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ISqlOver<long> DenseRank() => Over<long>("dense_rank()");
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// count() over(order by ...)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ISqlOver<long> Count() => Over<long>("count()");
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// sum(..) over(order by ...)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="column"></param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ISqlOver<decimal> Sum(object column) => Over<decimal>($"sum({expContext.Value.ParsedContent["column"]})");
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// avg(..) over(order by ...)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ISqlOver<decimal> Avg() => Over<decimal>($"avg({expContext.Value.ParsedContent["column"]})");
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// max(..) over(order by ...)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <typeparam name="T"></typeparam>
 | 
				
			||||||
 | 
					        /// <param name="column"></param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ISqlOver<T> Max<T>(T column) => Over<T>($"max({expContext.Value.ParsedContent["column"]})");
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// min(..) over(order by ...)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <typeparam name="T"></typeparam>
 | 
				
			||||||
 | 
					        /// <param name="column"></param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ISqlOver<T> Min<T>(T column) => Over<T>($"min({expContext.Value.ParsedContent["column"]})");
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// SqlServer row_number() over(order by ...)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ISqlOver<long> RowNumber() => Over<long>("row_number()");
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// case when .. then .. end
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static ICaseWhenEnd Case() => SqlExtExtensions.Case();
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// MySql group_concat(distinct .. order by .. separator ..)
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="column"></param>
 | 
				
			||||||
 | 
					        /// <returns></returns>
 | 
				
			||||||
 | 
					        public static IGroupConcat GroupConcat(object column) => SqlExtExtensions.GroupConcat(column);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [ExpressionCall]
 | 
				
			||||||
 | 
					    public static class SqlExtExtensions //这个类存在的意义,是不想使用者方法名污染
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        static ThreadLocal<ExpressionCallContext> expContextSelf = new ThreadLocal<ExpressionCallContext>();
 | 
				
			||||||
 | 
					        static ExpressionCallContext expContext => expContextSelf.Value ?? SqlExt.expContext.Value;
 | 
				
			||||||
 | 
					        internal static ThreadLocal<List<ExpSbInfo>> expSb = new ThreadLocal<List<ExpSbInfo>>();
 | 
				
			||||||
 | 
					        internal static ExpSbInfo expSbLast => expSb.Value.Last();
 | 
				
			||||||
 | 
					        internal class ExpSbInfo
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            public StringBuilder Sb { get; } = new StringBuilder();
 | 
				
			||||||
 | 
					            public bool IsOrderBy = false;
 | 
				
			||||||
 | 
					            public bool IsDistinct = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region .. over([partition by ..] order by ...)
 | 
					        #region .. over([partition by ..] order by ...)
 | 
				
			||||||
        static ThreadLocal<StringBuilder> expOverSb = new ThreadLocal<StringBuilder>();
 | 
					        internal static ISqlOver<TValue> Over<TValue>(string sqlFunc)
 | 
				
			||||||
        static ThreadLocal<bool> expOverSbIsOrderBy = new ThreadLocal<bool>();
 | 
					 | 
				
			||||||
        static ISqlOver<TValue> Over<TValue>(string sqlFunc)
 | 
					 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            expOverSb.Value = new StringBuilder();
 | 
					            if (expSb.Value == null) expSb.Value = new List<ExpSbInfo>();
 | 
				
			||||||
            expOverSbIsOrderBy.Value = false;
 | 
					            expSb.Value.Add(new ExpSbInfo());
 | 
				
			||||||
            expOverSb.Value.Append($"{sqlFunc} ");
 | 
					            expSbLast.Sb.Append(sqlFunc).Append(" ");
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static ISqlOver<TValue> Over<TValue>(this ISqlOver<TValue> that)
 | 
					        public static ISqlOver<TValue> Over<TValue>(this ISqlOver<TValue> that)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            expOverSb.Value.Append("OVER(");
 | 
					            expSbLast.Sb.Append("over(");
 | 
				
			||||||
            return that;
 | 
					            return that;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static ISqlOver<TValue> PartitionBy<TValue>(this ISqlOver<TValue> that, object column)
 | 
					        public static ISqlOver<TValue> PartitionBy<TValue>(this ISqlOver<TValue> that, object column)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            expOverSb.Value.Append("PARTITION BY ").Append(expContext.Value.ParsedContent["column"]).Append(",");
 | 
					            expSbLast.Sb.Append(" partition by ").Append(expContext.ParsedContent["column"]).Append(",");
 | 
				
			||||||
            return that;
 | 
					            return that;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static ISqlOver<TValue> OrderBy<TValue>(this ISqlOver<TValue> that, object column) => OrderBy(that, false);
 | 
					        public static ISqlOver<TValue> OrderBy<TValue>(this ISqlOver<TValue> that, object column) => OrderByPriv(that, false);
 | 
				
			||||||
        public static ISqlOver<TValue> OrderByDescending<TValue>(this ISqlOver<TValue> that, object column) => OrderBy(that, true);
 | 
					        public static ISqlOver<TValue> OrderByDescending<TValue>(this ISqlOver<TValue> that, object column) => OrderByPriv(that, true);
 | 
				
			||||||
        static ISqlOver<TValue> OrderBy<TValue>(this ISqlOver<TValue> that, bool isDesc)
 | 
					        static ISqlOver<TValue> OrderByPriv<TValue>(this ISqlOver<TValue> that, bool isDesc)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var sb = expOverSb.Value;
 | 
					            var sb = expSbLast.Sb;
 | 
				
			||||||
            if (expOverSbIsOrderBy.Value == false)
 | 
					            if (expSbLast.IsOrderBy == false)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                sb.Append("ORDER BY ");
 | 
					                sb.Append(" order by ");
 | 
				
			||||||
                expOverSbIsOrderBy.Value = true;
 | 
					                expSbLast.IsOrderBy = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            sb.Append(expContext.Value.ParsedContent["column"]);
 | 
					            sb.Append(expContext.ParsedContent["column"]);
 | 
				
			||||||
            if (isDesc) sb.Append(" desc");
 | 
					            if (isDesc) sb.Append(" desc");
 | 
				
			||||||
            sb.Append(",");
 | 
					            sb.Append(",");
 | 
				
			||||||
            return that;
 | 
					            return that;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static TValue ToValue<TValue>(this ISqlOver<TValue> that)
 | 
					        public static TValue ToValue<TValue>(this ISqlOver<TValue> that)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var sb = expOverSb.Value.ToString().TrimEnd(',');
 | 
					            var sql = expSbLast.Sb.ToString().TrimEnd(',');
 | 
				
			||||||
            expOverSb.Value.Clear();
 | 
					            expSbLast.Sb.Clear();
 | 
				
			||||||
            expContext.Value.Result = $"{sb})";
 | 
					            expSb.Value.RemoveAt(expSb.Value.Count - 1);
 | 
				
			||||||
 | 
					            expContext.Result = $"{sql})";
 | 
				
			||||||
            return default;
 | 
					            return default;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public interface ISqlOver<TValue> { }
 | 
					        public interface ISqlOver<TValue> { }
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        #region case when .. then .. when .. then .. end
 | 
					        #region case when .. then .. when .. then .. end
 | 
				
			||||||
        static ThreadLocal<List<StringBuilder>> expCaseWhenEndSb = new ThreadLocal<List<StringBuilder>>();
 | 
					 | 
				
			||||||
        public static ICaseWhenEnd Case()
 | 
					        public static ICaseWhenEnd Case()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (expCaseWhenEndSb.Value == null) expCaseWhenEndSb.Value = new List<StringBuilder>();
 | 
					            if (expSb.Value == null) expSb.Value = new List<ExpSbInfo>();
 | 
				
			||||||
            expCaseWhenEndSb.Value.Add(new StringBuilder().Append("CASE "));
 | 
					            expSb.Value.Add(new ExpSbInfo());
 | 
				
			||||||
 | 
					            expSbLast.Sb.Append("case ");
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static ICaseWhenEnd<TValue> When<TValue>(this ICaseWhenEnd that, bool test, TValue then)
 | 
					        public static ICaseWhenEnd<TValue> When<TValue>(this ICaseWhenEnd that, bool test, TValue then)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            expCaseWhenEndSb.Value.Last().Append("\r\n  WHEN ").Append(expContext.Value.ParsedContent["test"]).Append(" THEN ").Append(expContext.Value.ParsedContent["then"]);
 | 
					            expSbLast.Sb.Append($"\r\n{"".PadRight(expSb.Value.Count * 2)}when ").Append(expContext.ParsedContent["test"]).Append(" then ").Append(expContext.ParsedContent["then"]);
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static ICaseWhenEnd<TValue> When<TValue>(this ICaseWhenEnd<TValue> that, bool test, TValue then)
 | 
					        public static ICaseWhenEnd<TValue> When<TValue>(this ICaseWhenEnd<TValue> that, bool test, TValue then)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            expCaseWhenEndSb.Value.Last().Append("\r\n  WHEN ").Append(expContext.Value.ParsedContent["test"]).Append(" THEN ").Append(expContext.Value.ParsedContent["then"]);
 | 
					            expSbLast.Sb.Append($"\r\n{"".PadRight(expSb.Value.Count * 2)}when ").Append(expContext.ParsedContent["test"]).Append(" then ").Append(expContext.ParsedContent["then"]);
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static ICaseWhenEnd<TValue> Else<TValue>(this ICaseWhenEnd<TValue> that, TValue then)
 | 
					        public static ICaseWhenEnd<TValue> Else<TValue>(this ICaseWhenEnd<TValue> that, TValue then)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            expCaseWhenEndSb.Value.Last().Append("\r\n  ELSE ").Append(expContext.Value.ParsedContent["then"]);
 | 
					            expSbLast.Sb.Append($"\r\n{"".PadRight(expSb.Value.Count * 2)}else ").Append(expContext.ParsedContent["then"]);
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public static TValue End<TValue>(this ICaseWhenEnd<TValue> that)
 | 
					        public static TValue End<TValue>(this ICaseWhenEnd<TValue> that)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var sb = expCaseWhenEndSb.Value;
 | 
					            var sql = expSbLast.Sb.Append($"\r\n{"".PadRight(expSb.Value.Count * 2 - 2)}end").ToString();
 | 
				
			||||||
            var sql = sb.Last().Append("\r\nEND").ToString();
 | 
					            expSbLast.Sb.Clear();
 | 
				
			||||||
            sb.Last().Clear();
 | 
					            expSb.Value.RemoveAt(expSb.Value.Count - 1);
 | 
				
			||||||
            sb.RemoveAt(sb.Count - 1);
 | 
					            expContext.Result = sql;
 | 
				
			||||||
            expContext.Value.Result = sql;
 | 
					 | 
				
			||||||
            return default;
 | 
					            return default;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        public interface ICaseWhenEnd { }
 | 
					        public interface ICaseWhenEnd { }
 | 
				
			||||||
        public interface ICaseWhenEnd<TValue> { }
 | 
					        public interface ICaseWhenEnd<TValue> { }
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #region group_concat
 | 
				
			||||||
 | 
					        public static IGroupConcat GroupConcat(object column)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (expSb.Value == null) expSb.Value = new List<ExpSbInfo>();
 | 
				
			||||||
 | 
					            expSb.Value.Add(new ExpSbInfo());
 | 
				
			||||||
 | 
					            expSbLast.Sb.Append("group_concat(").Append(expContext.ParsedContent["column"]);
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public static IGroupConcat Distinct(this IGroupConcat that)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (expSbLast.IsDistinct == false)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                expSbLast.Sb.Insert(expSbLast.Sb.ToString().LastIndexOf("group_concat(") + 13, "distinct ");
 | 
				
			||||||
 | 
					                expSbLast.IsDistinct = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return that;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public static IGroupConcat Separator(this IGroupConcat that, object separator)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (expSbLast.IsOrderBy) expSbLast.Sb.Remove(expSbLast.Sb.Length - 1, 1);
 | 
				
			||||||
 | 
					            expSbLast.Sb.Append(" separator ").Append(expContext.ParsedContent["separator"]);
 | 
				
			||||||
 | 
					            return that;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public static IGroupConcat OrderBy(this IGroupConcat that, object column) => OrderByPriv(that, false);
 | 
				
			||||||
 | 
					        public static IGroupConcat OrderByDescending(this IGroupConcat that, object column) => OrderByPriv(that, true);
 | 
				
			||||||
 | 
					        static IGroupConcat OrderByPriv(this IGroupConcat that, bool isDesc)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var sb = expSbLast.Sb;
 | 
				
			||||||
 | 
					            if (expSbLast.IsOrderBy == false)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                sb.Append(" order by ");
 | 
				
			||||||
 | 
					                expSbLast.IsOrderBy = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            sb.Append(expContext.ParsedContent["column"]);
 | 
				
			||||||
 | 
					            if (isDesc) sb.Append(" desc");
 | 
				
			||||||
 | 
					            sb.Append(",");
 | 
				
			||||||
 | 
					            return that;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public static string ToValue(this IGroupConcat that)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            var sql = expSbLast.Sb.ToString().TrimEnd(',');
 | 
				
			||||||
 | 
					            expSbLast.Sb.Clear();
 | 
				
			||||||
 | 
					            expSb.Value.RemoveAt(expSb.Value.Count - 1);
 | 
				
			||||||
 | 
					            expContext.Result = $"{sql})";
 | 
				
			||||||
 | 
					            return default;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        public interface IGroupConcat { }
 | 
				
			||||||
 | 
					        #endregion
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -130,6 +130,7 @@ public static partial class FreeSqlGlobalExtensions
 | 
				
			|||||||
        if (that == typeof(string)) return default(string);
 | 
					        if (that == typeof(string)) return default(string);
 | 
				
			||||||
        if (that == typeof(Guid)) return default(Guid);
 | 
					        if (that == typeof(Guid)) return default(Guid);
 | 
				
			||||||
        if (that.IsArray) return Array.CreateInstance(that, 0);
 | 
					        if (that.IsArray) return Array.CreateInstance(that, 0);
 | 
				
			||||||
 | 
					        if (that.IsInterface || that.IsAbstract) return null;
 | 
				
			||||||
        var ctorParms = that.InternalGetTypeConstructor0OrFirst(false)?.GetParameters();
 | 
					        var ctorParms = that.InternalGetTypeConstructor0OrFirst(false)?.GetParameters();
 | 
				
			||||||
        if (ctorParms == null || ctorParms.Any() == false) return Activator.CreateInstance(that, true);
 | 
					        if (ctorParms == null || ctorParms.Any() == false) return Activator.CreateInstance(that, true);
 | 
				
			||||||
        return Activator.CreateInstance(that, ctorParms
 | 
					        return Activator.CreateInstance(that, ctorParms
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -684,6 +684,77 @@
 | 
				
			|||||||
            <param name="columnType"></param>
 | 
					            <param name="columnType"></param>
 | 
				
			||||||
            <param name="setExp"></param>
 | 
					            <param name="setExp"></param>
 | 
				
			||||||
        </member>
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="T:FreeSql.SqlExt">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            SqlExt 是利用自定表达式函数解析功能,解析默认常用的SQL函数,欢迎 PR
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.Rank">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            rank() over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.DenseRank">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            dense_rank() over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.Count">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            count() over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.Sum(System.Object)">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            sum(..) over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="column"></param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.Avg">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            avg(..) over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.Max``1(``0)">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            max(..) over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <typeparam name="T"></typeparam>
 | 
				
			||||||
 | 
					            <param name="column"></param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.Min``1(``0)">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            min(..) over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <typeparam name="T"></typeparam>
 | 
				
			||||||
 | 
					            <param name="column"></param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.RowNumber">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            SqlServer row_number() over(order by ...)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.Case">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            case when .. then .. end
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
 | 
					        <member name="M:FreeSql.SqlExt.GroupConcat(System.Object)">
 | 
				
			||||||
 | 
					            <summary>
 | 
				
			||||||
 | 
					            MySql group_concat(distinct .. order by .. separator ..)
 | 
				
			||||||
 | 
					            </summary>
 | 
				
			||||||
 | 
					            <param name="column"></param>
 | 
				
			||||||
 | 
					            <returns></returns>
 | 
				
			||||||
 | 
					        </member>
 | 
				
			||||||
        <member name="M:FreeSql.FreeSqlBuilder.UseConnectionString(FreeSql.DataType,System.String,System.Type)">
 | 
					        <member name="M:FreeSql.FreeSqlBuilder.UseConnectionString(FreeSql.DataType,System.String,System.Type)">
 | 
				
			||||||
            <summary>
 | 
					            <summary>
 | 
				
			||||||
            使用连接串(推荐)
 | 
					            使用连接串(推荐)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user