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 %}
-
+
\ 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