1
0
Fork 0

Merge branch 'devel' of https://github.com/arangodb/arangodb into agency-startup

This commit is contained in:
Kaveh Vahedipour 2016-08-16 15:46:16 +02:00
commit 632461db33
11 changed files with 324 additions and 29 deletions

View File

@ -42,10 +42,14 @@ devel
v3.0.5 (XXXX-XX-XX)
-------------------
* execute AQL ternary operator via C++ if possible
* fixed issue #1977
* fixed extraction of _id attribute in AQL traversal conditions
* fix SSL agency endpoint
v3.0.4 (2016-08-01)
-------------------

View File

@ -13,8 +13,6 @@ ArangoDB
2.8: [![Build Status](https://secure.travis-ci.org/arangodb/arangodb.png?branch=2.8)](http://travis-ci.org/arangodb/arangodb)
3.0: [![Build Status](https://secure.travis-ci.org/arangodb/arangodb.png?branch=3.0)](http://travis-ci.org/arangodb/arangodb)
Master: [![Build Status](https://secure.travis-ci.org/arangodb/arangodb.png?branch=master)](http://travis-ci.org/arangodb/arangodb)
Slack: [![ArangoDB-Logo](http://slack.arangodb.com/badge.svg)](https://slack.arangodb.com)
ArangoDB is a multi-model, open-source database with flexible data models for

View File

@ -210,11 +210,7 @@ AqlValue AqlValue::at(arangodb::AqlTransaction* trx, int64_t position,
if (position >= 0 && position < static_cast<int64_t>(n)) {
// only look up the value if it is within array bounds
TransactionBuilderLeaser builder(trx);
builder->add(
VPackValue(_data.range->at(static_cast<size_t>(position))));
mustDestroy = true;
return AqlValue(builder->slice());
return AqlValue(_data.range->at(static_cast<size_t>(position)));
}
// fall-through intentional
break;

View File

@ -38,6 +38,39 @@
#include <v8.h>
// some functionality borrowed from 3rdParty/velocypack/include/velocypack
// this is a copy of that functionality, because the functions in velocypack
// are not accessible from here
namespace {
static inline uint64_t toUInt64(int64_t v) noexcept {
// If v is negative, we need to add 2^63 to make it positive,
// before we can cast it to an uint64_t:
uint64_t shift2 = 1ULL << 63;
int64_t shift = static_cast<int64_t>(shift2 - 1);
return v >= 0 ? static_cast<uint64_t>(v)
: static_cast<uint64_t>((v + shift) + 1) + shift2;
// Note that g++ and clang++ with -O3 compile this away to
// nothing. Further note that a plain cast from int64_t to
// uint64_t is not guaranteed to work for negative values!
}
// returns number of bytes required to store the value in 2s-complement
static inline uint8_t intLength(int64_t value) {
if (value >= -0x80 && value <= 0x7f) {
// shortcut for the common case
return 1;
}
uint64_t x = value >= 0 ? static_cast<uint64_t>(value)
: static_cast<uint64_t>(-(value + 1));
uint8_t xSize = 0;
do {
xSize++;
x >>= 8;
} while (x >= 0x80);
return xSize + 1;
}
}
struct TRI_doc_mptr_t;
namespace arangodb {
@ -132,6 +165,75 @@ struct AqlValue final {
memcpy(_data.internal, slice.begin(), static_cast<size_t>(slice.byteSize()));
setType(AqlValueType::VPACK_INLINE);
}
// construct from a double value
explicit AqlValue(double value) {
if (std::isnan(value) || !std::isfinite(value) || value == HUGE_VAL || value == -HUGE_VAL) {
// null
_data.internal[0] = 0x18;
} else {
// a "real" double
_data.internal[0] = 0x1b;
uint64_t dv;
memcpy(&dv, &value, sizeof(double));
VPackValueLength vSize = sizeof(double);
int i = 1;
for (uint64_t x = dv; vSize > 0; vSize--) {
_data.internal[i] = x & 0xff;
x >>= 8;
++i;
}
}
setType(AqlValueType::VPACK_INLINE);
}
// construct from an int64 value
explicit AqlValue(int64_t value) {
if (value >= 0 && value <= 9) {
// a smallint
_data.internal[0] = static_cast<uint8_t>(0x30U + value);
} else if (value < 0 && value >= -6) {
// a negative smallint
_data.internal[0] = static_cast<uint8_t>(0x40U + value);
} else {
uint8_t vSize = intLength(value);
uint64_t x;
if (vSize == 8) {
x = toUInt64(value);
} else {
int64_t shift = 1LL << (vSize * 8 - 1); // will never overflow!
x = value >= 0 ? static_cast<uint64_t>(value)
: static_cast<uint64_t>(value + shift) + shift;
}
_data.internal[0] = 0x1fU + vSize;
int i = 1;
while (vSize-- > 0) {
_data.internal[i] = x & 0xffU;
++i;
x >>= 8;
}
}
setType(AqlValueType::VPACK_INLINE);
}
// construct from a uint64 value
explicit AqlValue(uint64_t value) {
if (value <= 9) {
// a smallint
_data.internal[0] = static_cast<uint8_t>(0x30U + value);
} else {
int i = 1;
uint8_t vSize = 0;
do {
vSize++;
_data.internal[i] = static_cast<uint8_t>(value & 0xffU);
++i;
value >>= 8;
} while (value != 0);
_data.internal[0] = 0x27U + vSize;
}
setType(AqlValueType::VPACK_INLINE);
}
// construct from char* and length, copying the string
AqlValue(char const* value, size_t length) {

View File

@ -1719,7 +1719,8 @@ bool AstNode::isSimple() const {
}
if (type == NODE_TYPE_OBJECT_ELEMENT || type == NODE_TYPE_ATTRIBUTE_ACCESS ||
type == NODE_TYPE_OPERATOR_UNARY_NOT) {
type == NODE_TYPE_OPERATOR_UNARY_NOT || type == NODE_TYPE_OPERATOR_UNARY_PLUS ||
type == NODE_TYPE_OPERATOR_UNARY_MINUS) {
TRI_ASSERT(numMembers() == 1);
if (!getMember(0)->isSimple()) {

View File

@ -444,6 +444,12 @@ AqlValue Expression::executeSimpleExpression(
regs, mustDestroy);
case NODE_TYPE_OPERATOR_UNARY_NOT:
return executeSimpleExpressionNot(node, trx, argv, startPos, vars, regs, mustDestroy);
case NODE_TYPE_OPERATOR_UNARY_PLUS:
return executeSimpleExpressionPlus(node, trx, argv, startPos, vars, regs, mustDestroy);
case NODE_TYPE_OPERATOR_UNARY_MINUS:
return executeSimpleExpressionMinus(node, trx, argv, startPos, vars, regs, mustDestroy);
case NODE_TYPE_OPERATOR_BINARY_AND:
case NODE_TYPE_OPERATOR_BINARY_OR:
@ -558,9 +564,9 @@ AqlValue Expression::executeSimpleExpressionIndexedAccess(
// etc.
TRI_ASSERT(node->numMembers() == 2);
auto member = node->getMember(0);
auto index = node->getMember(1);
auto member = node->getMemberUnchecked(0);
auto index = node->getMemberUnchecked(1);
mustDestroy = false;
AqlValue result = executeSimpleExpression(member, trx, argv,
startPos, vars, regs, mustDestroy, false);
@ -815,7 +821,7 @@ AqlValue Expression::executeSimpleExpressionReference(
auto v = static_cast<Variable const*>(node->getData());
TRI_ASSERT(v != nullptr);
{
if (!_variables.empty()) {
auto it = _variables.find(v);
if (it != _variables.end()) {
@ -825,7 +831,7 @@ AqlValue Expression::executeSimpleExpressionReference(
}
size_t i = 0;
for (auto it = vars.begin(); it != vars.end(); ++it, ++i) {
for (auto it = vars.begin(), it2 = vars.end(); it != it2; ++it, ++i) {
if ((*it)->id == v->id) {
if (doCopy) {
mustDestroy = true; // as we are copying
@ -947,6 +953,84 @@ AqlValue Expression::executeSimpleExpressionNot(
return AqlValue(!operandIsTrue);
}
/// @brief execute an expression of type SIMPLE with +
AqlValue Expression::executeSimpleExpressionPlus(
AstNode const* node, arangodb::AqlTransaction* trx,
AqlItemBlock const* argv, size_t startPos,
std::vector<Variable const*> const& vars,
std::vector<RegisterId> const& regs, bool& mustDestroy) {
mustDestroy = false;
AqlValue operand =
executeSimpleExpression(node->getMember(0), trx, argv,
startPos, vars, regs, mustDestroy, false);
AqlValueGuard guard(operand, mustDestroy);
if (operand.isNumber()) {
VPackSlice const s = operand.slice();
if (s.isSmallInt() || s.isInt()) {
// can use int64
return AqlValue(s.getNumber<int64_t>());
} else if (s.isUInt()) {
// can use uint64
return AqlValue(s.getNumber<uint64_t>());
}
// fallthrouh intentional
}
// use a double value for all other cases
bool failed = false;
double value = operand.toDouble(trx, failed);
if (failed) {
value = 0.0;
}
return AqlValue(+value);
}
/// @brief execute an expression of type SIMPLE with -
AqlValue Expression::executeSimpleExpressionMinus(
AstNode const* node, arangodb::AqlTransaction* trx,
AqlItemBlock const* argv, size_t startPos,
std::vector<Variable const*> const& vars,
std::vector<RegisterId> const& regs, bool& mustDestroy) {
mustDestroy = false;
AqlValue operand =
executeSimpleExpression(node->getMember(0), trx, argv,
startPos, vars, regs, mustDestroy, false);
AqlValueGuard guard(operand, mustDestroy);
if (operand.isNumber()) {
VPackSlice const s = operand.slice();
if (s.isSmallInt()) {
// can use int64
return AqlValue(-s.getNumber<int64_t>());
} else if (s.isInt()) {
int64_t v = s.getNumber<int64_t>();
if (v != INT64_MIN) {
// can use int64
return AqlValue(-v);
}
}
// fallthrouh intentional
}
// TODO: handle integer values separately here
bool failed = false;
double value = operand.toDouble(trx, failed);
if (failed) {
value = 0.0;
}
return AqlValue(-value);
}
/// @brief execute an expression of type SIMPLE with AND or OR
AqlValue Expression::executeSimpleExpressionAndOr(
AstNode const* node, arangodb::AqlTransaction* trx,

View File

@ -34,8 +34,6 @@
#include <velocypack/Builder.h>
#include <velocypack/Slice.h>
struct TRI_json_t;
namespace arangodb {
class AqlTransaction;
@ -293,6 +291,20 @@ class Expression {
std::vector<Variable const*> const&,
std::vector<RegisterId> const&,
bool& mustDestroy);
/// @brief execute an expression of type SIMPLE with +
AqlValue executeSimpleExpressionPlus(AstNode const*, arangodb::AqlTransaction*,
AqlItemBlock const*, size_t,
std::vector<Variable const*> const&,
std::vector<RegisterId> const&,
bool& mustDestroy);
/// @brief execute an expression of type SIMPLE with -
AqlValue executeSimpleExpressionMinus(AstNode const*, arangodb::AqlTransaction*,
AqlItemBlock const*, size_t,
std::vector<Variable const*> const&,
std::vector<RegisterId> const&,
bool& mustDestroy);
/// @brief execute an expression of type SIMPLE with AND or OR
AqlValue executeSimpleExpressionAndOr(AstNode const*,

View File

@ -599,7 +599,7 @@ void TRI_collection_t::addIndexFile(std::string const& filename) {
////////////////////////////////////////////////////////////////////////////////
int TRI_collection_t::removeIndexFile(TRI_idx_iid_t id) {
READ_LOCKER(readLocker, _filesLock);
WRITE_LOCKER(readLocker, _filesLock);
for (auto it = _indexFiles.begin(); it != _indexFiles.end(); ++it) {
if (GetNumericFilenamePart((*it).c_str()) == id) {

View File

@ -897,8 +897,6 @@ function executeArangod (cmd, args, options) {
testfn += '_';
}
testfn += valgrindTest;
if (valgrindOpts.xml === 'yes') {
valgrindOpts['xml-file'] = testfn + '.%p.xml';
}
@ -1055,7 +1053,7 @@ function runInArangosh (options, instanceInfo, file, addArgs) {
function createArangoshRunner(args) {
let runner = function(options, instanceInfo, file) {
return runInArangosh(options, instanceInfo, file, args);
}
};
runner.info = 'arangosh';
return runner;
}
@ -1195,7 +1193,7 @@ function shutdownInstance (instanceInfo, options) {
const n = instanceInfo.arangods.length;
let nonagencies = instanceInfo.arangods
.filter(arangod => arangod.role != 'agent');
.filter(arangod => arangod.role !== 'agent');
nonagencies.forEach(arangod => shutdownArangod(arangod, options)
);
@ -1219,7 +1217,7 @@ function shutdownInstance (instanceInfo, options) {
// are agents:
if (!agentsKilled && nrAgents > 0 && toShutdown.length === nrAgents) {
instanceInfo.arangods
.filter(arangod => arangod.role == 'agent')
.filter(arangod => arangod.role === 'agent')
.forEach(arangod => shutdownArangod(arangod, options));
agentsKilled = true;
}

View File

@ -1,5 +1,5 @@
/*jshint strict: false, sub: true */
/*global print, arango */
/*global print, arango, assertTrue, assertNotNull, assertNotUndefined */
'use strict';
////////////////////////////////////////////////////////////////////////////////
@ -64,7 +64,7 @@ let executeOnServer = function(code) {
} else {
throw new Error('Could not send to server ' + JSON.stringify(reply));
}
}
};
function serverSetup() {
let directory = require('./js/client/assets/queuetest/dirname.js');
@ -112,23 +112,23 @@ function FoxxmasterSuite() {
assertNotNull(server);
let instance = instanceInfo.arangods.filter(arangod => {
if (arangod.role == 'agent') {
if (arangod.role === 'agent') {
return false;
}
let url = arangod.endpoint.replace(/tcp/, 'http') + '/_admin/server/id';
let res = request({method: 'GET', url: url});
let parsed = JSON.parse(res.body);
if (parsed.id == server) {
if (parsed.id === server) {
assertTrue(suspendExternal(arangod.pid));
}
return parsed.id == server;
return parsed.id === server;
})[0];
assertNotUndefined(instance);
assertTrue(suspendExternal(instance.pid));
let newEndpoint = instanceInfo.arangods.filter(arangod => {
return arangod.role == 'coordinator' && arangod.pid != instance.pid;
return arangod.role === 'coordinator' && arangod.pid !== instance.pid;
})[0];
arango.reconnect(newEndpoint.endpoint, db._name(), 'root', '');
let waitInterval = 0.1;
@ -137,7 +137,7 @@ function FoxxmasterSuite() {
while (waited <= 20) {
document = db._collection('foxxqueuetest').document('test');
let newServer = document.server;
if (server != newServer) {
if (server !== newServer) {
ok = true;
break;
}
@ -150,7 +150,7 @@ function FoxxmasterSuite() {
throw new Error('Supervision should have moved the foxxqueues and foxxqueues should have been started to run on a new coordinator');
}
}
}
};
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -62,6 +62,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ 0 ];
var actual = getQueryResults("RETURN +0");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(+0)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(+0)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -72,6 +76,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ 1 ];
var actual = getQueryResults("RETURN +1");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(+1)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(+1)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -82,6 +90,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ 1 ];
var actual = getQueryResults("RETURN ++1");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(++1)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(++1)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -92,6 +104,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ -5 ];
var actual = getQueryResults("RETURN +-5");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(+-5)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(+-5)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -102,6 +118,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ 5.4 ];
var actual = getQueryResults("RETURN +++5.4");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(+++5.4)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(+++5.4)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -123,6 +143,36 @@ function ahuacatlArithmeticTestSuite () {
assertEqual([ 0 ], getQueryResults("RETURN +[ \"abc\" ]"));
assertEqual([ 3 ], getQueryResults("RETURN +[ \"3\" ]"));
assertEqual([ 0 ], getQueryResults("RETURN +{ }"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+null)"));
assertEqual([ 1 ], getQueryResults("RETURN NOOPT(+true)"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+false)"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+\"value\")"));
assertEqual([ 1 ], getQueryResults("RETURN NOOPT(+\"1\")"));
assertEqual([ -3 ], getQueryResults("RETURN NOOPT(+\"-3\")"));
assertEqual([ -3.4 ], getQueryResults("RETURN NOOPT(+\"-3.4\")"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+[ ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+[ 0 ])"));
assertEqual([ -34 ], getQueryResults("RETURN NOOPT(+[ -34 ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+[ 1, 2 ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+[ \"abc\" ])"));
assertEqual([ 3 ], getQueryResults("RETURN NOOPT(+[ \"3\" ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(+{ })"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+null)"));
assertEqual([ 1 ], getQueryResults("RETURN V8(+true)"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+false)"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+\"value\")"));
assertEqual([ 1 ], getQueryResults("RETURN V8(+\"1\")"));
assertEqual([ -3 ], getQueryResults("RETURN V8(+\"-3\")"));
assertEqual([ -3.4 ], getQueryResults("RETURN V8(+\"-3.4\")"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+[ ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+[ 0 ])"));
assertEqual([ -34 ], getQueryResults("RETURN V8(+[ -34 ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+[ 1, 2 ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+[ \"abc\" ])"));
assertEqual([ 3 ], getQueryResults("RETURN V8(+[ \"3\" ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(+{ })"));
},
////////////////////////////////////////////////////////////////////////////////
@ -133,6 +183,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ 0 ];
var actual = getQueryResults("RETURN -0");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(-0)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(-0)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -143,6 +197,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ -1 ];
var actual = getQueryResults("RETURN -1");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(-1)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(-1)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -153,6 +211,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ 1 ];
var actual = getQueryResults("RETURN --1");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(--1)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(--1)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -163,6 +225,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ -5 ];
var actual = getQueryResults("RETURN -+5");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(-+5)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(-+5)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -173,6 +239,10 @@ function ahuacatlArithmeticTestSuite () {
var expected = [ -5.4 ];
var actual = getQueryResults("RETURN ---5.4");
assertEqual(expected, actual);
actual = getQueryResults("RETURN NOOPT(---5.4)");
assertEqual(expected, actual);
actual = getQueryResults("RETURN V8(---5.4)");
assertEqual(expected, actual);
},
////////////////////////////////////////////////////////////////////////////////
@ -194,6 +264,36 @@ function ahuacatlArithmeticTestSuite () {
assertEqual([ 0 ], getQueryResults("RETURN -[ \"abc\" ]"));
assertEqual([ -3 ], getQueryResults("RETURN -[ \"3\" ]"));
assertEqual([ 0 ], getQueryResults("RETURN -{ }"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-null)"));
assertEqual([ -1 ], getQueryResults("RETURN NOOPT(-true)"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-false)"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-\"value\")"));
assertEqual([ -1 ], getQueryResults("RETURN NOOPT(-\"1\")"));
assertEqual([ 3 ], getQueryResults("RETURN NOOPT(-\"-3\")"));
assertEqual([ 3.5 ], getQueryResults("RETURN NOOPT(-\"-3.5\")"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-[ ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-[ 0 ])"));
assertEqual([ 34 ], getQueryResults("RETURN NOOPT(-[ -34 ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-[ 1, 2 ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-[ \"abc\" ])"));
assertEqual([ -3 ], getQueryResults("RETURN NOOPT(-[ \"3\" ])"));
assertEqual([ 0 ], getQueryResults("RETURN NOOPT(-{ })"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-null)"));
assertEqual([ -1 ], getQueryResults("RETURN V8(-true)"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-false)"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-\"value\")"));
assertEqual([ -1 ], getQueryResults("RETURN V8(-\"1\")"));
assertEqual([ 3 ], getQueryResults("RETURN V8(-\"-3\")"));
assertEqual([ 3.5 ], getQueryResults("RETURN V8(-\"-3.5\")"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-[ ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-[ 0 ])"));
assertEqual([ 34 ], getQueryResults("RETURN V8(-[ -34 ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-[ 1, 2 ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-[ \"abc\" ])"));
assertEqual([ -3 ], getQueryResults("RETURN V8(-[ \"3\" ])"));
assertEqual([ 0 ], getQueryResults("RETURN V8(-{ })"));
},
////////////////////////////////////////////////////////////////////////////////