bool TRI_ExcludeCollectionReplication (const char* name) {
  if (name == nullptr) {
    // name invalid
    return true;
  }

  if (*name != '_') {
    // all regular collections are included
    return false;
  }

  if (TRI_EqualString(name, TRI_COL_NAME_REPLICATION) ||
      TRI_EqualString(name, TRI_COL_NAME_TRANSACTION) ||
      TRI_EqualString(name, TRI_COL_NAME_USERS) ||
      TRI_IsPrefixString(name, TRI_COL_NAME_STATISTICS) ||
      TRI_EqualString(name, "_aal") ||
      TRI_EqualString(name, "_configuration") ||
      TRI_EqualString(name, "_cluster_kickstarter_plans") ||
      TRI_EqualString(name, "_fishbowl") ||
      TRI_EqualString(name, "_modules") ||
      TRI_EqualString(name, "_routing")) {
    // these system collections will be excluded
    return true;
  }

  return false;
}
Beispiel #2
0
TRI_json_t* TRI_LookupArrayJson (const TRI_json_t* const object, char const* name) {
  size_t i, n;

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

  TRI_ASSERT(object->_type == TRI_JSON_ARRAY);
  TRI_ASSERT(name != NULL);

  n = object->_value._objects._length;

  for (i = 0;  i < n;  i += 2) {
    TRI_json_t* key;

    key = (TRI_json_t*) TRI_AtVector(&object->_value._objects, i);

    if (! IsString(key)) {
      continue;
    }

    if (TRI_EqualString(key->_value._string.data, name)) {
      return (TRI_json_t*) TRI_AtVector(&object->_value._objects, i + 1);
    }
  }

  return NULL;
}
static bool EqualName (TRI_associative_pointer_t* array, 
                       void const* key, 
                       void const* element) {
  TRI_aql_function_t* function = (TRI_aql_function_t*) element;

  return TRI_EqualString(key, function->_externalName);
}
Beispiel #4
0
bool TRI_EqualVariableAql (TRI_associative_pointer_t* array, 
                           void const* key, 
                           void const* element) {
  TRI_aql_variable_t* variable = (TRI_aql_variable_t*) element;

  return TRI_EqualString(key, variable->_name);
}
bool TRI_EqualBindParameterAql (TRI_associative_pointer_t* array,
                                void const* key,
                                void const* element) {
  TRI_aql_bind_parameter_t* parameter = (TRI_aql_bind_parameter_t*) element;

  return TRI_EqualString(key, parameter->_name);
}
Beispiel #6
0
TRI_json_t* TRI_LookupArrayJson (TRI_json_t* object, char const* name) {
  size_t n;
  size_t i;

  assert(object->_type == TRI_JSON_ARRAY);
  assert(name);

  n = object->_value._objects._length;

  for (i = 0;  i < n;  i += 2) {
    TRI_json_t* key;

    key = TRI_AtVector(&object->_value._objects, i);

    if (key->_type != TRI_JSON_STRING) {
      continue;
    }

    if (TRI_EqualString(key->_value._string.data, name)) {
      return TRI_AtVector(&object->_value._objects, i + 1);
    }
  }

  return NULL;
}
bool TRI_ExcludeCollectionReplication(char const* name, bool includeSystem) {
    if (name == nullptr) {
        // name invalid
        return true;
    }

    if (*name != '_') {
        // all regular collections are included
        return false;
    }

    if (!includeSystem) {
        // do not include any system collections
        return true;
    }

    if (TRI_IsPrefixString(name, "_statistics") ||
            TRI_EqualString(name, "_apps") ||
            TRI_EqualString(name, "_configuration") ||
            TRI_EqualString(name, "_cluster_kickstarter_plans") ||
            TRI_EqualString(name, "_foxxlog") || TRI_EqualString(name, "_jobs") ||
            TRI_EqualString(name, "_queues") || TRI_EqualString(name, "_sessions")) {
        // these system collections will always be excluded
        return true;
    }

    return false;
}
Beispiel #8
0
static bool EqualNameKeyAttributePath (TRI_associative_synced_t* array, void const* key, void const* element) {
  char const* k;
  char const* e;
  TRI_shape_path_t const* ee;

  k = (char const*) key;
  e = (char const*) element;
  ee = (TRI_shape_path_t const*) element;

  return TRI_EqualString(k,e + sizeof(TRI_shape_path_t) + ee->_aidLength * sizeof(TRI_shape_aid_t));
}
TRI_aql_collection_t* TRI_GetCollectionAql (const TRI_aql_context_t* const context,
                                            const char* const collectionName) {
  size_t i, n;

  assert(context);

  n = context->_collections._length;
  for (i = 0; i < n; ++i) {
    TRI_aql_collection_t* col = (TRI_aql_collection_t*) TRI_AtVectorPointer(&context->_collections, i);

    if (TRI_EqualString(col->_name, collectionName)) {
      return col;
    }
  }

  return NULL;
}
Beispiel #10
0
bool TRI_DeleteArrayJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name) {
  size_t n;
  size_t i;

  TRI_ASSERT(object->_type == TRI_JSON_ARRAY);
  TRI_ASSERT(name);

  n = object->_value._objects._length;

  for (i = 0;  i < n;  i += 2) {
    TRI_json_t* key;

    key = (TRI_json_t*) TRI_AtVector(&object->_value._objects, i);

    if (! IsString(key)) {
      continue;
    }

    if (TRI_EqualString(key->_value._string.data, name)) {
      TRI_json_t* old;

      // remove key
      old = (TRI_json_t*) TRI_AtVector(&object->_value._objects, i);
      if (old != NULL) {
        TRI_DestroyJson(zone, old);
      }
      TRI_RemoveVector(&object->_value._objects, i);

      // remove value
      old = (TRI_json_t*) TRI_AtVector(&object->_value._objects, i);
      if (old != NULL) {
        TRI_DestroyJson(zone, old);
      }
      TRI_RemoveVector(&object->_value._objects, i);

      return true;
    }
  }

  return false;
}
Beispiel #11
0
bool TRI_ReplaceArrayJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name, TRI_json_t* replacement) {
  size_t n;
  size_t i;

  TRI_ASSERT(object->_type == TRI_JSON_ARRAY);
  TRI_ASSERT(name);

  n = object->_value._objects._length;

  for (i = 0;  i < n;  i += 2) {
    TRI_json_t* key;

    key = (TRI_json_t*) TRI_AtVector(&object->_value._objects, i);

    if (! IsString(key)) {
      continue;
    }

    if (TRI_EqualString(key->_value._string.data, name)) {
      TRI_json_t copy;

      // retrieve the old element
      TRI_json_t* old = (TRI_json_t*) TRI_AtVector(&object->_value._objects, i + 1);
      if (old != NULL) {
        TRI_DestroyJson(zone, old);
      }

      TRI_CopyToJson(zone, &copy, replacement);
      TRI_SetVector(&object->_value._objects, i + 1, &copy);
      return true;
    }
  }

  // object not found in array, now simply add it
  TRI_Insert2ArrayJson(zone, object, name, replacement);

  return false;
}
Beispiel #12
0
bool TRI_DeleteObjectJson (TRI_memory_zone_t* zone, TRI_json_t* object, char const* name) {
  TRI_ASSERT(object->_type == TRI_JSON_OBJECT);
  TRI_ASSERT(name != nullptr);

  size_t const n = TRI_LengthVector(&object->_value._objects);

  for (size_t i = 0;  i < n;  i += 2) {
    TRI_json_t* key = static_cast<TRI_json_t*>(TRI_AtVector(&object->_value._objects, i));

    if (! IsString(key)) {
      continue;
    }

    if (TRI_EqualString(key->_value._string.data, name)) {
      // remove key
      TRI_json_t* old = static_cast<TRI_json_t*>(TRI_AtVector(&object->_value._objects, i));

      if (old != nullptr) {
        TRI_DestroyJson(zone, old);
      }

      TRI_RemoveVector(&object->_value._objects, i);

      // remove value
      old = static_cast<TRI_json_t*>(TRI_AtVector(&object->_value._objects, i));

      if (old != nullptr) {
        TRI_DestroyJson(zone, old);
      }

      TRI_RemoveVector(&object->_value._objects, i);

      return true;
    }
  }

  return false;
}
Beispiel #13
0
bool TRI_BooleanString (char const* str) {
  if (TRI_CaseEqualString(str, "true")) {
    return true;
  }
  
  if (TRI_CaseEqualString(str, "yes")) {
    return true;
  }
  
  if (TRI_CaseEqualString(str, "on")) {
    return true;
  }
  
  if (TRI_CaseEqualString(str, "y")) {
    return true;
  }
  
  if (TRI_EqualString(str, "1")) {
    return true;
  }

  return false;
}
Beispiel #14
0
bool TRI_ReplaceObjectJson (TRI_memory_zone_t* zone, 
                            TRI_json_t* object, 
                            char const* name, 
                            TRI_json_t const* replacement) {
  TRI_ASSERT(object->_type == TRI_JSON_OBJECT);
  TRI_ASSERT(name != nullptr);

  size_t const n = TRI_LengthVector(&object->_value._objects);

  for (size_t i = 0;  i < n;  i += 2) {
    TRI_json_t* key = static_cast<TRI_json_t*>(TRI_AtVector(&object->_value._objects, i));

    if (! IsString(key)) {
      continue;
    }

    if (TRI_EqualString(key->_value._string.data, name)) {
      // retrieve the old element
      TRI_json_t* old = static_cast<TRI_json_t*>(TRI_AtVector(&object->_value._objects, i + 1));

      if (old != nullptr) {
        TRI_DestroyJson(zone, old);
      }

      TRI_json_t copy;
      TRI_CopyToJson(zone, &copy, replacement);
      TRI_SetVector(&object->_value._objects, i + 1, &copy);
      return true;
    }
  }

  // object not found in array, now simply add it
  TRI_Insert2ObjectJson(zone, object, name, replacement);

  return false;
}
Beispiel #15
0
std::string arangodb::options::EnvironmentTranslator(std::string const& value) {
    if (value.empty()) {
        return value;
    }

    char const* p = value.c_str();
    char const* e = p + value.size();

    std::string result;

    for (char const* q = p;  q < e;  q++) {
        if (*q == '@') {
            q++;

            if (*q == '@') {
                result.push_back('@');
            }
            else {
                char const* t = q;

                for (;  q < e && *q != '@';  q++) ;

                if (q < e) {
                    std::string k = std::string(t, q);
                    char* v = getenv(k.c_str());
                    std::string vv;

                    if (v != nullptr && *v == '\0') {
                        v = nullptr;
                    }

                    if (v == nullptr) {
#if _WIN32
                        if (TRI_EqualString(k.c_str(), "ROOTDIR")) {
                            vv = TRI_LocateInstallDirectory();

                            if (! vv.empty()) {
                                char c = *(vv.rbegin());

                                if (c == TRI_DIR_SEPARATOR_CHAR || c == '/') {
                                    vv.pop_back();
                                }
                            }
                        }
#endif
                    }
                    else {
                        vv = v;
                    }

                    result += vv;
                }
                else {
                    result += std::string(t - 1);
                }
            }
        }
        else {
            result.push_back(*q);
        }
    }

    return result;
}
Beispiel #16
0
int TRI_LoadCollectionInfo (char const* path, TRI_col_info_t* parameter) {
  TRI_json_t* json;
  char* filename;
  char* error = NULL;
  size_t i;
  size_t n;

  memset(parameter, 0, sizeof(TRI_col_info_t));

  // find parameter file
  filename = TRI_Concatenate2File(path, TRI_COL_PARAMETER_FILE);
  if (filename == NULL) {
    LOG_ERROR("cannot load parameter info for collection '%s', out of memory", path);

    return TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY);
  }

  if (! TRI_ExistsFile(filename)) {
    TRI_FreeString(TRI_CORE_MEM_ZONE, filename);
    return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE);
  }

  json = TRI_JsonFile(TRI_UNKNOWN_MEM_ZONE, filename, &error);

  if (json == NULL) {
    if (error != NULL) {
      LOG_ERROR("cannot open '%s', parameter block not readable: %s", filename, error);
      TRI_FreeString(TRI_CORE_MEM_ZONE, error);
    }
    else {
      LOG_ERROR("cannot open '%s', parameter block not readable", filename);
    }
    TRI_FreeString(TRI_CORE_MEM_ZONE, filename);

    return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE);
  }

  if (json->_type != TRI_JSON_ARRAY) {
    LOG_ERROR("cannot open '%s', file does not contain a json array", filename);
    TRI_FreeString(TRI_CORE_MEM_ZONE, filename);

    return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_PARAMETER_FILE);
  }

  TRI_FreeString(TRI_CORE_MEM_ZONE, filename);

  // convert json
  n = json->_value._objects._length;

  for (i = 0;  i < n;  i += 2) {
    TRI_json_t* key;
    TRI_json_t* value;

    key = TRI_AtVector(&json->_value._objects, i);
    value = TRI_AtVector(&json->_value._objects, i + 1);

    if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_NUMBER) {
      if (TRI_EqualString(key->_value._string.data, "version")) {
        parameter->_version = value->_value._number;
      }
      else if (TRI_EqualString(key->_value._string.data, "type")) {
        parameter->_type = value->_value._number;
      }
      else if (TRI_EqualString(key->_value._string.data, "cid")) {
        parameter->_cid = value->_value._number;
      }
      else if (TRI_EqualString(key->_value._string.data, "maximalSize")) {
        parameter->_maximalSize = value->_value._number;
      }
    }
    else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_STRING) {
      if (TRI_EqualString(key->_value._string.data, "name")) {
        TRI_CopyString(parameter->_name, value->_value._string.data, sizeof(parameter->_name));

        parameter->_isSystem = TRI_IsSystemCollectionName(parameter->_name);
      }
    }
    else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_BOOLEAN) {
      if (TRI_EqualString(key->_value._string.data, "deleted")) {
        parameter->_deleted = value->_value._boolean;
      }
      else if (TRI_EqualString(key->_value._string.data, "isVolatile")) {
        parameter->_isVolatile = value->_value._boolean;
      }
      else if (TRI_EqualString(key->_value._string.data, "waitForSync")) {
        parameter->_waitForSync = value->_value._boolean;
      }
    }
    else if (key->_type == TRI_JSON_STRING && value->_type == TRI_JSON_ARRAY) {
      if (TRI_EqualString(key->_value._string.data, "keyOptions")) {
        parameter->_keyOptions = TRI_CopyJson(TRI_UNKNOWN_MEM_ZONE, value);
      }
    }
  }

  TRI_FreeJson(TRI_UNKNOWN_MEM_ZONE, json);
  return TRI_ERROR_NO_ERROR;
}
Beispiel #17
0
TRI_aql_index_t* TRI_DetermineIndexAql (TRI_aql_context_t* const context,
                                        const TRI_vector_pointer_t* const availableIndexes,
                                        const char* const collectionName,
                                        const TRI_vector_pointer_t* candidates) {
  TRI_aql_index_t* picked = NULL;
  TRI_vector_pointer_t matches;
  size_t i, n;
  
  TRI_InitVectorPointer(&matches, TRI_UNKNOWN_MEM_ZONE);

  assert(context);
  assert(collectionName);
  assert(candidates);

  n = availableIndexes->_length;

  for (i = 0; i < n; ++i) {
    TRI_index_t* idx = (TRI_index_t*) availableIndexes->_buffer[i];
    size_t numIndexFields;
    bool lastTypeWasExact;
    size_t j;

    if (! CanUseIndex(idx)) {
      continue;
    }

    LogIndexString("checking", idx, collectionName);

    TRI_ClearVectorPointer(&matches);

    lastTypeWasExact = true;
    numIndexFields = idx->_fields._length;
    
    // now loop over all index fields, from left to right
    // index field order is important because skiplists can be used with leftmost prefixes as well,
    // but not with rightmost prefixes
    for (j = 0; j < numIndexFields; ++j) {
      char* indexedFieldName;
      char* fieldName;
      size_t k;

      indexedFieldName = idx->_fields._buffer[j];

      if (indexedFieldName == NULL) {
        continue;
      }

      // now loop over all candidates
      for (k = 0; k < candidates->_length; ++k) {
        TRI_aql_field_access_t* candidate = (TRI_aql_field_access_t*) TRI_AtVectorPointer(candidates, k);

        if (candidate->_type == TRI_AQL_ACCESS_IMPOSSIBLE ||
            candidate->_type == TRI_AQL_ACCESS_ALL) {
          // wrong index type, doesn't help us at all
          continue;
        }

        fieldName = candidate->_fullName + candidate->_variableNameLength + 1;

        if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX) {
          // primary index key names must be treated differently. _id and _key are the same
          if (! TRI_EqualString("_id", fieldName) && ! TRI_EqualString(TRI_VOC_ATTRIBUTE_KEY, fieldName)) {
            continue;
          }
        }
        else if (idx->_type == TRI_IDX_TYPE_EDGE_INDEX) {
          // edge index key names must be treated differently. _from and _to can be used independently
          if (! TRI_EqualString(TRI_VOC_ATTRIBUTE_FROM, fieldName) &&
              ! TRI_EqualString(TRI_VOC_ATTRIBUTE_TO, fieldName)) {
            continue;
          }
        }
        else if (! TRI_EqualString(indexedFieldName, fieldName)) {
          // different attribute, doesn't help
          continue;
        }

        // attribute is used in index

        if (idx->_type == TRI_IDX_TYPE_PRIMARY_INDEX || idx->_type == TRI_IDX_TYPE_EDGE_INDEX) {
          if (! IsExactCandidate(candidate)) {
            // wrong access type for primary index
            continue;
          }

          TRI_PushBackVectorPointer(&matches, candidate);
        }

        else if (idx->_type == TRI_IDX_TYPE_HASH_INDEX) {
          if (! IsExactCandidate(candidate)) {
            // wrong access type for hash index
            continue;
          }

          if (candidate->_type == TRI_AQL_ACCESS_LIST && numIndexFields != 1) {
            // we found a list, but the index covers multiple attributes. that means we cannot use list access
            continue;
          }

          TRI_PushBackVectorPointer(&matches, candidate);
        }

        else if (idx->_type == TRI_IDX_TYPE_BITARRAY_INDEX) {
          if (! IsExactCandidate(candidate)) {
            // wrong access type for hash index
            continue;
          }

          if (candidate->_type == TRI_AQL_ACCESS_LIST) {
            // we found a list, but the index covers multiple attributes. that means we cannot use list access
            continue;
          }

          TRI_PushBackVectorPointer(&matches, candidate);
        }

        else if (idx->_type == TRI_IDX_TYPE_SKIPLIST_INDEX) {
          bool candidateIsExact;

          if (candidate->_type != TRI_AQL_ACCESS_EXACT &&
              candidate->_type != TRI_AQL_ACCESS_LIST &&
              candidate->_type != TRI_AQL_ACCESS_RANGE_SINGLE &&
              candidate->_type != TRI_AQL_ACCESS_RANGE_DOUBLE &&
              candidate->_type != TRI_AQL_ACCESS_REFERENCE) {
            // wrong access type for skiplists
            continue;
          }

          if (candidate->_type == TRI_AQL_ACCESS_LIST && numIndexFields != 1) {
            // we found a list, but the index covers multiple attributes. that means we cannot use list access
            continue;
          }

          candidateIsExact = IsExactCandidate(candidate);

          if ((candidateIsExact && ! lastTypeWasExact) ||
              (! candidateIsExact && ! lastTypeWasExact)) {
            // if we already had a range query, we cannot check for equality after that
            // if we already had a range query, we cannot check another range after that
            continue;
          }

          if (candidate->_type == TRI_AQL_ACCESS_RANGE_SINGLE) {
            // range type. check if the compare value is a list or an object
            TRI_json_t* value = candidate->_value._singleRange._value;

            if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) {
              // list or object, we cannot use this for comparison in a skiplist
              continue;
            }
          }
          else if (candidate->_type == TRI_AQL_ACCESS_RANGE_DOUBLE) {
            // range type. check if the compare value is a list or an object
            TRI_json_t* value = candidate->_value._between._lower._value;

            if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) {
              // list or object, we cannot use this for comparison in a skiplist
              continue;
            }
            
            value = candidate->_value._between._upper._value;
            if (TRI_IsListJson(value) || TRI_IsArrayJson(value)) {
              // list or object, we cannot use this for comparison in a skiplist
              continue;
            }
          }

          lastTypeWasExact = candidateIsExact;

          TRI_PushBackVectorPointer(&matches, candidate);
        }
      }

      // finished iterating over all candidates

      if (matches._length != j + 1) {
        // we already have picked less candidate fields than we should
        break;
      }
    }

    if (matches._length < 1) {
      // nothing found
      continue;
    }

    // we now do or don't have an index candidate in the matches vector
    if (matches._length < numIndexFields && 
        TRI_NeedsFullCoverageIndex(idx->_type)) {
      // the matches vector does not fully cover the indexed fields, but the index requires it
      continue;
    }

    // if we can use the primary index, we'll use it
    picked = PickIndex(context, picked, idx, &matches);
  }

  TRI_DestroyVectorPointer(&matches);

  if (picked) {
    LogIndexString("using", picked->_idx, collectionName);
  }

  return picked;
}
bool IsEqualElementElement (TRI_associative_pointer_t* a, void const* l, void const* r) {
  data_container_s* left = (data_container_s*) l;
  data_container_s* right = (data_container_s*) r;

  return TRI_EqualString(left->key, right->key);
}
Beispiel #19
0
static bool EqualKeyCollectionName (TRI_associative_pointer_t* array, void const* key, void const* element) {
  char const* k = (char const*) key;
  TRI_vocbase_col_t const* e = element;

  return TRI_EqualString(k, e->_name);
}
Beispiel #20
0
bool TRI_CheckAuthenticationAuthInfo (char const* username,
                                      char const* password) {
  TRI_vocbase_auth_t* auth;
  bool res;
  char* hex;
  char* sha256;
  size_t hexLen;
  size_t len;
  size_t sha256Len;

  assert(DefaultAuthInfo);

  // look up username
  TRI_ReadLockReadWriteLock(&DefaultAuthInfo->_authInfoLock);
  auth = TRI_LookupByKeyAssociativePointer(&DefaultAuthInfo->_authInfo, username);

  if (auth == NULL || ! auth->_active) {
    TRI_ReadUnlockReadWriteLock(&DefaultAuthInfo->_authInfoLock);
    return false;
  }

  // convert password
  res = false;

  if (TRI_IsPrefixString(auth->_password, "$1$")) {
    if (strlen(auth->_password) < 12 || auth->_password[11] != '$') {
      LOG_WARNING("found corrupted password for user '%s'", username);
    }
    else {
      char* salted;

      len = 8 + strlen(password);
      salted = TRI_Allocate(TRI_CORE_MEM_ZONE, len + 1, false);
      memcpy(salted, auth->_password + 3, 8);
      memcpy(salted + 8, password, len - 8);
      salted[len] = '\0';

      sha256 = TRI_SHA256String(salted, len, &sha256Len);
      TRI_FreeString(TRI_CORE_MEM_ZONE, salted);

      hex = TRI_EncodeHexString(sha256, sha256Len, &hexLen);
      TRI_FreeString(TRI_CORE_MEM_ZONE, sha256);

      LOG_DEBUG("found active user '%s', expecting password '%s', got '%s'",
                username,
                auth->_password + 12,
                hex);

      res = TRI_EqualString(auth->_password + 12, hex);
      TRI_FreeString(TRI_CORE_MEM_ZONE, hex);
    }
  }
  else {
    len = strlen(password);
    sha256 = TRI_SHA256String(password, len, &sha256Len);

    hex = TRI_EncodeHexString(sha256, sha256Len, &hexLen);
    TRI_FreeString(TRI_CORE_MEM_ZONE, sha256);

    LOG_DEBUG("found active user '%s', expecting password '%s', got '%s'",
              username,
              auth->_password + 12,
              hex);

    res = TRI_EqualString(auth->_password, hex);
    TRI_FreeString(TRI_CORE_MEM_ZONE, hex);
  }

  TRI_ReadUnlockReadWriteLock(&DefaultAuthInfo->_authInfoLock);

  return res;
}
Beispiel #21
0
bool TRI_EqualStringKeyAssociativePointer (TRI_associative_pointer_t* array,
                                           void const* key,
                                           void const* element) {
  return TRI_EqualString((char*) key, (char*) element);
}
static void OptimisePaths (const TRI_aql_node_t* const fcallNode,
                           TRI_aql_context_t* const context,
                           TRI_aql_field_access_t* fieldAccess) {
  TRI_aql_node_t* args;
  TRI_aql_node_t* vertexCollection;
  TRI_aql_node_t* edgeCollection;
  TRI_aql_node_t* direction;
  char* directionValue;
  char* name;
  size_t n;

  args = TRI_AQL_NODE_MEMBER(fcallNode, 0);

  if (args == NULL) {
    return;
  }

  vertexCollection = TRI_AQL_NODE_MEMBER(args, 0);
  edgeCollection = TRI_AQL_NODE_MEMBER(args, 1);
  direction = TRI_AQL_NODE_MEMBER(args, 2);

  assert(vertexCollection);
  assert(edgeCollection);
  assert(direction);
  assert(fieldAccess);

  n = strlen(fieldAccess->_fullName);
  name = fieldAccess->_fullName + fieldAccess->_variableNameLength;

  directionValue = TRI_AQL_NODE_STRING(direction);
  // try to optimise the vertex collection access
  if (TRI_EqualString(directionValue, "outbound")) {
    CheckPathRestriction(fieldAccess, context, vertexCollection, ".source.", name, n);
  }
  else if (TRI_EqualString(directionValue, "inbound")) {
    CheckPathRestriction(fieldAccess, context, vertexCollection, ".source.", name, n);
  }
  else if (TRI_EqualString(directionValue, "any")) {
    // "any" cannot be optimised sanely becuase the conditions would be AND-combined
    // (but for "any", we'd need them OR-combined)

    // CheckPathRestriction(fieldAccess, context, vertexCollection, ".source.", name, n);
    // CheckPathRestriction(fieldAccess, context, vertexCollection, ".destination.", name, n);
  }

  // check if we have a filter on LENGTH(edges)
  if (args->_members._length <= 4 &&
      TRI_EqualString(name, ".edges.LENGTH()")) {
    // length restriction, can only be applied if length parameters are not already set
    TRI_json_t* value;
    double minValue = 0.0;
    double maxValue = 0.0;
    bool useMin = false;
    bool useMax = false;

    if (fieldAccess->_type == TRI_AQL_ACCESS_EXACT) {
      value = fieldAccess->_value._value;

      if (value != NULL && value->_type == TRI_JSON_NUMBER) {
        // LENGTH(p.edges) == const
        minValue = maxValue = value->_value._number;
        useMin = useMax = true;
      }
    }
    else if (fieldAccess->_type == TRI_AQL_ACCESS_RANGE_SINGLE) {
      value = fieldAccess->_value._singleRange._value;

      if (value != NULL && value->_type == TRI_JSON_NUMBER) {
        // LENGTH(p.edges) operator const
        if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_LOWER_INCLUDED) {
          minValue = value->_value._number;
          useMin = true;
        }
        else if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_UPPER_INCLUDED) {
          maxValue = value->_value._number;
          useMax = true;
        }
        else if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_LOWER_EXCLUDED) {
          if ((double) ((int) value->_value._number) == value->_value._number) {
            minValue = value->_value._number + 1.0;
            useMin = true;
          }
        }
        else if (fieldAccess->_value._singleRange._type == TRI_AQL_RANGE_UPPER_EXCLUDED) {
          if ((double) ((int) value->_value._number) == value->_value._number) {
            maxValue = value->_value._number - 1.0;
            useMax = true;
          }
        }
      }
    }
    else if (fieldAccess->_type == TRI_AQL_ACCESS_RANGE_DOUBLE) {
      // LENGTH(p.edges) > const && LENGTH(p.edges) < const
      value = fieldAccess->_value._between._lower._value;

      if (value != NULL && value->_type == TRI_JSON_NUMBER) {
        if (fieldAccess->_value._between._lower._type == TRI_AQL_RANGE_LOWER_INCLUDED) {
          minValue = value->_value._number;
          useMin = true;
        }
        else if (fieldAccess->_value._between._lower._type == TRI_AQL_RANGE_LOWER_EXCLUDED) {
          if ((double) ((int) value->_value._number) == value->_value._number) {
            minValue = value->_value._number + 1.0;
            useMin = true;
          }
        }
      }

      value = fieldAccess->_value._between._upper._value;

      if (value != NULL && value->_type == TRI_JSON_NUMBER) {
        if (fieldAccess->_value._between._upper._type == TRI_AQL_RANGE_UPPER_INCLUDED) {
          maxValue = value->_value._number;
          useMax = true;
        }
        else if (fieldAccess->_value._between._upper._type == TRI_AQL_RANGE_UPPER_EXCLUDED) {
          if ((double) ((int) value->_value._number) == value->_value._number) {
            maxValue = value->_value._number - 1.0;
            useMax = true;
          }
        }
      }
    }

    if (useMin || useMax) {
      TRI_aql_node_t* argNode;

      // minLength and maxLength are parameters 5 & 6
      // add as many null value nodes as are missing
      while (args->_members._length < 4) {
        argNode = TRI_CreateNodeValueNullAql(context);
        if (argNode) {
          TRI_PushBackVectorPointer(&args->_members, (void*) argNode);
        }
      }

      // add min and max values to the function call argument list
      argNode = TRI_CreateNodeValueIntAql(context, useMin ? (int64_t) minValue : (int64_t) 0);
      if (argNode) {
        // min value node
        TRI_PushBackVectorPointer(&args->_members, (void*) argNode);

        argNode = TRI_CreateNodeValueIntAql(context, useMax ? (int64_t) maxValue : (int64_t) (1024 * 1024));
        if (argNode) {
          // max value node
          TRI_PushBackVectorPointer(&args->_members, (void*) argNode);
        }
      }
    }
  }
}
Beispiel #23
0
static void OptimisePaths (const TRI_aql_node_t* const fcallNode,
                           TRI_aql_context_t* const context,
                           TRI_aql_field_access_t* fieldAccess) {
  TRI_aql_collection_hint_t* hint;
  TRI_aql_node_t* args;
  TRI_aql_node_t* vertexCollection;
  TRI_aql_node_t* edgeCollection;
  TRI_aql_node_t* direction;
  char* directionValue;
  char* name;
  const char* lookFor;
  size_t len;
  size_t n;
  
  args = TRI_AQL_NODE_MEMBER(fcallNode, 0);

  if (args == NULL) {
    return;
  }

  vertexCollection = TRI_AQL_NODE_MEMBER(args, 0);
  edgeCollection = TRI_AQL_NODE_MEMBER(args, 1);
  direction = TRI_AQL_NODE_MEMBER(args, 2);

  assert(vertexCollection);
  assert(edgeCollection);
  assert(direction);
  assert(fieldAccess);

  n = strlen(fieldAccess->_fullName);
  name = fieldAccess->_fullName + fieldAccess->_variableNameLength;

  directionValue = TRI_AQL_NODE_STRING(direction);

  // try to optimise the vertex collection access
  if (TRI_EqualString(directionValue, "outbound")) {
    lookFor = ".source.";
    len = strlen(lookFor);
  }
  else if (TRI_EqualString(directionValue, "inbound")) {
    lookFor = ".destination.";
    len = strlen(lookFor);
  }
  else {
    lookFor = NULL;
    len = 0;
  }

  if (len > 0 && 
      n > fieldAccess->_variableNameLength + len && 
      memcmp((void*) lookFor, (void*) name, len) == 0) {
    // field name is collection.source.XXX, e.g. users.source._id
    LOG_DEBUG("optimising PATHS() field access %s", fieldAccess->_fullName);
 
    // we can now modify this fieldaccess in place to collection.XXX, e.g. users._id
    // copy trailing \0 byte as well
    memmove(name, name + len - 1, n - fieldAccess->_variableNameLength - len + 2);
    
    // attach the modified fieldaccess to the collection
    hint = (TRI_aql_collection_hint_t*) (TRI_AQL_NODE_DATA(vertexCollection));
    hint->_ranges = TRI_AddAccessAql(context, hint->_ranges, fieldAccess);
  }
}
bool IsEqualKeyElement (TRI_associative_pointer_t* a, void const* k, void const* r) {
  data_container_s* element = (data_container_s*) r;

  return TRI_EqualString((char*) k, element->key);
}