- use a saner way to detect no records found
[platform/upstream/libzypp.git] / zypp / cache / ResolvableQuery.cc
1 #include <iterator>
2 #include <algorithm>
3
4 #include "zypp/cache/CacheTypes.h"
5 #include "zypp/cache/ResolvableQuery.h"
6 #include "zypp/Package.h"
7 #include "zypp/cache/sqlite3x/sqlite3x.hpp"
8
9 using namespace sqlite3x;
10 using namespace std;
11
12 namespace zypp { namespace cache {
13
14
15 struct ResolvableQuery::Impl
16 {
17   Pathname _dbdir;
18   string _fields;
19   CacheTypes _type_cache;
20   
21   Impl( const Pathname &dbdir)
22   : _dbdir(dbdir)
23     , _type_cache(dbdir)
24   {
25     _fields = "id, name, version, release, epoch, arch, kind, installed_size, archive_size, install_only, build_time, install_time, repository_id";
26   }
27
28   ~Impl()
29   {
30   }
31
32   data::ResObject_Ptr fromRow( sqlite3_reader &reader )
33   {
34     data::ResObject_Ptr ptr (new data::ResObject);
35
36     ptr->name = reader.getstring(1);
37     ptr->edition = Edition( reader.getstring(2), reader.getstring(3), reader.getint(4));
38     ptr->arch = _type_cache.archFor(reader.getint(5));
39
40     // TODO get the rest of the data
41
42     return ptr;
43   }
44
45   
46   void query( const data::RecordId &id,
47                   ProcessResolvable fnc )
48   {
49     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
50     //con.executenonquery("PRAGMA cache_size=8000;");
51     con.executenonquery("BEGIN;");
52     sqlite3_command cmd( con, "select " + _fields + " from resolvables where id=:id;");
53     cmd.bind(":id", id);
54     sqlite3_reader reader = cmd.executereader();
55     while(reader.read())
56     {
57       fnc( id, fromRow(reader) );
58     }
59     con.executenonquery("COMMIT;");
60   }
61
62
63   void query( const std::string &s,
64               ProcessResolvable fnc  )
65   {  
66     
67     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
68     //con.executenonquery("PRAGMA cache_size=8000;");
69     con.executenonquery("BEGIN;");
70     sqlite3_command cmd( con, "select " + _fields + " from resolvables where name like '%:name%';");
71     cmd.bind(":name", s);
72     sqlite3_reader reader = cmd.executereader();
73     while(reader.read())
74     {
75       fnc( reader.getint64(0), fromRow(reader) );
76     }
77     con.executenonquery("COMMIT;");
78   }
79
80
81   std::string queryStringAttribute( const data::RecordId &record_id,
82                                     const std::string &klass,
83                                     const std::string &name,
84                                     const std::string &default_value )
85   {
86     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
87     try {
88       return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name, default_value);
89     }
90     catch ( const Exception &e )
91     {
92       ZYPP_RETHROW(e);
93     }
94   }
95
96
97   std::string queryStringAttributeTranslation( const data::RecordId &record_id,
98                                                const Locale &locale,
99                                                const std::string &klass,
100                                                const std::string &name,
101                                                const std::string &default_value )
102   {
103     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
104     try {
105       return queryStringAttributeTranslationInternal( con, record_id, locale, klass, name, default_value );
106     }
107     catch ( const Exception &e )
108     {
109       ZYPP_RETHROW(e);
110     }
111   }
112
113
114   TranslatedText queryTranslatedStringAttribute( const data::RecordId &record_id,
115                                                  const std::string &klass,
116                                                  const std::string &name,
117                                                  const TranslatedText &default_value )
118   {
119     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
120     try {
121       return queryTranslatedStringAttributeInternal( con, record_id, klass, name, default_value );
122     }
123     catch ( const Exception &e )
124     {
125       ZYPP_RETHROW(e);
126     }
127   }
128
129
130   bool queryBooleanAttribute( const data::RecordId &record_id,
131                               const std::string &klass,
132                               const std::string &name,
133                               bool default_value )
134   {
135     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
136     try {
137       return queryNumericAttributeInternal( con, record_id, klass, name, default_value);
138     }
139     catch ( const Exception &e )
140     {
141       ZYPP_RETHROW(e);
142     }
143   }
144       
145   int queryNumericAttribute( const data::RecordId &record_id,
146                              const std::string &klass,
147                              const std::string &name,
148                              int default_value )
149   {
150     sqlite3_connection con((_dbdir + "zypp.db").asString().c_str());
151     try {
152       return queryNumericAttributeInternal( con, record_id, klass, name, default_value);
153     }
154     catch ( const Exception &e )
155     {
156       ZYPP_RETHROW(e);
157     }
158   }
159
160 private:
161
162   int queryNumericAttributeInternal( sqlite3_connection &con,
163                                      const data::RecordId &record_id,
164                                      const std::string &klass,
165                                      const std::string &name,
166                                      int default_value )
167   {
168     con.executenonquery("BEGIN;");
169     sqlite3_command cmd( 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;");
170
171     cmd.bind(":rid", record_id);
172
173     cmd.bind(":tclass", klass);
174     cmd.bind(":tname", name);
175
176     sqlite3_reader reader = cmd.executereader();
177     if ( reader.read() )
178       return reader.getint(0);
179     else
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     sqlite3_command cmd( 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;");
192
193     cmd.bind(":rid", record_id);
194     cmd.bind(":lclass", "lang");
195
196     cmd.bind(":tclass", klass);
197     cmd.bind(":tname", name);
198
199     TranslatedText result;
200     sqlite3_reader reader = cmd.executereader();
201     if ( reader.read() )
202     {
203       result.setText( reader.getstring(0), Locale( reader.getstring(1) ) );
204       return result;
205     }
206     else
207       return default_value;
208   }
209
210   std::string queryStringAttributeInternal( sqlite3_connection &con,
211                                             const data::RecordId &record_id,
212                                             const std::string &klass,
213                                             const std::string &name,
214                                             const std::string &default_value )
215   {
216     return queryStringAttributeTranslationInternal( con, record_id, Locale(), klass, name, default_value);
217   }
218
219   std::string queryStringAttributeTranslationInternal( sqlite3_connection &con,
220                                                        const data::RecordId &record_id,
221                                                        const Locale &locale,
222                                                        const std::string &klass,
223                                                        const std::string &name,
224                                                        const std::string &default_value )
225   {
226     //con.executenonquery("PRAGMA cache_size=8000;");
227     con.executenonquery("BEGIN;");
228     sqlite3_command cmd( 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;");
229
230     cmd.bind(":rid", record_id);
231     cmd.bind(":lclass", "lang");
232     if (locale == Locale() )
233       cmd.bind(":lname", "none");
234     else
235       cmd.bind(":lname", locale.code());
236
237     cmd.bind(":tclass", klass);
238     cmd.bind(":tname", name);
239
240     sqlite3_reader reader = cmd.executereader();
241     if ( reader.read() )
242       return reader.getstring(0);
243     else
244       return default_value;
245   }
246 };
247
248 //////////////////////////////////////////////////////////////////////////////
249 // FORWARD TO IMPLEMENTATION
250 //////////////////////////////////////////////////////////////////////////////
251
252 ResolvableQuery::ResolvableQuery( const Pathname &dbdir)
253   : _pimpl(new Impl(dbdir))
254 {
255 }
256
257 //////////////////////////////////////////////////////////////////////////////
258
259 void ResolvableQuery::query( const data::RecordId &id, ProcessResolvable fnc  )
260 {
261   _pimpl->query(id, fnc);
262 }
263
264 //////////////////////////////////////////////////////////////////////////////
265
266 void ResolvableQuery::query( const std::string &s, ProcessResolvable fnc  )
267 {
268   _pimpl->query(s, fnc);
269 }
270
271 //////////////////////////////////////////////////////////////////////////////
272
273 int ResolvableQuery::queryNumericAttribute( const data::RecordId &record_id,
274                                             const std::string &klass,
275                                             const std::string &name,
276                                             int default_value )
277 {
278   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
279 }
280
281 bool ResolvableQuery::queryBooleanAttribute( const data::RecordId &record_id,
282                                              const std::string &klass,
283                                              const std::string &name,
284                                              bool default_value )
285 {
286   return _pimpl->queryNumericAttribute(record_id, klass, name, default_value);
287 }
288
289
290 std::string ResolvableQuery::queryStringAttribute( const data::RecordId &record_id,
291                                                    const std::string &klass,
292                                                    const std::string &name,
293                                                    const std::string &default_value )
294 {
295   return _pimpl->queryStringAttribute(record_id, klass, name, default_value);
296 }
297
298 //////////////////////////////////////////////////////////////////////////////
299
300 std::string ResolvableQuery::queryStringAttributeTranslation( const data::RecordId &record_id,
301                                                               const Locale &locale,
302                                                               const std::string &klass,
303                                                               const std::string &name,
304                                                               const std::string &default_value )
305 {
306   return _pimpl->queryStringAttributeTranslation(record_id, locale, klass, name, default_value );
307 }
308
309 //////////////////////////////////////////////////////////////////////////////
310
311 TranslatedText ResolvableQuery::queryTranslatedStringAttribute( const data::RecordId &record_id,
312                                                                 const std::string &klass,
313                                                                 const std::string &name,
314                                                                 const TranslatedText &default_value )
315 {
316   return _pimpl->queryTranslatedStringAttribute(record_id, klass, name, default_value );
317 }
318
319 //////////////////////////////////////////////////////////////////////////////
320
321 } } // namespace zypp::cache