mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of https://github.com/arangodb/arangodb into devel
This commit is contained in:
commit
0883c49cd2
52
CHANGELOG
52
CHANGELOG
|
@ -15,6 +15,9 @@ devel
|
|||
|
||||
* fixed issue #2075
|
||||
|
||||
* added AQL function `DISTANCE` to calculate the distance between two arbitrary
|
||||
coordinates (haversine formula)
|
||||
|
||||
* rewrote scheduler and dispatcher based on boost::asio
|
||||
|
||||
parameters changed:
|
||||
|
@ -36,39 +39,44 @@ devel
|
|||
|
||||
* fixed issue #2071
|
||||
|
||||
make the AQL query optimizer inject filter condition expressions referred to by variables during filter condition aggregation.
|
||||
for example, in the following query
|
||||
make the AQL query optimizer inject filter condition expressions referred to
|
||||
by variables during filter condition aggregation.
|
||||
For example, in the following query
|
||||
|
||||
FOR doc IN collection
|
||||
LET cond1 = (doc.value == 1)
|
||||
LET cond2 = (doc.value == 2)
|
||||
FILTER cond1 || cond2
|
||||
RETURN { doc, cond1, cond2 }
|
||||
LET cond1 = (doc.value == 1)
|
||||
LET cond2 = (doc.value == 2)
|
||||
FILTER cond1 || cond2
|
||||
RETURN { doc, cond1, cond2 }
|
||||
|
||||
the optimizer will now inject the conditions for `cond1` and `cond2` into the filter condition `cond1 || cond2`, expanding it to
|
||||
`(doc.value == 1) || (doc.value == 2)` and making these conditions available for index searching.
|
||||
the optimizer will now inject the conditions for `cond1` and `cond2` into the filter
|
||||
condition `cond1 || cond2`, expanding it to `(doc.value == 1) || (doc.value == 2)`
|
||||
and making these conditions available for index searching.
|
||||
|
||||
note that the optimizer previously already injected some conditions into other conditions, but only if the variable that defined
|
||||
the condition was not used elsewhere. for example, the filter condition in the query
|
||||
Note that the optimizer previously already injected some conditions into other
|
||||
conditions, but only if the variable that defined the condition was not used
|
||||
elsewhere. For example, the filter condition in the query
|
||||
|
||||
FOR doc IN collection
|
||||
LET cond = (doc.value == 1)
|
||||
FILTER cond
|
||||
RETURN { doc }
|
||||
LET cond = (doc.value == 1)
|
||||
FILTER cond
|
||||
RETURN { doc }
|
||||
|
||||
already got optimized before because `cond` was only used once in the query and the optimizer decided to inject it into the
|
||||
place where it was used.
|
||||
already got optimized before because `cond` was only used once in the query and
|
||||
the optimizer decided to inject it into the place where it was used.
|
||||
|
||||
this only worked for variables that were referred to once in the query. when a variable was used multiple times, the condition
|
||||
was not injected as in the following query
|
||||
This only worked for variables that were referred to once in the query.
|
||||
When a variable was used multiple times, the condition was not injected as
|
||||
in the following query:
|
||||
|
||||
FOR doc IN collection
|
||||
LET cond = (doc.value == 1)
|
||||
FILTER cond
|
||||
RETURN { doc, cond }
|
||||
|
||||
the fix for #2070 now will enable this optimization so that the query can use an index on `doc.value` if available.
|
||||
LET cond = (doc.value == 1)
|
||||
FILTER cond
|
||||
RETURN { doc, cond }
|
||||
|
||||
The fix for #2070 now will enable this optimization so that the query can
|
||||
use an index on `doc.value` if available.
|
||||
|
||||
* changed behavior of AQL array comparison operators for empty arrays:
|
||||
* `ALL` and `ANY` now always return `false` when the left-hand operand is an
|
||||
empty array. The behavior for non-empty arrays does not change:
|
||||
|
|
|
@ -70,9 +70,35 @@ There is no guaranteed order in which the documents are returned.
|
|||
|
||||
!SECTION Geo utility functions
|
||||
|
||||
The following helper functions do **not use any geo index**. It is advisable to use
|
||||
them in combination with index-accelerated geo functions to limit the number of
|
||||
calls to the non-accelerated functions because of their computational costs.
|
||||
The following helper functions do **not use any geo index**. On large datasets,
|
||||
it is advisable to use them in combination with index-accelerated geo functions
|
||||
to limit the number of calls to these non-accelerated functions because of their
|
||||
computational costs.
|
||||
|
||||
!SUBSECTION DISTANCE()
|
||||
|
||||
`DISTANCE(latitude1, longitude1, latitude2, longitude2) → distance`
|
||||
|
||||
Calculate the distance between two arbitrary coordinates in meters (as birds
|
||||
would fly). The value is computed using the haversine formula, which is based
|
||||
on a spherical Earth model. It's fast to compute and is accurate to around 0.3%,
|
||||
which is sufficient for most use cases such as location-aware services.
|
||||
|
||||
- **latitude1** (number): the latitude portion of the first coordinate
|
||||
- **longitude1** (number): the longitude portion of the first coordinate
|
||||
- **latitude2** (number): the latitude portion of the second coordinate
|
||||
- **longitude2** (number): the longitude portion of the second coordinate
|
||||
- returns **distance** (number): the distance between both coordinates in meters
|
||||
|
||||
```js
|
||||
// Distance between Brandenburg Gate (Berlin) and ArangoDB headquarters (Cologne)
|
||||
DISTANCE(52.5163, 13.3777, 50.9322, 6.94) // 476918.89688380965 (~477km)
|
||||
|
||||
// Sort a small number of documents based on distance to Central Park (New York)
|
||||
FOR doc IN documentSubset // e.g. documents returned by a traversal
|
||||
SORT DISTANCE(doc.latitude, doc.longitude, 40.78, -73.97)
|
||||
RETURN doc
|
||||
```
|
||||
|
||||
!SUBSECTION IS_IN_POLYGON()
|
||||
|
||||
|
|
|
@ -135,11 +135,46 @@ string *text*. Positions start at 0.
|
|||
is not contained in *text*, -1 is returned.
|
||||
|
||||
```js
|
||||
FIND_LAST("foobarbaz", "ba"), // 6
|
||||
FIND_LAST("foobarbaz", "ba", 7), // -1
|
||||
FIND_LAST("foobarbaz", "ba") // 6
|
||||
FIND_LAST("foobarbaz", "ba", 7) // -1
|
||||
FIND_LAST("foobarbaz", "ba", 0, 4) // 3
|
||||
```
|
||||
|
||||
!SUBSECTION JSON_PARSE()
|
||||
|
||||
`JSON_PARSE(text) → value`
|
||||
|
||||
Return an AQL value described by the JSON-encoded input string.
|
||||
|
||||
- **text** (string): the string to parse as JSON
|
||||
- returns **value** (mixed): the value corresponding to the given JSON text.
|
||||
For input values that are no valid JSON strings, the function will return *null*.
|
||||
|
||||
```js
|
||||
JSON_PARSE("123") // 123
|
||||
JSON_PARSE("[ true, false, 2 ]") // [ true, false, 2 ]
|
||||
JSON_PARSE("\\\"abc\\\"") // "abc"
|
||||
JSON_PARSE("{\\\"a\\\": 1}") // { a : 1 }
|
||||
JSON_PARSE("abc") // null
|
||||
```
|
||||
|
||||
!SUBSECTION JSON_STRINGIFY()
|
||||
|
||||
`JSON_STRINGIFY(value) → text`
|
||||
|
||||
Return a JSON string representation of the input value.
|
||||
|
||||
- **value** (mixed): the value to convert to a JSON string
|
||||
- returns **text** (string): the JSON string representing *value*.
|
||||
For input values that cannot be converted to JSON, the function
|
||||
will return *null*.
|
||||
|
||||
```js
|
||||
JSON_STRINGIFY("1") // "1"
|
||||
JSON_STRINGIFY("abc") // "\"abc\""
|
||||
JSON_STRINGIFY("[1, 2, 3]") // "[1,2,3]"
|
||||
```
|
||||
|
||||
!SUBSECTION LEFT()
|
||||
|
||||
`LEFT(value, length) → substring`
|
||||
|
@ -160,7 +195,6 @@ LEFT("foobar", 10) // "foobar"
|
|||
|
||||
`LENGTH(str) → length`
|
||||
|
||||
|
||||
Determine the character length of a string.
|
||||
|
||||
- **str** (string): a string. If a number is passed, it will be casted to string first.
|
||||
|
|
|
@ -78,26 +78,57 @@ As ArangoDB supports MVCC (Multiple Version Concurrency Control),
|
|||
documents can exist in more than one
|
||||
revision. The document revision is the MVCC token used to specify
|
||||
a particular revision of a document (identified by its `_id`).
|
||||
It is a string value currently
|
||||
containing an integer number and is unique within the list of document
|
||||
revisions for a single document. Document revisions can be used to
|
||||
conditionally query, update, replace or delete documents in the database. In
|
||||
order to find a particular revision of a document, you need the document
|
||||
handle or key, and the document revision.
|
||||
It is a string value that contained (up to ArangoDB 3.0)
|
||||
an integer number and is unique within the list of document
|
||||
revisions for a single document.
|
||||
In ArangoDB >= 3.1 the _rev strings
|
||||
are in fact time stamps. They use the local clock of the DBserver that
|
||||
actually writes the document and have millisecond accuracy.
|
||||
Actually, a "Hybrid Logical Clock" is used (for
|
||||
this concept see
|
||||
[this paper](http://www.cse.buffalo.edu/tech-reports/2014-04.pdf)).
|
||||
|
||||
Within one shard it is guaranteed that two different document revisions
|
||||
have a different _rev string, even if they are written in the same
|
||||
millisecond, and that these stamps are ascending.
|
||||
|
||||
Note however that different servers in your cluster might have a clock
|
||||
skew, and therefore between different shards or even between different
|
||||
collections the time stamps are not guaranteed to be comparable.
|
||||
|
||||
The Hybrid Logical Clock feature does one thing to address this
|
||||
issue: Whenever a message is sent from some server A in your cluster to
|
||||
another one B, it is ensured that any timestamp taken on B after the
|
||||
message has arrived is greater than any timestamp taken on A before the
|
||||
message was sent. This ensures that if there is some "causality" between
|
||||
events on different servers, time stamps increase from cause to effect.
|
||||
A direct consequence of this is that sometimes a server has to take
|
||||
timestamps that seem to come from the future of its own clock. It will
|
||||
however still produce ever increasing timestamps. If the clock skew is
|
||||
small, then your timestamps will relatively accurately describe the time
|
||||
when the document revision was actually written.
|
||||
|
||||
ArangoDB uses 64bit unsigned integer values to maintain
|
||||
document revisions internally. When returning document revisions to
|
||||
document revisions internally. At this stage we intentionally do not
|
||||
document the exact format of the revision values. When returning
|
||||
document revisions to
|
||||
clients, ArangoDB will put them into a string to ensure the revision
|
||||
is not clipped by clients that do not support big integers. Clients
|
||||
should treat the revision returned by ArangoDB as an opaque string
|
||||
when they store or use it locally. This will allow ArangoDB to change
|
||||
the format of revisions later if this should be required. Clients can
|
||||
the format of revisions later if this should be required (as has happened
|
||||
with 3.1 with the Hybrid Logical Clock). Clients can
|
||||
use revisions to perform simple equality/non-equality comparisons
|
||||
(e.g. to check whether a document has changed or not), but they should
|
||||
not use revision ids to perform greater/less than comparisons with them
|
||||
to check if a document revision is older than one another, even if this
|
||||
might work for some cases.
|
||||
|
||||
Document revisions can be used to
|
||||
conditionally query, update, replace or delete documents in the database. In
|
||||
order to find a particular revision of a document, you need the document
|
||||
handle or key, and the document revision.
|
||||
|
||||
|
||||
!SUBSECTION Multiple Documents in a single Command
|
||||
|
||||
|
|
|
@ -4,6 +4,21 @@ The following list shows in detail which features have been added or improved in
|
|||
ArangoDB 3.1. ArangoDB 3.1 also contains several bugfixes that are not listed
|
||||
here.
|
||||
|
||||
!SECTION Data format
|
||||
|
||||
The format of the revision values stored in the `_rev` attribute of documents
|
||||
has been changed in 3.1. Up to 3.0 they were strings containing largish decimal numbers. With 3.1, revision values are still strings, but are actually encoded time stamps of the creation date of the revision of the document. The time stamps are acquired using a hybrid logical clock (HLC) on the DBserver that holds the
|
||||
revision (for the concept of a hybrid logical clock see
|
||||
[this paper](http://www.cse.buffalo.edu/tech-reports/2014-04.pdf)).
|
||||
See [this manual section](../DataModeling/Documents/DocumentAddress.html#document-revision) for details.
|
||||
|
||||
ArangoDB >= 3.1 can ArangoDB 3.0 database directories and will simply continue
|
||||
to use the old `_rev` attribute values. New revisions will be written with
|
||||
the new time stamps.
|
||||
|
||||
It is highly recommended to backup all your data before loading a database
|
||||
directory that was written by ArangoDB <= 3.0 into an ArangoDB >= 3.1.
|
||||
|
||||
!SECTION Communication Layer
|
||||
|
||||
ArangoDB up to 3.0 used [libev](http://software.schmorp.de/pkg/libev.html) for
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
!SECTION Whats New
|
||||
|
||||
- [Whats New in 3.1](NewFeatures31.md)
|
||||
- [Whats New in 3.0](NewFeatures30.md)
|
||||
- [Whats New in 2.8](NewFeatures28.md)
|
||||
- [Whats New in 2.7](NewFeatures27.md)
|
||||
|
@ -17,6 +18,7 @@
|
|||
Also see [Upgrading](../Administration/Upgrading/README.md) in the
|
||||
Administration chapter.
|
||||
|
||||
- [Incompatible changes in 3.1](UpgradingChanges31.md)
|
||||
- [Incompatible changes in 3.0](UpgradingChanges30.md)
|
||||
- [Incompatible changes in 2.8](UpgradingChanges28.md)
|
||||
- [Incompatible changes in 2.7](UpgradingChanges27.md)
|
||||
|
|
|
@ -51,7 +51,22 @@ meta-data files ("parameter.json"). Files containing the `maximalSize` attribute
|
|||
will still be picked up correctly for not-yet adjusted collections.
|
||||
|
||||
The format of the revision values stored in the `_rev` attribute of documents
|
||||
has been changed in 3.1. Revision values are stored as hybrid logical clock values.
|
||||
has been changed in 3.1. Up to 3.0 they were strings containing largish decimal numbers. With 3.1, revision values are still strings, but are actually encoded time stamps of the creation date of the revision of the document. The time stamps are acquired using a hybrid logical clock (HLC) on the DBserver that holds the
|
||||
revision (for the concept of a hybrid logical clock see
|
||||
[this paper](http://www.cse.buffalo.edu/tech-reports/2014-04.pdf)).
|
||||
See [this manual section](../DataModeling/Documents/DocumentAddress.html#document-revision) for details.
|
||||
|
||||
ArangoDB >= 3.1 can ArangoDB 3.0 database directories and will simply continue
|
||||
to use the old `_rev` attribute values. New revisions will be written with
|
||||
the new time stamps.
|
||||
|
||||
It is highly recommended to backup all your data before loading a database
|
||||
directory that was written by ArangoDB <= 3.0 into an ArangoDB >= 3.1.
|
||||
|
||||
To change all your old `_rev` attributes into new style time stamps you
|
||||
have to use `arangodump` to dump all data out (using ArangoDB 3.0), and
|
||||
use `arangorestore` into the new ArangoDB 3.1, which is the safest
|
||||
way to upgrade.
|
||||
|
||||
!SECTION HTTP API changes
|
||||
|
||||
|
|
|
@ -55,9 +55,9 @@ On success an object with the following attributes is returned:
|
|||
generating keys and supplying own key values in the *_key* attribute
|
||||
of documents is considered an error.
|
||||
|
||||
**Note**: some other collection properties, such as *type*, *isVolatile*,
|
||||
*numberOfShards* or *shardKeys* cannot be changed once a collection is
|
||||
created.
|
||||
**Note**: except for *waitForSync*, *journalSize* and *name*, collection
|
||||
properties **cannot be changed** once a collection is created. To rename
|
||||
a collection, the rename endpoint must be used.
|
||||
|
||||
@RESTRETURNCODES
|
||||
|
||||
|
|
|
@ -109,7 +109,8 @@ DistributeNode::DistributeNode(ExecutionPlan* plan,
|
|||
_varId(base.get("varId").getNumericValue<VariableId>()),
|
||||
_alternativeVarId(base.get("alternativeVarId").getNumericValue<VariableId>()),
|
||||
_createKeys(base.get("createKeys").getBoolean()),
|
||||
_allowKeyConversionToObject(base.get("allowKeyConversionToObject").getBoolean()) {}
|
||||
_allowKeyConversionToObject(base.get("allowKeyConversionToObject").getBoolean()),
|
||||
_allowSpecifiedKeys(false) {}
|
||||
|
||||
/// @brief toVelocyPack, for DistributedNode
|
||||
void DistributeNode::toVelocyPackHelper(VPackBuilder& nodes,
|
||||
|
|
|
@ -1304,17 +1304,6 @@ static void JS_GetCurrentResponse(
|
|||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
static void JS_IsEnterprise(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
#ifndef USE_ENTERPRISE
|
||||
TRI_V8_RETURN(v8::False(isolate));
|
||||
#else
|
||||
TRI_V8_RETURN(v8::True(isolate));
|
||||
#endif
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stores the V8 actions function inside the global variable
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1345,9 +1334,6 @@ void TRI_InitV8Actions(v8::Isolate* isolate, v8::Handle<v8::Context> context) {
|
|||
TRI_AddGlobalFunctionVocbase(isolate, context,
|
||||
TRI_V8_ASCII_STRING("SYS_REQUEST_PARTS"),
|
||||
JS_RequestParts, true);
|
||||
TRI_AddGlobalFunctionVocbase(isolate, context,
|
||||
TRI_V8_ASCII_STRING("SYS_IS_ENTERPRISE"),
|
||||
JS_IsEnterprise);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -2732,6 +2732,18 @@ void TRI_V8ReloadRouting(v8::Isolate* isolate) {
|
|||
TRI_V8_ASCII_STRING("reload routing"), false);
|
||||
}
|
||||
|
||||
|
||||
static void JS_IsEnterprise(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
#ifndef USE_ENTERPRISE
|
||||
TRI_V8_RETURN(v8::False(isolate));
|
||||
#else
|
||||
TRI_V8_RETURN(v8::True(isolate));
|
||||
#endif
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief creates a TRI_vocbase_t global context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -2919,6 +2931,10 @@ void TRI_InitV8VocBridge(v8::Isolate* isolate, v8::Handle<v8::Context> context,
|
|||
TRI_AddGlobalFunctionVocbase(isolate, context,
|
||||
TRI_V8_ASCII_STRING("TRUSTED_PROXIES"),
|
||||
JS_TrustedProxies, true);
|
||||
|
||||
TRI_AddGlobalFunctionVocbase(isolate, context,
|
||||
TRI_V8_ASCII_STRING("SYS_IS_ENTERPRISE"),
|
||||
JS_IsEnterprise);
|
||||
// .............................................................................
|
||||
// create global variables
|
||||
// .............................................................................
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="navlogo">
|
||||
<a class="logo big" href="#"><img id="ArangoDBLogo" class="arangodbLogo" src="img/arangodb-edition-optimized.svg"/></a>
|
||||
<a class="logo small" href="#"><img class="arangodbLogo" src="img/arangodb_logo_small.png"/></a>
|
||||
<a class="version"><span>VERSION: </span><span id="currentVersion"></span></a>
|
||||
<a class="version"><span id="currentVersion"></span></a>
|
||||
</div>
|
||||
<!-- <div id="progressPlaceholderIcon"></div> -->
|
||||
<div class="statmenu" id="statisticBar">
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
window.versionHelper.fromString(data.version);
|
||||
|
||||
$('.navbar #currentVersion').html(
|
||||
' ' + data.version.substr(0, 7) + '<i class="fa fa-exclamation-circle"></i>'
|
||||
data.version.substr(0, 7) + '<i class="fa fa-exclamation-circle"></i>'
|
||||
);
|
||||
|
||||
window.parseVersions = function (json) {
|
||||
|
|
|
@ -455,24 +455,35 @@
|
|||
});
|
||||
|
||||
_.each(obj.vertices, function (node) {
|
||||
vertices[node._id] = {
|
||||
id: node._id,
|
||||
label: node._key,
|
||||
// size: 0.3,
|
||||
color: color,
|
||||
x: Math.random(),
|
||||
y: Math.random()
|
||||
};
|
||||
if (node !== null) {
|
||||
vertices[node._id] = {
|
||||
id: node._id,
|
||||
label: node._key,
|
||||
size: 0.3,
|
||||
color: color,
|
||||
x: Math.random(),
|
||||
y: Math.random()
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
var nodeIds = [];
|
||||
_.each(vertices, function (node) {
|
||||
returnObj.nodes.push(node);
|
||||
nodeIds.push(node.id);
|
||||
});
|
||||
|
||||
_.each(edges, function (edge) {
|
||||
returnObj.edges.push(edge);
|
||||
if (nodeIds.includes(edge.source) && nodeIds.includes(edge.target)) {
|
||||
returnObj.edges.push(edge);
|
||||
}
|
||||
/* how to handle not correct data?
|
||||
else {
|
||||
console.log('target to from is missing');
|
||||
}
|
||||
*/
|
||||
});
|
||||
} else if (type === 'array') {
|
||||
_.each(data, function (edge) {
|
||||
|
|
|
@ -257,7 +257,7 @@
|
|||
position: fixed;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
top: 120px;
|
||||
top: 135px;
|
||||
width: 100%;
|
||||
|
||||
span {
|
||||
|
|
|
@ -3579,7 +3579,7 @@ testFuncs.endpoints = function(options) {
|
|||
return {
|
||||
status: true,
|
||||
skipped: true,
|
||||
}
|
||||
};
|
||||
} else {
|
||||
let instanceInfo = startInstance('tcp', Object.assign(options, {useReconnect: true}), {
|
||||
'server.endpoint': endpoint,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* global describe, it, beforeEach, afterEach*/
|
||||
/* global db, describe, it, beforeEach, afterEach*/
|
||||
'use strict';
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*jshint globalstrict:false, strict:false, maxlen: 500 */
|
||||
/*global AQL_EXECUTE, assertEqual */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for query language, geo queries
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2016 ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Simran Brucherseifer
|
||||
/// @author Copyright 2016, ArangoDB GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var jsunity = require("jsunity");
|
||||
var internal = require("internal");
|
||||
var errors = internal.errors;
|
||||
var db = require("@arangodb").db;
|
||||
var helper = require("@arangodb/aql-helper");
|
||||
var assertQueryError = helper.assertQueryError;
|
||||
var assertQueryWarningAndNull = helper.assertQueryWarningAndNull;
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function distanceSuite () {
|
||||
|
||||
return {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test DISTANCE function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testDistance1 : function () {
|
||||
var co1 = { lat: 52.5163, lon: 13.3777, _key: "BrandenburgGate" };
|
||||
var co2 = { lat: 50.9322, lon: 6.94, _key: "ArangoHQ" };
|
||||
var query = "DISTANCE(" + co1.lat + "," + co1.lon + "," + co2.lat + "," + co2.lon + ")";
|
||||
var expected = [ 476918.89688380965 ]; // Vincenty's formula: 477.47 km
|
||||
|
||||
var actual = AQL_EXECUTE("RETURN " + query).json;
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = AQL_EXECUTE("RETURN NOOPT(" + query + ")").json;
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = AQL_EXECUTE("RETURN NOOPT(V8(" + query + "))").json;
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test DISTANCE function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testDistance2 : function () {
|
||||
var co1 = { lat: 40.78, lon: -73.97, _key: "CentralPark" };
|
||||
var co2 = { lat: 34.05, lon: -118.25, _key: "LosAngeles" };
|
||||
var query = "DISTANCE(" + co1.lat + "," + co1.lon + "," + co2.lat + "," + co2.lon + ")";
|
||||
var expected = [ 3938926.7382122413 ]; // Vincenty's formula: 3943.29 km
|
||||
|
||||
var actual = AQL_EXECUTE("RETURN " + query).json;
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = AQL_EXECUTE("RETURN NOOPT(" + query + ")").json;
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = AQL_EXECUTE("RETURN NOOPT(V8(" + query + "))").json;
|
||||
assertEqual(expected, actual); },
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test DISTANCE function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testDistance3 : function () {
|
||||
var co1 = { lat: 0, lon: 0, _key: "zeroPoint" };
|
||||
var co2 = { lat: 0, lon: 180, _key: "otherSideOfGLobe" };
|
||||
var query = "DISTANCE(" + co1.lat + "," + co1.lon + "," + co2.lat + "," + co2.lon + ")";
|
||||
var expected = [ 20015086.79602057 ]; // Half of equatorial circumference (WGS 84): 20037.5085 km
|
||||
|
||||
var actual = AQL_EXECUTE("RETURN " + query).json;
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = AQL_EXECUTE("RETURN NOOPT(" + query + ")").json;
|
||||
assertEqual(expected, actual);
|
||||
|
||||
actual = AQL_EXECUTE("RETURN NOOPT(V8(" + query + "))").json;
|
||||
assertEqual(expected, actual);
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test invalid DISTANCE arguments
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testDistanceInvalid : function () {
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DISTANCE()");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DISTANCE( 0 )");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DISTANCE( 0, 0 )");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DISTANCE( 0, 0, 0 )");
|
||||
assertQueryError(errors.ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH.code, "RETURN DISTANCE( 0, 0, 0, 0, 0 )");
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DISTANCE( 0, 0, 0, \"foo\" )");
|
||||
assertQueryWarningAndNull(errors.ERROR_QUERY_FUNCTION_ARGUMENT_TYPE_MISMATCH.code, "RETURN DISTANCE( 0, 0, 0, [ 1, 2, 3 ] )");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsunity.run(distanceSuite);
|
||||
|
||||
return jsunity.done();
|
||||
|
Loading…
Reference in New Issue