1
0
Fork 0

Now the input for indexes is parsed using the new attribute parser. This means the flags for expanded Attributes are set. Also introduced a transformation function to transform an attributeName list back into a string.

This commit is contained in:
Michael Hackstein 2015-08-06 15:54:16 +02:00
parent f36c411afd
commit 17a8f73a06
22 changed files with 184 additions and 62 deletions

View File

@ -206,6 +206,35 @@ BOOST_AUTO_TEST_CASE (test_nonClosingBracket2) {
}
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test_reverseTransform
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (test_reverseTransform) {
std::string input = "foo[*].bar.baz[*]";
std::vector<AttributeName const> result;
TRI_ParseAttributeString(input, result);
std::string output = "";
TRI_AttributeNamesToString(result, output);
BOOST_CHECK_EQUAL(output, input);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief test_reverseTransformToPidPath
////////////////////////////////////////////////////////////////////////////////
BOOST_AUTO_TEST_CASE (test_reverseTransformToPidPath) {
std::string input = "foo[*].bar.baz[*]";
std::string expected = "foo.bar.baz";
std::vector<AttributeName const> result;
TRI_ParseAttributeString(input, result);
std::string output = "";
TRI_AttributeNamesToString(result, output, true);
BOOST_CHECK_EQUAL(output, expected);
}

View File

@ -1545,8 +1545,10 @@ void IndexRangeBlock::sortConditions () {
for (size_t t = 0; t < numFields; t++) {
for (size_t u = 0; u < _condition->at(s).size(); u++) {
auto const& ri = _condition->at(s)[u];
std::string fieldString;
TRI_AttributeNamesToString(en->_index->fields[t], fieldString);
if (en->_index->fields[t].name.compare(ri._attr) == 0) {
if (fieldString.compare(ri._attr) == 0) {
TRI_IF_FAILURE("IndexRangeBlock::sortConditionsInner") {
THROW_ARANGO_EXCEPTION(TRI_ERROR_DEBUG);

View File

@ -549,20 +549,22 @@ ExecutionNode::IndexMatch ExecutionNode::CompareIndex (ExecutionNode const* node
size_t j = 0;
for (; (i < idxFields && j < n); i++) {
if (equalityLookupAttributes.find(idx->fields[i].name) != equalityLookupAttributes.end()) {
std::string fieldString;
TRI_AttributeNamesToString(idx->fields[i], fieldString);
if (equalityLookupAttributes.find(fieldString) != equalityLookupAttributes.end()) {
// found an attribute in the sort criterion that is used in an equality lookup, too...
// (e.g. doc.value == 1 && SORT doc.value1)
// in this case, we can ignore the sorting for this particular attribute, as the index
// will only return constant values for it
match.matches.push_back(FORWARD_MATCH); // doesn't matter here if FORWARD or BACKWARD
++interestingCount;
if (attrs[j].first == idx->fields[i].name) {
if (attrs[j].first == fieldString) {
++j;
}
continue;
}
if (attrs[j].first == idx->fields[i].name) {
if (attrs[j].first == fieldString) {
if (attrs[j].second) {
// ascending
match.matches.push_back(FORWARD_MATCH);
@ -1246,7 +1248,9 @@ size_t EnumerateCollectionNode::getUsableFieldsOfIndex (Index const* idx,
std::unordered_set<std::string> const& attrs) const {
size_t count = 0;
for (size_t i = 0; i < idx->fields.size(); i++) {
if (attrs.find(idx->fields[i].name) == attrs.end()) {
std::string tmp;
TRI_AttributeNamesToString(idx->fields[i], tmp);
if (attrs.find(tmp) == attrs.end()) {
break;
}

View File

@ -97,7 +97,9 @@ namespace triagens {
auto * name = static_cast<TRI_json_t const*>(TRI_AtVector(&f->_value._objects, i));
if (TRI_IsStringJson(name)) {
fields.emplace_back(std::string(name->_value._string.data, name->_value._string.length - 1), false);
std::vector<triagens::basics::AttributeName const> parsedAttributes;
TRI_ParseAttributeString(std::string(name->_value._string.data, name->_value._string.length - 1), parsedAttributes);
fields.emplace_back(parsedAttributes);
}
}
}
@ -123,7 +125,9 @@ namespace triagens {
triagens::basics::Json f(triagens::basics::Json::Array);
for (auto const& field : fields) {
f.add(triagens::basics::Json(field.name));
std::string tmp;
TRI_AttributeNamesToString(field, tmp);
f.add(triagens::basics::Json(tmp));
}
json("fields", f);
@ -168,11 +172,11 @@ namespace triagens {
public:
TRI_idx_iid_t const id;
triagens::arango::Index::IndexType type;
bool unique;
bool sparse;
std::vector<triagens::basics::AttributeName> fields;
TRI_idx_iid_t const id;
triagens::arango::Index::IndexType type;
bool unique;
bool sparse;
std::vector<std::vector<triagens::basics::AttributeName const>> fields;
private:

View File

@ -2364,7 +2364,9 @@ class FilterToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
auto const map = _rangeInfoMapVec->find(var->name, validPos[k]);
for (size_t j = 0; j < idx->fields.size(); j++) {
auto range = map->find(idx->fields[j].name);
std::string fieldString;
TRI_AttributeNamesToString(idx->fields[j], fieldString);
auto range = map->find(fieldString);
if (range == map->end() || ! range->second.is1ValueRangeInfo()) {
indexOrCondition.clear(); // not usable
@ -2408,8 +2410,10 @@ class FilterToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
for (size_t k = 0; k < validPos.size(); k++) {
auto const map = _rangeInfoMapVec->find(var->name, validPos[k]);
std::string fieldString;
TRI_AttributeNamesToString(idx->fields[0], fieldString);
// check if there is a range that contains the first index attribute
auto range = map->find(idx->fields[0].name);
auto range = map->find(fieldString);
if (range == map->end()) {
indexOrCondition.clear();
@ -2424,7 +2428,9 @@ class FilterToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
bool handled = false;
size_t j = 0;
while (++j < prefixes.at(i) && equality) {
range = map->find(idx->fields[j].name);
std::string fieldString;
TRI_AttributeNamesToString(idx->fields[j], fieldString);
range = map->find(fieldString);
if (range == map->end()) {
indexOrCondition.clear();
@ -2452,7 +2458,9 @@ class FilterToEnumCollFinder final : public WalkerWorker<ExecutionNode> {
auto const map = _rangeInfoMapVec->find(var->name, validPos[k]);
for (size_t j = 0; j < idx->fields.size(); j++) {
auto range = map->find(idx->fields[j].name);
std::string fieldString;
TRI_AttributeNamesToString(idx->fields[j], fieldString);
auto range = map->find(fieldString);
if (range == map->end()) {
indexOrCondition.clear();

View File

@ -52,7 +52,7 @@ CapConstraint::CapConstraint (TRI_idx_iid_t iid,
TRI_document_collection_t* collection,
size_t count,
int64_t size)
: Index(iid, collection, std::vector<triagens::basics::AttributeName>()),
: Index(iid, collection, std::vector<std::vector<triagens::basics::AttributeName const>>()),
_count(count),
_size(static_cast<int64_t>(size)) {

View File

@ -315,7 +315,7 @@ static bool IsEqualElementEdgeToByKey (void const* left,
EdgeIndex::EdgeIndex (TRI_idx_iid_t iid,
TRI_document_collection_t* collection)
: Index(iid, collection, std::vector<triagens::basics::AttributeName>({ { TRI_VOC_ATTRIBUTE_FROM, false }, { TRI_VOC_ATTRIBUTE_TO , false } })),
: Index(iid, collection, std::vector<std::vector<triagens::basics::AttributeName const>>({ { { TRI_VOC_ATTRIBUTE_FROM, false } }, { { TRI_VOC_ATTRIBUTE_TO , false } } })),
_edgesFrom(nullptr),
_edgesTo(nullptr) {

View File

@ -121,7 +121,7 @@ FulltextIndex::FulltextIndex (TRI_idx_iid_t iid,
TRI_document_collection_t* collection,
std::string const& attribute,
int minWordLength)
: Index(iid, collection, std::vector<triagens::basics::AttributeName>{ { attribute, false } } ),
: Index(iid, collection, std::vector<std::vector<triagens::basics::AttributeName const>> { { { attribute, false } } } ),
_pid(0),
_fulltextIndex(nullptr),
_minWordLength(minWordLength > 0 ? minWordLength : 1) {

View File

@ -92,7 +92,9 @@ namespace triagens {
int cleanup () override final;
bool isSame (std::string const& field, int minWordLength) const {
return (_minWordLength == minWordLength && fields()[0].name == field);
std::string fieldString;
TRI_AttributeNamesToString(fields()[0], fieldString);
return (_minWordLength == minWordLength && fieldString == field);
}
TRI_fts_index_t* internals () {

View File

@ -49,7 +49,7 @@ using namespace triagens::arango;
GeoIndex2::GeoIndex2 (TRI_idx_iid_t iid,
TRI_document_collection_t* collection,
std::vector<triagens::basics::AttributeName> const& fields,
std::vector<std::vector<triagens::basics::AttributeName const>> const& fields,
std::vector<TRI_shape_pid_t> const& paths,
bool geoJson)
: Index(iid, collection, fields),
@ -76,7 +76,7 @@ GeoIndex2::GeoIndex2 (TRI_idx_iid_t iid,
GeoIndex2::GeoIndex2 (TRI_idx_iid_t iid,
TRI_document_collection_t* collection,
std::vector<triagens::basics::AttributeName> const& fields,
std::vector<std::vector<triagens::basics::AttributeName const>> const& fields,
std::vector<TRI_shape_pid_t> const& paths)
: Index(iid, collection, fields),
_paths(paths),

View File

@ -58,13 +58,13 @@ namespace triagens {
GeoIndex2 (TRI_idx_iid_t,
struct TRI_document_collection_t*,
std::vector<triagens::basics::AttributeName> const&,
std::vector<std::vector<triagens::basics::AttributeName const>> const&,
std::vector<TRI_shape_pid_t> const&,
bool);
GeoIndex2 (TRI_idx_iid_t,
struct TRI_document_collection_t*,
std::vector<triagens::basics::AttributeName> const&,
std::vector<std::vector<triagens::basics::AttributeName const>> const&,
std::vector<TRI_shape_pid_t> const&);
~GeoIndex2 ();

View File

@ -250,7 +250,7 @@ static int HashIndex_find (TRI_hash_array_t const* hashArray,
HashIndex::HashIndex (TRI_idx_iid_t iid,
TRI_document_collection_t* collection,
std::vector<triagens::basics::AttributeName> const& fields,
std::vector<std::vector<triagens::basics::AttributeName const>> const& fields,
std::vector<TRI_shape_pid_t> const& paths,
bool unique,
bool sparse)

View File

@ -57,7 +57,7 @@ namespace triagens {
HashIndex (TRI_idx_iid_t,
struct TRI_document_collection_t*,
std::vector<triagens::basics::AttributeName> const&,
std::vector<std::vector<triagens::basics::AttributeName const>> const&,
std::vector<TRI_shape_pid_t> const&,
bool,
bool);

View File

@ -45,7 +45,7 @@ using namespace triagens::arango;
Index::Index (TRI_idx_iid_t iid,
TRI_document_collection_t* collection,
std::vector<triagens::basics::AttributeName> const& fields)
std::vector<std::vector<triagens::basics::AttributeName const>> const& fields)
: _iid(iid),
_collection(collection),
_fields(fields) {
@ -340,7 +340,9 @@ triagens::basics::Json Index::toJson (TRI_memory_zone_t* zone) const {
triagens::basics::Json f(zone, triagens::basics::Json::Array, fields().size());
for (auto const& field : fields()) {
f.add(triagens::basics::Json(zone, field.name));
std::string fieldString;
TRI_AttributeNamesToString(field, fieldString);
f.add(triagens::basics::Json(zone, fieldString));
}
json("fields", f);

View File

@ -76,7 +76,7 @@ namespace triagens {
Index (TRI_idx_iid_t,
struct TRI_document_collection_t*,
std::vector<triagens::basics::AttributeName> const&);
std::vector<std::vector<triagens::basics::AttributeName const> >const&);
virtual ~Index ();
@ -118,7 +118,7 @@ namespace triagens {
/// @brief return the index fields
////////////////////////////////////////////////////////////////////////////////
inline std::vector<triagens::basics::AttributeName> const& fields () const {
inline std::vector<std::vector<triagens::basics::AttributeName const>> const& fields () const {
return _fields;
}
@ -204,11 +204,11 @@ namespace triagens {
protected:
TRI_idx_iid_t const _iid;
TRI_idx_iid_t const _iid;
struct TRI_document_collection_t* _collection;
struct TRI_document_collection_t* _collection;
std::vector<triagens::basics::AttributeName> const _fields;
std::vector<std::vector<triagens::basics::AttributeName const>> const _fields;
};

View File

@ -73,7 +73,7 @@ uint64_t const PrimaryIndex::InitialSize = 251;
// -----------------------------------------------------------------------------
PrimaryIndex::PrimaryIndex (TRI_document_collection_t* collection)
: Index(0, collection, std::vector<triagens::basics::AttributeName>( { { TRI_VOC_ATTRIBUTE_KEY, false } } )) {
: Index(0, collection, std::vector<std::vector<triagens::basics::AttributeName const>>( { { { TRI_VOC_ATTRIBUTE_KEY, false } } } )) {
_primaryIndex._nrAlloc = 0;
_primaryIndex._nrUsed = 0;

View File

@ -127,7 +127,7 @@ static int FillLookupOperator (TRI_index_operator_t* slOperator,
SkiplistIndex2::SkiplistIndex2 (TRI_idx_iid_t iid,
TRI_document_collection_t* collection,
std::vector<triagens::basics::AttributeName> const& fields,
std::vector<std::vector<triagens::basics::AttributeName const>> const& fields,
std::vector<TRI_shape_pid_t> const& paths,
bool unique,
bool sparse)

View File

@ -57,7 +57,7 @@ namespace triagens {
SkiplistIndex2 (TRI_idx_iid_t,
struct TRI_document_collection_t*,
std::vector<triagens::basics::AttributeName> const&,
std::vector<std::vector<triagens::basics::AttributeName const>> const&,
std::vector<TRI_shape_pid_t> const&,
bool,
bool);

View File

@ -183,7 +183,7 @@ static void CalculateSkipLimitSlice (size_t length,
////////////////////////////////////////////////////////////////////////////////
static TRI_index_operator_t* SetupConditionsSkiplist (v8::Isolate* isolate,
std::vector<triagens::basics::AttributeName> const& fields,
std::vector<std::vector<triagens::basics::AttributeName const>> const& fields,
VocShaper* shaper,
v8::Handle<v8::Object> conditions) {
TRI_index_operator_t* lastOperator = nullptr;
@ -199,7 +199,9 @@ static TRI_index_operator_t* SetupConditionsSkiplist (v8::Isolate* isolate,
// iterate over all index fields
size_t i = 0;
for (auto const& field : fields) {
v8::Handle<v8::String> key = TRI_V8_STD_STRING(field.name);
std::string fieldString;
TRI_AttributeNamesToString(field, fieldString);
v8::Handle<v8::String> key = TRI_V8_STD_STRING(fieldString);
if (! conditions->HasOwnProperty(key)) {
break;
@ -394,7 +396,7 @@ MEM_ERROR:
////////////////////////////////////////////////////////////////////////////////
static TRI_index_operator_t* SetupExampleSkiplist (v8::Isolate* isolate,
std::vector<triagens::basics::AttributeName> const& fields,
std::vector<std::vector<triagens::basics::AttributeName const>> const& fields,
VocShaper* shaper,
v8::Handle<v8::Object> example) {
TRI_json_t* parameters = TRI_CreateArrayJson(TRI_UNKNOWN_MEM_ZONE);
@ -404,7 +406,9 @@ static TRI_index_operator_t* SetupExampleSkiplist (v8::Isolate* isolate,
}
for (auto const& field : fields) {
v8::Handle<v8::String> key = TRI_V8_STD_STRING(field.name);
std::string fieldString;
TRI_AttributeNamesToString(field, fieldString);
v8::Handle<v8::String> key = TRI_V8_STD_STRING(fieldString);
if (! example->HasOwnProperty(key)) {
break;

View File

@ -3371,7 +3371,7 @@ static int FillIndex (TRI_document_collection_t* document,
////////////////////////////////////////////////////////////////////////////////
static triagens::arango::Index* LookupPathIndexDocumentCollection (TRI_document_collection_t* collection,
std::vector<triagens::basics::AttributeName> const& paths,
std::vector<std::vector<triagens::basics::AttributeName const>> const& paths,
triagens::arango::Index::IndexType type,
int sparsity,
bool unique,
@ -3434,11 +3434,16 @@ static triagens::arango::Index* LookupPathIndexDocumentCollection (TRI_document_
// any permutation of attributes is allowed
for (size_t i = 0; i < n; ++i) {
found = false;
size_t fieldSize = idxFields[i].size();
for (size_t j = 0; j < n; ++j) {
if (idxFields[i] == paths[j]) {
found = true;
break;
if (fieldSize == paths[j].size()) {
for (size_t k = 0; k < fieldSize; ++k) {
if (idxFields[j][k] == paths[j][k]) {
found = true;
break;
}
}
}
}
@ -3450,9 +3455,14 @@ static triagens::arango::Index* LookupPathIndexDocumentCollection (TRI_document_
else {
// attributes need to be present in a given order
for (size_t i = 0; i < n; ++i) {
if (idxFields[i] != paths[i]) {
found = false;
break;
size_t fieldSize = idxFields[i].size();
if (fieldSize == paths[i].size()) {
for (size_t k = 0; k < fieldSize; ++k) {
if (idxFields[i][k] != paths[i][k]) {
found = false;
break;
}
}
}
}
}
@ -3742,7 +3752,7 @@ bool TRI_DropIndexDocumentCollection (TRI_document_collection_t* document,
static int PidNamesByAttributeNames (std::vector<std::string> const& attributes,
VocShaper* shaper,
std::vector<TRI_shape_pid_t>& pids,
std::vector<triagens::basics::AttributeName>& names,
std::vector<std::vector<triagens::basics::AttributeName const>>& names,
bool sorted,
bool create) {
pids.reserve(attributes.size());
@ -3754,25 +3764,31 @@ static int PidNamesByAttributeNames (std::vector<std::string> const& attributes,
if (sorted) {
// combine name and pid
typedef std::pair<std::string, TRI_shape_pid_t> PidNameType;
typedef std::pair<std::vector<triagens::basics::AttributeName const>, TRI_shape_pid_t> PidNameType;
std::vector<PidNameType> pidNames;
pidNames.reserve(attributes.size());
for (auto const& name : attributes) {
std::vector<triagens::basics::AttributeName const> attrNameList;
TRI_ParseAttributeString(name, attrNameList);
TRI_ASSERT(attrNameList.size() > 0);
std::string pidPath;
TRI_AttributeNamesToString(attrNameList, pidPath, true);
TRI_shape_pid_t pid;
if (create) {
pid = shaper->findOrCreateAttributePathByName(name.c_str());
pid = shaper->findOrCreateAttributePathByName(pidPath.c_str());
}
else {
pid = shaper->lookupAttributePathByName(name.c_str());
pid = shaper->lookupAttributePathByName(pidPath.c_str());
}
if (pid == 0) {
return TRI_set_errno(TRI_ERROR_ARANGO_ILLEGAL_NAME);
}
pidNames.emplace_back(std::make_pair(name, pid));
pidNames.emplace_back(std::make_pair(attrNameList, pid));
}
// sort according to pid
@ -3782,7 +3798,7 @@ static int PidNamesByAttributeNames (std::vector<std::string> const& attributes,
for (auto const& it : pidNames) {
pids.emplace_back(it.second);
names.emplace_back(it.first, false);
names.emplace_back(it.first);
}
}
@ -3792,13 +3808,20 @@ static int PidNamesByAttributeNames (std::vector<std::string> const& attributes,
else {
for (auto const& name : attributes) {
std::vector<triagens::basics::AttributeName const> attrNameList;
TRI_ParseAttributeString(name, attrNameList);
TRI_ASSERT(attrNameList.size() > 0);
std::string pidPath;
TRI_AttributeNamesToString(attrNameList, pidPath, true);
TRI_shape_pid_t pid;
if (create) {
pid = shaper->findOrCreateAttributePathByName(name.c_str());
pid = shaper->findOrCreateAttributePathByName(pidPath.c_str());
}
else {
pid = shaper->lookupAttributePathByName(name.c_str());
pid = shaper->lookupAttributePathByName(pidPath.c_str());
}
if (pid == 0) {
@ -3806,7 +3829,7 @@ static int PidNamesByAttributeNames (std::vector<std::string> const& attributes,
}
pids.emplace_back(pid);
names.emplace_back(name, false);
names.emplace_back(attrNameList);
}
}
@ -4062,14 +4085,14 @@ static triagens::arango::Index* CreateGeoIndexDocumentCollection (TRI_document_c
// create a new index
if (! location.empty()) {
geoIndex.reset(new triagens::arango::GeoIndex2(iid, document, std::vector<triagens::basics::AttributeName>{ { location, false } }, std::vector<TRI_shape_pid_t>{ loc }, geoJson));
geoIndex.reset(new triagens::arango::GeoIndex2(iid, document, std::vector<std::vector<triagens::basics::AttributeName const>> { { { location, false } } }, std::vector<TRI_shape_pid_t>{ loc }, geoJson));
LOG_TRACE("created geo-index for location '%s': %ld",
location.c_str(),
(unsigned long) loc);
}
else if (! longitude.empty() && ! latitude.empty()) {
geoIndex.reset(new triagens::arango::GeoIndex2(iid, document, std::vector<triagens::basics::AttributeName>{ { latitude, false } , { longitude, false } }, std::vector<TRI_shape_pid_t>{ lat, lon }));
geoIndex.reset(new triagens::arango::GeoIndex2(iid, document, std::vector<std::vector<triagens::basics::AttributeName const>>{ { { latitude, false } } , { { longitude, false } } }, std::vector<TRI_shape_pid_t>{ lat, lon }));
LOG_TRACE("created geo-index for location '%s': %ld, %ld",
location.c_str(),
@ -4354,7 +4377,7 @@ static triagens::arango::Index* CreateHashIndexDocumentCollection (TRI_document_
bool unique,
bool* created) {
std::vector<TRI_shape_pid_t> paths;
std::vector<triagens::basics::AttributeName> fields;
std::vector<std::vector<triagens::basics::AttributeName const>> fields;
// determine the sorted shape ids for the attributes
int res = PidNamesByAttributeNames(attributes,
@ -4453,7 +4476,7 @@ triagens::arango::Index* TRI_LookupHashIndexDocumentCollection (TRI_document_col
int sparsity,
bool unique) {
std::vector<TRI_shape_pid_t> paths;
std::vector<triagens::basics::AttributeName> fields;
std::vector<std::vector<triagens::basics::AttributeName const>> fields;
// determine the sorted shape ids for the attributes
int res = PidNamesByAttributeNames(attributes,
@ -4521,7 +4544,7 @@ static triagens::arango::Index* CreateSkiplistIndexDocumentCollection (TRI_docum
bool unique,
bool* created) {
std::vector<TRI_shape_pid_t> paths;
std::vector<triagens::basics::AttributeName> fields;
std::vector<std::vector<triagens::basics::AttributeName const>> fields;
int res = PidNamesByAttributeNames(attributes,
document->getShaper(), // ONLY IN INDEX, PROTECTED by RUNTIME
@ -4617,7 +4640,7 @@ triagens::arango::Index* TRI_LookupSkiplistIndexDocumentCollection (TRI_document
int sparsity,
bool unique) {
std::vector<TRI_shape_pid_t> paths;
std::vector<triagens::basics::AttributeName> fields;
std::vector<std::vector<triagens::basics::AttributeName const>> fields;
// determine the unsorted shape ids for the attributes
int res = PidNamesByAttributeNames(attributes,

View File

@ -60,3 +60,25 @@ void triagens::basics::TRI_ParseAttributeString (
result.emplace_back(input.substr(parsedUntil), false);
}
}
void triagens::basics::TRI_AttributeNamesToString (
std::vector<AttributeName const> const& input,
std::string& result,
bool excludeExpansion
) {
TRI_ASSERT(result.size() == 0);
bool isFirst = true;
for (auto& it : input) {
if (!isFirst) {
result += ".";
}
isFirst = false;
result += it.name;
if (! excludeExpansion && it.shouldExpand) {
result += "[*]";
}
}
}

View File

@ -64,10 +64,32 @@ namespace triagens {
}
};
// -----------------------------------------------------------------------------
// --SECTION-- public functions
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief Parse an input string into attribute names and expansion flags
////////////////////////////////////////////////////////////////////////////////
void TRI_ParseAttributeString (
std::string const& input,
std::vector<AttributeName const>& result
);
////////////////////////////////////////////////////////////////////////////////
/// @brief Transform a vector of AttributeNames back into a string
////////////////////////////////////////////////////////////////////////////////
void TRI_AttributeNamesToString (
std::vector<AttributeName const> const& input,
std::string& result,
bool excludeExpansion = false
);
}
}