Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Additional work on CSHARP-433. Implemented "is" operator in LINQ quer…

…ies.
  • Loading branch information...
commit 8bf97a816a3b189ec44a725f7f9f2164f68f3e64 1 parent 3b46a19
authored April 13, 2012
6  Driver/Linq/Expressions/ExpressionFormatter.cs
@@ -362,7 +362,11 @@ protected override Expression VisitParameter(ParameterExpression node)
362 362
         /// <returns>The TypeBinaryExpression.</returns>
363 363
         protected override Expression VisitTypeBinary(TypeBinaryExpression node)
364 364
         {
365  
-            _sb.Append("<TypeBinaryExpression>");
  365
+            _sb.Append("(");
  366
+            Visit(node.Expression);
  367
+            _sb.Append(" is ");
  368
+            _sb.Append(FriendlyClassName(node.TypeOperand));
  369
+            _sb.Append(")");
366 370
             return node;
367 371
         }
368 372
 
9  Driver/Linq/Expressions/ExpressionPrettyPrinter.cs
@@ -332,7 +332,14 @@ protected override Expression VisitParameter(ParameterExpression node)
332 332
         /// <returns>The TypeBinaryExpression.</returns>
333 333
         protected override Expression VisitTypeBinary(TypeBinaryExpression node)
334 334
         {
335  
-            throw new NotImplementedException();
  335
+            WriteHeader(node);
  336
+            using (new Indentation(this))
  337
+            {
  338
+                WriteLine("TypeOperand={0}", FriendlyClassName(node.TypeOperand));
  339
+                WriteLine("Expression:");
  340
+                VisitIndented(node.Expression);
  341
+            }
  342
+            return node;
336 343
         }
337 344
 
338 345
         /// <summary>
35  Driver/Linq/Translators/SelectQuery.cs
@@ -844,6 +844,9 @@ private IMongoQuery BuildQuery(Expression expression)
844 844
                 case ExpressionType.OrElse:
845 845
                     query = BuildOrElseQuery((BinaryExpression)expression);
846 846
                     break;
  847
+                case ExpressionType.TypeIs:
  848
+                    query = BuildTypeIsQuery((TypeBinaryExpression)expression);
  849
+                    break;
847 850
             }
848 851
 
849 852
             if (query == null)
@@ -1248,6 +1251,26 @@ private IMongoQuery BuildStringQuery(MethodCallExpression methodCallExpression)
1248 1251
             return null;
1249 1252
         }
1250 1253
 
  1254
+        private IMongoQuery BuildTypeIsQuery(TypeBinaryExpression typeBinaryExpression)
  1255
+        {
  1256
+            var nominalType = typeBinaryExpression.Expression.Type;
  1257
+            var actualType = typeBinaryExpression.TypeOperand;
  1258
+
  1259
+            var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(nominalType);
  1260
+            var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType);
  1261
+            if (discriminator == null)
  1262
+            {
  1263
+                return Query.Not("_").Mod(1, 2); // best query I could come up with that's always true
  1264
+            }
  1265
+
  1266
+            if (discriminator.IsBsonArray)
  1267
+            {
  1268
+                discriminator = discriminator.AsBsonArray[discriminator.AsBsonArray.Count - 1];
  1269
+            }
  1270
+
  1271
+            return Query.EQ(discriminatorConvention.ElementName, discriminator);
  1272
+        }
  1273
+
1251 1274
         private void CombinePredicateWithWhereClause(MethodCallExpression methodCallExpression, LambdaExpression predicate)
1252 1275
         {
1253 1276
             if (predicate != null)
@@ -1870,11 +1893,6 @@ private void TranslateOfType(MethodCallExpression methodCallExpression)
1870 1893
             }
1871 1894
             var nominalType = sourceExpression.Type.GetGenericArguments()[0];
1872 1895
 
1873  
-            if (nominalType == actualType)
1874  
-            {
1875  
-                return; // nothing to do
1876  
-            }
1877  
-
1878 1896
             if (_projection != null)
1879 1897
             {
1880 1898
                 throw new NotSupportedException("OfType after a projection is not supported.");
@@ -1882,13 +1900,18 @@ private void TranslateOfType(MethodCallExpression methodCallExpression)
1882 1900
 
1883 1901
             var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(nominalType);
1884 1902
             var discriminator = discriminatorConvention.GetDiscriminator(nominalType, actualType);
  1903
+            if (discriminator == null)
  1904
+            {
  1905
+                return; // nothing to do
  1906
+            }
  1907
+
1885 1908
             if (discriminator.IsBsonArray)
1886 1909
             {
1887 1910
                 discriminator = discriminator.AsBsonArray[discriminator.AsBsonArray.Count - 1];
1888 1911
             }
  1912
+            var query = Query.EQ(discriminatorConvention.ElementName, discriminator);
1889 1913
 
1890 1914
             var injectMethodInfo = typeof(LinqToMongo).GetMethod("Inject");
1891  
-            var query = Query.EQ("_t", discriminator);
1892 1915
             var body = Expression.Call(injectMethodInfo, Expression.Constant(query));
1893 1916
             var parameter = Expression.Parameter(nominalType, "x");
1894 1917
             var predicate = Expression.Lambda(body, parameter);
81  DriverUnitTests/Linq/SelectOfTypeHierarchicalTests.cs
@@ -75,14 +75,14 @@ public void TestOfTypeB()
75 75
             Assert.AreSame(typeof(B), translatedQuery.DocumentType);
76 76
 
77 77
             var selectQuery = (SelectQuery)translatedQuery;
78  
-            Assert.IsNull(selectQuery.Where);
79  
-            Assert.AreEqual(null, selectQuery.OfType); // OfType ignored because <T> was the same as <TDocument>
  78
+            Assert.AreEqual("(B x) => LinqToMongo.Inject({ \"_t\" : \"B\" })", ExpressionFormatter.ToString(selectQuery.Where));
  79
+            Assert.AreEqual(typeof(B), selectQuery.OfType);
80 80
             Assert.IsNull(selectQuery.OrderBy);
81 81
             Assert.IsNull(selectQuery.Projection);
82 82
             Assert.IsNull(selectQuery.Skip);
83 83
             Assert.IsNull(selectQuery.Take);
84 84
 
85  
-            Assert.IsNull(selectQuery.BuildQuery());
  85
+            Assert.AreEqual("{ \"_t\" : \"B\" }", selectQuery.BuildQuery().ToJson());
86 86
             Assert.AreEqual(3, Consume(query));
87 87
         }
88 88
 
@@ -174,6 +174,81 @@ public void TestWhereBGreaterThan0OfTypeCWhereCGreaterThan0()
174 174
             Assert.AreEqual(2, Consume(query));
175 175
         }
176 176
 
  177
+        [Test]
  178
+        public void TestWhereBIsB()
  179
+        {
  180
+            var query =
  181
+                from b in _collection.AsQueryable<B>()
  182
+                where b is B
  183
+                select b;
  184
+
  185
+            var translatedQuery = MongoQueryTranslator.Translate(query);
  186
+            Assert.IsInstanceOf<SelectQuery>(translatedQuery);
  187
+            Assert.AreSame(_collection, translatedQuery.Collection);
  188
+            Assert.AreSame(typeof(B), translatedQuery.DocumentType);
  189
+
  190
+            var selectQuery = (SelectQuery)translatedQuery;
  191
+            Assert.AreEqual("(B b) => (b is B)", ExpressionFormatter.ToString(selectQuery.Where));
  192
+            Assert.AreEqual(null, selectQuery.OfType); // OfType ignored because <T> was the same as <TDocument>
  193
+            Assert.IsNull(selectQuery.OrderBy);
  194
+            Assert.IsNull(selectQuery.Projection);
  195
+            Assert.IsNull(selectQuery.Skip);
  196
+            Assert.IsNull(selectQuery.Take);
  197
+
  198
+            Assert.AreEqual("{ \"_t\" : \"B\" }", selectQuery.BuildQuery().ToJson());
  199
+            Assert.AreEqual(3, Consume(query));
  200
+        }
  201
+
  202
+        [Test]
  203
+        public void TestWhereBIsC()
  204
+        {
  205
+            var query =
  206
+                from b in _collection.AsQueryable<B>()
  207
+                where b is C
  208
+                select b;
  209
+
  210
+            var translatedQuery = MongoQueryTranslator.Translate(query);
  211
+            Assert.IsInstanceOf<SelectQuery>(translatedQuery);
  212
+            Assert.AreSame(_collection, translatedQuery.Collection);
  213
+            Assert.AreSame(typeof(B), translatedQuery.DocumentType);
  214
+
  215
+            var selectQuery = (SelectQuery)translatedQuery;
  216
+            Assert.AreEqual("(B b) => (b is C)", ExpressionFormatter.ToString(selectQuery.Where));
  217
+            Assert.AreEqual(null, selectQuery.OfType);
  218
+            Assert.IsNull(selectQuery.OrderBy);
  219
+            Assert.IsNull(selectQuery.Projection);
  220
+            Assert.IsNull(selectQuery.Skip);
  221
+            Assert.IsNull(selectQuery.Take);
  222
+
  223
+            Assert.AreEqual("{ \"_t\" : \"C\" }", selectQuery.BuildQuery().ToJson());
  224
+            Assert.AreEqual(2, Consume(query));
  225
+        }
  226
+
  227
+        [Test]
  228
+        public void TestWhereBIsD()
  229
+        {
  230
+            var query =
  231
+                from b in _collection.AsQueryable<B>()
  232
+                where b is D
  233
+                select b;
  234
+
  235
+            var translatedQuery = MongoQueryTranslator.Translate(query);
  236
+            Assert.IsInstanceOf<SelectQuery>(translatedQuery);
  237
+            Assert.AreSame(_collection, translatedQuery.Collection);
  238
+            Assert.AreSame(typeof(B), translatedQuery.DocumentType);
  239
+
  240
+            var selectQuery = (SelectQuery)translatedQuery;
  241
+            Assert.AreEqual("(B b) => (b is D)", ExpressionFormatter.ToString(selectQuery.Where));
  242
+            Assert.AreEqual(null, selectQuery.OfType);
  243
+            Assert.IsNull(selectQuery.OrderBy);
  244
+            Assert.IsNull(selectQuery.Projection);
  245
+            Assert.IsNull(selectQuery.Skip);
  246
+            Assert.IsNull(selectQuery.Take);
  247
+
  248
+            Assert.AreEqual("{ \"_t\" : \"D\" }", selectQuery.BuildQuery().ToJson());
  249
+            Assert.AreEqual(1, Consume(query));
  250
+        }
  251
+
177 252
         private int Consume<T>(IQueryable<T> query)
178 253
         {
179 254
             var count = 0;
75  DriverUnitTests/Linq/SelectOfTypeTests.cs
@@ -173,6 +173,81 @@ public void TestWhereBGreaterThan0OfTypeCWhereCGreaterThan0()
173 173
             Assert.AreEqual(1, Consume(query)); // should match 2 but for that you need to use the hierarchical discriminator
174 174
         }
175 175
 
  176
+        [Test]
  177
+        public void TestWhereBIsB()
  178
+        {
  179
+            var query =
  180
+                from b in _collection.AsQueryable<B>()
  181
+                where b is B
  182
+                select b;
  183
+
  184
+            var translatedQuery = MongoQueryTranslator.Translate(query);
  185
+            Assert.IsInstanceOf<SelectQuery>(translatedQuery);
  186
+            Assert.AreSame(_collection, translatedQuery.Collection);
  187
+            Assert.AreSame(typeof(B), translatedQuery.DocumentType);
  188
+
  189
+            var selectQuery = (SelectQuery)translatedQuery;
  190
+            Assert.AreEqual("(B b) => (b is B)", ExpressionFormatter.ToString(selectQuery.Where));
  191
+            Assert.AreEqual(null, selectQuery.OfType); // OfType ignored because <T> was the same as <TDocument>
  192
+            Assert.IsNull(selectQuery.OrderBy);
  193
+            Assert.IsNull(selectQuery.Projection);
  194
+            Assert.IsNull(selectQuery.Skip);
  195
+            Assert.IsNull(selectQuery.Take);
  196
+
  197
+            Assert.AreEqual("{ \"_\" : { \"$not\" : { \"$mod\" : [1, 2] } } }", selectQuery.BuildQuery().ToJson());
  198
+            Assert.AreEqual(3, Consume(query));
  199
+        }
  200
+
  201
+        [Test]
  202
+        public void TestWhereBIsC()
  203
+        {
  204
+            var query =
  205
+                from b in _collection.AsQueryable<B>()
  206
+                where b is C
  207
+                select b;
  208
+
  209
+            var translatedQuery = MongoQueryTranslator.Translate(query);
  210
+            Assert.IsInstanceOf<SelectQuery>(translatedQuery);
  211
+            Assert.AreSame(_collection, translatedQuery.Collection);
  212
+            Assert.AreSame(typeof(B), translatedQuery.DocumentType);
  213
+
  214
+            var selectQuery = (SelectQuery)translatedQuery;
  215
+            Assert.AreEqual("(B b) => (b is C)", ExpressionFormatter.ToString(selectQuery.Where));
  216
+            Assert.AreEqual(null, selectQuery.OfType);
  217
+            Assert.IsNull(selectQuery.OrderBy);
  218
+            Assert.IsNull(selectQuery.Projection);
  219
+            Assert.IsNull(selectQuery.Skip);
  220
+            Assert.IsNull(selectQuery.Take);
  221
+
  222
+            Assert.AreEqual("{ \"_t\" : \"C\" }", selectQuery.BuildQuery().ToJson());
  223
+            Assert.AreEqual(1, Consume(query)); // should match 2 but for that you need to use the hierarchical discriminator
  224
+        }
  225
+
  226
+        [Test]
  227
+        public void TestWhereBIsD()
  228
+        {
  229
+            var query =
  230
+                from b in _collection.AsQueryable<B>()
  231
+                where b is D
  232
+                select b;
  233
+
  234
+            var translatedQuery = MongoQueryTranslator.Translate(query);
  235
+            Assert.IsInstanceOf<SelectQuery>(translatedQuery);
  236
+            Assert.AreSame(_collection, translatedQuery.Collection);
  237
+            Assert.AreSame(typeof(B), translatedQuery.DocumentType);
  238
+
  239
+            var selectQuery = (SelectQuery)translatedQuery;
  240
+            Assert.AreEqual("(B b) => (b is D)", ExpressionFormatter.ToString(selectQuery.Where));
  241
+            Assert.AreEqual(null, selectQuery.OfType);
  242
+            Assert.IsNull(selectQuery.OrderBy);
  243
+            Assert.IsNull(selectQuery.Projection);
  244
+            Assert.IsNull(selectQuery.Skip);
  245
+            Assert.IsNull(selectQuery.Take);
  246
+
  247
+            Assert.AreEqual("{ \"_t\" : \"D\" }", selectQuery.BuildQuery().ToJson());
  248
+            Assert.AreEqual(1, Consume(query));
  249
+        }
  250
+
176 251
         private int Consume<T>(IQueryable<T> query)
177 252
         {
178 253
             var count = 0;

0 notes on commit 8bf97a8

Please sign in to comment.
Something went wrong with that request. Please try again.