mirror of https://gitee.com/bigwinds/arangodb
partial implementation
This commit is contained in:
parent
f7d5a612d9
commit
64089eea75
|
@ -1201,16 +1201,23 @@ bool AstNode::isSimple () const {
|
|||
}
|
||||
|
||||
if (type == NODE_TYPE_REFERENCE ||
|
||||
type == NODE_TYPE_VALUE) {
|
||||
type == NODE_TYPE_VALUE ||
|
||||
type == NODE_TYPE_VARIABLE ||
|
||||
type == NODE_TYPE_NOP) {
|
||||
setFlag(DETERMINED_SIMPLE, VALUE_SIMPLE);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type == NODE_TYPE_ARRAY ||
|
||||
type == NODE_TYPE_OBJECT) {
|
||||
type == NODE_TYPE_OBJECT ||
|
||||
type == NODE_TYPE_EXPANSION ||
|
||||
type == NODE_TYPE_ITERATOR ||
|
||||
type == NODE_TYPE_ARRAY_LIMIT) {
|
||||
size_t const n = numMembers();
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
auto member = getMember(i);
|
||||
auto member = getMemberUnchecked(i);
|
||||
|
||||
if (! member->isSimple()) {
|
||||
setFlag(DETERMINED_SIMPLE);
|
||||
return false;
|
||||
|
|
|
@ -176,8 +176,8 @@ namespace triagens {
|
|||
NODE_TYPE_ARRAY_LIMIT = 57
|
||||
};
|
||||
|
||||
static_assert(NODE_TYPE_VALUE < NODE_TYPE_ARRAY, "incorrect node types");
|
||||
static_assert(NODE_TYPE_ARRAY < NODE_TYPE_OBJECT, "incorrect node types");
|
||||
static_assert(NODE_TYPE_VALUE < NODE_TYPE_ARRAY, "incorrect node types order");
|
||||
static_assert(NODE_TYPE_ARRAY < NODE_TYPE_OBJECT, "incorrect node types order");
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- struct AstNode
|
||||
|
|
|
@ -1059,13 +1059,13 @@ void Executor::generateCodeExpansion (AstNode const* node) {
|
|||
_buffer->appendText(variable->name);
|
||||
_buffer->appendText("\"]=v; ");
|
||||
|
||||
_buffer->appendText("return ");
|
||||
size_t projectionNode = 1;
|
||||
if (node->getMember(4)->type != NODE_TYPE_NOP) {
|
||||
generateCodeNode(node->getMember(4));
|
||||
}
|
||||
else {
|
||||
generateCodeNode(node->getMember(1));
|
||||
projectionNode = 4;
|
||||
}
|
||||
|
||||
_buffer->appendText("return ");
|
||||
generateCodeNode(node->getMember(projectionNode));
|
||||
_buffer->appendText("; })");
|
||||
}
|
||||
|
||||
|
|
|
@ -305,10 +305,10 @@ bool Expression::findInArray (AqlValue const& left,
|
|||
while (true) {
|
||||
// determine midpoint
|
||||
size_t m = l + ((r - l) / 2);
|
||||
auto listItem = right.extractArrayMember(trx, rightCollection, m, false);
|
||||
AqlValue listItemValue(&listItem);
|
||||
auto arrayItem = right.extractArrayMember(trx, rightCollection, m, false);
|
||||
AqlValue arrayItemValue(&arrayItem);
|
||||
|
||||
int compareResult = AqlValue::Compare(trx, left, leftCollection, listItemValue, nullptr, false);
|
||||
int compareResult = AqlValue::Compare(trx, left, leftCollection, arrayItemValue, nullptr, false);
|
||||
|
||||
if (compareResult == 0) {
|
||||
// item found in the list
|
||||
|
@ -334,10 +334,10 @@ bool Expression::findInArray (AqlValue const& left,
|
|||
// use linear search
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
// do not copy the list element we're looking at
|
||||
auto listItem = right.extractArrayMember(trx, rightCollection, i, false);
|
||||
AqlValue listItemValue(&listItem);
|
||||
auto arrayItem = right.extractArrayMember(trx, rightCollection, i, false);
|
||||
AqlValue arrayItemValue(&arrayItem);
|
||||
|
||||
int compareResult = AqlValue::Compare(trx, left, leftCollection, listItemValue, nullptr, false);
|
||||
int compareResult = AqlValue::Compare(trx, left, leftCollection, arrayItemValue, nullptr, false);
|
||||
|
||||
if (compareResult == 0) {
|
||||
// item found in the list
|
||||
|
@ -627,6 +627,15 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
|||
else if (node->type == NODE_TYPE_REFERENCE) {
|
||||
auto v = static_cast<Variable const*>(node->getData());
|
||||
|
||||
{
|
||||
auto it = _variables.find(v);
|
||||
if (it != _variables.end()) {
|
||||
*collection = nullptr;
|
||||
return AqlValue(new Json(TRI_UNKNOWN_MEM_ZONE, TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (*it).second))); //, Json::NOFREE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t i = 0;
|
||||
for (auto it = vars.begin(); it != vars.end(); ++it, ++i) {
|
||||
if ((*it)->name == v->name) {
|
||||
|
@ -634,6 +643,7 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
|||
|
||||
// save the collection info
|
||||
*collection = argv->getDocumentCollection(regs[i]);
|
||||
|
||||
if (doCopy) {
|
||||
return argv->getValueReference(startPos, regs[i]).clone();
|
||||
}
|
||||
|
@ -820,8 +830,63 @@ AqlValue Expression::executeSimpleExpression (AstNode const* node,
|
|||
// return false part
|
||||
return executeSimpleExpression(node->getMember(2), &myCollection, trx, argv, startPos, vars, regs, true);
|
||||
}
|
||||
|
||||
else if (node->type == NODE_TYPE_EXPANSION) {
|
||||
TRI_ASSERT(node->numMembers() == 5);
|
||||
auto iterator = node->getMember(0);
|
||||
auto variable = static_cast<Variable*>(iterator->getMember(0)->getData());
|
||||
// TODO: implement flatten!
|
||||
auto levels = node->getIntValue(true);
|
||||
|
||||
TRI_document_collection_t const* myCollection = nullptr;
|
||||
AqlValue value = executeSimpleExpression(node->getMember(0), &myCollection, trx, argv, startPos, vars, regs, false);
|
||||
|
||||
if (! value.isArray()) {
|
||||
value.destroy();
|
||||
return AqlValue(new triagens::basics::Json(triagens::basics::Json::Array));
|
||||
}
|
||||
|
||||
size_t const n = value.arraySize();
|
||||
std::unique_ptr<Json> array(new Json(Json::Array, n));
|
||||
|
||||
size_t projectionNode = 1;
|
||||
if (node->getMember(4)->type != NODE_TYPE_NOP) {
|
||||
projectionNode = 4;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
// TODO: check why we must copy the array member. will crash without copying!
|
||||
auto arrayItem = value.extractArrayMember(trx, myCollection, i, true);
|
||||
|
||||
setVariable(variable, arrayItem.json());
|
||||
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, "unhandled type in simple expression");
|
||||
TRI_document_collection_t const* subCollection = nullptr;
|
||||
AqlValue sub = executeSimpleExpression(node->getMember(projectionNode), &subCollection, trx, argv, startPos, vars, regs, true);
|
||||
array->add(sub.toJson(trx, subCollection, true));
|
||||
|
||||
clearVariable(variable);
|
||||
|
||||
arrayItem.destroy();
|
||||
}
|
||||
|
||||
value.destroy();
|
||||
return AqlValue(array.release());
|
||||
}
|
||||
|
||||
else if (node->type == NODE_TYPE_ITERATOR) {
|
||||
TRI_ASSERT(node != nullptr);
|
||||
TRI_ASSERT(node->numMembers() == 2);
|
||||
|
||||
// intentionally do not stringify node 0
|
||||
TRI_document_collection_t const* myCollection = nullptr;
|
||||
AqlValue value = executeSimpleExpression(node->getMember(1), &myCollection, trx, argv, startPos, vars, regs, true);
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string msg("unhandled type '");
|
||||
msg.append(node->getTypeString());
|
||||
msg.append("' in executeSimpleExpression()");
|
||||
THROW_ARANGO_EXCEPTION_MESSAGE(TRI_ERROR_INTERNAL, msg.c_str());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -290,6 +290,13 @@ namespace triagens {
|
|||
|
||||
void invalidate ();
|
||||
|
||||
void setVariable (Variable const* variable, TRI_json_t const* value) {
|
||||
_variables.emplace(variable, value);
|
||||
}
|
||||
void clearVariable (Variable const* variable) {
|
||||
_variables.erase(variable);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- private methods
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -420,6 +427,8 @@ namespace triagens {
|
|||
|
||||
triagens::basics::StringBuffer _buffer;
|
||||
|
||||
std::unordered_map<Variable const*, TRI_json_t const*> _variables;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// --SECTION-- public static members
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue