mongodb-mongo 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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