- fix ResolvableQuery::query(), add ResolvableQuery::queryByName()
[platform/upstream/libzypp.git] / zypp / cache / ResolvableQuery.cc
1 #include <iterator>
2 #include <algorithm>
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"
9
10 using namespace sqlite3x;
11 using namespace std;
12 using namespace zypp;
13
14 typedef shared_ptr<sqlite3_command> sqlite3_command_ptr;
15
16 namespace zypp { namespace cache {
17
18 struct ResolvableQuery::Impl
19 {
20   Pathname _dbdir;
21   string _fields;
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
29   Impl( const Pathname &dbdir)
30   : _dbdir(dbdir)
31   , _type_cache(dbdir)
32   {
33     _con.open((dbdir + "zypp.db").asString().c_str());
34     _con.executenonquery("PRAGMA cache_size=8000;");
35
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;") );
37
38
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;"));
40
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;"));
42
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;"));
44     
45     MIL << "Creating Resolvable query impl" << endl;
46     _fields = "id, name, version, release, epoch, arch, kind, installed_size, archive_size, install_only, build_time, install_time, repository_id";
47   }
48
49   ~Impl()
50   {
51       MIL << "Destroying Resolvable query impl" << endl;
52   }
53
54   data::ResObject_Ptr fromRow( sqlite3_reader &reader )
55   {
56     data::ResObject_Ptr ptr (new data::ResObject);
57
58     ptr->name = reader.getstring(1);
59     ptr->edition = Edition( reader.getstring(2), reader.getstring(3), reader.getint(4));
60     ptr->arch = _type_cache.archFor(reader.getint(5));
61
62     // TODO get the rest of the data
63
64     return ptr;
65   }
66
67   
68   void query( const data::RecordId &id,
69                   ProcessResolvable fnc )
70   {
71     sqlite3_command cmd( _con, "select " + _fields + " from resolvables where id=:id;");
72     cmd.bind(":id", id);
73     sqlite3_reader reader = cmd.executereader();
74     while(reader.read())
75     {
76       fnc( id, fromRow(reader) );
77     }
78   }
79
80
81   void query( const std::string &s,
82               ProcessResolvable fnc  )
83   {  
84     
85     sqlite3_command cmd( _con, "select " + _fields + " from resolvables where name like :name;");
86     cmd.bind(":name", string("%") + s + "%");
87     sqlite3_reader reader = cmd.executereader();
88     while(reader.read())
89     {
90       fnc( reader.getint64(0), fromRow(reader) );
91     }
92   }
93
94   void queryByName( const std::string &name, int wild, ProcessResolvable fnc  )
95   {
96     std::string sqlcmd = "select " + _fields + " from resolvables where name ";
97     std::string s( name );
98     if (wild == 0)
99     {
100       sqlcmd += "=";
101     }
102     else
103     {
104       sqlcmd += "like";
105     }
106     sqlite3_command cmd( _con, sqlcmd + " :name;");
107     if (wild & 1)
108       s += "%";
109     if (wild & 2)
110       s = string("%") + s;
111     cmd.bind( ":name", s );
112     sqlite3_reader reader = cmd.executereader();
113     while(reader.read())
114     {
115       fnc( reader.getint64(0), fromRow(reader) );
116     }
117   }
118
119
120   std::string queryStringAttribute( const data::RecordId &record_id,
121                                     const std::string &klass,
122                                     const std::string &name,
123                                     const std::string &default_value )
124   {
125     string value;
126     return queryStringAttributeTranslationInternal( _con, record_id, Locale(), klass, name, default_value);
127   }
128
129
130   std::string queryStringAttributeTranslation( const data::RecordId &record_id,
131                                                const Locale &locale,
132                                                const std::string &klass,
133                                                const std::string &name,
134                                                const std::string &default_value )
135   {
136     return queryStringAttributeTranslationInternal( _con, record_id, locale, klass, name, default_value );
137   }
138
139
140   TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id,
141                                                  const std::string &klass,
142                                                  const std::string &name,
143                                                  const TranslatedText &default_value )
144   {
145     return queryTranslatedStringAttributeInternal( _con, record_id, klass, name, default_value );
146   }
147
148
149   bool queryBooleanAttribute( const data::RecordId &record_id,
150                               const std::string &klass,
151                               const std::string &name,
152                               bool default_value )
153   {
154     return ( queryNumericAttributeInternal( _con, record_id, klass, name, default_value) > 0 );
155   }
156       
157   int queryNumericAttribute( const data::RecordId &record_id,
158                              const std::string &klass,
159                              const std::string &name,
160                              int default_value )
161   {
162     return queryNumericAttributeInternal( _con, record_id, klass, name, default_value);
163   }
164
165   void queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
166   {
167     _cmd_disk_usage->bind(":rid", record_id);
168     sqlite3_reader reader = _cmd_disk_usage->executereader();
169
170     while ( reader.read() )
171     {
172       DiskUsage::Entry entry(reader.getstring(0),
173                              reader.getint(1),
174                              reader.getint(2) );
175       du.add(entry);
176     }
177   }
178
179   std::string queryRepositoryAlias( const data::RecordId &repo_id )
180   {
181     std::string alias;
182     sqlite3_command cmd( _con, "select alias from repositories where id=:id;" );
183     cmd.bind( ":id", repo_id );
184     sqlite3_reader reader = cmd.executereader();
185     while( reader.read() )
186     {
187       alias = reader.getstring( 0 );
188       break;
189     }
190     return alias;
191   }
192   
193 private:
194
195   int queryNumericAttributeInternal( sqlite3_connection &con,
196                                      const data::RecordId &record_id,
197                                      const std::string &klass,
198                                      const std::string &name,
199                                      int default_value )
200   {
201     //con.executenonquery("BEGIN;");
202     _cmd_attr_num->bind(":rid", record_id);
203
204     _cmd_attr_num->bind(":tclass", klass);
205     _cmd_attr_num->bind(":tname", name);
206
207     sqlite3_reader reader = _cmd_attr_num->executereader();
208     if ( reader.read() )
209       return reader.getint(0);
210
211     return default_value;
212   }
213   
214   TranslatedText queryTranslatedStringAttributeInternal( sqlite3_connection &con,
215                                                          const data::RecordId &record_id,
216                                                          const std::string &klass,
217                                                          const std::string &name,
218                                                          const TranslatedText &default_value )
219   {
220     //con.executenonquery("PRAGMA cache_size=8000;");
221     //con.executenonquery("BEGIN;");
222
223     _cmd_attr_tstr->bind(":rid", record_id);
224     _cmd_attr_tstr->bind(":lclass", "lang");
225
226     _cmd_attr_tstr->bind(":tclass", klass);
227     _cmd_attr_tstr->bind(":tname", name);
228
229     TranslatedText result;
230     sqlite3_reader reader = _cmd_attr_tstr->executereader();
231     
232     int c = 0;
233     while(reader.read())
234     {
235       result.setText( reader.getstring(0), Locale( reader.getstring(1) ) );
236       c++;
237     }
238
239     if ( c>0 )
240       return result;
241     
242     return default_value;
243   }
244
245   std::string queryStringAttributeInternal( sqlite3_connection &con,
246                                             const data::RecordId &record_id,
247                                             const std::string &klass,
248                                             const std::string &name,
249                                             const std::string &default_value )
250   {
251     return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name, default_value );
252   }
253
254   std::string queryStringAttributeTranslationInternal( sqlite3_connection &con,
255                                                        const data::RecordId &record_id,
256                                                        const Locale &locale,
257                                                        const std::string &klass,
258                                                        const std::string &name,
259                                                         const std::string &default_value )
260   {
261     //con.executenonquery("BEGIN;");
262     _cmd_attr_str->bind(":rid", record_id);
263     _cmd_attr_str->bind(":lclass", "lang");
264     if (locale == Locale() )
265       _cmd_attr_str->bind(":lname", "none");
266     else
267       _cmd_attr_str->bind(":lname", locale.code());
268
269     _cmd_attr_str->bind(":tclass", klass);
270     _cmd_attr_str->bind(":tname", name);
271
272     sqlite3_reader reader = _cmd_attr_str->executereader();
273     
274     if ( reader.read() )
275       return reader.getstring(0);
276     
277     return default_value;
278   }
279 };
280
281 //////////////////////////////////////////////////////////////////////////////
282 // FORWARD TO IMPLEMENTATION
283 //////////////////////////////////////////////////////////////////////////////
284
285 ResolvableQuery::ResolvableQuery( const Pathname &dbdir)
286   : _pimpl(new Impl(dbdir))
287 {
288   //MIL << "Creating Resolvable query" << endl;
289 }
290
291 ResolvableQuery::~ResolvableQuery()
292 {
293   //MIL << "Destroying Resolvable query" << endl;
294 }
295
296 //////////////////////////////////////////////////////////////////////////////
297
298 void ResolvableQuery::query( const data::RecordId &id, ProcessResolvable fnc  )
299 {
300   _pimpl->query(id, fnc);
301 }
302
303 //////////////////////////////////////////////////////////////////////////////
304
305 void ResolvableQuery::query( const std::string &s, ProcessResolvable fnc  )
306 {
307   _pimpl->query(s, fnc);
308 }
309
310 //////////////////////////////////////////////////////////////////////////////
311
312 int ResolvableQuery::queryNumericAttribute( const data::RecordId &record_id,
313                                             const std::string &klass,
314                                             const std::string &name,
315                                             int default_value )
316 {
317   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
318 }
319
320 bool ResolvableQuery::queryBooleanAttribute( const data::RecordId &record_id,
321                                              const std::string &klass,
322                                              const std::string &name,
323                                              bool default_value )
324 {
325   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
326 }
327
328
329 std::string ResolvableQuery::queryStringAttribute( const data::RecordId &record_id,
330                                                    const std::string &klass,
331                                                    const std::string &name,
332                                                    const std::string &default_value )
333 {
334   return _pimpl->queryStringAttribute(record_id, klass, name, default_value);
335 }
336
337 //////////////////////////////////////////////////////////////////////////////
338
339 std::string ResolvableQuery::queryStringAttributeTranslation( const data::RecordId &record_id,
340                                                               const Locale &locale,
341                                                               const std::string &klass,
342                                                               const std::string &name,
343                                                               const std::string &default_value )
344 {
345   return _pimpl->queryStringAttributeTranslation(record_id, locale, klass, name, default_value );
346 }
347
348 //////////////////////////////////////////////////////////////////////////////
349
350 TranslatedText ResolvableQuery::queryTranslatedStringAttribute( const data::RecordId &record_id,
351                                                                 const std::string &klass,
352                                                                 const std::string &name,
353                                                                 const TranslatedText &default_value )
354 {
355   return _pimpl->queryTranslatedStringAttribute(record_id, klass, name, default_value );
356 }
357
358 void ResolvableQuery::queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
359 {
360   _pimpl->queryDiskUsage(record_id, du);
361 }
362
363 std::string ResolvableQuery::queryRepositoryAlias( const data::RecordId &repo_id )
364 {
365   return _pimpl->queryRepositoryAlias( repo_id );
366 }
367
368 void ResolvableQuery::queryByName( const std::string &name, int wild, ProcessResolvable fnc  )
369 {
370   _pimpl->queryByName( name, wild, fnc );
371 }
372
373 //////////////////////////////////////////////////////////////////////////////
374
375 } } // namespace zypp::cache