@@ -34,11 +34,11 @@ namespace {
3434
3535auto doNothingVisitor = [](AstNode const *) {};
3636
37- bool accessesSearchVariableViaReference (AstNode const * current, Variable const * searchVariable) {
37+ bool isTargetVariable (AstNode const * const current, Variable const * const searchVariable) {
3838 if (current->type == NODE_TYPE_INDEXED_ACCESS) {
3939 auto sub = current->getMemberUnchecked (0 );
4040 if (sub->type == NODE_TYPE_REFERENCE) {
41- Variable const * v = static_cast <Variable const *>(sub->getData ());
41+ auto const v = static_cast <Variable const *>(sub->getData ());
4242 if (v->id == searchVariable->id ) {
4343 return true ;
4444 }
@@ -57,7 +57,7 @@ bool accessesSearchVariableViaReference(AstNode const* current, Variable const*
5757 if (sub1->type != NODE_TYPE_VARIABLE || sub2->type != NODE_TYPE_REFERENCE) {
5858 return false ;
5959 }
60- Variable const * v = static_cast <Variable const *>(sub2->getData ());
60+ auto const v = static_cast <Variable const *>(sub2->getData ());
6161 if (v->id == searchVariable->id ) {
6262 return true ;
6363 }
@@ -66,113 +66,34 @@ bool accessesSearchVariableViaReference(AstNode const* current, Variable const*
6666 return false ;
6767};
6868
69- bool isTargetVariable (AstNode const * node,
70- ::arangodb::containers::SmallVector<Variable const *>& searchVariables,
71- bool & isSafeForOptimization) {
72- TRI_ASSERT (!searchVariables.empty ());
73-
74- // given and expression like g3[0].`g2`[0].`g1`[0].`item1`.`_id`
75- // this loop resolves subtrees of the form: .`g2`[0].`g1`[0]
76- // search variables should equal [g1, g2, g3]. Therefor we need not match the
77- // variable names from the vector with those in the expression while going
78- // forward in the vector the we go backward in the expression
79-
80- auto current = node;
81- for (auto varIt = searchVariables.begin ();
82- varIt != std::prev (searchVariables.end ()); ++varIt) {
83- AstNode* next = nullptr ;
84- if (current->type == NODE_TYPE_INDEXED_ACCESS) {
85- next = current->getMemberUnchecked (0 );
86- } else if (current->type == NODE_TYPE_EXPANSION) {
87- if (current->numMembers () < 2 ) {
88- return false ;
89- } 90-
91- auto it = current->getMemberUnchecked (0 );
92- TRI_ASSERT (it);
93-
94- // The expansion is at the very end
95- if (it->type == NODE_TYPE_ITERATOR && it->numMembers () == 2 ) {
96- if (it->getMember (0 )->type != NODE_TYPE_VARIABLE) {
97- return false ;
98- }
99-
100- auto attributeAccess = it->getMember (1 );
101- TRI_ASSERT (attributeAccess);
102-
103- if (std::next (varIt) != searchVariables.end () &&
104- attributeAccess->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
105- next = attributeAccess;
106- } else {
107- return false ;
108- }
109-
110- } else {
111- // The expansion is not at the very end! we are unable to check if the
112- // variable will be accessed checking nested expansions is really crazy
113- // and would probably be best done in a recursive way. If the expansion
114- // is in the middle, then it would be still the very first node in the
115- // AST, having 2 subtrees that contain the other search variables
116- isSafeForOptimization = false ; // could be an access - we can not tell
117- return false ;
118- }
119- } else {
120- return false ;
121- }
122-
123- if (varIt == searchVariables.end ()) {
124- return false ;
125- }
126-
127- if (next && next->type == NODE_TYPE_ATTRIBUTE_ACCESS &&
128- next->getString () == (*varIt)->name ) {
129- current = next->getMemberUnchecked (0 );
130- } else if (next && next->type == NODE_TYPE_EXPANSION) {
131- isSafeForOptimization = false ;
132- return false ;
133- } else {
134- return false ;
135- }
136- } // for nodes but last
137-
138- if (!current) {
139- return false ;
140- }
141-
142- return accessesSearchVariableViaReference (current, searchVariables.back ());
143- }
144-
14569} // namespace
14670
147- std::unordered_set<std::string> arangodb::aql::ast::getReferencedAttributesForKeep (
148- const AstNode* node, ::arangodb::containers::SmallVector<const Variable*, 64 > searchVariables,
149- bool & isSafeForOptimization) {
150- std::unordered_set<std::string> result;
71+ auto arangodb::aql::ast::getReferencedAttributesForKeep (AstNode const * const node,
72+ Variable const * const searchVariable,
73+ bool & isSafeForOptimization)
74+ -> std::vector<std::string> {
75+ auto result = std::vector<std::string>();
15176 isSafeForOptimization = true ;
15277
153- std::function<bool (AstNode const *)> visitor = [&isSafeForOptimization, &result,
154- &searchVariables](AstNode const * node) {
155- if (!isSafeForOptimization) {
156- return false ;
157- }
158-
78+ auto const visitor = [&isSafeForOptimization, &result,
79+ &searchVariable](AstNode const * node) -> bool {
15980 if (node->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
16081 while (node->getMemberUnchecked (0 )->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
16182 node = node->getMemberUnchecked (0 );
16283 }
163- if (isTargetVariable (node->getMemberUnchecked (0 ), searchVariables, isSafeForOptimization )) {
164- result.emplace (node->getString ());
84+ if (isTargetVariable (node->getMemberUnchecked (0 ), searchVariable )) {
85+ result.emplace_back (node->getString ());
16586 // do not descend further
16687 return false ;
16788 }
16889 } else if (node->type == NODE_TYPE_REFERENCE) {
169- Variable const * v = static_cast <Variable const *>(node->getData ());
170- if (v->id == searchVariables. front () ->id ) {
90+ auto const v = static_cast <Variable const *>(node->getData ());
91+ if (v->id == searchVariable ->id ) {
17192 isSafeForOptimization = false ; // the expression references the searched variable
17293 return false ;
17394 }
17495 } else if (node->type == NODE_TYPE_EXPANSION) {
175- if (isTargetVariable (node, searchVariables, isSafeForOptimization )) {
96+ if (isTargetVariable (node, searchVariable )) {
17697 auto sub = node->getMemberUnchecked (1 );
17798 if (sub->type == NODE_TYPE_EXPANSION) {
17899 sub = sub->getMemberUnchecked (0 )->getMemberUnchecked (1 );
@@ -181,16 +102,16 @@ std::unordered_set<std::string> arangodb::aql::ast::getReferencedAttributesForKe
181102 while (sub->getMemberUnchecked (0 )->type == NODE_TYPE_ATTRIBUTE_ACCESS) {
182103 sub = sub->getMemberUnchecked (0 );
183104 }
184- result.emplace (sub->getString ());
105+ result.emplace_back (sub->getString ());
185106 // do not descend further
186107 return false ;
187108 }
188109 }
189110 } else if (node->type == NODE_TYPE_INDEXED_ACCESS) {
190111 auto sub = node->getMemberUnchecked (0 );
191112 if (sub-
85B0
>type == NODE_TYPE_REFERENCE) {
192- Variable const * v = static_cast <Variable const *>(sub->getData ());
193- if (v->id == searchVariables. back () ->id ) {
113+ auto const v = static_cast <Variable const *>(sub->getData ());
114+ if (v->id == searchVariable ->id ) {
194115 isSafeForOptimization = false ;
195116 return false ;
196117 }
0 commit comments