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());
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}