TRI_aql_statement_walker_t* TRI_CreateStatementWalkerAql (void* data, const bool canModify, TRI_aql_visit_f visitMember, TRI_aql_visit_f preVisitStatement, TRI_aql_visit_f postVisitStatement) { TRI_aql_statement_walker_t* walker; int res; walker = (TRI_aql_statement_walker_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_statement_walker_t), false); if (walker == NULL) { return NULL; } walker->_data = data; walker->_canModify = canModify; walker->visitMember = visitMember; walker->preVisitStatement = preVisitStatement; walker->postVisitStatement = postVisitStatement; res = TRI_InitVectorPointer2(&walker->_currentScopes, TRI_UNKNOWN_MEM_ZONE, 4); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, walker); return NULL; } return walker; }
int TRI_InitHashArrayMulti (TRI_hash_array_multi_t* array, size_t numFields) { TRI_ASSERT(numFields > 0); array->_numFields = numFields; array->_tablePtr = nullptr; array->_table = nullptr; array->_nrUsed = 0; array->_nrAlloc = 0; array->_nrOverflowUsed = 0; array->_nrOverflowAlloc = 0; array->_freelist = nullptr; TRI_InitVectorPointer2(&array->_blocks, TRI_UNKNOWN_MEM_ZONE, 16); return AllocateTable(array, InitialSize()); }
static bool BytecodeShapeAccessor (TRI_shaper_t* shaper, TRI_shape_access_t* accessor) { TRI_shape_aid_t const* paids; TRI_shape_path_t const* path; TRI_shape_t const* shape; TRI_vector_pointer_t ops; size_t i; size_t j; int res; // find the shape shape = shaper->lookupShapeId(shaper, accessor->_sid); if (shape == nullptr) { LOG_ERROR("unknown shape id %llu", (unsigned long long) accessor->_sid); #ifdef TRI_ENABLE_MAINTAINER_MODE TRI_ASSERT(false); #endif return false; } // find the attribute path path = shaper->lookupAttributePathByPid(shaper, accessor->_pid); if (path == nullptr) { LOG_ERROR("unknown attribute path %llu", (unsigned long long) accessor->_pid); #ifdef TRI_ENABLE_MAINTAINER_MODE TRI_ASSERT(false); #endif return false; } paids = (TRI_shape_aid_t*) (((char const*) path) + sizeof(TRI_shape_path_t)); // collect the bytecode // we need at least 2 entries in the vector to store an accessor TRI_InitVectorPointer2(&ops, shaper->_memoryZone, 2); // and follow it for (i = 0; i < path->_aidLength; ++i, ++paids) { #ifdef DEBUG_SHAPE_ACCESSOR printf("%lu: aid: %lu, sid: %lu, type %lu\n", (unsigned long) i, (unsigned long) *paids, (unsigned long) shape->_sid, (unsigned long) shape->_type); #endif if (shape->_type == TRI_SHAPE_ARRAY) { TRI_array_shape_t* s; TRI_shape_aid_t const* aids; TRI_shape_sid_t const* sids; TRI_shape_sid_t sid; TRI_shape_size_t const* offsetsF; TRI_shape_size_t f; TRI_shape_size_t n; TRI_shape_size_t v; char const* qtr; s = (TRI_array_shape_t*) shape; f = s->_fixedEntries; v = s->_variableEntries; n = f + v; // find the aid within the shape qtr = (char const*) shape; qtr += sizeof(TRI_array_shape_t); sids = (TRI_shape_sid_t const*) qtr; qtr += n * sizeof(TRI_shape_sid_t); aids = (TRI_shape_aid_t const*) qtr; qtr += n * sizeof(TRI_shape_aid_t); offsetsF = (TRI_shape_size_t const*) qtr; // check for fixed size aid for (j = 0; j < f; ++j, ++sids, ++aids, ++offsetsF) { if (*paids == *aids) { sid = *sids; LOG_TRACE("found aid '%ld' as fixed entry with sid '%ld' and offset '%ld' - '%ld'", (unsigned long) *paids, (unsigned long) sid, (unsigned long) offsetsF[0], (unsigned long) offsetsF[1]); shape = shaper->lookupShapeId(shaper, sid); if (shape == nullptr) { LOG_ERROR("unknown shape id '%ld' for attribute id '%ld'", (unsigned long) accessor->_sid, (unsigned long) *paids); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_OFFSET_FIX); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) (uintptr_t) (offsetsF[0])); // offset is always smaller than 4 GByte if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) (uintptr_t) (offsetsF[1])); // offset is always smaller than 4 GByte if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } break; } } if (j < f) { continue; } // check for variable size aid for (j = 0; j < v; ++j, ++sids, ++aids) { if (*paids == *aids) { sid = *sids; LOG_TRACE("found aid '%ld' as variable entry with sid '%ld'", (unsigned long) *paids, (unsigned long) sid); shape = shaper->lookupShapeId(shaper, sid); if (shape == nullptr) { LOG_ERROR("unknown shape id '%ld' for attribute id '%ld'", (unsigned long) accessor->_sid, (unsigned long) *paids); LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_OFFSET_VAR); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) j); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } break; } } if (j < v) { continue; } LOG_TRACE("unknown attribute id '%ld'", (unsigned long) *paids); TRI_DestroyVectorPointer(&ops); accessor->_resultSid = TRI_SHAPE_ILLEGAL; accessor->_code = nullptr; return true; } else { TRI_DestroyVectorPointer(&ops); accessor->_resultSid = TRI_SHAPE_ILLEGAL; accessor->_code = nullptr; return true; } } // travel attribute path to the end res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_DONE); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } // remember resulting sid accessor->_resultSid = shape->_sid; // steal buffer from ops vector so we don't need to copy it accessor->_code = const_cast<void const**>(ops._buffer); // inform the vector that we took over ownership ops._buffer = nullptr; TRI_DestroyVectorPointer(&ops); return true; }
static bool FindEdges (const TRI_edge_direction_e direction, TRI_multi_pointer_t* idx, TRI_vector_pointer_t* result, TRI_edge_header_t* entry, const int matchType) { TRI_vector_pointer_t found; TRI_edge_header_t* edge; entry->_flags = TRI_LookupFlagsEdge(direction); found = TRI_LookupByKeyMultiPointer(TRI_UNKNOWN_MEM_ZONE, idx, entry); if (found._length > 0) { size_t i; if (result->_capacity == 0) { int res; // if result vector is still empty and we have results, re-init the // result vector to a "good" size. this will save later reallocations res = TRI_InitVectorPointer2(result, TRI_UNKNOWN_MEM_ZONE, found._length); if (res != TRI_ERROR_NO_ERROR) { TRI_DestroyVectorPointer(&found); TRI_set_errno(res); return false; } } // add all results found for (i = 0; i < found._length; ++i) { edge = (TRI_edge_header_t*) found._buffer[i]; // the following queries will use the following sequences of matchTypes: // inEdges(): 1, 2, outEdges(): 1, 2, edges(): 1, 3 // if matchType is 1, we'll return all found edges without further filtering // // if matchType is 2 (inEdges or outEdges query), the direction is reversed. // We'll exclude all self-reflexive edges now (we already got them in iteration 1), // and alsoexclude all unidirectional edges // // if matchType is 3, the direction is also reversed. We'll exclude all // self-reflexive edges now (we already got them in iteration 1) if (matchType > 1) { // if the edge is self-reflexive, we have already found it in iteration 1 // we must skip it here, otherwise we would produce duplicates if (IsReflexive(edge)) { continue; } } TRI_PushBackVectorPointer(result, CONST_CAST(edge->_mptr)); } } TRI_DestroyVectorPointer(&found); return true; }
static bool BytecodeShapeAccessor (TRI_shaper_t* shaper, TRI_shape_access_t* accessor) { TRI_shape_aid_t const* paids; TRI_shape_path_t const* path; TRI_shape_t const* shape; TRI_vector_pointer_t ops; size_t i; size_t j; int res; // find the shape shape = shaper->lookupShapeId(shaper, accessor->_sid); if (shape == NULL) { LOG_ERROR("unknown shape id %llu", (unsigned long long) accessor->_sid); return false; } // find the attribute path path = shaper->lookupAttributePathByPid(shaper, accessor->_pid); if (path == NULL) { LOG_ERROR("unknown attribute path %llu", (unsigned long long) accessor->_pid); return false; } paids = (TRI_shape_aid_t*) (((char const*) path) + sizeof(TRI_shape_path_t)); // collect the bytecode // we need at least 4 entries in the vector to store an accessor TRI_InitVectorPointer2(&ops, shaper->_memoryZone, 4); // start with the shape res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_SHAPE_PTR); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, CONST_CAST(shape)); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } // and follow it for (i = 0; i < path->_aidLength; ++i, ++paids) { #ifdef DEBUG_SHAPE_ACCESSOR printf("%lu: aid: %lu, sid: %lu, type %lu\n", (unsigned long) i, (unsigned long) *paids, (unsigned long) shape->_sid, (unsigned long) shape->_type); #endif if (shape->_type == TRI_SHAPE_ARRAY) { TRI_array_shape_t* s; TRI_shape_aid_t const* aids; TRI_shape_sid_t const* sids; TRI_shape_sid_t sid; TRI_shape_size_t const* offsetsF; TRI_shape_size_t f; TRI_shape_size_t n; TRI_shape_size_t v; char const* qtr; s = (TRI_array_shape_t*) shape; f = s->_fixedEntries; v = s->_variableEntries; n = f + v; // find the aid within the shape qtr = (char const*) shape; qtr += sizeof(TRI_array_shape_t); sids = (TRI_shape_sid_t const*) qtr; qtr += n * sizeof(TRI_shape_sid_t); aids = (TRI_shape_aid_t const*) qtr; qtr += n * sizeof(TRI_shape_aid_t); offsetsF = (TRI_shape_size_t const*) qtr; // check for fixed size aid for (j = 0; j < f; ++j, ++sids, ++aids, ++offsetsF) { if (*paids == *aids) { sid = *sids; LOG_TRACE("found aid '%ld' as fixed entry with sid '%ld' and offset '%ld' - '%ld'", (unsigned long) *paids, (unsigned long) sid, (unsigned long) offsetsF[0], (unsigned long) offsetsF[1]); shape = shaper->lookupShapeId(shaper, sid); if (shape == NULL) { LOG_ERROR("unknown shape id '%ld' for attribute id '%ld'", (unsigned long) accessor->_sid, (unsigned long) *paids); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_OFFSET_FIX); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) (uintptr_t) (offsetsF[0])); // offset is always smaller than 4 GByte if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) (uintptr_t) (offsetsF[1])); // offset is always smaller than 4 GByte if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_SHAPE_PTR); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, CONST_CAST(shape)); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } break; } } if (j < f) { continue; } // check for variable size aid for (j = 0; j < v; ++j, ++sids, ++aids) { if (*paids == *aids) { sid = *sids; LOG_TRACE("found aid '%ld' as variable entry with sid '%ld'", (unsigned long) *paids, (unsigned long) sid); shape = shaper->lookupShapeId(shaper, sid); if (shape == NULL) { LOG_ERROR("unknown shape id '%ld' for attribute id '%ld'", (unsigned long) accessor->_sid, (unsigned long) *paids); LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_OFFSET_VAR); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) j); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_SHAPE_PTR); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } res = TRI_PushBackVectorPointer(&ops, CONST_CAST(shape)); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } break; } } if (j < v) { continue; } LOG_TRACE("unknown attribute id '%ld'", (unsigned long) *paids); TRI_DestroyVectorPointer(&ops); accessor->_shape = NULL; accessor->_code = NULL; return true; } else { TRI_DestroyVectorPointer(&ops); accessor->_shape = NULL; accessor->_code = NULL; return true; } } // travel attribute path to the end res = TRI_PushBackVectorPointer(&ops, (void*) TRI_SHAPE_AC_DONE); if (res != TRI_ERROR_NO_ERROR) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } accessor->_shape = shape; accessor->_code = TRI_Allocate(shaper->_memoryZone, ops._length * sizeof(void*), false); if (accessor->_code == NULL) { LOG_ERROR("out of memory"); TRI_DestroyVectorPointer(&ops); return false; } memcpy(CONST_CAST(accessor->_code), ops._buffer, ops._length * sizeof(void*)); TRI_DestroyVectorPointer(&ops); return true; }
TRI_aql_context_t* TRI_CreateContextAql (TRI_vocbase_t* vocbase, const char* const query) { TRI_aql_context_t* context; TRI_ASSERT_MAINTAINER(vocbase != NULL); TRI_ASSERT_MAINTAINER(query != NULL); LOG_TRACE("creating context"); context = (TRI_aql_context_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_context_t), false); if (context == NULL) { return NULL; } context->_vocbase = vocbase; context->_variableIndex = 0; context->_scopeIndex = 0; // actual bind parameter values TRI_InitAssociativePointer(&context->_parameters._values, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashBindParameterAql, &TRI_EqualBindParameterAql, 0); // bind parameter names used in the query TRI_InitAssociativePointer(&context->_parameters._names, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashStringKeyAssociativePointer, &TRI_EqualStringKeyAssociativePointer, 0); // collections TRI_InitAssociativePointer(&context->_collectionNames, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashStringKeyAssociativePointer, &TRI_EqualStringKeyAssociativePointer, 0); TRI_InitVectorPointer2(&context->_memory._nodes, TRI_UNKNOWN_MEM_ZONE, 16); TRI_InitVectorPointer2(&context->_memory._strings, TRI_UNKNOWN_MEM_ZONE, 16); TRI_InitVectorPointer(&context->_collections, TRI_UNKNOWN_MEM_ZONE); TRI_InitErrorAql(&context->_error); context->_parser = NULL; context->_statements = NULL; context->_query = query; context->_parser = TRI_CreateParserAql(context->_query); if (context->_parser == NULL) { // could not create the parser TRI_FreeContextAql(context); return NULL; } if (! TRI_InitParserAql(context)) { // could not initialise the lexer TRI_FreeContextAql(context); return NULL; } context->_statements = TRI_CreateStatementListAql(); if (context->_statements == NULL) { // could not create statement list TRI_FreeContextAql(context); return NULL; } TRI_InitScopesAql(context); return context; }
static bool FindEdges (const TRI_edge_direction_e direction, TRI_edge_index_t* idx, TRI_vector_pointer_t* result, TRI_edge_header_t* entry, const int matchType) { TRI_vector_pointer_t found; if (direction == TRI_EDGE_OUT) { found = TRI_LookupByKeyMultiPointer(TRI_UNKNOWN_MEM_ZONE, &idx->_edges_from, entry); } else if (direction == TRI_EDGE_IN) { found = TRI_LookupByKeyMultiPointer(TRI_UNKNOWN_MEM_ZONE, &idx->_edges_to, entry); } else { assert(false); // TRI_EDGE_ANY not supported here } if (found._length > 0) { size_t i; if (result->_capacity == 0) { int res; // if result vector is still empty and we have results, re-init the // result vector to a "good" size. this will save later reallocations res = TRI_InitVectorPointer2(result, TRI_UNKNOWN_MEM_ZONE, found._length); if (res != TRI_ERROR_NO_ERROR) { TRI_DestroyVectorPointer(&found); TRI_set_errno(res); return false; } } // add all results found for (i = 0; i < found._length; ++i) { TRI_doc_mptr_t* edge = (TRI_doc_mptr_t*) found._buffer[i]; // the following queries will use the following sequences of matchTypes: // inEdges(): 1, outEdges(): 1, edges(): 1, 3 // if matchType is 1, we'll return all found edges without filtering // We'll exclude all loop edges now (we already got them in iteration 1), // and alsoexclude all unidirectional edges // // if matchType is 3, the direction is also reversed. We'll exclude all // loop edges now (we already got them in iteration 1) if (matchType > 1) { // if the edge is a loop, we have already found it in iteration 1 // we must skip it here, otherwise we would produce duplicates if (IsReflexive(edge)) { continue; } } TRI_PushBackVectorPointer(result, CONST_CAST(edge)); } } TRI_DestroyVectorPointer(&found); return true; }
TRI_aql_context_t* TRI_CreateContextAql (TRI_vocbase_t* vocbase, const char* const query, const size_t queryLength, bool isCoordinator, TRI_json_t* userOptions) { TRI_aql_context_t* context; int res; TRI_ASSERT(vocbase != NULL); TRI_ASSERT(query != NULL); LOG_TRACE("creating context"); context = (TRI_aql_context_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_context_t), false); if (context == NULL) { return NULL; } context->_type = TRI_AQL_QUERY_READ; context->_vocbase = vocbase; context->_userOptions = userOptions; context->_writeOptions = NULL; context->_writeCollection = NULL; context->_variableIndex = 0; context->_scopeIndex = 0; context->_subQueries = 0; // actual bind parameter values res = TRI_InitAssociativePointer(&context->_parameters._values, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashBindParameterAql, &TRI_EqualBindParameterAql, 0); if (res != TRI_ERROR_NO_ERROR) { TRI_Free(TRI_UNKNOWN_MEM_ZONE, context); return NULL; } // bind parameter names used in the query res = TRI_InitAssociativePointer(&context->_parameters._names, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashStringKeyAssociativePointer, &TRI_EqualStringKeyAssociativePointer, 0); if (res != TRI_ERROR_NO_ERROR) { TRI_DestroyAssociativePointer(&context->_parameters._values); TRI_Free(TRI_UNKNOWN_MEM_ZONE, context); return NULL; } // collections res = TRI_InitAssociativePointer(&context->_collectionNames, TRI_UNKNOWN_MEM_ZONE, &TRI_HashStringKeyAssociativePointer, &TRI_HashStringKeyAssociativePointer, &TRI_EqualStringKeyAssociativePointer, 0); if (res != TRI_ERROR_NO_ERROR) { TRI_DestroyAssociativePointer(&context->_parameters._names); TRI_DestroyAssociativePointer(&context->_parameters._values); TRI_Free(TRI_UNKNOWN_MEM_ZONE, context); return NULL; } TRI_InitVectorPointer2(&context->_memory._nodes, TRI_UNKNOWN_MEM_ZONE, 16); TRI_InitVectorPointer2(&context->_memory._strings, TRI_UNKNOWN_MEM_ZONE, 16); TRI_InitVectorPointer(&context->_collections, TRI_UNKNOWN_MEM_ZONE); TRI_InitErrorAql(&context->_error); context->_parser = NULL; context->_statements = NULL; context->_query = query; TRI_InitScopesAql(context); context->_parser = TRI_CreateParserAql(context->_query, queryLength); if (context->_parser == NULL) { // could not create the parser TRI_FreeContextAql(context); return NULL; } if (! TRI_InitParserAql(context)) { // could not initialise the lexer TRI_FreeContextAql(context); return NULL; } context->_statements = TRI_CreateStatementListAql(); if (context->_statements == NULL) { // could not create statement list TRI_FreeContextAql(context); return NULL; } ProcessOptions(context); context->_isCoordinator = isCoordinator; return context; }