1
0
Fork 0

Merge branch 'devel' of github.com:arangodb/arangodb into devel

This commit is contained in:
Dan Larkin 2017-05-23 10:16:58 -04:00
commit fa2441cc96
30 changed files with 714 additions and 447 deletions

View File

@ -774,7 +774,7 @@ if test -n "${TARGET_DIR}"; then
${SED} -e "s/.*optimized;//" -e "s/;.*//" -e "s;/lib.*lib;;" -e "s;\([a-zA-Z]*\):;/cygdrive/\1;" ${SED} -e "s/.*optimized;//" -e "s/;.*//" -e "s;/lib.*lib;;" -e "s;\([a-zA-Z]*\):;/cygdrive/\1;"
) )
DLLS=$(find "${SSLDIR}" -name \*.dll |grep -i release) DLLS=$(find "${SSLDIR}" -name \*.dll |grep -i release)
cp "${DLLS}" "bin/${BUILD_CONFIG}" cp ${DLLS} "bin/${BUILD_CONFIG}"
cp "bin/${BUILD_CONFIG}/"* bin/ cp "bin/${BUILD_CONFIG}/"* bin/
cp "tests/${BUILD_CONFIG}/"*exe bin/ cp "tests/${BUILD_CONFIG}/"*exe bin/
fi fi

View File

@ -547,7 +547,7 @@ void Constituent::run() {
// Most recent vote // Most recent vote
{ {
std::string const aql("FOR l IN election SORT l._key DESC LIMIT 1 RETURN l"); std::string const aql("FOR l IN election SORT l._key DESC LIMIT 1 RETURN l");
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), arangodb::aql::Query query(false, _vocbase, arangodb::aql::QueryString(aql),
bindVars, nullptr, arangodb::aql::PART_MAIN); bindVars, nullptr, arangodb::aql::PART_MAIN);
auto queryResult = query.execute(_queryRegistry); auto queryResult = query.execute(_queryRegistry);

View File

@ -275,7 +275,7 @@ size_t State::removeConflicts(query_t const& transactions) { // Under MUTEX in A
stringify(idx) + "' REMOVE l IN log"); stringify(idx) + "' REMOVE l IN log");
arangodb::aql::Query query( arangodb::aql::Query query(
false, _vocbase, aql.c_str(), aql.size(), bindVars, nullptr, false, _vocbase, aql::QueryString(aql), bindVars, nullptr,
arangodb::aql::PART_MAIN); arangodb::aql::PART_MAIN);
auto queryResult = query.execute(_queryRegistry); auto queryResult = query.execute(_queryRegistry);
@ -537,7 +537,7 @@ bool State::loadCompacted() {
std::string const aql( std::string const aql(
std::string("FOR c IN compact SORT c._key DESC LIMIT 1 RETURN c")); std::string("FOR c IN compact SORT c._key DESC LIMIT 1 RETURN c"));
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars, arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
nullptr, arangodb::aql::PART_MAIN); nullptr, arangodb::aql::PART_MAIN);
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY); auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
@ -576,7 +576,7 @@ bool State::loadOrPersistConfiguration() {
std::string const aql( std::string const aql(
std::string("FOR c in configuration FILTER c._key==\"0\" RETURN c.cfg")); std::string("FOR c in configuration FILTER c._key==\"0\" RETURN c.cfg"));
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars, arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
nullptr, arangodb::aql::PART_MAIN); nullptr, arangodb::aql::PART_MAIN);
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY); auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
@ -652,7 +652,7 @@ bool State::loadRemaining() {
bindVars->close(); bindVars->close();
std::string const aql(std::string("FOR l IN log SORT l._key RETURN l")); std::string const aql(std::string("FOR l IN log SORT l._key RETURN l"));
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars, arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
nullptr, arangodb::aql::PART_MAIN); nullptr, arangodb::aql::PART_MAIN);
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY); auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
@ -755,7 +755,7 @@ bool State::compactPersisted(arangodb::consensus::index_t cind) {
std::string const aql(std::string("FOR l IN log FILTER l._key < \"") + std::string const aql(std::string("FOR l IN log FILTER l._key < \"") +
i_str.str() + "\" REMOVE l IN log"); i_str.str() + "\" REMOVE l IN log");
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), bindVars, arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql), bindVars,
nullptr, arangodb::aql::PART_MAIN); nullptr, arangodb::aql::PART_MAIN);
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY); auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
@ -785,7 +785,7 @@ bool State::removeObsolete(arangodb::consensus::index_t cind) {
std::string const aql(std::string("FOR c IN compact FILTER c._key < \"") + std::string const aql(std::string("FOR c IN compact FILTER c._key < \"") +
i_str.str() + "\" REMOVE c IN compact"); i_str.str() + "\" REMOVE c IN compact");
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql),
bindVars, nullptr, arangodb::aql::PART_MAIN); bindVars, nullptr, arangodb::aql::PART_MAIN);
auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY); auto queryResult = query.execute(QueryRegistryFeature::QUERY_REGISTRY);
@ -876,9 +876,9 @@ query_t State::allLogs() const {
std::string const comp("FOR c IN compact SORT c._key RETURN c"); std::string const comp("FOR c IN compact SORT c._key RETURN c");
std::string const logs("FOR l IN log SORT l._key RETURN l"); std::string const logs("FOR l IN log SORT l._key RETURN l");
arangodb::aql::Query compq(false, _vocbase, comp.c_str(), comp.size(), arangodb::aql::Query compq(false, _vocbase, aql::QueryString(comp),
bindVars, nullptr, arangodb::aql::PART_MAIN); bindVars, nullptr, arangodb::aql::PART_MAIN);
arangodb::aql::Query logsq(false, _vocbase, logs.c_str(), logs.size(), arangodb::aql::Query logsq(false, _vocbase, aql::QueryString(logs),
bindVars, nullptr, arangodb::aql::PART_MAIN); bindVars, nullptr, arangodb::aql::PART_MAIN);
auto compqResult = compq.execute(QueryRegistryFeature::QUERY_REGISTRY); auto compqResult = compq.execute(QueryRegistryFeature::QUERY_REGISTRY);

View File

@ -34,13 +34,19 @@ Parser::Parser(Query* query)
: _query(query), : _query(query),
_ast(query->ast()), _ast(query->ast()),
_scanner(nullptr), _scanner(nullptr),
_buffer(query->queryString()), _queryStringStart(nullptr),
_remainingLength(query->queryLength()), _buffer(nullptr),
_remainingLength(0),
_offset(0), _offset(0),
_marker(nullptr), _marker(nullptr),
_stack(), _stack(),
_isModificationQuery(false) { _isModificationQuery(false) {
_stack.reserve(4); _stack.reserve(4);
QueryString const& qs = queryString();
_queryStringStart = qs.data();
_buffer = qs.data();
_remainingLength = qs.size();
} }
/// @brief destroy the parser /// @brief destroy the parser
@ -64,9 +70,7 @@ bool Parser::configureWriteQuery(AstNode const* collectionNode,
/// @brief parse the query /// @brief parse the query
QueryResult Parser::parse(bool withDetails) { QueryResult Parser::parse(bool withDetails) {
char const* q = queryString(); if (queryString().empty() || remainingLength() == 0) {
if (q == nullptr || *q == '\0' || remainingLength() == 0) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_EMPTY); THROW_ARANGO_EXCEPTION(TRI_ERROR_QUERY_EMPTY);
} }
@ -137,7 +141,7 @@ void Parser::registerParseError(int errorCode, char const* data, int line,
TRI_ASSERT(data != nullptr); TRI_ASSERT(data != nullptr);
// extract the query string part where the error happened // extract the query string part where the error happened
std::string const region(_query->extractRegion(line, column)); std::string const region(queryString().extractRegion(line, column));
// note: line numbers reported by bison/flex start at 1, columns start at 0 // note: line numbers reported by bison/flex start at 1, columns start at 0
std::stringstream errorMessage; std::stringstream errorMessage;
@ -146,7 +150,7 @@ void Parser::registerParseError(int errorCode, char const* data, int line,
<< (column + 1); << (column + 1);
if (_query->verboseErrors()) { if (_query->verboseErrors()) {
errorMessage << std::endl << _query->queryString() << std::endl; errorMessage << std::endl << queryString() << std::endl;
// create a neat pointer to the location of the error. // create a neat pointer to the location of the error.
size_t i; size_t i;

View File

@ -73,7 +73,7 @@ class Parser {
inline void* scanner() const { return _scanner; } inline void* scanner() const { return _scanner; }
/// @brief a pointer to the start of the query string /// @brief a pointer to the start of the query string
inline char const* queryString() const { return _query->queryString(); } char const* queryStringStart() const { return _queryStringStart; }
/// @brief return the remaining length of the query string to process /// @brief return the remaining length of the query string to process
inline size_t remainingLength() const { return _remainingLength; } inline size_t remainingLength() const { return _remainingLength; }
@ -148,6 +148,10 @@ class Parser {
/// @brief peek at a temporary value from the parser's stack /// @brief peek at a temporary value from the parser's stack
void* peekStack(); void* peekStack();
private:
/// @brief a pointer to the start of the query string
QueryString const& queryString() const { return _query->queryString(); }
private: private:
/// @brief the query /// @brief the query
Query* _query; Query* _query;
@ -158,6 +162,8 @@ class Parser {
/// @brief lexer / scanner used when parsing the query (Aql/tokens.ll) /// @brief lexer / scanner used when parsing the query (Aql/tokens.ll)
void* _scanner; void* _scanner;
char const* _queryStringStart;
/// @brief currently processed part of the query string /// @brief currently processed part of the query string
char const* _buffer; char const* _buffer;

View File

@ -25,6 +25,7 @@
#include "Aql/Ast.h" #include "Aql/Ast.h"
#include "Aql/ExecutionPlan.h" #include "Aql/ExecutionPlan.h"
#include "Aql/Query.h" #include "Aql/Query.h"
#include "Aql/QueryString.h"
#include "Basics/ReadLocker.h" #include "Basics/ReadLocker.h"
#include "Basics/WriteLocker.h" #include "Basics/WriteLocker.h"
#include "VocBase/vocbase.h" #include "VocBase/vocbase.h"
@ -43,9 +44,9 @@ PlanCache::PlanCache() : _lock(), _plans() {}
PlanCache::~PlanCache() {} PlanCache::~PlanCache() {}
/// @brief lookup a plan in the cache /// @brief lookup a plan in the cache
std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash, std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase,
char const* queryString, uint64_t queryHash,
size_t queryStringLength) { QueryString const& queryString) {
READ_LOCKER(readLocker, _lock); READ_LOCKER(readLocker, _lock);
auto it = _plans.find(vocbase); auto it = _plans.find(vocbase);
@ -55,7 +56,7 @@ std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase, uint64
return std::shared_ptr<PlanCacheEntry>(); return std::shared_ptr<PlanCacheEntry>();
} }
auto it2 = (*it).second.find(hash); auto it2 = (*it).second.find(queryHash);
if (it2 == (*it).second.end()) { if (it2 == (*it).second.end()) {
// plan not found in cache // plan not found in cache
@ -68,10 +69,10 @@ std::shared_ptr<PlanCacheEntry> PlanCache::lookup(TRI_vocbase_t* vocbase, uint64
/// @brief store a plan in the cache /// @brief store a plan in the cache
void PlanCache::store( void PlanCache::store(
TRI_vocbase_t* vocbase, uint64_t hash, char const* queryString, TRI_vocbase_t* vocbase, uint64_t hash, QueryString const& queryString,
size_t queryStringLength, ExecutionPlan const* plan) { ExecutionPlan const* plan) {
auto entry = std::make_unique<PlanCacheEntry>(std::string(queryString, queryStringLength), plan->toVelocyPack(plan->getAst(), true)); auto entry = std::make_unique<PlanCacheEntry>(queryString.extract(SIZE_MAX), plan->toVelocyPack(plan->getAst(), true));
WRITE_LOCKER(writeLocker, _lock); WRITE_LOCKER(writeLocker, _lock);

View File

@ -36,6 +36,7 @@ class Builder;
namespace aql { namespace aql {
class ExecutionPlan; class ExecutionPlan;
class QueryString;
class VariableGenerator; class VariableGenerator;
struct PlanCacheEntry { struct PlanCacheEntry {
@ -60,10 +61,10 @@ class PlanCache {
public: public:
/// @brief lookup a plan in the cache /// @brief lookup a plan in the cache
std::shared_ptr<PlanCacheEntry> lookup(TRI_vocbase_t*, uint64_t, char const*, size_t); std::shared_ptr<PlanCacheEntry> lookup(TRI_vocbase_t*, uint64_t, QueryString const&);
/// @brief store a plan in the cache /// @brief store a plan in the cache
void store(TRI_vocbase_t*, uint64_t, char const*, size_t, ExecutionPlan const*); void store(TRI_vocbase_t*, uint64_t, QueryString const&, ExecutionPlan const*);
/// @brief invalidate all plans for a particular database /// @brief invalidate all plans for a particular database
void invalidate(TRI_vocbase_t*); void invalidate(TRI_vocbase_t*);

View File

@ -73,7 +73,7 @@ constexpr uint64_t DontCache = 0;
/// @brief creates a query /// @brief creates a query
Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase, Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
char const* queryString, size_t queryLength, QueryString const& queryString,
std::shared_ptr<VPackBuilder> const& bindParameters, std::shared_ptr<VPackBuilder> const& bindParameters,
std::shared_ptr<VPackBuilder> const& options, QueryPart part) std::shared_ptr<VPackBuilder> const& options, QueryPart part)
: _id(0), : _id(0),
@ -82,7 +82,6 @@ Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
_vocbase(vocbase), _vocbase(vocbase),
_context(nullptr), _context(nullptr),
_queryString(queryString), _queryString(queryString),
_queryStringLength(queryLength),
_queryBuilder(), _queryBuilder(),
_bindParameters(bindParameters), _bindParameters(bindParameters),
_options(options), _options(options),
@ -109,12 +108,12 @@ Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
if (tracing > 0) { if (tracing > 0) {
LOG_TOPIC(INFO, Logger::QUERIES) LOG_TOPIC(INFO, Logger::QUERIES)
<< TRI_microtime() - _startTime << " " << TRI_microtime() - _startTime << " "
<< "Query::Query queryString: " << std::string(queryString, queryLength) << "Query::Query queryString: " << _queryString
<< " this: " << (uintptr_t) this; << " this: " << (uintptr_t) this;
} else { } else {
LOG_TOPIC(DEBUG, Logger::QUERIES) LOG_TOPIC(DEBUG, Logger::QUERIES)
<< TRI_microtime() - _startTime << " " << TRI_microtime() - _startTime << " "
<< "Query::Query queryString: " << std::string(queryString, queryLength) << "Query::Query queryString: " << _queryString
<< " this: " << (uintptr_t) this; << " this: " << (uintptr_t) this;
} }
if (bindParameters != nullptr && !bindParameters->isEmpty() && if (bindParameters != nullptr && !bindParameters->isEmpty() &&
@ -150,8 +149,7 @@ Query::Query(bool contextOwnedByExterior, TRI_vocbase_t* vocbase,
_resources(&_resourceMonitor), _resources(&_resourceMonitor),
_vocbase(vocbase), _vocbase(vocbase),
_context(nullptr), _context(nullptr),
_queryString(nullptr), _queryString(),
_queryStringLength(0),
_queryBuilder(queryStruct), _queryBuilder(queryStruct),
_options(options), _options(options),
_collections(vocbase), _collections(vocbase),
@ -221,7 +219,7 @@ Query::~Query() {
/// the query /// the query
Query* Query::clone(QueryPart part, bool withPlan) { Query* Query::clone(QueryPart part, bool withPlan) {
auto clone = auto clone =
std::make_unique<Query>(false, _vocbase, _queryString, _queryStringLength, std::make_unique<Query>(false, _vocbase, _queryString,
std::shared_ptr<VPackBuilder>(), _options, part); std::shared_ptr<VPackBuilder>(), _options, part);
clone->_resourceMonitor = _resourceMonitor; clone->_resourceMonitor = _resourceMonitor;
@ -266,62 +264,6 @@ void Query::setExecutionTime() {
} }
} }
/// @brief extract a region from the query
std::string Query::extractRegion(int line, int column) const {
TRI_ASSERT(_queryString != nullptr);
// note: line numbers reported by bison/flex start at 1, columns start at 0
int currentLine = 1;
int currentColumn = 0;
char c;
char const* p = _queryString;
while ((static_cast<size_t>(p - _queryString) < _queryStringLength) && (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;
// eat a following newline
if (*p == '\n') {
++p;
}
} else {
++currentColumn;
++p;
}
}
// p is pointing at the position in the query the parse error occurred at
TRI_ASSERT(p >= _queryString);
size_t offset = static_cast<size_t>(p - _queryString);
static int const SNIPPET_LENGTH = 32;
static char const* SNIPPET_SUFFIX = "...";
if (_queryStringLength < offset + SNIPPET_LENGTH) {
// return a copy of the region
return std::string(_queryString + offset, _queryStringLength - offset);
}
// copy query part
std::string result(_queryString + offset, SNIPPET_LENGTH);
result.append(SNIPPET_SUFFIX);
return result;
}
/// @brief register an error, with an optional parameter inserted into printf /// @brief register an error, with an optional parameter inserted into printf
/// this also makes the query abort /// this also makes the query abort
void Query::registerError(int code, char const* details) { void Query::registerError(int code, char const* details) {
@ -373,7 +315,7 @@ void Query::registerWarning(int code, char const* details) {
} }
} }
void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) { void Query::prepare(QueryRegistry* registry, uint64_t queryHash) {
TRI_ASSERT(registry != nullptr); TRI_ASSERT(registry != nullptr);
init(); init();
@ -382,15 +324,15 @@ void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) {
std::unique_ptr<ExecutionPlan> plan; std::unique_ptr<ExecutionPlan> plan;
#if USE_PLAN_CACHE #if USE_PLAN_CACHE
if (_queryString != nullptr && if (!_queryString.empty() &&
queryStringHash != DontCache && queryHash != DontCache &&
_part == PART_MAIN) { _part == PART_MAIN) {
// LOG_TOPIC(INFO, Logger::FIXME) << "trying to find query in execution plan cache: '" << std::string(_queryString, _queryStringLength) << "', hash: " << queryStringHash; // LOG_TOPIC(INFO, Logger::FIXME) << "trying to find query in execution plan cache: '" << _queryString << "', hash: " << queryHash;
// store & lookup velocypack plans!! // store & lookup velocypack plans!!
std::shared_ptr<PlanCacheEntry> planCacheEntry = PlanCache::instance()->lookup(_vocbase, queryStringHash, _queryString, _queryStringLength); std::shared_ptr<PlanCacheEntry> planCacheEntry = PlanCache::instance()->lookup(_vocbase, queryHash, queryString);
if (planCacheEntry != nullptr) { if (planCacheEntry != nullptr) {
// LOG_TOPIC(INFO, Logger::FIXME) << "query found in execution plan cache: '" << std::string(_queryString, _queryStringLength) << "'"; // LOG_TOPIC(INFO, Logger::FIXME) << "query found in execution plan cache: '" << _queryString << "'";
TRI_ASSERT(_trx == nullptr); TRI_ASSERT(_trx == nullptr);
TRI_ASSERT(_collections.empty()); TRI_ASSERT(_collections.empty());
@ -433,13 +375,13 @@ void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) {
TRI_ASSERT(plan != nullptr); TRI_ASSERT(plan != nullptr);
#if USE_PLAN_CACHE #if USE_PLAN_CACHE
if (_queryString != nullptr && if (!_queryString.empty() &&
queryStringHash != DontCache && queryHash != DontCache &&
_part == PART_MAIN && _part == PART_MAIN &&
_warnings.empty() && _warnings.empty() &&
_ast->root()->isCacheable()) { _ast->root()->isCacheable()) {
// LOG_TOPIC(INFO, Logger::FIXME) << "storing query in execution plan cache '" << std::string(_queryString, _queryStringLength) << "', hash: " << queryStringHash; // LOG_TOPIC(INFO, Logger::FIXME) << "storing query in execution plan cache '" << _queryString << "', hash: " << queryHash;
PlanCache::instance()->store(_vocbase, queryStringHash, _queryString, _queryStringLength, plan.get()); PlanCache::instance()->store(_vocbase, queryHash, _queryString, plan.get());
} }
#endif #endif
} }
@ -451,7 +393,7 @@ void Query::prepare(QueryRegistry* registry, uint64_t queryStringHash) {
// own _engine attribute (the instanciation procedure may modify us // own _engine attribute (the instanciation procedure may modify us
// by calling our engine(ExecutionEngine*) function // by calling our engine(ExecutionEngine*) function
// this is confusing and should be fixed! // this is confusing and should be fixed!
std::unique_ptr<ExecutionEngine> engine(ExecutionEngine::instantiateFromPlan(registry, this, plan.get(), _queryString != nullptr)); std::unique_ptr<ExecutionEngine> engine(ExecutionEngine::instantiateFromPlan(registry, this, plan.get(), !_queryString.empty()));
if (_engine == nullptr) { if (_engine == nullptr) {
_engine = std::move(engine); _engine = std::move(engine);
@ -472,7 +414,7 @@ ExecutionPlan* Query::prepare() {
<< " this: " << (uintptr_t) this; << " this: " << (uintptr_t) this;
std::unique_ptr<ExecutionPlan> plan; std::unique_ptr<ExecutionPlan> plan;
if (_queryString != nullptr) { if (!_queryString.empty()) {
auto parser = std::make_unique<Parser>(this); auto parser = std::make_unique<Parser>(this);
parser->parse(false); parser->parse(false);
@ -491,7 +433,7 @@ ExecutionPlan* Query::prepare() {
// As soon as we start du instantiate the plan we have to clean it // As soon as we start du instantiate the plan we have to clean it
// up before killing the unique_ptr // up before killing the unique_ptr
if (_queryString != nullptr) { if (!_queryString.empty()) {
// we have an AST // we have an AST
// optimize the ast // optimize the ast
enterState(QueryExecutionState::ValueType::AST_OPTIMIZATION); enterState(QueryExecutionState::ValueType::AST_OPTIMIZATION);
@ -575,12 +517,12 @@ QueryResult Query::execute(QueryRegistry* registry) {
try { try {
bool useQueryCache = canUseQueryCache(); bool useQueryCache = canUseQueryCache();
uint64_t queryStringHash = hash(); uint64_t queryHash = hash();
if (useQueryCache) { if (useQueryCache) {
// check the query cache for an existing result // check the query cache for an existing result
auto cacheEntry = arangodb::aql::QueryCache::instance()->lookup( auto cacheEntry = arangodb::aql::QueryCache::instance()->lookup(
_vocbase, queryStringHash, _queryString, _queryStringLength); _vocbase, queryHash, _queryString);
arangodb::aql::QueryCacheResultEntryGuard guard(cacheEntry); arangodb::aql::QueryCacheResultEntryGuard guard(cacheEntry);
if (cacheEntry != nullptr) { if (cacheEntry != nullptr) {
@ -599,14 +541,14 @@ QueryResult Query::execute(QueryRegistry* registry) {
} }
// will throw if it fails // will throw if it fails
prepare(registry, queryStringHash); prepare(registry, queryHash);
if (_queryString == nullptr) { if (_queryString.empty()) {
// we don't have query string... now pass query id to WorkMonitor // we don't have query string... now pass query id to WorkMonitor
work.reset(new AqlWorkStack(_vocbase, _id)); work.reset(new AqlWorkStack(_vocbase, _id));
} else { } else {
// we do have a query string... pass query to WorkMonitor // we do have a query string... pass query to WorkMonitor
work.reset(new AqlWorkStack(_vocbase, _id, _queryString, _queryStringLength)); work.reset(new AqlWorkStack(_vocbase, _id, _queryString.data(), _queryString.size()));
} }
log(); log();
@ -658,7 +600,7 @@ QueryResult Query::execute(QueryRegistry* registry) {
if (_warnings.empty()) { if (_warnings.empty()) {
// finally store the generated result in the query cache // finally store the generated result in the query cache
auto result = QueryCache::instance()->store( auto result = QueryCache::instance()->store(
_vocbase, queryStringHash, _queryString, _queryStringLength, _vocbase, queryHash, _queryString,
resultBuilder, _trx->state()->collectionNames()); resultBuilder, _trx->state()->collectionNames());
if (result == nullptr) { if (result == nullptr) {
@ -759,12 +701,12 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
try { try {
bool useQueryCache = canUseQueryCache(); bool useQueryCache = canUseQueryCache();
uint64_t queryStringHash = hash(); uint64_t queryHash = hash();
if (useQueryCache) { if (useQueryCache) {
// check the query cache for an existing result // check the query cache for an existing result
auto cacheEntry = arangodb::aql::QueryCache::instance()->lookup( auto cacheEntry = arangodb::aql::QueryCache::instance()->lookup(
_vocbase, queryStringHash, _queryString, _queryStringLength); _vocbase, queryHash, _queryString);
arangodb::aql::QueryCacheResultEntryGuard guard(cacheEntry); arangodb::aql::QueryCacheResultEntryGuard guard(cacheEntry);
if (cacheEntry != nullptr) { if (cacheEntry != nullptr) {
@ -785,14 +727,14 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
} }
// will throw if it fails // will throw if it fails
prepare(registry, queryStringHash); prepare(registry, queryHash);
if (_queryString == nullptr) { if (_queryString.empty()) {
// we don't have query string... now pass query id to WorkMonitor // we don't have query string... now pass query id to WorkMonitor
work.reset(new AqlWorkStack(_vocbase, _id)); work.reset(new AqlWorkStack(_vocbase, _id));
} else { } else {
// we do have a query string... pass query to WorkMonitor // we do have a query string... pass query to WorkMonitor
work.reset(new AqlWorkStack(_vocbase, _id, _queryString, _queryStringLength)); work.reset(new AqlWorkStack(_vocbase, _id, _queryString.data(), _queryString.size()));
} }
log(); log();
@ -842,8 +784,7 @@ QueryResultV8 Query::executeV8(v8::Isolate* isolate, QueryRegistry* registry) {
if (_warnings.empty()) { if (_warnings.empty()) {
// finally store the generated result in the query cache // finally store the generated result in the query cache
QueryCache::instance()->store(_vocbase, queryStringHash, _queryString, QueryCache::instance()->store(_vocbase, queryHash, _queryString, builder,
_queryStringLength, builder,
_trx->state()->collectionNames()); _trx->state()->collectionNames());
} }
} else { } else {
@ -1033,7 +974,7 @@ QueryResult Query::explain() {
result.result = bestPlan->toVelocyPack(parser.ast(), verbosePlans()); result.result = bestPlan->toVelocyPack(parser.ast(), verbosePlans());
// cacheability // cacheability
result.cached = (_queryString != nullptr && _queryStringLength > 0 && result.cached = (!_queryString.empty() &&
!_isModificationQuery && _warnings.empty() && !_isModificationQuery && _warnings.empty() &&
_ast->root()->isCacheable()); _ast->root()->isCacheable());
} }
@ -1239,25 +1180,20 @@ void Query::init() {
/// @brief log a query /// @brief log a query
void Query::log() { void Query::log() {
if (_queryString != nullptr) { if (!_queryString.empty()) {
static size_t const MaxLength = 1024;
LOG_TOPIC(TRACE, Logger::QUERIES) LOG_TOPIC(TRACE, Logger::QUERIES)
<< "executing query " << _id << ": '" << "executing query " << _id << ": '" << _queryString.extract(1024) << "'";
<< std::string(_queryString, (std::min)(_queryStringLength, MaxLength))
.append(_queryStringLength > MaxLength ? "..." : "") << "'";
} }
} }
/// @brief calculate a hash value for the query and bind parameters /// @brief calculate a hash value for the query and bind parameters
uint64_t Query::hash() const { uint64_t Query::hash() {
if (_queryString == nullptr) { if (_queryString.empty()) {
return DontCache; return DontCache;
} }
// hash the query string first // hash the query string first
uint64_t hash = arangodb::aql::QueryCache::instance()->hashQueryString( uint64_t hash = _queryString.hash();
_queryString, _queryStringLength);
// handle "fullCount" option. if this option is set, the query result will // handle "fullCount" option. if this option is set, the query result will
// be different to when it is not set! // be different to when it is not set!
@ -1288,7 +1224,7 @@ uint64_t Query::hash() const {
/// @brief whether or not the query cache can be used for the query /// @brief whether or not the query cache can be used for the query
bool Query::canUseQueryCache() const { bool Query::canUseQueryCache() const {
if (_queryString == nullptr || _queryStringLength < 8) { if (_queryString.size() < 8) {
return false; return false;
} }
@ -1317,9 +1253,9 @@ bool Query::canUseQueryCache() const {
std::string Query::buildErrorMessage(int errorCode) const { std::string Query::buildErrorMessage(int errorCode) const {
std::string err(TRI_errno_string(errorCode)); std::string err(TRI_errno_string(errorCode));
if (_queryString != nullptr && verboseErrors()) { if (!_queryString.empty() && verboseErrors()) {
err += "\nwhile executing:\n"; err += "\nwhile executing:\n";
err.append(_queryString, _queryStringLength); _queryString.append(err);
err += "\n"; err += "\n";
} }

View File

@ -34,6 +34,7 @@
#include "Aql/QueryExecutionState.h" #include "Aql/QueryExecutionState.h"
#include "Aql/QueryResources.h" #include "Aql/QueryResources.h"
#include "Aql/QueryResultV8.h" #include "Aql/QueryResultV8.h"
#include "Aql/QueryString.h"
#include "Aql/ResourceUsage.h" #include "Aql/ResourceUsage.h"
#include "Aql/types.h" #include "Aql/types.h"
#include "Basics/Common.h" #include "Basics/Common.h"
@ -76,7 +77,7 @@ class Query {
Query& operator=(Query const&) = delete; Query& operator=(Query const&) = delete;
public: public:
Query(bool, TRI_vocbase_t*, char const*, size_t, Query(bool contextOwnedByExterior, TRI_vocbase_t*, QueryString const& queryString,
std::shared_ptr<arangodb::velocypack::Builder> const& bindParameters, std::shared_ptr<arangodb::velocypack::Builder> const& bindParameters,
std::shared_ptr<arangodb::velocypack::Builder> const& options, QueryPart); std::shared_ptr<arangodb::velocypack::Builder> const& options, QueryPart);
@ -93,6 +94,8 @@ class Query {
public: public:
QueryString const& queryString() const { return _queryString; }
/// @brief Inject a transaction from outside. Use with care! /// @brief Inject a transaction from outside. Use with care!
void injectTransaction (transaction::Methods* trx) { void injectTransaction (transaction::Methods* trx) {
_trx = trx; _trx = trx;
@ -137,12 +140,6 @@ class Query {
/// @brief return the query's id /// @brief return the query's id
TRI_voc_tick_t id() const { return _id; } TRI_voc_tick_t id() const { return _id; }
/// @brief get the query string
char const* queryString() const { return _queryString; }
/// @brief get the length of the query string
size_t queryLength() const { return _queryStringLength; }
/// @brief getter for _ast /// @brief getter for _ast
Ast* ast() const { Ast* ast() const {
return _ast.get(); return _ast.get();
@ -199,7 +196,7 @@ class Query {
} }
/// @brief extract a region from the query /// @brief extract a region from the query
std::string extractRegion(int, int) const; std::string extractRegion(int line, int column) const;
/// @brief register an error, with an optional parameter inserted into printf /// @brief register an error, with an optional parameter inserted into printf
/// this also makes the query abort /// this also makes the query abort
@ -212,7 +209,7 @@ class Query {
/// @brief register a warning /// @brief register a warning
void registerWarning(int, char const* = nullptr); void registerWarning(int, char const* = nullptr);
void prepare(QueryRegistry*, uint64_t queryStringHash); void prepare(QueryRegistry*, uint64_t queryHash);
/// @brief execute an AQL query /// @brief execute an AQL query
QueryResult execute(QueryRegistry*); QueryResult execute(QueryRegistry*);
@ -297,7 +294,7 @@ class Query {
void log(); void log();
/// @brief calculate a hash value for the query and bind parameters /// @brief calculate a hash value for the query and bind parameters
uint64_t hash() const; uint64_t hash();
/// @brief whether or not the query cache can be used for the query /// @brief whether or not the query cache can be used for the query
bool canUseQueryCache() const; bool canUseQueryCache() const;
@ -369,10 +366,7 @@ class Query {
std::unordered_map<std::string, Graph*> _graphs; std::unordered_map<std::string, Graph*> _graphs;
/// @brief the actual query string /// @brief the actual query string
char const* _queryString; QueryString _queryString;
/// @brief length of the query string in bytes
size_t const _queryStringLength;
/// @brief query in a VelocyPack structure /// @brief query in a VelocyPack structure
std::shared_ptr<arangodb::velocypack::Builder> const _queryBuilder; std::shared_ptr<arangodb::velocypack::Builder> const _queryBuilder;

View File

@ -46,10 +46,10 @@ static std::atomic<arangodb::aql::QueryCacheMode> Mode(CACHE_ON_DEMAND);
/// @brief create a cache entry /// @brief create a cache entry
QueryCacheResultEntry::QueryCacheResultEntry( QueryCacheResultEntry::QueryCacheResultEntry(
uint64_t hash, char const* queryString, size_t queryStringLength, uint64_t hash, QueryString const& queryString,
std::shared_ptr<VPackBuilder> queryResult, std::vector<std::string> const& collections) std::shared_ptr<VPackBuilder> queryResult, std::vector<std::string> const& collections)
: _hash(hash), : _hash(hash),
_queryString(queryString, queryStringLength), _queryString(queryString.data(), queryString.size()),
_queryResult(queryResult), _queryResult(queryResult),
_collections(collections), _collections(collections),
_prev(nullptr), _prev(nullptr),
@ -105,7 +105,7 @@ QueryCacheDatabaseEntry::~QueryCacheDatabaseEntry() {
/// @brief lookup a query result in the database-specific cache /// @brief lookup a query result in the database-specific cache
QueryCacheResultEntry* QueryCacheDatabaseEntry::lookup( QueryCacheResultEntry* QueryCacheDatabaseEntry::lookup(
uint64_t hash, char const* queryString, size_t queryStringLength) { uint64_t hash, QueryString const& queryString) {
auto it = _entriesByHash.find(hash); auto it = _entriesByHash.find(hash);
if (it == _entriesByHash.end()) { if (it == _entriesByHash.end()) {
@ -115,8 +115,8 @@ QueryCacheResultEntry* QueryCacheDatabaseEntry::lookup(
// found some result in cache // found some result in cache
if (queryStringLength != (*it).second->_queryString.size() || if (queryString.size() != (*it).second->_queryString.size() ||
memcmp(queryString, (*it).second->_queryString.c_str(), queryStringLength) != 0) { memcmp(queryString.data(), (*it).second->_queryString.c_str(), queryString.size()) != 0) {
// found something, but obviously the result of a different query with the // found something, but obviously the result of a different query with the
// same hash // same hash
return nullptr; return nullptr;
@ -362,8 +362,7 @@ std::string QueryCache::modeString(QueryCacheMode mode) {
/// @brief lookup a query result in the cache /// @brief lookup a query result in the cache
QueryCacheResultEntry* QueryCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash, QueryCacheResultEntry* QueryCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash,
char const* queryString, QueryString const& queryString) {
size_t queryStringLength) {
auto const part = getPart(vocbase); auto const part = getPart(vocbase);
READ_LOCKER(readLocker, _entriesLock[part]); READ_LOCKER(readLocker, _entriesLock[part]);
@ -374,18 +373,17 @@ QueryCacheResultEntry* QueryCache::lookup(TRI_vocbase_t* vocbase, uint64_t hash,
return nullptr; return nullptr;
} }
return (*it).second->lookup(hash, queryString, queryStringLength); return (*it).second->lookup(hash, queryString);
} }
/// @brief store a query in the cache /// @brief store a query in the cache
/// if the call is successful, the cache has taken over ownership for the /// if the call is successful, the cache has taken over ownership for the
/// query result! /// query result!
QueryCacheResultEntry* QueryCache::store( QueryCacheResultEntry* QueryCache::store(
TRI_vocbase_t* vocbase, uint64_t hash, char const* queryString, TRI_vocbase_t* vocbase, uint64_t hash, QueryString const& queryString,
size_t queryStringLength, std::shared_ptr<VPackBuilder> result, std::shared_ptr<VPackBuilder> result,
std::vector<std::string> const& collections) { std::vector<std::string> const& collections) {
if (!result->slice().isArray()) { if (!result->slice().isArray()) {
return nullptr; return nullptr;
} }
@ -395,7 +393,7 @@ QueryCacheResultEntry* QueryCache::store(
// create the cache entry outside the lock // create the cache entry outside the lock
auto entry = std::make_unique<QueryCacheResultEntry>( auto entry = std::make_unique<QueryCacheResultEntry>(
hash, queryString, queryStringLength, result, collections); hash, queryString, result, collections);
WRITE_LOCKER(writeLocker, _entriesLock[part]); WRITE_LOCKER(writeLocker, _entriesLock[part]);
@ -482,14 +480,6 @@ void QueryCache::invalidate() {
} }
} }
/// @brief hashes a query string
uint64_t QueryCache::hashQueryString(char const* queryString,
size_t queryLength) const {
TRI_ASSERT(queryString != nullptr);
return fasthash64(queryString, queryLength, 0x3123456789abcdef);
}
/// @brief get the query cache instance /// @brief get the query cache instance
QueryCache* QueryCache::instance() { return &Instance; } QueryCache* QueryCache::instance() { return &Instance; }

View File

@ -24,6 +24,7 @@
#ifndef ARANGOD_AQL_QUERY_CACHE_H #ifndef ARANGOD_AQL_QUERY_CACHE_H
#define ARANGOD_AQL_QUERY_CACHE_H 1 #define ARANGOD_AQL_QUERY_CACHE_H 1
#include "Aql/QueryString.h"
#include "Basics/Common.h" #include "Basics/Common.h"
#include "Basics/Mutex.h" #include "Basics/Mutex.h"
#include "Basics/ReadWriteLock.h" #include "Basics/ReadWriteLock.h"
@ -42,7 +43,7 @@ enum QueryCacheMode { CACHE_ALWAYS_OFF, CACHE_ALWAYS_ON, CACHE_ON_DEMAND };
struct QueryCacheResultEntry { struct QueryCacheResultEntry {
QueryCacheResultEntry() = delete; QueryCacheResultEntry() = delete;
QueryCacheResultEntry(uint64_t, char const*, size_t, std::shared_ptr<arangodb::velocypack::Builder>, QueryCacheResultEntry(uint64_t, QueryString const&, std::shared_ptr<arangodb::velocypack::Builder>,
std::vector<std::string> const&); std::vector<std::string> const&);
~QueryCacheResultEntry() = default; ~QueryCacheResultEntry() = default;
@ -99,7 +100,7 @@ struct QueryCacheDatabaseEntry {
~QueryCacheDatabaseEntry(); ~QueryCacheDatabaseEntry();
/// @brief lookup a query result in the database-specific cache /// @brief lookup a query result in the database-specific cache
QueryCacheResultEntry* lookup(uint64_t, char const*, size_t); QueryCacheResultEntry* lookup(uint64_t, QueryString const&);
/// @brief store a query result in the database-specific cache /// @brief store a query result in the database-specific cache
void store(uint64_t, QueryCacheResultEntry*); void store(uint64_t, QueryCacheResultEntry*);
@ -176,12 +177,12 @@ class QueryCache {
static std::string modeString(QueryCacheMode); static std::string modeString(QueryCacheMode);
/// @brief lookup a query result in the cache /// @brief lookup a query result in the cache
QueryCacheResultEntry* lookup(TRI_vocbase_t*, uint64_t, char const*, size_t); QueryCacheResultEntry* lookup(TRI_vocbase_t*, uint64_t, QueryString const&);
/// @brief store a query in the cache /// @brief store a query in the cache
/// if the call is successful, the cache has taken over ownership for the /// if the call is successful, the cache has taken over ownership for the
/// query result! /// query result!
QueryCacheResultEntry* store(TRI_vocbase_t*, uint64_t, char const*, size_t, QueryCacheResultEntry* store(TRI_vocbase_t*, uint64_t, QueryString const&,
std::shared_ptr<arangodb::velocypack::Builder>, std::shared_ptr<arangodb::velocypack::Builder>,
std::vector<std::string> const&); std::vector<std::string> const&);
@ -197,9 +198,6 @@ class QueryCache {
/// @brief invalidate all queries /// @brief invalidate all queries
void invalidate(); void invalidate();
/// @brief hashes a query string
uint64_t hashQueryString(char const*, size_t) const;
/// @brief get the pointer to the global query cache /// @brief get the pointer to the global query cache
static QueryCache* instance(); static QueryCache* instance();

View File

@ -61,7 +61,7 @@ QueryList::QueryList(TRI_vocbase_t*)
/// @brief insert a query /// @brief insert a query
bool QueryList::insert(Query* query) { bool QueryList::insert(Query* query) {
// not enable or no query string // not enable or no query string
if (!_enabled || query == nullptr || query->queryString() == nullptr) { if (!_enabled || query == nullptr || query->queryString().empty()) {
return false; return false;
} }
@ -92,7 +92,7 @@ void QueryList::remove(Query* query) {
// the list are correct // the list are correct
// no query string // no query string
if (query == nullptr || query->queryString() == nullptr) { if (query == nullptr || query->queryString().empty()) {
return; return;
} }
@ -164,9 +164,7 @@ int QueryList::kill(TRI_voc_tick_t id) {
} }
Query* query = (*it).second; Query* query = (*it).second;
StringRef queryString(query->queryString(), query->queryLength()); LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << id << " '" << query->queryString() << "'";
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << id << " '" << queryString << "'";
query->killed(true); query->killed(true);
return TRI_ERROR_NO_ERROR; return TRI_ERROR_NO_ERROR;
@ -181,12 +179,10 @@ uint64_t QueryList::killAll(bool silent) {
for (auto& it : _current) { for (auto& it : _current) {
Query* query = it.second; Query* query = it.second;
StringRef queryString(query->queryString(), query->queryLength());
if (silent) { if (silent) {
LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << queryString << "'"; LOG_TOPIC(TRACE, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << query->queryString() << "'";
} else { } else {
LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << queryString << "'"; LOG_TOPIC(WARN, arangodb::Logger::FIXME) << "killing AQL query " << query->id() << " '" << query->queryString() << "'";
} }
query->killed(true); query->killed(true);
@ -210,7 +206,7 @@ std::vector<QueryEntryCopy> QueryList::listCurrent() {
for (auto const& it : _current) { for (auto const& it : _current) {
Query const* query = it.second; Query const* query = it.second;
if (query == nullptr || query->queryString() == nullptr) { if (query == nullptr || query->queryString().empty()) {
continue; continue;
} }
@ -251,38 +247,5 @@ void QueryList::clearSlow() {
} }
std::string QueryList::extractQueryString(Query const* query, size_t maxLength) const { std::string QueryList::extractQueryString(Query const* query, size_t maxLength) const {
char const* queryString = query->queryString(); return query->queryString().extract(maxLength);
size_t length = query->queryLength();
if (length > maxLength) {
std::string q;
// query string needs truncation
length = maxLength;
// do not create invalid UTF-8 sequences
while (length > 0) {
uint8_t c = queryString[length - 1];
if ((c & 128) == 0) {
// single-byte character
break;
}
--length;
// start of a multi-byte sequence
if ((c & 192) == 192) {
// decrease length by one more, so we the string contains the
// last part of the previous (multi-byte?) sequence
break;
}
}
q.reserve(length + 3);
q.append(queryString, length);
q.append("...", 3);
return q;
}
// no truncation
return std::string(queryString, length);
} }

153
arangod/Aql/QueryString.cpp Normal file
View File

@ -0,0 +1,153 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#include "QueryString.h"
#include "Basics/fasthash.h"
using namespace arangodb::aql;
void QueryString::append(std::string& out) const {
if (empty()) {
return;
}
out.append(_data, _length);
}
uint64_t QueryString::hash() {
if (!_hashed) {
if (_data == nullptr) {
return 0;
}
_hash = fasthash64(_data, _length, 0x3123456789abcdef);
_hashed = true;
}
return _hash;
}
std::string QueryString::extract(size_t maxLength) const {
if (_length <= maxLength) {
// no truncation
return std::string(_data, _length);
}
// query string needs truncation
size_t length = maxLength;
// do not create invalid UTF-8 sequences
while (length > 0) {
uint8_t c = _data[length - 1];
if ((c & 128) == 0) {
// single-byte character
break;
}
--length;
// start of a multi-byte sequence
if ((c & 192) == 192) {
// decrease length by one more, so we the string contains the
// last part of the previous (multi-byte?) sequence
break;
}
}
std::string result;
result.reserve(length + 3);
result.append(_data, length);
result.append("...", 3);
return result;
}
/// @brief extract a region from the query
std::string QueryString::extractRegion(int line, int column) const {
TRI_ASSERT(_data != nullptr);
// note: line numbers reported by bison/flex start at 1, columns start at 0
int currentLine = 1;
int currentColumn = 0;
char c;
char const* p = _data;
while ((static_cast<size_t>(p - _data) < _length) && (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;
// eat a following newline
if (*p == '\n') {
++p;
}
} else {
++currentColumn;
++p;
}
}
// p is pointing at the position in the query the parse error occurred at
TRI_ASSERT(p >= _data);
size_t offset = static_cast<size_t>(p - _data);
static int const SNIPPET_LENGTH = 32;
if (_length < offset + SNIPPET_LENGTH) {
// return a copy of the region
return std::string(_data + offset, _length - offset);
}
// copy query part
std::string result;
result.reserve(SNIPPET_LENGTH + strlen("..."));
result.append(_data + offset, SNIPPET_LENGTH);
result.append("...");
return result;
}
namespace arangodb {
namespace aql {
std::ostream& operator<<(std::ostream& stream, QueryString const& queryString) {
if (queryString.empty()) {
stream << "(empty query)";
} else {
stream.write(queryString.data(), queryString.length());
}
return stream;
}
}
}

74
arangod/Aql/QueryString.h Normal file
View File

@ -0,0 +1,74 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGOD_AQL_QUERY_STRING_H
#define ARANGOD_AQL_QUERY_STRING_H 1
#include "Basics/Common.h"
#include "Basics/StringRef.h"
#include <iosfwd>
namespace arangodb {
namespace aql {
class QueryString {
public:
QueryString(QueryString const& other) = default;
QueryString& operator=(QueryString const& other) = default;
QueryString(char const* data, size_t length)
: _data(data), _length(length), _hash(0), _hashed(false) {}
explicit QueryString(arangodb::StringRef const& ref)
: QueryString(ref.data(), ref.size()) {}
explicit QueryString(std::string const& val)
: QueryString(val.data(), val.size()) {}
QueryString() : QueryString(nullptr, 0) {}
~QueryString() = default;
public:
char const* data() const { return _data; }
size_t size() const { return _length; }
size_t length() const { return _length; }
bool empty() const { return (_data == nullptr || _length == 0 || *_data == '\0'); }
void append(std::string& out) const;
uint64_t hash();
std::string extract(size_t maxLength) const;
std::string extractRegion(int line, int column) const;
private:
char const* _data;
size_t _length;
uint64_t _hash;
bool _hashed;
};
std::ostream& operator<<(std::ostream&, QueryString const&);
}
}
#endif

View File

@ -170,7 +170,7 @@ void RestAqlHandler::parseQuery() {
return; return;
} }
auto query = std::make_unique<Query>(false, _vocbase, queryString.c_str(), queryString.size(), auto query = std::make_unique<Query>(false, _vocbase, QueryString(queryString),
std::shared_ptr<VPackBuilder>(), nullptr, PART_MAIN); std::shared_ptr<VPackBuilder>(), nullptr, PART_MAIN);
QueryResult res = query->parse(); QueryResult res = query->parse();
if (res.code != TRI_ERROR_NO_ERROR) { if (res.code != TRI_ERROR_NO_ERROR) {
@ -241,8 +241,8 @@ void RestAqlHandler::explainQuery() {
VPackBuilder::clone(querySlice.get("options"))); VPackBuilder::clone(querySlice.get("options")));
auto query = auto query =
std::make_unique<Query>(false, _vocbase, queryString.c_str(), std::make_unique<Query>(false, _vocbase, QueryString(queryString),
queryString.size(), bindVars, options, PART_MAIN); bindVars, options, PART_MAIN);
QueryResult res = query->explain(); QueryResult res = query->explain();
if (res.code != TRI_ERROR_NO_ERROR) { if (res.code != TRI_ERROR_NO_ERROR) {
LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "failed to instantiate the Query: " << res.details; LOG_TOPIC(ERR, arangodb::Logger::FIXME) << "failed to instantiate the Query: " << res.details;
@ -309,8 +309,8 @@ void RestAqlHandler::createQueryFromString() {
auto options = std::make_shared<VPackBuilder>( auto options = std::make_shared<VPackBuilder>(
VPackBuilder::clone(querySlice.get("options"))); VPackBuilder::clone(querySlice.get("options")));
auto query = std::make_unique<Query>(false, _vocbase, queryString.c_str(), auto query = std::make_unique<Query>(false, _vocbase, QueryString(queryString),
queryString.size(), bindVars, options, bindVars, options,
(part == "main" ? PART_MAIN : PART_DEPENDENT)); (part == "main" ? PART_MAIN : PART_DEPENDENT));
try { try {

View File

@ -20,7 +20,7 @@
#define FLEX_SCANNER #define FLEX_SCANNER
#define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MAJOR_VERSION 2
#define YY_FLEX_MINOR_VERSION 6 #define YY_FLEX_MINOR_VERSION 6
#define YY_FLEX_SUBMINOR_VERSION 0 #define YY_FLEX_SUBMINOR_VERSION 1
#if YY_FLEX_SUBMINOR_VERSION > 0 #if YY_FLEX_SUBMINOR_VERSION > 0
#define FLEX_BETA #define FLEX_BETA
#endif #endif
@ -169,25 +169,13 @@ typedef unsigned int flex_uint32_t;
#ifdef __cplusplus /* TODO: this is always defined, so inline it */
/* The "const" storage-class-modifier is valid. */
#define YY_USE_CONST
#else /* ! __cplusplus */
/* C99 requires __STDC__ to be defined as 1. */
#if defined (__STDC__)
#define YY_USE_CONST
#endif /* defined (__STDC__) */
#endif /* ! __cplusplus */
#ifdef YY_USE_CONST
#define yyconst const #define yyconst const
#if defined(__GNUC__) && __GNUC__ >= 3
#define yynoreturn __attribute__((__noreturn__))
#else #else
#define yyconst #define yynoreturn
#endif #endif
@ -389,7 +377,7 @@ struct yy_buffer_state
/* Size of input buffer in bytes, not including room for EOB /* Size of input buffer in bytes, not including room for EOB
* characters. * characters.
*/ */
yy_size_t yy_buf_size; int yy_buf_size;
/* Number of characters read into yy_ch_buf, not including EOB /* Number of characters read into yy_ch_buf, not including EOB
* characters. * characters.
@ -489,7 +477,7 @@ static void Aql_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
YY_BUFFER_STATE Aql_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); YY_BUFFER_STATE Aql_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
YY_BUFFER_STATE Aql_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); YY_BUFFER_STATE Aql_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
YY_BUFFER_STATE Aql_scan_bytes (yyconst char *bytes,yy_size_t len ,yyscan_t yyscanner ); YY_BUFFER_STATE Aql_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
void *Aqlalloc (yy_size_t ,yyscan_t yyscanner ); void *Aqlalloc (yy_size_t ,yyscan_t yyscanner );
@ -550,10 +538,7 @@ typedef int yy_state_type;
static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
static int yy_get_next_buffer (yyscan_t yyscanner ); static int yy_get_next_buffer (yyscan_t yyscanner );
#if defined(__GNUC__) && __GNUC__ >= 3 static void yynoreturn yy_fatal_error (yyconst char* msg ,yyscan_t yyscanner );
__attribute__((__noreturn__))
#endif
static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
@ -563,7 +548,7 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
*/ */
#define YY_DO_BEFORE_ACTION \ #define YY_DO_BEFORE_ACTION \
yyg->yytext_ptr = yy_bp; \ yyg->yytext_ptr = yy_bp; \
yyleng = (size_t) (yy_cp - yy_bp); \ yyleng = (int) (yy_cp - yy_bp); \
yyg->yy_hold_char = *yy_cp; \ yyg->yy_hold_char = *yy_cp; \
*yy_cp = '\0'; \ *yy_cp = '\0'; \
yyg->yy_c_buf_p = yy_cp; yyg->yy_c_buf_p = yy_cp;
@ -987,7 +972,7 @@ struct yyguts_t
YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
char yy_hold_char; char yy_hold_char;
int yy_n_chars; int yy_n_chars;
yy_size_t yyleng_r; int yyleng_r;
char *yy_c_buf_p; char *yy_c_buf_p;
int yy_init; int yy_init;
int yy_start; int yy_start;
@ -1084,7 +1069,7 @@ void Aqlset_out (FILE * _out_str ,yyscan_t yyscanner );
yy_size_t Aqlget_leng (yyscan_t yyscanner ); int Aqlget_leng (yyscan_t yyscanner );
@ -1186,7 +1171,7 @@ static int input (yyscan_t yyscanner );
/* This used to be an fputs(), but since the string might contain NUL's, /* This used to be an fputs(), but since the string might contain NUL's,
* we now use fwrite(). * we now use fwrite().
*/ */
#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) #define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0)
#endif #endif
@ -1212,7 +1197,7 @@ static int input (yyscan_t yyscanner );
else \ else \
{ \ { \
errno=0; \ errno=0; \
while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
{ \ { \
if( errno != EINTR) \ if( errno != EINTR) \
{ \ { \
@ -1391,7 +1376,7 @@ yy_match:
if ( yy_current_state >= 259 ) if ( yy_current_state >= 259 )
yy_c = yy_meta[(unsigned int) yy_c]; yy_c = yy_meta[(unsigned int) yy_c];
} }
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
++yy_cp; ++yy_cp;
} }
while ( yy_current_state != 258 ); while ( yy_current_state != 258 );
@ -1406,7 +1391,7 @@ yy_find_action:
if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
{ {
yy_size_t yyl; size_t yyl;
for ( yyl = 0; yyl < yyleng; ++yyl ) for ( yyl = 0; yyl < yyleng; ++yyl )
if ( yytext[yyl] == '\n' ) if ( yytext[yyl] == '\n' )
@ -1820,7 +1805,7 @@ case 63:
YY_RULE_SETUP YY_RULE_SETUP
{ {
/* string enclosed in backticks */ /* string enclosed in backticks */
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(BACKTICK); BEGIN(BACKTICK);
} }
YY_BREAK YY_BREAK
@ -1830,7 +1815,7 @@ YY_RULE_SETUP
/* end of backtick-enclosed string */ /* end of backtick-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_STRING; return T_STRING;
} }
@ -1858,7 +1843,7 @@ case 68:
YY_RULE_SETUP YY_RULE_SETUP
{ {
/* string enclosed in forwardticks */ /* string enclosed in forwardticks */
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(FORWARDTICK); BEGIN(FORWARDTICK);
} }
YY_BREAK YY_BREAK
@ -1868,7 +1853,7 @@ YY_RULE_SETUP
/* end of forwardtick-enclosed string */ /* end of forwardtick-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 2, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 2, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_STRING; return T_STRING;
} }
@ -1898,7 +1883,7 @@ YY_RULE_SETUP
case 73: case 73:
YY_RULE_SETUP YY_RULE_SETUP
{ {
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(DOUBLE_QUOTE); BEGIN(DOUBLE_QUOTE);
} }
YY_BREAK YY_BREAK
@ -1908,7 +1893,7 @@ YY_RULE_SETUP
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_QUOTED_STRING; return T_QUOTED_STRING;
} }
@ -1935,7 +1920,7 @@ YY_RULE_SETUP
case 78: case 78:
YY_RULE_SETUP YY_RULE_SETUP
{ {
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(SINGLE_QUOTE); BEGIN(SINGLE_QUOTE);
} }
YY_BREAK YY_BREAK
@ -1945,7 +1930,7 @@ YY_RULE_SETUP
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_QUOTED_STRING; return T_QUOTED_STRING;
} }
@ -2312,7 +2297,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
char *source = yyg->yytext_ptr; char *source = yyg->yytext_ptr;
yy_size_t number_to_move, i; int number_to_move, i;
int ret_val; int ret_val;
if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
@ -2341,7 +2326,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
/* Try to read more data. */ /* Try to read more data. */
/* First move last chars to start of buffer. */ /* First move last chars to start of buffer. */
number_to_move = (yy_size_t) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1);
for ( i = 0; i < number_to_move; ++i ) for ( i = 0; i < number_to_move; ++i )
*(dest++) = *(source++); *(dest++) = *(source++);
@ -2354,7 +2339,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else else
{ {
yy_size_t num_to_read = int num_to_read =
YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
while ( num_to_read <= 0 ) while ( num_to_read <= 0 )
@ -2368,7 +2353,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( b->yy_is_our_buffer ) if ( b->yy_is_our_buffer )
{ {
yy_size_t new_size = b->yy_buf_size * 2; int new_size = b->yy_buf_size * 2;
if ( new_size <= 0 ) if ( new_size <= 0 )
b->yy_buf_size += b->yy_buf_size / 8; b->yy_buf_size += b->yy_buf_size / 8;
@ -2381,7 +2366,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
} }
else else
/* Can't grow it, we don't own it. */ /* Can't grow it, we don't own it. */
b->yy_ch_buf = 0; b->yy_ch_buf = NULL;
if ( ! b->yy_ch_buf ) if ( ! b->yy_ch_buf )
YY_FATAL_ERROR( YY_FATAL_ERROR(
@ -2423,7 +2408,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else else
ret_val = EOB_ACT_CONTINUE_SCAN; ret_val = EOB_ACT_CONTINUE_SCAN;
if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
/* Extend the array by 50%, plus the number we really need. */ /* Extend the array by 50%, plus the number we really need. */
int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); int new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1);
YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) Aqlrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) Aqlrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner );
@ -2466,7 +2451,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( yy_current_state >= 259 ) if ( yy_current_state >= 259 )
yy_c = yy_meta[(unsigned int) yy_c]; yy_c = yy_meta[(unsigned int) yy_c];
} }
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
} }
return yy_current_state; return yy_current_state;
@ -2496,7 +2481,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
if ( yy_current_state >= 259 ) if ( yy_current_state >= 259 )
yy_c = yy_meta[(unsigned int) yy_c]; yy_c = yy_meta[(unsigned int) yy_c];
} }
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_current_state = yy_nxt[yy_base[yy_current_state] + (flex_int16_t) yy_c];
yy_is_jam = (yy_current_state == 258); yy_is_jam = (yy_current_state == 258);
(void)yyg; (void)yyg;
@ -2533,7 +2518,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
else else
{ /* need more input */ { /* need more input */
yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
++yyg->yy_c_buf_p; ++yyg->yy_c_buf_p;
switch ( yy_get_next_buffer( yyscanner ) ) switch ( yy_get_next_buffer( yyscanner ) )
@ -2557,7 +2542,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
case EOB_ACT_END_OF_FILE: case EOB_ACT_END_OF_FILE:
{ {
if ( Aqlwrap(yyscanner ) ) if ( Aqlwrap(yyscanner ) )
return EOF; return 0;
if ( ! yyg->yy_did_buffer_switch_on_eof ) if ( ! yyg->yy_did_buffer_switch_on_eof )
YY_NEW_FILE; YY_NEW_FILE;
@ -2829,7 +2814,7 @@ void Aqlpop_buffer_state (yyscan_t yyscanner)
*/ */
static void Aqlensure_buffer_stack (yyscan_t yyscanner) static void Aqlensure_buffer_stack (yyscan_t yyscanner)
{ {
yy_size_t num_to_alloc; int num_to_alloc;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (!yyg->yy_buffer_stack) { if (!yyg->yy_buffer_stack) {
@ -2890,7 +2875,7 @@ YY_BUFFER_STATE Aql_scan_buffer (char * base, yy_size_t size , yyscan_t yyscan
base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-2] != YY_END_OF_BUFFER_CHAR ||
base[size-1] != YY_END_OF_BUFFER_CHAR ) base[size-1] != YY_END_OF_BUFFER_CHAR )
/* They forgot to leave room for the EOB's. */ /* They forgot to leave room for the EOB's. */
return 0; return NULL;
b = (YY_BUFFER_STATE) Aqlalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); b = (YY_BUFFER_STATE) Aqlalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
if ( ! b ) if ( ! b )
@ -2899,7 +2884,7 @@ YY_BUFFER_STATE Aql_scan_buffer (char * base, yy_size_t size , yyscan_t yyscan
b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
b->yy_buf_pos = b->yy_ch_buf = base; b->yy_buf_pos = b->yy_ch_buf = base;
b->yy_is_our_buffer = 0; b->yy_is_our_buffer = 0;
b->yy_input_file = 0; b->yy_input_file = NULL;
b->yy_n_chars = b->yy_buf_size; b->yy_n_chars = b->yy_buf_size;
b->yy_is_interactive = 0; b->yy_is_interactive = 0;
b->yy_at_bol = 1; b->yy_at_bol = 1;
@ -2925,7 +2910,7 @@ YY_BUFFER_STATE Aql_scan_buffer (char * base, yy_size_t size , yyscan_t yyscan
YY_BUFFER_STATE Aql_scan_string (yyconst char * yystr , yyscan_t yyscanner) YY_BUFFER_STATE Aql_scan_string (yyconst char * yystr , yyscan_t yyscanner)
{ {
return Aql_scan_bytes(yystr,strlen(yystr) ,yyscanner); return Aql_scan_bytes(yystr,(int) strlen(yystr) ,yyscanner);
} }
@ -2938,15 +2923,15 @@ YY_BUFFER_STATE Aql_scan_string (yyconst char * yystr , yyscan_t yyscanner)
* @param yyscanner The scanner object. * @param yyscanner The scanner object.
* @return the newly allocated buffer state object. * @return the newly allocated buffer state object.
*/ */
YY_BUFFER_STATE Aql_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) YY_BUFFER_STATE Aql_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
{ {
YY_BUFFER_STATE b; YY_BUFFER_STATE b;
char *buf; char *buf;
yy_size_t n; yy_size_t n;
yy_size_t i; int i;
/* Get memory for full buffer, including space for trailing EOB's. */ /* Get memory for full buffer, including space for trailing EOB's. */
n = _yybytes_len + 2; n = (yy_size_t) (_yybytes_len + 2);
buf = (char *) Aqlalloc(n ,yyscanner ); buf = (char *) Aqlalloc(n ,yyscanner );
if ( ! buf ) if ( ! buf )
YY_FATAL_ERROR( "out of dynamic memory in Aql_scan_bytes()" ); YY_FATAL_ERROR( "out of dynamic memory in Aql_scan_bytes()" );
@ -2982,7 +2967,7 @@ YY_BUFFER_STATE Aql_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len
#define YY_EXIT_FAILURE 2 #define YY_EXIT_FAILURE 2
#endif #endif
static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) static void yynoreturn yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
{ {
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg; (void)yyg;
@ -3082,7 +3067,7 @@ FILE *Aqlget_out (yyscan_t yyscanner)
/** Get the length of the current token. /** Get the length of the current token.
* @param yyscanner The scanner object. * @param yyscanner The scanner object.
*/ */
yy_size_t Aqlget_leng (yyscan_t yyscanner) int Aqlget_leng (yyscan_t yyscanner)
{ {
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
return yyleng; return yyleng;
@ -3304,10 +3289,10 @@ static int yy_init_globals (yyscan_t yyscanner)
yyg->yy_buffer_stack = 0; yyg->yy_buffer_stack = NULL;
yyg->yy_buffer_stack_top = 0; yyg->yy_buffer_stack_top = 0;
yyg->yy_buffer_stack_max = 0; yyg->yy_buffer_stack_max = 0;
yyg->yy_c_buf_p = (char *) 0; yyg->yy_c_buf_p = NULL;
yyg->yy_init = 0; yyg->yy_init = 0;
yyg->yy_start = 0; yyg->yy_start = 0;
@ -3326,8 +3311,8 @@ static int yy_init_globals (yyscan_t yyscanner)
yyin = stdin; yyin = stdin;
yyout = stdout; yyout = stdout;
#else #else
yyin = (FILE *) 0; yyin = NULL;
yyout = (FILE *) 0; yyout = NULL;
#endif #endif
/* For future reference: Set errno on error, since we are called by /* For future reference: Set errno on error, since we are called by
@ -3410,7 +3395,7 @@ void *Aqlalloc (yy_size_t size , yyscan_t yyscanner)
{ {
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
(void)yyg; (void)yyg;
return (void *) malloc( size ); return malloc(size);
} }
@ -3427,7 +3412,7 @@ void *Aqlrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
* any pointer type to void*, and deal with argument conversions * any pointer type to void*, and deal with argument conversions
* as though doing an assignment. * as though doing an assignment.
*/ */
return (void *) realloc( (char *) ptr, size ); return realloc(ptr, size);
} }

View File

@ -333,7 +333,7 @@ namespace arangodb {
<INITIAL>` { <INITIAL>` {
/* string enclosed in backticks */ /* string enclosed in backticks */
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(BACKTICK); BEGIN(BACKTICK);
} }
@ -341,7 +341,7 @@ namespace arangodb {
/* end of backtick-enclosed string */ /* end of backtick-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_STRING; return T_STRING;
} }
@ -361,7 +361,7 @@ namespace arangodb {
<INITIAL>´ { <INITIAL>´ {
/* string enclosed in forwardticks */ /* string enclosed in forwardticks */
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(FORWARDTICK); BEGIN(FORWARDTICK);
} }
@ -369,7 +369,7 @@ namespace arangodb {
/* end of forwardtick-enclosed string */ /* end of forwardtick-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 2, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 2, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_STRING; return T_STRING;
} }
@ -391,7 +391,7 @@ namespace arangodb {
* --------------------------------------------------------------------------- */ * --------------------------------------------------------------------------- */
<INITIAL>\" { <INITIAL>\" {
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(DOUBLE_QUOTE); BEGIN(DOUBLE_QUOTE);
} }
@ -399,7 +399,7 @@ namespace arangodb {
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_QUOTED_STRING; return T_QUOTED_STRING;
} }
@ -417,7 +417,7 @@ namespace arangodb {
} }
<INITIAL>' { <INITIAL>' {
yyextra->marker(yyextra->queryString() + yyextra->offset()); yyextra->marker(yyextra->queryStringStart() + yyextra->offset());
BEGIN(SINGLE_QUOTE); BEGIN(SINGLE_QUOTE);
} }
@ -425,7 +425,7 @@ namespace arangodb {
/* end of quote-enclosed string */ /* end of quote-enclosed string */
BEGIN(INITIAL); BEGIN(INITIAL);
size_t outLength; size_t outLength;
yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryString()) - 1, outLength); yylval->strval.value = yyextra->query()->registerEscapedString(yyextra->marker(), yyextra->offset() - (yyextra->marker() - yyextra->queryStringStart()) - 1, outLength);
yylval->strval.length = outLength; yylval->strval.length = outLength;
return T_QUOTED_STRING; return T_QUOTED_STRING;
} }

View File

@ -153,6 +153,7 @@ SET(ARANGOD_SOURCES
Aql/QueryList.cpp Aql/QueryList.cpp
Aql/QueryRegistry.cpp Aql/QueryRegistry.cpp
Aql/QueryResources.cpp Aql/QueryResources.cpp
Aql/QueryString.cpp
Aql/Range.cpp Aql/Range.cpp
Aql/RestAqlHandler.cpp Aql/RestAqlHandler.cpp
Aql/Scopes.cpp Aql/Scopes.cpp

View File

@ -25,6 +25,7 @@
#include "Aql/AqlTransaction.h" #include "Aql/AqlTransaction.h"
#include "Aql/Ast.h" #include "Aql/Ast.h"
#include "Aql/Query.h" #include "Aql/Query.h"
#include "Aql/QueryString.h"
#include "Basics/Exceptions.h" #include "Basics/Exceptions.h"
#include "Graph/EdgeCursor.h" #include "Graph/EdgeCursor.h"
#include "Graph/ShortestPathOptions.h" #include "Graph/ShortestPathOptions.h"
@ -105,7 +106,7 @@ BaseEngine::BaseEngine(TRI_vocbase_t* vocbase, VPackSlice info)
// created transaction is considered a "MAIN" part and will not switch // created transaction is considered a "MAIN" part and will not switch
// off collection locking completely! // off collection locking completely!
_query = _query =
new aql::Query(true, vocbase, "", 0, params, opts, aql::PART_DEPENDENT); new aql::Query(true, vocbase, aql::QueryString(), params, opts, aql::PART_DEPENDENT);
_query->injectTransaction(_trx); _query->injectTransaction(_trx);
VPackSlice variablesSlice = info.get(VARIABLES); VPackSlice variablesSlice = info.get(VARIABLES);

View File

@ -113,8 +113,8 @@ void RestCursorHandler::processQuery(VPackSlice const& slice) {
VPackValueLength l; VPackValueLength l;
char const* queryString = querySlice.getString(l); char const* queryString = querySlice.getString(l);
arangodb::aql::Query query(false, _vocbase, queryString, arangodb::aql::Query query(false, _vocbase, arangodb::aql::QueryString(queryString, static_cast<size_t>(l)),
static_cast<size_t>(l), bindVarsBuilder, options, bindVarsBuilder, options,
arangodb::aql::PART_MAIN); arangodb::aql::PART_MAIN);
registerQuery(&query); registerQuery(&query);

View File

@ -128,10 +128,7 @@ bool RestQueryHandler::readQuery(bool slow) {
return true; return true;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief returns AQL query tracking /// @brief returns AQL query tracking
////////////////////////////////////////////////////////////////////////////////
bool RestQueryHandler::readQuery() { bool RestQueryHandler::readQuery() {
auto const& suffixes = _request->suffixes(); auto const& suffixes = _request->suffixes();
@ -197,10 +194,7 @@ bool RestQueryHandler::deleteQuery(std::string const& name) {
return true; return true;
} }
////////////////////////////////////////////////////////////////////////////////
/// @brief interrupts a query /// @brief interrupts a query
////////////////////////////////////////////////////////////////////////////////
bool RestQueryHandler::deleteQuery() { bool RestQueryHandler::deleteQuery() {
auto const& suffixes = _request->suffixes(); auto const& suffixes = _request->suffixes();
@ -315,7 +309,7 @@ bool RestQueryHandler::parseQuery() {
std::string const&& queryString = std::string const&& queryString =
VelocyPackHelper::checkAndGetStringValue(body, "query"); VelocyPackHelper::checkAndGetStringValue(body, "query");
Query query(true, _vocbase, queryString.c_str(), queryString.size(), Query query(true, _vocbase, QueryString(queryString),
nullptr, nullptr, PART_MAIN); nullptr, nullptr, PART_MAIN);
auto parseResult = query.parse(); auto parseResult = query.parse();

View File

@ -24,6 +24,7 @@
#include "RestSimpleHandler.h" #include "RestSimpleHandler.h"
#include "Aql/Query.h" #include "Aql/Query.h"
#include "Aql/QueryRegistry.h" #include "Aql/QueryRegistry.h"
#include "Aql/QueryString.h"
#include "Basics/Exceptions.h" #include "Basics/Exceptions.h"
#include "Basics/MutexLocker.h" #include "Basics/MutexLocker.h"
#include "Basics/ScopeGuard.h" #include "Basics/ScopeGuard.h"
@ -221,7 +222,7 @@ void RestSimpleHandler::removeByKeys(VPackSlice const& slice) {
} }
} }
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), arangodb::aql::Query query(false, _vocbase, arangodb::aql::QueryString(aql),
bindVars, nullptr, arangodb::aql::PART_MAIN); bindVars, nullptr, arangodb::aql::PART_MAIN);
registerQuery(&query); registerQuery(&query);
@ -333,7 +334,7 @@ void RestSimpleHandler::lookupByKeys(VPackSlice const& slice) {
std::string const aql( std::string const aql(
"FOR doc IN @@collection FILTER doc._key IN @keys RETURN doc"); "FOR doc IN @@collection FILTER doc._key IN @keys RETURN doc");
arangodb::aql::Query query(false, _vocbase, aql.c_str(), aql.size(), arangodb::aql::Query query(false, _vocbase, aql::QueryString(aql),
bindVars, nullptr, arangodb::aql::PART_MAIN); bindVars, nullptr, arangodb::aql::PART_MAIN);
registerQuery(&query); registerQuery(&query);

View File

@ -71,6 +71,34 @@ void uint64ToPersistent(std::string& p, uint64_t value) {
} while (++len < sizeof(uint64_t)); } while (++len < sizeof(uint64_t));
} }
uint32_t uint32FromPersistent(char const* p) {
uint32_t value = 0;
uint32_t x = 0;
uint8_t const* ptr = reinterpret_cast<uint8_t const*>(p);
uint8_t const* end = ptr + sizeof(uint32_t);
do {
value += static_cast<uint16_t>(*ptr++) << x;
x += 8;
} while (ptr < end);
return value;
}
void uint32ToPersistent(char* p, uint32_t value) {
char* end = p + sizeof(uint32_t);
do {
*p++ = static_cast<uint8_t>(value & 0xffU);
value >>= 8;
} while (p < end);
}
void uint32ToPersistent(std::string& p, uint32_t value) {
size_t len = 0;
do {
p.push_back(static_cast<char>(value & 0xffU));
value >>= 8;
} while (++len < sizeof(uint32_t));
}
uint16_t uint16FromPersistent(char const* p) { uint16_t uint16FromPersistent(char const* p) {
uint16_t value = 0; uint16_t value = 0;
uint16_t x = 0; uint16_t x = 0;

View File

@ -82,6 +82,10 @@ uint64_t uint64FromPersistent(char const* p);
void uint64ToPersistent(char* p, uint64_t value); void uint64ToPersistent(char* p, uint64_t value);
void uint64ToPersistent(std::string& out, uint64_t value); void uint64ToPersistent(std::string& out, uint64_t value);
uint32_t uint32FromPersistent(char const* p);
void uint32ToPersistent(char* p, uint32_t value);
void uint32ToPersistent(std::string& out, uint32_t value);
uint16_t uint16FromPersistent(char const* p); uint16_t uint16FromPersistent(char const* p);
void uint16ToPersistent(char* p, uint16_t value); void uint16ToPersistent(char* p, uint16_t value);
void uint16ToPersistent(std::string& out, uint16_t value); void uint16ToPersistent(std::string& out, uint16_t value);

View File

@ -356,12 +356,21 @@ void RocksDBCounterManager::readIndexEstimates() {
iter->value().size() - sizeof(uint64_t)); iter->value().size() - sizeof(uint64_t));
// If this hits we have two estimates for the same index // If this hits we have two estimates for the same index
TRI_ASSERT(_estimators.find(objectId) == _estimators.end()); TRI_ASSERT(_estimators.find(objectId) == _estimators.end());
try {
if (RocksDBCuckooIndexEstimator<uint64_t>::isFormatSupported(estimateSerialisation)) {
_estimators.emplace( _estimators.emplace(
objectId, objectId,
std::make_pair(lastSeqNumber, std::make_pair(
lastSeqNumber,
std::make_unique<RocksDBCuckooIndexEstimator<uint64_t>>( std::make_unique<RocksDBCuckooIndexEstimator<uint64_t>>(
estimateSerialisation))); estimateSerialisation)));
} }
} catch (...) {
// Nothing to do, if the estimator fails to create we let it be recreated.
// Just validate that no corrupted memory was produced.
TRI_ASSERT(_estimators.find(objectId) == _estimators.end());
}
}
} }
std::unique_ptr<RocksDBCuckooIndexEstimator<uint64_t>> std::unique_ptr<RocksDBCuckooIndexEstimator<uint64_t>>
@ -421,7 +430,8 @@ struct WBReader final : public rocksdb::WriteBatch::Handler {
uint64_t _maxTick = 0; uint64_t _maxTick = 0;
uint64_t _maxHLC = 0; uint64_t _maxHLC = 0;
explicit WBReader(std::unordered_map< explicit WBReader(
std::unordered_map<
uint64_t, uint64_t,
std::pair<uint64_t, std::pair<uint64_t,
std::unique_ptr<RocksDBCuckooIndexEstimator<uint64_t>>>>* std::unique_ptr<RocksDBCuckooIndexEstimator<uint64_t>>>>*

View File

@ -67,13 +67,17 @@ class RocksDBCuckooIndexEstimator {
static constexpr uint32_t SlotsPerBucket = 4; static constexpr uint32_t SlotsPerBucket = 4;
private: private:
// Helper class to abstract away where which data is stored. // Helper class to hold the finger prints.
// Fingerprints are 64bit aligned and we
// have 4 slots per 64bit bucket.
struct Slot { struct Slot {
private: private:
uint16_t* _data; uint16_t* _data;
uint32_t* _counter;
public: public:
explicit Slot(uint16_t* data) : _data(data) {} explicit Slot(uint16_t* data) : _data(data), _counter(nullptr) {}
~Slot() { ~Slot() {
// Not responsible for anything // Not responsible for anything
@ -81,9 +85,14 @@ class RocksDBCuckooIndexEstimator {
bool operator==(const Slot& other) { return _data == other._data; } bool operator==(const Slot& other) { return _data == other._data; }
uint16_t* fingerprint() const { return _data; } uint16_t* fingerprint() const {
TRI_ASSERT(_data != nullptr);
uint16_t* counter() { return _data + 1; } return _data;
}
uint32_t* counter() const {
TRI_ASSERT(_counter != nullptr);
return _counter;
}
void reset() { void reset() {
*fingerprint() = 0; *fingerprint() = 0;
@ -93,22 +102,71 @@ class RocksDBCuckooIndexEstimator {
bool isEqual(uint16_t fp) const { return ((*fingerprint()) == fp); } bool isEqual(uint16_t fp) const { return ((*fingerprint()) == fp); }
bool isEmpty() const { return (*fingerprint()) == 0; } bool isEmpty() const { return (*fingerprint()) == 0; }
// If this returns FALSE we have removed the
// last element => we need to remove the fingerprint as well.
bool decrease() {
if (*counter() > 1) {
(*counter())--;
return true;
}
return false;
}
void increase() {
if ((*counter()) < UINT32_MAX) {
(*counter())++;
}
}
void init(uint16_t fp) {
// This is the first element
*fingerprint() = fp;
*counter() = 1;
}
void swap(uint16_t& fp, uint32_t& cnt) {
std::swap(*fingerprint(), fp);
std::swap(*counter(), cnt);
}
void injectCounter(uint32_t* cnt) { _counter = cnt; }
}; };
enum SerializeFormat : char { enum SerializeFormat : char {
// To describe this format we use | as a seperator for readability, but it // To describe this format we use | as a seperator for readability, but it
// is NOT a printed character in the serialized string // is NOT a printed character in the serialized string
// NOCOMPRESSION: type|length|size|nrUsed|nrCuckood|nrTotal|niceSize|logSize|base // NOCOMPRESSION:
NOCOMPRESSION = '0' // type|length|size|nrUsed|nrCuckood|nrTotal|niceSize|logSize|base|counters
NOCOMPRESSION = '1'
}; };
public: public:
static bool isFormatSupported(StringRef serialized) {
switch (serialized.front()) {
case SerializeFormat::NOCOMPRESSION:
return true;
}
return false;
}
RocksDBCuckooIndexEstimator(uint64_t size) RocksDBCuckooIndexEstimator(uint64_t size)
: _randState(0x2636283625154737ULL), : _randState(0x2636283625154737ULL),
_slotSize(2 * sizeof(uint16_t)), // Sort out offsets and alignments _slotSize(sizeof(uint16_t)), // Sort out offsets and alignments
_counterSize(sizeof(uint32_t)), // Sort out offsets and alignments
_logSize(0),
_size(0),
_niceSize(0),
_sizeMask(0),
_sizeShift(0),
_slotAllocSize(0),
_counterAllocSize(0),
_base(nullptr), _base(nullptr),
_allocBase(nullptr), _slotBase(nullptr),
_counters(nullptr),
_counterBase(nullptr),
_nrUsed(0), _nrUsed(0),
_nrCuckood(0), _nrCuckood(0),
_nrTotal(0), _nrTotal(0),
@ -125,9 +183,19 @@ class RocksDBCuckooIndexEstimator {
RocksDBCuckooIndexEstimator(arangodb::StringRef const serialized) RocksDBCuckooIndexEstimator(arangodb::StringRef const serialized)
: _randState(0x2636283625154737ULL), : _randState(0x2636283625154737ULL),
_slotSize(2 * sizeof(uint16_t)), // Sort out offsets and alignments _slotSize(sizeof(uint16_t)), // Sort out offsets and alignments
_counterSize(sizeof(uint32_t)), // Sort out offsets and alignments
_logSize(0),
_size(0),
_niceSize(0),
_sizeMask(0),
_sizeShift(0),
_slotAllocSize(0),
_counterAllocSize(0),
_base(nullptr), _base(nullptr),
_allocBase(nullptr), _slotBase(nullptr),
_counters(nullptr),
_counterBase(nullptr),
_nrUsed(0), _nrUsed(0),
_nrCuckood(0), _nrCuckood(0),
_nrTotal(0), _nrTotal(0),
@ -138,14 +206,18 @@ class RocksDBCuckooIndexEstimator {
break; break;
} }
default: { default: {
LOG_TOPIC(ERR, arangodb::Logger::ENGINES) << LOG_TOPIC(WARN, arangodb::Logger::ENGINES)
"unable to restore index estimates: invalid format found"; << "unable to restore index estimates: invalid format found";
initializeDefault(); // Do not construct from serialisation, use other constructor instead
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
} }
} }
} }
~RocksDBCuckooIndexEstimator() { delete[] _allocBase; } ~RocksDBCuckooIndexEstimator() {
delete[] _slotBase;
delete[] _counterBase;
}
RocksDBCuckooIndexEstimator(RocksDBCuckooIndexEstimator const&) = delete; RocksDBCuckooIndexEstimator(RocksDBCuckooIndexEstimator const&) = delete;
RocksDBCuckooIndexEstimator(RocksDBCuckooIndexEstimator&&) = delete; RocksDBCuckooIndexEstimator(RocksDBCuckooIndexEstimator&&) = delete;
@ -162,16 +234,19 @@ class RocksDBCuckooIndexEstimator {
serialized += SerializeFormat::NOCOMPRESSION; serialized += SerializeFormat::NOCOMPRESSION;
uint64_t serialLength = uint64_t serialLength =
(sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) + sizeof(_nrUsed) + (sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) +
sizeof(_nrCuckood) + sizeof(_nrTotal) + sizeof(_niceSize) + sizeof(_nrUsed) + sizeof(_nrCuckood) + sizeof(_nrTotal) +
sizeof(_logSize) + (_size * _slotSize * SlotsPerBucket)); sizeof(_niceSize) + sizeof(_logSize) +
(_size * _slotSize * SlotsPerBucket)) +
(_size * _counterSize * SlotsPerBucket);
serialized.reserve(sizeof(uint64_t) + serialLength); serialized.reserve(sizeof(uint64_t) + serialLength);
// We always prepend the length, so parsing is easier // We always prepend the length, so parsing is easier
rocksutils::uint64ToPersistent(serialized, serialLength); rocksutils::uint64ToPersistent(serialized, serialLength);
{ {
// Sorry we need a consistent state, so we have to read-lock from here on... // Sorry we need a consistent state, so we have to read-lock from here
// on...
READ_LOCKER(locker, _bucketLock); READ_LOCKER(locker, _bucketLock);
// Add all member variables // Add all member variables
rocksutils::uint64ToPersistent(serialized, _size); rocksutils::uint64ToPersistent(serialized, _size);
@ -183,12 +258,22 @@ class RocksDBCuckooIndexEstimator {
// Add the data blob // Add the data blob
// Size is as follows: nrOfBuckets * SlotsPerBucket * SlotSize // Size is as follows: nrOfBuckets * SlotsPerBucket * SlotSize
TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _allocSize); TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _slotAllocSize);
for (uint64_t i = 0; i < (_size * _slotSize * SlotsPerBucket) / sizeof(uint16_t); for (uint64_t i = 0;
++i) { i < (_size * _slotSize * SlotsPerBucket) ; i += _slotSize) {
rocksutils::uint16ToPersistent(serialized, *(reinterpret_cast<uint16_t*>(_base + i * 2))); rocksutils::uint16ToPersistent(
serialized, *(reinterpret_cast<uint16_t*>(_base + i)));
} }
TRI_ASSERT((_size * _counterSize * SlotsPerBucket) <= _counterAllocSize);
for (uint64_t i = 0;
i < (_size * _counterSize * SlotsPerBucket) ; i += _counterSize) {
rocksutils::uint32ToPersistent(
serialized, *(reinterpret_cast<uint32_t*>(_counters + i)));
}
} }
} }
@ -204,6 +289,7 @@ class RocksDBCuckooIndexEstimator {
for (uint32_t b = 0; b < _size; ++b) { for (uint32_t b = 0; b < _size; ++b) {
for (size_t i = 0; i < SlotsPerBucket; ++i) { for (size_t i = 0; i < SlotsPerBucket; ++i) {
Slot f = findSlot(b, i); Slot f = findSlot(b, i);
f.injectCounter(findCounter(b, i));
f.reset(); f.reset();
} }
} }
@ -262,16 +348,11 @@ class RocksDBCuckooIndexEstimator {
Slot slot = findSlotCuckoo(pos1, pos2, fingerprint); Slot slot = findSlotCuckoo(pos1, pos2, fingerprint);
if (slot.isEmpty()) { if (slot.isEmpty()) {
// Free slot insert ourself. // Free slot insert ourself.
*slot.fingerprint() = fingerprint; slot.init(fingerprint);
*slot.counter() = 1; // We are the first element
_nrUsed++; _nrUsed++;
} else { } else {
TRI_ASSERT(slot.isEqual(fingerprint)); TRI_ASSERT(slot.isEqual(fingerprint));
// TODO replace with constant uint16_t max slot.increase();
if (*slot.counter() < 65536) {
// just to avoid overflow...
(*slot.counter())++;
}
} }
_nrTotal++; _nrTotal++;
} }
@ -297,18 +378,15 @@ class RocksDBCuckooIndexEstimator {
_nrTotal--; _nrTotal--;
Slot slot = findSlotNoCuckoo(pos1, pos2, fingerprint, found); Slot slot = findSlotNoCuckoo(pos1, pos2, fingerprint, found);
if (found) { if (found) {
if (*slot.counter() <= 1) { if (!slot.decrease()) {
// We remove the last one of those, free slot // Removed last element. Have to remove
slot.reset(); slot.reset();
_nrUsed--; _nrUsed--;
} else {
// Just decrease the counter
(*slot.counter())--;
} }
return true; return true;
} }
// If we get here we assume that the element was once inserted, but removed // If we get here we assume that the element was once inserted, but
// by cuckoo // removed by cuckoo
// Reduce nrCuckood; // Reduce nrCuckood;
if (_nrCuckood > 0) { if (_nrCuckood > 0) {
--_nrCuckood; --_nrCuckood;
@ -326,9 +404,9 @@ class RocksDBCuckooIndexEstimator {
uint64_t nrCuckood() const { return _nrCuckood; } uint64_t nrCuckood() const { return _nrCuckood; }
private: // methods private: // methods
uint64_t memoryUsage() const { uint64_t memoryUsage() const {
return sizeof(RocksDBCuckooIndexEstimator) + _allocSize; return sizeof(RocksDBCuckooIndexEstimator) + _slotAllocSize +
_counterAllocSize;
} }
Slot findSlotNoCuckoo(uint64_t pos1, uint64_t pos2, uint16_t fp, Slot findSlotNoCuckoo(uint64_t pos1, uint64_t pos2, uint16_t fp,
@ -359,9 +437,11 @@ class RocksDBCuckooIndexEstimator {
Slot slot = findSlot(pos1, i); Slot slot = findSlot(pos1, i);
if (slot.isEqual(fp)) { if (slot.isEqual(fp)) {
// Found we are done, short-circuit. // Found we are done, short-circuit.
slot.injectCounter(findCounter(pos1, i));
return slot; return slot;
} }
if (!foundEmpty && slot.isEmpty()) { if (!foundEmpty && slot.isEmpty()) {
slot.injectCounter(findCounter(pos1, i));
foundEmpty = true; foundEmpty = true;
firstEmpty = slot; firstEmpty = slot;
} }
@ -371,9 +451,11 @@ class RocksDBCuckooIndexEstimator {
Slot slot = findSlot(pos2, i); Slot slot = findSlot(pos2, i);
if (slot.isEqual(fp)) { if (slot.isEqual(fp)) {
// Found we are done, short-circuit. // Found we are done, short-circuit.
slot.injectCounter(findCounter(pos2, i));
return slot; return slot;
} }
if (!foundEmpty && slot.isEmpty()) { if (!foundEmpty && slot.isEmpty()) {
slot.injectCounter(findCounter(pos2, i));
foundEmpty = true; foundEmpty = true;
firstEmpty = slot; firstEmpty = slot;
} }
@ -388,9 +470,10 @@ class RocksDBCuckooIndexEstimator {
// We also did not find an empty slot, now the cuckoo goes... // We also did not find an empty slot, now the cuckoo goes...
uint16_t counter = // We initially write a 0 in here, because the caller will
0; // We initially write a 0 in here, because the caller will
// Increase the counter by one // Increase the counter by one
uint32_t counter = 0;
uint8_t r = pseudoRandomChoice(); uint8_t r = pseudoRandomChoice();
if ((r & 1) != 0) { if ((r & 1) != 0) {
std::swap(pos1, pos2); std::swap(pos1, pos2);
@ -402,12 +485,8 @@ class RocksDBCuckooIndexEstimator {
r = pseudoRandomChoice(); r = pseudoRandomChoice();
uint64_t i = r & (SlotsPerBucket - 1); uint64_t i = r & (SlotsPerBucket - 1);
firstEmpty = findSlot(pos1, i); firstEmpty = findSlot(pos1, i);
uint16_t fDummy = *firstEmpty.fingerprint(); firstEmpty.injectCounter(findCounter(pos1, i));
uint16_t cDummy = *firstEmpty.counter(); firstEmpty.swap(fp, counter);
*firstEmpty.fingerprint() = fp;
*firstEmpty.counter() = counter;
fp = fDummy;
counter = cDummy;
uint64_t hash2 = _hasherPosFingerprint(pos1, fp); uint64_t hash2 = _hasherPosFingerprint(pos1, fp);
pos2 = hashToPos(hash2); pos2 = hashToPos(hash2);
@ -417,6 +496,7 @@ class RocksDBCuckooIndexEstimator {
for (uint64_t i = 0; i < SlotsPerBucket; ++i) { for (uint64_t i = 0; i < SlotsPerBucket; ++i) {
Slot slot = findSlot(pos2, i); Slot slot = findSlot(pos2, i);
if (slot.isEmpty()) { if (slot.isEmpty()) {
slot.injectCounter(findCounter(pos2, i));
// Yeah we found an empty place already // Yeah we found an empty place already
*slot.fingerprint() = fp; *slot.fingerprint() = fp;
*slot.counter() = counter; *slot.counter() = counter;
@ -439,12 +519,8 @@ class RocksDBCuckooIndexEstimator {
i = (i + 1) % SlotsPerBucket; i = (i + 1) % SlotsPerBucket;
slot = findSlot(pos1, i); slot = findSlot(pos1, i);
} }
fDummy = *slot.fingerprint(); slot.injectCounter(findCounter(pos1, i));
cDummy = *slot.counter(); slot.swap(fp, counter);
*slot.fingerprint() = fp;
*slot.counter() = counter;
fp = fDummy;
counter = cDummy;
hash2 = _hasherPosFingerprint(pos1, fp); hash2 = _hasherPosFingerprint(pos1, fp);
pos2 = hashToPos(hash2); pos2 = hashToPos(hash2);
@ -452,6 +528,7 @@ class RocksDBCuckooIndexEstimator {
for (uint64_t i = 0; i < SlotsPerBucket; ++i) { for (uint64_t i = 0; i < SlotsPerBucket; ++i) {
Slot slot = findSlot(pos2, i); Slot slot = findSlot(pos2, i);
if (slot.isEmpty()) { if (slot.isEmpty()) {
slot.injectCounter(findCounter(pos2, i));
// Finally an empty place // Finally an empty place
*slot.fingerprint() = fp; *slot.fingerprint() = fp;
*slot.counter() = counter; *slot.counter() = counter;
@ -472,6 +549,7 @@ class RocksDBCuckooIndexEstimator {
for (uint64_t i = 0; i < SlotsPerBucket; ++i) { for (uint64_t i = 0; i < SlotsPerBucket; ++i) {
Slot slot = findSlot(pos, i); Slot slot = findSlot(pos, i);
if (fp == *slot.fingerprint()) { if (fp == *slot.fingerprint()) {
slot.injectCounter(findCounter(pos, i));
found = true; found = true;
return slot; return slot;
} }
@ -480,11 +558,18 @@ class RocksDBCuckooIndexEstimator {
} }
Slot findSlot(uint64_t pos, uint64_t slot) const { Slot findSlot(uint64_t pos, uint64_t slot) const {
TRI_ASSERT(_slotSize * (pos * SlotsPerBucket + slot) <= _slotAllocSize );
char* address = _base + _slotSize * (pos * SlotsPerBucket + slot); char* address = _base + _slotSize * (pos * SlotsPerBucket + slot);
auto ret = reinterpret_cast<uint16_t*>(address); auto ret = reinterpret_cast<uint16_t*>(address);
return Slot(ret); return Slot(ret);
} }
uint32_t* findCounter(uint64_t pos, uint64_t slot) const {
TRI_ASSERT(_counterSize * (pos * SlotsPerBucket + slot) <= _counterAllocSize );
char* address = _counters + _counterSize * (pos * SlotsPerBucket + slot);
return reinterpret_cast<uint32_t*>(address);
}
uint64_t hashToPos(uint64_t hash) const { uint64_t hashToPos(uint64_t hash) const {
uint64_t relevantBits = (hash >> _sizeShift) & _sizeMask; uint64_t relevantBits = (hash >> _sizeShift) & _sizeMask;
return ((relevantBits < _size) ? relevantBits : (relevantBits - _size)); return ((relevantBits < _size) ? relevantBits : (relevantBits - _size));
@ -508,53 +593,72 @@ class RocksDBCuckooIndexEstimator {
void deserializeUncompressed(arangodb::StringRef const& serialized) { void deserializeUncompressed(arangodb::StringRef const& serialized) {
// Assert that we have at least the member variables // Assert that we have at least the member variables
TRI_ASSERT(serialized.size() >= (sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) + sizeof(_nrUsed) + TRI_ASSERT(serialized.size() >=
sizeof(_nrCuckood) + sizeof(_nrTotal) + sizeof(_niceSize) + (sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) +
sizeof(_logSize) )); sizeof(_nrUsed) + sizeof(_nrCuckood) + sizeof(_nrTotal) +
sizeof(_niceSize) + sizeof(_logSize)));
char const* current = serialized.data(); char const* current = serialized.data();
TRI_ASSERT(*current == SerializeFormat::NOCOMPRESSION); TRI_ASSERT(*current == SerializeFormat::NOCOMPRESSION);
current++; // Skip format char current++; // Skip format char
uint64_t length = rocksutils::uint64FromPersistent(current); uint64_t length = rocksutils::uint64FromPersistent(current);
current += sizeof(uint64_t); current += sizeof(uint64_t);
// Validate that the serialized format is exactly as long as we expect it to be // Validate that the serialized format is exactly as long as we expect it to
// be
TRI_ASSERT(serialized.size() == length); TRI_ASSERT(serialized.size() == length);
_size = rocksutils::uint64FromPersistent(current); _size = rocksutils::uint64FromPersistent(current);
current += sizeof(_size); current += sizeof(uint64_t);
if (_size <= 256) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
_nrUsed = rocksutils::uint64FromPersistent(current); _nrUsed = rocksutils::uint64FromPersistent(current);
current += sizeof(_nrUsed); current += sizeof(uint64_t);
_nrCuckood = rocksutils::uint64FromPersistent(current); _nrCuckood = rocksutils::uint64FromPersistent(current);
current += sizeof(_nrCuckood); current += sizeof(uint64_t);
_nrTotal = rocksutils::uint64FromPersistent(current); _nrTotal = rocksutils::uint64FromPersistent(current);
current += sizeof(_nrTotal); current += sizeof(uint64_t);
_niceSize = rocksutils::uint64FromPersistent(current); _niceSize = rocksutils::uint64FromPersistent(current);
current += sizeof(_niceSize); current += sizeof(uint64_t);
_logSize = rocksutils::uint64FromPersistent(current); _logSize = rocksutils::uint64FromPersistent(current);
current += sizeof(_logSize); current += sizeof(uint64_t);
deriveSizesAndAlloc(); deriveSizesAndAlloc();
// Validate that we have enough data in the serialized format. // Validate that we have enough data in the serialized format.
TRI_ASSERT(serialized.size() == TRI_ASSERT(serialized.size() ==
(sizeof(SerializeFormat) + sizeof( uint64_t) + sizeof(_size) + sizeof(_nrUsed) + (sizeof(SerializeFormat) + sizeof(uint64_t) + sizeof(_size) +
sizeof(_nrCuckood) + sizeof(_nrTotal) + sizeof(_niceSize) + sizeof(_nrUsed) + sizeof(_nrCuckood) + sizeof(_nrTotal) +
sizeof(_logSize) + (_size * _slotSize * SlotsPerBucket))); sizeof(_niceSize) + sizeof(_logSize) +
(_size * _slotSize * SlotsPerBucket)) +
(_size * _counterSize * SlotsPerBucket));
// Insert the raw data // Insert the raw data
// Size is as follows: nrOfBuckets * SlotsPerBucket * SlotSize // Size is as follows: nrOfBuckets * SlotsPerBucket * SlotSize
TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _allocSize); TRI_ASSERT((_size * _slotSize * SlotsPerBucket) <= _slotAllocSize);
for (uint64_t i = 0; i < (_size * _slotSize * SlotsPerBucket) / sizeof(uint16_t); for (uint64_t i = 0;
++i) { i < (_size * _slotSize * SlotsPerBucket) ; i += _slotSize) {
*(reinterpret_cast<uint16_t*>(_base + i * 2)) = rocksutils::uint16FromPersistent(current + (i * sizeof(uint16_t))); *(reinterpret_cast<uint16_t*>(_base + i)) =
rocksutils::uint16FromPersistent(current);
current += _slotSize;
} }
TRI_ASSERT((_size * _counterSize * SlotsPerBucket) <= _counterAllocSize);
for (uint64_t i = 0;
i < (_size * _counterSize * SlotsPerBucket); i += _counterSize) {
*(reinterpret_cast<uint32_t*>(_counters + i)) =
rocksutils::uint32FromPersistent(current);
current += _counterSize;
}
} }
void initializeDefault() { void initializeDefault() {
@ -571,6 +675,7 @@ class RocksDBCuckooIndexEstimator {
for (uint32_t b = 0; b < _size; ++b) { for (uint32_t b = 0; b < _size; ++b) {
for (size_t i = 0; i < SlotsPerBucket; ++i) { for (size_t i = 0; i < SlotsPerBucket; ++i) {
Slot f = findSlot(b, i); Slot f = findSlot(b, i);
f.injectCounter(findCounter(b, i));
f.reset(); f.reset();
} }
} }
@ -579,12 +684,24 @@ class RocksDBCuckooIndexEstimator {
void deriveSizesAndAlloc() { void deriveSizesAndAlloc() {
_sizeMask = _niceSize - 1; _sizeMask = _niceSize - 1;
_sizeShift = static_cast<uint32_t>((64 - _logSize) / 2); _sizeShift = static_cast<uint32_t>((64 - _logSize) / 2);
_allocSize = _size * _slotSize * SlotsPerBucket +
64; // give 64 bytes padding to enable 64-byte alignment // give 64 bytes padding to enable 64-byte alignment
_allocBase = new char[_allocSize]; _slotAllocSize = _size * _slotSize * SlotsPerBucket + 64;
_slotBase = new char[_slotAllocSize];
_base = reinterpret_cast<char*>( _base = reinterpret_cast<char*>(
(reinterpret_cast<uintptr_t>(_allocBase) + 63) & (reinterpret_cast<uintptr_t>(_slotBase) + 63) &
~((uintptr_t)0x3fu)); // to actually implement the 64-byte alignment,
// shift base pointer within allocated space to
// 64-byte boundary
// give 64 bytes padding to enable 64-byte alignment
_counterAllocSize = _size * _counterSize * SlotsPerBucket + 64;
_counterBase = new char[_counterAllocSize];
_counters = reinterpret_cast<char*>(
(reinterpret_cast<uintptr_t>(_counterBase) + 63) &
~((uintptr_t)0x3fu)); // to actually implement the 64-byte alignment, ~((uintptr_t)0x3fu)); // to actually implement the 64-byte alignment,
// shift base pointer within allocated space to // shift base pointer within allocated space to
// 64-byte boundary // 64-byte boundary
@ -594,6 +711,7 @@ class RocksDBCuckooIndexEstimator {
uint64_t _randState; // pseudo random state for expunging uint64_t _randState; // pseudo random state for expunging
size_t _slotSize; // total size of a slot size_t _slotSize; // total size of a slot
size_t _counterSize; // total size of a counter
uint64_t _logSize; // logarithm (base 2) of number of buckets uint64_t _logSize; // logarithm (base 2) of number of buckets
uint64_t _size; // actual number of buckets uint64_t _size; // actual number of buckets
@ -601,10 +719,14 @@ class RocksDBCuckooIndexEstimator {
// 2^_logSize // 2^_logSize
uint64_t _sizeMask; // used to mask out some bits from the hash uint64_t _sizeMask; // used to mask out some bits from the hash
uint32_t _sizeShift; // used to shift the bits down to get a position uint32_t _sizeShift; // used to shift the bits down to get a position
uint64_t _allocSize; // number of allocated bytes, uint64_t _slotAllocSize; // number of allocated bytes for the slots,
// == _size * SlotsPerBucket * _slotSize + 64 // == _size * SlotsPerBucket * _slotSize + 64
uint64_t _counterAllocSize; // number of allocated bytes ofr the counters,
// == _size * SlotsPerBucket * _counterSize + 64
char* _base; // pointer to allocated space, 64-byte aligned char* _base; // pointer to allocated space, 64-byte aligned
char* _allocBase; // base of original allocation char* _slotBase; // base of original allocation
char* _counters; // pointer to allocated space, 64-byte aligned
char* _counterBase; // base of original counter allocation
uint64_t _nrUsed; // number of pairs stored in the table uint64_t _nrUsed; // number of pairs stored in the table
uint64_t _nrCuckood; // number of elements that have been removed by cuckoo uint64_t _nrCuckood; // number of elements that have been removed by cuckoo
uint64_t _nrTotal; // number of elements included in total uint64_t _nrTotal; // number of elements included in total

View File

@ -24,6 +24,7 @@
#include "v8-query.h" #include "v8-query.h"
#include "Aql/Query.h" #include "Aql/Query.h"
#include "Aql/QueryResultV8.h" #include "Aql/QueryResultV8.h"
#include "Aql/QueryString.h"
#include "Basics/StaticStrings.h" #include "Basics/StaticStrings.h"
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Basics/fasthash.h" #include "Basics/fasthash.h"
@ -61,7 +62,7 @@ aql::QueryResultV8 AqlQuery(
TRI_ASSERT(col != nullptr); TRI_ASSERT(col != nullptr);
TRI_GET_GLOBALS(); TRI_GET_GLOBALS();
arangodb::aql::Query query(true, col->vocbase(), aql.c_str(), aql.size(), arangodb::aql::Query query(true, col->vocbase(), arangodb::aql::QueryString(aql),
bindVars, nullptr, arangodb::aql::PART_MAIN); bindVars, nullptr, arangodb::aql::PART_MAIN);
auto queryResult = query.executeV8( auto queryResult = query.executeV8(

View File

@ -42,6 +42,7 @@
#include "Aql/QueryExecutionState.h" #include "Aql/QueryExecutionState.h"
#include "Aql/QueryList.h" #include "Aql/QueryList.h"
#include "Aql/QueryRegistry.h" #include "Aql/QueryRegistry.h"
#include "Aql/QueryString.h"
#include "Basics/HybridLogicalClock.h" #include "Basics/HybridLogicalClock.h"
#include "Basics/MutexLocker.h" #include "Basics/MutexLocker.h"
#include "Basics/ScopeGuard.h" #include "Basics/ScopeGuard.h"
@ -744,8 +745,8 @@ static void JS_ParseAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
std::string const queryString(TRI_ObjectToString(args[0])); std::string const queryString(TRI_ObjectToString(args[0]));
arangodb::aql::Query query(true, vocbase, queryString.c_str(), arangodb::aql::Query query(true, vocbase, aql::QueryString(queryString),
queryString.size(), nullptr, nullptr, nullptr, nullptr,
arangodb::aql::PART_MAIN); arangodb::aql::PART_MAIN);
auto parseResult = query.parse(); auto parseResult = query.parse();
@ -882,8 +883,8 @@ static void JS_ExplainAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
} }
// bind parameters will be freed by the query later // bind parameters will be freed by the query later
arangodb::aql::Query query(true, vocbase, queryString.c_str(), arangodb::aql::Query query(true, vocbase, aql::QueryString(queryString),
queryString.size(), bindVars, options, bindVars, options,
arangodb::aql::PART_MAIN); arangodb::aql::PART_MAIN);
auto queryResult = query.explain(); auto queryResult = query.explain();
@ -1070,8 +1071,8 @@ static void JS_ExecuteAql(v8::FunctionCallbackInfo<v8::Value> const& args) {
// bind parameters will be freed by the query later // bind parameters will be freed by the query later
TRI_GET_GLOBALS(); TRI_GET_GLOBALS();
arangodb::aql::Query query(true, vocbase, queryString.c_str(), arangodb::aql::Query query(true, vocbase, aql::QueryString(queryString),
queryString.size(), bindVars, options, bindVars, options,
arangodb::aql::PART_MAIN); arangodb::aql::PART_MAIN);
auto queryResult = query.executeV8( auto queryResult = query.executeV8(

View File

@ -24,6 +24,7 @@
#include "AuthInfo.h" #include "AuthInfo.h"
#include "Aql/Query.h" #include "Aql/Query.h"
#include "Aql/QueryString.h"
#include "Basics/ReadLocker.h" #include "Basics/ReadLocker.h"
#include "Basics/VelocyPackHelper.h" #include "Basics/VelocyPackHelper.h"
#include "Basics/WriteLocker.h" #include "Basics/WriteLocker.h"
@ -266,8 +267,8 @@ void AuthInfo::reload() {
std::string const queryStr("FOR user IN _users RETURN user"); std::string const queryStr("FOR user IN _users RETURN user");
auto emptyBuilder = std::make_shared<VPackBuilder>(); auto emptyBuilder = std::make_shared<VPackBuilder>();
arangodb::aql::Query query(false, vocbase, queryStr.c_str(), arangodb::aql::Query query(false, vocbase, arangodb::aql::QueryString(queryStr),
queryStr.size(), emptyBuilder, emptyBuilder, emptyBuilder, emptyBuilder,
arangodb::aql::PART_MAIN); arangodb::aql::PART_MAIN);
LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "starting to load authentication and authorization information"; LOG_TOPIC(DEBUG, arangodb::Logger::FIXME) << "starting to load authentication and authorization information";
@ -448,8 +449,8 @@ AuthResult AuthInfo::checkPassword(std::string const& username,
binds.close(); // user binds.close(); // user
binds.close(); // obj binds.close(); // obj
arangodb::aql::Query query(false, vocbase, queryStr.c_str(), arangodb::aql::Query query(false, vocbase, arangodb::aql::QueryString(queryStr),
queryStr.size(), std::make_shared<VPackBuilder>(binds), emptyBuilder, std::make_shared<VPackBuilder>(binds), emptyBuilder,
arangodb::aql::PART_MAIN); arangodb::aql::PART_MAIN);
TRI_ASSERT(_queryRegistry != nullptr); TRI_ASSERT(_queryRegistry != nullptr);

View File

@ -1657,8 +1657,6 @@ std::string TRI_BinaryName(char const* argv0) {
std::string TRI_LocateBinaryPath(char const* argv0) { std::string TRI_LocateBinaryPath(char const* argv0) {
#if _WIN32 #if _WIN32
if (argv0 == nullptr) {
char buff[4096]; char buff[4096];
int res = GetModuleFileName(NULL, buff, sizeof(buff)); int res = GetModuleFileName(NULL, buff, sizeof(buff));
@ -1680,9 +1678,8 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
} }
return std::string(); return std::string();
}
#endif #else
std::string binaryPath; std::string binaryPath;
@ -1736,6 +1733,7 @@ std::string TRI_LocateBinaryPath(char const* argv0) {
} }
return binaryPath; return binaryPath;
#endif
} }
std::string TRI_GetInstallRoot(std::string const& binaryPath, std::string TRI_GetInstallRoot(std::string const& binaryPath,