1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/PoolQuery.h
12 #ifndef ZYPP_POOLQUERY_H
13 #define ZYPP_POOLQUERY_H
19 #include "zypp/base/Regex.h"
20 #include "zypp/base/PtrTypes.h"
21 #include "zypp/base/Function.h"
23 #include "zypp/sat/SolvIterMixin.h"
24 #include "zypp/sat/LookupAttr.h"
25 #include "zypp/sat/AttrMatcher.h"
26 #include "zypp/sat/Pool.h"
28 ///////////////////////////////////////////////////////////////////
30 { /////////////////////////////////////////////////////////////////
34 class PoolQueryIterator;
37 ///////////////////////////////////////////////////////////////////
39 // CLASS NAME : PoolQuery
42 * Meta-data query API. Returns solvables of specified kinds from specified
43 * repositories with attributes matching the specified search strings.
45 * The search strings can be specified via \ref addString() and
46 * \ref addAttribute() methods. String matching type can be set using the
47 * setMatch*() methods. Multiple search strings for a particular attribute
48 * will be combined into a regex (see \ref addString() and
49 * \ref addAttribute() for more details).
51 * The begin() and end() methods return a PoolQueryIterator returning
52 * \ref sat::Solvable objects which can easily be turned into \ref Resolvable
53 * objects. Additionally, thanx to the \ref sat::SolvIterMixin, a Selectable
54 * and PoolItem iterators are automatically available.
58 * q.addAttribute(sat::SolvAttr::name, "zypp*");
59 * q.addKind(ResKind::package);
62 * for (PoolQuery::Selectable_iterator it = q.selectableBegin();
63 * it != q.selectableEnd(); ++it)
65 * ui::Selectable::constPtr s = *it;
70 * Performance considerations
72 * Results of simple queries like those using one string and/or one attribute
73 * and/or one repository are filtered by sat-solver's Dataiterator directly,
74 * and thus it is fast.
76 * Queries with multiple strings are implemented using regexes. Queries based
77 * on kinds, multiple repos, and multiple attributes are filtered inside
78 * the PoolQuery, so these tend to be slower.
80 * \see detail::PoolQueryIterator on how to inspect matches in detail.
81 * \see tests/zypp/PoolQuery_test.cc for more examples
82 * \see sat::SolvIterMixin
84 class PoolQuery : public sat::SolvIterMixin<PoolQuery, detail::PoolQueryIterator>
87 typedef std::set<ResKind> Kinds;
88 typedef std::set<std::string> StrContainer;
89 typedef std::map<sat::SolvAttr, StrContainer> AttrRawStrMap;
91 typedef detail::PoolQueryIterator const_iterator;
92 typedef unsigned int size_type;
95 typedef function<bool( const sat::Solvable & )> ProcessResolvable;
100 /** Query result accessers. */
103 * Compile the query and return an iterator to the result.
105 * \return An iterator (\ref detail::PoolQueryIterator) returning
106 * sat::Solvable objects pointing at the beginning of the query result.
107 * \throws sat::MatchInvalidRegexException if the query was about to use a regex which
110 * \note Note that PoolQuery is derived from \ref sat::SolvIterMixin which
111 * makes PoolItem and Selectable iterators automatically available.
112 * \see \ref sat::SolvIterMixin
114 const_iterator begin() const;
116 /** An iterator pointing to the end of the query result. */
117 const_iterator end() const;
119 /** Whether the result is empty. */
122 /** Number of solvables in the query result. */
123 size_type size() const;
127 * Executes the query with the current settings.
128 * Results are yielded via the \a fnc callback.
130 void execute(ProcessResolvable fnc);
133 * Filter by selectable kind.
135 * By default, all kinds will be returned. If addKind() is used,
136 * only the specified kinds will be returned (multiple kinds will be ORed).
138 * Pass ResKind constants to this method, (e.g. ResKind::package).
140 void addKind(const ResKind & kind);
145 * By default, all repos will be returned. If addRepo() is used,
146 * only the specified repo will be returned (multiple repos will be ORed).
148 void addRepo(const std::string &repoalias);
150 /** Installed status filter setters. */
154 * Filter by status (installed uninstalled)
157 ALL = 0, // both install filter and uninstall filter bits are 0
162 /** Return only @System repo packages */
163 void setInstalledOnly();
164 /** Return only packages from repos other than @System. */
165 void setUninstalledOnly();
166 /** Set status filter directly \see StatusFilter */
167 void setStatusFilterFlags( StatusFilter flags );
172 * Add a global query string. The string added via this method is applied
173 * to all query attributes as if addAttribute(..., \value) was called
176 * This method can be used multiple times in which case the query strings
177 * will be combined (together with strings added via addAttribute()) into
178 * a regex. Searched attribute value will match this regex if <b>any</b>
179 * of these strings will match the value. This can be changed by
180 * (not yet implemented) \ref setRequireAll() method.
182 void addString(const std::string & value);
185 * Filter by the \a value of the specified \a attr attribute. This can
186 * be any of the available solvable attributes.
188 * This method can be used multiple times with the same \a attr in which
189 * case the query strings will be combined (together with strings added
190 * via addString()) into a regex. Searched attribute value will match
191 * this regex if <b>any</b> of these strings will match the value.
192 * This can be changed by (not yet implemented) \ref setRequireAll()
195 * \note Though it is possible to use dependency attributes like
196 * \ref Solv::Attr::provides here, note that the query string is
197 * matched against a dependencies \c "name" part only. Any
198 * <tt>"op edition"</tt> part of a \ref Capability is \b not
199 * considered at all. \see \ref addDependency on how to query for
200 * capabilities including edition ranges.
202 * \note Solvables of a kind not supporting the specified attribute will
203 * <b>not</b> be returned.
204 * \todo check the above
206 * \param attr Attribute identfier. Use sat::Solvattr::* constants
207 * \param value What to search for.
211 void addAttribute( const sat::SolvAttr & attr, const std::string & value = "" );
213 /** \name Filter by dependencies matching a broken down capability <tt>name [op edition]</tt>.
215 * The capabilities \c name part may be defined as query string
216 * like with \ref addAttribute. Globing and regex are supported.
217 * Global query strings defined by \ref addString are considered.
219 * So without any <tt>op edition</tt> addDependency behaves the
220 * same as \ref addAttribute. If an edition range is given, matches
221 * are restricted accordingly. Thete are various overloads, so pick
222 * the one you like best.
227 * setCaseSensitive( false );
228 * addDependency( sat::SolvAttr::provides, "kde*", Rel::EQ, Edition("2.0") );
229 * addDependency( sat::SolvAttr::provides, "kde*", Edition("2.0") ); // same as above
233 * setCaseSensitive( false );
234 * addString( "kde*" );
235 * addDependency( sat::SolvAttr::provides, Rel::EQ, Edition("2.0") );// same as above
236 * addDependency( sat::SolvAttr::provides, Edition("2.0") ); // same as above
240 * \note Thre's also a version of \ref addDependency provided, that takes a
241 * complete \ref Capability as argument. This always requires an exact match
242 * of the name part (as the resolver would do it).
244 * This is the list of valid dependency attributes:
247 * SolvAttr::obsoletes
248 * SolvAttr::conflicts
250 * SolvAttr::recommends
252 * SolvAttr::supplements
256 * \note <b>What happens if a non dependency attribute is passed?<\b>
257 * If an edition range is given, it is matched against the matching
258 * solvables edition instead. Without edition range it behaves the
259 * same as \ref addAttribute.
262 * // Find all packages providing "kernel > 2.0"
263 * addDependency( sat::SolvAttr::provides, "kernel", Rel::GT, Edition("2.0") );
265 * // // Find all packages named "kernel" and with edition "> 2.0"
266 * addDependency( sat::SolvAttr::name, "kernel", Rel::GT, Edition("2.0") );
270 /** Query <tt>"name|global op edition"</tt>. */
271 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition );
273 /** \overload Query <tt>"name|global == edition"</tt>. */
274 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition )
275 { addDependency( attr, name, Rel::EQ, edition ); }
277 /** \overload Query <tt>"name|global"</tt>. */
278 void addDependency( const sat::SolvAttr & attr, const std::string & name )
279 { addDependency( attr, name, Rel::ANY, Edition() ); }
281 /** \overload Query <tt>"global op edition"</tt>.*/
282 void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition )
283 { addDependency( attr, std::string(), op, edition ); }
285 /** \overload Query <tt>"global == edition"</tt>. */
286 void addDependency( const sat::SolvAttr & attr, const Edition & edition )
287 { addDependency( attr, std::string(), Rel::EQ, edition ); }
289 /** \overload Query <tt>"global"</tt>. */
290 void addDependency( const sat::SolvAttr & attr )
291 { addDependency( attr, std::string(), Rel::ANY, Edition() ); }
293 /** \overload Query taking a \ref Capability (always exact name match).
294 * \note If a non dependency attribute is passed, the \ref Capability
295 * will always be matched against the Solvables \c name and \c edition.
297 void addDependency( const sat::SolvAttr & attr, Capability cap_r );
301 * Set version condition. This will filter out solvables not matching
302 * <tt>solvableEdition \a op \a edition</tt>.
304 * \param edition Edition to look for.
305 * \param op Found-wanted relation operator.
307 void setEdition(const Edition & edition, const Rel & op = Rel::EQ);
309 /** \name Text Matching Options
310 * \note The implementation treats an empty search string as
311 * <it>"match always"</it>. So if you want to actually match
312 * an empty value, try <tt>( "^$", setMatchRegex )</tt>.
316 * Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag).
317 * PoolQuery defaults to case insensitive search unless this method
320 * \param value Whether to turn the case sensitivity on (default) or off.
322 void setCaseSensitive( bool value = true );
325 * If set (default), look at the full path when searching in filelists.
326 * Otherwise just match the the basenames.
327 * \see \ref Match::FILES
329 void setFilesMatchFullPath( bool value = true );
331 void setFilesMatchBasename( bool value = true )
332 { setFilesMatchFullPath( !value ); }
334 /** Set to match exact string instead of substring.*/
335 void setMatchExact();
336 /** Set to substring (the default). */
337 void setMatchSubstring();
338 /** Set to match globs. */
340 /** Set to use the query strings as regexes */
341 void setMatchRegex();
342 /** Set to match words (uses regex) */
344 //void setLocale(const Locale & locale);
348 * Require that all of the values set by addString or addAttribute
349 * match the values of respective attributes.
351 * \todo doesn't work yet, don't use this function
353 void setRequireAll( bool require_all = true );
359 /** Search strings added via addString() */
360 const StrContainer & strings() const;
362 * Map (map<SolvAttr, StrContainer>) of attribute values added via
363 * addAttribute(), addDep in string form */
364 const AttrRawStrMap & attributes() const;
366 const StrContainer & attribute(const sat::SolvAttr & attr) const;
368 const Kinds & kinds() const;
370 const StrContainer & repos() const;
372 const Edition edition() const;
373 const Rel editionRel() const;
376 * returns true if search is case sensitive
378 bool caseSensitive() const;
380 /** Whether searching in filelists looks at the full path or just at the basenames. */
381 bool filesMatchFullPath() const;
383 bool filesMatchBasename() const
384 { return !filesMatchFullPath(); }
386 bool matchExact() const;
387 bool matchSubstring() const;
388 bool matchGlob() const;
389 bool matchRegex() const;
390 bool matchWord() const;
392 /** Returns string matching mode as enum.
393 * \see \ref Match::Mode
395 Match::Mode matchMode() const
396 { return flags().mode(); }
399 * Whether all values added via addString() or addAttribute() are required
400 * to match the values of the respective attributes.
402 bool requireAll() const;
404 StatusFilter statusFilterFlags() const;
408 * Reads from stream query. Attributes is sepated by delim. Query is
409 * separated by two delim.
411 * \param str input stream which contains query
412 * \param delim delimeter for attributes
413 * \return true if non-empty query is recovered
415 * \see readPoolQueriesFromFile
417 bool recover( std::istream &str, char delim = '\n' );
420 * Writes a machine-readable string representation of the query to stream.
421 * Use \a delim as attribute delimiter.
423 * \param str output stream to write to
424 * \param delim delimiter for attributes
426 * \see writePoolQueriesToFile
428 void serialize( std::ostream &str, char delim = '\n' ) const;
430 /** Return a human-readable description of the query */
431 std::string asString() const;
433 bool operator==(const PoolQuery& b) const;
434 bool operator!=(const PoolQuery& b) const { return !(*this == b ); }
439 * Free function to get the satsolver repo search
447 * Free function to set the satsolver repo search
452 void setFlags( const Match & flags );
457 /** Pointer to implementation */
458 RW_pointer<Impl> _pimpl;
460 ///////////////////////////////////////////////////////////////////
462 /** \relates PoolQuery Stream output. */
463 std::ostream & operator<<( std::ostream & str, const PoolQuery & obj );
465 ///////////////////////////////////////////////////////////////////
467 { /////////////////////////////////////////////////////////////////
469 class PoolQueryMatcher;
471 ///////////////////////////////////////////////////////////////////
473 // CLASS NAME : PoolQuery::PoolQueryIterator
475 /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin.
477 * The \ref PoolQueryIterator visits sat::Solavables that do contain matches.
479 * But it also provides an iterator by itself, to allow a detailed inspection of
480 * the individual attribute matches within the current Solvable.
482 class PoolQueryIterator : public boost::iterator_adaptor<
483 PoolQueryIterator // Derived
484 , sat::LookupAttr::iterator // Base
485 , const sat::Solvable // Value
486 , boost::forward_traversal_tag // CategoryOrTraversal
487 , const sat::Solvable // Reference
490 typedef std::vector<sat::LookupAttr::iterator> Matches;
492 typedef Matches::size_type size_type;
493 typedef Matches::const_iterator matches_iterator;
495 /** Default ctor is also \c end.*/
499 /** \Ref PoolQuery ctor. */
500 PoolQueryIterator( const shared_ptr<PoolQueryMatcher> & matcher_r )
501 : _matcher( matcher_r )
504 /** \name Detailed inspection of attribute matches within the current Solvable.
506 * The \ref matches_iterator visits all attribute matches within the current Solvable,
507 * providing a \ref sat::LookupAttr::iterator pointing to attribute. While a
508 * \ref matches_iterator itself becomes invalid if the PoolQueryIterator is advanced,
509 * the \ref sat::LookupAttr::iterator it pointed to stays valid, even after the query
513 * // Setup query for "libzypp" in name or requires:
515 * q.addString( "libzypp" );
516 * q.setMatchSubstring();
517 * q.setCaseSensitive( false );
518 * q.addAttribute( sat::SolvAttr::name );
519 * q.addDependency( sat::SolvAttr::requires );
521 * // Iterate the result:
522 * for_( solvIter, q.begin(), q.end() )
524 * sat::Solvable solvable( *solvIter );
525 * cout << "Found matches in " << solvable << endl;
527 * for_( attrIter, solvIter.matchesBegin(), solvIter.matchesEnd() )
529 * sat::LookupAttr::iterator attr( *attrIter );
530 * cout << " " << attr.inSolvAttr() << "\t\"" << attr.asString() << "\"" << endl;
535 * Found matches in PackageKit-0.3.11-1.12.i586(@System)
536 * solvable:requires "libzypp.so.523"
537 * Found matches in libqdialogsolver1-1.2.6-1.1.2.i586(@System)
538 * solvable:requires "libzypp.so.523"
539 * solvable:requires "libzypp >= 5.25.3-0.1.2"
540 * Found matches in libzypp-5.30.3-0.1.1.i586(@System)
541 * solvable:name "libzypp"
542 * Found matches in libzypp-testsuite-tools-4.2.6-8.1.i586(@System)
543 * solvable:name "libzypp-testsuite-tools"
544 * solvable:requires "libzypp.so.523"
549 /** \c False unless this is the \c end iterator. */
550 bool matchesEmpty() const { return ! _matcher; }
551 /** Number of attribute matches. */
552 size_type matchesSize() const { return matches().size(); }
553 /** Begin of matches. */
554 matches_iterator matchesBegin() const { return matches().begin(); }
555 /** End of matches. */
556 matches_iterator matchesEnd() const { return matches().end(); }
560 friend class boost::iterator_core_access;
562 sat::Solvable dereference() const
563 { return base_reference().inSolvable(); }
568 const Matches & matches() const;
571 shared_ptr<PoolQueryMatcher> _matcher;
572 mutable shared_ptr<Matches> _matches;
574 ///////////////////////////////////////////////////////////////////
576 /** \relates PoolQueryIterator Stream output. */
577 inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj )
578 { return str << obj.base(); }
580 /** \relates PoolQueryIterator Detailed stream output. */
581 std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj );
583 ///////////////////////////////////////////////////////////////////
585 ///////////////////////////////////////////////////////////////////
587 inline detail::PoolQueryIterator PoolQuery::end() const
588 { return detail::PoolQueryIterator(); }
590 /////////////////////////////////////////////////////////////////
592 ///////////////////////////////////////////////////////////////////
594 #endif // ZYPP_POOLQUERY_H