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/base/StrMatcher.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.
56 * \note You will sometimes face the problem, that when using the \ref PoolItem
57 * iterator you hit multiple version of the same package, while when using the
58 * \ref ui::Selectable iterator the information which of the available candidates
59 * actually matched got lost. In this case class \ref PoolItemBest may help you.
60 * Use it to pick the best version only.
64 * q.addAttribute(sat::SolvAttr::name, "zypp*");
65 * q.addKind(ResKind::package);
68 * for (PoolQuery::Selectable_iterator it = q.selectableBegin();
69 * it != q.selectableEnd(); ++it)
71 * ui::Selectable::constPtr s = *it;
76 * Performance considerations
78 * Results of simple queries like those using one string and/or one attribute
79 * and/or one repository are filtered by sat-solver's Dataiterator directly,
80 * and thus it is fast.
82 * Queries with multiple strings are implemented using regexes. Queries based
83 * on kinds, multiple repos, and multiple attributes are filtered inside
84 * the PoolQuery, so these tend to be slower.
86 * \see detail::PoolQueryIterator on how to inspect matches in detail.
87 * \see tests/zypp/PoolQuery_test.cc for more examples
88 * \see sat::SolvIterMixin
90 class PoolQuery : public sat::SolvIterMixin<PoolQuery, detail::PoolQueryIterator>
93 typedef std::set<ResKind> Kinds;
94 typedef std::set<std::string> StrContainer;
95 typedef std::map<sat::SolvAttr, StrContainer> AttrRawStrMap;
97 typedef detail::PoolQueryIterator const_iterator;
98 typedef unsigned int size_type;
101 typedef function<bool( const sat::Solvable & )> ProcessResolvable;
106 /** Query result accessers. */
109 * Compile the query and return an iterator to the result.
111 * \return An iterator (\ref detail::PoolQueryIterator) returning
112 * sat::Solvable objects pointing at the beginning of the query result.
113 * \throws sat::MatchInvalidRegexException if the query was about to use a regex which
116 * \note Note that PoolQuery is derived from \ref sat::SolvIterMixin which
117 * makes PoolItem and Selectable iterators automatically available.
118 * \see \ref sat::SolvIterMixin
120 const_iterator begin() const;
122 /** An iterator pointing to the end of the query result. */
123 const_iterator end() const;
125 /** Whether the result is empty. */
128 /** Number of solvables in the query result. */
129 size_type size() const;
133 * Executes the query with the current settings.
134 * Results are yielded via the \a fnc callback.
136 void execute(ProcessResolvable fnc);
139 * Filter by selectable kind.
141 * By default, all kinds will be returned. If addKind() is used,
142 * only the specified kinds will be returned (multiple kinds will be ORed).
144 * \note This kind filter does not apply if you explicitly specify a ResKind
145 * when searching for \c sat::SolvAttr::name. The following will always match
146 * and include the kernel \c packages, no matter which kind filter is set.
148 * addDependency( sat::SolvAttr::name, "package:kernel" );
151 * Pass ResKind constants to this method, (e.g. ResKind::package).
153 void addKind(const ResKind & kind);
158 * By default, all repos will be returned. If addRepo() is used,
159 * only the specified repo will be returned (multiple repos will be ORed).
161 void addRepo(const std::string &repoalias);
163 /** Installed status filter setters. */
167 * Filter by status (installed uninstalled)
170 ALL = 0, // both install filter and uninstall filter bits are 0
175 /** Return only @System repo packages */
176 void setInstalledOnly();
177 /** Return only packages from repos other than @System. */
178 void setUninstalledOnly();
179 /** Set status filter directly \see StatusFilter */
180 void setStatusFilterFlags( StatusFilter flags );
185 * Add a global query string. The string added via this method is applied
186 * to all query attributes as if addAttribute(..., \value) was called
189 * This method can be used multiple times in which case the query strings
190 * will be combined (together with strings added via addAttribute()) into
191 * a regex. Searched attribute value will match this regex if <b>any</b>
192 * of these strings will match the value.
194 void addString(const std::string & value);
197 * Filter by the \a value of the specified \a attr attribute. This can
198 * be any of the available solvable attributes.
200 * This method can be used multiple times with the same \a attr in which
201 * case the query strings will be combined (together with strings added
202 * via addString()) into a regex. Searched attribute value will match
203 * this regex if <b>any</b> of these strings will match the value.
205 * \note Though it is possible to use dependency attributes like
206 * \ref Solv::Attr::provides here, note that the query string is
207 * matched against a dependencies \c "name" part only. Any
208 * <tt>"op edition"</tt> part of a \ref Capability is \b not
209 * considered at all. \see \ref addDependency on how to query for
210 * capabilities including edition ranges.
212 * \note Solvables of a kind not supporting the specified attribute will
213 * <b>not</b> be returned.
214 * \todo check the above
216 * \param attr Attribute identfier. Use sat::Solvattr::* constants
217 * \param value What to search for.
221 void addAttribute( const sat::SolvAttr & attr, const std::string & value = "" );
223 /** \name Filter by dependencies matching a broken down capability <tt>name [op edition]</tt> and/or architecture.
225 * The capabilities \c name part may be defined as query string
226 * like with \ref addAttribute. Globing and regex are supported.
227 * Global query strings defined by \ref addString are considered.
229 * So without any <tt>op edition arch</tt> addDependency behaves the
230 * same as \ref addAttribute. If an edition range is given, matches
231 * are restricted accordingly. There are various overloads, so pick
232 * the one you like best.
234 * An optional \c arch argument will additionally require the matching
235 * solvable to be of this arch.
240 * setCaseSensitive( false );
241 * addDependency( sat::SolvAttr::provides, "kde*", Rel::EQ, Edition("2.0") );
242 * addDependency( sat::SolvAttr::provides, "kde*", Edition("2.0") ); // same as above
246 * setCaseSensitive( false );
247 * addString( "kde*" );
248 * addDependency( sat::SolvAttr::provides, Rel::EQ, Edition("2.0") );// same as above
249 * addDependency( sat::SolvAttr::provides, Edition("2.0") ); // same as above
253 * \note Thre's also a version of \ref addDependency provided, that takes a
254 * complete \ref Capability as argument. This always requires an exact match
255 * of the name part (as the resolver would do it).
257 * This is the list of valid dependency attributes:
260 * SolvAttr::obsoletes
261 * SolvAttr::conflicts
263 * SolvAttr::recommends
265 * SolvAttr::supplements
269 * \note <b>What happens if a non dependency attribute is passed?<\b>
270 * If an edition range is given, it is matched against the matching
271 * solvables edition instead. Without edition range it behaves the
272 * same as \ref addAttribute.
275 * // Find all packages providing "kernel > 2.0"
276 * addDependency( sat::SolvAttr::provides, "kernel", Rel::GT, Edition("2.0") );
278 * // // Find all packages named "kernel" and with edition "> 2.0"
279 * addDependency( sat::SolvAttr::name, "kernel", Rel::GT, Edition("2.0") );
283 /** Query <tt>"name|global op edition"</tt>. */
284 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition );
285 /** \overload also restricting architecture */
286 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch );
287 /** \overload also use an individual Match::Mode for the \a name */
288 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch, Match::Mode mode );
290 /** \overload Query <tt>"name|global == edition"</tt>. */
291 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition )
292 { addDependency( attr, name, Rel::EQ, edition ); }
293 /** \overload also restricting architecture */
294 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition, const Arch & arch )
295 { addDependency( attr, name, Rel::EQ, edition, arch ); }
297 /** \overload Query <tt>"name|global"</tt>. */
298 void addDependency( const sat::SolvAttr & attr, const std::string & name )
299 { addDependency( attr, name, Rel::ANY, Edition() ); }
300 /** \overload also restricting architecture */
301 void addDependency( const sat::SolvAttr & attr, const std::string & name, const Arch & arch )
302 { addDependency( attr, name, Rel::ANY, Edition(), arch ); }
304 /** \overload Query <tt>"global op edition"</tt>.*/
305 void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition )
306 { addDependency( attr, std::string(), op, edition ); }
307 /** \overload also restricting architecture */
308 void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition, const Arch & arch )
309 { addDependency( attr, std::string(), op, edition, arch ); }
311 /** \overload Query <tt>"global == edition"</tt>. */
312 void addDependency( const sat::SolvAttr & attr, const Edition & edition )
313 { addDependency( attr, std::string(), Rel::EQ, edition ); }
314 /** \overload also restricting architecture */
315 void addDependency( const sat::SolvAttr & attr, const Edition & edition, const Arch & arch )
316 { addDependency( attr, std::string(), Rel::EQ, edition, arch ); }
318 /** \overload Query <tt>"global"</tt>. */
319 void addDependency( const sat::SolvAttr & attr )
320 { addDependency( attr, std::string(), Rel::ANY, Edition() ); }
321 /** \overload also restricting architecture */
322 void addDependency( const sat::SolvAttr & attr, const Arch & arch )
323 { addDependency( attr, std::string(), Rel::ANY, Edition(), arch ); }
325 /** \overload Query taking a \ref Capability (always exact name match).
326 * \note If a non dependency attribute is passed, the \ref Capability
327 * will always be matched against the Solvables \c name and \c edition.
329 void addDependency( const sat::SolvAttr & attr, Capability cap_r );
333 * Set version condition. This will filter out solvables not matching
334 * <tt>solvableEdition \a op \a edition</tt>.
336 * \param edition Edition to look for.
337 * \param op Found-wanted relation operator.
339 void setEdition(const Edition & edition, const Rel & op = Rel::EQ);
341 /** \name Text Matching Options
342 * \note The implementation treats an empty search string as
343 * <it>"match always"</it>. So if you want to actually match
344 * an empty value, try <tt>( "^$", setMatchRegex )</tt>.
348 * Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag).
349 * PoolQuery defaults to case insensitive search unless this method
352 * \param value Whether to turn the case sensitivity on (default) or off.
354 void setCaseSensitive( bool value = true );
357 * If set (default), look at the full path when searching in filelists.
358 * Otherwise just match the the basenames.
359 * \see \ref Match::FILES
361 void setFilesMatchFullPath( bool value = true );
363 void setFilesMatchBasename( bool value = true )
364 { setFilesMatchFullPath( !value ); }
366 /** Set to match exact string instead of substring.*/
367 void setMatchExact();
368 /** Set to substring (the default). */
369 void setMatchSubstring();
370 /** Set to match globs. */
372 /** Set to use the query strings as regexes */
373 void setMatchRegex();
374 /** Set substring to match words */
376 //void setLocale(const Locale & locale);
382 /** Search strings added via addString() */
383 const StrContainer & strings() const;
385 * Map (map<SolvAttr, StrContainer>) of attribute values added via
386 * addAttribute(), addDep in string form */
387 const AttrRawStrMap & attributes() const;
389 const StrContainer & attribute(const sat::SolvAttr & attr) const;
391 const Kinds & kinds() const;
393 const StrContainer & repos() const;
395 const Edition edition() const;
396 const Rel editionRel() const;
399 * returns true if search is case sensitive
401 bool caseSensitive() const;
403 /** Whether searching in filelists looks at the full path or just at the basenames. */
404 bool filesMatchFullPath() const;
406 bool filesMatchBasename() const
407 { return !filesMatchFullPath(); }
409 bool matchExact() const;
410 bool matchSubstring() const;
411 bool matchGlob() const;
412 bool matchRegex() const;
413 bool matchWord() const;
415 /** Returns string matching mode as enum.
416 * \see \ref Match::Mode
418 Match::Mode matchMode() const
419 { return flags().mode(); }
421 StatusFilter statusFilterFlags() const;
425 * Reads from stream query. Attributes is sepated by delim. Query is
426 * separated by two delim.
428 * \param str input stream which contains query
429 * \param delim delimeter for attributes
430 * \return true if non-empty query is recovered
432 * \see readPoolQueriesFromFile
434 bool recover( std::istream &str, char delim = '\n' );
437 * Writes a machine-readable string representation of the query to stream.
438 * Use \a delim as attribute delimiter.
440 * \param str output stream to write to
441 * \param delim delimiter for attributes
443 * \see writePoolQueriesToFile
445 void serialize( std::ostream &str, char delim = '\n' ) const;
447 /** Return a human-readable description of the query */
448 std::string asString() const;
450 bool operator<(const PoolQuery& b) const;
451 bool operator==(const PoolQuery& b) const;
452 bool operator!=(const PoolQuery& b) const { return !(*this == b ); }
457 * Free function to get libsolv repo search
465 * Free function to set libsolv repo search
470 void setFlags( const Match & flags );
473 /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */
474 void setRequireAll( bool require_all = true ) ZYPP_DEPRECATED;
475 /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */
476 bool requireAll() const ZYPP_DEPRECATED;
481 /** Pointer to implementation */
482 RW_pointer<Impl> _pimpl;
484 ///////////////////////////////////////////////////////////////////
486 /** \relates PoolQuery Stream output. */
487 std::ostream & operator<<( std::ostream & str, const PoolQuery & obj );
489 /** \relates PoolQuery Detailed stream output. */
490 std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj );
492 ///////////////////////////////////////////////////////////////////
494 { /////////////////////////////////////////////////////////////////
496 class PoolQueryMatcher;
498 ///////////////////////////////////////////////////////////////////
500 // CLASS NAME : PoolQuery::PoolQueryIterator
502 /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin.
504 * The \ref PoolQueryIterator visits sat::Solavables that do contain matches.
506 * But it also provides an iterator by itself, to allow a detailed inspection of
507 * the individual attribute matches within the current Solvable.
509 class PoolQueryIterator : public boost::iterator_adaptor<
510 PoolQueryIterator // Derived
511 , sat::LookupAttr::iterator // Base
512 , const sat::Solvable // Value
513 , boost::forward_traversal_tag // CategoryOrTraversal
514 , const sat::Solvable // Reference
517 typedef std::vector<sat::LookupAttr::iterator> Matches;
519 typedef Matches::size_type size_type;
520 typedef Matches::const_iterator matches_iterator;
522 /** Default ctor is also \c end.*/
526 /** \Ref PoolQuery ctor. */
527 PoolQueryIterator( const shared_ptr<PoolQueryMatcher> & matcher_r )
528 : _matcher( matcher_r )
531 /** \name Detailed inspection of attribute matches within the current Solvable.
533 * The \ref matches_iterator visits all attribute matches within the current Solvable,
534 * providing a \ref sat::LookupAttr::iterator pointing to attribute. While a
535 * \ref matches_iterator itself becomes invalid if the PoolQueryIterator is advanced,
536 * the \ref sat::LookupAttr::iterator it pointed to stays valid, even after the query
540 * // Setup query for "libzypp" in name or requires:
542 * q.addString( "libzypp" );
543 * q.setMatchSubstring();
544 * q.setCaseSensitive( false );
545 * q.addAttribute( sat::SolvAttr::name );
546 * q.addDependency( sat::SolvAttr::requires );
548 * // Iterate the result:
549 * for_( solvIter, q.begin(), q.end() )
551 * sat::Solvable solvable( *solvIter );
552 * cout << "Found matches in " << solvable << endl;
554 * for_( attrIter, solvIter.matchesBegin(), solvIter.matchesEnd() )
556 * sat::LookupAttr::iterator attr( *attrIter );
557 * cout << " " << attr.inSolvAttr() << "\t\"" << attr.asString() << "\"" << endl;
562 * Found matches in PackageKit-0.3.11-1.12.i586(@System)
563 * solvable:requires "libzypp.so.523"
564 * Found matches in libqdialogsolver1-1.2.6-1.1.2.i586(@System)
565 * solvable:requires "libzypp.so.523"
566 * solvable:requires "libzypp >= 5.25.3-0.1.2"
567 * Found matches in libzypp-5.30.3-0.1.1.i586(@System)
568 * solvable:name "libzypp"
569 * Found matches in libzypp-testsuite-tools-4.2.6-8.1.i586(@System)
570 * solvable:name "libzypp-testsuite-tools"
571 * solvable:requires "libzypp.so.523"
576 /** \c False unless this is the \c end iterator. */
577 bool matchesEmpty() const { return ! _matcher; }
578 /** Number of attribute matches. */
579 size_type matchesSize() const { return matches().size(); }
580 /** Begin of matches. */
581 matches_iterator matchesBegin() const { return matches().begin(); }
582 /** End of matches. */
583 matches_iterator matchesEnd() const { return matches().end(); }
587 friend class boost::iterator_core_access;
589 sat::Solvable dereference() const
590 { return base_reference().inSolvable(); }
595 const Matches & matches() const;
598 shared_ptr<PoolQueryMatcher> _matcher;
599 mutable shared_ptr<Matches> _matches;
601 ///////////////////////////////////////////////////////////////////
603 /** \relates PoolQueryIterator Stream output. */
604 inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj )
605 { return str << obj.base(); }
607 /** \relates PoolQueryIterator Detailed stream output. */
608 std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj );
610 ///////////////////////////////////////////////////////////////////
612 ///////////////////////////////////////////////////////////////////
614 inline detail::PoolQueryIterator PoolQuery::end() const
615 { return detail::PoolQueryIterator(); }
617 /////////////////////////////////////////////////////////////////
619 ///////////////////////////////////////////////////////////////////
621 #endif // ZYPP_POOLQUERY_H