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);
|
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
|
/// @brief get a string representation of the AqlValue
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -690,14 +727,55 @@ int AqlValue::Compare (AQL_TRANSACTION_V8* trx,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left._type == AqlValue::JSON && right._type == AqlValue::SHAPED) {
|
// JSON against x
|
||||||
triagens::basics::Json rjson = right.toJson(trx, rightcoll);
|
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);
|
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);
|
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
|
// No other comparisons are defined
|
||||||
|
|
|
@ -180,6 +180,12 @@ namespace triagens {
|
||||||
|
|
||||||
bool isArray () const;
|
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
|
/// @brief get a string representation of the AqlValue
|
||||||
/// this will fail if the value is not a string
|
/// 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());
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -382,12 +382,13 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (node->type == NODE_TYPE_RANGE) {
|
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 low = node->getMember(0);
|
||||||
auto high = node->getMember(1);
|
auto high = node->getMember(1);
|
||||||
AqlValue resultLow = executeSimpleExpression(low, &myCollection, trx, docColls, argv, startPos, vars, regs);
|
AqlValue resultLow = executeSimpleExpression(low, &leftCollection, trx, docColls, argv, startPos, vars, regs);
|
||||||
AqlValue resultHigh = executeSimpleExpression(high, &myCollection, trx, docColls, argv, startPos, vars, regs);
|
AqlValue resultHigh = executeSimpleExpression(high, &rightCollection, trx, docColls, argv, startPos, vars, regs);
|
||||||
|
|
||||||
if (! resultLow.isNumber() || ! resultHigh.isNumber()) {
|
if (! resultLow.isNumber() || ! resultHigh.isNumber()) {
|
||||||
resultLow.destroy();
|
resultLow.destroy();
|
||||||
|
@ -403,6 +404,78 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
||||||
return res;
|
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");
|
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
|
/// @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
|
/// @brief determines whether the JSON passed is of type array
|
||||||
|
|
Loading…
Reference in New Issue