|
@@ -2871,6 +2871,19 @@ public:
|
|
|
return root->numChildren();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Add a filter to an xpath query, with the appropriate filter flags
|
|
|
+ */
|
|
|
+ static void appendFilterToQueryString(StringBuffer& query, int flags, const char* name, const char* value)
|
|
|
+ {
|
|
|
+ query.append('[').append(name).append('=');
|
|
|
+ if (flags & WUSFnocase)
|
|
|
+ query.append('?');
|
|
|
+ if (flags & WUSFwild)
|
|
|
+ query.append('~');
|
|
|
+ query.append('"').append(value).append("\"]");
|
|
|
+ };
|
|
|
+
|
|
|
IConstWorkUnitIterator* getWorkUnitsSorted( WUSortField sortorder, // field to sort by (and flags for desc sort etc)
|
|
|
WUSortField *filters, // NULL or list of fields to filter on (terminated by WUSFterm)
|
|
|
const void *filterbuf, // (appended) string values for filters
|
|
@@ -2881,66 +2894,68 @@ public:
|
|
|
ISecManager *secmgr,
|
|
|
ISecUser *secuser)
|
|
|
{
|
|
|
- class CQueryOrFilter : public CInterface, implements IInterface
|
|
|
+ class CQueryOrFilter : public CInterface
|
|
|
{
|
|
|
- int fmt;
|
|
|
+ unsigned flags;
|
|
|
StringAttr name;
|
|
|
StringArray values;
|
|
|
public:
|
|
|
IMPLEMENT_IINTERFACE;
|
|
|
+ CQueryOrFilter(unsigned _flags, const char *_name, const char *_value)
|
|
|
+ : flags(_flags), name(_name)
|
|
|
+ {
|
|
|
+ values.appendListUniq(_value, "|");
|
|
|
+ };
|
|
|
|
|
|
- CQueryOrFilter() {};
|
|
|
-
|
|
|
- void setName(const char* _name) { name.set(_name); };
|
|
|
- void setFormat(int _fmt) { fmt = _fmt; };
|
|
|
- void appendValue(const char* _value) { values.append(_value); };
|
|
|
- const char* getName() { return name.get(); };
|
|
|
- int getFormat() { return fmt; };
|
|
|
- StringArray& getValues() { return values; };
|
|
|
+ const char* queryName() { return name.get(); };
|
|
|
+ unsigned querySearchFlags() { return flags; };
|
|
|
+ const StringArray& queryValues() const { return values; };
|
|
|
};
|
|
|
- class CWorkUnitsPagerHelper : public CInterface, implements IInterface
|
|
|
+ class CMultiPTreeIterator : public CInterfaceOf<IPropertyTreeIterator>
|
|
|
{
|
|
|
public:
|
|
|
- IMPLEMENT_IINTERFACE;
|
|
|
-
|
|
|
- CWorkUnitsPagerHelper() {};
|
|
|
- void setOrFilter(CQueryOrFilter& orFilter, int fmt, const char* name, const char* value, const char* sep)
|
|
|
+ virtual bool first() override
|
|
|
{
|
|
|
- if (!strieq(name, getEnumText(WUSFstate,workunitSortFields)) && !strieq(name, getEnumText(WUSFuser,workunitSortFields))
|
|
|
- && !strieq(name, getEnumText(WUSFcluster,workunitSortFields)))
|
|
|
- throw MakeStringException(WUERR_InvalidUserInput, "OR filters not allowed for %s", name);
|
|
|
-
|
|
|
- StringArray vlist;
|
|
|
- vlist.appendListUniq(value, sep);
|
|
|
- ForEachItemIn(q, vlist)
|
|
|
+ curSource = 0;
|
|
|
+ while (sources.isItem(curSource))
|
|
|
{
|
|
|
- const char* v = vlist.item(q);
|
|
|
- if (!isEmptyString(v))
|
|
|
- orFilter.appendValue(v);
|
|
|
+ if (sources.item(curSource).first())
|
|
|
+ return true;
|
|
|
+ curSource++;
|
|
|
}
|
|
|
- if (orFilter.getValues().length() < 2)
|
|
|
- throw MakeStringException(WUERR_InvalidUserInput, "Invalid OR filter %s for %s", value, name);
|
|
|
-
|
|
|
- orFilter.setName(name);
|
|
|
- orFilter.setFormat(fmt);
|
|
|
- };
|
|
|
- void appendFilterToQueryString(StringBuffer& query, int fmt, const char* name, const char* value)
|
|
|
- {
|
|
|
- query.append('[').append(name).append('=');
|
|
|
- if (fmt&WUSFnocase)
|
|
|
- query.append('?');
|
|
|
- if (fmt&WUSFwild)
|
|
|
- query.append('~');
|
|
|
- query.append('"').append(value).append("\"]");
|
|
|
- };
|
|
|
- void addToWUTree(IPropertyTree* wuTree, IPropertyTreeIterator* from)
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ virtual bool next() override
|
|
|
{
|
|
|
- ForEach (*from)
|
|
|
+ if (sources.isItem(curSource))
|
|
|
{
|
|
|
- IPropertyTree& pt = from->query();
|
|
|
- wuTree->addPropTree(pt.queryName(), LINK(&pt));
|
|
|
+ if (sources.item(curSource).next())
|
|
|
+ return true;
|
|
|
+ curSource++;
|
|
|
+ while (sources.isItem(curSource))
|
|
|
+ {
|
|
|
+ if (sources.item(curSource).first())
|
|
|
+ return true;
|
|
|
+ curSource++;
|
|
|
+ }
|
|
|
}
|
|
|
- };
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ virtual bool isValid() override
|
|
|
+ {
|
|
|
+ return sources.isItem(curSource);
|
|
|
+ }
|
|
|
+ virtual IPropertyTree & query() override
|
|
|
+ {
|
|
|
+ return sources.item(curSource).query();
|
|
|
+ }
|
|
|
+ void addSource(IPropertyTreeIterator &source)
|
|
|
+ {
|
|
|
+ sources.append(source);
|
|
|
+ }
|
|
|
+ private:
|
|
|
+ IArrayOf<IPropertyTreeIterator> sources;
|
|
|
+ unsigned curSource = 0;
|
|
|
};
|
|
|
class CWorkUnitsPager : public CSimpleInterface, implements IElementsPager
|
|
|
{
|
|
@@ -2949,7 +2964,7 @@ public:
|
|
|
StringAttr nameFilterLo;
|
|
|
StringAttr nameFilterHi;
|
|
|
StringArray unknownAttributes;
|
|
|
- CQueryOrFilter* orFilter;
|
|
|
+ Owned<CQueryOrFilter> orFilter;
|
|
|
|
|
|
public:
|
|
|
IMPLEMENT_IINTERFACE_USING(CSimpleInterface);
|
|
@@ -2972,23 +2987,28 @@ public:
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- CWorkUnitsPagerHelper helper;
|
|
|
- Owned<IPropertyTree> wuTree = createPTree("WorkUnits");
|
|
|
-
|
|
|
- const char* name = orFilter->getName();
|
|
|
- int fmt = orFilter->getFormat();
|
|
|
- StringArray& values = orFilter->getValues();
|
|
|
+ Owned <CMultiPTreeIterator> multi = new CMultiPTreeIterator;
|
|
|
+ bool added = false;
|
|
|
+ const char* fieldName = orFilter->queryName();
|
|
|
+ unsigned flags = orFilter->querySearchFlags();
|
|
|
+ const StringArray& values = orFilter->queryValues();
|
|
|
ForEachItemIn(i, values)
|
|
|
{
|
|
|
StringBuffer path = xPath.get();
|
|
|
const char* value = values.item(i);
|
|
|
- helper.appendFilterToQueryString(path, fmt, name, value);
|
|
|
- Owned<IPropertyTreeIterator> itr = conn->getElements(path.str());
|
|
|
- if (itr)
|
|
|
- helper.addToWUTree(wuTree, itr);
|
|
|
+ if (!isEmptyString(value))
|
|
|
+ {
|
|
|
+ appendFilterToQueryString(path, flags, fieldName, value);
|
|
|
+ IPropertyTreeIterator *itr = conn->getElements(path.str());
|
|
|
+ if (itr)
|
|
|
+ {
|
|
|
+ multi->addSource(*itr);
|
|
|
+ added = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- if(wuTree->hasChildren())
|
|
|
- iter.setown(wuTree->getElements("*"));
|
|
|
+ if (added)
|
|
|
+ iter.setown(multi.getClear());
|
|
|
}
|
|
|
if (!iter)
|
|
|
return NULL;
|
|
@@ -3032,9 +3052,7 @@ public:
|
|
|
return ret;
|
|
|
}
|
|
|
};
|
|
|
- CWorkUnitsPagerHelper helper;
|
|
|
- bool hasOrFilter = false;
|
|
|
- CQueryOrFilter orFilter;
|
|
|
+ Owned<CQueryOrFilter> orFilter;
|
|
|
Owned<ISortedElementsTreeFilter> sc = new CScopeChecker(secmgr,secuser);
|
|
|
StringBuffer query;
|
|
|
StringBuffer so;
|
|
@@ -3075,13 +3093,16 @@ public:
|
|
|
{
|
|
|
const char* fieldName = getEnumText(subfmt,workunitSortFields);
|
|
|
if (!strchr(fv, '|'))
|
|
|
- helper.appendFilterToQueryString(query, fmt, fieldName, fv);
|
|
|
- else if (hasOrFilter)
|
|
|
+ appendFilterToQueryString(query, fmt, fieldName, fv);
|
|
|
+ else if (orFilter)
|
|
|
throw MakeStringException(WUERR_InvalidUserInput, "Multiple OR filters not allowed");
|
|
|
else
|
|
|
{
|
|
|
- helper.setOrFilter(orFilter, fmt, fieldName, fv, "|");
|
|
|
- hasOrFilter = true;
|
|
|
+ if (!strieq(fieldName, getEnumText(WUSFstate,workunitSortFields)) &&
|
|
|
+ !strieq(fieldName, getEnumText(WUSFuser,workunitSortFields)) &&
|
|
|
+ !strieq(fieldName, getEnumText(WUSFcluster,workunitSortFields)))
|
|
|
+ throw MakeStringException(WUERR_InvalidUserInput, "OR filters not allowed for %s", fieldName);
|
|
|
+ orFilter.setown(new CQueryOrFilter(fmt, fieldName, fv));
|
|
|
}
|
|
|
}
|
|
|
fv = fv + strlen(fv)+1;
|
|
@@ -3103,7 +3124,7 @@ public:
|
|
|
so.append(getEnumText(sortorder&0xff,workunitSortFields));
|
|
|
}
|
|
|
IArrayOf<IPropertyTree> results;
|
|
|
- Owned<IElementsPager> elementsPager = new CWorkUnitsPager(query.str(), hasOrFilter ? &orFilter : nullptr, so.length()?so.str():NULL, namefilterlo.get(), namefilterhi.get(), unknownAttributes);
|
|
|
+ Owned<IElementsPager> elementsPager = new CWorkUnitsPager(query.str(), orFilter.getClear(), so.length()?so.str():NULL, namefilterlo.get(), namefilterhi.get(), unknownAttributes);
|
|
|
Owned<IRemoteConnection> conn=getElementsPaged(elementsPager,startoffset,maxnum,secmgr?sc:NULL,"",cachehint,results,total,NULL);
|
|
|
return new CConstWUArrayIterator(results);
|
|
|
}
|