ResolvableQuery.cc

Go to the documentation of this file.
00001 #include <iterator>
00002 #include <algorithm>
00003 #include "zypp/base/PtrTypes.h"
00004 #include "zypp/base/Logger.h"
00005 #include "zypp/cache/CacheTypes.h"
00006 #include "zypp/cache/ResolvableQuery.h"
00007 #include "zypp/Package.h"
00008 #include "zypp/cache/sqlite3x/sqlite3x.hpp"
00009 
00010 using namespace sqlite3x;
00011 using namespace std;
00012 using namespace zypp;
00013 
00014 typedef shared_ptr<sqlite3_command> sqlite3_command_ptr;
00015 
00016 namespace zypp { namespace cache {
00017 
00018 struct ResolvableQuery::Impl
00019 {
00020   Pathname _dbdir;
00021   string _fields;
00022   CacheTypes _type_cache;
00023   sqlite3_connection _con;
00024   sqlite3_command_ptr _cmd_attr_str;
00025   sqlite3_command_ptr _cmd_attr_tstr;
00026   sqlite3_command_ptr _cmd_attr_num;
00027   sqlite3_command_ptr _cmd_disk_usage;
00028   sqlite3_command_ptr _cmd_shared_id;
00029 
00030   Impl( const Pathname &dbdir)
00031   : _dbdir(dbdir)
00032   , _type_cache(dbdir)
00033   {
00034     _con.open((dbdir + "zypp.db").asString().c_str());
00035     _con.executenonquery("PRAGMA cache_size=8000;");
00036 
00037     _cmd_shared_id.reset( new sqlite3_command( _con, "select shared_id from resolvables where id=:rid;") );
00038 
00039     _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;") );
00040 
00041 
00042     _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;"));
00043 
00044     _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;"));
00045 
00046     _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;"));
00047     
00048     MIL << "Creating Resolvable query impl" << endl;
00049     //         0   1     2        3        4      5     6     7               8             9             10          11            12
00050     _fields = "id, name, version, release, epoch, arch, kind, installed_size, archive_size, install_only, build_time, install_time, repository_id";
00051   }
00052 
00053   ~Impl()
00054   {
00055       MIL << "Destroying Resolvable query impl" << endl;
00056   }
00057 
00058   //
00059   // convert regex ? and * operators to sql _ and % respectively
00060   //  example: regex2sql( "*foo?bar*" ) => "%foo_bar%"
00061   // FIXME: take care of ".*" and "."
00062   std::string regex2sql( const std::string & s)
00063   {
00064     std::string sql( s );
00065     string::iterator it;
00066     for (it = sql.begin(); it != sql.end(); ++it)
00067     {
00068       if (*it == '*') *it = '%';
00069       else if (*it == '?') *it = '_';
00070     }
00071     return sql;
00072   }
00073 
00074   data::ResObject_Ptr fromRow( sqlite3_reader &reader )
00075   {
00076     data::ResObject_Ptr ptr (new data::ResObject);
00077 
00078     // see _fields definition above for the getXXX() numbers
00079 
00080     ptr->name = reader.getstring(1);
00081     ptr->edition = Edition( reader.getstring(2), reader.getstring(3), reader.getint(4));
00082     ptr->arch = _type_cache.archFor(reader.getint(5));
00083     ptr->kind = _type_cache.kindFor( reader.getint(6) );
00084     ptr->repository = reader.getint( 12 );
00085 
00086     // TODO get the rest of the data
00087 
00088     return ptr;
00089   }
00090 
00091   
00092   void query( const data::RecordId &id,
00093                   ProcessResolvable fnc )
00094   {
00095     sqlite3_command cmd( _con, "select " + _fields + " from resolvables where id=:id;");
00096     cmd.bind(":id", id);
00097     sqlite3_reader reader = cmd.executereader();
00098     while(reader.read())
00099     {
00100       fnc( id, fromRow(reader) );
00101     }
00102   }
00103 
00104 
00105   void query( const std::string &s,
00106               ProcessResolvable fnc  )
00107   {  
00108     
00109     sqlite3_command cmd( _con, "select " + _fields + " from resolvables where name like :name;");
00110     cmd.bind( ":name", regex2sql( s ) );
00111     sqlite3_reader reader = cmd.executereader();
00112     while(reader.read())
00113     {
00114       fnc( reader.getint64(0), fromRow(reader) );
00115     }
00116   }
00117 
00118 
00119   std::string queryStringAttribute( const data::RecordId &record_id,
00120                                     const std::string &klass,
00121                                     const std::string &name,
00122                                     const std::string &default_value )
00123   {
00124     string value;
00125     return queryStringAttributeTranslationInternal( _con, record_id, Locale(), klass, name, default_value);
00126   }
00127 
00128 
00129   std::string queryStringAttributeTranslation( const data::RecordId &record_id,
00130                                                const Locale &locale,
00131                                                const std::string &klass,
00132                                                const std::string &name,
00133                                                const std::string &default_value )
00134   {
00135     return queryStringAttributeTranslationInternal( _con, record_id, locale, klass, name, default_value );
00136   }
00137 
00138 
00139   TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id,
00140                                                  const std::string &klass,
00141                                                  const std::string &name,
00142                                                  const TranslatedText &default_value )
00143   {
00144     return queryTranslatedStringAttributeInternal( _con, record_id, klass, name, default_value );
00145   }
00146 
00147 
00148   bool queryBooleanAttribute( const data::RecordId &record_id,
00149                               const std::string &klass,
00150                               const std::string &name,
00151                               bool default_value )
00152   {
00153     return ( queryNumericAttributeInternal( _con, record_id, klass, name, default_value) > 0 );
00154   }
00155       
00156   int queryNumericAttribute( const data::RecordId &record_id,
00157                              const std::string &klass,
00158                              const std::string &name,
00159                              int default_value )
00160   {
00161     return queryNumericAttributeInternal( _con, record_id, klass, name, default_value);
00162   }
00163 
00164   void queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
00165   {
00166     _cmd_disk_usage->bind(":rid", record_id);
00167     sqlite3_reader reader = _cmd_disk_usage->executereader();
00168 
00169     while ( reader.read() )
00170     {
00171       DiskUsage::Entry entry(reader.getstring(0),
00172                              reader.getint(1),
00173                              reader.getint(2) );
00174       du.add(entry);
00175     }
00176   }
00177 
00178   std::string queryRepositoryAlias( const data::RecordId &repo_id )
00179   {
00180     std::string alias;
00181     sqlite3_command cmd( _con, "select alias from repositories where id=:id;" );
00182     cmd.bind( ":id", repo_id );
00183     sqlite3_reader reader = cmd.executereader();
00184     while( reader.read() )
00185     {
00186       alias = reader.getstring( 0 );
00187       break;
00188     }
00189     return alias;
00190   }
00191   
00192   data::RecordId queryRepositoryId( const std::string &repo_alias )
00193   {
00194     long long id = 0;
00195     sqlite3_command cmd( _con, "select id from repositories where alias=:alias;" );
00196     cmd.bind( ":alias", repo_alias );
00197     sqlite3_reader reader = cmd.executereader();
00198     while( reader.read() )
00199     {
00200       id = reader.getint64(0);
00201       break;
00202     }
00203     return id;
00204   }
00205   
00206   void iterateResolvablesByKindsAndStringsAndRepos( const std::vector<zypp::Resolvable::Kind> & kinds,
00207                   const std::vector<std::string> &strings, int flags, const std::vector<std::string> repos, ProcessResolvable fnc )
00208   {
00209     std::string sqlcmd( "SELECT " + _fields + " FROM resolvables" );
00210 
00211     std::vector<std::string>::const_iterator it_s;
00212     for (it_s = strings.begin(); it_s != strings.end(); ++it_s)
00213     {
00214       std::string s( *it_s );
00215 
00216       if (it_s == strings.begin())
00217         sqlcmd += " WHERE (";
00218       else
00219         sqlcmd += " AND ";
00220 
00221 //FIXME: Implement MATCH_RESSUMM and MATCH_RESDESC
00222 
00223       sqlcmd += " name ";
00224       if (flags & MATCH_WILDCARDS == 0)
00225       {
00226         sqlcmd += "=";
00227       }
00228       else
00229       {
00230         sqlcmd += "like";
00231         s = regex2sql( s );
00232       }
00233       if (flags & MATCH_LEADING)
00234         s += "%";
00235       if (flags & MATCH_TRAILING)
00236         s = string("%") + s;
00237 
00238       sqlcmd += " '";
00239       sqlcmd += s;
00240       sqlcmd += "'";
00241     }
00242 
00243     if (it_s != strings.begin())
00244     {
00245       sqlcmd += ")";
00246     }
00247 
00248     std::vector<zypp::Resolvable::Kind>::const_iterator it_k;
00249     if (!kinds.empty())
00250     {
00251       if (it_s == strings.begin())
00252         sqlcmd += " WHERE";
00253       else
00254         sqlcmd += " AND";
00255 
00256       for (it_k = kinds.begin(); it_k != kinds.end(); ++it_k)
00257       {
00258         if (it_k == kinds.begin())
00259           sqlcmd += " kind IN (";
00260         else
00261           sqlcmd += ", ";
00262 
00263         char idbuf[16];
00264         snprintf( idbuf, 15, "%d", (int)(_type_cache.idForKind( *it_k )) );
00265         sqlcmd += idbuf;
00266       }
00267 
00268       if (it_k != kinds.begin())
00269       {
00270         sqlcmd += ")";
00271       }
00272     }
00273 
00274     std::vector<std::string>::const_iterator it_r;
00275     if (!repos.empty())
00276     {
00277       if (it_s == strings.begin()
00278           && it_k == kinds.begin())
00279         sqlcmd += " WHERE";
00280       else
00281         sqlcmd += " AND";
00282 
00283       for (it_r = repos.begin(); it_r != repos.end(); ++it_r)
00284       {
00285         if (it_r == repos.begin())
00286           sqlcmd += " (";
00287         else
00288           sqlcmd += " OR ";
00289 
00290         sqlcmd += "repository_id = ";
00291         char idbuf[16];
00292         snprintf( idbuf, 15, "%ld", (long)(queryRepositoryId( *it_r )) );
00293         sqlcmd += idbuf;
00294       }
00295 
00296       if (it_r != repos.begin())
00297       {
00298         sqlcmd += ")";
00299       }
00300     }
00301 
00302 MIL << "sqlcmd " << sqlcmd << endl;
00303     sqlite3_command cmd( _con, sqlcmd );
00304     sqlite3_reader reader = cmd.executereader();
00305     while(reader.read())
00306     {
00307       fnc( reader.getint64(0), fromRow(reader) );
00308     }
00309   }
00310 
00311 private:
00312 
00313   int queryNumericAttributeInternal( sqlite3_connection &con,
00314                                      const data::RecordId &record_id,
00315                                      const std::string &klass,
00316                                      const std::string &name,
00317                                      int default_value )
00318   {
00319     //con.executenonquery("BEGIN;");
00320     _cmd_attr_num->bind(":rid", record_id);
00321 
00322     _cmd_attr_num->bind(":tclass", klass);
00323     _cmd_attr_num->bind(":tname", name);
00324 
00325     sqlite3_reader reader = _cmd_attr_num->executereader();
00326     if ( reader.read() )
00327       return reader.getint(0);
00328     else
00329     {
00330       reader.close();
00331       sqlite3_reader idreader = _cmd_shared_id->executereader();
00332       if ( idreader.read() )
00333       {
00334         _cmd_shared_id->bind(":rid", record_id);
00335         data::RecordId sid = idreader.getint(0);
00336         idreader.close();
00337         return queryNumericAttributeInternal(con, sid, klass, name, default_value);
00338       }
00339     }
00340 
00341     return default_value;
00342   }
00343   
00344   TranslatedText queryTranslatedStringAttributeInternal( sqlite3_connection &con,
00345                                                          const data::RecordId &record_id,
00346                                                          const std::string &klass,
00347                                                          const std::string &name,
00348                                                          const TranslatedText &default_value )
00349   {
00350     //con.executenonquery("PRAGMA cache_size=8000;");
00351     //con.executenonquery("BEGIN;");
00352 
00353     _cmd_attr_tstr->bind(":rid", record_id);
00354     _cmd_attr_tstr->bind(":lclass", "lang");
00355 
00356     _cmd_attr_tstr->bind(":tclass", klass);
00357     _cmd_attr_tstr->bind(":tname", name);
00358 
00359     TranslatedText result;
00360     sqlite3_reader reader = _cmd_attr_tstr->executereader();
00361     
00362     int c = 0;
00363     while(reader.read())
00364     {
00365       result.setText( reader.getstring(0), Locale( reader.getstring(1) ) );
00366       c++;
00367     }
00368 
00369     if ( c>0 )
00370       return result;
00371     else
00372     {
00373       reader.close();
00374       _cmd_shared_id->bind(":rid", record_id);
00375       sqlite3_reader idreader = _cmd_shared_id->executereader();
00376       if ( idreader.read() )
00377       {
00378         data::RecordId sid = idreader.getint(0);
00379         idreader.close();
00380         return queryTranslatedStringAttributeInternal(con, sid, klass, name, default_value);
00381       }
00382     }
00383 
00384     return default_value;
00385   }
00386 
00387   std::string queryStringAttributeInternal( sqlite3_connection &con,
00388                                             const data::RecordId &record_id,
00389                                             const std::string &klass,
00390                                             const std::string &name,
00391                                             const std::string &default_value )
00392   {
00393     return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name, default_value );
00394   }
00395 
00396   std::string queryStringAttributeTranslationInternal( sqlite3_connection &con,
00397                                                        const data::RecordId &record_id,
00398                                                        const Locale &locale,
00399                                                        const std::string &klass,
00400                                                        const std::string &name,
00401                                                         const std::string &default_value )
00402   {
00403     //con.executenonquery("BEGIN;");
00404     _cmd_attr_str->bind(":rid", record_id);
00405     _cmd_attr_str->bind(":lclass", "lang");
00406     if (locale == Locale() )
00407       _cmd_attr_str->bind(":lname", "none");
00408     else
00409       _cmd_attr_str->bind(":lname", locale.code());
00410 
00411     _cmd_attr_str->bind(":tclass", klass);
00412     _cmd_attr_str->bind(":tname", name);
00413 
00414     sqlite3_reader reader = _cmd_attr_str->executereader();
00415     
00416     if ( reader.read() )
00417       return reader.getstring(0);
00418     else
00419     {
00420       reader.close();
00421       _cmd_shared_id->bind(":rid", record_id);
00422       sqlite3_reader idreader = _cmd_shared_id->executereader();
00423       if ( idreader.read() )
00424       {
00425         data::RecordId sid = idreader.getint(0);
00426         idreader.close();
00427         return queryStringAttributeTranslationInternal( con, sid, locale, klass, name, default_value );
00428       }
00429     }
00430 
00431     return default_value;
00432   }
00433 };
00434 
00436 // FORWARD TO IMPLEMENTATION
00438 
00439 ResolvableQuery::ResolvableQuery( const Pathname &dbdir)
00440   : _pimpl(new Impl(dbdir))
00441 {
00442   //MIL << "Creating Resolvable query" << endl;
00443 }
00444 
00445 ResolvableQuery::~ResolvableQuery()
00446 {
00447   //MIL << "Destroying Resolvable query" << endl;
00448 }
00449 
00451 
00452 void ResolvableQuery::query( const data::RecordId &id, ProcessResolvable fnc  )
00453 {
00454   _pimpl->query(id, fnc);
00455 }
00456 
00458 
00459 void ResolvableQuery::query( const std::string &s, ProcessResolvable fnc  )
00460 {
00461   _pimpl->query(s, fnc);
00462 }
00463 
00465 
00466 int ResolvableQuery::queryNumericAttribute( const data::RecordId &record_id,
00467                                             const std::string &klass,
00468                                             const std::string &name,
00469                                             int default_value )
00470 {
00471   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
00472 }
00473 
00474 bool ResolvableQuery::queryBooleanAttribute( const data::RecordId &record_id,
00475                                              const std::string &klass,
00476                                              const std::string &name,
00477                                              bool default_value )
00478 {
00479   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
00480 }
00481 
00482 
00483 std::string ResolvableQuery::queryStringAttribute( const data::RecordId &record_id,
00484                                                    const std::string &klass,
00485                                                    const std::string &name,
00486                                                    const std::string &default_value )
00487 {
00488   return _pimpl->queryStringAttribute(record_id, klass, name, default_value);
00489 }
00490 
00492 
00493 std::string ResolvableQuery::queryStringAttributeTranslation( const data::RecordId &record_id,
00494                                                               const Locale &locale,
00495                                                               const std::string &klass,
00496                                                               const std::string &name,
00497                                                               const std::string &default_value )
00498 {
00499   return _pimpl->queryStringAttributeTranslation(record_id, locale, klass, name, default_value );
00500 }
00501 
00503 
00504 TranslatedText ResolvableQuery::queryTranslatedStringAttribute( const data::RecordId &record_id,
00505                                                                 const std::string &klass,
00506                                                                 const std::string &name,
00507                                                                 const TranslatedText &default_value )
00508 {
00509   return _pimpl->queryTranslatedStringAttribute(record_id, klass, name, default_value );
00510 }
00511 
00512 void ResolvableQuery::queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
00513 {
00514   _pimpl->queryDiskUsage(record_id, du);
00515 }
00516 
00517 std::string ResolvableQuery::queryRepositoryAlias( const data::RecordId &repo_id )
00518 {
00519   return _pimpl->queryRepositoryAlias( repo_id );
00520 }
00521 
00522 void ResolvableQuery::iterateResolvablesByKindsAndStringsAndRepos( const std::vector<zypp::Resolvable::Kind> & kinds,
00523                   const std::vector<std::string> &strings, int flags, const std::vector<std::string> &repos, ProcessResolvable fnc )
00524 {
00525   _pimpl->iterateResolvablesByKindsAndStringsAndRepos( kinds, strings, flags, repos, fnc );
00526 }
00528 
00529 } } // namespace zypp::cache

Generated on Tue Sep 25 19:23:00 2007 for libzypp by  doxygen 1.5.3