using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; namespace SqlSugar { /// ///Json model to sql /// public abstract partial class SqlBuilderProvider : SqlBuilderAccessory, ISqlBuilder { #region Root public KeyValuePair FuncModelToSql(IFuncModel model) { ObjectFuncModel data = model as ObjectFuncModel; var name = data.FuncName; var parameters = data.Parameters; var dbMethods = this.Context.Queryable().QueryBuilder.LambdaExpressions.DbMehtods; var methods = GetAllMethods(dbMethods); var methodName = GetMethodName(name, methods); var methodInfo = GetMethod(dbMethods, methodName); var pars = methodInfo.GetParameters(); var resSql = ""; var resPars = new List(); resSql = GetSql(parameters, dbMethods, methodName, methodInfo, pars, resPars); if (name.EqualCase("MappingColumn")) { if (!(this.Context?. CurrentConnectionConfig?.MoreSettings?.EnableModelFuncMappingColumn == true)) { Check.ExceptionEasy("Enable MappingColumn need in ConnectionConfig - > MoreSettings - > EnableModelFuncMappingColumn set to true", "MappingColumn考虑到风险情况需要开启才能使用,请在 ConnectionConfig->MoreSettings->EnableModelFuncMappingColumn设置为true"); } resSql = parameters.First() +""; } return new KeyValuePair(resSql, resPars.ToArray()); } #endregion #region Level2 private string GetSql(List parameters, IDbMethods dbMethods, string methodName, System.Reflection.MethodInfo methodInfo, System.Reflection.ParameterInfo[] pars, List resPars) { string resSql; if (IsNoParameter(pars)) { resSql = GetNoParameterMehtodSql(dbMethods, methodInfo); } else if (IsFormatMethod(methodName)) { resSql = GetFormatMethodSql(parameters, resPars); } else if (IsSqlFuncMethod(pars)) { resSql = GetSqlFuncSql(parameters, dbMethods, methodName, methodInfo, resPars); } else if (IsMergeStringMethod(methodName)) { resSql = GetSqlFuncSql(parameters, dbMethods, methodName, methodInfo, resPars); } else { resSql = GetNoSupportMethodSql(methodInfo); } return resSql; } private static System.Reflection.MethodInfo GetMethod(IDbMethods dbMethods, string methodName) { return dbMethods.GetType().GetMethods() .Where(it => it.Name == methodName) .Where(it => it.Name != "Equals" || it.GetParameters().Length == 1 && it.GetParameters().First().ParameterType == typeof(MethodCallExpressionModel)) .FirstOrDefault(); } private static string GetMethodName(string name, List methods) { var result = methods.FirstOrDefault(it => name.EqualCase("SqlFunc_" + it) || name.EqualCase(it)); Check.Exception(result == null, $" { name } is error "); return result; } private static List GetAllMethods(IDbMethods dbMethods) { return new ReflectionInoCacheService().GetOrCreate("Json2SqlGetFuncSql", () => dbMethods.GetType() .GetMethods().Where(it => it.Name != "GetHashCode").Select(it => it.Name).ToList()); } #endregion #region Level3 private static string GetNoSupportMethodSql(System.Reflection.MethodInfo methodInfo) { throw new Exception(methodInfo.Name); } private string GetSqlFuncSql(List parameters, IDbMethods dbMethods, string methodName, System.Reflection.MethodInfo methodInfo, List resPars) { string resSql; var args = new List(); int i = 0; foreach (var item in parameters) { i++; string value = null; if (methodName.IsIn("ContainsArray", "ContainsArrayUseSqlParameters") &&i==1) { var first = Regex.Split(item+"", ":").First(); var last = Regex.Split(item + "", ":").Last(); object[] array = this.Context.Utilities.DeserializeObject(last); value = GetParameterName(resPars, array); } else { value = GetSqlPart(item, resPars); } args.Add(new MethodCallExpressionArgs { MemberName = value, MemberValue = resPars.FirstOrDefault(it => it.ParameterName == value)?.Value?? value, IsMember = true }); } if (IsMergeStringMethod(methodName)) { return methodInfo.Invoke(dbMethods, new object[] { args.Select(it=>it.MemberName.ObjToString()).ToArray() }).ObjToString(); } if (IsToStringFormat(methodName, args)) { var fieldName = args.First().MemberName.ObjToString(); var format = args.Last().MemberValue.ObjToString(); var queryable=this.Context.Queryable() .Select(it => SqlFunc.MappingColumn(fieldName).ToString(format)); var select=queryable.QueryBuilder.GetSelectValue; return select; } resSql = methodInfo.Invoke(dbMethods, new object[] { new MethodCallExpressionModel() { Name=methodName, Args=args } }).ObjToString(); return resSql; } private static bool IsToStringFormat(string methodName, List args) { return methodName == nameof(ToString) && args?.Count == 2; } private string GetFormatMethodSql(List parameters, List resPars) { string resSql; var objects = new List(); foreach (var item in parameters) { var value = GetSqlPart(item, resPars); objects.Add(value.ObjToString()); } resSql = string.Join(" ", string.Join(" ", objects)); return resSql; } private static string GetNoParameterMehtodSql(IDbMethods dbMethods, System.Reflection.MethodInfo methodInfo) { return methodInfo.Invoke(dbMethods, new object[] { }).ObjToString(); } #endregion #region Helper private static bool IsMergeStringMethod(string methodName) { return methodName == "MergeString"; } private static bool IsSqlFuncMethod(System.Reflection.ParameterInfo[] pars) { return pars.First().ParameterType == typeof(MethodCallExpressionModel); } private static bool IsFormatMethod(string methodName) { return methodName.EqualCase("format"); } private static bool IsNoParameter(System.Reflection.ParameterInfo[] pars) { return pars.Length == 0; } #endregion } }