mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
5d020b7ab7
|
@ -1,11 +1,14 @@
|
||||||
v2.3.0 (XXXX-XX-XX)
|
v2.3.0 (XXXX-XX-XX)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
* performance improvements for AQL queries that use JavaScript-based expressions
|
||||||
|
internally
|
||||||
|
|
||||||
* added AQL geo functions `WITHIN_RECTANGLE` and `IS_IN_POLYGON`
|
* added AQL geo functions `WITHIN_RECTANGLE` and `IS_IN_POLYGON`
|
||||||
|
|
||||||
* fixed non-working query results download in AQL editor of web interface
|
* fixed non-working query results download in AQL editor of web interface
|
||||||
|
|
||||||
* removed debug print message in AQL query export routine
|
* removed debug print message in AQL editor query export routine
|
||||||
|
|
||||||
* fixed issue #1075: Aardvark: user name required even if auth is off #1075
|
* fixed issue #1075: Aardvark: user name required even if auth is off #1075
|
||||||
|
|
||||||
|
|
|
@ -23,11 +23,13 @@ These operators accept any data types for the first and second operands.
|
||||||
|
|
||||||
Each of the comparison operators returns a boolean value if the comparison can
|
Each of the comparison operators returns a boolean value if the comparison can
|
||||||
be evaluated and returns *true* if the comparison evaluates to true, and *false*
|
be evaluated and returns *true* if the comparison evaluates to true, and *false*
|
||||||
otherwise.
|
otherwise. Please note that the comparsion operators will not perform any
|
||||||
|
implicit type casts if the compared operands have different types.
|
||||||
|
|
||||||
Some examples for comparison operations in AQL:
|
Some examples for comparison operations in AQL:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
0 == null // false
|
||||||
1 > 0 // true
|
1 > 0 // true
|
||||||
true != null // true
|
true != null // true
|
||||||
45 <= "yikes!" // true
|
45 <= "yikes!" // true
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
The default installation directory is *c:\Program Files\ArangoDB-1.x.y*. During the
|
The default installation directory is *c:\Program Files\ArangoDB-1.x.y*. During the
|
||||||
installation process you may change this. In the following description we will assume
|
installation process you may change this. In the following description we will assume
|
||||||
that ArangoDB has been installed in the location *<ROOTDIR>*.
|
that ArangoDB has been installed in the location *<ROOTDIR>*.
|
||||||
|
|
||||||
You have to be careful when choosing an installation directory. You need either
|
You have to be careful when choosing an installation directory. You need either
|
||||||
write permission to this directory or you need to modify the config file for the
|
write permission to this directory or you need to modify the config file for the
|
||||||
|
@ -10,17 +10,17 @@ server process. In the latter case the database directory and the Foxx directory
|
||||||
has to be writable by the user.
|
has to be writable by the user.
|
||||||
|
|
||||||
Installing for a single user: Select a different directory during
|
Installing for a single user: Select a different directory during
|
||||||
installation. For example *C:/Users/<username>/arangodb* or *C:/ArangoDB*.
|
installation. For example *c:\Users\<Username>\ArangoDB* or *c:\ArangoDB*.
|
||||||
|
|
||||||
Installing for multiple users: Keep the default directory. After the
|
Installing for multiple users: Keep the default directory. After the
|
||||||
installation edit the file *<ROOTDIR>/etc/arangodb/arangod.conf*. Adjust the
|
installation edit the file *<ROOTDIR>\etc\Arangodb\arangod.conf*. Adjust the
|
||||||
*directory* and *app-path* so that these paths point into your home directory.
|
*directory* and *app-path* so that these paths point into your home directory.
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
directory = @HOMEDRIVE@/@HOMEPATH@/arangodb/databases
|
directory = @HOMEDRIVE@\@HOMEPATH@\arangodb\databases
|
||||||
|
|
||||||
[javascript]
|
[javascript]
|
||||||
app-path = @HOMEDRIVE@/@HOMEPATH@/arangodb/apps
|
app-path = @HOMEDRIVE@\@HOMEPATH@\arangodb\apps
|
||||||
|
|
||||||
Create the directories for each user that wants to use ArangoDB.
|
Create the directories for each user that wants to use ArangoDB.
|
||||||
|
|
||||||
|
@ -28,16 +28,16 @@ Installing as Service: Keep the default directory. After the installation open
|
||||||
a command line as administrator (search for *cmd* and right click *run as
|
a command line as administrator (search for *cmd* and right click *run as
|
||||||
administrator*).
|
administrator*).
|
||||||
|
|
||||||
cmd> arangod --install-service
|
cmd> arangod --install-service
|
||||||
INFO: adding service 'ArangoDB - the multi-purpose database' (internal 'ArangoDB')
|
INFO: adding service 'ArangoDB - the multi-purpose database' (internal 'ArangoDB')
|
||||||
INFO: added service with command line '"C:\Program Files (x86)\ArangoDB 1.4.4\bin\arangod.exe" --start-service'
|
INFO: added service with command line '"C:\Program Files (x86)\ArangoDB 1.4.4\bin\arangod.exe" --start-service'
|
||||||
|
|
||||||
Open the service manager and start ArangoDB. In order to enable logging
|
Open the service manager and start ArangoDB. In order to enable logging
|
||||||
edit the file "<ROOTDIR>/etc/arangodb/arangod.conf" and uncomment the file
|
edit the file "<ROOTDIR>\etc\arangodb\arangod.conf" and uncomment the file
|
||||||
option.
|
option.
|
||||||
|
|
||||||
[log]
|
[log]
|
||||||
file = @ROOTDIR@/var/log/arangodb/arangod.log
|
file = @ROOTDIR@\var\log\arangodb\arangod.log
|
||||||
|
|
||||||
|
|
||||||
!SUBSECTION Client, Server and Lock-Files
|
!SUBSECTION Client, Server and Lock-Files
|
||||||
|
@ -51,9 +51,9 @@ not proceed correctly or if the server terminated unexpectedly.
|
||||||
!SUBSECTION Starting
|
!SUBSECTION Starting
|
||||||
|
|
||||||
To start an ArangoDB server instance with networking enabled, use the executable
|
To start an ArangoDB server instance with networking enabled, use the executable
|
||||||
*arangod.exe* located in *<ROOTDIR>/bin*. This will use the configuration
|
*arangod.exe* located in *<ROOTDIR>\bin*. This will use the configuration
|
||||||
file *arangod.conf* located in *<ROOTDIR>/etc/arangodb*, which you can adjust
|
file *arangod.conf* located in *<ROOTDIR>\etc\arangodb*, which you can adjust
|
||||||
to your needs and use the data directory *<ROOTDIR>/var/lib/arangodb*. This
|
to your needs and use the data directory *<ROOTDIR>\var\lib\arangodb*. This
|
||||||
is the place where all your data (databases and collections) will be stored
|
is the place where all your data (databases and collections) will be stored
|
||||||
by default.
|
by default.
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ containing the configuration files.
|
||||||
!SUBSECTION Using the Client
|
!SUBSECTION Using the Client
|
||||||
|
|
||||||
To connect to an already running ArangoDB server instance, there is a shell
|
To connect to an already running ArangoDB server instance, there is a shell
|
||||||
*arangosh.exe* located in *<ROOTDIR>/bin*. This starts a shell which can be
|
*arangosh.exe* located in *<ROOTDIR>\bin*. This starts a shell which can be
|
||||||
used – amongst other things – to administer and query a local or remote
|
used – amongst other things – to administer and query a local or remote
|
||||||
ArangoDB server.
|
ArangoDB server.
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ shell. To use it you must have a server running somewhere, e.g. by using
|
||||||
the *arangod.exe* executable.
|
the *arangod.exe* executable.
|
||||||
|
|
||||||
*arangosh.exe* uses configuration from the file *arangosh.conf* located in
|
*arangosh.exe* uses configuration from the file *arangosh.conf* located in
|
||||||
*<ROOTDIR>/etc/arangodb/*. Please adjust this to your needs if you want to
|
*<ROOTDIR>\etc\arangodb\*. Please adjust this to your needs if you want to
|
||||||
use different connection settings etc.
|
use different connection settings etc.
|
||||||
|
|
||||||
!SUBSECTION 32bit
|
!SUBSECTION 32bit
|
||||||
|
@ -121,9 +121,9 @@ completed successfully.
|
||||||
|
|
||||||
To uninstall the Arango server application you can use the windows control panel
|
To uninstall the Arango server application you can use the windows control panel
|
||||||
(as you would normally uninstall an application). Note however, that any data
|
(as you would normally uninstall an application). Note however, that any data
|
||||||
files created by the Arango server will remain as well as the *<ROOTDIR>*
|
files created by the Arango server will remain as well as the *<ROOTDIR>*
|
||||||
directory. To complete the uninstallation process, remove the data files and
|
directory. To complete the uninstallation process, remove the data files and
|
||||||
the *<ROOTDIR>* directory manually.
|
the *<ROOTDIR>* directory manually.
|
||||||
|
|
||||||
!SUBSECTION Limitations for Cygwin
|
!SUBSECTION Limitations for Cygwin
|
||||||
|
|
||||||
|
|
|
@ -418,7 +418,8 @@ void Executor::generateCodeExpression (AstNode const* node) {
|
||||||
TRI_ASSERT(_buffer != nullptr);
|
TRI_ASSERT(_buffer != nullptr);
|
||||||
|
|
||||||
// write prologue
|
// write prologue
|
||||||
_buffer->appendText("(function (vars) { var aql = require(\"org/arangodb/aql\"); return ");
|
// this checks if global variable _AQL is set and populates if it not
|
||||||
|
_buffer->appendText("(function (vars) { if (_AQL === undefined) { _AQL = require(\"org/arangodb/aql\"); } return ");
|
||||||
|
|
||||||
generateCodeNode(node);
|
generateCodeNode(node);
|
||||||
|
|
||||||
|
@ -509,7 +510,7 @@ void Executor::generateCodeUnaryOperator (AstNode const* node) {
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer->appendText("aql.", 4);
|
_buffer->appendText("_AQL.", 5);
|
||||||
_buffer->appendText((*it).second);
|
_buffer->appendText((*it).second);
|
||||||
_buffer->appendChar('(');
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
|
@ -535,7 +536,7 @@ void Executor::generateCodeBinaryOperator (AstNode const* node) {
|
||||||
bool wrap = (node->type == NODE_TYPE_OPERATOR_BINARY_AND ||
|
bool wrap = (node->type == NODE_TYPE_OPERATOR_BINARY_AND ||
|
||||||
node->type == NODE_TYPE_OPERATOR_BINARY_OR);
|
node->type == NODE_TYPE_OPERATOR_BINARY_OR);
|
||||||
|
|
||||||
_buffer->appendText("aql.", 4);
|
_buffer->appendText("_AQL.", 5);
|
||||||
_buffer->appendText((*it).second);
|
_buffer->appendText((*it).second);
|
||||||
_buffer->appendChar('(');
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
|
@ -570,7 +571,7 @@ void Executor::generateCodeTernaryOperator (AstNode const* node) {
|
||||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "function not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
_buffer->appendText("aql.", 4);
|
_buffer->appendText("_AQL.", 5);
|
||||||
_buffer->appendText((*it).second);
|
_buffer->appendText((*it).second);
|
||||||
_buffer->appendChar('(');
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
|
@ -622,7 +623,7 @@ void Executor::generateCodeCollection (AstNode const* node) {
|
||||||
|
|
||||||
char const* name = node->getStringValue();
|
char const* name = node->getStringValue();
|
||||||
|
|
||||||
_buffer->appendText("aql.GET_DOCUMENTS(");
|
_buffer->appendText("_AQL.GET_DOCUMENTS(");
|
||||||
generateCodeString(name);
|
generateCodeString(name);
|
||||||
_buffer->appendChar(')');
|
_buffer->appendChar(')');
|
||||||
}
|
}
|
||||||
|
@ -641,7 +642,7 @@ void Executor::generateCodeFunctionCall (AstNode const* node) {
|
||||||
TRI_ASSERT(args != nullptr);
|
TRI_ASSERT(args != nullptr);
|
||||||
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
||||||
|
|
||||||
_buffer->appendText("aql.", 4);
|
_buffer->appendText("_AQL.", 5);
|
||||||
_buffer->appendText(func->internalName);
|
_buffer->appendText(func->internalName);
|
||||||
_buffer->appendChar('(');
|
_buffer->appendChar('(');
|
||||||
|
|
||||||
|
@ -693,7 +694,7 @@ void Executor::generateCodeUserFunctionCall (AstNode const* node) {
|
||||||
TRI_ASSERT(args != nullptr);
|
TRI_ASSERT(args != nullptr);
|
||||||
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
TRI_ASSERT(args->type == NODE_TYPE_LIST);
|
||||||
|
|
||||||
_buffer->appendText("aql.FCALL_USER(");
|
_buffer->appendText("_AQL.FCALL_USER(");
|
||||||
generateCodeString(name);
|
generateCodeString(name);
|
||||||
_buffer->appendText(",[", 2);
|
_buffer->appendText(",[", 2);
|
||||||
|
|
||||||
|
@ -750,7 +751,7 @@ void Executor::generateCodeRange (AstNode const* node) {
|
||||||
TRI_ASSERT(node != nullptr);
|
TRI_ASSERT(node != nullptr);
|
||||||
TRI_ASSERT(node->numMembers() == 2);
|
TRI_ASSERT(node->numMembers() == 2);
|
||||||
|
|
||||||
_buffer->appendText("aql.AQL_RANGE(");
|
_buffer->appendText("_AQL.AQL_RANGE(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendChar(',');
|
_buffer->appendChar(',');
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
|
@ -765,7 +766,7 @@ void Executor::generateCodeNamedAccess (AstNode const* node) {
|
||||||
TRI_ASSERT(node != nullptr);
|
TRI_ASSERT(node != nullptr);
|
||||||
TRI_ASSERT(node->numMembers() == 1);
|
TRI_ASSERT(node->numMembers() == 1);
|
||||||
|
|
||||||
_buffer->appendText("aql.DOCUMENT_MEMBER(");
|
_buffer->appendText("_AQL.DOCUMENT_MEMBER(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendChar(',');
|
_buffer->appendChar(',');
|
||||||
generateCodeString(node->getStringValue());
|
generateCodeString(node->getStringValue());
|
||||||
|
@ -780,7 +781,7 @@ void Executor::generateCodeBoundAccess (AstNode const* node) {
|
||||||
TRI_ASSERT(node != nullptr);
|
TRI_ASSERT(node != nullptr);
|
||||||
TRI_ASSERT(node->numMembers() == 2);
|
TRI_ASSERT(node->numMembers() == 2);
|
||||||
|
|
||||||
_buffer->appendText("aql.DOCUMENT_MEMBER(");
|
_buffer->appendText("_AQL.DOCUMENT_MEMBER(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendChar(',');
|
_buffer->appendChar(',');
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
|
@ -795,7 +796,7 @@ void Executor::generateCodeIndexedAccess (AstNode const* node) {
|
||||||
TRI_ASSERT(node != nullptr);
|
TRI_ASSERT(node != nullptr);
|
||||||
TRI_ASSERT(node->numMembers() == 2);
|
TRI_ASSERT(node->numMembers() == 2);
|
||||||
|
|
||||||
_buffer->appendText("aql.GET_INDEX(");
|
_buffer->appendText("_AQL.GET_INDEX(");
|
||||||
generateCodeNode(node->getMember(0));
|
generateCodeNode(node->getMember(0));
|
||||||
_buffer->appendChar(',');
|
_buffer->appendChar(',');
|
||||||
generateCodeNode(node->getMember(1));
|
generateCodeNode(node->getMember(1));
|
||||||
|
|
|
@ -2561,6 +2561,10 @@ void TRI_InitV8VocBridge (triagens::arango::ApplicationV8* applicationV8,
|
||||||
|
|
||||||
// whether or not statistics are enabled
|
// whether or not statistics are enabled
|
||||||
context->Global()->Set(TRI_V8_SYMBOL("ENABLE_STATISTICS"), v8::Boolean::New(TRI_ENABLE_STATISTICS), v8::ReadOnly);
|
context->Global()->Set(TRI_V8_SYMBOL("ENABLE_STATISTICS"), v8::Boolean::New(TRI_ENABLE_STATISTICS), v8::ReadOnly);
|
||||||
|
|
||||||
|
// a thread-global variable that will is supposed to contain the AQL module
|
||||||
|
// do not remove this, otherwise AQL queries will break
|
||||||
|
context->Global()->Set(TRI_V8_SYMBOL("_AQL"), v8::Undefined(), v8::DontEnum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
|
@ -357,7 +357,8 @@ function require (path) {
|
||||||
id: id,
|
id: id,
|
||||||
path: normalizeModuleName(path + "/.."),
|
path: normalizeModuleName(path + "/.."),
|
||||||
origin: path2FileUri(filename),
|
origin: path2FileUri(filename),
|
||||||
type: type };
|
type: type
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to append ".js"
|
// try to append ".js"
|
||||||
|
@ -379,7 +380,8 @@ function require (path) {
|
||||||
id: path,
|
id: path,
|
||||||
path: normalizeModuleName(path + "/.."),
|
path: normalizeModuleName(path + "/.."),
|
||||||
origin: path2FileUri(agumented),
|
origin: path2FileUri(agumented),
|
||||||
type: "json" };
|
type: "json"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to append ".coffee"
|
// try to append ".coffee"
|
||||||
|
@ -390,7 +392,8 @@ function require (path) {
|
||||||
id: path,
|
id: path,
|
||||||
path: normalizeModuleName(path + "/.."),
|
path: normalizeModuleName(path + "/.."),
|
||||||
origin: path2FileUri(agumented),
|
origin: path2FileUri(agumented),
|
||||||
type: "coffee" };
|
type: "coffee"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe this is a directory with an index file
|
// maybe this is a directory with an index file
|
||||||
|
@ -402,7 +405,8 @@ function require (path) {
|
||||||
id: fs.join(path, "index"),
|
id: fs.join(path, "index"),
|
||||||
path: path,
|
path: path,
|
||||||
origin: path2FileUri(agumented),
|
origin: path2FileUri(agumented),
|
||||||
type: "js" };
|
type: "js"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@ function StatementSuite () {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
st.parse();
|
st.parse();
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
assertEqual(ERRORS.ERROR_QUERY_PARSE.code, e.errorNum);
|
assertEqual(ERRORS.ERROR_QUERY_PARSE.code, e.errorNum);
|
||||||
|
@ -146,6 +147,7 @@ function StatementSuite () {
|
||||||
|
|
||||||
assertEqual([ "users" ], result.collections);
|
assertEqual([ "users" ], result.collections);
|
||||||
assertEqual([ ], result.bindVars);
|
assertEqual([ ], result.bindVars);
|
||||||
|
assertTrue(result.hasOwnProperty("ast"));
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -158,6 +160,7 @@ function StatementSuite () {
|
||||||
|
|
||||||
assertEqual([ "friends", "users" ], result.collections.sort());
|
assertEqual([ "friends", "users" ], result.collections.sort());
|
||||||
assertEqual([ ], result.bindVars);
|
assertEqual([ ], result.bindVars);
|
||||||
|
assertTrue(result.hasOwnProperty("ast"));
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -170,6 +173,7 @@ function StatementSuite () {
|
||||||
|
|
||||||
assertEqual([ ], result.collections);
|
assertEqual([ ], result.collections);
|
||||||
assertEqual([ "@users", "name" ], result.bindVars.sort());
|
assertEqual([ "@users", "name" ], result.bindVars.sort());
|
||||||
|
assertTrue(result.hasOwnProperty("ast"));
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -182,6 +186,185 @@ function StatementSuite () {
|
||||||
|
|
||||||
assertEqual([ "friends" ], result.collections);
|
assertEqual([ "friends" ], result.collections);
|
||||||
assertEqual([ "@users", "name" ], result.bindVars.sort());
|
assertEqual([ "@users", "name" ], result.bindVars.sort());
|
||||||
|
assertTrue(result.hasOwnProperty("ast"));
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test explain method
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainError : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "for u in" });
|
||||||
|
|
||||||
|
try {
|
||||||
|
st.explain();
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
assertEqual(ERRORS.ERROR_QUERY_PARSE.code, e.errorNum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test explain method
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainOk : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN 1..10 RETURN i" });
|
||||||
|
var result = st.explain();
|
||||||
|
|
||||||
|
assertEqual([ ], result.warnings);
|
||||||
|
assertTrue(result.hasOwnProperty("plan"));
|
||||||
|
assertFalse(result.hasOwnProperty("plans"));
|
||||||
|
|
||||||
|
var plan = result.plan;
|
||||||
|
assertTrue(plan.hasOwnProperty("estimatedCost"));
|
||||||
|
assertTrue(plan.hasOwnProperty("rules"));
|
||||||
|
assertEqual([ ], plan.rules);
|
||||||
|
assertTrue(plan.hasOwnProperty("nodes"));
|
||||||
|
assertTrue(plan.hasOwnProperty("collections"));
|
||||||
|
assertEqual([ ], plan.collections);
|
||||||
|
assertTrue(plan.hasOwnProperty("variables"));
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test explain method
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainAllPlans : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN 1..10 RETURN i" });
|
||||||
|
var result = st.explain({ allPlans: true });
|
||||||
|
|
||||||
|
assertEqual([ ], result.warnings);
|
||||||
|
assertFalse(result.hasOwnProperty("plan"));
|
||||||
|
assertTrue(result.hasOwnProperty("plans"));
|
||||||
|
|
||||||
|
assertEqual(1, result.plans.length);
|
||||||
|
var plan = result.plans[0];
|
||||||
|
assertTrue(plan.hasOwnProperty("estimatedCost"));
|
||||||
|
assertTrue(plan.hasOwnProperty("rules"));
|
||||||
|
assertEqual([ ], plan.rules);
|
||||||
|
assertTrue(plan.hasOwnProperty("nodes"));
|
||||||
|
assertTrue(plan.hasOwnProperty("collections"));
|
||||||
|
assertEqual([ ], plan.collections);
|
||||||
|
assertTrue(plan.hasOwnProperty("variables"));
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test explain method, bind variables
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainBindMissing : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN @@list FILTER i == @value RETURN i" });
|
||||||
|
try {
|
||||||
|
st.explain();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
assertEqual(ERRORS.ERROR_QUERY_BIND_PARAMETER_MISSING.code, e.errorNum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test explain method, bind variables
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainBindInvalidType : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN @@list RETURN i" });
|
||||||
|
st.bind("@list", [ 1, 2, 3 ]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
st.explain();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
assertEqual(ERRORS.ERROR_QUERY_BIND_PARAMETER_TYPE.code, e.errorNum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test explain method, bind variables
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainBindInvalid : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN @list FILTER i == @value RETURN i" });
|
||||||
|
st.bind("list", [ 1, 2, 3 ]);
|
||||||
|
st.bind("value", 3);
|
||||||
|
st.bind("foo", "bar");
|
||||||
|
|
||||||
|
try {
|
||||||
|
st.explain();
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
assertEqual(ERRORS.ERROR_QUERY_BIND_PARAMETER_UNDECLARED.code, e.errorNum);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test bind method, bind variables
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainBind : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN @list FILTER i == @value RETURN i" });
|
||||||
|
st.bind("list", [ 1, 2, 3 ]);
|
||||||
|
st.bind("value", 3);
|
||||||
|
var result = st.explain();
|
||||||
|
|
||||||
|
assertEqual([ ], result.warnings);
|
||||||
|
assertTrue(result.hasOwnProperty("plan"));
|
||||||
|
assertFalse(result.hasOwnProperty("plans"));
|
||||||
|
|
||||||
|
var plan = result.plan;
|
||||||
|
assertTrue(plan.hasOwnProperty("estimatedCost"));
|
||||||
|
assertTrue(plan.hasOwnProperty("rules"));
|
||||||
|
assertEqual([ ], plan.rules);
|
||||||
|
assertTrue(plan.hasOwnProperty("nodes"));
|
||||||
|
assertTrue(plan.hasOwnProperty("collections"));
|
||||||
|
assertEqual([ ], plan.collections);
|
||||||
|
assertTrue(plan.hasOwnProperty("variables"));
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test bind method, bind variables
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainBindCollection : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN @@collection RETURN i" });
|
||||||
|
st.bind("@collection", "_users");
|
||||||
|
var result = st.explain();
|
||||||
|
|
||||||
|
assertEqual([ ], result.warnings);
|
||||||
|
assertTrue(result.hasOwnProperty("plan"));
|
||||||
|
assertFalse(result.hasOwnProperty("plans"));
|
||||||
|
|
||||||
|
var plan = result.plan;
|
||||||
|
assertTrue(plan.hasOwnProperty("estimatedCost"));
|
||||||
|
assertTrue(plan.hasOwnProperty("rules"));
|
||||||
|
assertEqual([ ], plan.rules);
|
||||||
|
assertTrue(plan.hasOwnProperty("nodes"));
|
||||||
|
assertTrue(plan.hasOwnProperty("collections"));
|
||||||
|
assertEqual([ { "name" : "_users", "type" : "read" } ], plan.collections);
|
||||||
|
assertTrue(plan.hasOwnProperty("variables"));
|
||||||
|
},
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief test bind method, bind variables
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
testExplainBindWarnings : function () {
|
||||||
|
var st = new ArangoStatement(db, { query : "FOR i IN 1..10 RETURN 1 / 0" });
|
||||||
|
var result = st.explain();
|
||||||
|
|
||||||
|
assertEqual(1, result.warnings.length);
|
||||||
|
assertEqual(ERRORS.ERROR_QUERY_DIVISION_BY_ZERO.code, result.warnings[0].code);
|
||||||
|
assertTrue(result.hasOwnProperty("plan"));
|
||||||
|
assertFalse(result.hasOwnProperty("plans"));
|
||||||
|
|
||||||
|
var plan = result.plan;
|
||||||
|
assertTrue(plan.hasOwnProperty("estimatedCost"));
|
||||||
|
assertTrue(plan.hasOwnProperty("rules"));
|
||||||
|
assertTrue(plan.hasOwnProperty("nodes"));
|
||||||
|
assertTrue(plan.hasOwnProperty("collections"));
|
||||||
|
assertEqual([ ], plan.collections);
|
||||||
|
assertTrue(plan.hasOwnProperty("variables"));
|
||||||
},
|
},
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -192,6 +375,7 @@ function StatementSuite () {
|
||||||
var st = new ArangoStatement(db, { query : "for u in" });
|
var st = new ArangoStatement(db, { query : "for u in" });
|
||||||
try {
|
try {
|
||||||
result = st.execute();
|
result = st.execute();
|
||||||
|
fail();
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
assertEqual(ERRORS.ERROR_QUERY_PARSE.code, e.errorNum);
|
assertEqual(ERRORS.ERROR_QUERY_PARSE.code, e.errorNum);
|
||||||
|
|
|
@ -43,19 +43,17 @@ var colName = "perf_" + ruleName.replace(/-/g, "_");
|
||||||
var theCollection;
|
var theCollection;
|
||||||
|
|
||||||
var dbdApi = function (query, plan, bindVars) {
|
var dbdApi = function (query, plan, bindVars) {
|
||||||
db._query(query, bindVars);
|
db._query(query, bindVars).toArray();
|
||||||
return {};
|
return {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
var setUp = function (options) {
|
var setUp = function (options) {
|
||||||
var loopto = options.dbcols;
|
var loopto = options.dbcols;
|
||||||
var contentmultipy = options.contentmultiply;
|
var contentmultiply = options.contentmultiply;
|
||||||
|
|
||||||
|
var Content = Array(contentmultiply).join('abcdefghijklmnopqrstuvwxyz')
|
||||||
|
|
||||||
var Content = [];
|
|
||||||
for (j = 0; j < contentmultipy; j ++ ) {
|
|
||||||
Content = Content.concat(['abcdefghijklmnopqrstuvwxyz']);
|
|
||||||
}
|
|
||||||
internal.db._drop(colName);
|
internal.db._drop(colName);
|
||||||
theCollection = internal.db._create(colName);
|
theCollection = internal.db._create(colName);
|
||||||
var i, j;
|
var i, j;
|
||||||
|
@ -75,6 +73,7 @@ var setUp = function (options) {
|
||||||
|
|
||||||
var tearDown = function () {
|
var tearDown = function () {
|
||||||
internal.db._drop(colName);
|
internal.db._drop(colName);
|
||||||
|
require("internal").wait(0);
|
||||||
theCollection = null;
|
theCollection = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -103,6 +102,15 @@ var testNonIndexedPartialRead = function (testParams, testMethodStr, testMethod,
|
||||||
return testMethod.executeQuery(query, {}, {});
|
return testMethod.executeQuery(query, {}, {});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Testcase: dump 10% of a table without using an index
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var testNonIndexedPartialReadCalcJS = function (testParams, testMethodStr, testMethod, runOptions) {
|
||||||
|
var tenPercent = (runOptions.dbcols / 10) * 9;
|
||||||
|
var query = "FOR i IN " + colName + " FILTER i.Key + 1 > " + tenPercent + " RETURN i";
|
||||||
|
return testMethod.executeQuery(query, {}, {});
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Testcase: dump a full table sorted by an unindexed key.
|
/// @brief Testcase: dump a full table sorted by an unindexed key.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -119,6 +127,33 @@ var testIndexedFullSort = function (testParams, testMethodStr, testMethod) {
|
||||||
return testMethod.executeQuery(query, {}, {});
|
return testMethod.executeQuery(query, {}, {});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Testcase: dump a full table sorted by an indexed key.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var testIndexedFullSortReverse = function (testParams, testMethodStr, testMethod) {
|
||||||
|
var query = "FOR i IN " + colName + " SORT i.indexedKey DESC RETURN i";
|
||||||
|
return testMethod.executeQuery(query, {}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Testcase: dump a full table sorted by an indexed key - use filter
|
||||||
|
/// so the old also has
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var testIndexedFullSortFilter = function (testParams, testMethodStr, testMethod) {
|
||||||
|
var query = "FOR i IN " + colName + " FILTER i.indexedKey > 0 SORT i.indexedKey RETURN i";
|
||||||
|
return testMethod.executeQuery(query, {}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief Testcase: dump a full table sorted by an indexed key - use filter
|
||||||
|
/// so the old also has
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
var testIndexedFullSortReverseFilter = function (testParams, testMethodStr, testMethod) {
|
||||||
|
var query = "FOR i IN " + colName + " FILTER i.indexedKey > 0 SORT i.indexedKey DESC RETURN i";
|
||||||
|
return testMethod.executeQuery(query, {}, {});
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief Simple join testsuite
|
/// @brief Simple join testsuite
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -126,12 +161,20 @@ var testIndexedFullSort = function (testParams, testMethodStr, testMethod) {
|
||||||
var testSuite = [
|
var testSuite = [
|
||||||
{ name: "setup", setUp: setUp, teardown: null, params: null, func: null},
|
{ name: "setup", setUp: setUp, teardown: null, params: null, func: null},
|
||||||
|
|
||||||
|
|
||||||
{ name: "testFullRead", func: testFullRead},
|
{ name: "testFullRead", func: testFullRead},
|
||||||
|
|
||||||
{ name: "testNonIndexedPartialRead", func: testNonIndexedPartialRead},
|
{ name: "testNonIndexedPartialRead", func: testNonIndexedPartialRead},
|
||||||
|
|
||||||
|
{ name: "testNonIndexedPartialReadCalcJS", func: testNonIndexedPartialReadCalcJS},
|
||||||
|
|
||||||
{ name: "testNonIndexedFullSort", func: testNonIndexedFullSort},
|
{ name: "testNonIndexedFullSort", func: testNonIndexedFullSort},
|
||||||
{ name: "testIndexedFullSort", func: testIndexedFullSort},
|
{ name: "testIndexedFullSort", func: testIndexedFullSort},
|
||||||
|
|
||||||
|
{ name: "testIndexedFullSortReverse", func: testIndexedFullSortReverse},
|
||||||
|
|
||||||
|
{ name: "testIndexedFullSortFilter", func: testIndexedFullSortFilter},
|
||||||
|
{ name: "testIndexedFullSortReverseFilter", func: testIndexedFullSortReverseFilter},
|
||||||
|
|
||||||
{ name: "teardown", setUp: null, teardown: tearDown, params: null, func: null}
|
{ name: "teardown", setUp: null, teardown: tearDown, params: null, func: null}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -141,8 +184,8 @@ var testSuite = [
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var k, l;
|
var k, l;
|
||||||
for (k = 4; k < 10; k++) {
|
for (k = 1; k < 22; k+=5) {
|
||||||
for (l = 4; l < 10; l++) {
|
for (l = 1; l < 22; l+=5) {
|
||||||
var testOptions = {
|
var testOptions = {
|
||||||
enableIndex: true,
|
enableIndex: true,
|
||||||
dbcols: 10000 * k,
|
dbcols: 10000 * k,
|
||||||
|
|
Loading…
Reference in New Issue