mirror of https://gitee.com/bigwinds/arangodb
Merge branch 'devel' of github.com:triAGENS/ArangoDB into devel
This commit is contained in:
commit
7f387d9ac8
|
@ -64,7 +64,7 @@ FOR u IN users
|
|||
!SUBSECTION Horizontal lists
|
||||
|
||||
|
||||
Note that in the above result, an user might be returned multiple times. This is the
|
||||
Note that in the above result, a user might be returned multiple times. This is the
|
||||
SQL way of returning data. If this is not desired, the friends' ids of each user
|
||||
can be returned in a horizontal list. This will return each user at most once.
|
||||
|
||||
|
|
|
@ -1,221 +1,221 @@
|
|||
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary {
|
||||
display: block
|
||||
display: block
|
||||
}
|
||||
audio,canvas,video {
|
||||
display: inline-block
|
||||
display: inline-block
|
||||
}
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0
|
||||
display: none;
|
||||
height: 0
|
||||
}
|
||||
[hidden] {
|
||||
display: none
|
||||
display: none
|
||||
}
|
||||
html {
|
||||
font-family: sans-serif;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%
|
||||
font-family: sans-serif;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%
|
||||
}
|
||||
body {
|
||||
margin: 0
|
||||
margin: 0
|
||||
}
|
||||
a:focus {
|
||||
outline: thin dotted
|
||||
outline: thin dotted
|
||||
}
|
||||
a:active,a:hover {
|
||||
outline: 0
|
||||
outline: 0
|
||||
}
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: .67em 0
|
||||
font-size: 2em;
|
||||
margin: .67em 0
|
||||
}
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted
|
||||
border-bottom: 1px dotted
|
||||
}
|
||||
b,strong {
|
||||
font-weight: bold
|
||||
font-weight: bold
|
||||
}
|
||||
dfn {
|
||||
font-style: italic
|
||||
font-style: italic
|
||||
}
|
||||
hr {
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0
|
||||
-moz-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
height: 0
|
||||
}
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000
|
||||
background: #ff0;
|
||||
color: #000
|
||||
}
|
||||
code,kbd,pre,samp {
|
||||
font-family: monospace,serif;
|
||||
font-size: 1em
|
||||
font-family: monospace,serif;
|
||||
font-size: 1em
|
||||
}
|
||||
pre {
|
||||
white-space: pre-wrap
|
||||
white-space: pre-wrap
|
||||
}
|
||||
q {
|
||||
quotes: "\201C" "\201D" "\2018" "\2019"
|
||||
quotes: "\201C" "\201D" "\2018" "\2019"
|
||||
}
|
||||
small {
|
||||
font-size: 80%
|
||||
font-size: 80%
|
||||
}
|
||||
sub,sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline
|
||||
}
|
||||
sup {
|
||||
top: -0.5em
|
||||
top: -0.5em
|
||||
}
|
||||
sub {
|
||||
bottom: -0.25em
|
||||
bottom: -0.25em
|
||||
}
|
||||
img {
|
||||
border: 0
|
||||
border: 0
|
||||
}
|
||||
svg:not(:root) {
|
||||
overflow: hidden
|
||||
overflow: hidden
|
||||
}
|
||||
figure {
|
||||
margin: 0
|
||||
margin: 0
|
||||
}
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: .35em .625em .75em
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: .35em .625em .75em
|
||||
}
|
||||
legend {
|
||||
border: 0;
|
||||
padding: 0
|
||||
border: 0;
|
||||
padding: 0
|
||||
}
|
||||
button,input,select,textarea {
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
margin: 0
|
||||
font-family: inherit;
|
||||
font-size: 100%;
|
||||
margin: 0
|
||||
}
|
||||
button,input {
|
||||
line-height: normal
|
||||
line-height: normal
|
||||
}
|
||||
button,select {
|
||||
text-transform: none
|
||||
text-transform: none
|
||||
}
|
||||
button,html input[type="button"],input[type="reset"],input[type="submit"] {
|
||||
-webkit-appearance: button;
|
||||
cursor: pointer
|
||||
-webkit-appearance: button;
|
||||
cursor: pointer
|
||||
}
|
||||
button[disabled],html input[disabled] {
|
||||
cursor: default
|
||||
cursor: default
|
||||
}
|
||||
input[type="checkbox"],input[type="radio"] {
|
||||
box-sizing: border-box;
|
||||
padding: 0
|
||||
box-sizing: border-box;
|
||||
padding: 0
|
||||
}
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield;
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box
|
||||
-webkit-appearance: textfield;
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box
|
||||
}
|
||||
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none
|
||||
-webkit-appearance: none
|
||||
}
|
||||
button::-moz-focus-inner,input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0
|
||||
border: 0;
|
||||
padding: 0
|
||||
}
|
||||
textarea {
|
||||
overflow: auto;
|
||||
vertical-align: top
|
||||
overflow: auto;
|
||||
vertical-align: top
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'FontAwesome';
|
||||
src: url('.//fonts/fontawesome/fontawesome-webfont.eot?v=4.1.0');
|
||||
src: url('.//fonts/fontawesome/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('.//fonts/fontawesome/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('.//fonts/fontawesome/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('.//fonts/fontawesome/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal
|
||||
font-family: 'FontAwesome';
|
||||
src: url('.//fonts/fontawesome/fontawesome-webfont.eot?v=4.1.0');
|
||||
src: url('.//fonts/fontawesome/fontawesome-webfont.eot?#iefix&v=4.1.0') format('embedded-opentype'),url('.//fonts/fontawesome/fontawesome-webfont.woff?v=4.1.0') format('woff'),url('.//fonts/fontawesome/fontawesome-webfont.ttf?v=4.1.0') format('truetype'),url('.//fonts/fontawesome/fontawesome-webfont.svg?v=4.1.0#fontawesomeregular') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal
|
||||
}
|
||||
.fa {
|
||||
display: inline-block;
|
||||
font-family: FontAwesome;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale
|
||||
display: inline-block;
|
||||
font-family: FontAwesome;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale
|
||||
}
|
||||
.fa-lg {
|
||||
font-size: 1.3333333333333333em;
|
||||
line-height: .75em;
|
||||
vertical-align: -15%
|
||||
font-size: 1.3333333333333333em;
|
||||
line-height: .75em;
|
||||
vertical-align: -15%
|
||||
}
|
||||
.fa-2x {
|
||||
font-size: 2em
|
||||
font-size: 2em
|
||||
}
|
||||
.fa-3x {
|
||||
font-size: 3em
|
||||
font-size: 3em
|
||||
}
|
||||
.fa-4x {
|
||||
font-size: 4em
|
||||
font-size: 4em
|
||||
}
|
||||
.fa-5x {
|
||||
font-size: 5em
|
||||
font-size: 5em
|
||||
}
|
||||
.fa-fw {
|
||||
width: 1.2857142857142858em;
|
||||
text-align: center
|
||||
width: 1.2857142857142858em;
|
||||
text-align: center
|
||||
}
|
||||
.fa-ul {
|
||||
padding-left: 0;
|
||||
margin-left: 2.142857142857143em;
|
||||
list-style-type: none
|
||||
padding-left: 0;
|
||||
margin-left: 2.142857142857143em;
|
||||
list-style-type: none
|
||||
}
|
||||
.fa-ul>li {
|
||||
position: relative
|
||||
position: relative
|
||||
}
|
||||
.fa-li {
|
||||
position: absolute;
|
||||
left: -2.142857142857143em;
|
||||
width: 2.142857142857143em;
|
||||
top: .14285714285714285em;
|
||||
text-align: center
|
||||
position: absolute;
|
||||
left: -2.142857142857143em;
|
||||
width: 2.142857142857143em;
|
||||
top: .14285714285714285em;
|
||||
text-align: center
|
||||
}
|
||||
.fa-li.fa-lg {
|
||||
left: -1.8571428571428572em
|
||||
left: -1.8571428571428572em
|
||||
}
|
||||
.fa-border {
|
||||
padding: .2em .25em .15em;
|
||||
border: solid .08em #eee;
|
||||
border-radius: .1em
|
||||
padding: .2em .25em .15em;
|
||||
border: solid .08em #eee;
|
||||
border-radius: .1em
|
||||
}
|
||||
.pull-right {
|
||||
float: right
|
||||
float: right
|
||||
}
|
||||
.pull-left {
|
||||
float: left
|
||||
float: left
|
||||
}
|
||||
.fa.pull-left {
|
||||
margin-right: .3em
|
||||
margin-right: .3em
|
||||
}
|
||||
.fa.pull-right {
|
||||
margin-left: .3em
|
||||
margin-left: .3em
|
||||
}
|
||||
.fa-spin {
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
-moz-animation: spin 2s infinite linear;
|
||||
-o-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
-moz-animation: spin 2s infinite linear;
|
||||
-o-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear
|
||||
}
|
||||
@-moz-keyframes spin {0% {
|
||||
-moz-transform: rotate(0deg)
|
||||
-moz-transform: rotate(0deg)
|
||||
}
|
||||
100% {
|
||||
-moz-transform: rotate(359deg)
|
||||
-moz-transform: rotate(359deg)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1634,6 +1634,9 @@ color: inherit
|
|||
.hidden {
|
||||
display: none
|
||||
}
|
||||
.lets-see-who-copies-this: {
|
||||
font-family: 'proven!';
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Merriweather';
|
||||
font-style: normal;
|
||||
|
@ -2904,10 +2907,10 @@ font-family: "Open Sans","Clear Sans","Helvetica Neue",Helvetica,Arial,sans-seri
|
|||
font-size: 14px
|
||||
}
|
||||
div.example_show_button {
|
||||
border: medium solid lightgray;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
border: medium solid lightgray;
|
||||
text-align: center;
|
||||
position: relative;
|
||||
top: -10px;
|
||||
}
|
||||
|
||||
.book .book-body .page-wrapper .page-inner section.normal .deprecated{
|
||||
|
@ -2919,26 +2922,26 @@ background-color: rgba(240,240,0,0.4);
|
|||
}
|
||||
|
||||
#clear-search {
|
||||
display: inline;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 9px;
|
||||
font-size: 18pt;
|
||||
line-height: 18pt;
|
||||
color: #364149; // needs to be updated on theme change
|
||||
display: inline;
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
right: 9px;
|
||||
font-size: 18pt;
|
||||
line-height: 18pt;
|
||||
color: #364149; // needs to be updated on theme change
|
||||
}
|
||||
|
||||
#clear-search:hover {
|
||||
color: #008cff; // needs to be updated on theme change
|
||||
text-decoration: none;
|
||||
color: #008cff; // needs to be updated on theme change
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.book .book-summary .book-search input{
|
||||
padding-right: 20px !important;
|
||||
padding-right: 20px !important;
|
||||
}
|
||||
|
||||
.book .book-header {
|
||||
background-color: #FFFFFF !important;
|
||||
width: 84%;
|
||||
position:fixed !important;
|
||||
background-color: #FFFFFF !important;
|
||||
width: 84%;
|
||||
position:fixed !important;
|
||||
}
|
|
@ -111,6 +111,23 @@ std::vector<std::string> Collection::shardIds () const {
|
|||
return ids;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the shard keys of a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::string> Collection::shardKeys () const {
|
||||
auto clusterInfo = triagens::arango::ClusterInfo::instance();
|
||||
auto collectionInfo = clusterInfo->getCollection(std::string(vocbase->_name), name);
|
||||
if (collectionInfo.get() == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "collection not found");
|
||||
}
|
||||
|
||||
std::vector<std::string> keys;
|
||||
for (auto const& x : collectionInfo.get()->shardKeys()) {
|
||||
keys.emplace_back(x);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the indexes of the collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -145,6 +145,12 @@ namespace triagens {
|
|||
|
||||
std::vector<std::string> shardIds () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the shard keys of a collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
std::vector<std::string> shardKeys () const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the indexes of the collection
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -3717,6 +3717,28 @@ size_t BlockWithClients::getClientId (std::string const& shardId) {
|
|||
return ((*it).second);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief preInitCursor: check if we should really init the cursor, and reset
|
||||
/// _doneForClient
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool BlockWithClients::preInitCursor () {
|
||||
|
||||
if (!_initOrShutdown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
_doneForClient.clear();
|
||||
_doneForClient.reserve(_nrClients);
|
||||
|
||||
for (size_t i = 0; i < _nrClients; i++) {
|
||||
_doneForClient.push_back(false);
|
||||
}
|
||||
|
||||
_initOrShutdown = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- class ScatterBlock
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -3727,25 +3749,20 @@ size_t BlockWithClients::getClientId (std::string const& shardId) {
|
|||
|
||||
int ScatterBlock::initializeCursor (AqlItemBlock* items, size_t pos) {
|
||||
|
||||
if (!_initOrShutdown) {
|
||||
if (!preInitCursor()) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
int res = ExecutionBlock::initializeCursor(items, pos);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
_posForClient.clear();
|
||||
_doneForClient.clear();
|
||||
_doneForClient.reserve(_nrClients);
|
||||
|
||||
for (size_t i = 0; i < _nrClients; i++) {
|
||||
_posForClient.push_back(std::make_pair(0, 0));
|
||||
_doneForClient.push_back(false);
|
||||
}
|
||||
_initOrShutdown = false;
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -3896,27 +3913,18 @@ DistributeBlock::DistributeBlock (ExecutionEngine* engine,
|
|||
|
||||
int DistributeBlock::initializeCursor (AqlItemBlock* items, size_t pos) {
|
||||
|
||||
if (!_initOrShutdown) {
|
||||
if (!preInitCursor()) {
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
int res = ExecutionBlock::initializeCursor(items, pos);
|
||||
|
||||
if (res != TRI_ERROR_NO_ERROR) {
|
||||
return res;
|
||||
}
|
||||
|
||||
for (auto x: _distBuffer) {
|
||||
x.clear();
|
||||
}
|
||||
_distBuffer.clear();
|
||||
_distBuffer.reserve(_nrClients);
|
||||
|
||||
for (auto x: _doneForClient) {
|
||||
x = false;
|
||||
}
|
||||
|
||||
_initOrShutdown = false;
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
|
@ -4115,10 +4123,17 @@ bool DistributeBlock::getBlockForClient (size_t atLeast,
|
|||
|
||||
size_t DistributeBlock::sendToClient (AqlValue val) {
|
||||
|
||||
TRI_ASSERT(val._type == AqlValue::JSON);
|
||||
//TODO should work for SHAPED too (maybe this requires converting it to TRI_json_t)
|
||||
|
||||
TRI_json_t const* json = val._json->json();
|
||||
TRI_json_t const* json;
|
||||
if (val._type == AqlValue::JSON) {
|
||||
json = val._json->json();
|
||||
}
|
||||
else if (val._type == AqlValue::SHAPED) {
|
||||
json = val.toJson(_trx, _collection->documentCollection()).json();
|
||||
}
|
||||
else {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_FAILED,
|
||||
"DistributeBlock: can only send JSON or SHAPED");
|
||||
}
|
||||
|
||||
std::string shardId;
|
||||
bool usesDefaultShardingAttributes;
|
||||
|
|
|
@ -1613,6 +1613,13 @@ namespace triagens {
|
|||
// --SECTION-- BlockWithClients protected methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief preInitCursor: check if we should really init the cursor, and reset
|
||||
/// _doneForClient
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool preInitCursor ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief getOrSkipSomeForShard
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -2448,7 +2448,6 @@ void DistributeNode::toJsonHelper (triagens::basics::Json& nodes,
|
|||
("collection", triagens::basics::Json(_collection->getName()))
|
||||
("varId", triagens::basics::Json(static_cast<int>(_varId)));
|
||||
|
||||
|
||||
// And add it:
|
||||
nodes(json);
|
||||
}
|
||||
|
|
|
@ -421,6 +421,16 @@ void Executor::generateCodeString (char const* value) {
|
|||
_buffer->appendChar('"');
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates code for a string value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Executor::generateCodeString (std::string const& value) {
|
||||
_buffer->appendChar('"');
|
||||
_buffer->appendJsonEncoded(value.c_str());
|
||||
_buffer->appendChar('"');
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for a list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
/// @author Copyright 2012-2013, triAGENS GmbH, Cologne, Germany
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef ARANGODB_AQL_V8_EXECUTOR_H
|
||||
#define ARANGODB_AQL_V8_EXECUTOR_H 1
|
||||
#ifndef ARANGODB_AQL_EXECUTOR_H
|
||||
#define ARANGODB_AQL_EXECUTOR_H 1
|
||||
|
||||
#include "Basics/Common.h"
|
||||
#include "Aql/Function.h"
|
||||
|
@ -121,6 +121,12 @@ namespace triagens {
|
|||
|
||||
void generateCodeString (char const*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generates code for a string value
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void generateCodeString (std::string const&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief generate JavaScript code for a list
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1689,7 +1689,6 @@ int triagens::aql::scatterInCluster (Optimizer* opt,
|
|||
// re-link with the remote node
|
||||
node->addDependency(remoteNode);
|
||||
|
||||
|
||||
// insert another remote node
|
||||
remoteNode = new RemoteNode(plan, plan->nextId(), vocbase, collection, "", "", "");
|
||||
plan->registerNode(remoteNode);
|
||||
|
@ -1742,21 +1741,30 @@ int triagens::aql::distributeInCluster (Optimizer* opt,
|
|||
auto const nodeType = node->getType();
|
||||
|
||||
if (nodeType != ExecutionNode::INSERT &&
|
||||
nodeType != ExecutionNode::UPDATE &&
|
||||
nodeType != ExecutionNode::REPLACE &&
|
||||
nodeType != ExecutionNode::REMOVE) {
|
||||
opt->addPlan(plan, rule->level, wasModified);
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
Collection const* collection = static_cast<ModificationNode*>(node)->collection();
|
||||
|
||||
if (nodeType == ExecutionNode::REMOVE) {
|
||||
// check if collection shard keys are only _key
|
||||
std::vector<std::string> shardKeys = collection->shardKeys();
|
||||
if (shardKeys.size() != 1 || shardKeys[0] != "_key") {
|
||||
opt->addPlan(plan, rule->level, wasModified);
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
auto deps = node->getDependencies();
|
||||
TRI_ASSERT(deps.size() == 1);
|
||||
|
||||
// unlink the node
|
||||
plan->unlinkNode(node, true);
|
||||
|
||||
// extract database and collection from plan node
|
||||
// extract database from plan node
|
||||
TRI_vocbase_t* vocbase = static_cast<ModificationNode*>(node)->vocbase();
|
||||
Collection const* collection = static_cast<ModificationNode*>(node)->collection();
|
||||
|
||||
// insert a distribute node
|
||||
TRI_ASSERT(node->getVariablesUsedHere().size() == 1);
|
||||
|
@ -1782,6 +1790,7 @@ int triagens::aql::distributeInCluster (Optimizer* opt,
|
|||
opt->addPlan(plan, rule->level, wasModified);
|
||||
return TRI_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief move filters up into the cluster distribution part of the plan
|
||||
/// this rule modifies the plan in place
|
||||
|
|
|
@ -37,9 +37,11 @@
|
|||
#include "Basics/JsonHelper.h"
|
||||
#include "Basics/json.h"
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Cluster/ServerState.h"
|
||||
#include "Utils/AqlTransaction.h"
|
||||
#include "Utils/Exception.h"
|
||||
#include "Utils/V8TransactionContext.h"
|
||||
#include "V8Server/ApplicationV8.h"
|
||||
#include "VocBase/vocbase.h"
|
||||
|
||||
using namespace triagens::aql;
|
||||
|
@ -115,14 +117,18 @@ TRI_json_t* Profile::toJson (TRI_memory_zone_t*) {
|
|||
/// @brief creates a query
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Query::Query (TRI_vocbase_t* vocbase,
|
||||
Query::Query (triagens::arango::ApplicationV8* applicationV8,
|
||||
bool contextOwnedByExterior,
|
||||
TRI_vocbase_t* vocbase,
|
||||
char const* queryString,
|
||||
size_t queryLength,
|
||||
TRI_json_t* bindParameters,
|
||||
TRI_json_t* options,
|
||||
QueryPart part)
|
||||
: _vocbase(vocbase),
|
||||
: _applicationV8(applicationV8),
|
||||
_vocbase(vocbase),
|
||||
_executor(nullptr),
|
||||
_context(nullptr),
|
||||
_queryString(queryString),
|
||||
_queryLength(queryLength),
|
||||
_queryJson(),
|
||||
|
@ -137,7 +143,9 @@ Query::Query (TRI_vocbase_t* vocbase,
|
|||
_parser(nullptr),
|
||||
_trx(nullptr),
|
||||
_engine(nullptr),
|
||||
_part(part) {
|
||||
_part(part),
|
||||
_clusterStatus(-1),
|
||||
_contextOwnedByExterior(contextOwnedByExterior) {
|
||||
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
|
||||
|
@ -156,12 +164,16 @@ Query::Query (TRI_vocbase_t* vocbase,
|
|||
/// @brief creates a query from Json
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Query::Query (TRI_vocbase_t* vocbase,
|
||||
Query::Query (triagens::arango::ApplicationV8* applicationV8,
|
||||
bool contextOwnedByExterior,
|
||||
TRI_vocbase_t* vocbase,
|
||||
triagens::basics::Json queryStruct,
|
||||
TRI_json_t* options,
|
||||
QueryPart part)
|
||||
: _vocbase(vocbase),
|
||||
: _applicationV8(applicationV8),
|
||||
_vocbase(vocbase),
|
||||
_executor(nullptr),
|
||||
_context(nullptr),
|
||||
_queryString(nullptr),
|
||||
_queryLength(0),
|
||||
_queryJson(queryStruct),
|
||||
|
@ -176,7 +188,9 @@ Query::Query (TRI_vocbase_t* vocbase,
|
|||
_parser(nullptr),
|
||||
_trx(nullptr),
|
||||
_engine(nullptr),
|
||||
_part(part) {
|
||||
_part(part),
|
||||
_clusterStatus(-1),
|
||||
_contextOwnedByExterior(contextOwnedByExterior) {
|
||||
|
||||
TRI_ASSERT(_vocbase != nullptr);
|
||||
|
||||
|
@ -213,6 +227,12 @@ Query::~Query () {
|
|||
_executor = nullptr;
|
||||
}
|
||||
|
||||
if (_context != nullptr) {
|
||||
TRI_ASSERT(! _contextOwnedByExterior);
|
||||
_applicationV8->exitContext(_context);
|
||||
_context = nullptr;
|
||||
}
|
||||
|
||||
if (_ast != nullptr) {
|
||||
delete _ast;
|
||||
_ast = nullptr;
|
||||
|
@ -242,7 +262,9 @@ Query* Query::clone (QueryPart part) {
|
|||
std::unique_ptr<Query> clone;
|
||||
|
||||
try {
|
||||
clone.reset(new Query(_vocbase,
|
||||
clone.reset(new Query(_applicationV8,
|
||||
false,
|
||||
_vocbase,
|
||||
_queryString,
|
||||
_queryLength,
|
||||
nullptr,
|
||||
|
@ -759,6 +781,55 @@ char* Query::registerString (std::string const& p,
|
|||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not we are running in a cluster
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Query::isRunningInCluster () {
|
||||
if (_clusterStatus == -1) {
|
||||
// not yet determined
|
||||
_clusterStatus = 0;
|
||||
if (triagens::arango::ServerState::instance()->isRunningInCluster()) {
|
||||
_clusterStatus = 1;
|
||||
}
|
||||
}
|
||||
TRI_ASSERT(_clusterStatus == 0 || _clusterStatus == 1);
|
||||
return (_clusterStatus == 1);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief enter a V8 context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Query::enterContext () {
|
||||
if (! _contextOwnedByExterior) {
|
||||
if (_context == nullptr) {
|
||||
_context = _applicationV8->enterContext("STANDARD", _vocbase, false, false);
|
||||
if (_context == nullptr) {
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "cannot enter V8 context");
|
||||
}
|
||||
}
|
||||
|
||||
TRI_ASSERT(_context != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief return a V8 context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Query::exitContext () {
|
||||
if (! _contextOwnedByExterior) {
|
||||
if (_context != nullptr) {
|
||||
if (isRunningInCluster()) {
|
||||
_applicationV8->exitContext(_context);
|
||||
_context = nullptr;
|
||||
}
|
||||
}
|
||||
TRI_ASSERT(_context == nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief fetch a boolean value from the options
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "Aql/types.h"
|
||||
#include "Utils/AqlTransaction.h"
|
||||
#include "Utils/V8TransactionContext.h"
|
||||
#include "V8Server/ApplicationV8.h"
|
||||
|
||||
struct TRI_json_t;
|
||||
struct TRI_vocbase_s;
|
||||
|
@ -127,14 +128,18 @@ namespace triagens {
|
|||
|
||||
public:
|
||||
|
||||
Query (struct TRI_vocbase_s*,
|
||||
Query (triagens::arango::ApplicationV8*,
|
||||
bool,
|
||||
struct TRI_vocbase_s*,
|
||||
char const*,
|
||||
size_t,
|
||||
struct TRI_json_t*,
|
||||
struct TRI_json_t*,
|
||||
QueryPart);
|
||||
|
||||
Query (struct TRI_vocbase_s*,
|
||||
Query (triagens::arango::ApplicationV8*,
|
||||
bool,
|
||||
struct TRI_vocbase_s*,
|
||||
triagens::basics::Json queryStruct,
|
||||
struct TRI_json_t*,
|
||||
QueryPart);
|
||||
|
@ -362,10 +367,28 @@ namespace triagens {
|
|||
|
||||
void setPlan (ExecutionPlan *plan);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief enter a V8 context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void enterContext ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief exits a V8 context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void exitContext ();
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not we are running in a cluster
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool isRunningInCluster ();
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief fetch a boolean value from the options
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -416,6 +439,12 @@ namespace triagens {
|
|||
|
||||
private:
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief application v8 used in the query, we need this for V8 context access
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::arango::ApplicationV8* _applicationV8;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief all nodes created in the AST - will be used for freeing them later
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -434,6 +463,12 @@ namespace triagens {
|
|||
|
||||
Executor* _executor;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the currently used V8 context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::arango::ApplicationV8::V8Context* _context;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief the actual query string
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -526,6 +561,18 @@ namespace triagens {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
QueryPart const _part;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief internal variable we use to determine whether we are in a cluster
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
short int _clusterStatus;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief whether or not someone else has acquired a V8 context for us
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool const _contextOwnedByExterior;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ void RestAqlHandler::createQueryFromJson () {
|
|||
|
||||
std::string const part = JsonHelper::getStringValue(queryJson.json(), "part", "");
|
||||
|
||||
auto query = new Query(_vocbase, plan, options.steal(), (part == "main" ? PART_MAIN : PART_DEPENDENT));
|
||||
auto query = new Query(_applicationV8, false, _vocbase, plan, options.steal(), (part == "main" ? PART_MAIN : PART_DEPENDENT));
|
||||
QueryResult res = query->prepare(_queryRegistry);
|
||||
if (res.code != TRI_ERROR_NO_ERROR) {
|
||||
generateError(HttpResponse::BAD, TRI_ERROR_QUERY_BAD_JSON_PLAN,
|
||||
|
@ -188,7 +188,7 @@ void RestAqlHandler::parseQuery () {
|
|||
return;
|
||||
}
|
||||
|
||||
auto query = new Query(_vocbase, queryString.c_str(), queryString.size(),
|
||||
auto query = new Query(_applicationV8, false, _vocbase, queryString.c_str(), queryString.size(),
|
||||
nullptr, nullptr, PART_MAIN);
|
||||
QueryResult res = query->parse();
|
||||
if (res.code != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -244,7 +244,7 @@ void RestAqlHandler::explainQuery () {
|
|||
Json options;
|
||||
options = queryJson.get("options").copy(); // cannot throw
|
||||
|
||||
auto query = new Query(_vocbase, queryString.c_str(), queryString.size(),
|
||||
auto query = new Query(_applicationV8, false, _vocbase, queryString.c_str(), queryString.size(),
|
||||
parameters.steal(), options.steal(), PART_MAIN);
|
||||
QueryResult res = query->explain();
|
||||
if (res.code != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -304,7 +304,7 @@ void RestAqlHandler::createQueryFromString () {
|
|||
Json options;
|
||||
options = queryJson.get("options").copy(); // cannot throw
|
||||
|
||||
auto query = new Query(_vocbase, queryString.c_str(), queryString.size(),
|
||||
auto query = new Query(_applicationV8, false, _vocbase, queryString.c_str(), queryString.size(),
|
||||
parameters.steal(), options.steal(), (part == "main" ? PART_MAIN : PART_DEPENDENT));
|
||||
QueryResult res = query->prepare(_queryRegistry);
|
||||
if (res.code != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -586,14 +586,6 @@ void RestAqlHandler::getInfoQuery (std::string const& operation,
|
|||
triagens::rest::HttpHandler::status_t RestAqlHandler::execute () {
|
||||
//std::cout << "GOT INCOMING REQUEST: " << triagens::rest::HttpRequest::translateMethod(_request->requestType()) << ", " << triagens::arango::ServerState::instance()->getId() << ": " << _request->fullUrl() << ": " << _request->body() << "\n";
|
||||
|
||||
auto context = _applicationV8->enterContext("STANDARD", _vocbase,
|
||||
false, false);
|
||||
|
||||
if (nullptr == context) {
|
||||
generateError(HttpResponse::SERVER_ERROR, TRI_ERROR_INTERNAL,
|
||||
"cannot enter V8 context");
|
||||
}
|
||||
else {
|
||||
std::vector<std::string> const& suffix = _request->suffix();
|
||||
|
||||
// extract the sub-request type
|
||||
|
@ -661,9 +653,6 @@ triagens::rest::HttpHandler::status_t RestAqlHandler::execute () {
|
|||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_applicationV8->exitContext(context);
|
||||
//std::cout << "REQUEST HANDLING DONE: " << triagens::arango::ServerState::instance()->getId() << ": " << _request->fullUrl() << ": " << _response->responseCode() << ", CONTENT-LENGTH: " << _response->contentLength() << "\n";
|
||||
|
||||
return status_t(HANDLER_DONE);
|
||||
|
|
|
@ -255,7 +255,6 @@ bool ServerState::isRunningInCluster () {
|
|||
_role == ServerState::ROLE_COORDINATOR);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief get the server id
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1224,7 +1224,7 @@ bool ApplicationV8::prepareV8Instance (const string& name, size_t i, bool useAct
|
|||
|
||||
context->_context->Enter();
|
||||
|
||||
TRI_InitV8VocBridge(context->_context, _queryRegistry, _server, _vocbase, &_startupLoader, i);
|
||||
TRI_InitV8VocBridge(this, context->_context, _queryRegistry, _server, _vocbase, &_startupLoader, i);
|
||||
TRI_InitV8Queries(context->_context);
|
||||
TRI_InitV8UserStructures(context->_context);
|
||||
|
||||
|
|
|
@ -1343,8 +1343,7 @@ void TRI_InitV8Actions (v8::Handle<v8::Context> context,
|
|||
GlobalV8Dealer = applicationV8;
|
||||
|
||||
// check the isolate
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
/* TRI_v8_global_t* v8g = */ TRI_CreateV8Globals(isolate);
|
||||
v8::Isolate::GetCurrent();
|
||||
|
||||
// .............................................................................
|
||||
// create the global functions
|
||||
|
|
|
@ -462,8 +462,7 @@ void TRI_InitV8Dispatcher (v8::Handle<v8::Context> context,
|
|||
GlobalV8Dealer = applicationV8;
|
||||
|
||||
// check the isolate
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
/* TRI_v8_global_t* v8g = */ TRI_CreateV8Globals(isolate);
|
||||
v8::Isolate::GetCurrent();
|
||||
|
||||
// .............................................................................
|
||||
// create the global functions
|
||||
|
|
|
@ -821,7 +821,8 @@ static v8::Handle<v8::Value> JS_ParseAql (v8::Arguments const& argv) {
|
|||
|
||||
string const&& queryString = TRI_ObjectToString(argv[0]);
|
||||
|
||||
triagens::aql::Query query(vocbase, queryString.c_str(), queryString.size(), nullptr, nullptr, triagens::aql::PART_MAIN);
|
||||
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, queryString.c_str(), queryString.size(), nullptr, nullptr, triagens::aql::PART_MAIN);
|
||||
|
||||
auto parseResult = query.parse();
|
||||
|
||||
|
@ -906,7 +907,8 @@ static v8::Handle<v8::Value> JS_ExplainAql (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
// bind parameters will be freed by the query later
|
||||
triagens::aql::Query query(vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
|
||||
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.explain();
|
||||
|
||||
|
@ -998,8 +1000,8 @@ static v8::Handle<v8::Value> JS_ExecuteAqlJson (v8::Arguments const& argv) {
|
|||
}
|
||||
|
||||
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, Json(TRI_UNKNOWN_MEM_ZONE, queryjson), options, triagens::aql::PART_MAIN);
|
||||
|
||||
triagens::aql::Query query(vocbase, Json(TRI_UNKNOWN_MEM_ZONE, queryjson), options, triagens::aql::PART_MAIN);
|
||||
auto queryResult = query.execute(static_cast<triagens::aql::QueryRegistry*>(v8g->_queryRegistry));
|
||||
|
||||
if (queryResult.code != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -1133,10 +1135,10 @@ static v8::Handle<v8::Value> JS_ExecuteAql (v8::Arguments const& argv) {
|
|||
options = TRI_ObjectToJson(argv[2]);
|
||||
}
|
||||
|
||||
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||
|
||||
// bind parameters will be freed by the query later
|
||||
triagens::aql::Query query(vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
|
||||
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(v8::Isolate::GetCurrent()->GetData());
|
||||
triagens::aql::Query query(v8g->_applicationV8, true, vocbase, queryString.c_str(), queryString.size(), parameters, options, triagens::aql::PART_MAIN);
|
||||
|
||||
auto queryResult = query.execute(static_cast<triagens::aql::QueryRegistry*>(v8g->_queryRegistry));
|
||||
|
||||
if (queryResult.code != TRI_ERROR_NO_ERROR) {
|
||||
|
@ -2489,7 +2491,8 @@ void TRI_V8ReloadRouting (v8::Handle<v8::Context> context) {
|
|||
/// @brief creates a TRI_vocbase_t global context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitV8VocBridge (v8::Handle<v8::Context> context,
|
||||
void TRI_InitV8VocBridge (triagens::arango::ApplicationV8* applicationV8,
|
||||
v8::Handle<v8::Context> context,
|
||||
triagens::aql::QueryRegistry* queryRegistry,
|
||||
TRI_server_t* server,
|
||||
TRI_vocbase_t* vocbase,
|
||||
|
@ -2502,7 +2505,6 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context,
|
|||
TRI_v8_global_t* v8g = TRI_CreateV8Globals(isolate);
|
||||
|
||||
TRI_ASSERT(v8g->_transactionContext == nullptr);
|
||||
|
||||
v8g->_transactionContext = new V8TransactionContext(true);
|
||||
static_cast<V8TransactionContext*>(v8g->_transactionContext)->makeGlobal();
|
||||
|
||||
|
@ -2518,6 +2520,9 @@ void TRI_InitV8VocBridge (v8::Handle<v8::Context> context,
|
|||
// register the startup loader
|
||||
v8g->_loader = loader;
|
||||
|
||||
// register the context dealer
|
||||
v8g->_applicationV8 = applicationV8;
|
||||
|
||||
v8::Handle<v8::ObjectTemplate> ArangoNS;
|
||||
v8::Handle<v8::ObjectTemplate> rt;
|
||||
v8::Handle<v8::FunctionTemplate> ft;
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace triagens {
|
|||
}
|
||||
|
||||
namespace arango {
|
||||
class ApplicationV8;
|
||||
class CollectionNameResolver;
|
||||
class JSLoader;
|
||||
}
|
||||
|
@ -95,7 +96,8 @@ void TRI_V8ReloadRouting (v8::Handle<v8::Context>);
|
|||
/// @brief creates a TRI_vocbase_t global context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitV8VocBridge (v8::Handle<v8::Context>,
|
||||
void TRI_InitV8VocBridge (triagens::arango::ApplicationV8*,
|
||||
v8::Handle<v8::Context>,
|
||||
triagens::aql::QueryRegistry*,
|
||||
struct TRI_server_s*,
|
||||
struct TRI_vocbase_s*,
|
||||
|
|
|
@ -159,7 +159,7 @@
|
|||
"count": this.getPageSize()
|
||||
};
|
||||
|
||||
query = "FOR x in @@collection";
|
||||
query = "FOR x in @@collection let att = slice(ATTRIBUTES(x), 0, 10)";
|
||||
query += this.setFiltersForQuery(bindVars);
|
||||
// Sort result, only useful for a small number of docs
|
||||
if (this.getTotal() < this.MAX_SORT) {
|
||||
|
@ -173,14 +173,14 @@
|
|||
}
|
||||
|
||||
if (bindVars.count !== 'all') {
|
||||
query += " LIMIT @offset, @count RETURN x";
|
||||
query += " LIMIT @offset, @count RETURN keep(x, att)";
|
||||
}
|
||||
else {
|
||||
tmp = {
|
||||
"@collection": this.collectionID
|
||||
};
|
||||
bindVars = tmp;
|
||||
query += " RETURN x";
|
||||
query += " RETURN keep(x, att)";
|
||||
}
|
||||
|
||||
queryObj = {
|
||||
|
|
|
@ -106,7 +106,20 @@
|
|||
visibility: [true, false],
|
||||
labels: ["datetime", "Major Page", "Minor Page"],
|
||||
div: "pageFaultsChart",
|
||||
labelsKMG2: false
|
||||
labelsKMG2: false,
|
||||
axes: {
|
||||
y: {
|
||||
valueFormatter: function (y) {
|
||||
return parseFloat(y.toPrecision(3));
|
||||
},
|
||||
axisLabelFormatter: function (y) {
|
||||
if (y === 0) {
|
||||
return 0;
|
||||
}
|
||||
return parseFloat(y.toPrecision(3));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
systemUserTime: {
|
||||
|
|
|
@ -46,7 +46,13 @@
|
|||
$('#collectionsToggle').addClass('activated');
|
||||
}
|
||||
|
||||
var length = searchOptions.searchPhrase.length;
|
||||
var length;
|
||||
|
||||
try {
|
||||
length = searchOptions.searchPhrase.length;
|
||||
}
|
||||
catch (ignore) {
|
||||
}
|
||||
$('#searchInput').val(searchOptions.searchPhrase);
|
||||
$('#searchInput').focus();
|
||||
$('#searchInput')[0].setSelectionRange(length, length);
|
||||
|
|
|
@ -80,7 +80,7 @@ function optimizerRuleTestSuite () {
|
|||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test that rule does not fire when it is not enabled
|
||||
/// @brief test that the rule fires when it is enabled
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testThisRuleEnabled : function () {
|
||||
|
@ -89,10 +89,71 @@ function optimizerRuleTestSuite () {
|
|||
[ "FOR d IN " + cn1 + " REMOVE d._key in " + cn1, 1],
|
||||
[ "FOR d IN " + cn1 + " INSERT d in " + cn2, 2],
|
||||
[ "FOR d IN " + cn1 + " INSERT d._key in " + cn2, 3],
|
||||
[ "FOR d IN " + cn1 + " REPLACE d in " + cn1, 4],
|
||||
[ "FOR d IN " + cn1 + " REPLACE d._key in " + cn1, 5],
|
||||
[ "FOR d IN " + cn1 + " UPDATE d in " + cn1 , 6],
|
||||
[ "FOR d IN " + cn1 + " UPDATE d._key in " + cn1 , 7]
|
||||
];
|
||||
|
||||
var expectedRules = [
|
||||
[
|
||||
"distribute-in-cluster",
|
||||
"scatter-in-cluster",
|
||||
],
|
||||
[
|
||||
"distribute-in-cluster",
|
||||
"scatter-in-cluster",
|
||||
"distribute-filtercalc-to-cluster"
|
||||
]
|
||||
];
|
||||
|
||||
var expectedNodes = [
|
||||
[
|
||||
"SingletonNode",
|
||||
"ScatterNode",
|
||||
"RemoteNode",
|
||||
"EnumerateCollectionNode",
|
||||
"RemoteNode",
|
||||
"GatherNode",
|
||||
"DistributeNode",
|
||||
"RemoteNode"
|
||||
],
|
||||
[
|
||||
"SingletonNode",
|
||||
"ScatterNode",
|
||||
"RemoteNode",
|
||||
"EnumerateCollectionNode",
|
||||
"CalculationNode",
|
||||
"RemoteNode",
|
||||
"GatherNode",
|
||||
"DistributeNode",
|
||||
"RemoteNode"
|
||||
]
|
||||
];
|
||||
|
||||
var finalNodes = [
|
||||
"RemoveNode", "RemoveNode",
|
||||
"InsertNode", "InsertNode"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
// can't turn this rule off so should always get the same answer
|
||||
var i = query[1] % 2;
|
||||
var result = AQL_EXPLAIN(query[0], { }, thisRuleEnabled);
|
||||
assertEqual(expectedRules[i], result.plan.rules, query);
|
||||
expectedNodes[i].push(finalNodes[query[1]]);
|
||||
assertEqual(expectedNodes[i], explain(result), query);
|
||||
expectedNodes[i].pop();
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test that rule fires when it is disabled (i.e. it can't be disabled)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testThisRuleDisabled : function () {
|
||||
var queries = [
|
||||
[ "FOR d IN " + cn1 + " REMOVE d in " + cn1, 0],
|
||||
[ "FOR d IN " + cn1 + " REMOVE d._key in " + cn1, 1],
|
||||
[ "FOR d IN " + cn1 + " INSERT d in " + cn2, 2],
|
||||
[ "FOR d IN " + cn1 + " INSERT d._key in " + cn2, 3],
|
||||
];
|
||||
|
||||
var expectedRules = [
|
||||
|
@ -131,12 +192,74 @@ function optimizerRuleTestSuite () {
|
|||
|
||||
var finalNodes = [
|
||||
"RemoveNode", "RemoveNode",
|
||||
"InsertNode", "InsertNode",
|
||||
"ReplaceNode", "ReplaceNode",
|
||||
"UpdateNode", "UpdateNode"
|
||||
"InsertNode", "InsertNode"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
// can't turn this rule off so should always get the same answer
|
||||
var i = query[1] % 2;
|
||||
var result = AQL_EXPLAIN(query[0], { }, rulesAll);
|
||||
assertEqual(expectedRules[i], result.plan.rules, query);
|
||||
expectedNodes[i].push(finalNodes[query[1]]);
|
||||
result = AQL_EXPLAIN(query[0], { }, thisRuleDisabled);
|
||||
assertEqual(expectedNodes[i], explain(result), query);
|
||||
expectedNodes[i].pop();
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test that rule does not fire when it is not enabled
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRulesAll : function () {
|
||||
var queries = [
|
||||
[ "FOR d IN " + cn1 + " REMOVE d in " + cn1, 0],
|
||||
[ "FOR d IN " + cn1 + " REMOVE d._key in " + cn1, 1],
|
||||
[ "FOR d IN " + cn1 + " INSERT d in " + cn2, 2],
|
||||
[ "FOR d IN " + cn1 + " INSERT d._key in " + cn2, 3],
|
||||
];
|
||||
|
||||
var expectedRules = [
|
||||
[
|
||||
"distribute-in-cluster",
|
||||
"scatter-in-cluster",
|
||||
"remove-unnecessary-remote-scatter"
|
||||
],
|
||||
[
|
||||
"distribute-in-cluster",
|
||||
"scatter-in-cluster",
|
||||
"distribute-filtercalc-to-cluster",
|
||||
"remove-unnecessary-remote-scatter"
|
||||
]
|
||||
];
|
||||
|
||||
var expectedNodes = [
|
||||
[
|
||||
"SingletonNode",
|
||||
"EnumerateCollectionNode",
|
||||
"RemoteNode",
|
||||
"GatherNode",
|
||||
"DistributeNode",
|
||||
"RemoteNode"
|
||||
],
|
||||
[
|
||||
"SingletonNode",
|
||||
"EnumerateCollectionNode",
|
||||
"CalculationNode",
|
||||
"RemoteNode",
|
||||
"GatherNode",
|
||||
"DistributeNode",
|
||||
"RemoteNode"
|
||||
]
|
||||
];
|
||||
|
||||
var finalNodes = [
|
||||
"RemoveNode", "RemoveNode",
|
||||
"InsertNode", "InsertNode"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
// can't turn this rule off so should always get the same answer
|
||||
var i = query[1] % 2;
|
||||
var result = AQL_EXPLAIN(query[0], { }, rulesAll);
|
||||
assertEqual(expectedRules[i], result.plan.rules, query);
|
||||
|
@ -146,6 +269,71 @@ function optimizerRuleTestSuite () {
|
|||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test that rule does not fire when it is not enabled
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
testRulesNone : function () {
|
||||
var queries = [
|
||||
[ "FOR d IN " + cn1 + " REMOVE d in " + cn1, 0],
|
||||
[ "FOR d IN " + cn1 + " REMOVE d._key in " + cn1, 1],
|
||||
[ "FOR d IN " + cn1 + " INSERT d in " + cn2, 2],
|
||||
[ "FOR d IN " + cn1 + " INSERT d._key in " + cn2, 3],
|
||||
];
|
||||
|
||||
var expectedRules = [
|
||||
[
|
||||
"distribute-in-cluster",
|
||||
"scatter-in-cluster",
|
||||
],
|
||||
[
|
||||
"distribute-in-cluster",
|
||||
"scatter-in-cluster",
|
||||
"distribute-filtercalc-to-cluster",
|
||||
]
|
||||
];
|
||||
|
||||
var expectedNodes = [
|
||||
[
|
||||
"SingletonNode",
|
||||
"ScatterNode",
|
||||
"RemoteNode",
|
||||
"EnumerateCollectionNode",
|
||||
"RemoteNode",
|
||||
"GatherNode",
|
||||
"DistributeNode",
|
||||
"RemoteNode"
|
||||
],
|
||||
[
|
||||
"SingletonNode",
|
||||
"ScatterNode",
|
||||
"RemoteNode",
|
||||
"EnumerateCollectionNode",
|
||||
"CalculationNode",
|
||||
"RemoteNode",
|
||||
"GatherNode",
|
||||
"DistributeNode",
|
||||
"RemoteNode"
|
||||
]
|
||||
];
|
||||
|
||||
var finalNodes = [
|
||||
"RemoveNode", "RemoveNode",
|
||||
"InsertNode", "InsertNode"
|
||||
];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
// can't turn this rule off so should always get the same answer
|
||||
var i = query[1] % 2;
|
||||
var result = AQL_EXPLAIN(query[0], { }, rulesNone);
|
||||
assertEqual(expectedRules[i], result.plan.rules, query);
|
||||
expectedNodes[i].push(finalNodes[query[1]]);
|
||||
assertEqual(expectedNodes[i], explain(result), query);
|
||||
expectedNodes[i].pop();
|
||||
|
||||
});
|
||||
},
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief test that rule has no effect
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -153,6 +341,10 @@ function optimizerRuleTestSuite () {
|
|||
testRuleNoEffect : function () {
|
||||
var queries = [
|
||||
"FOR d IN " + cn1 + " RETURN d",
|
||||
"FOR d IN " + cn1 + " REPLACE d in " + cn1,
|
||||
"FOR d IN " + cn1 + " REPLACE d._key in " + cn1,
|
||||
"FOR d IN " + cn1 + " UPDATE d in " + cn1,
|
||||
"FOR d IN " + cn1 + " UPDATE d._key in " + cn1 ,
|
||||
"FOR i IN 1..10 RETURN i" ];
|
||||
|
||||
queries.forEach(function(query) {
|
||||
|
|
|
@ -1625,7 +1625,7 @@ void TRI_InitV8Buffer (v8::Handle<v8::Context> context) {
|
|||
|
||||
// check the isolate
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
TRI_v8_global_t* v8g = TRI_CreateV8Globals(isolate);
|
||||
TRI_v8_global_t* v8g = TRI_GetV8Globals(isolate);
|
||||
|
||||
// .............................................................................
|
||||
// generate the general SlowBuffer template
|
||||
|
|
|
@ -134,6 +134,7 @@ TRI_v8_global_s::TRI_v8_global_s (v8::Isolate* isolate)
|
|||
_vocbase(nullptr),
|
||||
_allowUseDatabase(true),
|
||||
_hasDeadObjects(false),
|
||||
_applicationV8(nullptr),
|
||||
_loader(nullptr),
|
||||
_canceled(false) {
|
||||
v8::HandleScope scope;
|
||||
|
@ -228,11 +229,24 @@ TRI_v8_global_s::~TRI_v8_global_s () {
|
|||
TRI_v8_global_t* TRI_CreateV8Globals (v8::Isolate* isolate) {
|
||||
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(isolate->GetData());
|
||||
|
||||
if (v8g == nullptr) {
|
||||
TRI_ASSERT(v8g == nullptr);
|
||||
v8g = new TRI_v8_global_t(isolate);
|
||||
isolate->SetData(v8g);
|
||||
|
||||
return v8g;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns a global context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_v8_global_t* TRI_GetV8Globals (v8::Isolate* isolate) {
|
||||
TRI_v8_global_t* v8g = static_cast<TRI_v8_global_t*>(isolate->GetData());
|
||||
if (v8g == nullptr) {
|
||||
v8g = TRI_CreateV8Globals(isolate);
|
||||
}
|
||||
|
||||
TRI_ASSERT(v8g != nullptr);
|
||||
return v8g;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ struct TRI_vocbase_s;
|
|||
|
||||
namespace triagens {
|
||||
namespace arango {
|
||||
class ApplicationV8;
|
||||
class JSLoader;
|
||||
}
|
||||
}
|
||||
|
@ -809,6 +810,12 @@ typedef struct TRI_v8_global_s {
|
|||
// --SECTION-- GENERAL
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief pointer to the context dealer (ApplicationV8*)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
triagens::arango::ApplicationV8* _applicationV8;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief pointer to the startup loader (JSLoader*)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -833,6 +840,12 @@ TRI_v8_global_t;
|
|||
|
||||
TRI_v8_global_t* TRI_CreateV8Globals(v8::Isolate*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief gets the global context
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_v8_global_t* TRI_GetV8Globals(v8::Isolate*);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief adds a method to the prototype of an object
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -3792,7 +3792,7 @@ void TRI_InitV8Utils (v8::Handle<v8::Context> context,
|
|||
|
||||
// check the isolate
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
TRI_v8_global_t* v8g = TRI_CreateV8Globals(isolate);
|
||||
TRI_v8_global_t* v8g = TRI_GetV8Globals(isolate);
|
||||
|
||||
v8::Handle<v8::FunctionTemplate> ft;
|
||||
v8::Handle<v8::ObjectTemplate> rt;
|
||||
|
|
Loading…
Reference in New Issue