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;
28 sqlite3_command_ptr _cmd_shared_id;
30 Impl( const Pathname &dbdir)
34 _con.open((dbdir + "zypp.db").asString().c_str());
35 _con.executenonquery("PRAGMA cache_size=8000;");
37 _cmd_shared_id.reset( new sqlite3_command( _con, "select shared_id from resolvables where id=:rid;") );
39 _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;") );
42 _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;"));
44 _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;"));
46 _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;"));
48 MIL << "Creating Resolvable query impl" << endl;
49 // 0 1 2 3 4 5 6 7 8 9 10 11 12
50 _fields = "id, name, version, release, epoch, arch, kind, installed_size, archive_size, install_only, build_time, install_time, repository_id";
55 MIL << "Destroying Resolvable query impl" << endl;
59 // convert regex ? and * operators to sql _ and % respectively
60 // example: regex2sql( "*foo?bar*" ) => "%foo_bar%"
61 // FIXME: take care of ".*" and "."
62 std::string regex2sql( const std::string & s)
66 for (it = sql.begin(); it != sql.end(); ++it)
68 if (*it == '*') *it = '%';
69 else if (*it == '?') *it = '_';
74 data::ResObject_Ptr fromRow( sqlite3_reader &reader )
76 data::ResObject_Ptr ptr (new data::ResObject);
78 // see _fields definition above for the getXXX() numbers
80 ptr->name = reader.getstring(1);
81 ptr->edition = Edition( reader.getstring(2), reader.getstring(3), reader.getint(4) );
82 ptr->arch = _type_cache.archFor(reader.getint(5));
83 ptr->kind = _type_cache.kindFor( reader.getint(6) );
84 ptr->repository = reader.getint( 12 );
86 // TODO get the rest of the data
92 void query( const data::RecordId &id,
93 ProcessResolvable fnc )
95 sqlite3_command cmd( _con, "select " + _fields + " from resolvables where id=:id;");
97 sqlite3_reader reader = cmd.executereader();
100 fnc( id, fromRow(reader) );
105 void query( const std::string &s,
106 ProcessResolvable fnc )
109 sqlite3_command cmd( _con, "select " + _fields + " from resolvables where name like :name;");
110 cmd.bind( ":name", regex2sql( s ) );
111 sqlite3_reader reader = cmd.executereader();
114 fnc( reader.getint64(0), fromRow(reader) );
119 std::string queryStringAttribute( const data::RecordId &record_id,
120 const std::string &klass,
121 const std::string &name,
122 const std::string &default_value )
125 return queryStringAttributeTranslationInternal( _con, record_id, Locale(), klass, name, default_value);
129 std::string queryStringAttributeTranslation( const data::RecordId &record_id,
130 const Locale &locale,
131 const std::string &klass,
132 const std::string &name,
133 const std::string &default_value )
135 return queryStringAttributeTranslationInternal( _con, record_id, locale, klass, name, default_value );
139 TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id,
140 const std::string &klass,
141 const std::string &name,
142 const TranslatedText &default_value )
144 return queryTranslatedStringAttributeInternal( _con, record_id, klass, name, default_value );
148 bool queryBooleanAttribute( const data::RecordId &record_id,
149 const std::string &klass,
150 const std::string &name,
153 return ( queryNumericAttributeInternal( _con, record_id, klass, name, default_value) > 0 );
156 int queryNumericAttribute( const data::RecordId &record_id,
157 const std::string &klass,
158 const std::string &name,
161 return queryNumericAttributeInternal( _con, record_id, klass, name, default_value);
164 void queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
166 _cmd_disk_usage->bind(":rid", record_id);
167 sqlite3_reader reader = _cmd_disk_usage->executereader();
169 while ( reader.read() )
171 DiskUsage::Entry entry(reader.getstring(0),
178 std::string queryRepositoryAlias( const data::RecordId &repo_id )
181 sqlite3_command cmd( _con, "select alias from repositories where id=:id;" );
182 cmd.bind( ":id", repo_id );
183 sqlite3_reader reader = cmd.executereader();
184 while( reader.read() )
186 alias = reader.getstring( 0 );
192 data::RecordId queryRepositoryId( const std::string &repo_alias )
195 sqlite3_command cmd( _con, "select id from repositories where alias=:alias;" );
196 cmd.bind( ":alias", repo_alias );
197 sqlite3_reader reader = cmd.executereader();
198 while( reader.read() )
200 id = reader.getint64(0);
206 void iterateResolvablesByKindsAndStringsAndRepos( const std::vector<zypp::Resolvable::Kind> & kinds,
207 const std::vector<std::string> &strings, int flags, const std::vector<std::string> repos, ProcessResolvable fnc )
209 std::string sqlcmd( "SELECT " + _fields + " FROM resolvables" );
211 std::vector<std::string>::const_iterator it_s;
212 for (it_s = strings.begin(); it_s != strings.end(); ++it_s)
214 std::string s( *it_s );
216 if (it_s == strings.begin())
217 sqlcmd += " WHERE (";
221 //FIXME: Implement MATCH_RESSUMM and MATCH_RESDESC
224 if ((flags & MATCH_WILDCARDS) == 0)
233 if (flags & MATCH_LEADING)
235 if (flags & MATCH_TRAILING)
243 if (it_s != strings.begin())
248 std::vector<zypp::Resolvable::Kind>::const_iterator it_k;
251 if (it_s == strings.begin())
256 for (it_k = kinds.begin(); it_k != kinds.end(); ++it_k)
258 if (it_k == kinds.begin())
259 sqlcmd += " kind IN (";
264 snprintf( idbuf, 15, "%d", (int)(_type_cache.idForKind( *it_k )) );
268 if (it_k != kinds.begin())
274 std::vector<std::string>::const_iterator it_r;
277 if (it_s == strings.begin()
278 && it_k == kinds.begin())
283 for (it_r = repos.begin(); it_r != repos.end(); ++it_r)
285 if (it_r == repos.begin())
290 sqlcmd += "repository_id = ";
292 snprintf( idbuf, 15, "%ld", (long)(queryRepositoryId( *it_r )) );
296 if (it_r != repos.begin())
302 MIL << "sqlcmd " << sqlcmd << endl;
303 sqlite3_command cmd( _con, sqlcmd );
304 sqlite3_reader reader = cmd.executereader();
307 fnc( reader.getint64(0), fromRow(reader) );
313 int queryNumericAttributeInternal( sqlite3_connection &con,
314 const data::RecordId &record_id,
315 const std::string &klass,
316 const std::string &name,
319 //con.executenonquery("BEGIN;");
320 _cmd_attr_num->bind(":rid", record_id);
322 _cmd_attr_num->bind(":tclass", klass);
323 _cmd_attr_num->bind(":tname", name);
325 sqlite3_reader reader = _cmd_attr_num->executereader();
327 return reader.getint(0);
331 sqlite3_reader idreader = _cmd_shared_id->executereader();
332 if ( idreader.read() )
334 _cmd_shared_id->bind(":rid", record_id);
335 data::RecordId sid = idreader.getint(0);
337 return queryNumericAttributeInternal(con, sid, klass, name, default_value);
341 return default_value;
344 TranslatedText queryTranslatedStringAttributeInternal( sqlite3_connection &con,
345 const data::RecordId &record_id,
346 const std::string &klass,
347 const std::string &name,
348 const TranslatedText &default_value )
350 //con.executenonquery("PRAGMA cache_size=8000;");
351 //con.executenonquery("BEGIN;");
353 _cmd_attr_tstr->bind(":rid", record_id);
354 _cmd_attr_tstr->bind(":lclass", "lang");
356 _cmd_attr_tstr->bind(":tclass", klass);
357 _cmd_attr_tstr->bind(":tname", name);
359 TranslatedText result;
360 sqlite3_reader reader = _cmd_attr_tstr->executereader();
365 result.setText( reader.getstring(0), Locale( reader.getstring(1) ) );
374 _cmd_shared_id->bind(":rid", record_id);
375 sqlite3_reader idreader = _cmd_shared_id->executereader();
376 if ( idreader.read() )
378 data::RecordId sid = idreader.getint(0);
380 return queryTranslatedStringAttributeInternal(con, sid, klass, name, default_value);
384 return default_value;
387 std::string queryStringAttributeInternal( sqlite3_connection &con,
388 const data::RecordId &record_id,
389 const std::string &klass,
390 const std::string &name,
391 const std::string &default_value )
393 return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name, default_value );
396 std::string queryStringAttributeTranslationInternal( sqlite3_connection &con,
397 const data::RecordId &record_id,
398 const Locale &locale,
399 const std::string &klass,
400 const std::string &name,
401 const std::string &default_value )
403 //con.executenonquery("BEGIN;");
404 _cmd_attr_str->bind(":rid", record_id);
405 _cmd_attr_str->bind(":lclass", "lang");
406 if (locale == Locale() )
407 _cmd_attr_str->bind(":lname", "none");
409 _cmd_attr_str->bind(":lname", locale.code());
411 _cmd_attr_str->bind(":tclass", klass);
412 _cmd_attr_str->bind(":tname", name);
414 sqlite3_reader reader = _cmd_attr_str->executereader();
417 return reader.getstring(0);
421 _cmd_shared_id->bind(":rid", record_id);
422 sqlite3_reader idreader = _cmd_shared_id->executereader();
423 if ( idreader.read() )
425 data::RecordId sid = idreader.getint(0);
427 return queryStringAttributeTranslationInternal( con, sid, locale, klass, name, default_value );
431 return default_value;
435 //////////////////////////////////////////////////////////////////////////////
436 // FORWARD TO IMPLEMENTATION
437 //////////////////////////////////////////////////////////////////////////////
439 ResolvableQuery::ResolvableQuery( const Pathname &dbdir)
440 : _pimpl(/*new Impl(dbdir)*/)
442 //MIL << "Creating Resolvable query" << endl;
445 ResolvableQuery::~ResolvableQuery()
447 //MIL << "Destroying Resolvable query" << endl;
450 //////////////////////////////////////////////////////////////////////////////
452 void ResolvableQuery::query( const data::RecordId &id, ProcessResolvable fnc )
454 _pimpl->query(id, fnc);
457 //////////////////////////////////////////////////////////////////////////////
459 void ResolvableQuery::query( const std::string &s, ProcessResolvable fnc )
461 _pimpl->query(s, fnc);
464 //////////////////////////////////////////////////////////////////////////////
466 int ResolvableQuery::queryNumericAttribute( const data::RecordId &record_id,
467 const std::string &klass,
468 const std::string &name,
471 return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
474 bool ResolvableQuery::queryBooleanAttribute( const data::RecordId &record_id,
475 const std::string &klass,
476 const std::string &name,
479 return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
483 std::string ResolvableQuery::queryStringAttribute( const data::RecordId &record_id,
484 const std::string &klass,
485 const std::string &name,
486 const std::string &default_value )
488 return _pimpl->queryStringAttribute(record_id, klass, name, default_value);
491 //////////////////////////////////////////////////////////////////////////////
493 std::string ResolvableQuery::queryStringAttributeTranslation( const data::RecordId &record_id,
494 const Locale &locale,
495 const std::string &klass,
496 const std::string &name,
497 const std::string &default_value )
499 return _pimpl->queryStringAttributeTranslation(record_id, locale, klass, name, default_value );
502 //////////////////////////////////////////////////////////////////////////////
504 TranslatedText ResolvableQuery::queryTranslatedStringAttribute( const data::RecordId &record_id,
505 const std::string &klass,
506 const std::string &name,
507 const TranslatedText &default_value )
509 return _pimpl->queryTranslatedStringAttribute(record_id, klass, name, default_value );
512 void ResolvableQuery::queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
514 _pimpl->queryDiskUsage(record_id, du);
517 std::string ResolvableQuery::queryRepositoryAlias( const data::RecordId &repo_id )
519 return _pimpl->queryRepositoryAlias( repo_id );
522 void ResolvableQuery::iterateResolvablesByKindsAndStringsAndRepos( const std::vector<zypp::Resolvable::Kind> & kinds,
523 const std::vector<std::string> &strings, int flags, const std::vector<std::string> &repos, ProcessResolvable fnc )
525 _pimpl->iterateResolvablesByKindsAndStringsAndRepos( kinds, strings, flags, repos, fnc );
527 //////////////////////////////////////////////////////////////////////////////
529 } } // namespace zypp::cache