diff --git a/lib/mongo.rb b/lib/mongo.rb index c51e3ad..082fb42 100644 --- a/lib/mongo.rb +++ b/lib/mongo.rb @@ -1,8 +1,10 @@ -require 'mongo/mongo' require 'mongo/objectid' require 'mongo/dbref' require 'mongo/binary' +require 'mongo/regexp_of_holding' require 'mongo/undefined' + +require 'mongo/mongo' require 'mongo/message' require 'mongo/db' require 'mongo/cursor' diff --git a/lib/mongo/regexp_of_holding.rb b/lib/mongo/regexp_of_holding.rb new file mode 100644 index 0000000..94de008 --- /dev/null +++ b/lib/mongo/regexp_of_holding.rb @@ -0,0 +1,40 @@ +# -- +# Copyright (C) 2008-2009 10gen Inc. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Affero General Public License, version 3, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License +# for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# ++ + +module XGen + module Mongo + module Driver + + # A Regexp that can hold on to extra options and ignore them. Mongo + # regexes may contain option characters beyond 'i', 'm', and 'x'. (Note + # that Mongo only uses those three, but that regexes coming from other + # languages may store different option characters.) + class RegexpOfHolding < Regexp + + attr_accessor :extra_options_str + + # +str+ and +options+ are the same as Regexp. +extra_options_str+ + # contains all the other flags that were in Mongo but we do not use or + # understand. + def initialize(str, options, extra_options_str) + super(str, options) + @extra_options_str = extra_options_str + end + end + + end + end +end diff --git a/lib/mongo/util/bson.rb b/lib/mongo/util/bson.rb index 615a37b..8439e47 100644 --- a/lib/mongo/util/bson.rb +++ b/lib/mongo/util/bson.rb @@ -221,7 +221,8 @@ class BSON options |= Regexp::IGNORECASE if options_str.include?('i') options |= Regexp::MULTILINE if options_str.include?('m') options |= Regexp::EXTENDED if options_str.include?('x') - Regexp.new(str, options) + options_str.gsub!(/[imx]/, '') # Now remove the three we understand + XGen::Mongo::Driver::RegexpOfHolding.new(str, options, options_str) end def deserialize_string_data(buf) @@ -342,7 +343,9 @@ class BSON options_str << 'i' if ((options & Regexp::IGNORECASE) != 0) options_str << 'm' if ((options & Regexp::MULTILINE) != 0) options_str << 'x' if ((options & Regexp::EXTENDED) != 0) - self.class.serialize_cstr(buf, options_str) + options_str << val.extra_options_str if val.respond_to?(:extra_options_str) + # Must store option chars in alphabetical order + self.class.serialize_cstr(buf, options_str.split(//).sort.uniq.join) end def serialize_oid_element(buf, key, val) diff --git a/tests/test_bson.rb b/tests/test_bson.rb index b561157..c05852a 100644 --- a/tests/test_bson.rb +++ b/tests/test_bson.rb @@ -59,7 +59,26 @@ class BSONTest < Test::Unit::TestCase def test_regex doc = {'doc' => /foobar/i} @b.serialize(doc) - assert_equal doc, @b.deserialize + doc2 = @b.deserialize + assert_equal doc, doc2 + + r = doc2['doc'] + assert_kind_of XGen::Mongo::Driver::RegexpOfHolding, r + assert_equal '', r.extra_options_str + + r.extra_options_str << 'zywcab' + assert_equal 'zywcab', r.extra_options_str + + b = BSON.new + doc = {'doc' => r} + b.serialize(doc) + doc2 = nil + doc2 = b.deserialize + assert_equal doc, doc2 + + r = doc2['doc'] + assert_kind_of XGen::Mongo::Driver::RegexpOfHolding, r + assert_equal 'abcwyz', r.extra_options_str # must be sorted end def test_boolean