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
|
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
|
it "returns an error if collection idenifier is missing" do
|
||||||
cmd = "/_api/document"
|
cmd = "/_api/document"
|
||||||
body = "{}"
|
body = "{}"
|
||||||
|
@ -139,11 +127,10 @@ describe ArangoDB do
|
||||||
it "creating a new document" do
|
it "creating a new document" do
|
||||||
cmd = "/_api/document?collection=#{@cn}"
|
cmd = "/_api/document?collection=#{@cn}"
|
||||||
body = "{ \"Hallo\" : \"World\" }"
|
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.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -162,7 +149,7 @@ describe ArangoDB do
|
||||||
match[1].should eq("#{@cn}")
|
match[1].should eq("#{@cn}")
|
||||||
|
|
||||||
etag.should eq("\"#{rev}\"")
|
etag.should eq("\"#{rev}\"")
|
||||||
location.should eq("/_api/document/#{did}")
|
location.should eq("/_db/_system/_api/document/#{did}")
|
||||||
|
|
||||||
ArangoDB.delete(location)
|
ArangoDB.delete(location)
|
||||||
|
|
||||||
|
@ -176,7 +163,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -205,11 +191,10 @@ describe ArangoDB do
|
||||||
it "creating a new document complex body" do
|
it "creating a new document complex body" do
|
||||||
cmd = "/_api/document?collection=#{@cn}"
|
cmd = "/_api/document?collection=#{@cn}"
|
||||||
body = "{ \"Hallo\" : \"Wo\\\"rld\" }"
|
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.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -228,7 +213,7 @@ describe ArangoDB do
|
||||||
match[1].should eq("#{@cn}")
|
match[1].should eq("#{@cn}")
|
||||||
|
|
||||||
etag.should eq("\"#{rev}\"")
|
etag.should eq("\"#{rev}\"")
|
||||||
location.should eq("/_api/document/#{did}")
|
location.should eq("/_db/_system/_api/document/#{did}")
|
||||||
|
|
||||||
cmd = "/_api/document/#{did}"
|
cmd = "/_api/document/#{did}"
|
||||||
doc = ArangoDB.log_get("#{prefix}-complex", cmd)
|
doc = ArangoDB.log_get("#{prefix}-complex", cmd)
|
||||||
|
@ -249,7 +234,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -285,11 +269,10 @@ describe ArangoDB do
|
||||||
it "creating a new umlaut document" do
|
it "creating a new umlaut document" do
|
||||||
cmd = "/_api/document?collection=#{@cn}"
|
cmd = "/_api/document?collection=#{@cn}"
|
||||||
body = "{ \"Hallo\" : \"öäüÖÄÜßあ寿司\" }"
|
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.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -308,7 +291,7 @@ describe ArangoDB do
|
||||||
match[1].should eq("#{@cn}")
|
match[1].should eq("#{@cn}")
|
||||||
|
|
||||||
etag.should eq("\"#{rev}\"")
|
etag.should eq("\"#{rev}\"")
|
||||||
location.should eq("/_api/document/#{did}")
|
location.should eq("/_db/_system/_api/document/#{did}")
|
||||||
|
|
||||||
cmd = "/_api/document/#{did}"
|
cmd = "/_api/document/#{did}"
|
||||||
doc = ArangoDB.log_get("#{prefix}-umlaut", cmd)
|
doc = ArangoDB.log_get("#{prefix}-umlaut", cmd)
|
||||||
|
@ -319,7 +302,7 @@ describe ArangoDB do
|
||||||
newBody = doc.body()
|
newBody = doc.body()
|
||||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
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('öäüÖÄÜßあ寿司')
|
doc.parsed_response['Hallo'].should eq('öäüÖÄÜßあ寿司')
|
||||||
|
|
||||||
|
@ -335,7 +318,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -365,7 +347,7 @@ describe ArangoDB do
|
||||||
newBody = doc.body()
|
newBody = doc.body()
|
||||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
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('öäüÖÄÜßあ寿司')
|
doc.parsed_response['Hallo'].should eq('öäüÖÄÜßあ寿司')
|
||||||
|
|
||||||
|
@ -376,58 +358,11 @@ describe ArangoDB do
|
||||||
|
|
||||||
it "creating a new not normalized umlaut document" do
|
it "creating a new not normalized umlaut document" do
|
||||||
cmd = "/_api/document?collection=#{@cn}"
|
cmd = "/_api/document?collection=#{@cn}"
|
||||||
body = "{ \"Hallo\" : \"Gru\\u0308\\u00DF Gott.\" }"
|
body = "{ \"Hallo\" : \"Grüß Gott.\" }"
|
||||||
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.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
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 = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -457,7 +392,52 @@ describe ArangoDB do
|
||||||
newBody = doc.body()
|
newBody = doc.body()
|
||||||
newBody = newBody.sub!(/^.*"Hallo":"([^"]*)".*$/, '\1')
|
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.')
|
doc.parsed_response['Hallo'].should eq('Grüß Gott.')
|
||||||
|
|
||||||
|
@ -473,11 +453,10 @@ describe ArangoDB do
|
||||||
|
|
||||||
cmd = "/_api/document?collection=#{@cn}"
|
cmd = "/_api/document?collection=#{@cn}"
|
||||||
body = "{ \"some stuff\" : \"goes here\", \"_key\" : \"#{@key}\" }"
|
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.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -496,7 +475,7 @@ describe ArangoDB do
|
||||||
|
|
||||||
match[1].should eq("#{@cn}")
|
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}")
|
ArangoDB.delete("/_api/document/#{@cn}/#{@key}")
|
||||||
end
|
end
|
||||||
|
@ -512,7 +491,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -575,11 +553,10 @@ describe ArangoDB do
|
||||||
it "creating a new document" do
|
it "creating a new document" do
|
||||||
cmd = "/_api/document?collection=#{@cn}"
|
cmd = "/_api/document?collection=#{@cn}"
|
||||||
body = "{ \"Hallo\" : \"World\" }"
|
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.code.should eq(202)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -598,7 +575,7 @@ describe ArangoDB do
|
||||||
match[1].should eq("#{@cn}")
|
match[1].should eq("#{@cn}")
|
||||||
|
|
||||||
etag.should eq("\"#{rev}\"")
|
etag.should eq("\"#{rev}\"")
|
||||||
location.should eq("/_api/document/#{did}")
|
location.should eq("/_db/_system/_api/document/#{did}")
|
||||||
|
|
||||||
ArangoDB.delete(location)
|
ArangoDB.delete(location)
|
||||||
|
|
||||||
|
@ -612,7 +589,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(202)
|
doc.code.should eq(202)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -641,11 +617,10 @@ describe ArangoDB do
|
||||||
it "creating a new document, waitForSync URL param = false" do
|
it "creating a new document, waitForSync URL param = false" do
|
||||||
cmd = "/_api/document?collection=#{@cn}&waitForSync=false"
|
cmd = "/_api/document?collection=#{@cn}&waitForSync=false"
|
||||||
body = "{ \"Hallo\" : \"World\" }"
|
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.code.should eq(202)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -664,7 +639,7 @@ describe ArangoDB do
|
||||||
match[1].should eq("#{@cn}")
|
match[1].should eq("#{@cn}")
|
||||||
|
|
||||||
etag.should eq("\"#{rev}\"")
|
etag.should eq("\"#{rev}\"")
|
||||||
location.should eq("/_api/document/#{did}")
|
location.should eq("/_db/_system/_api/document/#{did}")
|
||||||
|
|
||||||
ArangoDB.delete(location)
|
ArangoDB.delete(location)
|
||||||
|
|
||||||
|
@ -678,7 +653,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(202)
|
doc.code.should eq(202)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -707,11 +681,10 @@ describe ArangoDB do
|
||||||
it "creating a new document, waitForSync URL param = true" do
|
it "creating a new document, waitForSync URL param = true" do
|
||||||
cmd = "/_api/document?collection=#{@cn}&waitForSync=true"
|
cmd = "/_api/document?collection=#{@cn}&waitForSync=true"
|
||||||
body = "{ \"Hallo\" : \"World\" }"
|
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.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -730,7 +703,7 @@ describe ArangoDB do
|
||||||
match[1].should eq("#{@cn}")
|
match[1].should eq("#{@cn}")
|
||||||
|
|
||||||
etag.should eq("\"#{rev}\"")
|
etag.should eq("\"#{rev}\"")
|
||||||
location.should eq("/_api/document/#{did}")
|
location.should eq("/_db/_system/_api/document/#{did}")
|
||||||
|
|
||||||
ArangoDB.delete(location)
|
ArangoDB.delete(location)
|
||||||
|
|
||||||
|
@ -744,7 +717,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -788,11 +760,10 @@ describe ArangoDB do
|
||||||
it "creating a new document" do
|
it "creating a new document" do
|
||||||
cmd = "/_api/document?collection=#{@cn}"
|
cmd = "/_api/document?collection=#{@cn}"
|
||||||
body = "{ \"Hallo\" : \"World\" }"
|
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.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
@ -811,7 +782,7 @@ describe ArangoDB do
|
||||||
match[1].should eq("#{@cn}")
|
match[1].should eq("#{@cn}")
|
||||||
|
|
||||||
etag.should eq("\"#{rev}\"")
|
etag.should eq("\"#{rev}\"")
|
||||||
location.should eq("/_api/document/#{did}")
|
location.should eq("/_db/_system/_api/document/#{did}")
|
||||||
|
|
||||||
ArangoDB.delete(location)
|
ArangoDB.delete(location)
|
||||||
|
|
||||||
|
@ -825,7 +796,6 @@ describe ArangoDB do
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
|
|
||||||
etag = doc.headers['etag']
|
etag = doc.headers['etag']
|
||||||
etag.should be_kind_of(String)
|
etag.should be_kind_of(String)
|
||||||
|
|
|
@ -236,7 +236,6 @@ describe ArangoDB do
|
||||||
doc = ArangoDB.log_post("#{prefix}-valid", cmd, :body => body)
|
doc = ArangoDB.log_post("#{prefix}-valid", cmd, :body => body)
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
doc.parsed_response['_key'].should eq(key)
|
doc.parsed_response['_key'].should eq(key)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
end
|
end
|
||||||
|
@ -264,7 +263,6 @@ describe ArangoDB do
|
||||||
doc = ArangoDB.log_post("#{prefix}-valid", cmd, :body => body)
|
doc = ArangoDB.log_post("#{prefix}-valid", cmd, :body => body)
|
||||||
|
|
||||||
doc.code.should eq(201)
|
doc.code.should eq(201)
|
||||||
doc.parsed_response['error'].should eq(false)
|
|
||||||
doc.parsed_response['_key'].should eq(key)
|
doc.parsed_response['_key'].should eq(key)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,10 @@ describe ArangoDB do
|
||||||
cmd = "/_api/document/123456"
|
cmd = "/_api/document/123456"
|
||||||
doc = ArangoDB.log_get("#{prefix}-bad-handle", cmd)
|
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['error'].should eq(true)
|
||||||
doc.parsed_response['errorNum'].should eq(1205)
|
doc.parsed_response['errorNum'].should eq(1203)
|
||||||
doc.parsed_response['code'].should eq(400)
|
doc.parsed_response['code'].should eq(404)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -552,10 +552,10 @@ describe ArangoDB do
|
||||||
doc.code.should eq(200)
|
doc.code.should eq(200)
|
||||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
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 = ArangoDB.head(cmd + "?rev=abcd")
|
||||||
|
|
||||||
doc.code.should eq(400)
|
doc.code.should eq(200)
|
||||||
|
|
||||||
hdr = { "if-match" => "'abcd'" }
|
hdr = { "if-match" => "'abcd'" }
|
||||||
doc = ArangoDB.log_head("#{prefix}-head-rev-invalid", cmd, :headers => hdr)
|
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
|
it "creates a document with an invalid type" do
|
||||||
cmd = api + "?collection=" + @cn
|
cmd = api + "?collection=" + @cn
|
||||||
body = "[ ]";
|
body = "[ [] ]";
|
||||||
doc = ArangoDB.log_post("#{prefix}-create-list1", cmd, :body => body)
|
doc = ArangoDB.log_post("#{prefix}-create-list1", cmd, :body => body)
|
||||||
|
|
||||||
doc.code.should eq(400)
|
doc.code.should eq(400)
|
||||||
|
|
|
@ -66,6 +66,17 @@ using VertexId = arangodb::traverser::VertexId;
|
||||||
thread_local std::unordered_map<std::string, RegexMatcher*>* RegexCache =
|
thread_local std::unordered_map<std::string, RegexMatcher*>* RegexCache =
|
||||||
nullptr;
|
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
|
/// @brief clear the regex cache in a thread
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -436,116 +447,6 @@ static bool SortNumberList(VPackSlice const& values,
|
||||||
return true;
|
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,
|
static void RequestEdges(VPackSlice const& vertexSlice,
|
||||||
arangodb::AqlTransaction* trx,
|
arangodb::AqlTransaction* trx,
|
||||||
std::string const& collectionName,
|
std::string const& collectionName,
|
||||||
|
@ -577,7 +478,6 @@ static void RequestEdges(VPackSlice const& vertexSlice,
|
||||||
parts[0].c_str());
|
parts[0].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#warning might be optimized
|
|
||||||
VPackBuilder searchValueBuilder;
|
VPackBuilder searchValueBuilder;
|
||||||
searchValueBuilder.openArray();
|
searchValueBuilder.openArray();
|
||||||
switch (direction) {
|
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
|
/// @brief Helper function to merge given parameters
|
||||||
/// Works for an array of objects as first parameter or arbitrary many
|
/// 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);
|
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
|
/// @brief Transforms an unordered_map<VertexId> to AQL VelocyPack values
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static AqlValue$ VertexIdsToAqlValueVPack(
|
static AqlValue$ VertexIdsToAqlValueVPack(arangodb::aql::Query* query,
|
||||||
arangodb::aql::Query* query, arangodb::AqlTransaction* trx,
|
arangodb::AqlTransaction* trx,
|
||||||
CollectionNameResolver const* resolver, std::unordered_set<VertexId>& ids,
|
std::unordered_set<std::string>& ids,
|
||||||
bool includeData = false) {
|
bool includeData = false) {
|
||||||
std::shared_ptr<VPackBuilder> result = query->getSharedBuilder();
|
std::shared_ptr<VPackBuilder> result = query->getSharedBuilder();
|
||||||
{
|
{
|
||||||
VPackArrayBuilder b(result.get());
|
VPackArrayBuilder b(result.get());
|
||||||
if (includeData) {
|
if (includeData) {
|
||||||
for (auto& it : ids) {
|
for (auto& it : ids) {
|
||||||
VertexIdToVPack(trx, resolver, it, *result);
|
// THROWS ERRORS if the Document was not found
|
||||||
|
GetDocumentByIdentifier(trx, "", it, false, *result);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (auto& it : ids) {
|
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,
|
static AqlValue$ buildGeoResult(arangodb::aql::Query* query,
|
||||||
GeoCoordinates* cors, VocShaper* shaper,
|
GeoCoordinates* cors,
|
||||||
CollectionNameResolver const* resolver,
|
|
||||||
TRI_voc_cid_t const& cid,
|
TRI_voc_cid_t const& cid,
|
||||||
std::string const& attributeName) {
|
std::string const& attributeName) {
|
||||||
// TODO FIXME
|
|
||||||
// note: shaper will always be nullptr here...
|
|
||||||
if (cors == nullptr) {
|
if (cors == nullptr) {
|
||||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||||
{
|
{
|
||||||
|
@ -944,19 +905,22 @@ static AqlValue$ buildGeoResult(arangodb::aql::Query* query,
|
||||||
try {
|
try {
|
||||||
VPackArrayBuilder guard(b.get());
|
VPackArrayBuilder guard(b.get());
|
||||||
std::unordered_set<std::string> forbidden;
|
std::unordered_set<std::string> forbidden;
|
||||||
bool saveAttr = !attributeName.empty();
|
if (!attributeName.empty()) {
|
||||||
if (saveAttr) {
|
// We have to copy the entire document
|
||||||
forbidden.emplace(attributeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& it : distances) {
|
for (auto& it : distances) {
|
||||||
#warning convert to vpack
|
VPackObjectBuilder docGuard(b.get());
|
||||||
ExpandShapedJson(shaper, resolver, cid, it._mptr, *b,
|
|
||||||
saveAttr, forbidden);
|
|
||||||
if (saveAttr) {
|
|
||||||
// The Object is Open and attributeName is not set
|
|
||||||
b->add(attributeName, VPackValue(it._distance));
|
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 (...) {
|
} catch (...) {
|
||||||
|
@ -2384,7 +2348,7 @@ AqlValue$ Functions::Neighbors(arangodb::aql::Query* query,
|
||||||
if (n > 4) {
|
if (n > 4) {
|
||||||
auto edgeExamples = ExtractFunctionParameter(trx, parameters, 4);
|
auto edgeExamples = ExtractFunctionParameter(trx, parameters, 4);
|
||||||
if (!(edgeExamples.isArray() && edgeExamples.length() == 0)) {
|
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);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_set<VertexId> neighbors;
|
std::unordered_set<std::string> neighbors;
|
||||||
TRI_RunNeighborsSearch(edgeCollectionInfos, opts, 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>(),
|
trx, latitude.getNumericValue<double>(),
|
||||||
longitude.getNumericValue<double>(), limitValue);
|
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>(),
|
trx, latitude.getNumericValue<double>(),
|
||||||
longitude.getNumericValue<double>(), radius.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());
|
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
|
/// @brief function Document
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -2862,7 +2729,7 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
||||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||||
if (id.isString()) {
|
if (id.isString()) {
|
||||||
std::string identifier = id.copyString();
|
std::string identifier = id.copyString();
|
||||||
GetDocumentByIdentifier(trx, identifier, *b);
|
GetDocumentByIdentifier(trx, "", identifier, true, *b);
|
||||||
if (b->isEmpty()) {
|
if (b->isEmpty()) {
|
||||||
// not found
|
// not found
|
||||||
b->add(VPackValue(VPackValueType::Null));
|
b->add(VPackValue(VPackValueType::Null));
|
||||||
|
@ -2870,13 +2737,9 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
||||||
} else if (id.isArray()) {
|
} else if (id.isArray()) {
|
||||||
VPackArrayBuilder guard(b.get());
|
VPackArrayBuilder guard(b.get());
|
||||||
for (auto const& next : VPackArrayIterator(id)) {
|
for (auto const& next : VPackArrayIterator(id)) {
|
||||||
try {
|
|
||||||
if (next.isString()) {
|
if (next.isString()) {
|
||||||
std::string identifier = next.copyString();
|
std::string identifier = next.copyString();
|
||||||
GetDocumentByIdentifier(trx, identifier, *b);
|
GetDocumentByIdentifier(trx, "", identifier, true, *b);
|
||||||
}
|
|
||||||
} catch (arangodb::basics::Exception const&) {
|
|
||||||
// Ignore all ArangoDB exceptions here
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2891,19 +2754,8 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
||||||
}
|
}
|
||||||
std::string collectionName = collectionSlice.copyString();
|
std::string collectionName = collectionSlice.copyString();
|
||||||
|
|
||||||
TRI_voc_cid_t cid;
|
|
||||||
bool notFound = false;
|
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);
|
VPackSlice id = ExtractFunctionParameter(trx, parameters, 1);
|
||||||
if (id.isString()) {
|
if (id.isString()) {
|
||||||
if (notFound) {
|
if (notFound) {
|
||||||
|
@ -2913,7 +2765,7 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
||||||
}
|
}
|
||||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||||
std::string identifier = id.copyString();
|
std::string identifier = id.copyString();
|
||||||
GetDocumentByIdentifier(trx, collectionName, identifier, *b);
|
GetDocumentByIdentifier(trx, collectionName, identifier, true, *b);
|
||||||
if (b->isEmpty()) {
|
if (b->isEmpty()) {
|
||||||
b->add(VPackValue(VPackValueType::Null));
|
b->add(VPackValue(VPackValueType::Null));
|
||||||
}
|
}
|
||||||
|
@ -2924,13 +2776,9 @@ AqlValue$ Functions::Document(arangodb::aql::Query* query,
|
||||||
VPackArrayBuilder guard(b.get());
|
VPackArrayBuilder guard(b.get());
|
||||||
if (!notFound) {
|
if (!notFound) {
|
||||||
for (auto const& next : VPackArrayIterator(id)) {
|
for (auto const& next : VPackArrayIterator(id)) {
|
||||||
try {
|
|
||||||
if (next.isString()) {
|
if (next.isString()) {
|
||||||
std::string identifier = next.copyString();
|
std::string identifier = next.copyString();
|
||||||
GetDocumentByIdentifier(trx, collectionName, identifier, *b);
|
GetDocumentByIdentifier(trx, collectionName, identifier, true, *b);
|
||||||
}
|
|
||||||
} catch (arangodb::basics::Exception const&) {
|
|
||||||
// Ignore all ArangoDB exceptions here
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3014,8 +2862,6 @@ AqlValue$ Functions::Edges(arangodb::aql::Query* query,
|
||||||
return AqlValue$(b.get());
|
return AqlValue$(b.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resolver = trx->resolver();
|
|
||||||
|
|
||||||
std::unique_ptr<arangodb::ExampleMatcher> matcher;
|
std::unique_ptr<arangodb::ExampleMatcher> matcher;
|
||||||
|
|
||||||
TRI_document_collection_t* documentCollection = trx->documentCollection(cid);
|
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()) {
|
if ((exampleSlice.isArray() && exampleSlice.length() != 0)|| exampleSlice.isObject()) {
|
||||||
try {
|
try {
|
||||||
matcher.reset(
|
matcher.reset(
|
||||||
new arangodb::ExampleMatcher(exampleSlice, resolver, false));
|
new arangodb::ExampleMatcher(exampleSlice, false));
|
||||||
} catch (arangodb::basics::Exception const& e) {
|
} catch (arangodb::basics::Exception const& e) {
|
||||||
if (e.code() != TRI_RESULT_ELEMENT_NOT_FOUND) {
|
if (e.code() != TRI_RESULT_ELEMENT_NOT_FOUND) {
|
||||||
throw;
|
throw;
|
||||||
|
@ -4361,7 +4207,6 @@ AqlValue$ Functions::Fulltext(arangodb::aql::Query* query,
|
||||||
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shaper = document->getShaper();
|
|
||||||
size_t const numResults = queryResult->_numDocuments;
|
size_t const numResults = queryResult->_numDocuments;
|
||||||
|
|
||||||
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
|
||||||
|
@ -4369,11 +4214,8 @@ AqlValue$ Functions::Fulltext(arangodb::aql::Query* query,
|
||||||
VPackArrayBuilder guard(b.get());
|
VPackArrayBuilder guard(b.get());
|
||||||
|
|
||||||
for (size_t i = 0; i < numResults; ++i) {
|
for (size_t i = 0; i < numResults; ++i) {
|
||||||
std::unordered_set<std::string> unused;
|
InsertMasterPointer((TRI_doc_mptr_t const*)queryResult->_documents[i],
|
||||||
#warning convert to vpack
|
*b);
|
||||||
ExpandShapedJson(shaper, resolver, cid,
|
|
||||||
(TRI_doc_mptr_t const*)queryResult->_documents[i], *b,
|
|
||||||
false, unused);
|
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
TRI_FreeResultFulltextIndex(queryResult);
|
TRI_FreeResultFulltextIndex(queryResult);
|
||||||
|
|
|
@ -81,25 +81,29 @@ HttpHandler::status_t RestDocumentHandler::execute() {
|
||||||
bool RestDocumentHandler::createDocument() {
|
bool RestDocumentHandler::createDocument() {
|
||||||
std::vector<std::string> const& suffix = _request->suffix();
|
std::vector<std::string> const& suffix = _request->suffix();
|
||||||
|
|
||||||
if (!suffix.empty()) {
|
if (suffix.size() > 1) {
|
||||||
generateError(HttpResponse::BAD, TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
generateError(HttpResponse::BAD, TRI_ERROR_HTTP_SUPERFLUOUS_SUFFICES,
|
||||||
"superfluous suffix, expecting " + DOCUMENT_PATH +
|
"superfluous suffix, expecting " + DOCUMENT_PATH +
|
||||||
"?collection=<identifier>");
|
"?collection=<identifier>");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the cid
|
|
||||||
bool found;
|
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,
|
generateError(HttpResponse::BAD,
|
||||||
TRI_ERROR_ARANGO_COLLECTION_PARAMETER_MISSING,
|
TRI_ERROR_ARANGO_COLLECTION_PARAMETER_MISSING,
|
||||||
"'collection' is missing, expecting " + DOCUMENT_PATH +
|
"'collection' is missing, expecting " + DOCUMENT_PATH +
|
||||||
"?collection=<identifier>");
|
"/<collectionname> or query parameter 'collection'");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string collectionName(collection);
|
|
||||||
|
|
||||||
bool parseSuccess = true;
|
bool parseSuccess = true;
|
||||||
// copy default options
|
// copy default options
|
||||||
|
@ -111,28 +115,23 @@ bool RestDocumentHandler::createDocument() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO
|
|
||||||
if (!checkCreateCollection(collection, getCollectionType())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// find and load collection given by name or identifier
|
// find and load collection given by name or identifier
|
||||||
SingleCollectionTransaction trx(StandaloneTransactionContext::Create(_vocbase),
|
SingleCollectionTransaction trx(StandaloneTransactionContext::Create(_vocbase),
|
||||||
collection, TRI_TRANSACTION_WRITE);
|
collectionName, TRI_TRANSACTION_WRITE);
|
||||||
|
VPackSlice body = parsedBody->slice();
|
||||||
|
if (!body.isArray()) {
|
||||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||||
|
}
|
||||||
|
|
||||||
int res = trx.begin();
|
int res = trx.begin();
|
||||||
|
|
||||||
if (res != TRI_ERROR_NO_ERROR) {
|
if (res != TRI_ERROR_NO_ERROR) {
|
||||||
generateTransactionError(collection, res, "");
|
generateTransactionError(collectionName, res, "");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
arangodb::OperationOptions opOptions;
|
arangodb::OperationOptions opOptions;
|
||||||
opOptions.waitForSync = extractWaitForSync();
|
opOptions.waitForSync = extractWaitForSync();
|
||||||
VPackSlice body = parsedBody->slice();
|
|
||||||
arangodb::OperationResult result = trx.insert(collectionName, body, opOptions);
|
arangodb::OperationResult result = trx.insert(collectionName, body, opOptions);
|
||||||
|
|
||||||
// Will commit if no error occured.
|
// Will commit if no error occured.
|
||||||
|
@ -165,12 +164,8 @@ bool RestDocumentHandler::readDocument() {
|
||||||
|
|
||||||
switch (len) {
|
switch (len) {
|
||||||
case 0:
|
case 0:
|
||||||
return readAllDocuments();
|
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
generateError(HttpResponse::BAD, TRI_ERROR_ARANGO_DOCUMENT_HANDLE_BAD,
|
return readAllDocuments();
|
||||||
"expecting GET /_api/document/<document-handle>");
|
|
||||||
return false;
|
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
return readSingleDocument(true);
|
return readSingleDocument(true);
|
||||||
|
@ -227,9 +222,9 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
||||||
collection, TRI_TRANSACTION_READ);
|
collection, TRI_TRANSACTION_READ);
|
||||||
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||||
|
|
||||||
// .............................................................................
|
// ...........................................................................
|
||||||
// inside read transaction
|
// inside read transaction
|
||||||
// .............................................................................
|
// ...........................................................................
|
||||||
|
|
||||||
int res = trx.begin();
|
int res = trx.begin();
|
||||||
|
|
||||||
|
@ -239,6 +234,7 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OperationOptions options;
|
OperationOptions options;
|
||||||
|
options.ignoreRevs = false;
|
||||||
OperationResult result = trx.document(collection, search, options);
|
OperationResult result = trx.document(collection, search, options);
|
||||||
|
|
||||||
res = trx.finish(result.code);
|
res = trx.finish(result.code);
|
||||||
|
@ -260,9 +256,7 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_voc_rid_t const rid =
|
TRI_voc_rid_t const rid = TRI_extractRevisionId(result.slice());
|
||||||
VelocyPackHelper::getNumericValue<TRI_voc_rid_t>(
|
|
||||||
result.slice(), TRI_VOC_ATTRIBUTE_REV, 0);
|
|
||||||
if (ifNoneRid != 0 && ifNoneRid == rid) {
|
if (ifNoneRid != 0 && ifNoneRid == rid) {
|
||||||
generateNotModified(rid);
|
generateNotModified(rid);
|
||||||
} else {
|
} else {
|
||||||
|
@ -280,7 +274,14 @@ bool RestDocumentHandler::readSingleDocument(bool generateBody) {
|
||||||
|
|
||||||
bool RestDocumentHandler::readAllDocuments() {
|
bool RestDocumentHandler::readAllDocuments() {
|
||||||
bool found;
|
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);
|
std::string returnType = _request->value("type", found);
|
||||||
|
|
||||||
if (returnType.empty()) {
|
if (returnType.empty()) {
|
||||||
|
|
|
@ -150,9 +150,9 @@ void RestVocbaseBaseHandler::generateSaved(
|
||||||
arangodb::OperationResult const& result, std::string const& collectionName,
|
arangodb::OperationResult const& result, std::string const& collectionName,
|
||||||
TRI_col_type_e type) {
|
TRI_col_type_e type) {
|
||||||
if (result.wasSynchronous) {
|
if (result.wasSynchronous) {
|
||||||
createResponse(rest::HttpResponse::ACCEPTED);
|
|
||||||
} else {
|
|
||||||
createResponse(rest::HttpResponse::CREATED);
|
createResponse(rest::HttpResponse::CREATED);
|
||||||
|
} else {
|
||||||
|
createResponse(rest::HttpResponse::ACCEPTED);
|
||||||
}
|
}
|
||||||
generate20x(result, collectionName, type);
|
generate20x(result, collectionName, type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,6 +366,21 @@ class CollectionNameResolver {
|
||||||
buffer.appendText("_unknown");
|
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:
|
private:
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief vocbase base pointer
|
/// @brief vocbase base pointer
|
||||||
|
|
|
@ -198,25 +198,6 @@ std::string Transaction::extractKey(VPackSlice const slice) {
|
||||||
return "";
|
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
|
/// @brief extract the _id attribute from a slice, and convert it into a
|
||||||
/// string
|
/// string
|
||||||
|
@ -575,7 +556,7 @@ OperationResult Transaction::documentCoordinator(std::string const& collectionNa
|
||||||
if (key.empty()) {
|
if (key.empty()) {
|
||||||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
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(
|
int res = arangodb::getDocumentOnCoordinator(
|
||||||
_vocbase->_name, collectionName, key, expectedRevision, headers, true,
|
_vocbase->_name, collectionName, key, expectedRevision, headers, true,
|
||||||
|
@ -636,7 +617,7 @@ OperationResult Transaction::documentLocal(std::string const& collectionName,
|
||||||
|
|
||||||
TRI_voc_rid_t expectedRevision = 0;
|
TRI_voc_rid_t expectedRevision = 0;
|
||||||
if (!options.ignoreRevs) {
|
if (!options.ignoreRevs) {
|
||||||
expectedRevision = Transaction::extractRevisionId(value);
|
expectedRevision = TRI_extractRevisionId(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRI_doc_mptr_t mptr;
|
TRI_doc_mptr_t mptr;
|
||||||
|
@ -654,6 +635,8 @@ OperationResult Transaction::documentLocal(std::string const& collectionName,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.silent) {
|
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()));
|
resultBuilder.add(VPackSlice(mptr.vpack()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -950,7 +933,7 @@ OperationResult Transaction::updateCoordinator(std::string const& collectionName
|
||||||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
||||||
}
|
}
|
||||||
TRI_voc_rid_t const expectedRevision
|
TRI_voc_rid_t const expectedRevision
|
||||||
= options.ignoreRevs ? 0 : Transaction::extractRevisionId(newValue);
|
= options.ignoreRevs ? 0 : TRI_extractRevisionId(newValue);
|
||||||
|
|
||||||
int res = arangodb::modifyDocumentOnCoordinator(
|
int res = arangodb::modifyDocumentOnCoordinator(
|
||||||
_vocbase->_name, collectionName, key, expectedRevision,
|
_vocbase->_name, collectionName, key, expectedRevision,
|
||||||
|
@ -1038,7 +1021,7 @@ OperationResult Transaction::replaceCoordinator(std::string const& collectionNam
|
||||||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
||||||
}
|
}
|
||||||
TRI_voc_rid_t const expectedRevision
|
TRI_voc_rid_t const expectedRevision
|
||||||
= options.ignoreRevs ? 0 : Transaction::extractRevisionId(newValue);
|
= options.ignoreRevs ? 0 : TRI_extractRevisionId(newValue);
|
||||||
|
|
||||||
int res = arangodb::modifyDocumentOnCoordinator(
|
int res = arangodb::modifyDocumentOnCoordinator(
|
||||||
_vocbase->_name, collectionName, key, expectedRevision,
|
_vocbase->_name, collectionName, key, expectedRevision,
|
||||||
|
@ -1206,7 +1189,7 @@ OperationResult Transaction::removeCoordinator(std::string const& collectionName
|
||||||
if (key.empty()) {
|
if (key.empty()) {
|
||||||
return OperationResult(TRI_ERROR_ARANGO_DOCUMENT_KEY_BAD);
|
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(
|
int res = arangodb::deleteDocumentOnCoordinator(
|
||||||
_vocbase->_name, collectionName, key, expectedRevision,
|
_vocbase->_name, collectionName, key, expectedRevision,
|
||||||
|
@ -1309,16 +1292,18 @@ OperationResult Transaction::allKeys(std::string const& collectionName,
|
||||||
|
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
|
|
||||||
|
std::string realCollName = resolver()->getCollectionName(collectionName);
|
||||||
|
|
||||||
if (type == "key") {
|
if (type == "key") {
|
||||||
prefix = "";
|
prefix = "";
|
||||||
} else if (type == "id") {
|
} else if (type == "id") {
|
||||||
prefix = collectionName + "/";
|
prefix = realCollName + "/";
|
||||||
} else {
|
} else {
|
||||||
// default return type: paths to documents
|
// default return type: paths to documents
|
||||||
if (isEdgeCollection(collectionName)) {
|
if (isEdgeCollection(collectionName)) {
|
||||||
prefix = std::string("/_db/") + _vocbase->_name + "/_api/edge/" + collectionName + "/";
|
prefix = std::string("/_db/") + _vocbase->_name + "/_api/edge/" + realCollName + "/";
|
||||||
} else {
|
} 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);
|
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
|
/// @brief extract the _id attribute from a slice, and convert it into a
|
||||||
/// string
|
/// string
|
||||||
|
|
|
@ -248,13 +248,12 @@ bool BasicOptions::matchesVertex(VertexId const& v) const {
|
||||||
// OperationResult opRes = trx->document(it->second.col, slice, options);
|
// OperationResult opRes = trx->document(it->second.col, slice, options);
|
||||||
OperationResult opRes(TRI_ERROR_INTERNAL);
|
OperationResult opRes(TRI_ERROR_INTERNAL);
|
||||||
#warning fill vertex
|
#warning fill vertex
|
||||||
TRI_doc_mptr_t vertex;
|
|
||||||
|
|
||||||
if (!opRes.successful()) {
|
if (!opRes.successful()) {
|
||||||
return false;
|
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
|
/// @brief Insert a new edge matcher object
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void BasicOptions::addEdgeFilter(VPackSlice const& example, VocShaper* shaper,
|
void BasicOptions::addEdgeFilter(VPackSlice const& example,
|
||||||
TRI_voc_cid_t const& cid,
|
TRI_voc_cid_t const& cid) {
|
||||||
CollectionNameResolver const* resolver) {
|
|
||||||
useEdgeFilter = true;
|
useEdgeFilter = true;
|
||||||
auto it = _edgeFilter.find(cid);
|
auto it = _edgeFilter.find(cid);
|
||||||
if (it == _edgeFilter.end()) {
|
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 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,
|
TRI_voc_cid_t const& cid,
|
||||||
arangodb::CollectionNameResolver const* resolver);
|
arangodb::CollectionNameResolver const* resolver);
|
||||||
|
|
||||||
void addEdgeFilter(arangodb::velocypack::Slice const& example, VocShaper* shaper,
|
void addEdgeFilter(arangodb::velocypack::Slice const& example,
|
||||||
TRI_voc_cid_t const& cid,
|
TRI_voc_cid_t const& cid);
|
||||||
arangodb::CollectionNameResolver const* resolver);
|
|
||||||
|
|
||||||
void addVertexFilter(v8::Isolate* isolate,
|
void addVertexFilter(v8::Isolate* isolate,
|
||||||
v8::Handle<v8::Value> const& example,
|
v8::Handle<v8::Value> const& example,
|
||||||
|
|
|
@ -526,12 +526,13 @@ static void DocumentVocbase(
|
||||||
LocalCollectionGuard g(const_cast<TRI_vocbase_col_t*>(col));
|
LocalCollectionGuard g(const_cast<TRI_vocbase_col_t*>(col));
|
||||||
|
|
||||||
TRI_ASSERT(col != nullptr);
|
TRI_ASSERT(col != nullptr);
|
||||||
|
|
||||||
TRI_ASSERT(!collectionName.empty());
|
TRI_ASSERT(!collectionName.empty());
|
||||||
|
|
||||||
VPackSlice search = builder.slice();
|
VPackSlice search = builder.slice();
|
||||||
TRI_ASSERT(search.isObject());
|
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);
|
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||||
|
|
||||||
int res = trx.begin();
|
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(
|
static void RemoveVocbaseCol(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
bool useCollection, 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::Isolate* isolate = args.GetIsolate();
|
||||||
v8::HandleScope scope(isolate);
|
v8::HandleScope scope(isolate);
|
||||||
OperationOptions options;
|
OperationOptions options;
|
||||||
|
@ -607,34 +718,16 @@ static void RemoveVocbaseVPack(
|
||||||
TRI_vocbase_t* vocbase;
|
TRI_vocbase_t* vocbase;
|
||||||
TRI_vocbase_col_t const* col = nullptr;
|
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) {
|
if (vocbase == nullptr) {
|
||||||
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_DATABASE_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto transactionContext = std::make_shared<V8TransactionContext>(vocbase, true);
|
auto transactionContext = std::make_shared<V8TransactionContext>(vocbase, true);
|
||||||
|
|
||||||
VPackBuilder builder;
|
VPackBuilder builder;
|
||||||
std::string collectionName;
|
std::string collectionName;
|
||||||
|
|
||||||
LocalCollectionGuard g(useCollection ? nullptr
|
|
||||||
: const_cast<TRI_vocbase_col_t*>(col));
|
|
||||||
|
|
||||||
{ VPackObjectBuilder guard(&builder);
|
{ VPackObjectBuilder guard(&builder);
|
||||||
int res = ParseDocumentOrDocumentHandle(
|
int res = ParseDocumentOrDocumentHandle(
|
||||||
isolate, vocbase, transactionContext->getResolver(), col, collectionName, builder,
|
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();
|
VPackSlice toRemove = builder.slice();
|
||||||
TRI_ASSERT(toRemove.isObject());
|
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);
|
trx.addHint(TRI_TRANSACTION_HINT_SINGLE_OPERATION, false);
|
||||||
|
|
||||||
int res = trx.begin();
|
int res = trx.begin();
|
||||||
|
@ -662,7 +761,8 @@ static void RemoveVocbaseVPack(
|
||||||
res = trx.finish(result.code);
|
res = trx.finish(result.code);
|
||||||
|
|
||||||
if (!result.successful()) {
|
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();
|
TRI_V8_RETURN_FALSE();
|
||||||
} else {
|
} else {
|
||||||
TRI_V8_THROW_EXCEPTION(result.code);
|
TRI_V8_THROW_EXCEPTION(result.code);
|
||||||
|
@ -1329,10 +1429,10 @@ static void JS_PropertiesVocbaseCol(
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
static void JS_RemoveVocbaseVPack(
|
static void JS_RemoveVocbaseCol(
|
||||||
v8::FunctionCallbackInfo<v8::Value> const& args) {
|
v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||||
return RemoveVocbaseVPack(true, args);
|
return RemoveVocbaseCol(args);
|
||||||
TRI_V8_TRY_CATCH_END
|
TRI_V8_TRY_CATCH_END
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2615,7 +2715,7 @@ static void JS_CompletionsVocbase(
|
||||||
|
|
||||||
static void JS_RemoveVocbase(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
static void JS_RemoveVocbase(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||||
return RemoveVocbaseVPack(false, args);
|
return RemoveVocbase(args);
|
||||||
TRI_V8_TRY_CATCH_END
|
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"),
|
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("properties"),
|
||||||
JS_PropertiesVocbaseCol);
|
JS_PropertiesVocbaseCol);
|
||||||
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("remove"),
|
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("remove"),
|
||||||
JS_RemoveVocbaseVPack);
|
JS_RemoveVocbaseCol);
|
||||||
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("revision"),
|
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("revision"),
|
||||||
JS_RevisionVocbaseCol);
|
JS_RevisionVocbaseCol);
|
||||||
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("rename"),
|
TRI_AddMethodVocbase(isolate, rt, TRI_V8_ASCII_STRING("rename"),
|
||||||
|
|
|
@ -75,7 +75,7 @@ void ExampleMatcher::fillExampleDefinition(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExampleMatcher::fillExampleDefinition(
|
void ExampleMatcher::fillExampleDefinition(
|
||||||
VPackSlice const& example, CollectionNameResolver const* resolver,
|
VPackSlice const& example,
|
||||||
ExampleDefinition& def) {
|
ExampleDefinition& def) {
|
||||||
TRI_ASSERT(def._values.isEmpty());
|
TRI_ASSERT(def._values.isEmpty());
|
||||||
VPackArrayBuilder guard(&def._values);
|
VPackArrayBuilder guard(&def._values);
|
||||||
|
@ -166,11 +166,10 @@ ExampleMatcher::ExampleMatcher(TRI_json_t const* example,
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
||||||
CollectionNameResolver const* resolver,
|
|
||||||
bool allowStrings) {
|
bool allowStrings) {
|
||||||
if (example.isObject() || example.isString()) {
|
if (example.isObject() || example.isString()) {
|
||||||
ExampleDefinition def;
|
ExampleDefinition def;
|
||||||
ExampleMatcher::fillExampleDefinition(example, resolver, def);
|
ExampleMatcher::fillExampleDefinition(example, def);
|
||||||
definitions.emplace_back(std::move(def));
|
definitions.emplace_back(std::move(def));
|
||||||
} else if (example.isArray()) {
|
} else if (example.isArray()) {
|
||||||
for (auto const& e : VPackArrayIterator(example)) {
|
for (auto const& e : VPackArrayIterator(example)) {
|
||||||
|
@ -179,7 +178,7 @@ ExampleMatcher::ExampleMatcher(VPackSlice const& example,
|
||||||
// We do not match strings in Array
|
// We do not match strings in Array
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ExampleMatcher::fillExampleDefinition(e, resolver, def);
|
ExampleMatcher::fillExampleDefinition(e, def);
|
||||||
definitions.emplace_back(std::move(def));
|
definitions.emplace_back(std::move(def));
|
||||||
}
|
}
|
||||||
if (definitions.empty()) {
|
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 {
|
bool ExampleMatcher::matches(VPackSlice const toMatch) const {
|
||||||
if (mptr == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
VPackSlice toMatch(mptr->vpack());
|
|
||||||
for (auto const& def : definitions) {
|
for (auto const& def : definitions) {
|
||||||
VPackSlice const compareValue = def.slice();
|
VPackSlice const compareValue = def.slice();
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -220,12 +214,3 @@ bool ExampleMatcher::matches(TRI_voc_cid_t, TRI_doc_mptr_t const* mptr) const {
|
||||||
}
|
}
|
||||||
return false;
|
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>
|
#include <v8.h>
|
||||||
|
|
||||||
struct TRI_doc_mptr_t;
|
|
||||||
|
|
||||||
namespace arangodb {
|
namespace arangodb {
|
||||||
|
|
||||||
namespace velocypack {
|
namespace velocypack {
|
||||||
|
@ -50,7 +48,6 @@ class ExampleMatcher {
|
||||||
std::vector<ExampleDefinition> definitions;
|
std::vector<ExampleDefinition> definitions;
|
||||||
|
|
||||||
void fillExampleDefinition(arangodb::velocypack::Slice const& example,
|
void fillExampleDefinition(arangodb::velocypack::Slice const& example,
|
||||||
arangodb::CollectionNameResolver const* resolver,
|
|
||||||
ExampleDefinition& def);
|
ExampleDefinition& def);
|
||||||
|
|
||||||
void fillExampleDefinition(v8::Isolate* isolate,
|
void fillExampleDefinition(v8::Isolate* isolate,
|
||||||
|
@ -69,13 +66,10 @@ class ExampleMatcher {
|
||||||
arangodb::CollectionNameResolver const* resolver);
|
arangodb::CollectionNameResolver const* resolver);
|
||||||
|
|
||||||
ExampleMatcher(arangodb::velocypack::Slice const& example,
|
ExampleMatcher(arangodb::velocypack::Slice const& example,
|
||||||
arangodb::CollectionNameResolver const* resolver,
|
|
||||||
bool allowStrings);
|
bool allowStrings);
|
||||||
|
|
||||||
~ExampleMatcher() { }
|
~ExampleMatcher() { }
|
||||||
|
|
||||||
bool matches(TRI_voc_cid_t, TRI_doc_mptr_t const* mptr) const;
|
|
||||||
|
|
||||||
bool matches(arangodb::velocypack::Slice const) const;
|
bool matches(arangodb::velocypack::Slice const) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "MasterPointer.h"
|
#include "MasterPointer.h"
|
||||||
#include "Basics/VelocyPackHelper.h"
|
#include "Basics/VelocyPackHelper.h"
|
||||||
|
#include "VocBase/vocbase.h"
|
||||||
|
|
||||||
#include <velocypack/Slice.h>
|
#include <velocypack/Slice.h>
|
||||||
#include <velocypack/velocypack-aliases.h>
|
#include <velocypack/velocypack-aliases.h>
|
||||||
|
@ -31,13 +32,6 @@ using namespace arangodb;
|
||||||
|
|
||||||
TRI_voc_rid_t TRI_doc_mptr_t::revisionId() const {
|
TRI_voc_rid_t TRI_doc_mptr_t::revisionId() const {
|
||||||
VPackSlice const slice(vpack());
|
VPackSlice const slice(vpack());
|
||||||
VPackSlice const revisionSlice = slice.get(TRI_VOC_ATTRIBUTE_REV);
|
return TRI_extractRevisionId(slice);
|
||||||
if (revisionSlice.isString()) {
|
|
||||||
return arangodb::basics::VelocyPackHelper::stringUInt64(revisionSlice);
|
|
||||||
}
|
|
||||||
else if (revisionSlice.isNumber()) {
|
|
||||||
return revisionSlice.getNumber<TRI_voc_rid_t>();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1046,8 +1046,6 @@ int TRI_AddOperationTransaction(TRI_transaction_t* trx,
|
||||||
trx->_waitForSync = true;
|
trx->_waitForSync = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// default is false
|
|
||||||
waitForSync = false;
|
|
||||||
if (isSingleOperationTransaction) {
|
if (isSingleOperationTransaction) {
|
||||||
waitForSync |= document->_info.waitForSync();
|
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/Common.h"
|
||||||
#include "Basics/DeadlockDetector.h"
|
#include "Basics/DeadlockDetector.h"
|
||||||
#include "Basics/ReadWriteLock.h"
|
#include "Basics/ReadWriteLock.h"
|
||||||
|
#include "Basics/StringUtils.h"
|
||||||
#include "Basics/threads.h"
|
#include "Basics/threads.h"
|
||||||
#include "Basics/vector.h"
|
#include "Basics/vector.h"
|
||||||
#include "Basics/voc-errors.h"
|
#include "Basics/voc-errors.h"
|
||||||
|
@ -627,4 +628,10 @@ bool TRI_GetThrowCollectionNotLoadedVocBase(TRI_vocbase_t*);
|
||||||
|
|
||||||
void TRI_SetThrowCollectionNotLoadedVocBase(TRI_vocbase_t*, bool);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue