- 修复 InsertOrUpdateDict 异常;#1067

This commit is contained in:
2881099
2022-04-11 13:23:38 +08:00
parent ecd27fb3ae
commit 7c2b7ea5ef
21 changed files with 331 additions and 41 deletions

View File

@ -209,14 +209,14 @@ namespace FreeSql.DataAnnotations
cn = columnName.Replace("[", "\\[").Replace("]", "\\]").Replace(".", "\\.");
return new[]
{
new Regex($@"({cn}\s*(<|<=|>|>=|=|between)\s*)(datetime|cdate|to_date)\(('[^']+')\)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))to_timestamp\(('[^']+')\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))cast\(('[^']+') as (datetime|timestamp)\)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))('[^']+')::(datetime|timestamp)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and\s+)(datetime|cdate|to_date)\(('[^']+')\)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))to_timestamp\(('[^']+')\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))cast\(('[^']+') as (datetime|timestamp)\)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))('[^']+')::(datetime|timestamp)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(<|<=|>|>=|=|between)\s*)(datetime|cdate|to_date)\(('[^']+')\)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))to_timestamp\(('[^']+')\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))cast\(('[^']+') as (datetime|timestamp)\)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(<|<=|>|>=|=|between)(\s*))('[^']+')::(datetime|timestamp)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and\s+)(datetime|cdate|to_date)\(('[^']+')\)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))to_timestamp\(('[^']+')\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))cast\(('[^']+') as (datetime|timestamp)\)", RegexOptions.IgnoreCase),
//new Regex($@"({cn}\s*(between)\s+'[^']+'\s+and(\s+))('[^']+')::(datetime|timestamp)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(<|<=|>|>=|=)\s*)(datetime|cdate|to_date)\(({quoteParameterName}[\w_]+)\)", RegexOptions.IgnoreCase),
new Regex($@"({cn}\s*(<|<=|>|>=|=)(\s*))to_timestamp\(({quoteParameterName}[\w_]+)\s*,\s*'YYYY-MM-DD[^']+'\)", RegexOptions.IgnoreCase),
@ -228,13 +228,13 @@ namespace FreeSql.DataAnnotations
new Regex($@"({cn}\s*(between)\s+{quoteParameterName}[\w_]+\s+and(\s+))({quoteParameterName}[^w_]+)::(datetime|timestamp)", RegexOptions.IgnoreCase),
new Regex($@"{cn}\s*between\s*'([^']+)'\s*and\s*'([^']+)'", RegexOptions.IgnoreCase),
new Regex($@"{cn}\s*between\s*'([^']+)'\s*and\s*'([^']+)'", RegexOptions.IgnoreCase), //预留暂时不用
new Regex($@"{cn}\s*between\s*{quoteParameterName}([\w_]+)\s*and\s*{quoteParameterName}([\w_]+)", RegexOptions.IgnoreCase),
new Regex($@"{cn}\s*(<|<=|>|>=)\s*'([^']+)'\s*and\s*{cn}\s*(<|<=|>|>=)\s*'([^']+)'", RegexOptions.IgnoreCase),
new Regex($@"{cn}\s*(<|<=|>|>=)\s*'([^']+)'\s*and\s*{cn}\s*(<|<=|>|>=)\s*'([^']+)'", RegexOptions.IgnoreCase), //预留暂时不用
new Regex($@"{cn}\s*(<|<=|>|>=)\s*{quoteParameterName}([\w_]+)\s*and\s*{cn}\s*(<|<=|>|>=)\s*{quoteParameterName}([\w_]+)", RegexOptions.IgnoreCase),
new Regex($@"{cn}\s*(<|<=|>|>=)\s*'([^']+)'", RegexOptions.IgnoreCase),
new Regex($@"{cn}\s*(<|<=|>|>=)\s*'([^']+)'", RegexOptions.IgnoreCase), //预留暂时不用
new Regex($@"{cn}\s*(<|<=|>|>=)\s*{quoteParameterName}([\w_]+)", RegexOptions.IgnoreCase),
};
});
@ -256,44 +256,53 @@ namespace FreeSql.DataAnnotations
public string[] GetTableNamesBySqlWhere(string sqlWhere, List<DbParameter> dbParams, SelectTableInfo tb, CommonUtils commonUtils)
{
if (string.IsNullOrWhiteSpace(sqlWhere)) return AllTables;
var dictParams = new Dictionary<string, string>();
var newSqlWhere = Utils.ReplaceSqlConstString(sqlWhere, dictParams);
var tsqlWhere = Utils.ParseSqlWhereLevel1(sqlWhere);
var quoteParameterName = commonUtils.QuoteParamterName("");
var quoteParameterNameCharArray = quoteParameterName.ToCharArray();
var columnName = commonUtils.QuoteSqlName(tb.Table.AsTableColumn.Attribute.Name);
var regs = GetRegSqlWhereDateTimes($"{(string.IsNullOrWhiteSpace(tb.Alias) ? "" : $"{tb.Alias}.")}{commonUtils.QuoteSqlName(tb.Table.AsTableColumn.Attribute.Name)}", quoteParameterName);
for (var a = 0; a < 16; a++) sqlWhere = regs[a].Replace(sqlWhere, "$1$4");
for (var a = 0; a < 8; a++) newSqlWhere = regs[a].Replace(newSqlWhere, "$1$4");
var m = regs[16].Match(sqlWhere);
if (m.Success) return GetTableNamesByColumnValueRange(m.Groups[1].Value, m.Groups[2].Value);
m = m = regs[18].Match(sqlWhere);
if (m.Success) return LocalGetTables(m.Groups[1].Value, m.Groups[3].Value, ParseColumnValue(m.Groups[2].Value), ParseColumnValue(m.Groups[4].Value));
m = regs[20].Match(sqlWhere);
if (m.Success) return LocalGetTables2(m.Groups[1].Value, ParseColumnValue(m.Groups[2].Value));
//var m = regs[8].Match(newSqlWhere);
//if (m.Success) return GetTableNamesByColumnValueRange(m.Groups[1].Value, m.Groups[2].Value);
//m = m = regs[10].Match(newSqlWhere);
//if (m.Success) return LocalGetTables(m.Groups[1].Value, m.Groups[3].Value, ParseColumnValue(m.Groups[2].Value), ParseColumnValue(m.Groups[4].Value));
//m = regs[12].Match(newSqlWhere);
//if (m.Success) return LocalGetTables2(m.Groups[1].Value, ParseColumnValue(m.Groups[2].Value));
m = m = regs[17].Match(sqlWhere);
var m = regs[9].Match(newSqlWhere);
if (m.Success)
{
var val1 = dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == m.Groups[2].Value).FirstOrDefault();
var val2 = dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == m.Groups[4].Value).FirstOrDefault();
var val1 = LocalGetParamValue(m.Groups[1].Value);
var val2 = LocalGetParamValue(m.Groups[2].Value);
if (val1 == null || val2 == null) throw new Exception($"未能解析分表字段值 {sqlWhere}");
return GetTableNamesByColumnValueRange(val1, val2);
}
m = regs[19].Match(sqlWhere);
m = regs[11].Match(newSqlWhere);
if (m.Success)
{
var val1 = dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == m.Groups[2].Value).FirstOrDefault();
var val2 = dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == m.Groups[4].Value).FirstOrDefault();
var val1 = LocalGetParamValue(m.Groups[2].Value);
var val2 = LocalGetParamValue(m.Groups[4].Value);
if (val1 == null || val2 == null) throw new Exception($"未能解析分表字段值 {sqlWhere}");
return LocalGetTables(m.Groups[1].Value, m.Groups[3].Value, ParseColumnValue(val1), ParseColumnValue(val2));
}
m = regs[21].Match(sqlWhere);
m = regs[13].Match(newSqlWhere);
if (m.Success)
{
var val1 = dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == m.Groups[2].Value).FirstOrDefault();
var val1 = LocalGetParamValue(m.Groups[2].Value);
if (val1 == null) throw new Exception($"未能解析分表字段值 {sqlWhere}");
return LocalGetTables2(m.Groups[1].Value, ParseColumnValue(val1));
}
return AllTables;
object LocalGetParamValue(string paramName)
{
if (dictParams.TryGetValue(quoteParameterName + paramName, out var trydictVal)) return trydictVal;
return dbParams.Where(a => a.ParameterName.Trim(quoteParameterNameCharArray) == m.Groups[2].Value).FirstOrDefault()?.Value;
}
string[] LocalGetTables(string opt1, string opt2, DateTime val1, DateTime val2)
{
switch (opt1)
@ -317,7 +326,7 @@ namespace FreeSql.DataAnnotations
break;
case ">":
case ">=":
if (opt1 == ">") val1 = val1.AddSeconds(1);
if (opt1 == ">") val1 = val1.AddSeconds(1);
switch (opt2)
{
case "<":

View File

@ -572,6 +572,7 @@ namespace FreeSql.Internal.CommonProvider
public IInsert<T1> AsType(Type entityType)
{
if (entityType == typeof(object)) throw new Exception("IInsert.AsType 参数不支持指定为 object");
if (entityType == typeof(T1)) return this;
if (entityType == _table.Type) return this;
var newtb = _commonUtils.GetTableByEntity(entityType);
_table = newtb ?? throw new Exception("IInsert.AsType 参数错误,请传入正确的实体类型");

View File

@ -2267,5 +2267,162 @@ namespace FreeSql.Internal
name = Regex.Replace(name.TrimStart('@'), @"[^\w]", "_");
return char.IsLetter(name, 0) ? name : string.Concat("_", name);
}
public static string ReplaceSqlConstString(string sql, Dictionary<string, string> parms)
{
var nsb = new StringBuilder();
var sidx = 0;
var pidx = 0;
while (sidx < sql.Length)
{
var chr = sql[sidx++];
if (chr != '\'')
{
nsb.Append(chr);
continue;
}
var startIdx = sidx;
var startLength = 0;
while (sidx < sql.Length)
{
var chrb = sql[sidx++];
if (chrb != '\'')
{
startLength++;
continue;
}
if (sidx < sql.Length && sql[sidx] == '\'')
{
startLength += 2;
continue;
}
break;
}
if (startLength > 0)
{
var pvalue = sql.Substring(startIdx, startLength).Replace("''", "'");
var pname = parms.Where(a => a.Value == pvalue).Select(a => a.Key).FirstOrDefault();
if (string.IsNullOrEmpty(pname))
{
while (true)
{
pidx++;
pname = $"@p{pidx}";
if (parms.ContainsKey(pname) == false) break;
}
}
nsb.Append(pname);
if (parms.ContainsKey(pname) == false) parms.Add(pname, pvalue);
}
}
return nsb.ToString();
}
internal static string ParseSqlWhereLevel1(string sql)
{
var dictParms = new Dictionary<string, string>();
var rawsql = ReplaceSqlConstString(sql, dictParms).Trim();
sql = Regex.Replace(rawsql, @"[\r\n\t]", " ");
var remidx = sql.IndexOf("WHERE ");
if (remidx != -1) sql = sql.Substring(remidx + 6);
var sidx = 0;
var ltcou = 0;
var ltidxStack = new Stack<int>();
while (sidx < sql.Length)
{
var chr = sql[sidx++];
if (chr == '(')
{
ltcou++;
ltidxStack.Push(sidx - 1);
}
if (chr == ')')
{
ltcou--;
var ltidx = ltidxStack.Pop();
if (ltidx == 0 && sidx == sql.Length - 1)
break;
var sqlLeft = ltidx == 0 ? "" : sql.Remove(ltidx);
var sqlMid = sql.Substring(ltidx, sidx - ltidx);
var sqlMidNew = "";
var sqlRight = sidx == sql.Length - 1 ? "" : sql.Substring(sidx + 1);
var mLeft = Regex.Match(sqlLeft, @" (and|or|not)\s*$", RegexOptions.IgnoreCase);
if (mLeft.Success)
{
switch (mLeft.Groups[1].Value)
{
case "and":
sqlMidNew = sqlMid.Substring(1, sqlMid.Length - 2);
break;
case "or":
break;
case "not":
break;
}
}
sidx -= sqlMid.Length - sqlMidNew.Length;
sql = $"{sqlLeft}{sqlMidNew}{sqlRight}";
}
}
return sql;
}
static string ParseSqlWhereLevel12(string sql)
{
var dictParms = new Dictionary<string, string>();
var rawsql = ReplaceSqlConstString(sql, dictParms);
sql = Regex.Replace(rawsql, @"[\r\n\t]", " ");
var remidx = sql.IndexOf("WHERE ");
if (remidx != -1) sql = sql.Substring(remidx + 6);
Dictionary<string, string> dicSqlParts = new Dictionary<string, string>();
var nsb = new StringBuilder();
var swliRoot = new SqlWhereLogicInfo();
var swliCurrent = swliRoot;
LocalParseSqlWhere(sql);
return nsb.ToString();
void LocalParseSqlWhere(string sqlPart)
{
var sidx = 0;
var ltcou = 0;
var ltidxStack = new Stack<int>();
while (sidx < sqlPart.Length)
{
var chr = sqlPart[sidx++];
if (chr == '(')
{
ltcou++;
ltidxStack.Push(sidx - 1);
//swliCurrent.Filters.Add()
}
if (chr == ')')
{
ltcou--;
var ltidx = ltidxStack.Pop();
var pvalue = sqlPart.Substring(ltidx, sidx - ltidx);
break;
//var pname = $"@p_{Guid.NewGuid().ToString("N")}";
//dicSqlParts.Add(pname, pvalue);
//LocalParseSqlWhere(sqlPart);
//var ltsql = sqlPart.Substring(Math.Max(0, ltidx - 5), ltidx);
//if (Regex.IsMatch(ltsql, @"(and|or|not)$"))
// ltsb.Last().Append("1=1");
}
}
}
}
class SqlWhereLogicInfo
{
public string Field { get; set; }
public string Operator { get; set; }
public object Value { get; set; }
public DynamicFilterLogic Logic { get; set; }
public List<SqlWhereLogicInfo> Filters { get; set; }
}
}
}