using Newtonsoft.Json.Linq; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using TEAMModelOS.SDK; namespace TEAMModelOS.SDK.DI { public class SQLHelper { static readonly string[] LogicOpers = new string[] { " and ", " or " }; static readonly string[] CompareOpers = new string[] { " > ", " < ", " <= ", " >= ", " = ", " != ", " like ", " not like ", " in " }; public static void ReplaceKeyWords(ref StringBuilder sql) { sql.Replace(".order.", "['order']."); sql.Replace(".order ", "['order'] "); sql.Replace(".Order.", "['Order']."); sql.Replace(".Order ", "['Order'] "); sql.Replace(".group.", "['group']."); sql.Replace(".group ", "['group'] "); sql.Replace(".Group.", "['Group']."); sql.Replace(".Group ", "['Group'] "); sql.Replace(".end.", "['end']."); sql.Replace(".end ", "['end'] "); sql.Replace(".End.", "['End']."); sql.Replace(".End ", "['End'] "); sql.Replace(".having.", "['having']."); sql.Replace(".having ", "['having'] "); sql.Replace(".Having.", "['Having']."); sql.Replace(".Having ", "['Having'] "); } public static StringBuilder GetSQLSelect(List propertys) { StringBuilder sql; if (propertys.IsNotEmpty()) { string tmpSQL = " select "; int i = 0; foreach (string item in propertys) { if (i == 0) { tmpSQL += " c." + item + " "; } else { tmpSQL += " ,c." + item + " "; } i++; } tmpSQL += "from c"; sql = new StringBuilder(tmpSQL); } else { sql = new StringBuilder("select value(c) from c"); } return sql; } public static bool DictIsNotNULL(Dictionary dict) { Dictionary keyValuePairs = new Dictionary(); foreach (KeyValuePair keyValuePair in dict) { if (keyValuePair.Value is JArray array) { if (array == null || array.Count == 0) keyValuePairs.Add(keyValuePair.Key, keyValuePair.Value); } else if (keyValuePair.Value is IList enumerable && !(keyValuePair.Value is String)) { if (enumerable == null || enumerable.Count == 0) keyValuePairs.Add(keyValuePair.Key, keyValuePair.Value); } else if (keyValuePair.Value is JsonElement jsonElement && jsonElement.ValueKind is JsonValueKind.Array) { if (jsonElement.EnumerateArray().Count() == 0) { keyValuePairs.Add(keyValuePair.Key, keyValuePair.Value); } } else if (keyValuePair.Value is null) { //keyValuePairs.Add(keyValuePair.Key, keyValuePair.Value); } } if (keyValuePairs.Count > 0) { foreach (KeyValuePair keyValuePair in keyValuePairs) { dict.Remove(keyValuePair.Key); } } if (dict.Keys.Count > 0) { return true; } else { return false; } } public static AzureCosmosQuery GetSQL(JsonElement json, StringBuilder sql, string pk = null) { Dictionary dict = new Dictionary(); var emobj = json.EnumerateObject(); while (emobj.MoveNext()) { dict[emobj.Current.Name] = emobj.Current.Value; } var query = GetSQL(dict, sql, pk); return query; } public static AzureCosmosQuery GetSQL(Dictionary dict, StringBuilder sql, string pk = null) { AzureCosmosQuery cosmosDbQuery; if (dict != null && dict.Count > 0) { if (!DictIsNotNULL(dict)) { return null; } Dictionary parmeters = new Dictionary(); int offsetNum = -1; int limitNum = 0; bool pageBool = false; GetPageNum(dict, ref offsetNum, ref limitNum, ref pageBool); string OrderByValue = ""; //处理code /*if (dict.TryGetValue("code", out object _)) { dict.Remove("code"); }*/ // 处理OrderBy if (dict.TryGetValue("@ASC", out object ASC)) { OrderByValue = Regex.Replace(ASC.ToString(), "\\s{1,}", ""); dict.Remove("@ASC"); } if (dict.TryGetValue("@DESC", out object DESC)) { OrderByValue = Regex.Replace(DESC.ToString(), "\\s{1,}", ""); dict.Remove("@DESC"); }; //处理顺序 Stack> stack = new Stack>(); Dictionary forGetParmeter = new Dictionary(); foreach (string item in dict.Keys) { if (item.EndsWith(".|")) { stack.Push(new KeyValuePair(item, dict[item])); } } foreach (string item in dict.Keys) { if (!item.EndsWith(".|")) { stack.Push(new KeyValuePair(item, dict[item])); } } string Join = " join "; string instring = " in "; Dictionary keyValues = new Dictionary(); StringBuilder WhereString = new StringBuilder(); int heada = 0; string[] sqlHead = new string[] { "A", "B", "C", "D", "E", "F" }; int kslength = 0; int logicOperNum = 0; bool keyListValueList = false; int keyListValueListNum = 0; int stackCount = stack.Count; for (int k = 0; k < stackCount; k++) { KeyValuePair item = stack.Pop(); forGetParmeter.Add(item.Key, item.Value); bool isLikeSQL = false; if (item.Key.StartsWith("$.") || item.Key.StartsWith("!$.")) { isLikeSQL = true; } string key = item.Key; string[] keyHead = key.Split("."); int index = 0; int compareOper = 4; int logicOper = 0; if (key.EndsWith(".&")) { logicOper = (int)LogicOper.and; key = key.Replace(".&", ""); } else if (key.EndsWith(".|")) { logicOper = (int)LogicOper.or; key = key.Replace(".|", ""); } CompareOperSwitch(keyHead[0], ref key, ref compareOper); string[] keyBody = key.Split("[*]"); if (keyBody.Length > 1) { key = key.Replace("[*]", ""); key = key.Replace(".", ""); key += k; kslength += keyBody.Length; if (kslength < (7 + heada)) { StringBuilder sqlitem = new StringBuilder(); for (int i = 0; i < keyBody.Length - 1; i++) { if (i == 0) { sqlitem.Append(Join); string a = sqlHead[heada] + index; sqlitem.Append(a + " "); //keyValues.Add(ks[i], a); keyValues[keyBody[i]] = a; sqlitem.Append(instring); sqlitem.Append("c."); sqlitem.Append(keyBody[i]); } else { sqlitem.Append(Join); string a = sqlHead[heada] + index; sqlitem.Append(a + " "); //keyValues.Add(ks[i], a); keyValues[keyBody[i]] = a; sqlitem.Append(instring); sqlitem.Append(keyValues[keyBody[i - 1]]); sqlitem.Append(keyBody[i]); } index += 1; } sql.Append(sqlitem); string s = ""; if (isLikeSQL) { s = ValueIsLike(sqlHead[heada] + (keyBody.Length - 2) + keyBody[index] + "", key, item.Value, LogicOpers[logicOper], logicOperNum, compareOper, ref keyListValueList); } else { s = ValueNotLike(sqlHead[heada] + (keyBody.Length - 2) + keyBody[index] + "", key, item.Value, LogicOpers[logicOper], logicOperNum, compareOper, ref keyListValueList); } WhereString.Append(s); if (keyListValueList && keyListValueListNum == 0) { sql = sql.Replace("select ", "select distinct "); keyListValueList = false; keyListValueListNum++; } } else { // throw new BizException("数组总共深度不能超过5层", ResponseCode.PARAMS_ERROR); } heada += 1; } else { string itemKey = key.Replace(".", ""); itemKey += k; WhereString.Append(KeyNotElement(dict[item.Key], item.Key, itemKey, LogicOpers[logicOper], logicOperNum, compareOper)); } logicOperNum += 1; } if (pk == null) { sql.Append(" where 1=1 ").Append(WhereString); } else { sql.Append(" where c.pk='" + pk + "'").Append(WhereString); } if (ASC != null) { sql.Append(" Order By c." + OrderByValue); //sql.Append(" Order By c." + "@OrderByValue"); } else if (DESC != null) { sql.Append(" Order By c." + OrderByValue + " DESC "); // sql.Append(" Order By c." + "@OrderByValue"+ " DESC " ); } if (pageBool && offsetNum != -1 && limitNum != 0) { //sql.Append(" OFFSET " + offsetNum + " LIMIT " + limitNum); sql.Append(" OFFSET " + " @offsetNum " + " LIMIT " + " @limitNum "); } //替换关键字 ReplaceKeyWords(ref sql); //参数化查询拼接 参数dict parmeters = GetParmeter(forGetParmeter, parmeters, offsetNum, limitNum); cosmosDbQuery = new AzureCosmosQuery { QueryText = sql.ToString(), Parameters = parmeters }; if (cosmosDbQuery.QueryText.Contains("order", StringComparison.OrdinalIgnoreCase) && cosmosDbQuery.QueryText.Contains("by", StringComparison.OrdinalIgnoreCase) && cosmosDbQuery.QueryText.Contains("distinct", StringComparison.OrdinalIgnoreCase)) { cosmosDbQuery.QueryText = cosmosDbQuery.QueryText.Replace("distinct", " "); } return cosmosDbQuery; } cosmosDbQuery = new AzureCosmosQuery { QueryText = sql.ToString() }; if (cosmosDbQuery.QueryText.Contains("order", StringComparison.OrdinalIgnoreCase) && cosmosDbQuery.QueryText.Contains("by", StringComparison.OrdinalIgnoreCase) && cosmosDbQuery.QueryText.Contains("distinct", StringComparison.OrdinalIgnoreCase)) { cosmosDbQuery.QueryText = cosmosDbQuery.QueryText.Replace("distinct", " "); } return cosmosDbQuery; } private static void GetPageNum(Dictionary dict, ref int offsetNum, ref int limitNum, ref bool pageBool) { dict.TryGetValue("@CURRPAGE", out object page); dict.Remove("@CURRPAGE"); dict.TryGetValue("@PAGESIZE", out object limit); dict.Remove("@PAGESIZE"); if (page != null && limit != null) { pageBool = true; limitNum = int.Parse(limit.ToString()); if (limitNum < 0) { //throw new BizException("PAGESIZE can't be less than 0 !"); } offsetNum = (int.Parse(page.ToString()) - 1) * limitNum; if (offsetNum < 0) { // throw new BizException("CURRPAGE can't be less than 1 !"); } } } private static void CompareOperSwitch(string keyHead, ref string key, ref int compareOper) { switch (keyHead) { case ">": compareOper = (int)CompareOper.moreThan; key = key.Replace(">.", ""); break; case "<": compareOper = (int)CompareOper.lessThan; key = key.Replace("<.", ""); break; case "<=": compareOper = (int)CompareOper.notMoreThan; key = key.Replace("<=.", ""); break; case ">=": compareOper = (int)CompareOper.notLessThan; key = key.Replace(">=.", ""); break; case "=": compareOper = (int)CompareOper.equal; key = key.Replace("=.", ""); break; case "!=": compareOper = (int)CompareOper.notEqual; key = key.Replace("!=.", ""); break; case "$": compareOper = (int)CompareOper.like; key = key.Replace("$.", ""); break; case "!$": compareOper = (int)CompareOper.notLike; key = key.Replace("!$.", ""); break; default: compareOper = 4; break; } } private static string ValueNotLike(string key, string key1, object value, string logicOperParams, int logicOperNum, int compareOperNum, ref bool keyListValueList) { string logicOper = " and "; string compareOper = " = "; if (compareOperNum != 4) compareOper = CompareOpers[compareOperNum]; if (logicOperNum != 0) logicOper = logicOperParams; StringBuilder sql = new StringBuilder(logicOper + key + " in ("); if (value is JArray array) { keyListValueList = true; int aa = 0; foreach (JValue obja in array) { sql.Append(" @" + key1 + aa + " ,"); aa++; } string sqls = sql.ToString().Substring(0, sql.Length - 1); sqls += " ) "; return sqls; } else if (value is IEnumerable enumerable && !(value is String)) { keyListValueList = true; int aa = 0; foreach (object obja in enumerable) { sql.Append(" @" + key1 + aa + " ,"); aa++; } string sqls = sql.ToString().Substring(0, sql.Length - 1); sqls += ") "; return sqls; } else if (value is JsonElement jsonElement) { if (jsonElement.ValueKind is JsonValueKind.Array) { keyListValueList = true; int aa = 0; foreach (JsonElement obja in jsonElement.EnumerateArray().ToArray()) { sql.Append(" @" + key1 + aa + " ,"); aa++; } } else { if (compareOperNum != 4) keyListValueList = true; return logicOper + key + compareOper + " @" + key1 + " "; } string sqls = sql.ToString().Substring(0, sql.Length - 1); sqls += " ) "; return sqls; } else { Type s = value.GetType(); TypeCode typeCode = Type.GetTypeCode(s); if (compareOperNum != 4) keyListValueList = true; return logicOper + key + compareOper + " @" + key1 + " "; } } private static string ValueIsLike(string key, string key1, object value, string logicOperParams, int logicOperNum, int compareOperNum, ref bool keyListValueList) { string compareOperBool = " true "; compareOperBool = CompareBoolSwitch(compareOperNum); string logicOper = " and "; if (logicOperNum != 0) logicOper = logicOperParams; StringBuilder s = new StringBuilder(logicOper + " ( Contains( "); if (value is JArray array) { keyListValueList = true; int aa = 0; foreach (JValue obja in array) { if (aa != 0) s.Append("or Contains("); s.Append(key + "," + " @" + key1 + aa + " ) = " + compareOperBool + " "); if (obja.Value is string) { s.Append(key + "," + " @" + key1 + aa + " ) = " + compareOperBool + " "); } else { s.Append("ToString( " + key + " )," + " \'@" + key1 + aa + "\' ) = " + compareOperBool + " "); } aa++; } } else if (value is IEnumerable enumerable && !(value is String)) { keyListValueList = true; int aa = 0; foreach (object obja in enumerable) { if (aa != 0) s.Append("or Contains("); if (obja is string) { s.Append(key + "," + " @" + key1 + aa + " ) = " + compareOperBool + " "); } else { s.Append("ToString( " + key + " )," + " \'@" + key1 + aa + "\' ) = " + compareOperBool + " "); } aa++; } } else if (value is JsonElement jsonElement && jsonElement.ValueKind is JsonValueKind.Array) { keyListValueList = true; int aa = 0; foreach (JsonElement obja in jsonElement.EnumerateArray().ToArray()) { if (aa != 0) s.Append("or Contains("); if (obja.ValueKind is JsonValueKind.String) { s.Append(key + "," + " @" + key1 + aa + " ) = " + compareOperBool + " "); } else { s.Append("ToString( " + key + " )," + " \'@" + key1 + aa + "\' ) = " + compareOperBool + " "); } aa++; } } else { Type stype = value.GetType(); TypeCode typeCode = Type.GetTypeCode(stype); if (compareOperNum == 7) keyListValueList = true; string sql = ""; if (value is string) { sql = logicOper + "Contains( " + key + " , @" + key1 + " ) = " + compareOperBool + " "; } else if (value is JsonElement jsonElement1 && jsonElement1.ValueKind is JsonValueKind.String) { sql = logicOper + "Contains( " + key + " , @" + key1 + " ) = " + compareOperBool + " "; } else { sql = logicOper + "Contains( ToString(" + key + " ), \'@" + key1 + "\' ) = " + compareOperBool + " "; } return sql; } s.Append(" )"); return s.ToString(); } private static string CompareBoolSwitch(int compareOperNum) { return compareOperNum switch { 6 => " true ", 7 => " false ", _ => " true ", }; } private static string KeyNotElement(object value, string key, string key1, string logicOperParams, int logicOperNum, int compareOperNum) { string compareOperBool = " true "; compareOperBool = CompareBoolSwitch(compareOperNum); string logicOper = " and "; int compareOper = 4; if (logicOperNum != 0) logicOper = logicOperParams; if (key.EndsWith(".&")) { key = key.Replace(".&", ""); } else if (key.EndsWith(".|")) { key = key.Replace(".|", ""); } string[] keyHead = key.Split("."); CompareOperSwitch(keyHead[0], ref key, ref compareOper); if (compareOper == 6 || compareOper == 7) { StringBuilder sql = new StringBuilder(logicOper + " ( Contains( "); if (value is JArray jarray) { int aa = 0; foreach (JValue obja in jarray) { if (aa != 0) sql.Append("or Contains("); if (obja.Value is string) { sql.Append(" c." + key + "," + " @" + key1 + aa + " ) = " + compareOperBool + " "); } else { sql.Append("ToString( c." + key + " )," + " \'@" + key1 + aa + "\' ) = " + compareOperBool + " "); } sql.Append(" c." + key + ", @" + key1 + aa + " )= " + compareOperBool + " "); aa++; } } else if (value is IEnumerable enumerable && !(value is String)) { int aa = 0; foreach (object obja in enumerable) { if (aa != 0) sql.Append("or Contains("); if (obja is string) { sql.Append(" c." + key + "," + " @" + key1 + aa + " ) = " + compareOperBool + " "); } else { sql.Append("ToString( c." + key + " )," + " \'@" + key1 + aa + "\' ) = " + compareOperBool + " "); } aa++; } } else if (value is JsonElement jsonElement && jsonElement.ValueKind is JsonValueKind.Array) { int aa = 0; foreach (JsonElement obja in jsonElement.EnumerateArray().ToArray()) { if (aa != 0) sql.Append("or Contains("); if (obja.ValueKind is JsonValueKind.String) { sql.Append(" c." + key + "," + " @" + key1 + aa + " ) = " + compareOperBool + " "); } else { sql.Append("ToString( c." + key + " )," + " \'@" + key1 + aa + "\' ) = " + compareOperBool + " "); } aa++; } } else { Type s = value.GetType(); TypeCode typeCode = Type.GetTypeCode(s); string sql1 = ""; if (value is string) { sql1 = logicOper + "Contains( c." + key + " , @" + key1 + " ) = " + compareOperBool + " "; } if (value is JsonElement jsonElement1 && jsonElement1.ValueKind is JsonValueKind.String) { sql1 = logicOper + "Contains( c." + key + " , @" + key1 + " ) = " + compareOperBool + " "; } else { sql1 = logicOper + "Contains( ToString( c." + key + " ), \'@" + key1 + "\' ) = " + compareOperBool + " "; } return sql1; } sql.Append(")"); return sql.ToString(); } else { StringBuilder sql = new StringBuilder(logicOper + " c." + key + " in ("); if (value is JArray array) { int aa = 0; foreach (JValue obja in array) { sql.Append(" @" + key1 + aa + " ,"); aa++; } string sqls = sql.ToString().Substring(0, sql.Length - 1); sqls += " ) "; return sqls; } else if (value is IEnumerable enumerable && !(value is String)) { int aa = 0; foreach (object obja in enumerable) { sql.Append(" @" + key1 + aa + " ,"); aa++; } string sqls = sql.ToString().Substring(0, sql.Length - 1); sqls += " ) "; return sqls; } else if (value is JsonElement jsonElement) { if (jsonElement.ValueKind is JsonValueKind.Array) { int aa = 0; foreach (JsonElement obja in jsonElement.EnumerateArray().ToArray()) { sql.Append(" @" + key1 + aa + " ,"); aa++; } } else { return logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1; } string sqls = sql.ToString().Substring(0, sql.Length - 1); sqls += " ) "; return sqls; } else { if (value != null) { Type s = value.GetType(); TypeCode typeCode = Type.GetTypeCode(s); return typeCode switch { TypeCode.String => logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1,// + "\'" + value.ToString() + "\'", TypeCode.Char => logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1,// + "\'" + value.ToString() + "\'", TypeCode.Int32 => logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1,// + int.Parse(value.ToString()), TypeCode.Double => logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1,// + double.Parse(value.ToString()), TypeCode.Boolean => logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1,// + bool.Parse(value.ToString()), TypeCode.DateTime => logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1,// + (DateTime)value, TypeCode.Int64 => logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1,// + long.Parse(value.ToString()), _ => null, }; } else { return logicOper + " c." + key + CompareOpers[compareOperNum] + " @" + key1; } } } } public enum LogicOper : int { and = 0, or = 1 } public enum CompareOper : int { moreThan = 0, lessThan = 1, notMoreThan = 2, notLessThan = 3, equal = 4, notEqual = 5, like = 6, notLike = 7, IN = 8 } private static Dictionary GetParmeter(Dictionary dict, Dictionary parmeters, int offset = 0, int limit = 0) { int i = 0; foreach (KeyValuePair keyValue in dict) { string key = ""; string[] keyHead = keyValue.Key.Split("."); switch (keyHead[0]) { case ">": key = keyValue.Key.Replace(">.", ""); break; case "<": key = keyValue.Key.Replace("<.", ""); break; case "<=": key = keyValue.Key.Replace("<=.", ""); break; case ">=": key = keyValue.Key.Replace(">=.", ""); break; case "=": key = keyValue.Key.Replace("=.", ""); break; case "!=": key = keyValue.Key.Replace("!=.", ""); break; case "$": key = keyValue.Key.Replace("$.", ""); break; case "!$": key = keyValue.Key.Replace("!$.", ""); break; default: key = keyValue.Key; break; } if (key.EndsWith(".&")) { key = key.Replace(".&", ""); } else if (key.EndsWith(".|")) { key = key.Replace(".|", ""); } key = key.Replace("[*]", ""); key = key.Replace(".", ""); key += i; if (keyValue.Value is JArray array) { int aa = 0; foreach (JValue obja in array) { parmeters.Add("@" + key + aa, obja); aa++; } } else if (keyValue.Value is IEnumerable enumerable && !(keyValue.Value is String)) { int aa = 0; foreach (object obja in enumerable) { parmeters.Add("@" + key + aa, obja); aa++; } } else if (keyValue.Value is JsonElement jsonElement) { if (jsonElement.ValueKind is JsonValueKind.Array) { int aa = 0; foreach (JsonElement obja in jsonElement.EnumerateArray().ToArray()) { if (obja.ValueKind is JsonValueKind.String) { parmeters.Add("@" + key + aa, obja.ToString()); } if (obja.ValueKind is JsonValueKind.Number) { parmeters.Add("@" + key + aa, double.Parse(obja.ToString())); } if (obja.ValueKind is JsonValueKind.True) { parmeters.Add("@" + key + aa, bool.Parse(obja.ToString())); } if (obja.ValueKind is JsonValueKind.False) { parmeters.Add("@" + key + aa, bool.Parse(obja.ToString())); } aa++; } } else { if (jsonElement.ValueKind is JsonValueKind.String) { parmeters.Add("@" + key, keyValue.Value.ToString()); } else if (jsonElement.ValueKind is JsonValueKind.Number) { parmeters.Add("@" + key, double.Parse(keyValue.Value.ToString())); } else if (jsonElement.ValueKind is JsonValueKind.True) { parmeters.Add("@" + key, bool.Parse(keyValue.Value.ToString())); } else if (jsonElement.ValueKind is JsonValueKind.False) { parmeters.Add("@" + key, bool.Parse(keyValue.Value.ToString())); } else { parmeters.Add("@" + key, keyValue.Value.ToString()); } } } else { parmeters.Add("@" + key, keyValue.Value); } i++; } if (offset != -1 && limit != 0) { parmeters.Add("@offsetNum", offset); parmeters.Add("@limitNum", limit); } return parmeters; } } }