Revise user visible error messages
Summary: A quick clean-up of user visible error messages. Tried to make them gramatically correct by capitalizing the first word in the sentence and putting a dot at the end. Reviewers: teon.banek, buda, ipaljak Reviewed By: teon.banek Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1571
This commit is contained in:
parent
28ba872668
commit
bff56bcf89
@ -9,7 +9,7 @@ namespace mvcc {
|
||||
|
||||
class SerializationError : public utils::BasicException {
|
||||
static constexpr const char *default_message =
|
||||
"Can't serialize due to concurrent operations";
|
||||
"Can't serialize due to concurrent operations.";
|
||||
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
|
@ -18,7 +18,7 @@ int64_t ParseIntegerLiteral(const std::string &s) {
|
||||
// Not really correct since long long can have a bigger range than int64_t.
|
||||
return static_cast<int64_t>(std::stoll(s, 0, 0));
|
||||
} catch (const std::out_of_range &) {
|
||||
throw SemanticException("Integer literal exceeds 64 bits");
|
||||
throw SemanticException("Integer literal exceeds 64 bits.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -55,12 +55,12 @@ std::string ParseStringLiteral(const std::string &s) {
|
||||
// t is high surrogate pair. Expect one more utf16 codepoint.
|
||||
j = i + kShortUnicodeLength + 1;
|
||||
if (j >= static_cast<int>(s.size()) - 1 || s[j] != '\\') {
|
||||
throw SemanticException("Invalid utf codepoint");
|
||||
throw SemanticException("Invalid UTF codepoint.");
|
||||
}
|
||||
++j;
|
||||
if (j >= static_cast<int>(s.size()) - 1 ||
|
||||
(s[j] != 'u' && s[j] != 'U')) {
|
||||
throw SemanticException("Invalid utf codepoint");
|
||||
throw SemanticException("Invalid UTF codepoint.");
|
||||
}
|
||||
++j;
|
||||
int k = j;
|
||||
@ -69,7 +69,7 @@ std::string ParseStringLiteral(const std::string &s) {
|
||||
++k;
|
||||
}
|
||||
if (k != j + kShortUnicodeLength) {
|
||||
throw SemanticException("Invalid utf codepoint");
|
||||
throw SemanticException("Invalid UTF codepoint.");
|
||||
}
|
||||
char16_t surrogates[3] = {t,
|
||||
static_cast<char16_t>(stoi(
|
||||
@ -131,14 +131,14 @@ std::string ParseStringLiteral(const std::string &s) {
|
||||
try {
|
||||
unescaped += EncodeEscapedUnicodeCodepointUtf32(s, i);
|
||||
} catch (const std::range_error &) {
|
||||
throw SemanticException("Invalid utf codepoint");
|
||||
throw SemanticException("Invalid UTF codepoint.");
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
try {
|
||||
unescaped += EncodeEscapedUnicodeCodepointUtf16(s, i);
|
||||
} catch (const std::range_error &) {
|
||||
throw SemanticException("Invalid utf codepoint");
|
||||
throw SemanticException("Invalid UTF codepoint.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -161,7 +161,7 @@ double ParseDoubleLiteral(const std::string &s) {
|
||||
try {
|
||||
return utils::ParseDouble(s);
|
||||
} catch (const utils::BasicException &) {
|
||||
throw SemanticException("Couldn't parse string to double");
|
||||
throw SemanticException("Couldn't parse string to double.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,7 +229,7 @@ bool TypedValueCompare(const TypedValue &a, const TypedValue &b) {
|
||||
// the same type, or int+float combinations
|
||||
if ((a.type() != b.type() && !(a.IsNumeric() && b.IsNumeric())))
|
||||
throw QueryRuntimeException(
|
||||
"Can't compare value of type {} to value of type {}", a.type(),
|
||||
"Can't compare value of type {} to value of type {}.", a.type(),
|
||||
b.type());
|
||||
|
||||
switch (a.type()) {
|
||||
@ -253,7 +253,7 @@ bool TypedValueCompare(const TypedValue &a, const TypedValue &b) {
|
||||
case TypedValue::Type::Edge:
|
||||
case TypedValue::Type::Path:
|
||||
throw QueryRuntimeException(
|
||||
"Comparison is not defined for values of type {}", a.type());
|
||||
"Comparison is not defined for values of type {}.", a.type());
|
||||
default:
|
||||
LOG(FATAL) << "Unhandled comparison for types";
|
||||
}
|
||||
|
@ -46,13 +46,13 @@ class SemanticException : public QueryException {
|
||||
class UnboundVariableError : public SemanticException {
|
||||
public:
|
||||
explicit UnboundVariableError(const std::string &name)
|
||||
: SemanticException("Unbound variable: " + name) {}
|
||||
: SemanticException("Unbound variable: " + name + ".") {}
|
||||
};
|
||||
|
||||
class RedeclareVariableError : public SemanticException {
|
||||
public:
|
||||
explicit RedeclareVariableError(const std::string &name)
|
||||
: SemanticException("Redeclaring variable: " + name) {}
|
||||
: SemanticException("Redeclaring variable: " + name + ".") {}
|
||||
};
|
||||
|
||||
class TypeMismatchError : public SemanticException {
|
||||
@ -60,7 +60,7 @@ class TypeMismatchError : public SemanticException {
|
||||
TypeMismatchError(const std::string &name, const std::string &datum,
|
||||
const std::string &expected)
|
||||
: SemanticException(fmt::format(
|
||||
"Type mismatch: '{}' already defined as '{}', but expected '{}'.",
|
||||
"Type mismatch: {} already defined as {}, expected {}.",
|
||||
name, datum, expected)) {}
|
||||
};
|
||||
|
||||
@ -74,7 +74,7 @@ class IndexInMulticommandTxException : public QueryException {
|
||||
using QueryException::QueryException;
|
||||
IndexInMulticommandTxException()
|
||||
: QueryException(
|
||||
"Index creation not allowed in multicommand transactions") {}
|
||||
"CREATE INDEX not allowed in multicommand transactions.") {}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -96,7 +96,7 @@ class HintedAbortError : public utils::BasicException {
|
||||
: utils::BasicException(
|
||||
"Transaction was asked to abort, most likely because it was "
|
||||
"executing longer than time specified by "
|
||||
"--query-execution-time-sec flag") {}
|
||||
"--query-execution-time-sec flag.") {}
|
||||
};
|
||||
|
||||
class ReconstructionException : public QueryException {
|
||||
@ -111,7 +111,7 @@ class RemoveAttachedVertexException : public QueryRuntimeException {
|
||||
public:
|
||||
RemoveAttachedVertexException()
|
||||
: QueryRuntimeException(
|
||||
"Failed to remove vertex because of it's existing "
|
||||
"Failed to remove node because of it's existing "
|
||||
"connections. Consider using DETACH DELETE.") {}
|
||||
};
|
||||
|
||||
@ -119,14 +119,15 @@ class UserModificationInMulticommandTxException : public QueryException {
|
||||
public:
|
||||
UserModificationInMulticommandTxException()
|
||||
: QueryException(
|
||||
"User modification not allowed in multicommand transactions") {}
|
||||
"Authentication clause not allowed in multicommand transactions.") {
|
||||
}
|
||||
};
|
||||
|
||||
class StreamClauseInMulticommandTxException : public QueryException {
|
||||
public:
|
||||
StreamClauseInMulticommandTxException()
|
||||
: QueryException(
|
||||
"Stream clause not allowed in multicommand transactions") {}
|
||||
"Stream clause not allowed in multicommand transactions.") {}
|
||||
};
|
||||
|
||||
} // namespace query
|
||||
|
@ -129,16 +129,17 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
||||
if (dynamic_cast<Unwind *>(clause)) {
|
||||
if (has_update || has_return) {
|
||||
throw SemanticException(
|
||||
"Unwind can't be after return or update clause");
|
||||
"UNWIND can't be put after RETURN clause or after an update.");
|
||||
}
|
||||
} else if (auto *match = dynamic_cast<Match *>(clause)) {
|
||||
if (has_update || has_return) {
|
||||
throw SemanticException("Match can't be after return or update clause");
|
||||
throw SemanticException(
|
||||
"MATCH can't be put after RETURN clause or after an update.");
|
||||
}
|
||||
if (match->optional_) {
|
||||
has_optional_match = true;
|
||||
} else if (has_optional_match) {
|
||||
throw SemanticException("Match can't be after optional match");
|
||||
throw SemanticException("MATCH can't be put after OPTIONAL MATCH.");
|
||||
}
|
||||
} else if (dynamic_cast<Create *>(clause) ||
|
||||
dynamic_cast<Delete *>(clause) ||
|
||||
@ -149,24 +150,24 @@ antlrcpp::Any CypherMainVisitor::visitSingleQuery(
|
||||
dynamic_cast<RemoveLabels *>(clause) ||
|
||||
dynamic_cast<Merge *>(clause)) {
|
||||
if (has_return) {
|
||||
throw SemanticException("Update clauses can't be after return");
|
||||
throw SemanticException("Update clause can't be used after RETURN.");
|
||||
}
|
||||
has_update = true;
|
||||
} else if (dynamic_cast<Return *>(clause)) {
|
||||
if (has_return) {
|
||||
throw SemanticException("There can be only one return in a clause");
|
||||
throw SemanticException("There can only be one RETURN in a clause.");
|
||||
}
|
||||
has_return = true;
|
||||
} else if (dynamic_cast<With *>(clause)) {
|
||||
if (has_return) {
|
||||
throw SemanticException("Return can't be before with");
|
||||
throw SemanticException("RETURN can't be put before WITH.");
|
||||
}
|
||||
has_update = has_return = has_optional_match = false;
|
||||
} else if (dynamic_cast<CreateIndex *>(clause)) {
|
||||
// If there is CreateIndex clause then there shouldn't be anything else.
|
||||
if (single_query->clauses_.size() != 1U) {
|
||||
throw SemanticException(
|
||||
"CreateIndex must be only clause in the query.");
|
||||
"CREATE INDEX must be the only clause in a query.");
|
||||
}
|
||||
has_create_index = true;
|
||||
} else {
|
||||
@ -272,7 +273,7 @@ antlrcpp::Any CypherMainVisitor::visitUserOrRoleName(
|
||||
std::string value = ctx->symbolicName()->accept(this).as<std::string>();
|
||||
const std::regex NAME_REGEX("[a-zA-Z0-9_.+-]+");
|
||||
if (!std::regex_match(value, NAME_REGEX)) {
|
||||
throw SyntaxException("invalid user or role name");
|
||||
throw SyntaxException("Invalid user or role name.");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@ -319,7 +320,7 @@ antlrcpp::Any CypherMainVisitor::visitCreateUser(
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
if (ctx->password) {
|
||||
if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
|
||||
throw SyntaxException("password should be a string literal or NULL");
|
||||
throw SyntaxException("Password should be a string literal or null.");
|
||||
}
|
||||
auth->password_ = ctx->password->accept(this);
|
||||
}
|
||||
@ -335,7 +336,7 @@ antlrcpp::Any CypherMainVisitor::visitSetPassword(
|
||||
auth->action_ = AuthQuery::Action::SET_PASSWORD;
|
||||
auth->user_ = ctx->user->accept(this).as<std::string>();
|
||||
if (!ctx->password->StringLiteral() && !ctx->literal()->CYPHERNULL()) {
|
||||
throw SyntaxException("password should be a string literal or NULL");
|
||||
throw SyntaxException("Password should be a string literal or null.");
|
||||
}
|
||||
auth->password_ = ctx->password->accept(this);
|
||||
return auth;
|
||||
@ -499,17 +500,17 @@ antlrcpp::Any CypherMainVisitor::visitCreateStream(
|
||||
MemgraphCypher::CreateStreamContext *ctx) {
|
||||
std::string stream_name(ctx->streamName()->getText());
|
||||
if (!ctx->streamUri->StringLiteral()) {
|
||||
throw SyntaxException("Stream URI should be a string literal!");
|
||||
throw SyntaxException("Stream URI should be a string literal.");
|
||||
}
|
||||
Expression *stream_uri = ctx->streamUri->accept(this);
|
||||
|
||||
if (!ctx->streamTopic->StringLiteral()) {
|
||||
throw SyntaxException("Topic should be a string literal!");
|
||||
throw SyntaxException("Topic should be a string literal.");
|
||||
}
|
||||
Expression *stream_topic = ctx->streamTopic->accept(this);
|
||||
|
||||
if (!ctx->transformUri->StringLiteral()) {
|
||||
throw SyntaxException("Transform URI should be a string literal!");
|
||||
throw SyntaxException("Transform URI should be a string literal.");
|
||||
}
|
||||
Expression *transform_uri = ctx->transformUri->accept(this);
|
||||
|
||||
@ -535,7 +536,7 @@ antlrcpp::Any CypherMainVisitor::visitBatchIntervalOption(
|
||||
MemgraphCypher::BatchIntervalOptionContext *ctx) {
|
||||
if (!ctx->literal()->numberLiteral() ||
|
||||
!ctx->literal()->numberLiteral()->integerLiteral()) {
|
||||
throw SyntaxException("Batch interval should be an integer literal!");
|
||||
throw SyntaxException("Batch interval should be an integer.");
|
||||
}
|
||||
return ctx->literal()->accept(this);
|
||||
}
|
||||
@ -547,7 +548,7 @@ antlrcpp::Any CypherMainVisitor::visitBatchSizeOption(
|
||||
MemgraphCypher::BatchSizeOptionContext *ctx) {
|
||||
if (!ctx->literal()->numberLiteral() ||
|
||||
!ctx->literal()->numberLiteral()->integerLiteral()) {
|
||||
throw SyntaxException("Batch size should be an integer literal!");
|
||||
throw SyntaxException("Batch size should be an integer.");
|
||||
}
|
||||
return ctx->literal()->accept(this);
|
||||
}
|
||||
@ -579,7 +580,7 @@ antlrcpp::Any CypherMainVisitor::visitStartStopStream(
|
||||
|
||||
if (ctx->limitBatchesOption()) {
|
||||
if (!is_start) {
|
||||
throw SyntaxException("Stop stream clause can't set batch limit!");
|
||||
throw SyntaxException("STOP STREAM can't set batch limit.");
|
||||
}
|
||||
limit_batches = ctx->limitBatchesOption()->accept(this);
|
||||
}
|
||||
@ -594,7 +595,7 @@ antlrcpp::Any CypherMainVisitor::visitLimitBatchesOption(
|
||||
MemgraphCypher::LimitBatchesOptionContext *ctx) {
|
||||
if (!ctx->literal()->numberLiteral() ||
|
||||
!ctx->literal()->numberLiteral()->integerLiteral()) {
|
||||
throw SyntaxException("Batch limit should be an integer literal!");
|
||||
throw SyntaxException("Batch limit should be an integer.");
|
||||
}
|
||||
return ctx->literal()->accept(this);
|
||||
}
|
||||
@ -673,7 +674,7 @@ antlrcpp::Any CypherMainVisitor::visitReturnItem(
|
||||
std::string(ctx->variable()->accept(this).as<std::string>());
|
||||
} else {
|
||||
if (in_with_ && !dynamic_cast<Identifier *>(named_expr->expression_)) {
|
||||
throw SemanticException("Only variables can be non aliased in with");
|
||||
throw SemanticException("Only variables can be non-aliased in WITH.");
|
||||
}
|
||||
named_expr->name_ = std::string(ctx->getText());
|
||||
named_expr->token_position_ =
|
||||
@ -752,7 +753,7 @@ antlrcpp::Any CypherMainVisitor::visitMapLiteral(
|
||||
ctx->propertyKeyName()[i]->accept(this);
|
||||
Expression *value = ctx->expression()[i]->accept(this);
|
||||
if (!map.insert({key, value}).second) {
|
||||
throw SemanticException("Same key can't appear twice in map literal");
|
||||
throw SemanticException("Same key can't appear twice in a map literal.");
|
||||
}
|
||||
}
|
||||
return map;
|
||||
@ -900,7 +901,8 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
if (relationshipDetail->total_weight &&
|
||||
edge->type_ != EdgeAtom::Type::WEIGHTED_SHORTEST_PATH)
|
||||
throw SemanticException(
|
||||
"Variable for total weight is allowed only in wShortest");
|
||||
"Variable for total weight is allowed only with weighted shortest "
|
||||
"path expansion.");
|
||||
auto visit_lambda = [this](auto *lambda) {
|
||||
EdgeAtom::Lambda edge_lambda;
|
||||
std::string traversed_edge_variable =
|
||||
@ -927,7 +929,8 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
case 0:
|
||||
if (edge->type_ == EdgeAtom::Type::WEIGHTED_SHORTEST_PATH)
|
||||
throw SemanticException(
|
||||
"Lambda for calculating weights is mandatory");
|
||||
"Lambda for calculating weights is mandatory with weighted "
|
||||
"shortest path expansion.");
|
||||
// In variable expansion inner variables are mandatory.
|
||||
anonymous_identifiers.push_back(&edge->filter_lambda_.inner_edge);
|
||||
anonymous_identifiers.push_back(&edge->filter_lambda_.inner_node);
|
||||
@ -948,17 +951,17 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
break;
|
||||
case 2:
|
||||
if (edge->type_ != EdgeAtom::Type::WEIGHTED_SHORTEST_PATH)
|
||||
throw SemanticException("Only one relationship lambda allowed");
|
||||
throw SemanticException("Only one filter lambda can be supplied.");
|
||||
edge->weight_lambda_ = visit_lambda(relationshipLambdas[0]);
|
||||
visit_total_weight();
|
||||
edge->filter_lambda_ = visit_lambda(relationshipLambdas[1]);
|
||||
break;
|
||||
default:
|
||||
throw SemanticException("Only one relationship lambda allowed");
|
||||
throw SemanticException("Only one filter lambda can be supplied.");
|
||||
}
|
||||
} else if (!relationshipLambdas.empty()) {
|
||||
throw SemanticException(
|
||||
"Relationship lambda only supported in variable length expansion");
|
||||
"Filter lambda is only allowed in variable length expansion.");
|
||||
}
|
||||
|
||||
auto properties = relationshipDetail->properties();
|
||||
@ -974,7 +977,8 @@ antlrcpp::Any CypherMainVisitor::visitRelationshipPattern(
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw SemanticException("Only one property map supported in edge");
|
||||
throw SemanticException(
|
||||
"Only one property map can be supplied for edge.");
|
||||
}
|
||||
|
||||
return edge;
|
||||
@ -1037,7 +1041,8 @@ antlrcpp::Any CypherMainVisitor::visitVariableExpansion(
|
||||
upper = ctx->expression()[1]->accept(this);
|
||||
}
|
||||
if (lower && edge_type == EdgeAtom::Type::WEIGHTED_SHORTEST_PATH)
|
||||
throw SemanticException("Lower bound is not allowed in wShortest.");
|
||||
throw SemanticException(
|
||||
"Lower bound is not allowed in weighted shortest path expansion.");
|
||||
|
||||
return std::make_tuple(edge_type, lower, upper);
|
||||
}
|
||||
@ -1301,7 +1306,7 @@ antlrcpp::Any CypherMainVisitor::visitAtom(MemgraphCypher::AtomContext *ctx) {
|
||||
Expression *list_expr =
|
||||
ctx->filterExpression()->idInColl()->expression()->accept(this);
|
||||
if (!ctx->filterExpression()->where()) {
|
||||
throw SyntaxException("all(...) requires a WHERE predicate");
|
||||
throw SyntaxException("ALL(...) requires a WHERE predicate.");
|
||||
}
|
||||
Where *where = ctx->filterExpression()->where()->accept(this);
|
||||
return static_cast<Expression *>(
|
||||
@ -1315,7 +1320,7 @@ antlrcpp::Any CypherMainVisitor::visitAtom(MemgraphCypher::AtomContext *ctx) {
|
||||
Expression *list_expr =
|
||||
ctx->filterExpression()->idInColl()->expression()->accept(this);
|
||||
if (!ctx->filterExpression()->where()) {
|
||||
throw SyntaxException("single(...) requires a WHERE predicate");
|
||||
throw SyntaxException("SINGLE(...) requires a WHERE predicate.");
|
||||
}
|
||||
Where *where = ctx->filterExpression()->where()->accept(this);
|
||||
return static_cast<Expression *>(
|
||||
|
@ -51,7 +51,7 @@ void SymbolGenerator::VisitReturnBody(ReturnBody &body, Where *where) {
|
||||
user_symbols.emplace_back(sym_pair.second);
|
||||
}
|
||||
if (user_symbols.empty()) {
|
||||
throw SemanticException("There are no variables in scope to use for '*'");
|
||||
throw SemanticException("There are no variables in scope to use for '*'.");
|
||||
}
|
||||
}
|
||||
// WITH/RETURN clause removes declarations of all the previous variables and
|
||||
@ -132,7 +132,7 @@ bool SymbolGenerator::PreVisit(CypherUnion &) {
|
||||
bool SymbolGenerator::PostVisit(CypherUnion &cypher_union) {
|
||||
if (prev_return_names_ != curr_return_names_) {
|
||||
throw SemanticException(
|
||||
"All sub queries in an UNION must have the same column names");
|
||||
"All subqueries in an UNION must have the same column names.");
|
||||
}
|
||||
|
||||
// create new symbols for the result of the union
|
||||
@ -238,7 +238,7 @@ bool SymbolGenerator::Visit(TestStream &) { return true; }
|
||||
|
||||
SymbolGenerator::ReturnType SymbolGenerator::Visit(Identifier &ident) {
|
||||
if (scope_.in_skip || scope_.in_limit) {
|
||||
throw SemanticException("Variables are not allowed in {}",
|
||||
throw SemanticException("Variables are not allowed in {}.",
|
||||
scope_.in_skip ? "SKIP" : "LIMIT");
|
||||
}
|
||||
Symbol symbol;
|
||||
@ -297,12 +297,12 @@ bool SymbolGenerator::PreVisit(Aggregation &aggr) {
|
||||
if ((!scope_.in_return && !scope_.in_with) || scope_.in_order_by ||
|
||||
scope_.in_skip || scope_.in_limit || scope_.in_where) {
|
||||
throw SemanticException(
|
||||
"Aggregation functions are only allowed in WITH and RETURN");
|
||||
"Aggregation functions are only allowed in WITH and RETURN.");
|
||||
}
|
||||
if (scope_.in_aggregation) {
|
||||
throw SemanticException(
|
||||
"Using aggregation functions inside aggregation functions is not "
|
||||
"allowed");
|
||||
"allowed.");
|
||||
}
|
||||
if (scope_.num_if_operators) {
|
||||
// Neo allows aggregations here and produces very interesting behaviors.
|
||||
@ -313,7 +313,7 @@ bool SymbolGenerator::PreVisit(Aggregation &aggr) {
|
||||
// TODO: Rethink of allowing aggregations in some parts of the CASE
|
||||
// construct.
|
||||
throw SemanticException(
|
||||
"Using aggregation functions inside of CASE is not allowed");
|
||||
"Using aggregation functions inside of CASE is not allowed.");
|
||||
}
|
||||
// Create a virtual symbol for aggregation result.
|
||||
// Currently, we only have aggregation operators which return numbers.
|
||||
|
@ -56,7 +56,7 @@ StrippedQuery::StrippedQuery(const std::string &query) : original_(query) {
|
||||
update(MatchEscapedName(i), Token::ESCAPED_NAME);
|
||||
update(MatchUnescapedName(i), Token::UNESCAPED_NAME);
|
||||
update(MatchWhitespaceAndComments(i), Token::SPACE);
|
||||
if (token == Token::UNMATCHED) throw LexingException("Invalid query");
|
||||
if (token == Token::UNMATCHED) throw LexingException("Invalid query.");
|
||||
tokens.emplace_back(token, original_.substr(i, len));
|
||||
i += len;
|
||||
}
|
||||
@ -233,26 +233,26 @@ std::string GetFirstUtf8Symbol(const char *_s) {
|
||||
if ((*s >> 7) == 0x00) return std::string(_s, _s + 1);
|
||||
if ((*s >> 5) == 0x06) {
|
||||
auto *s1 = s + 1;
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
return std::string(_s, _s + 2);
|
||||
}
|
||||
if ((*s >> 4) == 0x0e) {
|
||||
auto *s1 = s + 1;
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
auto *s2 = s + 2;
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
return std::string(_s, _s + 3);
|
||||
}
|
||||
if ((*s >> 3) == 0x1e) {
|
||||
auto *s1 = s + 1;
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
auto *s2 = s + 2;
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
auto *s3 = s + 3;
|
||||
if ((*s3 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s3 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
return std::string(_s, _s + 4);
|
||||
}
|
||||
throw LexingException("Invalid character");
|
||||
throw LexingException("Invalid character.");
|
||||
}
|
||||
|
||||
// Return codepoint of first utf8 symbol and its encoded length.
|
||||
@ -264,28 +264,28 @@ std::pair<int, int> GetFirstUtf8SymbolCodepoint(const char *_s) {
|
||||
if ((*s >> 7) == 0x00) return {*s & 0x7f, 1};
|
||||
if ((*s >> 5) == 0x06) {
|
||||
auto *s1 = s + 1;
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
return {((*s & 0x1f) << 6) | (*s1 & 0x3f), 2};
|
||||
}
|
||||
if ((*s >> 4) == 0x0e) {
|
||||
auto *s1 = s + 1;
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
auto *s2 = s + 2;
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
return {((*s & 0x0f) << 12) | ((*s1 & 0x3f) << 6) | (*s2 & 0x3f), 3};
|
||||
}
|
||||
if ((*s >> 3) == 0x1e) {
|
||||
auto *s1 = s + 1;
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s1 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
auto *s2 = s + 2;
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s2 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
auto *s3 = s + 3;
|
||||
if ((*s3 >> 6) != 0x02) throw LexingException("Invalid character");
|
||||
if ((*s3 >> 6) != 0x02) throw LexingException("Invalid character.");
|
||||
return {((*s & 0x07) << 18) | ((*s1 & 0x3f) << 12) | ((*s2 & 0x3f) << 6) |
|
||||
(*s3 & 0x3f),
|
||||
4};
|
||||
}
|
||||
throw LexingException("Invalid character");
|
||||
throw LexingException("Invalid character.");
|
||||
}
|
||||
|
||||
// From here until end of file there are functions that calculate matches for
|
||||
|
@ -34,7 +34,7 @@ namespace {
|
||||
|
||||
TypedValue Coalesce(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() == 0U) {
|
||||
throw QueryRuntimeException("coalesce requires at least one argument");
|
||||
throw QueryRuntimeException("'coalesce' requires at least one argument.");
|
||||
}
|
||||
for (auto &arg : args) {
|
||||
if (arg.type() != TypedValue::Type::Null) {
|
||||
@ -46,7 +46,7 @@ TypedValue Coalesce(const std::vector<TypedValue> &args, Context *) {
|
||||
|
||||
TypedValue EndNode(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("endNode requires one argument");
|
||||
throw QueryRuntimeException("'endNode' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -54,13 +54,13 @@ TypedValue EndNode(const std::vector<TypedValue> &args, Context *) {
|
||||
case TypedValue::Type::Edge:
|
||||
return args[0].Value<EdgeAccessor>().to();
|
||||
default:
|
||||
throw QueryRuntimeException("endNode argument should be an edge");
|
||||
throw QueryRuntimeException("'endNode' argument must be an edge.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Head(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("head requires one argument");
|
||||
throw QueryRuntimeException("'head' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -71,13 +71,13 @@ TypedValue Head(const std::vector<TypedValue> &args, Context *) {
|
||||
return list[0];
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("head argument should be a list");
|
||||
throw QueryRuntimeException("'head' argument must be a list.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Last(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("last requires one argument");
|
||||
throw QueryRuntimeException("'last' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -88,13 +88,13 @@ TypedValue Last(const std::vector<TypedValue> &args, Context *) {
|
||||
return list.back();
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("last argument should be a list");
|
||||
throw QueryRuntimeException("'last' argument must be a list.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Properties(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("properties requires one argument");
|
||||
throw QueryRuntimeException("'properties' requires exactly one argument.");
|
||||
}
|
||||
auto get_properties = [&](const auto &record_accessor) {
|
||||
std::map<std::string, TypedValue> properties;
|
||||
@ -113,13 +113,13 @@ TypedValue Properties(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
return get_properties(args[0].Value<EdgeAccessor>());
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"properties argument should be a vertex or an edge");
|
||||
"'properties' argument must be a node or an edge.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Size(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("size requires one argument");
|
||||
throw QueryRuntimeException("'size' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -138,13 +138,13 @@ TypedValue Size(const std::vector<TypedValue> &args, Context *) {
|
||||
return static_cast<int64_t>(args[0].ValuePath().edges().size());
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"size argument should be a string, a collection or a path");
|
||||
"'size' argument must be a string, a collection or a path.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue StartNode(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("startNode requires one argument");
|
||||
throw QueryRuntimeException("'startNode' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -152,13 +152,13 @@ TypedValue StartNode(const std::vector<TypedValue> &args, Context *) {
|
||||
case TypedValue::Type::Edge:
|
||||
return args[0].Value<EdgeAccessor>().from();
|
||||
default:
|
||||
throw QueryRuntimeException("startNode argument should be an edge");
|
||||
throw QueryRuntimeException("'startNode' argument must be an edge.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Degree(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("degree requires one argument");
|
||||
throw QueryRuntimeException("'degree' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -168,13 +168,13 @@ TypedValue Degree(const std::vector<TypedValue> &args, Context *) {
|
||||
return static_cast<int64_t>(vertex.out_degree() + vertex.in_degree());
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("degree argument should be a vertex");
|
||||
throw QueryRuntimeException("'degree' argument must be a node.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue ToBoolean(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("toBoolean requires one argument");
|
||||
throw QueryRuntimeException("'toBoolean' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -193,13 +193,13 @@ TypedValue ToBoolean(const std::vector<TypedValue> &args, Context *) {
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"toBoolean argument should be an integer, a string or a boolean");
|
||||
"'toBoolean' argument must be an integer, a string or a boolean.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue ToFloat(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("toFloat requires one argument");
|
||||
throw QueryRuntimeException("'toFloat' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -216,13 +216,13 @@ TypedValue ToFloat(const std::vector<TypedValue> &args, Context *) {
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"toFloat argument should be a string or a number");
|
||||
"'toFloat' argument must be a string or a number.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue ToInteger(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("toInteger requires one argument");
|
||||
throw QueryRuntimeException("'toInteger' requires exactly one argument'");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -244,13 +244,13 @@ TypedValue ToInteger(const std::vector<TypedValue> &args, Context *) {
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"toInteger argument should be a string, a boolean or a number");
|
||||
"'toInteger' argument must be a string, a boolean or a number.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Type(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("type requires one argument");
|
||||
throw QueryRuntimeException("'type' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -259,13 +259,13 @@ TypedValue Type(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
return ctx->db_accessor_.EdgeTypeName(
|
||||
args[0].Value<EdgeAccessor>().EdgeType());
|
||||
default:
|
||||
throw QueryRuntimeException("type argument should be an edge");
|
||||
throw QueryRuntimeException("'type' argument must be an edge.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Keys(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("keys requires one argument");
|
||||
throw QueryRuntimeException("'keys' requires exactly one argument.");
|
||||
}
|
||||
auto get_keys = [&](const auto &record_accessor) {
|
||||
std::vector<TypedValue> keys;
|
||||
@ -282,14 +282,13 @@ TypedValue Keys(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
case TypedValue::Type::Edge:
|
||||
return get_keys(args[0].Value<EdgeAccessor>());
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"keys argument should be a vertex or an edge");
|
||||
throw QueryRuntimeException("'keys' argument must be a node or an edge.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Labels(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("labels requires one argument");
|
||||
throw QueryRuntimeException("'labels' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -302,17 +301,17 @@ TypedValue Labels(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
return labels;
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("labels argument should be a vertex");
|
||||
throw QueryRuntimeException("'labels' argument must be a node.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Nodes(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("nodes requires one argument");
|
||||
throw QueryRuntimeException("'nodes' requires exactly one argument.");
|
||||
}
|
||||
if (args[0].IsNull()) return TypedValue::Null;
|
||||
if (!args[0].IsPath()) {
|
||||
throw QueryRuntimeException("nodes argument should be a path");
|
||||
throw QueryRuntimeException("'nodes' argument should be a path.");
|
||||
}
|
||||
auto &vertices = args[0].ValuePath().vertices();
|
||||
return std::vector<TypedValue>(vertices.begin(), vertices.end());
|
||||
@ -320,11 +319,12 @@ TypedValue Nodes(const std::vector<TypedValue> &args, Context *) {
|
||||
|
||||
TypedValue Relationships(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("relationships requires one argument");
|
||||
throw QueryRuntimeException(
|
||||
"'relationships' requires exactly one argument.");
|
||||
}
|
||||
if (args[0].IsNull()) return TypedValue::Null;
|
||||
if (!args[0].IsPath()) {
|
||||
throw QueryRuntimeException("relationships argument should be a path");
|
||||
throw QueryRuntimeException("'relationships' argument must be a path.");
|
||||
}
|
||||
auto &edges = args[0].ValuePath().edges();
|
||||
return std::vector<TypedValue>(edges.begin(), edges.end());
|
||||
@ -332,14 +332,14 @@ TypedValue Relationships(const std::vector<TypedValue> &args, Context *) {
|
||||
|
||||
TypedValue Range(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 2U && args.size() != 3U) {
|
||||
throw QueryRuntimeException("range requires two or three arguments");
|
||||
throw QueryRuntimeException("'range' requires two or three arguments.");
|
||||
}
|
||||
bool has_null = false;
|
||||
auto check_type = [&](const TypedValue &t) {
|
||||
if (t.IsNull()) {
|
||||
has_null = true;
|
||||
} else if (t.type() != TypedValue::Type::Int) {
|
||||
throw QueryRuntimeException("arguments of range should be integers");
|
||||
throw QueryRuntimeException("arguments of 'range' must be integers.");
|
||||
}
|
||||
};
|
||||
std::for_each(args.begin(), args.end(), check_type);
|
||||
@ -348,7 +348,7 @@ TypedValue Range(const std::vector<TypedValue> &args, Context *) {
|
||||
auto rbound = args[1].Value<int64_t>();
|
||||
int64_t step = args.size() == 3U ? args[2].Value<int64_t>() : 1;
|
||||
if (step == 0) {
|
||||
throw QueryRuntimeException("step argument in range can't be zero");
|
||||
throw QueryRuntimeException("step argument of 'range' can't be zero.");
|
||||
}
|
||||
std::vector<TypedValue> list;
|
||||
if (lbound <= rbound && step > 0) {
|
||||
@ -365,7 +365,7 @@ TypedValue Range(const std::vector<TypedValue> &args, Context *) {
|
||||
|
||||
TypedValue Tail(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("tail requires one argument");
|
||||
throw QueryRuntimeException("'tail' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -377,13 +377,13 @@ TypedValue Tail(const std::vector<TypedValue> &args, Context *) {
|
||||
return list;
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("tail argument should be a list");
|
||||
throw QueryRuntimeException("'tail' argument must be a list.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Abs(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("abs requires one argument");
|
||||
throw QueryRuntimeException("'abs' requires exactly one argument.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -394,26 +394,27 @@ TypedValue Abs(const std::vector<TypedValue> &args, Context *) {
|
||||
case TypedValue::Type::Double:
|
||||
return std::abs(args[0].Value<double>());
|
||||
default:
|
||||
throw QueryRuntimeException("abs argument should be a number");
|
||||
throw QueryRuntimeException("'abs' argument should be a number.");
|
||||
}
|
||||
}
|
||||
|
||||
#define WRAP_CMATH_FLOAT_FUNCTION(name, lowercased_name) \
|
||||
TypedValue name(const std::vector<TypedValue> &args, Context *) { \
|
||||
if (args.size() != 1U) { \
|
||||
throw QueryRuntimeException(#lowercased_name " requires one argument"); \
|
||||
} \
|
||||
switch (args[0].type()) { \
|
||||
case TypedValue::Type::Null: \
|
||||
return TypedValue::Null; \
|
||||
case TypedValue::Type::Int: \
|
||||
return lowercased_name(args[0].Value<int64_t>()); \
|
||||
case TypedValue::Type::Double: \
|
||||
return lowercased_name(args[0].Value<double>()); \
|
||||
default: \
|
||||
throw QueryRuntimeException(#lowercased_name \
|
||||
" argument should be a number"); \
|
||||
} \
|
||||
#define WRAP_CMATH_FLOAT_FUNCTION(name, lowercased_name) \
|
||||
TypedValue name(const std::vector<TypedValue> &args, Context *) { \
|
||||
if (args.size() != 1U) { \
|
||||
throw QueryRuntimeException("'" #lowercased_name \
|
||||
"' requires exactly one argument."); \
|
||||
} \
|
||||
switch (args[0].type()) { \
|
||||
case TypedValue::Type::Null: \
|
||||
return TypedValue::Null; \
|
||||
case TypedValue::Type::Int: \
|
||||
return lowercased_name(args[0].Value<int64_t>()); \
|
||||
case TypedValue::Type::Double: \
|
||||
return lowercased_name(args[0].Value<double>()); \
|
||||
default: \
|
||||
throw QueryRuntimeException(#lowercased_name \
|
||||
" argument must be a number."); \
|
||||
} \
|
||||
}
|
||||
|
||||
WRAP_CMATH_FLOAT_FUNCTION(Ceil, ceil)
|
||||
@ -436,7 +437,7 @@ WRAP_CMATH_FLOAT_FUNCTION(Tan, tan)
|
||||
|
||||
TypedValue Atan2(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 2U) {
|
||||
throw QueryRuntimeException("atan2 requires two arguments");
|
||||
throw QueryRuntimeException("'atan2' requires two arguments.");
|
||||
}
|
||||
if (args[0].type() == TypedValue::Type::Null) return TypedValue::Null;
|
||||
if (args[1].type() == TypedValue::Type::Null) return TypedValue::Null;
|
||||
@ -447,7 +448,7 @@ TypedValue Atan2(const std::vector<TypedValue> &args, Context *) {
|
||||
case TypedValue::Type::Double:
|
||||
return t.Value<double>();
|
||||
default:
|
||||
throw QueryRuntimeException("arguments of atan2 should be numbers");
|
||||
throw QueryRuntimeException("Arguments of 'atan2' must be numbers.");
|
||||
}
|
||||
};
|
||||
double y = to_double(args[0]);
|
||||
@ -457,7 +458,7 @@ TypedValue Atan2(const std::vector<TypedValue> &args, Context *) {
|
||||
|
||||
TypedValue Sign(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("sign requires one argument");
|
||||
throw QueryRuntimeException("'sign' requires exactly one argument.");
|
||||
}
|
||||
auto sign = [](auto x) { return (0 < x) - (x < 0); };
|
||||
switch (args[0].type()) {
|
||||
@ -468,20 +469,20 @@ TypedValue Sign(const std::vector<TypedValue> &args, Context *) {
|
||||
case TypedValue::Type::Double:
|
||||
return sign(args[0].Value<double>());
|
||||
default:
|
||||
throw QueryRuntimeException("sign argument should be a number");
|
||||
throw QueryRuntimeException("'sign' argument must be a number.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue E(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 0U) {
|
||||
throw QueryRuntimeException("e requires no arguments");
|
||||
throw QueryRuntimeException("'e' requires no arguments.");
|
||||
}
|
||||
return M_E;
|
||||
}
|
||||
|
||||
TypedValue Pi(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 0U) {
|
||||
throw QueryRuntimeException("pi requires no arguments");
|
||||
throw QueryRuntimeException("'pi' requires no arguments.");
|
||||
}
|
||||
return M_PI;
|
||||
}
|
||||
@ -490,7 +491,7 @@ TypedValue Rand(const std::vector<TypedValue> &args, Context *) {
|
||||
static thread_local std::mt19937 pseudo_rand_gen_{std::random_device{}()};
|
||||
static thread_local std::uniform_real_distribution<> rand_dist_{0, 1};
|
||||
if (args.size() != 0U) {
|
||||
throw QueryRuntimeException("rand requires no arguments");
|
||||
throw QueryRuntimeException("'rand' requires no arguments.");
|
||||
}
|
||||
return rand_dist_(pseudo_rand_gen_);
|
||||
}
|
||||
@ -499,7 +500,7 @@ template <bool (*Predicate)(const std::string &s1, const std::string &s2)>
|
||||
TypedValue StringMatchOperator(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 2U) {
|
||||
throw QueryRuntimeException(
|
||||
"startsWith and endsWith require two arguments");
|
||||
"'startsWith' and 'endsWith' require two arguments.");
|
||||
}
|
||||
bool has_null = false;
|
||||
auto check_arg = [&](const TypedValue &t) {
|
||||
@ -507,7 +508,7 @@ TypedValue StringMatchOperator(const std::vector<TypedValue> &args, Context *) {
|
||||
has_null = true;
|
||||
} else if (t.type() != TypedValue::Type::String) {
|
||||
throw QueryRuntimeException(
|
||||
"arguments of startsWith and endsWith should be strings");
|
||||
"Arguments of 'startsWith' and 'endsWith' must be strings.");
|
||||
}
|
||||
};
|
||||
check_arg(args[0]);
|
||||
@ -541,15 +542,18 @@ auto Contains = StringMatchOperator<ContainsPredicate>;
|
||||
|
||||
TypedValue Assert(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() < 1U || args.size() > 2U) {
|
||||
throw QueryRuntimeException("assert requires one or two arguments");
|
||||
throw QueryRuntimeException("'assert' requires one or two arguments");
|
||||
}
|
||||
if (args[0].type() != TypedValue::Type::Bool)
|
||||
throw QueryRuntimeException("first argument of assert must be a boolean");
|
||||
throw QueryRuntimeException(
|
||||
"First argument of 'assert' must be a boolean.");
|
||||
if (args.size() == 2U && args[1].type() != TypedValue::Type::String)
|
||||
throw QueryRuntimeException("second argument of assert must be a string");
|
||||
throw QueryRuntimeException(
|
||||
"Second argument of 'assert' must be a string.");
|
||||
if (!args[0].ValueBool()) {
|
||||
std::string message("assertion failed");
|
||||
std::string message("Assertion failed");
|
||||
if (args.size() == 2U) message += ": " + args[1].ValueString();
|
||||
message += ".";
|
||||
throw QueryRuntimeException(message);
|
||||
}
|
||||
return args[0];
|
||||
@ -557,31 +561,31 @@ TypedValue Assert(const std::vector<TypedValue> &args, Context *) {
|
||||
|
||||
TypedValue Counter(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("counter requires one argument");
|
||||
throw QueryRuntimeException("'counter' requires exactly one argument.");
|
||||
}
|
||||
if (!args[0].IsString())
|
||||
throw QueryRuntimeException("counter argument must be a string");
|
||||
throw QueryRuntimeException("'counter' argument must be a string.");
|
||||
|
||||
return ctx->db_accessor_.Counter(args[0].ValueString());
|
||||
}
|
||||
|
||||
TypedValue CounterSet(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 2U) {
|
||||
throw QueryRuntimeException("counterSet requires two arguments");
|
||||
throw QueryRuntimeException("'counterSet' requires two arguments.");
|
||||
}
|
||||
if (!args[0].IsString())
|
||||
throw QueryRuntimeException(
|
||||
"first argument of counterSet must be a string");
|
||||
"First argument of 'counterSet' must be a string.");
|
||||
if (!args[1].IsInt())
|
||||
throw QueryRuntimeException(
|
||||
"second argument of counterSet must be an integer");
|
||||
"Second argument of 'counterSet' must be an integer.");
|
||||
ctx->db_accessor_.CounterSet(args[0].ValueString(), args[1].ValueInt());
|
||||
return TypedValue::Null;
|
||||
}
|
||||
|
||||
TypedValue IndexInfo(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 0U)
|
||||
throw QueryRuntimeException("indexInfo requires no arguments");
|
||||
throw QueryRuntimeException("'indexInfo' requires no arguments.");
|
||||
|
||||
auto info = ctx->db_accessor_.IndexInfo();
|
||||
return std::vector<TypedValue>(info.begin(), info.end());
|
||||
@ -589,7 +593,7 @@ TypedValue IndexInfo(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
|
||||
TypedValue WorkerId(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("workerId requires one argument");
|
||||
throw QueryRuntimeException("'workerId' requires exactly one argument.");
|
||||
}
|
||||
auto &arg = args[0];
|
||||
switch (arg.type()) {
|
||||
@ -599,13 +603,13 @@ TypedValue WorkerId(const std::vector<TypedValue> &args, Context *) {
|
||||
return arg.ValueEdge().GlobalAddress().worker_id();
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"workerId argument must be a vertex or an edge");
|
||||
"'workerId' argument must be a node or an edge.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Id(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("id requires one argument");
|
||||
throw QueryRuntimeException("'id' requires exactly one argument.");
|
||||
}
|
||||
auto &arg = args[0];
|
||||
switch (arg.type()) {
|
||||
@ -616,13 +620,13 @@ TypedValue Id(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
return TypedValue(arg.ValueEdge().cypher_id());
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("id argument must be a vertex or an edge");
|
||||
throw QueryRuntimeException("'id' argument must be a node or an edge.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue ToString(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 1U) {
|
||||
throw QueryRuntimeException("toString requires one argument");
|
||||
throw QueryRuntimeException("'toString' requires exactly one argument.");
|
||||
}
|
||||
auto &arg = args[0];
|
||||
switch (arg.type()) {
|
||||
@ -638,20 +642,20 @@ TypedValue ToString(const std::vector<TypedValue> &args, Context *) {
|
||||
return arg.ValueBool() ? "true" : "false";
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"toString argument must be a number, a string or a boolean");
|
||||
"'toString' argument must be a number, a string or a boolean.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Timestamp(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 0) {
|
||||
throw QueryRuntimeException("timestamp requires no arguments");
|
||||
throw QueryRuntimeException("'timestamp' requires no arguments.");
|
||||
}
|
||||
return ctx->timestamp_;
|
||||
}
|
||||
|
||||
TypedValue Left(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 2) {
|
||||
throw QueryRuntimeException("left requires two arguments");
|
||||
throw QueryRuntimeException("'left' requires two arguments.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -659,21 +663,21 @@ TypedValue Left(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
return TypedValue::Null;
|
||||
}
|
||||
throw QueryRuntimeException(
|
||||
"second argument of left must be a non-negative integer");
|
||||
"Second argument of 'left' must be a non-negative integer.");
|
||||
case TypedValue::Type::String:
|
||||
if (args[1].IsInt() && args[1].ValueInt() >= 0) {
|
||||
return args[0].ValueString().substr(0, args[1].ValueInt());
|
||||
}
|
||||
throw QueryRuntimeException(
|
||||
"second argument of left must be a non-negative integer");
|
||||
"Second argument of 'left' must be a non-negative integer.");
|
||||
default:
|
||||
throw QueryRuntimeException("first argument of left must be a string");
|
||||
throw QueryRuntimeException("First argument of 'left' must be a string.");
|
||||
}
|
||||
}
|
||||
|
||||
TypedValue Right(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 2) {
|
||||
throw QueryRuntimeException("right requires two arguments");
|
||||
throw QueryRuntimeException("'right' requires two arguments.");
|
||||
}
|
||||
switch (args[0].type()) {
|
||||
case TypedValue::Type::Null:
|
||||
@ -681,7 +685,7 @@ TypedValue Right(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
return TypedValue::Null;
|
||||
}
|
||||
throw QueryRuntimeException(
|
||||
"second argument of right must be a non-negative integer");
|
||||
"Second argument of 'right' must be a non-negative integer.");
|
||||
case TypedValue::Type::String: {
|
||||
const auto &str = args[0].ValueString();
|
||||
if (args[1].IsInt() && args[1].ValueInt() >= 0) {
|
||||
@ -689,27 +693,29 @@ TypedValue Right(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
return len <= str.size() ? str.substr(str.size() - len, len) : str;
|
||||
}
|
||||
throw QueryRuntimeException(
|
||||
"second argument of right must be a non-negative integer");
|
||||
"Second argument of 'right' must be a non-negative integer.");
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("first argument of right must be a string");
|
||||
throw QueryRuntimeException(
|
||||
"First argument of 'right' must be a string.");
|
||||
}
|
||||
}
|
||||
|
||||
#define WRAP_STRING_FUNCTION(name, lowercased_name, function) \
|
||||
TypedValue name(const std::vector<TypedValue> &args, Context *) { \
|
||||
if (args.size() != 1U) { \
|
||||
throw QueryRuntimeException(#lowercased_name " requires one argument"); \
|
||||
} \
|
||||
switch (args[0].type()) { \
|
||||
case TypedValue::Type::Null: \
|
||||
return TypedValue::Null; \
|
||||
case TypedValue::Type::String: \
|
||||
return function(args[0].ValueString()); \
|
||||
default: \
|
||||
throw QueryRuntimeException(#lowercased_name \
|
||||
" argument should be a string"); \
|
||||
} \
|
||||
#define WRAP_STRING_FUNCTION(name, lowercased_name, function) \
|
||||
TypedValue name(const std::vector<TypedValue> &args, Context *) { \
|
||||
if (args.size() != 1U) { \
|
||||
throw QueryRuntimeException("'" #lowercased_name \
|
||||
"' requires exactly one argument."); \
|
||||
} \
|
||||
switch (args[0].type()) { \
|
||||
case TypedValue::Type::Null: \
|
||||
return TypedValue::Null; \
|
||||
case TypedValue::Type::String: \
|
||||
return function(args[0].ValueString()); \
|
||||
default: \
|
||||
throw QueryRuntimeException("'" #lowercased_name \
|
||||
"' argument should be a string."); \
|
||||
} \
|
||||
}
|
||||
|
||||
WRAP_STRING_FUNCTION(LTrim, lTrim, utils::LTrim);
|
||||
@ -721,17 +727,19 @@ WRAP_STRING_FUNCTION(ToUpper, toUpper, utils::ToUpperCase);
|
||||
|
||||
TypedValue Replace(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 3U) {
|
||||
throw QueryRuntimeException("replace requires three arguments");
|
||||
throw QueryRuntimeException("'replace' requires three arguments.");
|
||||
}
|
||||
if (!args[0].IsNull() && !args[0].IsString()) {
|
||||
throw QueryRuntimeException("first argument of replace should be a string");
|
||||
throw QueryRuntimeException(
|
||||
"First argument of 'replace' should be a string.");
|
||||
}
|
||||
if (!args[1].IsNull() && !args[1].IsString()) {
|
||||
throw QueryRuntimeException(
|
||||
"second argument of replace should be a string");
|
||||
"Second argument of 'replace' should be a string.");
|
||||
}
|
||||
if (!args[2].IsNull() && !args[2].IsString()) {
|
||||
throw QueryRuntimeException("third argument of replace should be a string");
|
||||
throw QueryRuntimeException(
|
||||
"Third argument of 'replace' should be a string.");
|
||||
}
|
||||
if (args[0].IsNull() || args[1].IsNull() || args[2].IsNull()) {
|
||||
return TypedValue::Null;
|
||||
@ -742,13 +750,15 @@ TypedValue Replace(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
|
||||
TypedValue Split(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
if (args.size() != 2U) {
|
||||
throw QueryRuntimeException("split requires two arguments");
|
||||
throw QueryRuntimeException("'split' requires two arguments.");
|
||||
}
|
||||
if (!args[0].IsNull() && !args[0].IsString()) {
|
||||
throw QueryRuntimeException("first argument of split should be a string");
|
||||
throw QueryRuntimeException(
|
||||
"First argument of 'split' should be a string.");
|
||||
}
|
||||
if (!args[1].IsNull() && !args[1].IsString()) {
|
||||
throw QueryRuntimeException("second argument of split should be a string");
|
||||
throw QueryRuntimeException(
|
||||
"Second argument of 'split' should be a string.");
|
||||
}
|
||||
if (args[0].IsNull() || args[1].IsNull()) {
|
||||
return TypedValue::Null;
|
||||
@ -763,19 +773,19 @@ TypedValue Split(const std::vector<TypedValue> &args, Context *ctx) {
|
||||
|
||||
TypedValue Substring(const std::vector<TypedValue> &args, Context *) {
|
||||
if (args.size() != 2U && args.size() != 3U) {
|
||||
throw QueryRuntimeException("substring requires two or three arguments");
|
||||
throw QueryRuntimeException("'substring' requires two or three arguments.");
|
||||
}
|
||||
if (!args[0].IsNull() && !args[0].IsString()) {
|
||||
throw QueryRuntimeException(
|
||||
"first argument of substring should be a string");
|
||||
"First argument of 'substring' should be a string.");
|
||||
}
|
||||
if (!args[1].IsInt() || args[1].ValueInt() < 0) {
|
||||
throw QueryRuntimeException(
|
||||
"second argument of substring should be a non-negative integer");
|
||||
"Second argument of 'substring' should be a non-negative integer.");
|
||||
}
|
||||
if (args.size() == 3U && (!args[2].IsInt() || args[2].ValueInt() < 0)) {
|
||||
throw QueryRuntimeException(
|
||||
"third argument of substring should be a non-negative integer");
|
||||
"Third argument of 'substring' should be a non-negative integer.");
|
||||
}
|
||||
if (args[0].IsNull()) {
|
||||
return TypedValue::Null;
|
||||
|
@ -80,20 +80,20 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
try { \
|
||||
return val1 CPP_OP val2; \
|
||||
} catch (const TypedValueException &) { \
|
||||
throw QueryRuntimeException("Invalid types: {} and {} for '{}'", \
|
||||
throw QueryRuntimeException("Invalid types: {} and {} for '{}'.", \
|
||||
val1.type(), val2.type(), #CYPHER_OP); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define UNARY_OPERATOR_VISITOR(OP_NODE, CPP_OP, CYPHER_OP) \
|
||||
TypedValue Visit(OP_NODE &op) override { \
|
||||
auto val = op.expression_->Accept(*this); \
|
||||
try { \
|
||||
return CPP_OP val; \
|
||||
} catch (const TypedValueException &) { \
|
||||
throw QueryRuntimeException("Invalid type {} for '{}'", val.type(), \
|
||||
#CYPHER_OP); \
|
||||
} \
|
||||
#define UNARY_OPERATOR_VISITOR(OP_NODE, CPP_OP, CYPHER_OP) \
|
||||
TypedValue Visit(OP_NODE &op) override { \
|
||||
auto val = op.expression_->Accept(*this); \
|
||||
try { \
|
||||
return CPP_OP val; \
|
||||
} catch (const TypedValueException &) { \
|
||||
throw QueryRuntimeException("Invalid type {} for '{}'.", val.type(), \
|
||||
#CYPHER_OP); \
|
||||
} \
|
||||
}
|
||||
|
||||
BINARY_OPERATOR_VISITOR(OrOperator, ||, OR);
|
||||
@ -127,7 +127,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
try {
|
||||
return value1 && value2;
|
||||
} catch (const TypedValueException &) {
|
||||
throw QueryRuntimeException("Invalid types: {} and {} for 'AND'",
|
||||
throw QueryRuntimeException("Invalid types: {} and {} for AND.",
|
||||
value1.type(), value2.type());
|
||||
}
|
||||
}
|
||||
@ -139,8 +139,8 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
}
|
||||
if (condition.type() != TypedValue::Type::Bool) {
|
||||
// At the moment IfOperator is used only in CASE construct.
|
||||
throw QueryRuntimeException(
|
||||
"'CASE' expected boolean expression, but got {}", condition.type());
|
||||
throw QueryRuntimeException("CASE expected boolean expression, got {}.",
|
||||
condition.type());
|
||||
}
|
||||
if (condition.Value<bool>()) {
|
||||
return if_operator.then_expression_->Accept(*this);
|
||||
@ -157,7 +157,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
// Exceptions have higher priority than returning nulls when list expression
|
||||
// is not null.
|
||||
if (_list.type() != TypedValue::Type::List) {
|
||||
throw QueryRuntimeException("'IN' expected a list, but got {}",
|
||||
throw QueryRuntimeException("IN expected a list, got {}.",
|
||||
_list.type());
|
||||
}
|
||||
auto list = _list.Value<std::vector<TypedValue>>();
|
||||
@ -190,14 +190,14 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
if (!lhs.IsList() && !lhs.IsMap() && !lhs.IsVertex() && !lhs.IsEdge() &&
|
||||
!lhs.IsNull())
|
||||
throw QueryRuntimeException(
|
||||
"Expected a list, a map, a vertex or an edge to index with '[]', but "
|
||||
"got {}",
|
||||
"Expected a list, a map, a node or an edge to index with '[]', got "
|
||||
"{}.",
|
||||
lhs.type());
|
||||
if (lhs.IsNull() || index.IsNull()) return TypedValue::Null;
|
||||
if (lhs.IsList()) {
|
||||
if (!index.IsInt())
|
||||
throw QueryRuntimeException(
|
||||
"Expected an int as a list index, but got {}", index.type());
|
||||
"Expected an integer as a list index, got {}.", index.type());
|
||||
auto index_int = index.Value<int64_t>();
|
||||
const auto &list = lhs.Value<std::vector<TypedValue>>();
|
||||
if (index_int < 0) {
|
||||
@ -210,8 +210,8 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
|
||||
if (lhs.IsMap()) {
|
||||
if (!index.IsString())
|
||||
throw QueryRuntimeException(
|
||||
"Expected a string as a map index, but got {}", index.type());
|
||||
throw QueryRuntimeException("Expected a string as a map index, got {}.",
|
||||
index.type());
|
||||
const auto &map = lhs.Value<std::map<std::string, TypedValue>>();
|
||||
auto found = map.find(index.Value<std::string>());
|
||||
if (found == map.end()) return TypedValue::Null;
|
||||
@ -221,7 +221,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
if (lhs.IsVertex()) {
|
||||
if (!index.IsString())
|
||||
throw QueryRuntimeException(
|
||||
"Expected a string as a property name, but got {}", index.type());
|
||||
"Expected a string as a property name, got {}.", index.type());
|
||||
return lhs.Value<VertexAccessor>().PropsAt(
|
||||
context_->db_accessor_.Property(index.Value<std::string>()));
|
||||
}
|
||||
@ -229,7 +229,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
if (lhs.IsEdge()) {
|
||||
if (!index.IsString())
|
||||
throw QueryRuntimeException(
|
||||
"Expected a string as a property name, but got {}", index.type());
|
||||
"Expected a string as a property name, got {}.", index.type());
|
||||
return lhs.Value<EdgeAccessor>().PropsAt(
|
||||
context_->db_accessor_.Property(index.Value<std::string>()));
|
||||
}
|
||||
@ -249,7 +249,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
is_null = true;
|
||||
} else if (bound.type() != TypedValue::Type::Int) {
|
||||
throw QueryRuntimeException(
|
||||
"Expected an int for a bound in list slicing, but got {}",
|
||||
"Expected an integer for a bound in list slicing, got {}.",
|
||||
bound.type());
|
||||
}
|
||||
return bound;
|
||||
@ -264,7 +264,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
if (_list.type() == TypedValue::Type::Null) {
|
||||
is_null = true;
|
||||
} else if (_list.type() != TypedValue::Type::List) {
|
||||
throw QueryRuntimeException("Expected a list to slice, but got {}",
|
||||
throw QueryRuntimeException("Expected a list to slice, got {}.",
|
||||
_list.type());
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Expected Node, Edge or Map for property lookup");
|
||||
"Only nodes, edges and maps have properties to be looked-up.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -332,7 +332,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException("Expected Node in labels test");
|
||||
throw QueryRuntimeException("Only nodes have labels.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,7 +379,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
return TypedValue::Null;
|
||||
}
|
||||
if (list_value.type() != TypedValue::Type::List) {
|
||||
throw QueryRuntimeException("'REDUCE' expected a list, but got {}",
|
||||
throw QueryRuntimeException("REDUCE expected a list, got {}.",
|
||||
list_value.type());
|
||||
}
|
||||
const auto &list = list_value.Value<std::vector<TypedValue>>();
|
||||
@ -402,7 +402,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
return TypedValue::Null;
|
||||
}
|
||||
if (list_value.type() != TypedValue::Type::List) {
|
||||
throw QueryRuntimeException("'EXTRACT' expected a list, but got {}",
|
||||
throw QueryRuntimeException("EXTRACT expected a list, got {}.",
|
||||
list_value.type());
|
||||
}
|
||||
const auto &list = list_value.Value<std::vector<TypedValue>>();
|
||||
@ -427,7 +427,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
return TypedValue::Null;
|
||||
}
|
||||
if (list_value.type() != TypedValue::Type::List) {
|
||||
throw QueryRuntimeException("'ALL' expected a list, but got {}",
|
||||
throw QueryRuntimeException("ALL expected a list, got {}.",
|
||||
list_value.type());
|
||||
}
|
||||
const auto &list = list_value.Value<std::vector<TypedValue>>();
|
||||
@ -437,8 +437,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
auto result = all.where_->expression_->Accept(*this);
|
||||
if (!result.IsNull() && result.type() != TypedValue::Type::Bool) {
|
||||
throw QueryRuntimeException(
|
||||
"Predicate of 'ALL' needs to evaluate to 'Boolean', but it "
|
||||
"resulted in '{}'",
|
||||
"Predicate of ALL must evaluate to boolean, got {}.",
|
||||
result.type());
|
||||
}
|
||||
if (result.IsNull() || !result.Value<bool>()) {
|
||||
@ -454,7 +453,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
return TypedValue::Null;
|
||||
}
|
||||
if (list_value.type() != TypedValue::Type::List) {
|
||||
throw QueryRuntimeException("'SINGLE' expected a list, but got {}",
|
||||
throw QueryRuntimeException("SINGLE expected a list, got {}.",
|
||||
list_value.type());
|
||||
}
|
||||
const auto &list = list_value.Value<std::vector<TypedValue>>();
|
||||
@ -465,8 +464,7 @@ class ExpressionEvaluator : public TreeVisitor<TypedValue> {
|
||||
auto result = single.where_->expression_->Accept(*this);
|
||||
if (!result.IsNull() && result.type() != TypedValue::Type::Bool) {
|
||||
throw QueryRuntimeException(
|
||||
"Predicate of 'SINGLE' needs to evaluate to 'Boolean', but it "
|
||||
"resulted in '{}'",
|
||||
"Predicate of SINGLE must evaluate to boolean, got {}.",
|
||||
result.type());
|
||||
}
|
||||
if (result.IsNull() || !result.Value<bool>()) {
|
||||
|
@ -46,7 +46,7 @@ Interpreter::Results Interpreter::operator()(
|
||||
auto param_it = params.find(param_pair.second);
|
||||
if (param_it == params.end()) {
|
||||
throw query::UnprovidedParameterError(
|
||||
fmt::format("Parameter ${} not provided", param_pair.second));
|
||||
fmt::format("Parameter ${} not provided.", param_pair.second));
|
||||
}
|
||||
ctx.parameters_.Add(param_pair.first, param_it->second);
|
||||
}
|
||||
|
@ -208,13 +208,13 @@ class RemotePuller {
|
||||
break;
|
||||
case distributed::PullState::SERIALIZATION_ERROR:
|
||||
throw mvcc::SerializationError(
|
||||
"Serialization error occured during PullRemote !");
|
||||
"Serialization error occured during PullRemote!");
|
||||
case distributed::PullState::LOCK_TIMEOUT_ERROR:
|
||||
throw utils::LockTimeoutException(
|
||||
"LockTimeout error occured during PullRemote !");
|
||||
"LockTimeout error occured during PullRemote!");
|
||||
case distributed::PullState::UPDATE_DELETED_ERROR:
|
||||
throw QueryRuntimeException(
|
||||
"RecordDeleted error ocured during PullRemote !");
|
||||
"RecordDeleted error ocured during PullRemote!");
|
||||
case distributed::PullState::RECONSTRUCTION_ERROR:
|
||||
throw query::ReconstructionException();
|
||||
case distributed::PullState::UNABLE_TO_DELETE_VERTEX_ERROR:
|
||||
@ -223,7 +223,7 @@ class RemotePuller {
|
||||
throw HintedAbortError();
|
||||
case distributed::PullState::QUERY_ERROR:
|
||||
throw QueryRuntimeException(
|
||||
"Query runtime error occurred during PullRemote !");
|
||||
"Query runtime error occurred during PullRemote!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -501,23 +501,23 @@ class SynchronizeCursor : public Cursor {
|
||||
continue;
|
||||
case distributed::PullState::CURSOR_IN_PROGRESS:
|
||||
throw QueryRuntimeException(
|
||||
"Expected exhausted cursor after remote pull accumulate");
|
||||
"Expected exhausted cursor after remote pull accumulate!");
|
||||
case distributed::PullState::SERIALIZATION_ERROR:
|
||||
throw mvcc::SerializationError(
|
||||
"Failed to perform remote accumulate due to "
|
||||
"SerializationError");
|
||||
"SerializationError!");
|
||||
case distributed::PullState::UPDATE_DELETED_ERROR:
|
||||
throw QueryRuntimeException(
|
||||
"Failed to perform remote accumulate due to "
|
||||
"RecordDeletedError");
|
||||
"RecordDeletedError!");
|
||||
case distributed::PullState::LOCK_TIMEOUT_ERROR:
|
||||
throw utils::LockTimeoutException(
|
||||
"Failed to perform remote accumulate due to "
|
||||
"LockTimeoutException");
|
||||
"LockTimeoutException!");
|
||||
case distributed::PullState::RECONSTRUCTION_ERROR:
|
||||
throw QueryRuntimeException(
|
||||
"Failed to perform remote accumulate due to "
|
||||
"ReconstructionError");
|
||||
"ReconstructionError!");
|
||||
case distributed::PullState::UNABLE_TO_DELETE_VERTEX_ERROR:
|
||||
throw RemoveAttachedVertexException();
|
||||
case distributed::PullState::HINTED_ABORT_ERROR:
|
||||
@ -525,7 +525,7 @@ class SynchronizeCursor : public Cursor {
|
||||
case distributed::PullState::QUERY_ERROR:
|
||||
throw QueryRuntimeException(
|
||||
"Failed to perform remote accumulate due to Query runtime "
|
||||
"error");
|
||||
"error!");
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,15 +541,15 @@ class SynchronizeCursor : public Cursor {
|
||||
switch (future.get()) {
|
||||
case distributed::UpdateResult::SERIALIZATION_ERROR:
|
||||
throw mvcc::SerializationError(
|
||||
"Failed to apply deferred updates due to SerializationError");
|
||||
"Failed to apply deferred updates due to SerializationError!");
|
||||
case distributed::UpdateResult::UNABLE_TO_DELETE_VERTEX_ERROR:
|
||||
throw RemoveAttachedVertexException();
|
||||
case distributed::UpdateResult::UPDATE_DELETED_ERROR:
|
||||
throw QueryRuntimeException(
|
||||
"Failed to apply deferred updates due to RecordDeletedError");
|
||||
"Failed to apply deferred updates due to RecordDeletedError!");
|
||||
case distributed::UpdateResult::LOCK_TIMEOUT_ERROR:
|
||||
throw utils::LockTimeoutException(
|
||||
"Failed to apply deferred update due to LockTimeoutException");
|
||||
"Failed to apply deferred update due to LockTimeoutException!");
|
||||
case distributed::UpdateResult::DONE:
|
||||
break;
|
||||
}
|
||||
|
@ -93,7 +93,8 @@ bool EvaluateFilter(ExpressionEvaluator &evaluator, Expression *filter) {
|
||||
if (result.IsNull()) return false;
|
||||
if (result.type() != TypedValue::Type::Bool)
|
||||
throw QueryRuntimeException(
|
||||
"Filter expression must be a bool or null, but got {}.", result.type());
|
||||
"Filter expression must evaluate to bool or null, got {}.",
|
||||
result.type());
|
||||
return result.Value<bool>();
|
||||
}
|
||||
|
||||
@ -885,7 +886,7 @@ class ExpandVariableCursor : public Cursor {
|
||||
auto value = EvaluateInt(&evaluator, bound, "Variable expansion bound");
|
||||
if (value < 0)
|
||||
throw QueryRuntimeException(
|
||||
"Variable expansion bound must be positive or zero");
|
||||
"Variable expansion bound must be a non-negative integer.");
|
||||
return value;
|
||||
};
|
||||
|
||||
@ -1281,7 +1282,7 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
break;
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Expansion condition must be boolean or null");
|
||||
"Expansion condition must evaluate to boolean or null.");
|
||||
}
|
||||
}
|
||||
to_visit_next_.emplace_back(edge, vertex);
|
||||
@ -1331,8 +1332,7 @@ class SingleSourceShortestPathCursor : public query::plan::Cursor {
|
||||
: std::numeric_limits<int64_t>::max();
|
||||
if (upper_bound_ < 1)
|
||||
throw QueryRuntimeException(
|
||||
"Max depth in breadth-first expansion must be greater then "
|
||||
"zero");
|
||||
"Maximum depth in breadth-first expansion must be at least 1.");
|
||||
|
||||
// go back to loop start and see if we expanded anything
|
||||
continue;
|
||||
@ -1433,11 +1433,11 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
self_.weight_lambda_->expression->Accept(evaluator);
|
||||
|
||||
if (!typed_weight.IsNumeric()) {
|
||||
throw QueryRuntimeException("Calculated weight must be numeric, got {}",
|
||||
typed_weight.type());
|
||||
throw QueryRuntimeException(
|
||||
"Calculated weight must be numeric, got {}.", typed_weight.type());
|
||||
}
|
||||
if ((typed_weight < 0).Value<bool>()) {
|
||||
throw QueryRuntimeException("Calculated weight can't be negative!");
|
||||
throw QueryRuntimeException("Calculated weight must be non-negative!");
|
||||
}
|
||||
|
||||
auto next_state = create_state(vertex, depth);
|
||||
@ -1491,8 +1491,8 @@ class ExpandWeightedShortestPathCursor : public query::plan::Cursor {
|
||||
}
|
||||
if (upper_bound_ < 1)
|
||||
throw QueryRuntimeException(
|
||||
"Max depth in weighted shortest path expansion must be greater "
|
||||
"than zero");
|
||||
"Maximum depth in weighted shortest path expansion must be at "
|
||||
"least 1.");
|
||||
|
||||
// Clear existing data structures.
|
||||
previous_.clear();
|
||||
@ -1880,7 +1880,7 @@ bool Delete::DeleteCursor::Pull(Frame &frame, Context &context) {
|
||||
break;
|
||||
// check we're not trying to delete anything except vertices and edges
|
||||
default:
|
||||
throw QueryRuntimeException("Can only delete edges and vertices");
|
||||
throw QueryRuntimeException("Only edges and vertices can be deleted.");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1935,7 +1935,7 @@ bool SetProperty::SetPropertyCursor::Pull(Frame &frame, Context &context) {
|
||||
// TODO: fix above described bug
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Properties can only be set on Vertices and Edges");
|
||||
"Properties can only be set on edges and vertices.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1983,7 +1983,7 @@ bool SetProperties::SetPropertiesCursor::Pull(Frame &frame, Context &context) {
|
||||
break;
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Properties can only be set on Vertices and Edges");
|
||||
"Properties can only be set on edges and vertices.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2026,7 +2026,8 @@ void SetProperties::SetPropertiesCursor::Set(TRecordAccessor &record,
|
||||
}
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Can only set Vertices, Edges and maps as properties");
|
||||
"Right-hand side in SET expression must be a node, an edge or a "
|
||||
"map.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2069,7 +2070,7 @@ bool SetLabels::SetLabelsCursor::Pull(Frame &frame, Context &context) {
|
||||
try {
|
||||
for (auto label : self_.labels_) vertex.add_label(label);
|
||||
} catch (const RecordDeletedError &) {
|
||||
throw QueryRuntimeException("Trying to set labels on a deleted Vertex");
|
||||
throw QueryRuntimeException("Trying to set labels on a deleted node.");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2111,7 +2112,7 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame,
|
||||
lhs.Value<VertexAccessor>().PropsErase(self_.lhs_->property_);
|
||||
} catch (const RecordDeletedError &) {
|
||||
throw QueryRuntimeException(
|
||||
"Trying to remove properties from a deleted Vertex");
|
||||
"Trying to remove properties from a deleted node.");
|
||||
}
|
||||
break;
|
||||
case TypedValue::Type::Edge:
|
||||
@ -2119,7 +2120,7 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame,
|
||||
lhs.Value<EdgeAccessor>().PropsErase(self_.lhs_->property_);
|
||||
} catch (const RecordDeletedError &) {
|
||||
throw QueryRuntimeException(
|
||||
"Trying to remove properties from a deleted Edge");
|
||||
"Trying to remove properties from a deleted edge.");
|
||||
}
|
||||
break;
|
||||
case TypedValue::Type::Null:
|
||||
@ -2127,7 +2128,7 @@ bool RemoveProperty::RemovePropertyCursor::Pull(Frame &frame,
|
||||
break;
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Properties can only be removed on Vertices and Edges");
|
||||
"Properties can only be removed from vertices and edges.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -2168,7 +2169,7 @@ bool RemoveLabels::RemoveLabelsCursor::Pull(Frame &frame, Context &context) {
|
||||
for (auto label : self_.labels_) vertex.remove_label(label);
|
||||
} catch (const RecordDeletedError &) {
|
||||
throw QueryRuntimeException(
|
||||
"Trying to remove labels from a deleted Vertex");
|
||||
"Trying to remove labels from a deleted node.");
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -2497,7 +2498,7 @@ void Aggregate::AggregateCursor::Update(
|
||||
case Aggregation::Op::COLLECT_MAP:
|
||||
auto key = agg_elem_it->key->Accept(evaluator);
|
||||
if (key.type() != TypedValue::Type::String)
|
||||
throw QueryRuntimeException("Map key must be a string");
|
||||
throw QueryRuntimeException("Map key must be a string.");
|
||||
value_it->Value<std::map<std::string, TypedValue>>().emplace(
|
||||
key.Value<std::string>(), input_value);
|
||||
break;
|
||||
@ -2519,7 +2520,7 @@ void Aggregate::AggregateCursor::Update(
|
||||
// safe to assume a bool TypedValue
|
||||
if (comparison_result.Value<bool>()) *value_it = input_value;
|
||||
} catch (const TypedValueException &) {
|
||||
throw QueryRuntimeException("Unable to get MIN of '{}' and '{}'",
|
||||
throw QueryRuntimeException("Unable to get MIN of '{}' and '{}'.",
|
||||
input_value.type(), value_it->type());
|
||||
}
|
||||
break;
|
||||
@ -2531,7 +2532,7 @@ void Aggregate::AggregateCursor::Update(
|
||||
TypedValue comparison_result = input_value > *value_it;
|
||||
if (comparison_result.Value<bool>()) *value_it = input_value;
|
||||
} catch (const TypedValueException &) {
|
||||
throw QueryRuntimeException("Unable to get MAX of '{}' and '{}'",
|
||||
throw QueryRuntimeException("Unable to get MAX of '{}' and '{}'.",
|
||||
input_value.type(), value_it->type());
|
||||
}
|
||||
break;
|
||||
@ -2549,7 +2550,7 @@ void Aggregate::AggregateCursor::Update(
|
||||
case Aggregation::Op::COLLECT_MAP:
|
||||
auto key = agg_elem_it->key->Accept(evaluator);
|
||||
if (key.type() != TypedValue::Type::String)
|
||||
throw QueryRuntimeException("Map key must be a string");
|
||||
throw QueryRuntimeException("Map key must be a string.");
|
||||
value_it->Value<std::map<std::string, TypedValue>>().emplace(
|
||||
key.Value<std::string>(), input_value);
|
||||
break;
|
||||
@ -2574,8 +2575,8 @@ void Aggregate::AggregateCursor::EnsureOkForMinMax(
|
||||
return;
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Only Bool, Int, Double and String values are allowed in "
|
||||
"MIN and MAX aggregations");
|
||||
"Only boolean, numeric and string values are allowed in "
|
||||
"MIN and MAX aggregations.");
|
||||
}
|
||||
}
|
||||
void Aggregate::AggregateCursor::EnsureOkForAvgSum(
|
||||
@ -2586,7 +2587,7 @@ void Aggregate::AggregateCursor::EnsureOkForAvgSum(
|
||||
return;
|
||||
default:
|
||||
throw QueryRuntimeException(
|
||||
"Only numeric values allowed in SUM and AVG aggregations");
|
||||
"Only numeric values allowed in SUM and AVG aggregations.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2631,12 +2632,13 @@ bool Skip::SkipCursor::Pull(Frame &frame, Context &context) {
|
||||
ExpressionEvaluator evaluator(frame, &context, GraphView::OLD);
|
||||
TypedValue to_skip = self_.expression_->Accept(evaluator);
|
||||
if (to_skip.type() != TypedValue::Type::Int)
|
||||
throw QueryRuntimeException("Result of SKIP expression must be an int");
|
||||
throw QueryRuntimeException(
|
||||
"Number of elements to skip must be an integer.");
|
||||
|
||||
to_skip_ = to_skip.Value<int64_t>();
|
||||
if (to_skip_ < 0)
|
||||
throw QueryRuntimeException(
|
||||
"Result of SKIP expression must be greater or equal to zero");
|
||||
"Number of elements to skip must be non-negative.");
|
||||
}
|
||||
|
||||
if (skipped_++ < to_skip_) continue;
|
||||
@ -2686,12 +2688,13 @@ bool Limit::LimitCursor::Pull(Frame &frame, Context &context) {
|
||||
ExpressionEvaluator evaluator(frame, &context, GraphView::OLD);
|
||||
TypedValue limit = self_.expression_->Accept(evaluator);
|
||||
if (limit.type() != TypedValue::Type::Int)
|
||||
throw QueryRuntimeException("Result of LIMIT expression must be an int");
|
||||
throw QueryRuntimeException(
|
||||
"Limit on number of returned elements must be an integer.");
|
||||
|
||||
limit_ = limit.Value<int64_t>();
|
||||
if (limit_ < 0)
|
||||
throw QueryRuntimeException(
|
||||
"Result of LIMIT expression must be greater or equal to zero");
|
||||
"Limit on number of returned elements must be non-negative.");
|
||||
}
|
||||
|
||||
// check we have not exceeded the limit before pulling
|
||||
@ -2976,8 +2979,9 @@ bool Unwind::UnwindCursor::Pull(Frame &frame, Context &context) {
|
||||
ExpressionEvaluator evaluator(frame, &context, GraphView::OLD);
|
||||
TypedValue input_value = self_.input_expression_->Accept(evaluator);
|
||||
if (input_value.type() != TypedValue::Type::List)
|
||||
throw QueryRuntimeException("UNWIND only accepts list values, got '{}'",
|
||||
input_value.type());
|
||||
throw QueryRuntimeException(
|
||||
"Argument of UNWIND must be a list, but '{}' was provided.",
|
||||
input_value.type());
|
||||
input_value_ = input_value.Value<std::vector<TypedValue>>();
|
||||
input_value_it_ = input_value_.begin();
|
||||
}
|
||||
@ -3377,7 +3381,8 @@ class AuthHandlerCursor : public Cursor {
|
||||
auto password_tv = self_.password()->Accept(evaluator);
|
||||
if (!password_tv.IsString() && !password_tv.IsNull()) {
|
||||
throw QueryRuntimeException(
|
||||
"Password must be a string or null, not '{}'!", password_tv.type());
|
||||
"Expected string or null for password, got {}.",
|
||||
password_tv.type());
|
||||
}
|
||||
if (password_tv.IsString()) {
|
||||
password = password_tv.ValueString();
|
||||
@ -3391,7 +3396,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto user = auth.AddUser(self_.user(), password);
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User or role '{}' already exists!",
|
||||
throw QueryRuntimeException("User or role '{}' already exists.",
|
||||
self_.user());
|
||||
}
|
||||
return false;
|
||||
@ -3401,10 +3406,10 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto user = auth.GetUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist!", self_.user());
|
||||
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user());
|
||||
}
|
||||
if (!auth.RemoveUser(self_.user())) {
|
||||
throw QueryRuntimeException("Couldn't remove user '{}'!",
|
||||
throw QueryRuntimeException("Couldn't remove user '{}'.",
|
||||
self_.user());
|
||||
}
|
||||
return false;
|
||||
@ -3414,7 +3419,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto user = auth.GetUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist!", self_.user());
|
||||
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user());
|
||||
}
|
||||
user->UpdatePassword(password);
|
||||
auth.SaveUser(*user);
|
||||
@ -3425,7 +3430,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto role = auth.AddRole(self_.role());
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("User or role '{}' already exists!",
|
||||
throw QueryRuntimeException("User or role '{}' already exists.",
|
||||
self_.role());
|
||||
}
|
||||
return false;
|
||||
@ -3435,10 +3440,10 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto role = auth.GetRole(self_.role());
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist!", self_.role());
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role());
|
||||
}
|
||||
if (!auth.RemoveRole(self_.role())) {
|
||||
throw QueryRuntimeException("Couldn't remove role '{}'!",
|
||||
throw QueryRuntimeException("Couldn't remove role '{}'.",
|
||||
self_.role());
|
||||
}
|
||||
return false;
|
||||
@ -3478,15 +3483,15 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto user = auth.GetUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist!", self_.user());
|
||||
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user());
|
||||
}
|
||||
auto role = auth.GetRole(self_.role());
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist!", self_.role());
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist.", self_.role());
|
||||
}
|
||||
if (user->role()) {
|
||||
throw QueryRuntimeException(
|
||||
"User '{}' is already a member of role '{}'!", self_.user(),
|
||||
"User '{}' is already a member of role '{}'.", self_.user(),
|
||||
user->role()->rolename());
|
||||
}
|
||||
user->SetRole(*role);
|
||||
@ -3498,7 +3503,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto user = auth.GetUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist!", self_.user());
|
||||
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user());
|
||||
}
|
||||
user->ClearRole();
|
||||
auth.SaveUser(*user);
|
||||
@ -3512,7 +3517,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
auto user = auth.GetUser(self_.user_or_role());
|
||||
auto role = auth.GetRole(self_.user_or_role());
|
||||
if (!user && !role) {
|
||||
throw QueryRuntimeException("User or role '{}' doesn't exist!",
|
||||
throw QueryRuntimeException("User or role '{}' doesn't exist.",
|
||||
self_.user_or_role());
|
||||
}
|
||||
auto permissions = GetAuthPermissions();
|
||||
@ -3554,7 +3559,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
auto user = auth.GetUser(self_.user_or_role());
|
||||
auto role = auth.GetRole(self_.user_or_role());
|
||||
if (!user && !role) {
|
||||
throw QueryRuntimeException("User or role '{}' doesn't exist!",
|
||||
throw QueryRuntimeException("User or role '{}' doesn't exist.",
|
||||
self_.user_or_role());
|
||||
}
|
||||
if (user) {
|
||||
@ -3580,7 +3585,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto user = auth.GetUser(self_.user());
|
||||
if (!user) {
|
||||
throw QueryRuntimeException("User '{}' doesn't exist!", self_.user());
|
||||
throw QueryRuntimeException("User '{}' doesn't exist.", self_.user());
|
||||
}
|
||||
if (user->role()) {
|
||||
frame[self_.role_symbol()] = user->role()->rolename();
|
||||
@ -3596,7 +3601,7 @@ class AuthHandlerCursor : public Cursor {
|
||||
std::lock_guard<std::mutex> lock(auth.WithLock());
|
||||
auto role = auth.GetRole(self_.role());
|
||||
if (!role) {
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist!",
|
||||
throw QueryRuntimeException("Role '{}' doesn't exist.",
|
||||
self_.role());
|
||||
}
|
||||
users_.emplace(auth.AllUsersForRole(self_.role()));
|
||||
|
@ -36,7 +36,7 @@
|
||||
|
||||
- name: integration__auth
|
||||
cd: auth
|
||||
commands: TIMEOUT=600 ./runner.py
|
||||
commands: TIMEOUT=820 ./runner.py
|
||||
infiles:
|
||||
- runner.py # runner script
|
||||
- ../../../build_debug/memgraph # memgraph binary
|
||||
|
@ -1403,7 +1403,7 @@ TEST(ExpressionEvaluator, FunctionAssert) {
|
||||
try {
|
||||
EvaluateFunction("ASSERT", {false, "bbgba"});
|
||||
} catch (QueryRuntimeException &e) {
|
||||
ASSERT_TRUE(utils::EndsWith(e.what(), "bbgba"));
|
||||
ASSERT_TRUE(std::string(e.what()).find("bbgba") != std::string::npos);
|
||||
}
|
||||
|
||||
// Valid calls, assertion passes.
|
||||
|
Loading…
Reference in New Issue
Block a user