rename collection

This commit is contained in:
Mike Dirolf 2009-08-04 14:16:02 -04:00
parent fb48299975
commit 91d6ab4caa
4 changed files with 94 additions and 8 deletions

View File

@ -192,6 +192,35 @@ EOS
}))["result"]
end
# Rename this collection.
#
# If operating in auth mode, client must be authorized as an admin to
# perform this operation. Raises an error if +new_name+ is an invalid
# collection name.
#
# :new_name :: new name for this collection
def rename(new_name)
case new_name
when Symbol, String
else
raise RuntimeError, "new_name must be a string or symbol"
end
new_name = new_name.to_s
if new_name.empty? or new_name.include? ".."
raise RuntimeError, "collection names cannot be empty"
end
if new_name.include? "$"
raise RuntimeError, "collection names must not contain '$'"
end
if new_name.match(/^\./) or new_name.match(/\.$/)
raise RuntimeError, "collection names must not start or end with '.'"
end
@db.rename_collection(@name, new_name)
end
# Get information on the indexes for the collection +collection_name+.
# Returns a hash where the keys are index names (as returned by
# Collection#create_index and the values are lists of [key, direction]

View File

@ -31,8 +31,8 @@ module XGen
attr_reader :db, :collection, :query
def initialize(db, collection, query)
@db, @collection, @query = db, collection, query
def initialize(db, collection, query, admin=false)
@db, @collection, @query, @admin = db, collection, query, admin
@num_to_return = @query.number_to_return || 0
@cache = []
@closed = false
@ -194,7 +194,7 @@ module XGen
def refill_via_get_more
send_query_if_needed
return if @cursor_id == 0
@db.send_to_db(GetMoreMessage.new(@db.name, @collection.name, @cursor_id))
@db.send_to_db(GetMoreMessage.new(@admin ? 'admin' : @db.name, @collection.name, @cursor_id))
read_all
end
@ -212,7 +212,7 @@ module XGen
def send_query_if_needed
# Run query first time we request an object from the wire
unless @query_run
@db.send_query_message(QueryMessage.new(@db.name, @collection.name, @query))
@db.send_query_message(QueryMessage.new(@admin ? 'admin' : @db.name, @collection.name, @query))
@query_run = true
read_all
end

View File

@ -340,8 +340,8 @@ module XGen
# Note that the query gets sent lazily; the cursor calls
# #send_query_message when needed. If the caller never requests an
# object from the cursor, the query never gets sent.
def query(collection, query)
Cursor.new(self, collection, query)
def query(collection, query, admin=false)
Cursor.new(self, collection, query, admin)
end
# Used by a Cursor to lazily send the query to the database.
@ -416,6 +416,16 @@ module XGen
raise "Error with eval command: #{doc.inspect}"
end
# Rename collection +from+ to +to+. Meant to be called by
# Collection#rename.
def rename_collection(from, to)
oh = OrderedHash.new
oh[:renameCollection] = "#{@name}.#{from}"
oh[:to] = "#{@name}.#{to}"
doc = db_command(oh, true)
raise "Error renaming collection: #{doc.inspect}" unless ok?(doc)
end
# Drop index +name+ from +collection_name+. Normally called from
# Collection#drop_index or Collection#drop_indexes.
def drop_index(collection_name, name)
@ -511,7 +521,7 @@ module XGen
# that the "command" key be first.
#
# Do not call this. Intended for driver use only.
def db_command(selector)
def db_command(selector, use_admin_db=false)
if !selector.kind_of?(OrderedHash)
if !selector.kind_of?(Hash) || selector.keys.length > 1
raise "db_command must be given an OrderedHash when there is more than one key"
@ -520,7 +530,7 @@ module XGen
q = Query.new(selector)
q.number_to_return = 1
query(Collection.new(self, SYSTEM_COMMAND_COLLECTION), q).next_object
query(Collection.new(self, SYSTEM_COMMAND_COLLECTION), q, use_admin_db).next_object
end
private

View File

@ -713,6 +713,53 @@ class DBAPITest < Test::Unit::TestCase
@@coll.modify({"hello" => "world"}, {"$inc" => "hello"})
end
def test_rename_collection
@@db.drop_collection("foo")
@@db.drop_collection("bar")
a = @@db.collection("foo")
b = @@db.collection("bar")
assert_raise RuntimeError do
a.rename(5)
end
assert_raise RuntimeError do
a.rename("")
end
assert_raise RuntimeError do
a.rename("te$t")
end
assert_raise RuntimeError do
a.rename(".test")
end
assert_raise RuntimeError do
a.rename("test.")
end
assert_raise RuntimeError do
a.rename("tes..t")
end
assert_equal 0, a.count()
assert_equal 0, b.count()
a.insert("x" => 1)
a.insert("x" => 2)
assert_equal 2, a.count()
a.rename("bar")
assert_equal 0, a.count()
assert_equal 2, b.count()
assert_equal 1, b.find().to_a()[0]["x"]
assert_equal 2, b.find().to_a()[1]["x"]
b.rename(:foo)
assert_equal 2, a.count()
assert_equal 0, b.count()
end
# TODO this test fails with error message "Undefed Before end of object"
# That is a database error. The undefined type may go away.