diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index d8f7e2bf..f2304308 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -1984,6 +1984,43 @@ WHERE (((a.""Code"") LIKE '%val1%' AND (a.""Name"") LIKE 'val2%' OR (a.""Name"") sql = fsql.Select().WhereDynamicFilter(JsonConvert.DeserializeObject(@" { + ""Logic"" : ""Or"", + ""Filters"" : + [ + { + ""Field"" : ""CreateTime"", + ""Operator"" : ""DateRange"", + ""Value"" : ""2010-10-10,2010-11-10"" + }, + { + ""Field"" : ""CreateTime"", + ""Operator"" : ""DateRange"", + ""Value"" : ""2010-10-10,2010-11"" + }, + { + ""Field"" : ""CreateTime"", + ""Operator"" : ""DateRange"", + ""Value"" : ""2010-10-10,2010"" + }, + { + ""Field"" : ""CreateTime"", + ""Operator"" : ""DateRange"", + ""Value"" : ""2010-10-10,2010-11-10 11"" + }, + { + ""Field"" : ""CreateTime"", + ""Operator"" : ""DateRange"", + ""Value"" : ""2010-10-10,2010-11-10 11:20"" + }, + ] +} +")).ToSql(); + Assert.Equal(@"SELECT a.""Code"", a.""Name"", a.""CreateTime"", a.""testint"", a.""ParentCode"" +FROM ""D_District"" a +WHERE ((a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2010-11-11 00:00:00' OR a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2010-12-01 00:00:00' OR a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2011-01-01 00:00:00' OR a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2010-11-10 12:00:00' OR a.""CreateTime"" >= '2010-10-10 00:00:00' AND a.""CreateTime"" < '2010-11-10 11:21:00'))", sql); + + sql = fsql.Select().WhereDynamicFilter(JsonConvert.DeserializeObject(@" +{ ""Logic"" : ""Or"", ""Filters"" : [ diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 91c6a3fb..50fab767 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -3119,6 +3119,19 @@ 此时 Value 的值格式为逗号分割:value1,value2 + + + >= and < + 此时 Value 的值格式为逗号分割:date1,date2 + 这是专门为日期范围查询定制的操作符,它会处理 date2 + 1,比如: + 当 date2 选择的是 2020-05-30,那查询的时候是 < 2020-05-31 + 当 date2 选择的是 2020-05,那查询的时候是 < 2020-06 + 当 date2 选择的是 2020,那查询的时候是 < 2021 + 当 date2 选择的是 2020-05-30 12,那查询的时候是 < 2020-05-30 13 + 当 date2 选择的是 2020-05-30 12:30,那查询的时候是 < 2020-05-30 12:31 + 并且 date2 只支持以上 5 种格式 (date1 没有限制) + + in (1,2,3) diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index b1d550c5..a77c9b65 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; +using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -1102,11 +1103,24 @@ namespace FreeSql.Internal.CommonProvider case DynamicFilterOperator.LessThanOrEqual: exp = Expression.LessThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fi.Value), exp.Type)); break; case DynamicFilterOperator.Range: var fiValueRangeArray = fi.Value.Split(','); - if (fiValueRangeArray.Length != 2) throw new ArgumentException($"Range 对应 Value 应该逗号分割,并且长度为 2"); + if (fiValueRangeArray.Length != 2) throw new ArgumentException($"Range 要求 Value 应该逗号分割,并且长度为 2"); exp = Expression.AndAlso( Expression.GreaterThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[0]), exp.Type)), Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueRangeArray[1]), exp.Type))); break; + case DynamicFilterOperator.DateRange: + var fiValueDateRangeArray = fi.Value.Split(','); + if (fiValueDateRangeArray.Length != 2) throw new ArgumentException($"DateRange 要求 Value 应该逗号分割,并且长度为 2"); + if (Regex.IsMatch(fiValueDateRangeArray[1], @"^\d\d\d\d[\-/]\d\d?[\-/]\d\d?$")) fiValueDateRangeArray[1] = DateTime.Parse(fiValueDateRangeArray[1]).AddDays(1).ToString("yyyy-MM-dd HH:mm:ss"); + else if (Regex.IsMatch(fiValueDateRangeArray[1], @"^\d\d\d\d[\-/]\d\d?$")) fiValueDateRangeArray[1] = DateTime.Parse($"{fiValueDateRangeArray[1]}-01").AddMonths(1).ToString("yyyy-MM-dd HH:mm:ss"); + else if (Regex.IsMatch(fiValueDateRangeArray[1], @"^\d\d\d\d$")) fiValueDateRangeArray[1] = DateTime.Parse($"{fiValueDateRangeArray[1]}-01-01").AddYears(1).ToString("yyyy-MM-dd HH:mm:ss"); + else if (Regex.IsMatch(fiValueDateRangeArray[1], @"^\d\d\d\d[\-/]\d\d?[\-/]\d\d? \d\d?$")) fiValueDateRangeArray[1] = DateTime.Parse($"{fiValueDateRangeArray[1]}:00:00").AddHours(1).ToString("yyyy-MM-dd HH:mm:ss"); + else if (Regex.IsMatch(fiValueDateRangeArray[1], @"^\d\d\d\d[\-/]\d\d?[\-/]\d\d? \d\d?:\d\d?$")) fiValueDateRangeArray[1] = DateTime.Parse($"{fiValueDateRangeArray[1]}:00").AddMinutes(1).ToString("yyyy-MM-dd HH:mm:ss"); + else throw new ArgumentException($"DateRange 要求 Value[1] 格式必须为:yyyy、yyyy-MM、yyyy-MM-dd、yyyy-MM-dd HH、yyyy、yyyy-MM-dd HH:mm"); + exp = Expression.AndAlso( + Expression.GreaterThanOrEqual(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueDateRangeArray[0]), exp.Type)), + Expression.LessThan(exp, Expression.Constant(Utils.GetDataReaderValue(exp.Type, fiValueDateRangeArray[1]), exp.Type))); + break; case DynamicFilterOperator.Any: var fiValueAnyArray = fi.Value.Split(','); var fiValueAnyArrayType = exp.Type.MakeArrayType(); diff --git a/FreeSql/Internal/Model/DynamicFilterInfo.cs b/FreeSql/Internal/Model/DynamicFilterInfo.cs index fac235fa..69424118 100644 --- a/FreeSql/Internal/Model/DynamicFilterInfo.cs +++ b/FreeSql/Internal/Model/DynamicFilterInfo.cs @@ -97,6 +97,19 @@ namespace FreeSql.Internal.Model /// Range, + /// + /// >= and < + /// 此时 Value 的值格式为逗号分割:date1,date2 + /// 这是专门为日期范围查询定制的操作符,它会处理 date2 + 1,比如: + /// 当 date2 选择的是 2020-05-30,那查询的时候是 < 2020-05-31 + /// 当 date2 选择的是 2020-05,那查询的时候是 < 2020-06 + /// 当 date2 选择的是 2020,那查询的时候是 < 2021 + /// 当 date2 选择的是 2020-05-30 12,那查询的时候是 < 2020-05-30 13 + /// 当 date2 选择的是 2020-05-30 12:30,那查询的时候是 < 2020-05-30 12:31 + /// 并且 date2 只支持以上 5 种格式 (date1 没有限制) + /// + DateRange, + /// /// in (1,2,3) /// 此时 Value 的值格式为逗号分割:value1,value2,value3...