<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/dm-mongo-adapter/conditions.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -7,6 +7,7 @@ require 'mongo'
 dir = Pathname(__FILE__).dirname.expand_path / 'dm-mongo-adapter'
 
 require dir / 'query'
+require dir / 'conditions'
 require dir / 'adapter'
 require dir / 'types'
 require dir / 'resource'</diff>
      <filename>lib/dm-mongo-adapter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -7,7 +7,7 @@ module DataMapper
       def initialize(collection, query)
         assert_kind_of 'collection', collection, ::Mongo::Collection
         assert_kind_of 'query', query, DataMapper::Query
-        @collection, @query, @statements = collection, query, {}
+        @collection, @query, @statements, @conditions = collection, query, {}, Conditions.new
       end
 
       def read
@@ -17,78 +17,78 @@ module DataMapper
 
         conditions_statement(@query.conditions)
 
-        @collection.find(@statements, options).to_a
+        @statements.merge!(@conditions.to_statement) unless @conditions.empty?
+
+        @conditions.filter_collection!(@collection.find(@statements, options).to_a)
       end
 
       private
-        def conditions_statement(conditions, affirmative = true)
-          case conditions
-            when AbstractOperation  then operation_statement(conditions, affirmative)
-            when AbstractComparison then comparison_statement(conditions, affirmative)
-          end
+      
+      def conditions_statement(conditions, affirmative = true)
+        case conditions
+        when AbstractOperation  then operation_statement(conditions, affirmative)
+        when AbstractComparison then comparison_statement(conditions, affirmative)
         end
+      end
 
-        def operation_statement(operation, affirmative = true)
-          case operation
-            when NotOperation then conditions_statement(operation.first, !affirmative)
-            when AndOperation then operation.each{|op| conditions_statement(op, affirmative)}
-            when OrOperation  then raise NotImplementedError
-          end
+      def operation_statement(operation, affirmative = true)
+        case operation
+        when NotOperation then conditions_statement(operation.first, !affirmative)
+        when AndOperation then operation.each{|op| conditions_statement(op, affirmative)}
+        when OrOperation  then operation.each{|op| @conditions.add(op, affirmative)}
         end
+      end
 
-        #--
-        # TODO: Rather than raise an error do what we can in a $where operation or in memory.
-        def comparison_statement(comparison, affirmative = true)
-          if comparison.relationship?
-            return conditions_statement(comparison.foreign_key_mapping, affirmative)
-          end
-
-          field = comparison.subject.field
-          value = comparison.value
-
-          operator = if affirmative
-            case comparison
-              when EqualToComparison              then value
-              when GreaterThanComparison          then {'$gt'  =&gt; value}
-              when LessThanComparison             then {'$lt'  =&gt; value}
-              when GreaterThanOrEqualToComparison then {'$gte' =&gt; value}
-              when LessThanOrEqualToComparison    then {'$lte' =&gt; value}
-              when InclusionComparison            then value.kind_of?(Range) ? range_comparison(field, value) : {'$in'  =&gt; value}
-              when RegexpComparison               then value
-              when LikeComparison                 then like_comparison_regexp(value)
-              else raise NotImplementedError
-            end
-          else
-            case comparison
-              when EqualToComparison              then {'$ne'  =&gt; value}
-              when InclusionComparison            then value.kind_of?(Range) ? range_comparison(field, value, false) : {'$nin' =&gt; value}
-              else raise NotImplementedError
-            end
-          end
+      def comparison_statement(comparison, affirmative = true)
+        if comparison.relationship?
+          return conditions_statement(comparison.foreign_key_mapping, affirmative)
+        end
 
-          statement = operator.is_a?(Hash) &amp;&amp; operator.has_key?('$where') ? operator : {field.to_sym =&gt; operator}
+        field = comparison.subject.field
+        value = comparison.value
 
-          @statements.update(statement)
+        # these comparisons should be handled by the conditions object, because:
+        #
+        # * $nin with range requires $where clause
+        # * negated regexp comparison is currently not supported by mongo, see: http://jira.mongodb.org/browse/SERVER-251
+       if (comparison.kind_of?(InclusionComparison) &amp;&amp; value.kind_of?(Range) &amp;&amp; !affirmative) ||
+          (comparison.kind_of?(RegexpComparison) &amp;&amp; !affirmative)
+          @conditions.add(comparison, affirmative)
+          return
         end
 
-        def sort_statement(conditions)
-          conditions.inject([]) do |sort_arr, condition|
-           sort_arr &lt;&lt; [condition.target.field, condition.operator == :asc ? 'ascending' : 'descending']
+        operator = if affirmative
+          case comparison
+            when EqualToComparison              then value
+            when GreaterThanComparison          then {'$gt'  =&gt; value}
+            when LessThanComparison             then {'$lt'  =&gt; value}
+            when GreaterThanOrEqualToComparison then {'$gte' =&gt; value}
+            when LessThanOrEqualToComparison    then {'$lte' =&gt; value}
+            when InclusionComparison            then value.kind_of?(Range) ?
+              {'$gte' =&gt; value.first, value.exclude_end? ? '$lt' : '$lte' =&gt; value.last}  : {'$in'  =&gt; value}
+            when RegexpComparison               then value
+            when LikeComparison                 then comparison.send(:expected_value)
+          else
+            raise NotImplementedError
+          end
+        else
+          case comparison
+            when EqualToComparison              then {'$ne'  =&gt; value}
+            when InclusionComparison            then {'$nin' =&gt; value}
+          else
+            raise NotImplementedError
           end
         end
 
-        def like_comparison_regexp(value)
-          # TODO: %% isn't supported. It isn't in LikeComparison's matches? fyi.
-          Regexp.new(value.to_s.gsub(/^([^%])/, '^\\1').gsub(/([^%])$/, '\\1$').gsub(/%/, '.*').gsub('_', '.'))
-        end
+        operator.is_a?(Hash) ?
+          (@statements[field.to_sym] ||= {}).merge!(operator) : @statements[field.to_sym] = operator
+      end
 
-        def range_comparison(field, range, affirmative=true)
-          if affirmative
-            {'$gte' =&gt; range.first, range.exclude_end? ? '$lt' : '$lte' =&gt; range.last}
-          else
-            {'$where' =&gt; &quot;this.#{field} &lt; #{range.first} || this.#{field} #{range.exclude_end? ? '&gt;=' : '&gt;'} #{range.last}&quot;}
-          end
+      def sort_statement(conditions)
+        conditions.inject([]) do |sort_arr, condition|
+          sort_arr &lt;&lt; [condition.target.field, condition.operator == :asc ? 'ascending' : 'descending']
         end
+      end
     end # Query
   end # Mongo
 end # DataMapper</diff>
      <filename>lib/dm-mongo-adapter/query.rb</filename>
    </modified>
    <modified>
      <diff>@@ -23,6 +23,21 @@ describe DataMapper::Adapters::MongoAdapter do
 
   it_should_behave_like 'An Adapter'
 
+  describe &quot;queries&quot; do
+    before :all do
+      @red   = Heffalump.create(:color =&gt; 'red', :num_spots =&gt; 2)
+      @green = Heffalump.create(:color =&gt; 'green', :num_spots =&gt; 3)
+      @blue  = Heffalump.create(:color =&gt; 'blue', :num_spots =&gt; 5)
+    end
+
+    it &quot;should be able to search for objects matching conditions for the same property&quot; do
+      col = Heffalump.all(:num_spots.gt =&gt; 2, :num_spots.not =&gt; 3)
+
+      col.size.should == 1
+      col.first.should eql(@blue)
+    end
+  end
+
   describe &quot;embedded objects as properties&quot; do
     before :all do
       class Zoo</diff>
      <filename>spec/adapter_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>565c48efd0af8dff66d1f18bd750b90251517eb1</id>
    </parent>
  </parents>
  <author>
    <name>Piotr Solnica</name>
    <email>piotr@zenbe.com</email>
  </author>
  <url>http://github.com/solnic/dm-mongo-adapter/commit/0bf728d48b99e7c0256415c2f9b368eaf7680923</url>
  <id>0bf728d48b99e7c0256415c2f9b368eaf7680923</id>
  <committed-date>2009-11-07T06:37:20-08:00</committed-date>
  <authored-date>2009-11-07T06:37:20-08:00</authored-date>
  <message>Added Conditions object which can construct $where clause required for OR
statements, negated range (:things.not =&gt; 1..2) and negated regexp comparisons
(:field.not =&gt; /blak/)

In the worst case fetched collection is filtered out using Comparison objects
that don't have a corresponding mongodb query syntax (like mentioned negated
regexp comparison)

This change makes the adapter to pass shared adapter specs from dm-core, w00t!</message>
  <tree>d37733947cd939b3bd02612f13f72815f15be01b</tree>
  <committer>
    <name>Piotr Solnica</name>
    <email>piotr@zenbe.com</email>
  </committer>
</commit>
