From f1acbee534d752d265080fa11d3523571b6c8ff7 Mon Sep 17 00:00:00 2001 From: Brant Burnett Date: Mon, 2 Aug 2021 11:46:23 -0400 Subject: [PATCH] Use JSON-style string escaping Motivation ---------- The current approach to string escaping causes problems if a backslash is included, and also can't handle special characters like tab or CR. Modifications ------------- Serialize string and character constants to the N1QL query using a JSON serializer. Also change some other locations rendering strings to use double quotes for consistency. Results ------- String and character constant expressions now support the full set of characters supported by JSON. Strings now appear on the query wrapped in double quotes instead of single quotes. Fixes #348 --- .../QueryGeneration/AggregateTests.cs | 2 +- .../QueryGeneration/ArrayOperatorTests.cs | 16 ++--- .../QueryGeneration/BinaryExpressionTests.cs | 10 +-- .../ConstantExpressionTests.cs | 20 +++++- .../QueryGeneration/EnumTests.cs | 36 +++++------ .../QueryGeneration/HintTests.cs | 8 +-- .../QueryGeneration/JoinTests.cs | 16 ++--- .../MemberNameResolutionTests.cs | 6 +- .../ContainsMethodCallTranslatorTests.cs | 12 ++-- .../KeyMethodCallTranslatorTests.cs | 2 +- .../N1QlFunctionMethodCallTranslatorTests.cs | 4 +- .../QueryGeneration/NestTests.cs | 32 +++++----- .../QueryGeneration/OrderByClauseTests.cs | 2 +- .../QueryGeneration/SelectTests.cs | 2 +- .../QueryGeneration/StringTests.cs | 64 +++++++++---------- .../QueryGeneration/SubqueryTests.cs | 8 +-- .../QueryGeneration/UnionTests.cs | 40 ++++++------ .../QueryGeneration/WhereClauseTests.cs | 20 +++--- .../ContainsMethodCallTranslator.cs | 4 +- .../N1QLExpressionTreeVisitor.cs | 26 ++++++-- 20 files changed, 181 insertions(+), 149 deletions(-) diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/AggregateTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/AggregateTests.cs index f174fae..b8701d0 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/AggregateTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/AggregateTests.cs @@ -492,7 +492,7 @@ where string.Compare(g.Key, "N") >= 0 "FROM `default` as `Extent1` " + "INNER JOIN `default` as `Extent2` ON (`Extent1`.`brewery_id` = META(`Extent2`).id) " + "GROUP BY `Extent2`.`name` " + - "HAVING (`Extent2`.`name` >= 'N')"; + "HAVING (`Extent2`.`name` >= \"N\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/ArrayOperatorTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/ArrayOperatorTests.cs index 8c703f3..8189382 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/ArrayOperatorTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/ArrayOperatorTests.cs @@ -22,7 +22,7 @@ public void Test_ArrayContains() QueryFactory.Queryable(mockBucket.Object) .Where(e => e.Array.Contains("abc")); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE 'abc' IN (`Extent1`.`Array`)"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE \"abc\" IN (`Extent1`.`Array`)"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -41,7 +41,7 @@ public void Test_ListContains() QueryFactory.Queryable(mockBucket.Object) .Where(e => e.List.Contains("abc")); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE 'abc' IN (`Extent1`.`List`)"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE \"abc\" IN (`Extent1`.`List`)"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -61,7 +61,7 @@ public void Test_StaticArrayContains() QueryFactory.Queryable(mockBucket.Object) .Where(e => staticArray.Contains(e.Name)); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE `Extent1`.`name` IN (['abc', 'def'])"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE `Extent1`.`name` IN ([\"abc\", \"def\"])"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -81,7 +81,7 @@ public void Test_AlteredStaticArrayContains() QueryFactory.Queryable(mockBucket.Object) .Where(e => staticArray.Select(p => "a" + p).Contains(e.Name)); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE `Extent1`.`name` IN (ARRAY ('a' || `Extent2`) FOR `Extent2` IN ['abc', 'def'] END)"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE `Extent1`.`name` IN (ARRAY (\"a\" || `Extent2`) FOR `Extent2` IN [\"abc\", \"def\"] END)"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -101,7 +101,7 @@ public void Test_StaticListContains() QueryFactory.Queryable(mockBucket.Object) .Where(e => staticArray.Contains(e.Name)); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE `Extent1`.`name` IN (['abc', 'def'])"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE `Extent1`.`name` IN ([\"abc\", \"def\"])"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -120,7 +120,7 @@ public void Test_ArrayAny() QueryFactory.Queryable(mockBucket.Object) .Where(e => e.Beers.Any(p => p == "test")); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE ANY `Extent2` IN `Extent1`.`beers` SATISFIES (`Extent2` = 'test') END"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE ANY `Extent2` IN `Extent1`.`beers` SATISFIES (`Extent2` = \"test\") END"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -139,7 +139,7 @@ public void Test_StringSplitAny() QueryFactory.Queryable(mockBucket.Object) .Where(e => e.Name.Split().Any(p => p == "test")); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE ANY `Extent2` IN SPLIT(`Extent1`.`name`) SATISFIES (`Extent2` = 'test') END"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE ANY `Extent2` IN SPLIT(`Extent1`.`name`) SATISFIES (`Extent2` = \"test\") END"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -158,7 +158,7 @@ public void Test_StringSplitTwoParamAny() QueryFactory.Queryable(mockBucket.Object) .Where(e => e.Name.Split(new[] {' '}).Any(p => p == "test")); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE ANY `Extent2` IN SPLIT(`Extent1`.`name`, ' ') SATISFIES (`Extent2` = 'test') END"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE ANY `Extent2` IN SPLIT(`Extent1`.`name`, \" \") SATISFIES (`Extent2` = \"test\") END"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/BinaryExpressionTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/BinaryExpressionTests.cs index 90d1a29..c96caa2 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/BinaryExpressionTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/BinaryExpressionTests.cs @@ -319,7 +319,7 @@ public void Test_StringAddition() .Select(e => new { name = e.FirstName + " " + e.LastName }); const string expected = - "SELECT ((`Extent1`.`fname` || ' ') || `Extent1`.`lname`) as `name` FROM `default` as `Extent1`"; + "SELECT ((`Extent1`.`fname` || \" \") || `Extent1`.`lname`) as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -337,7 +337,7 @@ public void Test_StringAdditionNonString() .Select(e => new { key = "constant-" + e.Age }); const string expected = - "SELECT ('constant-' || `Extent1`.`age`) as `key` FROM `default` as `Extent1`"; + "SELECT (\"constant-\" || `Extent1`.`age`) as `key` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -355,7 +355,7 @@ public void Test_StringConcat() .Select(e => new { name = String.Concat(e.FirstName, " ", e.LastName) }); const string expected = - "SELECT (`Extent1`.`fname` || ' ' || `Extent1`.`lname`) as `name` FROM `default` as `Extent1`"; + "SELECT (`Extent1`.`fname` || \" \" || `Extent1`.`lname`) as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -373,7 +373,7 @@ public void Test_StringConcatArray() .Select(e => new { name = String.Concat(new[] {e.FirstName, " ", e.LastName}) }); const string expected = - "SELECT (`Extent1`.`fname` || ' ' || `Extent1`.`lname`) as `name` FROM `default` as `Extent1`"; + "SELECT (`Extent1`.`fname` || \" \" || `Extent1`.`lname`) as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -391,7 +391,7 @@ public void Test_StringConcatFiveParameters() .Select(e => new { name = String.Concat(e.FirstName, " ", e.LastName, " ", "suffix") }); const string expected = - "SELECT (`Extent1`.`fname` || ' ' || `Extent1`.`lname` || ' ' || 'suffix') as `name` FROM `default` as `Extent1`"; + "SELECT (`Extent1`.`fname` || \" \" || `Extent1`.`lname` || \" \" || \"suffix\") as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/ConstantExpressionTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/ConstantExpressionTests.cs index dfdcadb..463c6b1 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/ConstantExpressionTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/ConstantExpressionTests.cs @@ -26,7 +26,25 @@ public void Test_String() .Where(e => e.FirstName != "Test"); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`fname` != 'Test')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`fname` != \"Test\")"; + + var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); + + Assert.AreEqual(expected, n1QlQuery); + } + + [Test] + public void Test_EscapedString() + { + var mockBucket = new Mock(); + mockBucket.SetupGet(e => e.Name).Returns("default"); + + var query = + QueryFactory.Queryable(mockBucket.Object) + .Where(e => e.FirstName != "Test\\\"This"); + + const string expected = + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`fname` != \"Test\\\\\\\"This\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/EnumTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/EnumTests.cs index 7b88ca2..c8f81f9 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/EnumTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/EnumTests.cs @@ -205,7 +205,7 @@ public void Test_StringEnumConverter_WhereEqual() .Where(p => p.Value == StringEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -222,7 +222,7 @@ public void Test_StringEnumConverter_WhereEqualReversed() .Where(p => StringEnum.Value0 == p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -239,7 +239,7 @@ public void Test_StringEnumConverter_WhereNotEqual() .Where(p => p.Value != StringEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -256,7 +256,7 @@ public void Test_StringEnumConverter_WhereEqualToValueWithEnumMemberAttribute() .Where(p => p.Value == StringEnum.Value1); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value 1')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value 1\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -273,7 +273,7 @@ public void Test_StringEnumConverter_WhereNotEqualReversed() .Where(p => StringEnum.Value0 != p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -294,7 +294,7 @@ public void Test_StringEnumConverterOnNullable_WhereEqual() .Where(p => p.Value == StringEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -328,7 +328,7 @@ public void Test_StringEnumConverterOnNullable_WhereEqualReversed() .Where(p => StringEnum.Value0 == p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -345,7 +345,7 @@ public void Test_StringEnumConverterOnNullable_WhereNotEqual() .Where(p => p.Value != StringEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -379,7 +379,7 @@ public void Test_StringEnumConverterOnNullable_WhereNotEqualReversed() .Where(p => StringEnum.Value0 != p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -400,7 +400,7 @@ public void Test_StringEnumConverterOnProperty_WhereEqual() .Where(p => p.Value == IntegerEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -417,7 +417,7 @@ public void Test_StringEnumConverterOnProperty_WhereEqualReversed() .Where(p => IntegerEnum.Value0 == p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -434,7 +434,7 @@ public void Test_StringEnumConverterOnProperty_WhereNotEqual() .Where(p => p.Value != IntegerEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -451,7 +451,7 @@ public void Test_StringEnumConverterOnProperty_WhereEqualToValueWithEnumMemberAt .Where(p => p.Value == IntegerEnum.Value2); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value 2')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value 2\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -468,7 +468,7 @@ public void Test_StringEnumConverterOnProperty_WhereNotEqualReversed() .Where(p => IntegerEnum.Value0 != p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -489,7 +489,7 @@ public void Test_StringEnumConverterOnPropertyNullable_WhereEqual() .Where(p => p.Value == IntegerEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -523,7 +523,7 @@ public void Test_StringEnumConverterOnPropertyNullable_WhereEqualReversed() .Where(p => IntegerEnum.Value0 == p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` = \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -540,7 +540,7 @@ public void Test_StringEnumConverterOnPropertyNullable_WhereNotEqual() .Where(p => p.Value != IntegerEnum.Value0); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -574,7 +574,7 @@ public void Test_StringEnumConverterOnPropertyNullable_WhereNotEqualReversed() .Where(p => IntegerEnum.Value0 != p.Value); const string expected = - "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != 'Value0')"; + "SELECT RAW `Extent1` FROM `default` as `Extent1` WHERE (`Extent1`.`Value` != \"Value0\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/HintTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/HintTests.cs index 7314198..6869b8f 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/HintTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/HintTests.cs @@ -24,7 +24,7 @@ public void Test_UseIndex() const string expected = "SELECT RAW `Extent1` " + "FROM `default` as `Extent1` USE INDEX (`IndexName` USING GSI) " + - "WHERE (`Extent1`.`type` = 'contact')"; + "WHERE (`Extent1`.`type` = \"contact\")"; Assert.AreEqual(expected, n1QlQuery); } @@ -55,7 +55,7 @@ public void Test_UseIndexWithType() const string expected = "SELECT RAW `Extent1` " + "FROM `default` as `Extent1` USE INDEX (`IndexName` USING VIEW) " + - "WHERE (`Extent1`.`type` = 'contact')"; + "WHERE (`Extent1`.`type` = \"contact\")"; Assert.AreEqual(expected, n1QlQuery); } @@ -71,7 +71,7 @@ public void Test_UseIndex_Any() const string expected = "SELECT true as result " + "FROM `default` as `Extent1` USE INDEX (`IndexName` USING GSI) " + - "WHERE (`Extent1`.`type` = 'contact') " + + "WHERE (`Extent1`.`type` = \"contact\") " + "LIMIT 1"; Assert.AreEqual(expected, n1QlQuery); @@ -88,7 +88,7 @@ public void Test_UseIndexWithType_Any() const string expected = "SELECT true as result " + "FROM `default` as `Extent1` USE INDEX (`IndexName` USING VIEW) " + - "WHERE (`Extent1`.`type` = 'contact') " + + "WHERE (`Extent1`.`type` = \"contact\") " + "LIMIT 1"; Assert.AreEqual(expected, n1QlQuery); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/JoinTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/JoinTests.cs index 0bed6b6..3aa23db 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/JoinTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/JoinTests.cs @@ -72,8 +72,8 @@ on beer.BreweryId equals N1QlFunctions.Key(brewery) const string expected = "SELECT `Extent1`.`name` as `Name`, `Extent1`.`abv` as `Abv`, `Extent2`.`name` as `BreweryName` " + "FROM `default` as `Extent1` " + "INNER JOIN `default` as `Extent2` " + - "ON (`Extent1`.`brewery_id` = META(`Extent2`).id) AND (`Extent2`.`type` = 'brewery') " + - "WHERE (`Extent1`.`type` = 'beer')"; + "ON (`Extent1`.`brewery_id` = META(`Extent2`).id) AND (`Extent2`.`type` = \"brewery\") " + + "WHERE (`Extent1`.`type` = \"beer\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -143,8 +143,8 @@ from brewery in bg.DefaultIfEmpty() const string expected = "SELECT `Extent1`.`name` as `Name`, `Extent1`.`abv` as `Abv`, `Extent2`.`name` as `BreweryName` " + "FROM `default` as `Extent1` " + "LEFT JOIN `default` as `Extent2` " + - "ON (`Extent1`.`brewery_id` = META(`Extent2`).id) AND (`Extent2`.`type` = 'brewery') " + - "WHERE (`Extent1`.`type` = 'beer')"; + "ON (`Extent1`.`brewery_id` = META(`Extent2`).id) AND (`Extent2`.`type` = \"brewery\") " + + "WHERE (`Extent1`.`type` = \"beer\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -235,8 +235,8 @@ on route.DestinationAirport equals airport.Faa const string expected = "SELECT `Extent2`.`airportname` as `AirportName`, `Extent1`.`airline` as `Airline` " + "FROM `default` as `Extent1` "+ "INNER JOIN `default` as `Extent2` " + - "ON (`Extent1`.`destinationairport` = `Extent2`.`faa`) AND (`Extent2`.`type` = 'airport') " + - "WHERE (`Extent1`.`type` = 'route')"; + "ON (`Extent1`.`destinationairport` = `Extent2`.`faa`) AND (`Extent2`.`type` = \"airport\") " + + "WHERE (`Extent1`.`type` = \"route\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -280,8 +280,8 @@ from airport in ra.DefaultIfEmpty() const string expected = "SELECT `Extent2`.`airportname` as `AirportName`, `Extent1`.`airline` as `Airline` " + "FROM `default` as `Extent1` "+ "LEFT JOIN `default` as `Extent2` " + - "ON (`Extent1`.`destinationairport` = `Extent2`.`faa`) AND (`Extent2`.`type` = 'airport') " + - "WHERE (`Extent1`.`type` = 'route')"; + "ON (`Extent1`.`destinationairport` = `Extent2`.`faa`) AND (`Extent2`.`type` = \"airport\") " + + "WHERE (`Extent1`.`type` = \"route\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MemberNameResolutionTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MemberNameResolutionTests.cs index 94bc823..6788b0c 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MemberNameResolutionTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MemberNameResolutionTests.cs @@ -25,7 +25,7 @@ public void Test_Default_JsonProp_Att() e => new {age = e.Age, firstName = e.FirstName, lastName = e.LastName, children = e.Children}); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `firstName`, `Extent1`.`lname` as `lastName`, `Extent1`.`children` as `children` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` < 40) AND (`Extent1`.`fname` LIKE '%a%'))"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `firstName`, `Extent1`.`lname` as `lastName`, `Extent1`.`children` as `children` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` < 40) AND (`Extent1`.`fname` LIKE \"%a%\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -46,7 +46,7 @@ public void Test_Default_No_Att() .Select(e => new {brewName = e.Name, brewCity = e.City}); const string expected = - "SELECT `Extent1`.`name` as `brewName`, `Extent1`.`city` as `brewCity` FROM `default` as `Extent1` WHERE (`Extent1`.`country` LIKE '%a%')"; + "SELECT `Extent1`.`name` as `brewName`, `Extent1`.`city` as `brewCity` FROM `default` as `Extent1` WHERE (`Extent1`.`country` LIKE \"%a%\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -67,7 +67,7 @@ public void Test_Camel_No_Att() .Select(e => new {brewName = e.Name, brewCity = e.City}); const string expected = - "SELECT `Extent1`.`name` as `brewName`, `Extent1`.`city` as `brewCity` FROM `default` as `Extent1` WHERE (`Extent1`.`country` LIKE '%a%')"; + "SELECT `Extent1`.`name` as `brewName`, `Extent1`.`city` as `brewCity` FROM `default` as `Extent1` WHERE (`Extent1`.`country` LIKE \"%a%\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslatorTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslatorTests.cs index 86547c2..8c912b2 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslatorTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslatorTests.cs @@ -74,7 +74,7 @@ public void Translate_ContainsConstant_RendersCorrectly() // Assert - Assert.AreEqual("('test' LIKE '%t%')", result); + Assert.AreEqual("(\"test\" LIKE \"%t%\")", result); } [Test] @@ -105,7 +105,7 @@ public void Translate_ContainsExpression_RendersCorrectly() // Assert - Assert.AreEqual("('test' LIKE '%' || FAKE || '%')", result); + Assert.AreEqual("(\"test\" LIKE \"%\" || FAKE || \"%\")", result); } [Test] @@ -130,7 +130,7 @@ public void Translate_StartsWithConstant_RendersCorrectly() // Assert - Assert.AreEqual("('test' LIKE 't%')", result); + Assert.AreEqual("(\"test\" LIKE \"t%\")", result); } [Test] @@ -161,7 +161,7 @@ public void Translate_StartsWithExpression_RendersCorrectly() // Assert - Assert.AreEqual("('test' LIKE FAKE || '%')", result); + Assert.AreEqual("(\"test\" LIKE FAKE || \"%\")", result); } [Test] @@ -186,7 +186,7 @@ public void Translate_EndsWithConstant_RendersCorrectly() // Assert - Assert.AreEqual("('test' LIKE '%t')", result); + Assert.AreEqual("(\"test\" LIKE \"%t\")", result); } [Test] @@ -217,7 +217,7 @@ public void Translate_EndsWithExpression_RendersCorrectly() // Assert - Assert.AreEqual("('test' LIKE '%' || FAKE)", result); + Assert.AreEqual("(\"test\" LIKE \"%\" || FAKE)", result); } #endregion diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/KeyMethodCallTranslatorTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/KeyMethodCallTranslatorTests.cs index 61c70e0..cf822c5 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/KeyMethodCallTranslatorTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/KeyMethodCallTranslatorTests.cs @@ -76,7 +76,7 @@ public void Translate_OneParameter_RendersCorrectly() // Assert - Assert.AreEqual("META('arg1').id", result); + Assert.AreEqual("META(\"arg1\").id", result); } #endregion diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/N1QlFunctionMethodCallTranslatorTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/N1QlFunctionMethodCallTranslatorTests.cs index 9c9e559..e0ff080 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/N1QlFunctionMethodCallTranslatorTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/MethodCallTranslators/N1QlFunctionMethodCallTranslatorTests.cs @@ -192,7 +192,7 @@ public void Translate_OneParameter_RendersCorrectly() // Assert - Assert.AreEqual("FUNC('arg1')", result); + Assert.AreEqual("FUNC(\"arg1\")", result); } [Test] @@ -219,7 +219,7 @@ public void Translate_TwoParameters_RendersCorrectly() // Assert - Assert.AreEqual("FUNC('arg1', 'arg2')", result); + Assert.AreEqual("FUNC(\"arg1\", \"arg2\")", result); } #endregion diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/NestTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/NestTests.cs index 932bcb8..6d056c9 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/NestTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/NestTests.cs @@ -69,7 +69,7 @@ from address in brewery.Address.Where(p => p != "123 First Street") const string expected = "SELECT `Extent1`.`name` as `name`, `Extent2` as `address` " + "FROM `default` as `Extent1` " + "INNER UNNEST `Extent1`.`address` as `Extent2` " + - "WHERE (`Extent2` != '123 First Street')"; + "WHERE (`Extent2` != \"123 First Street\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -197,8 +197,8 @@ public void Test_Nest_Prefiltered() const string expected = "SELECT `Extent1`.`Value` as `Value`, `Extent2` as `level2` " + "FROM `default` as `Extent1` " + "INNER NEST `default` as `Extent2` " + - "ON (META(`Extent2`).id IN `Extent1`.`NestLevel2Keys`) AND (`Extent2`.`Type` = 'level2') " + - "WHERE (`Extent1`.`Type` = 'level1')"; + "ON (META(`Extent2`).id IN `Extent1`.`NestLevel2Keys`) AND (`Extent2`.`Type` = \"level2\") " + + "WHERE (`Extent1`.`Type` = \"level1\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -242,8 +242,8 @@ public void Test_LeftOuterNest_Prefiltered() const string expected = "SELECT `Extent1`.`Value` as `Value`, `Extent2` as `level2` " + "FROM `default` as `Extent1` " + "LEFT OUTER NEST `default` as `Extent2` " + - "ON (META(`Extent2`).id IN `Extent1`.`NestLevel2Keys`) AND (`Extent2`.`Type` = 'level2') " + - "WHERE (`Extent1`.`Type` = 'level1')"; + "ON (META(`Extent2`).id IN `Extent1`.`NestLevel2Keys`) AND (`Extent2`.`Type` = \"level2\") " + + "WHERE (`Extent1`.`Type` = \"level1\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -265,7 +265,7 @@ on N1QlFunctions.Key(level1) equals level2.NestLevel1Key into level2List const string expected = "SELECT `Extent1`.`Value` as `Value`, `Extent2` as `level2List` " + "FROM `default` as `Extent1` " + "LEFT OUTER NEST `default` as `Extent2` ON (META(`Extent1`).id = `Extent2`.`NestLevel1Key`) " + - "WHERE (`Extent1`.`Type` = 'level1')"; + "WHERE (`Extent1`.`Type` = \"level1\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -287,8 +287,8 @@ on N1QlFunctions.Key(level1) equals level2.NestLevel1Key into level2List const string expected = "SELECT `Extent1`.`Value` as `Value`, `Extent2` as `level2List` " + "FROM `default` as `Extent1` " + "LEFT OUTER NEST `default` as `Extent2` "+ - "ON (META(`Extent1`).id = `Extent2`.`NestLevel1Key`) AND (`Extent2`.`Type` = 'level2') " + - "WHERE (`Extent1`.`Type` = 'level1')"; + "ON (META(`Extent1`).id = `Extent2`.`NestLevel1Key`) AND (`Extent2`.`Type` = \"level2\") " + + "WHERE (`Extent1`.`Type` = \"level1\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -311,7 +311,7 @@ on airline.Iata equals route.Airline into routes "FROM `default` as `Extent1` " + "LEFT OUTER NEST `default` as `Extent2` " + "ON (`Extent1`.`iata` = `Extent2`.`airline`) " + - "WHERE (`Extent1`.`type` = 'airline')"; + "WHERE (`Extent1`.`type` = \"airline\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -334,7 +334,7 @@ on airline.Iata equals route.Airline into routes "FROM `default` as `Extent1` " + "INNER NEST `default` as `Extent2` " + "ON (`Extent1`.`iata` = `Extent2`.`airline`) " + - "WHERE (`Extent1`.`type` = 'airline')"; + "WHERE (`Extent1`.`type` = \"airline\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -356,8 +356,8 @@ on airline.Iata equals route.Airline into routes const string expected = "SELECT `Extent1`.`name` as `name`, `Extent2` as `routes` " + "FROM `default` as `Extent1` " + "LEFT OUTER NEST `default` as `Extent2` " + - "ON (`Extent1`.`iata` = `Extent2`.`airline`) AND (`Extent2`.`type` = 'route') " + - "WHERE (`Extent1`.`type` = 'airline')"; + "ON (`Extent1`.`iata` = `Extent2`.`airline`) AND (`Extent2`.`type` = \"route\") " + + "WHERE (`Extent1`.`type` = \"airline\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -379,8 +379,8 @@ on airline.Iata equals route.Airline into routes const string expected = "SELECT `Extent1`.`name` as `name`, `Extent2` as `routes` " + "FROM `default` as `Extent1` " + "INNER NEST `default` as `Extent2` " + - "ON (`Extent1`.`iata` = `Extent2`.`airline`) AND (`Extent2`.`type` = 'route') " + - "WHERE (`Extent1`.`type` = 'airline')"; + "ON (`Extent1`.`iata` = `Extent2`.`airline`) AND (`Extent2`.`type` = \"route\") " + + "WHERE (`Extent1`.`type` = \"airline\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -400,11 +400,11 @@ on airline.Iata equals route.Airline into routes select new { name = airline.Name, routes = routes.Where(p => p.DestinationAirport == "SCO").ToList() }; const string expected = "SELECT `Extent1`.`name` as `name`, " + - "ARRAY `Extent3` FOR `Extent3` IN `Extent2` WHEN (`Extent3`.`destinationairport` = 'SCO') END as `routes` " + + "ARRAY `Extent3` FOR `Extent3` IN `Extent2` WHEN (`Extent3`.`destinationairport` = \"SCO\") END as `routes` " + "FROM `default` as `Extent1` " + "LEFT OUTER NEST `default` as `Extent2` " + "ON (`Extent1`.`iata` = `Extent2`.`airline`) " + - "WHERE (`Extent1`.`type` = 'airline')"; + "WHERE (`Extent1`.`type` = \"airline\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/OrderByClauseTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/OrderByClauseTests.cs index b194405..396b52b 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/OrderByClauseTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/OrderByClauseTests.cs @@ -23,7 +23,7 @@ public void Test_Where_With_OrderBy() const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam')) ORDER BY `Extent1`.`age` ASC"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\")) ORDER BY `Extent1`.`age` ASC"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/SelectTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/SelectTests.cs index 2b9bcb4..9963a39 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/SelectTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/SelectTests.cs @@ -144,7 +144,7 @@ public void Test_Select_UseKeys() .UseKeys(new[] { "abc", "def" }) .Select(e => e); - const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` USE KEYS ['abc', 'def']"; + const string expected = "SELECT RAW `Extent1` FROM `default` as `Extent1` USE KEYS [\"abc\", \"def\"]"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/StringTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/StringTests.cs index 50031c7..a4c44c1 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/StringTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/StringTests.cs @@ -35,7 +35,7 @@ public void Test_StringLiteral() const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` = 'M')"; + "WHERE (`Extent1`.`fname` = \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -49,12 +49,12 @@ public void Test_StringLiteralWithQuote() mockBucket.SetupGet(e => e.Name).Returns("default"); var query = from contact in QueryFactory.Queryable(mockBucket.Object) - where contact.FirstName == "M'" + where contact.FirstName == "M\"" select new { contact.FirstName }; const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` = 'M''')"; + "WHERE (`Extent1`.`fname` = \"M\\\"\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -71,7 +71,7 @@ public void Test_CharLiteral() select new { contact.FirstName, ch = 'M' }; const string expected = - "SELECT `Extent1`.`fname` as `FirstName`, 'M' as `ch` FROM `default` as `Extent1`"; + "SELECT `Extent1`.`fname` as `FirstName`, \"M\" as `ch` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -85,10 +85,10 @@ public void Test_CharLiteral_Quote() mockBucket.SetupGet(e => e.Name).Returns("default"); var query = from contact in QueryFactory.Queryable(mockBucket.Object) - select new { contact.FirstName, ch = '\'' }; + select new { contact.FirstName, ch = '\"' }; const string expected = - "SELECT `Extent1`.`fname` as `FirstName`, '''' as `ch` FROM `default` as `Extent1`"; + "SELECT `Extent1`.`fname` as `FirstName`, \"\\\"\" as `ch` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -130,7 +130,7 @@ where contact.FirstName.ToUpper() == "BOB" const string expected = "SELECT `Extent1`.`lname` as `LastName` FROM `default` as `Extent1` " + - "WHERE (UPPER(`Extent1`.`fname`) = 'BOB')"; + "WHERE (UPPER(`Extent1`.`fname`) = \"BOB\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -149,7 +149,7 @@ where contact.FirstName.ToLower() == "bob" const string expected = "SELECT `Extent1`.`lname` as `LastName` FROM `default` as `Extent1` " + - "WHERE (LOWER(`Extent1`.`fname`) = 'bob')"; + "WHERE (LOWER(`Extent1`.`fname`) = \"bob\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -251,7 +251,7 @@ public void Test_Split_HasCharacter() select new { name = contact.FirstName.Split(new[] {' '}) }; const string expected = - "SELECT SPLIT(`Extent1`.`fname`, ' ') as `name` FROM `default` as `Extent1`"; + "SELECT SPLIT(`Extent1`.`fname`, \" \") as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -280,7 +280,7 @@ public void Test_IndexOf_Character() select new { index = contact.FirstName.IndexOf(' ') }; const string expected = - "SELECT POSITION(`Extent1`.`fname`, ' ') as `index` FROM `default` as `Extent1`"; + "SELECT POSITION(`Extent1`.`fname`, \" \") as `index` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -297,7 +297,7 @@ public void Test_IndexOf_String() select new { index = contact.FirstName.IndexOf(" ") }; const string expected = - "SELECT POSITION(`Extent1`.`fname`, ' ') as `index` FROM `default` as `Extent1`"; + "SELECT POSITION(`Extent1`.`fname`, \" \") as `index` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -314,7 +314,7 @@ public void Test_Replace() select new { name = contact.FirstName.Replace(" ", "") }; const string expected = - "SELECT REPLACE(`Extent1`.`fname`, ' ', '') as `name` FROM `default` as `Extent1`"; + "SELECT REPLACE(`Extent1`.`fname`, \" \", \"\") as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -362,10 +362,10 @@ public void Test_Trim_WithChars() mockBucket.SetupGet(e => e.Name).Returns("default"); var query = from contact in QueryFactory.Queryable(mockBucket.Object) - select new { name = contact.FirstName.Trim(' ', '\t', '\'') }; + select new { name = contact.FirstName.Trim(' ', '\t', '\"') }; const string expected = - "SELECT TRIM(`Extent1`.`fname`, ' \t''') as `name` FROM `default` as `Extent1`"; + "SELECT TRIM(`Extent1`.`fname`, \" \\t\\\"\") as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -413,10 +413,10 @@ public void Test_TrimEnd_WithChars() mockBucket.SetupGet(e => e.Name).Returns("default"); var query = from contact in QueryFactory.Queryable(mockBucket.Object) - select new { name = contact.FirstName.TrimEnd(' ', '\t', '\'') }; + select new { name = contact.FirstName.TrimEnd(' ', '\t', '\"') }; const string expected = - "SELECT RTRIM(`Extent1`.`fname`, ' \t''') as `name` FROM `default` as `Extent1`"; + "SELECT RTRIM(`Extent1`.`fname`, \" \\t\\\"\") as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -464,10 +464,10 @@ public void Test_TrimStart_WithChars() mockBucket.SetupGet(e => e.Name).Returns("default"); var query = from contact in QueryFactory.Queryable(mockBucket.Object) - select new { name = contact.FirstName.TrimStart(' ', '\t', '\'') }; + select new { name = contact.FirstName.TrimStart(' ', '\t', '\"') }; const string expected = - "SELECT LTRIM(`Extent1`.`fname`, ' \t''') as `name` FROM `default` as `Extent1`"; + "SELECT LTRIM(`Extent1`.`fname`, \" \\t\\\"\") as `name` FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -528,7 +528,7 @@ where string.Compare(contact.FirstName, "M") == 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` = 'M')"; + "WHERE (`Extent1`.`fname` = \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -547,7 +547,7 @@ where string.Compare(contact.FirstName, "M", StringComparison.Ordinal) == 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` = 'M')"; + "WHERE (`Extent1`.`fname` = \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -566,7 +566,7 @@ where string.Compare(contact.FirstName, "M", StringComparison.OrdinalIgnoreCase) const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (LOWER(`Extent1`.`fname`) = LOWER('M'))"; + "WHERE (LOWER(`Extent1`.`fname`) = LOWER(\"M\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -624,7 +624,7 @@ where string.Compare(contact.FirstName, "M") != 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` != 'M')"; + "WHERE (`Extent1`.`fname` != \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -643,7 +643,7 @@ where string.Compare(contact.FirstName, "M") < 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` < 'M')"; + "WHERE (`Extent1`.`fname` < \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -662,7 +662,7 @@ where string.Compare(contact.FirstName, "M") <= 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` <= 'M')"; + "WHERE (`Extent1`.`fname` <= \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -681,7 +681,7 @@ where string.Compare(contact.FirstName, "M") > 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` > 'M')"; + "WHERE (`Extent1`.`fname` > \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -700,7 +700,7 @@ where string.Compare(contact.FirstName, "M") >= 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` >= 'M')"; + "WHERE (`Extent1`.`fname` >= \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -719,7 +719,7 @@ where contact.FirstName.CompareTo("M") == 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` = 'M')"; + "WHERE (`Extent1`.`fname` = \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -738,7 +738,7 @@ where contact.FirstName.CompareTo("M") != 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` != 'M')"; + "WHERE (`Extent1`.`fname` != \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -757,7 +757,7 @@ where contact.FirstName.CompareTo("M") < 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` < 'M')"; + "WHERE (`Extent1`.`fname` < \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -776,7 +776,7 @@ where contact.FirstName.CompareTo("M") <= 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` <= 'M')"; + "WHERE (`Extent1`.`fname` <= \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -795,7 +795,7 @@ where contact.FirstName.CompareTo("M") > 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` > 'M')"; + "WHERE (`Extent1`.`fname` > \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -814,7 +814,7 @@ where contact.FirstName.CompareTo("M") >= 0 const string expected = "SELECT `Extent1`.`fname` as `FirstName` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`fname` >= 'M')"; + "WHERE (`Extent1`.`fname` >= \"M\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/SubqueryTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/SubqueryTests.cs index a108d2c..f6db34a 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/SubqueryTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/SubqueryTests.cs @@ -143,7 +143,7 @@ where QueryFactory.Queryable(mockBucket.Object).UseKeys(brewery.Beers).Any "SELECT `Extent1`.`name` as `name` " + "FROM `default` as `Extent1` " + "WHERE ANY `Extent3` IN (SELECT * FROM `default` as `Extent2` USE KEYS `Extent1`.`beers` " + - "WHERE (`Extent2`.`name` LIKE '%IPA%')) SATISFIES true END"; + "WHERE (`Extent2`.`name` LIKE \"%IPA%\")) SATISFIES true END"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -256,7 +256,7 @@ from brewery in QueryFactory.Queryable(mockBucket.Object) const string expected = "SELECT `Extent1`.`name` as `name`, " + - "ARRAY ('Address ' || `Extent2`) FOR `Extent2` IN `Extent1`.`address` END as `addresses` " + + "ARRAY (\"Address \" || `Extent2`) FOR `Extent2` IN `Extent1`.`address` END as `addresses` " + "FROM `default` as `Extent1`"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -325,8 +325,8 @@ where brewery.Address.Where(p => p == "563 Second Street").All(p => p == "101 Fa "SELECT `Extent1`.`name` as `name`, `Extent1`.`address` as `addresses` " + "FROM `default` as `Extent1` " + "WHERE EVERY `Extent3` IN " + - "(ARRAY `Extent2` FOR `Extent2` IN `Extent1`.`address` WHEN (`Extent2` = '563 Second Street') END) " + - "SATISFIES (`Extent3` = '101 Fake Street') END"; + "(ARRAY `Extent2` FOR `Extent2` IN `Extent1`.`address` WHEN (`Extent2` = \"563 Second Street\") END) " + + "SATISFIES (`Extent3` = \"101 Fake Street\") END"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/UnionTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/UnionTests.cs index 349ad0d..ecf384c 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/UnionTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/UnionTests.cs @@ -30,9 +30,9 @@ public void Test_Union() .Select(e => new { e.Name })); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')"; + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -58,9 +58,9 @@ public void Test_SortedUnion() .OrderBy(e => e.Name); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')" + + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")" + " ORDER BY `Name` ASC"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -90,11 +90,11 @@ public void Test_MultiUnionType1() .Select(e => new { Name = e.FirstName}))); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')" + + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")" + " UNION " + - "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = 'contact')"; + "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = \"contact\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -123,11 +123,11 @@ public void Test_MultiUnionType2() .Select(e => new { Name = e.FirstName })); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')" + + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")" + " UNION " + - "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = 'contact')"; + "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = \"contact\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -152,9 +152,9 @@ public void Test_Concat() .Select(e => new { e.Name })); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION ALL " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')"; + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -180,9 +180,9 @@ public void Test_SortedConcat() .OrderBy(e => e.Name); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION ALL " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')" + + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")" + " ORDER BY `Name` ASC"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -212,11 +212,11 @@ public void Test_MultiConcatType1() .Select(e => new { Name = e.FirstName }))); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION ALL " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')" + + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")" + " UNION ALL " + - "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = 'contact')"; + "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = \"contact\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -245,11 +245,11 @@ public void Test_MultiConcatType2() .Select(e => new { Name = e.FirstName })); const string expected = - "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = 'beer')" + + "SELECT `Extent1`.`name` as `Name` FROM `default` as `Extent1` WHERE (`Extent1`.`type` = \"beer\")" + " UNION ALL " + - "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = 'brewery')" + + "SELECT `Extent2`.`name` as `Name` FROM `default` as `Extent2` WHERE (`Extent2`.`type` = \"brewery\")" + " UNION ALL " + - "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = 'contact')"; + "SELECT `Extent3`.`fname` as `Name` FROM `default` as `Extent3` WHERE (`Extent3`.`type` = \"contact\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq.UnitTests/QueryGeneration/WhereClauseTests.cs b/Src/Couchbase.Linq.UnitTests/QueryGeneration/WhereClauseTests.cs index cbcdf07..819688c 100644 --- a/Src/Couchbase.Linq.UnitTests/QueryGeneration/WhereClauseTests.cs +++ b/Src/Couchbase.Linq.UnitTests/QueryGeneration/WhereClauseTests.cs @@ -24,7 +24,7 @@ public void Test_Where_With_OrderBy() .Select(e => new { age = e.Age, name = e.FirstName }); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam')) ORDER BY `Extent1`.`age` ASC"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\")) ORDER BY `Extent1`.`age` ASC"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -45,7 +45,7 @@ public void Test_Where_With_Missing() .Select(e => new { age = e.Age, name = e.FirstName }); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (`Extent1`.`email` = 'something@gmail.com') AND `Extent1`.`age` IS MISSING ORDER BY `Extent1`.`age` ASC"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (`Extent1`.`email` = \"something@gmail.com\") AND `Extent1`.`age` IS MISSING ORDER BY `Extent1`.`age` ASC"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -64,7 +64,7 @@ public void Test_Where_With_Like() .Select(e => new { age = e.Age, name = e.FirstName }); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam')) AND (`Extent1`.`lname` LIKE '%a%'))"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\")) AND (`Extent1`.`lname` LIKE \"%a%\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -83,7 +83,7 @@ public void Test_Where_With_StartsWith() .Select(e => new { age = e.Age, name = e.FirstName }); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam')) AND (`Extent1`.`lname` LIKE 'a%'))"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\")) AND (`Extent1`.`lname` LIKE \"a%\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -102,7 +102,7 @@ public void Test_Where_With_EndsWith() .Select(e => new { age = e.Age, name = e.FirstName }); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam')) AND (`Extent1`.`lname` LIKE '%a'))"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE (((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\")) AND (`Extent1`.`lname` LIKE \"%a\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -122,7 +122,7 @@ public void Test_Where() const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam'))"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -145,7 +145,7 @@ public void Test_Where_With_Parameters() const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam'))"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -165,7 +165,7 @@ public void Test_Multiple_Where() .Select(e => new { age = e.Age, name = e.FirstName }); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = 'Sam')) AND (`Extent1`.`email` = 'myemail@test.com')"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) AND (`Extent1`.`fname` = \"Sam\")) AND (`Extent1`.`email` = \"myemail@test.com\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -184,7 +184,7 @@ public void Test_Where_With_Or() .Select(e => new { age = e.Age, name = e.FirstName }); const string expected = - "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) OR (`Extent1`.`fname` = 'Sam'))"; + "SELECT `Extent1`.`age` as `age`, `Extent1`.`fname` as `name` FROM `default` as `Extent1` WHERE ((`Extent1`.`age` > 10) OR (`Extent1`.`fname` = \"Sam\"))"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); @@ -325,7 +325,7 @@ public void Test_Where_With_Guid() string expected = "SELECT `Extent1`.`Id` as `id`, `Extent1`.`Name` as `name` FROM `default` as `Extent1` " + - "WHERE (`Extent1`.`Id` = '" + guid.ToString() + "')"; + "WHERE (`Extent1`.`Id` = \"" + guid.ToString() + "\")"; var n1QlQuery = CreateN1QlQuery(mockBucket.Object, query.Expression); diff --git a/Src/Couchbase.Linq/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslator.cs b/Src/Couchbase.Linq/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslator.cs index 1e7f45b..992350e 100644 --- a/Src/Couchbase.Linq/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslator.cs +++ b/Src/Couchbase.Linq/QueryGeneration/MethodCallTranslators/ContainsMethodCallTranslator.cs @@ -65,14 +65,14 @@ public Expression Translate(MethodCallExpression methodCallExpression, N1QlExpre if (methodCallExpression.Method.Name != StartsWith) { - expression.Append("'%' || "); + expression.Append("\"%\" || "); } expressionTreeVisitor.Visit(methodCallExpression.Arguments[0]); if (methodCallExpression.Method.Name != EndsWith) { - expression.Append(" || '%'"); + expression.Append(" || \"%\""); } } diff --git a/Src/Couchbase.Linq/QueryGeneration/N1QLExpressionTreeVisitor.cs b/Src/Couchbase.Linq/QueryGeneration/N1QLExpressionTreeVisitor.cs index 3645c70..246ca34 100644 --- a/Src/Couchbase.Linq/QueryGeneration/N1QLExpressionTreeVisitor.cs +++ b/Src/Couchbase.Linq/QueryGeneration/N1QLExpressionTreeVisitor.cs @@ -1,14 +1,16 @@ using System; using System.Collections.Generic; +using System.Globalization; +using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using Couchbase.Core.IO.Serializers; using Couchbase.Linq.QueryGeneration.Expressions; +using Newtonsoft.Json; using Remotion.Linq.Clauses.Expressions; using Remotion.Linq.Parsing; -using Remotion.Linq.Parsing.ExpressionVisitors; namespace Couchbase.Linq.QueryGeneration { @@ -17,8 +19,16 @@ internal class N1QlExpressionTreeVisitor : ThrowingExpressionVisitor, IN1QlExpre private static readonly Assembly Mscorlib = typeof(string).GetTypeInfo().Assembly; private readonly StringBuilder _expression = new StringBuilder(); + private JsonTextWriter? _jsonConstantWriter; + public StringBuilder Expression => _expression; + /// + /// which can serialize a constant as JSON directly to the . + /// + private JsonTextWriter JsonConstantWriter => + _jsonConstantWriter ??= new JsonTextWriter(new StringWriter(_expression, CultureInfo.InvariantCulture)); + public N1QlQueryGenerationContext QueryGenerationContext { get; } protected N1QlExpressionTreeVisitor(N1QlQueryGenerationContext queryGenerationContext) @@ -479,13 +489,17 @@ protected override Expression VisitConstant(ConstantExpression expression) { _expression.Append("NULL"); } - else if (namedParameter.Value is string) + else if (namedParameter.Value is string stringValue) { - _expression.AppendFormat("'{0}'", namedParameter.Value.ToString().Replace("'", "''")); + var writer = JsonConstantWriter; + writer.WriteValue(stringValue); + writer.Flush(); } - else if (namedParameter.Value is char) + else if (namedParameter.Value is char charValue) { - _expression.AppendFormat("'{0}'", (char)namedParameter.Value != '\'' ? namedParameter.Value : "''"); + var writer = JsonConstantWriter; + writer.WriteValue(charValue); + writer.Flush(); } else if (namedParameter.Value is bool) { @@ -533,7 +547,7 @@ protected override Expression VisitConstant(ConstantExpression expression) } else if (namedParameter.Value is Guid) { - _expression.AppendFormat("'{0}'", namedParameter.Value.ToString()); + _expression.AppendFormat("\"{0}\"", namedParameter.Value); } else {