3 #include "zypp/base/PtrTypes.h"
4 #include "zypp/base/Logger.h"
5 #include "zypp/cache/CacheTypes.h"
6 #include "zypp/cache/ResolvableQuery.h"
7 #include "zypp/Package.h"
8 #include "zypp/cache/sqlite3x/sqlite3x.hpp"
10 using namespace sqlite3x;
14 typedef shared_ptr<sqlite3_command> sqlite3_command_ptr;
16 namespace zypp { namespace cache {
18 struct ResolvableQuery::Impl
22 CacheTypes _type_cache;
23 sqlite3_connection _con;
24 sqlite3_command_ptr _cmd_attr_str;
25 sqlite3_command_ptr _cmd_attr_tstr;
26 sqlite3_command_ptr _cmd_attr_num;
27 sqlite3_command_ptr _cmd_disk_usage;
29 Impl( const Pathname &dbdir)
33 _con.open((dbdir + "zypp.db").asString().c_str());
34 _con.executenonquery("PRAGMA cache_size=8000;");
36 _cmd_attr_tstr.reset( new sqlite3_command( _con, "select a.text, l.name from text_attributes a,types l,types t where a.weak_resolvable_id=:rid and a.lang_id=l.id and a.attr_id=t.id and l.class=:lclass and t.class=:tclass and t.name=:tname;") );
39 _cmd_attr_str.reset( new sqlite3_command( _con, "select a.text from text_attributes a,types l,types t where a.weak_resolvable_id=:rid and a.lang_id=l.id and a.attr_id=t.id and l.class=:lclass and l.name=:lname and t.class=:tclass and t.name=:tname;"));
41 _cmd_attr_num.reset( new sqlite3_command( _con, "select a.value from numeric_attributes a,types t where a.weak_resolvable_id=:rid and a.attr_id=t.id and t.class=:tclass and t.name=:tname;"));
43 _cmd_disk_usage.reset( new sqlite3_command( _con, "select d.name,du.size,du.files from resolvable_disk_usage du,dir_names d where du.resolvable_id=:rid and du.dir_name_id=d.id;"));
45 MIL << "Creating Resolvable query impl" << endl;
46 // 0 1 2 3 4 5 6 7 8 9 10 11 12
47 _fields = "id, name, version, release, epoch, arch, kind, installed_size, archive_size, install_only, build_time, install_time, repository_id";
52 MIL << "Destroying Resolvable query impl" << endl;
56 // convert regex ? and * operators to sql _ and % respectively
57 // example: regex2sql( "*foo?bar*" ) => "%foo_bar%"
58 // FIXME: take care of ".*" and "."
59 std::string regex2sql( const std::string & s)
63 for (it = sql.begin(); it != sql.end(); ++it)
65 if (*it == '*') *it = '%';
66 else if (*it == '?') *it = '_';
71 data::ResObject_Ptr fromRow( sqlite3_reader &reader )
73 data::ResObject_Ptr ptr (new data::ResObject);
75 // see _fields definition above for the getXXX() numbers
77 ptr->name = reader.getstring(1);
78 ptr->edition = Edition( reader.getstring(2), reader.getstring(3), reader.getint(4));
79 ptr->arch = _type_cache.archFor(reader.getint(5));
80 ptr->kind = _type_cache.kindFor( reader.getint(6) );
81 ptr->repository = reader.getint( 12 );
83 // TODO get the rest of the data
89 void query( const data::RecordId &id,
90 ProcessResolvable fnc )
92 sqlite3_command cmd( _con, "select " + _fields + " from resolvables where id=:id;");
94 sqlite3_reader reader = cmd.executereader();
97 fnc( id, fromRow(reader) );
102 void query( const std::string &s,
103 ProcessResolvable fnc )
106 sqlite3_command cmd( _con, "select " + _fields + " from resolvables where name like :name;");
107 cmd.bind( ":name", regex2sql( s ) );
108 sqlite3_reader reader = cmd.executereader();
111 fnc( reader.getint64(0), fromRow(reader) );
116 std::string queryStringAttribute( const data::RecordId &record_id,
117 const std::string &klass,
118 const std::string &name,
119 const std::string &default_value )
122 return queryStringAttributeTranslationInternal( _con, record_id, Locale(), klass, name, default_value);
126 std::string queryStringAttributeTranslation( const data::RecordId &record_id,
127 const Locale &locale,
128 const std::string &klass,
129 const std::string &name,
130 const std::string &default_value )
132 return queryStringAttributeTranslationInternal( _con, record_id, locale, klass, name, default_value );
136 TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id,
137 const std::string &klass,
138 const std::string &name,
139 const TranslatedText &default_value )
141 return queryTranslatedStringAttributeInternal( _con, record_id, klass, name, default_value );
145 bool queryBooleanAttribute( const data::RecordId &record_id,
146 const std::string &klass,
147 const std::string &name,
150 return ( queryNumericAttributeInternal( _con, record_id, klass, name, default_value) > 0 );
153 int queryNumericAttribute( const data::RecordId &record_id,
154 const std::string &klass,
155 const std::string &name,
158 return queryNumericAttributeInternal( _con, record_id, klass, name, default_value);
161 void queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
163 _cmd_disk_usage->bind(":rid", record_id);
164 sqlite3_reader reader = _cmd_disk_usage->executereader();
166 while ( reader.read() )
168 DiskUsage::Entry entry(reader.getstring(0),
175 std::string queryRepositoryAlias( const data::RecordId &repo_id )
178 sqlite3_command cmd( _con, "select alias from repositories where id=:id;" );
179 cmd.bind( ":id", repo_id );
180 sqlite3_reader reader = cmd.executereader();
181 while( reader.read() )
183 alias = reader.getstring( 0 );
189 void iterateResolvablesByKind( zypp::Resolvable::Kind kind, ProcessResolvable fnc )
191 sqlite3_command cmd( _con, "select " + _fields + " from resolvables where kind=:kind;");
192 data::RecordId kind_id = _type_cache.idForKind( kind );
193 cmd.bind(":kind", kind_id);
194 sqlite3_reader reader = cmd.executereader();
197 fnc( reader.getint64(0), fromRow(reader) );
201 void iterateResolvablesByKindsAndStrings( const std::vector<zypp::Resolvable::Kind> & kinds,
202 const std::vector<std::string> &strings, int flags, ProcessResolvable fnc )
204 std::string sqlcmd( "SELECT " + _fields + " FROM resolvables WHERE (" );
205 std::vector<std::string>::const_iterator it_s;
206 for (it_s = strings.begin(); it_s != strings.end(); ++it_s)
208 std::string s( *it_s );
210 if (it_s != strings.begin())
213 //FIXME: Implement MATCH_RESSUMM and MATCH_RESDESC
216 if (flags & MATCH_WILDCARDS == 0)
225 if (flags & MATCH_LEADING)
227 if (flags & MATCH_TRAILING)
234 sqlcmd += ") AND kind IN (";
236 std::vector<zypp::Resolvable::Kind>::const_iterator it_k;
237 for (it_k = kinds.begin(); it_k != kinds.end(); ++it_k)
239 if (it_k != kinds.begin())
242 snprintf( idbuf, 15, "%d", (int)(_type_cache.idForKind( *it_k )) );
245 sqlite3_command cmd( _con, sqlcmd + ")");
247 sqlite3_reader reader = cmd.executereader();
250 fnc( reader.getint64(0), fromRow(reader) );
256 int queryNumericAttributeInternal( sqlite3_connection &con,
257 const data::RecordId &record_id,
258 const std::string &klass,
259 const std::string &name,
262 //con.executenonquery("BEGIN;");
263 _cmd_attr_num->bind(":rid", record_id);
265 _cmd_attr_num->bind(":tclass", klass);
266 _cmd_attr_num->bind(":tname", name);
268 sqlite3_reader reader = _cmd_attr_num->executereader();
270 return reader.getint(0);
272 return default_value;
275 TranslatedText queryTranslatedStringAttributeInternal( sqlite3_connection &con,
276 const data::RecordId &record_id,
277 const std::string &klass,
278 const std::string &name,
279 const TranslatedText &default_value )
281 //con.executenonquery("PRAGMA cache_size=8000;");
282 //con.executenonquery("BEGIN;");
284 _cmd_attr_tstr->bind(":rid", record_id);
285 _cmd_attr_tstr->bind(":lclass", "lang");
287 _cmd_attr_tstr->bind(":tclass", klass);
288 _cmd_attr_tstr->bind(":tname", name);
290 TranslatedText result;
291 sqlite3_reader reader = _cmd_attr_tstr->executereader();
296 result.setText( reader.getstring(0), Locale( reader.getstring(1) ) );
303 return default_value;
306 std::string queryStringAttributeInternal( sqlite3_connection &con,
307 const data::RecordId &record_id,
308 const std::string &klass,
309 const std::string &name,
310 const std::string &default_value )
312 return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name, default_value );
315 std::string queryStringAttributeTranslationInternal( sqlite3_connection &con,
316 const data::RecordId &record_id,
317 const Locale &locale,
318 const std::string &klass,
319 const std::string &name,
320 const std::string &default_value )
322 //con.executenonquery("BEGIN;");
323 _cmd_attr_str->bind(":rid", record_id);
324 _cmd_attr_str->bind(":lclass", "lang");
325 if (locale == Locale() )
326 _cmd_attr_str->bind(":lname", "none");
328 _cmd_attr_str->bind(":lname", locale.code());
330 _cmd_attr_str->bind(":tclass", klass);
331 _cmd_attr_str->bind(":tname", name);
333 sqlite3_reader reader = _cmd_attr_str->executereader();
336 return reader.getstring(0);
338 return default_value;
342 //////////////////////////////////////////////////////////////////////////////
343 // FORWARD TO IMPLEMENTATION
344 //////////////////////////////////////////////////////////////////////////////
346 ResolvableQuery::ResolvableQuery( const Pathname &dbdir)
347 : _pimpl(new Impl(dbdir))
349 //MIL << "Creating Resolvable query" << endl;
352 ResolvableQuery::~ResolvableQuery()
354 //MIL << "Destroying Resolvable query" << endl;
357 //////////////////////////////////////////////////////////////////////////////
359 void ResolvableQuery::query( const data::RecordId &id, ProcessResolvable fnc )
361 _pimpl->query(id, fnc);
364 //////////////////////////////////////////////////////////////////////////////
366 void ResolvableQuery::query( const std::string &s, ProcessResolvable fnc )
368 _pimpl->query(s, fnc);
371 //////////////////////////////////////////////////////////////////////////////
373 int ResolvableQuery::queryNumericAttribute( const data::RecordId &record_id,
374 const std::string &klass,
375 const std::string &name,
378 return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
381 bool ResolvableQuery::queryBooleanAttribute( const data::RecordId &record_id,
382 const std::string &klass,
383 const std::string &name,
386 return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
390 std::string ResolvableQuery::queryStringAttribute( const data::RecordId &record_id,
391 const std::string &klass,
392 const std::string &name,
393 const std::string &default_value )
395 return _pimpl->queryStringAttribute(record_id, klass, name, default_value);
398 //////////////////////////////////////////////////////////////////////////////
400 std::string ResolvableQuery::queryStringAttributeTranslation( const data::RecordId &record_id,
401 const Locale &locale,
402 const std::string &klass,
403 const std::string &name,
404 const std::string &default_value )
406 return _pimpl->queryStringAttributeTranslation(record_id, locale, klass, name, default_value );
409 //////////////////////////////////////////////////////////////////////////////
411 TranslatedText ResolvableQuery::queryTranslatedStringAttribute( const data::RecordId &record_id,
412 const std::string &klass,
413 const std::string &name,
414 const TranslatedText &default_value )
416 return _pimpl->queryTranslatedStringAttribute(record_id, klass, name, default_value );
419 void ResolvableQuery::queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
421 _pimpl->queryDiskUsage(record_id, du);
424 std::string ResolvableQuery::queryRepositoryAlias( const data::RecordId &repo_id )
426 return _pimpl->queryRepositoryAlias( repo_id );
429 void ResolvableQuery::iterateResolvablesByKind( zypp::Resolvable::Kind kind, ProcessResolvable fnc )
431 return _pimpl->iterateResolvablesByKind( kind, fnc );
434 void ResolvableQuery::iterateResolvablesByKindsAndStrings( const std::vector<zypp::Resolvable::Kind> & kinds,
435 const std::vector<std::string> &strings, int flags, ProcessResolvable fnc )
437 _pimpl->iterateResolvablesByKindsAndStrings( kinds, strings, flags, fnc );
439 //////////////////////////////////////////////////////////////////////////////
441 } } // namespace zypp::cache