1
0
Fork 0

execute several types of expressions in C++

This commit is contained in:
Jan Steemann 2014-09-19 15:21:01 +02:00
parent 94bcd23070
commit 9a6dfa1db2
5 changed files with 178 additions and 9 deletions

View File

@ -263,6 +263,43 @@ bool AqlValue::isArray () const {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the length of an AqlValue containing a list
////////////////////////////////////////////////////////////////////////////////
size_t AqlValue::listSize () const {
switch (_type) {
case JSON: {
TRI_json_t const* json = _json->json();
if (TRI_IsListJson(json)) {
return TRI_LengthListJson(json);
}
return 0;
}
case DOCVEC: {
TRI_ASSERT(_vector != nullptr);
// calculate the result list length
size_t totalSize = 0;
for (auto it = _vector->begin(); it != _vector->end(); ++it) {
totalSize += (*it)->size();
}
return totalSize;
}
case RANGE: {
TRI_ASSERT(_range != nullptr);
return _range->size();
}
case SHAPED:
case EMPTY: {
}
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue
////////////////////////////////////////////////////////////////////////////////
@ -690,14 +727,55 @@ int AqlValue::Compare (AQL_TRANSACTION_V8* trx,
return 1;
}
if (left._type == AqlValue::JSON && right._type == AqlValue::SHAPED) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
// JSON against x
if (left._type == AqlValue::JSON &&
(right._type == AqlValue::SHAPED ||
right._type == AqlValue::RANGE ||
right._type == AqlValue::DOCVEC)) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
return TRI_CompareValuesJson(left._json->json(), rjson.json(), true);
}
if (left._type == AqlValue::SHAPED && right._type == AqlValue::JSON) {
// SHAPED against x
if (left._type == AqlValue::SHAPED) {
triagens::basics::Json ljson = left.toJson(trx, leftcoll);
return TRI_CompareValuesJson(ljson.json(), right._json->json(), true);
if (right._type == AqlValue::JSON) {
return TRI_CompareValuesJson(ljson.json(), right._json->json(), true);
}
else if (right._type == AqlValue::RANGE ||
right._type == AqlValue::DOCVEC) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
return TRI_CompareValuesJson(ljson.json(), rjson.json(), true);
}
}
// RANGE against x
if (left._type == AqlValue::RANGE) {
triagens::basics::Json ljson = left.toJson(trx, leftcoll);
if (right._type == AqlValue::JSON) {
return TRI_CompareValuesJson(ljson.json(), right._json->json(), true);
}
else if (right._type == AqlValue::SHAPED ||
right._type == AqlValue::DOCVEC) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
return TRI_CompareValuesJson(ljson.json(), rjson.json(), true);
}
}
// DOCVEC against x
if (left._type == AqlValue::DOCVEC) {
triagens::basics::Json ljson = left.toJson(trx, leftcoll);
if (right._type == AqlValue::JSON) {
return TRI_CompareValuesJson(ljson.json(), right._json->json(), true);
}
else if (right._type == AqlValue::SHAPED ||
right._type == AqlValue::RANGE) {
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
return TRI_CompareValuesJson(ljson.json(), rjson.json(), true);
}
}
// No other comparisons are defined

View File

@ -180,6 +180,12 @@ namespace triagens {
bool isArray () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the length of an AqlValue containing a list
////////////////////////////////////////////////////////////////////////////////
size_t listSize () const;
////////////////////////////////////////////////////////////////////////////////
/// @brief get a string representation of the AqlValue
/// this will fail if the value is not a string

View File

@ -672,6 +672,18 @@ bool AstNode::isSimple () const {
return (getMember(0)->isSimple() && getMember(1)->isSimple());
}
if (type == NODE_TYPE_OPERATOR_BINARY_EQ ||
type == NODE_TYPE_OPERATOR_BINARY_NE ||
type == NODE_TYPE_OPERATOR_BINARY_LT ||
type == NODE_TYPE_OPERATOR_BINARY_LE ||
type == NODE_TYPE_OPERATOR_BINARY_GT ||
type == NODE_TYPE_OPERATOR_BINARY_GE ||
type == NODE_TYPE_OPERATOR_BINARY_IN ||
type == NODE_TYPE_OPERATOR_BINARY_NIN) {
// a comparison operator is simple if both bounds are simple
return (getMember(0)->isSimple() && getMember(1)->isSimple());
}
return false;
}

View File

@ -382,12 +382,13 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
}
else if (node->type == NODE_TYPE_RANGE) {
TRI_document_collection_t const* myCollection = nullptr;
TRI_document_collection_t const* leftCollection = nullptr;
TRI_document_collection_t const* rightCollection = nullptr;
auto low = node->getMember(0);
auto high = node->getMember(1);
AqlValue resultLow = executeSimpleExpression(low, &myCollection, trx, docColls, argv, startPos, vars, regs);
AqlValue resultHigh = executeSimpleExpression(high, &myCollection, trx, docColls, argv, startPos, vars, regs);
AqlValue resultLow = executeSimpleExpression(low, &leftCollection, trx, docColls, argv, startPos, vars, regs);
AqlValue resultHigh = executeSimpleExpression(high, &rightCollection, trx, docColls, argv, startPos, vars, regs);
if (! resultLow.isNumber() || ! resultHigh.isNumber()) {
resultLow.destroy();
@ -403,6 +404,78 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
return res;
}
else if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ ||
node->type == NODE_TYPE_OPERATOR_BINARY_NE ||
node->type == NODE_TYPE_OPERATOR_BINARY_LT ||
node->type == NODE_TYPE_OPERATOR_BINARY_LE ||
node->type == NODE_TYPE_OPERATOR_BINARY_GT ||
node->type == NODE_TYPE_OPERATOR_BINARY_GE ||
node->type == NODE_TYPE_OPERATOR_BINARY_IN ||
node->type == NODE_TYPE_OPERATOR_BINARY_NIN) {
TRI_document_collection_t const* leftCollection = nullptr;
AqlValue left = executeSimpleExpression(node->getMember(0), &leftCollection, trx, docColls, argv, startPos, vars, regs);
TRI_document_collection_t const* rightCollection = nullptr;
AqlValue right = executeSimpleExpression(node->getMember(1), &rightCollection, trx, docColls, argv, startPos, vars, regs);
if (node->type == NODE_TYPE_OPERATOR_BINARY_IN ||
node->type == NODE_TYPE_OPERATOR_BINARY_NIN) {
// IN and NOT IN
if (! right.isList()) {
// right operand must be a list
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_LIST_EXPECTED);
}
size_t const n = right.listSize();
for (size_t i = 0; i < n; ++i) {
auto listItem = right.extractListMember(trx, rightCollection, i);
AqlValue listItemValue(&listItem);
int compareResult = AqlValue::Compare(trx, left, leftCollection, listItemValue, nullptr);
if (compareResult == 0) {
// item found in the list
left.destroy();
right.destroy();
// found
return AqlValue(new triagens::basics::Json(node->type == NODE_TYPE_OPERATOR_BINARY_IN));
}
}
left.destroy();
right.destroy();
// not found
return AqlValue(new triagens::basics::Json(node->type != NODE_TYPE_OPERATOR_BINARY_IN));
}
// all other comparison operators
int compareResult = AqlValue::Compare(trx, left, leftCollection, right, rightCollection);
left.destroy();
right.destroy();
if (node->type == NODE_TYPE_OPERATOR_BINARY_EQ) {
return AqlValue(new triagens::basics::Json(compareResult == 0));
}
else if (node->type == NODE_TYPE_OPERATOR_BINARY_NE) {
return AqlValue(new triagens::basics::Json(compareResult != 0));
}
else if (node->type == NODE_TYPE_OPERATOR_BINARY_LT) {
return AqlValue(new triagens::basics::Json(compareResult < 0));
}
else if (node->type == NODE_TYPE_OPERATOR_BINARY_LE) {
return AqlValue(new triagens::basics::Json(compareResult <= 0));
}
else if (node->type == NODE_TYPE_OPERATOR_BINARY_GT) {
return AqlValue(new triagens::basics::Json(compareResult > 0));
}
else if (node->type == NODE_TYPE_OPERATOR_BINARY_GE) {
return AqlValue(new triagens::basics::Json(compareResult >= 0));
}
// fall-through intentional
}
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unhandled type in simple expression");
}

View File

@ -250,7 +250,7 @@ void TRI_FreeJson (TRI_memory_zone_t*, TRI_json_t*);
/// @brief determines the length of a list json
////////////////////////////////////////////////////////////////////////////////
size_t TRI_LengthListJson ( TRI_json_t const*);
size_t TRI_LengthListJson (TRI_json_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief determines whether the JSON passed is of type array