support BSON MinKey and MaxKey RUBY-84

This commit is contained in:
Kyle Banker 2010-01-20 18:50:07 -05:00
parent 80afca2fe2
commit bf7ffcfa82
6 changed files with 109 additions and 6 deletions

View File

@ -60,6 +60,8 @@ static VALUE Time;
static VALUE ObjectID;
static VALUE DBRef;
static VALUE Code;
static VALUE MinKey;
static VALUE MaxKey;
static VALUE RegexpOfHolding;
static VALUE OrderedHash;
static VALUE InvalidName;
@ -369,9 +371,18 @@ static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow
SAFE_WRITE_AT_POS(buffer, length_location, (const char*)&obj_length, 4);
break;
}
if (strcmp(cls, "Mongo::MaxKey") == 0) {
write_name_and_type(buffer, key, 0x7f);
break;
}
if (strcmp(cls, "Mongo::MinKey") == 0) {
write_name_and_type(buffer, key, 0xff);
break;
}
if (strcmp(cls, "DateTime") == 0 || strcmp(cls, "Date") == 0 || strcmp(cls, "ActiveSupport::TimeWithZone") == 0) {
buffer_free(buffer);
rb_raise(InvalidDocument, "Trying to serialize and instance of Date, DateTime, or TimeWithZone; the MongoDB Ruby driver currently supports Time objects only.",
rb_raise(InvalidDocument,
"Trying to serialize and instance of Date, DateTime, or TimeWithZone; the MongoDB Ruby driver currently supports Time objects only.",
TYPE(value));
}
buffer_free(buffer);
@ -506,6 +517,11 @@ static VALUE method_serialize(VALUE self, VALUE doc, VALUE check_keys) {
static VALUE get_value(const char* buffer, int* position, int type) {
VALUE value;
switch (type) {
case -1:
{
value = rb_class_new_instance(0, NULL, MinKey);
break;
}
case 1:
{
double d;
@ -727,6 +743,11 @@ static VALUE get_value(const char* buffer, int* position, int type) {
*position += 8;
break;
}
case 127:
{
value = rb_class_new_instance(0, NULL, MaxKey);
break;
}
default:
{
rb_raise(rb_eTypeError, "no c decoder for this type yet (%d)", type);
@ -825,6 +846,9 @@ void Init_cbson() {
DBRef = rb_const_get(mongo, rb_intern("DBRef"));
rb_require("mongo/types/code");
Code = rb_const_get(mongo, rb_intern("Code"));
rb_require("mongo/types/min_max_keys");
MinKey = rb_const_get(mongo, rb_intern("MinKey"));
MaxKey = rb_const_get(mongo, rb_intern("MaxKey"));
rb_require("mongo/types/regexp_of_holding");
RegexpOfHolding = rb_const_get(mongo, rb_intern("RegexpOfHolding"));
rb_require("mongo/exceptions");

View File

@ -45,6 +45,7 @@ require 'mongo/types/code'
require 'mongo/types/dbref'
require 'mongo/types/objectid'
require 'mongo/types/regexp_of_holding'
require 'mongo/types/min_max_keys'
require 'mongo/util/support'
require 'mongo/util/conversions'

View File

@ -0,0 +1,31 @@
# --
# Copyright (C) 2008-2009 10gen Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ++
module Mongo
class MaxKey
def ==(obj)
obj.class == MaxKey
end
end
class MinKey
def ==(obj)
obj.class == MinKey
end
end
end

View File

@ -163,6 +163,10 @@ class BSON_RUBY
serialize_null_element(@buf, k)
when CODE_W_SCOPE
serialize_code_w_scope(@buf, k, v)
when MAXKEY
serialize_max_key_element(@buf, k)
when MINKEY
serialize_min_key_element(@buf, k)
else
raise "unhandled type #{type}"
end
@ -234,6 +238,12 @@ class BSON_RUBY
key = deserialize_cstr(@buf)
doc[key] = [deserialize_number_int_data(@buf),
deserialize_number_int_data(@buf)]
when MAXKEY
key = deserialize_cstr(@buf)
doc[key] = MaxKey.new
when MINKEY, 255 # This is currently easier than unpack the type byte as an unsigned char.
key = deserialize_cstr(@buf)
doc[key] = MinKey.new
when EOO
break
else
@ -466,6 +476,16 @@ class BSON_RUBY
self.class.serialize_cstr(buf, options_str.split(//).sort.uniq.join)
end
def serialize_max_key_element(buf, key)
buf.put(MAXKEY)
self.class.serialize_key(buf, key)
end
def serialize_min_key_element(buf, key)
buf.put(MINKEY)
self.class.serialize_key(buf, key)
end
def serialize_oid_element(buf, key, val)
buf.put(OID)
self.class.serialize_key(buf, key)
@ -553,6 +573,10 @@ class BSON_RUBY
OBJECT
when Symbol
SYMBOL
when MaxKey
MAXKEY
when MinKey
MINKEY
when Date, DateTime
raise InvalidDocument, "Trying to serialize an instance of #{o.class}; " +
"the MongoDB Ruby driver currently supports Time objects only."

View File

@ -356,6 +356,18 @@ class BSONTest < Test::Unit::TestCase
end
end
def test_max_key
doc = {"a" => MaxKey.new}
assert_equal doc, BSON.deserialize(BSON.serialize(doc).to_a)
end
def test_min_key
doc = {"a" => MinKey.new}
assert_equal doc, BSON.deserialize(BSON.serialize(doc).to_a)
end
def test_invalid_object
o = Object.new
assert_raise InvalidDocument do

View File

@ -1,4 +1,5 @@
require 'test/test_helper'
require 'logger'
# NOTE: assumes Mongo is running
class CursorTest < Test::Unit::TestCase
@ -17,11 +18,6 @@ class CursorTest < Test::Unit::TestCase
@@coll_full_name = 'ruby-mongo-test.test'
end
def teardown
@@coll.remove
@@db.error
end
def test_explain
cursor = @@coll.find('a' => 1)
explaination = cursor.explain
@ -112,6 +108,21 @@ class CursorTest < Test::Unit::TestCase
assert_equal 2004, @@coll.find().sort([[:created_at, :desc]]).next_document["created_at"].year
end
def test_sort_min_max_keys
@@coll.remove
@@coll.insert({"n" => 1000000})
@@coll.insert({"n" => -1000000})
@@coll.insert({"n" => MaxKey.new})
@@coll.insert({"n" => MinKey.new})
results = @@coll.find.sort([:n, :asc]).to_a
assert_equal MinKey.new, results[0]['n']
assert_equal -1000000, results[1]['n']
assert_equal 1000000, results[2]['n']
assert_equal MaxKey.new, results[3]['n']
end
def test_limit
@@coll.remove