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