@@ -292,14 +292,15 @@ impl Conjunction {
292292 } else {
293293 (idx + 1).to_string()
294294 };
295+ self.variables.insert(variable.clone(), self.nodes.len());
296+
295297 self.nodes.push(NodeSearchSpecEntry {
296298 var: variable.clone(),
297299 spec: node,
298300 optional,
299301 location: location.clone(),
300302 });
301303
302- self.variables.insert(variable.clone(), idx);
303304 if included_in_output && !optional {
304305 self.include_in_output.insert(variable.clone());
305306 }
@@ -315,9 +316,11 @@ impl Conjunction {
315316 var: &str,
316317 location: Option<LineColumnRange>,
317318 ) -> Result<()> {
318- if let Some(idx) = self.variables.get(var) {
319- self.unary_operators
320- .push(UnaryOperatorSpecEntry { op, idx: *idx });
319+ if let Some(local_idx) = self.variables.get(var) {
320+ self.unary_operators.push(UnaryOperatorSpecEntry {
321+ op,
322+ idx: *local_idx,
323+ });
321324 Ok(())
322325 } else {
323326 Err(GraphAnnisError::AQLSemanticError(AQLError {
@@ -370,34 +373,28 @@ impl Conjunction {
370373 location: Option<LineColumnRange>,
371374 ) -> Result<usize> {
372375 if let Some(pos) = self.variables.get(variable) {
373- return Ok(* pos);
376+ return Ok(pos + self.var_idx_offset );
374377 }
375378 Err(GraphAnnisError::AQLSemanticError(AQLError {
376379 desc: format!("Operand \"#{}\" not found", variable),
377380 location,
378381 }))
379382 }
380383
384+ /// Return true if the given query node variable is supposed to be included
385+ /// in a match output. This is not the case if it is an optional node or a
386+ /// legacy `meta::` query reference.
381387 pub fn is_included_in_output(&self, variable: &str) -> bool {
382388 self.include_in_output.contains(variable)
383389 }
384390
385- /// Return the variable name for a given position in the match output list.
386- ///
387- /// Optional nodes that are not part of the output are ignored. If there are
388- /// no optional nodes, this corresponds to the index of the node in the
389- /// query.
390- pub fn get_variable_by_pos(&self, pos: usize) -> Option<String> {
391- let mut output_pos = 0;
392- for n in self.nodes.iter() {
393- if self.is_included_in_output(&n.var) {
394- if output_pos == pos {
395- return Some(n.var.clone());
396- }
397- output_pos += 1;
398- }
399- }
400- None
391+ /// Return the variable name for a node number. The node number is the
392+ /// position of an node description in the query. In case of a query with
393+ /// multiple alternatives, this refers to the node number of the whole query and
394+ /// not only the conjunction.
395+ pub fn get_variable_by_node_nr(&self, node_nr: usize) -> Option<String> {
396+ let pos = node_nr.checked_sub(self.var_idx_offset)?;
397+ self.nodes.get(pos).map(|spec| spec.var.clone())
401398 }
402399
403400 pub fn resolve_variable(
@@ -725,7 +722,7 @@ impl Conjunction {
725722 .ok_or(GraphAnnisError::NoComponentForNode(spec_idx_right + 1))?);
726723
727724 // get the original execution node
728- let exec_left: Box<dyn ExecutionNode<Item = Result<MatchGroup>> + 'a> = component2exec
725+ let exec_left = component2exec
729726 .remove(&component_left)
730727 .ok_or(GraphAnnisError::NoExecutionNode(component_left))?;
731728
@@ -821,7 +818,7 @@ impl Conjunction {
821818
822819 // 2. add unary operators as filter to the existing node search
823820 for op_spec_entry in self.unary_operators.iter() {
824- let child_exec: Box<dyn ExecutionNode<Item = Result<MatchGroup>> + 'a> = component2exec
821+ let child_exec = component2exec
825822 .remove(&op_spec_entry.idx)
826823 .ok_or(GraphAnnisError::NoExecutionNode(op_spec_entry.idx))?;
827824
0 commit comments