mirror of https://gitee.com/bigwinds/arangodb
added waitForSync parameter, added JavaScript tests
This commit is contained in:
parent
b0f717ccb8
commit
41a622652b
|
@ -46,14 +46,6 @@
|
|||
#include "BasicsC/locks-win32.h"
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- POSIX SPINS
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
#ifdef TRI_HAVE_POSIX_THREADS
|
||||
#include "BasicsC/locks-posix.h"
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- MAC OS X SPIN
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
@ -915,9 +915,11 @@ void QLOptimizeFreeRangeVector (TRI_vector_pointer_t* vector) {
|
|||
if (range->_valueType == RANGE_TYPE_STRING) {
|
||||
if (range->_minValue._stringValue) {
|
||||
TRI_FreeString(range->_minValue._stringValue);
|
||||
range->_minValue._stringValue = 0;
|
||||
}
|
||||
if (range->_maxValue._stringValue) {
|
||||
TRI_FreeString(range->_maxValue._stringValue);
|
||||
range->_maxValue._stringValue = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1434,7 +1436,7 @@ static QL_optimize_range_t* QLOptimizeCreateRange (TRI_query_node_t* memberNode,
|
|||
}
|
||||
else if (range->_valueType == RANGE_TYPE_STRING) {
|
||||
range->_minValue._stringValue = TRI_DuplicateString(valueNode->_value._stringValue);
|
||||
range->_maxValue._stringValue = range->_minValue._stringValue;
|
||||
range->_maxValue._stringValue = TRI_DuplicateString(valueNode->_value._stringValue);
|
||||
}
|
||||
else if (range->_valueType == RANGE_TYPE_JSON) {
|
||||
documentJs = TRI_InitQueryJavascript();
|
||||
|
@ -1446,7 +1448,7 @@ static QL_optimize_range_t* QLOptimizeCreateRange (TRI_query_node_t* memberNode,
|
|||
}
|
||||
TRI_ConvertQueryJavascript(documentJs, valueNode, bindParameters);
|
||||
range->_minValue._stringValue = TRI_DuplicateString(documentJs->_buffer->_buffer);
|
||||
range->_maxValue._stringValue = range->_minValue._stringValue;
|
||||
range->_maxValue._stringValue = TRI_DuplicateString(documentJs->_buffer->_buffer);
|
||||
TRI_FreeQueryJavascript(documentJs);
|
||||
if (!range->_minValue._stringValue) {
|
||||
TRI_FreeStringBuffer(name);
|
||||
|
|
697
QL/parser.c
697
QL/parser.c
File diff suppressed because it is too large
Load Diff
24
QL/parser.y
24
QL/parser.y
|
@ -561,6 +561,7 @@ named_attribute:
|
|||
ABORT_IF_OOM($1);
|
||||
ABORT_IF_OOM($3);
|
||||
str->_value._stringValue = TRI_ParseQueryRegisterString(template_, TRI_UnescapeUtf8String($1, strlen($1), &outLength));
|
||||
ABORT_IF_OOM(str->_value._stringValue);
|
||||
|
||||
$$ = TRI_ParseQueryCreateNode(template_, TRI_QueryNodeValueNamedValue);
|
||||
ABORT_IF_OOM($$);
|
||||
|
@ -574,6 +575,7 @@ named_attribute:
|
|||
ABORT_IF_OOM($1);
|
||||
ABORT_IF_OOM($3);
|
||||
str->_value._stringValue = TRI_ParseQueryRegisterString(template_, TRI_UnescapeUtf8String($1 + 1, strlen($1) - 2, &outLength));
|
||||
ABORT_IF_OOM(str->_value._stringValue);
|
||||
|
||||
$$ = TRI_ParseQueryCreateNode(template_, TRI_QueryNodeValueNamedValue);
|
||||
ABORT_IF_OOM($$);
|
||||
|
@ -613,7 +615,6 @@ collection_reference:
|
|||
}
|
||||
;
|
||||
|
||||
|
||||
collection_name:
|
||||
IDENTIFIER {
|
||||
$$ = TRI_ParseQueryCreateNode(template_, TRI_QueryNodeValueIdentifier);
|
||||
|
@ -627,6 +628,7 @@ collection_name:
|
|||
ABORT_IF_OOM($$);
|
||||
ABORT_IF_OOM($1);
|
||||
$$->_value._stringValue = TRI_ParseQueryRegisterString(template_, TRI_UnescapeUtf8String($1 + 1, strlen($1) - 2, &outLength));
|
||||
ABORT_IF_OOM($$->_value._stringValue);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -643,6 +645,7 @@ collection_alias:
|
|||
ABORT_IF_OOM($$);
|
||||
ABORT_IF_OOM($1);
|
||||
$$->_value._stringValue = TRI_ParseQueryRegisterString(template_, TRI_UnescapeUtf8String($1 + 1, strlen($1) - 2, &outLength));
|
||||
ABORT_IF_OOM($$->_value._stringValue);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -775,6 +778,15 @@ object_access:
|
|||
name->_value._stringValue = $2;
|
||||
TRI_ParseQueryContextAddElement(template_, name);
|
||||
}
|
||||
| '.' QUOTED_IDENTIFIER {
|
||||
TRI_query_node_t* name = TRI_ParseQueryCreateNode(template_, TRI_QueryNodeValueIdentifier);
|
||||
size_t outLength;
|
||||
ABORT_IF_OOM(name);
|
||||
ABORT_IF_OOM($2);
|
||||
name->_value._stringValue = TRI_ParseQueryRegisterString(template_, TRI_UnescapeUtf8String($2 + 1, strlen($2) - 2, &outLength));
|
||||
ABORT_IF_OOM(name->_value._stringValue);
|
||||
TRI_ParseQueryContextAddElement(template_, name);
|
||||
}
|
||||
| '.' function_call {
|
||||
ABORT_IF_OOM($2);
|
||||
TRI_ParseQueryContextAddElement(template_, $2);
|
||||
|
@ -786,6 +798,15 @@ object_access:
|
|||
name->_value._stringValue = $3;
|
||||
TRI_ParseQueryContextAddElement(template_, name);
|
||||
}
|
||||
| object_access '.' QUOTED_IDENTIFIER {
|
||||
TRI_query_node_t* name = TRI_ParseQueryCreateNode(template_, TRI_QueryNodeValueIdentifier);
|
||||
size_t outLength;
|
||||
ABORT_IF_OOM(name);
|
||||
ABORT_IF_OOM($3);
|
||||
name->_value._stringValue = TRI_ParseQueryRegisterString(template_, TRI_UnescapeUtf8String($3 + 1, strlen($3) - 2, &outLength));
|
||||
ABORT_IF_OOM(name->_value._stringValue);
|
||||
TRI_ParseQueryContextAddElement(template_, name);
|
||||
}
|
||||
| object_access '.' function_call {
|
||||
ABORT_IF_OOM($1);
|
||||
ABORT_IF_OOM($3);
|
||||
|
@ -1042,6 +1063,7 @@ atom:
|
|||
ABORT_IF_OOM($$);
|
||||
ABORT_IF_OOM($1);
|
||||
$$->_value._stringValue = TRI_ParseQueryRegisterString(template_, TRI_UnescapeUtf8String($1 + 1, strlen($1) - 2, &outLength));
|
||||
ABORT_IF_OOM($$->_value._stringValue);
|
||||
}
|
||||
| REAL {
|
||||
double d = TRI_DoubleString($1);
|
||||
|
|
|
@ -171,6 +171,10 @@ HttpHandler::status_e RestCollectionHandler::execute () {
|
|||
/// document. The "ETag" header field contains the revision of the newly created
|
||||
/// document.
|
||||
///
|
||||
/// If the collection parameter @LIT{waitForSync} is @LIT{false}, then a
|
||||
/// @LIT{HTTP 202} is returned in order to indicate that the document has been
|
||||
/// accepted but not yet stored.
|
||||
///
|
||||
/// If the @FA{collection-identifier} is unknown, then a @LIT{HTTP 404} is
|
||||
/// returned.
|
||||
///
|
||||
|
@ -227,6 +231,7 @@ bool RestCollectionHandler::createDocument () {
|
|||
|
||||
_documentCollection->beginWrite(_documentCollection);
|
||||
|
||||
bool waitForSync = _documentCollection->base._waitForSync;
|
||||
TRI_doc_mptr_t const* mptr = _documentCollection->createJson(_documentCollection, TRI_DOC_MARKER_DOCUMENT, json, 0, true);
|
||||
TRI_voc_did_t did = 0;
|
||||
TRI_voc_rid_t rid = 0;
|
||||
|
@ -241,7 +246,13 @@ bool RestCollectionHandler::createDocument () {
|
|||
// .............................................................................
|
||||
|
||||
if (mptr != 0) {
|
||||
generateCreated(_documentCollection->base._cid, did, rid);
|
||||
if (waitForSync) {
|
||||
generateCreated(_documentCollection->base._cid, did, rid);
|
||||
}
|
||||
else {
|
||||
generateAccepted(_documentCollection->base._cid, did, rid);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -162,6 +162,17 @@ void RestVocbaseBaseHandler::generateCreated (TRI_voc_cid_t cid, TRI_voc_did_t d
|
|||
response->setHeader("location", DOCUMENT_PATH + "/" + StringUtils::itoa(cid) + "/" + StringUtils::itoa(did));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates accepted message without content but a location header
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RestVocbaseBaseHandler::generateAccepted (TRI_voc_cid_t cid, TRI_voc_did_t did, TRI_voc_rid_t rid) {
|
||||
response = new HttpResponse(HttpResponse::ACCEPTED);
|
||||
|
||||
response->setHeader("ETag", "\"" + StringUtils::itoa(rid) + "\"");
|
||||
response->setHeader("location", DOCUMENT_PATH + "/" + StringUtils::itoa(cid) + "/" + StringUtils::itoa(did));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates collection not found error message
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -222,6 +222,12 @@ namespace triagens {
|
|||
|
||||
void generateCreated (TRI_voc_cid_t, TRI_voc_did_t, TRI_voc_rid_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates accepted message without content but a location header
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generateAccepted (TRI_voc_cid_t, TRI_voc_did_t, TRI_voc_rid_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates collection not found error message
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -668,7 +668,7 @@ void AvocadoServer::executeShell () {
|
|||
|
||||
V8LineEditor* console = new V8LineEditor(context, ".avocado");
|
||||
|
||||
console->open();
|
||||
console->open(true);
|
||||
|
||||
while (true) {
|
||||
while(! v8::V8::IdleNotification()) {
|
||||
|
@ -690,11 +690,16 @@ void AvocadoServer::executeShell () {
|
|||
console->addHistory(input);
|
||||
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
TRI_ExecuteStringVocBase(context, v8::String::New(input), name, true, true);
|
||||
|
||||
TRI_ExecuteStringVocBase(context, v8::String::New(input), name, true);
|
||||
TRI_FreeString(input);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
cout << TRI_StringifyV8Exception(&tryCatch);
|
||||
}
|
||||
}
|
||||
|
||||
console->close();
|
||||
|
||||
delete console;
|
||||
|
|
|
@ -137,6 +137,7 @@ string const& JSLoader::findScript (string const& name) {
|
|||
|
||||
bool JSLoader::loadScript (v8::Persistent<v8::Context> context, string const& name) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
findScript(name);
|
||||
|
||||
|
@ -146,11 +147,17 @@ bool JSLoader::loadScript (v8::Persistent<v8::Context> context, string const& na
|
|||
return false;
|
||||
}
|
||||
|
||||
return TRI_ExecuteStringVocBase(context,
|
||||
v8::String::New(i->second.c_str()),
|
||||
v8::String::New(name.c_str()),
|
||||
false,
|
||||
true);
|
||||
TRI_ExecuteStringVocBase(context,
|
||||
v8::String::New(i->second.c_str()),
|
||||
v8::String::New(name.c_str()),
|
||||
false);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
TRI_LogV8Exception(&tryCatch);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -158,6 +165,9 @@ bool JSLoader::loadScript (v8::Persistent<v8::Context> context, string const& na
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool JSLoader::loadAllScripts (v8::Persistent<v8::Context> context) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
if (_directory.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
@ -171,6 +181,7 @@ bool JSLoader::loadAllScripts (v8::Persistent<v8::Context> context) {
|
|||
|
||||
bool JSLoader::executeScript (v8::Persistent<v8::Context> context, string const& name) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
findScript(name);
|
||||
|
||||
|
@ -182,11 +193,17 @@ bool JSLoader::executeScript (v8::Persistent<v8::Context> context, string const&
|
|||
|
||||
string content = "(function() { " + i->second + "/* end-of-file '" + name + "' */ })()";
|
||||
|
||||
return TRI_ExecuteStringVocBase(context,
|
||||
v8::String::New(content.c_str()),
|
||||
v8::String::New(name.c_str()),
|
||||
false,
|
||||
true);
|
||||
TRI_ExecuteStringVocBase(context,
|
||||
v8::String::New(content.c_str()),
|
||||
v8::String::New(name.c_str()),
|
||||
false);
|
||||
|
||||
if (! tryCatch.HasCaught()) {
|
||||
TRI_LogV8Exception(&tryCatch);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -194,6 +211,9 @@ bool JSLoader::executeScript (v8::Persistent<v8::Context> context, string const&
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool JSLoader::executeAllScripts (v8::Persistent<v8::Context> context) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
if (_directory.empty()) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -504,7 +504,7 @@ HttpResponse* TRI_ExecuteActionVocBase (TRI_vocbase_t* vocbase,
|
|||
|
||||
// convert the result
|
||||
if (tryCatch.HasCaught()) {
|
||||
string msg = TRI_ReportV8Exception(&tryCatch);
|
||||
string msg = TRI_StringifyV8Exception(&tryCatch);
|
||||
|
||||
HttpResponse* response = new HttpResponse(HttpResponse::SERVER_ERROR);
|
||||
response->body().appendText(msg);
|
||||
|
|
|
@ -83,7 +83,7 @@ static void RunShell (v8::Handle<v8::Context> context) {
|
|||
|
||||
V8LineEditor* console = new V8LineEditor(context, ".avoc");
|
||||
|
||||
console->open();
|
||||
console->open(true);
|
||||
|
||||
while (true) {
|
||||
while(! V8::IdleNotification()) {
|
||||
|
@ -103,7 +103,7 @@ static void RunShell (v8::Handle<v8::Context> context) {
|
|||
|
||||
HandleScope scope;
|
||||
|
||||
TRI_ExecuteStringVocBase(context, String::New(input), name, true, true);
|
||||
TRI_ExecuteStringVocBase(context, String::New(input), name, true);
|
||||
TRI_FreeString(input);
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ static int RunMain (v8::Handle<v8::Context> context, int argc, char* argv[]) {
|
|||
v8::Handle<v8::String> source = v8::String::New(content);
|
||||
TRI_FreeString(content);
|
||||
|
||||
bool ok = TRI_ExecuteStringVocBase(context, source, filename, false, true);
|
||||
bool ok = TRI_ExecuteStringVocBase(context, source, filename, false);
|
||||
|
||||
if (! ok) {
|
||||
return 1;
|
||||
|
|
|
@ -94,9 +94,7 @@ typedef struct TRI_v8_global_s {
|
|||
JournalSizeKey(),
|
||||
ParametersKey(),
|
||||
ResponseCodeKey(),
|
||||
SyncAfterBytesKey(),
|
||||
SyncAfterObjectsKey(),
|
||||
SyncAfterTimeKey(),
|
||||
WaitForSyncKey(),
|
||||
DocumentIdRegex() {
|
||||
}
|
||||
|
||||
|
@ -417,22 +415,10 @@ typedef struct TRI_v8_global_s {
|
|||
v8::Persistent<v8::String> SuffixKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief "syncAfterBytes" key name
|
||||
/// @brief "waitForSync" key name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Persistent<v8::String> SyncAfterBytesKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief "syncAfterObjects" key name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Persistent<v8::String> SyncAfterObjectsKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief "syncAfterTime" key name
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
v8::Persistent<v8::String> SyncAfterTimeKey;
|
||||
v8::Persistent<v8::String> WaitForSyncKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -380,12 +380,14 @@ V8LineEditor::V8LineEditor (v8::Handle<v8::Context> context, string const& histo
|
|||
/// @brief line editor open
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool V8LineEditor::open () {
|
||||
bool V8LineEditor::open (const bool autoComplete) {
|
||||
rl_initialize();
|
||||
rl_attempted_completion_function = AttemptedCompletion;
|
||||
rl_completer_word_break_characters = WordBreakCharacters;
|
||||
if (autoComplete) {
|
||||
rl_attempted_completion_function = AttemptedCompletion;
|
||||
rl_completer_word_break_characters = WordBreakCharacters;
|
||||
|
||||
rl_bind_key('\t', rl_complete);
|
||||
rl_bind_key('\t', rl_complete);
|
||||
}
|
||||
|
||||
using_history();
|
||||
stifle_history(MAX_HISTORY_ENTRIES);
|
||||
|
|
|
@ -72,7 +72,7 @@ class V8LineEditor {
|
|||
/// @brief line editor open
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool open ();
|
||||
bool open (const bool);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief line editor shutdown
|
||||
|
|
125
V8/v8-utils.cpp
125
V8/v8-utils.cpp
|
@ -686,9 +686,10 @@ bool TRI_ExecuteOrderExecutionContext (TRI_js_exec_context_t context, int* r) {
|
|||
/// @brief reads/execute a file into/in the current context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool LoadJavaScriptFile (v8::Handle<v8::Context> context, char const* filename, bool execute) {
|
||||
static bool LoadJavaScriptFile (v8::Handle<v8::Context> context,
|
||||
char const* filename,
|
||||
bool execute) {
|
||||
v8::HandleScope handleScope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
char* content = TRI_SlurpFile(filename);
|
||||
|
||||
|
@ -718,8 +719,6 @@ static bool LoadJavaScriptFile (v8::Handle<v8::Context> context, char const* fil
|
|||
|
||||
// compilation failed, print errors that happened during compilation
|
||||
if (script.IsEmpty()) {
|
||||
LOG_ERROR("cannot compile java script file '%s'", filename);
|
||||
TRI_ReportV8Exception(&tryCatch);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -727,17 +726,10 @@ static bool LoadJavaScriptFile (v8::Handle<v8::Context> context, char const* fil
|
|||
v8::Handle<v8::Value> result = script->Run();
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
assert(tryCatch.HasCaught());
|
||||
|
||||
// print errors that happened during execution
|
||||
LOG_ERROR("cannot execute java script file '%s'", filename);
|
||||
TRI_ReportV8Exception(&tryCatch);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_TRACE("loaded java script file: '%s'", filename);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -746,6 +738,7 @@ static bool LoadJavaScriptFile (v8::Handle<v8::Context> context, char const* fil
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool LoadJavaScriptDirectory (v8::Handle<v8::Context> context, char const* path, bool execute) {
|
||||
v8::HandleScope scope;
|
||||
TRI_vector_string_t files;
|
||||
bool result;
|
||||
regex_t re;
|
||||
|
@ -760,6 +753,7 @@ static bool LoadJavaScriptDirectory (v8::Handle<v8::Context> context, char const
|
|||
result = true;
|
||||
|
||||
for (i = 0; i < files._length; ++i) {
|
||||
v8::TryCatch tryCatch;
|
||||
bool ok;
|
||||
char const* filename;
|
||||
char* full;
|
||||
|
@ -771,12 +765,14 @@ static bool LoadJavaScriptDirectory (v8::Handle<v8::Context> context, char const
|
|||
}
|
||||
|
||||
full = TRI_Concatenate2File(path, filename);
|
||||
|
||||
ok = LoadJavaScriptFile(context, full, execute);
|
||||
|
||||
TRI_FreeString(full);
|
||||
|
||||
result = result && ok;
|
||||
|
||||
if (! ok) {
|
||||
TRI_LogV8Exception(&tryCatch);
|
||||
}
|
||||
}
|
||||
|
||||
TRI_DestroyVectorString(&files);
|
||||
|
@ -813,7 +809,6 @@ static bool LoadJavaScriptDirectory (v8::Handle<v8::Context> context, char const
|
|||
|
||||
static v8::Handle<v8::Value> JS_Execute (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
size_t i;
|
||||
|
||||
// extract arguments
|
||||
|
@ -868,32 +863,24 @@ static v8::Handle<v8::Value> JS_Execute (v8::Arguments const& argv) {
|
|||
|
||||
// compilation failed, print errors that happened during compilation
|
||||
if (script.IsEmpty()) {
|
||||
assert(tryCatch.HasCaught());
|
||||
|
||||
TRI_PrintV8Exception(&tryCatch);
|
||||
|
||||
if (useSandbox) {
|
||||
context->DetachGlobal();
|
||||
context->Exit();
|
||||
}
|
||||
|
||||
return scope.Close(tryCatch.ReThrow());
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
// compilation succeeded, run the script
|
||||
v8::Handle<v8::Value> result = script->Run();
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
assert(tryCatch.HasCaught());
|
||||
|
||||
TRI_PrintV8Exception(&tryCatch);
|
||||
|
||||
if (useSandbox) {
|
||||
context->DetachGlobal();
|
||||
context->Exit();
|
||||
}
|
||||
|
||||
return scope.Close(tryCatch.ReThrow());
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
// copy result back into the sandbox
|
||||
|
@ -941,7 +928,6 @@ static v8::Handle<v8::Value> JS_Execute (v8::Arguments const& argv) {
|
|||
|
||||
static v8::Handle<v8::Value> JS_Load (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
// extract arguments
|
||||
if (argv.Length() != 1) {
|
||||
|
@ -960,11 +946,10 @@ static v8::Handle<v8::Value> JS_Load (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(v8::String::New(TRI_last_error())));
|
||||
}
|
||||
|
||||
bool ok = TRI_ExecuteStringVocBase(v8::Context::GetCurrent(), v8::String::New(content), argv[0], false, true);
|
||||
|
||||
TRI_ExecuteStringVocBase(v8::Context::GetCurrent(), v8::String::New(content), argv[0], false);
|
||||
TRI_FreeString(content);
|
||||
|
||||
return scope.Close(ok ? v8::True() : v8::False());
|
||||
return scope.Close(v8::Undefined());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1400,7 +1385,7 @@ void TRI_AugmentObject (v8::Handle<v8::Value> value, TRI_json_t const* json) {
|
|||
/// @brief reports an exception
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
string TRI_ReportV8Exception (v8::TryCatch* tryCatch) {
|
||||
string TRI_StringifyV8Exception (v8::TryCatch* tryCatch) {
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
v8::String::Utf8Value exception(tryCatch->Exception());
|
||||
|
@ -1411,12 +1396,10 @@ string TRI_ReportV8Exception (v8::TryCatch* tryCatch) {
|
|||
// V8 didn't provide any extra information about this error; just print the exception.
|
||||
if (message.IsEmpty()) {
|
||||
if (exceptionString == 0) {
|
||||
LOG_ERROR("JavaScript exception");
|
||||
result = "JavaScript exception";
|
||||
result = "JavaScript exception\n";
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("JavaScript exception: %s", exceptionString);
|
||||
result = "JavaScript exception: " + string(exceptionString);
|
||||
result = "JavaScript exception: " + string(exceptionString) + "\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -1424,35 +1407,51 @@ string TRI_ReportV8Exception (v8::TryCatch* tryCatch) {
|
|||
const char* filenameString = *filename;
|
||||
int linenum = message->GetLineNumber();
|
||||
int start = message->GetStartColumn() + 1;
|
||||
int end = message->GetEndColumn();
|
||||
|
||||
if (filenameString == 0) {
|
||||
if (exceptionString == 0) {
|
||||
LOG_ERROR("JavaScript exception");
|
||||
result = "JavaScript exception";
|
||||
result = "JavaScript exception\n";
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("JavaScript exception: %s", exceptionString);
|
||||
result = "JavaScript exception: " + string(exceptionString);
|
||||
result = "JavaScript exception: " + string(exceptionString) + "\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (exceptionString == 0) {
|
||||
LOG_ERROR("JavaScript exception in file '%s' at %d,%d", filenameString, linenum, start);
|
||||
result = "JavaScript exception in file '" + string(filenameString) + "' at "
|
||||
+ StringUtils::itoa(linenum) + "," + StringUtils::itoa(start);
|
||||
+ StringUtils::itoa(linenum) + "," + StringUtils::itoa(start) + "\n";
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("JavaScript exception in file '%s' at %d,%d: %s", filenameString, linenum, start, exceptionString);
|
||||
result = "JavaScript exception in file '" + string(filenameString) + "' at "
|
||||
+ StringUtils::itoa(linenum) + "," + StringUtils::itoa(start)
|
||||
+ ": " + exceptionString;
|
||||
+ ": " + exceptionString + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
v8::String::Utf8Value sourceline(message->GetSourceLine());
|
||||
|
||||
if (*sourceline) {
|
||||
string l = *sourceline;
|
||||
|
||||
result += "!" + l + "\n";
|
||||
|
||||
if (1 < start) {
|
||||
l = string(start - 1, ' ');
|
||||
}
|
||||
else {
|
||||
l = "";
|
||||
}
|
||||
|
||||
l += string((size_t)(end - start + 1), '^');
|
||||
|
||||
result += "!" + l + "\n";
|
||||
}
|
||||
|
||||
v8::String::Utf8Value stacktrace(tryCatch->StackTrace());
|
||||
|
||||
if (*stacktrace && stacktrace.length() > 0) {
|
||||
LOG_DEBUG("stacktrace: %s", *stacktrace);
|
||||
result += "stacktrace: " + string(*stacktrace) + "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1463,7 +1462,7 @@ string TRI_ReportV8Exception (v8::TryCatch* tryCatch) {
|
|||
/// @brief prints an exception and stacktrace
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_PrintV8Exception (v8::TryCatch* tryCatch) {
|
||||
void TRI_LogV8Exception (v8::TryCatch* tryCatch) {
|
||||
v8::HandleScope handle_scope;
|
||||
|
||||
v8::String::Utf8Value exception(tryCatch->Exception());
|
||||
|
@ -1488,18 +1487,18 @@ void TRI_PrintV8Exception (v8::TryCatch* tryCatch) {
|
|||
|
||||
if (filenameString == 0) {
|
||||
if (exceptionString == 0) {
|
||||
LOG_ERROR("exception");
|
||||
LOG_ERROR("JavaScript exception");
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("exception: %s", exceptionString);
|
||||
LOG_ERROR("JavaScript exception: %s", exceptionString);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (exceptionString == 0) {
|
||||
LOG_ERROR("exception in file '%s' at %d,%d", filenameString, linenum, start);
|
||||
LOG_ERROR("JavaScript exception in file '%s' at %d,%d", filenameString, linenum, start);
|
||||
}
|
||||
else {
|
||||
LOG_ERROR("exception in file '%s' at %d,%d: %s", filenameString, linenum, start, exceptionString);
|
||||
LOG_ERROR("JavaScript exception in file '%s' at %d,%d: %s", filenameString, linenum, start, exceptionString);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1508,18 +1507,18 @@ void TRI_PrintV8Exception (v8::TryCatch* tryCatch) {
|
|||
if (*sourceline) {
|
||||
string l = *sourceline;
|
||||
|
||||
LOG_ERROR("[%s]", l.c_str());
|
||||
LOG_ERROR("!%s", l.c_str());
|
||||
|
||||
if (1 < start) {
|
||||
l = string(start - 1, '_');
|
||||
l = string(start - 1, ' ');
|
||||
}
|
||||
else {
|
||||
l = "";
|
||||
l = "";
|
||||
}
|
||||
|
||||
l += string((size_t)(end - start + 1), '^');
|
||||
|
||||
LOG_ERROR("_%s", l.c_str());
|
||||
LOG_ERROR("!%s", l.c_str());
|
||||
}
|
||||
|
||||
v8::String::Utf8Value stacktrace(tryCatch->StackTrace());
|
||||
|
@ -1569,19 +1568,13 @@ bool TRI_ExecuteJavaScriptDirectory (v8::Handle<v8::Context> context, char const
|
|||
bool TRI_ExecuteStringVocBase (v8::Handle<v8::Context> context,
|
||||
v8::Handle<v8::String> source,
|
||||
v8::Handle<v8::Value> name,
|
||||
bool printResult,
|
||||
bool reportExceptions) {
|
||||
v8::HandleScope handleScope;
|
||||
v8::TryCatch tryCatch;
|
||||
bool printResult) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
v8::Handle<v8::Script> script = v8::Script::Compile(source, name);
|
||||
|
||||
// compilation failed, print errors that happened during compilation
|
||||
if (script.IsEmpty()) {
|
||||
if (reportExceptions) {
|
||||
TRI_PrintV8Exception(&tryCatch);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1590,25 +1583,23 @@ bool TRI_ExecuteStringVocBase (v8::Handle<v8::Context> context,
|
|||
v8::Handle<v8::Value> result = script->Run();
|
||||
|
||||
if (result.IsEmpty()) {
|
||||
assert(tryCatch.HasCaught());
|
||||
|
||||
// print errors that happened during execution
|
||||
if (reportExceptions) {
|
||||
TRI_PrintV8Exception(&tryCatch);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
assert(! tryCatch.HasCaught());
|
||||
|
||||
// if all went well and the result wasn't undefined then print the returned value
|
||||
if (printResult && ! result->IsUndefined()) {
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
v8::Handle<v8::String> printFuncName = v8::String::New("print");
|
||||
v8::Handle<v8::Function> print = v8::Handle<v8::Function>::Cast(context->Global()->Get(printFuncName));
|
||||
|
||||
v8::Handle<v8::Value> args[] = { result };
|
||||
print->Call(print, 1, args);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
TRI_LogV8Exception(&tryCatch);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -56,13 +56,13 @@ void TRI_AugmentObject (v8::Handle<v8::Value> value, TRI_json_t const* json);
|
|||
/// @brief reports an exception
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::string TRI_ReportV8Exception (v8::TryCatch* tryCatch);
|
||||
std::string TRI_StringifyV8Exception (v8::TryCatch* tryCatch);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief prints an exception and stacktrace
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_PrintV8Exception (v8::TryCatch* tryCatch);
|
||||
void TRI_LogV8Exception (v8::TryCatch* tryCatch);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads a file into the current context
|
||||
|
@ -95,8 +95,7 @@ bool TRI_ExecuteJavaScriptDirectory (v8::Handle<v8::Context> context, char const
|
|||
bool TRI_ExecuteStringVocBase (v8::Handle<v8::Context> context,
|
||||
v8::Handle<v8::String> source,
|
||||
v8::Handle<v8::Value> name,
|
||||
bool printResult,
|
||||
bool reportExceptions);
|
||||
bool printResult);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief stores the V8 utils function inside the global variable
|
||||
|
|
|
@ -731,6 +731,8 @@ static TRI_rc_cursor_t* ExecuteQuery (v8::Handle<v8::Object> queryObject,
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_query_cursor_t* ExecuteQueryInstance (v8::Handle<v8::Object> queryObject,
|
||||
bool doCount,
|
||||
uint32_t max,
|
||||
v8::Handle<v8::Value>* err) {
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
|
@ -743,7 +745,7 @@ static TRI_query_cursor_t* ExecuteQueryInstance (v8::Handle<v8::Object> queryObj
|
|||
|
||||
LOG_TRACE("executing query");
|
||||
|
||||
TRI_query_cursor_t* cursor = TRI_ExecuteQueryInstance(instance);
|
||||
TRI_query_cursor_t* cursor = TRI_ExecuteQueryInstance(instance, doCount, max);
|
||||
if (!cursor) {
|
||||
if (tryCatch.HasCaught()) {
|
||||
*err = tryCatch.Exception();
|
||||
|
@ -2037,14 +2039,29 @@ static v8::Handle<v8::Value> JS_ExecuteAql (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a query instance
|
||||
/// @brief executes a query, returns a cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_ExecuteQueryInstance (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// return number of total records in cursor?
|
||||
bool doCount = false;
|
||||
if (argv.Length() > 0) {
|
||||
doCount = TRI_ObjectToBoolean(argv[0]);
|
||||
}
|
||||
|
||||
// maximum number of results to return at once
|
||||
uint32_t max = 1000;
|
||||
if (argv.Length() > 1) {
|
||||
double maxValue = TRI_ObjectToDouble(argv[1]);
|
||||
if (maxValue >= 1.0) {
|
||||
max = (uint32_t) maxValue;
|
||||
}
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> err;
|
||||
TRI_query_cursor_t* cursor = ExecuteQueryInstance(argv.Holder(), &err);
|
||||
TRI_query_cursor_t* cursor = ExecuteQueryInstance(argv.Holder(), doCount, max, &err);
|
||||
|
||||
if (!cursor) {
|
||||
return v8::ThrowException(err);
|
||||
|
@ -2065,10 +2082,6 @@ static v8::Handle<v8::Value> JS_ExecuteQueryInstance (v8::Arguments const& argv)
|
|||
// --SECTION-- AQL CURSOR
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- javascript functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup VocBase
|
||||
/// @{
|
||||
|
@ -2092,6 +2105,7 @@ static v8::Handle<v8::Value> JS_DisposeQueryCursor (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
// set the deleted flag so the gc can catch this instance
|
||||
TRI_LockQueryCursor(cursor);
|
||||
cursor->_deleted = true;
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
|
@ -2179,32 +2193,39 @@ static v8::Handle<v8::Value> JS_NextQueryCursor (v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> value;
|
||||
|
||||
TRI_LockQueryCursor(cursor);
|
||||
if (cursor->_deleted) {
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> value;
|
||||
bool ok = true;
|
||||
|
||||
TRI_js_exec_context_t context = NULL;
|
||||
|
||||
// exceptions must be caught in the following part because we hold an exclusive
|
||||
// lock that might otherwise not be freed
|
||||
try {
|
||||
TRI_rc_result_t* next = cursor->next(cursor);
|
||||
if (!next) {
|
||||
value = v8::Undefined();
|
||||
}
|
||||
else {
|
||||
TRI_js_exec_context_t context = TRI_CreateExecutionContext(cursor->_functionCode);
|
||||
context = TRI_CreateExecutionContext(cursor->_functionCode);
|
||||
if (context) {
|
||||
TRI_DefineSelectExecutionContext(context, next);
|
||||
ok = TRI_ExecuteExecutionContext(context, (void*) &value);
|
||||
TRI_FreeExecutionContext(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
if (context) {
|
||||
TRI_FreeExecutionContext(context);
|
||||
}
|
||||
// always free lock
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
|
||||
if (!ok) {
|
||||
|
@ -2219,6 +2240,142 @@ static v8::Handle<v8::Value> JS_NextQueryCursor (v8::Arguments const& argv) {
|
|||
return scope.Close(value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the next x rows from the cursor in one go
|
||||
///
|
||||
/// This function constructs multiple rows at once and should be preferred over
|
||||
/// hasNext()...next() when iterating over bigger result sets
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_GetRowsQueryCursor (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
if (argv.Length() != 0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("usage: getRows()")));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> self = argv.Holder();
|
||||
TRI_query_cursor_t* cursor = UnwrapQueryCursor(self);
|
||||
|
||||
if (!cursor) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Array> result = v8::Array::New();
|
||||
|
||||
TRI_LockQueryCursor(cursor);
|
||||
if (cursor->_deleted) {
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
TRI_js_exec_context_t context = NULL;
|
||||
bool ok = true;
|
||||
|
||||
// exceptions must be caught in the following part because we hold an exclusive
|
||||
// lock that might otherwise not be freed
|
||||
try {
|
||||
uint32_t max = cursor->getMax(cursor);
|
||||
context = TRI_CreateExecutionContext(cursor->_functionCode);
|
||||
|
||||
if (context) {
|
||||
for (uint32_t i = 0; i < max; i++) {
|
||||
TRI_rc_result_t* next = cursor->next(cursor);
|
||||
if (!next) {
|
||||
break;
|
||||
}
|
||||
|
||||
TRI_DefineSelectExecutionContext(context, next);
|
||||
v8::Handle<v8::Value> value;
|
||||
ok = TRI_ExecuteExecutionContext(context, (void*) &value);
|
||||
if (ok) {
|
||||
result->Set(i, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
}
|
||||
|
||||
if (context) {
|
||||
TRI_FreeExecutionContext(context);
|
||||
}
|
||||
// always free lock
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
|
||||
if (!ok) {
|
||||
if (tryCatch.HasCaught()) {
|
||||
return scope.Close(v8::ThrowException(tryCatch.Exception()));
|
||||
}
|
||||
else {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("cannot convert to JavaScript")));
|
||||
}
|
||||
}
|
||||
|
||||
return scope.Close(result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return max number of results per transfer for cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_GetMaxQueryCursor (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
if (argv.Length() != 0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("usage: getMax()")));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> self = argv.Holder();
|
||||
TRI_query_cursor_t* cursor = UnwrapQueryCursor(self);
|
||||
|
||||
if (!cursor) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
TRI_LockQueryCursor(cursor);
|
||||
if (cursor->_deleted) {
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
uint32_t max = cursor->getMax(cursor);
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
|
||||
return scope.Close(v8::Number::New(max));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return if count flag was set for cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> JS_HasCountQueryCursor (v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
if (argv.Length() != 0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("usage: hasCount()")));
|
||||
}
|
||||
|
||||
v8::Handle<v8::Object> self = argv.Holder();
|
||||
TRI_query_cursor_t* cursor = UnwrapQueryCursor(self);
|
||||
|
||||
if (!cursor) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
TRI_LockQueryCursor(cursor);
|
||||
if (cursor->_deleted) {
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
return scope.Close(v8::ThrowException(v8::String::New("corrupted cursor")));
|
||||
}
|
||||
|
||||
bool hasCount = cursor->hasCount(cursor);
|
||||
TRI_UnlockQueryCursor(cursor);
|
||||
|
||||
return scope.Close(hasCount ? v8::True() : v8::False());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief checks if the cursor is exhausted
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -3468,49 +3625,18 @@ static v8::Handle<v8::Value> JS_ParameterVocbaseCol (v8::Arguments const& argv)
|
|||
v8::Handle<v8::Object> po = par->ToObject();
|
||||
|
||||
TRI_LockCondition(&sim->_journalsCondition);
|
||||
|
||||
TRI_voc_size_t syncAfterObjects = sim->base.base._syncAfterObjects;
|
||||
TRI_voc_size_t syncAfterBytes = sim->base.base._syncAfterBytes;
|
||||
double syncAfterTime = sim->base.base._syncAfterTime;
|
||||
|
||||
bool waitForSync = sim->base.base._waitForSync;
|
||||
TRI_UnlockCondition(&sim->_journalsCondition);
|
||||
|
||||
bool error;
|
||||
|
||||
// extract sync after objects
|
||||
if (po->Has(v8g->SyncAfterObjectsKey)) {
|
||||
syncAfterObjects = TRI_ObjectToDouble(po->Get(v8g->SyncAfterObjectsKey), error);
|
||||
|
||||
if (error || syncAfterObjects < 0.0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("<parameter>.syncAfterObjects must be a number")));
|
||||
}
|
||||
}
|
||||
|
||||
// extract sync after bytes
|
||||
if (po->Has(v8g->SyncAfterBytesKey)) {
|
||||
syncAfterBytes = TRI_ObjectToDouble(po->Get(v8g->SyncAfterBytesKey), error);
|
||||
|
||||
if (error || syncAfterBytes < 0.0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("<parameter>.syncAfterBytes must be a number")));
|
||||
}
|
||||
}
|
||||
|
||||
// extract sync after times
|
||||
if (po->Has(v8g->SyncAfterTimeKey)) {
|
||||
syncAfterTime = TRI_ObjectToDouble(po->Get(v8g->SyncAfterTimeKey), error);
|
||||
|
||||
if (error || syncAfterTime < 0.0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("<parameter>.syncAfterTime must be a non-negative number")));
|
||||
}
|
||||
if (po->Has(v8g->WaitForSyncKey)) {
|
||||
waitForSync = TRI_ObjectToBoolean(po->Get(v8g->WaitForSyncKey));
|
||||
}
|
||||
|
||||
// try to write new parameter to file
|
||||
TRI_LockCondition(&sim->_journalsCondition);
|
||||
|
||||
sim->base.base._syncAfterObjects = syncAfterObjects;
|
||||
sim->base.base._syncAfterBytes = syncAfterBytes;
|
||||
sim->base.base._syncAfterTime = syncAfterTime;
|
||||
|
||||
sim->base.base._waitForSync = waitForSync;
|
||||
bool ok = TRI_UpdateParameterInfoCollection(&sim->base.base);
|
||||
|
||||
TRI_UnlockCondition(&sim->_journalsCondition);
|
||||
|
@ -3528,15 +3654,11 @@ static v8::Handle<v8::Value> JS_ParameterVocbaseCol (v8::Arguments const& argv)
|
|||
TRI_LockCondition(&sim->_journalsCondition);
|
||||
|
||||
TRI_voc_size_t maximalSize = sim->base.base._maximalSize;
|
||||
TRI_voc_size_t syncAfterObjects = sim->base.base._syncAfterObjects;
|
||||
TRI_voc_size_t syncAfterBytes = sim->base.base._syncAfterBytes;
|
||||
double syncAfterTime = sim->base.base._syncAfterTime;
|
||||
bool waitForSync = sim->base.base._waitForSync;
|
||||
|
||||
TRI_UnlockCondition(&sim->_journalsCondition);
|
||||
|
||||
result->Set(v8g->SyncAfterObjectsKey, v8::Number::New(syncAfterObjects));
|
||||
result->Set(v8g->SyncAfterBytesKey, v8::Number::New(syncAfterBytes));
|
||||
result->Set(v8g->SyncAfterTimeKey, v8::Number::New(syncAfterTime));
|
||||
result->Set(v8g->WaitForSyncKey, waitForSync ? v8::True() : v8::False());
|
||||
result->Set(v8g->JournalSizeKey, v8::Number::New(maximalSize));
|
||||
}
|
||||
|
||||
|
@ -4537,6 +4659,9 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
v8::Handle<v8::String> ExecuteFuncName = v8::Persistent<v8::String>::New(v8::String::New("execute"));
|
||||
v8::Handle<v8::String> FiguresFuncName = v8::Persistent<v8::String>::New(v8::String::New("figures"));
|
||||
v8::Handle<v8::String> GetIndexesFuncName = v8::Persistent<v8::String>::New(v8::String::New("getIndexes"));
|
||||
v8::Handle<v8::String> GetMaxFuncName = v8::Persistent<v8::String>::New(v8::String::New("getMax"));
|
||||
v8::Handle<v8::String> GetRowsFuncName = v8::Persistent<v8::String>::New(v8::String::New("getRows"));
|
||||
v8::Handle<v8::String> HasCountFuncName = v8::Persistent<v8::String>::New(v8::String::New("hasCount"));
|
||||
v8::Handle<v8::String> HasNextFuncName = v8::Persistent<v8::String>::New(v8::String::New("hasNext"));
|
||||
v8::Handle<v8::String> IdFuncName = v8::Persistent<v8::String>::New(v8::String::New("id"));
|
||||
v8::Handle<v8::String> InEdgesFuncName = v8::Persistent<v8::String>::New(v8::String::New("inEdges"));
|
||||
|
@ -4561,9 +4686,7 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
// .............................................................................
|
||||
|
||||
v8g->JournalSizeKey = v8::Persistent<v8::String>::New(v8::String::New("journalSize"));
|
||||
v8g->SyncAfterBytesKey = v8::Persistent<v8::String>::New(v8::String::New("syncAfterBytes"));
|
||||
v8g->SyncAfterObjectsKey = v8::Persistent<v8::String>::New(v8::String::New("syncAfterObjects"));
|
||||
v8g->SyncAfterTimeKey = v8::Persistent<v8::String>::New(v8::String::New("syncAfterTime"));
|
||||
v8g->WaitForSyncKey = v8::Persistent<v8::String>::New(v8::String::New("waitForSync"));
|
||||
|
||||
if (v8g->DidKey.IsEmpty()) {
|
||||
v8g->DidKey = v8::Persistent<v8::String>::New(v8::String::New("_id"));
|
||||
|
@ -4803,11 +4926,14 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context, TRI_vocbase_t* vocbas
|
|||
rt = ft->InstanceTemplate();
|
||||
rt->SetInternalFieldCount(2);
|
||||
|
||||
rt->Set(HasNextFuncName, v8::FunctionTemplate::New(JS_HasNextQueryCursor));
|
||||
rt->Set(NextFuncName, v8::FunctionTemplate::New(JS_NextQueryCursor));
|
||||
rt->Set(CountFuncName, v8::FunctionTemplate::New(JS_CountQueryCursor));
|
||||
rt->Set(IdFuncName, v8::FunctionTemplate::New(JS_IdQueryCursor));
|
||||
rt->Set(DisposeFuncName, v8::FunctionTemplate::New(JS_DisposeQueryCursor));
|
||||
rt->Set(GetMaxFuncName, v8::FunctionTemplate::New(JS_GetMaxQueryCursor));
|
||||
rt->Set(GetRowsFuncName, v8::FunctionTemplate::New(JS_GetRowsQueryCursor));
|
||||
rt->Set(HasCountFuncName, v8::FunctionTemplate::New(JS_HasCountQueryCursor));
|
||||
rt->Set(HasNextFuncName, v8::FunctionTemplate::New(JS_HasNextQueryCursor));
|
||||
rt->Set(IdFuncName, v8::FunctionTemplate::New(JS_IdQueryCursor));
|
||||
rt->Set(NextFuncName, v8::FunctionTemplate::New(JS_NextQueryCursor));
|
||||
|
||||
v8g->QueryCursorTempl = v8::Persistent<v8::ObjectTemplate>::New(rt);
|
||||
|
||||
|
|
|
@ -94,10 +94,12 @@ namespace triagens {
|
|||
_version = vs->getValue();
|
||||
}
|
||||
}
|
||||
delete json;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete result;
|
||||
}
|
||||
|
||||
V8ClientConnection::~V8ClientConnection () {
|
||||
|
|
|
@ -48,8 +48,6 @@
|
|||
#include "V8/v8-utils.h"
|
||||
#include "V8Client/V8ClientConnection.h"
|
||||
|
||||
using namespace v8;
|
||||
|
||||
using namespace std;
|
||||
using namespace triagens::basics;
|
||||
using namespace triagens::httpclient;
|
||||
|
@ -145,6 +143,12 @@ static bool noColors = false;
|
|||
|
||||
static bool prettyPrint = false;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief disable auto completion
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool noAutoComplete = false;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -159,7 +163,7 @@ static bool prettyPrint = false;
|
|||
/// @verbinclude fluent39
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> Tri_Output (v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> Js_Pager_Output (v8::Arguments const& argv) {
|
||||
for (int i = 0; i < argv.Length(); i++) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
|
@ -264,7 +268,8 @@ static void ParseProgramOptions (int argc, char* argv[]) {
|
|||
("startup", &StartupPath, "startup path containing the JavaScript files")
|
||||
("use_pager", &usePager, "use pager")
|
||||
("pager", &OutputPager, "output pager (default: 'more')")
|
||||
("no_colors", &noColors, "deaktivate color support")
|
||||
("no_colors", &noColors, "deactivate color support")
|
||||
("no_autocomplete", &noAutoComplete, "disable auto completion")
|
||||
("pretty_print", &prettyPrint, "pretty print values")
|
||||
;
|
||||
|
||||
|
@ -358,7 +363,7 @@ static T* UnwrapClass (v8::Handle<v8::Object> obj, int32_t type) {
|
|||
/// @brief ClientConnection constructor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_ConstructorCallback(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_ConstructorCallback(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
string server = DEFAULT_SERVER_NAME;
|
||||
|
@ -398,7 +403,7 @@ static Handle<Value> ClientConnection_ConstructorCallback(v8::Arguments const& a
|
|||
/// @brief ClientConnection method "httpGet"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_httpGet(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_httpGet(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -428,7 +433,7 @@ static Handle<Value> ClientConnection_httpGet(v8::Arguments const& argv) {
|
|||
/// @brief ClientConnection method "httpDelete"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_httpDelete(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_httpDelete(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -458,7 +463,7 @@ static Handle<Value> ClientConnection_httpDelete(v8::Arguments const& argv) {
|
|||
/// @brief ClientConnection method "httpPost"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_httpPost(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_httpPost(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -489,7 +494,7 @@ static Handle<Value> ClientConnection_httpPost(v8::Arguments const& argv) {
|
|||
/// @brief ClientConnection method "httpPut"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_httpPut(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_httpPut(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -520,7 +525,7 @@ static Handle<Value> ClientConnection_httpPut(v8::Arguments const& argv) {
|
|||
/// @brief ClientConnection method "lastError"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_lastHttpReturnCode(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_lastHttpReturnCode(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -542,7 +547,7 @@ static Handle<Value> ClientConnection_lastHttpReturnCode(v8::Arguments const& ar
|
|||
/// @brief ClientConnection method "lastErrorMessage"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_lastErrorMessage(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_lastErrorMessage(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -564,7 +569,7 @@ static Handle<Value> ClientConnection_lastErrorMessage(v8::Arguments const& argv
|
|||
/// @brief ClientConnection method "isConnected"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_isConnected(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_isConnected(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -585,7 +590,7 @@ static Handle<Value> ClientConnection_isConnected(v8::Arguments const& argv) {
|
|||
/// @brief ClientConnection method "isConnected"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static Handle<Value> ClientConnection_toString(v8::Arguments const& argv) {
|
||||
static v8::Handle<v8::Value> ClientConnection_toString(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
|
@ -599,13 +604,15 @@ static Handle<Value> ClientConnection_toString(v8::Arguments const& argv) {
|
|||
return scope.Close(v8::ThrowException(v8::String::New("usage: toString()")));
|
||||
}
|
||||
|
||||
string result = "[object AvocadoConnection/"
|
||||
string result = "[object AvocadoConnection:"
|
||||
+ connection->getHostname()
|
||||
+ ":"
|
||||
+ triagens::basics::StringUtils::itoa(connection->getPort());
|
||||
+ triagens::basics::StringUtils::itoa(connection->getPort())
|
||||
+ ","
|
||||
+ connection->getVersion();
|
||||
|
||||
if (connection->isConnected()) {
|
||||
result += "/connected]";
|
||||
result += ",connected]";
|
||||
}
|
||||
else {
|
||||
result += "]";
|
||||
|
@ -614,7 +621,26 @@ static Handle<Value> ClientConnection_toString(v8::Arguments const& argv) {
|
|||
return scope.Close(v8::String::New(result.c_str()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief ClientConnection method "isConnected"
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static v8::Handle<v8::Value> ClientConnection_getVersion(v8::Arguments const& argv) {
|
||||
v8::HandleScope scope;
|
||||
|
||||
// get the connection
|
||||
V8ClientConnection* connection = UnwrapClass<V8ClientConnection>(argv.Holder(), WRAP_TYPE_CONNECTION);
|
||||
|
||||
if (connection == 0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("connection class corrupted")));
|
||||
}
|
||||
|
||||
if (argv.Length() != 0) {
|
||||
return scope.Close(v8::ThrowException(v8::String::New("usage: getVersion()")));
|
||||
}
|
||||
|
||||
return scope.Close(v8::String::New(connection->getVersion().c_str()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -635,10 +661,10 @@ static void RunShell (v8::Handle<v8::Context> context) {
|
|||
|
||||
V8LineEditor* console = new V8LineEditor(context, ".avocsh");
|
||||
|
||||
console->open();
|
||||
console->open(!noAutoComplete);
|
||||
|
||||
while (true) {
|
||||
while (!V8::IdleNotification()) {
|
||||
while (! v8::V8::IdleNotification()) {
|
||||
}
|
||||
|
||||
char* input = console->prompt("avocsh> ");
|
||||
|
@ -663,12 +689,19 @@ static void RunShell (v8::Handle<v8::Context> context) {
|
|||
|
||||
console->addHistory(input);
|
||||
|
||||
HandleScope scope;
|
||||
|
||||
v8::HandleScope scope;
|
||||
v8::TryCatch tryCatch;
|
||||
|
||||
init_pager();
|
||||
TRI_ExecuteStringVocBase(context, String::New(input), name, true, true);
|
||||
end_pager();
|
||||
|
||||
TRI_ExecuteStringVocBase(context, v8::String::New(input), name, true);
|
||||
TRI_FreeString(input);
|
||||
|
||||
if (tryCatch.HasCaught()) {
|
||||
cout << TRI_StringifyV8Exception(&tryCatch);
|
||||
}
|
||||
|
||||
end_pager();
|
||||
}
|
||||
|
||||
console->close();
|
||||
|
@ -696,21 +729,37 @@ static char DEF_BRIGHT[5] = "\x1b[1m";
|
|||
static char DEF_RESET[5] = "\x1b[0m";
|
||||
|
||||
static void addColors (v8::Handle<v8::Context> context) {
|
||||
context->Global()->Set(v8::String::New("COLOR_RED"), v8::String::New(DEF_RED, 5));
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_RED"), v8::String::New(DEF_BOLD_RED, 8));
|
||||
context->Global()->Set(v8::String::New("COLOR_GREEN"), v8::String::New(DEF_GREEN, 5));
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_GREEN"), v8::String::New(DEF_BOLD_GREEN, 8));
|
||||
context->Global()->Set(v8::String::New("COLOR_BLUE"), v8::String::New(DEF_BLUE, 5));
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_BLUE"), v8::String::New(DEF_BOLD_BLUE, 8));
|
||||
context->Global()->Set(v8::String::New("COLOR_WHITE"), v8::String::New(DEF_WHITE, 5));
|
||||
context->Global()->Set(v8::String::New("COLOR_YELLOW"), v8::String::New(DEF_YELLOW, 5));
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_WHITE"), v8::String::New(DEF_BOLD_WHITE, 7));
|
||||
context->Global()->Set(v8::String::New("COLOR_BLACK"), v8::String::New(DEF_BLACK, 5));
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_BLACK"), v8::String::New(DEF_BOLD_BLACK, 8));
|
||||
context->Global()->Set(v8::String::New("COLOR_BLINK"), v8::String::New(DEF_BLINK, 4));
|
||||
context->Global()->Set(v8::String::New("COLOR_BRIGHT"), v8::String::New(DEF_BRIGHT, 4));
|
||||
context->Global()->Set(v8::String::New("COLOR_OUTPUT"), v8::String::New(DEF_BRIGHT, 4));
|
||||
context->Global()->Set(v8::String::New("COLOR_OUTPUT_RESET"), v8::String::New(DEF_RESET, 4));
|
||||
context->Global()->Set(v8::String::New("COLOR_RED"), v8::String::New(DEF_RED, 5),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_RED"), v8::String::New(DEF_BOLD_RED, 8),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_GREEN"), v8::String::New(DEF_GREEN, 5),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_GREEN"), v8::String::New(DEF_BOLD_GREEN, 8),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BLUE"), v8::String::New(DEF_BLUE, 5),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_BLUE"), v8::String::New(DEF_BOLD_BLUE, 8),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_WHITE"), v8::String::New(DEF_WHITE, 5),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_YELLOW"), v8::String::New(DEF_YELLOW, 5),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_WHITE"), v8::String::New(DEF_BOLD_WHITE, 7),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BLACK"), v8::String::New(DEF_BLACK, 5),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BOLD_BLACK"), v8::String::New(DEF_BOLD_BLACK, 8),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BLINK"), v8::String::New(DEF_BLINK, 4),
|
||||
v8::ReadOnly);
|
||||
context->Global()->Set(v8::String::New("COLOR_BRIGHT"), v8::String::New(DEF_BRIGHT, 4),
|
||||
v8::ReadOnly);
|
||||
if (!noColors) {
|
||||
context->Global()->Set(v8::String::New("COLOR_OUTPUT"), v8::String::New(DEF_BRIGHT, 4));
|
||||
}
|
||||
context->Global()->Set(v8::String::New("COLOR_OUTPUT_RESET"), v8::String::New(DEF_RESET, 4),
|
||||
v8::ReadOnly);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -755,8 +804,8 @@ int main (int argc, char* argv[]) {
|
|||
context->Enter();
|
||||
|
||||
// add function SYS_OUTPUT to use pager
|
||||
context->Global()->Set(v8::String::New("SYS_OUTPUT"),
|
||||
v8::FunctionTemplate::New(Tri_Output)->GetFunction(),
|
||||
context->Global()->Set(v8::String::New("TRI_SYS_OUTPUT"),
|
||||
v8::FunctionTemplate::New(Js_Pager_Output)->GetFunction(),
|
||||
v8::ReadOnly);
|
||||
|
||||
|
||||
|
@ -782,19 +831,20 @@ int main (int argc, char* argv[]) {
|
|||
// .............................................................................
|
||||
// define AvocadoConnection class
|
||||
// .............................................................................
|
||||
v8::Handle<v8::FunctionTemplate> connection_templ = FunctionTemplate::New();
|
||||
connection_templ->SetClassName(String::New("AvocadoConnection"));
|
||||
v8::Handle<v8::FunctionTemplate> connection_templ = v8::FunctionTemplate::New();
|
||||
connection_templ->SetClassName(v8::String::New("AvocadoConnection"));
|
||||
v8::Handle<v8::ObjectTemplate> connection_proto = connection_templ->PrototypeTemplate();
|
||||
connection_proto->Set("get", FunctionTemplate::New(ClientConnection_httpGet));
|
||||
connection_proto->Set("post", FunctionTemplate::New(ClientConnection_httpPost));
|
||||
connection_proto->Set("delete", FunctionTemplate::New(ClientConnection_httpDelete));
|
||||
connection_proto->Set("put", FunctionTemplate::New(ClientConnection_httpPut));
|
||||
connection_proto->Set("lastHttpReturnCode", FunctionTemplate::New(ClientConnection_lastHttpReturnCode));
|
||||
connection_proto->Set("lastErrorMessage", FunctionTemplate::New(ClientConnection_lastErrorMessage));
|
||||
connection_proto->Set("isConnected", FunctionTemplate::New(ClientConnection_isConnected));
|
||||
connection_proto->Set("toString", FunctionTemplate::New(ClientConnection_toString));
|
||||
connection_proto->Set("get", v8::FunctionTemplate::New(ClientConnection_httpGet));
|
||||
connection_proto->Set("post", v8::FunctionTemplate::New(ClientConnection_httpPost));
|
||||
connection_proto->Set("delete", v8::FunctionTemplate::New(ClientConnection_httpDelete));
|
||||
connection_proto->Set("put", v8::FunctionTemplate::New(ClientConnection_httpPut));
|
||||
connection_proto->Set("lastHttpReturnCode", v8::FunctionTemplate::New(ClientConnection_lastHttpReturnCode));
|
||||
connection_proto->Set("lastErrorMessage", v8::FunctionTemplate::New(ClientConnection_lastErrorMessage));
|
||||
connection_proto->Set("isConnected", v8::FunctionTemplate::New(ClientConnection_isConnected));
|
||||
connection_proto->Set("toString", v8::FunctionTemplate::New(ClientConnection_toString));
|
||||
connection_proto->Set("getVersion", v8::FunctionTemplate::New(ClientConnection_getVersion));
|
||||
connection_proto->SetCallAsFunctionHandler(ClientConnection_ConstructorCallback);
|
||||
Handle<ObjectTemplate> connection_inst = connection_templ->InstanceTemplate();
|
||||
v8::Handle<v8::ObjectTemplate> connection_inst = connection_templ->InstanceTemplate();
|
||||
connection_inst->SetInternalFieldCount(2);
|
||||
context->Global()->Set(v8::String::New("AvocadoConnection"), connection_proto->NewInstance());
|
||||
ConnectionTempl = v8::Persistent<v8::ObjectTemplate>::New(connection_inst);
|
||||
|
@ -810,18 +860,18 @@ int main (int argc, char* argv[]) {
|
|||
|
||||
// http://www.network-science.de/ascii/ Font: ogre
|
||||
if (noColors) {
|
||||
printf(" " " _ \n");
|
||||
printf(" __ ___ _____ ___ " "___| |__ \n");
|
||||
printf(" / _` \\ \\ / / _ \\ / __" "/ __| '_ \\ \n");
|
||||
printf("| (_| |\\ V / (_) | (__" "\\__ \\ | | | \n");
|
||||
printf(" \\__,_| \\_/ \\___/ \\___" "|___/_| |_| \n\n");
|
||||
printf(" " " _ \n");
|
||||
printf(" __ ___ _____ ___ " "___| |__ \n");
|
||||
printf(" / _` \\ \\ / / _ \\ / __" "/ __| '_ \\ \n");
|
||||
printf(" | (_| |\\ V / (_) | (__" "\\__ \\ | | | \n");
|
||||
printf(" \\__,_| \\_/ \\___/ \\___" "|___/_| |_| \n\n");
|
||||
}
|
||||
else {
|
||||
printf( " " "\x1b[31m _ \x1b[0m\n");
|
||||
printf("\x1b[32m __ ___ _____ ___ " "\x1b[31m___| |__ \x1b[0m\n");
|
||||
printf("\x1b[32m / _` \\ \\ / / _ \\ / __" "\x1b[31m/ __| '_ \\ \x1b[0m\n");
|
||||
printf("\x1b[32m| (_| |\\ V / (_) | (__" "\x1b[31m\\__ \\ | | | \x1b[0m\n");
|
||||
printf("\x1b[32m \\__,_| \\_/ \\___/ \\___" "\x1b[31m|___/_| |_| \x1b[0m\n\n");
|
||||
printf( " " "\x1b[31m _ \x1b[0m\n");
|
||||
printf("\x1b[32m __ ___ _____ ___ " "\x1b[31m___| |__ \x1b[0m\n");
|
||||
printf("\x1b[32m / _` \\ \\ / / _ \\ / __" "\x1b[31m/ __| '_ \\ \x1b[0m\n");
|
||||
printf("\x1b[32m | (_| |\\ V / (_) | (__" "\x1b[31m\\__ \\ | | | \x1b[0m\n");
|
||||
printf("\x1b[32m \\__,_| \\_/ \\___/ \\___" "\x1b[31m|___/_| |_| \x1b[0m\n\n");
|
||||
}
|
||||
printf("Welcome to avocsh %s. Copyright (c) 2012 triAGENS GmbH.\n", TRIAGENS_VERSION);
|
||||
|
||||
|
@ -846,7 +896,9 @@ int main (int argc, char* argv[]) {
|
|||
}
|
||||
|
||||
// add the client connection to the context:
|
||||
context->Global()->Set(v8::String::New("avocado"), wrapV8ClientConnection(clientConnection));
|
||||
context->Global()->Set(v8::String::New("avocado"),
|
||||
wrapV8ClientConnection(clientConnection),
|
||||
v8::ReadOnly);
|
||||
|
||||
if (prettyPrint) {
|
||||
printf("Pretty print values.\n");
|
||||
|
@ -856,10 +908,7 @@ int main (int argc, char* argv[]) {
|
|||
context->Global()->Set(v8::String::New("PRETTY_PRINT"), v8::Boolean::New(prettyPrint));
|
||||
|
||||
// add colors for print.js
|
||||
if (!noColors) {
|
||||
addColors(context);
|
||||
}
|
||||
|
||||
addColors(context);
|
||||
|
||||
// load java script from js/bootstrap/*.h files
|
||||
if (StartupPath.empty()) {
|
||||
|
|
|
@ -62,9 +62,7 @@ static void InitCollection (TRI_collection_t* collection,
|
|||
collection->_cid = info->_cid;
|
||||
TRI_CopyString(collection->_name, info->_name, sizeof(collection->_name));
|
||||
collection->_maximalSize = info->_maximalSize;
|
||||
collection->_syncAfterObjects = info->_syncAfterObjects;
|
||||
collection->_syncAfterBytes = info->_syncAfterBytes;
|
||||
collection->_syncAfterTime = info->_syncAfterTime;
|
||||
collection->_waitForSync = info->_waitForSync;
|
||||
|
||||
collection->_directory = directory;
|
||||
|
||||
|
@ -318,9 +316,7 @@ void TRI_InitParameterCollection (TRI_col_parameter_t* parameter,
|
|||
|
||||
parameter->_type = TRI_COL_TYPE_SIMPLE_DOCUMENT;
|
||||
|
||||
parameter->_syncAfterObjects = 1;
|
||||
parameter->_syncAfterBytes = 0;
|
||||
parameter->_syncAfterTime = 0.0;
|
||||
parameter->_waitForSync = true;
|
||||
|
||||
parameter->_maximalSize = (maximalSize / PageSize) * PageSize;
|
||||
|
||||
|
@ -511,14 +507,8 @@ bool TRI_LoadParameterInfo (char const* path,
|
|||
else if (TRI_EqualString(key->_value._string.data, "maximalSize")) {
|
||||
parameter->_maximalSize = value->_value._number;
|
||||
}
|
||||
else if (TRI_EqualString(key->_value._string.data, "syncAfterObjects")) {
|
||||
parameter->_syncAfterObjects = value->_value._number;
|
||||
}
|
||||
else if (TRI_EqualString(key->_value._string.data, "syncAfterBytes")) {
|
||||
parameter->_syncAfterBytes = value->_value._number;
|
||||
}
|
||||
else if (TRI_EqualString(key->_value._string.data, "syncAfterTime")) {
|
||||
parameter->_syncAfterTime = value->_value._number;
|
||||
else if (TRI_EqualString(key->_value._string.data, "waitForSync")) {
|
||||
parameter->_waitForSync = value->_value._boolean;
|
||||
}
|
||||
}
|
||||
else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_STRING) {
|
||||
|
@ -551,9 +541,7 @@ bool TRI_SaveParameterInfo (char const* path,
|
|||
TRI_Insert2ArrayJson(json, "cid", TRI_CreateNumberJson(info->_cid));
|
||||
TRI_Insert2ArrayJson(json, "name", TRI_CreateStringCopyJson(info->_name));
|
||||
TRI_Insert2ArrayJson(json, "maximalSize", TRI_CreateNumberJson(info->_maximalSize));
|
||||
TRI_Insert2ArrayJson(json, "syncAfterObjects", TRI_CreateNumberJson(info->_syncAfterObjects));
|
||||
TRI_Insert2ArrayJson(json, "syncAfterBytes", TRI_CreateNumberJson(info->_syncAfterBytes));
|
||||
TRI_Insert2ArrayJson(json, "syncAfterTime", TRI_CreateNumberJson(info->_syncAfterTime));
|
||||
TRI_Insert2ArrayJson(json, "waitForSync", TRI_CreateBooleanJson(info->_waitForSync));
|
||||
|
||||
// save json info to file
|
||||
filename = TRI_Concatenate2File(path, TRI_COL_PARAMETER_FILE);
|
||||
|
@ -583,9 +571,7 @@ bool TRI_UpdateParameterInfoCollection (TRI_collection_t* collection) {
|
|||
parameter._cid = collection->_cid;
|
||||
TRI_CopyString(parameter._name, collection->_name, sizeof(parameter._name));
|
||||
parameter._maximalSize = collection->_maximalSize;
|
||||
parameter._syncAfterObjects = collection->_syncAfterObjects;
|
||||
parameter._syncAfterBytes = collection->_syncAfterBytes;
|
||||
parameter._syncAfterTime = collection->_syncAfterTime;
|
||||
parameter._waitForSync = collection->_waitForSync;
|
||||
parameter._size = sizeof(TRI_col_info_t);
|
||||
|
||||
return TRI_SaveParameterInfo(collection->_directory, ¶meter);
|
||||
|
|
|
@ -161,9 +161,7 @@ typedef struct TRI_col_parameter_s {
|
|||
char _name[TRI_COL_PATH_LENGTH]; // name of the collection
|
||||
TRI_voc_size_t _maximalSize; // maximal size of memory mapped file
|
||||
|
||||
TRI_voc_size_t _syncAfterObjects; // 0 = ignore, 1 = always, n = at most n non-synced
|
||||
TRI_voc_size_t _syncAfterBytes; // 0 = ignore, n = at most n bytes
|
||||
TRI_voc_ms_t _syncAfterTime; // 0 = ignore, n = at most n milli-seconds
|
||||
bool _waitForSync; // if true, wait for msync
|
||||
}
|
||||
TRI_col_parameter_t;
|
||||
|
||||
|
@ -178,9 +176,7 @@ typedef struct TRI_col_info_s {
|
|||
|
||||
char _name[TRI_COL_PATH_LENGTH]; // name of the collection
|
||||
TRI_voc_size_t _maximalSize; // maximal size of memory mapped file
|
||||
TRI_voc_size_t _syncAfterObjects; // 0 = ignore, 1 = always, n = at most n non-synced
|
||||
TRI_voc_size_t _syncAfterBytes; // 0 = ignore, n = at most n bytes
|
||||
double _syncAfterTime; // 0 = ignore, n = at most n seconds
|
||||
TRI_voc_size_t _waitForSync; // if true, wait for msync
|
||||
|
||||
TRI_voc_size_t _size; // total size of the parameter info block
|
||||
}
|
||||
|
@ -201,9 +197,7 @@ typedef struct TRI_collection_s {
|
|||
char _name[TRI_COL_PATH_LENGTH]; // name of the collection
|
||||
|
||||
TRI_voc_size_t _maximalSize; // maximal size of memory mapped file
|
||||
TRI_voc_size_t _syncAfterObjects; // 0 = ignore, 1 = always, n = at most n non-synced
|
||||
TRI_voc_size_t _syncAfterBytes; // 0 = ignore, n = at most n bytes
|
||||
double _syncAfterTime; // 0 = ignore, n = at most n seconds
|
||||
TRI_voc_size_t _waitForSync; // if true, wait for msync
|
||||
|
||||
char* _directory; // directory of the collection
|
||||
|
||||
|
|
|
@ -66,9 +66,8 @@ static int const COMPACTOR_INTERVAL = 5 * 1000 * 1000;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief selects a journal, possibly waits until a journal appears
|
||||
///
|
||||
/// Note that the function is garbs a lock. We have to release this
|
||||
/// lock, in order to allow the gc to start when waiting for a journal
|
||||
/// to appear.
|
||||
/// Note that the function grabs a lock. We have to release this lock, in order
|
||||
/// to allow the gc to start when waiting for a journal to appear.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static TRI_datafile_t* SelectCompactor (TRI_sim_collection_t* collection,
|
||||
|
|
|
@ -73,6 +73,22 @@ static bool HasNextQueryCursor (const TRI_query_cursor_t* const cursor) {
|
|||
return cursor->_currentRow < cursor->_length;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns if the count flag is set for the cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool HasCountQueryCursor (const TRI_query_cursor_t* const cursor) {
|
||||
return cursor->_hasCount;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the maximum number of results per transfer
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static uint32_t GetMaxQueryCursor (const TRI_query_cursor_t* const cursor) {
|
||||
return cursor->_maxResults;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief frees a cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -99,7 +115,9 @@ static void FreeQueryCursor (TRI_query_cursor_t* cursor) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const instance,
|
||||
const TRI_select_result_t* const selectResult) {
|
||||
const TRI_select_result_t* const selectResult,
|
||||
const bool doCount,
|
||||
const uint32_t maxResults) {
|
||||
TRI_query_cursor_t* cursor;
|
||||
|
||||
cursor = TRI_Allocate(sizeof(TRI_query_cursor_t));
|
||||
|
@ -116,6 +134,8 @@ TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const instance,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
cursor->_hasCount = doCount;
|
||||
cursor->_maxResults = maxResults;
|
||||
cursor->_deleted = false;
|
||||
cursor->_vocbase = instance->_template->_vocbase;
|
||||
|
||||
|
@ -133,6 +153,8 @@ TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const instance,
|
|||
}
|
||||
cursor->next = NextQueryCursor;
|
||||
cursor->hasNext = HasNextQueryCursor;
|
||||
cursor->hasCount = HasCountQueryCursor;
|
||||
cursor->getMax = GetMaxQueryCursor;
|
||||
cursor->free = FreeQueryCursor;
|
||||
|
||||
TRI_InitMutex(&cursor->_lock);
|
||||
|
|
|
@ -50,6 +50,8 @@ typedef struct TRI_query_cursor_s {
|
|||
TRI_vocbase_t* _vocbase;
|
||||
TRI_shadow_t* _shadow;
|
||||
char* _functionCode;
|
||||
bool _hasCount;
|
||||
uint32_t _maxResults;
|
||||
TRI_vector_pointer_t _containers;
|
||||
TRI_mutex_t _lock;
|
||||
bool _deleted;
|
||||
|
@ -61,6 +63,8 @@ typedef struct TRI_query_cursor_s {
|
|||
void (*free) (struct TRI_query_cursor_s*);
|
||||
TRI_rc_result_t* (*next)(struct TRI_query_cursor_s* const);
|
||||
bool (*hasNext)(const struct TRI_query_cursor_s* const);
|
||||
bool (*hasCount)(const struct TRI_query_cursor_s* const);
|
||||
uint32_t (*getMax)(const struct TRI_query_cursor_s* const);
|
||||
}
|
||||
TRI_query_cursor_t;
|
||||
|
||||
|
@ -70,7 +74,9 @@ TRI_query_cursor_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_cursor_t* TRI_CreateQueryCursor (TRI_query_instance_t* const,
|
||||
const TRI_select_result_t* const);
|
||||
const TRI_select_result_t* const,
|
||||
const bool,
|
||||
const uint32_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief Free a cursor based on its shadow
|
||||
|
|
|
@ -149,7 +149,9 @@ static bool AddCollectionsBarrierQueryInstance (TRI_query_instance_t* const inst
|
|||
/// @brief executes a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_cursor_t* TRI_ExecuteQueryInstance (TRI_query_instance_t* const instance) {
|
||||
TRI_query_cursor_t* TRI_ExecuteQueryInstance (TRI_query_instance_t* const instance,
|
||||
const bool doCount,
|
||||
const uint32_t max) {
|
||||
TRI_select_result_t* selectResult;
|
||||
TRI_query_cursor_t* cursor;
|
||||
TRI_voc_ssize_t noLimit = (TRI_voc_ssize_t) INT32_MAX;
|
||||
|
@ -161,7 +163,7 @@ TRI_query_cursor_t* TRI_ExecuteQueryInstance (TRI_query_instance_t* const instan
|
|||
return NULL;
|
||||
}
|
||||
|
||||
cursor = TRI_CreateQueryCursor(instance, selectResult);
|
||||
cursor = TRI_CreateQueryCursor(instance, selectResult, doCount, max);
|
||||
if (!cursor) {
|
||||
selectResult->free(selectResult);
|
||||
return NULL;
|
||||
|
|
|
@ -556,7 +556,9 @@ extern "C" {
|
|||
/// @brief executes a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_query_cursor_t* TRI_ExecuteQueryInstance (TRI_query_instance_t* const);
|
||||
TRI_query_cursor_t* TRI_ExecuteQueryInstance (TRI_query_instance_t* const,
|
||||
const bool,
|
||||
const uint32_t);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
|
@ -140,12 +140,11 @@ static void WaitSync (TRI_sim_collection_t* collection,
|
|||
TRI_datafile_t* journal,
|
||||
char const* position) {
|
||||
TRI_collection_t* base;
|
||||
bool done;
|
||||
|
||||
base = &collection->base.base;
|
||||
|
||||
// no condition at all
|
||||
if (0 == base->_syncAfterObjects && 0 == base->_syncAfterBytes && 0 == base->_syncAfterTime) {
|
||||
if (! base->_waitForSync) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -153,7 +152,6 @@ static void WaitSync (TRI_sim_collection_t* collection,
|
|||
|
||||
// wait until the sync condition is fullfilled
|
||||
while (true) {
|
||||
done = true;
|
||||
|
||||
// check for error
|
||||
if (journal->_state == TRI_DF_STATE_WRITE_ERROR) {
|
||||
|
@ -161,37 +159,7 @@ static void WaitSync (TRI_sim_collection_t* collection,
|
|||
}
|
||||
|
||||
// always sync
|
||||
if (1 == base->_syncAfterObjects) {
|
||||
if (journal->_synced < position) {
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
|
||||
// at most that many outstanding objects
|
||||
else if (1 < base->_syncAfterObjects) {
|
||||
if (journal->_nWritten - journal->_nSynced < base->_syncAfterObjects) {
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
|
||||
// at most that many outstanding bytes
|
||||
if (0 < base->_syncAfterBytes) {
|
||||
if (journal->_written - journal->_synced < base->_syncAfterBytes) {
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
|
||||
// at most that many seconds
|
||||
if (0 < base->_syncAfterTime && journal->_synced < journal->_written) {
|
||||
double t = TRI_microtime();
|
||||
|
||||
if (journal->_lastSynced < t - base->_syncAfterTime) {
|
||||
done = false;
|
||||
}
|
||||
}
|
||||
|
||||
// stop waiting of we reached our limits
|
||||
if (done) {
|
||||
if (position <= journal->_synced) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -796,7 +796,7 @@ bool TRI_ManifestCollectionVocBase (TRI_vocbase_t* vocbase, TRI_vocbase_col_t co
|
|||
TRI_InitParameterCollection(¶meter, vc->_name, DEFAULT_MAXIMAL_SIZE);
|
||||
|
||||
parameter._type = type;
|
||||
parameter._syncAfterTime = 1;
|
||||
parameter._waitForSync = false;
|
||||
|
||||
sim = TRI_CreateSimCollection(vocbase->_path, ¶meter);
|
||||
|
||||
|
|
|
@ -34,8 +34,22 @@
|
|||
// --SECTION-- global variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief change internal.output to shell output
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ModuleCache["/internal"].exports.output = TRI_SYS_OUTPUT;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief default collection for saving queries
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var DEFAULT_QUERY_COLLECTION = "query";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief help texts
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
var HELP = "";
|
||||
var helpQueries = "";
|
||||
var helpAvocadoDatabase = "";
|
||||
|
@ -191,18 +205,14 @@ function start_color_print (color) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getHeadline (text) {
|
||||
var x = parseInt((78 - text.length) / 2);
|
||||
var x = parseInt(Math.abs(78 - text.length) / 2);
|
||||
|
||||
var p = "";
|
||||
for (var i = 0; i < x; ++i) {
|
||||
p += "-";
|
||||
}
|
||||
|
||||
if ( typeof(COLOR_BRIGHT) != "undefined" ) {
|
||||
return COLOR_BRIGHT + p + " " + text + " " + p + COLOR_OUTPUT_RESET + "\n";
|
||||
}
|
||||
|
||||
return p + " " + text + " " + p + "\n";
|
||||
return "\n" + p + " " + text + " " + p + "\n";
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -229,7 +239,7 @@ function help () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ModuleCache["/internal"].exports.log = function(level, msg) {
|
||||
internal.output(msg, "\n");
|
||||
internal.output(level, ": ", msg, "\n");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -892,7 +902,7 @@ AvocadoDatabase.prototype._collection = function (id) {
|
|||
/// @brief factory method to create a new query template
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoDatabase.prototype.createQueryTemplate = function (queryData) {
|
||||
AvocadoDatabase.prototype._createQueryTemplate = function (queryData) {
|
||||
var qt = new AvocadoQueryTemplate(this, queryData);
|
||||
if (qt.save()) {
|
||||
return qt;
|
||||
|
@ -901,7 +911,7 @@ AvocadoDatabase.prototype.createQueryTemplate = function (queryData) {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
AvocadoDatabase.prototype.getQueryTemplate = function (id) {
|
||||
AvocadoDatabase.prototype._getQueryTemplate = function (id) {
|
||||
var qt = new AvocadoQueryTemplate(this, {"_id" : id});
|
||||
if (qt.load()) {
|
||||
return qt;
|
||||
|
@ -914,7 +924,7 @@ AvocadoDatabase.prototype.getQueryTemplate = function (id) {
|
|||
/// @brief factory method to create a new query instance
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoDatabase.prototype.createQueryInstance = function (queryData) {
|
||||
AvocadoDatabase.prototype._createQueryInstance = function (queryData) {
|
||||
return new AvocadoQueryInstance(this, queryData);
|
||||
}
|
||||
|
||||
|
@ -960,13 +970,13 @@ getHeadline("Help") +
|
|||
helpQueries =
|
||||
getHeadline("Simple queries help") +
|
||||
'Create query template: ' + "\n" +
|
||||
' > qt1 = db.createQueryTemplate("select ..."); simple query ' + "\n" +
|
||||
' > qt2 = db.createQueryTemplate( complex query ' + "\n" +
|
||||
' > qt1 = db._createQueryTemplate("select ..."); simple query ' + "\n" +
|
||||
' > qt2 = db._createQueryTemplate( complex query ' + "\n" +
|
||||
' {query:"select...", ' + "\n" +
|
||||
' name:"qname", ' + "\n" +
|
||||
' collection:"q" ' + "\n" +
|
||||
' ... } ' + "\n" +
|
||||
' > qt3 = db.getQueryTemplate("4334:2334"); query by id ' + "\n" +
|
||||
' > qt3 = db._getQueryTemplate("4334:2334"); query by id ' + "\n" +
|
||||
' > qt1.update("select ..."); update ' + "\n" +
|
||||
' > qt1.delete("4334:2334"); delete ' + "\n" +
|
||||
'Create query instance: ' + "\n" +
|
||||
|
@ -1039,7 +1049,7 @@ helpAvocadoQueryInstance =
|
|||
getHeadline("AvocadoQueryInstance help") +
|
||||
'AvocadoQueryInstance constructor: ' + "\n" +
|
||||
' > qi1 = qt1.getInstance(); ' + "\n" +
|
||||
' > qi2 = db.createQueryInstance("select ...."); ' + "\n" +
|
||||
' > qi2 = db._createQueryInstance("select ...."); ' + "\n" +
|
||||
'Functions: ' + "\n" +
|
||||
' bind(<key>, <value>); bind vars ' + "\n" +
|
||||
' setCount(true); ' + "\n" +
|
||||
|
@ -1054,7 +1064,7 @@ getHeadline("AvocadoQueryInstance help") +
|
|||
' maxResults maximum number of results ' + "\n" +
|
||||
' query the query string ' + "\n" +
|
||||
'Example: ' + "\n" +
|
||||
' > qi2 = db.createQueryInstance("select a from colA a ' + "\n" +
|
||||
' > qi2 = db._createQueryInstance("select a from colA a ' + "\n" +
|
||||
' where a.x = @a@ and a.y = @b@"); ' + "\n" +
|
||||
' > qi2.bind("a", "hello"); ' + "\n" +
|
||||
' > qi2.bind("b", "world"); ' + "\n" +
|
||||
|
@ -1063,8 +1073,8 @@ getHeadline("AvocadoQueryInstance help") +
|
|||
helpAvocadoQueryTemplate =
|
||||
getHeadline("AvocadoQueryTemplate help") +
|
||||
'AvocadoQueryTemplate constructor: ' + "\n" +
|
||||
' > qt1 = db.createQueryTemplate("select ..."); simple query ' + "\n" +
|
||||
' > qt2 = db.createQueryTemplate( complex query ' + "\n" +
|
||||
' > qt1 = db._createQueryTemplate("select ..."); simple query ' + "\n" +
|
||||
' > qt2 = db._createQueryTemplate( complex query ' + "\n" +
|
||||
' {query:"select...", ' + "\n" +
|
||||
' name:"qname", ' + "\n" +
|
||||
' collection:"q" ' + "\n" +
|
||||
|
@ -1080,7 +1090,7 @@ getHeadline("AvocadoQueryTemplate help") +
|
|||
' _id template id ' + "\n" +
|
||||
' name collection name ' + "\n" +
|
||||
'Example: ' + "\n" +
|
||||
' > qt1 = db.getQueryTemplate("4334:2334"); ' + "\n" +
|
||||
' > qt1 = db._getQueryTemplate("4334:2334"); ' + "\n" +
|
||||
' > qt1.update("select a from collA a"); ' + "\n" +
|
||||
' > qi1 = qt1.getInstance(); ' + "\n" +
|
||||
' > qt1.delete("4334:2334"); ';
|
||||
|
|
|
@ -35,8 +35,22 @@ static string JS_client_client =
|
|||
"// --SECTION-- global variables\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief change internal.output to shell output\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"ModuleCache[\"/internal\"].exports.output = TRI_SYS_OUTPUT;\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief default collection for saving queries\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"var DEFAULT_QUERY_COLLECTION = \"query\";\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"/// @brief help texts\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"var HELP = \"\";\n"
|
||||
"var helpQueries = \"\";\n"
|
||||
"var helpAvocadoDatabase = \"\";\n"
|
||||
|
@ -192,18 +206,14 @@ static string JS_client_client =
|
|||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"function getHeadline (text) {\n"
|
||||
" var x = parseInt((78 - text.length) / 2);\n"
|
||||
" var x = parseInt(Math.abs(78 - text.length) / 2);\n"
|
||||
" \n"
|
||||
" var p = \"\";\n"
|
||||
" for (var i = 0; i < x; ++i) {\n"
|
||||
" p += \"-\";\n"
|
||||
" }\n"
|
||||
" \n"
|
||||
" if ( typeof(COLOR_BRIGHT) != \"undefined\" ) {\n"
|
||||
" return COLOR_BRIGHT + p + \" \" + text + \" \" + p + COLOR_OUTPUT_RESET + \"\\n\";\n"
|
||||
" }\n"
|
||||
"\n"
|
||||
" return p + \" \" + text + \" \" + p + \"\\n\";\n"
|
||||
" return \"\\n\" + p + \" \" + text + \" \" + p + \"\\n\";\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
|
@ -230,7 +240,7 @@ static string JS_client_client =
|
|||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"ModuleCache[\"/internal\"].exports.log = function(level, msg) {\n"
|
||||
" internal.output(msg, \"\\n\");\n"
|
||||
" internal.output(level, \": \", msg, \"\\n\");\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"// -----------------------------------------------------------------------------\n"
|
||||
|
@ -893,7 +903,7 @@ static string JS_client_client =
|
|||
"/// @brief factory method to create a new query template\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoDatabase.prototype.createQueryTemplate = function (queryData) { \n"
|
||||
"AvocadoDatabase.prototype._createQueryTemplate = function (queryData) { \n"
|
||||
" var qt = new AvocadoQueryTemplate(this, queryData);\n"
|
||||
" if (qt.save()) {\n"
|
||||
" return qt;\n"
|
||||
|
@ -902,7 +912,7 @@ static string JS_client_client =
|
|||
" return undefined;\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"AvocadoDatabase.prototype.getQueryTemplate = function (id) { \n"
|
||||
"AvocadoDatabase.prototype._getQueryTemplate = function (id) { \n"
|
||||
" var qt = new AvocadoQueryTemplate(this, {\"_id\" : id});\n"
|
||||
" if (qt.load()) {\n"
|
||||
" return qt;\n"
|
||||
|
@ -915,7 +925,7 @@ static string JS_client_client =
|
|||
"/// @brief factory method to create a new query instance\n"
|
||||
"////////////////////////////////////////////////////////////////////////////////\n"
|
||||
"\n"
|
||||
"AvocadoDatabase.prototype.createQueryInstance = function (queryData) { \n"
|
||||
"AvocadoDatabase.prototype._createQueryInstance = function (queryData) { \n"
|
||||
" return new AvocadoQueryInstance(this, queryData);\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
|
@ -961,13 +971,13 @@ static string JS_client_client =
|
|||
"helpQueries = \n"
|
||||
"getHeadline(\"Simple queries help\") +\n"
|
||||
"'Create query template: ' + \"\\n\" +\n"
|
||||
"' > qt1 = db.createQueryTemplate(\"select ...\"); simple query ' + \"\\n\" +\n"
|
||||
"' > qt2 = db.createQueryTemplate( complex query ' + \"\\n\" +\n"
|
||||
"' > qt1 = db._createQueryTemplate(\"select ...\"); simple query ' + \"\\n\" +\n"
|
||||
"' > qt2 = db._createQueryTemplate( complex query ' + \"\\n\" +\n"
|
||||
"' {query:\"select...\", ' + \"\\n\" +\n"
|
||||
"' name:\"qname\", ' + \"\\n\" +\n"
|
||||
"' collection:\"q\" ' + \"\\n\" +\n"
|
||||
"' ... } ' + \"\\n\" +\n"
|
||||
"' > qt3 = db.getQueryTemplate(\"4334:2334\"); query by id ' + \"\\n\" +\n"
|
||||
"' > qt3 = db._getQueryTemplate(\"4334:2334\"); query by id ' + \"\\n\" +\n"
|
||||
"' > qt1.update(\"select ...\"); update ' + \"\\n\" +\n"
|
||||
"' > qt1.delete(\"4334:2334\"); delete ' + \"\\n\" +\n"
|
||||
"'Create query instance: ' + \"\\n\" +\n"
|
||||
|
@ -1040,7 +1050,7 @@ static string JS_client_client =
|
|||
"getHeadline(\"AvocadoQueryInstance help\") +\n"
|
||||
"'AvocadoQueryInstance constructor: ' + \"\\n\" +\n"
|
||||
"' > qi1 = qt1.getInstance(); ' + \"\\n\" +\n"
|
||||
"' > qi2 = db.createQueryInstance(\"select ....\"); ' + \"\\n\" +\n"
|
||||
"' > qi2 = db._createQueryInstance(\"select ....\"); ' + \"\\n\" +\n"
|
||||
"'Functions: ' + \"\\n\" +\n"
|
||||
"' bind(<key>, <value>); bind vars ' + \"\\n\" +\n"
|
||||
"' setCount(true); ' + \"\\n\" +\n"
|
||||
|
@ -1055,7 +1065,7 @@ static string JS_client_client =
|
|||
"' maxResults maximum number of results ' + \"\\n\" +\n"
|
||||
"' query the query string ' + \"\\n\" +\n"
|
||||
"'Example: ' + \"\\n\" +\n"
|
||||
"' > qi2 = db.createQueryInstance(\"select a from colA a ' + \"\\n\" +\n"
|
||||
"' > qi2 = db._createQueryInstance(\"select a from colA a ' + \"\\n\" +\n"
|
||||
"' where a.x = @a@ and a.y = @b@\"); ' + \"\\n\" +\n"
|
||||
"' > qi2.bind(\"a\", \"hello\"); ' + \"\\n\" +\n"
|
||||
"' > qi2.bind(\"b\", \"world\"); ' + \"\\n\" +\n"
|
||||
|
@ -1064,8 +1074,8 @@ static string JS_client_client =
|
|||
"helpAvocadoQueryTemplate = \n"
|
||||
"getHeadline(\"AvocadoQueryTemplate help\") +\n"
|
||||
"'AvocadoQueryTemplate constructor: ' + \"\\n\" +\n"
|
||||
"' > qt1 = db.createQueryTemplate(\"select ...\"); simple query ' + \"\\n\" +\n"
|
||||
"' > qt2 = db.createQueryTemplate( complex query ' + \"\\n\" +\n"
|
||||
"' > qt1 = db._createQueryTemplate(\"select ...\"); simple query ' + \"\\n\" +\n"
|
||||
"' > qt2 = db._createQueryTemplate( complex query ' + \"\\n\" +\n"
|
||||
"' {query:\"select...\", ' + \"\\n\" +\n"
|
||||
"' name:\"qname\", ' + \"\\n\" +\n"
|
||||
"' collection:\"q\" ' + \"\\n\" +\n"
|
||||
|
@ -1081,7 +1091,7 @@ static string JS_client_client =
|
|||
"' _id template id ' + \"\\n\" +\n"
|
||||
"' name collection name ' + \"\\n\" +\n"
|
||||
"'Example: ' + \"\\n\" +\n"
|
||||
"' > qt1 = db.getQueryTemplate(\"4334:2334\"); ' + \"\\n\" +\n"
|
||||
"' > qt1 = db._getQueryTemplate(\"4334:2334\"); ' + \"\\n\" +\n"
|
||||
"' > qt1.update(\"select a from collA a\"); ' + \"\\n\" +\n"
|
||||
"' > qi1 = qt1.getInstance(); ' + \"\\n\" +\n"
|
||||
"' > qt1.delete(\"4334:2334\"); ';\n"
|
||||
|
|
|
@ -37,6 +37,7 @@ var AvocadoEdgesCollection = internal.AvocadoEdgesCollection;
|
|||
/// <ol>
|
||||
/// <li>@ref SimpleQueryDocument "db.@FA{collection}.document(@FA{document-reference})"</li>
|
||||
/// <li>@ref SimpleQueryAll "db.@FA{collection}.all()"</li>
|
||||
/// <li>@ref SimpleQuerySelect "db.@FA{collection}.select()"</li>
|
||||
/// <li>@ref SimpleQueryCount "@FA{query}.count()"</li>
|
||||
/// </ol>
|
||||
/// </li>
|
||||
|
@ -93,6 +94,10 @@ var AvocadoEdgesCollection = internal.AvocadoEdgesCollection;
|
|||
/// @copydetails JSF_AvocadoCollection_prototype_all
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor SimpleQuerySelect
|
||||
/// @copydetails JSF_AvocadoCollection_prototype_select
|
||||
/// <hr>
|
||||
///
|
||||
/// @anchor SimpleQueryCount
|
||||
/// @copydetails JSF_SimpleQuery_prototype_count
|
||||
///
|
||||
|
@ -807,6 +812,184 @@ SimpleQueryAll.prototype._PRINT = function () {
|
|||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- SELECT QUERY
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- constructors and destructors
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup SimpleQuery
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief select query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function SimpleQuerySelect (collection, example) {
|
||||
this._collection = collection;
|
||||
this._example = example;
|
||||
}
|
||||
|
||||
SimpleQuerySelect.prototype = new SimpleQuery();
|
||||
SimpleQuerySelect.prototype.constructor = SimpleQuerySelect;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief constructs a select query for a collection
|
||||
///
|
||||
/// @FUN{select()}
|
||||
///
|
||||
/// Selects all documents of a collection that match the specified example.
|
||||
/// The example must be specified as an object, with the object attributes being
|
||||
/// the search values. Allowed attribute types for searching are numbers,
|
||||
/// strings, and boolean values.
|
||||
///
|
||||
/// You can use @FN{toArray}, @FN{next},
|
||||
/// @FN{nextRef}, or @FN{hasNext} to access the result. The result can be
|
||||
/// limited using the @FN{skip} and @FN{limit} operator.
|
||||
///
|
||||
/// @EXAMPLES
|
||||
///
|
||||
/// Use @FN{toArray} to get all documents at once:
|
||||
///
|
||||
/// @verbinclude simple18
|
||||
///
|
||||
/// Use @FN{next} to loop over all documents:
|
||||
///
|
||||
/// @verbinclude simple19
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AvocadoCollection.prototype.select = function (example) {
|
||||
return new SimpleQuerySelect(this, example);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup SimpleQuery
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief clones a select query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SimpleQuerySelect.prototype.clone = function () {
|
||||
var query;
|
||||
|
||||
query = new SimpleQuerySelect(this._collection, this._example);
|
||||
query._skip = this._skip;
|
||||
query._limit = this._limit;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes a select query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SimpleQuerySelect.prototype.execute = function () {
|
||||
var documents;
|
||||
|
||||
if (this._execution == null) {
|
||||
if (this._skip == null || this._skip <= 0) {
|
||||
this._skip = 0;
|
||||
}
|
||||
|
||||
var queryString = "SELECT c FROM `" + this._collection._name + "` c";
|
||||
|
||||
if (!(this._example instanceof Object)) {
|
||||
throw "invalid example specification";
|
||||
}
|
||||
|
||||
var found = false;
|
||||
for (var i in this._example) {
|
||||
if (!this._example.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var typeString = typeof(this._example[i]);
|
||||
if (typeString !== "number" && typeString !== "string" && typeString !== "boolean") {
|
||||
throw "invalid example specification for key " + i;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
queryString += "&& ";
|
||||
}
|
||||
else {
|
||||
queryString += " WHERE ";
|
||||
found = true;
|
||||
}
|
||||
|
||||
queryString += "c.`" + i + "` == ";
|
||||
if (typeString == "number") {
|
||||
queryString += this._example[i];
|
||||
}
|
||||
else if (typeString == "string") {
|
||||
queryString += QuoteJSONString(this._example[i]);
|
||||
}
|
||||
else if (typeString == "boolean") {
|
||||
queryString += this._example[i];
|
||||
}
|
||||
}
|
||||
|
||||
var result = AQL_PREPARE(db, queryString);
|
||||
if (result instanceof AvocadoQueryError) {
|
||||
throw result.message;
|
||||
}
|
||||
|
||||
var cursor = result.execute();
|
||||
if (cursor instanceof AvocadoQueryError) {
|
||||
throw cursor.message;
|
||||
}
|
||||
|
||||
var documents = { "count" : cursor.count(), "total" : cursor.count(), "documents": [] };
|
||||
while (cursor.hasNext()) {
|
||||
documents.documents.push(cursor.next());
|
||||
}
|
||||
cursor.dispose();
|
||||
|
||||
this._execution = new SimpleQueryArray(documents.documents);
|
||||
this._execution._skip = this._skip;
|
||||
this._execution._limit = this._limit;
|
||||
this._countQuery = documents.count;
|
||||
this._countTotal = documents.total;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief print a select query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SimpleQuerySelect.prototype._PRINT = function () {
|
||||
var text;
|
||||
|
||||
text = "SimpleQuerySelect(" + this._collection._name + ")";
|
||||
|
||||
if (this._skip != null && this._skip != 0) {
|
||||
text += ".skip(" + this._skip + ")";
|
||||
}
|
||||
|
||||
if (this._limit != null) {
|
||||
text += ".limit(" + this._limit + ")";
|
||||
}
|
||||
|
||||
internal.output(text);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- SIMPLE QUERY ARRAY
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -1142,7 +1325,7 @@ function SimpleQueryNear (collection, latitiude, longitude, iid) {
|
|||
}
|
||||
|
||||
if (this._index == null) {
|
||||
throw "an geo-index must be known";
|
||||
throw "a geo-index must be known";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1325,7 +1508,7 @@ function SimpleQueryWithin (collection, latitiude, longitude, radius, iid) {
|
|||
}
|
||||
|
||||
if (this._index == null) {
|
||||
throw "an geo-index must be known";
|
||||
throw "a geo-index must be known";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1468,6 +1651,7 @@ exports.AvocadoCollection = AvocadoCollection;
|
|||
exports.AvocadoEdgesCollection = AvocadoEdgesCollection;
|
||||
exports.SimpleQuery = SimpleQuery;
|
||||
exports.SimpleQueryAll = SimpleQueryAll;
|
||||
exports.SimpleQuerySelect = SimpleQuerySelect;
|
||||
exports.SimpleQueryArray = SimpleQueryArray;
|
||||
exports.SimpleQueryGeo = SimpleQueryGeo;
|
||||
exports.SimpleQueryNear = SimpleQueryNear;
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief query results cursor actions
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Achim Brandt
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- global variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
var actions = require("actions");
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private functions
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a result set from a cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getCursorResult(cursor) {
|
||||
var hasCount = cursor.hasCount();
|
||||
var lines = cursor.getRows();
|
||||
|
||||
var result = {
|
||||
"result" : lines,
|
||||
"_id" : cursor.id(),
|
||||
"hasMore" : cursor.hasNext()
|
||||
};
|
||||
|
||||
if (hasCount) {
|
||||
result["count"] = cursor.count();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief create a cursor and return the first results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function postCursor(req, res) {
|
||||
if (req.suffix.length != 0) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotModified, "Cursor not created");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var json = JSON.parse(req.requestBody);
|
||||
var queryString;
|
||||
|
||||
if (json.qid != undefined) {
|
||||
var q = db.query.document_wrapped(json.qid);
|
||||
queryString = q.query;
|
||||
}
|
||||
else if (json.query != undefined) {
|
||||
queryString = json.query;
|
||||
}
|
||||
|
||||
if (queryString == undefined) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotModified, "Missing query identifier");
|
||||
return;
|
||||
}
|
||||
|
||||
var result;
|
||||
if (json.bindVars) {
|
||||
result = AQL_PREPARE(db, queryString, json.bindVars);
|
||||
}
|
||||
else {
|
||||
result = AQL_PREPARE(db, queryString);
|
||||
}
|
||||
|
||||
if (result instanceof AvocadoQueryError) {
|
||||
actions.actionResultError (req, res, 404, result.code, result.message);
|
||||
return;
|
||||
}
|
||||
|
||||
var cursor = result.execute((json.count != undefined ? json.count : false), (json.maxResults != undefined ? json.maxResults : 1000));
|
||||
if (cursor instanceof AvocadoQueryError) {
|
||||
actionResultError (req, res, 404, result.code, result.message);
|
||||
return;
|
||||
}
|
||||
|
||||
actions.actionResultOK(req, res, 201, getCursorResult(cursor));
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotModified, "Cursor not created");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return the next results from an existing cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function putCursor(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var cursorId = decodeURIComponent(req.suffix[0]);
|
||||
var cursor = AQL_CURSOR(db, cursorId);
|
||||
if (!(cursor instanceof AvocadoQueryCursor)) {
|
||||
throw "cursor not found";
|
||||
}
|
||||
|
||||
actions.actionResultOK(req, res, 200, getCursorResult(cursor));
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief dispose an existing cursor
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function deleteCursor(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var cursorId = decodeURIComponent(req.suffix[0]);
|
||||
var cursor = AQL_CURSOR(db, cursorId);
|
||||
if (!(cursor instanceof AvocadoQueryCursor)) {
|
||||
throw "cursor not found";
|
||||
}
|
||||
|
||||
cursor.dispose();
|
||||
actions.actionResultOK(req, res, 202, { "_id" : cursorId });
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- initialiser
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief cursor actions gateway
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_api/cursor",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
switch (req.requestType) {
|
||||
case ("POST") :
|
||||
postCursor(req, res);
|
||||
break;
|
||||
|
||||
case ("PUT") :
|
||||
putCursor(req, res);
|
||||
break;
|
||||
|
||||
case ("DELETE") :
|
||||
deleteCursor(req, res);
|
||||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -0,0 +1,46 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief query actions
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @addtogroup AvocadoAPI
|
||||
/// @{
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- global variables
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
var actions = require("actions");
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -1,145 +0,0 @@
|
|||
var actions = require("actions");
|
||||
|
||||
function postCursor(req, res) {
|
||||
if (req.suffix.length != 0) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotModified, "Cursor not created");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var json = JSON.parse(req.requestBody);
|
||||
var queryString;
|
||||
|
||||
if (json.qid != undefined) {
|
||||
var q = db.query.document_wrapped(json.qid);
|
||||
queryString = q.query;
|
||||
}
|
||||
else if (json.query != undefined) {
|
||||
queryString = json.query;
|
||||
}
|
||||
|
||||
if (queryString == undefined) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotModified, "Missing query identifier");
|
||||
return;
|
||||
}
|
||||
|
||||
var result;
|
||||
if (json.bindVars) {
|
||||
result = AQL_PREPARE(db, queryString, json.bindVars);
|
||||
}
|
||||
else {
|
||||
result = AQL_PREPARE(db, queryString);
|
||||
}
|
||||
|
||||
if (result instanceof AvocadoQueryError) {
|
||||
actions.actionResultError (req, res, 404, result.code, result.message);
|
||||
return;
|
||||
}
|
||||
|
||||
var cursor = result.execute();
|
||||
if (cursor instanceof AvocadoQueryError) {
|
||||
actionResultError (req, res, 404, result.code, result.message);
|
||||
return;
|
||||
}
|
||||
|
||||
var maxResults = 1000;
|
||||
if (json.maxResults && parseInt(json.maxResults) > 0) {
|
||||
maxResults = parseInt(json.maxResults);
|
||||
}
|
||||
|
||||
var lines = [];
|
||||
var i = 0;
|
||||
|
||||
while (i < maxResults && cursor.hasNext()) {
|
||||
lines[i++] = cursor.next();
|
||||
}
|
||||
|
||||
var cursorId;
|
||||
var count = cursor.count();
|
||||
var hasMore = i < count;
|
||||
|
||||
var result = {
|
||||
"result" : lines,
|
||||
"_id" : cursorId,
|
||||
"hasMore" : hasMore
|
||||
};
|
||||
|
||||
if (json.count) {
|
||||
result["count"] = count;
|
||||
}
|
||||
|
||||
actions.actionResultOK(req, res, 201, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotModified, "Cursor not created");
|
||||
}
|
||||
}
|
||||
|
||||
function putCursor(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var cursorId = decodeURIComponent(req.suffix[0]);
|
||||
|
||||
// TODO
|
||||
|
||||
var result = {
|
||||
"result" : [{"test":"protest"}, {"hello":"world"}],
|
||||
"count" : 2,
|
||||
"_id" : cursorId,
|
||||
"hasMore" : false
|
||||
};
|
||||
|
||||
actions.actionResultOK(req, res, 200, result);
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
}
|
||||
}
|
||||
|
||||
function deleteCursor(req, res) {
|
||||
if (req.suffix.length != 1) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var cid = decodeURIComponent(req.suffix[0]);
|
||||
if(db.cursor.delete(qid)) {
|
||||
actions.actionResultOK(req, res, 202, {"cid" : cid});
|
||||
}
|
||||
else {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
actions.actionResultError (req, res, 404, actions.cursorNotFound, "Cursor not found");
|
||||
}
|
||||
}
|
||||
|
||||
actions.defineHttp({
|
||||
url : "_api/cursor",
|
||||
context : "api",
|
||||
|
||||
callback : function (req, res) {
|
||||
switch (req.requestType) {
|
||||
case ("POST") :
|
||||
postCursor(req, res);
|
||||
break;
|
||||
|
||||
case ("PUT") :
|
||||
putCursor(req, res);
|
||||
break;
|
||||
|
||||
case ("DELETE") :
|
||||
deleteCursor(req, res);
|
||||
break;
|
||||
|
||||
default:
|
||||
actions.actionResultUnsupported(req, res);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,254 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for query language, joins
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function aqlJoinsTestSuite () {
|
||||
var collection = null;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function setUp () {
|
||||
this.persons = db.UnitTestsPersons;
|
||||
this.friends = db.UnitTestsFriends;
|
||||
this.locations = db.UnitTestsLocations;
|
||||
|
||||
if (this.persons.count() == 0) {
|
||||
this.persons.save( { "id" : 1, "name" : "fox" } );
|
||||
this.persons.save( { "id" : 2, "name" : "brown" } );
|
||||
this.persons.save( { "id" : 5, "name" : "peter" } );
|
||||
this.persons.save( { "id" : 6, "name" : "hulk" } );
|
||||
this.persons.save( { "id" : 9, "name" : "fred" } );
|
||||
}
|
||||
|
||||
if (this.friends.count() == 0) {
|
||||
this.friends.save( { "person1" : 1, "person2" : 2 } );
|
||||
this.friends.save( { "person1" : 9, "person2" : 1 } );
|
||||
this.friends.save( { "person1" : 1, "person2" : 9 } );
|
||||
this.friends.save( { "person1" : 5, "person2" : 6 } );
|
||||
this.friends.save( { "person1" : 6, "person2" : 9 } );
|
||||
}
|
||||
|
||||
if (this.locations.count() == 0) {
|
||||
this.locations.save( { "person" : 1, "x" : 1, "y": 5 } );
|
||||
this.locations.save( { "person" : 1, "x" : 3, "y": 4 } );
|
||||
this.locations.save( { "person" : 1, "x" : -2, "y": 3 } );
|
||||
this.locations.save( { "person" : 2, "x" : 3, "y": -2 } );
|
||||
this.locations.save( { "person" : 2, "x" : 2, "y": 1 } );
|
||||
this.locations.save( { "person" : 5, "x" : 4, "y": -1 } );
|
||||
this.locations.save( { "person" : 5, "x" : 3, "y": -2 } );
|
||||
this.locations.save( { "person" : 5, "x" : 2, "y": -2 } );
|
||||
this.locations.save( { "person" : 5, "x" : 5, "y": -5 } );
|
||||
this.locations.save( { "person" : 5, "x" : 6, "y": -5 } );
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function tearDown () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief sanitize a result row, recursively
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function sanitizeRow (row) {
|
||||
var copy;
|
||||
|
||||
if (row instanceof Array) {
|
||||
copy = [ ];
|
||||
}
|
||||
else {
|
||||
copy = { };
|
||||
}
|
||||
|
||||
for (var i in row) {
|
||||
if (i === "_id" || !row.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
if (row[i] instanceof Array || row[i] instanceof Object) {
|
||||
copy[i] = this.sanitizeRow(row[i]);
|
||||
}
|
||||
else {
|
||||
copy[i] = row[i];
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute a given query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function executeQuery (query) {
|
||||
var aQuery = AQL_PREPARE(db, query);
|
||||
assertFalse(aQuery instanceof AvocadoQueryError);
|
||||
return aQuery.execute();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute a given query and return the results as an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getQueryResults (query) {
|
||||
var aCursor = this.executeQuery(query);
|
||||
if (aCursor) {
|
||||
var results = [ ];
|
||||
while (aCursor.hasNext()) {
|
||||
results.push(this.sanitizeRow(aCursor.next()));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
return aCursor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test inner join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testInnerJoin1 () {
|
||||
var expected = [{ "id" : 1, "name" : "fox"}, { "id" : 1, "name" : "fox"}, { "id" : 1, "name" : "fox"}, { "id" : 2, "name" : "brown"}, { "id" : 2, "name" : "brown"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}];
|
||||
|
||||
var result = this.getQueryResults("SELECT p FROM " + this.persons._name + " p INNER JOIN " + this.locations._name + " l ON (p.id == l.person) ORDER BY p.id, l.x, l.y");
|
||||
assertEqual(10, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test inner join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testInnerJoin2 () {
|
||||
var expected = [{ "p" : { "id" : 1, "name" : "fox"}, "l" : { "person" : 1, "x" : -2, "y" : 3}}, { "p" : { "id" : 1, "name" : "fox"}, "l" : { "person" : 1, "x" : 1, "y" : 5}}, { "p" : { "id" : 1, "name" : "fox"}, "l" : { "person" : 1, "x" : 3, "y" : 4}}, { "p" : { "id" : 2, "name" : "brown"}, "l" : { "person" : 2, "x" : 2, "y" : 1}}, { "p" : { "id" : 2, "name" : "brown"}, "l" : { "person" : 2, "x" : 3, "y" : -2}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 2, "y" : -2}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 3, "y" : -2}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 4, "y" : -1}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 5, "y" : -5}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 6, "y" : -5}}];
|
||||
|
||||
var result = this.getQueryResults("SELECT { p : p, l : l } FROM " + this.persons._name + " p INNER JOIN " + this.locations._name + " l ON (p.id == l.person) ORDER BY p.id, l.x, l.y");
|
||||
assertEqual(10, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test inner join results with limit
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testInnerJoinLimit1 () {
|
||||
var expected = [{ "id" : 1, "name" : "fox"}, { "id" : 1, "name" : "fox"}, { "id" : 2, "name" : "brown"}];
|
||||
|
||||
var result = this.getQueryResults("SELECT p FROM " + this.persons._name + " p INNER JOIN " + this.locations._name + " l ON (p.id == l.person) ORDER BY p.id, l.x, l.y LIMIT 1, 3");
|
||||
assertEqual(3, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test left join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testLeftJoin1 () {
|
||||
var expected = [{ "id" : 1, "name" : "fox"}, { "id" : 1, "name" : "fox"}, { "id" : 1, "name" : "fox"}, { "id" : 2, "name" : "brown"}, { "id" : 2, "name" : "brown"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}, { "id" : 5, "name" : "peter"}, { "id" : 6, "name" : "hulk"}, { "id" : 9, "name" : "fred"}];
|
||||
|
||||
var result = this.getQueryResults("SELECT p FROM " + this.persons._name + " p LEFT JOIN " + this.locations._name + " l ON (p.id == l.person) ORDER BY p.id, l.x, l.y");
|
||||
assertEqual(12, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test left join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testLeftJoin2 () {
|
||||
var expected = [{ "p" : { "id" : 1, "name" : "fox"}, "l" : { "person" : 1, "x" : -2, "y" : 3}}, { "p" : { "id" : 1, "name" : "fox"}, "l" : { "person" : 1, "x" : 1, "y" : 5}}, { "p" : { "id" : 1, "name" : "fox"}, "l" : { "person" : 1, "x" : 3, "y" : 4}}, { "p" : { "id" : 2, "name" : "brown"}, "l" : { "person" : 2, "x" : 2, "y" : 1}}, { "p" : { "id" : 2, "name" : "brown"}, "l" : { "person" : 2, "x" : 3, "y" : -2}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 2, "y" : -2}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 3, "y" : -2}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 4, "y" : -1}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 5, "y" : -5}}, { "p" : { "id" : 5, "name" : "peter"}, "l" : { "person" : 5, "x" : 6, "y" : -5}}, { "p" : { "id" : 6, "name" : "hulk"}, "l" : null}, { "p" : { "id" : 9, "name" : "fred"}, "l" : null}];
|
||||
|
||||
var result = this.getQueryResults("SELECT { p : p, l : l } FROM " + this.persons._name + " p LEFT JOIN " + this.locations._name + " l ON (p.id == l.person) ORDER BY p.id, l.x, l.y");
|
||||
assertEqual(12, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test list join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testListJoin1 () {
|
||||
var expected = [{ "p" : { "id" : 1, "name" : "fox"}, "l" : [{ "person" : 1, "x" : 1, "y" : 5}, { "person" : 1, "x" : 3, "y" : 4}, { "person" : 1, "x" : -2, "y" : 3}]}, { "p" : { "id" : 2, "name" : "brown"}, "l" : [{ "person" : 2, "x" : 2, "y" : 1}, { "person" : 2, "x" : 3, "y" : -2}]}, { "p" : { "id" : 5, "name" : "peter"}, "l" : [{ "person" : 5, "x" : 5, "y" : -5}, { "person" : 5, "x" : 3, "y" : -2}, { "person" : 5, "x" : 2, "y" : -2}, { "person" : 5, "x" : 6, "y" : -5}, { "person" : 5, "x" : 4, "y" : -1}]}, { "p" : { "id" : 6, "name" : "hulk"}, "l" : [ ]}, { "p" : { "id" : 9, "name" : "fred"}, "l" : [ ]}];
|
||||
|
||||
var result = this.getQueryResults("SELECT { p : p, l : l } FROM " + this.persons._name + " p LIST JOIN " + this.locations._name + " l ON (p.id == l.person) ORDER BY p.id, l.x, l.y");
|
||||
assertEqual(5, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test list join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testListJoin2 () {
|
||||
var expected = [{ "p" : { "id" : 1, "name" : "fox"}, "f" : [{ "person1" : 1, "person2" : 9}, { "person1" : 1, "person2" : 2}]}, { "p" : { "id" : 2, "name" : "brown"}, "f" : [ ]}, { "p" : { "id" : 5, "name" : "peter"}, "f" : [{ "person1" : 5, "person2" : 6}]}, { "p" : { "id" : 6, "name" : "hulk"}, "f" : [{ "person1" : 6, "person2" : 9}]}, { "p" : { "id" : 9, "name" : "fred"}, "f" : [{ "person1" : 9, "person2" : 1}]}];
|
||||
|
||||
var result = this.getQueryResults("SELECT { p : p, f : f } FROM " + this.persons._name + " p LIST JOIN " + this.friends._name + " f ON (p.id == f.person1) ORDER BY p.id");
|
||||
assertEqual(5, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test list join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testListJoin3 () {
|
||||
var expected = [{ "p" : { "id" : 1, "name" : "fox"}, "f" : [{ "person1" : 9, "person2" : 1}, { "person1" : 1, "person2" : 9}, { "person1" : 1, "person2" : 2}]}, { "p" : { "id" : 2, "name" : "brown"}, "f" : [{ "person1" : 1, "person2" : 2}]}, { "p" : { "id" : 5, "name" : "peter"}, "f" : [{ "person1" : 5, "person2" : 6}]}, { "p" : { "id" : 6, "name" : "hulk"}, "f" : [{ "person1" : 6, "person2" : 9}, { "person1" : 5, "person2" : 6}]}, { "p" : { "id" : 9, "name" : "fred"}, "f" : [{ "person1" : 9, "person2" : 1}, { "person1" : 1, "person2" : 9}, { "person1" : 6, "person2" : 9}]}];
|
||||
|
||||
var result = this.getQueryResults("SELECT { p : p, f : f } FROM " + this.persons._name + " p LIST JOIN " + this.friends._name + " f ON (p.id == f.person1 || p.id == f.person2) ORDER BY p.id");
|
||||
assertEqual(5, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test self join results
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testSelfJoin () {
|
||||
var expected = [{ "id" : 1, "name" : "fox"}, { "id" : 2, "name" : "brown"}, { "id" : 5, "name" : "peter"}, { "id" : 6, "name" : "hulk"}, { "id" : 9, "name" : "fred"}];
|
||||
|
||||
var result = this.getQueryResults("SELECT p FROM " + this.persons._name + " p INNER JOIN " + this.persons._name + " p2 ON (p.id == p2.id) ORDER BY p.id");
|
||||
assertEqual(5, result.length);
|
||||
assertEqual(expected, result);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsUnity.run(aqlJoinsTestSuite);
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -0,0 +1,250 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tests for query language, keywords
|
||||
///
|
||||
/// @file
|
||||
///
|
||||
/// DISCLAIMER
|
||||
///
|
||||
/// Copyright 2010-2012 triagens GmbH, Cologne, Germany
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
/// Copyright holder is triAGENS GmbH, Cologne, Germany
|
||||
///
|
||||
/// @author Jan Steemann
|
||||
/// @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function aqlKeywordsTestSuite () {
|
||||
var collection = null;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set up
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function setUp () {
|
||||
this.keywords = [ "select", "from", "where", "join", "inner", "left", "right", "on", "limit", "order", "by", "near", "within" ];
|
||||
|
||||
this.keywordHash = { };
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
this.keywordHash[this.keywords[i]] = this.keywords[i];
|
||||
}
|
||||
|
||||
this.collection = db.UnitTestsKeywords;
|
||||
|
||||
if (this.collection.count() == 0) {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var k = this.keywords[i];
|
||||
var row = { };
|
||||
row[k] = k;
|
||||
|
||||
this.collection.save(row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tear down
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function tearDown () {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute a given query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function executeQuery (query, expectError) {
|
||||
var aQuery = AQL_PREPARE(db, query);
|
||||
if (expectError) {
|
||||
assertTrue(aQuery instanceof AvocadoQueryError);
|
||||
return null;
|
||||
}
|
||||
|
||||
assertFalse(aQuery instanceof AvocadoQueryError);
|
||||
return aQuery.execute();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief execute a given query and return the results as an array
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function getQueryResults (query, expectError) {
|
||||
var aCursor = this.executeQuery(query, expectError);
|
||||
if (aCursor) {
|
||||
var results = [ ];
|
||||
while (aCursor.hasNext()) {
|
||||
results.push(aCursor.next());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
return aCursor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesSelectInvalid () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to fail
|
||||
this.getQueryResults("SELECT { " + this.keywords[i] + " : null } FROM " + this.collection._name + " c", true);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesSelectValid1 () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to work
|
||||
this.getQueryResults("SELECT { \"" + this.keywords[i] + "\" : null } FROM " + this.collection._name + " c", false);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesSelectValid2 () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to work
|
||||
this.getQueryResults("SELECT { value : \"" + this.keywords[i] + "\" } FROM " + this.collection._name + " c", false);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in select
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesSelectValid3 () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to work
|
||||
var result = this.getQueryResults("SELECT { value : c.`" + this.keywords[i] + "` } FROM " + this.collection._name + " c WHERE c.`" + this.keywords[i] + "` == '" + this.keywords[i] + "'", false);
|
||||
for (var j in result) {
|
||||
if (!result.hasOwnProperty(j)) {
|
||||
continue;
|
||||
}
|
||||
assertEqual(this.keywords[i], result[j]["value"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in from alias
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesFromInvalid () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to work
|
||||
this.getQueryResults("SELECT { } FROM " + this.collection._name + " " + this.keywords[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in from alias
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesFromValid () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to work
|
||||
var result = this.getQueryResults("SELECT `" + this.keywords[i] + "` FROM " + this.collection._name + " `" + this.keywords[i] + "`", false);
|
||||
assertEqual(result.length, this.keywords.length);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesWhereInvalid () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to work
|
||||
this.getQueryResults("SELECT { } FROM " + this.collection._name + " c WHERE c." + this.keywords[i] + " == '" + this.keywords[i] + "'", true);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check keyword names in where
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testKeywordNamesWhereValid () {
|
||||
for (var i in this.keywords) {
|
||||
if (!this.keywords.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// this is expected to work
|
||||
var result = this.getQueryResults("SELECT { \"" + this.keywords[i] + "\" : c.`" + this.keywords[i] + "` } FROM " + this.collection._name + " c WHERE '" + this.keywords[i] + "' == c.`" + this.keywords[i] + "`", false);
|
||||
for (var j in result) {
|
||||
if (!result.hasOwnProperty(j)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
assertEqual(this.keywords[i], result[j][this.keywords[i]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief executes the test suite
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
jsUnity.run(aqlKeywordsTestSuite);
|
||||
|
||||
// Local Variables:
|
||||
// mode: outline-minor
|
||||
// outline-regexp: "^\\(/// @brief\\|/// @addtogroup\\|// --SECTION--\\|/// @page\\|/// @}\\)"
|
||||
// End:
|
|
@ -61,6 +61,10 @@ function aqlSimpleTestSuite () {
|
|||
|
||||
function executeQuery (query) {
|
||||
var aQuery = AQL_PREPARE(db, query);
|
||||
if (aQuery instanceof AvocadoQueryError) {
|
||||
print(query, aQuery.message);
|
||||
}
|
||||
assertFalse(aQuery instanceof AvocadoQueryError);
|
||||
if (aQuery) {
|
||||
return aQuery.execute();
|
||||
}
|
||||
|
@ -83,29 +87,54 @@ function aqlSimpleTestSuite () {
|
|||
return aCursor;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief assemble a query string from the parameters given and run the query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function runQuery (select, wheres, limit, order) {
|
||||
var query = this.assembleQuery(select, wheres, limit, order);
|
||||
var result = this.getQueryResults(query);
|
||||
assertFalse(result instanceof AvocadoQueryError);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief assemble a query string from the parameters given
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function assembleQuery (value1, value2, limit) {
|
||||
var query = 'SELECT { } FROM ' + this.collection._name + ' c WHERE ';
|
||||
var cond = '';
|
||||
|
||||
if (value1 !== undefined) {
|
||||
cond += value1;
|
||||
}
|
||||
if (value2 !== undefined) {
|
||||
if (cond != '') {
|
||||
cond += ' && ';
|
||||
function assembleQuery (select, wheres, limit, order) {
|
||||
var selectClause = select;
|
||||
|
||||
var whereClause = "";
|
||||
if (wheres instanceof Array) {
|
||||
whereClause = "WHERE ";
|
||||
var found = false;
|
||||
for (var i in wheres) {
|
||||
if (wheres[i] == "" || wheres[i] === undefined || wheres[i] === null || !wheres.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
if (found) {
|
||||
whereClause += "&& ";
|
||||
}
|
||||
found = true;
|
||||
whereClause += wheres[i] + " ";
|
||||
}
|
||||
cond += value2;
|
||||
}
|
||||
query += cond;
|
||||
|
||||
if (limit !== undefined) {
|
||||
query += ' LIMIT ' + limit;
|
||||
var orderClause = "";
|
||||
if (order != "" && order !== undefined && order !== null) {
|
||||
orderClause = "ORDER BY " + order + " ";
|
||||
}
|
||||
|
||||
var limitClause = "";
|
||||
if (limit !== undefined && limit !== null) {
|
||||
limitClause = "LIMIT " + limit;
|
||||
}
|
||||
|
||||
var query = "SELECT " + selectClause + " FROM " + this.collection._name + " c " +
|
||||
whereClause + orderClause + limitClause;
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
@ -114,8 +143,7 @@ function aqlSimpleTestSuite () {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function checkLength (expected, value1, value2, limit) {
|
||||
var query = this.assembleQuery(value1, value2, limit);
|
||||
var result = this.getQueryResults(query);
|
||||
var result = this.runQuery("{ }", new Array(value1, value2), limit);
|
||||
assertTrue(result instanceof Array);
|
||||
var actual = result.length;
|
||||
assertEqual(expected, actual);
|
||||
|
@ -505,6 +533,233 @@ function aqlSimpleTestSuite () {
|
|||
this.checkLength(2,'c.value1 <= 9', 'c.value2 == 8');
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check query result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testIdemValues1 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value: c.value1 }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(i, results[j]["value"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check query result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testIdemValues2 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value: c.value2 }", new Array("c.value2 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(i, results[j]["value"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check query result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testIdemValues3 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: c.value1, value2: c.value2 }", new Array("c.value1 == " + i, "c.value2 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(i, results[j]["value1"]);
|
||||
assertEqual(i, results[j]["value2"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check query result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testIdemValues3 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: c.value1, value2: c.value2 }", new Array("c.value1 == " + i, "c.value2 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(i, results[j]["value1"]);
|
||||
assertEqual(i, results[j]["value2"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check computed query result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testValueTypes1 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: c.value1, value2: c.value1 - 1, value3: c.value1 + 1, value4: null, value5: 'der fux' + 'xx' }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(i, results[j]["value1"]);
|
||||
assertEqual(i - 1, results[j]["value2"]);
|
||||
assertEqual(i + 1, results[j]["value3"]);
|
||||
assertEqual(null, results[j]["value4"]);
|
||||
assertEqual("der fuxxx", results[j]["value5"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check computed const result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testValueTypes2 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: null, value2: null + null, value3: undefined, value4: [], value5: { }, value6: 0, value7: 0.0 }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(null, results[j]["value1"]);
|
||||
assertEqual(0, results[j]["value2"]);
|
||||
assertEqual(undefined, results[j]["value3"]);
|
||||
assertEqual([], results[j]["value4"]);
|
||||
assertEqual({}, results[j]["value5"]);
|
||||
assertEqual(0, results[j]["value6"]);
|
||||
assertEqual(0.0, results[j]["value7"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check numeric result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testNumericValues1 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: 0, value2: -0, value3: +0, value4: 0 + 0, value5: 0 - 0, value6: 0 * 0 }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(0, results[j]["value1"]);
|
||||
assertEqual(0, results[j]["value2"]);
|
||||
assertEqual(0, results[j]["value3"]);
|
||||
assertEqual(0, results[j]["value4"]);
|
||||
assertEqual(0, results[j]["value5"]);
|
||||
assertEqual(0, results[j]["value6"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check numeric result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testNumericValues2 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: 1, value2: -1, value3: +1, value4: -1 + 2, value5: 2 - 1, value6: 1 * 1 }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(1, results[j]["value1"]);
|
||||
assertEqual(-1, results[j]["value2"]);
|
||||
assertEqual(1, results[j]["value3"]);
|
||||
assertEqual(1, results[j]["value4"]);
|
||||
assertEqual(1, results[j]["value5"]);
|
||||
assertEqual(1, results[j]["value6"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check numeric result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testNumericValues3 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: 1.0, value2: -1.0, value3: +1.0, value4: -1.0 + 2.0, value5: 2.0 - 1.0, value6: 1.0 * 1.0 }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(1, results[j]["value1"]);
|
||||
assertEqual(-1, results[j]["value2"]);
|
||||
assertEqual(1, results[j]["value3"]);
|
||||
assertEqual(1, results[j]["value4"]);
|
||||
assertEqual(1, results[j]["value5"]);
|
||||
assertEqual(1, results[j]["value6"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check numeric result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testNumericValues4 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: 42.0 - 10, value2: -15 + 37.5, value3: +11.4 - 18.3, value4: -15.3 - 16.5, value5: 14.0 - 18.5, value6: 14.2 * -13.5, value7: -14.05 * -14.15 }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(32, results[j]["value1"]);
|
||||
assertEqual(22.5, results[j]["value2"]);
|
||||
assertEqual(-6.9, results[j]["value3"]);
|
||||
assertEqual(-31.8, results[j]["value4"]);
|
||||
assertEqual(-4.5, results[j]["value5"]);
|
||||
assertEqual(-191.7, results[j]["value6"]);
|
||||
assertEqual(198.8075, results[j]["value7"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check string result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testStringValues1 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery("{ value1: '', value2: ' ', value3: ' ', value4: '\\'', value5: '\n', value6: '\\\\ \n\\'\\n\\\\\\'' }", new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual("", results[j]["value1"]);
|
||||
assertEqual(" ", results[j]["value2"]);
|
||||
assertEqual(" ", results[j]["value3"]);
|
||||
assertEqual("\'", results[j]["value4"]);
|
||||
assertEqual("\n", results[j]["value5"]);
|
||||
assertEqual("\\ \n\'\n\\\'", results[j]["value6"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check string result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testStringValues2 () {
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery('{ value1: "", value2: " ", value3: " ", value4: "\\"", value5: "\n", value6: "\\\\ \n\\"\\n\\\\\\"" }', new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual("", results[j]["value1"]);
|
||||
assertEqual(" ", results[j]["value2"]);
|
||||
assertEqual(" ", results[j]["value3"]);
|
||||
assertEqual("\"", results[j]["value4"]);
|
||||
assertEqual("\n", results[j]["value5"]);
|
||||
assertEqual("\\ \n\"\n\\\"", results[j]["value6"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check document result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testDocumentValues () {
|
||||
var expected = { "value1" : { "value11" : { "value111" : "", "value112" : 4 }, "value12" : "bang" }, "value2" : -5, "value3": { } };
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery(JSON.stringify(expected), new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(expected, results[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief check array result values
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function testArrayValues () {
|
||||
var expected = { "v" : [ 1, 2, 5, 99, { }, [ "value1", "value99", [ { "value5" : 5, "null" : null }, [ 1, -99, 0 ], "peng" ], { "x": 9 } ], { "aha" : 55 }, [ 0 ], [ ] ] };
|
||||
for (var i = 0; i <= 20; i++) {
|
||||
var results = this.runQuery(JSON.stringify(expected), new Array("c.value1 == " + i));
|
||||
for (var j = 0; j < results.length; j++) {
|
||||
assertEqual(expected, results[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue