diff --git a/Documentation/Books/Users/book.epub b/Documentation/Books/Users/book.epub deleted file mode 100644 index f456452636..0000000000 Binary files a/Documentation/Books/Users/book.epub and /dev/null differ diff --git a/Documentation/Books/Users/localtheme/templates/includes/book/header.html b/Documentation/Books/Users/localtheme/templates/includes/book/header.html index d2076a60ce..f7afe2f95c 100644 --- a/Documentation/Books/Users/localtheme/templates/includes/book/header.html +++ b/Documentation/Books/Users/localtheme/templates/includes/book/header.html @@ -14,5 +14,5 @@ {% endif %} -

ArangoDB2.2.3

+

ArangoDBVERSION_NUMBER

\ No newline at end of file diff --git a/Documentation/Books/Users/localtheme/templates/includes/book/summary.html b/Documentation/Books/Users/localtheme/templates/includes/book/summary.html index 2d8677b537..855dd9eff5 100644 --- a/Documentation/Books/Users/localtheme/templates/includes/book/summary.html +++ b/Documentation/Books/Users/localtheme/templates/includes/book/summary.html @@ -50,11 +50,11 @@ {% if options.links.gitbook !== false %}
  • - Have any Issues? - Have any questions? + Have any issues? + Have any questions?
  • - Whats New? + Whats new in the latest version?
  • {% endif %}
  • diff --git a/Documentation/Books/deprecated.py b/Documentation/Books/deprecated.py index 8cb60d720a..e723c0111d 100644 --- a/Documentation/Books/deprecated.py +++ b/Documentation/Books/deprecated.py @@ -2,15 +2,15 @@ import sys import re import os -def walk_on_files(dirpath): +def walk_on_files(dirpath, newVersionNumber): for root, dirs, files in os.walk(dirpath): for file in files: if file.endswith(".html"): full_path= os.path.join(root, file) - replaceCode(full_path) + replaceCode(full_path, newVersionNumber) return -def replaceCode(pathOfFile): +def replaceCode(pathOfFile, newVersionNumber): f=open(pathOfFile,"rU") if f: s=f.read() @@ -27,12 +27,17 @@ def replaceCode(pathOfFile): lines = lines.replace("","") lines = lines.replace("","") lines = lines.replace("","") + lines = lines.replace("VERSION_NUMBER", newVersionNumber) f.write(lines) f.close() if __name__ == '__main__': path = ["Documentation/Books/books/Users"] + g = open(os.path.abspath(os.path.join(os.path.dirname( __file__ ), os.pardir, "ArangoDB/../../VERSION"))) + if g: + newVersionNumber=g.read() + g.close for i in path: dirpath = os.path.abspath(os.path.join(os.path.dirname( __file__ ), os.pardir,"ArangoDB/../../"+i)) print "Tagging deprecated files" - walk_on_files(dirpath) \ No newline at end of file + walk_on_files(dirpath, newVersionNumber) \ No newline at end of file diff --git a/arangod/Aql/Collection.cpp b/arangod/Aql/Collection.cpp index 0e4fd5861e..64789d9714 100644 --- a/arangod/Aql/Collection.cpp +++ b/arangod/Aql/Collection.cpp @@ -81,6 +81,7 @@ Collection::~Collection () { size_t Collection::count () const { if (numDocuments == UNINITIALIZED) { if (ExecutionEngine::isCoordinator()) { + // cluster case uint64_t result; int res = triagens::arango::countOnCoordinator(vocbase->_name, name, result); if (res != TRI_ERROR_NO_ERROR) { @@ -89,6 +90,7 @@ size_t Collection::count () const { numDocuments = static_cast(result); } else { + // local case auto document = documentCollection(); // cache the result numDocuments = static_cast(document->size(document)); @@ -214,14 +216,45 @@ void Collection::fillIndexes () const { } TRI_json_t const* json = (*collectionInfo).getIndexes(); - size_t const n = document->_allIndexes._length; + if (! TRI_IsListJson(json)) { + THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unexpected index list format"); + } + + size_t const n = TRI_LengthListJson(json); indexes.reserve(n); // register indexes for (size_t i = 0; i < n; ++i) { TRI_json_t const* v = TRI_LookupListJson(json, i); - if (v != nullptr) { - indexes.emplace_back(new Index(v)); + if (TRI_IsArrayJson(v)) { + // lookup index id + TRI_json_t const* id = TRI_LookupArrayJson(v, "id"); + if (! TRI_IsStringJson(id)) { + continue; + } + + // use numeric index id + uint64_t iid = triagens::basics::StringUtils::uint64(id->_value._string.data, id->_value._string.length - 1); + TRI_index_t* data = nullptr; + + // now check if we can find the local index and map it + for (size_t j = 0; j < document->_allIndexes._length; ++j) { + auto localIndex = static_cast(document->_allIndexes._buffer[j]); + if (localIndex != nullptr && localIndex->_iid == iid) { + // found + data = localIndex; + break; + } + else if (localIndex->_type == TRI_IDX_TYPE_PRIMARY_INDEX || + localIndex->_type == TRI_IDX_TYPE_EDGE_INDEX) { + } + } + + auto idx = new Index(v); + // assign the found local index + idx->data = data; + + indexes.push_back(idx); } } } diff --git a/arangod/Aql/Index.h b/arangod/Aql/Index.h index f9e2e508ea..b05949f7b1 100644 --- a/arangod/Aql/Index.h +++ b/arangod/Aql/Index.h @@ -62,7 +62,7 @@ namespace triagens { for (size_t i = 0; i < n; ++i) { char const* field = idx->_fields._buffer[i]; - fields.push_back(std::string(field)); + fields.emplace_back(std::string(field)); } TRI_ASSERT(data != nullptr); @@ -84,10 +84,12 @@ namespace triagens { for (size_t i = 0; i < n; ++i) { TRI_json_t const* name = static_cast(TRI_AtVector(&f->_value._objects, i)); if (TRI_IsStringJson(name)) { - fields.push_back(std::string(name->_value._string.data, name->_value._string.length - 1)); + fields.emplace_back(std::string(name->_value._string.data, name->_value._string.length - 1)); } } } + + // it is the caller's responsibility to fill the data attribute with something sensible later! } ~Index() { diff --git a/js/server/tests/aql-hash-cluster.js b/js/server/tests/aql-hash-cluster.js new file mode 100644 index 0000000000..bc6648bbfa --- /dev/null +++ b/js/server/tests/aql-hash-cluster.js @@ -0,0 +1,348 @@ +//////////////////////////////////////////////////////////////////////////////// +/// @brief tests for Ahuacatl, hash index queries +/// +/// @file +/// +/// DISCLAIMER +/// +/// Copyright 2010-2012 triagens GmbH, Cologne, Germany +/// +/// Licensed under the Apache License, Version 2.0 (the "License"); +/// you may not use this file except in compliance with the License. +/// You may obtain a copy of the License at +/// +/// http://www.apache.org/licenses/LICENSE-2.0 +/// +/// Unless required by applicable law or agreed to in writing, software +/// distributed under the License is distributed on an "AS IS" BASIS, +/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +/// See the License for the specific language governing permissions and +/// limitations under the License. +/// +/// Copyright holder is triAGENS GmbH, Cologne, Germany +/// +/// @author Jan Steemann +/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany +//////////////////////////////////////////////////////////////////////////////// + +var internal = require("internal"); +var jsunity = require("jsunity"); +var helper = require("org/arangodb/aql-helper"); +var getQueryResults = helper.getQueryResults2; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test suite +//////////////////////////////////////////////////////////////////////////////// + +function ahuacatlHashTestSuite () { + var hash; + + var explain = function (query, params) { + return helper.getCompactPlan(AQL_EXPLAIN(query, params, { optimizer: { rules: [ "-all", "+use-index-range" ] } })).map(function(node) { return node.type; }); + }; + + return { + +//////////////////////////////////////////////////////////////////////////////// +/// @brief set up +//////////////////////////////////////////////////////////////////////////////// + + setUp : function () { + internal.db._drop("UnitTestsAhuacatlHash"); + + hash = internal.db._create("UnitTestsAhuacatlHash"); + + for (var i = 1; i <= 5; ++i) { + for (var j = 1; j <= 5; ++j) { + hash.save({ "a" : i, "b": j, "c" : i }); + } + } + + hash.ensureHashIndex("a", "b"); + hash.ensureHashIndex("c"); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief tear down +//////////////////////////////////////////////////////////////////////////////// + + tearDown : function () { + internal.db._drop("UnitTestsAhuacatlHash"); + hash = null; + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the single field hash index with equality +//////////////////////////////////////////////////////////////////////////////// + + testEqSingle1 : function () { + var query = "FOR v IN " + hash.name() + " FILTER v.c == 1 SORT v.b RETURN [ v.b ]"; + var expected = [ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "CalculationNode", "ReturnNode" ], explain(query)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the single field hash index with equality +//////////////////////////////////////////////////////////////////////////////// + + testEqSingle2 : function () { + var query = "FOR v IN " + hash.name() + " FILTER 1 == v.c SORT v.b RETURN [ v.b ]"; + var expected = [ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "CalculationNode", "ReturnNode" ], explain(query)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first hash index field with equality +//////////////////////////////////////////////////////////////////////////////// + + testEqSingle3 : function () { + var expected = [ [ 1, 4 ], [ 2, 4 ], [ 3, 4 ], [ 4, 4 ], [ 5, 4 ] ]; + var actual = getQueryResults("FOR v IN " + hash.name() + " FILTER v.c == 4 SORT v.b RETURN [ v.b, v.c ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test the first hash index field with equality +//////////////////////////////////////////////////////////////////////////////// + + testEqSingle4 : function () { + var expected = [ [ 1, 4 ], [ 2, 4 ], [ 3, 4 ], [ 4, 4 ], [ 5, 4 ] ]; + var actual = getQueryResults("FOR v IN " + hash.name() + " FILTER 4 == v.c SORT v.b RETURN [ v.b, v.c ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple hash fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testEqMultiAll1 : function () { + for (var i = 1; i <= 5; ++i) { + for (var j = 1; j <=5; ++j) { + var query = "FOR v IN " + hash.name() + " FILTER v.a == @a && v.b == @b RETURN [ v.a, v.b ]"; + var expected = [ [ i, j ] ]; + var actual = getQueryResults(query, { "a": i, "b": j }); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "CalculationNode", "RemoteNode", "GatherNode", "ReturnNode" ], explain(query, { a: i, b: j })); + } + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test multiple hash fields with multiple operators +//////////////////////////////////////////////////////////////////////////////// + + testEqMultiAll2 : function () { + for (var i = 1; i <= 5; ++i) { + for (var j = 1; j <=5; ++j) { + var query = "FOR v IN " + hash.name() + " FILTER @a == v.a && @b == v.b RETURN [ v.a, v.b ]"; + var expected = [ [ i, j ] ]; + var actual = getQueryResults(query, { "a": i, "b": j }); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "CalculationNode", "RemoteNode", "GatherNode", "ReturnNode" ], explain(query, { a: i, b: j })); + } + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test references with constants +//////////////////////////////////////////////////////////////////////////////// + + testRefConst1 : function () { + var query = "LET x = 4 FOR v IN " + hash.name() + " FILTER v.c == x SORT v.b RETURN [ v.b, v.c ]"; + var expected = [ [ 1, 4 ], [ 2, 4 ], [ 3, 4 ], [ 4, 4 ], [ 5, 4 ] ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "CalculationNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "CalculationNode", "ReturnNode" ], explain(query)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test references with constants +//////////////////////////////////////////////////////////////////////////////// + + testRefConst2 : function () { + var expected = [ [ 3, 5 ] ]; + var actual = getQueryResults("LET x = 3 LET y = 5 FOR v IN " + hash.name() + " FILTER v.a == x && v.b == y RETURN [ v.a, v.b ]"); + + assertEqual(expected, actual); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access +//////////////////////////////////////////////////////////////////////////////// + + testRefSingle1 : function () { + for (var i = 1; i <= 5; ++i) { + var expected = [ [ i, i ] ]; + var actual = getQueryResults("FOR v1 IN " + hash.name() + " FOR v2 IN " + hash.name() + " FILTER v1.c == @c && v1.b == 1 && v2.c == v1.c && v2.b == 1 RETURN [ v1.c, v2.c ]", { "c" : i }); + + assertEqual(expected, actual); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access +//////////////////////////////////////////////////////////////////////////////// + + testRefSingle2 : function () { + for (var i = 1; i <= 5; ++i) { + var expected = [ [ i, i ] ]; + var actual = getQueryResults("FOR v1 IN " + hash.name() + " FOR v2 IN " + hash.name() + " FILTER v1.c == @c && v1.b == 1 && v2.c == v1.c && v2.b == v1.b RETURN [ v1.c, v2.c ]", { "c" : i }); + + assertEqual(expected, actual); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access +//////////////////////////////////////////////////////////////////////////////// + + testRefSingle3 : function () { + for (var i = 1; i <= 5; ++i) { + var expected = [ [ i, i ] ]; + var actual = getQueryResults("FOR v1 IN " + hash.name() + " FOR v2 IN " + hash.name() + " FILTER @c == v1.c && 1 == v1.b && v1.c == v2.c && v1.b == v2.b RETURN [ v1.c, v2.c ]", { "c" : i }); + + assertEqual(expected, actual); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access +//////////////////////////////////////////////////////////////////////////////// + + testRefMulti1 : function () { + for (var i = 1; i <= 5; ++i) { + var expected = [ [ i, 1 ] ]; + var actual = getQueryResults("FOR v1 IN " + hash.name() + " FOR v2 IN " + hash.name() + " FILTER v1.c == @a && v1.b == 1 && v2.c == v1.c && v2.b == v1.b RETURN [ v1.a, v1.b ]", { "a" : i }); + + assertEqual(expected, actual); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access +//////////////////////////////////////////////////////////////////////////////// + + testRefMulti2 : function () { + for (var i = 1; i <= 5; ++i) { + var expected = [ [ i, 1 ] ]; + var actual = getQueryResults("FOR v1 IN " + hash.name() + " FOR v2 IN " + hash.name() + " FILTER @a == v1.c && 1 == v1.b && v1.c == v2.c && v1.b == v2.b RETURN [ v1.a, v1.b ]", { "a" : i }); + + assertEqual(expected, actual); + } + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access +//////////////////////////////////////////////////////////////////////////////// + + testRefMulti3 : function () { + var query = "FOR v1 IN " + hash.name() + " FILTER @a == v1.a && @b == v1.b RETURN [ v1.a, v1.b ]"; + var expected = [ [ 2, 3 ] ]; + var actual = getQueryResults(query, { "a": 2, "b": 3 }); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "IndexRangeNode", "CalculationNode", "FilterNode", "CalculationNode", "RemoteNode", "GatherNode", "ReturnNode" ], explain(query, { a: 2, b: 3 })); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access with filters on the same attribute +//////////////////////////////////////////////////////////////////////////////// + + testRefFilterSame1 : function () { + var query = "FOR a IN " + hash.name() + " FILTER a.a == a.a SORT a.a RETURN a.a"; + var expected = [ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5 ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "CalculationNode", "ReturnNode" ], explain(query)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access with filters on the same attribute +//////////////////////////////////////////////////////////////////////////////// + + testRefFilterSame2 : function () { + var query = "FOR a IN " + hash.name() + " FILTER a.a == a.c SORT a.a RETURN a.a"; + var expected = [ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5 ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "CalculationNode", "ReturnNode" ], explain(query)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access with filters on the same attribute +//////////////////////////////////////////////////////////////////////////////// + + testRefNon1 : function () { + var query = "FOR a IN " + hash.name() + " FILTER a.a == 1 RETURN a.a"; + var expected = [ 1, 1, 1, 1, 1 ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "RemoteNode", "GatherNode", "ReturnNode" ], explain(query)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access with filters on the same attribute +//////////////////////////////////////////////////////////////////////////////// + + testRefNon2 : function () { + var query = "FOR a IN " + hash.name() + " FILTER a.d == a.a SORT a.a RETURN a.a"; + var expected = [ ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "CalculationNode", "ReturnNode" ], explain(query)); + }, + +//////////////////////////////////////////////////////////////////////////////// +/// @brief test ref access with filters on the same attribute +//////////////////////////////////////////////////////////////////////////////// + + testRefNon3 : function () { + var query = "FOR a IN " + hash.name() + " FILTER a.d == 1 SORT a.a RETURN a.a"; + var expected = [ ]; + var actual = getQueryResults(query); + + assertEqual(expected, actual); + + assertEqual([ "SingletonNode", "ScatterNode", "RemoteNode", "EnumerateCollectionNode", "CalculationNode", "FilterNode", "CalculationNode", "SortNode", "RemoteNode", "GatherNode", "CalculationNode", "ReturnNode" ], explain(query)); + } + + }; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes the test suite +//////////////////////////////////////////////////////////////////////////////// + +jsunity.run(ahuacatlHashTestSuite); + +return jsunity.done(); + +// Local Variables: +// mode: outline-minor +// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)" +// End: diff --git a/js/server/tests/aql-hash.js b/js/server/tests/aql-hash-noncluster.js similarity index 100% rename from js/server/tests/aql-hash.js rename to js/server/tests/aql-hash-noncluster.js