fix the sqlite3_bind() for query-by-name, the wildcards '%'
[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_connection con((_dbdir + "zypp.db").asString().c_str());
72     //con.executenonquery("PRAGMA cache_size=8000;");
73     con.executenonquery("BEGIN;");
74     sqlite3_command cmd( con, "select " + _fields + " from resolvables where id=:id;");
75     cmd.bind(":id", id);
76     sqlite3_reader reader = cmd.executereader();
77     while(reader.read())
78     {
79       fnc( id, fromRow(reader) );
80     }
81     con.executenonquery("COMMIT;");
82   }
83
84
85   void query( const std::string &s,
86               ProcessResolvable fnc  )
87   {  
88     
89     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
90     //con.executenonquery("PRAGMA cache_size=8000;");
91     con.executenonquery("BEGIN;");
92     sqlite3_command cmd( con, "select " + _fields + " from resolvables where name like :name;");
93     cmd.bind(":name", string("%") + s + "%");
94     sqlite3_reader reader = cmd.executereader();
95     while(reader.read())
96     {
97       fnc( reader.getint64(0), fromRow(reader) );
98     }
99     con.executenonquery("COMMIT;");
100   }
101
102
103   std::string queryStringAttribute( const data::RecordId &record_id,
104                                     const std::string &klass,
105                                     const std::string &name,
106                                     const std::string &default_value )
107   {
108     string value;
109     return queryStringAttributeTranslationInternal( _con, record_id, Locale(), klass, name, default_value);
110   }
111
112
113   std::string queryStringAttributeTranslation( const data::RecordId &record_id,
114                                                const Locale &locale,
115                                                const std::string &klass,
116                                                const std::string &name,
117                                                const std::string &default_value )
118   {
119     return queryStringAttributeTranslationInternal( _con, record_id, locale, klass, name, default_value );
120   }
121
122
123   TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id,
124                                                  const std::string &klass,
125                                                  const std::string &name,
126                                                  const TranslatedText &default_value )
127   {
128     return queryTranslatedStringAttributeInternal( _con, record_id, klass, name, default_value );
129   }
130
131
132   bool queryBooleanAttribute( const data::RecordId &record_id,
133                               const std::string &klass,
134                               const std::string &name,
135                               bool default_value )
136   {
137     return ( queryNumericAttributeInternal( _con, record_id, klass, name, default_value) > 0 );
138   }
139       
140   int queryNumericAttribute( const data::RecordId &record_id,
141                              const std::string &klass,
142                              const std::string &name,
143                              int default_value )
144   {
145     return queryNumericAttributeInternal( _con, record_id, klass, name, default_value);
146   }
147
148   void queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
149   {
150     _cmd_disk_usage->bind(":rid", record_id);
151     sqlite3_reader reader = _cmd_disk_usage->executereader();
152
153     while ( reader.read() )
154     {
155       DiskUsage::Entry entry(reader.getstring(0),
156                              reader.getint(1),
157                              reader.getint(2) );
158       du.add(entry);
159     }
160   }
161   
162 private:
163
164   int queryNumericAttributeInternal( sqlite3_connection &con,
165                                      const data::RecordId &record_id,
166                                      const std::string &klass,
167                                      const std::string &name,
168                                      int default_value )
169   {
170     //con.executenonquery("BEGIN;");
171     _cmd_attr_num->bind(":rid", record_id);
172
173     _cmd_attr_num->bind(":tclass", klass);
174     _cmd_attr_num->bind(":tname", name);
175
176     sqlite3_reader reader = _cmd_attr_num->executereader();
177     if ( reader.read() )
178       return reader.getint(0);
179
180     return default_value;
181   }
182   
183   TranslatedText queryTranslatedStringAttributeInternal( sqlite3_connection &con,
184                                                          const data::RecordId &record_id,
185                                                          const std::string &klass,
186                                                          const std::string &name,
187                                                          const TranslatedText &default_value )
188   {
189     //con.executenonquery("PRAGMA cache_size=8000;");
190     //con.executenonquery("BEGIN;");
191
192     _cmd_attr_tstr->bind(":rid", record_id);
193     _cmd_attr_tstr->bind(":lclass", "lang");
194
195     _cmd_attr_tstr->bind(":tclass", klass);
196     _cmd_attr_tstr->bind(":tname", name);
197
198     TranslatedText result;
199     sqlite3_reader reader = _cmd_attr_tstr->executereader();
200     
201     int c = 0;
202     while(reader.read())
203     {
204       result.setText( reader.getstring(0), Locale( reader.getstring(1) ) );
205       c++;
206     }
207
208     if ( c>0 )
209       return result;
210     
211     return default_value;
212   }
213
214   std::string queryStringAttributeInternal( sqlite3_connection &con,
215                                             const data::RecordId &record_id,
216                                             const std::string &klass,
217                                             const std::string &name,
218                                             const std::string &default_value )
219   {
220     return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name, default_value );
221   }
222
223   std::string queryStringAttributeTranslationInternal( sqlite3_connection &con,
224                                                        const data::RecordId &record_id,
225                                                        const Locale &locale,
226                                                        const std::string &klass,
227                                                        const std::string &name,
228                                                         const std::string &default_value )
229   {
230     //con.executenonquery("BEGIN;");
231     _cmd_attr_str->bind(":rid", record_id);
232     _cmd_attr_str->bind(":lclass", "lang");
233     if (locale == Locale() )
234       _cmd_attr_str->bind(":lname", "none");
235     else
236       _cmd_attr_str->bind(":lname", locale.code());
237
238     _cmd_attr_str->bind(":tclass", klass);
239     _cmd_attr_str->bind(":tname", name);
240
241     sqlite3_reader reader = _cmd_attr_str->executereader();
242     
243     if ( reader.read() )
244       return reader.getstring(0);
245     
246     return default_value;
247   }
248 };
249
250 //////////////////////////////////////////////////////////////////////////////
251 // FORWARD TO IMPLEMENTATION
252 //////////////////////////////////////////////////////////////////////////////
253
254 ResolvableQuery::ResolvableQuery( const Pathname &dbdir)
255   : _pimpl(new Impl(dbdir))
256 {
257   //MIL << "Creating Resolvable query" << endl;
258 }
259
260 ResolvableQuery::~ResolvableQuery()
261 {
262   //MIL << "Destroying Resolvable query" << endl;
263 }
264
265 //////////////////////////////////////////////////////////////////////////////
266
267 void ResolvableQuery::query( const data::RecordId &id, ProcessResolvable fnc  )
268 {
269   _pimpl->query(id, fnc);
270 }
271
272 //////////////////////////////////////////////////////////////////////////////
273
274 void ResolvableQuery::query( const std::string &s, ProcessResolvable fnc  )
275 {
276   _pimpl->query(s, fnc);
277 }
278
279 //////////////////////////////////////////////////////////////////////////////
280
281 int ResolvableQuery::queryNumericAttribute( const data::RecordId &record_id,
282                                             const std::string &klass,
283                                             const std::string &name,
284                                             int default_value )
285 {
286   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
287 }
288
289 bool ResolvableQuery::queryBooleanAttribute( const data::RecordId &record_id,
290                                              const std::string &klass,
291                                              const std::string &name,
292                                              bool default_value )
293 {
294   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
295 }
296
297
298 std::string ResolvableQuery::queryStringAttribute( const data::RecordId &record_id,
299                                                    const std::string &klass,
300                                                    const std::string &name,
301                                                    const std::string &default_value )
302 {
303   return _pimpl->queryStringAttribute(record_id, klass, name, default_value);
304 }
305
306 //////////////////////////////////////////////////////////////////////////////
307
308 std::string ResolvableQuery::queryStringAttributeTranslation( const data::RecordId &record_id,
309                                                               const Locale &locale,
310                                                               const std::string &klass,
311                                                               const std::string &name,
312                                                               const std::string &default_value )
313 {
314   return _pimpl->queryStringAttributeTranslation(record_id, locale, klass, name, default_value );
315 }
316
317 //////////////////////////////////////////////////////////////////////////////
318
319 TranslatedText ResolvableQuery::queryTranslatedStringAttribute( const data::RecordId &record_id,
320                                                                 const std::string &klass,
321                                                                 const std::string &name,
322                                                                 const TranslatedText &default_value )
323 {
324   return _pimpl->queryTranslatedStringAttribute(record_id, klass, name, default_value );
325 }
326
327 void ResolvableQuery::queryDiskUsage( const data::RecordId &record_id, DiskUsage &du )
328 {
329   _pimpl->queryDiskUsage(record_id, du);
330 }
331
332 //////////////////////////////////////////////////////////////////////////////
333
334 } } // namespace zypp::cache