-
-
Notifications
You must be signed in to change notification settings - Fork 199
json functions support #392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| using System; | ||
|
|
||
| namespace YesSql.Sql | ||
| { | ||
| public class JsonPathExpressionFunction : ISqlFunction | ||
| { | ||
| private readonly string _template; | ||
| private readonly int[] _argumentIds; | ||
|
|
||
| public JsonPathExpressionFunction(string template, params int[] argumentIds) | ||
| { | ||
| _template = template; | ||
| _argumentIds = argumentIds; | ||
| } | ||
|
|
||
| public string Render(string[] arguments) | ||
| { | ||
| foreach (var id in _argumentIds) | ||
| { | ||
| arguments[id] = TransformPathExpression(arguments[id]); | ||
| } | ||
| return String.Format(_template, arguments); | ||
| } | ||
|
|
||
| private string TransformPathExpression(string jsonPathExpression) | ||
| { | ||
| return jsonPathExpression | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we might need to think about better way here |
||
| .Replace("$.", "") | ||
| .Replace("[", ",") | ||
| .Replace("].", ",") | ||
| .Replace("]", "") | ||
| .Replace(".", ","); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -87,6 +87,8 @@ public MySqlDialect() | |||
| { | ||||
| AddTypeHandler<TimeSpan, long>(x => x.Ticks); | ||||
| Methods.Add("now", new TemplateFunction("UTC_TIMESTAMP()")); | ||||
|
|
||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| Methods.Add("JSON_MODIFY", new TemplateFunction("json_set({0}, {1}, {2})")); | ||||
| } | ||||
|
|
||||
| public override string Name => "MySql"; | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -95,6 +95,9 @@ public PostgreSqlDialect() | |||
| Methods.Add("month", new TemplateFunction("extract(month from {0})")); | ||||
| Methods.Add("year", new TemplateFunction("extract(year from {0})")); | ||||
| Methods.Add("now", new TemplateFunction("now() at time zone 'utc'")); | ||||
|
|
||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| Methods.Add("JSON_VALUE", new JsonPathExpressionFunction("{0}::json#>>string_to_array({1}, ',')", 1)); | ||||
| Methods.Add("JSON_MODIFY", new JsonPathExpressionFunction("jsonb_set({0}, string_to_array({1}, ','), to_jsonb({2}), false)", 1)); | ||||
| } | ||||
|
|
||||
| public override string Name => "PostgreSql"; | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -91,6 +91,9 @@ public SqliteDialect() | |||
| Methods.Add("month", new TemplateFunction("cast(strftime('%m', {0}) as int)")); | ||||
| Methods.Add("year", new TemplateFunction("cast(strftime('%Y', {0}) as int)")); | ||||
| Methods.Add("now", new TemplateFunction("DATETIME('now')")); | ||||
|
|
||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||
| Methods.Add("JSON_VALUE", new TemplateFunction("json_extract({0}, {1})")); | ||||
| Methods.Add("JSON_MODIFY", new TemplateFunction("json_set({0}, {1}, {2})")); | ||||
| } | ||||
|
|
||||
| public override string Name => "Sqlite"; | ||||
|
|
||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -4372,6 +4372,45 @@ public async Task SqlNowFunction() | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assert.Equal(10, publishedInThePastResult); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Theory] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [InlineData("JSON_VALUE", "'{ \"a\" : 1, \"b\" : 2 }'", "'$.b'", "2")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [InlineData("JSON_VALUE", "'{ \"a\" : { \"b\" : { \"c\" : 3 } } }'", "'$.a.b.c'", "3")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [InlineData("JSON_VALUE", "'{ \"a\" : { \"b\" : [{ \"c\" : 1 }, { \"c\" : 2 }, { \"c\" : 3 }] } }'", "'$.a.b[2].c'", "3")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public async Task SqlJsonValueFunction(string method, string json, string jsonPathExpression, string expected) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using (var connection = _store.Configuration.ConnectionFactory.CreateConnection()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await connection.OpenAsync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var dialect = _store.Configuration.SqlDialect; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var sql = "SELECT " + dialect.RenderMethod(method, json, jsonPathExpression); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = await connection.QueryFirstOrDefaultAsync<string>(sql); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assert.Equal(expected, result); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+4381
to
+4391
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Theory] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [InlineData("JSON_MODIFY", "'{\"a\":1,\"b\":2}'", "'$.b'", "3", "{\"a\":1,\"b\":3}")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [InlineData("JSON_MODIFY", "'{ \"a\" : { \"b\" : { \"c\" : 3 } } }'", "'$.a.b.c'", "4", "{\"a\":{\"b\":{\"c\":4}}}")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [InlineData("JSON_MODIFY", "'{ \"a\" : { \"b\" : [{ \"c\" : 1 }, { \"c\" : 2 }, { \"c\" : 3 }] } }'", "'$.a.b[2].c'", "5", "{\"a\":{\"b\":[{\"c\":1},{\"c\":2},{\"c\":5}]}}")] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public async Task SqlJsonModifyFunction(string method, string json, string jsonPathExpression, string newValue, string expected) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string result; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| using (var connection = _store.Configuration.ConnectionFactory.CreateConnection()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| await connection.OpenAsync(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var dialect = _store.Configuration.SqlDialect; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var sql = "SELECT " + dialect.RenderMethod(method, json, jsonPathExpression, newValue); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = await connection.QueryFirstOrDefaultAsync<string>(sql); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| //we are getting rid of unnecessary JSON formatting | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Assert.Equal(expected, result.Replace(": ", ":").Replace(" :", ":").Replace(", ", ",").Replace("{ ", "{").Replace(" }", "}")); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+4400
to
+4411
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| [Fact] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| public virtual async Task CanUseStaticMethodsInLinqQueries() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.