From f841daf68098d2883b4512f1f38cb4d06b5f5dad Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 14 Oct 2015 16:08:23 +0200 Subject: [PATCH] Improve performance for object queries fixes #10360 --- lib/remote/objectqueryhandler.cpp | 42 ++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 9 deletions(-) diff --git a/lib/remote/objectqueryhandler.cpp b/lib/remote/objectqueryhandler.cpp index d8565acc4..888d5a50f 100644 --- a/lib/remote/objectqueryhandler.cpp +++ b/lib/remote/objectqueryhandler.cpp @@ -61,14 +61,17 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re attrs.insert(uattr); String::SizeType dpos = uattr.FindFirstOf("."); - if (dpos != String::NPos) { - String userJoinAttr = uattr.SubStr(0, dpos); + if (dpos == String::NPos) { + HttpUtility::SendJsonError(response, 400, "Attribute name must contain '.'."); + return true; + } - if (userJoinAttr == type->GetName().ToLower()) - userJoinAttr = ""; + String userJoinAttr = uattr.SubStr(0, dpos); - userJoinAttrs.insert(userJoinAttr); - } + if (userJoinAttr == type->GetName().ToLower()) + userJoinAttr = ""; + + userJoinAttrs.insert(userJoinAttr); } } @@ -98,6 +101,7 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re std::vector objs = FilterUtility::GetFilterTargets(qd, params, user); Array::Ptr results = new Array(); + results->Reserve(objs.size()); BOOST_FOREACH(const ConfigObject::Ptr& obj, objs) { Dictionary::Ptr result1 = new Dictionary(); @@ -128,11 +132,31 @@ bool ObjectQueryHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re Type::Ptr joinedType = joinedObj->GetReflectionType(); - for (int fid = 0; fid < joinedType->GetFieldCount(); fid++) { + std::vector fids; + + if (attrs.empty()) { + for (int fid = 0; fid < joinedType->GetFieldCount(); fid++) { + fids.push_back(fid); + } + } else { + BOOST_FOREACH(const String& aname, attrs) { + String::SizeType dpos = aname.FindFirstOf("."); + ASSERT(dpos != String::NPos); + + String userJoinAttr = aname.SubStr(0, dpos); + if (userJoinAttr != prefix) + continue; + + String userAttr = aname.SubStr(dpos + 1); + + int fid = joinedType->GetFieldId(userAttr); + fids.push_back(fid); + } + } + + BOOST_FOREACH(int& fid, fids) { Field field = joinedType->GetFieldInfo(fid); String aname = prefix + "." + field.Name; - if (!attrs.empty() && attrs.find(aname) == attrs.end()) - continue; Value val = joinedObj->GetField(fid); -- 2.40.0