1
0
Fork 0

Included a backward transformation AqlValueVPack -> AqlValueJson. This allows to use the new VPack Functions without modification after switch. They return AqlValueVPack.

This commit is contained in:
Michael Hackstein 2016-02-03 10:44:32 +01:00
parent 6eeb686287
commit f478411bb8
4 changed files with 294 additions and 105 deletions

View File

@ -37,6 +37,11 @@ using namespace arangodb::aql;
using Json = arangodb::basics::Json;
using JsonHelper = arangodb::basics::JsonHelper;
AqlValue::AqlValue(AqlValue$ const& other) : _json(nullptr), _type(JSON) {
_json = new Json(TRI_UNKNOWN_MEM_ZONE, arangodb::basics::VelocyPackHelper::velocyPackToJson(other.slice()));
TRI_ASSERT(_json != nullptr);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief a quick method to decide whether a value is true
////////////////////////////////////////////////////////////////////////////////
@ -723,19 +728,65 @@ Json AqlValue::toJson(arangodb::AqlTransaction* trx,
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor
////////////////////////////////////////////////////////////////////////////////
AqlValue$::AqlValue$(VPackBuilder const& data) {
TRI_ASSERT(data.isClosed());
VPackValueLength l = data.size();
if (l < 16) {
// Use internal
memcpy(_data.internal, data.data(), l);
_data.internal[15] = AqlValueType::INTERNAL;
} else {
// Use external
_data.external = new VPackBuffer<uint8_t>(l);
memcpy(_data.external->data(), data.data(), l);
_data.internal[15] = AqlValueType::EXTERNAL;
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor
////////////////////////////////////////////////////////////////////////////////
AqlValue$::AqlValue$(VPackBuilder const* data) : AqlValue$(*data){};
////////////////////////////////////////////////////////////////////////////////
/// @brief Constructor
////////////////////////////////////////////////////////////////////////////////
AqlValue$::AqlValue$(VPackSlice const& data) {
VPackValueLength l = data.byteSize();
if (l < 16) {
// Use internal
memcpy(_data.internal, data.start(), l);
_data.internal[15] = AqlValueType::INTERNAL;
} else {
// Use external
_data.external = new VPackBuffer<uint8_t>(l);
memcpy(_data.external->data(), data.start(), l);
_data.internal[15] = AqlValueType::EXTERNAL;
}
};
////////////////////////////////////////////////////////////////////////////////
/// @brief Copy Constructor.
////////////////////////////////////////////////////////////////////////////////
AqlValue$::AqlValue$(AqlValue$ const& other) {
VPackSlice s = other.slice();
VPackValueLength length = s.length();
VPackValueLength length = s.byteSize();
if (other.type()) {
// Isse external
_data.external = new VPackBuffer<uint8_t>(length);
memcpy(_data.external->data(), other._data.external->data(), length);
_data.internal[15] = AqlValueType::EXTERNAL;
} else {
memcpy(_data.internal, other._data.internal, length);
_data.internal[15] = AqlValueType::INTERNAL;
}
}
@ -785,18 +836,15 @@ AqlValue$::AqlValue$(AqlValue const& other, arangodb::AqlTransaction* trx,
}
case AqlValue::RANGE: {
// TODO Has to be replaced by VPackCustom Type
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL);
/*
TRI_ASSERT(_range != nullptr);
TRI_ASSERT(other._range != nullptr);
try {
VPackArrayBuilder b(&builder);
size_t const n = _range->size();
size_t const n = other._range->size();
for (size_t i = 0; i < n; ++i) {
builder.add(VPackValue(_range->at(i)));
builder.add(VPackValue(other._range->at(i)));
}
} catch (...) {
}
*/
break;
}
case AqlValue::EMPTY: {
@ -813,18 +861,18 @@ AqlValue$::AqlValue$(AqlValue const& other, arangodb::AqlTransaction* trx,
// Small enough for local
// copy memory from the builder into the internal data.
memcpy(_data.internal, builder.data(), length);
_data.internal[15] = 1;
_data.internal[15] = AqlValueType::INTERNAL;
} else {
// We need a large external buffer
// TODO: Replace by SlimBuffer
_data.external = new VPackBuffer<uint8_t>(length);
memcpy(_data.external->data(), builder.data(), length);
_data.internal[15] = 0;
_data.internal[15] = AqlValueType::EXTERNAL;
}
}
bool AqlValue$::type() const {
return _data.internal[15] == 0;
AqlValue$::AqlValueType AqlValue$::type() const {
return static_cast<AqlValueType>(_data.internal[15]);
}
VPackSlice AqlValue$::slice() const {

View File

@ -46,6 +46,9 @@ namespace aql {
class AqlItemBlock;
// Temporary Forward
struct AqlValue$;
////////////////////////////////////////////////////////////////////////////////
/// @brief a struct to hold a value, registers hole AqlValue* during the
/// execution
@ -89,6 +92,8 @@ struct AqlValue {
_range = new Range(low, high);
}
explicit AqlValue(AqlValue$ const& other);
//////////////////////////////////////////////////////////////////////////////
/// @brief destructor, doing nothing automatically!
//////////////////////////////////////////////////////////////////////////////
@ -358,6 +363,13 @@ struct AqlValue {
};
struct AqlValue$ {
public:
//////////////////////////////////////////////////////////////////////////////
/// @brief AqlValueType, indicates what sort of value we have
//////////////////////////////////////////////////////////////////////////////
enum AqlValueType { INTERNAL, EXTERNAL };
//////////////////////////////////////////////////////////////////////////////
/// @brief Holds the actual data for this AqlValue it has the following
/// semantics:
@ -378,8 +390,9 @@ struct AqlValue$ {
} _data;
public:
AqlValue$(VPackBuilder const& data);
AqlValue$(VPackBuilder const* data);
AqlValue$(arangodb::velocypack::Builder const&);
AqlValue$(arangodb::velocypack::Builder const*);
AqlValue$(arangodb::velocypack::Slice const&);
AqlValue$(AqlValue const&, arangodb::AqlTransaction*,
TRI_document_collection_t const*);
@ -402,7 +415,7 @@ struct AqlValue$ {
//////////////////////////////////////////////////////////////////////////////
// Read last bit of the union
bool type() const;
AqlValueType type() const;
//////////////////////////////////////////////////////////////////////////////
/// @brief Returns a slice to read this Value's data

View File

@ -912,17 +912,20 @@ AqlValue Functions::IsNull(arangodb::aql::Query* q, arangodb::AqlTransaction* tr
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return IsNullVPack(q, trx, tmp);
return AqlValue(IsNullVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isNull()));
#endif
}
AqlValue Functions::IsNullVPack(arangodb::aql::Query*, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::IsNullVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0);
return AqlValue(new Json(slice.isNull()));
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
b->add(VPackValue(slice.isNull()));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -933,18 +936,20 @@ AqlValue Functions::IsBool(arangodb::aql::Query* q, arangodb::AqlTransaction* tr
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return IsBoolVPack(q, trx, tmp);
return AqlValue(IsBoolVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isBoolean()));
#endif
}
AqlValue Functions::IsBoolVPack(arangodb::aql::Query*,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::IsBoolVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0);
return AqlValue(new Json(slice.isBoolean()));
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
b->add(VPackValue(slice.isBool()));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -956,18 +961,20 @@ AqlValue Functions::IsNumber(arangodb::aql::Query* q,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return IsNumberVPack(q, trx, tmp);
return AqlValue(IsNumberVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isNumber()));
#endif
}
AqlValue Functions::IsNumberVPack(arangodb::aql::Query*,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::IsNumberVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0);
return AqlValue(new Json(slice.isNumber()));
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
b->add(VPackValue(slice.isNumber()));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -980,18 +987,20 @@ AqlValue Functions::IsString(arangodb::aql::Query* q,
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return IsStringVPack(q, trx, tmp);
return AqlValue(IsStringVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isString()));
#endif
}
AqlValue Functions::IsStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::IsStringVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0);
return AqlValue(new Json(slice.isString()));
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
b->add(VPackValue(slice.isString()));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -1003,18 +1012,20 @@ AqlValue Functions::IsArray(arangodb::aql::Query* q,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return IsArrayVPack(q, trx, tmp);
return AqlValue(IsArrayVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isArray()));
#endif
}
AqlValue Functions::IsArrayVPack(arangodb::aql::Query*,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::IsArrayVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0);
return AqlValue(new Json(slice.isArray()));
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
b->add(VPackValue(slice.isArray()));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -1026,18 +1037,20 @@ AqlValue Functions::IsObject(arangodb::aql::Query* q,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return IsObjectVPack(q, trx, tmp);
return AqlValue(IsObjectVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isObject()));
#endif
}
AqlValue Functions::IsObjectVPack(arangodb::aql::Query*,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::IsObjectVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0);
return AqlValue(new Json(slice.isObject()));
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
b->add(VPackValue(slice.isObject()));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -1049,7 +1062,7 @@ AqlValue Functions::ToNumber(arangodb::aql::Query* q,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return ToNumberVPack(q, trx, tmp);
return AqlValue(ToNumberVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1063,7 +1076,7 @@ AqlValue Functions::ToNumber(arangodb::aql::Query* q,
#endif
}
AqlValue Functions::ToNumberVPack(arangodb::aql::Query*,
AqlValue$ Functions::ToNumberVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0);
@ -1071,10 +1084,14 @@ AqlValue Functions::ToNumberVPack(arangodb::aql::Query*,
bool isValid;
double v = ValueToNumber(slice, isValid);
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
if (!isValid) {
return AqlValue(new Json(Json::Null));
b->add(VPackValue(VPackValueType::Null));
} else {
b->add(VPackValue(v));
}
return AqlValue(new Json(v));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -1086,7 +1103,7 @@ AqlValue Functions::ToString(arangodb::aql::Query* q,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return ToStringVPack(q, trx, tmp);
return AqlValue(ToStringVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1107,26 +1124,23 @@ AqlValue Functions::ToString(arangodb::aql::Query* q,
#endif
}
AqlValue Functions::ToStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::ToStringVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const value = ExtractFunctionParameter(trx, parameters, 0);
arangodb::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE, 24);
arangodb::basics::VPackStringBufferAdapter adapter(buffer.stringBuffer());
AppendAsString(adapter, value);
size_t length = buffer.length();
std::unique_ptr<TRI_json_t> j(
TRI_CreateStringJson(TRI_UNKNOWN_MEM_ZONE, buffer.steal(), length));
if (j == nullptr) {
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
try {
std::string res(buffer.begin(), buffer.length());
b->add(VPackValue(res));
} catch (...) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
}
auto jr = new Json(TRI_UNKNOWN_MEM_ZONE, j.get());
j.release();
return AqlValue(jr);
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -1137,7 +1151,7 @@ AqlValue Functions::ToBool(arangodb::aql::Query* q, arangodb::AqlTransaction* tr
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return ToBoolVPack(q, trx, tmp);
return AqlValue(ToBoolVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1145,10 +1159,13 @@ AqlValue Functions::ToBool(arangodb::aql::Query* q, arangodb::AqlTransaction* tr
#endif
}
AqlValue Functions::ToBoolVPack(arangodb::aql::Query* q, arangodb::AqlTransaction* trx,
AqlValue$ Functions::ToBoolVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const value = ExtractFunctionParameter(trx, parameters, 0);
return AqlValue(new Json(ValueToBoolean(value)));
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
b->add(VPackValue(ValueToBoolean(value)));
return AqlValue$(b.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -1160,7 +1177,7 @@ AqlValue Functions::ToArray(arangodb::aql::Query* q,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return ToArrayVPack(q, trx, tmp);
return AqlValue(ToArrayVPack(q, trx, tmp));
#else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1195,43 +1212,43 @@ AqlValue Functions::ToArray(arangodb::aql::Query* q,
#endif
}
AqlValue Functions::ToArrayVPack(arangodb::aql::Query*,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
AqlValue$ Functions::ToArrayVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const value = ExtractFunctionParameter(trx, parameters, 0);
if (value.isArray()) {
// return copy of the original array
return AqlValue(
new Json(TRI_UNKNOWN_MEM_ZONE,
arangodb::basics::VelocyPackHelper::velocyPackToJson(value)));
return AqlValue$(value);
}
VPackBuilder result;
std::shared_ptr<VPackBuilder> result = query->getSharedBuilder();
{
VPackArrayBuilder b(&result);
VPackArrayBuilder b(result.get());
if (value.isBoolean() || value.isNumber() || value.isString()) {
// return array with single member
result.add(value);
result->add(value);
} else if (value.isObject()) {
// return an array with the attribute values
for (auto const& it : VPackObjectIterator(value)) {
result.add(it.value);
result->add(it.value);
}
}
// else return empty array
}
return AqlValue(
new Json(TRI_UNKNOWN_MEM_ZONE,
arangodb::basics::VelocyPackHelper::velocyPackToJson(result.slice())));
return AqlValue$(result.get());
}
////////////////////////////////////////////////////////////////////////////////
/// @brief function LENGTH
////////////////////////////////////////////////////////////////////////////////
AqlValue Functions::Length(arangodb::aql::Query*, arangodb::AqlTransaction* trx,
AqlValue Functions::Length(arangodb::aql::Query* q, arangodb::AqlTransaction* trx,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return AqlValue(LengthVPack(q, trx, tmp));
#else
if (!parameters.empty() && parameters[0].first.isArray()) {
// shortcut!
return AqlValue(
@ -1292,6 +1309,44 @@ AqlValue Functions::Length(arangodb::aql::Query*, arangodb::AqlTransaction* trx,
}
return AqlValue(new Json(static_cast<double>(length)));
#endif
}
AqlValue$ Functions::LengthVPack(arangodb::aql::Query* q,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const value = ExtractFunctionParameter(trx, parameters, 0);
std::shared_ptr<VPackBuilder> builder = q->getSharedBuilder();
if (value.isArray()) {
// shortcut!
builder->add(VPackValue(static_cast<double>(value.length())));
return AqlValue$(builder->slice());
}
size_t length = 0;
if (value.isNone() || value.isNull()) {
length = 0;
} else if (value.isBoolean()) {
if (value.getBoolean()) {
length = 1;
} else {
length = 0;
}
} else if (value.isNumber()) {
double tmp = value.getNumericValue<double>();
if (std::isnan(tmp) || !std::isfinite(tmp)) {
length = strlen("null");
} else {
char buffer[24];
length = static_cast<size_t>(fpconv_dtoa(tmp, buffer));
}
} else if (value.isString()) {
std::string tmp = value.copyString();
length = TRI_CharLengthUtf8String(tmp.c_str());
} else if (value.isObject()) {
length = static_cast<size_t>(value.length());
}
builder->add(VPackValue(static_cast<double>(length)));
return AqlValue$(builder.get());
}
////////////////////////////////////////////////////////////////////////////////
@ -1301,6 +1356,10 @@ AqlValue Functions::Length(arangodb::aql::Query*, arangodb::AqlTransaction* trx,
AqlValue Functions::First(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return AqlValue(FirstVPack(query, trx, tmp));
#else
if (parameters.size() < 1) {
THROW_ARANGO_EXCEPTION_PARAMS(
TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "FIRST", (int)1,
@ -1322,6 +1381,35 @@ AqlValue Functions::First(arangodb::aql::Query* query,
auto j = new Json(TRI_UNKNOWN_MEM_ZONE, value.at(0).copy().steal(),
Json::AUTOFREE);
return AqlValue(j);
#endif
}
AqlValue$ Functions::FirstVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
if (parameters.size() < 1) {
THROW_ARANGO_EXCEPTION_PARAMS(
TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "FIRST", (int)1,
(int)1);
}
auto value = ExtractFunctionParameter(trx, parameters, 0);
if (!value.isArray()) {
// not an array
RegisterWarning(query, "FIRST", TRI_ERROR_QUERY_ARRAY_EXPECTED);
std::shared_ptr<VPackBuilder> builder = query->getSharedBuilder();
builder->add(VPackValue(VPackValueType::Null));
return AqlValue$(builder.get());
}
if (value.length() == 0) {
std::shared_ptr<VPackBuilder> builder = query->getSharedBuilder();
builder->add(VPackValue(VPackValueType::Null));
return AqlValue$(builder.get());
}
return AqlValue$(value.at(0));
}
////////////////////////////////////////////////////////////////////////////////
@ -1331,6 +1419,10 @@ AqlValue Functions::First(arangodb::aql::Query* query,
AqlValue Functions::Last(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return AqlValue(LastVPack(query, trx, tmp));
#else
if (parameters.size() < 1) {
THROW_ARANGO_EXCEPTION_PARAMS(
TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "LAST", (int)1,
@ -1354,6 +1446,36 @@ AqlValue Functions::Last(arangodb::aql::Query* query,
auto j = new Json(TRI_UNKNOWN_MEM_ZONE, value.at(n - 1).copy().steal(),
Json::AUTOFREE);
return AqlValue(j);
#endif
}
AqlValue$ Functions::LastVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
if (parameters.size() < 1) {
THROW_ARANGO_EXCEPTION_PARAMS(
TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "LAST", (int)1,
(int)1);
}
auto value = ExtractFunctionParameter(trx, parameters, 0);
if (!value.isArray()) {
// not an array
RegisterWarning(query, "LAST", TRI_ERROR_QUERY_ARRAY_EXPECTED);
std::shared_ptr<VPackBuilder> builder = query->getSharedBuilder();
builder->add(VPackValue(VPackValueType::Null));
return AqlValue$(builder.get());
}
VPackValueLength const n = value.length();
if (n == 0) {
std::shared_ptr<VPackBuilder> builder = query->getSharedBuilder();
builder->add(VPackValue(VPackValueType::Null));
return AqlValue$(builder.get());
}
return AqlValue$(value.at(n-1));
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -65,57 +65,63 @@ struct Functions {
static AqlValue IsNull(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue IsNullVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ IsNullVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue IsBool(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue IsBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ IsBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue IsNumber(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue IsNumberVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ IsNumberVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue IsString(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue IsStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ IsStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue IsArray(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue IsArrayVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue IsObject(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue IsObjectVPack(arangodb::aql::Query*,
static AqlValue$ IsArrayVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue IsObject(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue$ IsObjectVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue ToNumber(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue ToNumberVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ ToNumberVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue ToString(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue ToStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ ToStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue ToBool(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue ToBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ ToBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue ToArray(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue ToArrayVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue$ ToArrayVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue Length(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue$ LengthVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue First(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue$ FirstVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue Last(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue$ LastVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue Nth(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&);
static AqlValue Concat(arangodb::aql::Query*, arangodb::AqlTransaction*,