mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'spdvpk' of https://github.com/arangodb/arangodb into spdvpk
This commit is contained in:
commit
7e01c3208a
|
@ -1,85 +0,0 @@
|
|||
# coding: utf-8
|
||||
|
||||
require 'rspec'
|
||||
require 'arangodb.rb'
|
||||
|
||||
describe ArangoDB do
|
||||
prefix = "rest-create-document"
|
||||
didRegex = /^([0-9a-zA-Z]+)\/([0-9a-zA-Z\-_]+)/
|
||||
|
||||
context "creating a document:" do
|
||||
|
||||
################################################################################
|
||||
## unknown collection name
|
||||
################################################################################
|
||||
|
||||
context "unknown collection name:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionNamed#{Time.now.to_i}"
|
||||
end
|
||||
|
||||
after do
|
||||
ArangoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "create the collection and the document" do
|
||||
cmd = "/_api/document?collection=#{@cn}&createCollection=true"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create-collection", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
|
||||
doc.code.should eq(202)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
rev = doc.parsed_response['_rev']
|
||||
rev.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
ArangoDB.size_collection(@cn).should eq(0)
|
||||
end
|
||||
|
||||
it "create the collection and the document, setting compatibility header" do
|
||||
cmd = "/_api/document?collection=#{@cn}&createCollection=true"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-create-collection", cmd, :body => body, :headers => { "x-arango-version" => "1.4" })
|
||||
|
||||
doc.code.should eq(202)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
rev = doc.parsed_response['_rev']
|
||||
rev.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
ArangoDB.size_collection(@cn).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -14,18 +14,6 @@ describe ArangoDB do
|
|||
################################################################################
|
||||
|
||||
context "error handling:" do
|
||||
it "returns an error if url contains a suffix" do
|
||||
cmd = "/_api/document/123456"
|
||||
body = "{}"
|
||||
doc = ArangoDB.log_post("#{prefix}-superfluous-suffix", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(601)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
end
|
||||
|
||||
it "returns an error if collection idenifier is missing" do
|
||||
cmd = "/_api/document"
|
||||
body = "{}"
|
||||
|
@ -139,11 +127,10 @@ describe ArangoDB do
|
|||
it "creating a new document" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -162,7 +149,7 @@ describe ArangoDB do
|
|||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
|
@ -176,7 +163,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -205,11 +191,10 @@ describe ArangoDB do
|
|||
it "creating a new document complex body" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"Wo\\\"rld\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -228,7 +213,7 @@ describe ArangoDB do
|
|||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
cmd = "/_api/document/#{did}"
|
||||
doc = ArangoDB.log_get("#{prefix}-complex", cmd)
|
||||
|
@ -249,7 +234,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -285,11 +269,10 @@ describe ArangoDB do
|
|||
it "creating a new umlaut document" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"öäüÖÄÜßあ寿司\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-umlaut", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}-umlaut", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -308,7 +291,7 @@ describe ArangoDB do
|
|||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
cmd = "/_api/document/#{did}"
|
||||
doc = ArangoDB.log_get("#{prefix}-umlaut", cmd)
|
||||
|
@ -319,7 +302,7 @@ describe ArangoDB do
|
|||
newBody = doc.body()
|
||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
||||
|
||||
newBody.should eq("\\u00F6\\u00E4\\u00FC\\u00D6\\u00C4\\u00DC\\u00DF\\u3042\\u5BFF\\u53F8")
|
||||
newBody.should eq("öäüÖÄÜßあ寿司")
|
||||
|
||||
doc.parsed_response['Hallo'].should eq('öäüÖÄÜßあ寿司')
|
||||
|
||||
|
@ -335,7 +318,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -365,7 +347,7 @@ describe ArangoDB do
|
|||
newBody = doc.body()
|
||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
||||
|
||||
newBody.should eq("\\u00F6\\u00E4\\u00FC\\u00D6\\u00C4\\u00DC\\u00DF\\u3042\\u5BFF\\u53F8")
|
||||
newBody.should eq("öäüÖÄÜßあ寿司")
|
||||
|
||||
doc.parsed_response['Hallo'].should eq('öäüÖÄÜßあ寿司')
|
||||
|
||||
|
@ -376,58 +358,11 @@ describe ArangoDB do
|
|||
|
||||
it "creating a new not normalized umlaut document" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"Gru\\u0308\\u00DF Gott.\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-umlaut", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
body = "{ \"Hallo\" : \"Grüß Gott.\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-umlaut", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
rev = doc.parsed_response['_rev']
|
||||
rev.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
match = didRegex.match(did)
|
||||
|
||||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
|
||||
cmd = "/_api/document/#{did}"
|
||||
doc = ArangoDB.log_get("#{prefix}-umlaut", cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
newBody = doc.body()
|
||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
||||
|
||||
newBody.should eq("Gr\\u00FC\\u00DF Gott.")
|
||||
|
||||
doc.parsed_response['Hallo'].should eq('Grüß Gott.')
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
ArangoDB.size_collection(@cn).should eq(0)
|
||||
end
|
||||
|
||||
it "creating a new not normalized umlaut document, setting compatibility header" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"Gru\\u0308\\u00DF Gott.\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-umlaut", cmd, :body => body, :headers => { "x-arango-version" => "1.4" })
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -457,7 +392,52 @@ describe ArangoDB do
|
|||
newBody = doc.body()
|
||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
||||
|
||||
newBody.should eq("Gr\\u00FC\\u00DF Gott.")
|
||||
newBody.should eq("Grüß Gott.")
|
||||
|
||||
doc.parsed_response['Hallo'].should eq('Grüß Gott.')
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
ArangoDB.size_collection(@cn).should eq(0)
|
||||
end
|
||||
|
||||
it "creating a new not normalized umlaut document, setting compatibility header" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"Grüß Gott.\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-umlaut", cmd, :body => body, :headers => { "x-arango-version" => "1.4" })
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
rev = doc.parsed_response['_rev']
|
||||
rev.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
match = didRegex.match(did)
|
||||
|
||||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
cmd = "/_api/document/#{did}"
|
||||
doc = ArangoDB.log_get("#{prefix}-umlaut", cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
newBody = doc.body()
|
||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
||||
|
||||
newBody.should eq("Grüß Gott.")
|
||||
|
||||
doc.parsed_response['Hallo'].should eq('Grüß Gott.')
|
||||
|
||||
|
@ -473,11 +453,10 @@ describe ArangoDB do
|
|||
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"some stuff\" : \"goes here\", \"_key\" : \"#{@key}\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-existing-id", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}-existing-id", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -496,7 +475,7 @@ describe ArangoDB do
|
|||
|
||||
match[1].should eq("#{@cn}")
|
||||
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete("/_api/document/#{@cn}/#{@key}")
|
||||
end
|
||||
|
@ -512,7 +491,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -575,11 +553,10 @@ describe ArangoDB do
|
|||
it "creating a new document" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-accept", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}-accept", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(202)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -598,7 +575,7 @@ describe ArangoDB do
|
|||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
|
@ -612,7 +589,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(202)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -641,11 +617,10 @@ describe ArangoDB do
|
|||
it "creating a new document, waitForSync URL param = false" do
|
||||
cmd = "/_api/document?collection=#{@cn}&waitForSync=false"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-accept-sync-false", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}-accept-sync-false", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(202)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -664,7 +639,7 @@ describe ArangoDB do
|
|||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
|
@ -678,7 +653,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(202)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -707,11 +681,10 @@ describe ArangoDB do
|
|||
it "creating a new document, waitForSync URL param = true" do
|
||||
cmd = "/_api/document?collection=#{@cn}&waitForSync=true"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-accept-sync-true", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}-accept-sync-true", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -730,7 +703,7 @@ describe ArangoDB do
|
|||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
|
@ -744,7 +717,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -788,11 +760,10 @@ describe ArangoDB do
|
|||
it "creating a new document" do
|
||||
cmd = "/_api/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = ArangoDB.log_post("#{prefix}-named-collection", cmd, :body => body, :headers => { "x-arango-version" => "1.3" })
|
||||
doc = ArangoDB.log_post("#{prefix}-named-collection", cmd, :body => body, :headers => {})
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
@ -811,7 +782,7 @@ describe ArangoDB do
|
|||
match[1].should eq("#{@cn}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/_api/document/#{did}")
|
||||
location.should eq("/_db/_system/_api/document/#{did}")
|
||||
|
||||
ArangoDB.delete(location)
|
||||
|
||||
|
@ -825,7 +796,6 @@ describe ArangoDB do
|
|||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
|
|
@ -236,7 +236,6 @@ describe ArangoDB do
|
|||
doc = ArangoDB.log_post("#{prefix}-valid", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.parsed_response['_key'].should eq(key)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
end
|
||||
|
@ -264,7 +263,6 @@ describe ArangoDB do
|
|||
doc = ArangoDB.log_post("#{prefix}-valid", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.parsed_response['_key'].should eq(key)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
|
|
|
@ -32,10 +32,10 @@ describe ArangoDB do
|
|||
cmd = "/_api/document/123456"
|
||||
doc = ArangoDB.log_get("#{prefix}-bad-handle", cmd)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1205)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.parsed_response['errorNum'].should eq(1203)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
end
|
||||
|
||||
|
@ -552,10 +552,10 @@ describe ArangoDB do
|
|||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
# get the document head
|
||||
# get the document head, withdrawn for 3.0
|
||||
doc = ArangoDB.head(cmd + "?rev=abcd")
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.code.should eq(200)
|
||||
|
||||
hdr = { "if-match" => "'abcd'" }
|
||||
doc = ArangoDB.log_head("#{prefix}-head-rev-invalid", cmd, :headers => hdr)
|
||||
|
|
|
@ -26,7 +26,7 @@ describe ArangoDB do
|
|||
|
||||
it "creates a document with an invalid type" do
|
||||
cmd = api + "?collection=" + @cn
|
||||
body = "[ ]";
|
||||
body = "[ [] ]";
|
||||
doc = ArangoDB.log_post("#{prefix}-create-list1", cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
|
|
|
@ -66,6 +66,17 @@ using VertexId = arangodb::traverser::VertexId;
|
|||
thread_local std::unordered_map<std::string, RegexMatcher*>* RegexCache =
|
||||
nullptr;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Insert a mptr into the result
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void InsertMasterPointer(TRI_doc_mptr_t const* mptr, VPackBuilder& builder) {
|
||||
//builder.add(VPackValue(static_cast<void const*>(mptr->vpack()),
|
||||
// VPackValueType::External));
|
||||
// This is the future, for now we have to copy:
|
||||
builder.add(VPackSlice(mptr->vpack()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clear the regex cache in a thread
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -436,116 +447,6 @@ static bool SortNumberList(VPackSlice const& values,
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void ExpandShapedJson(
|
||||
VocShaper* shaper, CollectionNameResolver const* resolver,
|
||||
TRI_voc_cid_t const& cid, TRI_doc_mptr_t const* mptr, VPackBuilder& b,
|
||||
bool keepTopLevelOpen,
|
||||
std::unordered_set<std::string> const& forbidden) {
|
||||
b.add(VPackValue(VPackValueType::Object));
|
||||
|
||||
TRI_df_marker_t const* marker =
|
||||
static_cast<TRI_df_marker_t const*>(mptr->getDataPtr());
|
||||
|
||||
TRI_shaped_json_t shaped;
|
||||
TRI_EXTRACT_SHAPED_JSON_MARKER(shaped, marker);
|
||||
std::shared_ptr<VPackBuilder> tmp = TRI_VelocyPackShapedJson(shaper, &shaped);
|
||||
// Copy the shaped into our local builder
|
||||
for (auto const& it : VPackObjectIterator(tmp->slice())) {
|
||||
std::string key = it.key.copyString();
|
||||
if (forbidden.count(key) == 0) {
|
||||
b.add(it.key.copyString(), it.value);
|
||||
}
|
||||
}
|
||||
|
||||
char const* key = TRI_EXTRACT_MARKER_KEY(marker);
|
||||
std::string id(resolver->getCollectionName(cid));
|
||||
id.push_back('/');
|
||||
id.append(key);
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_ID) == 0) {
|
||||
b.add(TRI_VOC_ATTRIBUTE_ID, VPackValue(id));
|
||||
}
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_REV) == 0) {
|
||||
b.add(TRI_VOC_ATTRIBUTE_REV,
|
||||
VPackValue(std::to_string(TRI_EXTRACT_MARKER_RID(marker))));
|
||||
}
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_KEY) == 0) {
|
||||
b.add(TRI_VOC_ATTRIBUTE_KEY, VPackValue(key));
|
||||
}
|
||||
|
||||
#if 0
|
||||
// TODO
|
||||
if (TRI_IS_EDGE_MARKER(marker)) {
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_FROM) == 0) {
|
||||
std::string from(resolver->getCollectionNameCluster(
|
||||
TRI_EXTRACT_MARKER_FROM_CID(marker)));
|
||||
from.push_back('/');
|
||||
from.append(TRI_EXTRACT_MARKER_FROM_KEY(marker));
|
||||
b.add(TRI_VOC_ATTRIBUTE_FROM, VPackValue(from));
|
||||
}
|
||||
|
||||
if (forbidden.count(TRI_VOC_ATTRIBUTE_TO) == 0) {
|
||||
std::string to(
|
||||
resolver->getCollectionNameCluster(TRI_EXTRACT_MARKER_TO_CID(marker)));
|
||||
|
||||
to.push_back('/');
|
||||
to.append(TRI_EXTRACT_MARKER_TO_KEY(marker));
|
||||
b.add(TRI_VOC_ATTRIBUTE_TO, VPackValue(to));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!keepTopLevelOpen) {
|
||||
b.close();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Reads a document by cid and key
|
||||
/// Also lazy locks the collection.
|
||||
/// Returns null if the document does not exist
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void ReadDocument(arangodb::AqlTransaction* trx,
|
||||
CollectionNameResolver const* resolver,
|
||||
TRI_voc_cid_t cid, char const* key,
|
||||
VPackBuilder& result) {
|
||||
trx->addCollectionAtRuntime(cid);
|
||||
|
||||
OperationOptions options;
|
||||
|
||||
VPackSlice slice;
|
||||
#warning fill slice from key
|
||||
OperationResult opRes = trx->document(trx->collectionName(cid), slice, options);
|
||||
#warning fill mptr
|
||||
|
||||
if (opRes.code != TRI_ERROR_NO_ERROR) {
|
||||
result.add(VPackValue(VPackValueType::Null));
|
||||
} else {
|
||||
#warning convert opRes result to vpack external
|
||||
result.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function to filter the given list of mptr
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void FilterDocuments(arangodb::ExampleMatcher const* matcher,
|
||||
TRI_voc_cid_t cid,
|
||||
std::vector<TRI_doc_mptr_t>& toFilter) {
|
||||
if (matcher == nullptr) {
|
||||
return;
|
||||
}
|
||||
size_t resultCount = toFilter.size();
|
||||
for (size_t i = 0; i < resultCount; /* nothing */) {
|
||||
if (!matcher->matches(cid, &toFilter[i])) {
|
||||
toFilter.erase(toFilter.begin() + i);
|
||||
--resultCount;
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void RequestEdges(VPackSlice const& vertexSlice,
|
||||
arangodb::AqlTransaction* trx,
|
||||
std::string const& collectionName,
|
||||
|
@ -577,7 +478,6 @@ static void RequestEdges(VPackSlice const& vertexSlice,
|
|||
parts[0].c_str());
|
||||
}
|
||||
|
||||
#warning might be optimized
|
||||
VPackBuilder searchValueBuilder;
|
||||
searchValueBuilder.openArray();
|
||||
switch (direction) {
|
||||
|
@ -707,6 +607,108 @@ static void UnsetOrKeep(VPackSlice const& value,
|
|||
}
|
||||
}
|
||||
|
||||
static void RegisterCollectionInTransaction(
|
||||
arangodb::AqlTransaction* trx, std::string const& collectionName,
|
||||
TRI_voc_cid_t& cid) {
|
||||
cid = trx->resolver()->getCollectionIdLocal(collectionName);
|
||||
|
||||
if (cid == 0) {
|
||||
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, "'%s'",
|
||||
collectionName.c_str());
|
||||
}
|
||||
trx->addCollectionAtRuntime(cid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to get a document by it's identifier
|
||||
/// Lazy Locks the collection if necessary.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void GetDocumentByIdentifier(arangodb::AqlTransaction* trx,
|
||||
std::string const& collectionName,
|
||||
std::string const& identifier,
|
||||
bool ignoreError,
|
||||
VPackBuilder& result) {
|
||||
OperationOptions options;
|
||||
OperationResult opRes;
|
||||
VPackBuilder searchBuilder;
|
||||
searchBuilder.openObject();
|
||||
searchBuilder.add(VPackValue(TRI_VOC_ATTRIBUTE_KEY));
|
||||
|
||||
std::vector<std::string> parts =
|
||||
arangodb::basics::StringUtils::split(identifier, "/");
|
||||
|
||||
|
||||
if (parts.size() == 1) {
|
||||
searchBuilder.add(VPackValue(identifier));
|
||||
searchBuilder.close();
|
||||
|
||||
try {
|
||||
TRI_voc_cid_t cid;
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
opRes = trx->document(collectionName, searchBuilder.slice(), options);
|
||||
} else if (parts.size() == 2) {
|
||||
if (collectionName.empty()) {
|
||||
searchBuilder.add(VPackValue(parts[1]));
|
||||
searchBuilder.close();
|
||||
|
||||
try {
|
||||
TRI_voc_cid_t cid;
|
||||
RegisterCollectionInTransaction(trx, parts[0], cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
opRes = trx->document(parts[0], searchBuilder.slice(), options);
|
||||
} else if (parts[0] != collectionName) {
|
||||
// Reqesting an _id that cannot be stored in this collection
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST);
|
||||
} else {
|
||||
searchBuilder.add(VPackValue(parts[1]));
|
||||
searchBuilder.close();
|
||||
|
||||
try {
|
||||
TRI_voc_cid_t cid;
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
opRes = trx->document(collectionName, searchBuilder.slice(), options);
|
||||
}
|
||||
} else {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
||||
}
|
||||
if (opRes.failed()) {
|
||||
if (ignoreError) {
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(opRes.code);
|
||||
}
|
||||
|
||||
result.add(opRes.slice());
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to merge given parameters
|
||||
/// Works for an array of objects as first parameter or arbitrary many
|
||||
|
@ -784,63 +786,25 @@ static AqlValue$ MergeParameters(arangodb::aql::Query* query,
|
|||
return AqlValue$(b);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transforms VertexId to VelocyPack
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void VertexIdToVPack(arangodb::AqlTransaction* trx,
|
||||
CollectionNameResolver const* resolver,
|
||||
VertexId const& id,
|
||||
VPackBuilder& b) {
|
||||
trx->addCollectionAtRuntime(id.cid);
|
||||
|
||||
OperationOptions options;
|
||||
|
||||
VPackSlice slice;
|
||||
#warning fill slice from id.key
|
||||
OperationResult opRes = trx->document(trx->collectionName(id.cid), slice, options);
|
||||
#warning fill mptr
|
||||
int res = opRes.code;
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
if (res == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) {
|
||||
b.add(VPackValue(VPackValueType::Null));
|
||||
return;
|
||||
}
|
||||
THROW_ARANGO_EXCEPTION(res);
|
||||
}
|
||||
|
||||
#warning convert to vpack
|
||||
b.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transforms VertexId to std::string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static std::string VertexIdToString(CollectionNameResolver const* resolver,
|
||||
VertexId const& id) {
|
||||
return resolver->getCollectionName(id.cid) + "/" + std::string(id.key);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Transforms an unordered_map<VertexId> to AQL VelocyPack values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static AqlValue$ VertexIdsToAqlValueVPack(
|
||||
arangodb::aql::Query* query, arangodb::AqlTransaction* trx,
|
||||
CollectionNameResolver const* resolver, std::unordered_set<VertexId>& ids,
|
||||
bool includeData = false) {
|
||||
static AqlValue$ VertexIdsToAqlValueVPack(arangodb::aql::Query* query,
|
||||
arangodb::AqlTransaction* trx,
|
||||
std::unordered_set<std::string>& ids,
|
||||
bool includeData = false) {
|
||||
std::shared_ptr<VPackBuilder> result = query->getSharedBuilder();
|
||||
{
|
||||
VPackArrayBuilder b(result.get());
|
||||
if (includeData) {
|
||||
for (auto& it : ids) {
|
||||
VertexIdToVPack(trx, resolver, it, *result);
|
||||
// THROWS ERRORS if the Document was not found
|
||||
GetDocumentByIdentifier(trx, "", it, false, *result);
|
||||
}
|
||||
} else {
|
||||
for (auto& it : ids) {
|
||||
result->add(VPackValue(VertexIdToString(resolver, it)));
|
||||
result->add(VPackValue(it));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -884,12 +848,9 @@ static arangodb::Index* getGeoIndex(arangodb::AqlTransaction* trx,
|
|||
}
|
||||
|
||||
static AqlValue$ buildGeoResult(arangodb::aql::Query* query,
|
||||
GeoCoordinates* cors, VocShaper* shaper,
|
||||
CollectionNameResolver const* resolver,
|
||||
GeoCoordinates* cors,
|
||||
TRI_voc_cid_t const& cid,
|
||||
std::string const& attributeName) {
|
||||
// TODO FIXME
|
||||
// note: shaper will always be nullptr here...
|
||||
if (cors == nullptr) {
|
||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
{
|
||||
|
@ -944,19 +905,22 @@ static AqlValue$ buildGeoResult(arangodb::aql::Query* query,
|
|||
try {
|
||||
VPackArrayBuilder guard(b.get());
|
||||
std::unordered_set<std::string> forbidden;
|
||||
bool saveAttr = !attributeName.empty();
|
||||
if (saveAttr) {
|
||||
forbidden.emplace(attributeName);
|
||||
}
|
||||
|
||||
for (auto& it : distances) {
|
||||
#warning convert to vpack
|
||||
ExpandShapedJson(shaper, resolver, cid, it._mptr, *b,
|
||||
saveAttr, forbidden);
|
||||
if (saveAttr) {
|
||||
// The Object is Open and attributeName is not set
|
||||
if (!attributeName.empty()) {
|
||||
// We have to copy the entire document
|
||||
for (auto& it : distances) {
|
||||
VPackObjectBuilder docGuard(b.get());
|
||||
b->add(attributeName, VPackValue(it._distance));
|
||||
b->close();
|
||||
VPackSlice doc(it._mptr->vpack());
|
||||
for (auto const& entry : VPackObjectIterator(doc)) {
|
||||
std::string key = entry.key.copyString();
|
||||
if (key != attributeName) {
|
||||
b->add(key, entry.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (auto& it : distances) {
|
||||
InsertMasterPointer(it._mptr, *b);
|
||||
}
|
||||
}
|
||||
} catch (...) {
|
||||
|
@ -2384,7 +2348,7 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
|
|||
if (n > 4) {
|
||||
auto edgeExamples = ExtractFunctionParameter(trx, parameters, 4);
|
||||
if (!(edgeExamples.isArray() && edgeExamples.length() == 0)) {
|
||||
opts.addEdgeFilter(edgeExamples, eci->getShaper(), eCid, resolver);
|
||||
opts.addEdgeFilter(edgeExamples, eCid);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2401,10 +2365,10 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||
}
|
||||
|
||||
std::unordered_set<VertexId> neighbors;
|
||||
TRI_RunNeighborsSearch(edgeCollectionInfos, opts, neighbors);
|
||||
std::unordered_set<std::string> neighbors;
|
||||
#warning TRI_RunNeighborsSearch(edgeCollectionInfos, opts, neighbors);
|
||||
|
||||
return VertexIdsToAqlValueVPack(query, trx, resolver, neighbors, includeData);
|
||||
return VertexIdsToAqlValueVPack(query, trx, neighbors, includeData);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2478,7 +2442,7 @@ AqlValue$ Functions::Near(arangodb::aql::Query* query,
|
|||
trx, latitude.getNumericValue<double>(),
|
||||
longitude.getNumericValue<double>(), limitValue);
|
||||
|
||||
return buildGeoResult(query, cors, nullptr, resolver, cid, attributeName);
|
||||
return buildGeoResult(query, cors, cid, attributeName);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2540,7 +2504,7 @@ AqlValue$ Functions::Within(arangodb::aql::Query* query,
|
|||
trx, latitude.getNumericValue<double>(),
|
||||
longitude.getNumericValue<double>(), radius.getNumericValue<double>());
|
||||
|
||||
return buildGeoResult(query, cors, nullptr, resolver, cid, attributeName);
|
||||
return buildGeoResult(query, cors, cid, attributeName);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2745,103 +2709,6 @@ AqlValue$ Functions::Minus(arangodb::aql::Query* query,
|
|||
return AqlValue$(b.get());
|
||||
}
|
||||
|
||||
static void RegisterCollectionInTransaction(
|
||||
arangodb::AqlTransaction* trx, std::string const& collectionName,
|
||||
TRI_voc_cid_t& cid) {
|
||||
cid = trx->resolver()->getCollectionIdLocal(collectionName);
|
||||
|
||||
if (cid == 0) {
|
||||
THROW_ARANGO_EXCEPTION_FORMAT(TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND, "'%s'",
|
||||
collectionName.c_str());
|
||||
}
|
||||
trx->addCollectionAtRuntime(cid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to get a document by it's identifier
|
||||
/// The collection has to be locked by the transaction before
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void GetDocumentByIdentifier(arangodb::AqlTransaction* trx,
|
||||
std::string const& collectionName,
|
||||
std::string const& identifier,
|
||||
VPackBuilder& result) {
|
||||
OperationOptions options;
|
||||
|
||||
std::vector<std::string> parts =
|
||||
arangodb::basics::StringUtils::split(identifier, "/");
|
||||
|
||||
if (parts.size() == 1) {
|
||||
VPackSlice slice;
|
||||
#warning fill slice from parts[0]
|
||||
OperationResult opRes = trx->document(collectionName, slice, options);
|
||||
#warning fill mptr
|
||||
if (!opRes.successful()) {
|
||||
return;
|
||||
}
|
||||
} else if (parts.size() == 2) {
|
||||
if (parts[0] != collectionName) {
|
||||
// Reqesting an _id that cannot be stored in this collection
|
||||
return;
|
||||
}
|
||||
VPackSlice slice;
|
||||
#warning fill slice from parts[1]
|
||||
OperationResult opRes = trx->document(collectionName, slice, options);
|
||||
#warning fill mptr
|
||||
if (!opRes.successful()) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
#warning convert to vpack
|
||||
result.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Helper function to get a document by its _id
|
||||
/// This function will lazy read-lock the collection.
|
||||
/// this function will not throw if the document or the collection cannot be
|
||||
/// found
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void GetDocumentByIdentifier(arangodb::AqlTransaction* trx,
|
||||
std::string const& identifier,
|
||||
VPackBuilder& result) {
|
||||
std::vector<std::string> parts =
|
||||
arangodb::basics::StringUtils::split(identifier, "/");
|
||||
|
||||
if (parts.size() != 2) {
|
||||
return;
|
||||
}
|
||||
std::string collectionName = parts[0];
|
||||
TRI_voc_cid_t cid = 0;
|
||||
try {
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
// don't throw if collection is not found
|
||||
if (ex.code() == TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
|
||||
return;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
OperationOptions options;
|
||||
|
||||
VPackSlice slice;
|
||||
#warning fill slice from parts[1]
|
||||
OperationResult opRes = trx->document(collectionName, slice, options);
|
||||
#warning fill mptr
|
||||
|
||||
if (opRes.code != TRI_ERROR_NO_ERROR) {
|
||||
return;
|
||||
}
|
||||
|
||||
#warning convert opRes result to vpack external
|
||||
result.add(VPackValue(static_cast<void const*>(nullptr), VPackValueType::External));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief function Document
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2862,7 +2729,7 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
if (id.isString()) {
|
||||
std::string identifier = id.copyString();
|
||||
GetDocumentByIdentifier(trx, identifier, *b);
|
||||
GetDocumentByIdentifier(trx, "", identifier, true, *b);
|
||||
if (b->isEmpty()) {
|
||||
// not found
|
||||
b->add(VPackValue(VPackValueType::Null));
|
||||
|
@ -2870,13 +2737,9 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
} else if (id.isArray()) {
|
||||
VPackArrayBuilder guard(b.get());
|
||||
for (auto const& next : VPackArrayIterator(id)) {
|
||||
try {
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, identifier, *b);
|
||||
}
|
||||
} catch (arangodb::basics::Exception const&) {
|
||||
// Ignore all ArangoDB exceptions here
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, "", identifier, true, *b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2891,19 +2754,8 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
}
|
||||
std::string collectionName = collectionSlice.copyString();
|
||||
|
||||
TRI_voc_cid_t cid;
|
||||
bool notFound = false;
|
||||
|
||||
try {
|
||||
RegisterCollectionInTransaction(trx, collectionName, cid);
|
||||
} catch (arangodb::basics::Exception const& ex) {
|
||||
// don't throw if collection is not found
|
||||
if (ex.code() != TRI_ERROR_ARANGO_COLLECTION_NOT_FOUND) {
|
||||
throw;
|
||||
}
|
||||
notFound = true;
|
||||
}
|
||||
|
||||
VPackSlice id = ExtractFunctionParameter(trx, parameters, 1);
|
||||
if (id.isString()) {
|
||||
if (notFound) {
|
||||
|
@ -2913,7 +2765,7 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
}
|
||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
std::string identifier = id.copyString();
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, *b);
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, true, *b);
|
||||
if (b->isEmpty()) {
|
||||
b->add(VPackValue(VPackValueType::Null));
|
||||
}
|
||||
|
@ -2924,13 +2776,9 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
|||
VPackArrayBuilder guard(b.get());
|
||||
if (!notFound) {
|
||||
for (auto const& next : VPackArrayIterator(id)) {
|
||||
try {
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, *b);
|
||||
}
|
||||
} catch (arangodb::basics::Exception const&) {
|
||||
// Ignore all ArangoDB exceptions here
|
||||
if (next.isString()) {
|
||||
std::string identifier = next.copyString();
|
||||
GetDocumentByIdentifier(trx, collectionName, identifier, true, *b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3014,8 +2862,6 @@ AqlValue$ Functions::Edges(arangodb::aql::Query* query,
|
|||
return AqlValue$(b.get());
|
||||
}
|
||||
|
||||
auto resolver = trx->resolver();
|
||||
|
||||
std::unique_ptr<arangodb::ExampleMatcher> matcher;
|
||||
|
||||
TRI_document_collection_t* documentCollection = trx->documentCollection(cid);
|
||||
|
@ -3029,7 +2875,7 @@ AqlValue$ Functions::Edges(arangodb::aql::Query* query,
|
|||
if ((exampleSlice.isArray() && exampleSlice.length() != 0)|| exampleSlice.isObject()) {
|
||||
try {
|
||||
matcher.reset(
|
||||
new arangodb::ExampleMatcher(exampleSlice, resolver, false));
|
||||
new arangodb::ExampleMatcher(exampleSlice, false));
|
||||
} catch (arangodb::basics::Exception const& e) {
|
||||
if (e.code() != TRI_RESULT_ELEMENT_NOT_FOUND) {
|
||||
throw;
|
||||
|
@ -4361,7 +4207,6 @@ AqlValue$ Functions::Fulltext(arangodb::aql::Query* query,
|
|||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||
}
|
||||
|
||||
auto shaper = document->getShaper();
|
||||
size_t const numResults = queryResult->_numDocuments;
|
||||
|
||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||
|
@ -4369,11 +4214,8 @@ AqlValue$ Functions::Fulltext(arangodb::aql::Query* query,
|
|||
VPackArrayBuilder guard(b.get());
|
||||
|
||||
for (size_t i = 0; i < numResults; ++i) {
|
||||
std::unordered_set<std::string> unused;
|
||||
#warning convert to vpack
|
||||
ExpandShapedJson(shaper, resolver, cid,
|
||||
(TRI_doc_mptr_t const*)queryResult->_documents[i], *b,
|
||||
false, unused);
|
||||
InsertMasterPointer((TRI_doc_mptr_t const*)queryResult->_documents[i],
|
||||
*b);
|
||||
}
|
||||
} catch (...) {
|
||||
TRI_FreeResultFulltextIndex(queryResult);
|
||||
|
|
|
@ -81,25 +81,29 @@ HttpHandler::status_t RestDocumentHandler::execute() {
|
|||
bool RestDocumentHandler::createDocument() {
|
||||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
if (!suffix.empty()) {
|
||||
if (suffix.size() > 1) {
|
||||
generateError(HttpResponse::BAD, TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||
"superfluous suffix, expecting " + DOCUMENT_PATH +
|
||||
"?collection=<identifier>");
|
||||
return false;
|
||||
}
|
||||
|
||||
// extract the cid
|
||||
bool found;
|
||||
char const* collection = _request->value("collection", found);
|
||||
std::string collectionName;
|
||||
if (suffix.size() == 1) {
|
||||
collectionName = suffix[0];
|
||||
found = true;
|
||||
} else {
|
||||
collectionName = _request->value("collection", found);
|
||||
}
|
||||
|
||||
if (!found || *collection == '\0') {
|
||||
if (!found || collectionName.empty()) {
|
||||
generateError(HttpResponse::BAD,
|
||||
TRI_ERROR_ARANGO_COLLECTION_PARAMETER_MISSING,
|
||||
"'collection' is missing, expecting " + DOCUMENT_PATH +
|
||||
"?collection=<identifier>");
|
||||
"/<collectionname> or query parameter 'collection'");
|
||||
return false;
|
||||
}
|
||||
std::string collectionName(collection);
|
||||
|
||||
bool parseSuccess = true;
|
||||
// copy default options
|
||||
|
@ -111,28 +115,23 @@ bool RestDocumentHandler::createDocument() {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* TODO
|
||||
if (!checkCreateCollection(collection, getCollectionType())) {
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
// find and load collection given by name or identifier
|
||||
SingleCollectionTransaction trx(StandaloneTransactionContext::Create(_vocbase),
|
||||
collection, TRI_TRANSACTION_WRITE);
|
||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||
collectionName, TRI_TRANSACTION_WRITE);
|
||||
VPackSlice body = parsedBody->slice();
|
||||
if (!body.isArray()) {
|
||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||
}
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
generateTransactionError(collection, res, "");
|
||||
generateTransactionError(collectionName, res, "");
|
||||
return false;
|
||||
}
|
||||
|
||||
arangodb::OperationOptions opOptions;
|
||||
opOptions.waitForSync = extractWaitForSync();
|
||||
VPackSlice body = parsedBody->slice();
|
||||
arangodb::OperationResult result = trx.insert(collectionName, body, opOptions);
|
||||
|
||||
// Will commit if no error occured.
|
||||
|
@ -165,12 +164,8 @@ bool RestDocumentHandler::readDocument() {
|
|||
|
||||
switch (len) {
|
||||
case 0:
|
||||
return readAllDocuments();
|
||||
|
||||
case 1:
|
||||
generateError(HttpResponse::BAD, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD,
|
||||
"expecting GET /_api/document/<document-handle>");
|
||||
return false;
|
||||
return readAllDocuments();
|
||||
|
||||
case 2:
|
||||
return readSingleDocument(true);
|
||||
|
@ -227,9 +222,9 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
|||
collection, TRI_TRANSACTION_READ);
|
||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||
|
||||
// .............................................................................
|
||||
// ...........................................................................
|
||||
// inside read transaction
|
||||
// .............................................................................
|
||||
// ...........................................................................
|
||||
|
||||
int res = trx.begin();
|
||||
|
||||
|
@ -239,6 +234,7 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
|||
}
|
||||
|
||||
OperationOptions options;
|
||||
options.ignoreRevs = false;
|
||||
OperationResult result = trx.document(collection, search, options);
|
||||
|
||||
res = trx.finish(result.code);
|
||||
|
@ -260,9 +256,7 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
|||
return false;
|
||||
}
|
||||
|
||||
TRI_voc_rid_t const rid =
|
||||
VelocyPackHelper::getNumericValue<TRI_voc_rid_t>(
|
||||
result.slice(), TRI_VOC_ATTRIBUTE_REV, 0);
|
||||
TRI_voc_rid_t const rid = TRI_extractRevisionId(result.slice());
|
||||
if (ifNoneRid != 0 && ifNoneRid == rid) {
|
||||
generateNotModified(rid);
|
||||
} else {
|
||||
|
@ -280,7 +274,14 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
|||
|
||||
bool RestDocumentHandler::readAllDocuments() {
|
||||
bool found;
|
||||
std::string const collectionName = _request->value("collection", found);
|
||||
std::string collectionName;
|
||||
|
||||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
if (suffix.size() == 1) {
|
||||
collectionName = suffix[0];
|
||||
} else {
|
||||
collectionName = _request->value("collection", found);
|
||||
}
|
||||
std::string returnType = _request->value("type", found);
|
||||
|
||||
if (returnType.empty()) {
|
||||
|
|
|
@ -150,9 +150,9 @@ void RestVocbaseBaseHandler::generateSaved(
|
|||
arangodb::OperationResult const& result, std::string const& collectionName,
|
||||
TRI_col_type_e type) {
|
||||
if (result.wasSynchronous) {
|
||||
createResponse(rest::HttpResponse::ACCEPTED);
|
||||
} else {
|
||||
createResponse(rest::HttpResponse::CREATED);
|
||||
} else {
|
||||
createResponse(rest::HttpResponse::ACCEPTED);
|
||||
}
|
||||
generate20x(result, collectionName, type);
|
||||
}
|
||||
|
|
|
@ -366,6 +366,21 @@ class CollectionNameResolver {
|
|||
buffer.appendText("_unknown");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return collection name if given string is either the name or
|
||||
/// a string with the (numerical) collection id, this returns the cluster
|
||||
/// wide collection name in the DBserver case
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string getCollectionName(std::string const& nameOrId) const {
|
||||
if (!nameOrId.empty() &&
|
||||
(nameOrId[0] < '0' || nameOrId[0] > '9')) {
|
||||
return nameOrId;
|
||||
}
|
||||
TRI_voc_cid_t tmp = arangodb::basics::StringUtils::uint64(nameOrId);
|
||||
return getCollectionName(tmp);
|
||||
}
|
||||
|
||||
private:
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief vocbase base pointer
|
||||
|
|
|
@ -198,25 +198,6 @@ std::string Transaction::extractKey(VPackSlice const slice) {
|
|||
return "";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the _rev attribute from a slice
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_rid_t Transaction::extractRevisionId(VPackSlice const slice) {
|
||||
TRI_ASSERT(slice.isObject());
|
||||
|
||||
VPackSlice r(slice.get(TRI_VOC_ATTRIBUTE_REV));
|
||||
if (r.isString()) {
|
||||
VPackValueLength length;
|
||||
char const* p = r.getString(length);
|
||||
return arangodb::basics::StringUtils::uint64(p, length);
|
||||
}
|
||||
if (r.isInteger()) {
|
||||
return r.getNumber<TRI_voc_rid_t>();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the _id attribute from a slice, and convert it into a
|
||||
/// string
|
||||
|
@ -575,7 +556,7 @@ OperationResult Transaction::documentCoordinator(std::string const& collectionNa
|
|||
if (key.empty()) {
|
||||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
||||
}
|
||||
TRI_voc_rid_t expectedRevision = Transaction::extractRevisionId(value);
|
||||
TRI_voc_rid_t expectedRevision = TRI_extractRevisionId(value);
|
||||
|
||||
int res = arangodb::getDocumentOnCoordinator(
|
||||
_vocbase->_name, collectionName, key, expectedRevision, headers, true,
|
||||
|
@ -636,7 +617,7 @@ OperationResult Transaction::documentLocal(std::string const& collectionName,
|
|||
|
||||
TRI_voc_rid_t expectedRevision = 0;
|
||||
if (!options.ignoreRevs) {
|
||||
expectedRevision = Transaction::extractRevisionId(value);
|
||||
expectedRevision = TRI_extractRevisionId(value);
|
||||
}
|
||||
|
||||
TRI_doc_mptr_t mptr;
|
||||
|
@ -654,6 +635,8 @@ OperationResult Transaction::documentLocal(std::string const& collectionName,
|
|||
}
|
||||
|
||||
if (!options.silent) {
|
||||
//resultBuilder.add(VPackValue(static_cast<void const*>(mptr.vpack()), VPackValueType::External));
|
||||
// This is the future, for now, we have to do this:
|
||||
resultBuilder.add(VPackSlice(mptr.vpack()));
|
||||
}
|
||||
|
||||
|
@ -950,7 +933,7 @@ OperationResult Transaction::updateCoordinator(std::string const& collectionName
|
|||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
||||
}
|
||||
TRI_voc_rid_t const expectedRevision
|
||||
= options.ignoreRevs ? 0 : Transaction::extractRevisionId(newValue);
|
||||
= options.ignoreRevs ? 0 : TRI_extractRevisionId(newValue);
|
||||
|
||||
int res = arangodb::modifyDocumentOnCoordinator(
|
||||
_vocbase->_name, collectionName, key, expectedRevision,
|
||||
|
@ -1038,7 +1021,7 @@ OperationResult Transaction::replaceCoordinator(std::string const& collectionNam
|
|||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
||||
}
|
||||
TRI_voc_rid_t const expectedRevision
|
||||
= options.ignoreRevs ? 0 : Transaction::extractRevisionId(newValue);
|
||||
= options.ignoreRevs ? 0 : TRI_extractRevisionId(newValue);
|
||||
|
||||
int res = arangodb::modifyDocumentOnCoordinator(
|
||||
_vocbase->_name, collectionName, key, expectedRevision,
|
||||
|
@ -1206,7 +1189,7 @@ OperationResult Transaction::removeCoordinator(std::string const& collectionName
|
|||
if (key.empty()) {
|
||||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
||||
}
|
||||
TRI_voc_rid_t expectedRevision = Transaction::extractRevisionId(value);
|
||||
TRI_voc_rid_t expectedRevision = TRI_extractRevisionId(value);
|
||||
|
||||
int res = arangodb::deleteDocumentOnCoordinator(
|
||||
_vocbase->_name, collectionName, key, expectedRevision,
|
||||
|
@ -1309,16 +1292,18 @@ OperationResult Transaction::allKeys(std::string const& collectionName,
|
|||
|
||||
std::string prefix;
|
||||
|
||||
std::string realCollName = resolver()->getCollectionName(collectionName);
|
||||
|
||||
if (type == "key") {
|
||||
prefix = "";
|
||||
} else if (type == "id") {
|
||||
prefix = collectionName + "/";
|
||||
prefix = realCollName + "/";
|
||||
} else {
|
||||
// default return type: paths to documents
|
||||
if (isEdgeCollection(collectionName)) {
|
||||
prefix = std::string("/_db/") + _vocbase->_name + "/_api/edge/" + collectionName + "/";
|
||||
prefix = std::string("/_db/") + _vocbase->_name + "/_api/edge/" + realCollName + "/";
|
||||
} else {
|
||||
prefix = std::string("/_db/") + _vocbase->_name + "/_api/document/" + collectionName + "/";
|
||||
prefix = std::string("/_db/") + _vocbase->_name + "/_api/document/" + realCollName + "/";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -216,12 +216,6 @@ class Transaction {
|
|||
|
||||
static std::string extractKey(VPackSlice const);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the _rev attribute from a slice
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_voc_rid_t extractRevisionId(VPackSlice const);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the _id attribute from a slice, and convert it into a
|
||||
/// string
|
||||
|
|
|
@ -248,13 +248,12 @@ bool BasicOptions::matchesVertex(VertexId const& v) const {
|
|||
// OperationResult opRes = trx->document(it->second.col, slice, options);
|
||||
OperationResult opRes(TRI_ERROR_INTERNAL);
|
||||
#warning fill vertex
|
||||
TRI_doc_mptr_t vertex;
|
||||
|
||||
if (!opRes.successful()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return it->second.matcher->matches(v.cid, &vertex);
|
||||
return it->second.matcher->matches(opRes.slice());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -302,13 +301,12 @@ void BasicOptions::addEdgeFilter(Json const& example, VocShaper* shaper,
|
|||
/// @brief Insert a new edge matcher object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BasicOptions::addEdgeFilter(VPackSlice const& example, VocShaper* shaper,
|
||||
TRI_voc_cid_t const& cid,
|
||||
CollectionNameResolver const* resolver) {
|
||||
void BasicOptions::addEdgeFilter(VPackSlice const& example,
|
||||
TRI_voc_cid_t const& cid) {
|
||||
useEdgeFilter = true;
|
||||
auto it = _edgeFilter.find(cid);
|
||||
if (it == _edgeFilter.end()) {
|
||||
_edgeFilter.emplace(cid, new ExampleMatcher(example, resolver, true));
|
||||
_edgeFilter.emplace(cid, new ExampleMatcher(example, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +330,7 @@ bool BasicOptions::matchesEdge(EdgeId& e, TRI_doc_mptr_t* edge) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
return it->second->matches(e.cid, edge);
|
||||
return it->second->matches(VPackSlice(edge->vpack()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -121,9 +121,8 @@ struct BasicOptions {
|
|||
TRI_voc_cid_t const& cid,
|
||||
arangodb::CollectionNameResolver const* resolver);
|
||||
|
||||
void addEdgeFilter(arangodb::velocypack::Slice const& example, VocShaper* shaper,
|
||||
TRI_voc_cid_t const& cid,
|
||||
arangodb::CollectionNameResolver const* resolver);
|
||||
void addEdgeFilter(arangodb::velocypack::Slice const& example,
|
||||
TRI_voc_cid_t const& cid);
|
||||
|
||||
void addVertexFilter(v8::Isolate* isolate,
|
||||
v8::Handle<v8::Value> const& example,
|
||||
|
|
|
@ -526,12 +526,13 @@ static void DocumentVocbase(
|
|||
LocalCollectionGuard g(const_cast<TRI_vocbase_col_t*>(col));
|
||||
|
||||
TRI_ASSERT(col != nullptr);
|
||||
|
||||
TRI_ASSERT(!collectionName.empty());
|
||||
|
||||
VPackSlice search = builder.slice();
|
||||
TRI_ASSERT(search.isObject());
|
||||
|
||||
SingleCollectionTransaction trx(transactionContext, collectionName, TRI_TRANSACTION_READ);
|
||||
SingleCollectionTransaction trx(transactionContext, collectionName,
|
||||
TRI_TRANSACTION_READ);
|
||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||
|
||||
int res = trx.begin();
|
||||
|
@ -564,11 +565,121 @@ static void DocumentVocbase(
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deletes a document, using a VPack marker
|
||||
/// @brief deletes (a) document(s), collection method
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void RemoveVocbaseVPack(
|
||||
bool useCollection, v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
static void RemoveVocbaseCol(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
OperationOptions options;
|
||||
options.ignoreRevs = false;
|
||||
|
||||
// check the arguments
|
||||
uint32_t const argLength = args.Length();
|
||||
|
||||
TRI_GET_GLOBALS();
|
||||
|
||||
if (argLength < 1 || argLength > 3) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("remove(<document>, <options>)");
|
||||
}
|
||||
|
||||
if (argLength > 1) {
|
||||
if (args[1]->IsObject()) {
|
||||
v8::Handle<v8::Object> optionsObject = args[1].As<v8::Object>();
|
||||
TRI_GET_GLOBAL_STRING(OverwriteKey);
|
||||
if (optionsObject->Has(OverwriteKey)) {
|
||||
options.ignoreRevs = TRI_ObjectToBoolean(optionsObject->Get(OverwriteKey));
|
||||
}
|
||||
TRI_GET_GLOBAL_STRING(WaitForSyncKey);
|
||||
if (optionsObject->Has(WaitForSyncKey)) {
|
||||
options.waitForSync =
|
||||
TRI_ObjectToBoolean(optionsObject->Get(WaitForSyncKey));
|
||||
}
|
||||
} else { // old variant remove(<document>, <overwrite>, <waitForSync>)
|
||||
options.ignoreRevs = TRI_ObjectToBoolean(args[1]);
|
||||
if (argLength > 2) {
|
||||
options.waitForSync = TRI_ObjectToBoolean(args[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find collection and vocbase
|
||||
std::string collectionName;
|
||||
TRI_vocbase_col_t const* col
|
||||
= TRI_UnwrapClass<TRI_vocbase_col_t>(args.Holder(), WRP_VOCBASE_COL_TYPE);
|
||||
if (col == nullptr) {
|
||||
TRI_V8_THROW_EXCEPTION_INTERNAL("cannot extract collection");
|
||||
}
|
||||
TRI_vocbase_t* vocbase = col->_vocbase;
|
||||
collectionName = col->name();
|
||||
if (vocbase == nullptr) {
|
||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
auto transactionContext = std::make_shared<V8TransactionContext>(vocbase, true);
|
||||
|
||||
SingleCollectionTransaction trx(transactionContext, collectionName, TRI_TRANSACTION_WRITE);
|
||||
if (!args[0]->IsArray()) {
|
||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||
}
|
||||
|
||||
int res = trx.begin();
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_THROW_EXCEPTION(res);
|
||||
}
|
||||
|
||||
VPackBuilder searchBuilder;
|
||||
|
||||
auto workOnOneDocument = [&](v8::Local<v8::Value> const searchValue) {
|
||||
std::string collName;
|
||||
if (!ExtractDocumentHandle(isolate, searchValue, collName, searchBuilder,
|
||||
true)) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD);
|
||||
}
|
||||
if (!collName.empty() && collName != collectionName) {
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_ARANGO_CROSS_COLLECTION_REQUEST);
|
||||
}
|
||||
};
|
||||
|
||||
if (!args[0]->IsArray()) {
|
||||
VPackObjectBuilder guard(&searchBuilder);
|
||||
workOnOneDocument(args[0]);
|
||||
} else {
|
||||
VPackArrayBuilder guard(&searchBuilder);
|
||||
auto searchVals = v8::Local<v8::Array>::Cast(args[0]);
|
||||
for (uint32_t i = 0; i < searchVals->Length(); ++i) {
|
||||
VPackObjectBuilder guard(&searchBuilder);
|
||||
workOnOneDocument(searchVals->Get(i));
|
||||
}
|
||||
}
|
||||
|
||||
VPackSlice toRemove = searchBuilder.slice();
|
||||
|
||||
OperationResult result = trx.remove(collectionName, toRemove, options);
|
||||
|
||||
res = trx.finish(result.code);
|
||||
|
||||
if (!result.successful()) {
|
||||
if (result.code == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND &&
|
||||
options.ignoreRevs && !args[0]->IsArray()) {
|
||||
TRI_V8_RETURN_FALSE();
|
||||
} else {
|
||||
TRI_V8_THROW_EXCEPTION(result.code);
|
||||
}
|
||||
}
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
TRI_V8_THROW_EXCEPTION(res);
|
||||
}
|
||||
|
||||
TRI_V8_RETURN_TRUE();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deletes a document, database method
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void RemoveVocbase(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
v8::Isolate* isolate = args.GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
OperationOptions options;
|
||||
|
@ -607,34 +718,16 @@ static void RemoveVocbaseVPack(
|
|||
TRI_vocbase_t* vocbase;
|
||||
TRI_vocbase_col_t const* col = nullptr;
|
||||
|
||||
if (useCollection) {
|
||||
// called as db.collection.remove()
|
||||
col =
|
||||
TRI_UnwrapClass<TRI_vocbase_col_t>(args.Holder(), WRP_VOCBASE_COL_TYPE);
|
||||
|
||||
if (col == nullptr) {
|
||||
TRI_V8_THROW_EXCEPTION_INTERNAL("cannot extract collection");
|
||||
}
|
||||
|
||||
vocbase = col->_vocbase;
|
||||
} else {
|
||||
// called as db._remove()
|
||||
vocbase = GetContextVocBase(isolate);
|
||||
}
|
||||
|
||||
vocbase = GetContextVocBase(isolate);
|
||||
if (vocbase == nullptr) {
|
||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
auto transactionContext = std::make_shared<V8TransactionContext>(vocbase, true);
|
||||
|
||||
VPackBuilder builder;
|
||||
std::string collectionName;
|
||||
|
||||
LocalCollectionGuard g(useCollection ? nullptr
|
||||
: const_cast<TRI_vocbase_col_t*>(col));
|
||||
|
||||
{ VPackObjectBuilder guard(&builder);
|
||||
int res = ParseDocumentOrDocumentHandle(
|
||||
isolate, vocbase, transactionContext->getResolver(), col, collectionName, builder,
|
||||
|
@ -645,10 +738,16 @@ static void RemoveVocbaseVPack(
|
|||
}
|
||||
}
|
||||
|
||||
LocalCollectionGuard g(const_cast<TRI_vocbase_col_t*>(col));
|
||||
|
||||
TRI_ASSERT(col != nullptr);
|
||||
TRI_ASSERT(!collectionName.empty());
|
||||
|
||||
VPackSlice toRemove = builder.slice();
|
||||
TRI_ASSERT(toRemove.isObject());
|
||||
|
||||
SingleCollectionTransaction trx(transactionContext, collectionName, TRI_TRANSACTION_WRITE);
|
||||
SingleCollectionTransaction trx(transactionContext, collectionName,
|
||||
TRI_TRANSACTION_WRITE);
|
||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||
|
||||
int res = trx.begin();
|
||||
|
@ -662,7 +761,8 @@ static void RemoveVocbaseVPack(
|
|||
res = trx.finish(result.code);
|
||||
|
||||
if (!result.successful()) {
|
||||
if (result.code == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND && options.ignoreRevs) {
|
||||
if (result.code == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND &&
|
||||
options.ignoreRevs) {
|
||||
TRI_V8_RETURN_FALSE();
|
||||
} else {
|
||||
TRI_V8_THROW_EXCEPTION(result.code);
|
||||
|
@ -1329,10 +1429,10 @@ static void JS_PropertiesVocbaseCol(
|
|||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
static void JS_RemoveVocbaseVPack(
|
||||
static void JS_RemoveVocbaseCol(
|
||||
v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
return RemoveVocbaseVPack(true, args);
|
||||
return RemoveVocbaseCol(args);
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
|
@ -2615,7 +2715,7 @@ static void JS_CompletionsVocbase(
|
|||
|
||||
static void JS_RemoveVocbase(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
return RemoveVocbaseVPack(false, args);
|
||||
return RemoveVocbase(args);
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
|
@ -2921,7 +3021,7 @@ void TRI_InitV8collection(v8::Handle<v8::Context> context, TRI_server_t* server,
|
|||
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("properties"),
|
||||
JS_PropertiesVocbaseCol);
|
||||
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("remove"),
|
||||
JS_RemoveVocbaseVPack);
|
||||
JS_RemoveVocbaseCol);
|
||||
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("revision"),
|
||||
JS_RevisionVocbaseCol);
|
||||
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("rename"),
|
||||
|
|
|
@ -75,7 +75,7 @@ void ExampleMatcher::fillExampleDefinition(
|
|||
}
|
||||
|
||||
void ExampleMatcher::fillExampleDefinition(
|
||||
VPackSlice const& example, CollectionNameResolver const* resolver,
|
||||
VPackSlice const& example,
|
||||
ExampleDefinition& def) {
|
||||
TRI_ASSERT(def._values.isEmpty());
|
||||
VPackArrayBuilder guard(&def._values);
|
||||
|
@ -166,11 +166,10 @@ ExampleMatcher::ExampleMatcher(TRI_json_t const* example,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
||||
CollectionNameResolver const* resolver,
|
||||
bool allowStrings) {
|
||||
if (example.isObject() || example.isString()) {
|
||||
ExampleDefinition def;
|
||||
ExampleMatcher::fillExampleDefinition(example, resolver, def);
|
||||
ExampleMatcher::fillExampleDefinition(example, def);
|
||||
definitions.emplace_back(std::move(def));
|
||||
} else if (example.isArray()) {
|
||||
for (auto const& e : VPackArrayIterator(example)) {
|
||||
|
@ -179,7 +178,7 @@ ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
|||
// We do not match strings in Array
|
||||
continue;
|
||||
}
|
||||
ExampleMatcher::fillExampleDefinition(e, resolver, def);
|
||||
ExampleMatcher::fillExampleDefinition(e, def);
|
||||
definitions.emplace_back(std::move(def));
|
||||
}
|
||||
if (definitions.empty()) {
|
||||
|
@ -190,16 +189,11 @@ ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Checks if the given mptr matches the examples in this class
|
||||
/// @brief Checks if the given velocyPack matches the examples in this class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ExampleMatcher::matches(TRI_voc_cid_t, TRI_doc_mptr_t const* mptr) const {
|
||||
if (mptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
VPackSlice toMatch(mptr->vpack());
|
||||
bool ExampleMatcher::matches(VPackSlice const toMatch) const {
|
||||
for (auto const& def : definitions) {
|
||||
VPackSlice const compareValue = def.slice();
|
||||
size_t i = 0;
|
||||
|
@ -220,12 +214,3 @@ bool ExampleMatcher::matches(TRI_voc_cid_t, TRI_doc_mptr_t const* mptr) const {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Checks if the given velocyPack matches the examples in this class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ExampleMatcher::matches(VPackSlice const slice) const {
|
||||
#warning IMPLEMENT THIS
|
||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_NOT_IMPLEMENTED);
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
|
||||
#include <v8.h>
|
||||
|
||||
struct TRI_doc_mptr_t;
|
||||
|
||||
namespace arangodb {
|
||||
|
||||
namespace velocypack {
|
||||
|
@ -50,7 +48,6 @@ class ExampleMatcher {
|
|||
std::vector<ExampleDefinition> definitions;
|
||||
|
||||
void fillExampleDefinition(arangodb::velocypack::Slice const& example,
|
||||
arangodb::CollectionNameResolver const* resolver,
|
||||
ExampleDefinition& def);
|
||||
|
||||
void fillExampleDefinition(v8::Isolate* isolate,
|
||||
|
@ -69,13 +66,10 @@ class ExampleMatcher {
|
|||
arangodb::CollectionNameResolver const* resolver);
|
||||
|
||||
ExampleMatcher(arangodb::velocypack::Slice const& example,
|
||||
arangodb::CollectionNameResolver const* resolver,
|
||||
bool allowStrings);
|
||||
|
||||
~ExampleMatcher() { }
|
||||
|
||||
bool matches(TRI_voc_cid_t, TRI_doc_mptr_t const* mptr) const;
|
||||
|
||||
bool matches(arangodb::velocypack::Slice const) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include "MasterPointer.h"
|
||||
#include "Basics/VelocyPackHelper.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
#include <velocypack/Slice.h>
|
||||
#include <velocypack/velocypack-aliases.h>
|
||||
|
@ -31,13 +32,6 @@ using namespace arangodb;
|
|||
|
||||
TRI_voc_rid_t TRI_doc_mptr_t::revisionId() const {
|
||||
VPackSlice const slice(vpack());
|
||||
VPackSlice const revisionSlice = slice.get(TRI_VOC_ATTRIBUTE_REV);
|
||||
if (revisionSlice.isString()) {
|
||||
return arangodb::basics::VelocyPackHelper::stringUInt64(revisionSlice);
|
||||
}
|
||||
else if (revisionSlice.isNumber()) {
|
||||
return revisionSlice.getNumber<TRI_voc_rid_t>();
|
||||
}
|
||||
return 0;
|
||||
return TRI_extractRevisionId(slice);
|
||||
}
|
||||
|
||||
|
|
|
@ -1046,8 +1046,6 @@ int TRI_AddOperationTransaction(TRI_transaction_t* trx,
|
|||
trx->_waitForSync = true;
|
||||
}
|
||||
|
||||
// default is false
|
||||
waitForSync = false;
|
||||
if (isSingleOperationTransaction) {
|
||||
waitForSync |= document->_info.waitForSync();
|
||||
}
|
||||
|
|
|
@ -2317,3 +2317,22 @@ void TRI_FillVPackSub(TRI_vpack_sub_t* sub,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the _rev attribute from a slice
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_rid_t TRI_extractRevisionId(VPackSlice const slice) {
|
||||
TRI_ASSERT(slice.isObject());
|
||||
|
||||
VPackSlice r(slice.get(TRI_VOC_ATTRIBUTE_REV));
|
||||
if (r.isString()) {
|
||||
VPackValueLength length;
|
||||
char const* p = r.getString(length);
|
||||
return arangodb::basics::StringUtils::uint64(p, length);
|
||||
}
|
||||
if (r.isInteger()) {
|
||||
return r.getNumber<TRI_voc_rid_t>();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Basics/Common.h"
|
||||
#include "Basics/DeadlockDetector.h"
|
||||
#include "Basics/ReadWriteLock.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/threads.h"
|
||||
#include "Basics/vector.h"
|
||||
#include "Basics/voc-errors.h"
|
||||
|
@ -627,4 +628,10 @@ bool TRI_GetThrowCollectionNotLoadedVocBase(TRI_vocbase_t*);
|
|||
|
||||
void TRI_SetThrowCollectionNotLoadedVocBase(TRI_vocbase_t*, bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief extract the _rev attribute from a slice
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_voc_rid_t TRI_extractRevisionId(VPackSlice const slice);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue