diff --git a/arangod/Aql/ExecutionBlock.cpp b/arangod/Aql/ExecutionBlock.cpp index ce29b2ea94..ba54b4f7d7 100644 --- a/arangod/Aql/ExecutionBlock.cpp +++ b/arangod/Aql/ExecutionBlock.cpp @@ -3560,6 +3560,14 @@ void RemoveBlock::work (std::vector& blocks) { 0, nullptr, ep->_options.waitForSync); + if (ExecutionEngine::isDBServer() && + errorCode == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) { + auto* node = static_cast(getPlanNode()); + if (node->getOptions().ignoreDocumentNotFound) { + // Ignore document not found on the DBserver: + errorCode = TRI_ERROR_NO_ERROR; + } + } } handleResult(errorCode, ep->_options.ignoreErrors); @@ -3795,6 +3803,14 @@ void UpdateBlock::work (std::vector& blocks) { errorCode = TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND; } } + if (ExecutionEngine::isDBServer() && + errorCode == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) { + auto* node = static_cast(getPlanNode()); + if (node->getOptions().ignoreDocumentNotFound) { + // Ignore document not found on the DBserver: + errorCode = TRI_ERROR_NO_ERROR; + } + } } handleResult(errorCode, ep->_options.ignoreErrors, &errorMessage); @@ -3884,6 +3900,16 @@ void ReplaceBlock::work (std::vector& blocks) { // all exceptions are caught in _trx->update() errorCode = _trx->update(trxCollection, key, 0, &mptr, json.json(), TRI_DOC_UPDATE_LAST_WRITE, 0, nullptr, ep->_options.waitForSync); + if (ExecutionEngine::isDBServer() && + errorCode == TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND) { + auto* node = static_cast(getPlanNode()); + if (node->getOptions().ignoreDocumentNotFound) { + errorCode = TRI_ERROR_NO_ERROR; + } + else { + errorCode = TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND_OR_SHARDING_ATTRIBUTES_CHANGED; + } + } } handleResult(errorCode, ep->_options.ignoreErrors); diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index c9cba05aa1..0149aea0a9 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -425,13 +425,13 @@ struct CoordinatorInstanciator : public WalkerWorker { // this map allows to find the queries which are the parts of the big // query. There are two cases, the first is for the remote queries on // the DBservers, for these, the key is: - // itoa(ID of RemoteNode in original plan) + "_" + shardId + // itoa(ID of RemoteNode in original plan) + ":" + shardId // and the value is the // queryId on DBserver // with a * appended, if it is a PART_MAIN query. // The second case is a query, which lives on the coordinator but is not // the main query. For these, we store - // itoa(ID of RemoteNode in original plan) + // itoa(ID of RemoteNode in original plan) + "/" + // and the value is the // queryId used in the QueryRegistry // this is built up when we instanciate the various engines on the @@ -603,7 +603,7 @@ struct CoordinatorInstanciator : public WalkerWorker { // std::cout << "DB SERVER ANSWERED WITHOUT ERROR: " << res->answer->body() << ", REMOTENODEID: " << info.idOfRemoteNode << " SHARDID:" << res->shardID << ", QUERYID: " << queryId << "\n"; std::string theID = triagens::basics::StringUtils::itoa(info.idOfRemoteNode) - + "_" + res->shardID; + + ":" + res->shardID; if (info.part == triagens::aql::PART_MAIN) { queryIds.emplace(theID, queryId+"*"); } @@ -736,7 +736,7 @@ struct CoordinatorInstanciator : public WalkerWorker { for (auto const& shardId : shardIds) { std::string theId = triagens::basics::StringUtils::itoa(remoteNode->id()) - + "_" + shardId; + + ":" + shardId; auto it = queryIds.find(theId); if (it == queryIds.end()) { THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "could not find query id in list"); @@ -952,7 +952,8 @@ ExecutionEngine* ExecutionEngine::instanciateFromPlan (QueryRegistry* queryRegis for (auto& q : inst.get()->queryIds) { std::string theId = q.first; std::string queryId = q.second; - auto pos = theId.find('_'); + // std::cout << "queryIds: " << theId << " : " << queryId << std::endl; + auto pos = theId.find(':'); if (pos != std::string::npos) { // So this is a remote one on a DBserver: if (queryId.back() == '*') { // only the PART_MAIN one! @@ -963,6 +964,25 @@ ExecutionEngine* ExecutionEngine::instanciateFromPlan (QueryRegistry* queryRegis } } } + // Second round, this time we deal with the coordinator pieces + // and tell them the lockedShards as well, we need to copy, since + // they want to delete independently: + for (auto& q : inst.get()->queryIds) { + std::string theId = q.first; + std::string queryId = q.second; + // std::cout << "queryIds: " << theId << " : " << queryId << std::endl; + auto pos = theId.find('/'); + if (pos != std::string::npos) { + // std::cout << "Setting lockedShards for query ID " + // << queryId << std::endl; + QueryId qId = triagens::basics::StringUtils::uint64(queryId); + TRI_vocbase_t* vocbase = query->vocbase(); + Query* q = queryRegistry->open(vocbase, qId); + q->engine()->setLockedShards(new std::unordered_set(*engine->_lockedShards)); + queryRegistry->close(vocbase, qId); + // std::cout << "Setting lockedShards done." << std::endl; + } + } // Now lock them all in the right order: for (auto& p : forLocking) { std::string const& shardId = p.first; @@ -998,7 +1018,7 @@ ExecutionEngine* ExecutionEngine::instanciateFromPlan (QueryRegistry* queryRegis for (auto& q : inst.get()->queryIds) { std::string theId = q.first; std::string queryId = q.second; - auto pos = theId.find('_'); + auto pos = theId.find(':'); if (pos != std::string::npos) { // So this is a remote one on a DBserver: std::string shardId = theId.substr(pos+1); diff --git a/arangod/Aql/ExecutionEngine.h b/arangod/Aql/ExecutionEngine.h index bf11473991..661107dc92 100644 --- a/arangod/Aql/ExecutionEngine.h +++ b/arangod/Aql/ExecutionEngine.h @@ -239,6 +239,14 @@ namespace triagens { return _lockedShards; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief _lockedShards +//////////////////////////////////////////////////////////////////////////////// + + void setLockedShards (std::unordered_set* lockedShards) { + _lockedShards = lockedShards; + } + // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- diff --git a/arangod/Aql/ExecutionNode.h b/arangod/Aql/ExecutionNode.h index 3a28722c65..52c7b11e50 100644 --- a/arangod/Aql/ExecutionNode.h +++ b/arangod/Aql/ExecutionNode.h @@ -2251,6 +2251,22 @@ namespace triagens { double estimateCost (size_t&) const override final; +//////////////////////////////////////////////////////////////////////////////// +/// @brief getOptions +//////////////////////////////////////////////////////////////////////////////// + + ModificationOptions const& getOptions () const { + return _options; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief getOptions +//////////////////////////////////////////////////////////////////////////////// + + ModificationOptions& getOptions () { + return _options; + } + // ----------------------------------------------------------------------------- // --SECTION-- protected variables // ----------------------------------------------------------------------------- @@ -2553,6 +2569,8 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// virtual std::vector getVariablesUsedHere () const override final { + // Please do not change the order here without adjusting the + // optimizer rule distributeInCluster as well! std::vector v; v.push_back(_inDocVariable); @@ -2669,6 +2687,8 @@ namespace triagens { //////////////////////////////////////////////////////////////////////////////// virtual std::vector getVariablesUsedHere () const override final { + // Please do not change the order here without adjusting the + // optimizer rule distributeInCluster as well! std::vector v; v.push_back(_inDocVariable); @@ -3087,7 +3107,7 @@ namespace triagens { : ExecutionNode(plan, id), _vocbase(vocbase), _collection(collection), - _varId(varId){ + _varId(varId) { } DistributeNode (ExecutionPlan*, diff --git a/arangod/Aql/ModificationOptions.cpp b/arangod/Aql/ModificationOptions.cpp index 19ba9bbce0..b63efd4261 100644 --- a/arangod/Aql/ModificationOptions.cpp +++ b/arangod/Aql/ModificationOptions.cpp @@ -37,6 +37,7 @@ ModificationOptions::ModificationOptions (Json const& json) { waitForSync = JsonHelper::getBooleanValue(array.json(), "waitForSync", false); nullMeansRemove = JsonHelper::getBooleanValue(array.json(), "nullMeansRemove", false); mergeObjects = JsonHelper::getBooleanValue(array.json(), "mergeObjects", true); + ignoreDocumentNotFound = JsonHelper::getBooleanValue(array.json(), "ignoreDocumentNotFound", false); } void ModificationOptions::toJson (triagens::basics::Json& json, @@ -46,7 +47,8 @@ void ModificationOptions::toJson (triagens::basics::Json& json, ("ignoreErrors", Json(ignoreErrors)) ("waitForSync", Json(waitForSync)) ("nullMeansRemove", Json(nullMeansRemove)) - ("mergeObjects", Json(mergeObjects)); + ("mergeObjects", Json(mergeObjects)) + ("ignoreDocumentNotFound", Json(ignoreDocumentNotFound)); json ("modificationFlags", flags); } diff --git a/arangod/Aql/ModificationOptions.h b/arangod/Aql/ModificationOptions.h index 33280ae058..4353f930b1 100644 --- a/arangod/Aql/ModificationOptions.h +++ b/arangod/Aql/ModificationOptions.h @@ -54,7 +54,8 @@ namespace triagens { : ignoreErrors(false), waitForSync(false), nullMeansRemove(false), - mergeObjects(true) { + mergeObjects(true), + ignoreDocumentNotFound(false) { } void toJson (triagens::basics::Json& json, TRI_memory_zone_t* zone) const; @@ -67,6 +68,7 @@ namespace triagens { bool waitForSync; bool nullMeansRemove; bool mergeObjects; + bool ignoreDocumentNotFound; }; diff --git a/arangod/Aql/OptimizerRules.cpp b/arangod/Aql/OptimizerRules.cpp index 937a614dd6..3697705d7e 100644 --- a/arangod/Aql/OptimizerRules.cpp +++ b/arangod/Aql/OptimizerRules.cpp @@ -2499,6 +2499,12 @@ int triagens::aql::scatterInClusterRule (Optimizer* opt, nodeType == ExecutionNode::REMOVE) { vocbase = static_cast(node)->vocbase(); collection = static_cast(node)->collection(); + if (nodeType == ExecutionNode::REMOVE || + nodeType == ExecutionNode::UPDATE || + nodeType == ExecutionNode::REPLACE) { + auto* modNode = static_cast(node); + modNode->getOptions().ignoreDocumentNotFound = true; + } } else { TRI_ASSERT(false); @@ -2553,7 +2559,7 @@ int triagens::aql::scatterInClusterRule (Optimizer* opt, /// /// this rule inserts distribute, remote nodes so operations on sharded /// collections actually work, this differs from scatterInCluster in that every -/// incoming row is only set to one shard and not all as in scatterInCluster +/// incoming row is only sent to one shard and not all as in scatterInCluster /// /// it will change plans in place //////////////////////////////////////////////////////////////////////////////// @@ -2571,22 +2577,33 @@ int triagens::aql::distributeInClusterRule (Optimizer* opt, auto const nodeType = node->getType(); if (nodeType != ExecutionNode::INSERT && - nodeType != ExecutionNode::REMOVE) { + nodeType != ExecutionNode::REMOVE && + nodeType != ExecutionNode::REPLACE && + nodeType != ExecutionNode::UPDATE) { opt->addPlan(plan, rule->level, wasModified); return TRI_ERROR_NO_ERROR; } Collection const* collection = static_cast(node)->collection(); - if (nodeType == ExecutionNode::REMOVE) { - // check if collection shard keys are only _key - std::vector shardKeys = collection->shardKeys(); - if (shardKeys.size() != 1 || shardKeys[0] != TRI_VOC_ATTRIBUTE_KEY) { + bool defaultSharding = true; + // check if collection shard keys are only _key + std::vector shardKeys = collection->shardKeys(); + if (shardKeys.size() != 1 || shardKeys[0] != TRI_VOC_ATTRIBUTE_KEY) { + defaultSharding = false; + } + + if (nodeType == ExecutionNode::REMOVE || + nodeType == ExecutionNode::UPDATE) { + if (! defaultSharding) { + // We have to use a ScatterNode. opt->addPlan(plan, rule->level, wasModified); return TRI_ERROR_NO_ERROR; } } + // In the INSERT and REPLACE cases we use a DistributeNode... + auto deps = node->getDependencies(); TRI_ASSERT(deps.size() == 1); @@ -2597,9 +2614,33 @@ int triagens::aql::distributeInClusterRule (Optimizer* opt, TRI_vocbase_t* vocbase = static_cast(node)->vocbase(); // insert a distribute node - TRI_ASSERT(node->getVariablesUsedHere().size() == 1); - ExecutionNode* distNode = new DistributeNode(plan, plan->nextId(), - vocbase, collection, node->getVariablesUsedHere()[0]->id); + ExecutionNode* distNode = nullptr; + if (nodeType == ExecutionNode::INSERT || + nodeType == ExecutionNode::REMOVE) { + TRI_ASSERT(node->getVariablesUsedHere().size() == 1); + distNode = new DistributeNode(plan, plan->nextId(), + vocbase, collection, node->getVariablesUsedHere()[0]->id); + } + else if (nodeType == ExecutionNode::REPLACE) { + std::vector v = node->getVariablesUsedHere(); + if (defaultSharding) { + // We only look into _inKeyVariable + distNode = new DistributeNode(plan, plan->nextId(), + vocbase, collection, v[1]->id); + } + else { + // We only look into _inDocVariable + distNode = new DistributeNode(plan, plan->nextId(), + vocbase, collection, v[0]->id); + } + } + else { // if (nodeType == ExecutionNode::UPDATE) + std::vector v = node->getVariablesUsedHere(); + distNode = new DistributeNode(plan, plan->nextId(), + vocbase, collection, v[1]->id); + // This is the _inKeyVariable! This works, since we use a ScatterNode + // for non-default-sharding attributes. + } plan->registerNode(distNode); distNode->addDependency(deps[0]); diff --git a/arangod/Aql/QueryRegistry.cpp b/arangod/Aql/QueryRegistry.cpp index 3d367f73de..ed793839ee 100644 --- a/arangod/Aql/QueryRegistry.cpp +++ b/arangod/Aql/QueryRegistry.cpp @@ -138,6 +138,7 @@ void QueryRegistry::insert (QueryId id, Query* QueryRegistry::open (TRI_vocbase_t* vocbase, QueryId id) { + // std::cout << "Taking out query with ID " << id << std::endl; WRITE_LOCKER(_lock); auto m = _queries.find(vocbase->_name); @@ -161,6 +162,7 @@ Query* QueryRegistry::open (TRI_vocbase_t* vocbase, // If we had set _makeNolockHeaders, we need to reset it: if (qi->_query->engine()->lockedShards() != nullptr) { if (Transaction::_makeNolockHeaders == nullptr) { + // std::cout << "Setting _makeNolockHeaders\n"; Transaction::_makeNolockHeaders = qi->_query->engine()->lockedShards(); } else { @@ -177,6 +179,7 @@ Query* QueryRegistry::open (TRI_vocbase_t* vocbase, void QueryRegistry::close (TRI_vocbase_t* vocbase, QueryId id, double ttl) { + // std::cout << "Returning query with ID " << id << std::endl; WRITE_LOCKER(_lock); auto m = _queries.find(vocbase->_name); @@ -200,6 +203,7 @@ void QueryRegistry::close (TRI_vocbase_t* vocbase, QueryId id, double ttl) { // If we have set _makeNolockHeaders, we need to unset it: if (Transaction::_makeNolockHeaders != nullptr) { if (Transaction::_makeNolockHeaders == qi->_query->engine()->lockedShards()) { + // std::cout << "Resetting _makeNolockHeaders to nullptr\n"; Transaction::_makeNolockHeaders = nullptr; } else { diff --git a/arangod/Aql/RestAqlHandler.cpp b/arangod/Aql/RestAqlHandler.cpp index d098e319b0..ae83303e1d 100644 --- a/arangod/Aql/RestAqlHandler.cpp +++ b/arangod/Aql/RestAqlHandler.cpp @@ -589,7 +589,7 @@ void RestAqlHandler::getInfoQuery (std::string const& operation, //////////////////////////////////////////////////////////////////////////////// triagens::rest::HttpHandler::status_t RestAqlHandler::execute () { - // std::cout << "GOT INCOMING REQUEST: " << triagens::rest::HttpRequest::translateMethod(_request->requestType()) << ", " << triagens::arango::ServerState::instance()->getId() << ": " << _request->fullUrl() << ": " << _request->body() << "\n"; + // std::cout << "GOT INCOMING REQUEST: " << triagens::rest::HttpRequest::translateMethod(_request->requestType()) << ", " << triagens::arango::ServerState::instance()->getId() << ": " << _request->fullUrl() << ": " << _request->body() << "\n\n"; std::vector const& suffix = _request->suffix(); diff --git a/arangod/Cluster/ClusterComm.cpp b/arangod/Cluster/ClusterComm.cpp index 0701b3fc67..4806d95e02 100644 --- a/arangod/Cluster/ClusterComm.cpp +++ b/arangod/Cluster/ClusterComm.cpp @@ -196,8 +196,12 @@ ClusterCommResult* ClusterComm::asyncRequest ( op->serverID = ClusterInfo::instance()->getResponsibleServer(op->shardID); LOG_DEBUG("Responsible server: %s", op->serverID.c_str()); if (triagens::arango::Transaction::_makeNolockHeaders != nullptr) { + // LOCKING-DEBUG + // std::cout << "Found Nolock header\n"; auto it = triagens::arango::Transaction::_makeNolockHeaders->find(op->shardID); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { + // LOCKING-DEBUG + // std::cout << "Found our shard\n"; (*headerFields)["X-Arango-Nolock"] = op->shardID; } } @@ -240,6 +244,13 @@ ClusterCommResult* ClusterComm::asyncRequest ( op->endTime = timeout == 0.0 ? TRI_microtime()+24*60*60.0 : TRI_microtime()+timeout; + // LOCKING-DEBUG + // std::cout << "asyncRequest: sending " << triagens::rest::HttpRequest::translateMethod(reqtype) << " request to DB server '" << op->serverID << ":" << path << "\n" << body << "\n"; + // for (auto& h : *headerFields) { + // std::cout << h.first << ":" << h.second << std::endl; + // } + // std::cout << std::endl; + ClusterCommResult* res = new ClusterCommResult(); *res = *static_cast(op); @@ -311,8 +322,12 @@ ClusterCommResult* ClusterComm::syncRequest ( return res; } if (triagens::arango::Transaction::_makeNolockHeaders != nullptr) { + // LOCKING-DEBUG + // std::cout << "Found Nolock header\n"; auto it = triagens::arango::Transaction::_makeNolockHeaders->find(res->shardID); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { + // LOCKING-DEBUG + // std::cout << "Found this shard: " << res->shardID << std::endl; headersCopy["X-Arango-Nolock"] = res->shardID; } } @@ -355,6 +370,12 @@ ClusterCommResult* ClusterComm::syncRequest ( LOG_DEBUG("sending %s request to DB server '%s': %s", triagens::rest::HttpRequest::translateMethod(reqtype).c_str(), res->serverID.c_str(), body.c_str()); + // LOCKING-DEBUG + // std::cout << "syncRequest: sending " << triagens::rest::HttpRequest::translateMethod(reqtype) << " request to DB server '" << res->serverID << ":" << path << "\n" << body << "\n"; + // for (auto& h : headersCopy) { + // std::cout << h.first << ":" << h.second << std::endl; + // } + // std::cout << std::endl; triagens::httpclient::SimpleHttpClient* client = new triagens::httpclient::SimpleHttpClient( connection->connection, diff --git a/arangod/RestHandler/RestVocbaseBaseHandler.cpp b/arangod/RestHandler/RestVocbaseBaseHandler.cpp index 8d10e7401c..a9fb6c5881 100644 --- a/arangod/RestHandler/RestVocbaseBaseHandler.cpp +++ b/arangod/RestHandler/RestVocbaseBaseHandler.cpp @@ -663,6 +663,13 @@ int RestVocbaseBaseHandler::parseDocumentId (CollectionNameResolver const* resol void RestVocbaseBaseHandler::prepareExecute () { bool found; + // LOCKING-DEBUG + // std::cout << "REQ coming in: " << _request->requestType() << ": " <<_request->fullUrl() << std::endl; + //std::map h = _request->headers(); + //for (auto& hh : h) { + // std::cout << hh.first << ": " << hh.second << std::endl; + //} + //std::cout << std::endl; char const* shardId = _request->header("x-arango-nolock", found); if (found) { _nolockHeaderSet = new std::unordered_set(); diff --git a/arangod/VocBase/document-collection.cpp b/arangod/VocBase/document-collection.cpp index 2a4c48deb5..8c0fc6c3ed 100644 --- a/arangod/VocBase/document-collection.cpp +++ b/arangod/VocBase/document-collection.cpp @@ -861,9 +861,13 @@ static int BeginRead (TRI_document_collection_t* document) { auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "BeginRead blocked: " << document->_info._name << std::endl; return TRI_ERROR_NO_ERROR; } } + // LOCKING-DEBUG + // std::cout << "BeginRead: " << document->_info._name << std::endl; TRI_READ_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); return TRI_ERROR_NO_ERROR; @@ -879,9 +883,13 @@ static int EndRead (TRI_document_collection_t* document) { auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "EndRead blocked: " << document->_info._name << std::endl; return TRI_ERROR_NO_ERROR; } } + // LOCKING-DEBUG + // std::cout << "EndRead: " << document->_info._name << std::endl; TRI_READ_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); return TRI_ERROR_NO_ERROR; @@ -897,9 +905,13 @@ static int BeginWrite (TRI_document_collection_t* document) { auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "BeginWrite blocked: " << document->_info._name << std::endl; return TRI_ERROR_NO_ERROR; } } + // LOCKING_DEBUG + // std::cout << "BeginWrite: " << document->_info._name << std::endl; TRI_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); return TRI_ERROR_NO_ERROR; @@ -915,9 +927,13 @@ static int EndWrite (TRI_document_collection_t* document) { auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "EndWrite blocked: " << document->_info._name << std::endl; return TRI_ERROR_NO_ERROR; } } + // LOCKING-DEBUG + // std::cout << "EndWrite: " << document->_info._name << std::endl; TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document); return TRI_ERROR_NO_ERROR; @@ -935,11 +951,15 @@ static int BeginReadTimed (TRI_document_collection_t* document, auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "BeginReadTimed blocked: " << document->_info._name << std::endl; return TRI_ERROR_NO_ERROR; } } uint64_t waited = 0; + // LOCKING-DEBUG + // std::cout << "BeginReadTimed: " << document->_info._name << std::endl; while (! TRI_TRY_READ_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document)) { #ifdef _WIN32 usleep((unsigned long) sleepPeriod); @@ -969,11 +989,15 @@ static int BeginWriteTimed (TRI_document_collection_t* document, auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "BeginWriteTimed blocked: " << document->_info._name << std::endl; return TRI_ERROR_NO_ERROR; } } uint64_t waited = 0; + // LOCKING-DEBUG + // std::cout << "BeginWriteTimed: " << document->_info._name << std::endl; while (! TRI_TRY_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(document)) { #ifdef _WIN32 usleep((unsigned long) sleepPeriod); diff --git a/arangod/VocBase/transaction.cpp b/arangod/VocBase/transaction.cpp index f36d1aa133..8449940459 100644 --- a/arangod/VocBase/transaction.cpp +++ b/arangod/VocBase/transaction.cpp @@ -348,6 +348,8 @@ static int LockCollection (TRI_transaction_collection_t* trxCollection, auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "LockCollection blocked: " << collName << std::endl; return TRI_ERROR_NO_ERROR; } } @@ -411,6 +413,8 @@ static int UnlockCollection (TRI_transaction_collection_t* trxCollection, auto it = triagens::arango::Transaction::_makeNolockHeaders->find(collName); if (it != triagens::arango::Transaction::_makeNolockHeaders->end()) { // do not lock by command + // LOCKING-DEBUG + // std::cout << "UnlockCollection blocked: " << collName << std::endl; return TRI_ERROR_NO_ERROR; } } diff --git a/js/apps/system/aardvark/frontend/js/bootstrap/errors.js b/js/apps/system/aardvark/frontend/js/bootstrap/errors.js index 212b7427e1..0b5d458755 100644 --- a/js/apps/system/aardvark/frontend/js/bootstrap/errors.js +++ b/js/apps/system/aardvark/frontend/js/bootstrap/errors.js @@ -145,6 +145,7 @@ "ERROR_CLUSTER_READING_PLAN_AGENCY" : { "code" : 1472, "message" : "error reading Plan in agency" }, "ERROR_CLUSTER_COULD_NOT_TRUNCATE_COLLECTION" : { "code" : 1473, "message" : "could not truncate collection" }, "ERROR_CLUSTER_AQL_COMMUNICATION" : { "code" : 1474, "message" : "error in cluster internal communication for AQL" }, + "ERROR_ARANGO_DOCUMENT_NOT_FOUND_OR_SHARDING_ATTRIBUTES_CHANGED" : { "code" : 1475, "message" : "document not found or sharding attributes changed" }, "ERROR_QUERY_KILLED" : { "code" : 1500, "message" : "query killed" }, "ERROR_QUERY_PARSE" : { "code" : 1501, "message" : "%s" }, "ERROR_QUERY_EMPTY" : { "code" : 1502, "message" : "query is empty" }, diff --git a/js/common/bootstrap/errors.js b/js/common/bootstrap/errors.js index 212b7427e1..0b5d458755 100644 --- a/js/common/bootstrap/errors.js +++ b/js/common/bootstrap/errors.js @@ -145,6 +145,7 @@ "ERROR_CLUSTER_READING_PLAN_AGENCY" : { "code" : 1472, "message" : "error reading Plan in agency" }, "ERROR_CLUSTER_COULD_NOT_TRUNCATE_COLLECTION" : { "code" : 1473, "message" : "could not truncate collection" }, "ERROR_CLUSTER_AQL_COMMUNICATION" : { "code" : 1474, "message" : "error in cluster internal communication for AQL" }, + "ERROR_ARANGO_DOCUMENT_NOT_FOUND_OR_SHARDING_ATTRIBUTES_CHANGED" : { "code" : 1475, "message" : "document not found or sharding attributes changed" }, "ERROR_QUERY_KILLED" : { "code" : 1500, "message" : "query killed" }, "ERROR_QUERY_PARSE" : { "code" : 1501, "message" : "%s" }, "ERROR_QUERY_EMPTY" : { "code" : 1502, "message" : "query is empty" }, diff --git a/js/node/node_modules/aqb/.npmignore b/js/node/node_modules/aqb/.npmignore deleted file mode 100644 index d8edb24a82..0000000000 --- a/js/node/node_modules/aqb/.npmignore +++ /dev/null @@ -1,3 +0,0 @@ -.gitignore -node_modules -test \ No newline at end of file diff --git a/js/node/node_modules/aqb/.travis.yml b/js/node/node_modules/aqb/.travis.yml deleted file mode 100644 index 63c20e2605..0000000000 --- a/js/node/node_modules/aqb/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: node_js -node_js: - - "0.10" -services: - - redis-server -after_script: - - npm test \ No newline at end of file diff --git a/js/node/node_modules/aqb/README.md b/js/node/node_modules/aqb/README.md index b21f54fd48..b3a8dbe229 100644 --- a/js/node/node_modules/aqb/README.md +++ b/js/node/node_modules/aqb/README.md @@ -2,6 +2,55 @@ The query builder allows constructing complex AQL queries with a pure JavaScript fluid API. +[![license - APACHE-2.0](https://img.shields.io/npm/l/aqb.svg)](http://opensource.org/licenses/APACHE-2.0) [![Dependencies](https://img.shields.io/david/arangodb/aqbjs.svg)](https://david-dm.org/arangodb/aqbjs) + +[![NPM status](https://nodei.co/npm/aqb.png?downloads=true&stars=true)](https://npmjs.org/package/aqb) + +[![Build status](https://img.shields.io/travis/arangodb/aqbjs.svg)](https://travis-ci.org/arangodb/aqbjs) [![Coverage Status](https://img.shields.io/coveralls/arangodb/aqbjs.svg)](https://coveralls.io/r/arangodb/aqbjs?branch=master) [![Codacy rating](https://img.shields.io/codacy/1d5a1be201024e0caaf0aa6bc990231e.svg)](https://www.codacy.com/public/me_4/aqbjs) + +# Install + +## With NPM + +```sh +npm install aqb +``` + +## With Bower + +```sh +bower install aqb +``` + +## ArangoDB + +As of ArangoDB 1.3, a version of `aqb` comes pre-installed with ArangoDB. + +```js +var qb = require('aqb'); +``` + +If you want to use a more recent version of `aqb` in a Foxx app, you can add it to your NPM dependencies as usual. + +## Browser + +This CommonJS module is compatible with [browserify](http://browserify.org). + +If you don't want to use browserify, you can simply use the AMD-compatible [browserify bundle](https://raw.githubusercontent.com/arangodb/aqbjs/master/dist/aqb.min.js) (~30 kB minified, ~6 kB gzipped). + +If you want to use this module in non-ES5 browsers like Microsoft Internet Explorer 8 and earlier, you may need to include [es5-shim](https://www.npmjs.com/package/es5-shim) or a similar ES5 polyfill. + +## From source + +```sh +git clone https://github.com/arangodb/aqbjs.git +cd aqbjs +npm install +npm run dist +``` + +# Example + ```js // in arangosh var db = require('org/arangodb').db; @@ -9,15 +58,15 @@ var qb = require('aqb'); console.log(db._query(qb.for('x').in('1..5').return('x')).toArray()); // [1, 2, 3, 4, 5] ``` -## API +# API -### AQL Types +## AQL Types If raw JavaScript values are passed to AQL statements, they will be wrapped in a matching AQL type automatically. JavaScript strings wrapped in quotation marks will be wrapped in AQL strings, all other JavaScript strings will be wrapped as simple references (see below) and throw an *AQLError* if they are not well-formed. -#### Boolean +### Boolean Wraps the given value as an AQL Boolean literal. @@ -27,7 +76,7 @@ If the value is truthy, it will be converted to the AQL Boolean *true*, otherwis If the value is already an AQL Boolean, its own value will be wrapped instead. -#### Number +### Number Wraps the given value as an AQL Number literal. @@ -39,7 +88,7 @@ If the value does not represent a finite number, an *AQLError* will be thrown. If the value is already an AQL Number or AQL Integer, its own value will be wrapped instead. -#### Integer +### Integer Wraps the given value as an AQL Integer literal. @@ -53,7 +102,7 @@ If the value is already an AQL Number or AQL Integer, its own value will be wrap *Alias:* `qb.int_(value)` -#### String +### String Wraps the given value as an AQL String literal. @@ -65,7 +114,7 @@ If the value is already an AQL String, its own value will be wrapped instead. If the value is an object with a *toAQL* method, the result of calling that method will be wrapped instead. -#### List +### List Wraps the given value as an AQL List (Array) literal. @@ -77,7 +126,7 @@ If the value is already an AQL List, its own value will be wrapped instead. Any list elements that are not already AQL values will be converted automatically. -#### Object +### Object Wraps the given value as an AQL Object literal. @@ -89,7 +138,7 @@ If the value is already an AQL List, its own value will be wrapped instead. Any property values that are not already AQL values will be converted automatically. -#### Simple Reference +### Simple Reference Wraps a given value in an AQL Simple Reference. @@ -127,9 +176,9 @@ var myUserCollection = applicationContext.collection('users'); var users = db._query(qb.for('u').in(myUserCollection).return('u')).toArray(); ``` -### AQL Expressions +## AQL Expressions -#### Range +### Range Creates a range expression from the given values. @@ -137,7 +186,7 @@ Creates a range expression from the given values. If the values are not already AQL values, they will be converted automatically. -#### Property Access +### Property Access Creates a property access expression from the given values. @@ -145,7 +194,7 @@ Creates a property access expression from the given values. If the values are not already AQL values, they will be converted automatically. -#### Raw Expression +### Raw Expression Wraps a given value in a raw AQL expression. @@ -155,9 +204,9 @@ If the value is already an AQL Raw Expression, its value is wrapped instead. **Warning:** Whenever possible, you should use one of the other methods or a combination thereof instead of using a raw expression. Raw expressions allow passing arbitrary strings into your AQL and thus will open you to AQL injection attacks if you are passing in untrusted user input. -### AQL Operations +## AQL Operations -#### Boolean And +### Boolean And Creates an "and" operation from the given values. @@ -171,7 +220,7 @@ This function can take any number of arguments. `qb.and(a, b, c, d, e, f)` -> `(a && b && c && d && e && f)` -#### Boolean Or +### Boolean Or Creates an "or" operation from the given values. @@ -185,7 +234,7 @@ This function can take any number of arguments. `qb.or(a, b, c, d, e, f)` -> `(a || b || c || d || e || f)` -#### Addition +### Addition Creates an addition operation from the given values. @@ -201,7 +250,7 @@ This function can take any number of arguments. `qb.add(a, b, c, d, e, f)` -> `(a + b + c + d + e + f)` -#### Subtraction +### Subtraction Creates a subtraction operation from the given values. @@ -217,7 +266,7 @@ This function can take any number of arguments. `qb.sub(a, b, c, d, e, f)` -> `(a - b - c - d - e - f)` -#### Multiplication +### Multiplication Creates a multiplication operation from the given values. @@ -233,7 +282,7 @@ This function can take any number of arguments. `qb.mul(a, b, c, d, e, f)` -> `(a * b * c * d * e * f)` -#### Division +### Division Creates a division operation from the given values. @@ -247,7 +296,7 @@ This function can take any number of arguments. `qb.div(a, b, c, d, e, f)` -> `(a / b / c / d / e / f)` -#### Modulus +### Modulus Creates a modulus operation from the given values. @@ -261,7 +310,7 @@ This function can take any number of arguments. `qb.mod(a, b, c, d, e, f)` -> `(a % b % c % d % e % f)` -#### Equality +### Equality Creates an equality comparison from the given values. @@ -269,7 +318,7 @@ Creates an equality comparison from the given values. If the values are not already AQL values, they will be converted automatically. -#### Inequality +### Inequality Creates an inequality comparison from the given values. @@ -277,7 +326,7 @@ Creates an inequality comparison from the given values. If the values are not already AQL values, they will be converted automatically. -#### Greater Than +### Greater Than Creates a greater-than comparison from the given values. @@ -285,7 +334,7 @@ Creates a greater-than comparison from the given values. If the values are not already AQL values, they will be converted automatically. -#### Greater Than Or Equal To +### Greater Than Or Equal To Creates a greater-than-or-equal-to comparison from the given values. @@ -293,7 +342,7 @@ Creates a greater-than-or-equal-to comparison from the given values. If the values are not already AQL values, they will be converted automatically. -#### Less Than +### Less Than Creates a less-than comparison from the given values. @@ -301,7 +350,7 @@ Creates a less-than comparison from the given values. If the values are not already AQL values, they will be converted automatically. -#### Less Than Or Equal To +### Less Than Or Equal To Creates a less-than-or-equal-to comparison from the given values. @@ -309,7 +358,7 @@ Creates a less-than-or-equal-to comparison from the given values. If the values are not already AQL values, they will be converted automatically. -#### Contains +### Contains Creates an "in" comparison from the given values. @@ -319,7 +368,7 @@ If the values are not already AQL values, they will be converted automatically. *Aliases:* `qb.in_(a, b)` -#### Negation +### Negation Creates a negation from the given value. @@ -327,7 +376,7 @@ Creates a negation from the given value. If the value is not already an AQL value, it will be converted automatically. -#### Negative Value +### Negative Value Creates a negative value expression from the given value. @@ -335,7 +384,7 @@ Creates a negative value expression from the given value. If the value is not already an AQL value, it will be converted automatically. -#### Ternary (if / else) +### Ternary (if / else) Creates a ternary expression from the given values. @@ -345,7 +394,7 @@ If the values are not already AQL values, they will be converted automatically. *Aliases:* `qb.if_(condition, then, otherwise)` -#### Function Call +### Function Call Creates a function call for the given name and arguments. @@ -362,7 +411,7 @@ For built-in functions, methods with the relevant function name are already prov * `qb.RANDOM()` -> `RANDOM()` * `qb.FLOOR(qb.div(5, 2))` -> `FLOOR((5 / 2))` -### AQL Statements +## AQL Statements In addition to the methods documented above, the query builder provides all methods of *PartialStatement* objects. @@ -375,59 +424,59 @@ qb.for('doc').in('my_collection').return('doc._key').toAQL() // -> FOR doc IN my_collection RETURN doc._key ``` -#### FOR expression IN collection +### FOR expression IN collection `PartialStatement::for(expression).in(collection) : Statement` *Alias:* `for_(expression).in_(collection)` -#### LET varname = expression +### LET varname = expression `PartialStatement::let(varname, expression) : Statement` *Alias:* `let_(varname, expression)` -#### LET var1 = expr1, var2 = expr2, …, varn = exprn +### LET var1 = expr1, var2 = expr2, …, varn = exprn `PartialStatement::let(definitions) : Statement` *Alias:* `let_(definitions)` -#### FILTER expression +### FILTER expression `PartialStatement::filter(expression) : Statement` -#### COLLECT varname = expression +### COLLECT varname = expression `PartialStatement::collect(varname, expression) : Statement` -#### COLLECT varname1 = expression INTO varname2 +### COLLECT varname1 = expression INTO varname2 `PartialStatement::collect(varname1, expression).into(varname2) : Statement` -#### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn +### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn `PartialStatement::collect(definitions) : Statement` -#### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn INTO varname +### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn INTO varname `PartialStatement::collect(definitions).into(varname) : Statement` -#### SORT args… +### SORT args… `PartialStatement::sort(args…) : Statement` -#### LIMIT offset, count +### LIMIT offset, count `PartialStatement::limit([offset,] count) : Statement` -#### RETURN expression +### RETURN expression `PartialStatement::return(expression) : Statement` *Alias:* `return_(expression)` -#### REMOVE expression IN collection +### REMOVE expression IN collection `PartialStatement::remove(expression).in(collection) : RemoveExpression` @@ -436,11 +485,11 @@ qb.for('doc').in('my_collection').return('doc._key').toAQL() * `remove(expression).in_(collection)` * `remove(expression).into(collection)` -#### REMOVE … OPTIONS options +### REMOVE … OPTIONS options `RemoveExpression::options(options) : Statement` -#### INSERT expression INTO collection +### INSERT expression INTO collection `PartialStatement::insert(expression).into(collection) : InsertExpression` @@ -449,11 +498,11 @@ qb.for('doc').in('my_collection').return('doc._key').toAQL() * `insert(expression).in(collection)` * `insert(expression).in_(collection)` -#### INSERT … OPTIONS options +### INSERT … OPTIONS options `InsertExpression::options(options) : Statement` -#### UPDATE expression1 WITH expression2 IN collection +### UPDATE expression1 WITH expression2 IN collection `PartialStatement::update(expression1).with(expression2).in(collection) : UpdateExpression` @@ -465,7 +514,7 @@ qb.for('doc').in('my_collection').return('doc._key').toAQL() * `update(expression1).with_(expression2).in_(collection)` * `update(expression1).with_(expression2).into(collection)` -#### UPDATE expression IN collection +### UPDATE expression IN collection `PartialStatement::update(expression).in(collection) : UpdateExpression` @@ -474,11 +523,11 @@ qb.for('doc').in('my_collection').return('doc._key').toAQL() * `update(expression).in_(collection)` * `update(expression).into(collection)` -#### UPDATE … OPTIONS options +### UPDATE … OPTIONS options `UpdateExpression::options(options) : Statement` -#### REPLACE expression1 WITH expression2 IN collection +### REPLACE expression1 WITH expression2 IN collection `PartialStatement::replace(expression1).with(expression2).in(collection) : ReplaceExpression` @@ -490,7 +539,7 @@ qb.for('doc').in('my_collection').return('doc._key').toAQL() * `replace(expression1).with_(expression2).in_(collection)` * `replace(expression1).with_(expression2).into(collection)` -#### REPLACE expression IN collection +### REPLACE expression IN collection `PartialStatement::replace(expression).in(collection) : ReplaceExpression` @@ -499,6 +548,10 @@ qb.for('doc').in('my_collection').return('doc._key').toAQL() * `replace(expression).in_(collection)` * `replace(expression).into(collection)` -#### REPLACE … OPTIONS options +### REPLACE … OPTIONS options `ReplaceExpression::options(options) : Statement` + +# License + +The Apache License, Version 2.0. For more information, see the accompanying LICENSE file. diff --git a/js/node/node_modules/aqb/assumptions.js b/js/node/node_modules/aqb/assumptions.js index c8943ac7ab..cbe181b89c 100644 --- a/js/node/node_modules/aqb/assumptions.js +++ b/js/node/node_modules/aqb/assumptions.js @@ -1,5 +1,4 @@ -/* jshint globalstrict: true, es3: true */ -/* globals require: false, exports: false */ +/*jshint browserify: true */ 'use strict'; exports.keywords = [ 'asc', diff --git a/js/node/node_modules/aqb/errors.js b/js/node/node_modules/aqb/errors.js index 2e513138e4..14f0596420 100644 --- a/js/node/node_modules/aqb/errors.js +++ b/js/node/node_modules/aqb/errors.js @@ -1,5 +1,4 @@ -/* jshint globalstrict: true, es3: true */ -/* globals require: false, exports: false */ +/*jshint browserify: true */ 'use strict'; function AqlError(message) { this.message = message; diff --git a/js/node/node_modules/aqb/index.js b/js/node/node_modules/aqb/index.js index b4a3859b83..85b4e441b1 100644 --- a/js/node/node_modules/aqb/index.js +++ b/js/node/node_modules/aqb/index.js @@ -1,26 +1,14 @@ -/* jshint globalstrict: true, es3: true */ -/* globals require: false, module: false, console: false */ +/*jshint browserify: true */ +/*globals console: false */ 'use strict'; var AqlError = require('./errors').AqlError, assumptions = require('./assumptions'), types = require('./types'), QB = {}, - bind, toArray, warn; - -bind = (typeof Function.prototype.bind === 'function' ? ( - Function.prototype.call.bind(Function.prototype.bind) -) : ( - function (fn, self) { - return function () { - return fn.apply(self, arguments); - }; - } -)); - -toArray = bind(Function.prototype.call, Array.prototype.slice); +toArray = Function.prototype.call.bind(Array.prototype.slice); warn = (function () { if (typeof console !== 'undefined') { @@ -34,15 +22,14 @@ warn = (function () { } }()); -for (var key in types._PartialStatement.prototype) { - if (types._PartialStatement.prototype.hasOwnProperty(key) && key !== 'constructor') { - QB[key] = bind(types._PartialStatement.prototype[key], null); - } -} +Object.keys(types._PartialStatement.prototype).forEach(function (key) { + if (key === 'constructor') return; + QB[key] = types._PartialStatement.prototype[key].bind(null); +}); QB.bool = function (value) {return new types.BooleanLiteral(value);}; QB.num = function (value) {return new types.NumberLiteral(value);}; -QB.int_ = function (value) {return new types.IntegerLiteral(value);}; +QB.int_ = QB.int = function (value) {return new types.IntegerLiteral(value);}; QB.str = function (value) {return new types.StringLiteral(value);}; QB.list = function (arr) {return new types.ListLiteral(arr);}; QB.obj = function (obj) {return new types.ObjectLiteral(obj);}; @@ -58,9 +45,9 @@ QB.expr = function (value) {return new types.RawExpression(value);}; QB.and = function (/* x, y... */) {return new types.NAryOperation('&&', toArray(arguments));}; QB.or = function (/* x, y... */) {return new types.NAryOperation('||', toArray(arguments));}; -QB.add = function (/* x, y... */) {return new types.NAryOperation('+', toArray(arguments));}; -QB.sub = function (/* x, y... */) {return new types.NAryOperation('-', toArray(arguments));}; -QB.mul = function (/* x, y... */) {return new types.NAryOperation('*', toArray(arguments));}; +QB.plus = QB.add = function (/* x, y... */) {return new types.NAryOperation('+', toArray(arguments));}; +QB.minus = QB.sub = function (/* x, y... */) {return new types.NAryOperation('-', toArray(arguments));}; +QB.times = QB.mul = function (/* x, y... */) {return new types.NAryOperation('*', toArray(arguments));}; QB.div = function (/* x, y... */) {return new types.NAryOperation('/', toArray(arguments));}; QB.mod = function (/* x, y... */) {return new types.NAryOperation('%', toArray(arguments));}; QB.eq = function (x, y) {return new types.BinaryOperation('==', x, y);}; @@ -71,16 +58,8 @@ QB.lte = function (x, y) {return new types.BinaryOperation('<=', x, y);}; QB.neq = function (x, y) {return new types.BinaryOperation('!=', x, y);}; QB.not = function (x) {return new types.UnaryOperation('!', x);}; QB.neg = function (x) {return new types.UnaryOperation('-', x);}; -QB.in_ = function (x, y) {return new types.BinaryOperation('in', x, y);}; -QB.if_ = function (x, y, z) {return new types.TernaryOperation('?', ':', x, y, z);}; - -QB.plus = QB.add; -QB.minus = QB.sub; -QB.times = QB.mul; - -QB['int'] = QB.int_; -QB['in'] = QB.in_; -QB['if'] = QB.if_; +QB.in_ = QB.in = function (x, y) {return new types.BinaryOperation('in', x, y);}; +QB.if_ = QB.if = function (x, y, z) {return new types.TernaryOperation('?', ':', x, y, z);}; QB.fn = function (functionName, arity) { if (typeof arity === 'number') { @@ -120,13 +99,11 @@ function deprecateAqlFunction(fn, functionName) { }; } -for (var key in assumptions.builtins) { - if (assumptions.builtins.hasOwnProperty(key)) { - QB[key] = QB.fn(key, assumptions.builtins[key]); - if (assumptions.deprecatedBuiltins.indexOf(key) !== -1) { - QB[key] = deprecateAqlFunction(QB[key], key); - } +Object.keys(assumptions.builtins).forEach(function (key) { + QB[key] = QB.fn(key, assumptions.builtins[key]); + if (assumptions.deprecatedBuiltins.indexOf(key) !== -1) { + QB[key] = deprecateAqlFunction(QB[key], key); } -} +}); module.exports = QB; \ No newline at end of file diff --git a/js/node/node_modules/aqb/package.json b/js/node/node_modules/aqb/package.json index ed52e95893..1c7d414840 100644 --- a/js/node/node_modules/aqb/package.json +++ b/js/node/node_modules/aqb/package.json @@ -1,43 +1,59 @@ { "name": "aqb", - "license": "APACHE2_0", - "version": "1.4.1", + "version": "1.5.1", "description": "ArangoDB AQL query builder.", + "main": "index.js", "keywords": [ "arangodb", "aql", "nosql", "query" ], - "author": { - "name": "Alan Plum", - "email": "me@pluma.io", - "url": "https://www.arangodb.org" - }, - "dependencies": {}, - "devDependencies": { - "expect.js": "^0.3.1", - "mocha": "^1.21.4" - }, - "engine": "node >= 0.8.0", - "bugs": { - "url": "https://github.com/arangodb/aqbjs/issues" - }, + "files": [ + "*.js", + "package.json", + "README.md", + "LICENSE" + ], "scripts": { - "test": "mocha --growl -R spec test test/**" + "test": "npm run lint && npm run test-only", + "test-only": "mocha -t 30000 --growl -R spec test test/**", + "cover": "npm run lint && istanbul cover --report lcov _mocha -- -t 30000 -R spec", + "coveralls": "npm run cover && cat ./coverage/lcov.info | coveralls ; rm -rf ./coverage", + "dist": "npm run bundle && npm run minify", + "bundle": "browserify -t dekeywordify -u console -s aqb ./index.js > dist/aqb.js", + "minify": "uglifyjs dist/aqb.js > dist/aqb.min.js", + "lint": "jshint index.js *.js test test/**", + "prepublish": "npm run lint" }, "repository": { "type": "git", "url": "git://github.com/arangodb/aqbjs.git" }, - "main": "index.js", - "readme": "# ArangoDB Query Builder\n\nThe query builder allows constructing complex AQL queries with a pure JavaScript fluid API.\n\n```js\n// in arangosh\nvar db = require('org/arangodb').db;\nvar qb = require('aqb');\nconsole.log(db._query(qb.for('x').in('1..5').return('x')).toArray()); // [1, 2, 3, 4, 5]\n```\n\n## API\n\n### AQL Types\n\nIf raw JavaScript values are passed to AQL statements, they will be wrapped in a matching AQL type automatically.\n\nJavaScript strings wrapped in quotation marks will be wrapped in AQL strings, all other JavaScript strings will be wrapped as simple references (see below) and throw an *AQLError* if they are not well-formed.\n\n#### Boolean\n\nWraps the given value as an AQL Boolean literal.\n\n`qb.bool(value)`\n\nIf the value is truthy, it will be converted to the AQL Boolean *true*, otherwise it will be converted to the AQL Boolean *false*.\n\nIf the value is already an AQL Boolean, its own value will be wrapped instead.\n\n#### Number\n\nWraps the given value as an AQL Number literal.\n\n`qb.num(value)`\n\nIf the value is not a JavaScript Number, it will be converted first.\n\nIf the value does not represent a finite number, an *AQLError* will be thrown.\n\nIf the value is already an AQL Number or AQL Integer, its own value will be wrapped instead.\n\n#### Integer\n\nWraps the given value as an AQL Integer literal.\n\n`qb.int(value)`\n\nIf the value is not a JavaScript Number, it will be converted first.\n\nIf the value does not represent a finite integer, an *AQLError* will be thrown.\n\nIf the value is already an AQL Number or AQL Integer, its own value will be wrapped instead.\n\n*Alias:* `qb.int_(value)`\n\n#### String\n\nWraps the given value as an AQL String literal.\n\n`qb.str(value)`\n\nIf the value is not a JavaScript String, it will be converted first.\n\nIf the value is already an AQL String, its own value will be wrapped instead.\n\nIf the value is an object with a *toAQL* method, the result of calling that method will be wrapped instead.\n\n#### List\n\nWraps the given value as an AQL List (Array) literal.\n\n`qb.list(value)`\n\nIf the value is not a JavaScript Array, an *AQLError* will be thrown.\n\nIf the value is already an AQL List, its own value will be wrapped instead.\n\nAny list elements that are not already AQL values will be converted automatically.\n\n#### Object\n\nWraps the given value as an AQL Object literal.\n\n`qb.obj(value)`\n\nIf the value is not a JavaScript Object, an *AQLError* will be thrown.\n\nIf the value is already an AQL List, its own value will be wrapped instead.\n\nAny property values that are not already AQL values will be converted automatically.\n\n#### Simple Reference\n\nWraps a given value in an AQL Simple Reference.\n\n`qb.ref(value)`\n\nIf the value is not a JavaScript string or not a well-formed simple reference, an *AQLError* will be thrown.\n\nIf the value is an *ArangoCollection*, its *name* property will be used instead.\n\nIf the value is already an AQL Simple Reference, its value is wrapped instead.\n\n*Examples*\n\nValid values:\n\n* `foo`\n* `foo.bar`\n* `foo[*].bar`\n* `foo.bar.QUX`\n* `_foo._bar._qux`\n* `foo1.bar2`\n\nInvalid values:\n\n* `1foo`\n* `föö`\n* `foo bar`\n* `foo-bar`\n* `foo[bar]`\n\nArangoDB collection objects can be passed directly:\n\n```js\nvar myUserCollection = applicationContext.collection('users');\nvar users = db._query(qb.for('u').in(myUserCollection).return('u')).toArray();\n```\n\n### AQL Expressions\n\n#### Range\n\nCreates a range expression from the given values.\n\n`qb.range(value1, value2)` -> `value1..value2`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Property Access\n\nCreates a property access expression from the given values.\n\n`qb.get(obj, key)` -> `obj[key]`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Raw Expression\n\nWraps a given value in a raw AQL expression.\n\n`qb.expr(value)`\n\nIf the value is already an AQL Raw Expression, its value is wrapped instead.\n\n**Warning:** Whenever possible, you should use one of the other methods or a combination thereof instead of using a raw expression. Raw expressions allow passing arbitrary strings into your AQL and thus will open you to AQL injection attacks if you are passing in untrusted user input.\n\n### AQL Operations\n\n#### Boolean And\n\nCreates an \"and\" operation from the given values.\n\n`qb.and(a, b)` -> `(a && b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.and(a, b, c, d, e, f)` -> `(a && b && c && d && e && f)`\n\n#### Boolean Or\n\nCreates an \"or\" operation from the given values.\n\n`qb.or(a, b)` -> `(a || b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.or(a, b, c, d, e, f)` -> `(a || b || c || d || e || f)`\n\n#### Addition\n\nCreates an addition operation from the given values.\n\n`qb.add(a, b)` -> `(a + b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Alias:* `qb.plus(a, b)`\n\n*Examples*\n\n`qb.add(a, b, c, d, e, f)` -> `(a + b + c + d + e + f)`\n\n#### Subtraction\n\nCreates a subtraction operation from the given values.\n\n`qb.sub(a, b)` -> `(a - b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Alias:* `qb.minus(a, b)`\n\n*Examples*\n\n`qb.sub(a, b, c, d, e, f)` -> `(a - b - c - d - e - f)`\n\n#### Multiplication\n\nCreates a multiplication operation from the given values.\n\n`qb.mul(a, b)` -> `(a * b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Alias:* `qb.times(a, b)`\n\n*Examples*\n\n`qb.mul(a, b, c, d, e, f)` -> `(a * b * c * d * e * f)`\n\n#### Division\n\nCreates a division operation from the given values.\n\n`qb.div(a, b)` -> `(a / b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.div(a, b, c, d, e, f)` -> `(a / b / c / d / e / f)`\n\n#### Modulus\n\nCreates a modulus operation from the given values.\n\n`qb.mod(a, b)` -> `(a % b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.mod(a, b, c, d, e, f)` -> `(a % b % c % d % e % f)`\n\n#### Equality\n\nCreates an equality comparison from the given values.\n\n`qb.eq(a, b)` -> `(a == b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Inequality\n\nCreates an inequality comparison from the given values.\n\n`qb.neq(a, b)` -> `(a != b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Greater Than\n\nCreates a greater-than comparison from the given values.\n\n`qb.gt(a, b)` -> `(a > b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Greater Than Or Equal To\n\nCreates a greater-than-or-equal-to comparison from the given values.\n\n`qb.gte(a, b)` -> `(a >= b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Less Than\n\nCreates a less-than comparison from the given values.\n\n`qb.lt(a, b)` -> `(a < b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Less Than Or Equal To\n\nCreates a less-than-or-equal-to comparison from the given values.\n\n`qb.lte(a, b)` -> `(a <= b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n#### Contains\n\nCreates an \"in\" comparison from the given values.\n\n`qb.in(a, b)` -> `(a in b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n*Aliases:* `qb.in_(a, b)`\n\n#### Negation\n\nCreates a negation from the given value.\n\n`qb.not(a)` -> `!(a)`\n\nIf the value is not already an AQL value, it will be converted automatically.\n\n#### Negative Value\n\nCreates a negative value expression from the given value.\n\n`qb.neg(a)` -> `-(a)`\n\nIf the value is not already an AQL value, it will be converted automatically.\n\n#### Ternary (if / else)\n\nCreates a ternary expression from the given values.\n\n`qb.if(condition, then, otherwise)` -> `(condition ? then : otherwise)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n*Aliases:* `qb.if_(condition, then, otherwise)`\n\n#### Function Call\n\nCreates a function call for the given name and arguments.\n\n`qb.fn(name)(args…)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nFor built-in functions, methods with the relevant function name are already provided by the query builder.\n\n*Examples*\n\n* `qb.fn('MY::USER::FUNC')(1, 2, 3)` -> `MY::USER::FUNC(1, 2, 3)`\n* `qb.fn('hello')()` -> `hello()`\n* `qb.RANDOM()` -> `RANDOM()`\n* `qb.FLOOR(qb.div(5, 2))` -> `FLOOR((5 / 2))`\n\n### AQL Statements\n\nIn addition to the methods documented above, the query builder provides all methods of *PartialStatement* objects.\n\nAQL *Statement* objects have a method *toAQL()* which returns their AQL representation as a JavaScript string.\n\n*Examples*\n\n```\nqb.for('doc').in('my_collection').return('doc._key').toAQL()\n// -> FOR doc IN my_collection RETURN doc._key\n```\n\n#### FOR expression IN collection\n\n`PartialStatement::for(expression).in(collection) : Statement`\n\n*Alias:* `for_(expression).in_(collection)`\n\n#### LET varname = expression\n\n`PartialStatement::let(varname, expression) : Statement`\n\n*Alias:* `let_(varname, expression)`\n\n#### LET var1 = expr1, var2 = expr2, …, varn = exprn\n\n`PartialStatement::let(definitions) : Statement`\n\n*Alias:* `let_(definitions)`\n\n#### FILTER expression\n\n`PartialStatement::filter(expression) : Statement`\n\n#### COLLECT varname = expression\n\n`PartialStatement::collect(varname, expression) : Statement`\n\n#### COLLECT varname1 = expression INTO varname2\n\n`PartialStatement::collect(varname1, expression).into(varname2) : Statement`\n\n#### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn\n\n`PartialStatement::collect(definitions) : Statement`\n\n#### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn INTO varname\n\n`PartialStatement::collect(definitions).into(varname) : Statement`\n\n#### SORT args…\n\n`PartialStatement::sort(args…) : Statement`\n\n#### LIMIT offset, count\n\n`PartialStatement::limit([offset,] count) : Statement`\n\n#### RETURN expression\n\n`PartialStatement::return(expression) : Statement`\n\n*Alias:* `return_(expression)`\n\n#### REMOVE expression IN collection\n\n`PartialStatement::remove(expression).in(collection) : RemoveExpression`\n\n*Aliases:*\n\n* `remove(expression).in_(collection)`\n* `remove(expression).into(collection)`\n\n#### REMOVE … OPTIONS options\n\n`RemoveExpression::options(options) : Statement`\n\n#### INSERT expression INTO collection\n\n`PartialStatement::insert(expression).into(collection) : InsertExpression`\n\n*Aliases:*\n\n* `insert(expression).in(collection)`\n* `insert(expression).in_(collection)`\n\n#### INSERT … OPTIONS options\n\n`InsertExpression::options(options) : Statement`\n\n#### UPDATE expression1 WITH expression2 IN collection\n\n`PartialStatement::update(expression1).with(expression2).in(collection) : UpdateExpression`\n\n*Aliases:*\n\n* `update(expression1).with(expression2).in_(collection)`\n* `update(expression1).with(expression2).into(collection)`\n* `update(expression1).with_(expression2).in(collection)`\n* `update(expression1).with_(expression2).in_(collection)`\n* `update(expression1).with_(expression2).into(collection)`\n\n#### UPDATE expression IN collection\n\n`PartialStatement::update(expression).in(collection) : UpdateExpression`\n\n*Aliases:*\n\n* `update(expression).in_(collection)`\n* `update(expression).into(collection)`\n\n#### UPDATE … OPTIONS options\n\n`UpdateExpression::options(options) : Statement`\n\n#### REPLACE expression1 WITH expression2 IN collection\n\n`PartialStatement::replace(expression1).with(expression2).in(collection) : ReplaceExpression`\n\n*Aliases:*\n\n* `replace(expression1).with(expression2).in_(collection)`\n* `replace(expression1).with(expression2).into(collection)`\n* `replace(expression1).with_(expression2).in(collection)`\n* `replace(expression1).with_(expression2).in_(collection)`\n* `replace(expression1).with_(expression2).into(collection)`\n\n#### REPLACE expression IN collection\n\n`PartialStatement::replace(expression).in(collection) : ReplaceExpression`\n\n*Aliases:*\n\n* `replace(expression).in_(collection)`\n* `replace(expression).into(collection)`\n\n#### REPLACE … OPTIONS options\n\n`ReplaceExpression::options(options) : Statement`\n", - "readmeFilename": "README.md", - "homepage": "https://github.com/arangodb/aqbjs", - "_id": "aqb@1.4.1", - "dist": { - "shasum": "7fdd9f39bb51103f5915f135f8fc12a1d3826247" + "author": { + "name": "Alan Plum", + "email": "me@pluma.io" }, - "_from": "aqb@1.4.1", - "_resolved": "https://registry.npmjs.org/aqb/-/aqb-1.4.1.tgz" + "license": "APACHE-2.0", + "bugs": { + "url": "https://github.com/arangodb/aqbjs/issues" + }, + "homepage": "https://github.com/arangodb/aqbjs", + "devDependencies": { + "browserify": "^7.0.2", + "coveralls": "^2.11.2", + "dekeywordify": "^0.2.1", + "expect.js": "^0.3.1", + "istanbul": "^0.3.5", + "jshint": "^2.5.11", + "mocha": "^2.1.0", + "uglify-js": "^2.4.15" + }, + "dependencies": {}, + "readme": "# ArangoDB Query Builder\n\nThe query builder allows constructing complex AQL queries with a pure JavaScript fluid API.\n\n[![license - APACHE-2.0](https://img.shields.io/npm/l/aqb.svg)](http://opensource.org/licenses/APACHE-2.0) [![Dependencies](https://img.shields.io/david/arangodb/aqbjs.svg)](https://david-dm.org/arangodb/aqbjs)\n\n[![NPM status](https://nodei.co/npm/aqb.png?downloads=true&stars=true)](https://npmjs.org/package/aqb)\n\n[![Build status](https://img.shields.io/travis/arangodb/aqbjs.svg)](https://travis-ci.org/arangodb/aqbjs) [![Coverage Status](https://img.shields.io/coveralls/arangodb/aqbjs.svg)](https://coveralls.io/r/arangodb/aqbjs?branch=master) [![Codacy rating](https://img.shields.io/codacy/1d5a1be201024e0caaf0aa6bc990231e.svg)](https://www.codacy.com/public/me_4/aqbjs)\n\n# Install\n\n## With NPM\n\n```sh\nnpm install aqb\n```\n\n## With Bower\n\n```sh\nbower install aqb\n```\n\n## ArangoDB\n\nAs of ArangoDB 1.3, a version of `aqb` comes pre-installed with ArangoDB.\n\n```js\nvar qb = require('aqb');\n```\n\nIf you want to use a more recent version of `aqb` in a Foxx app, you can add it to your NPM dependencies as usual.\n\n## Browser\n\nThis CommonJS module is compatible with [browserify](http://browserify.org).\n\nIf you don't want to use browserify, you can simply use the AMD-compatible [browserify bundle](https://raw.githubusercontent.com/arangodb/aqbjs/master/dist/aqb.min.js) (~30 kB minified, ~6 kB gzipped).\n\nIf you want to use this module in non-ES5 browsers like Microsoft Internet Explorer 8 and earlier, you may need to include [es5-shim](https://www.npmjs.com/package/es5-shim) or a similar ES5 polyfill.\n\n## From source\n\n```sh\ngit clone https://github.com/arangodb/aqbjs.git\ncd aqbjs\nnpm install\nnpm run dist\n```\n\n# Example\n\n```js\n// in arangosh\nvar db = require('org/arangodb').db;\nvar qb = require('aqb');\nconsole.log(db._query(qb.for('x').in('1..5').return('x')).toArray()); // [1, 2, 3, 4, 5]\n```\n\n# API\n\n## AQL Types\n\nIf raw JavaScript values are passed to AQL statements, they will be wrapped in a matching AQL type automatically.\n\nJavaScript strings wrapped in quotation marks will be wrapped in AQL strings, all other JavaScript strings will be wrapped as simple references (see below) and throw an *AQLError* if they are not well-formed.\n\n### Boolean\n\nWraps the given value as an AQL Boolean literal.\n\n`qb.bool(value)`\n\nIf the value is truthy, it will be converted to the AQL Boolean *true*, otherwise it will be converted to the AQL Boolean *false*.\n\nIf the value is already an AQL Boolean, its own value will be wrapped instead.\n\n### Number\n\nWraps the given value as an AQL Number literal.\n\n`qb.num(value)`\n\nIf the value is not a JavaScript Number, it will be converted first.\n\nIf the value does not represent a finite number, an *AQLError* will be thrown.\n\nIf the value is already an AQL Number or AQL Integer, its own value will be wrapped instead.\n\n### Integer\n\nWraps the given value as an AQL Integer literal.\n\n`qb.int(value)`\n\nIf the value is not a JavaScript Number, it will be converted first.\n\nIf the value does not represent a finite integer, an *AQLError* will be thrown.\n\nIf the value is already an AQL Number or AQL Integer, its own value will be wrapped instead.\n\n*Alias:* `qb.int_(value)`\n\n### String\n\nWraps the given value as an AQL String literal.\n\n`qb.str(value)`\n\nIf the value is not a JavaScript String, it will be converted first.\n\nIf the value is already an AQL String, its own value will be wrapped instead.\n\nIf the value is an object with a *toAQL* method, the result of calling that method will be wrapped instead.\n\n### List\n\nWraps the given value as an AQL List (Array) literal.\n\n`qb.list(value)`\n\nIf the value is not a JavaScript Array, an *AQLError* will be thrown.\n\nIf the value is already an AQL List, its own value will be wrapped instead.\n\nAny list elements that are not already AQL values will be converted automatically.\n\n### Object\n\nWraps the given value as an AQL Object literal.\n\n`qb.obj(value)`\n\nIf the value is not a JavaScript Object, an *AQLError* will be thrown.\n\nIf the value is already an AQL List, its own value will be wrapped instead.\n\nAny property values that are not already AQL values will be converted automatically.\n\n### Simple Reference\n\nWraps a given value in an AQL Simple Reference.\n\n`qb.ref(value)`\n\nIf the value is not a JavaScript string or not a well-formed simple reference, an *AQLError* will be thrown.\n\nIf the value is an *ArangoCollection*, its *name* property will be used instead.\n\nIf the value is already an AQL Simple Reference, its value is wrapped instead.\n\n*Examples*\n\nValid values:\n\n* `foo`\n* `foo.bar`\n* `foo[*].bar`\n* `foo.bar.QUX`\n* `_foo._bar._qux`\n* `foo1.bar2`\n\nInvalid values:\n\n* `1foo`\n* `föö`\n* `foo bar`\n* `foo-bar`\n* `foo[bar]`\n\nArangoDB collection objects can be passed directly:\n\n```js\nvar myUserCollection = applicationContext.collection('users');\nvar users = db._query(qb.for('u').in(myUserCollection).return('u')).toArray();\n```\n\n## AQL Expressions\n\n### Range\n\nCreates a range expression from the given values.\n\n`qb.range(value1, value2)` -> `value1..value2`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Property Access\n\nCreates a property access expression from the given values.\n\n`qb.get(obj, key)` -> `obj[key]`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Raw Expression\n\nWraps a given value in a raw AQL expression.\n\n`qb.expr(value)`\n\nIf the value is already an AQL Raw Expression, its value is wrapped instead.\n\n**Warning:** Whenever possible, you should use one of the other methods or a combination thereof instead of using a raw expression. Raw expressions allow passing arbitrary strings into your AQL and thus will open you to AQL injection attacks if you are passing in untrusted user input.\n\n## AQL Operations\n\n### Boolean And\n\nCreates an \"and\" operation from the given values.\n\n`qb.and(a, b)` -> `(a && b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.and(a, b, c, d, e, f)` -> `(a && b && c && d && e && f)`\n\n### Boolean Or\n\nCreates an \"or\" operation from the given values.\n\n`qb.or(a, b)` -> `(a || b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.or(a, b, c, d, e, f)` -> `(a || b || c || d || e || f)`\n\n### Addition\n\nCreates an addition operation from the given values.\n\n`qb.add(a, b)` -> `(a + b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Alias:* `qb.plus(a, b)`\n\n*Examples*\n\n`qb.add(a, b, c, d, e, f)` -> `(a + b + c + d + e + f)`\n\n### Subtraction\n\nCreates a subtraction operation from the given values.\n\n`qb.sub(a, b)` -> `(a - b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Alias:* `qb.minus(a, b)`\n\n*Examples*\n\n`qb.sub(a, b, c, d, e, f)` -> `(a - b - c - d - e - f)`\n\n### Multiplication\n\nCreates a multiplication operation from the given values.\n\n`qb.mul(a, b)` -> `(a * b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Alias:* `qb.times(a, b)`\n\n*Examples*\n\n`qb.mul(a, b, c, d, e, f)` -> `(a * b * c * d * e * f)`\n\n### Division\n\nCreates a division operation from the given values.\n\n`qb.div(a, b)` -> `(a / b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.div(a, b, c, d, e, f)` -> `(a / b / c / d / e / f)`\n\n### Modulus\n\nCreates a modulus operation from the given values.\n\n`qb.mod(a, b)` -> `(a % b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nThis function can take any number of arguments.\n\n*Examples*\n\n`qb.mod(a, b, c, d, e, f)` -> `(a % b % c % d % e % f)`\n\n### Equality\n\nCreates an equality comparison from the given values.\n\n`qb.eq(a, b)` -> `(a == b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Inequality\n\nCreates an inequality comparison from the given values.\n\n`qb.neq(a, b)` -> `(a != b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Greater Than\n\nCreates a greater-than comparison from the given values.\n\n`qb.gt(a, b)` -> `(a > b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Greater Than Or Equal To\n\nCreates a greater-than-or-equal-to comparison from the given values.\n\n`qb.gte(a, b)` -> `(a >= b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Less Than\n\nCreates a less-than comparison from the given values.\n\n`qb.lt(a, b)` -> `(a < b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Less Than Or Equal To\n\nCreates a less-than-or-equal-to comparison from the given values.\n\n`qb.lte(a, b)` -> `(a <= b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n### Contains\n\nCreates an \"in\" comparison from the given values.\n\n`qb.in(a, b)` -> `(a in b)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n*Aliases:* `qb.in_(a, b)`\n\n### Negation\n\nCreates a negation from the given value.\n\n`qb.not(a)` -> `!(a)`\n\nIf the value is not already an AQL value, it will be converted automatically.\n\n### Negative Value\n\nCreates a negative value expression from the given value.\n\n`qb.neg(a)` -> `-(a)`\n\nIf the value is not already an AQL value, it will be converted automatically.\n\n### Ternary (if / else)\n\nCreates a ternary expression from the given values.\n\n`qb.if(condition, then, otherwise)` -> `(condition ? then : otherwise)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\n*Aliases:* `qb.if_(condition, then, otherwise)`\n\n### Function Call\n\nCreates a function call for the given name and arguments.\n\n`qb.fn(name)(args…)`\n\nIf the values are not already AQL values, they will be converted automatically.\n\nFor built-in functions, methods with the relevant function name are already provided by the query builder.\n\n*Examples*\n\n* `qb.fn('MY::USER::FUNC')(1, 2, 3)` -> `MY::USER::FUNC(1, 2, 3)`\n* `qb.fn('hello')()` -> `hello()`\n* `qb.RANDOM()` -> `RANDOM()`\n* `qb.FLOOR(qb.div(5, 2))` -> `FLOOR((5 / 2))`\n\n## AQL Statements\n\nIn addition to the methods documented above, the query builder provides all methods of *PartialStatement* objects.\n\nAQL *Statement* objects have a method *toAQL()* which returns their AQL representation as a JavaScript string.\n\n*Examples*\n\n```\nqb.for('doc').in('my_collection').return('doc._key').toAQL()\n// -> FOR doc IN my_collection RETURN doc._key\n```\n\n### FOR expression IN collection\n\n`PartialStatement::for(expression).in(collection) : Statement`\n\n*Alias:* `for_(expression).in_(collection)`\n\n### LET varname = expression\n\n`PartialStatement::let(varname, expression) : Statement`\n\n*Alias:* `let_(varname, expression)`\n\n### LET var1 = expr1, var2 = expr2, …, varn = exprn\n\n`PartialStatement::let(definitions) : Statement`\n\n*Alias:* `let_(definitions)`\n\n### FILTER expression\n\n`PartialStatement::filter(expression) : Statement`\n\n### COLLECT varname = expression\n\n`PartialStatement::collect(varname, expression) : Statement`\n\n### COLLECT varname1 = expression INTO varname2\n\n`PartialStatement::collect(varname1, expression).into(varname2) : Statement`\n\n### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn\n\n`PartialStatement::collect(definitions) : Statement`\n\n### COLLECT var1 = expr1, var2 = expr2, …, varn = exprn INTO varname\n\n`PartialStatement::collect(definitions).into(varname) : Statement`\n\n### SORT args…\n\n`PartialStatement::sort(args…) : Statement`\n\n### LIMIT offset, count\n\n`PartialStatement::limit([offset,] count) : Statement`\n\n### RETURN expression\n\n`PartialStatement::return(expression) : Statement`\n\n*Alias:* `return_(expression)`\n\n### REMOVE expression IN collection\n\n`PartialStatement::remove(expression).in(collection) : RemoveExpression`\n\n*Aliases:*\n\n* `remove(expression).in_(collection)`\n* `remove(expression).into(collection)`\n\n### REMOVE … OPTIONS options\n\n`RemoveExpression::options(options) : Statement`\n\n### INSERT expression INTO collection\n\n`PartialStatement::insert(expression).into(collection) : InsertExpression`\n\n*Aliases:*\n\n* `insert(expression).in(collection)`\n* `insert(expression).in_(collection)`\n\n### INSERT … OPTIONS options\n\n`InsertExpression::options(options) : Statement`\n\n### UPDATE expression1 WITH expression2 IN collection\n\n`PartialStatement::update(expression1).with(expression2).in(collection) : UpdateExpression`\n\n*Aliases:*\n\n* `update(expression1).with(expression2).in_(collection)`\n* `update(expression1).with(expression2).into(collection)`\n* `update(expression1).with_(expression2).in(collection)`\n* `update(expression1).with_(expression2).in_(collection)`\n* `update(expression1).with_(expression2).into(collection)`\n\n### UPDATE expression IN collection\n\n`PartialStatement::update(expression).in(collection) : UpdateExpression`\n\n*Aliases:*\n\n* `update(expression).in_(collection)`\n* `update(expression).into(collection)`\n\n### UPDATE … OPTIONS options\n\n`UpdateExpression::options(options) : Statement`\n\n### REPLACE expression1 WITH expression2 IN collection\n\n`PartialStatement::replace(expression1).with(expression2).in(collection) : ReplaceExpression`\n\n*Aliases:*\n\n* `replace(expression1).with(expression2).in_(collection)`\n* `replace(expression1).with(expression2).into(collection)`\n* `replace(expression1).with_(expression2).in(collection)`\n* `replace(expression1).with_(expression2).in_(collection)`\n* `replace(expression1).with_(expression2).into(collection)`\n\n### REPLACE expression IN collection\n\n`PartialStatement::replace(expression).in(collection) : ReplaceExpression`\n\n*Aliases:*\n\n* `replace(expression).in_(collection)`\n* `replace(expression).into(collection)`\n\n### REPLACE … OPTIONS options\n\n`ReplaceExpression::options(options) : Statement`\n\n# License\n\nThe Apache License, Version 2.0. For more information, see the accompanying LICENSE file.\n", + "readmeFilename": "README.md", + "gitHead": "56c20faadce7aaee49a87aa8089d29148f142a6c", + "_id": "aqb@1.5.1", + "_shasum": "0e4fd5b0bf0597003a6da8cae7ad19b212fd95dd", + "_from": "aqb@1.5.1" } diff --git a/js/node/node_modules/aqb/types.js b/js/node/node_modules/aqb/types.js index bedc7cb14e..e89f07e2ee 100644 --- a/js/node/node_modules/aqb/types.js +++ b/js/node/node_modules/aqb/types.js @@ -1,8 +1,7 @@ -/* jshint globalstrict: true, es3: true */ -/* globals require: false, exports: false */ +/*jshint browserify: true */ 'use strict'; -var AqlError = require('./errors').AqlError, - keywords = require('./assumptions').keywords; +var AqlError = require('./errors').AqlError; +var keywords = require('./assumptions').keywords; function wrapAQL(expr) { if ( @@ -15,50 +14,69 @@ function wrapAQL(expr) { return expr.toAQL(); } +function isValidNumber(number) { + return ( + number === number && + number !== Infinity && + number !== -Infinity + ); +} + +function castNumber(number) { + if (Math.floor(number) === number) { + return new IntegerLiteral(number); + } + return new NumberLiteral(number); +} + +function castBoolean(bool) { + return new BooleanLiteral(bool); +} + +function castString(str) { + if (str.match(NumberLiteral.re)) { + return autoCastToken(Number(str)); + } + if (str.charAt(0) === '"') { + return new StringLiteral(JSON.parse(str)); + } + var match = str.match(RangeExpression.re); + if (match) { + return new RangeExpression(Number(match[1]), Number(match[2])); + } + if (str.match(Identifier.re)) { + return new Identifier(str); + } + return new SimpleReference(str); +} + +function castObject(obj) { + if (obj.constructor && obj.constructor.name === 'ArangoCollection') { + return new Identifier(obj.name()); + } + if (Array.isArray(obj)) { + return new ListLiteral(obj); + } + return new ObjectLiteral(obj); +} + function autoCastToken(token) { - var match; if (token === null || token === undefined) { return new NullLiteral(); } if (token instanceof Expression || token instanceof PartialStatement) { return token; } - if (typeof token === 'number' && token === token && token !== Infinity && token !== -Infinity) { - if (Math.floor(token) === token) { - return new IntegerLiteral(token); - } - return new NumberLiteral(token); + var type = typeof token; + if (Object.keys(autoCastToken).indexOf(type) === -1) { + throw new AqlError('Invalid AQL value: (' + type + ') ' + token); } - if (typeof token === 'boolean') { - return new BooleanLiteral(token); - } - if (typeof token === 'string') { - if (token.match(/^[-+]?[0-9]+(\.[0-9]+)?$/)) { - return autoCastToken(Number(token)); - } - if (token.charAt(0) === '"') { - return new StringLiteral(JSON.parse(token)); - } - match = token.match(/^([0-9]+)\.\.([0-9]+)$/); - if (match) { - return new RangeExpression(Number(match[1]), Number(match[2])); - } - if (token.match(Identifier.re)) { - return new Identifier(token); - } - return new SimpleReference(token); - } - if (typeof token === 'object') { - if (token.constructor && token.constructor.name === 'ArangoCollection') { - return new Identifier(token.name()); - } - if (Object.prototype.toString.call(token) === '[object Array]') { - return new ListLiteral(token); - } - return new ObjectLiteral(token); - } - throw new AqlError('Invalid AQL value: (' + (typeof token) + ') ' + token); + return autoCastToken[type](token); } +autoCastToken.number = castNumber; +autoCastToken.boolean = castBoolean; +autoCastToken.string = castString; +autoCastToken.object = castObject; function Expression() {} function Operation() {} @@ -98,10 +116,11 @@ function NumberLiteral(value) { value instanceof IntegerLiteral )) {value = value.value;} this.value = Number(value); - if (this.value !== this.value || this.value === Infinity) { + if (!isValidNumber(this.value)) { throw new AqlError('Expected value to be a finite number: ' + value); } } +NumberLiteral.re = /^[-+]?[0-9]+(\.[0-9]+)?$/; NumberLiteral.prototype = new Expression(); NumberLiteral.prototype.constructor = NumberLiteral; NumberLiteral.prototype.toAQL = function () {return String(this.value);}; @@ -112,7 +131,7 @@ function IntegerLiteral(value) { value instanceof IntegerLiteral )) {value = value.value;} this.value = Number(value); - if (this.value !== this.value || this.value === Infinity || Math.floor(this.value) !== this.value) { + if (!isValidNumber(this.value) || Math.floor(this.value) !== this.value) { throw new AqlError('Expected value to be a finite integer: ' + value); } } @@ -131,21 +150,15 @@ StringLiteral.prototype.toAQL = function () {return JSON.stringify(this.value);} function ListLiteral(value) { if (value && value instanceof ListLiteral) {value = value.value;} - if (!value || Object.prototype.toString.call(value) !== '[object Array]') { + if (!value || !Array.isArray(value)) { throw new AqlError('Expected value to be an array: ' + value); } - this.value = []; - for (var i = 0; i < value.length; i++) { - this.value[i] = autoCastToken(value[i]); - } + this.value = value.map(autoCastToken); } ListLiteral.prototype = new Expression(); ListLiteral.prototype.constructor = ListLiteral; ListLiteral.prototype.toAQL = function () { - var value = [], i; - for (i = 0; i < this.value.length; i++) { - value.push(wrapAQL(this.value[i])); - } + var value = this.value.map(wrapAQL); return '[' + value.join(', ') + ']'; }; @@ -155,25 +168,22 @@ function ObjectLiteral(value) { throw new AqlError('Expected value to be an object: ' + value); } this.value = {}; - for (var key in value) { - if (value.hasOwnProperty(key)) { - this.value[key] = autoCastToken(value[key]); - } - } + var self = this; + Object.keys(value).forEach(function (key) { + self.value[key] = autoCastToken(value[key]); + }); } ObjectLiteral.prototype = new Expression(); ObjectLiteral.prototype.constructor = ObjectLiteral; ObjectLiteral.prototype.toAQL = function () { - var items = [], key; - for (key in this.value) { - if (this.value.hasOwnProperty(key)) { - if (key.match(Identifier.re) || key === String(Number(key))) { - items.push(key + ': ' + wrapAQL(this.value[key])); - } else { - items.push(JSON.stringify(key) + ': ' + wrapAQL(this.value[key])); - } + var value = this.value; + var items = Object.keys(value).map(function (key) { + if (key.match(Identifier.re) || key === String(Number(key))) { + return key + ': ' + wrapAQL(value[key]); + } else { + return JSON.stringify(key) + ': ' + wrapAQL(value[key]); } - } + }); return '{' + items.join(', ') + '}'; }; @@ -181,6 +191,7 @@ function RangeExpression(start, end) { this.start = autoCastToken(start); this.end = autoCastToken(end); } +RangeExpression.re = /^([0-9]+)\.\.([0-9]+)$/; RangeExpression.prototype = new Expression(); RangeExpression.prototype.constructor = RangeExpression; RangeExpression.prototype.toAQL = function () { @@ -224,7 +235,7 @@ function Identifier(value) { } this.value = value; } -Identifier.re = /^[_a-z][_0-9a-z]*$/i; +Identifier.re = /^[_a-z][-_0-9a-z]*$/i; Identifier.prototype = new Expression(); Identifier.prototype.constructor = Identifier; Identifier.prototype.toAQL = function () { @@ -249,14 +260,10 @@ SimpleReference.re = /^@{0,2}[_a-z][_0-9a-z]*(\.[_a-z][_0-9a-z]*|\[\*\])*$/i; SimpleReference.prototype = new Expression(); SimpleReference.prototype.constructor = SimpleReference; SimpleReference.prototype.toAQL = function () { - var value = String(this.value), - tokens = value.split('.'), - i; - for (i = 0; i < tokens.length; i++) { - if (keywords.indexOf(tokens[i]) !== -1) { - tokens[i] = '`' + tokens[i] + '`'; - } - } + var value = String(this.value); + var tokens = value.split('.').map(function (token) { + return keywords.indexOf(token) === -1 ? token : '`' + token + '`'; + }); return tokens.join('.'); }; @@ -317,18 +324,12 @@ function NAryOperation(operator, values) { throw new AqlError('Expected operator to be a string: ' + operator); } this.operator = operator; - this.values = []; - for (var i = 0; i < values.length; i++) { - this.values.push(autoCastToken(values[i])); - } + this.values = values.map(autoCastToken); } NAryOperation.prototype = new Operation(); NAryOperation.prototype.constructor = NAryOperation; NAryOperation.prototype.toAQL = function () { - var values = [], i; - for (i = 0; i < this.values.length; i++) { - values.push(wrapAQL(this.values[i])); - } + var values = this.values.map(wrapAQL); return values.join(' ' + this.operator + ' '); }; @@ -339,30 +340,22 @@ function FunctionCall(functionName, args) { if (!functionName.match(FunctionCall.re)) { throw new AqlError('Not a valid function name: ' + functionName); } - if (args && Object.prototype.toString.call(args) !== '[object Array]') { + if (args && !Array.isArray(args)) { throw new AqlError('Expected arguments to be an array: ' + args); } this.functionName = functionName; - this.args = []; - if (args) { - for (var i = 0; i < args.length; i++) { - this.args[i] = autoCastToken(args[i]); - } - } + this.args = args ? args.map(autoCastToken) : []; } FunctionCall.re = /^[_a-z][_0-9a-z]*(::[_a-z][_0-9a-z]*)*$/i; FunctionCall.prototype = new Expression(); FunctionCall.prototype.constructor = FunctionCall; FunctionCall.prototype.toAQL = function () { - var args = [], i; - for (i = 0; i < this.args.length; i++) { - args.push(wrapAQL(this.args[i])); - } + var args = this.args.map(wrapAQL); return this.functionName + '(' + args.join(', ') + ')'; }; function PartialStatement() {} -PartialStatement.prototype.for_ = function (varname) { +PartialStatement.prototype.for = function (varname) { var self = this, inFn; inFn = function (expr) { // assert expr is an expression @@ -371,7 +364,7 @@ PartialStatement.prototype.for_ = function (varname) { return {'in': inFn, in_: inFn}; }; PartialStatement.prototype.filter = function (expr) {return new FilterExpression(this, expr);}; -PartialStatement.prototype.let_ = function (varname, expr) { +PartialStatement.prototype.let = function (varname, expr) { if (expr === undefined) { return new LetExpression(this, varname); } @@ -388,7 +381,7 @@ PartialStatement.prototype.sort = function () { return new SortExpression(this, args); }; PartialStatement.prototype.limit = function (x, y) {return new LimitExpression(this, x, y);}; -PartialStatement.prototype.return_ = function (x) {return new ReturnExpression(this, x);}; +PartialStatement.prototype.return = function (x) {return new ReturnExpression(this, x);}; PartialStatement.prototype.remove = function (expr) { var self = this, inFn; inFn = function (collection) { @@ -430,42 +423,39 @@ PartialStatement.prototype.replace = function (expr) { return {'with': withFn, with_: withFn, into: inFn, 'in': inFn, in_: inFn}; }; -PartialStatement.prototype['for'] = PartialStatement.prototype.for_; -PartialStatement.prototype['let'] = PartialStatement.prototype.let_; -PartialStatement.prototype['return'] = PartialStatement.prototype.return_; +PartialStatement.prototype.for_ = PartialStatement.prototype.for; +PartialStatement.prototype.let_ = PartialStatement.prototype.let; +PartialStatement.prototype.return_ = PartialStatement.prototype.return; function Definitions(dfns) { if (dfns instanceof Definitions) { dfns = dfns.dfns; } this.dfns = []; + var self = this; if (!dfns || typeof dfns !== 'object') { throw new AqlError('Expected definitions to be an object'); } - if (Object.prototype.toString.call(dfns) === '[object Array]') { - for (var i = 0; i < dfns.length; i++) { - if (Object.prototype.toString.call(dfns[i]) !== '[object Array]' || dfns[i].length !== 2) { + if (Array.isArray(dfns)) { + dfns.forEach(function (dfn, i) { + if (!Array.isArray(dfn) || dfn.length !== 2) { throw new AqlError('Expected definitions[' + i + '] to be a tuple'); } - this.dfns.push([new Identifier(dfns[i][0]), autoCastToken(dfns[i][1])]); - } + self.dfns.push([new Identifier(dfn[0]), autoCastToken(dfn[1])]); + }); } else { - for (var key in dfns) { - if (dfns.hasOwnProperty(key)) { - this.dfns.push([new Identifier(key), autoCastToken(dfns[key])]); - } - } + Object.keys(dfns).forEach(function (key) { + self.dfns.push([new Identifier(key), autoCastToken(dfns[key])]); + }); } if (this.dfns.length === 0) { throw new AqlError('Expected definitions not to be empty'); } } Definitions.prototype.toAQL = function () { - var dfns = []; - for (var i = 0; i < this.dfns.length; i++) { - dfns.push(this.dfns[i][0].toAQL() + ' = ' + wrapAQL(this.dfns[i][1])); - } - return dfns.join(', '); + return this.dfns.map(function (dfn) { + return dfn[0].toAQL() + ' = ' + wrapAQL(dfn[1]); + }).join(', '); }; function ForExpression(prev, varname, expr) { @@ -541,7 +531,7 @@ CollectIntoExpression.prototype.toAQL = function () { }; function SortExpression(prev, args) { - if (!args || Object.prototype.toString.call(args) !== '[object Array]') { + if (!args || !Array.isArray(args)) { throw new AqlError('Expected sort list to be an array: ' + args); } if (!args.length) { @@ -549,37 +539,36 @@ function SortExpression(prev, args) { } this.prev = prev; this.args = []; - var allowKeyword = false, i, value; - for (i = 0; i < args.length; i++) { - value = args[i]; - if (!allowKeyword && value) { - if (value instanceof Keyword || ( - typeof value === 'string' && SortExpression.keywords.indexOf(value.toUpperCase()) !== -1 + var allowKeyword = false; + this.args = args.map(function (arg, i) { + if (!allowKeyword && arg) { + if (arg instanceof Keyword || ( + typeof arg === 'string' && SortExpression.keywords.indexOf(arg.toUpperCase()) !== -1 )) { - throw new AqlError('Unexpected keyword ' + value.toString() + ' at offset ' + i); + throw new AqlError('Unexpected keyword ' + arg.toString() + ' at offset ' + i); } } - if (typeof value === 'string' && SortExpression.keywords.indexOf(value.toUpperCase()) !== -1) { - this.args[i] = new Keyword(value); + if (typeof arg === 'string' && SortExpression.keywords.indexOf(arg.toUpperCase()) !== -1) { allowKeyword = false; + return new Keyword(arg); } else { - this.args[i] = autoCastToken(value); allowKeyword = true; + return autoCastToken(arg); } - } + }); } SortExpression.keywords = ['ASC', 'DESC']; SortExpression.prototype = new PartialStatement(); SortExpression.prototype.constructor = SortExpression; SortExpression.prototype.toAQL = function () { var args = [], j = 0; - for (var i = 0; i < this.args.length; i++) { - if (this.args[i] instanceof Keyword) { - args[j] += ' ' + this.args[i].toAQL(); + this.args.forEach(function (arg, i) { + if (arg instanceof Keyword) { + args[j] += ' ' + arg.toAQL(); } else { - j = args.push(wrapAQL(this.args[i])) - 1; + j = args.push(wrapAQL(arg)) - 1; } - } + }); return ( (this.prev ? this.prev.toAQL() + ' ' : '') + 'SORT ' + diff --git a/js/node/package.json b/js/node/package.json index 2acdf5af32..712150ed08 100644 --- a/js/node/package.json +++ b/js/node/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "aqb": "1.4.1", + "aqb": "1.5.1", "buster-format": "0.5.6", "cheerio": "0.17.0", "coffee-script": "1.7.1", diff --git a/lib/Basics/errors.dat b/lib/Basics/errors.dat index de600a6f76..8e0b31580b 100755 --- a/lib/Basics/errors.dat +++ b/lib/Basics/errors.dat @@ -181,6 +181,7 @@ ERROR_CLUSTER_ONLY_ON_COORDINATOR,1471,"this operation is only valid on a coordi ERROR_CLUSTER_READING_PLAN_AGENCY,1472,"error reading Plan in agency","Will be raised if a coordinator or DBserver cannot read the Plan in the agency." ERROR_CLUSTER_COULD_NOT_TRUNCATE_COLLECTION,1473,"could not truncate collection","Will be raised if a coordinator cannot truncate all shards of a cluster collection." ERROR_CLUSTER_AQL_COMMUNICATION,1474,"error in cluster internal communication for AQL","Will be raised if the internal communication of the cluster for AQL produces an error." +ERROR_ARANGO_DOCUMENT_NOT_FOUND_OR_SHARDING_ATTRIBUTES_CHANGED,1475,"document not found or sharding attributes changed","Will be raised when a document with a given identifier or handle is unknown, or if the sharding attributes have been changed in a REPLACE operation in the cluster." ################################################################################ ## ArangoDB query errors diff --git a/lib/Basics/voc-errors.cpp b/lib/Basics/voc-errors.cpp index a6f9083678..64400b0186 100644 --- a/lib/Basics/voc-errors.cpp +++ b/lib/Basics/voc-errors.cpp @@ -141,6 +141,7 @@ void TRI_InitialiseErrorMessages () { REG_ERROR(ERROR_CLUSTER_READING_PLAN_AGENCY, "error reading Plan in agency"); REG_ERROR(ERROR_CLUSTER_COULD_NOT_TRUNCATE_COLLECTION, "could not truncate collection"); REG_ERROR(ERROR_CLUSTER_AQL_COMMUNICATION, "error in cluster internal communication for AQL"); + REG_ERROR(ERROR_ARANGO_DOCUMENT_NOT_FOUND_OR_SHARDING_ATTRIBUTES_CHANGED, "document not found or sharding attributes changed"); REG_ERROR(ERROR_QUERY_KILLED, "query killed"); REG_ERROR(ERROR_QUERY_PARSE, "%s"); REG_ERROR(ERROR_QUERY_EMPTY, "query is empty"); diff --git a/lib/Basics/voc-errors.h b/lib/Basics/voc-errors.h index ca80a4d753..58736639d3 100644 --- a/lib/Basics/voc-errors.h +++ b/lib/Basics/voc-errors.h @@ -344,6 +344,10 @@ /// - 1474: @LIT{error in cluster internal communication for AQL} /// Will be raised if the internal communication of the cluster for AQL /// produces an error. +/// - 1475: @LIT{document not found or sharding attributes changed} +/// Will be raised when a document with a given identifier or handle is +/// unknown, or if the sharding attributes have been changed in a REPLACE +/// operation in the cluster. /// - 1500: @LIT{query killed} /// Will be raised when a running query is killed by an explicit admin /// command. @@ -2018,6 +2022,18 @@ void TRI_InitialiseErrorMessages (); #define TRI_ERROR_CLUSTER_AQL_COMMUNICATION (1474) +//////////////////////////////////////////////////////////////////////////////// +/// @brief 1475: ERROR_ARANGO_DOCUMENT_NOT_FOUND_OR_SHARDING_ATTRIBUTES_CHANGED +/// +/// document not found or sharding attributes changed +/// +/// Will be raised when a document with a given identifier or handle is +/// unknown, or if the sharding attributes have been changed in a REPLACE +/// operation in the cluster. +//////////////////////////////////////////////////////////////////////////////// + +#define TRI_ERROR_ARANGO_DOCUMENT_NOT_FOUND_OR_SHARDING_ATTRIBUTES_CHANGED (1475) + //////////////////////////////////////////////////////////////////////////////// /// @brief 1500: ERROR_QUERY_KILLED ///