mirror of https://gitee.com/bigwinds/arangodb
merge with SVN
This commit is contained in:
parent
46243e8288
commit
6f35cfaecc
|
@ -143,7 +143,7 @@ void ActionDispatcherThread::tick (bool idle) {
|
|||
_gc += (idle ? 10 : 1);
|
||||
|
||||
if (_gc > _gcInterval) {
|
||||
LOG_DEBUG("collecting garbage...");
|
||||
LOG_TRACE("collecting garbage...");
|
||||
|
||||
while (!v8::V8::IdleNotification()) {
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@
|
|||
/// The basic operations (create, read, update, delete) for documents are mapped
|
||||
/// to the standard HTTP methods (POST, GET, PUT, DELETE).
|
||||
///
|
||||
/// @section HttpCollectionResource Address of an Collection
|
||||
/// @section HttpCollectionResource Address of a Collection
|
||||
////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// All collections in AvocadoDB have an unique identifier. This collection
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
source :rubygems
|
||||
|
||||
gem "httparty", "~> 0.8.1"
|
||||
gem "rspec", "~> 2.8.0"
|
|
@ -0,0 +1,132 @@
|
|||
require 'httparty'
|
||||
|
||||
class AvocadoDB
|
||||
include HTTParty
|
||||
|
||||
base_uri 'http://localhost:8529'
|
||||
format :json
|
||||
|
||||
################################################################################
|
||||
## create a collection
|
||||
################################################################################
|
||||
|
||||
def self.create_collection (name, wait_for_sync = true)
|
||||
body = "{ \"name\" : \"#{name}\", \"waitForSync\" : #{wait_for_sync} }"
|
||||
|
||||
doc = self.post("/_api/database/collection", :body => body)
|
||||
|
||||
if doc.code == 409
|
||||
return doc.parsed_response['id']
|
||||
end
|
||||
|
||||
if doc.code != 200
|
||||
return nil
|
||||
end
|
||||
|
||||
return doc.parsed_response['id']
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## drop a collection
|
||||
################################################################################
|
||||
|
||||
def self.drop_collection (name)
|
||||
# TODO
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## size of a collection
|
||||
################################################################################
|
||||
|
||||
def self.size_collection (name)
|
||||
doc = self.get("/document?collection=#{name}") # TODO use api call
|
||||
|
||||
return doc.parsed_response['documents'].length
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## generate log file
|
||||
################################################################################
|
||||
|
||||
def self.log (args)
|
||||
if args.key?(:output)
|
||||
logfile = File.new("logs/#{args[:output]}", "a")
|
||||
else
|
||||
logfile = File.new("output.log", "a")
|
||||
end
|
||||
|
||||
method = args[:method] || :get
|
||||
url = args[:url]
|
||||
body = args[:body]
|
||||
headers = args[:headers]
|
||||
result = args[:result]
|
||||
response = result.parsed_response
|
||||
|
||||
logfile.puts '-' * 80
|
||||
|
||||
h_option = ""
|
||||
h_sep = ""
|
||||
|
||||
if headers
|
||||
for k in [ "if-match", "if-none-match" ] do
|
||||
if headers.key?(k)
|
||||
h_option = h_option + h_sep + "'-H #{k}: #{headers[k]}'"
|
||||
h_sep = " "
|
||||
end
|
||||
end
|
||||
h_option = h_option + h_sep
|
||||
end
|
||||
|
||||
if method == :get
|
||||
logfile.puts "> curl -X GET #{h_option}--dump - http://localhost:8529#{url}"
|
||||
logfile.puts
|
||||
elsif method == :head
|
||||
logfile.puts "> curl -X HEAD #{h_option}--dump - http://localhost:8529#{url}"
|
||||
logfile.puts
|
||||
elsif method == :delete
|
||||
logfile.puts "> curl -X DELETE #{h_option}--dump - http://localhost:8529#{url}"
|
||||
logfile.puts
|
||||
elsif method == :post
|
||||
if body == nil
|
||||
logfile.puts "> curl -X POST #{h_option}--dump - http://localhost:8529#{url}"
|
||||
logfile.puts
|
||||
else
|
||||
logfile.puts "> curl --data @- -X POST #{h_option}--dump - http://localhost:8529#{url}"
|
||||
logfile.puts body
|
||||
logfile.puts
|
||||
end
|
||||
elsif method == :put
|
||||
if body == nil
|
||||
logfile.puts "> curl -X PUT #{h_option}--dump - http://localhost:8529#{url}"
|
||||
logfile.puts
|
||||
else
|
||||
logfile.puts "> curl --data @- -X PUT #{h_option}--dump - http://localhost:8529#{url}"
|
||||
logfile.puts body
|
||||
logfile.puts
|
||||
end
|
||||
else
|
||||
logfile.puts "MISSING"
|
||||
end
|
||||
|
||||
logfile.puts "HTTP/1.1 #{result.code} #{result.message}"
|
||||
|
||||
if result.headers.key?('content-type')
|
||||
logfile.puts "content-type: #{result.headers['content-type']}"
|
||||
end
|
||||
|
||||
if result.headers.key?('location')
|
||||
logfile.puts "location: #{result.headers['location']}"
|
||||
end
|
||||
|
||||
if result.headers.key?('etag')
|
||||
logfile.puts "etag: #{result.headers['etag']}"
|
||||
end
|
||||
|
||||
if response != nil
|
||||
logfile.puts
|
||||
logfile.puts JSON.pretty_generate(response)
|
||||
end
|
||||
|
||||
logfile.close
|
||||
end
|
||||
end
|
|
@ -0,0 +1,305 @@
|
|||
require 'rspec'
|
||||
require './avocadodb.rb'
|
||||
|
||||
describe AvocadoDB do
|
||||
prefix = "rest_create-document"
|
||||
|
||||
context "creating a document:" do
|
||||
|
||||
################################################################################
|
||||
## error handling
|
||||
################################################################################
|
||||
|
||||
context "error handling:" do
|
||||
it "returns an error if url contains a suffix" do
|
||||
cmd = "/document/123456"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.post(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")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-superfluous-suffix")
|
||||
end
|
||||
|
||||
it "returns an error if collection idenifier is missing" do
|
||||
cmd = "/document"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1204)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-missing-cid")
|
||||
end
|
||||
|
||||
it "returns an error if the collection identifier is unknown" do
|
||||
cmd = "/document?collection=123456"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1203)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-unknown-cid")
|
||||
end
|
||||
|
||||
it "returns an error if the collection name is unknown" do
|
||||
cmd = "/document?collection=unknown_collection"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1203)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-unknown-name")
|
||||
end
|
||||
|
||||
it "returns an error if the JSON body is corrupted" do
|
||||
cn = "UnitTestsCollectionBasics"
|
||||
id = AvocadoDB.create_collection(cn)
|
||||
|
||||
id.should be_kind_of(Integer)
|
||||
id.should_not be_zero
|
||||
|
||||
cmd = "/document?collection=#{id}"
|
||||
body = "{ 1 : 2 }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(600)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-bad-json")
|
||||
|
||||
AvocadoDB.size_collection(cn).should eq(0)
|
||||
|
||||
AvocadoDB.drop_collection(cn)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## known collection identifier, waitForSync = true
|
||||
################################################################################
|
||||
|
||||
context "known collection identifier, waitForSync = true:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "creating a new document" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
rev = doc.parsed_response['_rev']
|
||||
rev.should be_kind_of(Integer)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
match = /([0-9]*)\/([0-9]*)/.match(did)
|
||||
|
||||
match[1].should eq("#{@cid}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/document/#{did}")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## known collection identifier, waitForSync = false
|
||||
################################################################################
|
||||
|
||||
context "known collection identifier, waitForSync = false:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionUnsynced"
|
||||
@cid = AvocadoDB.create_collection(@cn, false)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "creating a new document" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
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(Integer)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
match = /([0-9]*)\/([0-9]*)/.match(did)
|
||||
|
||||
match[1].should eq("#{@cid}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/document/#{did}")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-accept")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## known collection name
|
||||
################################################################################
|
||||
|
||||
context "known collection name:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "creating a new document" do
|
||||
cmd = "/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
rev = doc.parsed_response['_rev']
|
||||
rev.should be_kind_of(Integer)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
match = /([0-9]*)\/([0-9]*)/.match(did)
|
||||
|
||||
match[1].should eq("#{@cid}")
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/document/#{did}")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-named-collection")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## unknown collection name
|
||||
################################################################################
|
||||
|
||||
context "unknown collection name:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionNamed#{Time.now.to_i}"
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "returns an error if collection is unknown" do
|
||||
cmd = "/document?collection=#{@cn}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1203)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-unknown-collection-name")
|
||||
end
|
||||
|
||||
it "create the collection and the document" do
|
||||
cmd = "/document?collection=#{@cn}&createCollection=true"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
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(Integer)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
did.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
location.should eq("/document/#{did}")
|
||||
|
||||
AvocadoDB.log(:method => :post, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-create-collection")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cn).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,346 @@
|
|||
require 'rspec'
|
||||
require './avocadodb.rb'
|
||||
|
||||
describe AvocadoDB do
|
||||
prefix = "rest_delete-document"
|
||||
|
||||
context "delete a document:" do
|
||||
|
||||
################################################################################
|
||||
## error handling
|
||||
################################################################################
|
||||
|
||||
context "error handling:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "returns an error if document handle is missing" do
|
||||
cmd = "/document"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(400)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}-missing-handle")
|
||||
end
|
||||
|
||||
it "returns an error if document handle is corrupted" do
|
||||
cmd = "/document/123456"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(400)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}-bad-handle")
|
||||
end
|
||||
|
||||
it "returns an error if document handle is corrupted" do
|
||||
cmd = "/document//123456"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(600)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}-bad-handle2")
|
||||
end
|
||||
|
||||
it "returns an error if collection identifier is unknown" do
|
||||
cmd = "/document/123456/234567"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1203)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}-unknown-cid")
|
||||
end
|
||||
|
||||
it "returns an error if document handle is unknown" do
|
||||
cmd = "/document/#{@cid}/234567"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1202)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}-unknown-handle")
|
||||
end
|
||||
|
||||
it "returns an error if the policy parameter is bad" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# delete document, different revision
|
||||
cmd = "/document/#{did}?policy=last-write"
|
||||
hdr = { "if-match" => "\"#{rev-1}\"" }
|
||||
doc = AvocadoDB.delete(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-policy-bad")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## deleting documents
|
||||
################################################################################
|
||||
|
||||
context "deleting documents:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "create a document and delete it" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# delete document
|
||||
cmd = "/document/#{did}"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and delete it, using if-match" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# delete document, different revision
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-match" => "\"#{rev-1}\"" }
|
||||
doc = AvocadoDB.delete(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(412)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-if-match-other")
|
||||
|
||||
# delete document, same revision
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-match" => "\"#{rev}\"" }
|
||||
doc = AvocadoDB.delete(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-if-match")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and delete it, using if-match and last-write wins" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# delete document, different revision
|
||||
cmd = "/document/#{did}?policy=last"
|
||||
hdr = { "if-match" => "\"#{rev-1}\"" }
|
||||
doc = AvocadoDB.delete(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-if-match-other-last-write")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and delete it, using rev" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# delete document, different revision
|
||||
cmd = "/document/#{did}?rev=#{rev-1}"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(412)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}-rev-other")
|
||||
|
||||
# delete document, same revision
|
||||
cmd = "/document/#{did}?rev=#{rev}"
|
||||
doc = AvocadoDB.delete(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :result => doc, :output => "#{prefix}-rev")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and delete it, using rev and last-write wins" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# delete document, different revision
|
||||
cmd = "/document/#{did}?policy=last"
|
||||
hdr = { "rev" => "\"#{rev-1}\"" }
|
||||
doc = AvocadoDB.delete(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :delete, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-rev-other-last-write")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,404 @@
|
|||
require 'rspec'
|
||||
require './avocadodb.rb'
|
||||
|
||||
describe AvocadoDB do
|
||||
prefix = "rest_read-document"
|
||||
|
||||
context "reading a document:" do
|
||||
|
||||
################################################################################
|
||||
## error handling
|
||||
################################################################################
|
||||
|
||||
context "error handling:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "returns an error if document handle is corrupted" do
|
||||
cmd = "/document/123456"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
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")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}-bad-handle")
|
||||
end
|
||||
|
||||
it "returns an error if document handle is corrupted" do
|
||||
cmd = "/document//123456"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(600)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}-bad-handle2")
|
||||
end
|
||||
|
||||
it "returns an error if collection identifier is unknown" do
|
||||
cmd = "/document/123456/234567"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1203)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}-unknown-cid")
|
||||
end
|
||||
|
||||
it "returns an error if document handle is unknown" do
|
||||
cmd = "/document/#{@cid}/234567"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1202)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}-unknown-handle")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## reading documents
|
||||
################################################################################
|
||||
|
||||
context "reading a document:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "create a document and read it" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# get document
|
||||
cmd = "/document/#{did}"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and read it, use if-none-match" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# get document, if-none-match with same rev
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-none-match" => "\"#{rev}\"" }
|
||||
doc = AvocadoDB.get(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(304)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-if-none-match")
|
||||
|
||||
# get document, if-none-match with different rev
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-none-match" => "\"#{rev-1}\"" }
|
||||
doc = AvocadoDB.get(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-if-none-match-other")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and read it, use if-match" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# get document, if-match with same rev
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-match" => "\"#{rev}\"" }
|
||||
doc = AvocadoDB.get(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
etag = doc.headers['etag']
|
||||
etag.should be_kind_of(String)
|
||||
|
||||
etag.should eq("\"#{rev}\"")
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-if-match")
|
||||
|
||||
# get document, if-match with different rev
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-match" => "\"#{rev-1}\"" }
|
||||
doc = AvocadoDB.get(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(412)
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-if-match-other")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## reading all documents
|
||||
################################################################################
|
||||
|
||||
context "reading all documents:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionAll"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "get all documents of an empty collection" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
|
||||
# get documents
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
documents = doc.parsed_response['documents']
|
||||
documents.should be_kind_of(Array)
|
||||
documents.length.should eq(0)
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}-all-0")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create three documents and read them using the collection identifier" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
|
||||
location = []
|
||||
|
||||
for i in [ 1, 2, 3 ]
|
||||
body = "{ \"Hallo\" : \"World-#{i}\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location.push(doc.headers['location'])
|
||||
end
|
||||
|
||||
# get document
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
documents = doc.parsed_response['documents']
|
||||
documents.should be_kind_of(Array)
|
||||
documents.length.should eq(3)
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}-all")
|
||||
|
||||
for l in location
|
||||
AvocadoDB.delete(l)
|
||||
end
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create three documents and read them using the collection name" do
|
||||
cmd = "/document?collection=#{@cn}"
|
||||
|
||||
location = []
|
||||
|
||||
for i in [ 1, 2, 3 ]
|
||||
body = "{ \"Hallo\" : \"World-#{i}\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location.push(doc.headers['location'])
|
||||
end
|
||||
|
||||
# get document
|
||||
cmd = "/document?collection=#{@cn}"
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
documents = doc.parsed_response['documents']
|
||||
documents.should be_kind_of(Array)
|
||||
documents.length.should eq(3)
|
||||
|
||||
AvocadoDB.log(:method => :get, :url => cmd, :result => doc, :output => "#{prefix}-all-name")
|
||||
|
||||
for l in location
|
||||
AvocadoDB.delete(l)
|
||||
end
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## checking document
|
||||
################################################################################
|
||||
|
||||
context "checking a document:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "create a document and read it" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
# get document
|
||||
cmd = location
|
||||
doc = AvocadoDB.get(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
content_length = doc.headers['content-length']
|
||||
|
||||
# get the document head
|
||||
doc = AvocadoDB.head(cmd)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
doc.headers['content-length'].should eq(content_length)
|
||||
doc.body.should eq(nil)
|
||||
|
||||
AvocadoDB.log(:method => :head, :url => cmd, :result => doc, :output => "#{prefix}-head")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,375 @@
|
|||
require 'rspec'
|
||||
require './avocadodb.rb'
|
||||
|
||||
describe AvocadoDB do
|
||||
prefix = "rest_update-document"
|
||||
|
||||
context "update a document:" do
|
||||
|
||||
################################################################################
|
||||
## error handling
|
||||
################################################################################
|
||||
|
||||
context "error handling:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "returns an error if document handle is missing" do
|
||||
cmd = "/document"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(400)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-missing-handle")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "returns an error if document handle is corrupted" do
|
||||
cmd = "/document/123456"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(400)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-bad-handle")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "returns an error if document handle is corrupted" do
|
||||
cmd = "/document//123456"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(600)
|
||||
doc.parsed_response['code'].should eq(400)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-bad-handle2")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "returns an error if collection identifier is unknown" do
|
||||
cmd = "/document/123456/234567"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1203)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-unknown-cid")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "returns an error if document handle is unknown" do
|
||||
cmd = "/document/#{@cid}/234567"
|
||||
body = "{}"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(404)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.parsed_response['errorNum'].should eq(1202)
|
||||
doc.parsed_response['code'].should eq(404)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-unknown-handle")
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "returns an error if the policy parameter is bad" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# update document, different revision
|
||||
cmd = "/document/#{did}?policy=last-write"
|
||||
hdr = { "if-match" => "\"#{rev-1}\"" }
|
||||
doc = AvocadoDB.put(cmd, :headers => hdr)
|
||||
|
||||
doc.code.should eq(400)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :headers => hdr, :result => doc, :output => "#{prefix}-policy-bad")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
## updating documents
|
||||
################################################################################
|
||||
|
||||
context "updating document:" do
|
||||
before do
|
||||
@cn = "UnitTestsCollectionBasics"
|
||||
@cid = AvocadoDB.create_collection(@cn)
|
||||
end
|
||||
|
||||
after do
|
||||
AvocadoDB.drop_collection(@cn)
|
||||
end
|
||||
|
||||
it "create a document and update it" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# update document
|
||||
cmd = "/document/#{did}"
|
||||
body = "{ \"World\" : \"Hallo\" }"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should_not eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and update it, using if-match" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# update document, different revision
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-match" => "\"#{rev-1}\"" }
|
||||
body = "{ \"World\" : \"Hallo\" }"
|
||||
doc = AvocadoDB.put(cmd, :headers => hdr, :body => body)
|
||||
|
||||
doc.code.should eq(412)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :headers => hdr, :result => doc, :output => "#{prefix}-if-match-other")
|
||||
|
||||
# update document, same revision
|
||||
cmd = "/document/#{did}"
|
||||
hdr = { "if-match" => "\"#{rev}\"" }
|
||||
body = "{ \"World\" : \"Hallo\" }"
|
||||
doc = AvocadoDB.put(cmd, :headers => hdr, :body => body)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should_not eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :headers => hdr, :result => doc, :output => "#{prefix}-if-match")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and update it, using if-match and last-write wins" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# update document, different revision
|
||||
cmd = "/document/#{did}?policy=last"
|
||||
hdr = { "if-match" => "\"#{rev-1}\"" }
|
||||
body = "{ \"World\" : \"Hallo\" }"
|
||||
doc = AvocadoDB.put(cmd, :headers => hdr, :body => body)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should_not eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :headers => hdr, :result => doc, :output => "#{prefix}-if-match-other-last-write")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and update it, using rev" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# update document, different revision
|
||||
cmd = "/document/#{did}?rev=#{rev-1}"
|
||||
body = "{ \"World\" : \"Hallo\" }"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(412)
|
||||
doc.parsed_response['error'].should eq(true)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-rev-other")
|
||||
|
||||
# update document, same revision
|
||||
cmd = "/document/#{did}?rev=#{rev}"
|
||||
body = "{ \"World\" : \"Hallo\" }"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should_not eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-rev")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
|
||||
it "create a document and update it, using rev and last-write wins" do
|
||||
cmd = "/document?collection=#{@cid}"
|
||||
body = "{ \"Hallo\" : \"World\" }"
|
||||
doc = AvocadoDB.post(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(201)
|
||||
|
||||
location = doc.headers['location']
|
||||
location.should be_kind_of(String)
|
||||
|
||||
did = doc.parsed_response['_id']
|
||||
rev = doc.parsed_response['_rev']
|
||||
|
||||
# update document, different revision
|
||||
cmd = "/document/#{did}?policy=last&rev=#{rev-1}"
|
||||
body = "{ \"World\" : \"Hallo\" }"
|
||||
doc = AvocadoDB.put(cmd, :body => body)
|
||||
|
||||
doc.code.should eq(200)
|
||||
doc.headers['content-type'].should eq("application/json; charset=utf-8")
|
||||
doc.parsed_response['error'].should eq(false)
|
||||
|
||||
did2 = doc.parsed_response['_id']
|
||||
did2.should be_kind_of(String)
|
||||
did2.should eq(did)
|
||||
|
||||
rev2 = doc.parsed_response['_rev']
|
||||
rev2.should be_kind_of(Integer)
|
||||
rev2.should_not eq(rev)
|
||||
|
||||
AvocadoDB.log(:method => :put, :url => cmd, :body => body, :result => doc, :output => "#{prefix}-rev-other-last-write")
|
||||
|
||||
AvocadoDB.delete(location)
|
||||
|
||||
AvocadoDB.size_collection(@cid).should eq(0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
test -d logs || mkdir logs
|
||||
|
||||
rspec rest_create-document_spec.rb --format d
|
||||
rspec rest_read-document_spec.rb --format d
|
||||
rspec rest_update-document_spec.rb --format d
|
||||
rspec rest_delete-document_spec.rb --format d
|
|
@ -1121,9 +1121,6 @@ static void FreeJoinsQueryInstance (TRI_query_instance_t* const instance) {
|
|||
|
||||
static bool AddBindParameterValues (TRI_query_instance_t* const instance,
|
||||
const TRI_json_t* parameters) {
|
||||
TRI_bind_parameter_t* parameter;
|
||||
void* nameParameter;
|
||||
void* valueParameter;
|
||||
size_t i;
|
||||
|
||||
assert(parameters);
|
||||
|
@ -1136,6 +1133,10 @@ static bool AddBindParameterValues (TRI_query_instance_t* const instance,
|
|||
}
|
||||
|
||||
for (i = 0; i < parameters->_value._objects._length; i += 2) {
|
||||
void* nameParameter;
|
||||
void* valueParameter;
|
||||
TRI_bind_parameter_t* parameter;
|
||||
|
||||
nameParameter = TRI_AtVector(¶meters->_value._objects, i);
|
||||
valueParameter = TRI_AtVector(¶meters->_value._objects, i + 1);
|
||||
|
||||
|
@ -1181,7 +1182,6 @@ static bool AddBindParameterValues (TRI_query_instance_t* const instance,
|
|||
static bool ValidateBindParameters (TRI_query_instance_t* const instance) {
|
||||
TRI_associative_pointer_t* templateParameters;
|
||||
TRI_associative_pointer_t* instanceParameters;
|
||||
TRI_bind_parameter_t* parameter;
|
||||
size_t i;
|
||||
|
||||
templateParameters = &instance->_template->_bindParameters;
|
||||
|
@ -1189,6 +1189,8 @@ static bool ValidateBindParameters (TRI_query_instance_t* const instance) {
|
|||
|
||||
// enumerate all template bind parameters....
|
||||
for (i = 0; i < templateParameters->_nrAlloc; i++) {
|
||||
TRI_bind_parameter_t* parameter;
|
||||
|
||||
parameter = (TRI_bind_parameter_t*) templateParameters->_table[i];
|
||||
if (!parameter) {
|
||||
continue;
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include "VocBase/query-cursor.h"
|
||||
#include "VocBase/query-context.h"
|
||||
#include "VocBase/query-locks.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
|
@ -143,14 +142,12 @@ static uint32_t GetBatchSizeQueryCursor (const TRI_query_cursor_t* const cursor)
|
|||
void TRI_FreeQueryCursor (TRI_query_cursor_t* cursor) {
|
||||
FreeData(cursor);
|
||||
|
||||
if (cursor->_locks) {
|
||||
TRI_FreeLocksQueryInstance(cursor->_vocbase, cursor->_locks);
|
||||
}
|
||||
|
||||
TRI_DestroyMutex(&cursor->_lock);
|
||||
TRI_DestroyVectorPointer(&cursor->_containers);
|
||||
|
||||
TRI_Free(cursor);
|
||||
|
||||
LOG_DEBUG("destroyed query cursor");
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,6 +198,8 @@ TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const instance,
|
|||
|
||||
TRI_InitMutex(&cursor->_lock);
|
||||
TRI_InitVectorPointer(&cursor->_containers);
|
||||
|
||||
LOG_DEBUG("created query cursor");
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
|
|
@ -170,12 +170,6 @@ TRI_query_cursor_t* TRI_ExecuteQueryInstance (TRI_query_instance_t* const instan
|
|||
cursor->_length = selectResult->_numRows;
|
||||
cursor->_currentRow = 0;
|
||||
|
||||
if (cursor->_length > 0 && !instance->_query._select._isConstant) {
|
||||
// we have a result set. the cursor now becomes responsible
|
||||
// for freeing any locks we still have on the underlying collections
|
||||
TRI_HandoverLocksQueryInstance(instance, cursor);
|
||||
}
|
||||
|
||||
return cursor;
|
||||
}
|
||||
|
||||
|
|
|
@ -256,18 +256,6 @@ bool TRI_AddCollectionsBarrierQueryInstance (TRI_query_instance_t* const instanc
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hand over locks from query instance to result cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_HandoverLocksQueryInstance (TRI_query_instance_t* const instance,
|
||||
TRI_query_cursor_t* const cursor) {
|
||||
cursor->_locks = instance->_locks;
|
||||
instance->_locks = NULL;
|
||||
// cursor is now responsible for freeing the locks
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a vector for holding collection locks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -109,19 +109,6 @@ void TRI_ReadUnlockCollectionsQueryInstance (TRI_query_instance_t* const);
|
|||
bool TRI_AddCollectionsBarrierQueryInstance (TRI_query_instance_t* const,
|
||||
TRI_query_cursor_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hand over locks from query instance to result cursor
|
||||
///
|
||||
/// This function is called when there is a select result with at least one row.
|
||||
/// The query instance will be freed immediately after executing the select,
|
||||
/// but the result set cursor might still be in use. The underlying collections
|
||||
/// are still needed and are still read-locked. When the cursor usage is over,
|
||||
/// the cursor is responsible for freeing the locks held.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_HandoverLocksQueryInstance (TRI_query_instance_t* const,
|
||||
TRI_query_cursor_t* const);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a vector for holding collection locks
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -77,6 +77,68 @@ static TRI_shadow_t* CreateShadow (const void* const data) {
|
|||
return shadow;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief decrease the refcount for a shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void DecreaseRefCount (TRI_shadow_store_t* const store, TRI_shadow_t* const shadow) {
|
||||
LOG_TRACE("decreasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
if (--shadow->_rc <= 0 && shadow->_type == SHADOW_TRANSIENT) {
|
||||
LOG_TRACE("deleting shadow %p", shadow);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&store->_ids, &shadow->_id);
|
||||
TRI_RemoveKeyAssociativePointer(&store->_pointers, shadow->_data);
|
||||
store->destroyShadow(shadow->_data);
|
||||
TRI_Free(shadow);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief increase the refcount for a shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void IncreaseRefCount (TRI_shadow_store_t* const store, TRI_shadow_t* const shadow) {
|
||||
LOG_TRACE("increasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
++shadow->_rc;
|
||||
UpdateTimestampShadow(shadow);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the persistence flag for a shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void PersistShadow (TRI_shadow_t* const shadow) {
|
||||
LOG_TRACE("persisting shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_type = SHADOW_PERSISTENT;
|
||||
UpdateTimestampShadow(shadow);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the deleted flag for a shadow
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void DeleteShadow (TRI_shadow_store_t* const store, TRI_shadow_t* const shadow) {
|
||||
LOG_TRACE("setting deleted flag for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_deleted = true;
|
||||
DecreaseRefCount(store, shadow);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief hashes an element in the ids index
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -260,13 +322,7 @@ void* TRI_BeginUsageDataShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("increasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
++shadow->_rc;
|
||||
UpdateTimestampShadow(shadow);
|
||||
IncreaseRefCount(store, shadow);
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
return shadow->_data;
|
||||
}
|
||||
|
@ -292,13 +348,7 @@ void* TRI_BeginUsageIdShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, (void const*) &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("increasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
++shadow->_rc;
|
||||
UpdateTimestampShadow(shadow);
|
||||
IncreaseRefCount(store, shadow);
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
return shadow->_data;
|
||||
}
|
||||
|
@ -325,19 +375,7 @@ void TRI_EndUsageDataShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("decreasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
if (--shadow->_rc <= 0 && shadow->_type == SHADOW_TRANSIENT) {
|
||||
LOG_TRACE("deleting shadow %p", shadow);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&store->_ids, &shadow->_id);
|
||||
TRI_RemoveKeyAssociativePointer(&store->_pointers, data);
|
||||
store->destroyShadow(shadow->_data);
|
||||
TRI_Free(shadow);
|
||||
}
|
||||
DecreaseRefCount(store, shadow); // this might delete the shadow
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
@ -361,19 +399,7 @@ void TRI_EndUsageIdShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("decreasing refcount for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
if (--shadow->_rc <= 0 && shadow->_type == SHADOW_TRANSIENT) {
|
||||
LOG_TRACE("deleting shadow %p", shadow);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&store->_ids, &id);
|
||||
TRI_RemoveKeyAssociativePointer(&store->_pointers, shadow->_data);
|
||||
store->destroyShadow(shadow->_data);
|
||||
TRI_Free(shadow);
|
||||
}
|
||||
DecreaseRefCount(store, shadow); // this might delete the shadow
|
||||
}
|
||||
|
||||
TRI_UnlockMutex(&store->_lock);
|
||||
|
@ -394,13 +420,7 @@ bool TRI_PersistDataShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("persisting shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_type = SHADOW_PERSISTENT;
|
||||
UpdateTimestampShadow(shadow);
|
||||
PersistShadow(shadow);
|
||||
result = true;
|
||||
}
|
||||
|
||||
|
@ -424,13 +444,7 @@ bool TRI_PersistIdShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("persisting shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_type = SHADOW_PERSISTENT;
|
||||
UpdateTimestampShadow(shadow);
|
||||
PersistShadow(shadow);
|
||||
result = true;
|
||||
}
|
||||
|
||||
|
@ -455,12 +469,7 @@ bool TRI_DeleteDataShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_pointers, data);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("setting deleted flag for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_deleted = true;
|
||||
DeleteShadow(store, shadow);
|
||||
found = true;
|
||||
}
|
||||
|
||||
|
@ -485,12 +494,7 @@ bool TRI_DeleteIdShadowData (TRI_shadow_store_t* const store,
|
|||
shadow = (TRI_shadow_t*) TRI_LookupByKeyAssociativePointer(&store->_ids, &id);
|
||||
|
||||
if (shadow && !shadow->_deleted) {
|
||||
LOG_TRACE("setting deleted flag for shadow %p with data ptr %p and id %lu",
|
||||
shadow,
|
||||
shadow->_data,
|
||||
(unsigned long) shadow->_id);
|
||||
|
||||
shadow->_deleted = true;
|
||||
DeleteShadow(store, shadow);
|
||||
found = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ function getCursorResult(cursor) {
|
|||
|
||||
function postCursor(req, res) {
|
||||
if (req.suffix.length != 0) {
|
||||
actions.actionResultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
actions.resultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,7 @@ function postCursor(req, res) {
|
|||
var json = JSON.parse(req.requestBody);
|
||||
|
||||
if (!json || !(json instanceof Object)) {
|
||||
actions.actionResultError (req, res, 400, actions.errorQuerySpecificationInvalid, "Query specification invalid");
|
||||
actions.resultError (req, res, 400, actions.errorQuerySpecificationInvalid, "Query specification invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -104,23 +104,23 @@ function postCursor(req, res) {
|
|||
(json.batchSize != undefined ? json.batchSize : 1000));
|
||||
}
|
||||
else {
|
||||
actions.actionResultError (req, res, 400, actions.errorQuerySpecificationInvalid, "Query specification invalid");
|
||||
actions.resultError (req, res, 400, actions.errorQuerySpecificationInvalid, "Query specification invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (cursor instanceof AvocadoQueryError) {
|
||||
// error occurred
|
||||
actions.actionResultError (req, res, 404, cursor.code, cursor.message);
|
||||
actions.resultError (req, res, 404, cursor.code, cursor.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// this might dispose or persist the cursor
|
||||
var result = getCursorResult(cursor);
|
||||
|
||||
actions.actionResultOK(req, res, 201, result);
|
||||
actions.resultOk(req, res, 201, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.errorJavascriptException, "Javascript exception");
|
||||
actions.resultError (req, res, 404, actions.errorJavascriptException, "Javascript exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ function postCursor(req, res) {
|
|||
|
||||
function putCursor(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
actions.resultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -142,10 +142,10 @@ function putCursor(req, res) {
|
|||
}
|
||||
|
||||
// note: this might dispose or persist the cursor
|
||||
actions.actionResultOK(req, res, 200, getCursorResult(cursor));
|
||||
actions.resultOk(req, res, 200, getCursorResult(cursor));
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.errorCursorNotFound, "Cursor not found");
|
||||
actions.resultError (req, res, 404, actions.errorCursorNotFound, "Cursor not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ function putCursor(req, res) {
|
|||
|
||||
function deleteCursor(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
actions.resultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -167,10 +167,10 @@ function deleteCursor(req, res) {
|
|||
}
|
||||
|
||||
cursor.dispose();
|
||||
actions.actionResultOK(req, res, 202, { "_id" : cursorId });
|
||||
actions.resultOk(req, res, 202, { "_id" : cursorId });
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.errorCursorNotFound, "Cursor not found");
|
||||
actions.resultError (req, res, 404, actions.errorCursorNotFound, "Cursor not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ actions.defineHttp({
|
|||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -74,7 +74,7 @@ actions.defineHttp({
|
|||
for (var i = 0; i < collections.length; ++i) {
|
||||
collection = collections[i];
|
||||
|
||||
result.push({ id : collection._id, name : collection._name });
|
||||
result.push({ id : collection._id, name : collection.name() });
|
||||
}
|
||||
|
||||
actions.result(req, res, actions.HTTP_OK, result);
|
||||
|
@ -129,7 +129,7 @@ function GET_api_database_collection (req, res) {
|
|||
var result = {};
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection._name;
|
||||
result.name = collection.name();
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ function POST_api_database_collection (req, res) {
|
|||
actions.VERR_COLLECTION_EXISTS,
|
||||
"collection already exists",
|
||||
undefined,
|
||||
{ name : collection._name, id : collection._id });
|
||||
{ name : collection.name(), id : collection._id });
|
||||
}
|
||||
else {
|
||||
collection = db[name];
|
||||
|
@ -219,7 +219,7 @@ function POST_api_database_collection (req, res) {
|
|||
var result = {};
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection._name;
|
||||
result.name = collection.name();
|
||||
|
||||
collection.parameter({ waitForSync : waitForSync });
|
||||
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief JavaScript actions modules
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var actions = require("actions");
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var API = "_api/";
|
||||
var ApiRequests = {};
|
||||
|
||||
ApiRequests.cursor = {};
|
||||
ApiRequests.cursor["POST /" + API + "cursor"] = "create and execute query. (creates a cursor)";
|
||||
ApiRequests.cursor["PUT /" + API + "cursor/<cursor-id>"] = "get next results";
|
||||
ApiRequests.cursor["DELETE /" + API + "cursor/<cursor-id>"] = "delete cursor";
|
||||
|
||||
ApiRequests.collection = {};
|
||||
ApiRequests.collection["GET /" + API + "collections"] = "get list of collections";
|
||||
ApiRequests.collection["GET /" + API + "collection/<collection-id>"] = "get all elements of collection";
|
||||
|
||||
ApiRequests.document = {};
|
||||
ApiRequests.document["POST /" + API + "document/<collection-id>"] = "create new document";
|
||||
ApiRequests.document["PUT /" + API + "document/<collection-id>/<document-id>"] = "update document";
|
||||
ApiRequests.document["GET /" + API + "document/<collection-id>/<document-id>"] = "get a document";
|
||||
ApiRequests.document["DELETE /" + API + "document/<collection-id>/<document-id>"] = "delete a document";
|
||||
|
||||
ApiRequests.query = {};
|
||||
ApiRequests.query["POST /" + API + "query"] = "create a query";
|
||||
ApiRequests.query["GET /" + API + "query/<query-id>"] = "get query";
|
||||
ApiRequests.query["PUT /" + API + "query/<query-id>"] = "change query";
|
||||
ApiRequests.query["DELETE /" + API + "query/<query-id>"] = "delete query";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a help
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "help",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
var result = {
|
||||
requests : ApiRequests
|
||||
}
|
||||
|
||||
actions.actionResultOK(req, res, 200, result);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -42,7 +42,7 @@ var actions = require("actions");
|
|||
|
||||
function postQuery(req, res) {
|
||||
if (req.suffix.length != 0) {
|
||||
actions.actionResultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
actions.resultError (req, res, 404, actions.errorInvalidRequest, "Invalid request");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -50,22 +50,22 @@ function postQuery(req, res) {
|
|||
var json = JSON.parse(req.requestBody);
|
||||
|
||||
if (!json || !(json instanceof Object) || json.query == undefined) {
|
||||
actions.actionResultError (req, res, 400, actions.errorQuerySpecificationInvalid, "Query specification invalid");
|
||||
actions.resultError (req, res, 400, actions.errorQuerySpecificationInvalid, "Query specification invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
var result = AQL_PARSE(json.query);
|
||||
if (result instanceof AvocadoQueryError) {
|
||||
actions.actionResultError (req, res, 404, result.code, result.message);
|
||||
actions.resultError (req, res, 404, result.code, result.message);
|
||||
return;
|
||||
}
|
||||
|
||||
result = { "bindVars" : result };
|
||||
|
||||
actions.actionResultOK(req, res, 200, result);
|
||||
actions.resultOk (req, res, 200, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.errorJavascriptException, "Javascript exception");
|
||||
actions.resultError (req, res, 404, actions.errorJavascriptException, "Javascript exception");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -88,7 +88,7 @@ actions.defineHttp({
|
|||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,388 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief querying and managing collections
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var actions = require("actions");
|
||||
var API = "_api/";
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a collection
|
||||
///
|
||||
/// @REST{POST /_api/collection}
|
||||
///
|
||||
/// Creates an new collection with a given name. The request must contain an
|
||||
/// object with the following attributes.
|
||||
///
|
||||
/// @LIT{name}: The name of the collection.
|
||||
///
|
||||
/// @LIT{waitForSync} (optional, default: false): If @LIT{true} then the data
|
||||
/// is synchronised to disk before returning from a create or update of an
|
||||
/// document.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// @verbinclude api-collection-create-collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function POST_api_collection (req, res) {
|
||||
var body;
|
||||
|
||||
try {
|
||||
body = JSON.parse(req.requestBody || "{}") || {};
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultBad(req, res, actions.ERROR_HTTP_CORRUPTED_JSON, err);
|
||||
return;
|
||||
}
|
||||
|
||||
var waitForSync = false;
|
||||
|
||||
if (! body.hasOwnProperty("name")) {
|
||||
actions.resultBad(req, res, actions.ERROR_AVOCADO_ILLEGAL_NAME,
|
||||
"name must be non-empty");
|
||||
return;
|
||||
}
|
||||
|
||||
var name = body.name;
|
||||
|
||||
if (body.hasOwnProperty("waitForSync")) {
|
||||
waitForSync = body.waitForSync;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = db._create(name, waitForSync);
|
||||
|
||||
var result = {};
|
||||
var headers = {};
|
||||
|
||||
collection.parameter({ waitForSync : waitForSync });
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection.name();
|
||||
result.waitForSync = collection.parameter().waitForSync;
|
||||
result.status = collection.status();
|
||||
|
||||
headers.location = "/" + API + "collection/" + collection._id;
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result, headers);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a collection
|
||||
///
|
||||
/// @REST{GET /_api/collection/@FA{collection-identifier}}
|
||||
///
|
||||
/// The result is an objects describing the collection with the following
|
||||
/// attributes:
|
||||
///
|
||||
/// @LIT{id}: The identifier of the collection.
|
||||
///
|
||||
/// @LIT{name}: The name of the collection.
|
||||
///
|
||||
/// @LIT{waitForSync}: If @LIT{true} then creating or changing a document will
|
||||
/// wait until the data has been synchronised to disk.
|
||||
///
|
||||
/// @LIT{status}: The status of the collection as number.
|
||||
///
|
||||
/// - 1: new born collection
|
||||
/// - 2: unloaded
|
||||
/// - 3: loaded
|
||||
/// - 4: in the process of being unloaded
|
||||
/// - 5: deleted
|
||||
///
|
||||
/// Every other status indicates a corrupted collection.
|
||||
///
|
||||
/// If the @FA{collection-identifier} is missing, then a @LIT{HTTP 400} is
|
||||
/// returned. If the @FA{collection-identifier} is unknown, then a @LIT{HTTP
|
||||
/// 404} is returned.
|
||||
///
|
||||
/// It is possible to specify a name instead of an identifier. In this case the
|
||||
/// response will contain a field "Location" which contains the correct
|
||||
/// location.
|
||||
///
|
||||
/// @REST{GET /_api/collection/@FA{collection-identifier}/count}
|
||||
///
|
||||
/// In addition to the above, the result also contains the number of documents.
|
||||
/// Note that this will always load the collection into memory.
|
||||
///
|
||||
/// @LIT{count}: The number of documents inside the collection.
|
||||
///
|
||||
/// @REST{GET /_api/collection/@FA{collection-identifier}/figures}
|
||||
///
|
||||
/// In addition to the above, the result also contains the number of documents
|
||||
/// and additional statistical information about the collection. Note that this
|
||||
/// will always load the collection into memory.
|
||||
///
|
||||
/// @LIT{count}: The number of documents inside the collection.
|
||||
///
|
||||
/// @LIT{figures.alive.count}: The number of living documents.
|
||||
///
|
||||
/// @LIT{figures.alive.size}: The total size in bytes used by all living
|
||||
/// documents.
|
||||
///
|
||||
/// @LIT{figures.dead.count}: The number of dead documents.
|
||||
///
|
||||
/// @LIT{figures.dead.size}: The total size in bytes used by all dead
|
||||
/// documents.
|
||||
///
|
||||
/// @LIT{figures.datafile.count}: The number of active datafiles.
|
||||
///
|
||||
/// @LIT{journalSize}: The maximal size of the journal in bytes.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Using an identifier:
|
||||
///
|
||||
/// @verbinclude api-collection-get-collection-identifier
|
||||
///
|
||||
/// Using a name:
|
||||
///
|
||||
/// @verbinclude api-collection-get-collection-name
|
||||
///
|
||||
/// Using an identifier and requesting the number of documents:
|
||||
///
|
||||
/// @verbinclude api-collection-get-collection-count
|
||||
///
|
||||
/// Using an identifier and requesting the figures of the collection:
|
||||
///
|
||||
/// @verbinclude api-collection-get-collection-figures
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function GET_api_collection (req, res) {
|
||||
if (req.suffix.length == 0) {
|
||||
actions.resultBad(req, res, actions.ERROR_HTTP_BAD_PARAMETER,
|
||||
"expected GET /" + API + "collection/<collection-identifer>")
|
||||
}
|
||||
else {
|
||||
var name = decodeURIComponent(req.suffix[0]);
|
||||
var id = parseInt(name) || name;
|
||||
var collection = db._collection(id);
|
||||
|
||||
if (collection == null) {
|
||||
actions.collectionNotFound(req, res, name);
|
||||
}
|
||||
else {
|
||||
|
||||
// .............................................................................
|
||||
// /_api/collection/<identifier>
|
||||
// .............................................................................
|
||||
|
||||
if (req.suffix.length == 1) {
|
||||
var result = {};
|
||||
var headers = {};
|
||||
var parameter = collection.parameter();
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection.name();
|
||||
result.waitForSync = parameter.waitForSync;
|
||||
result.status = collection.status();
|
||||
|
||||
headers.location = "/" + API + "collection/" + collection._id;
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result, headers);
|
||||
}
|
||||
|
||||
else if (req.suffix.length == 2) {
|
||||
var sub = decodeURIComponent(req.suffix[1]);
|
||||
|
||||
// .............................................................................
|
||||
// /_api/collection/<identifier>/figures
|
||||
// .............................................................................
|
||||
|
||||
if (sub == "figures") {
|
||||
var result = {};
|
||||
var headers = {};
|
||||
var parameter = collection.parameter();
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection.name();
|
||||
result.count = collection.count();
|
||||
result.journalSize = parameter.journalSize;
|
||||
result.waitForSync = parameter.waitForSync;
|
||||
|
||||
var figures = collection.figures();
|
||||
|
||||
if (figures) {
|
||||
result.figures = {
|
||||
alive : {
|
||||
count : figures.numberAlive,
|
||||
size : figures.sizeAlive
|
||||
},
|
||||
dead : {
|
||||
count : figures.numberDead,
|
||||
size : figures.sizeDead
|
||||
},
|
||||
datafiles : {
|
||||
count : figures.numberDatafiles
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
result.status = collection.status();
|
||||
|
||||
headers.location = "/" + API + "collection/" + collection._id + "/figures";
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result, headers);
|
||||
}
|
||||
|
||||
// .............................................................................
|
||||
// /_api/collection/<identifier>/count
|
||||
// .............................................................................
|
||||
|
||||
else if (sub == "count") {
|
||||
var result = {};
|
||||
var headers = {};
|
||||
var parameter = collection.parameter();
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection.name();
|
||||
result.count = collection.count();
|
||||
result.waitForSync = parameter.waitForSync;
|
||||
result.status = collection.status();
|
||||
|
||||
headers.location = "/" + API + "collection/" + collection._id + "/count";
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result, headers);
|
||||
}
|
||||
|
||||
else {
|
||||
actions.resultNotFound(req, res, "expecting one of the sub-method 'count', 'figures'");
|
||||
}
|
||||
}
|
||||
else {
|
||||
actions.resultBad(req, res, actions.ERROR_HTTP_BAD_PARAMETER,
|
||||
"expect GET /" + API + "collection/<collection-identifer>/<method>")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief deletes a collection
|
||||
///
|
||||
/// @REST{DELETE /_api/collection/@FA{collection-identifier}}
|
||||
///
|
||||
/// Deletes a collection identified by @FA{collection-identified}.
|
||||
///
|
||||
/// If the collection was successfully deleted then, an object is returned with
|
||||
/// the following attributes:
|
||||
///
|
||||
/// @LIT{error}: @LIT{false}
|
||||
///
|
||||
/// @LIT{id}: The identifier of the deleted collection.
|
||||
///
|
||||
/// If the @FA{collection-identifier} is missing, then a @LIT{HTTP 400} is
|
||||
/// returned. If the @FA{collection-identifier} is unknown, then a @LIT{HTTP
|
||||
/// 404} is returned.
|
||||
///
|
||||
/// It is possible to specify a name instead of an identifier.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Using an identifier:
|
||||
///
|
||||
/// @verbinclude api-collection-delete-collection-identifier
|
||||
///
|
||||
/// Using a name:
|
||||
///
|
||||
/// @verbinclude api-collection-delete-collection-name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function DELETE_api_collection (req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.resultBad(req, res, actions.ERROR_HTTP_BAD_PARAMETER,
|
||||
"expected DELETE /" + API + "collection/<collection-identifer>")
|
||||
}
|
||||
else {
|
||||
var name = decodeURIComponent(req.suffix[0]);
|
||||
var id = parseInt(name) || name;
|
||||
var collection = db._collection(id);
|
||||
|
||||
if (collection == null) {
|
||||
actions.collectionNotFound(req, res, name);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var result = {
|
||||
id : collection._id
|
||||
};
|
||||
|
||||
collection.drop();
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.resultException(req, res, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads or creates a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "collection",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
if (req.requestType == actions.GET) {
|
||||
GET_api_collection(req, res);
|
||||
}
|
||||
else if (req.requestType == actions.DELETE) {
|
||||
DELETE_api_collection(req, res);
|
||||
}
|
||||
else if (req.requestType == actions.POST) {
|
||||
POST_api_collection(req, res);
|
||||
}
|
||||
else {
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -1,261 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief querying and managing collections
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var actions = require("actions");
|
||||
var API = "_api/database/";
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn JSA_GET_api_datebase_collections
|
||||
/// @brief returns all collections
|
||||
///
|
||||
/// @REST{GET /_api/database/collections}
|
||||
///
|
||||
/// Returns all collections. The result is a list of objects with the following
|
||||
/// attributes:
|
||||
///
|
||||
/// @FA{id}
|
||||
///
|
||||
/// The identifier of the collection.
|
||||
///
|
||||
/// @FA{name}
|
||||
///
|
||||
/// The name of the collection.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// @verbinclude api_database1
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "collections",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
if (req.requestType != actions.GET) {
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
else {
|
||||
var collections = db._collections();
|
||||
var result = [];
|
||||
|
||||
for (var i = 0; i < collections.length; ++i) {
|
||||
collection = collections[i];
|
||||
|
||||
result.push({ id : collection._id, name : collection._name });
|
||||
}
|
||||
|
||||
actions.result(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns information about a collection
|
||||
///
|
||||
/// @REST{GET /_api/database/collection/@FA{collection-identifier}}
|
||||
///
|
||||
/// The result is an objects with the following attributes:
|
||||
///
|
||||
/// @FA{id}
|
||||
///
|
||||
/// The identifier of the collection.
|
||||
///
|
||||
/// @FA{name}
|
||||
///
|
||||
/// The name of the collection.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Using a name:
|
||||
///
|
||||
/// @verbinclude api_database2
|
||||
///
|
||||
/// Using an identifier:
|
||||
///
|
||||
/// @verbinclude api_database3
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function GET_api_database_collection (req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.collectionUnknown(req, res);
|
||||
}
|
||||
else {
|
||||
var name = req.suffix[0];
|
||||
var id = parseInt(name);
|
||||
|
||||
if (id != NaN) {
|
||||
name = id;
|
||||
}
|
||||
|
||||
var collection = db._collection(name);
|
||||
|
||||
if (collection == null) {
|
||||
actions.collectionUnknown(req, res, name);
|
||||
}
|
||||
else {
|
||||
var result = {};
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection._name;
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a new collection
|
||||
///
|
||||
/// @REST{POST /_api/database/collection}
|
||||
///
|
||||
/// Creates a new collection. If the collection could be create, a @LIT{HTTP 200}
|
||||
/// is returned. If the collection already exists, a @LIT{HTTP 409} is
|
||||
/// returned.
|
||||
///
|
||||
/// The call expects a JSON hash array as body with the following
|
||||
/// attributes:
|
||||
///
|
||||
/// @FA{name}
|
||||
///
|
||||
/// The name of the collection.
|
||||
///
|
||||
/// @FA{waitForSync} (optional, default true)
|
||||
///
|
||||
/// If @FA{waitForSync} is false, then creation of documents will not wait
|
||||
/// for the synchronization to file.
|
||||
///
|
||||
/// In case of success, returns information about the created collection:
|
||||
///
|
||||
/// @FA{id}
|
||||
///
|
||||
/// The identifier of the collection.
|
||||
///
|
||||
/// @FA{name}
|
||||
///
|
||||
/// The name of the collection.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Create a collection named test:
|
||||
///
|
||||
/// @verbinclude api_database4
|
||||
///
|
||||
/// Try it again:
|
||||
///
|
||||
/// @verbinclude api_database5
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function POST_api_database_collection (req, res) {
|
||||
var body = JSON.parse(req.requestBody || "{}");
|
||||
var name = body.name;
|
||||
var waitForSync = true;
|
||||
|
||||
if (body.hasOwnProperty("waitForSync")) {
|
||||
waitForSync = body.waitForSync;
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
badParameter(req, res, "name");
|
||||
}
|
||||
else {
|
||||
var collection = db._collection(name);
|
||||
|
||||
if (collection != null) {
|
||||
actions.error(req, res,
|
||||
actions.HTTP_CONFLICT,
|
||||
actions.VERR_COLLECTION_EXISTS,
|
||||
"collection already exists",
|
||||
undefined,
|
||||
{ name : collection._name, id : collection._id });
|
||||
}
|
||||
else {
|
||||
collection = db[name];
|
||||
|
||||
if (collection == null) {
|
||||
actions.badParameter(req, res, "cannot create collection named '" + name + "'");
|
||||
}
|
||||
else {
|
||||
if (collection._id == 0) {
|
||||
collection.load();
|
||||
}
|
||||
|
||||
if (collection._id == 0) {
|
||||
actions.badParameter(req, res, "cannot create collection named '" + name + "'");
|
||||
}
|
||||
else {
|
||||
var result = {};
|
||||
|
||||
result.id = collection._id;
|
||||
result.name = collection._name;
|
||||
|
||||
collection.parameter({ waitForSync : waitForSync });
|
||||
|
||||
actions.resultOk(req, res, actions.HTTP_OK, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads or creates a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "collection",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
if (req.requestType == actions.GET) {
|
||||
GET_api_database_collection(req, res);
|
||||
}
|
||||
else if (req.requestType == actions.POST) {
|
||||
POST_api_database_collection(req, res);
|
||||
}
|
||||
else {
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -1,423 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief simple queries
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var actions = require("actions");
|
||||
var simple = require("simple-query");
|
||||
var API = "_api/simple/";
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn JSA_PUT_api_simple_all
|
||||
/// @brief returns all documents of a collection
|
||||
///
|
||||
/// @REST{PUT /_api/simple/all}
|
||||
///
|
||||
/// Returns all documents of a collections. The call expects a JSON hash array
|
||||
/// as body with the following attributes:
|
||||
///
|
||||
/// @FA{collection}
|
||||
///
|
||||
/// The identifier or name of the collection to query.
|
||||
///
|
||||
/// @FA{skip} (optional)
|
||||
///
|
||||
/// The documents to skip in the query.
|
||||
///
|
||||
/// @FA{limit} (optional)
|
||||
///
|
||||
/// The maximal amount of documents to return.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// To get all documents (NEVER DO THAT!)
|
||||
///
|
||||
/// @verbinclude api_simple1
|
||||
///
|
||||
/// Limit the amount of documents using
|
||||
///
|
||||
/// @verbinclude api_simple2
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "all",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
var body = JSON.parse(req.requestBody || "{}");
|
||||
|
||||
var limit = body.limit;
|
||||
var skip = body.skip;
|
||||
var name = body.collection;
|
||||
|
||||
if (req.requestType != actions.PUT) {
|
||||
actions.unsupported(req, res);
|
||||
}
|
||||
else {
|
||||
collection = db._collection(name);
|
||||
|
||||
if (collection == null) {
|
||||
actions.collectionUnknown(req, res, name);
|
||||
}
|
||||
else {
|
||||
var result = collection.all();
|
||||
|
||||
if (skip != null) {
|
||||
result = result.skip(skip);
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
result = result.limit(limit);
|
||||
}
|
||||
|
||||
actions.result(req, res, actions.HTTP_OK, result.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn JSA_PUT_api_simple_near
|
||||
/// @brief returns all documents of a collection near a given location
|
||||
///
|
||||
/// @REST{PUT /_api/simple/near}
|
||||
///
|
||||
/// The default will find at most 100 documents near a given coordinate. The
|
||||
/// returned list is sorted according to the distance, with the nearest document
|
||||
/// coming first. If there are near documents of equal distance, documents are
|
||||
/// chosen randomly from this set until the limit is reached. It is possible to
|
||||
/// change the limit using the @FA{limit} operator.
|
||||
///
|
||||
/// In order to use the @FN{near} operator, a geo index must be defined for the
|
||||
/// collection. This index also defines which attribute holds the coordinates
|
||||
/// for the document. If you have more then one geo-spatial index, you can use
|
||||
/// the @FN{geo} operator to select a particular index.
|
||||
///
|
||||
/// The call expects a JSON hash array as body with the following attributes:
|
||||
///
|
||||
/// @FA{collection}
|
||||
///
|
||||
/// The identifier or name of the collection to query.
|
||||
///
|
||||
/// @FA{latitude}
|
||||
///
|
||||
/// The latitude of the coordinate.
|
||||
///
|
||||
/// @FA{longitude}
|
||||
///
|
||||
/// The longitude of the coordinate.
|
||||
///
|
||||
/// @FA{distance} (optional)
|
||||
///
|
||||
/// If given, the attribute key used to store the distance.
|
||||
///
|
||||
/// @FA{skip} (optional)
|
||||
///
|
||||
/// The documents to skip in the query.
|
||||
///
|
||||
/// @FA{limit} (optional)
|
||||
///
|
||||
/// The maximal amount of documents to return.
|
||||
///
|
||||
/// @FA{geo} (optional)
|
||||
///
|
||||
/// If given, the identifier of the geo-index to use.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Without distance:
|
||||
///
|
||||
/// @verbinclude api_simple3
|
||||
///
|
||||
/// With distance:
|
||||
///
|
||||
/// @verbinclude api_simple4
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "near",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
var body = JSON.parse(req.requestBody || "{}");
|
||||
|
||||
var limit = body.limit;
|
||||
var skip = body.skip;
|
||||
var latitude = body.latitude;
|
||||
var longitude = body.longitude;
|
||||
var distance = body.distance;
|
||||
var name = body.collection;
|
||||
var geo = body.geo;
|
||||
|
||||
if (req.requestType != actions.PUT) {
|
||||
actions.unsupported(req, res);
|
||||
}
|
||||
else {
|
||||
collection = db._collection(name);
|
||||
|
||||
if (collection == null) {
|
||||
actions.collectionUnknown(req, res, name);
|
||||
}
|
||||
else if (latitude == null) {
|
||||
actions.badParameter(req, res, "latitude");
|
||||
}
|
||||
else if (longitude == null) {
|
||||
actions.badParameter(req, res, "longitude");
|
||||
}
|
||||
else {
|
||||
var result;
|
||||
|
||||
if (geo == null) {
|
||||
result = collection.near(latitude, longitude);
|
||||
}
|
||||
else {
|
||||
result = collection.geo(geo).near(latitude, longitude);
|
||||
}
|
||||
|
||||
if (skip != null) {
|
||||
result = result.skip(skip);
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
result = result.limit(limit);
|
||||
}
|
||||
|
||||
if (distance != null) {
|
||||
result = result.distance(distance);
|
||||
}
|
||||
|
||||
actions.result(req, res, actions.HTTP_OK, result.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn JSA_PUT_api_simple_within
|
||||
/// @brief returns all documents of a collection within a given radius
|
||||
///
|
||||
/// @REST{PUT /_api/simple/within}
|
||||
///
|
||||
/// This will find all documents with in a given radius around the coordinate
|
||||
/// (@FA{latitude}, @FA{longitude}). The returned list is sorted by distance.
|
||||
///
|
||||
/// In order to use the @FN{within} operator, a geo index must be defined for the
|
||||
/// collection. This index also defines which attribute holds the coordinates
|
||||
/// for the document. If you have more then one geo-spatial index, you can use
|
||||
/// the @FN{geo} operator to select a particular index.
|
||||
///
|
||||
/// The call expects a JSON hash array as body with the following attributes:
|
||||
///
|
||||
/// @FA{collection}
|
||||
///
|
||||
/// The identifier or name of the collection to query.
|
||||
///
|
||||
/// @FA{latitude}
|
||||
///
|
||||
/// The latitude of the coordinate.
|
||||
///
|
||||
/// @FA{longitude}
|
||||
///
|
||||
/// The longitude of the coordinate.
|
||||
///
|
||||
/// @FA{radius}
|
||||
///
|
||||
/// The maximal radius.
|
||||
///
|
||||
/// @FA{distance} (optional)
|
||||
///
|
||||
/// If given, the attribute key used to store the distance.
|
||||
///
|
||||
/// @FA{skip} (optional)
|
||||
///
|
||||
/// The documents to skip in the query.
|
||||
///
|
||||
/// @FA{limit} (optional)
|
||||
///
|
||||
/// The maximal amount of documents to return.
|
||||
///
|
||||
/// @FA{geo} (optional)
|
||||
///
|
||||
/// If given, the identifier of the geo-index to use.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Without distance:
|
||||
///
|
||||
/// @verbinclude api_simple5
|
||||
///
|
||||
/// With distance:
|
||||
///
|
||||
/// @verbinclude api_simple6
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "within",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
var body = JSON.parse(req.requestBody || "{}");
|
||||
|
||||
var limit = body.limit;
|
||||
var skip = body.skip;
|
||||
var latitude = body.latitude;
|
||||
var longitude = body.longitude;
|
||||
var distance = body.distance;
|
||||
var radius = body.radius;
|
||||
var name = body.collection;
|
||||
var geo = body.geo;
|
||||
|
||||
if (req.requestType != actions.PUT) {
|
||||
actions.unsupported(req, res);
|
||||
}
|
||||
else {
|
||||
collection = db._collection(name);
|
||||
|
||||
if (collection == null) {
|
||||
actions.collectionUnknown(req, res, name);
|
||||
}
|
||||
else if (latitude == null) {
|
||||
actions.badParameter(req, res, "latitude");
|
||||
}
|
||||
else if (longitude == null) {
|
||||
actions.badParameter(req, res, "longitude");
|
||||
}
|
||||
else {
|
||||
var result;
|
||||
|
||||
if (geo == null) {
|
||||
result = collection.within(latitude, longitude, radius);
|
||||
}
|
||||
else {
|
||||
result = collection.geo(geo).within(latitude, longitude, radius);
|
||||
}
|
||||
|
||||
if (skip != null) {
|
||||
result = result.skip(skip);
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
result = result.limit(limit);
|
||||
}
|
||||
|
||||
if (distance != null) {
|
||||
result = result.distance(distance);
|
||||
}
|
||||
|
||||
actions.result(req, res, actions.HTTP_OK, result.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @fn JSA_PUT_api_simple_by_example
|
||||
/// @brief returns all documents of a collection matching a given example
|
||||
///
|
||||
/// @REST{PUT /_api/simple/by-example}
|
||||
///
|
||||
/// This will find all documents matching a given example.
|
||||
///
|
||||
/// The call expects a JSON hash array as body with the following attributes:
|
||||
///
|
||||
/// @FA{collection}
|
||||
///
|
||||
/// The identifier or name of the collection to query.
|
||||
///
|
||||
/// @FA{example}
|
||||
///
|
||||
/// The example.
|
||||
///
|
||||
/// @FA{skip} (optional)
|
||||
///
|
||||
/// The documents to skip in the query.
|
||||
///
|
||||
/// @FA{limit} (optional)
|
||||
///
|
||||
/// The maximal amount of documents to return.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// @verbinclude api_simple7
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : API + "by-example",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
var body = JSON.parse(req.requestBody || "{}");
|
||||
|
||||
var limit = body.limit;
|
||||
var skip = body.skip;
|
||||
var name = body.collection;
|
||||
var example = body.example;
|
||||
|
||||
if (req.requestType != actions.PUT) {
|
||||
actions.unsupported(req, res);
|
||||
}
|
||||
else {
|
||||
collection = db._collection(name);
|
||||
|
||||
if (collection == null) {
|
||||
actions.collectionUnknown(req, res, name);
|
||||
}
|
||||
else if (typeof example !== "object") {
|
||||
actions.badParameter(req, res, "example");
|
||||
}
|
||||
else {
|
||||
var result = collection.byExample(example);
|
||||
|
||||
if (skip != null) {
|
||||
result = result.skip(skip);
|
||||
}
|
||||
|
||||
if (limit != null) {
|
||||
result = result.limit(limit);
|
||||
}
|
||||
|
||||
actions.result(req, res, actions.HTTP_OK, result.toArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -44,15 +44,16 @@ function getCollections(req, res) {
|
|||
|
||||
for (var i = skip; i < end; ++i) {
|
||||
coll = colls[i];
|
||||
result.collections[coll._name] = {
|
||||
var name = coll.name();
|
||||
result.collections[name] = {
|
||||
_id : coll._id,
|
||||
name : coll._name,
|
||||
name : name,
|
||||
status : coll.status(),
|
||||
figures : coll.figures()
|
||||
};
|
||||
}
|
||||
|
||||
actions.actionResultOK(req, res, 200, result);
|
||||
actions.resultOk(req, res, 200, result);
|
||||
}
|
||||
|
||||
actions.defineHttp({
|
||||
|
@ -66,7 +67,7 @@ actions.defineHttp({
|
|||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
var actions = require("actions");
|
||||
|
||||
function getDocument(req, res) {
|
||||
if (req.suffix.length != 2) {
|
||||
actions.actionResultError (req, res, 404, actions.documentNotFound, "Document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = decodeURIComponent(req.suffix[0]);
|
||||
var documentId = decodeURIComponent(req.suffix[1]);
|
||||
var result = {
|
||||
"document" : {}
|
||||
};
|
||||
|
||||
result.document = db[collection].document(documentId);
|
||||
actions.actionResultOK(req, res, 200, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.documentNotFound, "Document not found: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
function deleteDocument(req, res) {
|
||||
if (req.suffix.length != 2) {
|
||||
actions.actionResultError (req, res, 404, actions.documentNotFound, "Document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = decodeURIComponent(req.suffix[0]);
|
||||
var documentId = decodeURIComponent(req.suffix[1]);
|
||||
|
||||
var result = {};
|
||||
|
||||
|
||||
if (db[collection].delete(documentId)) {
|
||||
result = {
|
||||
"deleted" : true,
|
||||
"_id" : documentId
|
||||
};
|
||||
|
||||
actions.actionResultOK(req, res, 200, result);
|
||||
}
|
||||
else {
|
||||
actions.actionResultError (req, res, 304, actions.documentNotModified, "Document not deleted");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError(req, res, 304, actions.documentNotModified, "Document not deleted: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
function postDocument(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.collectionNotFound, "Collection not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = decodeURIComponent(req.suffix[0]);
|
||||
var json = JSON.parse(req.requestBody);
|
||||
var id = db[collection].save(json);
|
||||
|
||||
var result = {
|
||||
"created" : true,
|
||||
"_id" : id
|
||||
};
|
||||
|
||||
actions.actionResultOK(req, res, 201, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.documentNotModified, "Document not saved: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
function putDocument(req, res) {
|
||||
if (req.suffix.length != 2) {
|
||||
actions.actionResultError (req, res, 404, actions.documentNotFound, "Document not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var collection = decodeURIComponent(req.suffix[0]);
|
||||
var documentId = decodeURIComponent(req.suffix[1]);
|
||||
var json = JSON.parse(req.requestBody);
|
||||
var id = db[collection].replace(documentId, json);
|
||||
|
||||
var result = {
|
||||
"updated" : true,
|
||||
"_id" : id
|
||||
};
|
||||
|
||||
actions.actionResultOK(req, res, 202, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.documentNotModified, "Document not changed: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_api/document",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
switch (req.requestType) {
|
||||
case ("GET") :
|
||||
getDocument(req, res);
|
||||
break;
|
||||
|
||||
case ("POST") :
|
||||
postDocument(req, res);
|
||||
break;
|
||||
|
||||
case ("PUT") :
|
||||
putDocument(req, res);
|
||||
break;
|
||||
|
||||
case ("DELETE") :
|
||||
deleteDocument(req, res);
|
||||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -2,7 +2,7 @@ var actions = require("actions");
|
|||
|
||||
function getDocuments(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.collectionNotFound, "Collection not found");
|
||||
actions.resultError (req, res, 404, actions.collectionNotFound, "Collection not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -26,10 +26,10 @@ function getDocuments(req, res) {
|
|||
|
||||
try {
|
||||
var result = db[collection].ALL(skip, limit);
|
||||
actions.actionResultOK(req, res, 200, result);
|
||||
actions.resultOk(req, res, 200, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.collectionNotFound, "Collection not found")
|
||||
actions.resultError (req, res, 404, actions.collectionNotFound, "Collection not found")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ actions.defineHttp({
|
|||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -36,57 +36,6 @@ var actions = require("actions");
|
|||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns information about all collections
|
||||
///
|
||||
/// @REST{GET /_system/collections}
|
||||
///
|
||||
/// Returns information about all collections of the database. The returned
|
||||
/// array contains the following entries.
|
||||
///
|
||||
/// - path: The server directory containing the database.
|
||||
/// - collections : An associative array of all collections.
|
||||
///
|
||||
/// An entry of collections is again an associative array containing the
|
||||
/// following entries.
|
||||
///
|
||||
/// - name: The name of the collection.
|
||||
/// - status: The status of the collection. 1 = new born, 2 = unloaded,
|
||||
/// 3 = loaded, 4 = corrupted.
|
||||
///
|
||||
/// @verbinclude rest15
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_system/collections",
|
||||
context : "admin",
|
||||
|
||||
callback : function (req, res) {
|
||||
var colls;
|
||||
var coll;
|
||||
var result;
|
||||
|
||||
colls = db._collections();
|
||||
result = {
|
||||
path : db._path,
|
||||
collections : {}
|
||||
};
|
||||
|
||||
for (var i = 0; i < colls.length; ++i) {
|
||||
coll = colls[i];
|
||||
|
||||
result.collections[coll._name] = {
|
||||
id : coll._id,
|
||||
name : coll._name,
|
||||
status : coll.status(),
|
||||
figures : coll.figures()
|
||||
};
|
||||
}
|
||||
|
||||
actions.actionResult(req, res, 200, result);
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief loads a collection
|
||||
///
|
||||
|
@ -98,17 +47,17 @@ actions.defineHttp({
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_system/collection/load",
|
||||
url : "_system/collection/load", // TODO -> api_collection.js
|
||||
context : "admin",
|
||||
|
||||
callback : function (req, res) {
|
||||
try {
|
||||
req.collection.load();
|
||||
|
||||
actions.actionResult(req, res, 204);
|
||||
actions.resultOk(req, res, 204);
|
||||
}
|
||||
catch (err) {
|
||||
actions.actionError(req, res, err);
|
||||
actions.resultError(req, res, err);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -117,61 +66,6 @@ actions.defineHttp({
|
|||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief information about a collection
|
||||
///
|
||||
/// @REST{GET /_system/collection/info?collection=@FA{identifier}}
|
||||
///
|
||||
/// Returns information about a collection
|
||||
///
|
||||
/// @verbinclude rest16
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_system/collection/info",
|
||||
context : "admin",
|
||||
|
||||
callback : function (req, res) {
|
||||
try {
|
||||
result = {};
|
||||
result.id = req.collection._id;
|
||||
result.name = req.collection._name;
|
||||
result.status = req.collection.status();
|
||||
result.figures = req.collection.figures();
|
||||
|
||||
actions.actionResult(req, res, 200, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.actionError(req, res, err);
|
||||
}
|
||||
},
|
||||
|
||||
parameters : {
|
||||
collection : "collection-identifier"
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns information about all documents
|
||||
///
|
||||
/// @REST{GET /_system/documents}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_system/documents",
|
||||
context : "admin",
|
||||
|
||||
callback : function (req, res) {
|
||||
queryReferences(req, res, req.collection.all());
|
||||
},
|
||||
|
||||
parameters : {
|
||||
collection : "collection-identifier",
|
||||
blocksize : "number",
|
||||
page : "number"
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns information about all indexes of a collection
|
||||
///
|
||||
|
@ -181,20 +75,20 @@ actions.defineHttp({
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_system/collection/indexes",
|
||||
url : "_system/collection/indexes", // TODO api_indexes.js
|
||||
context : "admin",
|
||||
|
||||
callback : function (req, res) {
|
||||
try {
|
||||
result = {};
|
||||
result.name = req.collection._name;
|
||||
result.name = req.collection.name();
|
||||
result.id = req.collection._id;
|
||||
result.indexes = req.collection.getIndexes();
|
||||
|
||||
actions.actionResult(req, res, 200, result);
|
||||
actions.resultOk(req, res, 200, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.actionError(req, res, err);
|
||||
actions.resultError(req, res, err);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -210,7 +104,7 @@ actions.defineHttp({
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_system/status",
|
||||
url : "_system/status", // TODO -> _api/system
|
||||
context : "admin",
|
||||
|
||||
callback : function (req, res) {
|
||||
|
@ -218,10 +112,10 @@ actions.defineHttp({
|
|||
result = {};
|
||||
result.system = SYS_PROCESS_STAT();
|
||||
|
||||
actions.actionResult(req, res, 200, result);
|
||||
actions.resultOk(req, res, 200, result);
|
||||
}
|
||||
catch (err) {
|
||||
actions.actionError(req, res, err);
|
||||
actions.resultError(req, res, err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -113,7 +113,7 @@ function buildDocumentFromReq(req) {
|
|||
|
||||
function postKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not created. Missing key.");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not created. Missing key.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@ function postKeyValue(req, res) {
|
|||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ function postKeyValue(req, res) {
|
|||
s.execute();
|
||||
|
||||
if (s._countTotal != 0) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Use PUT to change value");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Use PUT to change value");
|
||||
}
|
||||
else {
|
||||
var id = db[collection].save(doc);
|
||||
|
@ -139,11 +139,11 @@ function postKeyValue(req, res) {
|
|||
"saved" : true,
|
||||
"_id" : id
|
||||
}
|
||||
actions.actionResultOK(req, res, 201, result);
|
||||
actions.resultOk(req, res, 201, result);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not created. " + e.message);
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not created. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ function postKeyValue(req, res) {
|
|||
|
||||
function putKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ function putKeyValue(req, res) {
|
|||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -177,13 +177,13 @@ function putKeyValue(req, res) {
|
|||
"saved" : true,
|
||||
"_id" : id
|
||||
}
|
||||
actions.actionResultOK(req, res, 201, result);
|
||||
actions.resultOk(req, res, 201, result);
|
||||
return;
|
||||
}
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
}
|
||||
else if (s._countTotal > 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. Wrong key?");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. Wrong key?");
|
||||
}
|
||||
else {
|
||||
// get _id
|
||||
|
@ -197,15 +197,15 @@ function putKeyValue(req, res) {
|
|||
|
||||
// replace the document
|
||||
if (db[collection].replace(id, doc)) {
|
||||
actions.actionResultOK(req, res, 202, {"changed" : true});
|
||||
actions.resultOk(req, res, 202, {"changed" : true});
|
||||
}
|
||||
else {
|
||||
actions.actionResultError(req, res, 404, actions.keyValueNotModified, "Value not changed");
|
||||
actions.resultError(req, res, 404, actions.keyValueNotModified, "Value not changed");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. " + e.message);
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ function putKeyValue(req, res) {
|
|||
|
||||
function deleteKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -223,7 +223,7 @@ function deleteKeyValue(req, res) {
|
|||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -237,23 +237,23 @@ function deleteKeyValue(req, res) {
|
|||
s.execute();
|
||||
|
||||
if (s._countTotal < 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found");
|
||||
}
|
||||
else if (s._countTotal > 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. Wrong key?");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. Wrong key?");
|
||||
}
|
||||
else {
|
||||
var id = s._execution._documents[0]._id;
|
||||
if (db[collection].delete(id)) {
|
||||
actions.actionResultOK(req, res, 202, {"removed" : true});
|
||||
actions.resultOk(req, res, 202, {"removed" : true});
|
||||
}
|
||||
else {
|
||||
actions.actionResultError(req, res, 404, actions.keyValueNotModified, "Value not removed");
|
||||
actions.resultError(req, res, 404, actions.keyValueNotModified, "Value not removed");
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. " + e.message);
|
||||
actions.resultError (req, res, 404, actions.keyValueNotModified, "Key value pair not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ function deleteKeyValue(req, res) {
|
|||
|
||||
function getKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ function getKeyValue(req, res) {
|
|||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Collection not found.");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -285,10 +285,10 @@ function getKeyValue(req, res) {
|
|||
s.execute();
|
||||
|
||||
if (s._countTotal < 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found");
|
||||
}
|
||||
else if (s._countTotal > 1) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found. Wrong key?");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found. Wrong key?");
|
||||
}
|
||||
else {
|
||||
var headers = {};
|
||||
|
@ -306,11 +306,11 @@ function getKeyValue(req, res) {
|
|||
headers["x-voc-created"] = formatTimeStamp(s._execution._documents[0]["x-voc-created"]);
|
||||
}
|
||||
|
||||
actions.actionResultOK(req, res, 200, s._execution._documents[0].value, headers);
|
||||
actions.resultOk(req, res, 200, s._execution._documents[0].value, headers);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found. " + e.message);
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Key value pair not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -345,7 +345,7 @@ actions.defineHttp({
|
|||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -370,7 +370,7 @@ actions.defineHttp({
|
|||
|
||||
function searchKeyValue(req, res) {
|
||||
if (req.suffix.length < 2) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pairs not found.");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Key value pairs not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -378,7 +378,7 @@ function searchKeyValue(req, res) {
|
|||
var collection = req.suffix[0];
|
||||
|
||||
if (db._collection(collection) == null) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Collection not found.");
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Collection not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -407,10 +407,10 @@ function searchKeyValue(req, res) {
|
|||
}
|
||||
}
|
||||
|
||||
actions.actionResult (req, res, 200, result);
|
||||
actions.result (req, res, 200, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.keyValueNotFound, "Key value pairs not found. " + e.message);
|
||||
actions.resultError (req, res, 404, actions.keyValueNotFound, "Key value pairs not found. " + e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,7 +433,7 @@ actions.defineHttp({
|
|||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
actions.resultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -585,16 +585,8 @@ AvocadoDatabase.prototype._create = function (name) {
|
|||
"name" : name
|
||||
};
|
||||
|
||||
var str = this._connection.post("/_api/database/collection", JSON.stringify(body));
|
||||
var requestResult = this._connection.post("/_api/collection", JSON.stringify(body));
|
||||
|
||||
print(str);
|
||||
|
||||
var requestResult = undefined;
|
||||
|
||||
if (str != undefined) {
|
||||
requestResult = JSON.parse(str);
|
||||
}
|
||||
|
||||
if (isErrorResult(requestResult)) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -617,278 +609,7 @@ AvocadoDatabase.prototype._help = function () {
|
|||
AvocadoDatabase.prototype.toString = function () {
|
||||
return "[object AvocadoDatabase]";
|
||||
}
|
||||
/*
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- AvocadoStoredStatement
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function AvocadoStoredStatement (database, data) {
|
||||
this._database = database;
|
||||
this._doCount = false;
|
||||
this._batchSize = null;
|
||||
this._bindVars = {};
|
||||
this._id = null;
|
||||
this.document = {
|
||||
"queryCollection" : DEFAULT_QUERY_COLLECTION
|
||||
};
|
||||
|
||||
if (!(data instanceof Object)) {
|
||||
throw "AvocadoStoredStatement needs a data attribute";
|
||||
}
|
||||
|
||||
if (data["name"] != undefined) {
|
||||
this.document.name = data["name"];
|
||||
}
|
||||
|
||||
if (data["query"] != undefined) {
|
||||
this.document.query = data["query"];
|
||||
}
|
||||
|
||||
if (data["queryCollection"] != undefined) {
|
||||
this.document.queryCollection = data["queryCollection"];
|
||||
}
|
||||
|
||||
this._isNew = (data["query"] != undefined);
|
||||
|
||||
this.validate();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief update a stored statement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.update = function (data) {
|
||||
// update query string
|
||||
if (data["query"] != undefined) {
|
||||
this.document.query = data["query"];
|
||||
}
|
||||
|
||||
this.validate();
|
||||
|
||||
var queryCollection = new AvocadoCollection(this._database, this.document.queryCollection);
|
||||
if (!queryCollection) {
|
||||
throw "Could not determine collection for AvocadoStoredStatement";
|
||||
}
|
||||
|
||||
if (this._isNew) {
|
||||
var requestResult = queryCollection.save(this.document);
|
||||
if (requestResult == undefined) {
|
||||
throw "Could not save AvocadoStoredStatement";
|
||||
}
|
||||
|
||||
// document saved
|
||||
this._id = requestResult;
|
||||
this._isNew = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!queryCollection.update(this.document._id, this.document)) {
|
||||
throw "Could not update AvocadoStoredStatement";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief save a stored statement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.save = function () {
|
||||
return this.update(this.document);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief validate the data of an AvocadoStoredStatement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.validate = function () {
|
||||
if (this._isNew) {
|
||||
if (this.document.query == undefined || this.document.query == "") {
|
||||
throw "AvocadoStoredStatement needs a valid query";
|
||||
}
|
||||
}
|
||||
|
||||
if (this.document.name == undefined || this.document.name == "") {
|
||||
throw "AvocadoStoredStatement needs a name attribute";
|
||||
}
|
||||
|
||||
if (this.document.queryCollection == undefined || this.document.queryCollection == "") {
|
||||
throw "AvocadoStoredStatement needs a queryCollection";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief lookup the data of an AvocadoStoredStatement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.lookup = function () {
|
||||
if (this.isNew) {
|
||||
throw "Cannot lookup a new AvocadoStoredStatement";
|
||||
}
|
||||
|
||||
var data = {
|
||||
"query" : "SELECT c FROM `" + this.document.queryCollection +
|
||||
"` c WHERE c.name == '" + QuoteJSONString(this.document.name) + "'"
|
||||
}
|
||||
var statement = new AvocadoStatement(this._database, data);
|
||||
var result = statement.execute();
|
||||
if (result instanceof AvocadoQueryError) {
|
||||
throw result.message;
|
||||
}
|
||||
|
||||
if (!result.hasNext()) {
|
||||
throw "Could not find stored statement for the given parameters";
|
||||
}
|
||||
|
||||
var row = result.next();
|
||||
this._id = row["id"];
|
||||
this._query = row["query"];
|
||||
this._isNew = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief delete a stored statement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.delete = function () {
|
||||
if (this._isNew) {
|
||||
throw "Cannot delete a new AvocadoStoredStatement";
|
||||
}
|
||||
|
||||
if (this._id == undefined || this._id == null) {
|
||||
this.lookup();
|
||||
}
|
||||
|
||||
var queryCollection = new AvocadoCollection(this._database, this.document.collection);
|
||||
if (!queryCollection) {
|
||||
throw "Could not determine collection for AvocadoStoredStatement";
|
||||
}
|
||||
|
||||
if (!queryCollection.delete(this.document._id)) {
|
||||
this.document = {};
|
||||
this._isNew = true;
|
||||
this._bindVars = {};
|
||||
this._id = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief bind a parameter to the statement
|
||||
///
|
||||
/// This function can be called multiple times, once for each bind parameter.
|
||||
/// All bind parameters will be transferred to the server in one go when
|
||||
/// execute() is called.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.bind = function (key, value) {
|
||||
if (typeof(key) != "string") {
|
||||
throw "bind parameter name must be a string";
|
||||
}
|
||||
|
||||
if (this._bindVars[key] != undefined) {
|
||||
throw "redeclaration of bind parameter";
|
||||
}
|
||||
|
||||
this._bindVars[key] = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the count flag for the statement
|
||||
///
|
||||
/// Setting the count flag will make the query instance's cursor return the
|
||||
/// total number of result documents. The count flag is not set by default.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.setCount = function (bool) {
|
||||
this._doCount = bool ? true : false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the maximum number of results documents the cursor will return
|
||||
/// in a single server roundtrip.
|
||||
/// The higher this number is, the less server roundtrips will be made when
|
||||
/// iterating over the result documents of a cursor.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.setBatchSize = function (value) {
|
||||
if (parseInt(value) > 0) {
|
||||
this._batchSize = parseInt(value);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute the query
|
||||
///
|
||||
/// Invoking execute() will transfer the query and all bind parameters to the
|
||||
/// server. It will return a cursor with the query results in case of success.
|
||||
/// In case of an error, the error will be printed
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.execute = function () {
|
||||
if (this._isNew) {
|
||||
this.save();
|
||||
}
|
||||
|
||||
var body = {
|
||||
"name" : this.document.name,
|
||||
"count" : this._doCount,
|
||||
"bindVars" : this._bindVars,
|
||||
"_id" : this._id
|
||||
}
|
||||
|
||||
if (this._batchSize) {
|
||||
body["batchSize"] = this._batchSize;
|
||||
}
|
||||
|
||||
var requestResult = this._database._connection.post("/_api/cursor", JSON.stringify(body));
|
||||
|
||||
if (isErrorResult(requestResult)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return new AvocadoQueryCursor(this._database, requestResult);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief print the help for AvocadoStoredStatement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype._help = function () {
|
||||
print(helpAvocadoStoredStatement);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a string representation of the stored statement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStoredStatement.prototype.toString = function () {
|
||||
return getIdString(this, "AvocadoStoredStatement");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief factory method to create a new stored statement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoDatabase.prototype._createStoredStatement = function (data) {
|
||||
return new AvocadoStoredStatement(this, data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief factory method to retrieve an existing stored statement
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoDatabase.prototype._getStoredStatement = function (data) {
|
||||
return new AvocadoStoredStatement(this, data);
|
||||
}
|
||||
|
||||
*/
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- AvocadoStatement
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -977,7 +698,7 @@ AvocadoStatement.prototype.getCount = function () {
|
|||
/// in a single server roundtrip.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoStatement.prototype.getMax = function () {
|
||||
AvocadoStatement.prototype.getBatchSize = function () {
|
||||
return this._batchSize;
|
||||
}
|
||||
|
||||
|
@ -1126,7 +847,7 @@ getHeadline("Select query help") +
|
|||
' > st.setCount(<value>); set count flag (return number of ' + "\n" +
|
||||
' results in "count" attribute) ' + "\n" +
|
||||
'Get query options: ' + "\n" +
|
||||
' > st.getMax(); return the max. number of results ' + "\n" +
|
||||
' > st.setBatchSize(); return the max. number of results ' + "\n" +
|
||||
' to be transferred per roundtrip ' + "\n" +
|
||||
' > st.getCount(); return count flag (return number of' + "\n" +
|
||||
' results in "count" attribute) ' + "\n" +
|
||||
|
@ -1205,7 +926,7 @@ getHeadline("AvocadoStatement help") +
|
|||
' to be transferred per roundtrip ' + "\n" +
|
||||
' setCount(<value>); set count flag (return number of ' + "\n" +
|
||||
' results in "count" attribute) ' + "\n" +
|
||||
' getMax(); return max. number of results ' + "\n" +
|
||||
' getBatchSize(); return max. number of results ' + "\n" +
|
||||
' to be transferred per roundtrip ' + "\n" +
|
||||
' getCount(); return count flag (return number of' + "\n" +
|
||||
' results in "count" attribute) ' + "\n" +
|
||||
|
@ -1221,32 +942,7 @@ getHeadline("AvocadoStatement help") +
|
|||
' > st.bind("b", "world"); ' + "\n" +
|
||||
' > c = st.execute(); ' + "\n" +
|
||||
' > print(c.elements()); ';
|
||||
/*
|
||||
helpAvocadoStoredStatement =
|
||||
getHeadline("AvocadoQueryTemplate help") +
|
||||
'AvocadoQueryTemplate constructor: ' + "\n" +
|
||||
' > qt1 = db._createQueryTemplate("select ..."); simple query ' + "\n" +
|
||||
' > qt2 = db._createQueryTemplate( complex query ' + "\n" +
|
||||
' {query:"select...", ' + "\n" +
|
||||
' name:"qname", ' + "\n" +
|
||||
' collection:"q" ' + "\n" +
|
||||
' ... } ' + "\n" +
|
||||
'Functions: ' + "\n" +
|
||||
' update(<new data>); update query template ' + "\n" +
|
||||
' delete(<id>); delete query template by id ' + "\n" +
|
||||
' getInstance(); get a query instance ' + "\n" +
|
||||
' returns: AvocadoQueryInstance' + "\n" +
|
||||
' _help(); this help ' + "\n" +
|
||||
'Attributes: ' + "\n" +
|
||||
' _database database object ' + "\n" +
|
||||
' _id template id ' + "\n" +
|
||||
' name collection name ' + "\n" +
|
||||
'Example: ' + "\n" +
|
||||
' > qt1 = db._getQueryTemplate("4334:2334"); ' + "\n" +
|
||||
' > qt1.update("select a from collA a"); ' + "\n" +
|
||||
' > qi1 = qt1.getInstance(); ' + "\n" +
|
||||
' > qt1.delete("4334:2334"); ';
|
||||
*/
|
||||
|
||||
helpExtended =
|
||||
getHeadline("More help") +
|
||||
'Pager: ' + "\n" +
|
||||
|
|
|
@ -586,16 +586,8 @@ static string JS_client_client =
|
|||
" \"name\" : name\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" var str = this._connection.post(\"/_api/database/collection\", JSON.stringify(body));\n"
|
||||
" var requestResult = this._connection.post(\"/_api/collection\", JSON.stringify(body));\n"
|
||||
"\n"
|
||||
" print(str);\n"
|
||||
" \n"
|
||||
" var requestResult = undefined;\n"
|
||||
"\n"
|
||||
" if (str != undefined) {\n"
|
||||
" requestResult = JSON.parse(str);\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if (isErrorResult(requestResult)) {\n"
|
||||
" return undefined;\n"
|
||||
" }\n"
|
||||
|
@ -618,278 +610,7 @@ static string JS_client_client =
|
|||
"AvocadoDatabase.prototype.toString = function () { \n"
|
||||
" return \"[object AvocadoDatabase]\";\n"
|
||||
"}\n"
|
||||
"/*\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- AvocadoStoredStatement\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief constructor\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"function AvocadoStoredStatement (database, data) {\n"
|
||||
" this._database = database;\n"
|
||||
" this._doCount = false;\n"
|
||||
" this._batchSize = null;\n"
|
||||
" this._bindVars = {};\n"
|
||||
" this._id = null;\n"
|
||||
" this.document = {\n"
|
||||
" \"queryCollection\" : DEFAULT_QUERY_COLLECTION\n"
|
||||
" };\n"
|
||||
"\n"
|
||||
" if (!(data instanceof Object)) {\n"
|
||||
" throw \"AvocadoStoredStatement needs a data attribute\";\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if (data[\"name\"] != undefined) {\n"
|
||||
" this.document.name = data[\"name\"];\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if (data[\"query\"] != undefined) {\n"
|
||||
" this.document.query = data[\"query\"];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (data[\"queryCollection\"] != undefined) {\n"
|
||||
" this.document.queryCollection = data[\"queryCollection\"];\n"
|
||||
" } \n"
|
||||
" \n"
|
||||
" this._isNew = (data[\"query\"] != undefined); \n"
|
||||
"\n"
|
||||
" this.validate();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief update a stored statement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.update = function (data) {\n"
|
||||
" // update query string\n"
|
||||
" if (data[\"query\"] != undefined) {\n"
|
||||
" this.document.query = data[\"query\"];\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" this.validate();\n"
|
||||
"\n"
|
||||
" var queryCollection = new AvocadoCollection(this._database, this.document.queryCollection);\n"
|
||||
" if (!queryCollection) {\n"
|
||||
" throw \"Could not determine collection for AvocadoStoredStatement\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (this._isNew) {\n"
|
||||
" var requestResult = queryCollection.save(this.document);\n"
|
||||
" if (requestResult == undefined) {\n"
|
||||
" throw \"Could not save AvocadoStoredStatement\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" // document saved\n"
|
||||
" this._id = requestResult;\n"
|
||||
" this._isNew = false;\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (!queryCollection.update(this.document._id, this.document)) {\n"
|
||||
" throw \"Could not update AvocadoStoredStatement\";\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" return true;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief save a stored statement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.save = function () {\n"
|
||||
" return this.update(this.document);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief validate the data of an AvocadoStoredStatement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.validate = function () {\n"
|
||||
" if (this._isNew) {\n"
|
||||
" if (this.document.query == undefined || this.document.query == \"\") {\n"
|
||||
" throw \"AvocadoStoredStatement needs a valid query\";\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (this.document.name == undefined || this.document.name == \"\") {\n"
|
||||
" throw \"AvocadoStoredStatement needs a name attribute\";\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if (this.document.queryCollection == undefined || this.document.queryCollection == \"\") {\n"
|
||||
" throw \"AvocadoStoredStatement needs a queryCollection\";\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief lookup the data of an AvocadoStoredStatement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.lookup = function () {\n"
|
||||
" if (this.isNew) {\n"
|
||||
" throw \"Cannot lookup a new AvocadoStoredStatement\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" var data = {\n"
|
||||
" \"query\" : \"SELECT c FROM `\" + this.document.queryCollection + \n"
|
||||
" \"` c WHERE c.name == '\" + QuoteJSONString(this.document.name) + \"'\"\n"
|
||||
" } \n"
|
||||
" var statement = new AvocadoStatement(this._database, data);\n"
|
||||
" var result = statement.execute();\n"
|
||||
" if (result instanceof AvocadoQueryError) {\n"
|
||||
" throw result.message;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (!result.hasNext()) {\n"
|
||||
" throw \"Could not find stored statement for the given parameters\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" var row = result.next();\n"
|
||||
" this._id = row[\"id\"];\n"
|
||||
" this._query = row[\"query\"];\n"
|
||||
" this._isNew = false;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief delete a stored statement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.delete = function () {\n"
|
||||
" if (this._isNew) {\n"
|
||||
" throw \"Cannot delete a new AvocadoStoredStatement\";\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if (this._id == undefined || this._id == null) {\n"
|
||||
" this.lookup();\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" var queryCollection = new AvocadoCollection(this._database, this.document.collection);\n"
|
||||
" if (!queryCollection) {\n"
|
||||
" throw \"Could not determine collection for AvocadoStoredStatement\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (!queryCollection.delete(this.document._id)) {\n"
|
||||
" this.document = {};\n"
|
||||
" this._isNew = true;\n"
|
||||
" this._bindVars = {};\n"
|
||||
" this._id = null;\n"
|
||||
" return true;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" return false;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief bind a parameter to the statement\n"
|
||||
"///\n"
|
||||
"/// This function can be called multiple times, once for each bind parameter.\n"
|
||||
"/// All bind parameters will be transferred to the server in one go when \n"
|
||||
"/// execute() is called.\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.bind = function (key, value) {\n"
|
||||
" if (typeof(key) != \"string\") {\n"
|
||||
" throw \"bind parameter name must be a string\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (this._bindVars[key] != undefined) {\n"
|
||||
" throw \"redeclaration of bind parameter\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" this._bindVars[key] = value;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief set the count flag for the statement\n"
|
||||
"///\n"
|
||||
"/// Setting the count flag will make the query instance's cursor return the\n"
|
||||
"/// total number of result documents. The count flag is not set by default.\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.setCount = function (bool) {\n"
|
||||
" this._doCount = bool ? true : false;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief set the maximum number of results documents the cursor will return\n"
|
||||
"/// in a single server roundtrip.\n"
|
||||
"/// The higher this number is, the less server roundtrips will be made when\n"
|
||||
"/// iterating over the result documents of a cursor.\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.setBatchSize = function (value) {\n"
|
||||
" if (parseInt(value) > 0) {\n"
|
||||
" this._batchSize = parseInt(value);\n"
|
||||
" }\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief execute the query\n"
|
||||
"///\n"
|
||||
"/// Invoking execute() will transfer the query and all bind parameters to the\n"
|
||||
"/// server. It will return a cursor with the query results in case of success.\n"
|
||||
"/// In case of an error, the error will be printed\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.execute = function () {\n"
|
||||
" if (this._isNew) {\n"
|
||||
" this.save();\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" var body = {\n"
|
||||
" \"name\" : this.document.name,\n"
|
||||
" \"count\" : this._doCount,\n"
|
||||
" \"bindVars\" : this._bindVars,\n"
|
||||
" \"_id\" : this._id\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" if (this._batchSize) {\n"
|
||||
" body[\"batchSize\"] = this._batchSize;\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" var requestResult = this._database._connection.post(\"/_api/cursor\", JSON.stringify(body));\n"
|
||||
" \n"
|
||||
" if (isErrorResult(requestResult)) {\n"
|
||||
" return undefined;\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return new AvocadoQueryCursor(this._database, requestResult);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief print the help for AvocadoStoredStatement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype._help = function () {\n"
|
||||
" print(helpAvocadoStoredStatement);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief return a string representation of the stored statement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStoredStatement.prototype.toString = function () { \n"
|
||||
" return getIdString(this, \"AvocadoStoredStatement\");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief factory method to create a new stored statement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoDatabase.prototype._createStoredStatement = function (data) { \n"
|
||||
" return new AvocadoStoredStatement(this, data);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief factory method to retrieve an existing stored statement\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoDatabase.prototype._getStoredStatement = function (data) { \n"
|
||||
" return new AvocadoStoredStatement(this, data);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"*/\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"// --SECTION-- AvocadoStatement\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
|
@ -978,7 +699,7 @@ static string JS_client_client =
|
|||
"/// in a single server roundtrip.\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoStatement.prototype.getMax = function () {\n"
|
||||
"AvocadoStatement.prototype.getBatchSize = function () {\n"
|
||||
" return this._batchSize;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
@ -1127,7 +848,7 @@ static string JS_client_client =
|
|||
"' > st.setCount(<value>); set count flag (return number of ' + \"\\n\" +\n"
|
||||
"' results in \"count\" attribute) ' + \"\\n\" +\n"
|
||||
"'Get query options: ' + \"\\n\" +\n"
|
||||
"' > st.getMax(); return the max. number of results ' + \"\\n\" +\n"
|
||||
"' > st.setBatchSize(); return the max. number of results ' + \"\\n\" +\n"
|
||||
"' to be transferred per roundtrip ' + \"\\n\" +\n"
|
||||
"' > st.getCount(); return count flag (return number of' + \"\\n\" +\n"
|
||||
"' results in \"count\" attribute) ' + \"\\n\" +\n"
|
||||
|
@ -1206,7 +927,7 @@ static string JS_client_client =
|
|||
"' to be transferred per roundtrip ' + \"\\n\" +\n"
|
||||
"' setCount(<value>); set count flag (return number of ' + \"\\n\" +\n"
|
||||
"' results in \"count\" attribute) ' + \"\\n\" +\n"
|
||||
"' getMax(); return max. number of results ' + \"\\n\" +\n"
|
||||
"' getBatchSize(); return max. number of results ' + \"\\n\" +\n"
|
||||
"' to be transferred per roundtrip ' + \"\\n\" +\n"
|
||||
"' getCount(); return count flag (return number of' + \"\\n\" +\n"
|
||||
"' results in \"count\" attribute) ' + \"\\n\" +\n"
|
||||
|
@ -1222,32 +943,7 @@ static string JS_client_client =
|
|||
"' > st.bind(\"b\", \"world\"); ' + \"\\n\" +\n"
|
||||
"' > c = st.execute(); ' + \"\\n\" +\n"
|
||||
"' > print(c.elements()); ';\n"
|
||||
"/*\n"
|
||||
"helpAvocadoStoredStatement = \n"
|
||||
"getHeadline(\"AvocadoQueryTemplate help\") +\n"
|
||||
"'AvocadoQueryTemplate constructor: ' + \"\\n\" +\n"
|
||||
"' > qt1 = db._createQueryTemplate(\"select ...\"); simple query ' + \"\\n\" +\n"
|
||||
"' > qt2 = db._createQueryTemplate( complex query ' + \"\\n\" +\n"
|
||||
"' {query:\"select...\", ' + \"\\n\" +\n"
|
||||
"' name:\"qname\", ' + \"\\n\" +\n"
|
||||
"' collection:\"q\" ' + \"\\n\" +\n"
|
||||
"' ... } ' + \"\\n\" +\n"
|
||||
"'Functions: ' + \"\\n\" +\n"
|
||||
"' update(<new data>); update query template ' + \"\\n\" +\n"
|
||||
"' delete(<id>); delete query template by id ' + \"\\n\" +\n"
|
||||
"' getInstance(); get a query instance ' + \"\\n\" +\n"
|
||||
"' returns: AvocadoQueryInstance' + \"\\n\" +\n"
|
||||
"' _help(); this help ' + \"\\n\" +\n"
|
||||
"'Attributes: ' + \"\\n\" +\n"
|
||||
"' _database database object ' + \"\\n\" +\n"
|
||||
"' _id template id ' + \"\\n\" +\n"
|
||||
"' name collection name ' + \"\\n\" +\n"
|
||||
"'Example: ' + \"\\n\" +\n"
|
||||
"' > qt1 = db._getQueryTemplate(\"4334:2334\"); ' + \"\\n\" +\n"
|
||||
"' > qt1.update(\"select a from collA a\"); ' + \"\\n\" +\n"
|
||||
"' > qi1 = qt1.getInstance(); ' + \"\\n\" +\n"
|
||||
"' > qt1.delete(\"4334:2334\"); ';\n"
|
||||
"*/\n"
|
||||
"\n"
|
||||
"helpExtended = \n"
|
||||
"getHeadline(\"More help\") +\n"
|
||||
"'Pager: ' + \"\\n\" +\n"
|
||||
|
|
|
@ -16,7 +16,9 @@ ModuleCache["/internal"].exports.errors = {
|
|||
"ERROR_DEAD_PID" : { "code" : 8, "message" : "dead process identifier" },
|
||||
"ERROR_NOT_IMPLEMENTED" : { "code" : 9, "message" : "not implemented" },
|
||||
"ERROR_HTTP_BAD_PARAMETER" : { "code" : 400, "message" : "bad parameter" },
|
||||
"ERROR_HTTP_NOT_FOUND" : { "code" : 404, "message" : "not found" },
|
||||
"ERROR_HTTP_METHOD_NOT_ALLOWED" : { "code" : 405, "message" : "method not supported" },
|
||||
"ERROR_HTTP_SERVER_ERROR" : { "code" : 500, "message" : "internal server error" },
|
||||
"ERROR_HTTP_CORRUPTED_JSON" : { "code" : 600, "message" : "invalid JSON object" },
|
||||
"ERROR_HTTP_SUPERFLUOUS_SUFFICES" : { "code" : 601, "message" : "superfluous URL suffices" },
|
||||
"ERROR_AVOCADO_ILLEGAL_STATE" : { "code" : 1000, "message" : "illegal state" },
|
||||
|
|
|
@ -17,7 +17,9 @@ static string JS_common_bootstrap_errors =
|
|||
" \"ERROR_DEAD_PID\" : { \"code\" : 8, \"message\" : \"dead process identifier\" }, \n"
|
||||
" \"ERROR_NOT_IMPLEMENTED\" : { \"code\" : 9, \"message\" : \"not implemented\" }, \n"
|
||||
" \"ERROR_HTTP_BAD_PARAMETER\" : { \"code\" : 400, \"message\" : \"bad parameter\" }, \n"
|
||||
" \"ERROR_HTTP_NOT_FOUND\" : { \"code\" : 404, \"message\" : \"not found\" }, \n"
|
||||
" \"ERROR_HTTP_METHOD_NOT_ALLOWED\" : { \"code\" : 405, \"message\" : \"method not supported\" }, \n"
|
||||
" \"ERROR_HTTP_SERVER_ERROR\" : { \"code\" : 500, \"message\" : \"internal server error\" }, \n"
|
||||
" \"ERROR_HTTP_CORRUPTED_JSON\" : { \"code\" : 600, \"message\" : \"invalid JSON object\" }, \n"
|
||||
" \"ERROR_HTTP_SUPERFLUOUS_SUFFICES\" : { \"code\" : 601, \"message\" : \"superfluous URL suffices\" }, \n"
|
||||
" \"ERROR_AVOCADO_ILLEGAL_STATE\" : { \"code\" : 1000, \"message\" : \"illegal state\" }, \n"
|
||||
|
|
Loading…
Reference in New Issue