mirror of https://gitee.com/bigwinds/arangodb
added tests, fixed unique constraints
This commit is contained in:
parent
a88b1adf8e
commit
c1ff7d249f
|
@ -0,0 +1,579 @@
|
|||
# coding: utf-8
|
||||
|
||||
require 'rspec'
|
||||
require 'arangodb.rb'
|
||||
|
||||
describe ArangoDB do
|
||||
prefix = "api-index-persistent"
|
||||
|
||||
################################################################################
|
||||
## unique constraints during create
|
||||
################################################################################
|
||||
|
||||
context "creating persistent index:" do
|
||||
context "dealing with unique constraints violation:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionIndexes"
|
||||
ArangoDB.drop_collection(@cn)
|
||||
@cid = ArangoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
ArangoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "does not create the index in case of violation" do
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# create another document
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# try to create the index
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ] }"
|
||||
doc = ArangoDB.log_post("#{prefix}-fail", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.parsed_response['errorNum'].should eq(1210)
|
||||
end
|
||||
|
||||
it "does not create the index in case of violation, null attributes" do
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : null, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# create another document
|
||||
body = "{ \"a\" : null, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# try to create the index
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ] }"
|
||||
doc = ArangoDB.log_post("#{prefix}-fail", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.parsed_response['errorNum'].should eq(1210)
|
||||
end
|
||||
|
||||
it "does not create the index in case of violation, sparse index" do
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# create another document
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# try to create the index
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ], \"sparse\" : true }"
|
||||
doc = ArangoDB.log_post("#{prefix}-fail", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.parsed_response['errorNum'].should eq(1210)
|
||||
end
|
||||
|
||||
it "creates the index in case of null attributes, sparse index" do
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : null, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# create another document
|
||||
body = "{ \"a\" : null, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
# try to create the index
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ], \"sparse\" : true }"
|
||||
doc = ArangoDB.log_post("#{prefix}-fail", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## unique constraints during create
|
||||
################################################################################
|
||||
|
||||
context "creating documents:" do
|
||||
context "dealing with unique constraints:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionIndexes"
|
||||
ArangoDB.drop_collection(@cn)
|
||||
@cid = ArangoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
ArangoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "rolls back in case of violation" do
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ] }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create1", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.parsed_response['type'].should eq("persistent")
|
||||
doc.parsed_response['unique'].should eq(true)
|
||||
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
id1 = doc.parsed_response['_id']
|
||||
id1.should be_kind_of(String)
|
||||
|
||||
rev1 = doc.parsed_response['_rev']
|
||||
rev1.should be_kind_of(String)
|
||||
|
||||
# check it
|
||||
cmd2 = "/_api/document/#{id1}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# create a unique constraint violation
|
||||
body = "{ \"a\" : 1, \"b\" : 2 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create3", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check it again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# third try (make sure the rollback has not destroyed anything)
|
||||
body = "{ \"a\" : 1, \"b\" : 3 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create4", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check it again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# unload collection
|
||||
cmd3 = "/_api/collection/#{@cn}/unload"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd3)
|
||||
doc.code.should eq(200)
|
||||
|
||||
# flush wal
|
||||
doc = ArangoDB.put("/_admin/wal/flush");
|
||||
doc.code.should eq(200)
|
||||
|
||||
cmd3 = "/_api/collection/#{@cn}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd3)
|
||||
doc.code.should eq(200)
|
||||
|
||||
while doc.parsed_response['status'] != 2
|
||||
doc = ArangoDB.get(cmd3)
|
||||
doc.code.should eq(200)
|
||||
sleep 1
|
||||
end
|
||||
|
||||
# check it again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
end
|
||||
|
||||
it "rolls back in case of violation, sparse index" do
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ], \"sparse\" : true }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create1", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.parsed_response['type'].should eq("persistent")
|
||||
doc.parsed_response['unique'].should eq(true)
|
||||
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
id1 = doc.parsed_response['_id']
|
||||
id1.should be_kind_of(String)
|
||||
|
||||
rev1 = doc.parsed_response['_rev']
|
||||
rev1.should be_kind_of(String)
|
||||
|
||||
# check it
|
||||
cmd2 = "/_api/document/#{id1}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# create a unique constraint violation
|
||||
body = "{ \"a\" : 1, \"b\" : 2 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create3", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check it again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# third try (make sure the rollback has not destroyed anything)
|
||||
body = "{ \"a\" : 1, \"b\" : 3 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create4", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check it again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# unload collection
|
||||
cmd3 = "/_api/collection/#{@cn}/unload"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd3)
|
||||
doc.code.should eq(200)
|
||||
|
||||
# flush wal
|
||||
doc = ArangoDB.put("/_admin/wal/flush");
|
||||
doc.code.should eq(200)
|
||||
|
||||
cmd3 = "/_api/collection/#{@cn}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd3)
|
||||
doc.code.should eq(200)
|
||||
|
||||
while doc.parsed_response['status'] != 2
|
||||
doc = ArangoDB.get(cmd3)
|
||||
doc.code.should eq(200)
|
||||
sleep 1
|
||||
end
|
||||
|
||||
# check it again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## unique constraints during update
|
||||
################################################################################
|
||||
|
||||
context "updating documents:" do
|
||||
context "dealing with unique constraints:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionIndexes"
|
||||
ArangoDB.drop_collection(@cn)
|
||||
@cid = ArangoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
ArangoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "rolls back in case of violation" do
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ] }"
|
||||
doc = ArangoDB.log_post("#{prefix}-update1", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.parsed_response['type'].should eq("persistent")
|
||||
doc.parsed_response['unique'].should eq(true)
|
||||
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-update2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
id1 = doc.parsed_response['_id']
|
||||
id1.should be_kind_of(String)
|
||||
|
||||
rev1 = doc.parsed_response['_rev']
|
||||
rev1.should be_kind_of(String)
|
||||
|
||||
# check it
|
||||
cmd2 = "/_api/document/#{id1}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# create a second document
|
||||
body = "{ \"a\" : 2, \"b\" : 2 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-update3", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
id2 = doc.parsed_response['_id']
|
||||
id2.should be_kind_of(String)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(String)
|
||||
|
||||
# create a unique constraint violation during update
|
||||
body = "{ \"a\" : 2, \"b\" : 3 }"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd2, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check first document again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
rev3 = doc.parsed_response['_rev']
|
||||
rev3.should be_kind_of(String)
|
||||
|
||||
# check second document again
|
||||
cmd3 = "/_api/document/#{id2}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd3)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(2)
|
||||
doc.parsed_response['b'].should eq(2)
|
||||
doc.parsed_response['_id'].should eq(id2)
|
||||
doc.parsed_response['_rev'].should eq(rev2)
|
||||
|
||||
# third try (make sure the rollback has not destroyed anything)
|
||||
body = "{ \"a\" : 2, \"b\" : 4 }"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd2, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check the first document again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
doc.parsed_response['_rev'].should_not eq(rev2)
|
||||
|
||||
# unload collection
|
||||
cmd4 = "/_api/collection/#{@cn}/unload"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd4)
|
||||
doc.code.should eq(200)
|
||||
|
||||
# flush wal
|
||||
doc = ArangoDB.put("/_admin/wal/flush");
|
||||
doc.code.should eq(200)
|
||||
|
||||
cmd4 = "/_api/collection/#{@cn}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd4)
|
||||
doc.code.should eq(200)
|
||||
|
||||
while doc.parsed_response['status'] != 2
|
||||
doc = ArangoDB.get(cmd4)
|
||||
doc.code.should eq(200)
|
||||
sleep 1
|
||||
end
|
||||
|
||||
# check the first document again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
doc.parsed_response['_rev'].should_not eq(rev2)
|
||||
end
|
||||
|
||||
it "rolls back in case of violation, sparse index" do
|
||||
cmd = "/_api/index?collection=#{@cn}"
|
||||
body = "{ \"type\" : \"persistent\", \"unique\" : true, \"fields\" : [ \"a\" ], \"sparse\" : true }"
|
||||
doc = ArangoDB.log_post("#{prefix}-update1", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.parsed_response['type'].should eq("persistent")
|
||||
doc.parsed_response['unique'].should eq(true)
|
||||
|
||||
# create a document
|
||||
cmd1 = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"a\" : 1, \"b\" : 1 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-update2", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
id1 = doc.parsed_response['_id']
|
||||
id1.should be_kind_of(String)
|
||||
|
||||
rev1 = doc.parsed_response['_rev']
|
||||
rev1.should be_kind_of(String)
|
||||
|
||||
# check it
|
||||
cmd2 = "/_api/document/#{id1}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
# create a second document
|
||||
body = "{ \"a\" : 2, \"b\" : 2 }"
|
||||
doc = ArangoDB.log_post("#{prefix}-update3", cmd1, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
id2 = doc.parsed_response['_id']
|
||||
id2.should be_kind_of(String)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(String)
|
||||
|
||||
# create a unique constraint violation during update
|
||||
body = "{ \"a\" : 2, \"b\" : 3 }"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd2, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check first document again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
|
||||
rev3 = doc.parsed_response['_rev']
|
||||
rev3.should be_kind_of(String)
|
||||
|
||||
# check second document again
|
||||
cmd3 = "/_api/document/#{id2}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd3)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(2)
|
||||
doc.parsed_response['b'].should eq(2)
|
||||
doc.parsed_response['_id'].should eq(id2)
|
||||
doc.parsed_response['_rev'].should eq(rev2)
|
||||
|
||||
# third try (make sure the rollback has not destroyed anything)
|
||||
body = "{ \"a\" : 2, \"b\" : 4 }"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd2, :body => body)
|
||||
|
||||
doc.code.should eq(409)
|
||||
|
||||
# check the first document again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
doc.parsed_response['_rev'].should_not eq(rev2)
|
||||
|
||||
# unload collection
|
||||
cmd4 = "/_api/collection/#{@cn}/unload"
|
||||
doc = ArangoDB.log_put("#{prefix}", cmd4)
|
||||
doc.code.should eq(200)
|
||||
|
||||
# flush wal
|
||||
doc = ArangoDB.put("/_admin/wal/flush");
|
||||
doc.code.should eq(200)
|
||||
|
||||
cmd4 = "/_api/collection/#{@cn}"
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd4)
|
||||
doc.code.should eq(200)
|
||||
|
||||
while doc.parsed_response['status'] != 2
|
||||
doc = ArangoDB.get(cmd4)
|
||||
doc.code.should eq(200)
|
||||
sleep 1
|
||||
end
|
||||
|
||||
# check the first document again
|
||||
doc = ArangoDB.log_get("#{prefix}", cmd2)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['a'].should eq(1)
|
||||
doc.parsed_response['b'].should eq(1)
|
||||
doc.parsed_response['_id'].should eq(id1)
|
||||
doc.parsed_response['_rev'].should eq(rev1)
|
||||
doc.parsed_response['_rev'].should_not eq(rev2)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -258,6 +258,7 @@ void RocksDBIndex::toVelocyPackFigures(VPackBuilder& builder) const {
|
|||
|
||||
int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_doc_mptr_t const* doc,
|
||||
bool) {
|
||||
auto comparator = RocksDBFeature::instance()->comparator();
|
||||
std::vector<TRI_index_element_t*> elements;
|
||||
|
||||
int res;
|
||||
|
@ -281,9 +282,18 @@ int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_doc_mptr_t const* doc,
|
|||
}
|
||||
|
||||
VPackSlice const key = Transaction::extractKeyFromDocument(VPackSlice(doc->vpack()));
|
||||
std::string const prefix = buildPrefix(trx->vocbase()->_id, _collection->_info.id(), _iid);
|
||||
|
||||
VPackBuilder builder;
|
||||
std::vector<std::string> values;
|
||||
values.reserve(elements.size());
|
||||
|
||||
// lower and upper bounds, only required if the index is unique
|
||||
std::vector<std::pair<std::string, std::string>> bounds;
|
||||
if (_unique) {
|
||||
bounds.reserve(elements.size());
|
||||
}
|
||||
|
||||
for (auto& it : elements) {
|
||||
builder.clear();
|
||||
builder.openArray();
|
||||
|
@ -296,9 +306,44 @@ int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_doc_mptr_t const* doc,
|
|||
VPackSlice const s = builder.slice();
|
||||
std::string value;
|
||||
value.reserve(keyPrefixSize() + s.byteSize());
|
||||
value += buildPrefix(trx->vocbase()->_id, _collection->_info.id(), _iid);
|
||||
value += prefix;
|
||||
value.append(s.startAs<char const>(), s.byteSize());
|
||||
values.emplace_back(std::move(value));
|
||||
|
||||
if (_unique) {
|
||||
builder.clear();
|
||||
builder.openArray();
|
||||
for (size_t i = 0; i < _fields.size(); ++i) {
|
||||
builder.add(it->subObjects()[i].slice(doc));
|
||||
}
|
||||
builder.add(VPackSlice::minKeySlice());
|
||||
builder.close();
|
||||
|
||||
VPackSlice s = builder.slice();
|
||||
std::string value;
|
||||
value.reserve(keyPrefixSize() + s.byteSize());
|
||||
value += prefix;
|
||||
value.append(s.startAs<char const>(), s.byteSize());
|
||||
|
||||
std::pair<std::string, std::string> p;
|
||||
p.first = value;
|
||||
|
||||
builder.clear();
|
||||
builder.openArray();
|
||||
for (size_t i = 0; i < _fields.size(); ++i) {
|
||||
builder.add(it->subObjects()[i].slice(doc));
|
||||
}
|
||||
builder.add(VPackSlice::maxKeySlice());
|
||||
builder.close();
|
||||
|
||||
s = builder.slice();
|
||||
value.clear();
|
||||
value += prefix;
|
||||
value.append(s.startAs<char const>(), s.byteSize());
|
||||
|
||||
p.second = value;
|
||||
bounds.emplace_back(std::move(p));
|
||||
}
|
||||
}
|
||||
|
||||
auto rocksTransaction = trx->rocksTransaction();
|
||||
|
@ -309,10 +354,28 @@ int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_doc_mptr_t const* doc,
|
|||
size_t const count = elements.size();
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (_unique) {
|
||||
std::string existing;
|
||||
auto status = rocksTransaction->Get(readOptions, values[i], &existing);
|
||||
bool uniqueConstraintViolated = false;
|
||||
auto iterator = rocksTransaction->GetIterator(readOptions);
|
||||
|
||||
if (status.ok()) {
|
||||
if (iterator != nullptr) {
|
||||
auto& bound = bounds[i];
|
||||
iterator->Seek(rocksdb::Slice(bound.first.c_str(), bound.first.size()));
|
||||
|
||||
while (iterator->Valid()) {
|
||||
int res = comparator->Compare(iterator->key(), rocksdb::Slice(bound.second.c_str(), bound.second.size()));
|
||||
|
||||
if (res > 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uniqueConstraintViolated = true;
|
||||
break;
|
||||
}
|
||||
|
||||
delete iterator;
|
||||
}
|
||||
|
||||
if (uniqueConstraintViolated) {
|
||||
// duplicate key
|
||||
res = TRI_ERROR_ARANGO_UNIQUE_CONSTRAINT_VIOLATED;
|
||||
if (!_collection->useSecondaryIndexes()) {
|
||||
|
@ -324,6 +387,7 @@ int RocksDBIndex::insert(arangodb::Transaction* trx, TRI_doc_mptr_t const* doc,
|
|||
|
||||
if (res == TRI_ERROR_NO_ERROR) {
|
||||
auto status = rocksTransaction->Put(values[i], std::string());
|
||||
|
||||
if (! status.ok()) {
|
||||
res = TRI_ERROR_INTERNAL;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue