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
}
}