add new code type rather than doing hacks based on field name. use code_w_scope instead of code
This commit is contained in:
parent
d3594fe8b5
commit
0f546eb5c5
|
@ -16,6 +16,7 @@
|
|||
|
||||
require 'mongo/collection'
|
||||
require 'mongo/message'
|
||||
require 'mongo/types/code'
|
||||
|
||||
module XGen
|
||||
module Mongo
|
||||
|
@ -70,14 +71,16 @@ module XGen
|
|||
self.fields = return_fields
|
||||
end
|
||||
|
||||
# Set query selector hash. If sel is a string, it will be used as a
|
||||
# Set query selector hash. If sel is Code/string, it will be used as a
|
||||
# $where clause. (See Mongo docs for details.)
|
||||
def selector=(sel)
|
||||
@selector = case sel
|
||||
when nil
|
||||
{}
|
||||
when String
|
||||
when Code
|
||||
{"$where" => sel}
|
||||
when String
|
||||
{"$where" => Code.new(sel)}
|
||||
when Hash
|
||||
sel
|
||||
end
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
# --
|
||||
# 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 XGen
|
||||
module Mongo
|
||||
module Driver
|
||||
|
||||
# JavaScript code to be evaluated by MongoDB
|
||||
class Code < String
|
||||
# Hash mapping identifiers to their values
|
||||
attr_accessor :scope
|
||||
|
||||
def initialize(code, scope={})
|
||||
super(code)
|
||||
@scope = scope
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -95,9 +95,9 @@ class BSON
|
|||
end
|
||||
|
||||
def serialize_key_value(k, v)
|
||||
type = bson_type(v, k)
|
||||
type = bson_type(v)
|
||||
case type
|
||||
when STRING, CODE, SYMBOL
|
||||
when STRING, SYMBOL
|
||||
serialize_string_element(@buf, k, v, type)
|
||||
when NUMBER, NUMBER_INT
|
||||
serialize_number_element(@buf, k, v, type)
|
||||
|
@ -122,8 +122,7 @@ class BSON
|
|||
when UNDEFINED
|
||||
serialize_undefined_element(@buf, k)
|
||||
when CODE_W_SCOPE
|
||||
# TODO CODE_W_SCOPE unimplemented; may be removed
|
||||
raise "unimplemented type #{type}"
|
||||
serialize_code_w_scope(@buf, k, v)
|
||||
else
|
||||
raise "unhandled type #{type}"
|
||||
end
|
||||
|
@ -198,8 +197,8 @@ class BSON
|
|||
key = deserialize_cstr(@buf)
|
||||
doc[key] = deserialize_binary_data(@buf)
|
||||
when CODE_W_SCOPE
|
||||
# TODO CODE_W_SCOPE unimplemented; may be removed
|
||||
raise "unimplemented type #{type}"
|
||||
key = deserialize_cstr(@buf)
|
||||
doc[key] = deserialize_code_w_scope_data(@buf)
|
||||
when EOO
|
||||
break
|
||||
else
|
||||
|
@ -280,6 +279,24 @@ class BSON
|
|||
str
|
||||
end
|
||||
|
||||
def deserialize_code_w_scope_data(buf)
|
||||
buf.get_int
|
||||
len = buf.get_int
|
||||
code = buf.get(len)[0..-2]
|
||||
if code.respond_to? "pack"
|
||||
code = code.pack("C*")
|
||||
end
|
||||
if RUBY_VERSION >= '1.9'
|
||||
code.force_encoding("utf-8")
|
||||
end
|
||||
|
||||
scope_size = buf.get_int
|
||||
buf.position -= 4
|
||||
scope = BSON.new().deserialize(buf.get(scope_size))
|
||||
|
||||
Code.new(code, scope)
|
||||
end
|
||||
|
||||
def deserialize_oid_data(buf)
|
||||
ObjectID.new(buf.get(12))
|
||||
end
|
||||
|
@ -416,6 +433,23 @@ class BSON
|
|||
buf.position = end_pos
|
||||
end
|
||||
|
||||
def serialize_code_w_scope(buf, key, val)
|
||||
buf.put(CODE_W_SCOPE)
|
||||
self.class.serialize_cstr(buf, key)
|
||||
|
||||
# Make a hole for the length
|
||||
len_pos = buf.position
|
||||
buf.put_int(0)
|
||||
|
||||
buf.put_int(val.length + 1)
|
||||
self.class.serialize_cstr(buf, val)
|
||||
buf.put_array(BSON.new.serialize(val.scope).to_a)
|
||||
|
||||
end_pos = buf.position
|
||||
buf.put_int(end_pos - len_pos, len_pos)
|
||||
buf.position = end_pos
|
||||
end
|
||||
|
||||
def deserialize_cstr(buf)
|
||||
chars = ""
|
||||
while true
|
||||
|
@ -429,7 +463,7 @@ class BSON
|
|||
chars
|
||||
end
|
||||
|
||||
def bson_type(o, key)
|
||||
def bson_type(o)
|
||||
case o
|
||||
when nil
|
||||
NULL
|
||||
|
@ -439,9 +473,10 @@ class BSON
|
|||
NUMBER
|
||||
when ByteBuffer
|
||||
BINARY
|
||||
when Code
|
||||
CODE_W_SCOPE
|
||||
when String
|
||||
# magic awful stuff - the DB requires that a where clause is sent as CODE
|
||||
key == "$where" ? CODE : STRING
|
||||
STRING
|
||||
when Array
|
||||
ARRAY
|
||||
when Regexp
|
||||
|
|
|
@ -42,8 +42,10 @@ class XMLToRuby
|
|||
e.text.to_i
|
||||
when 'number'
|
||||
e.text.to_f
|
||||
when 'string', 'code'
|
||||
when 'string'
|
||||
e.text.to_s
|
||||
when 'code'
|
||||
Code.new (e.text.to_s)
|
||||
when 'binary'
|
||||
bin = Binary.new
|
||||
decoded = Base64.decode64(e.text.to_s)
|
||||
|
|
|
@ -21,7 +21,7 @@ class BSONTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_code
|
||||
doc = {'$where' => 'this.a.b < this.b'}
|
||||
doc = {'$where' => Code.new('this.a.b < this.b')}
|
||||
@b.serialize(doc)
|
||||
assert_equal doc, @b.deserialize
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue