mongodb-mongo 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/README.rdoc +216 -0
  2. data/Rakefile +54 -0
  3. data/bin/mongo_console +21 -0
  4. data/bin/validate +51 -0
  5. data/examples/benchmarks.rb +38 -0
  6. data/examples/blog.rb +76 -0
  7. data/examples/index_test.rb +128 -0
  8. data/examples/simple.rb +17 -0
  9. data/lib/mongo/admin.rb +86 -0
  10. data/lib/mongo/collection.rb +161 -0
  11. data/lib/mongo/cursor.rb +230 -0
  12. data/lib/mongo/db.rb +399 -0
  13. data/lib/mongo/message/get_more_message.rb +21 -0
  14. data/lib/mongo/message/insert_message.rb +19 -0
  15. data/lib/mongo/message/kill_cursors_message.rb +20 -0
  16. data/lib/mongo/message/message.rb +68 -0
  17. data/lib/mongo/message/message_header.rb +34 -0
  18. data/lib/mongo/message/msg_message.rb +17 -0
  19. data/lib/mongo/message/opcodes.rb +16 -0
  20. data/lib/mongo/message/query_message.rb +67 -0
  21. data/lib/mongo/message/remove_message.rb +20 -0
  22. data/lib/mongo/message/update_message.rb +21 -0
  23. data/lib/mongo/message.rb +4 -0
  24. data/lib/mongo/mongo.rb +98 -0
  25. data/lib/mongo/query.rb +110 -0
  26. data/lib/mongo/types/binary.rb +34 -0
  27. data/lib/mongo/types/dbref.rb +37 -0
  28. data/lib/mongo/types/objectid.rb +137 -0
  29. data/lib/mongo/types/regexp_of_holding.rb +44 -0
  30. data/lib/mongo/types/undefined.rb +31 -0
  31. data/lib/mongo/util/bson.rb +431 -0
  32. data/lib/mongo/util/byte_buffer.rb +163 -0
  33. data/lib/mongo/util/ordered_hash.rb +68 -0
  34. data/lib/mongo/util/xml_to_ruby.rb +102 -0
  35. data/lib/mongo.rb +12 -0
  36. data/mongo-ruby-driver.gemspec +62 -0
  37. data/tests/test_admin.rb +60 -0
  38. data/tests/test_bson.rb +135 -0
  39. data/tests/test_byte_buffer.rb +69 -0
  40. data/tests/test_cursor.rb +66 -0
  41. data/tests/test_db.rb +85 -0
  42. data/tests/test_db_api.rb +354 -0
  43. data/tests/test_db_connection.rb +17 -0
  44. data/tests/test_message.rb +35 -0
  45. data/tests/test_objectid.rb +98 -0
  46. data/tests/test_ordered_hash.rb +85 -0
  47. data/tests/test_round_trip.rb +116 -0
  48. metadata +100 -0
@@ -0,0 +1,21 @@
1
+ require 'mongo/message/message'
2
+ require 'mongo/message/opcodes'
3
+
4
+ module XGen
5
+ module Mongo
6
+ module Driver
7
+
8
+ class UpdateMessage < Message
9
+
10
+ def initialize(db_name, collection_name, sel, obj, repsert)
11
+ super(OP_UPDATE)
12
+ write_int(0)
13
+ write_string("#{db_name}.#{collection_name}")
14
+ write_int(repsert ? 1 : 0) # 1 if a repsert operation (upsert)
15
+ write_doc(sel)
16
+ write_doc(obj)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,4 @@
1
+ %w(get_more_message insert_message kill_cursors_message message_header
2
+ msg_message query_message remove_message update_message).each { |f|
3
+ require "mongo/message/#{f}"
4
+ }
@@ -0,0 +1,98 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ require 'mongo/db'
18
+
19
+ module XGen
20
+ module Mongo
21
+ module Driver
22
+
23
+ # Represents a Mongo database server.
24
+ class Mongo
25
+
26
+ DEFAULT_PORT = 27017
27
+
28
+ # Either nodes_or_host is a host name string and port is an optional
29
+ # port number that defaults to DEFAULT_PORT, or nodes_or_host is an
30
+ # array of arrays, where each is a host/port pair (or a host with no
31
+ # port). Finally, if nodes_or_host is nil then host is 'localhost' and
32
+ # port is DEFAULT_PORT. Since that's so confusing, here are a few
33
+ # examples:
34
+ #
35
+ # Mongo.new # localhost, DEFAULT_PORT
36
+ # Mongo.new("localhost") # localhost, DEFAULT_PORT
37
+ # Mongo.new("localhost", 3000) # localhost, 3000
38
+ # Mongo.new([["localhost"]]) # localhost, DEFAULT_PORT
39
+ # Mongo.new([["localhost", 3000]]) # localhost, 3000
40
+ # Mongo.new([["db1.example.com", 3000], ["db2.example.com", 3000]]])
41
+ #
42
+ # When a DB object first connects, it tries nodes and stops at the
43
+ # first one it connects to.
44
+ def initialize(nodes_or_host=nil, port=nil)
45
+ @nodes = case nodes_or_host
46
+ when String
47
+ [[nodes_or_host, port || DEFAULT_PORT]]
48
+ when Array
49
+ nodes_or_host.collect { |nh| [nh[0], nh[1] || DEFAULT_PORT] }
50
+ when nil
51
+ [['localhost', DEFAULT_PORT]]
52
+ end
53
+ end
54
+
55
+ # Return the XGen::Mongo::Driver::DB named +db_name+. See DB#new for
56
+ # +options+.
57
+ def db(db_name, options={})
58
+ XGen::Mongo::Driver::DB.new(db_name, @nodes, options)
59
+ end
60
+
61
+ # Returns a hash containing database names as keys and disk space for
62
+ # each as values.
63
+ def database_info
64
+ admin_db = nil
65
+ begin
66
+ admin_db = db('admin')
67
+ doc = admin_db.db_command(:listDatabases => 1)
68
+ raise "error retrieving database info" unless admin_db.ok?(doc)
69
+ h = {}
70
+ doc['databases'].each { |db|
71
+ h[db['name']] = db['sizeOnDisk'].to_i
72
+ }
73
+ h
74
+ ensure
75
+ admin_db.close
76
+ end
77
+ end
78
+
79
+ # Returns an array of database names.
80
+ def database_names
81
+ database_info.keys
82
+ end
83
+
84
+ # Not implemented.
85
+ def clone_database(from)
86
+ raise "not implemented"
87
+ end
88
+
89
+ # Not implemented.
90
+ def copy_database(from_host, from_db, to_db)
91
+ raise "not implemented"
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+ end
98
+
@@ -0,0 +1,110 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ require 'mongo/collection'
18
+ require 'mongo/message'
19
+
20
+ module XGen
21
+ module Mongo
22
+ module Driver
23
+
24
+ # A query against a collection. A query's selector is a hash. See the
25
+ # Mongo documentation for query details.
26
+ class Query
27
+
28
+ attr_accessor :number_to_skip, :number_to_return, :order_by
29
+ # If true, $explain will be set in QueryMessage that uses this query.
30
+ attr_accessor :explain
31
+ # Either +nil+ or an array of hint field names.
32
+ attr_accessor :hint_fields
33
+ attr_reader :selector # writer defined below
34
+
35
+ # sel :: A hash describing the query. See the Mongo docs for details.
36
+ #
37
+ # return_fields :: If not +nil+, a single field name or an array of
38
+ # field names. Only those fields will be returned.
39
+ # (Called :fields in calls to Collection#find.)
40
+ #
41
+ # number_to_skip :: Number of records to skip before returning
42
+ # records. (Called :offset in calls to
43
+ # Collection#find.) Default is 0.
44
+ #
45
+ # number_to_return :: Max number of records to return. (Called :limit
46
+ # in calls to Collection#find.) Default is 0 (all
47
+ # records).
48
+ #
49
+ # order_by :: If not +nil+, specifies record sort order. May be a
50
+ # String, Hash, OrderedHash, or Array. If a string, the
51
+ # results will be ordered by that field in ascending
52
+ # order. If an array, it should be an array of field names
53
+ # which will all be sorted in ascending order. If a hash,
54
+ # it may be either a regular Hash or an OrderedHash. The
55
+ # keys should be field names, and the values should be 1
56
+ # (ascending) or -1 (descending). Note that if it is a
57
+ # regular Hash then sorting by more than one field
58
+ # probably will not be what you intend because key order
59
+ # is not preserved. (order_by is called :sort in calls to
60
+ # Collection#find.)
61
+ def initialize(sel={}, return_fields=nil, number_to_skip=0, number_to_return=0, order_by=nil)
62
+ @number_to_skip, @number_to_return, @order_by = number_to_skip, number_to_return, order_by
63
+ self.selector = sel
64
+ self.fields = return_fields
65
+ end
66
+
67
+ # Set query selector hash. If sel is a string, it will be used as a
68
+ # $where clause. (See Mongo docs for details.)
69
+ def selector=(sel)
70
+ @selector = case sel
71
+ when nil
72
+ {}
73
+ when String
74
+ {"$where" => sel}
75
+ when Hash
76
+ sel
77
+ end
78
+ end
79
+
80
+ # Set fields to return. If +val+ is +nil+ or empty, all fields will be
81
+ # returned.
82
+ def fields=(val)
83
+ @fields = val
84
+ @fields = nil if @fields && @fields.empty?
85
+ end
86
+
87
+ def fields
88
+ case @fields
89
+ when String
90
+ {@fields => 1}
91
+ when Array
92
+ if @fields.length == 0
93
+ nil
94
+ else
95
+ h = {}
96
+ @fields.each { |field| h[field] = 1 }
97
+ h
98
+ end
99
+ else # nil, anything else
100
+ nil
101
+ end
102
+ end
103
+
104
+ def contains_special_fields
105
+ (@order_by != nil && @order_by.length > 0) || @explain || @hint_fields
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,34 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ module XGen
18
+ module Mongo
19
+ module Driver
20
+
21
+ # An array of binary bytes. The only reason this exists is so that the
22
+ # BSON encoder will know to output the Mongo BINARY type.
23
+ class Binary < String; end
24
+
25
+ end
26
+ end
27
+ end
28
+
29
+ class String
30
+ # Convert a string into a XGen::Mongo::Driver::Binary
31
+ def to_mongo_binary
32
+ XGen::Mongo::Driver::Binary.new(self)
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ module XGen
18
+ module Mongo
19
+ module Driver
20
+
21
+ class DBRef
22
+
23
+ attr_reader :parent, :field_name, :db, :namespace, :object_id
24
+
25
+ def initialize(parent, field_name, db, namespace, object_id)
26
+ @parent, @field_name, @db, @namespace, @object_id =
27
+ parent, field_name, db, namespace, object_id
28
+ end
29
+
30
+ def to_s
31
+ "ns: #{namespace}, id: #{object_id}"
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,137 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ require 'mutex_m'
18
+ require 'mongo/util/byte_buffer'
19
+
20
+ module XGen
21
+ module Mongo
22
+ module Driver
23
+
24
+ # Implementation of the Babble OID. Object ids are not required by
25
+ # Mongo, but they make certain operations more efficient.
26
+ #
27
+ # The driver does not automatically assign ids to records that are
28
+ # inserted. (An upcoming feature will allow you to give an id "factory"
29
+ # to a database and/or a collection.)
30
+ #
31
+ # 12 bytes
32
+ # ---
33
+ # 0 time
34
+ # 1
35
+ # 2
36
+ # 3
37
+ # 4 machine
38
+ # 5
39
+ # 6
40
+ # 7 pid
41
+ # 8
42
+ # 9 inc
43
+ # 10
44
+ # 11
45
+ class ObjectID
46
+
47
+ MACHINE = ( val = rand(0x1000000); [val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff] )
48
+ PID = ( val = rand(0x10000); [val & 0xff, (val >> 8) & 0xff]; )
49
+
50
+ # The string representation of an OID is different than its internal
51
+ # and BSON byte representations. The BYTE_ORDER here maps
52
+ # internal/BSON byte position (the index in BYTE_ORDER) to the
53
+ # position of the two hex characters representing that byte in the
54
+ # string representation. For example, the 0th BSON byte corresponds to
55
+ # the (0-based) 7th pair of hex chars in the string.
56
+ BYTE_ORDER = [7, 6, 5, 4, 3, 2, 1, 0, 11, 10, 9, 8]
57
+
58
+ LOCK = Object.new
59
+ LOCK.extend Mutex_m
60
+
61
+ @@index_time = Time.new.to_i
62
+ @@index = 0
63
+
64
+ # Given a string representation of an ObjectID, return a new ObjectID
65
+ # with that value.
66
+ def self.from_string(str)
67
+ raise "illegal ObjectID format" unless legal_oid_string(str)
68
+ data = []
69
+ BYTE_ORDER.each_with_index { |string_position, data_index|
70
+ data[data_index] = str[string_position * 2, 2].to_i(16)
71
+ }
72
+ self.new(data)
73
+ end
74
+
75
+ def self.legal_oid_string(str)
76
+ len = BYTE_ORDER.length * 2
77
+ str =~ /([0-9a-f]+)/i
78
+ match = $1
79
+ str && str.length == len && match == str
80
+ end
81
+
82
+ # +data+ is an array of bytes. If nil, a new id will be generated.
83
+ # The time +t+ is only used for testing; leave it nil.
84
+ def initialize(data=nil, t=nil)
85
+ @data = data || generate_id(t)
86
+ end
87
+
88
+ def eql?(other)
89
+ @data == other.to_a
90
+ end
91
+ alias_method :==, :eql?
92
+
93
+ def to_a
94
+ @data.dup
95
+ end
96
+
97
+ def to_s
98
+ str = ' ' * 24
99
+ BYTE_ORDER.each_with_index { |string_position, data_index|
100
+ str[string_position * 2, 2] = '%02x' % @data[data_index]
101
+ }
102
+ str
103
+ end
104
+
105
+ # (Would normally be private, but isn't so we can test it.)
106
+ def generate_id(t=nil)
107
+ t ||= Time.new.to_i
108
+ buf = ByteBuffer.new
109
+ buf.put_int(t & 0xffffffff)
110
+ buf.put_array(MACHINE)
111
+ buf.put_array(PID)
112
+ i = index_for_time(t)
113
+ buf.put(i & 0xff)
114
+ buf.put((i >> 8) & 0xff)
115
+ buf.put((i >> 16) & 0xff)
116
+
117
+ buf.rewind
118
+ buf.to_a.dup
119
+ end
120
+
121
+ # (Would normally be private, but isn't so we can test it.)
122
+ def index_for_time(t)
123
+ LOCK.mu_synchronize {
124
+ if t != @@index_time
125
+ @@index = 0
126
+ @@index_time = t
127
+ end
128
+ retval = @@index
129
+ @@index += 1
130
+ retval
131
+ }
132
+ end
133
+
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,44 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ module XGen
18
+ module Mongo
19
+ module Driver
20
+
21
+ # A Regexp that can hold on to extra options and ignore them. Mongo
22
+ # regexes may contain option characters beyond 'i', 'm', and 'x'. (Note
23
+ # that Mongo only uses those three, but that regexes coming from other
24
+ # languages may store different option characters.)
25
+ #
26
+ # Note that you do not have to use this class at all if you wish to
27
+ # store regular expressions in Mongo. The Mongo and Ruby regex option
28
+ # flags are the same. Storing regexes is discouraged, in any case.
29
+ class RegexpOfHolding < Regexp
30
+
31
+ attr_accessor :extra_options_str
32
+
33
+ # +str+ and +options+ are the same as Regexp. +extra_options_str+
34
+ # contains all the other flags that were in Mongo but we do not use or
35
+ # understand.
36
+ def initialize(str, options, extra_options_str)
37
+ super(str, options)
38
+ @extra_options_str = extra_options_str
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,31 @@
1
+ # --
2
+ # Copyright (C) 2008-2009 10gen Inc.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify it
5
+ # under the terms of the GNU Affero General Public License, version 3, as
6
+ # published by the Free Software Foundation.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
11
+ # for more details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ # ++
16
+
17
+ module XGen
18
+ module Mongo
19
+ module Driver
20
+
21
+ # A special "undefined" type to match Mongo's storage of UNKNOWN values.
22
+ # "UNKNOWN" comes from JavaScript.
23
+ #
24
+ # NOTE: this class does not attempt to provide ANY of the semantics an
25
+ # "unknown" object might need. It isn't nil, it isn't special in any
26
+ # way, and there isn't any singleton value.
27
+ class Undefined < Object; end
28
+
29
+ end
30
+ end
31
+ end