jmongo 1.1.1 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -36,6 +36,10 @@ def replace_header(head, header_name)
36
36
  head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
37
37
  end
38
38
 
39
+ def jruby?
40
+ RUBY_PLATFORM.to_s == 'java'
41
+ end
42
+
39
43
  #############################################################################
40
44
  #
41
45
  # Custom tasks
@@ -65,7 +69,16 @@ task :release => :build do
65
69
  sh "git tag v#{version}"
66
70
  sh "git push origin master"
67
71
  sh "git push origin v#{version}"
68
- sh "gem push pkg/#{name}-#{version}.gem"
72
+
73
+ command = "gem push pkg/#{name}-#{version}.gem"
74
+
75
+ if jruby?
76
+ puts "--------------------------------------------------------------------------------------"
77
+ puts "can't push to rubygems using jruby at the moment, so switch to mri and run: #{command}"
78
+ puts "--------------------------------------------------------------------------------------"
79
+ else
80
+ sh command
81
+ end
69
82
  end
70
83
 
71
84
  desc "Build #{gem_file} into the pkg directory"
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'jmongo'
3
- s.version = '1.1.1'
4
- s.date = '2011-10-06'
3
+ s.version = '1.1.2'
4
+ s.date = '2011-10-10'
5
5
  s.platform = Gem::Platform::RUBY
6
6
  s.authors = ["Chuck Remes","Guy Boertje", "Lee Henson"]
7
7
  s.email = ["cremes@mac.com", "guyboertje@gmail.com", "lee.m.henson@gmail.com"]
@@ -19,7 +19,7 @@ module Mongo
19
19
  include Mongo::JavaImpl::Collection_
20
20
 
21
21
  attr_reader :j_collection, :j_db
22
- attr_reader :db, :name, :pk_factory, :hint
22
+ attr_reader :db, :name, :pk_factory
23
23
 
24
24
  # Initialize a collection object.
25
25
  #
@@ -57,9 +57,13 @@ module Mongo
57
57
  @name = validate_name(name)
58
58
  @db, @j_db = db, db.j_db
59
59
  @connection = @db.connection
60
- @pk_factory = @opts[:pk] || BSON::ObjectId
60
+ @pk_factory = @opts.delete(:pk)|| BSON::ObjectId
61
61
  @hint = nil
62
- @j_collection = j_collection || @j_db.get_collection(@name)
62
+ @j_collection = j_collection || @j_db.create_collection(@name, to_dbobject(@opts))
63
+ end
64
+
65
+ def safe
66
+ !!@opts.fetch(:safe, false)
63
67
  end
64
68
 
65
69
  # Return a sub-collection of this collection by name. If 'users' is a collection, then
@@ -75,13 +79,13 @@ module Mongo
75
79
  # the specified sub-collection
76
80
  def [](name)
77
81
  new_name = "#{self.name}.#{name}"
78
- validate_name new_name
79
- @db.create_collection(new_name, @opts)
82
+ @db.collection(new_name, @opts)
80
83
  end
81
84
 
82
85
  def capped?
83
- @j_collection.isCapped
86
+ @j_collection.capped?
84
87
  end
88
+
85
89
  # Set a hint field for query optimizer. Hint may be a single field
86
90
  # name, array of field names, or a hash (preferably an [OrderedHash]).
87
91
  # If using MongoDB > 1.1, you probably don't ever need to set a hint.
@@ -89,8 +93,13 @@ module Mongo
89
93
  # @param [String, Array, OrderedHash] hint a single field, an array of
90
94
  # fields, or a hash specifying fields
91
95
  def hint=(hint=nil)
96
+ @hint = prep_hint(hint)
97
+ self
92
98
  end
93
99
 
100
+ def hint
101
+ @hint
102
+ end
94
103
  # Query the database.
95
104
  #
96
105
  # The +selector+ argument is a prototype document that all results must
@@ -152,7 +161,7 @@ module Mongo
152
161
  end
153
162
 
154
163
  if hint
155
- hint = normalize_hint_fields(hint)
164
+ hint = prep_hint(hint)
156
165
  else
157
166
  hint = @hint # assumed to be normalized already
158
167
  end
@@ -239,9 +248,13 @@ module Mongo
239
248
  # @core insert insert-instance_method
240
249
  def insert(doc_or_docs, options={})
241
250
  doc_or_docs = [doc_or_docs] unless doc_or_docs.kind_of?(Array)
242
- doc_or_docs.collect! { |doc| @pk_factory.create_pk(doc) }
251
+ doc_or_docs.collect! do |doc|
252
+ @pk_factory.create_pk(doc)
253
+ prep_id(doc)
254
+ end
255
+ safe = options.fetch(:safe, @opts[:safe])
243
256
  continue = (options[:continue_on_error] || false)
244
- docs = insert_documents(doc_or_docs, options[:safe], continue)
257
+ docs = insert_documents(doc_or_docs, safe, continue)
245
258
  docs.size == 1 ? docs.first['_id'] : docs.collect{|doc| doc['_id']}
246
259
  end
247
260
  alias_method :<<, :insert
@@ -293,7 +306,8 @@ module Mongo
293
306
  # @core update update-instance_method
294
307
  def update(selector, document, options={})
295
308
  upsert, multi = !!(options[:upsert]), !!(options[:multi])
296
- update_documents(selector, document, upsert, multi, options[:safe])
309
+ safe = options.fetch(:safe, @opts[:safe])
310
+ update_documents(selector, document, upsert, multi, safe)
297
311
  end
298
312
 
299
313
  # Create a new index.
@@ -339,10 +353,13 @@ module Mongo
339
353
  #
340
354
  # @core indexes create_index-instance_method
341
355
  def create_index(spec, opts={})
342
- _create_indexes(spec, opts)
356
+ _create_index(spec, opts)
343
357
  end
344
- alias_method :ensure_index, :create_index
345
358
 
359
+ def ensure_index(spec, opts={})
360
+ _ensure_index(spec, opts)
361
+ end
362
+
346
363
  # Drop a specified index.
347
364
  #
348
365
  # @param [String, Array] spec
@@ -583,10 +600,10 @@ module Mongo
583
600
  #
584
601
  # @raise [Mongo::InvalidNSName] if +new_name+ is an invalid collection name.
585
602
  def rename(new_name)
586
- name = validate_name(new_name)
603
+ _name = validate_name(new_name)
587
604
  begin
588
- jcol = @j_collection.rename(name)
589
- @name = name
605
+ jcol = @j_collection.rename(_name)
606
+ @name = _name
590
607
  @j_collection = jcol
591
608
  rescue => ex
592
609
  raise MongoDBError, "Error renaming collection: #{name}, more: #{ex.message}"
@@ -608,7 +625,6 @@ module Mongo
608
625
  # @return [Hash] options that apply to this collection.
609
626
  def options
610
627
  info = @db.collections_info(@name).to_a
611
- ap info
612
628
  info.last['options']
613
629
  end
614
630
 
@@ -632,39 +648,5 @@ module Mongo
632
648
  end
633
649
 
634
650
  alias :size :count
635
-
636
- protected
637
-
638
- def validate_name(new_name)
639
- raise TypeError, "new_name must be a string like" unless new_name.respond_to?(:to_s)
640
-
641
- name = new_name.to_s
642
-
643
- if name.empty? || name.include?("..")
644
- raise Mongo::InvalidNSName, "collection names cannot be empty"
645
- end
646
- if name.include? "$"
647
- raise Mongo::InvalidNSName, "collection names must not contain '$'" unless name =~ /((^\$cmd)|(oplog\.\$main))/
648
- end
649
- if name.match(/^\./) || name.match(/\.$/)
650
- raise Mongo::InvalidNSName, "collection names must not start or end with '.'"
651
- end
652
- name
653
- end
654
-
655
- def normalize_hint_fields(hint)
656
- case hint
657
- when String
658
- {hint => 1}
659
- when Hash
660
- hint
661
- when nil
662
- nil
663
- else
664
- h = BSON::OrderedHash.new
665
- hint.to_a.each { |k| h[k.to_s] = 1 }
666
- h
667
- end
668
- end
669
651
  end
670
652
  end
@@ -20,28 +20,40 @@ module Mongo
20
20
  include Mongo::JavaImpl::Connection_::InstanceMethods
21
21
  extend Mongo::JavaImpl::Connection_::ClassMethods
22
22
 
23
- attr_reader :connection, :connector, :logger, :auths, :primary
23
+ attr_reader :connection, :connector, :logger, :auths, :primary, :write_concern
24
24
 
25
25
  DEFAULT_PORT = 27017
26
26
 
27
27
  def initialize host = nil, port = nil, opts = {}
28
+ @logger = opts.delete(:logger)
29
+ @auths = opts.delete(:auths) || []
28
30
  if opts.has_key?(:new_from_uri)
29
- @options = opts
30
31
  @mongo_uri = opts[:new_from_uri]
32
+ @options = @mongo_uri.options
33
+ @write_concern = @options.write_concern
31
34
  @connection = JMongo::Mongo.new(@mongo_uri)
32
35
  else
33
- @logger = opts[:logger]
34
36
  @host = host || 'localhost'
35
37
  @port = port || 27017
36
38
  @server_address = JMongo::ServerAddress.new @host, @port
37
39
  @options = JMongo::MongoOptions.new
38
- @options.connectionsPerHost = opts[:pool_size] || 1
39
- @options.socketTimeout = opts[:timeout].to_i * 1000 || 5000
40
+ opts.each do |k,v|
41
+ key = k.to_sym
42
+ jmo_key = JMongo.options_ruby2java_lu(key)
43
+ case jmo_key
44
+ when :safe
45
+ @write_concern = DB.write_concern(v)
46
+ @options.w = @write_concern.w
47
+ @options.wtimeout = @write_concern.wtimeout
48
+ @options.fsync = @write_concern.fsync
49
+ else
50
+ jmo_val = JMongo.options_ruby2java_xf(key, v)
51
+ @options.send("#{jmo_key}=", jmo_val)
52
+ end
53
+ end
40
54
  @connection = JMongo::Mongo.new(@server_address, @options)
41
55
  end
42
56
  @connector = @connection.connector
43
- @logger = opts[:logger]
44
- @auths = opts.fetch(:auths, [])
45
57
  add = @connector.address
46
58
  @primary = [add.host, add.port]
47
59
  end
@@ -124,7 +136,10 @@ module Mongo
124
136
  #
125
137
  # @return [Hash]
126
138
  def database_info
127
- raise_not_implemented
139
+ doc = self['admin'].command({:listDatabases => 1})
140
+ doc['databases'].each_with_object({}) do |db, info|
141
+ info[db['name']] = db['sizeOnDisk'].to_i
142
+ end
128
143
  end
129
144
 
130
145
  # Return an array of database names.
@@ -143,7 +158,7 @@ module Mongo
143
158
  #
144
159
  # @core databases db-instance_method
145
160
  def db(db_name, options={})
146
- DB.new db_name, self, options
161
+ DB.new db_name, self, options
147
162
  end
148
163
 
149
164
  # Shortcut for returning a database. Use DB#db to accept options.
@@ -18,19 +18,30 @@ module Mongo
18
18
  include Mongo::JavaImpl::Db_
19
19
  include Mongo::JavaImpl::Utils
20
20
 
21
- attr_reader :j_db
22
- attr_reader :name
23
- attr_reader :connection
21
+ attr_reader :j_db, :name, :connection, :safe
24
22
 
25
- attr_writer :strict
23
+ attr_accessor :strict
26
24
 
27
25
  ProfileLevel = {:off => 0, :slow_only => 1, :all => 2, 0 => 'off', 1 => 'slow_only', 2 => 'all'}
28
26
 
27
+ def self.write_concern(safe_)
28
+ return safe_ if safe_.is_a?(JMongo::WriteConcern)
29
+ return JMongo::WriteConcern.new(0) if safe_.is_a?(FalseClass)
30
+ return JMongo::WriteConcern.new(true) if safe_.is_a?(TrueClass)
31
+ return JMongo::WriteConcern.new(safe.to_i) if safe_.is_a?(Numeric)
32
+ return JMongo::WriteConcern.new(-1) unless safe_.is_a?(Hash)
33
+ w = safe_.fetch(:w, 0)
34
+ t = safe_.fetch(:wtimeout, 0)
35
+ f = !!safe_.fetch(:fsync, false)
36
+ JMongo::WriteConcern.new(w, t, f) #dont laugh!
37
+ end
38
+
29
39
  def initialize(db_name, connection, options={})
30
40
  @name = db_name
31
41
  @connection = connection
32
42
  @j_db = @connection.connection.get_db db_name
33
43
  @pk_factory = options[:pk]
44
+ @safe = options[:safe]
34
45
  @strict = options.fetch(:strict, false)
35
46
  end
36
47
 
@@ -64,39 +75,45 @@ module Mongo
64
75
 
65
76
  def collections
66
77
  collection_names.map do |name|
67
- Collection.new(self, name)
78
+ collection(name)
68
79
  end
69
80
  end
70
81
 
71
82
  def collections_info(coll_name=nil)
72
- selector = {}
73
- selector[:name] = full_collection_name(coll_name) if coll_name
74
- coll = self.collection(SYSTEM_NAMESPACE_COLLECTION)
75
- coll.find selector
83
+ _collections_info coll_name
76
84
  end
77
85
 
78
86
  def create_collection(name, options={})
79
- if collection_names.include?(name)
80
- raise MongoDBError, "Collection #{name} already exists. Currently in strict mode." if @strict
81
- collection(name, options)
82
- else
83
- begin
84
- jc = @j_db.create_collection(name, to_dbobject(options))
85
- Collection.new self, name, options, jc
86
- rescue NativeException => ex
87
- raise MongoDBError, "Collection #{name} creation error: " +
88
- ex.message
87
+ validate_name(name)
88
+ if collection_exists?(name)
89
+ if strict?
90
+ raise MongoDBError, "Collection #{name} already exists. Currently in strict mode."
91
+ else
92
+ return Collection.new self, name, options, @j_db.get_collection(name)
89
93
  end
90
94
  end
95
+ begin
96
+ Collection.new self, name, options
97
+ rescue => ex
98
+ raise MongoDBError, "Collection #{name} creation error: " + ex.message
99
+ end
91
100
  end
92
101
 
93
102
  def collection(name, options = {})
94
- Collection.new self, name, options
103
+ validate_name(name)
104
+ if strict? && !collection_exists?(name)
105
+ raise MongoDBError, "Collection #{name} does not exists. Currently in strict mode."
106
+ else
107
+ Collection.new self, name, options, @j_db.get_collection(name)
108
+ end
95
109
  end
96
110
  alias_method :[], :collection
97
111
 
98
112
  def drop_collection(name)
99
- coll = collection(name).j_collection.drop
113
+ col_name = name.to_s
114
+ return true unless collection_exists?(col_name)
115
+
116
+ ok?(command(:drop => col_name))
100
117
  end
101
118
 
102
119
  def get_last_error
@@ -122,15 +139,13 @@ module Mongo
122
139
 
123
140
  def dereference(dbref)
124
141
  ns = dbref.namespace
125
- raise MongoArgumentError, "No namespace for dbref: #{dbref.inspect}"
142
+ raise MongoArgumentError, "No collection for dbref: #{dbref.inspect}" unless collection_exists?(ns)
126
143
  collection(ns).find_one("_id" => dbref.object_id)
127
144
  end
128
145
 
129
146
  def eval(code, *args)
130
147
  doc = do_eval(code, *args)
131
- return unless doc
132
- return doc['retval']['value'] if doc['retval'] && doc['retval']['value']
133
- doc['retval']
148
+ (retval = doc['retval']).is_a?(Hash) && (value = retval['value']) ? value : retval
134
149
  end
135
150
 
136
151
  def rename_collection(from, to)
@@ -143,12 +158,12 @@ module Mongo
143
158
  end
144
159
 
145
160
  def drop_index(collection_name, index_name)
146
- self[collection_name].drop_index(index_name)
161
+ collection(collection_name).drop_index(index_name)
147
162
  end
148
163
 
149
164
  def index_information(collection_name)
150
165
  info = {}
151
- from_dbobject(@j_db.get_collection(collection_name).get_index_info).each do |index|
166
+ from_dbobject(@j_db.getCollectionFromString(collection_name).getIndexInfo).each do |index|
152
167
  info[index['name']] = index
153
168
  end
154
169
  info
@@ -258,11 +273,6 @@ module Mongo
258
273
  end
259
274
  doc
260
275
  end
261
-
262
- # additions to the ruby driver
263
- def has_collection?(name)
264
- has_coll name
265
- end
266
276
  end # class DB
267
277
 
268
278
  end # module Mongo
@@ -2,7 +2,6 @@ module BSON
2
2
  # add missing BSON::ObjectId ruby methods
3
3
  java_import Java::OrgBsonTypes::ObjectId
4
4
 
5
- java_import Java::ComMongodb::DBRef
6
5
  java_import Java::OrgBsonTypes::MaxKey
7
6
  java_import Java::OrgBsonTypes::MinKey
8
7
  java_import Java::OrgBsonTypes::Symbol
@@ -18,7 +17,7 @@ module BSON
18
17
  end
19
18
 
20
19
  def self.create_pk(doc)
21
- doc.has_key?(:_id) || doc.has_key?('_id') ? doc : doc.merge!(:_id => self.new)
20
+ doc.has_key?(:_id) || doc.has_key?('_id') ? doc : doc.merge!('_id' => self.new)
22
21
  end
23
22
 
24
23
  def self.from_time(time, opts={})
@@ -105,6 +104,31 @@ module BSON
105
104
  alias :to_bson_code :to_bson
106
105
  end
107
106
 
107
+ class DBRef
108
+
109
+ attr_reader :namespace, :object_id
110
+
111
+ # Create a DBRef. Use this class in conjunction with DB#dereference.
112
+ #
113
+ # @param [String] a collection name
114
+ # @param [ObjectId] an object id
115
+ #
116
+ # @core dbrefs constructor_details
117
+ def initialize(namespace, object_id)
118
+ @namespace = namespace
119
+ @object_id = object_id
120
+ end
121
+
122
+ def to_s
123
+ "ns: #{namespace}, id: #{object_id}"
124
+ end
125
+
126
+ def to_hash
127
+ {"$ns" => @namespace, "$id" => @object_id }
128
+ end
129
+
130
+ end
131
+
108
132
  # Generic Mongo Ruby Driver exception class.
109
133
  class MongoRubyError < StandardError; end
110
134