|
1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "c12keypredictivesearchtable.h" |
|
19 #include "dbsqlconstants.h" |
|
20 #include "cntitem.h" |
|
21 #include "c12keykeymap.h" |
|
22 #include <QStringList> |
|
23 |
|
24 // This macro suppresses log writes |
|
25 //#define NO_PRED_SEARCH_LOGS |
|
26 #include "predictivesearchlog.h" |
|
27 |
|
28 |
|
29 // Max amount of tokens stored from contact |
|
30 const TInt KMaxTokens = 4; |
|
31 |
|
32 // How many digits are stored at most in the numeric field |
|
33 // Since BIGINT is a signed 64-bit integer, store only 15 hexadecimal characters |
|
34 // to prevent overflow when comparing upper and lower limits. |
|
35 const TInt KMaxTokenLength = 15; |
|
36 |
|
37 const quint64 KConversionError = 0xeeeeeeeeeeeeeee; |
|
38 |
|
39 #define MAPPED_CHAR_FOR_STAR 'a' |
|
40 #define MAPPED_CHAR_FOR_HASH 'b' |
|
41 |
|
42 const QChar KPadChar = 'f'; // Pad with hex-digit 0xF |
|
43 |
|
44 |
|
45 /** |
|
46 @param aDatabase A handle to the database. |
|
47 |
|
48 @return A pointer to a new C12keyPredictiveSearchTable object. |
|
49 */ |
|
50 C12keyPredictiveSearchTable* |
|
51 C12keyPredictiveSearchTable::NewL(RSqlDatabase& aDatabase) |
|
52 { |
|
53 PRINT(_L("C12keyPredictiveSearchTable::NewL")); |
|
54 C12keyPredictiveSearchTable* self = C12keyPredictiveSearchTable::NewLC(aDatabase); |
|
55 CleanupStack::Pop(self); |
|
56 PRINT(_L("C12keyPredictiveSearchTable::NewL ends")); |
|
57 return self; |
|
58 } |
|
59 |
|
60 |
|
61 /** |
|
62 @param aDatabase A handle to the database. |
|
63 |
|
64 @return A pointer to a new C12keyPredictiveSearchTable object. |
|
65 */ |
|
66 C12keyPredictiveSearchTable* |
|
67 C12keyPredictiveSearchTable::NewLC(RSqlDatabase& aDatabase) |
|
68 { |
|
69 PRINT(_L("C12keyPredictiveSearchTable::NewLC")); |
|
70 C12keyPredictiveSearchTable* self = |
|
71 new (ELeave) C12keyPredictiveSearchTable(aDatabase); |
|
72 CleanupStack::PushL(self); |
|
73 self->ConstructL(); |
|
74 PRINT(_L("C12keyPredictiveSearchTable::NewLC ends")); |
|
75 return self; |
|
76 } |
|
77 |
|
78 |
|
79 /** |
|
80 Destructor |
|
81 */ |
|
82 C12keyPredictiveSearchTable::~C12keyPredictiveSearchTable() |
|
83 { |
|
84 PRINT(_L("C12keyPredictiveSearchTable dtor")); |
|
85 PRINT(_L("C12keyPredictiveSearchTable dtor ends")); |
|
86 } |
|
87 |
|
88 |
|
89 /** |
|
90 Creates the 12-key predictive search tables and its indexes in the database. |
|
91 */ |
|
92 void C12keyPredictiveSearchTable::CreateTableL() |
|
93 { |
|
94 PRINT(_L("C12keyPredictiveSearchTable::CreateTableL")); |
|
95 |
|
96 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable0Stmnt)); |
|
97 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable1Stmnt)); |
|
98 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable2Stmnt)); |
|
99 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable3Stmnt)); |
|
100 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable4Stmnt)); |
|
101 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable5Stmnt)); |
|
102 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable6Stmnt)); |
|
103 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable7Stmnt)); |
|
104 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable8Stmnt)); |
|
105 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable9Stmnt)); |
|
106 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable10Stmnt)); |
|
107 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateTable11Stmnt)); |
|
108 |
|
109 |
|
110 PRINT(_L("Create indexes")); |
|
111 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable0)); |
|
112 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable0)); |
|
113 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable0)); |
|
114 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable0)); |
|
115 |
|
116 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable1)); |
|
117 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable1)); |
|
118 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable1)); |
|
119 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable1)); |
|
120 |
|
121 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable2)); |
|
122 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable2)); |
|
123 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable2)); |
|
124 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable2)); |
|
125 |
|
126 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable3)); |
|
127 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable3)); |
|
128 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable3)); |
|
129 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable3)); |
|
130 |
|
131 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable4)); |
|
132 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable4)); |
|
133 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable4)); |
|
134 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable4)); |
|
135 |
|
136 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable5)); |
|
137 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable5)); |
|
138 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable5)); |
|
139 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable5)); |
|
140 |
|
141 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable6)); |
|
142 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable6)); |
|
143 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable6)); |
|
144 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable6)); |
|
145 |
|
146 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable7)); |
|
147 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable7)); |
|
148 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable7)); |
|
149 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable7)); |
|
150 |
|
151 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable8)); |
|
152 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable8)); |
|
153 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable8)); |
|
154 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable8)); |
|
155 |
|
156 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable9)); |
|
157 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable9)); |
|
158 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable9)); |
|
159 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable9)); |
|
160 |
|
161 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable10)); |
|
162 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable10)); |
|
163 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable10)); |
|
164 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable10)); |
|
165 |
|
166 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbrIndexTable11)); |
|
167 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr2IndexTable11)); |
|
168 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr3IndexTable11)); |
|
169 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateNbr4IndexTable11)); |
|
170 |
|
171 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable0)); |
|
172 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable0)); |
|
173 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable1)); |
|
174 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable1)); |
|
175 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable2)); |
|
176 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable2)); |
|
177 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable3)); |
|
178 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable3)); |
|
179 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable4)); |
|
180 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable4)); |
|
181 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable5)); |
|
182 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable5)); |
|
183 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable6)); |
|
184 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable6)); |
|
185 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable7)); |
|
186 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable7)); |
|
187 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable8)); |
|
188 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable8)); |
|
189 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable9)); |
|
190 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable9)); |
|
191 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable10)); |
|
192 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable10)); |
|
193 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateFNIndexInTable11)); |
|
194 User::LeaveIfError(iDatabase.Exec(KPredSearchCreateLNIndexInTable11)); |
|
195 |
|
196 PRINT(_L("C12keyPredictiveSearchTable::CreateTableL ends")); |
|
197 } |
|
198 |
|
199 |
|
200 QList<QChar> C12keyPredictiveSearchTable::FillAllTables() const |
|
201 { |
|
202 QList<QChar> tables; |
|
203 |
|
204 const TInt KLargestDigitKey = '9'; |
|
205 for (TInt i = '0'; i <= KLargestDigitKey; ++i) |
|
206 { |
|
207 QChar ch = i; |
|
208 tables.append(ch); |
|
209 } |
|
210 tables.append(MAPPED_CHAR_FOR_STAR); |
|
211 tables.append(MAPPED_CHAR_FOR_HASH); |
|
212 |
|
213 return tables; |
|
214 } |
|
215 |
|
216 |
|
217 HBufC* C12keyPredictiveSearchTable::TableNameL(const QChar aCh) const |
|
218 { |
|
219 // Enough space for the longest table name |
|
220 HBufC* tableName = HBufC::NewLC(KSqlContactPredSearchTable11().Length()); |
|
221 TPtr ptr = tableName->Des(); |
|
222 ptr.Append(GetTableNameL(aCh)); |
|
223 CleanupStack::Pop(tableName); |
|
224 return tableName; |
|
225 } |
|
226 |
|
227 |
|
228 TBool C12keyPredictiveSearchTable::IsValidChar(const QChar aChar) const |
|
229 { |
|
230 return (aChar >= '0' && aChar <= '9') || |
|
231 aChar == MAPPED_CHAR_FOR_STAR || |
|
232 aChar == MAPPED_CHAR_FOR_HASH; |
|
233 } |
|
234 |
|
235 |
|
236 void C12keyPredictiveSearchTable::FillKeyboardSpecificFieldsL( |
|
237 RSqlStatement& aSqlStatement, |
|
238 QStringList aTokens) |
|
239 { |
|
240 const TDesC* paramNames[] = { |
|
241 &KPredSearchNameAsNumberParam, |
|
242 &KPredSearchNameAsNumber2Param, |
|
243 &KPredSearchNameAsNumber3Param, |
|
244 &KPredSearchNameAsNumber4Param}; |
|
245 for (TInt i = 0; i < aTokens.count(); ++i) |
|
246 { |
|
247 quint64 hex(0); |
|
248 QT_TRYCATCH_LEAVING(hex = ConvertToHex(aTokens[i])); |
|
249 if (hex == KConversionError) |
|
250 { |
|
251 User::Leave(KErrArgument); |
|
252 } |
|
253 User::LeaveIfError(aSqlStatement.BindInt64( |
|
254 User::LeaveIfError(aSqlStatement.ParameterIndex(*paramNames[i])), hex)); |
|
255 } |
|
256 } |
|
257 |
|
258 |
|
259 /** |
|
260 Set up the CCntSqlStatement objects held by the class. |
|
261 */ |
|
262 void C12keyPredictiveSearchTable::ConstructL() |
|
263 { |
|
264 PRINT(_L("C12keyPredictiveSearchTable::ConstructL")); |
|
265 |
|
266 CPplPredictiveSearchTableBase::ConstructL(); |
|
267 // Set details of INSERT |
|
268 iInsertStmnt->SetParamL(KPredSearchContactId, |
|
269 KPredSearchContactIdParam); |
|
270 iInsertStmnt->SetParamL(KPredSearchNameAsNumber, |
|
271 KPredSearchNameAsNumberParam); |
|
272 iInsertStmnt->SetParamL(KPredSearchNameAsNumber2, |
|
273 KPredSearchNameAsNumber2Param); |
|
274 iInsertStmnt->SetParamL(KPredSearchNameAsNumber3, |
|
275 KPredSearchNameAsNumber3Param); |
|
276 iInsertStmnt->SetParamL(KPredSearchNameAsNumber4, |
|
277 KPredSearchNameAsNumber4Param); |
|
278 iInsertStmnt->SetParamL(KPredSearchFirstName, |
|
279 KPredSearchFirstNameParam); |
|
280 iInsertStmnt->SetParamL(KPredSearchLastName, |
|
281 KPredSearchLastNameParam); |
|
282 |
|
283 PRINT(_L("C12keyPredictiveSearchTable::ConstructL create key map")); |
|
284 iKeyMap = C12keyKeyMap::NewL(); |
|
285 |
|
286 PRINT(_L("C12keyPredictiveSearchTable::ConstructL ends")); |
|
287 } |
|
288 |
|
289 |
|
290 /** |
|
291 Constructor |
|
292 */ |
|
293 C12keyPredictiveSearchTable::C12keyPredictiveSearchTable(RSqlDatabase& aDatabase) : |
|
294 CPplPredictiveSearchTableBase(aDatabase, KMaxTokens, KMaxTokenLength) |
|
295 { |
|
296 } |
|
297 |
|
298 |
|
299 // TODO: maybe move this fn to CPcsKeyMap, and it can use code of GetNumericLimits() |
|
300 |
|
301 // E.g. aToken = "01230" -> append KPadChar until has KMaxTokenLength characters |
|
302 // -> "01230ffffffffff" -> convert to hexadecimal number -> 0x01230ffffffffff. |
|
303 // If this function would leave, causes panic, perhaps because of QString parameter? |
|
304 quint64 C12keyPredictiveSearchTable::ConvertToHex(QString aToken) const |
|
305 { |
|
306 if (aToken.length() > KMaxTokenLength) |
|
307 { |
|
308 return KConversionError; |
|
309 } |
|
310 QString padded = aToken.leftJustified(KMaxTokenLength, KPadChar); |
|
311 |
|
312 TBuf<KMaxTokenLength> log(padded.utf16()); |
|
313 PRINT1(_L("C12keyPredictiveSearchTable::ConvertToHex padded '%S'"), &log); |
|
314 |
|
315 // Replace unmapped char and the following characters with KPadChar. |
|
316 QString replaced = padded; |
|
317 bool done(false); |
|
318 for (TInt i = 0; i < KMaxTokenLength && !done; ++i) |
|
319 { |
|
320 if (!IsValidChar(padded[i])) |
|
321 { |
|
322 // replace() does not work, it puts just one KPadChar at end |
|
323 // replaced = padded.replace(i, KMaxTokenLength - i, KPadChar); |
|
324 |
|
325 padded.remove(i, KMaxTokenLength - i); |
|
326 replaced = padded.leftJustified(KMaxTokenLength, KPadChar); |
|
327 done = true; |
|
328 |
|
329 TBuf<KMaxTokenLength> log2(replaced.utf16()); |
|
330 PRINT1(_L("After replacing '%S'"), &log2); |
|
331 } |
|
332 } |
|
333 |
|
334 const TInt KHexadecimalBase = 16; |
|
335 bool ok(true); |
|
336 quint64 hex = replaced.toULongLong(&ok, KHexadecimalBase); |
|
337 if (!ok) |
|
338 { |
|
339 PRINT(_L("conv to hex failed")); |
|
340 return KConversionError; |
|
341 } |
|
342 |
|
343 PRINT1(_L("C12keyPredictiveSearchTable::ConvertToHex result 0x%lx"), hex); |
|
344 return hex; |
|
345 } |
|
346 |
|
347 |
|
348 const TDesC& C12keyPredictiveSearchTable::GetTableNameL(const QChar aCh) const |
|
349 { |
|
350 switch (aCh.toAscii()) |
|
351 { |
|
352 case '0': return KSqlContactPredSearchTable0; |
|
353 case '1': return KSqlContactPredSearchTable1; |
|
354 case '2': return KSqlContactPredSearchTable2; |
|
355 case '3': return KSqlContactPredSearchTable3; |
|
356 case '4': return KSqlContactPredSearchTable4; |
|
357 case '5': return KSqlContactPredSearchTable5; |
|
358 case '6': return KSqlContactPredSearchTable6; |
|
359 case '7': return KSqlContactPredSearchTable7; |
|
360 case '8': return KSqlContactPredSearchTable8; |
|
361 case '9': return KSqlContactPredSearchTable9; |
|
362 case MAPPED_CHAR_FOR_STAR: return KSqlContactPredSearchTable10; |
|
363 case MAPPED_CHAR_FOR_HASH: return KSqlContactPredSearchTable11; |
|
364 default: |
|
365 PRINT1(_L("C12keyPredictiveSearchTable::GetTableNameL unknown char '%c'"), |
|
366 aCh.toAscii()); |
|
367 User::Leave(KErrArgument); |
|
368 return KNullDesC; |
|
369 } |
|
370 } |