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
50
CHANGELOG
50
CHANGELOG
|
@ -15,6 +15,9 @@ devel
|
||||||
|
|
||||||
* fixed issue #2075
|
* 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
|
* rewrote scheduler and dispatcher based on boost::asio
|
||||||
|
|
||||||
parameters changed:
|
parameters changed:
|
||||||
|
@ -36,38 +39,43 @@ devel
|
||||||
|
|
||||||
* fixed issue #2071
|
* fixed issue #2071
|
||||||
|
|
||||||
make the AQL query optimizer inject filter condition expressions referred to by variables during filter condition aggregation.
|
make the AQL query optimizer inject filter condition expressions referred to
|
||||||
for example, in the following query
|
by variables during filter condition aggregation.
|
||||||
|
For example, in the following query
|
||||||
|
|
||||||
FOR doc IN collection
|
FOR doc IN collection
|
||||||
LET cond1 = (doc.value == 1)
|
LET cond1 = (doc.value == 1)
|
||||||
LET cond2 = (doc.value == 2)
|
LET cond2 = (doc.value == 2)
|
||||||
FILTER cond1 || cond2
|
FILTER cond1 || cond2
|
||||||
RETURN { doc, 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
|
the optimizer will now inject the conditions for `cond1` and `cond2` into the filter
|
||||||
`(doc.value == 1) || (doc.value == 2)` and making these conditions available for index searching.
|
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
|
Note that the optimizer previously already injected some conditions into other
|
||||||
the condition was not used elsewhere. for example, the filter condition in the query
|
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
|
FOR doc IN collection
|
||||||
LET cond = (doc.value == 1)
|
LET cond = (doc.value == 1)
|
||||||
FILTER cond
|
FILTER cond
|
||||||
RETURN { doc }
|
RETURN { doc }
|
||||||
|
|
||||||
already got optimized before because `cond` was only used once in the query and the optimizer decided to inject it into the
|
already got optimized before because `cond` was only used once in the query and
|
||||||
place where it was used.
|
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
|
This only worked for variables that were referred to once in the query.
|
||||||
was not injected as in the following query
|
When a variable was used multiple times, the condition was not injected as
|
||||||
|
in the following query:
|
||||||
|
|
||||||
FOR doc IN collection
|
FOR doc IN collection
|
||||||
LET cond = (doc.value == 1)
|
LET cond = (doc.value == 1)
|
||||||
FILTER cond
|
FILTER cond
|
||||||
RETURN { doc, 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.
|
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:
|
* changed behavior of AQL array comparison operators for empty arrays:
|
||||||
* `ALL` and `ANY` now always return `false` when the left-hand operand is an
|
* `ALL` and `ANY` now always return `false` when the left-hand operand is an
|
||||||
|
|
|
@ -70,9 +70,35 @@ There is no guaranteed order in which the documents are returned.
|
||||||
|
|
||||||
!SECTION Geo utility functions
|
!SECTION Geo utility functions
|
||||||
|
|
||||||
The following helper functions do **not use any geo index**. It is advisable to use
|
The following helper functions do **not use any geo index**. On large datasets,
|
||||||
them in combination with index-accelerated geo functions to limit the number of
|
it is advisable to use them in combination with index-accelerated geo functions
|
||||||
calls to the non-accelerated functions because of their computational costs.
|
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()
|
!SUBSECTION IS_IN_POLYGON()
|
||||||
|
|
||||||
|
|
|
@ -135,11 +135,46 @@ string *text*. Positions start at 0.
|
||||||
is not contained in *text*, -1 is returned.
|
is not contained in *text*, -1 is returned.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
FIND_LAST("foobarbaz", "ba"), // 6
|
FIND_LAST("foobarbaz", "ba") // 6
|
||||||
FIND_LAST("foobarbaz", "ba", 7), // -1
|
FIND_LAST("foobarbaz", "ba", 7) // -1
|
||||||
FIND_LAST("foobarbaz", "ba", 0, 4) // 3
|
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()
|
!SUBSECTION LEFT()
|
||||||
|
|
||||||
`LEFT(value, length) → substring`
|
`LEFT(value, length) → substring`
|
||||||
|
@ -160,7 +195,6 @@ LEFT("foobar", 10) // "foobar"
|
||||||
|
|
||||||
`LENGTH(str) → length`
|
`LENGTH(str) → length`
|
||||||
|
|
||||||
|
|
||||||
Determine the character length of a string.
|
Determine the character length of a string.
|
||||||
|
|
||||||
- **str** (string): a string. If a number is passed, it will be casted to string first.
|
- **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
|
documents can exist in more than one
|
||||||
revision. The document revision is the MVCC token used to specify
|
revision. The document revision is the MVCC token used to specify
|
||||||
a particular revision of a document (identified by its `_id`).
|
a particular revision of a document (identified by its `_id`).
|
||||||
It is a string value currently
|
It is a string value that contained (up to ArangoDB 3.0)
|
||||||
containing an integer number and is unique within the list of document
|
an integer number and is unique within the list of document
|
||||||
revisions for a single document. Document revisions can be used to
|
revisions for a single document.
|
||||||
conditionally query, update, replace or delete documents in the database. In
|
In ArangoDB >= 3.1 the _rev strings
|
||||||
order to find a particular revision of a document, you need the document
|
are in fact time stamps. They use the local clock of the DBserver that
|
||||||
handle or key, and the document revision.
|
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
|
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
|
clients, ArangoDB will put them into a string to ensure the revision
|
||||||
is not clipped by clients that do not support big integers. Clients
|
is not clipped by clients that do not support big integers. Clients
|
||||||
should treat the revision returned by ArangoDB as an opaque string
|
should treat the revision returned by ArangoDB as an opaque string
|
||||||
when they store or use it locally. This will allow ArangoDB to change
|
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
|
use revisions to perform simple equality/non-equality comparisons
|
||||||
(e.g. to check whether a document has changed or not), but they should
|
(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
|
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
|
to check if a document revision is older than one another, even if this
|
||||||
might work for some cases.
|
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
|
!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
|
ArangoDB 3.1. ArangoDB 3.1 also contains several bugfixes that are not listed
|
||||||
here.
|
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
|
!SECTION Communication Layer
|
||||||
|
|
||||||
ArangoDB up to 3.0 used [libev](http://software.schmorp.de/pkg/libev.html) for
|
ArangoDB up to 3.0 used [libev](http://software.schmorp.de/pkg/libev.html) for
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
!SECTION Whats New
|
!SECTION Whats New
|
||||||
|
|
||||||
|
- [Whats New in 3.1](NewFeatures31.md)
|
||||||
- [Whats New in 3.0](NewFeatures30.md)
|
- [Whats New in 3.0](NewFeatures30.md)
|
||||||
- [Whats New in 2.8](NewFeatures28.md)
|
- [Whats New in 2.8](NewFeatures28.md)
|
||||||
- [Whats New in 2.7](NewFeatures27.md)
|
- [Whats New in 2.7](NewFeatures27.md)
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
Also see [Upgrading](../Administration/Upgrading/README.md) in the
|
Also see [Upgrading](../Administration/Upgrading/README.md) in the
|
||||||
Administration chapter.
|
Administration chapter.
|
||||||
|
|
||||||
|
- [Incompatible changes in 3.1](UpgradingChanges31.md)
|
||||||
- [Incompatible changes in 3.0](UpgradingChanges30.md)
|
- [Incompatible changes in 3.0](UpgradingChanges30.md)
|
||||||
- [Incompatible changes in 2.8](UpgradingChanges28.md)
|
- [Incompatible changes in 2.8](UpgradingChanges28.md)
|
||||||
- [Incompatible changes in 2.7](UpgradingChanges27.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.
|
will still be picked up correctly for not-yet adjusted collections.
|
||||||
|
|
||||||
The format of the revision values stored in the `_rev` attribute of documents
|
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
|
!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
|
generating keys and supplying own key values in the *_key* attribute
|
||||||
of documents is considered an error.
|
of documents is considered an error.
|
||||||
|
|
||||||
**Note**: some other collection properties, such as *type*, *isVolatile*,
|
**Note**: except for *waitForSync*, *journalSize* and *name*, collection
|
||||||
*numberOfShards* or *shardKeys* cannot be changed once a collection is
|
properties **cannot be changed** once a collection is created. To rename
|
||||||
created.
|
a collection, the rename endpoint must be used.
|
||||||
|
|
||||||
@RESTRETURNCODES
|
@RESTRETURNCODES
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,8 @@ DistributeNode::DistributeNode(ExecutionPlan* plan,
|
||||||
_varId(base.get("varId").getNumericValue<VariableId>()),
|
_varId(base.get("varId").getNumericValue<VariableId>()),
|
||||||
_alternativeVarId(base.get("alternativeVarId").getNumericValue<VariableId>()),
|
_alternativeVarId(base.get("alternativeVarId").getNumericValue<VariableId>()),
|
||||||
_createKeys(base.get("createKeys").getBoolean()),
|
_createKeys(base.get("createKeys").getBoolean()),
|
||||||
_allowKeyConversionToObject(base.get("allowKeyConversionToObject").getBoolean()) {}
|
_allowKeyConversionToObject(base.get("allowKeyConversionToObject").getBoolean()),
|
||||||
|
_allowSpecifiedKeys(false) {}
|
||||||
|
|
||||||
/// @brief toVelocyPack, for DistributedNode
|
/// @brief toVelocyPack, for DistributedNode
|
||||||
void DistributeNode::toVelocyPackHelper(VPackBuilder& nodes,
|
void DistributeNode::toVelocyPackHelper(VPackBuilder& nodes,
|
||||||
|
|
|
@ -1304,17 +1304,6 @@ static void JS_GetCurrentResponse(
|
||||||
TRI_V8_TRY_CATCH_END
|
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
|
/// @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_AddGlobalFunctionVocbase(isolate, context,
|
||||||
TRI_V8_ASCII_STRING("SYS_REQUEST_PARTS"),
|
TRI_V8_ASCII_STRING("SYS_REQUEST_PARTS"),
|
||||||
JS_RequestParts, true);
|
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);
|
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
|
/// @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_AddGlobalFunctionVocbase(isolate, context,
|
||||||
TRI_V8_ASCII_STRING("TRUSTED_PROXIES"),
|
TRI_V8_ASCII_STRING("TRUSTED_PROXIES"),
|
||||||
JS_TrustedProxies, true);
|
JS_TrustedProxies, true);
|
||||||
|
|
||||||
|
TRI_AddGlobalFunctionVocbase(isolate, context,
|
||||||
|
TRI_V8_ASCII_STRING("SYS_IS_ENTERPRISE"),
|
||||||
|
JS_IsEnterprise);
|
||||||
// .............................................................................
|
// .............................................................................
|
||||||
// create global variables
|
// create global variables
|
||||||
// .............................................................................
|
// .............................................................................
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="navlogo">
|
<div class="navlogo">
|
||||||
<a class="logo big" href="#"><img id="ArangoDBLogo" class="arangodbLogo" src="img/arangodb-edition-optimized.svg"/></a>
|
<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="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>
|
||||||
<!-- <div id="progressPlaceholderIcon"></div> -->
|
<!-- <div id="progressPlaceholderIcon"></div> -->
|
||||||
<div class="statmenu" id="statisticBar">
|
<div class="statmenu" id="statisticBar">
|
||||||
|
|
|
@ -139,7 +139,7 @@
|
||||||
window.versionHelper.fromString(data.version);
|
window.versionHelper.fromString(data.version);
|
||||||
|
|
||||||
$('.navbar #currentVersion').html(
|
$('.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) {
|
window.parseVersions = function (json) {
|
||||||
|
|
|
@ -455,24 +455,35 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
_.each(obj.vertices, function (node) {
|
_.each(obj.vertices, function (node) {
|
||||||
vertices[node._id] = {
|
if (node !== null) {
|
||||||
id: node._id,
|
vertices[node._id] = {
|
||||||
label: node._key,
|
id: node._id,
|
||||||
// size: 0.3,
|
label: node._key,
|
||||||
color: color,
|
size: 0.3,
|
||||||
x: Math.random(),
|
color: color,
|
||||||
y: Math.random()
|
x: Math.random(),
|
||||||
};
|
y: Math.random()
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var nodeIds = [];
|
||||||
_.each(vertices, function (node) {
|
_.each(vertices, function (node) {
|
||||||
returnObj.nodes.push(node);
|
returnObj.nodes.push(node);
|
||||||
|
nodeIds.push(node.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
_.each(edges, function (edge) {
|
_.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') {
|
} else if (type === 'array') {
|
||||||
_.each(data, function (edge) {
|
_.each(data, function (edge) {
|
||||||
|
|
|
@ -257,7 +257,7 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0;
|
right: 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
top: 120px;
|
top: 135px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
|
|
|
@ -3579,7 +3579,7 @@ testFuncs.endpoints = function(options) {
|
||||||
return {
|
return {
|
||||||
status: true,
|
status: true,
|
||||||
skipped: true,
|
skipped: true,
|
||||||
}
|
};
|
||||||
} else {
|
} else {
|
||||||
let instanceInfo = startInstance('tcp', Object.assign(options, {useReconnect: true}), {
|
let instanceInfo = startInstance('tcp', Object.assign(options, {useReconnect: true}), {
|
||||||
'server.endpoint': endpoint,
|
'server.endpoint': endpoint,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global describe, it, beforeEach, afterEach*/
|
/* global db, describe, it, beforeEach, afterEach*/
|
||||||
'use strict';
|
'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