diff --git a/CHANGELOG b/CHANGELOG index 8dc606075d..3abc3648c1 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -305,6 +305,8 @@ v2.6.0 (XXXX-XX-XX) v2.5.3 (XXXX-XX-XX) ------------------- +* issue #1318: Inconsistent db._create() syntax + * issue #1315: queries to a collection fail with an empty response if the collection contains specific JSON data diff --git a/Documentation/Books/Users/README.mdpp b/Documentation/Books/Users/README.mdpp index e1a2e4685d..e1c98ee6f1 100644 --- a/Documentation/Books/Users/README.mdpp +++ b/Documentation/Books/Users/README.mdpp @@ -4,7 +4,7 @@ Welcome to the ArangoDB documentation! The documentation introduces ArangoDB for you as an user, developer and administrator and describes all of its functions in detail. -ArangoDB is a multi-purpose, open-source database with flexible data models for documents, graphs, and key-values. Build high performance applications using a convenient SQL-like query language or JavaScript extensions. Use ACID transactions if you require them. Scale horizontally and vertically with a few mouse clicks. +ArangoDB is a multi-model, open-source database with flexible data models for documents, graphs, and key-values. Build high performance applications using a convenient SQL-like query language or JavaScript extensions. Use ACID transactions if you require them. Scale horizontally and vertically with a few mouse clicks. Key features include: @@ -34,4 +34,3 @@ If you have any questions don't hesitate to ask on: - [stackoverflow](http://stackoverflow.com/questions/tagged/arangodb) We will respond as soon as possible. - diff --git a/arangod/Aql/AqlItemBlock.h b/arangod/Aql/AqlItemBlock.h index 2d92407382..4e1dcd3d3a 100644 --- a/arangod/Aql/AqlItemBlock.h +++ b/arangod/Aql/AqlItemBlock.h @@ -62,6 +62,8 @@ namespace triagens { class AqlItemBlock { + friend class AqlItemBlockManager; + // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/AqlItemBlockManager.cpp b/arangod/Aql/AqlItemBlockManager.cpp new file mode 100644 index 0000000000..9152534268 --- /dev/null +++ b/arangod/Aql/AqlItemBlockManager.cpp @@ -0,0 +1,97 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Aql, item block manager +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2014 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 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 ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany +/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#include "AqlItemBlockManager.h" +#include "Aql/AqlItemBlock.h" + +using namespace triagens::aql; + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors / destructors +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create the manager +//////////////////////////////////////////////////////////////////////////////// + +AqlItemBlockManager::AqlItemBlockManager () + : _last(nullptr) { + +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destroy the manager +//////////////////////////////////////////////////////////////////////////////// + +AqlItemBlockManager::~AqlItemBlockManager () { + delete _last; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief request a block with the specified size +//////////////////////////////////////////////////////////////////////////////// + +AqlItemBlock* AqlItemBlockManager::requestBlock (size_t nrItems, + RegisterId nrRegs) { + if (_last != nullptr && + _last->size() == nrItems && + _last->getNrRegs() == nrRegs) { + auto block = _last; + _last = nullptr; + return block; + } + + return new AqlItemBlock(nrItems, nrRegs); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return a block to the manager +//////////////////////////////////////////////////////////////////////////////// + +void AqlItemBlockManager::returnBlock (AqlItemBlock*& block) { + TRI_ASSERT(block != nullptr); + block->destroy(); + + delete _last; + _last = block; + block = nullptr; +} + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" +// End: diff --git a/arangod/Aql/AqlItemBlockManager.h b/arangod/Aql/AqlItemBlockManager.h new file mode 100644 index 0000000000..df2ba01d42 --- /dev/null +++ b/arangod/Aql/AqlItemBlockManager.h @@ -0,0 +1,111 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief Aql, item block manager +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2014 ArangoDB GmbH, Cologne, Germany +/// Copyright 2004-2014 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 ArangoDB GmbH, Cologne, Germany +/// +/// @author Jan Steemann +/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany +/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +#ifndef ARANGODB_AQL_ITEM_BLOCK_MANAGER_H +#define ARANGODB_AQL_ITEM_BLOCK_MANAGER_H 1 + +#include "Basics/Common.h" +#include "Aql/types.h" + +namespace triagens { + namespace aql { + + class AqlItemBlock; + +// ----------------------------------------------------------------------------- +// --SECTION-- class AqlItemBlockManager +// ----------------------------------------------------------------------------- + + class AqlItemBlockManager { + +// ----------------------------------------------------------------------------- +// --SECTION-- constructors / destructors +// ----------------------------------------------------------------------------- + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief create the manager +//////////////////////////////////////////////////////////////////////////////// + + AqlItemBlockManager (); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief destroy the manager +//////////////////////////////////////////////////////////////////////////////// + + ~AqlItemBlockManager (); + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- + + public: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief request a block with the specified size +//////////////////////////////////////////////////////////////////////////////// + + AqlItemBlock* requestBlock (size_t, + RegisterId); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return a block to the manager +//////////////////////////////////////////////////////////////////////////////// + + void returnBlock (AqlItemBlock*&); + +// ----------------------------------------------------------------------------- +// --SECTION-- private variables +// ----------------------------------------------------------------------------- + + private: + +//////////////////////////////////////////////////////////////////////////////// +/// @brief last block handed back to the manager +/// this is the block that may be recycled +//////////////////////////////////////////////////////////////////////////////// + + AqlItemBlock* _last; + + }; + + } +} + +#endif + +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + +// Local Variables: +// mode: outline-minor +// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}" +// End: diff --git a/arangod/Aql/CollectionScanner.h b/arangod/Aql/CollectionScanner.h index f223fdeffa..8de07a1ac5 100644 --- a/arangod/Aql/CollectionScanner.h +++ b/arangod/Aql/CollectionScanner.h @@ -72,7 +72,7 @@ namespace triagens { // --SECTION-- struct RandomCollectionScanner // ----------------------------------------------------------------------------- - struct RandomCollectionScanner : public CollectionScanner { + struct RandomCollectionScanner final : public CollectionScanner { // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors @@ -82,9 +82,9 @@ namespace triagens { TRI_transaction_collection_t*); int scan (std::vector&, - size_t); + size_t) override; - void reset (); + void reset () override; uint32_t initialPosition; uint32_t step; @@ -94,7 +94,7 @@ namespace triagens { // --SECTION-- struct LinearCollectionScanner // ----------------------------------------------------------------------------- - struct LinearCollectionScanner : public CollectionScanner { + struct LinearCollectionScanner final : public CollectionScanner { // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors @@ -104,9 +104,9 @@ namespace triagens { TRI_transaction_collection_t*); int scan (std::vector&, - size_t); + size_t) override; - void reset (); + void reset () override; }; } diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index da34ca8f73..922b101241 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -351,6 +351,23 @@ AqlItemBlock* ExecutionBlock::getSome (size_t atLeast, size_t atMost) { // --SECTION-- protected methods // ----------------------------------------------------------------------------- +//////////////////////////////////////////////////////////////////////////////// +/// @brief request an AqlItemBlock from the memory manager +//////////////////////////////////////////////////////////////////////////////// + +AqlItemBlock* ExecutionBlock::requestBlock (size_t nrItems, + RegisterId nrRegs) { + return _engine->_itemBlockManager.requestBlock(nrItems, nrRegs); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return an AqlItemBlock to the memory manager +//////////////////////////////////////////////////////////////////////////////// + +void ExecutionBlock::returnBlock (AqlItemBlock* block) { + _engine->_itemBlockManager.returnBlock(block); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief resolve a collection name and return cid and document key /// this is used for parsing _from, _to and _id values @@ -887,12 +904,13 @@ AqlItemBlock* EnumerateCollectionBlock::getSome (size_t, // atLeast, size_t available = _documents.size() - _posInDocuments; size_t toSend = (std::min)(atMost, available); + RegisterId nrRegs = getPlanNode()->getRegisterPlan()->nrRegs[getPlanNode()->getDepth()]; - unique_ptr res(new AqlItemBlock(toSend, getPlanNode()->getRegisterPlan()->nrRegs[getPlanNode()->getDepth()])); + unique_ptr res(requestBlock(toSend, nrRegs)); // automatically freed if we throw TRI_ASSERT(curRegs <= res->getNrRegs()); - // only copy 1st row of registers inherited from previous frame(s) + // only copy 1st row of registers inherited from previous frame(s)1 inheritRegisters(cur, res.get(), _pos); // set our collection for our output register @@ -928,15 +946,18 @@ AqlItemBlock* EnumerateCollectionBlock::getSome (size_t, // atLeast, if (! moreDocuments(atMost)) { // nothing more to read, re-initialize fetching of documents initializeDocuments(); + if (++_pos >= cur->size()) { _buffer.pop_front(); // does not throw - delete cur; + returnBlock(cur); _pos = 0; } } } + // Clear out registers no longer needed later: clearRegisters(res.get()); + return res.release(); } @@ -1080,7 +1101,6 @@ void IndexRangeBlock::buildExpressions () { // The following are needed to evaluate expressions with local data from // the current incoming item: AqlItemBlock* cur = _buffer.front(); - vector& docColls(cur->getDocumentCollections()); IndexOrCondition* newCondition = nullptr; @@ -2692,8 +2712,6 @@ void CalculationBlock::fillBlockWithReference (AqlItemBlock* result) { //////////////////////////////////////////////////////////////////////////////// void CalculationBlock::executeExpression (AqlItemBlock* result) { - std::vector& docColls(result->getDocumentCollections()); - result->setDocumentCollection(_outReg, nullptr); bool const hasCondition = (static_cast(_exeNode)->_conditionVariable != nullptr); @@ -3531,6 +3549,7 @@ int HashedAggregateBlock::getOrSkipSome (size_t atLeast, size_t& skipped) { TRI_ASSERT(result == nullptr && skipped == 0); + if (_done) { return TRI_ERROR_NO_ERROR; } @@ -3658,23 +3677,21 @@ int HashedAggregateBlock::getOrSkipSome (size_t atLeast, ++skipped; result = buildResult(cur); - - delete cur; - cur = nullptr; + + returnBlock(cur); _done = true; return TRI_ERROR_NO_ERROR; } catch (...) { - delete cur; - cur = nullptr; + returnBlock(cur); throw; } } // hasMore - delete cur; + returnBlock(cur); cur = _buffer.front(); } } diff --git a/arangod/Aql/ExecutionBlock.h b/arangod/Aql/ExecutionBlock.h index 646bbe610f..a4e0a8a3bd 100644 --- a/arangod/Aql/ExecutionBlock.h +++ b/arangod/Aql/ExecutionBlock.h @@ -102,6 +102,10 @@ namespace triagens { class ExecutionBlock { +// ----------------------------------------------------------------------------- +// --SECTION-- constructors / destructors +// ----------------------------------------------------------------------------- + public: //////////////////////////////////////////////////////////////////////////////// @@ -116,6 +120,10 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// virtual ~ExecutionBlock (); + +// ----------------------------------------------------------------------------- +// --SECTION-- public methods +// ----------------------------------------------------------------------------- public: @@ -234,6 +242,19 @@ namespace triagens { protected: +//////////////////////////////////////////////////////////////////////////////// +/// @brief request an AqlItemBlock from the memory manager +//////////////////////////////////////////////////////////////////////////////// + + AqlItemBlock* requestBlock (size_t, + RegisterId); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief return an AqlItemBlock to the memory manager +//////////////////////////////////////////////////////////////////////////////// + + void returnBlock (AqlItemBlock*); + //////////////////////////////////////////////////////////////////////////////// /// @brief resolve a collection name and return cid and document key /// this is used for parsing _from, _to and _id values diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index b627806254..c690a39f7d 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -1094,7 +1094,6 @@ void ExecutionEngine::addBlock (ExecutionBlock* block) { _blocks.emplace_back(block); } - // ----------------------------------------------------------------------------- // --SECTION-- END-OF-FILE // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/ExecutionEngine.h b/arangod/Aql/ExecutionEngine.h index 0afcba8d11..3306bab0b4 100644 --- a/arangod/Aql/ExecutionEngine.h +++ b/arangod/Aql/ExecutionEngine.h @@ -31,12 +31,12 @@ #define ARANGODB_AQL_EXECUTION_ENGINE_H 1 #include "Basics/Common.h" - -#include "arangod/Aql/AqlItemBlock.h" -#include "arangod/Aql/ExecutionBlock.h" -#include "arangod/Aql/ExecutionPlan.h" -#include "arangod/Aql/ExecutionStats.h" -#include "arangod/Aql/QueryRegistry.h" +#include "Aql/AqlItemBlock.h" +#include "Aql/AqlItemBlockManager.h" +#include "Aql/ExecutionBlock.h" +#include "Aql/ExecutionPlan.h" +#include "Aql/ExecutionStats.h" +#include "Aql/QueryRegistry.h" #include "Utils/AqlTransaction.h" namespace triagens { @@ -206,6 +206,22 @@ namespace triagens { void addBlock (ExecutionBlock*); +//////////////////////////////////////////////////////////////////////////////// +/// @brief _lockedShards +//////////////////////////////////////////////////////////////////////////////// + + void setLockedShards (std::unordered_set* lockedShards) { + _lockedShards = lockedShards; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief _lockedShards +//////////////////////////////////////////////////////////////////////////////// + + std::unordered_set* lockedShards () const { + return _lockedShards; + } + // ----------------------------------------------------------------------------- // --SECTION-- public variables // ----------------------------------------------------------------------------- @@ -220,21 +236,11 @@ namespace triagens { ExecutionStats _stats; //////////////////////////////////////////////////////////////////////////////// -/// @brief _lockedShards +/// @brief memory recycler for AqlItemBlocks //////////////////////////////////////////////////////////////////////////////// - std::unordered_set* lockedShards () { - return _lockedShards; - } - -//////////////////////////////////////////////////////////////////////////////// -/// @brief _lockedShards -//////////////////////////////////////////////////////////////////////////////// + AqlItemBlockManager _itemBlockManager; - void setLockedShards (std::unordered_set* lockedShards) { - _lockedShards = lockedShards; - } - // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- diff --git a/arangod/CMakeLists.txt b/arangod/CMakeLists.txt index ccccbc5ae1..32d0619366 100644 --- a/arangod/CMakeLists.txt +++ b/arangod/CMakeLists.txt @@ -44,6 +44,7 @@ add_executable( Actions/RestActionHandler.cpp Aql/AggregationOptions.cpp Aql/AqlItemBlock.cpp + Aql/AqlItemBlockManager.cpp Aql/AqlValue.cpp Aql/Ast.cpp Aql/AstNode.cpp diff --git a/arangod/Makefile.files b/arangod/Makefile.files index 70c5f7254c..2f3c92b8e1 100644 --- a/arangod/Makefile.files +++ b/arangod/Makefile.files @@ -17,6 +17,7 @@ arangod_libarangod_a_SOURCES = \ arangod/Actions/RestActionHandler.cpp \ arangod/Aql/AggregationOptions.cpp \ arangod/Aql/AqlItemBlock.cpp \ + arangod/Aql/AqlItemBlockManager.cpp \ arangod/Aql/AqlValue.cpp \ arangod/Aql/Ast.cpp \ arangod/Aql/AstNode.cpp \ diff --git a/arangod/Utils/StandaloneTransactionContext.h b/arangod/Utils/StandaloneTransactionContext.h index 68475dd4bd..3f83fdb5cd 100644 --- a/arangod/Utils/StandaloneTransactionContext.h +++ b/arangod/Utils/StandaloneTransactionContext.h @@ -41,7 +41,7 @@ struct TRI_transaction_s; namespace triagens { namespace arango { - class StandaloneTransactionContext : public TransactionContext { + class StandaloneTransactionContext final : public TransactionContext { // ----------------------------------------------------------------------------- // --SECTION-- class StandaloneTransactionContext diff --git a/arangod/Utils/V8TransactionContext.h b/arangod/Utils/V8TransactionContext.h index 85c9de0bd1..872e4b9ae8 100644 --- a/arangod/Utils/V8TransactionContext.h +++ b/arangod/Utils/V8TransactionContext.h @@ -39,7 +39,7 @@ struct TRI_transaction_s; namespace triagens { namespace arango { - class V8TransactionContext : public TransactionContext { + class V8TransactionContext final : public TransactionContext { // ----------------------------------------------------------------------------- // --SECTION-- class V8TransactionContext @@ -61,7 +61,7 @@ namespace triagens { /// @brief destroy the context //////////////////////////////////////////////////////////////////////////////// - virtual ~V8TransactionContext (); + ~V8TransactionContext (); // ----------------------------------------------------------------------------- // --SECTION-- public functions diff --git a/arangod/V8Server/v8-actions.cpp b/arangod/V8Server/v8-actions.cpp index 8d06a085c4..0e55d68afd 100644 --- a/arangod/V8Server/v8-actions.cpp +++ b/arangod/V8Server/v8-actions.cpp @@ -563,7 +563,7 @@ static HttpResponse* ResponseV8ToCpp (v8::Isolate* isolate, ((int) (TRI_ObjectToDouble(res->Get(ResponseCodeKey)))); } - HttpResponse* response = new HttpResponse(code, compatibility); + std::unique_ptr response(new HttpResponse(code, compatibility)); TRI_GET_GLOBAL_STRING(ContentTypeKey); if (res->Has(ContentTypeKey)) { @@ -578,6 +578,7 @@ static HttpResponse* ResponseV8ToCpp (v8::Isolate* isolate, TRI_GET_GLOBAL_STRING(BodyFromFileKey); TRI_GET_GLOBAL_STRING(HeadersKey); TRI_GET_GLOBAL_STRING(CookiesKey); + if (res->Has(BodyKey)) { // check if we should apply result transformations // transformations turn the result from one type into another @@ -624,7 +625,8 @@ static HttpResponse* ResponseV8ToCpp (v8::Isolate* isolate, } else { // treat body as a string - response->body().appendText(TRI_ObjectToString(res->Get(BodyKey))); + std::string&& obj(TRI_ObjectToString(res->Get(BodyKey))); + response->body().appendText(obj); } } } @@ -685,17 +687,17 @@ static HttpResponse* ResponseV8ToCpp (v8::Isolate* isolate, for (uint32_t i = 0; i < v8Array->Length(); i++) { v8::Handle v8Cookie = v8Array->Get(i); if (v8Cookie->IsObject()) { - AddCookie(isolate, v8g, response, v8Cookie.As()); + AddCookie(isolate, v8g, response.get(), v8Cookie.As()); } } } else if (v8Cookies->IsObject()) { // one cookie - AddCookie(isolate, v8g, response, v8Cookies); + AddCookie(isolate, v8g, response.get(), v8Cookies); } } - return response; + return response.release(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/arangod/V8Server/v8-collection.cpp b/arangod/V8Server/v8-collection.cpp index 81b8112e6d..e190a2927b 100644 --- a/arangod/V8Server/v8-collection.cpp +++ b/arangod/V8Server/v8-collection.cpp @@ -3142,8 +3142,7 @@ static void InsertEdgeColCoordinator (TRI_vocbase_col_t* collection, /// `collection.insert(data)` /// /// Creates a new document in the *collection* from the given *data*. The -/// *data* must be an object. It must not contain attributes starting -/// with *_*. +/// *data* must be an object. /// /// The method returns a document with the attributes *_id* and *_rev*. /// The attribute *_id* contains the document handle of the newly created diff --git a/arangod/V8Server/v8-vocindex.cpp b/arangod/V8Server/v8-vocindex.cpp index 138726c0f6..479d47ca19 100644 --- a/arangod/V8Server/v8-vocindex.cpp +++ b/arangod/V8Server/v8-vocindex.cpp @@ -1589,14 +1589,26 @@ static void CreateVocBase (const v8::FunctionCallbackInfo& args, // We require exactly 1 or exactly 2 arguments -- anything else is an error // ........................................................................... - if (args.Length() < 1 || args.Length() > 2) { - TRI_V8_THROW_EXCEPTION_USAGE("_create(, )"); + if (args.Length() < 1 || args.Length() > 3) { + TRI_V8_THROW_EXCEPTION_USAGE("_create(, , )"); } if (TRI_GetOperationModeServer() == TRI_VOCBASE_MODE_NO_CREATE) { TRI_V8_THROW_EXCEPTION(TRI_ERROR_ARANGO_READ_ONLY); } + // optional, third parameter can override collection type + if (args.Length() == 3 && args[2]->IsString()) { + + std::string typeString = TRI_ObjectToString(args[2]); + if (typeString == "edge") { + collectionType = TRI_COL_TYPE_EDGE; + } + else if (typeString == "document") { + collectionType = TRI_COL_TYPE_DOCUMENT; + } + } + PREVENT_EMBEDDED_TRANSACTION(); diff --git a/arangod/VocBase/key-generator.h b/arangod/VocBase/key-generator.h index 4bc11e6990..2be86eb586 100644 --- a/arangod/VocBase/key-generator.h +++ b/arangod/VocBase/key-generator.h @@ -216,20 +216,20 @@ class TraditionalKeyGenerator : public KeyGenerator { /// @brief generate a key //////////////////////////////////////////////////////////////////////////////// - std::string generate (TRI_voc_tick_t); + std::string generate (TRI_voc_tick_t) override; //////////////////////////////////////////////////////////////////////////////// /// @brief validate a key //////////////////////////////////////////////////////////////////////////////// int validate (std::string const&, - bool); + bool) override; //////////////////////////////////////////////////////////////////////////////// /// @brief track usage of a key //////////////////////////////////////////////////////////////////////////////// - void track (TRI_voc_key_t); + void track (TRI_voc_key_t) override; //////////////////////////////////////////////////////////////////////////////// /// @brief return the generator name @@ -243,7 +243,7 @@ class TraditionalKeyGenerator : public KeyGenerator { /// @brief return a JSON representation of the generator //////////////////////////////////////////////////////////////////////////////// - struct TRI_json_t* toJson (TRI_memory_zone_t*) const; + struct TRI_json_t* toJson (TRI_memory_zone_t*) const override; }; // ----------------------------------------------------------------------------- @@ -294,20 +294,20 @@ class AutoIncrementKeyGenerator : public KeyGenerator { /// @brief generate a key //////////////////////////////////////////////////////////////////////////////// - std::string generate (TRI_voc_tick_t); + std::string generate (TRI_voc_tick_t) override; //////////////////////////////////////////////////////////////////////////////// /// @brief validate a key //////////////////////////////////////////////////////////////////////////////// int validate (std::string const&, - bool); + bool) override; //////////////////////////////////////////////////////////////////////////////// /// @brief track usage of a key //////////////////////////////////////////////////////////////////////////////// - void track (TRI_voc_key_t); + void track (TRI_voc_key_t) override; //////////////////////////////////////////////////////////////////////////////// /// @brief return the generator name @@ -321,7 +321,7 @@ class AutoIncrementKeyGenerator : public KeyGenerator { /// @brief return a JSON representation of the generator //////////////////////////////////////////////////////////////////////////////// - struct TRI_json_t* toJson (TRI_memory_zone_t*) const; + struct TRI_json_t* toJson (TRI_memory_zone_t*) const override; // ----------------------------------------------------------------------------- // --SECTION-- private variables diff --git a/js/common/tests/shell-collection.js b/js/common/tests/shell-collection.js index f45990a3e0..9b5019e322 100644 --- a/js/common/tests/shell-collection.js +++ b/js/common/tests/shell-collection.js @@ -479,6 +479,55 @@ function CollectionSuite () { db._drop(cn); }, +//////////////////////////////////////////////////////////////////////////////// +/// @brief creating with type +//////////////////////////////////////////////////////////////////////////////// + + testCreatingTypeDocument : function () { + var cn = "example"; + + db._drop(cn); + var c1 = db._create(cn, { }, "document"); + + assertTypeOf("string", c1._id); + assertEqual(cn, c1.name()); + assertEqual(ArangoCollection.TYPE_DOCUMENT, c1.type()); + db._drop(cn); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creating with type +//////////////////////////////////////////////////////////////////////////////// + + testCreatingTypeEdge : function () { + var cn = "example"; + + db._drop(cn); + var c1 = db._create(cn, { }, "edge"); + + assertTypeOf("string", c1._id); + assertEqual(cn, c1.name()); + assertEqual(ArangoCollection.TYPE_EDGE, c1.type()); + db._drop(cn); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creating with type +//////////////////////////////////////////////////////////////////////////////// + + testCreatingTypeInvalid : function () { + var cn = "example"; + + db._drop(cn); + // invalid type defaults to type "document" + var c1 = db._create(cn, { }, "foobar"); + + assertTypeOf("string", c1._id); + assertEqual(cn, c1.name()); + assertEqual(ArangoCollection.TYPE_DOCUMENT, c1.type()); + db._drop(cn); + }, + //////////////////////////////////////////////////////////////////////////////// /// @brief drop new-born //////////////////////////////////////////////////////////////////////////////// diff --git a/js/server/modules/org/arangodb/testing.js b/js/server/modules/org/arangodb/testing.js index ac89a7cf99..00f2f04e3d 100644 --- a/js/server/modules/org/arangodb/testing.js +++ b/js/server/modules/org/arangodb/testing.js @@ -61,6 +61,7 @@ var optionsDocumentation = [ ' - `skipTimeCritical`: if set to true, time critical tests will be skipped.', ' - `skipSsl`: ommit the ssl_server rspec tests.', ' - `skipLogAnalysis`: don\'t try to crawl the server logs', + ' - `skipConfig`: ommit the noisy configuration tests', '', ' - `cluster`: if set to true the tests are run with the coordinator', ' of a small local cluster', @@ -836,6 +837,7 @@ function runInArangosh (options, instanceInfo, file, addArgs) { } var arangosh = fs.join("bin","arangosh"); var result; + print(toArgv(args)); var rc = executeAndWait(arangosh, toArgv(args)); try { result = JSON.parse(fs.read("testresult.json")); @@ -1154,7 +1156,10 @@ testFuncs.shell_client = function(options) { return results; }; -testFuncs.config = function () { +testFuncs.config = function (options) { + if (options.skipConfig) { + return {}; + } var topDir = findTopDir(); var results = {}; var ts = ["arangod", diff --git a/lib/Rest/EndpointUnixDomain.h b/lib/Rest/EndpointUnixDomain.h index 68f315bb2e..4325790607 100644 --- a/lib/Rest/EndpointUnixDomain.h +++ b/lib/Rest/EndpointUnixDomain.h @@ -71,7 +71,7 @@ namespace triagens { /// @brief destroys an endpoint //////////////////////////////////////////////////////////////////////////////// - virtual ~EndpointUnixDomain (); + ~EndpointUnixDomain (); // ----------------------------------------------------------------------------- // --SECTION-- public methods @@ -89,13 +89,13 @@ namespace triagens { /// @brief disconnect the endpoint //////////////////////////////////////////////////////////////////////////////// - virtual void disconnect (); + void disconnect () override; //////////////////////////////////////////////////////////////////////////////// /// @brief init an incoming connection //////////////////////////////////////////////////////////////////////////////// - virtual bool initIncoming (TRI_socket_t); + bool initIncoming (TRI_socket_t) override; //////////////////////////////////////////////////////////////////////////////// /// @brief get endpoint domain diff --git a/lib/Rest/HttpResponse.h b/lib/Rest/HttpResponse.h index 387599c05d..ce0fbb2915 100644 --- a/lib/Rest/HttpResponse.h +++ b/lib/Rest/HttpResponse.h @@ -177,11 +177,11 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// /// @brief deletes a http response /// -/// The descrutor will free the string buffers used. After the http response +/// The destructor will free the string buffers used. After the http response /// is deleted, the string buffers returned by body() become invalid. //////////////////////////////////////////////////////////////////////////////// - virtual ~HttpResponse (); + ~HttpResponse (); // ----------------------------------------------------------------------------- // --SECTION-- public methods diff --git a/lib/SimpleHttpClient/ClientConnection.cpp b/lib/SimpleHttpClient/ClientConnection.cpp index 2a7fe7abe3..1d8fd314a4 100644 --- a/lib/SimpleHttpClient/ClientConnection.cpp +++ b/lib/SimpleHttpClient/ClientConnection.cpp @@ -163,7 +163,7 @@ void ClientConnection::disconnectSocket () { /// @brief prepare connection for read/write I/O //////////////////////////////////////////////////////////////////////////////// -bool ClientConnection::prepare (const double timeout, const bool isWrite) const { +bool ClientConnection::prepare (double timeout, bool isWrite) const { struct timeval tv; fd_set fdset; int res; diff --git a/lib/SimpleHttpClient/ClientConnection.h b/lib/SimpleHttpClient/ClientConnection.h index db43166d77..5355bfefa3 100644 --- a/lib/SimpleHttpClient/ClientConnection.h +++ b/lib/SimpleHttpClient/ClientConnection.h @@ -46,7 +46,7 @@ namespace triagens { /// @brief client connection //////////////////////////////////////////////////////////////////////////////// - class ClientConnection : public GeneralClientConnection { + class ClientConnection final : public GeneralClientConnection { // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors @@ -72,7 +72,7 @@ namespace triagens { /// @brief destroys a client connection //////////////////////////////////////////////////////////////////////////////// - virtual ~ClientConnection (); + ~ClientConnection (); // ----------------------------------------------------------------------------- // --SECTION-- private methods @@ -94,38 +94,38 @@ namespace triagens { /// @brief connect //////////////////////////////////////////////////////////////////////////////// - bool connectSocket (); + bool connectSocket () override; //////////////////////////////////////////////////////////////////////////////// /// @brief disconnect //////////////////////////////////////////////////////////////////////////////// - void disconnectSocket (); + void disconnectSocket () override; //////////////////////////////////////////////////////////////////////////////// /// @brief prepare connection for read/write I/O //////////////////////////////////////////////////////////////////////////////// - bool prepare (const double, const bool) const; + bool prepare (double, bool) const override; //////////////////////////////////////////////////////////////////////////////// /// @brief write data to the connection //////////////////////////////////////////////////////////////////////////////// - bool writeClientConnection (void*, size_t, size_t*); + bool writeClientConnection (void*, size_t, size_t*) override; //////////////////////////////////////////////////////////////////////////////// /// @brief read data from the connection //////////////////////////////////////////////////////////////////////////////// bool readClientConnection (triagens::basics::StringBuffer&, - bool& connectionClosed); + bool& connectionClosed) override; //////////////////////////////////////////////////////////////////////////////// /// @brief return whether the connection is readable //////////////////////////////////////////////////////////////////////////////// - bool readable (); + bool readable () override; // ----------------------------------------------------------------------------- // --SECTION-- private variables diff --git a/lib/SimpleHttpClient/GeneralClientConnection.h b/lib/SimpleHttpClient/GeneralClientConnection.h index edd059ea42..f01c300730 100644 --- a/lib/SimpleHttpClient/GeneralClientConnection.h +++ b/lib/SimpleHttpClient/GeneralClientConnection.h @@ -106,7 +106,7 @@ namespace triagens { /// @brief return the endpoint //////////////////////////////////////////////////////////////////////////////// - const triagens::rest::Endpoint* getEndpoint () const { + triagens::rest::Endpoint const* getEndpoint () const { return _endpoint; } @@ -114,7 +114,7 @@ namespace triagens { /// @brief returns a string representation of the connection endpoint //////////////////////////////////////////////////////////////////////////////// - const std::string getEndpointSpecification () const { + std::string getEndpointSpecification () const { return _endpoint->getSpecification(); } @@ -197,7 +197,7 @@ namespace triagens { /// @brief prepare connection for read/write I/O //////////////////////////////////////////////////////////////////////////////// - virtual bool prepare (const double, const bool) const = 0; + virtual bool prepare (double, bool) const = 0; //////////////////////////////////////////////////////////////////////////////// /// @brief write data to the connection diff --git a/lib/SimpleHttpClient/SslClientConnection.cpp b/lib/SimpleHttpClient/SslClientConnection.cpp index 79ba6c9693..c903cbd4ab 100644 --- a/lib/SimpleHttpClient/SslClientConnection.cpp +++ b/lib/SimpleHttpClient/SslClientConnection.cpp @@ -264,7 +264,7 @@ void SslClientConnection::disconnectSocket () { /// @brief prepare connection for read/write I/O //////////////////////////////////////////////////////////////////////////////// -bool SslClientConnection::prepare (const double timeout, const bool isWrite) const { +bool SslClientConnection::prepare (double timeout, bool isWrite) const { struct timeval tv; fd_set fdset; int res; diff --git a/lib/SimpleHttpClient/SslClientConnection.h b/lib/SimpleHttpClient/SslClientConnection.h index 40a4784212..3d925b9648 100644 --- a/lib/SimpleHttpClient/SslClientConnection.h +++ b/lib/SimpleHttpClient/SslClientConnection.h @@ -50,7 +50,7 @@ namespace triagens { /// @brief client connection //////////////////////////////////////////////////////////////////////////////// - class SslClientConnection : public GeneralClientConnection { + class SslClientConnection final : public GeneralClientConnection { // ----------------------------------------------------------------------------- // --SECTION-- constructors / destructors @@ -77,7 +77,7 @@ namespace triagens { /// @brief destroys a client connection //////////////////////////////////////////////////////////////////////////////// - virtual ~SslClientConnection (); + ~SslClientConnection (); // ----------------------------------------------------------------------------- // --SECTION-- protected virtual methods @@ -89,38 +89,44 @@ namespace triagens { /// @brief connect //////////////////////////////////////////////////////////////////////////////// - bool connectSocket (); + bool connectSocket () override; //////////////////////////////////////////////////////////////////////////////// /// @brief disconnect //////////////////////////////////////////////////////////////////////////////// - void disconnectSocket (); + void disconnectSocket () override; //////////////////////////////////////////////////////////////////////////////// /// @brief prepare connection for read/write I/O //////////////////////////////////////////////////////////////////////////////// - bool prepare (const double, const bool) const; + bool prepare (double, bool) const override; //////////////////////////////////////////////////////////////////////////////// /// @brief write data to the connection //////////////////////////////////////////////////////////////////////////////// - bool writeClientConnection (void*, size_t, size_t*); + bool writeClientConnection (void*, size_t, size_t*) override; //////////////////////////////////////////////////////////////////////////////// /// @brief read data from the connection //////////////////////////////////////////////////////////////////////////////// bool readClientConnection (triagens::basics::StringBuffer&, - bool& connectionClosed); + bool& connectionClosed) override; //////////////////////////////////////////////////////////////////////////////// /// @brief return whether the connection is readable //////////////////////////////////////////////////////////////////////////////// - bool readable (); + bool readable () override; + +// ----------------------------------------------------------------------------- +// --SECTION-- private methods +// ----------------------------------------------------------------------------- + + private: //////////////////////////////////////////////////////////////////////////////// /// @brief return whether the socket is still workable