fix gcc-4.2 errors, warnings, add -D_FILE_OFFSET_BITS=64 and -O3
[platform/upstream/libzypp.git] / zypp / cache / CacheStore.cc
1 #include <sqlite3.h>
2 #include <map>
3 #include "zypp/cache/sqlite3x/sqlite3x.hpp"
4
5 #include "zypp/base/Logger.h"
6 #include "zypp/base/Measure.h"
7 #include "zypp/ZYppFactory.h"
8 #include "zypp/ZYpp.h"
9 #include "zypp/Package.h"
10 #include "zypp/cache/CacheInitializer.h"
11 #include "zypp/cache/CacheStore.h"
12 #include "zypp/cache/CacheException.h"
13
14 using namespace std;
15 using namespace zypp;
16 using namespace zypp::capability;
17 using namespace zypp::cache;
18 using zypp::data::RecordId;
19 using namespace sqlite3x;
20
21 using zypp::debug::Measure;
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26 ///////////////////////////////////////////////////////////////////
27 namespace cache
28 { /////////////////////////////////////////////////////////////////
29
30 typedef shared_ptr<sqlite3_command> sqlite3_command_ptr;
31
32 struct CacheStore::Impl
33 {
34   Impl( const Pathname &dbdir )
35   : name_cache_hits(0)
36   {
37     cache::CacheInitializer initializer(dbdir, "zypp.db");
38     if ( initializer.justInitialized() )
39     {
40       MIL << "database " << (dbdir + "zypp.db") << " was just created" << endl;
41     }
42
43     try
44     {
45       con.open( (dbdir + "zypp.db").asString().c_str());
46       //_insert_resolvable_cmd = new sqlite3_command( *_con, INSERT_RESOLVABLE_QUERY );
47       //_insert_package_cmd = new sqlite3_command( *_con, INSERT_PACKAGE_QUERY );
48     }
49     catch(exception &ex)
50     {
51       //ZYPP_CAUGHT(ex);
52       ZYPP_THROW(Exception(ex.what()));
53     }
54
55
56     // initialize all pre-compiled statements
57
58     insert_resolvable_in_repository_cmd.reset( new sqlite3_command( con, "insert into resolvables_repositories (resolvable_id, repository_id) values (:resolvable_id, :repository_id);" ));
59
60     update_repository_cmd.reset( new sqlite3_command( con, "update repositories set checksum=:checksum, timestamp=:timestamp where id=:repository_id;" ));
61
62     select_repository_cmd.reset( new sqlite3_command( con, "select id from repositories where alias=:alias;" ));
63     insert_repository_cmd.reset( new sqlite3_command( con, "insert into repositories (alias,timestamp) values (:alias, :timestamp);" ));
64
65     select_name_cmd.reset( new sqlite3_command( con, "select id from names where name=:name;" ));
66     insert_name_cmd.reset( new sqlite3_command( con, "insert into names (name) values (:name);" ));
67
68     select_dirname_cmd.reset( new sqlite3_command( con, "select id from dir_names where name=:name;" ));
69     insert_dirname_cmd.reset( new sqlite3_command( con, "insert into dir_names (name) values (:name);" ));
70
71     select_filename_cmd.reset( new sqlite3_command( con, "select id from file_names where name=:name;" ));
72     insert_filename_cmd.reset( new sqlite3_command( con, "insert into file_names (name) values (:name);" ));
73
74     select_file_cmd.reset( new sqlite3_command( con, "select id from files where dir_name_id=:dir_name_id and file_name_id=:file_name_id;" ));
75     insert_file_cmd.reset( new sqlite3_command( con, "insert into files (dir_name_id,file_name_id) values (:dir_name_id,:file_name_id);" ));
76
77     select_type_cmd.reset( new sqlite3_command( con, "select id from types where class=:class and name=:name;" ));
78     insert_type_cmd.reset( new sqlite3_command( con, "insert into types (class,name) values (:class,:name);" ));
79
80     set_shared_flag_cmd.reset( new sqlite3_command( con, "update resolvables set shared_id=:shared_id where id=:resolvable_id;" ));
81
82     append_text_attribute_cmd.reset( new sqlite3_command( con, "insert into text_attributes ( weak_resolvable_id, lang_id, attr_id, text ) values ( :rid, :lang_id, :attr_id, :text );" ));
83     append_num_attribute_cmd.reset( new sqlite3_command( con, "insert into numeric_attributes ( weak_resolvable_id, attr_id, value ) values ( :rid, :attr_id, :value );" ));
84
85     //insert_dependency_entry_cmd.reset( new sqlite3_command( con, "insert into capabilities ( resolvable_id, dependency_type, refers_kind ) values ( :resolvable_id, :dependency_type, :refers_kind );" ));
86     append_file_dependency_cmd.reset( new sqlite3_command( con, "insert into file_capabilities ( resolvable_id, dependency_type, refers_kind, file_id ) values ( :resolvable_id, :dependency_type, :refers_kind, :file_id );" ));
87     append_named_dependency_cmd.reset( new sqlite3_command( con, "insert into named_capabilities ( resolvable_id, dependency_type, refers_kind, name_id, version, release, epoch, relation ) values ( :resolvable_id, :dependency_type, :refers_kind, :name_id, :version, :release, :epoch, :relation );" ));
88
89     append_modalias_dependency_cmd.reset( new sqlite3_command( con, "insert into modalias_capabilities ( resolvable_id, dependency_type, refers_kind, name, value, relation ) values ( :resolvable_id, :dependency_type, :refers_kind, :name, :value, :relation );" ));
90
91     append_hal_dependency_cmd.reset( new sqlite3_command( con, "insert into hal_capabilities ( resolvable_id, dependency_type, refers_kind, name, value, relation ) values ( :resolvable_id, :dependency_type, :refers_kind, :name, :value, :relation );" ));
92
93     append_other_dependency_cmd.reset( new sqlite3_command( con, "insert into other_capabilities ( resolvable_id, dependency_type, refers_kind, value ) values ( :resolvable_id, :dependency_type, :refers_kind, :value );" ));
94
95     append_resolvable_cmd.reset( new sqlite3_command( con, "insert into resolvables ( name, version, release, epoch, arch, kind, repository_id ) values ( :name, :version, :release, :epoch, :arch, :kind, :repository_id );" ));
96
97     count_shared_cmd.reset( new sqlite3_command( con, "select count(id) from resolvables where shared_id=:rid;" ));
98
99     insert_patchrpm_cmd.reset( new sqlite3_command (con,
100       "insert into patch_packages (repository_id, media_nr, location, checksum, download_size, build_time) "
101       "values (:repository_id, :media_nr, :location, :checksum, :download_size, :build_time);" ));
102     insert_deltarpm_cmd.reset( new sqlite3_command (con,
103       "insert into delta_packages (repository_id, media_nr, location, checksum, download_size, build_time, "
104         "baseversion_version, baseversion_release, baseversion_epoch, baseversion_checksum, "
105         "baseversion_build_time, baseversion_sequence_info) "
106       "values (:repository_id, :media_nr, :location, :checksum, :download_size, :build_time, "
107         ":baseversion_version, :baseversion_release, :baseversion_epoch, :baseversion_checksum, "
108         ":baseversion_build_time, :baseversion_sequence_info);" ));
109     append_patch_baseversion_cmd.reset( new sqlite3_command (con,
110       "insert into patch_packages_baseversions (patch_package_id, version, release, epoch) "
111       "values (:patch_package_id, :version, :release, :epoch)" ));
112
113
114     // disable autocommit
115     con.executenonquery("BEGIN;");
116   }
117
118   Impl()
119   {
120     Impl( getZYpp()->homePath() );
121   }
122
123   ~Impl()
124   {
125     MIL << "name cache hits: " << name_cache_hits << " | cache size: " << name_cache.size() << endl;
126   }
127
128  /**
129   * SQL statements
130   * (we precompile them
131   */
132   sqlite3_connection con;
133
134   sqlite3_command_ptr update_repository_cmd;
135   sqlite3_command_ptr insert_resolvable_in_repository_cmd;
136
137   sqlite3_command_ptr select_name_cmd;
138   sqlite3_command_ptr insert_name_cmd;
139
140   sqlite3_command_ptr select_dirname_cmd;
141   sqlite3_command_ptr insert_dirname_cmd;
142
143   sqlite3_command_ptr select_filename_cmd;
144   sqlite3_command_ptr insert_filename_cmd;
145
146   sqlite3_command_ptr select_repository_cmd;
147   sqlite3_command_ptr insert_repository_cmd;
148
149   sqlite3_command_ptr select_file_cmd;
150   sqlite3_command_ptr insert_file_cmd;
151
152   sqlite3_command_ptr select_type_cmd;
153   sqlite3_command_ptr insert_type_cmd;
154
155   //sqlite3_command_ptr insert_dependency_entry_cmd;
156
157   sqlite3_command_ptr append_file_dependency_cmd;
158   sqlite3_command_ptr append_named_dependency_cmd;
159   sqlite3_command_ptr append_modalias_dependency_cmd;
160   sqlite3_command_ptr append_hal_dependency_cmd;
161   sqlite3_command_ptr append_other_dependency_cmd;
162
163   sqlite3_command_ptr append_resolvable_cmd;
164
165   sqlite3_command_ptr append_text_attribute_cmd;
166   sqlite3_command_ptr append_num_attribute_cmd;
167
168   sqlite3_command_ptr set_shared_flag_cmd;
169
170   sqlite3_command_ptr count_shared_cmd;
171
172   sqlite3_command_ptr insert_patchrpm_cmd;
173   sqlite3_command_ptr insert_deltarpm_cmd;
174   sqlite3_command_ptr append_patch_baseversion_cmd;
175
176   map<string, RecordId> name_cache;
177   map< pair<string,string>, RecordId> type_cache;
178   int name_cache_hits;
179 };
180
181
182 CacheStore::CacheStore( const Pathname &dbdir )
183   : _pimpl( new Impl(dbdir) )
184 {
185
186 }
187
188 CacheStore::CacheStore()
189     : _pimpl( new Impl() )
190 {
191
192 }
193
194 CacheStore::~CacheStore()
195 {
196
197 }
198
199 void CacheStore::commit()
200 {
201   _pimpl->con.executenonquery("COMMIT;");
202 }
203
204 void CacheStore::appendResObjectAttributes( const data::RecordId &rid,
205                                             const data::ResObject_Ptr & res )
206 {
207   appendTranslatedStringAttribute( rid, "ResObject", "description", res->description );
208   appendTranslatedStringAttribute( rid, "ResObject", "summary", res->summary );
209   appendNumericAttribute( rid, "ResObject", "installedSize", res->installedSize );
210   appendNumericAttribute( rid, "ResObject", "buildTime", res->buildTime );
211   appendBooleanAttribute( rid, "ResObject", "installOnly", res->installOnly );
212   appendStringAttribute( rid, "ResObject", "vendor", res->vendor );
213   appendTranslatedStringAttribute( rid, "ResObject", "licenseToConfirm", res->licenseToConfirm );
214   appendTranslatedStringAttribute( rid, "ResObject", "insnotify", res->insnotify );
215   appendTranslatedStringAttribute( rid, "ResObject", "delnotify", res->delnotify );
216 }
217
218
219 void CacheStore::appendPackageBaseAttributes( const RecordId & pkgid,
220                                               const data::Packagebase_Ptr & package )
221 {
222   appendStringAttribute( pkgid, "Package", "checksum", package->repositoryLocation.fileChecksum.checksum() );
223   appendStringAttribute( pkgid, "Package", "checksumType", package->repositoryLocation.fileChecksum.type() );
224   appendStringAttribute( pkgid, "Package", "buildhost", package->buildhost );
225   appendStringAttribute( pkgid, "Package", "distribution", package->distribution );
226   appendStringAttribute( pkgid, "Package", "license", package->license );
227   appendStringAttribute( pkgid, "Package", "group", package->packager );
228   appendStringAttribute( pkgid, "Package", "url", package->url );
229   appendStringAttribute( pkgid, "Package", "operatingSystem", package->operatingSystem );
230   appendStringAttribute( pkgid, "Package", "prein", package->prein );
231   appendStringAttribute( pkgid, "Package", "postin", package->postin );
232   appendStringAttribute( pkgid, "Package", "preun", package->preun );
233   appendStringAttribute( pkgid, "Package", "postun", package->postun );
234   appendStringContainerAttribute( pkgid, "Package", "keywords", package->keywords.begin(), package->keywords.end() );
235   appendStringContainerAttribute( pkgid, "Package", "authors", package->authors.begin(), package->authors.end() );
236   appendStringAttribute( pkgid, "Package", "location", package->repositoryLocation.filePath.asString() );
237 }
238
239 RecordId CacheStore::consumePackage( const RecordId & repository_id,
240                                  const data::Package_Ptr & package )
241 {
242   RecordId id = appendResolvable( repository_id, ResTraits<Package>::kind,
243       NVRA( package->name, package->edition, package->arch ), package->deps );
244   appendResObjectAttributes( id, package );
245   appendPackageBaseAttributes( id, package );
246   return id;
247 }
248
249 RecordId CacheStore::consumeSourcePackage( const data::RecordId & repository_id,
250                                        const data::SrcPackage_Ptr & package )
251 {
252   RecordId id = appendResolvable( repository_id, ResTraits<SrcPackage>::kind,
253       NVRA( package->name, package->edition, package->arch ), package->deps );
254   appendResObjectAttributes( id, package );
255   appendPackageBaseAttributes( id, package );
256 #warning TBD WRONG IMPLEMENTATION
257   return id;
258 }
259
260 RecordId CacheStore::consumePatch( const data::RecordId & repository_id,
261                                const data::Patch_Ptr & patch)
262 {
263   RecordId id = appendResolvable(
264       repository_id, ResTraits<Patch>::kind,
265       NVRA( patch->name, patch->edition, patch->arch ), patch->deps );
266
267   appendResObjectAttributes( id, patch );
268
269   // patch attributes
270   appendNumericAttribute( id, "Patch", "timestamp",         patch->timestamp );
271   appendStringAttribute(  id, "Patch", "category",          patch->category );
272   appendBooleanAttribute( id, "Patch", "rebootNeeded",      patch->rebootNeeded );
273   appendBooleanAttribute( id, "Patch", "affectsPkgManager", patch->affectsPkgManager );
274
275
276   DBG << "got patch " << patch->name << ", atoms: ";
277   // cosume atoms
278   for (set<data::ResObject_Ptr>::const_iterator p = patch->atoms.begin();
279        p != patch->atoms.end(); ++p)
280   {
281     data::PackageAtom_Ptr atom = dynamic_pointer_cast<data::PackageAtom>(*p);
282     if (atom)
283     {
284       DBG << atom->name << "(atom) ";
285       consumePackageAtom(repository_id, atom);
286       continue;
287     }
288
289     data::Script_Ptr script = dynamic_pointer_cast<data::Script>(*p);
290     if (script)
291     {
292       DBG << script->name << "(script) ";
293       consumeScript(repository_id, script);
294       continue;
295     }
296
297     data::Message_Ptr message = dynamic_pointer_cast<data::Message>(*p);
298     if (message)
299     {
300       DBG << message->name << "(message) ";
301       consumeMessage(repository_id, message);
302       continue;
303     }
304
305     ERR << " ignoring !badatom! ";
306     if (*p) ERR << (*p)->name;
307     ERR << endl;
308   }
309
310   DBG << endl;
311   return id;
312 }
313
314 RecordId CacheStore::consumePackageAtom( const data::RecordId & repository_id,
315                                      const data::PackageAtom_Ptr & atom )
316 {
317   RecordId id = appendResolvable( repository_id, ResTraits<Atom>::kind,
318       NVRA( atom->name, atom->edition, atom->arch ), atom->deps );
319   appendResObjectAttributes( id, atom );
320   appendPackageBaseAttributes( id, atom );
321
322   for (set<data::PatchRpm_Ptr>::const_iterator p = atom->patchRpms.begin();
323        p != atom->patchRpms.end(); ++p)
324     appendPatchRpm(repository_id, *p);
325
326   for (set<data::DeltaRpm_Ptr>::const_iterator d = atom->deltaRpms.begin();
327        d != atom->deltaRpms.end(); ++d)
328     appendDeltaRpm(repository_id, *d);
329   return id;
330 }
331
332 RecordId CacheStore::consumeMessage( const data::RecordId & repository_id,
333                                  const data::Message_Ptr & message )
334 {
335   RecordId id = appendResolvable( repository_id, ResTraits<Message>::kind,
336       NVRA( message->name, message->edition, message->arch ), message->deps );
337   appendResObjectAttributes( id, message );
338
339   appendTranslatedStringAttribute( id, "Message", "text", message->text );
340   return id;
341 }
342
343 RecordId CacheStore::consumeScript( const data::RecordId & repository_id,
344                                 const data::Script_Ptr & script )
345 {
346   RecordId id = appendResolvable( repository_id, ResTraits<Script>::kind,
347       NVRA( script->name, script->edition, script->arch ), script->deps );
348   appendResObjectAttributes( id, script );
349
350   appendStringAttribute( id, "Script", "doScript", script->doScript );
351   appendStringAttribute( id, "Script", "doScriptLocation", script->doScriptLocation.filePath.asString() );
352   appendStringAttribute( id, "Script", "doScriptChecksum", script->doScriptLocation.fileChecksum.checksum() );
353   appendStringAttribute( id, "Script", "doScriptChecksumType", script->doScriptLocation.fileChecksum.type() );
354   appendStringAttribute( id, "Script", "undoScript", script->undoScript );
355   appendStringAttribute( id, "Script", "undoScriptLocation", script->undoScriptLocation.filePath.asString() );
356   appendStringAttribute( id, "Script", "undoScriptChecksum", script->undoScriptLocation.fileChecksum.checksum() );
357   appendStringAttribute( id, "Script", "undoScriptChecksumType", script->undoScriptLocation.fileChecksum.type() );
358   return id;
359 }
360
361 RecordId CacheStore::consumePattern( const data::RecordId & repository_id,
362                                  const data::Pattern_Ptr & pattern )
363 {
364   RecordId id = appendResolvable( repository_id, ResTraits<Pattern>::kind,
365       NVRA( pattern->name, pattern->edition, pattern->arch ), pattern->deps );
366   appendResObjectAttributes( id, pattern );
367
368   appendBooleanAttribute( id, "Pattern", "isDefault", pattern->isDefault );
369   appendBooleanAttribute( id, "Pattern", "userVisible", pattern->userVisible );
370   appendTranslatedStringAttribute( id, "Pattern", "category", pattern->category );
371   appendStringAttribute( id, "Pattern", "icon", pattern->icon );
372   appendStringAttribute( id, "Pattern", "order", pattern->order );
373   return id;
374 }
375
376 RecordId CacheStore::consumeProduct( const data::RecordId & repository_id,
377                                  const data::Product_Ptr & product )
378 {
379   RecordId id = appendResolvable( repository_id, ResTraits<Product>::kind,
380       NVRA( product->name, product->edition, product->arch ), product->deps );
381   appendResObjectAttributes( id, product );
382
383   appendTranslatedStringAttribute( id, "Product", "shortName", product->shortName );
384   appendTranslatedStringAttribute( id, "Product", "longName", product->longName );
385   appendStringContainerAttribute( id, "Product", "flags", product->flags.begin(), product->flags.end() );
386   appendStringAttribute( id, "Product", "releasenotesUrl", product->releasenotesUrl.asString() );
387   appendStringContainerAttribute( id, "Product", "updateUrls", product->updateUrls );
388   appendStringContainerAttribute( id, "Product", "extraUrls", product->extraUrls );
389   appendStringContainerAttribute( id, "Product", "optionalUrls", product->optionalUrls );
390   appendStringAttribute( id, "Product", "distributionName", product->distributionName );
391   appendStringAttribute( id, "Product", "distributionEdition", product->distributionEdition.asString() );
392   return id;
393 }
394
395 RecordId CacheStore::consumeChangelog( const data::RecordId & repository_id,
396                                    const data::Resolvable_Ptr & resolvable,
397                                    const Changelog & changelog )
398 {
399   //! \todo maybe appendChangelog(const data::RecordId & resolvable_id, Changelog changelog) will be needed
400   //! for inserting the changelog using in-memory record id of corresponding resolvable.
401   //! (first, we'll see how fast is the inserting without remembering those ids)
402   return data::noRecordId;
403 }
404
405 RecordId CacheStore::consumeFilelist( const data::RecordId & repository_id,
406                                   const data::Resolvable_Ptr & resolvable,
407                                   const data::Filenames & filenames )
408 {
409   //! \todo maybe consumeFilelist(const data::RecordId & resolvable_id, data::Filenames &) will be needed
410   return data::noRecordId;
411 }
412
413 RecordId CacheStore::appendResolvable( const RecordId &repository_id,
414                                        const Resolvable::Kind &kind,
415                                        const NVRA &nvra,
416                                        const data::Dependencies &deps )
417 {
418   _pimpl->append_resolvable_cmd->bind( ":name", nvra.name );
419   _pimpl->append_resolvable_cmd->bind( ":version", nvra.edition.version() );
420   _pimpl->append_resolvable_cmd->bind( ":release", nvra.edition.release() );
421   _pimpl->append_resolvable_cmd->bind( ":epoch", static_cast<int>( nvra.edition.epoch() ) );
422   _pimpl->append_resolvable_cmd->bind( ":arch", lookupOrAppendType("arch", nvra.arch.asString()) );
423   _pimpl->append_resolvable_cmd->bind( ":kind", lookupOrAppendType("kind", kind.asString()) );
424   _pimpl->append_resolvable_cmd->bind( ":repository_id", repository_id );
425
426   _pimpl->append_resolvable_cmd->executenonquery();
427
428   long long id = _pimpl->con.insertid();
429
430   appendDependencies( id, deps );
431   /*
432   _pimpl->insert_resolvable_in_repository_cmd->bind(":repository_id", repository_id);
433   _pimpl->insert_resolvable_in_repository_cmd->bind(":resolvable_id", id);
434   _pimpl->insert_resolvable_in_repository_cmd->executenonquery();*/
435
436   return static_cast<RecordId>(id);
437   return 1;
438 }
439
440 void CacheStore::appendDependencies( const RecordId &resolvable_id, const data::Dependencies &deps )
441 {
442   for ( data::Dependencies::const_iterator it = deps.begin(); it != deps.end(); ++it )
443   {
444     appendDependencyList( resolvable_id, it->first, it->second );
445   }
446 }
447
448 void CacheStore::appendDependencyList( const RecordId &resolvable_id, zypp::Dep deptype, const data::DependencyList &caps )
449 {
450   for ( data::DependencyList::const_iterator it = caps.begin(); it != caps.end(); ++it )
451   {
452     appendDependency( resolvable_id, deptype, *it );
453   }
454 }
455
456 void CacheStore::appendDependency( const RecordId &resolvable_id, zypp::Dep deptype, capability::CapabilityImpl::Ptr cap )
457 {
458   if ( cap == 0 )
459   {
460     DBG << "invalid capability" << endl;
461     return;
462   }
463
464   if ( capability::isKind<NamedCap>(cap) )
465   {
466       appendNamedDependency( resolvable_id, deptype, capability::asKind<NamedCap>(cap) );
467   }
468   else if ( capability::isKind<FileCap>(cap) )
469   {
470     appendFileDependency( resolvable_id, deptype, capability::asKind<FileCap>(cap) );
471     return;
472   }
473   else if ( capability::isKind<ModaliasCap>(cap) )
474   {
475       appendModaliasDependency( resolvable_id, deptype, capability::asKind<ModaliasCap>(cap) );
476   }
477   else if ( capability::isKind<HalCap>(cap) )
478   {
479       appendHalDependency( resolvable_id, deptype, capability::asKind<HalCap>(cap) );
480   }
481   else
482   {
483       appendUnknownDependency( resolvable_id, deptype, cap );
484   }
485 }
486
487 // RecordId CacheStore::lookupOrAppendNamedDependencyEntry( const RecordId name_id, const Edition &edition, const zypp::Rel &rel )
488 // {
489 //   _pimpl->select_named_dependency_cmd->bind( ":name_id", name_id);
490 //   _pimpl->select_named_dependency_cmd->bind( ":version", edition.version() );
491 //   _pimpl->select_named_dependency_cmd->bind( ":release", edition.release() );
492 //   _pimpl->select_named_dependency_cmd->bind( ":epoch", static_cast<int>( edition.epoch() ) );
493 //   _pimpl->select_named_dependency_cmd->bind( ":relation", zypp_rel2db_rel( rel ) );
494 //   long long id = 0;
495 //   try {
496 //     id = _pimpl->select_named_dependency_cmd->executeint64();
497 //   }
498 //   catch ( const sqlite3x::database_error &e )
499 //   {
500 //     // does not exist
501 //     _pimpl->append_named_dependency_entry_cmd->bind( ":name_id", name_id);
502 //     _pimpl->append_named_dependency_entry_cmd->bind( ":version", edition.version() );
503 //     _pimpl->append_named_dependency_entry_cmd->bind( ":release", edition.release() );
504 //     _pimpl->append_named_dependency_entry_cmd->bind( ":epoch", static_cast<int>( edition.epoch() ) );
505 //     _pimpl->append_named_dependency_entry_cmd->bind( ":relation", zypp_rel2db_rel( rel ) );
506 //     _pimpl->append_named_dependency_entry_cmd->executenonquery();
507 //     id = _pimpl->con.insertid();
508 //     return static_cast<RecordId>(id);
509 //   }
510 //   return static_cast<RecordId>(id);
511 // }
512
513 void CacheStore::appendNamedDependency( const RecordId &resolvable_id, zypp::Dep deptype, capability::NamedCap::Ptr cap )
514 {
515   if ( !cap )
516     ZYPP_THROW(Exception("bad versioned dep"));
517   //DBG << "versioned : " << cap << endl;
518
519   //RecordId capability_id = appendDependencyEntry( resolvable_id, deptype, cap->refers() );
520   RecordId name_id = lookupOrAppendName(cap->name());
521
522   _pimpl->append_named_dependency_cmd->bind( ":resolvable_id", resolvable_id );
523   _pimpl->append_named_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) );
524   _pimpl->append_named_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) );
525
526   //_pimpl->append_named_dependency_cmd->bind( ":capability_id", capability_id);
527   _pimpl->append_named_dependency_cmd->bind( ":name_id", name_id);
528   _pimpl->append_named_dependency_cmd->bind( ":version", cap->edition().version() );
529   _pimpl->append_named_dependency_cmd->bind( ":release", cap->edition().release() );
530   _pimpl->append_named_dependency_cmd->bind( ":epoch", static_cast<int>( cap->edition().epoch() ) );
531   _pimpl->append_named_dependency_cmd->bind( ":relation", lookupOrAppendType("rel", cap->op().asString()) );
532   _pimpl->append_named_dependency_cmd->executenonquery();
533
534   //delete cmd;
535 }
536
537 void CacheStore::appendModaliasDependency( const RecordId &resolvable_id,
538                                                  zypp::Dep deptype,
539                                                  capability::ModaliasCap::Ptr cap )
540 {
541   if ( !cap )
542     ZYPP_THROW(Exception("Null modalias capability"));
543
544   _pimpl->append_modalias_dependency_cmd->bind( ":resolvable_id", resolvable_id );
545   _pimpl->append_modalias_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) );
546   _pimpl->append_modalias_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) );
547
548   //_pimpl->append_modalias_dependency_cmd->bind( ":capability_id", capability_id);
549   _pimpl->append_modalias_dependency_cmd->bind( ":name", cap->name());
550   _pimpl->append_modalias_dependency_cmd->bind( ":value", cap->value());
551   _pimpl->append_modalias_dependency_cmd->bind( ":relation", lookupOrAppendType("rel", cap->op().asString()) );
552
553   _pimpl->append_modalias_dependency_cmd->executenonquery();
554   //delete cmd;
555 }
556
557 void CacheStore::appendHalDependency( const RecordId &resolvable_id,
558                                                  zypp::Dep deptype,
559                                                  capability::HalCap::Ptr cap )
560 {
561   if ( !cap )
562     ZYPP_THROW(Exception("Null HAL capability"));
563
564   _pimpl->append_hal_dependency_cmd->bind( ":resolvable_id", resolvable_id );
565   _pimpl->append_hal_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) );
566   _pimpl->append_hal_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) );
567
568   //_pimpl->append_hal_dependency_cmd->bind( ":capability_id", capability_id);
569   _pimpl->append_hal_dependency_cmd->bind( ":name", cap->name());
570   _pimpl->append_hal_dependency_cmd->bind( ":value", cap->value());
571   _pimpl->append_hal_dependency_cmd->bind( ":relation", lookupOrAppendType("rel", cap->op().asString()) );
572
573   _pimpl->append_hal_dependency_cmd->executenonquery();
574   //delete cmd;
575 }
576
577 void CacheStore::appendFileDependency( const RecordId &resolvable_id, zypp::Dep deptype,
578                                        capability::FileCap::Ptr cap )
579 {
580   if ( !cap )
581     ZYPP_THROW(Exception("Null file capability"));
582
583   //RecordId capability_id = appendDependencyEntry( resolvable_id, deptype, cap->refers() );
584   RecordId file_id = lookupOrAppendFile(cap->filename());
585
586   _pimpl->append_file_dependency_cmd->bind( ":resolvable_id", resolvable_id );
587   _pimpl->append_file_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) );
588   _pimpl->append_file_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) );
589
590   //_pimpl->append_file_dependency_cmd->bind( ":capability_id", capability_id);
591   _pimpl->append_file_dependency_cmd->bind( ":file_id", file_id);
592
593   _pimpl->append_file_dependency_cmd->executenonquery();
594   //delete cmd;
595 }
596
597 void CacheStore::appendUnknownDependency( const RecordId &resolvable_id,
598                                                zypp::Dep deptype,
599                                                capability::CapabilityImpl::Ptr cap )
600 {
601   if ( !cap )
602     ZYPP_THROW(Exception("Null unknown capability"));
603
604   _pimpl->append_other_dependency_cmd->bind( ":resolvable_id", resolvable_id );
605   _pimpl->append_other_dependency_cmd->bind( ":dependency_type", lookupOrAppendType("deptype", deptype.asString()) );
606   _pimpl->append_other_dependency_cmd->bind( ":refers_kind", lookupOrAppendType("kind", cap->refers().asString()) );
607   _pimpl->append_other_dependency_cmd->bind( ":value", cap->encode());
608
609   _pimpl->append_hal_dependency_cmd->executenonquery();
610   //delete cmd;
611 }
612
613
614 /** \todo lookupOrAppend ? */
615 RecordId CacheStore::appendPatchRpm(const zypp::data::RecordId &repository_id, const data::PatchRpm_Ptr & prpm)
616 {
617   RecordId id;
618
619   //! \todo what's this? _pimpl->insert_patchrpm_cmd->bind(":media_nr", ???);
620   _pimpl->insert_patchrpm_cmd->bind(":repository_id", repository_id);
621   _pimpl->insert_patchrpm_cmd->bind(":location", prpm->location.filePath.asString());
622   _pimpl->insert_patchrpm_cmd->bind(":checksum", prpm->location.fileChecksum.checksum());
623   //! \todo checksum type
624   _pimpl->insert_patchrpm_cmd->bind(":download_size", static_cast<ByteCount::SizeType>(prpm->location.fileSize));
625   _pimpl->insert_patchrpm_cmd->bind(":build_time", prpm->buildTime.asSeconds());
626   _pimpl->insert_patchrpm_cmd->executenonquery();
627
628   id = _pimpl->con.insertid();
629
630   for (set<data::BaseVersion_Ptr>::const_iterator bv = prpm->baseVersions.begin();
631        bv != prpm->baseVersions.end(); ++bv)
632   {
633     _pimpl->append_patch_baseversion_cmd->bind(":patch_package_id", id);
634     _pimpl->append_patch_baseversion_cmd->bind(":version", (*bv)->edition.version());
635     _pimpl->append_patch_baseversion_cmd->bind(":release", (*bv)->edition.release());
636     _pimpl->append_patch_baseversion_cmd->bind(":epoch", (int) (*bv)->edition.epoch());
637     _pimpl->append_patch_baseversion_cmd->executenonquery();
638   }
639
640   return id;
641 }
642
643
644 /** \todo lookupOrAppend ? */
645 RecordId CacheStore::appendDeltaRpm(const zypp::data::RecordId &repository_id, const data::DeltaRpm_Ptr & drpm)
646 {
647   RecordId id;
648
649   //! \todo what's this? _pimpl->insert_deltarpm_cmd->bind(":media_nr", ???);
650   _pimpl->insert_deltarpm_cmd->bind(":repository_id", repository_id);
651   _pimpl->insert_deltarpm_cmd->bind(":location", drpm->location.filePath.asString());
652   _pimpl->insert_deltarpm_cmd->bind(":checksum", drpm->location.fileChecksum.checksum());
653   //! \todo checksum type
654   _pimpl->insert_deltarpm_cmd->bind(":download_size", static_cast<ByteCount::SizeType>(drpm->location.fileSize));
655   _pimpl->insert_deltarpm_cmd->bind(":build_time", drpm->buildTime.asSeconds());
656
657   _pimpl->insert_deltarpm_cmd->bind(":baseversion_version", drpm->baseVersion.edition.version());
658   _pimpl->insert_deltarpm_cmd->bind(":baseversion_release", drpm->baseVersion.edition.release());
659   _pimpl->insert_deltarpm_cmd->bind(":baseversion_epoch", (int) drpm->baseVersion.edition.epoch());
660   _pimpl->insert_deltarpm_cmd->bind(":baseversion_build_time", drpm->baseVersion.buildTime.asSeconds());
661   _pimpl->insert_deltarpm_cmd->bind(":baseversion_checksum", drpm->baseVersion.checkSum.checksum());
662   _pimpl->insert_deltarpm_cmd->bind(":baseversion_sequence_info", drpm->baseVersion.sequenceInfo);
663
664   _pimpl->insert_deltarpm_cmd->executenonquery();
665   id = _pimpl->con.insertid();
666
667   return id;
668 }
669
670
671 // RecordId CacheStore::appendDependencyEntry( const RecordId &resolvable_id, zypp::Dep deptype, const Resolvable::Kind &refers )
672 // {
673 //   //DBG << "rid: " << resolvable_id << " deptype: " << deptype << " " << "refers: " << refers << endl;
674 //   _pimpl->insert_dependency_entry_cmd->bind( ":resolvable_id", resolvable_id );
675 //
676 //   db::DependencyType dt = zypp_deptype2db_deptype(deptype);
677 //   if ( dt == db::DEP_TYPE_UNKNOWN )
678 //   {
679 //     ZYPP_THROW(Exception("Unknown depenency type"));
680 //   }
681 //
682 //   _pimpl->insert_dependency_entry_cmd->bind( ":dependency_type", zypp_deptype2db_deptype(deptype) );
683 //   _pimpl->insert_dependency_entry_cmd->bind( ":refers_kind", zypp_kind2db_kind(refers) );
684 //
685 //   _pimpl->insert_dependency_entry_cmd->executenonquery();
686 //   //delete cmd;
687 //   long long id = _pimpl->con.insertid();
688 //   return static_cast<RecordId>(id);
689 // }
690
691 RecordId CacheStore::lookupOrAppendFile( const Pathname &path )
692 {
693   RecordId dir_name_id = lookupOrAppendDirName(path.dirname().asString());
694   RecordId file_name_id = lookupOrAppendFileName(path.basename());
695
696   _pimpl->select_file_cmd->bind(":dir_name_id", dir_name_id);
697   _pimpl->select_file_cmd->bind(":file_name_id", file_name_id);
698   long long id = 0;
699
700   try
701   {
702     sqlite3_reader reader= _pimpl->select_file_cmd->executereader();
703     if (!reader.read())
704     {
705       // does not exist
706       _pimpl->insert_file_cmd->bind(":dir_name_id", dir_name_id);
707       _pimpl->insert_file_cmd->bind(":file_name_id", file_name_id);
708       _pimpl->insert_file_cmd->executenonquery();
709       id = _pimpl->con.insertid();
710       return id;
711    }
712    return reader.getint64(0);
713   }
714   catch ( const sqlite3x::database_error &e )
715   {
716     ZYPP_RETHROW(e);
717   }
718   return id;
719 }
720
721 void CacheStore::updateRepository( const RecordId &id,
722                                    const string &checksum,
723                                    const Date &timestamp )
724 {
725   _pimpl->update_repository_cmd->bind(":repository_id", id);
726   _pimpl->update_repository_cmd->bind(":checksum", checksum);
727   _pimpl->update_repository_cmd->bind(":timestamp", static_cast<int>((Date::ValueType) timestamp) );
728   _pimpl->insert_repository_cmd->executenonquery();
729 }
730
731 RecordId CacheStore::lookupOrAppendRepository( const string &alias )
732 {
733   _pimpl->select_repository_cmd->bind(":alias", alias);
734   long long id = 0;
735   try
736   {
737     sqlite3_reader reader= _pimpl->select_repository_cmd->executereader();
738     if (!reader.read())
739     {
740       // does not exist
741       _pimpl->insert_repository_cmd->bind(":alias", alias);
742       _pimpl->insert_repository_cmd->bind(":timestamp", static_cast<int>((Date::ValueType) Date::now()) );
743       _pimpl->insert_repository_cmd->executenonquery();
744       id = _pimpl->con.insertid();
745       return id;
746    }
747    return reader.getint64(0);
748   }
749   catch ( const sqlite3x::database_error &e )
750   {
751     ZYPP_RETHROW(e);
752   }
753   return id;
754 }
755
756 void CacheStore::cleanRepository( const data::RecordId &id,
757                                   const ProgressData::ReceiverFnc & progressrcv )
758 {
759   sqlite3_command cmd( _pimpl->con, "delete from repositories where id=:id");
760   cmd.bind(":id", id);
761
762   try
763   {
764     cmd.executenonquery();
765   }
766   catch ( const sqlite3x::database_error &e )
767   {
768     ZYPP_THROW(CacheRecordNotFoundException());
769   }
770 }
771
772 void CacheStore::cleanRepository( const std::string &alias,
773                                   const ProgressData::ReceiverFnc & progressrcv )
774 {
775   cleanRepository(lookupRepository(alias), progressrcv);
776 }
777
778 RepoStatus CacheStore::repositoryStatus( const data::RecordId &id )
779 {
780   sqlite3_command cmd( _pimpl->con, "select id,alias,checksum,timestamp from repositories where id=:id");
781   cmd.bind(":id", id);
782
783   try
784   {
785     sqlite3_reader reader = cmd.executereader();
786     RepoStatus status;
787     if ( reader.read() )
788     {
789       status.setChecksum( reader.getstring(2) );
790       status.setTimestamp( reader.getstring(3) );
791     }
792     return status;
793   }
794   catch ( const sqlite3x::database_error &e )
795   {
796     ZYPP_THROW(CacheRecordNotFoundException());
797   }
798 }
799
800 RepoStatus CacheStore::repositoryStatus( const string &alias )
801 {
802   return repositoryStatus(lookupRepository(alias));
803 }
804
805 bool CacheStore::isCached( const string &alias )
806 {
807   sqlite3_command cmd(_pimpl->con, "select id from repositories where alias=:alias;");
808   cmd.bind(":alias", alias);
809   try
810   {
811     sqlite3_reader reader= cmd.executereader();
812     if (!reader.read())
813     {
814       return false;
815    }
816    return true;
817   }
818   catch ( const sqlite3x::database_error &e )
819   {
820     ZYPP_RETHROW(e);
821   }
822   return false;
823 }
824
825 RecordId CacheStore::lookupRepository( const string &alias )
826 {
827   long long id = 0;
828   sqlite3_command cmd(_pimpl->con, "select id from repositories where alias=:alias;");
829   cmd.bind(":alias", alias);
830   try
831   {
832     sqlite3_reader reader= cmd.executereader();
833     if (!reader.read())
834     {
835       // does not exist
836       ZYPP_THROW(CacheRecordNotFoundException());
837    }
838    return reader.getint64(0);
839   }
840   catch ( const sqlite3x::database_error &e )
841   {
842     ZYPP_RETHROW(e);
843   }
844   return id;
845 }
846
847 RecordId CacheStore::lookupOrAppendType( const string &klass, const string &name )
848 {
849   pair<string, string> thetype = make_pair(klass,name);
850   if ( _pimpl->type_cache.find(thetype) != _pimpl->type_cache.end() )
851   {
852     //_pimpl->name_cache_hits++;
853     return _pimpl->type_cache[thetype];
854   }
855
856   _pimpl->select_type_cmd->bind(":class", klass);
857   _pimpl->select_type_cmd->bind(":name", name);
858   long long id = 0;
859   try
860   {
861     sqlite3_reader reader= _pimpl->select_type_cmd->executereader();
862     if (!reader.read())
863     {
864       // does not exist
865       _pimpl->insert_type_cmd->bind(":class", klass);
866       _pimpl->insert_type_cmd->bind(":name", name);
867       _pimpl->insert_type_cmd->executenonquery();
868       id = _pimpl->con.insertid();
869       _pimpl->type_cache[thetype] = id;
870       return id;
871    }
872    return reader.getint64(0);
873   }
874   catch ( const sqlite3x::database_error &e )
875   {
876     ZYPP_RETHROW(e);
877   }
878   return id;
879 }
880
881 RecordId CacheStore::lookupOrAppendName( const string &name )
882 {
883   if ( _pimpl->name_cache.find(name) != _pimpl->name_cache.end() )
884   {
885     _pimpl->name_cache_hits++;
886     return _pimpl->name_cache[name];
887   }
888   long long id = 0;
889   try
890   {
891     _pimpl->select_name_cmd->bind(":name", name);
892     sqlite3_reader reader= _pimpl->select_name_cmd->executereader();
893     if (!reader.read())
894     {
895       // does not exist
896       _pimpl->insert_name_cmd->bind(":name", name);
897       _pimpl->insert_name_cmd->executenonquery();
898       id = _pimpl->con.insertid();
899       _pimpl->name_cache[name] = id;
900       return id;
901    }
902    return reader.getint64(0);
903   }
904   catch ( const sqlite3x::database_error &e )
905   {
906     ZYPP_RETHROW(e);
907   }
908   return id;
909 }
910
911 RecordId CacheStore::lookupOrAppendDirName( const string &name )
912 {
913   long long id = 0;
914   try
915   {
916     _pimpl->select_dirname_cmd->bind(":name", name);
917     sqlite3_reader reader= _pimpl->select_dirname_cmd->executereader();
918     if (!reader.read())
919     {
920       // does not exist
921       _pimpl->insert_dirname_cmd->bind(":name", name);
922       _pimpl->insert_dirname_cmd->executenonquery();
923       id = _pimpl->con.insertid();
924       return id;
925    }
926    return reader.getint64(0);
927   }
928   catch ( const sqlite3x::database_error &e )
929   {
930     ZYPP_RETHROW(e);
931   }
932   return id;
933 }
934
935 RecordId CacheStore::lookupOrAppendFileName( const string &name )
936 {
937   long long id = 0;
938   try
939   {
940     _pimpl->select_filename_cmd->bind(":name", name);
941     sqlite3_reader reader= _pimpl->select_filename_cmd->executereader();
942     if (!reader.read())
943     {
944       // does not exist
945       _pimpl->insert_filename_cmd->bind(":name", name);
946       _pimpl->insert_filename_cmd->executenonquery();
947       id = _pimpl->con.insertid();
948       return id;
949    }
950    return reader.getint64(0);
951   }
952   catch ( const sqlite3x::database_error &e )
953   {
954     ZYPP_RETHROW(e);
955   }
956   return id;
957 }
958
959 void CacheStore::setSharedData( const data::RecordId &resolvable_id,
960                                 const data::RecordId &shared_id )
961 {
962   _pimpl->set_shared_flag_cmd->bind(":resolvable_id", resolvable_id);
963
964   if ( shared_id == data::noRecordId )
965    _pimpl->set_shared_flag_cmd->bind(":shared_id");
966   else
967    _pimpl->set_shared_flag_cmd->bind(":shared_id", shared_id);
968
969   _pimpl->set_shared_flag_cmd->executenonquery();
970 }
971
972 void CacheStore::appendBooleanAttribute( const data::RecordId & resolvable_id,
973                                          const std::string & klass,
974                                          const std::string & name,
975                                          bool value)
976 {
977   RecordId type_id = lookupOrAppendType( klass, name );
978   appendNumericAttribute( resolvable_id, type_id, value ? 1 : 0 );
979 }
980
981 void CacheStore::appendNumericAttribute( const data::RecordId &resolvable_id,
982                                          const std::string &klass,
983                                          const std::string &name,
984                                          int value )
985 {
986   RecordId type_id = lookupOrAppendType( klass, name );
987   appendNumericAttribute( resolvable_id, type_id, value );
988 }
989
990 void CacheStore::appendNumericAttribute( const RecordId &resolvable_id,
991                                          const RecordId &type_id,
992                                          int value )
993 {
994   // weak resolvable_id
995   _pimpl->append_num_attribute_cmd->bind(":rid", resolvable_id );
996   _pimpl->append_num_attribute_cmd->bind(":attr_id", type_id );
997
998   _pimpl->append_num_attribute_cmd->bind(":value", value );
999
1000   _pimpl->append_num_attribute_cmd->executenonquery();
1001 }
1002
1003
1004 void CacheStore::appendTranslatedStringAttribute( const data::RecordId &resolvable_id,
1005                                                   const std::string &klass,
1006                                                   const std::string &name,
1007                                                   const TranslatedText &text )
1008 {
1009   set<Locale> locales = text.locales();
1010   for ( set<Locale>::const_iterator it = locales.begin(); it != locales.end(); ++it )
1011   {
1012     appendStringAttributeTranslation( resolvable_id, *it, klass, name, text.text(*it) );
1013   }
1014 }
1015
1016
1017 void CacheStore::appendStringAttributeTranslation( const data::RecordId &resolvable_id,
1018                                                    const Locale &locale,
1019                                                    const std::string &klass,
1020                                                    const std::string &name,
1021                                                    const std::string &text )
1022 {
1023   // don't bother with writing if the string is empty
1024   if (text.empty()) return;
1025
1026   RecordId lang_id = lookupOrAppendType("lang",
1027       locale.code().empty() ? "none" : locale.code() );
1028   RecordId type_id = lookupOrAppendType( klass, name );
1029   appendStringAttribute( resolvable_id, lang_id, type_id, text );
1030 }
1031
1032 void CacheStore::appendStringAttribute( const data::RecordId &resolvable_id,
1033                                         const std::string &klass,
1034                                         const std::string &name,
1035                                         const std::string &value )
1036 {
1037   // don't bother with writing if the string is empty
1038   if (value.empty()) return;
1039
1040   RecordId type_id = lookupOrAppendType(klass, name);
1041   appendStringAttribute( resolvable_id, type_id, value );
1042 }
1043
1044 void CacheStore::appendStringAttribute( const RecordId &resolvable_id,
1045                                         const RecordId &type_id,
1046                                         const std::string &value )
1047 {
1048   // don't bother with writing if the string is empty
1049   if (value.empty()) return;
1050
1051   RecordId lang_id = lookupOrAppendType("lang", "none");
1052   appendStringAttribute( resolvable_id, lang_id, type_id, value );
1053 }
1054
1055 void CacheStore::appendStringAttribute( const RecordId &resolvable_id,
1056                             const RecordId &lang_id,
1057                             const RecordId &type_id,
1058                             const string &value )
1059 {
1060   // don't bother with writing if the string is empty
1061   if (value.empty()) return;
1062
1063   // weak resolvable_id
1064   _pimpl->append_text_attribute_cmd->bind(":rid", resolvable_id );
1065   _pimpl->append_text_attribute_cmd->bind(":lang_id", lang_id );
1066   _pimpl->append_text_attribute_cmd->bind(":attr_id", type_id );
1067
1068   _pimpl->append_text_attribute_cmd->bind(":text", value );
1069
1070   _pimpl->append_text_attribute_cmd->executenonquery();
1071 }
1072
1073 }
1074 }
1075