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; }
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; }
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; } }
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; }