From 51f07b9a8f7534ecca0bd4017ad07380a785b798 Mon Sep 17 00:00:00 2001 From: Victor Qu Date: Sat, 12 Oct 2024 13:58:43 +0800 Subject: [PATCH] JsonExtract --- ProjectCommon.targets | 2 +- README.md | 12 ++++---- src/SV.Db.Sloth/ExpressionExtensions.cs | 38 ++++++++++++++++++++++--- src/SV.Db.Sloth/From.Expression.cs | 8 ++++++ test/UT/Sloth/QueryTest.cs | 11 +++++++ 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/ProjectCommon.targets b/ProjectCommon.targets index 51e7634..d69e18d 100644 --- a/ProjectCommon.targets +++ b/ProjectCommon.targets @@ -1,7 +1,7 @@ $(VersionSuffix) - 0.0.2.0 + 0.0.2.1 $(Version) $(Version) $(Version)$(VersionSuffix) diff --git a/README.md b/README.md index e9125ac..59c8328 100644 --- a/README.md +++ b/README.md @@ -161,8 +161,8 @@ such filter operater just make api more restful (`Where=urlencode(complex condit #### Func Fields: - `Fields` return some Fields , no Fields or `Fields=*` is return all - - query string `?Fields=name,age` - - body `{"Fields":"name,age"}` + - query string `?Fields=name,age,json(data,'$.age')` + - body `{"Fields":"name,age,json(data,'$.age')"}` - `TotalCount` return total count - query string `?TotalCount=true` - body `{"TotalCount":"true"}` @@ -176,8 +176,8 @@ such filter operater just make api more restful (`Where=urlencode(complex condit - query string `?Rows=100` - body `{"Rows":100}` - `OrderBy` sort result - - query string `?OrderBy=name:asc,age:desc` - - body `{"OrderBy":"name:asc,age:desc"}` + - query string `?OrderBy=name asc,age desc,json(data,'$.age') desc` + - body `{"OrderBy":"name asc,age desc,json(data,'$.age') desc"}` - `Where` complex condition filter - query string `?Where=urlencode( not(name like 'H%') or name like '%v%' )` - body `{"Where":"not(name like 'H%') or name like '%v%'"}` @@ -217,4 +217,6 @@ such filter operater just make api more restful (`Where=urlencode(complex condit - `or` - example ` age <= 30 or age > 60` - `()` - - example ` (age <= 30 or age > 60) and name = 'killer'` \ No newline at end of file + - example ` (age <= 30 or age > 60) and name = 'killer'` + - support json + - example ` json(data,'$.age') > 60` \ No newline at end of file diff --git a/src/SV.Db.Sloth/ExpressionExtensions.cs b/src/SV.Db.Sloth/ExpressionExtensions.cs index 6e347a7..33bca9b 100644 --- a/src/SV.Db.Sloth/ExpressionExtensions.cs +++ b/src/SV.Db.Sloth/ExpressionExtensions.cs @@ -1,5 +1,4 @@ -using System.IO; -using System.Linq.Expressions; +using System.Linq.Expressions; namespace SV.Db { @@ -63,12 +62,12 @@ public static bool In(this object o, params R[] source) throw new NotImplementedException(); } - public static object JsonExtract(this object o, string path) + public static Any JsonExtract(this object o, string path) { throw new NotImplementedException(); } - public static object JsonExtract(this object o, string path, string aS) + public static Any JsonExtract(this object o, string path, string aS) { throw new NotImplementedException(); } @@ -78,4 +77,35 @@ public static object Desc(this object o) throw new NotImplementedException(); } } + + public class Any + { + public static bool operator ==(Any obj1, Any obj2) => throw new NotImplementedException(); + + public static bool operator !=(Any obj1, Any obj2) => throw new NotImplementedException(); + + public static bool operator >=(Any obj1, Any obj2) => throw new NotImplementedException(); + + public static bool operator <=(Any obj1, Any obj2) => throw new NotImplementedException(); + + public static bool operator >(Any obj1, Any obj2) => throw new NotImplementedException(); + + public static bool operator <(Any obj1, Any obj2) => throw new NotImplementedException(); + + public static implicit operator int(Any d) => throw new NotImplementedException(); + + public static implicit operator decimal(Any d) => throw new NotImplementedException(); + + public static implicit operator double(Any d) => throw new NotImplementedException(); + + public static implicit operator string(Any d) => throw new NotImplementedException(); + + public static implicit operator float(Any d) => throw new NotImplementedException(); + + public static implicit operator long(Any d) => throw new NotImplementedException(); + + public static implicit operator bool(Any d) => throw new NotImplementedException(); + + //public static explicit operator Any(byte b) => new Digit(b); + } } \ No newline at end of file diff --git a/src/SV.Db.Sloth/From.Expression.cs b/src/SV.Db.Sloth/From.Expression.cs index 9e388b1..c224582 100644 --- a/src/SV.Db.Sloth/From.Expression.cs +++ b/src/SV.Db.Sloth/From.Expression.cs @@ -274,6 +274,14 @@ private static ValueStatement ConvertValueStatement(Expression v) } else if (v.NodeType == ExpressionType.Call) { + if (v is MethodCallExpression mc && mc.Method.Name == nameof(ExpressionExtensions.JsonExtract)) + { + var f = new JsonFieldStatement(); + f.Field = ExpressionExtensions.GetMemberName(mc.Arguments[0]); + f.Path = Expression.Lambda(mc.Arguments[1]).Compile().DynamicInvoke().ToString(); + f.As = mc.Arguments.Count > 2 ? "," + Expression.Lambda(mc.Arguments[2]).Compile().DynamicInvoke().ToString() : string.Empty; + return f; + } var o = Expression.Lambda(v).Compile().DynamicInvoke(); return ConvertConstantStatement(o); } diff --git a/test/UT/Sloth/QueryTest.cs b/test/UT/Sloth/QueryTest.cs index 2ab299d..9f2846f 100644 --- a/test/UT/Sloth/QueryTest.cs +++ b/test/UT/Sloth/QueryTest.cs @@ -37,6 +37,17 @@ public void SelectOrderByFields() [Fact] public void Where() { + AssertWhere(i => i.A.JsonExtract("$.a") == 1, o => + { + Assert.Equal("=", o.Operater); + var f = Assert.IsType(o.Left); + Assert.Equal("A", f.Field); + Assert.Equal("$.a", f.Path); + Assert.Empty(f.As); + var v = Assert.IsType(o.Right); + Assert.Equal(1, v.Value); + }); + AssertWhere(i => i.A > 1, o => { Assert.Equal(">", o.Operater);