summaryrefslogtreecommitdiff
authoreilers <eilers>2005-03-20 17:47:23 (UTC)
committer eilers <eilers>2005-03-20 17:47:23 (UTC)
commit22d113c0b0dc0a9a71cb55f565c4df04272809e1 (patch) (unidiff)
tree4decc50e15c93f1c6afc9131e3124c4f11115475
parent5bc93a55c05c7292502c908fc0a99d5010a641c7 (diff)
downloadopie-22d113c0b0dc0a9a71cb55f565c4df04272809e1.zip
opie-22d113c0b0dc0a9a71cb55f565c4df04272809e1.tar.gz
opie-22d113c0b0dc0a9a71cb55f565c4df04272809e1.tar.bz2
Fixing #1608, second issue: QueryByExample-Datediff does not work properly.
This solution is not the best. I will rethink it as I have enough time. But it should work..
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiepim/ChangeLog4
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp46
2 files changed, 39 insertions, 11 deletions
diff --git a/libopie2/opiepim/ChangeLog b/libopie2/opiepim/ChangeLog
index 84517fb..acb6cb1 100644
--- a/libopie2/opiepim/ChangeLog
+++ b/libopie2/opiepim/ChangeLog
@@ -1,34 +1,36 @@
12005-03.19 Stefan Eilers <stefan@eilers-online.net> 12005-03-20 Stefan Eilers <stefan@eilers-online.net>
2 * #1608 Quickfix for problem with DateDiff on SQL backend. I have to rethink this solution, but due to the short time, this should work.
32005-03-19 Stefan Eilers <stefan@eilers-online.net>
2 * Minor update for sorted(). Now ignoring any category search if "DoNotShowWithCategory" filter is activated. 4 * Minor update for sorted(). Now ignoring any category search if "DoNotShowWithCategory" filter is activated.
3 * Fixing uninitialized member variable, caused crash of backend 5 * Fixing uninitialized member variable, caused crash of backend
42005-03-18 Stefan Eilers <stefan@eilers-online.net> 62005-03-18 Stefan Eilers <stefan@eilers-online.net>
5 * Rewrote generic sorted filter and added filter for "DoNotShowWithCategory", needed by addressbook (other filters need to be added!) 7 * Rewrote generic sorted filter and added filter for "DoNotShowWithCategory", needed by addressbook (other filters need to be added!)
62005-01-16 Stefan Eilers <stefan@eilers-online.net> 82005-01-16 Stefan Eilers <stefan@eilers-online.net>
7 * Added new OPimEventSortVector class, improved OPimSortVector 9 * Added new OPimEventSortVector class, improved OPimSortVector
8 * OPimAccessBackend now supports generic sorting. 10 * OPimAccessBackend now supports generic sorting.
92005-01-03 Stefan Eilers <stefan@eilers-online.net> 112005-01-03 Stefan Eilers <stefan@eilers-online.net>
10 * Fixing bug in API documentation 12 * Fixing bug in API documentation
11 * Moving hasQuerySettings() and querySettings() to OPimAccessTemplate to be available for all frontends 13 * Moving hasQuerySettings() and querySettings() to OPimAccessTemplate to be available for all frontends
122004-12-28 Stefan Eilers <stefan@eilers-online.net> 142004-12-28 Stefan Eilers <stefan@eilers-online.net>
13 * Make improved query by example accessable via frontend 15 * Make improved query by example accessable via frontend
14 * Some API documentation improvement 16 * Some API documentation improvement
15 * Cleanup of backend api.. 17 * Cleanup of backend api..
16 * Fixing bug #1501 18 * Fixing bug #1501
172004-11-23 Stefan Eilers <stefan@eilers-online.net> 192004-11-23 Stefan Eilers <stefan@eilers-online.net>
18 * Implement fast and full featured version of sorted() for addressbook 20 * Implement fast and full featured version of sorted() for addressbook
19 * Implement generic queryByExample for all Addressboook backends. It allows incremental search. 21 * Implement generic queryByExample for all Addressboook backends. It allows incremental search.
20 * Update of API Documentation 22 * Update of API Documentation
212004-11-18 Holger Freyther <freyther@handhelds.org> 232004-11-18 Holger Freyther <freyther@handhelds.org>
22 * Every Access can give a set of Occurrences for a period or a datetime 24 * Every Access can give a set of Occurrences for a period or a datetime
23 * QueryByExample, Find, Sort can be generically accessed by OPimBase 25 * QueryByExample, Find, Sort can be generically accessed by OPimBase
24 pointer interface 26 pointer interface
25 * OPimBackendOccurrence gets split up to OPimOccurrences by 27 * OPimBackendOccurrence gets split up to OPimOccurrences by
26 OPimTemplateBase 28 OPimTemplateBase
27 * Add safeCast to various OPimRecords 29 * Add safeCast to various OPimRecords
28 * Kill memleak in OPimTodo 30 * Kill memleak in OPimTodo
29 * Add SortVector implementations for OPimTodo and OPimContact 31 * Add SortVector implementations for OPimTodo and OPimContact
30 32
31 2004-??-??The Opie Team <opie@handhelds.org> 33 2004-??-??The Opie Team <opie@handhelds.org>
32 * Implemented some important modifications to allow to use OPimRecords as it is, without 34 * Implemented some important modifications to allow to use OPimRecords as it is, without
33 have to cast them. This makes it possible to write applications which handling pim 35 have to cast them. This makes it possible to write applications which handling pim
34 data in a generic manner (see opimconvertion tool) (eilers) \ No newline at end of file 36 data in a generic manner (see opimconvertion tool) (eilers) \ No newline at end of file
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
index 2368865..50421e2 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
@@ -38,1029 +38,1055 @@
38#include <opie2/opimdateconversion.h> 38#include <opie2/opimdateconversion.h>
39#include <opie2/osqldriver.h> 39#include <opie2/osqldriver.h>
40#include <opie2/osqlresult.h> 40#include <opie2/osqlresult.h>
41#include <opie2/osqlmanager.h> 41#include <opie2/osqlmanager.h>
42#include <opie2/osqlquery.h> 42#include <opie2/osqlquery.h>
43#include <opie2/odebug.h> 43#include <opie2/odebug.h>
44 44
45#include <qpe/global.h> 45#include <qpe/global.h>
46#include <qpe/recordfields.h> 46#include <qpe/recordfields.h>
47 47
48/* QT */ 48/* QT */
49#include <qarray.h> 49#include <qarray.h>
50#include <qdatetime.h> 50#include <qdatetime.h>
51#include <qstringlist.h> 51#include <qstringlist.h>
52 52
53 53
54using namespace Opie; 54using namespace Opie;
55using namespace Opie::DB; 55using namespace Opie::DB;
56 56
57 57
58/* 58/*
59 * Implementation of used query types * CREATE query 59 * Implementation of used query types * CREATE query
60 * LOAD query 60 * LOAD query
61 * INSERT 61 * INSERT
62 * REMOVE 62 * REMOVE
63 * CLEAR 63 * CLEAR
64 */ 64 */
65namespace { 65namespace {
66 /** 66 /**
67 * CreateQuery for the Todolist Table 67 * CreateQuery for the Todolist Table
68 */ 68 */
69 class CreateQuery : public OSQLQuery { 69 class CreateQuery : public OSQLQuery {
70 public: 70 public:
71 CreateQuery(); 71 CreateQuery();
72 ~CreateQuery(); 72 ~CreateQuery();
73 QString query()const; 73 QString query()const;
74 }; 74 };
75 75
76 /** 76 /**
77 * Clears (delete) a Table 77 * Clears (delete) a Table
78 */ 78 */
79 class ClearQuery : public OSQLQuery { 79 class ClearQuery : public OSQLQuery {
80 public: 80 public:
81 ClearQuery(); 81 ClearQuery();
82 ~ClearQuery(); 82 ~ClearQuery();
83 QString query()const; 83 QString query()const;
84 84
85 }; 85 };
86 86
87 87
88 /** 88 /**
89 * LoadQuery 89 * LoadQuery
90 * this one queries for all uids 90 * this one queries for all uids
91 */ 91 */
92 class LoadQuery : public OSQLQuery { 92 class LoadQuery : public OSQLQuery {
93 public: 93 public:
94 LoadQuery(); 94 LoadQuery();
95 ~LoadQuery(); 95 ~LoadQuery();
96 QString query()const; 96 QString query()const;
97 }; 97 };
98 98
99 /** 99 /**
100 * inserts/adds a OPimContact to the table 100 * inserts/adds a OPimContact to the table
101 */ 101 */
102 class InsertQuery : public OSQLQuery { 102 class InsertQuery : public OSQLQuery {
103 public: 103 public:
104 InsertQuery(const OPimContact& ); 104 InsertQuery(const OPimContact& );
105 ~InsertQuery(); 105 ~InsertQuery();
106 QString query()const; 106 QString query()const;
107 private: 107 private:
108 OPimContact m_contact; 108 OPimContact m_contact;
109 }; 109 };
110 110
111 111
112 /** 112 /**
113 * removes one from the table 113 * removes one from the table
114 */ 114 */
115 class RemoveQuery : public OSQLQuery { 115 class RemoveQuery : public OSQLQuery {
116 public: 116 public:
117 RemoveQuery(int uid ); 117 RemoveQuery(int uid );
118 ~RemoveQuery(); 118 ~RemoveQuery();
119 QString query()const; 119 QString query()const;
120 private: 120 private:
121 int m_uid; 121 int m_uid;
122 }; 122 };
123 123
124 /** 124 /**
125 * a find query for noncustom elements 125 * a find query for noncustom elements
126 */ 126 */
127 class FindQuery : public OSQLQuery { 127 class FindQuery : public OSQLQuery {
128 public: 128 public:
129 FindQuery(int uid); 129 FindQuery(int uid);
130 FindQuery(const UIDArray& ); 130 FindQuery(const UIDArray& );
131 ~FindQuery(); 131 ~FindQuery();
132 QString query()const; 132 QString query()const;
133 private: 133 private:
134 QString single()const; 134 QString single()const;
135 QString multi()const; 135 QString multi()const;
136 UIDArray m_uids; 136 UIDArray m_uids;
137 int m_uid; 137 int m_uid;
138 }; 138 };
139 139
140 /** 140 /**
141 * a find query for custom elements 141 * a find query for custom elements
142 */ 142 */
143 class FindCustomQuery : public OSQLQuery { 143 class FindCustomQuery : public OSQLQuery {
144 public: 144 public:
145 FindCustomQuery(int uid); 145 FindCustomQuery(int uid);
146 FindCustomQuery(const UIDArray& ); 146 FindCustomQuery(const UIDArray& );
147 ~FindCustomQuery(); 147 ~FindCustomQuery();
148 QString query()const; 148 QString query()const;
149 private: 149 private:
150 QString single()const; 150 QString single()const;
151 QString multi()const; 151 QString multi()const;
152 UIDArray m_uids; 152 UIDArray m_uids;
153 int m_uid; 153 int m_uid;
154 }; 154 };
155 155
156 156
157 157
158 // We using two tables to store the information: 158 // We using two tables to store the information:
159 // 1. addressbook : It contains General information about the contact (non custom) 159 // 1. addressbook : It contains General information about the contact (non custom)
160 // 2. custom_data : Not official supported entries 160 // 2. custom_data : Not official supported entries
161 // All tables are connected by the uid of the contact. 161 // All tables are connected by the uid of the contact.
162 // Maybe I should add a table for meta-information ? 162 // Maybe I should add a table for meta-information ?
163 CreateQuery::CreateQuery() : OSQLQuery() {} 163 CreateQuery::CreateQuery() : OSQLQuery() {}
164 CreateQuery::~CreateQuery() {} 164 CreateQuery::~CreateQuery() {}
165 QString CreateQuery::query()const { 165 QString CreateQuery::query()const {
166 QString qu; 166 QString qu;
167 167
168 qu += "create table addressbook( uid PRIMARY KEY "; 168 qu += "create table addressbook( uid PRIMARY KEY ";
169 169
170 QStringList fieldList = OPimContactFields::untrfields( false ); 170 QStringList fieldList = OPimContactFields::untrfields( false );
171 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 171 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
172 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it ); 172 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it );
173 } 173 }
174 qu += " );"; 174 qu += " );";
175 175
176 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), priority INTEGER, value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );"; 176 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), priority INTEGER, value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
177 177
178 return qu; 178 return qu;
179 } 179 }
180 180
181 ClearQuery::ClearQuery() 181 ClearQuery::ClearQuery()
182 : OSQLQuery() {} 182 : OSQLQuery() {}
183 ClearQuery::~ClearQuery() {} 183 ClearQuery::~ClearQuery() {}
184 QString ClearQuery::query()const { 184 QString ClearQuery::query()const {
185 QString qu = "drop table addressbook;"; 185 QString qu = "drop table addressbook;";
186 qu += "drop table custom_data;"; 186 qu += "drop table custom_data;";
187// qu += "drop table dates;"; 187// qu += "drop table dates;";
188 return qu; 188 return qu;
189 } 189 }
190 190
191 191
192 LoadQuery::LoadQuery() : OSQLQuery() {} 192 LoadQuery::LoadQuery() : OSQLQuery() {}
193 LoadQuery::~LoadQuery() {} 193 LoadQuery::~LoadQuery() {}
194 QString LoadQuery::query()const { 194 QString LoadQuery::query()const {
195 QString qu; 195 QString qu;
196 qu += "select uid from addressbook"; 196 qu += "select uid from addressbook";
197 197
198 return qu; 198 return qu;
199 } 199 }
200 200
201 201
202 InsertQuery::InsertQuery( const OPimContact& contact ) 202 InsertQuery::InsertQuery( const OPimContact& contact )
203 : OSQLQuery(), m_contact( contact ) { 203 : OSQLQuery(), m_contact( contact ) {
204 } 204 }
205 205
206 InsertQuery::~InsertQuery() { 206 InsertQuery::~InsertQuery() {
207 } 207 }
208 208
209 /* 209 /*
210 * converts from a OPimContact to a query 210 * converts from a OPimContact to a query
211 */ 211 */
212 QString InsertQuery::query()const{ 212 QString InsertQuery::query()const{
213 213
214 QString qu; 214 QString qu;
215 qu += "insert into addressbook VALUES( " + 215 qu += "insert into addressbook VALUES( " +
216 QString::number( m_contact.uid() ); 216 QString::number( m_contact.uid() );
217 217
218 // Get all information out of the contact-class 218 // Get all information out of the contact-class
219 // Remember: The category is stored in contactMap, too ! 219 // Remember: The category is stored in contactMap, too !
220 QMap<int, QString> contactMap = m_contact.toMap(); 220 QMap<int, QString> contactMap = m_contact.toMap();
221 221
222 QStringList fieldList = OPimContactFields::untrfields( false ); 222 QStringList fieldList = OPimContactFields::untrfields( false );
223 QMap<QString, int> translate = OPimContactFields::untrFieldsToId(); 223 QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
224 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 224 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
225 // Convert Column-String to Id and get value for this id.. 225 // Convert Column-String to Id and get value for this id..
226 // Hmmm.. Maybe not very cute solution.. 226 // Hmmm.. Maybe not very cute solution..
227 int id = translate[*it]; 227 int id = translate[*it];
228 switch ( id ){ 228 switch ( id ){
229 case Qtopia::Birthday: 229 case Qtopia::Birthday:
230 case Qtopia::Anniversary:{ 230 case Qtopia::Anniversary:{
231 QDate day; 231 QDate day;
232 if ( id == Qtopia::Birthday ){ 232 if ( id == Qtopia::Birthday ){
233 day = m_contact.birthday(); 233 day = m_contact.birthday();
234 } else { 234 } else {
235 day = m_contact.anniversary(); 235 day = m_contact.anniversary();
236 } 236 }
237 // These entries should stored in a special format 237 // These entries should stored in a special format
238 // year-month-day 238 // year-month-day
239 if ( day.isValid() ){ 239 if ( day.isValid() ){
240 qu += QString(",\"%1-%2-%3\"") 240 qu += QString(",\"%1-%2-%3\"")
241 .arg( QString::number( day.year() ).rightJustify( 4, '0' ) ) 241 .arg( QString::number( day.year() ).rightJustify( 4, '0' ) )
242 .arg( QString::number( day.month() ).rightJustify( 2, '0' ) ) 242 .arg( QString::number( day.month() ).rightJustify( 2, '0' ) )
243 .arg( QString::number( day.day() ).rightJustify( 2, '0' ) ); 243 .arg( QString::number( day.day() ).rightJustify( 2, '0' ) );
244 } else { 244 } else {
245 qu += ",\"\""; 245 qu += ",\"\"";
246 } 246 }
247 } 247 }
248 break; 248 break;
249 default: 249 default:
250 qu += QString( ",\"%1\"" ).arg( contactMap[id] ); 250 qu += QString( ",\"%1\"" ).arg( contactMap[id] );
251 } 251 }
252 } 252 }
253 qu += " );"; 253 qu += " );";
254 254
255 255
256 // Now add custom data.. 256 // Now add custom data..
257 int id = 0; 257 int id = 0;
258 id = 0; 258 id = 0;
259 QMap<QString, QString> customMap = m_contact.toExtraMap(); 259 QMap<QString, QString> customMap = m_contact.toExtraMap();
260 for( QMap<QString, QString>::Iterator it = customMap.begin(); 260 for( QMap<QString, QString>::Iterator it = customMap.begin();
261 it != customMap.end(); ++it ){ 261 it != customMap.end(); ++it ){
262 qu += "insert into custom_data VALUES(" 262 qu += "insert into custom_data VALUES("
263 + QString::number( m_contact.uid() ) 263 + QString::number( m_contact.uid() )
264 + "," 264 + ","
265 + QString::number( id++ ) 265 + QString::number( id++ )
266 + ",'" 266 + ",'"
267 + it.key() 267 + it.key()
268 + "'," 268 + "',"
269 + "0" // Priority for future enhancements 269 + "0" // Priority for future enhancements
270 + ",'" 270 + ",'"
271 + it.data() 271 + it.data()
272 + "');"; 272 + "');";
273 } 273 }
274 // qu += "commit;"; 274 // qu += "commit;";
275 odebug << "add " << qu << "" << oendl; 275 odebug << "add " << qu << "" << oendl;
276 return qu; 276 return qu;
277 } 277 }
278 278
279 279
280 RemoveQuery::RemoveQuery(int uid ) 280 RemoveQuery::RemoveQuery(int uid )
281 : OSQLQuery(), m_uid( uid ) {} 281 : OSQLQuery(), m_uid( uid ) {}
282 282
283 RemoveQuery::~RemoveQuery() {} 283 RemoveQuery::~RemoveQuery() {}
284 284
285 QString RemoveQuery::query()const { 285 QString RemoveQuery::query()const {
286 QString qu = "DELETE from addressbook where uid = " 286 QString qu = "DELETE from addressbook where uid = "
287 + QString::number(m_uid) + ";"; 287 + QString::number(m_uid) + ";";
288 qu += "DELETE from custom_data where uid = " 288 qu += "DELETE from custom_data where uid = "
289 + QString::number(m_uid) + ";"; 289 + QString::number(m_uid) + ";";
290 return qu; 290 return qu;
291 } 291 }
292 292
293 293
294 FindQuery::FindQuery(int uid) 294 FindQuery::FindQuery(int uid)
295 : OSQLQuery(), m_uid( uid ) { 295 : OSQLQuery(), m_uid( uid ) {
296 } 296 }
297 FindQuery::FindQuery(const UIDArray& ints) 297 FindQuery::FindQuery(const UIDArray& ints)
298 : OSQLQuery(), m_uids( ints ){ 298 : OSQLQuery(), m_uids( ints ){
299 } 299 }
300 FindQuery::~FindQuery() { 300 FindQuery::~FindQuery() {
301 } 301 }
302 QString FindQuery::query()const{ 302 QString FindQuery::query()const{
303 if ( m_uids.count() == 0 ) 303 if ( m_uids.count() == 0 )
304 return single(); 304 return single();
305 else 305 else
306 return multi(); 306 return multi();
307 } 307 }
308 308
309 309
310 310
311 QString FindQuery::multi()const { 311 QString FindQuery::multi()const {
312 QString qu = "select * from addressbook where"; 312 QString qu = "select * from addressbook where";
313 for (uint i = 0; i < m_uids.count(); i++ ) { 313 for (uint i = 0; i < m_uids.count(); i++ ) {
314 qu += " uid = " + QString::number( m_uids[i] ) + " OR"; 314 qu += " uid = " + QString::number( m_uids[i] ) + " OR";
315 } 315 }
316 qu.remove( qu.length()-2, 2 ); // Hmmmm.. 316 qu.remove( qu.length()-2, 2 ); // Hmmmm..
317 317
318 odebug << "find query: " << qu << "" << oendl; 318 odebug << "find query: " << qu << "" << oendl;
319 return qu; 319 return qu;
320 } 320 }
321 321
322 QString FindQuery::single()const{ 322 QString FindQuery::single()const{
323 QString qu = "select *"; 323 QString qu = "select *";
324 qu += " from addressbook where uid = " + QString::number(m_uid); 324 qu += " from addressbook where uid = " + QString::number(m_uid);
325 325
326 // owarn << "find query: " << qu << "" << oendl; 326 // owarn << "find query: " << qu << "" << oendl;
327 return qu; 327 return qu;
328 } 328 }
329 329
330 330
331 FindCustomQuery::FindCustomQuery(int uid) 331 FindCustomQuery::FindCustomQuery(int uid)
332 : OSQLQuery(), m_uid( uid ) { 332 : OSQLQuery(), m_uid( uid ) {
333 } 333 }
334 FindCustomQuery::FindCustomQuery(const UIDArray& ints) 334 FindCustomQuery::FindCustomQuery(const UIDArray& ints)
335 : OSQLQuery(), m_uids( ints ){ 335 : OSQLQuery(), m_uids( ints ){
336 } 336 }
337 FindCustomQuery::~FindCustomQuery() { 337 FindCustomQuery::~FindCustomQuery() {
338 } 338 }
339 QString FindCustomQuery::query()const{ 339 QString FindCustomQuery::query()const{
340// if ( m_uids.count() == 0 ) 340// if ( m_uids.count() == 0 )
341 return single(); 341 return single();
342 } 342 }
343 QString FindCustomQuery::single()const{ 343 QString FindCustomQuery::single()const{
344 QString qu = "select uid, type, value from custom_data where uid = "; 344 QString qu = "select uid, type, value from custom_data where uid = ";
345 qu += QString::number(m_uid); 345 qu += QString::number(m_uid);
346 return qu; 346 return qu;
347 } 347 }
348 348
349}; 349};
350 350
351 351
352/* --------------------------------------------------------------------------- */ 352/* --------------------------------------------------------------------------- */
353 353
354namespace Opie { 354namespace Opie {
355 355
356OPimContactAccessBackend_SQL::OPimContactAccessBackend_SQL ( const QString& /* appname */, 356OPimContactAccessBackend_SQL::OPimContactAccessBackend_SQL ( const QString& /* appname */,
357 const QString& filename ): 357 const QString& filename ):
358 OPimContactAccessBackend(), m_changed(false), m_driver( NULL ) 358 OPimContactAccessBackend(), m_changed(false), m_driver( NULL )
359{ 359{
360 odebug << "C'tor OPimContactAccessBackend_SQL starts" << oendl; 360 odebug << "C'tor OPimContactAccessBackend_SQL starts" << oendl;
361 QTime t; 361 QTime t;
362 t.start(); 362 t.start();
363 363
364 /* Expecting to access the default filename if nothing else is set */ 364 /* Expecting to access the default filename if nothing else is set */
365 if ( filename.isEmpty() ){ 365 if ( filename.isEmpty() ){
366 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" ); 366 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
367 } else 367 } else
368 m_fileName = filename; 368 m_fileName = filename;
369 369
370 // Get the standart sql-driver from the OSQLManager.. 370 // Get the standart sql-driver from the OSQLManager..
371 OSQLManager man; 371 OSQLManager man;
372 m_driver = man.standard(); 372 m_driver = man.standard();
373 m_driver->setUrl( m_fileName ); 373 m_driver->setUrl( m_fileName );
374 374
375 load(); 375 load();
376 376
377 odebug << "C'tor OPimContactAccessBackend_SQL ends: " << t.elapsed() << " ms" << oendl; 377 odebug << "C'tor OPimContactAccessBackend_SQL ends: " << t.elapsed() << " ms" << oendl;
378} 378}
379 379
380OPimContactAccessBackend_SQL::~OPimContactAccessBackend_SQL () 380OPimContactAccessBackend_SQL::~OPimContactAccessBackend_SQL ()
381{ 381{
382 if( m_driver ) 382 if( m_driver )
383 delete m_driver; 383 delete m_driver;
384} 384}
385 385
386bool OPimContactAccessBackend_SQL::load () 386bool OPimContactAccessBackend_SQL::load ()
387{ 387{
388 if (!m_driver->open() ) 388 if (!m_driver->open() )
389 return false; 389 return false;
390 390
391 // Don't expect that the database exists. 391 // Don't expect that the database exists.
392 // It is save here to create the table, even if it 392 // It is save here to create the table, even if it
393 // do exist. ( Is that correct for all databases ?? ) 393 // do exist. ( Is that correct for all databases ?? )
394 CreateQuery creat; 394 CreateQuery creat;
395 OSQLResult res = m_driver->query( &creat ); 395 OSQLResult res = m_driver->query( &creat );
396 396
397 update(); 397 update();
398 398
399 return true; 399 return true;
400 400
401} 401}
402 402
403bool OPimContactAccessBackend_SQL::reload() 403bool OPimContactAccessBackend_SQL::reload()
404{ 404{
405 return load(); 405 return load();
406} 406}
407 407
408bool OPimContactAccessBackend_SQL::save() 408bool OPimContactAccessBackend_SQL::save()
409{ 409{
410 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers) 410 return m_driver->close(); // Shouldn't m_driver->sync be better than close ? (eilers)
411} 411}
412 412
413 413
414void OPimContactAccessBackend_SQL::clear () 414void OPimContactAccessBackend_SQL::clear ()
415{ 415{
416 ClearQuery cle; 416 ClearQuery cle;
417 OSQLResult res = m_driver->query( &cle ); 417 OSQLResult res = m_driver->query( &cle );
418 418
419 reload(); 419 reload();
420} 420}
421 421
422bool OPimContactAccessBackend_SQL::wasChangedExternally() 422bool OPimContactAccessBackend_SQL::wasChangedExternally()
423{ 423{
424 return false; 424 return false;
425} 425}
426 426
427UIDArray OPimContactAccessBackend_SQL::allRecords() const 427UIDArray OPimContactAccessBackend_SQL::allRecords() const
428{ 428{
429 429
430 // FIXME: Think about cute handling of changed tables.. 430 // FIXME: Think about cute handling of changed tables..
431 // Thus, we don't have to call update here... 431 // Thus, we don't have to call update here...
432 if ( m_changed ) 432 if ( m_changed )
433 ((OPimContactAccessBackend_SQL*)this)->update(); 433 ((OPimContactAccessBackend_SQL*)this)->update();
434 434
435 return m_uids; 435 return m_uids;
436} 436}
437 437
438bool OPimContactAccessBackend_SQL::add ( const OPimContact &newcontact ) 438bool OPimContactAccessBackend_SQL::add ( const OPimContact &newcontact )
439{ 439{
440 odebug << "add in contact SQL-Backend" << oendl; 440 odebug << "add in contact SQL-Backend" << oendl;
441 InsertQuery ins( newcontact ); 441 InsertQuery ins( newcontact );
442 OSQLResult res = m_driver->query( &ins ); 442 OSQLResult res = m_driver->query( &ins );
443 443
444 if ( res.state() == OSQLResult::Failure ) 444 if ( res.state() == OSQLResult::Failure )
445 return false; 445 return false;
446 446
447 int c = m_uids.count(); 447 int c = m_uids.count();
448 m_uids.resize( c+1 ); 448 m_uids.resize( c+1 );
449 m_uids[c] = newcontact.uid(); 449 m_uids[c] = newcontact.uid();
450 450
451 return true; 451 return true;
452} 452}
453 453
454 454
455bool OPimContactAccessBackend_SQL::remove ( int uid ) 455bool OPimContactAccessBackend_SQL::remove ( int uid )
456{ 456{
457 RemoveQuery rem( uid ); 457 RemoveQuery rem( uid );
458 OSQLResult res = m_driver->query(&rem ); 458 OSQLResult res = m_driver->query(&rem );
459 459
460 if ( res.state() == OSQLResult::Failure ) 460 if ( res.state() == OSQLResult::Failure )
461 return false; 461 return false;
462 462
463 m_changed = true; 463 m_changed = true;
464 464
465 return true; 465 return true;
466} 466}
467 467
468bool OPimContactAccessBackend_SQL::replace ( const OPimContact &contact ) 468bool OPimContactAccessBackend_SQL::replace ( const OPimContact &contact )
469{ 469{
470 if ( !remove( contact.uid() ) ) 470 if ( !remove( contact.uid() ) )
471 return false; 471 return false;
472 472
473 return add( contact ); 473 return add( contact );
474} 474}
475 475
476 476
477OPimContact OPimContactAccessBackend_SQL::find ( int uid ) const 477OPimContact OPimContactAccessBackend_SQL::find ( int uid ) const
478{ 478{
479 odebug << "OPimContactAccessBackend_SQL::find(" << uid << ")" << oendl; 479 odebug << "OPimContactAccessBackend_SQL::find(" << uid << ")" << oendl;
480 QTime t; 480 QTime t;
481 t.start(); 481 t.start();
482 482
483 OPimContact retContact( requestNonCustom( uid ) ); 483 OPimContact retContact( requestNonCustom( uid ) );
484 retContact.setExtraMap( requestCustom( uid ) ); 484 retContact.setExtraMap( requestCustom( uid ) );
485 485
486 odebug << "OPimContactAccessBackend_SQL::find() needed: " << t.elapsed() << " ms" << oendl; 486 odebug << "OPimContactAccessBackend_SQL::find() needed: " << t.elapsed() << " ms" << oendl;
487 return retContact; 487 return retContact;
488} 488}
489 489
490OPimContact OPimContactAccessBackend_SQL::find( int uid, const UIDArray& queryUids, uint current, Frontend::CacheDirection direction ) const 490OPimContact OPimContactAccessBackend_SQL::find( int uid, const UIDArray& queryUids, uint current, Frontend::CacheDirection direction ) const
491{ 491{
492 odebug << "OPimContactAccessBackend_SQL::find( ..multi.. )" << oendl; 492 odebug << "OPimContactAccessBackend_SQL::find( ..multi.. )" << oendl;
493 odebug << "searching for " << uid << "" << oendl; 493 odebug << "searching for " << uid << "" << oendl;
494 494
495 QTime t; 495 QTime t;
496 t.start(); 496 t.start();
497 497
498 uint numReadAhead = readAhead(); 498 uint numReadAhead = readAhead();
499 QArray<int> searchList( numReadAhead ); 499 QArray<int> searchList( numReadAhead );
500 500
501 uint size =0; 501 uint size =0;
502 502
503 // Build an array with all elements which should be requested and cached 503 // Build an array with all elements which should be requested and cached
504 // We will just request "numReadAhead" elements, starting from "current" position in 504 // We will just request "numReadAhead" elements, starting from "current" position in
505 // the list of many uids ! 505 // the list of many uids !
506 switch( direction ) { 506 switch( direction ) {
507 /* forward */ 507 /* forward */
508 case Frontend::Forward: 508 case Frontend::Forward:
509 for ( uint i = current; i < queryUids.count() && size < numReadAhead; i++ ) { 509 for ( uint i = current; i < queryUids.count() && size < numReadAhead; i++ ) {
510 searchList[size] = queryUids[i]; 510 searchList[size] = queryUids[i];
511 size++; 511 size++;
512 } 512 }
513 break; 513 break;
514 /* reverse */ 514 /* reverse */
515 case Frontend::Reverse: 515 case Frontend::Reverse:
516 for ( uint i = current; i != 0 && size < numReadAhead; i-- ) { 516 for ( uint i = current; i != 0 && size < numReadAhead; i-- ) {
517 searchList[size] = queryUids[i]; 517 searchList[size] = queryUids[i];
518 size++; 518 size++;
519 } 519 }
520 break; 520 break;
521 } 521 }
522 522
523 //Shrink to real size.. 523 //Shrink to real size..
524 searchList.resize( size ); 524 searchList.resize( size );
525 525
526 OPimContact retContact( requestContactsAndCache( uid, searchList ) ); 526 OPimContact retContact( requestContactsAndCache( uid, searchList ) );
527 527
528 odebug << "OPimContactAccessBackend_SQL::find( ..multi.. ) needed: " << t.elapsed() << " ms" << oendl; 528 odebug << "OPimContactAccessBackend_SQL::find( ..multi.. ) needed: " << t.elapsed() << " ms" << oendl;
529 return retContact; 529 return retContact;
530} 530}
531 531
532 532
533UIDArray OPimContactAccessBackend_SQL::queryByExample ( const UIDArray& uidlist, const OPimContact &query, int settings, 533UIDArray OPimContactAccessBackend_SQL::queryByExample ( const UIDArray& uidlist, const OPimContact &query, int settings,
534 const QDateTime& qd ) const 534 const QDateTime& qd ) const
535{ 535{
536 QString qu = "SELECT uid FROM addressbook WHERE"; 536 QString qu = "SELECT uid FROM addressbook WHERE";
537 537
538 // Just add uid's selection if we really try to search in a subset of all uids! Otherwise this would 538 // Just add uid's selection if we really try to search in a subset of all uids! Otherwise this would
539 // just take time and memory! 539 // just take time and memory!
540 if ( uidlist.count() != m_uids.count() ) { 540 if ( uidlist.count() != m_uids.count() ) {
541 qu += " ("; 541 qu += " (";
542 542
543 for ( uint i = 0; i < uidlist.count(); i++ ) { 543 for ( uint i = 0; i < uidlist.count(); i++ ) {
544 qu += " uid = " + QString::number( uidlist[i] ) + " OR"; 544 qu += " uid = " + QString::number( uidlist[i] ) + " OR";
545 } 545 }
546 qu.remove( qu.length()-2, 2 ); // Hmmmm.. 546 qu.remove( qu.length()-2, 2 ); // Hmmmm..
547 qu += " ) AND "; 547 qu += " ) AND ";
548 } 548 }
549 549
550 QString searchQuery =""; 550 QString searchQuery = "";
551 QString temp_searchQuery = "";
551 552
552 QDate startDate; 553 QDate startDate;
553 554
554 if ( qd.isValid() ) 555 if ( qd.isValid() )
555 startDate = qd.date(); 556 startDate = qd.date();
556 else 557 else
557 startDate = QDate::currentDate(); 558 startDate = QDate::currentDate();
558 559
559 560
560 QMap<int, QString> queryFields = query.toMap(); 561 QMap<int, QString> queryFields = query.toMap();
561 QStringList fieldList = OPimContactFields::untrfields( false ); 562 QStringList fieldList = OPimContactFields::untrfields( false );
562 QMap<QString, int> translate = OPimContactFields::untrFieldsToId(); 563 QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
563 564
564 // Convert every filled field to a SQL-Query 565 // Convert every filled field to a SQL-Query
565// bool isAnyFieldSelected = false; 566// bool isAnyFieldSelected = false;
566 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 567 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
567 568
568 int id = translate[*it]; 569 int id = translate[*it];
569 QString queryStr = queryFields[id]; 570 QString queryStr = queryFields[id];
570 QDate* endDate = 0l; 571 QDate* endDate = 0l;
571 572
572 if ( !queryStr.isEmpty() ){ 573 if ( !queryStr.isEmpty() ){
573 // If something is alredy stored in the query, add an "AND" 574 // If something is alredy stored in the query, add an "AND"
574 // to the end of the string to prepare for the next .. 575 // to the end of the string to prepare for the next ..
575 if ( !searchQuery.isEmpty() ) 576 if ( !searchQuery.isEmpty() )
576 searchQuery += " AND"; 577 searchQuery += " AND";
577 578
578// isAnyFieldSelected = true; 579// isAnyFieldSelected = true;
579 switch( id ){ 580 switch( id ){
580 case Qtopia::Birthday: 581 case Qtopia::Birthday:
581 endDate = new QDate( query.birthday() ); 582 endDate = new QDate( query.birthday() );
582 // Fall through ! 583 // Fall through !
583 case Qtopia::Anniversary: 584 case Qtopia::Anniversary:
584 if ( endDate == 0l ) 585 if ( endDate == 0l )
585 endDate = new QDate( query.anniversary() ); 586 endDate = new QDate( query.anniversary() );
586 587
587 if ( settings & OPimContactAccess::DateDiff ) { 588 if ( settings & OPimContactAccess::DateDiff ) {
588 searchQuery += QString( " (\"%1\" <= '%2-%3-%4\' AND \"%5\" >= '%6-%7-%8')" ) 589 // To handle datediffs correctly, we need to remove the year information from
590 // the birthday and anniversary.
591 // To do this efficiently, we will create a temporary table which contains the
592 // information we need and do the query on it.
593 // This table is just visible for this process and will be removed
594 // automatically after using.
595 temp_searchQuery = "CREATE TEMP TABLE bs ( uid, \"Birthday\", \"Anniversary\" );";
596 temp_searchQuery += "INSERT INTO bs SELECT uid,substr(\"Birthday\", 6, 10),substr(\"Anniversary\", 6, 10) FROM addressbook WHERE ( \"Birthday\" != '' OR \"Anniversary\" != '' );";
597
598 temp_searchQuery += QString( "SELECT uid FROM bs WHERE (\"%1\" <= '%2-%3\' AND \"%4\" >= '%5-%6')" )
589 .arg( *it ) 599 .arg( *it )
590 .arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) ) 600 //.arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) )
591 .arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) ) 601 .arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) )
592 .arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) ) 602 .arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) )
593 .arg( *it ) 603 .arg( *it )
594 .arg( QString::number( startDate.year() ).rightJustify( 4, '0' ) ) 604 //.arg( QString::number( startDate.year() ).rightJustify( 4, '0' ) )
595 .arg( QString::number( startDate.month() ).rightJustify( 2, '0' ) ) 605 .arg( QString::number( startDate.month() ).rightJustify( 2, '0' ) )
596 .arg( QString::number( startDate.day() ).rightJustify( 2, '0' ) ) ; 606 .arg( QString::number( startDate.day() ).rightJustify( 2, '0' ) ) ;
597 } 607 }
598 608
599 if ( settings & OPimContactAccess::DateYear ){ 609 if ( settings & OPimContactAccess::DateYear ){
600 if ( settings & OPimContactAccess::DateDiff ) 610 // if ( settings & OPimContactAccess::DateDiff )
601 searchQuery += " AND"; 611 // searchQuery += " AND";
602 612
603 searchQuery += QString( " (\"%1\" LIKE '%2-%')" ) 613 searchQuery += QString( " (\"%1\" LIKE '%2-%')" )
604 .arg( *it ) 614 .arg( *it )
605 .arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) ); 615 .arg( QString::number( endDate->year() ).rightJustify( 4, '0' ) );
606 } 616 }
607 617
608 if ( settings & OPimContactAccess::DateMonth ){ 618 if ( settings & OPimContactAccess::DateMonth ){
609 if ( ( settings & OPimContactAccess::DateDiff ) 619 if ( ( settings & OPimContactAccess::DateDiff )
610 || ( settings & OPimContactAccess::DateYear ) ) 620 || ( settings & OPimContactAccess::DateYear ) )
611 searchQuery += " AND"; 621 searchQuery += " AND";
612 622
613 searchQuery += QString( " (\"%1\" LIKE '%-%2-%')" ) 623 searchQuery += QString( " (\"%1\" LIKE '%-%2-%')" )
614 .arg( *it ) 624 .arg( *it )
615 .arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) ); 625 .arg( QString::number( endDate->month() ).rightJustify( 2, '0' ) );
616 } 626 }
617 627
618 if ( settings & OPimContactAccess::DateDay ){ 628 if ( settings & OPimContactAccess::DateDay ){
619 if ( ( settings & OPimContactAccess::DateDiff ) 629 if ( ( settings & OPimContactAccess::DateDiff )
620 || ( settings & OPimContactAccess::DateYear ) 630 || ( settings & OPimContactAccess::DateYear )
621 || ( settings & OPimContactAccess::DateMonth ) ) 631 || ( settings & OPimContactAccess::DateMonth ) )
622 searchQuery += " AND"; 632 searchQuery += " AND";
623 633
624 searchQuery += QString( " (\"%1\" LIKE '%-%-%2')" ) 634 searchQuery += QString( " (\"%1\" LIKE '%-%-%2')" )
625 .arg( *it ) 635 .arg( *it )
626 .arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) ); 636 .arg( QString::number( endDate->day() ).rightJustify( 2, '0' ) );
627 } 637 }
628 638
629 break; 639 break;
630 default: 640 default:
631 // Switching between case sensitive and insensitive... 641 // Switching between case sensitive and insensitive...
632 // LIKE is not case sensitive, GLOB is case sensitive 642 // LIKE is not case sensitive, GLOB is case sensitive
633 // Do exist a better solution to switch this ? 643 // Do exist a better solution to switch this ?
634 if ( settings & OPimContactAccess::IgnoreCase ) 644 if ( settings & OPimContactAccess::IgnoreCase )
635 searchQuery += "(\"" + *it + "\"" + " LIKE " + "'" 645 searchQuery += "(\"" + *it + "\"" + " LIKE " + "'"
636 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ")"; 646 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ")";
637 else 647 else
638 searchQuery += "(\"" + *it + "\"" + " GLOB " + "'" 648 searchQuery += "(\"" + *it + "\"" + " GLOB " + "'"
639 + queryStr + "'" + ")"; 649 + queryStr + "'" + ")";
640 650
641 } 651 }
642 } 652 }
643 653
644 delete endDate; 654 delete endDate;
645 } 655 }
646 // Skip trailing "AND"
647// if ( isAnyFieldSelected )
648// qu = qu.left( qu.length() - 4 );
649 656
650 qu += searchQuery; 657 // The following is very ugly! (eilers)
658 if ( !temp_searchQuery.isEmpty() && !searchQuery.isEmpty() ){
659 // If we use DateDiff, we have to intersect two queries.
660 qu = temp_searchQuery + QString( " INTERSECT " ) + qu + searchQuery;
661 } else if ( temp_searchQuery.isEmpty() && !searchQuery.isEmpty() ){
662 qu += searchQuery;
663 } else if ( !temp_searchQuery.isEmpty() && searchQuery.isEmpty() ){
664 // This will cause wrong results!! Uid filter is not used here!
665 qu = temp_searchQuery;
666 } else if ( temp_searchQuery.isEmpty() && searchQuery.isEmpty() ){
667 UIDArray empty;
668 return empty;
669 }
651 670
652 odebug << "queryByExample query: " << qu << "" << oendl; 671 odebug << "queryByExample query: " << qu << "" << oendl;
653 672
654 // Execute query and return the received uid's 673 // Execute query and return the received uid's
655 OSQLRawQuery raw( qu ); 674 OSQLRawQuery raw( qu );
656 OSQLResult res = m_driver->query( &raw ); 675 OSQLResult res = m_driver->query( &raw );
657 if ( res.state() != OSQLResult::Success ){ 676 if ( res.state() != OSQLResult::Success ){
658 UIDArray empty; 677 UIDArray empty;
659 return empty; 678 return empty;
660 } 679 }
661 680
662 UIDArray list = extractUids( res ); 681 UIDArray list = extractUids( res );
663 682
683 // Remove temp table if created
684 if ( !temp_searchQuery.isEmpty( ) ){
685 qu = "DROP TABLE bs";
686 OSQLRawQuery raw( qu );
687 OSQLResult res = m_driver->query( &raw );
688 }
689
664 return list; 690 return list;
665} 691}
666 692
667UIDArray OPimContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const 693UIDArray OPimContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
668{ 694{
669#if 0 695#if 0
670 QArray<int> nix(0); 696 QArray<int> nix(0);
671 return nix; 697 return nix;
672 698
673#else 699#else
674 QString qu = "SELECT uid FROM addressbook WHERE ("; 700 QString qu = "SELECT uid FROM addressbook WHERE (";
675 QString searchlist; 701 QString searchlist;
676 702
677 QStringList fieldList = OPimContactFields::untrfields( false ); 703 QStringList fieldList = OPimContactFields::untrfields( false );
678 // QMap<QString, int> translate = OPimContactFields::untrFieldsToId(); 704 // QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
679 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 705 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
680 if ( !searchlist.isEmpty() ) 706 if ( !searchlist.isEmpty() )
681 searchlist += " OR "; 707 searchlist += " OR ";
682 searchlist += " rlike(\""+ r.pattern() + "\",\"" + *it + "\") "; 708 searchlist += " rlike(\""+ r.pattern() + "\",\"" + *it + "\") ";
683 } 709 }
684 710
685 qu = qu + searchlist + ")"; 711 qu = qu + searchlist + ")";
686 712
687 odebug << "query: " << qu << "" << oendl; 713 odebug << "query: " << qu << "" << oendl;
688 714
689 OSQLRawQuery raw( qu ); 715 OSQLRawQuery raw( qu );
690 OSQLResult res = m_driver->query( &raw ); 716 OSQLResult res = m_driver->query( &raw );
691 717
692 return extractUids( res ); 718 return extractUids( res );
693 719
694 720
695#endif 721#endif
696} 722}
697 723
698const uint OPimContactAccessBackend_SQL::querySettings() const 724const uint OPimContactAccessBackend_SQL::querySettings() const
699{ 725{
700 return OPimContactAccess::IgnoreCase 726 return OPimContactAccess::IgnoreCase
701 | OPimContactAccess::WildCards 727 | OPimContactAccess::WildCards
702 | OPimContactAccess::DateDiff 728 | OPimContactAccess::DateDiff
703 | OPimContactAccess::DateYear 729 | OPimContactAccess::DateYear
704 | OPimContactAccess::DateMonth 730 | OPimContactAccess::DateMonth
705 | OPimContactAccess::DateDay 731 | OPimContactAccess::DateDay
706 ; 732 ;
707} 733}
708 734
709bool OPimContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const 735bool OPimContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
710{ 736{
711 /* OPimContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay 737 /* OPimContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
712 * may be added with any of the other settings. IgnoreCase should never used alone. 738 * may be added with any of the other settings. IgnoreCase should never used alone.
713 * Wildcards, RegExp, ExactMatch should never used at the same time... 739 * Wildcards, RegExp, ExactMatch should never used at the same time...
714 */ 740 */
715 741
716 // Step 1: Check whether the given settings are supported by this backend 742 // Step 1: Check whether the given settings are supported by this backend
717 if ( ( querySettings & ( 743 if ( ( querySettings & (
718 OPimContactAccess::IgnoreCase 744 OPimContactAccess::IgnoreCase
719 | OPimContactAccess::WildCards 745 | OPimContactAccess::WildCards
720 | OPimContactAccess::DateDiff 746 | OPimContactAccess::DateDiff
721 | OPimContactAccess::DateYear 747 | OPimContactAccess::DateYear
722 | OPimContactAccess::DateMonth 748 | OPimContactAccess::DateMonth
723 | OPimContactAccess::DateDay 749 | OPimContactAccess::DateDay
724// | OPimContactAccess::RegExp 750// | OPimContactAccess::RegExp
725// | OPimContactAccess::ExactMatch 751// | OPimContactAccess::ExactMatch
726 ) ) != querySettings ) 752 ) ) != querySettings )
727 return false; 753 return false;
728 754
729 // Step 2: Check whether the given combinations are ok.. 755 // Step 2: Check whether the given combinations are ok..
730 756
731 // IngoreCase alone is invalid 757 // IngoreCase alone is invalid
732 if ( querySettings == OPimContactAccess::IgnoreCase ) 758 if ( querySettings == OPimContactAccess::IgnoreCase )
733 return false; 759 return false;
734 760
735 // WildCards, RegExp and ExactMatch should never used at the same time 761 // WildCards, RegExp and ExactMatch should never used at the same time
736 switch ( querySettings & ~( OPimContactAccess::IgnoreCase 762 switch ( querySettings & ~( OPimContactAccess::IgnoreCase
737 | OPimContactAccess::DateDiff 763 | OPimContactAccess::DateDiff
738 | OPimContactAccess::DateYear 764 | OPimContactAccess::DateYear
739 | OPimContactAccess::DateMonth 765 | OPimContactAccess::DateMonth
740 | OPimContactAccess::DateDay 766 | OPimContactAccess::DateDay
741 ) 767 )
742 ){ 768 ){
743 case OPimContactAccess::RegExp: 769 case OPimContactAccess::RegExp:
744 return ( true ); 770 return ( true );
745 case OPimContactAccess::WildCards: 771 case OPimContactAccess::WildCards:
746 return ( true ); 772 return ( true );
747 case OPimContactAccess::ExactMatch: 773 case OPimContactAccess::ExactMatch:
748 return ( true ); 774 return ( true );
749 case 0: // one of the upper removed bits were set.. 775 case 0: // one of the upper removed bits were set..
750 return ( true ); 776 return ( true );
751 default: 777 default:
752 return ( false ); 778 return ( false );
753 } 779 }
754 780
755} 781}
756 782
757UIDArray OPimContactAccessBackend_SQL::sorted( const UIDArray& ar, bool asc, int sortOrder, 783UIDArray OPimContactAccessBackend_SQL::sorted( const UIDArray& ar, bool asc, int sortOrder,
758 int filter, const QArray<int>& categories )const 784 int filter, const QArray<int>& categories )const
759{ 785{
760 QTime t; 786 QTime t;
761 t.start(); 787 t.start();
762 788
763 QString query = "SELECT uid FROM addressbook"; 789 QString query = "SELECT uid FROM addressbook";
764 790
765 query += " WHERE ("; 791 query += " WHERE (";
766 for ( uint i = 0; i < ar.count(); i++ ) { 792 for ( uint i = 0; i < ar.count(); i++ ) {
767 query += " uid = " + QString::number( ar[i] ) + " OR"; 793 query += " uid = " + QString::number( ar[i] ) + " OR";
768 } 794 }
769 query.remove( query.length()-2, 2 ); // Hmmmm.. 795 query.remove( query.length()-2, 2 ); // Hmmmm..
770 query += ")"; 796 query += ")";
771 797
772 798
773 if ( filter != OPimBase::FilterOff ){ 799 if ( filter != OPimBase::FilterOff ){
774 if ( filter & OPimContactAccess::DoNotShowWithCategory ){ 800 if ( filter & OPimContactAccess::DoNotShowWithCategory ){
775 query += " AND ( \"Categories\" == '' )"; 801 query += " AND ( \"Categories\" == '' )";
776 } else if ( filter & OPimBase::FilterCategory ){ 802 } else if ( filter & OPimBase::FilterCategory ){
777 query += " AND ("; 803 query += " AND (";
778 for ( uint i = 0; i < categories.count(); i++ ){ 804 for ( uint i = 0; i < categories.count(); i++ ){
779 query += "\"Categories\" LIKE"; 805 query += "\"Categories\" LIKE";
780 query += QString( " '%" ) + QString::number( categories[i] ) + "%' OR"; 806 query += QString( " '%" ) + QString::number( categories[i] ) + "%' OR";
781 } 807 }
782 query.remove( query.length()-2, 2 ); // Hmmmm.. 808 query.remove( query.length()-2, 2 ); // Hmmmm..
783 query += ")"; 809 query += ")";
784 } 810 }
785 811
786 if ( filter & OPimContactAccess::DoNotShowWithoutChildren ){ 812 if ( filter & OPimContactAccess::DoNotShowWithoutChildren ){
787 query += " AND ( \"Children\" != '' )"; 813 query += " AND ( \"Children\" != '' )";
788 } 814 }
789 815
790 if ( filter & OPimContactAccess::DoNotShowWithoutAnniversary ){ 816 if ( filter & OPimContactAccess::DoNotShowWithoutAnniversary ){
791 query += " AND ( \"Anniversary\" != '' )"; 817 query += " AND ( \"Anniversary\" != '' )";
792 } 818 }
793 819
794 if ( filter & OPimContactAccess::DoNotShowWithoutBirthday ){ 820 if ( filter & OPimContactAccess::DoNotShowWithoutBirthday ){
795 query += " AND ( \"Birthday\" != '' )"; 821 query += " AND ( \"Birthday\" != '' )";
796 } 822 }
797 823
798 if ( filter & OPimContactAccess::DoNotShowWithoutHomeAddress ){ 824 if ( filter & OPimContactAccess::DoNotShowWithoutHomeAddress ){
799 // Expect that no Street means no Address, too! (eilers) 825 // Expect that no Street means no Address, too! (eilers)
800 query += " AND ( \"Home Street\" != '' )"; 826 query += " AND ( \"Home Street\" != '' )";
801 } 827 }
802 828
803 if ( filter & OPimContactAccess::DoNotShowWithoutBusinessAddress ){ 829 if ( filter & OPimContactAccess::DoNotShowWithoutBusinessAddress ){
804 // Expect that no Street means no Address, too! (eilers) 830 // Expect that no Street means no Address, too! (eilers)
805 query += " AND ( \"Business Street\" != '' )"; 831 query += " AND ( \"Business Street\" != '' )";
806 } 832 }
807 833
808 } 834 }
809 835
810 query += " ORDER BY"; 836 query += " ORDER BY";
811 837
812 switch ( sortOrder ) { 838 switch ( sortOrder ) {
813 case OPimContactAccess::SortSummary: 839 case OPimContactAccess::SortSummary:
814 query += " \"Notes\""; 840 query += " \"Notes\"";
815 break; 841 break;
816 case OPimContactAccess::SortByCategory: 842 case OPimContactAccess::SortByCategory:
817 query += " \"Categories\""; 843 query += " \"Categories\"";
818 break; 844 break;
819 case OPimContactAccess::SortByDate: 845 case OPimContactAccess::SortByDate:
820 query += " \"\""; 846 query += " \"\"";
821 break; 847 break;
822 case OPimContactAccess::SortTitle: 848 case OPimContactAccess::SortTitle:
823 query += " \"Name Title\""; 849 query += " \"Name Title\"";
824 break; 850 break;
825 case OPimContactAccess::SortFirstName: 851 case OPimContactAccess::SortFirstName:
826 query += " \"First Name\""; 852 query += " \"First Name\"";
827 break; 853 break;
828 case OPimContactAccess::SortMiddleName: 854 case OPimContactAccess::SortMiddleName:
829 query += " \"Middle Name\""; 855 query += " \"Middle Name\"";
830 break; 856 break;
831 case OPimContactAccess::SortLastName: 857 case OPimContactAccess::SortLastName:
832 query += " \"Last Name\""; 858 query += " \"Last Name\"";
833 break; 859 break;
834 case OPimContactAccess::SortFileAsName: 860 case OPimContactAccess::SortFileAsName:
835 query += " \"File As\""; 861 query += " \"File As\"";
836 break; 862 break;
837 case OPimContactAccess::SortSuffix: 863 case OPimContactAccess::SortSuffix:
838 query += " \"Suffix\""; 864 query += " \"Suffix\"";
839 break; 865 break;
840 case OPimContactAccess::SortEmail: 866 case OPimContactAccess::SortEmail:
841 query += " \"Default Email\""; 867 query += " \"Default Email\"";
842 break; 868 break;
843 case OPimContactAccess::SortNickname: 869 case OPimContactAccess::SortNickname:
844 query += " \"Nickname\""; 870 query += " \"Nickname\"";
845 break; 871 break;
846 case OPimContactAccess::SortAnniversary: 872 case OPimContactAccess::SortAnniversary:
847 query += " \"Anniversary\""; 873 query += " \"Anniversary\"";
848 break; 874 break;
849 case OPimContactAccess::SortBirthday: 875 case OPimContactAccess::SortBirthday:
850 query += " \"Birthday\""; 876 query += " \"Birthday\"";
851 break; 877 break;
852 case OPimContactAccess::SortGender: 878 case OPimContactAccess::SortGender:
853 query += " \"Gender\""; 879 query += " \"Gender\"";
854 break; 880 break;
855 default: 881 default:
856 query += " \"Last Name\""; 882 query += " \"Last Name\"";
857 } 883 }
858 884
859 if ( !asc ) 885 if ( !asc )
860 query += " DESC"; 886 query += " DESC";
861 887
862 888
863 odebug << "sorted query is: " << query << "" << oendl; 889 odebug << "sorted query is: " << query << "" << oendl;
864 890
865 OSQLRawQuery raw( query ); 891 OSQLRawQuery raw( query );
866 OSQLResult res = m_driver->query( &raw ); 892 OSQLResult res = m_driver->query( &raw );
867 if ( res.state() != OSQLResult::Success ){ 893 if ( res.state() != OSQLResult::Success ){
868 UIDArray empty; 894 UIDArray empty;
869 return empty; 895 return empty;
870 } 896 }
871 897
872 UIDArray list = extractUids( res ); 898 UIDArray list = extractUids( res );
873 899
874 odebug << "sorted needed " << t.elapsed() << " ms!" << oendl; 900 odebug << "sorted needed " << t.elapsed() << " ms!" << oendl;
875 return list; 901 return list;
876} 902}
877 903
878 904
879void OPimContactAccessBackend_SQL::update() 905void OPimContactAccessBackend_SQL::update()
880{ 906{
881 odebug << "Update starts" << oendl; 907 odebug << "Update starts" << oendl;
882 QTime t; 908 QTime t;
883 t.start(); 909 t.start();
884 910
885 // Now load the database set and extract the uid's 911 // Now load the database set and extract the uid's
886 // which will be held locally 912 // which will be held locally
887 913
888 LoadQuery lo; 914 LoadQuery lo;
889 OSQLResult res = m_driver->query(&lo); 915 OSQLResult res = m_driver->query(&lo);
890 if ( res.state() != OSQLResult::Success ) 916 if ( res.state() != OSQLResult::Success )
891 return; 917 return;
892 918
893 m_uids = extractUids( res ); 919 m_uids = extractUids( res );
894 920
895 m_changed = false; 921 m_changed = false;
896 922
897 odebug << "Update ends " << t.elapsed() << " ms" << oendl; 923 odebug << "Update ends " << t.elapsed() << " ms" << oendl;
898} 924}
899 925
900UIDArray OPimContactAccessBackend_SQL::extractUids( OSQLResult& res ) const 926UIDArray OPimContactAccessBackend_SQL::extractUids( OSQLResult& res ) const
901{ 927{
902 odebug << "extractUids" << oendl; 928 odebug << "extractUids" << oendl;
903 QTime t; 929 QTime t;
904 t.start(); 930 t.start();
905 OSQLResultItem::ValueList list = res.results(); 931 OSQLResultItem::ValueList list = res.results();
906 OSQLResultItem::ValueList::Iterator it; 932 OSQLResultItem::ValueList::Iterator it;
907 UIDArray ints(list.count() ); 933 UIDArray ints(list.count() );
908 odebug << " count = " << list.count() << "" << oendl; 934 odebug << " count = " << list.count() << "" << oendl;
909 935
910 int i = 0; 936 int i = 0;
911 for (it = list.begin(); it != list.end(); ++it ) { 937 for (it = list.begin(); it != list.end(); ++it ) {
912 ints[i] = (*it).data("uid").toInt(); 938 ints[i] = (*it).data("uid").toInt();
913 i++; 939 i++;
914 } 940 }
915 odebug << "extractUids ready: count2 = " << i << " needs " << t.elapsed() << " ms" << oendl; 941 odebug << "extractUids ready: count2 = " << i << " needs " << t.elapsed() << " ms" << oendl;
916 942
917 return ints; 943 return ints;
918 944
919} 945}
920 946
921QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) const 947QMap<int, QString> OPimContactAccessBackend_SQL::requestNonCustom( int uid ) const
922{ 948{
923 QTime t; 949 QTime t;
924 t.start(); 950 t.start();
925 951
926 int t2needed = 0; 952 int t2needed = 0;
927 int t3needed = 0; 953 int t3needed = 0;
928 QTime t2; 954 QTime t2;
929 t2.start(); 955 t2.start();
930 FindQuery query( uid ); 956 FindQuery query( uid );
931 OSQLResult res_noncustom = m_driver->query( &query ); 957 OSQLResult res_noncustom = m_driver->query( &query );
932 t2needed = t2.elapsed(); 958 t2needed = t2.elapsed();
933 959
934 OSQLResultItem resItem = res_noncustom.first(); 960 OSQLResultItem resItem = res_noncustom.first();
935 961
936 QMap<int, QString> nonCustomMap; 962 QMap<int, QString> nonCustomMap;
937 QTime t3; 963 QTime t3;
938 t3.start(); 964 t3.start();
939 nonCustomMap = fillNonCustomMap( resItem ); 965 nonCustomMap = fillNonCustomMap( resItem );
940 t3needed = t3.elapsed(); 966 t3needed = t3.elapsed();
941 967
942 968
943 // odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl; 969 // odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl;
944 odebug << "RequestNonCustom needed: insg.:" << t.elapsed() << " ms, query: " << t2needed 970 odebug << "RequestNonCustom needed: insg.:" << t.elapsed() << " ms, query: " << t2needed
945 << " ms, mapping: " << t3needed << " ms" << oendl; 971 << " ms, mapping: " << t3needed << " ms" << oendl;
946 972
947 return nonCustomMap; 973 return nonCustomMap;
948} 974}
949 975
950/* Returns contact requested by uid and fills cache with contacts requested by uids in the cachelist */ 976/* Returns contact requested by uid and fills cache with contacts requested by uids in the cachelist */
951OPimContact OPimContactAccessBackend_SQL::requestContactsAndCache( int uid, const UIDArray& uidlist )const 977OPimContact OPimContactAccessBackend_SQL::requestContactsAndCache( int uid, const UIDArray& uidlist )const
952{ 978{
953 // We want to get all contacts with one query. 979 // We want to get all contacts with one query.
954 // We don't have to add the given uid to the uidlist, it is expected to be there already (see opimrecordlist.h). 980 // We don't have to add the given uid to the uidlist, it is expected to be there already (see opimrecordlist.h).
955 // All contacts will be stored in the cache, afterwards the contact with the user id "uid" will be returned 981 // All contacts will be stored in the cache, afterwards the contact with the user id "uid" will be returned
956 // by using the cache.. 982 // by using the cache..
957 UIDArray cachelist = uidlist; 983 UIDArray cachelist = uidlist;
958 OPimContact retContact; 984 OPimContact retContact;
959 985
960 odebug << "Reqest and cache" << cachelist.size() << "elements !" << oendl; 986 odebug << "Reqest and cache" << cachelist.size() << "elements !" << oendl;
961 987
962 QTime t; 988 QTime t;
963 t.start(); 989 t.start();
964 990
965 int t2needed = 0; 991 int t2needed = 0;
966 int t3needed = 0; 992 int t3needed = 0;
967 QTime t2; 993 QTime t2;
968 t2.start(); 994 t2.start();
969 FindQuery query( cachelist ); 995 FindQuery query( cachelist );
970 OSQLResult res_noncustom = m_driver->query( &query ); 996 OSQLResult res_noncustom = m_driver->query( &query );
971 t2needed = t2.elapsed(); 997 t2needed = t2.elapsed();
972 998
973 QMap<int, QString> nonCustomMap; 999 QMap<int, QString> nonCustomMap;
974 QTime t3; 1000 QTime t3;
975 t3.start(); 1001 t3.start();
976 OSQLResultItem resItem = res_noncustom.first(); 1002 OSQLResultItem resItem = res_noncustom.first();
977 do { 1003 do {
978 OPimContact contact( fillNonCustomMap( resItem ) ); 1004 OPimContact contact( fillNonCustomMap( resItem ) );
979 contact.setExtraMap( requestCustom( contact.uid() ) ); 1005 contact.setExtraMap( requestCustom( contact.uid() ) );
980 odebug << "Caching uid: " << contact.uid() << oendl; 1006 odebug << "Caching uid: " << contact.uid() << oendl;
981 cache( contact ); 1007 cache( contact );
982 if ( contact.uid() == uid ) 1008 if ( contact.uid() == uid )
983 retContact = contact; 1009 retContact = contact;
984 resItem = res_noncustom.next(); 1010 resItem = res_noncustom.next();
985 } while ( ! res_noncustom.atEnd() ); //atEnd() is true if we are past(!) the list !! 1011 } while ( ! res_noncustom.atEnd() ); //atEnd() is true if we are past(!) the list !!
986 t3needed = t3.elapsed(); 1012 t3needed = t3.elapsed();
987 1013
988 1014
989 // odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl; 1015 // odebug << "Adding UID: " << resItem.data( "uid" ) << "" << oendl;
990 odebug << "RequestContactsAndCache needed: insg.:" << t.elapsed() << " ms, query: " << t2needed 1016 odebug << "RequestContactsAndCache needed: insg.:" << t.elapsed() << " ms, query: " << t2needed
991 << " ms, mapping: " << t3needed << " ms" << oendl; 1017 << " ms, mapping: " << t3needed << " ms" << oendl;
992 1018
993 return retContact; 1019 return retContact;
994} 1020}
995 1021
996QMap<int, QString> OPimContactAccessBackend_SQL::fillNonCustomMap( const OSQLResultItem& resultItem ) const 1022QMap<int, QString> OPimContactAccessBackend_SQL::fillNonCustomMap( const OSQLResultItem& resultItem ) const
997{ 1023{
998 QMap<int, QString> nonCustomMap; 1024 QMap<int, QString> nonCustomMap;
999 1025
1000 // Now loop through all columns 1026 // Now loop through all columns
1001 QStringList fieldList = OPimContactFields::untrfields( false ); 1027 QStringList fieldList = OPimContactFields::untrfields( false );
1002 QMap<QString, int> translate = OPimContactFields::untrFieldsToId(); 1028 QMap<QString, int> translate = OPimContactFields::untrFieldsToId();
1003 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 1029 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
1004 // Get data for the selected column and store it with the 1030 // Get data for the selected column and store it with the
1005 // corresponding id into the map.. 1031 // corresponding id into the map..
1006 1032
1007 int id = translate[*it]; 1033 int id = translate[*it];
1008 QString value = resultItem.data( (*it) ); 1034 QString value = resultItem.data( (*it) );
1009 1035
1010 // odebug << "Reading " << (*it) << "... found: " << value << "" << oendl; 1036 // odebug << "Reading " << (*it) << "... found: " << value << "" << oendl;
1011 1037
1012 switch( id ){ 1038 switch( id ){
1013 case Qtopia::Birthday: 1039 case Qtopia::Birthday:
1014 case Qtopia::Anniversary:{ 1040 case Qtopia::Anniversary:{
1015 // Birthday and Anniversary are encoded special ( yyyy-mm-dd ) 1041 // Birthday and Anniversary are encoded special ( yyyy-mm-dd )
1016 QStringList list = QStringList::split( '-', value ); 1042 QStringList list = QStringList::split( '-', value );
1017 QStringList::Iterator lit = list.begin(); 1043 QStringList::Iterator lit = list.begin();
1018 int year = (*lit).toInt(); 1044 int year = (*lit).toInt();
1019 int month = (*(++lit)).toInt(); 1045 int month = (*(++lit)).toInt();
1020 int day = (*(++lit)).toInt(); 1046 int day = (*(++lit)).toInt();
1021 if ( ( day != 0 ) && ( month != 0 ) && ( year != 0 ) ){ 1047 if ( ( day != 0 ) && ( month != 0 ) && ( year != 0 ) ){
1022 QDate date( year, month, day ); 1048 QDate date( year, month, day );
1023 nonCustomMap.insert( id, OPimDateConversion::dateToString( date ) ); 1049 nonCustomMap.insert( id, OPimDateConversion::dateToString( date ) );
1024 } 1050 }
1025 } 1051 }
1026 break; 1052 break;
1027 case Qtopia::AddressCategory: 1053 case Qtopia::AddressCategory:
1028 odebug << "Category is: " << value << "" << oendl; 1054 odebug << "Category is: " << value << "" << oendl;
1029 default: 1055 default:
1030 nonCustomMap.insert( id, value ); 1056 nonCustomMap.insert( id, value );
1031 } 1057 }
1032 } 1058 }
1033 1059
1034 nonCustomMap.insert( Qtopia::AddressUid, resultItem.data( "uid" ) ); 1060 nonCustomMap.insert( Qtopia::AddressUid, resultItem.data( "uid" ) );
1035 1061
1036 return nonCustomMap; 1062 return nonCustomMap;
1037} 1063}
1038 1064
1039 1065
1040QMap<QString, QString> OPimContactAccessBackend_SQL::requestCustom( int uid ) const 1066QMap<QString, QString> OPimContactAccessBackend_SQL::requestCustom( int uid ) const
1041{ 1067{
1042 QTime t; 1068 QTime t;
1043 t.start(); 1069 t.start();
1044 1070
1045 QMap<QString, QString> customMap; 1071 QMap<QString, QString> customMap;
1046 1072
1047 FindCustomQuery query( uid ); 1073 FindCustomQuery query( uid );
1048 OSQLResult res_custom = m_driver->query( &query ); 1074 OSQLResult res_custom = m_driver->query( &query );
1049 1075
1050 if ( res_custom.state() == OSQLResult::Failure ) { 1076 if ( res_custom.state() == OSQLResult::Failure ) {
1051 owarn << "OSQLResult::Failure in find query !!" << oendl; 1077 owarn << "OSQLResult::Failure in find query !!" << oendl;
1052 QMap<QString, QString> empty; 1078 QMap<QString, QString> empty;
1053 return empty; 1079 return empty;
1054 } 1080 }
1055 1081
1056 OSQLResultItem::ValueList list = res_custom.results(); 1082 OSQLResultItem::ValueList list = res_custom.results();
1057 OSQLResultItem::ValueList::Iterator it = list.begin(); 1083 OSQLResultItem::ValueList::Iterator it = list.begin();
1058 for ( ; it != list.end(); ++it ) { 1084 for ( ; it != list.end(); ++it ) {
1059 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) ); 1085 customMap.insert( (*it).data( "type" ), (*it).data( "value" ) );
1060 } 1086 }
1061 1087
1062 odebug << "RequestCustom needed: " << t.elapsed() << " ms" << oendl; 1088 odebug << "RequestCustom needed: " << t.elapsed() << " ms" << oendl;
1063 return customMap; 1089 return customMap;
1064} 1090}
1065 1091
1066} 1092}