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 Json = arangodb::basics::Json;
using JsonHelper = arangodb::basics::JsonHelper; 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 /// @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); 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. /// @brief Copy Constructor.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AqlValue$::AqlValue$(AqlValue$ const& other) { AqlValue$::AqlValue$(AqlValue$ const& other) {
VPackSlice s = other.slice(); VPackSlice s = other.slice();
VPackValueLength length = s.length(); VPackValueLength length = s.byteSize();
if (other.type()) { if (other.type()) {
// Isse external // Isse external
_data.external = new VPackBuffer<uint8_t>(length); _data.external = new VPackBuffer<uint8_t>(length);
memcpy(_data.external->data(), other._data.external->data(), length); memcpy(_data.external->data(), other._data.external->data(), length);
_data.internal[15] = AqlValueType::EXTERNAL;
} else { } else {
memcpy(_data.internal, other._data.internal, length); 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: { case AqlValue::RANGE: {
// TODO Has to be replaced by VPackCustom Type // TODO Has to be replaced by VPackCustom Type
THROW_ARANGO_EXCEPTION(TRI_ERROR_INTERNAL); TRI_ASSERT(other._range != nullptr);
/*
TRI_ASSERT(_range != nullptr);
try { try {
VPackArrayBuilder b(&builder); VPackArrayBuilder b(&builder);
size_t const n = _range->size(); size_t const n = other._range->size();
for (size_t i = 0; i < n; ++i) { for (size_t i = 0; i < n; ++i) {
builder.add(VPackValue(_range->at(i))); builder.add(VPackValue(other._range->at(i)));
} }
} catch (...) { } catch (...) {
} }
*/
break; break;
} }
case AqlValue::EMPTY: { case AqlValue::EMPTY: {
@ -813,18 +861,18 @@ AqlValue$::AqlValue$(AqlValue const& other, arangodb::AqlTransaction* trx,
// Small enough for local // Small enough for local
// copy memory from the builder into the internal data. // copy memory from the builder into the internal data.
memcpy(_data.internal, builder.data(), length); memcpy(_data.internal, builder.data(), length);
_data.internal[15] = 1; _data.internal[15] = AqlValueType::INTERNAL;
} else { } else {
// We need a large external buffer // We need a large external buffer
// TODO: Replace by SlimBuffer // TODO: Replace by SlimBuffer
_data.external = new VPackBuffer<uint8_t>(length); _data.external = new VPackBuffer<uint8_t>(length);
memcpy(_data.external->data(), builder.data(), length); memcpy(_data.external->data(), builder.data(), length);
_data.internal[15] = 0; _data.internal[15] = AqlValueType::EXTERNAL;
} }
} }
bool AqlValue$::type() const { AqlValue$::AqlValueType AqlValue$::type() const {
return _data.internal[15] == 0; return static_cast<AqlValueType>(_data.internal[15]);
} }
VPackSlice AqlValue$::slice() const { VPackSlice AqlValue$::slice() const {

View File

@ -46,6 +46,9 @@ namespace aql {
class AqlItemBlock; class AqlItemBlock;
// Temporary Forward
struct AqlValue$;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief a struct to hold a value, registers hole AqlValue* during the /// @brief a struct to hold a value, registers hole AqlValue* during the
/// execution /// execution
@ -89,6 +92,8 @@ struct AqlValue {
_range = new Range(low, high); _range = new Range(low, high);
} }
explicit AqlValue(AqlValue$ const& other);
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief destructor, doing nothing automatically! /// @brief destructor, doing nothing automatically!
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -358,6 +363,13 @@ struct AqlValue {
}; };
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 /// @brief Holds the actual data for this AqlValue it has the following
/// semantics: /// semantics:
@ -378,8 +390,9 @@ struct AqlValue$ {
} _data; } _data;
public: public:
AqlValue$(VPackBuilder const& data); AqlValue$(arangodb::velocypack::Builder const&);
AqlValue$(VPackBuilder const* data); AqlValue$(arangodb::velocypack::Builder const*);
AqlValue$(arangodb::velocypack::Slice const&);
AqlValue$(AqlValue const&, arangodb::AqlTransaction*, AqlValue$(AqlValue const&, arangodb::AqlTransaction*,
TRI_document_collection_t const*); TRI_document_collection_t const*);
@ -402,7 +415,7 @@ struct AqlValue$ {
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// Read last bit of the union // Read last bit of the union
bool type() const; AqlValueType type() const;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
/// @brief Returns a slice to read this Value's data /// @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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return IsNullVPack(q, trx, tmp); return AqlValue(IsNullVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isNull())); return AqlValue(new Json(value.isNull()));
#endif #endif
} }
AqlValue Functions::IsNullVPack(arangodb::aql::Query*, arangodb::AqlTransaction* trx, AqlValue$ Functions::IsNullVPack(arangodb::aql::Query* query,
VPackFunctionParameters const& parameters) { arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0); 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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return IsBoolVPack(q, trx, tmp); return AqlValue(IsBoolVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isBoolean())); return AqlValue(new Json(value.isBoolean()));
#endif #endif
} }
AqlValue Functions::IsBoolVPack(arangodb::aql::Query*, AqlValue$ Functions::IsBoolVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0); 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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return IsNumberVPack(q, trx, tmp); return AqlValue(IsNumberVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isNumber())); return AqlValue(new Json(value.isNumber()));
#endif #endif
} }
AqlValue Functions::IsNumberVPack(arangodb::aql::Query*, AqlValue$ Functions::IsNumberVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0); 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 #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return IsStringVPack(q, trx, tmp); return AqlValue(IsStringVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isString())); return AqlValue(new Json(value.isString()));
#endif #endif
} }
AqlValue Functions::IsStringVPack(arangodb::aql::Query*, AqlValue$ Functions::IsStringVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0); 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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return IsArrayVPack(q, trx, tmp); return AqlValue(IsArrayVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isArray())); return AqlValue(new Json(value.isArray()));
#endif #endif
} }
AqlValue Functions::IsArrayVPack(arangodb::aql::Query*, AqlValue$ Functions::IsArrayVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0); 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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return IsObjectVPack(q, trx, tmp); return AqlValue(IsObjectVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
return AqlValue(new Json(value.isObject())); return AqlValue(new Json(value.isObject()));
#endif #endif
} }
AqlValue Functions::IsObjectVPack(arangodb::aql::Query*, AqlValue$ Functions::IsObjectVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0); 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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return ToNumberVPack(q, trx, tmp); return AqlValue(ToNumberVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1063,7 +1076,7 @@ AqlValue Functions::ToNumber(arangodb::aql::Query* q,
#endif #endif
} }
AqlValue Functions::ToNumberVPack(arangodb::aql::Query*, AqlValue$ Functions::ToNumberVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const slice = ExtractFunctionParameter(trx, parameters, 0); auto const slice = ExtractFunctionParameter(trx, parameters, 0);
@ -1071,10 +1084,14 @@ AqlValue Functions::ToNumberVPack(arangodb::aql::Query*,
bool isValid; bool isValid;
double v = ValueToNumber(slice, isValid); double v = ValueToNumber(slice, isValid);
std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
if (!isValid) { 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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return ToStringVPack(q, trx, tmp); return AqlValue(ToStringVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1107,26 +1124,23 @@ AqlValue Functions::ToString(arangodb::aql::Query* q,
#endif #endif
} }
AqlValue Functions::ToStringVPack(arangodb::aql::Query*, AqlValue$ Functions::ToStringVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const value = ExtractFunctionParameter(trx, parameters, 0); auto const value = ExtractFunctionParameter(trx, parameters, 0);
arangodb::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE, 24); arangodb::basics::StringBuffer buffer(TRI_UNKNOWN_MEM_ZONE, 24);
arangodb::basics::VPackStringBufferAdapter adapter(buffer.stringBuffer()); arangodb::basics::VPackStringBufferAdapter adapter(buffer.stringBuffer());
AppendAsString(adapter, value); AppendAsString(adapter, value);
size_t length = buffer.length(); std::shared_ptr<VPackBuilder> b = query->getSharedBuilder();
std::unique_ptr<TRI_json_t> j( try {
TRI_CreateStringJson(TRI_UNKNOWN_MEM_ZONE, buffer.steal(), length)); std::string res(buffer.begin(), buffer.length());
b->add(VPackValue(res));
if (j == nullptr) { } catch (...) {
THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY); THROW_ARANGO_EXCEPTION(TRI_ERROR_OUT_OF_MEMORY);
} }
return AqlValue$(b.get());
auto jr = new Json(TRI_UNKNOWN_MEM_ZONE, j.get());
j.release();
return AqlValue(jr);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -1137,7 +1151,7 @@ AqlValue Functions::ToBool(arangodb::aql::Query* q, arangodb::AqlTransaction* tr
FunctionParameters const& parameters) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return ToBoolVPack(q, trx, tmp); return AqlValue(ToBoolVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1145,10 +1159,13 @@ AqlValue Functions::ToBool(arangodb::aql::Query* q, arangodb::AqlTransaction* tr
#endif #endif
} }
AqlValue Functions::ToBoolVPack(arangodb::aql::Query* q, arangodb::AqlTransaction* trx, AqlValue$ Functions::ToBoolVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const value = ExtractFunctionParameter(trx, parameters, 0); 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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK #ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx); auto tmp = transformParameters(parameters, trx);
return ToArrayVPack(q, trx, tmp); return AqlValue(ToArrayVPack(q, trx, tmp));
#else #else
auto const value = ExtractFunctionParameter(trx, parameters, 0, false); auto const value = ExtractFunctionParameter(trx, parameters, 0, false);
@ -1195,43 +1212,43 @@ AqlValue Functions::ToArray(arangodb::aql::Query* q,
#endif #endif
} }
AqlValue Functions::ToArrayVPack(arangodb::aql::Query*, AqlValue$ Functions::ToArrayVPack(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
VPackFunctionParameters const& parameters) { VPackFunctionParameters const& parameters) {
auto const value = ExtractFunctionParameter(trx, parameters, 0); auto const value = ExtractFunctionParameter(trx, parameters, 0);
if (value.isArray()) { if (value.isArray()) {
// return copy of the original array // return copy of the original array
return AqlValue( return AqlValue$(value);
new Json(TRI_UNKNOWN_MEM_ZONE,
arangodb::basics::VelocyPackHelper::velocyPackToJson(value)));
} }
VPackBuilder result; std::shared_ptr<VPackBuilder> result = query->getSharedBuilder();
{ {
VPackArrayBuilder b(&result); VPackArrayBuilder b(result.get());
if (value.isBoolean() || value.isNumber() || value.isString()) { if (value.isBoolean() || value.isNumber() || value.isString()) {
// return array with single member // return array with single member
result.add(value); result->add(value);
} else if (value.isObject()) { } else if (value.isObject()) {
// return an array with the attribute values // return an array with the attribute values
for (auto const& it : VPackObjectIterator(value)) { for (auto const& it : VPackObjectIterator(value)) {
result.add(it.value); result->add(it.value);
} }
} }
// else return empty array // else return empty array
} }
return AqlValue$(result.get());
return AqlValue(
new Json(TRI_UNKNOWN_MEM_ZONE,
arangodb::basics::VelocyPackHelper::velocyPackToJson(result.slice())));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief function LENGTH /// @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) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return AqlValue(LengthVPack(q, trx, tmp));
#else
if (!parameters.empty() && parameters[0].first.isArray()) { if (!parameters.empty() && parameters[0].first.isArray()) {
// shortcut! // shortcut!
return AqlValue( return AqlValue(
@ -1292,6 +1309,44 @@ AqlValue Functions::Length(arangodb::aql::Query*, arangodb::AqlTransaction* trx,
} }
return AqlValue(new Json(static_cast<double>(length))); 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, AqlValue Functions::First(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
FunctionParameters const& parameters) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return AqlValue(FirstVPack(query, trx, tmp));
#else
if (parameters.size() < 1) { if (parameters.size() < 1) {
THROW_ARANGO_EXCEPTION_PARAMS( THROW_ARANGO_EXCEPTION_PARAMS(
TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "FIRST", (int)1, 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(), auto j = new Json(TRI_UNKNOWN_MEM_ZONE, value.at(0).copy().steal(),
Json::AUTOFREE); Json::AUTOFREE);
return AqlValue(j); 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, AqlValue Functions::Last(arangodb::aql::Query* query,
arangodb::AqlTransaction* trx, arangodb::AqlTransaction* trx,
FunctionParameters const& parameters) { FunctionParameters const& parameters) {
#ifdef TMPUSEVPACK
auto tmp = transformParameters(parameters, trx);
return AqlValue(LastVPack(query, trx, tmp));
#else
if (parameters.size() < 1) { if (parameters.size() < 1) {
THROW_ARANGO_EXCEPTION_PARAMS( THROW_ARANGO_EXCEPTION_PARAMS(
TRI_ERROR_QUERY_FUNCTION_ARGUMENT_NUMBER_MISMATCH, "LAST", (int)1, 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(), auto j = new Json(TRI_UNKNOWN_MEM_ZONE, value.at(n - 1).copy().steal(),
Json::AUTOFREE); Json::AUTOFREE);
return AqlValue(j); 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*, static AqlValue IsNull(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue IsNullVPack(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue$ IsNullVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue IsBool(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue IsBool(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue IsBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue$ IsBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue IsNumber(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue IsNumber(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue IsNumberVPack(arangodb::aql::Query*, static AqlValue$ IsNumberVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue IsString(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue IsString(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue IsStringVPack(arangodb::aql::Query*, static AqlValue$ IsStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue IsArray(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue IsArray(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue IsArrayVPack(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*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); 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*, static AqlValue ToNumber(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue ToNumberVPack(arangodb::aql::Query*, static AqlValue$ ToNumberVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue ToString(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue ToString(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue ToStringVPack(arangodb::aql::Query*, static AqlValue$ ToStringVPack(arangodb::aql::Query*,
arangodb::AqlTransaction*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue ToBool(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue ToBool(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue ToBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue$ ToBoolVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue ToArray(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue ToArray(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue ToArrayVPack(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue$ ToArrayVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&); VPackFunctionParameters const&);
static AqlValue Length(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue Length(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue$ LengthVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue First(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue First(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue$ FirstVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue Last(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue Last(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue$ LastVPack(arangodb::aql::Query*, arangodb::AqlTransaction*,
VPackFunctionParameters const&);
static AqlValue Nth(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue Nth(arangodb::aql::Query*, arangodb::AqlTransaction*,
FunctionParameters const&); FunctionParameters const&);
static AqlValue Concat(arangodb::aql::Query*, arangodb::AqlTransaction*, static AqlValue Concat(arangodb::aql::Query*, arangodb::AqlTransaction*,