예제 #1
0
char* TRI_GetContextErrorAql (const char* const query, const size_t line, const size_t column) {
  const char* p;
  char* temp;
  char* result;
  char c;
  // note: line numbers reported by bison/flex start at 1, columns start at 0 
  size_t offset;
  size_t currentLine = 1;
  size_t currentColumn = 0;

  assert(query);

  p = query;
  while ((c = *p)) {
    if (currentLine > line || (currentLine >= line && currentColumn >= column)) {
      break;
    }

    if (c == '\n') {
      ++p;
      ++currentLine;
      currentColumn = 0;
    }
    else if (c == '\r') {
      ++p;
      ++currentLine;
      currentColumn = 0;

      if (*p == '\n') {
        ++p;
      }
    }
    else {
      ++currentColumn;
      ++p;
    }
  }

  // p is pointing at the position in the query the parse error occurred at
  assert(p >= query);

  offset = p - query;

  if (strlen(query) < offset + SNIPPET_LENGTH) {
    return TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, query + offset, strlen(query) - offset);
  }

  temp = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, query + offset, SNIPPET_LENGTH);
  if (!temp) {
    // out of memory
    return NULL;
  }

  result = TRI_Concatenate2StringZ(TRI_UNKNOWN_MEM_ZONE, temp, SNIPPET_SUFFIX);
  TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, temp);

  return result;
}
예제 #2
0
파일: json.cpp 프로젝트: morsdatum/ArangoDB
void TRI_Insert2ArrayJson (TRI_memory_zone_t* zone,
                           TRI_json_t* object,
                           char const* name,
                           TRI_json_t* subobject) {
  TRI_json_t copy;
  char* att;
  size_t length;

  TRI_ASSERT(object->_type == TRI_JSON_ARRAY);

  if (subobject == NULL) {
    return;
  }

  if (TRI_ReserveVector(&object->_value._objects, 2) != TRI_ERROR_NO_ERROR) {
    // TODO: signal OOM here
    return;
  }

  length = strlen(name);
  att = TRI_DuplicateString2Z(zone, name, length);

  if (att == NULL) {
    // TODO: signal OOM here
    return;
  }

  // attribute name
  InitString(&copy, att, length);
  TRI_PushBackVector(&object->_value._objects, &copy);

  // attribute value
  TRI_PushBackVector(&object->_value._objects, subobject);
}
예제 #3
0
static TRI_aql_bind_parameter_t* CreateParameter (const char* const name,
                                                  const size_t nameLength,
                                                  const TRI_json_t* const value) {
  TRI_aql_bind_parameter_t* parameter;

  assert(name);
  assert(value);

  parameter = (TRI_aql_bind_parameter_t*) TRI_Allocate(TRI_UNKNOWN_MEM_ZONE, sizeof(TRI_aql_bind_parameter_t), false);

  if (parameter == NULL) {
    return NULL;
  }

  parameter->_name = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, name, nameLength);

  if (parameter->_name == NULL) {
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter);

    return NULL;
  }

  parameter->_value = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, (TRI_json_t*) value);

  if (parameter->_value == NULL) {
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter->_name);
    TRI_Free(TRI_UNKNOWN_MEM_ZONE, parameter);

    return NULL;
  }

  return parameter;
}
예제 #4
0
char* TRI_GetErrorMessageAql (const TRI_aql_error_t* const error) {
  char* message;
  char buffer[256];
  int code;

  TRI_ASSERT(error);

  code = TRI_GetErrorCodeAql(error);

  if (code == TRI_ERROR_NO_ERROR) {
    return NULL;
  }

  message = error->_message;

  if (message == NULL) {
    return NULL;
  }

  if (error->_data && (NULL != strstr(message, "%s"))) {
    int written = snprintf(buffer, sizeof(buffer), message, error->_data);

    return TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, (const char*) &buffer, (size_t) written);
  }

  return TRI_DuplicateStringZ(TRI_UNKNOWN_MEM_ZONE, message);
}
예제 #5
0
파일: json.cpp 프로젝트: m0ppers/arangodb
void TRI_Insert2ObjectJson (TRI_memory_zone_t* zone,
                           TRI_json_t* object,
                           char const* name,
                           TRI_json_t const* subobject) {
  TRI_ASSERT(object->_type == TRI_JSON_OBJECT);

  if (subobject == nullptr) {
    return;
  }

  if (TRI_ReserveVector(&object->_value._objects, 2) != TRI_ERROR_NO_ERROR) {
    // TODO: signal OOM here
    return;
  }

  size_t length = strlen(name);
  char* att = TRI_DuplicateString2Z(zone, name, length);

  if (att == nullptr) {
    // TODO: signal OOM here
    return;
  }

  // create attribute name in place
  TRI_json_t* next = static_cast<TRI_json_t*>(TRI_NextVector(&object->_value._objects));
  // we have made sure above with the reserve call that the vector has enough capacity
  TRI_ASSERT(next != nullptr);
  InitString(next, att, length);

  // attribute value
  TRI_PushBackVector(&object->_value._objects, subobject);
}
예제 #6
0
char* TRI_RegisterStringAql (TRI_aql_context_t* const context,
                             const char* const value,
                             const size_t length,
                             const bool deescape) {
  char* copy;

  if (value == NULL) {
    ABORT_OOM
  }

  if (deescape && length > 0) {
    size_t outLength;

    copy = TRI_UnescapeUtf8StringZ(TRI_UNKNOWN_MEM_ZONE, value, length, &outLength);
  }
  else {
    copy = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, value, length);
  }

  if (copy == NULL) {
    ABORT_OOM
  }

  if (TRI_PushBackVectorPointer(&context->_memory._strings, copy) != TRI_ERROR_NO_ERROR) {
    TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, copy);
    ABORT_OOM
  }
예제 #7
0
파일: json.cpp 프로젝트: morsdatum/ArangoDB
int TRI_InitString2CopyJson (TRI_memory_zone_t* zone, TRI_json_t* result, char const* value, size_t length) {
  char* copy = TRI_DuplicateString2Z(zone, value, length);
  if (copy == nullptr) {
    return TRI_ERROR_OUT_OF_MEMORY;
  }
  InitString(result, copy, length);
  return TRI_ERROR_NO_ERROR;
}
예제 #8
0
파일: json.cpp 프로젝트: m0ppers/arangodb
int TRI_InitStringCopyJson (TRI_memory_zone_t* zone, TRI_json_t* result, char const* value, size_t length) {
  if (value == nullptr) {
    // initial string should be valid
    return TRI_ERROR_INTERNAL;
  }

  char* copy = TRI_DuplicateString2Z(zone, value, length);

  if (copy == nullptr) {
    return TRI_ERROR_OUT_OF_MEMORY;
  }

  InitString(result, copy, length);

  return TRI_ERROR_NO_ERROR;
}
예제 #9
0
파일: json.cpp 프로젝트: morsdatum/ArangoDB
TRI_json_t* TRI_CreateString2CopyJson (TRI_memory_zone_t* zone, char const* value, size_t length) {
  TRI_json_t* result;

  result = (TRI_json_t*) TRI_Allocate(zone, sizeof(TRI_json_t), false);

  if (result == NULL) {
    return NULL;
  }

  InitString(result, TRI_DuplicateString2Z(zone, value, length), length);

  if (result->_value._string.data == NULL) {
    TRI_Free(zone, result);
    return NULL;
  }

  return result;
}
예제 #10
0
파일: json.cpp 프로젝트: m0ppers/arangodb
TRI_json_t* TRI_CreateStringCopyJson (TRI_memory_zone_t* zone, char const* value, size_t length) {
  if (value == nullptr) {
    // initial string should be valid...
    return nullptr;
  }

  TRI_json_t* result = static_cast<TRI_json_t*>(TRI_Allocate(zone, sizeof(TRI_json_t), false));

  if (result != nullptr) {
    char* copy = TRI_DuplicateString2Z(zone, value, length);

    if (copy == nullptr) {
      TRI_Free(zone, result);
      return nullptr;
    }

    InitString(result, copy, length);
  }

  return result;
}
예제 #11
0
void TRI_Insert2ArrayJson (TRI_memory_zone_t* zone,
                           TRI_json_t* object,
                           char const* name, 
                           TRI_json_t* subobject) {
  TRI_json_t copy;
  size_t length;

  assert(object->_type == TRI_JSON_ARRAY);

  if (subobject == NULL) {
    return;
  }

  length = strlen(name);

  copy._type = TRI_JSON_STRING;
  copy._value._string.length = length + 1;
  copy._value._string.data = TRI_DuplicateString2Z(zone, name, length); // including '\0'

  TRI_PushBackVector(&object->_value._objects, &copy);
  TRI_PushBackVector(&object->_value._objects, subobject);
}
예제 #12
0
TRI_json_t* TRI_CreateStringCopyJson (TRI_memory_zone_t* zone, char const* value) {
  TRI_json_t* result;
  size_t length;

  length = strlen(value);

  result = (TRI_json_t*) TRI_Allocate(zone, sizeof(TRI_json_t), false);

  if (result == NULL) {
    return NULL;
  }

  result->_type = TRI_JSON_STRING;
  result->_value._string.length = length + 1;
  result->_value._string.data = TRI_DuplicateString2Z(zone, value, length);

  if (result->_value._string.data == NULL) {
    TRI_Free(zone, result);
    return NULL;
  }

  return result;
}
예제 #13
0
static int LoadConfiguration (TRI_vocbase_t* vocbase,
                              TRI_replication_applier_configuration_t* config) {
  TRI_json_t* json;
  TRI_json_t* value;
  char* filename;
  int res;
   
  TRI_DestroyConfigurationReplicationApplier(config);
  TRI_InitConfigurationReplicationApplier(config);
  filename = GetConfigurationFilename(vocbase);

  if (! TRI_ExistsFile(filename)) {
    TRI_FreeString(TRI_CORE_MEM_ZONE, filename);

    return TRI_ERROR_FILE_NOT_FOUND;
  }
  
  json  = TRI_JsonFile(TRI_CORE_MEM_ZONE, filename, NULL);
  TRI_FreeString(TRI_CORE_MEM_ZONE, filename);

  if (! TRI_IsArrayJson(json)) {
    if (json != NULL) {
      TRI_FreeJson(TRI_CORE_MEM_ZONE, json);
    }

    return TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION;
  }

  res = TRI_ERROR_NO_ERROR;

  if (config->_endpoint != NULL) {
    TRI_FreeString(TRI_CORE_MEM_ZONE, config->_endpoint);
    config->_endpoint = NULL;
  }
  if (config->_database != NULL) {
    TRI_FreeString(TRI_CORE_MEM_ZONE, config->_database);
    config->_database = NULL;
  }
  if (config->_username != NULL) {
    TRI_FreeString(TRI_CORE_MEM_ZONE, config->_username);
    config->_username = NULL;
  }
  if (config->_password != NULL) {
    TRI_FreeString(TRI_CORE_MEM_ZONE, config->_password);
    config->_password = NULL;
  }

  // read the endpoint
  value = TRI_LookupArrayJson(json, "endpoint");

  if (! TRI_IsStringJson(value)) {
    res = TRI_ERROR_REPLICATION_INVALID_APPLIER_CONFIGURATION;
  }
  else {
    config->_endpoint = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, 
                                              value->_value._string.data, 
                                              value->_value._string.length - 1);
  }
  
  // read the database name
  value = TRI_LookupArrayJson(json, "database");

  if (! TRI_IsStringJson(value)) {
    config->_database = TRI_DuplicateStringZ(TRI_CORE_MEM_ZONE, 
                                             vocbase->_name); 
  }
  else {
    config->_database = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, 
                                              value->_value._string.data, 
                                              value->_value._string.length - 1);
  }

  // read username / password
  value = TRI_LookupArrayJson(json, "username");

  if (TRI_IsStringJson(value)) {
    config->_username = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, 
                                              value->_value._string.data, 
                                              value->_value._string.length - 1);
  }
  
  value = TRI_LookupArrayJson(json, "password");

  if (TRI_IsStringJson(value)) {
    config->_password = TRI_DuplicateString2Z(TRI_CORE_MEM_ZONE, 
                                              value->_value._string.data, 
                                              value->_value._string.length - 1);
  }

  value = TRI_LookupArrayJson(json, "requestTimeout");

  if (TRI_IsNumberJson(value)) {
    config->_requestTimeout = value->_value._number;
  }
  
  value = TRI_LookupArrayJson(json, "connectTimeout");

  if (TRI_IsNumberJson(value)) {
    config->_connectTimeout = value->_value._number;
  }
  
  value = TRI_LookupArrayJson(json, "maxConnectRetries");

  if (TRI_IsNumberJson(value)) {
    config->_maxConnectRetries = (uint64_t) value->_value._number;
  }
  
  value = TRI_LookupArrayJson(json, "chunkSize");

  if (TRI_IsNumberJson(value)) {
    config->_chunkSize = (uint64_t) value->_value._number;
  }

  value = TRI_LookupArrayJson(json, "autoStart");

  if (TRI_IsBooleanJson(value)) {
    config->_autoStart = value->_value._boolean;
  }
  
  value = TRI_LookupArrayJson(json, "adaptivePolling");

  if (TRI_IsBooleanJson(value)) {
    config->_adaptivePolling = value->_value._boolean;
  }

  TRI_FreeJson(TRI_CORE_MEM_ZONE, json);

  return res;
}
예제 #14
0
static TRI_shape_pid_t FindNameAttributePath (TRI_shaper_t* shaper, char const* name) {
  TRI_shape_aid_t* aids;
  TRI_shape_path_t* result;
  size_t count;
  size_t len;
  size_t total;
  char* buffer;
  char* end;
  char* prev;
  char* ptr;
  void const* f;
  void const* p;

  p = TRI_LookupByKeyAssociativeSynced(&shaper->_attributePathsByName, name);
  
  if (p != NULL) {
    return ((TRI_shape_path_t const*) p)->_pid;
  }

  // create a attribute path
  len = strlen(name);

  // lock the index and check that the element is still missing
  TRI_LockMutex(&shaper->_attributePathLock);

  // if the element appeared, return the pid
  p = TRI_LookupByKeyAssociativeSynced(&shaper->_attributePathsByName, name);

  if (p != NULL) {
    TRI_UnlockMutex(&shaper->_attributePathLock);
    return ((TRI_shape_path_t const*) p)->_pid;
  }

  // split path into attribute pieces
  count = 0;
  aids = TRI_Allocate(shaper->_memoryZone, len * sizeof(TRI_shape_aid_t), false);

  if (aids == NULL) {
    TRI_UnlockMutex(&shaper->_attributePathLock);
    LOG_ERROR("out of memory in shaper");
    return 0;
  }

  buffer = ptr = TRI_DuplicateString2Z(shaper->_memoryZone, name, len);

  if (buffer == NULL) {
    TRI_UnlockMutex(&shaper->_attributePathLock);
    TRI_Free(shaper->_memoryZone, aids);
    LOG_ERROR("out of memory in shaper");
    return 0;
  }

  end = buffer + len + 1;
  prev = buffer;

  for (;  ptr < end;  ++ptr) {
    if (*ptr == '.' || *ptr == '\0') {
      *ptr = '\0';

      if (ptr != prev) {
        aids[count++] = shaper->findAttributeName(shaper, prev);
      }

      prev = ptr + 1;
    }
  }

  TRI_FreeString(shaper->_memoryZone, buffer);

  // create element
  total = sizeof(TRI_shape_path_t) + (len + 1) + (count * sizeof(TRI_shape_aid_t));
  result = TRI_Allocate(shaper->_memoryZone, total, false);

  if (result == NULL) {
    TRI_UnlockMutex(&shaper->_attributePathLock);
    TRI_Free(shaper->_memoryZone, aids);
    LOG_ERROR("out of memory in shaper");
    return 0;
  }

  result->_pid = shaper->_nextPid++;
  result->_nameLength = len + 1;
  result->_aidLength = count;

  memcpy(((char*) result) + sizeof(TRI_shape_path_t), aids, count * sizeof(TRI_shape_aid_t));
  memcpy(((char*) result) + sizeof(TRI_shape_path_t) + count * sizeof(TRI_shape_aid_t), name, len + 1);

  TRI_Free(shaper->_memoryZone, aids);

  f = TRI_InsertKeyAssociativeSynced(&shaper->_attributePathsByName, name, result);
  assert(f == NULL);

  f = TRI_InsertKeyAssociativeSynced(&shaper->_attributePathsByPid, &result->_pid, result);
  assert(f == NULL);

  // return pid
  TRI_UnlockMutex(&shaper->_attributePathLock);
  return result->_pid;
}
예제 #15
0
char* TRI_GetContextErrorAql (const char* const query,
                              const size_t queryLength,
                              const size_t line,
                              const size_t column) {
  const char* p;
  char* q;
  char* result;
  char c;
  // note: line numbers reported by bison/flex start at 1, columns start at 0
  size_t offset;
  size_t currentLine = 1;
  size_t currentColumn = 0;

  TRI_ASSERT(query);

  p = query;
  while ((c = *p)) {
    if (currentLine > line || (currentLine >= line && currentColumn >= column)) {
      break;
    }

    if (c == '\n') {
      ++p;
      ++currentLine;
      currentColumn = 0;
    }
    else if (c == '\r') {
      ++p;
      ++currentLine;
      currentColumn = 0;

      if (*p == '\n') {
        ++p;
      }
    }
    else {
      ++currentColumn;
      ++p;
    }
  }

  // p is pointing at the position in the query the parse error occurred at
  TRI_ASSERT(p >= query);

  offset = (size_t) (p - query);

  if (queryLength < offset + SNIPPET_LENGTH) {
    return TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, query + offset, queryLength - offset);
  }

  q = result = static_cast<char*>(TRI_Allocate(TRI_UNKNOWN_MEM_ZONE,
                       SNIPPET_LENGTH + strlen(SNIPPET_SUFFIX) + 1, false));

  if (result == NULL) {
    // out of memory
    return NULL;
  }

  // copy query part
  memcpy(q, query + offset, SNIPPET_LENGTH);
  q += SNIPPET_LENGTH;

  // copy ...
  memcpy(q, SNIPPET_SUFFIX, strlen(SNIPPET_SUFFIX));
  q += strlen(SNIPPET_SUFFIX);

  *q = '\0';

  return result;
}
예제 #16
0
static void PatchVariables (TRI_aql_statement_walker_t* const walker) {
  TRI_aql_context_t* context = ((aql_optimiser_t*) walker->_data)->_context;
  TRI_vector_pointer_t* ranges;
  size_t i, n;

  ranges = TRI_GetCurrentRangesStatementWalkerAql(walker);
  if (ranges == NULL) {
    // no ranges defined, exit early
    return;
  }

  // iterate over all ranges found
  n = ranges->_length;
  for (i = 0; i < n; ++i) {
    TRI_aql_field_access_t* fieldAccess;
    TRI_aql_variable_t* variable;
    TRI_aql_node_t* definingNode;
    TRI_aql_node_t* expressionNode;
    char* variableName;
    size_t scopeCount;
    bool isReference;

    fieldAccess = (TRI_aql_field_access_t*) TRI_AtVectorPointer(ranges, i);
    assert(fieldAccess);
    assert(fieldAccess->_fullName);
    assert(fieldAccess->_variableNameLength > 0);

    variableName = TRI_DuplicateString2Z(TRI_UNKNOWN_MEM_ZONE, fieldAccess->_fullName, fieldAccess->_variableNameLength);
    if (variableName == NULL) {
      // out of memory!
      TRI_SetErrorContextAql(context, TRI_ERROR_OUT_OF_MEMORY, NULL);
      return;
    }

    isReference = (fieldAccess->_type == TRI_AQL_ACCESS_REFERENCE);

    variable = TRI_GetVariableStatementWalkerAql(walker, variableName, &scopeCount);
    TRI_FreeString(TRI_UNKNOWN_MEM_ZONE, variableName);

    if (variable == NULL) {
      continue;
    }

    if (isReference && scopeCount > 0) {
      // unfortunately, the referenced variable is in an outer scope, so we cannot use it
      continue;
    }

    // note: we must not modify outer variables of subqueries 

    // get the node that defines the variable
    definingNode = variable->_definingNode;

    assert(definingNode != NULL);

    expressionNode = NULL;
    switch (definingNode->_type) {
      case TRI_AQL_NODE_LET:
        expressionNode = TRI_AQL_NODE_MEMBER(definingNode, 1);
        break;
      case TRI_AQL_NODE_FOR:
        expressionNode = TRI_AQL_NODE_MEMBER(definingNode, 1);
        break;
      default: {
      }
    }

    if (expressionNode != NULL) {
      if (expressionNode->_type == TRI_AQL_NODE_FCALL) {
        // the defining node is a function call
        // get the function name
        TRI_aql_function_t* function = TRI_AQL_NODE_DATA(expressionNode);

        if (function->optimise != NULL) {
          // call the function's optimise callback
          function->optimise(expressionNode, context, fieldAccess);
        }
      }

      if (expressionNode->_type == TRI_AQL_NODE_COLLECTION) {
        TRI_aql_collection_hint_t* hint = (TRI_aql_collection_hint_t*) (TRI_AQL_NODE_DATA(expressionNode));

        // set new value
        hint->_ranges = TRI_AddAccessAql(context, hint->_ranges, fieldAccess);
      }
    }
  } 
}