From 00210cd63aa6153db0334bc64ad20e195a23f253 Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Wed, 13 Apr 2022 14:21:21 +0200 Subject: [PATCH 1/2] fix(linq): query expression for inline joins of binary operators --- Client.Linq.Test/InfluxDBQueryVisitorTest.cs | 24 +++++++++++++++++++ .../Internal/QueryExpressionTreeVisitor.cs | 11 ++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Client.Linq.Test/InfluxDBQueryVisitorTest.cs b/Client.Linq.Test/InfluxDBQueryVisitorTest.cs index 1f772c002..ea8a01b5f 100644 --- a/Client.Linq.Test/InfluxDBQueryVisitorTest.cs +++ b/Client.Linq.Test/InfluxDBQueryVisitorTest.cs @@ -1070,6 +1070,30 @@ public void AlignFieldsWithPivot() } } + [Test] + public void FilterByTimeAndTagWithAnds() + { + var start = new DateTime(2019, 11, 16, 8, 20, 15, DateTimeKind.Utc); + var stop = new DateTime(2021, 01, 10, 5, 10, 0, DateTimeKind.Utc); + + var query = from s in InfluxDBQueryable.Queryable("my-bucket", "my-org", _queryApi) + where s.Timestamp >= start && s.Timestamp < stop && s.SensorId == "id-1" + select s; + var visitor = BuildQueryVisitor(query); + + const string expected = "start_shifted = int(v: time(v: p3))\n" + + "stop_shifted = int(v: time(v: p4))\n\n" + + "from(bucket: p1) " + + "|> range(start: time(v: start_shifted), stop: time(v: stop_shifted)) " + + "|> filter(fn: (r) => (r[\"sensor_id\"] == p5)) " + + "|> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\") " + + "|> drop(columns: [\"_start\", \"_stop\", \"_measurement\"])"; + + Console.WriteLine(visitor.BuildFluxQuery()); + + Assert.AreEqual(expected, visitor.BuildFluxQuery()); + } + private InfluxDBQueryVisitor BuildQueryVisitor(IQueryable queryable, Expression expression = null) { var queryExecutor = (InfluxDBQueryExecutor)((DefaultQueryProvider)queryable.Provider).Executor; diff --git a/Client.Linq/Internal/QueryExpressionTreeVisitor.cs b/Client.Linq/Internal/QueryExpressionTreeVisitor.cs index 1e3354f14..0757a5f4f 100644 --- a/Client.Linq/Internal/QueryExpressionTreeVisitor.cs +++ b/Client.Linq/Internal/QueryExpressionTreeVisitor.cs @@ -395,7 +395,7 @@ internal static void NormalizeExpressions(List parts) .Where(i => parts[i] is LeftParenthesis) .ToList(); - foreach (var index in indexes) + foreach (var index in indexes) { // () if (parts.Count > index + 1 && parts[index + 1] is RightParenthesis) { @@ -405,6 +405,15 @@ internal static void NormalizeExpressions(List parts) NormalizeExpressions(parts); return; } + // ( + if (parts.Count == 1 && parts[index] is LeftParenthesis) + { + parts.RemoveAt(index); + + NormalizeExpressions(parts); + return; + } + } // (( )) if (parts.Count >= 4 && parts[0] is LeftParenthesis && parts[1] is LeftParenthesis && From 825bfde69c76bb76572f6b3443092eabbad3efc5 Mon Sep 17 00:00:00 2001 From: Jakub Bednar Date: Wed, 13 Apr 2022 14:24:39 +0200 Subject: [PATCH 2/2] docs: update CHANGELOG.md --- CHANGELOG.md | 3 +++ Client.Linq.Test/InfluxDBQueryVisitorTest.cs | 4 ++-- Client.Linq/Internal/QueryExpressionTreeVisitor.cs | 6 ++++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55556b46b..b7c77d5ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ ### Features 1. [#101](https://github.com/influxdata/influxdb-client-csharp/pull/304): Add `InvocableScriptsApi` to create, update, list, delete and invoke scripts by seamless way +### Bug Fixes +1. [#309](https://github.com/influxdata/influxdb-client-csharp/pull/309): Query expression for joins of binary operators [LINQ] + ## 4.0.0 [2022-03-18] :warning: The underlying `RestSharp` library was updated the latest major version `v107`. The new version of `RestSharp` switched from the legacy `HttpWebRequest` class to the standard well-known `System.Net.Http.HttpClient` instead. This improves performance and solves lots of issues, like hanging connections, updated protocols support, and many other problems. diff --git a/Client.Linq.Test/InfluxDBQueryVisitorTest.cs b/Client.Linq.Test/InfluxDBQueryVisitorTest.cs index ea8a01b5f..94f2dca12 100644 --- a/Client.Linq.Test/InfluxDBQueryVisitorTest.cs +++ b/Client.Linq.Test/InfluxDBQueryVisitorTest.cs @@ -1075,7 +1075,7 @@ public void FilterByTimeAndTagWithAnds() { var start = new DateTime(2019, 11, 16, 8, 20, 15, DateTimeKind.Utc); var stop = new DateTime(2021, 01, 10, 5, 10, 0, DateTimeKind.Utc); - + var query = from s in InfluxDBQueryable.Queryable("my-bucket", "my-org", _queryApi) where s.Timestamp >= start && s.Timestamp < stop && s.SensorId == "id-1" select s; @@ -1088,7 +1088,7 @@ public void FilterByTimeAndTagWithAnds() "|> filter(fn: (r) => (r[\"sensor_id\"] == p5)) " + "|> pivot(rowKey:[\"_time\"], columnKey: [\"_field\"], valueColumn: \"_value\") " + "|> drop(columns: [\"_start\", \"_stop\", \"_measurement\"])"; - + Console.WriteLine(visitor.BuildFluxQuery()); Assert.AreEqual(expected, visitor.BuildFluxQuery()); diff --git a/Client.Linq/Internal/QueryExpressionTreeVisitor.cs b/Client.Linq/Internal/QueryExpressionTreeVisitor.cs index 0757a5f4f..d1f7816b4 100644 --- a/Client.Linq/Internal/QueryExpressionTreeVisitor.cs +++ b/Client.Linq/Internal/QueryExpressionTreeVisitor.cs @@ -395,7 +395,8 @@ internal static void NormalizeExpressions(List parts) .Where(i => parts[i] is LeftParenthesis) .ToList(); - foreach (var index in indexes) { + foreach (var index in indexes) + { // () if (parts.Count > index + 1 && parts[index + 1] is RightParenthesis) { @@ -405,11 +406,12 @@ internal static void NormalizeExpressions(List parts) NormalizeExpressions(parts); return; } + // ( if (parts.Count == 1 && parts[index] is LeftParenthesis) { parts.RemoveAt(index); - + NormalizeExpressions(parts); return; }