mirror of https://gitee.com/bigwinds/arangodb
execute several types of expressions in C++
This commit is contained in:
parent
94bcd23070
commit
9a6dfa1db2
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue