示例#1
0
void TRI_CompactStatementListAql (TRI_aql_statement_list_t* const list) {
  size_t i, j, n;

  assert(list);

  i = 0;
  j = 0;
  n = list->_statements._length;

  while (i < n) {
    TRI_aql_node_t* node = StatementAt(list, i);

    if (node->_type == TRI_AQL_NODE_NOP) {
      ++i;
      continue;
    }

    if (node->_type == TRI_AQL_NODE_RETURN_EMPTY) {
      i = TRI_InvalidateStatementListAql(list, i);
      j = i;
      continue; 
    }

    list->_statements._buffer[j++] = node;
    ++i;
  }

  list->_statements._length = j;
}
示例#2
0
size_t TRI_InvalidateStatementListAql (TRI_aql_statement_list_t* const list,
                                       const size_t position) {
  size_t i, n;
  size_t start;
  size_t scopes;
  size_t ignoreScopes;

  assert(list);
  assert(position >= 0);
  n = list->_statements._length;

  // walk the scope from the specified position backwards until we find the start of the scope
  scopes = 1;
  ignoreScopes = 0;
  i = position;
  while (true) {
    TRI_aql_node_t* node = StatementAt(list, i);
    TRI_aql_node_type_e type = node->_type;

    list->_statements._buffer[i] = TRI_GetDummyNopNodeAql();
    start = i;

    if (type == TRI_AQL_NODE_SCOPE_START) {
      // node is a scope start
      TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node);

      if (ignoreScopes > 0) {
        // this is an inner, parallel scope that we can ignore
        --ignoreScopes;
      }
      else {
        if (scope->_type != TRI_AQL_SCOPE_FOR_NESTED) {
          // we have reached the scope and need to stop
          break;
        }
        scopes++;
      }
    }
    else if (type == TRI_AQL_NODE_SCOPE_END) {
      // we found the end of another scope
      // we must remember how many other scopes we passed
      ignoreScopes++;
    }

    if (i-- == 0) {
      break;
    }
  }

  assert(ignoreScopes == 0);

  // remove from position forwards to scope end
  i = position;
  while (true) {
    TRI_aql_node_t* node = StatementAt(list, i);
    TRI_aql_node_type_e type = node->_type;
    
    list->_statements._buffer[i] = TRI_GetDummyNopNodeAql();

    if (type == TRI_AQL_NODE_SCOPE_START) {
      ++scopes;
    }
    else if (type == TRI_AQL_NODE_SCOPE_END) {
      assert(scopes > 0);
      if (--scopes == 0) {
        break;
      }
    }

    if (++i == n) {
      break;
    }
  }
  
  list->_statements._buffer[start] = TRI_GetDummyReturnEmptyNodeAql();

  return start + 1;
}
示例#3
0
void TRI_PulloutStatementListAql (TRI_aql_statement_list_t* const list) {
  size_t i, n;
  size_t scopes = 0;
  size_t targetScope = 0;
  size_t moveStart = 0;
  bool watch = false;

  assert(list);

  i = 0;
  n = list->_statements._length;
  
  while (i < n) {
    TRI_aql_node_t* node = StatementAt(list, i);
    TRI_aql_node_type_e type = node->_type;
    
    if (type == TRI_AQL_NODE_SCOPE_START) {
      // node is a scope start
      TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node);
      
      if (scope->_type == TRI_AQL_SCOPE_SUBQUERY && scope->_selfContained) {
        if (! watch && scopes > 0) {
          watch = true;
          targetScope = scopes;
          moveStart = i;
        }
      }
      
      ++scopes;
    }
    else if (type == TRI_AQL_NODE_SCOPE_END) {
      // node is a scope end
      --scopes;

      if (watch && scopes == targetScope) {
        watch = false;

        node = StatementAt(list, i + 1);

        // check if next statement is a subquery statement
        if (i + 1 < n && node->_type == TRI_AQL_NODE_SUBQUERY) {
          size_t j = moveStart;
          size_t inserted = 0;

          // moving statements from the middle to the beginning of the list will also 
          // modify the positions we're moving from
          while (j < i + 2) {
            node = StatementAt(list, j + inserted);
            if (! TRI_InsertStatementListAql(list, node, inserted + 0)) {
              return;
            }

            // insert a dummy node in place of the moved node 
            list->_statements._buffer[j + inserted + 1] = TRI_GetDummyNopNodeAql();

            // next
            ++j;
            ++inserted;
          }

          // moving statements from the middle to the beginning of the list will also 
          // change the list length and the position we'll be continuing from
          n += inserted;
          i = j + inserted;
        }

      }
    }

    ++i;
  }
}
示例#4
0
size_t TRI_InvalidateStatementListAql (TRI_aql_statement_list_t* const list,
                                       const size_t position) {
  size_t i, n;
  size_t start;
  size_t scopes;

  assert(list);
  assert(position >= 0);
  n = list->_statements._length;

  // remove from position backwards to scope start
  scopes = 1;
  i = position;
  while (true) {
    TRI_aql_node_t* node = StatementAt(list, i);
    TRI_aql_node_type_e type = node->_type;

    list->_statements._buffer[i] = TRI_GetDummyNopNodeAql();
    start = i;

    if (type == TRI_AQL_NODE_SCOPE_START) {
      TRI_aql_scope_t* scope = (TRI_aql_scope_t*) TRI_AQL_NODE_DATA(node);

      if (scope->_type != TRI_AQL_SCOPE_FOR_NESTED) {
        break;
      }
      scopes++;
    }

    if (i-- == 0) {
      break;
    }
  }

  // remove from position forwards to scope end
  i = position;
  while (true) {
    TRI_aql_node_t* node = StatementAt(list, i);
    TRI_aql_node_type_e type = node->_type;
    
    list->_statements._buffer[i] = TRI_GetDummyNopNodeAql();

    if (type == TRI_AQL_NODE_SCOPE_START) {
      ++scopes;
    }
    else if (type == TRI_AQL_NODE_SCOPE_END) {
      assert(scopes > 0);
      if (--scopes == 0) {
        break;
      }
    }

    if (++i == n) {
      break;
    }
  }
  
  list->_statements._buffer[start] = TRI_GetDummyReturnEmptyNodeAql();

  return start + 1;
}