From: Gunnar Beutner Date: Wed, 14 Oct 2015 14:08:23 +0000 (+0200) Subject: Improve performance for object queries X-Git-Tag: v2.4.0~204 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f841daf68098d2883b4512f1f38cb4d06b5f5dad;p=icinga2 Improve performance for object queries fixes #10360 --- 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);