|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include "dscdatabase_sql.h" |
|
17 #include "dscitem.h" |
|
18 #include <e32debug.h> |
|
19 #include <e32math.h> |
|
20 #include <f32file.h> |
|
21 #include "e32modes.h" |
|
22 |
|
23 |
|
24 //DSC Database name |
|
25 _LIT(KDatabaseName, "%s:[2000836D]DBS_DSC.db"); |
|
26 //Table name |
|
27 _LIT(KDscTable, "DSC"); |
|
28 _LIT(KItemTable, "DscItem"); |
|
29 //Column name |
|
30 _LIT(KDscIdCol, "DscId"); |
|
31 _LIT(KDescriptionCol, "Description"); |
|
32 _LIT(KItemIdCol, "ItemId"); |
|
33 _LIT(KFileNameCol, "FileName"); |
|
34 _LIT(KArgListCol, "ArgList"); |
|
35 _LIT(KStartMethodCol, "StartMethod"); |
|
36 _LIT(KTimeoutCol, "Timeout"); |
|
37 _LIT(KNoOfRetriesCol, "NoOfRetries"); |
|
38 _LIT(KMonitorCol, "Monitored"); |
|
39 _LIT(KStartupTypeCol, "StartupType"); |
|
40 _LIT(KViewlessCol, "Viewless"); |
|
41 _LIT(KStartInBackgroundCol, "StartInBackground"); |
|
42 |
|
43 |
|
44 _LIT8(KBeginTrans, "BEGIN"); |
|
45 _LIT8(KRollbackTrans, "ROLLBACK"); |
|
46 _LIT8(KCommitTrans, "COMMIT"); |
|
47 |
|
48 /** |
|
49 The maximum length for DBMS varchar: 255 characters. |
|
50 @internalTechnology |
|
51 @released |
|
52 */ |
|
53 const TInt KDscStoreMaxStringLength =255; |
|
54 |
|
55 //length of characters in TUint 32 |
|
56 //This is used to calculate the length of sqlCmd in order to allocate adequate buffer. |
|
57 //characters in TUint32 and TInt32 |
|
58 //This is used to calculate the length of sqlCmd in order to allocate adequate buffer. |
|
59 const TInt lengthOfTUint=10; |
|
60 const TInt lengthOfTInt=11; |
|
61 |
|
62 //The maximum characters in DSC database name |
|
63 const TInt KMaxDatabaseName=40; |
|
64 |
|
65 CDscDatabase* CDscDatabase::NewL() |
|
66 { |
|
67 CDscDatabase* db = new(ELeave) CDscDatabase(); |
|
68 CleanupStack::PushL(db); |
|
69 |
|
70 db->ConstructL(); |
|
71 |
|
72 CleanupStack::Pop(db); |
|
73 return db; |
|
74 } |
|
75 |
|
76 //Second phase constructor, Open connection to Dscdatabase. |
|
77 //If DSC database doesn't exist, create it. |
|
78 void CDscDatabase::ConstructL() |
|
79 { |
|
80 |
|
81 TBuf<KMaxDatabaseName> databaseName; |
|
82 GetDatabaseName(databaseName); |
|
83 |
|
84 //Open DSC database |
|
85 TInt error=iDatabase.Open(databaseName ); |
|
86 |
|
87 if (KErrNotFound!=error) //Dsc Database exists |
|
88 { |
|
89 //If open with error. Leave with error code return from SQLite |
|
90 User::LeaveIfError(ConvertErrCode(error)); |
|
91 //Opened successfully |
|
92 return; |
|
93 } |
|
94 |
|
95 //DscDatabase doesn't exist |
|
96 //Create security policy: Read: ReadDeviceData, Write: WriteDeviceData, |
|
97 //Schema: ReadDeviceData and WriteDeviceData |
|
98 TSecurityPolicy defaultPolicy; |
|
99 RSqlSecurityPolicy securityPolicy; |
|
100 CleanupClosePushL(securityPolicy); |
|
101 User::LeaveIfError(securityPolicy.Create(defaultPolicy)); |
|
102 |
|
103 const TSecurityPolicy KSchemePolicy(ECapabilityReadDeviceData, ECapabilityWriteDeviceData); |
|
104 const TSecurityPolicy KReadPolicy(ECapabilityReadDeviceData); |
|
105 const TSecurityPolicy KWritePolicy(ECapabilityWriteDeviceData); |
|
106 |
|
107 User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy,KSchemePolicy)); |
|
108 User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy,KWritePolicy)); |
|
109 User::LeaveIfError(securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy,KReadPolicy)); |
|
110 |
|
111 //Create DSC database according to security policy. |
|
112 User::LeaveIfError(iDatabase.Create(databaseName, securityPolicy)); |
|
113 |
|
114 CleanupStack::PopAndDestroy(&securityPolicy); |
|
115 |
|
116 //Create tables for DSC database |
|
117 TRAP(error,CreateTablesL()); |
|
118 |
|
119 if (KErrNone > error) |
|
120 { |
|
121 //Fail to create tables, destroy the DB, so next time can recreate it |
|
122 DeleteDb(); |
|
123 } |
|
124 User::LeaveIfError(error); |
|
125 } |
|
126 |
|
127 //Default constructor |
|
128 CDscDatabase::CDscDatabase():iIsEnumOpened(EFalse) |
|
129 { |
|
130 } |
|
131 |
|
132 CDscDatabase::~CDscDatabase() |
|
133 { |
|
134 iStmt.Close(); |
|
135 iDatabase.Close(); |
|
136 } |
|
137 |
|
138 //Destroy DSC database, |
|
139 TInt CDscDatabase::DeleteDb() |
|
140 { |
|
141 iDatabase.Close(); |
|
142 |
|
143 TBuf<KMaxDatabaseName> databaseName; |
|
144 GetDatabaseName(databaseName); |
|
145 return iDatabase.Delete(databaseName); |
|
146 } |
|
147 |
|
148 void CDscDatabase::CreateTablesL() |
|
149 { |
|
150 RBuf sqlCmd; |
|
151 CleanupClosePushL(sqlCmd); |
|
152 //Allocate memory for create item table sql cmd which has the most characters. |
|
153 _LIT(KCreateItemTable,"CREATE TABLE %S (%S INTEGER NOT NULL, %S INTEGER NOT NULL, %S VARCHAR (%d)NOT NULL,\ |
|
154 %S VARCHAR(%d), %S TINYINT, %S INTEGER, %S INTEGER, %S BIT, %S TINYINT, %S BIT, %S BIT, \ |
|
155 UNIQUE(%S, %S))"); |
|
156 //the extra characters for the %S, %d in the format string |
|
157 const TInt extraLength=32; |
|
158 //chars in KDscStoreMaxStringLength |
|
159 const TInt lengthOfKDscStoreMaxStringLength=3; |
|
160 |
|
161 // The maximum number of characters for create table DscItem sql command |
|
162 const TInt length=KCreateItemTable().Length()+KItemTable().Length()+KDscIdCol().Length()+KItemIdCol().Length()+ |
|
163 KFileNameCol().Length()+KArgListCol().Length()+ |
|
164 KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length()+KMonitorCol().Length()+ |
|
165 KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length()+ |
|
166 KDscIdCol().Length()+KItemIdCol().Length()-extraLength+2* lengthOfKDscStoreMaxStringLength; |
|
167 |
|
168 sqlCmd.CreateL(length); |
|
169 |
|
170 //format a sql cmd for create table dsc |
|
171 _LIT(KCreateDscTable,"CREATE TABLE %S (%S INTEGER NOT NULL, %S VARCHAR(%d), PRIMARY KEY(%S))"); |
|
172 sqlCmd.Format(KCreateDscTable,&KDscTable,&KDscIdCol,&KDescriptionCol, KDscStoreMaxStringLength, &KDscIdCol); |
|
173 |
|
174 |
|
175 PrintSqlCmd(sqlCmd); |
|
176 |
|
177 //Start a new transaction |
|
178 DatabaseBeginLC(); |
|
179 |
|
180 //Create Table DSC |
|
181 TInt error=iDatabase.Exec(sqlCmd); |
|
182 User::LeaveIfError(ConvertErrCode(error)); |
|
183 |
|
184 //Create Table DscItem |
|
185 |
|
186 sqlCmd.Format(KCreateItemTable,&KItemTable,&KDscIdCol, &KItemIdCol,&KFileNameCol,KDscStoreMaxStringLength,&KArgListCol, |
|
187 KDscStoreMaxStringLength, &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, |
|
188 &KViewlessCol, &KStartInBackgroundCol, &KDscIdCol, &KItemIdCol); |
|
189 |
|
190 PrintSqlCmd(sqlCmd); |
|
191 |
|
192 error=iDatabase.Exec(sqlCmd); |
|
193 User::LeaveIfError(ConvertErrCode(error)); |
|
194 DatabaseCommitLP(); |
|
195 CleanupStack::PopAndDestroy(&sqlCmd); |
|
196 |
|
197 |
|
198 |
|
199 } |
|
200 |
|
201 #ifdef _DEBUG |
|
202 //Help, print out SQL message |
|
203 void CDscDatabase::PrintSqlCmd(const TDesC& aMess) const |
|
204 { |
|
205 RDebug::RawPrint(aMess); |
|
206 } |
|
207 #else |
|
208 void CDscDatabase::PrintSqlCmd(const TDesC& /*aMess*/) const |
|
209 { |
|
210 |
|
211 } |
|
212 #endif |
|
213 |
|
214 //Add a DSC with aDscId to DSC DB. if the aDscId exists, leave with KErrAlreadyExists |
|
215 void CDscDatabase::CreateDscL(const TUid& aDscId, const TDesC& aDescription) |
|
216 { |
|
217 //If the DSC is opened for enumeration, leave with KErrLocked |
|
218 if (iIsEnumOpened) |
|
219 { |
|
220 User::Leave( KErrLocked); |
|
221 } |
|
222 |
|
223 //Start a new transaction |
|
224 DatabaseBeginLC(); |
|
225 |
|
226 //Insert aDscId in Table DSC. If aDscId exists, leave with KErrAlreadyExists |
|
227 RBuf sqlCmd; |
|
228 CleanupClosePushL(sqlCmd); |
|
229 |
|
230 _LIT(KSQLQuery,"INSERT INTO %S (%S,%S) VALUES (%d,'%S')"); |
|
231 |
|
232 //Allocate memory for insert sql cmd |
|
233 const TInt length=KSQLQuery().Length()+ KDscTable().Length()+KDscIdCol().Length()+ |
|
234 KDescriptionCol().Length()+aDescription.Length(); |
|
235 sqlCmd.CreateL(length); |
|
236 |
|
237 |
|
238 sqlCmd.Format(KSQLQuery,&KDscTable,&KDscIdCol,&KDescriptionCol, aDscId, &aDescription); |
|
239 |
|
240 PrintSqlCmd(sqlCmd); |
|
241 |
|
242 TInt error=iDatabase.Exec(sqlCmd); |
|
243 CleanupStack::PopAndDestroy(&sqlCmd); |
|
244 User::LeaveIfError(ConvertErrCode(error)); |
|
245 |
|
246 DatabaseCommitLP(); |
|
247 } |
|
248 |
|
249 //Delete the DSC with aDscId, all items related to aDscId are deleted too. |
|
250 void CDscDatabase::DeleteDscL(const TUid& aDscId) |
|
251 { |
|
252 //If the DSC is opened for enumeration, leave with KErrLocked |
|
253 if (iIsEnumOpened) |
|
254 { |
|
255 User::Leave(KErrLocked); |
|
256 } |
|
257 |
|
258 //Start a new transaction |
|
259 DatabaseBeginLC(); |
|
260 if (!DscExistsL(aDscId)) |
|
261 { |
|
262 // aDscId doesn't exist, leave with KErrNotFound |
|
263 User::Leave(KErrNotFound); |
|
264 } |
|
265 |
|
266 //Delete all items related with aDscId first |
|
267 _LIT(KSQLQuery,"DELETE FROM %S WHERE %S=%d "); |
|
268 RBuf sqlCmd; |
|
269 CleanupClosePushL(sqlCmd); |
|
270 |
|
271 // the extra characters for the %S, %d in the format string |
|
272 const TInt extraLength=6; |
|
273 //Allocate memory for delete sql cmd |
|
274 const TInt length=KSQLQuery().Length()+ KItemTable().Length()+KDscIdCol().Length()+ |
|
275 lengthOfTUint-extraLength ; |
|
276 sqlCmd.CreateL(length); |
|
277 sqlCmd.Format(KSQLQuery,&KItemTable,&KDscIdCol,aDscId); |
|
278 TInt error=iDatabase.Exec(sqlCmd); |
|
279 User::LeaveIfError(ConvertErrCode(error)); |
|
280 |
|
281 //Delete aDscId from Table DSC |
|
282 sqlCmd.Format(KSQLQuery,&KDscTable,&KDscIdCol,aDscId); |
|
283 error=iDatabase.Exec(sqlCmd); |
|
284 User::LeaveIfError(ConvertErrCode(error)); |
|
285 CleanupStack::PopAndDestroy(&sqlCmd); |
|
286 DatabaseCommitLP(); |
|
287 } |
|
288 |
|
289 //Check the existance of the aDscId |
|
290 TBool CDscDatabase::DscExistsL(const TUid& aDscId) const |
|
291 { |
|
292 |
|
293 RSqlStatement stmt; |
|
294 CleanupClosePushL(stmt); |
|
295 |
|
296 _LIT(KSQLQuery,"SELECT %S FROM %S WHERE %S=%d "); |
|
297 |
|
298 RBuf sqlCmd; |
|
299 CleanupClosePushL(sqlCmd); |
|
300 |
|
301 // the extra characters for the %S, %d in the format string |
|
302 const TInt extraLength=8; |
|
303 //Allocate memory for delete sql cmd |
|
304 const TInt length=KSQLQuery().Length()+ KDscTable().Length()+2*KDscIdCol().Length()+ |
|
305 lengthOfTUint-extraLength ; |
|
306 sqlCmd.CreateL(length); |
|
307 sqlCmd.Format(KSQLQuery, &KDscIdCol, &KDscTable,&KDscIdCol,aDscId); |
|
308 |
|
309 TInt error=stmt.Prepare(iDatabase, sqlCmd); |
|
310 CleanupStack::PopAndDestroy(&sqlCmd); |
|
311 |
|
312 User::LeaveIfError(ConvertErrCode(error)); |
|
313 |
|
314 error=stmt.Next(); |
|
315 User::LeaveIfError(ConvertErrCode(error)); |
|
316 |
|
317 CleanupStack::PopAndDestroy(&stmt); |
|
318 return KSqlAtRow==error ? ETrue:EFalse; |
|
319 } |
|
320 |
|
321 //Check the existance of aItem |
|
322 TBool CDscDatabase::ItemExistsL( const CDscItem& aItem) const |
|
323 { |
|
324 |
|
325 RSqlStatement stmt; |
|
326 CleanupClosePushL(stmt); |
|
327 |
|
328 TBool result=QueryItemL(stmt, aItem); |
|
329 |
|
330 |
|
331 |
|
332 CleanupStack::PopAndDestroy(&stmt); |
|
333 |
|
334 return result; |
|
335 } |
|
336 |
|
337 //Query the aItem from Table DscItem |
|
338 TBool CDscDatabase::QueryItemL(RSqlStatement& aStmt, const CDscItem& aItem) const |
|
339 { |
|
340 |
|
341 RBuf sqlCmd; |
|
342 CleanupClosePushL(sqlCmd); |
|
343 |
|
344 |
|
345 TUid dscId=aItem.DscId(); |
|
346 TPtrC name=aItem.FileName(); |
|
347 |
|
348 //If fileName is NULL, query aItem by DSC ID and ItemId |
|
349 if (name ==KNullDesC) |
|
350 { |
|
351 _LIT(KSQLQuery,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d AND %S=%d "); |
|
352 // the extra characters for the %S, %d in the format string |
|
353 const TInt extraLength=32; |
|
354 //Allocate memory for search sql cmd |
|
355 const TInt length=KSQLQuery().Length()+2*KDscIdCol().Length()+KItemIdCol().Length()+ KFileNameCol().Length() |
|
356 +KArgListCol().Length()+KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length() |
|
357 +KMonitorCol().Length()+KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length() |
|
358 +KItemTable().Length()+lengthOfTInt+lengthOfTUint+KItemIdCol().Length()-extraLength; |
|
359 sqlCmd.CreateL(length); |
|
360 sqlCmd.Format(KSQLQuery,&KDscIdCol, &KItemIdCol,&KFileNameCol,&KArgListCol, |
|
361 &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, |
|
362 &KViewlessCol, &KStartInBackgroundCol, &KItemTable,&KDscIdCol, dscId, &KItemIdCol,aItem.ItemId()); |
|
363 } |
|
364 //Otherwise query aItem by DSC ID, fileName and arguments |
|
365 else |
|
366 { |
|
367 if(name.Length() >KDscStoreMaxStringLength || aItem.Args().Length() >KDscStoreMaxStringLength) |
|
368 { |
|
369 User::Leave(KErrArgument); |
|
370 } |
|
371 |
|
372 TBuf<KDscStoreMaxStringLength> argList=aItem.Args(); |
|
373 argList.TrimAll(); |
|
374 |
|
375 _LIT(KSQLQuery,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d AND %S= '%S' AND %S = '%S' "); |
|
376 // the extra characters for the %S, %d in the format string |
|
377 const TInt extraLength=36; |
|
378 //Allocate memory for search sql cmd |
|
379 const TInt length=KSQLQuery().Length()+2*KDscIdCol().Length()+KItemIdCol().Length()+ KFileNameCol().Length() |
|
380 +KArgListCol().Length()+KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length() |
|
381 +KMonitorCol().Length()+KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length() |
|
382 +KItemTable().Length()+lengthOfTUint+KFileNameCol().Length()+aItem.FileName().Length() |
|
383 +KArgListCol().Length()+argList.Length()-extraLength; |
|
384 sqlCmd.CreateL(length); |
|
385 sqlCmd.Format(KSQLQuery,&KDscIdCol, &KItemIdCol,&KFileNameCol,&KArgListCol, &KStartMethodCol, &KTimeoutCol, |
|
386 &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol,&KViewlessCol, &KStartInBackgroundCol, |
|
387 &KItemTable,&KDscIdCol, dscId, &KFileNameCol,&name, &KArgListCol, &argList); |
|
388 } |
|
389 |
|
390 |
|
391 PrintSqlCmd(sqlCmd); |
|
392 |
|
393 |
|
394 TInt error=aStmt.Prepare(iDatabase, sqlCmd); |
|
395 CleanupStack::PopAndDestroy(&sqlCmd); |
|
396 if(KErrNone <= error) |
|
397 { |
|
398 error=aStmt.Next(); //no error for non existing item |
|
399 } |
|
400 |
|
401 return KSqlAtRow==error? ETrue: EFalse; |
|
402 } |
|
403 |
|
404 //Open a result set of items with aDscID for enumeration, need to |
|
405 //call EnumClose() to close the set after enumeration. |
|
406 void CDscDatabase::EnumOpenLC(const TUid& aDscId) |
|
407 { |
|
408 //If the DSC is opened for enumeration, leave with KErrLocked |
|
409 if (iIsEnumOpened) |
|
410 { |
|
411 User::Leave(KErrLocked); |
|
412 } |
|
413 EnumBeginLC(); |
|
414 iIsEnumOpened=ETrue; |
|
415 |
|
416 //Leave with KErrNotFound if aDscId doesn't exist |
|
417 if (!DscExistsL(aDscId)) |
|
418 { |
|
419 User::Leave(KErrNotFound); |
|
420 } |
|
421 |
|
422 RBuf sqlCmd; |
|
423 CleanupClosePushL(sqlCmd); |
|
424 _LIT(KSQLQuery,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d ORDER BY %S"); |
|
425 // the extra characters for the %S, %d in the format string |
|
426 const TInt extraLength=30; |
|
427 //Allocate memory for delete sql cmd |
|
428 const TInt length=KSQLQuery().Length()+ 2*KDscIdCol().Length()+2*KItemIdCol().Length()+ KFileNameCol().Length() |
|
429 +KArgListCol().Length()+KStartMethodCol().Length()+KTimeoutCol().Length()+KNoOfRetriesCol().Length() |
|
430 +KMonitorCol().Length()+KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length() |
|
431 +KItemTable().Length()+lengthOfTUint-extraLength; |
|
432 sqlCmd.CreateL(length); |
|
433 sqlCmd.Format(KSQLQuery, &KDscIdCol, &KItemIdCol,&KFileNameCol,&KArgListCol, |
|
434 &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, |
|
435 &KViewlessCol, &KStartInBackgroundCol,&KItemTable,&KDscIdCol,aDscId, &KItemIdCol); |
|
436 |
|
437 |
|
438 //Open a result stmt contains all items in aDscId |
|
439 TInt error=iStmt.Prepare(iDatabase, sqlCmd); |
|
440 CleanupStack::PopAndDestroy(&sqlCmd); |
|
441 User::LeaveIfError(ConvertErrCode(error)); |
|
442 } |
|
443 |
|
444 //Enumrating the result stmt opened by EnumOpenLC(), if there are no item in the DSC |
|
445 //or has reached the end of the list, return NULL |
|
446 CDscItem* CDscDatabase::EnumReadNextL() |
|
447 { |
|
448 if (!iIsEnumOpened) |
|
449 { |
|
450 //EnumOpenLC() has not been called. |
|
451 User::Leave(KErrNotReady); |
|
452 } |
|
453 TInt err=iStmt.Next(); |
|
454 User::LeaveIfError(ConvertErrCode(err)); |
|
455 |
|
456 if (KSqlAtEnd==err) |
|
457 { |
|
458 //reached to the end of the result set |
|
459 return NULL; |
|
460 } |
|
461 |
|
462 //Read item from the result stmt |
|
463 CDscItem* item=CDscItem::NewL(); |
|
464 CleanupStack::PushL(item); |
|
465 ReadDscItemL(iStmt, *item); |
|
466 CleanupStack::Pop(item); |
|
467 return item; |
|
468 } |
|
469 |
|
470 //Read aItem from the stmt |
|
471 void CDscDatabase::ReadDscItemL(RSqlStatement& aStmt, CDscItem& aItem) |
|
472 { |
|
473 TPtrC name=aStmt.ColumnTextL(2); |
|
474 TPtrC args=aStmt.ColumnTextL(3); |
|
475 aItem.SetDscId(TUid::Uid(aStmt.ColumnInt(0))); |
|
476 aItem.SetItemId(aStmt.ColumnInt(1)); |
|
477 aItem.SetFileParamsL(name, args); |
|
478 aItem.SetStartMethodL(static_cast<TStartMethod> (aStmt.ColumnInt(4))); |
|
479 aItem.SetFailureParams(aStmt.ColumnInt(6), aStmt.ColumnInt(5)); |
|
480 aItem.SetMonitored(aStmt.ColumnInt(7)); |
|
481 aItem.SetStartupType(static_cast<TStartupType> (aStmt.ColumnInt(8))); |
|
482 aItem.SetViewless(aStmt.ColumnInt(9)); |
|
483 aItem.SetStartInBackground( aStmt.ColumnInt(10)); |
|
484 } |
|
485 |
|
486 |
|
487 //Close the view opened by EnumOpenLC() and rollback the transaction |
|
488 void CDscDatabase::EnumClose() |
|
489 { |
|
490 //To avoid double close |
|
491 if (iIsEnumOpened) |
|
492 { |
|
493 iStmt.Close(); |
|
494 iIsEnumOpened=EFalse; |
|
495 |
|
496 //Roll back transaction |
|
497 Rollback(); |
|
498 CleanupStack::Pop();//Pop client CleanupEnumRollback |
|
499 } |
|
500 } |
|
501 |
|
502 //Add aItem to DSC at aPos |
|
503 void CDscDatabase::AddItemL(CDscItem& aItem, TDscPosition aPos) |
|
504 { |
|
505 //Leave if DB is opened for enumeration |
|
506 if (iIsEnumOpened) |
|
507 { |
|
508 User::Leave(KErrLocked); |
|
509 } |
|
510 |
|
511 //verify data integrity |
|
512 VerifyDataL(aItem); |
|
513 |
|
514 DatabaseBeginLC(); |
|
515 |
|
516 TUid dscId=aItem.DscId(); |
|
517 //Leave if aDscId doesn't exist |
|
518 if (!DscExistsL(dscId)) |
|
519 { |
|
520 User::Leave(KErrNotFound); |
|
521 } |
|
522 //Leave if aItem exists |
|
523 if (ItemExistsL( aItem)) |
|
524 { |
|
525 User::Leave(KErrAlreadyExists); |
|
526 } |
|
527 |
|
528 RBuf sqlCmd; |
|
529 CleanupClosePushL(sqlCmd); |
|
530 //Allocate memory for insert item sql cmd which has the most characters. |
|
531 _LIT(KSQLQuery1,"INSERT INTO %S (%S,%S,%S,%S,%S,%S,%S,%S,%S, %S, %S ) VALUES \ |
|
532 (%d,%d,'%S','%S',%d,%d, %d, %b, %d, %b, %b)"); |
|
533 // the extra characters for the %S, %d in the format string |
|
534 const TInt extraLength=40; |
|
535 const TInt length=KSQLQuery1().Length()+KItemTable().Length()+KDscIdCol().Length()+KItemIdCol().Length() |
|
536 +KFileNameCol().Length()+KArgListCol().Length()+KStartMethodCol().Length() |
|
537 +KTimeoutCol().Length()+KNoOfRetriesCol().Length()+KMonitorCol().Length() |
|
538 +KStartupTypeCol().Length()+KViewlessCol().Length()+KStartInBackgroundCol().Length() |
|
539 +4*lengthOfTUint+ aItem.FileName().Length()+aItem.Args().Length()-extraLength; |
|
540 sqlCmd.CreateL(length); |
|
541 |
|
542 RSqlStatement stmt; |
|
543 CleanupClosePushL(stmt); |
|
544 |
|
545 |
|
546 //calculate item id according to the position to be inserted |
|
547 //add at ELast: pos =max of itemId+1 |
|
548 if (ELast==aPos ) |
|
549 { |
|
550 _LIT(KSQLQuery,"SELECT MAX(%S) FROM %S WHERE %S=%d "); |
|
551 sqlCmd.Format(KSQLQuery, &KItemIdCol, &KItemTable,&KDscIdCol, dscId ); |
|
552 } |
|
553 //add at EFirst: pos=min of itemId-1 |
|
554 else |
|
555 { |
|
556 _LIT(KSQLQuery,"SELECT MIN(%S) FROM %S WHERE %S=%d "); |
|
557 sqlCmd.Format(KSQLQuery, &KItemIdCol, &KItemTable,&KDscIdCol, dscId ); |
|
558 } |
|
559 |
|
560 |
|
561 PrintSqlCmd(sqlCmd); |
|
562 |
|
563 |
|
564 TInt err=stmt.Prepare(iDatabase, sqlCmd); |
|
565 User::LeaveIfError(ConvertErrCode(err)); |
|
566 err=stmt.Next(); |
|
567 User::LeaveIfError(ConvertErrCode(err)); |
|
568 |
|
569 //for empty DSC, 0 will be returned from the stmt, so the initial value |
|
570 //of itemId will be -1 or 1 depend on where to insert, |
|
571 //this is slightly different from DBMS implementation, where |
|
572 //initial value for itemId is always 0 |
|
573 //Since itemId is used as reference for relative orders, this should |
|
574 //be acceptable |
|
575 |
|
576 |
|
577 //Get the next available itemId for the item |
|
578 TInt itemId=GetItemIdL(aPos, stmt); |
|
579 |
|
580 CleanupStack::PopAndDestroy(&stmt); |
|
581 |
|
582 //set the item id, it will be return to client |
|
583 aItem.SetItemId(itemId); |
|
584 |
|
585 //insert item into DSC |
|
586 TPtrC name=aItem.FileName(); |
|
587 |
|
588 //Trim white space in argment list |
|
589 TBuf<KDscStoreMaxStringLength> argList=aItem.Args(); |
|
590 argList.TrimAll(); |
|
591 |
|
592 sqlCmd.Format(KSQLQuery1,&KItemTable,&KDscIdCol,&KItemIdCol,&KFileNameCol,&KArgListCol, |
|
593 &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, |
|
594 &KViewlessCol, &KStartInBackgroundCol, dscId,itemId,&name, &argList, aItem.StartMethod(), |
|
595 aItem.Timeout(), aItem.NoOfRetries(), aItem.Monitored(), |
|
596 aItem.StartupType(), aItem.Viewless(), aItem.StartInBackground()); |
|
597 |
|
598 |
|
599 PrintSqlCmd(sqlCmd); |
|
600 |
|
601 err=iDatabase.Exec(sqlCmd); |
|
602 CleanupStack::PopAndDestroy(&sqlCmd); |
|
603 User::LeaveIfError(ConvertErrCode(err)); |
|
604 |
|
605 DatabaseCommitLP(); |
|
606 } |
|
607 |
|
608 //Delete aItem from DSC |
|
609 void CDscDatabase::DeleteItemL( const CDscItem& aItem) |
|
610 { |
|
611 //Leave if DB is opened for enumeration |
|
612 if (iIsEnumOpened) |
|
613 { |
|
614 User::Leave(KErrLocked); |
|
615 } |
|
616 |
|
617 DatabaseBeginLC(); |
|
618 |
|
619 //Leave if aItem does not exist |
|
620 if (!ItemExistsL( aItem)) |
|
621 { |
|
622 User::Leave(KErrNotFound); |
|
623 } |
|
624 |
|
625 |
|
626 RBuf sqlCmd; |
|
627 CleanupClosePushL(sqlCmd); |
|
628 |
|
629 |
|
630 TPtrC name=aItem.FileName(); |
|
631 TUid dscId=aItem.DscId(); |
|
632 //Delete the item by itemId |
|
633 if (name==KNullDesC) |
|
634 { |
|
635 _LIT(KSQLQuery,"DELETE FROM %S WHERE %S=%d AND %S=%d "); |
|
636 // the extra characters for the %S, %d in the format string |
|
637 const TInt extraLength=10; |
|
638 const TInt length=KSQLQuery().Length()+KItemTable().Length()+KDscIdCol().Length()+2*lengthOfTUint |
|
639 +KItemIdCol().Length()-extraLength; |
|
640 sqlCmd.CreateL(length); |
|
641 |
|
642 sqlCmd.Format(KSQLQuery,&KItemTable,&KDscIdCol, dscId,&KItemIdCol,aItem.ItemId()); |
|
643 } |
|
644 //Delete the item by fileName + arguments |
|
645 else |
|
646 { |
|
647 |
|
648 TBuf<KDscStoreMaxStringLength> argList=aItem.Args(); |
|
649 argList.TrimAll(); |
|
650 _LIT(KSQLQuery,"DELETE FROM %S WHERE %S=%d AND %S='%S' AND %S= '%S' "); |
|
651 // the extra characters for the %S, %d in the format string |
|
652 const TInt extraLength=14; |
|
653 const TInt length=KSQLQuery().Length()+KItemTable().Length()+KDscIdCol().Length()+lengthOfTUint |
|
654 +KFileNameCol().Length()+aItem.FileName().Length()+KArgListCol().Length() |
|
655 +aItem.Args().Length()-extraLength; |
|
656 sqlCmd.CreateL(length); |
|
657 |
|
658 sqlCmd.Format(KSQLQuery,&KItemTable,&KDscIdCol, dscId,&KFileNameCol,&name, &KArgListCol, &argList); |
|
659 } |
|
660 |
|
661 PrintSqlCmd(sqlCmd); |
|
662 |
|
663 |
|
664 TInt err=iDatabase.Exec(sqlCmd); |
|
665 CleanupStack::PopAndDestroy(&sqlCmd); |
|
666 |
|
667 User::LeaveIfError(ConvertErrCode(err)); |
|
668 DatabaseCommitLP(); |
|
669 |
|
670 } |
|
671 |
|
672 //Update aItem. Unable to update an item only determined by itemId |
|
673 void CDscDatabase::UpdateItemL( const CDscItem& aItem) |
|
674 { |
|
675 //Leave if DB is opened for enumeration |
|
676 if (iIsEnumOpened) |
|
677 { |
|
678 User::Leave(KErrLocked); |
|
679 } |
|
680 |
|
681 //verify data integrity, |
|
682 VerifyDataL(aItem); |
|
683 |
|
684 DatabaseBeginLC(); |
|
685 //Leave if aItem does not exist |
|
686 if (!ItemExistsL( aItem)) |
|
687 { |
|
688 User::Leave(KErrNotFound); |
|
689 } |
|
690 |
|
691 |
|
692 RBuf sqlCmd; |
|
693 CleanupClosePushL(sqlCmd); |
|
694 |
|
695 TPtrC name=aItem.FileName(); |
|
696 |
|
697 TBuf<KDscStoreMaxStringLength> argList=aItem.Args(); |
|
698 argList.TrimAll(); |
|
699 TUid dscId=aItem.DscId(); |
|
700 |
|
701 //update aItem determined by fileName, argList and dscId. These three fields can't be updated |
|
702 _LIT(KSQLQuery,"UPDATE %S SET %S=%d,%S=%d, %S=%d,%S=%b,%S=%d,%S=%b, %S=%b WHERE %S=%d AND %S='%S' AND %S='%S'"); |
|
703 // the extra characters for the %S, %d in the format string |
|
704 const TInt extraLength=38; |
|
705 const TInt length=KSQLQuery().Length()+KItemTable().Length()+KStartMethodCol().Length()+ KTimeoutCol().Length() |
|
706 +3* lengthOfTUint + KNoOfRetriesCol().Length() +KMonitorCol().Length()+ KStartupTypeCol().Length() |
|
707 +KViewlessCol().Length()+ KStartInBackgroundCol().Length()+KDscIdCol().Length()+ KFileNameCol().Length() |
|
708 +KArgListCol().Length()+aItem.FileName().Length()+aItem.Args().Length()-extraLength; |
|
709 sqlCmd.CreateL(length); |
|
710 |
|
711 sqlCmd.Format(KSQLQuery,&KItemTable, &KStartMethodCol, aItem.StartMethod(), &KTimeoutCol, aItem.Timeout(), |
|
712 &KNoOfRetriesCol,aItem.NoOfRetries(), &KMonitorCol, aItem.Monitored(), &KStartupTypeCol,aItem.StartupType(), |
|
713 &KViewlessCol, aItem.Viewless(), &KStartInBackgroundCol, aItem.StartInBackground(), |
|
714 &KDscIdCol, dscId, &KFileNameCol, &name, &KArgListCol, &argList); |
|
715 |
|
716 |
|
717 PrintSqlCmd(sqlCmd); |
|
718 |
|
719 |
|
720 TInt err=iDatabase.Exec(sqlCmd); |
|
721 CleanupStack::PopAndDestroy(&sqlCmd); |
|
722 User::LeaveIfError(ConvertErrCode(err)); |
|
723 DatabaseCommitLP(); |
|
724 } |
|
725 |
|
726 //Read aItem from DSC DB either by fileName, argList and dscId, or by itemId and dscId |
|
727 void CDscDatabase::ReadItemL(CDscItem& aItem) |
|
728 { |
|
729 //Leave if DB is opened for enumeration |
|
730 if (iIsEnumOpened) |
|
731 { |
|
732 User::Leave(KErrLocked); |
|
733 } |
|
734 |
|
735 DatabaseBeginLC(); |
|
736 RSqlStatement stmt; |
|
737 CleanupClosePushL(stmt); |
|
738 |
|
739 |
|
740 TBool itemExists=QueryItemL(stmt, aItem); |
|
741 |
|
742 //aItem exists |
|
743 if(itemExists) |
|
744 { |
|
745 ReadDscItemL(stmt, aItem); |
|
746 |
|
747 //Reset all other values to default |
|
748 aItem.SetRecoveryParams(EIgnoreOnFailure,EStartupModeUndefined); |
|
749 aItem.SetLocalizationParamsL(KNullDesC,0); |
|
750 } |
|
751 //aItem does not exist |
|
752 else |
|
753 { |
|
754 User::Leave(KErrNotFound); |
|
755 } |
|
756 |
|
757 CleanupStack::PopAndDestroy(&stmt); |
|
758 DatabaseCommitLP(); |
|
759 } |
|
760 |
|
761 |
|
762 //Rollback a transaction |
|
763 void CDscDatabase::Rollback() |
|
764 { |
|
765 iDatabase.Exec(KRollbackTrans); |
|
766 } |
|
767 |
|
768 //Verify aItem |
|
769 void CDscDatabase::VerifyDataL(const CDscItem& aItem) |
|
770 { |
|
771 TInt noOfRetries=aItem.NoOfRetries(); |
|
772 |
|
773 //item with empty filename is not allowed to add to DB, or been updated |
|
774 //fileName and argList of aItem is limited to KDscStoreMaxStringLength |
|
775 //noOfRetries is restricted to 0 or 1 |
|
776 //StartMethod is retricted to EFireAndForget or EWaitForStart |
|
777 //Recovery policy of DscItem is restricted to IgnoreprocessFailure. |
|
778 if((aItem.FileName()==KNullDesC) ||(aItem.FileName().Length() > KDscStoreMaxStringLength) || |
|
779 (aItem.Args().Length() > KDscStoreMaxStringLength)|| |
|
780 (noOfRetries!=0 && noOfRetries!=1 ) ||(aItem.Timeout() <0) || |
|
781 (aItem.StartMethod() !=EFireAndForget && aItem.StartMethod() !=EWaitForStart )|| |
|
782 (aItem.RecoveryMethod() !=EIgnoreOnFailure )) |
|
783 { |
|
784 User::Leave(KErrArgument); |
|
785 } |
|
786 } |
|
787 |
|
788 //Start a new transaction.Pushes cleanup rollback action to the cleanup stack. |
|
789 void CDscDatabase::DatabaseBeginLC() |
|
790 { |
|
791 TInt err=iDatabase.Exec(KBeginTrans); |
|
792 User::LeaveIfError(ConvertErrCode(err)); |
|
793 CleanupStack::PushL(TCleanupItem(CleanupDatabaseRollback,this)); |
|
794 |
|
795 } |
|
796 |
|
797 //Commit transaction. Pops cleanup rollback action |
|
798 void CDscDatabase::DatabaseCommitLP() |
|
799 { |
|
800 TInt err=iDatabase.Exec(KCommitTrans); |
|
801 User::LeaveIfError(ConvertErrCode(err)); // force a rollback on error |
|
802 // Pop CleanupDatabaseRollback |
|
803 CleanupStack::Pop(); |
|
804 } |
|
805 |
|
806 //Cleanup rollback action for DatabaseBeginLC() |
|
807 void CDscDatabase::CleanupDatabaseRollback(TAny *aDatabase) |
|
808 { |
|
809 ASSERT(aDatabase); |
|
810 CDscDatabase* database=static_cast <CDscDatabase *>(aDatabase); |
|
811 |
|
812 database->Rollback(); |
|
813 } |
|
814 |
|
815 //Start a new transaction for enumeration.Pushes cleanup rollback action to the cleanup stack. |
|
816 void CDscDatabase::EnumBeginLC() |
|
817 { |
|
818 |
|
819 TInt err=iDatabase.Exec(KBeginTrans); |
|
820 User::LeaveIfError(ConvertErrCode(err)); |
|
821 |
|
822 CleanupStack::PushL(TCleanupItem(CleanupEnumRollback,this)); |
|
823 |
|
824 } |
|
825 //Cleanup rollback action for EnumOpenLC() |
|
826 void CDscDatabase::CleanupEnumRollback(TAny *aDatabase) |
|
827 { |
|
828 ASSERT(aDatabase); |
|
829 CDscDatabase* database=static_cast <CDscDatabase *>(aDatabase); |
|
830 database->iStmt.Close(); |
|
831 database->iIsEnumOpened=EFalse; |
|
832 |
|
833 //Roll back transaction |
|
834 database->Rollback(); |
|
835 } |
|
836 |
|
837 //Covert SQLite specific error code to Symbian standard error code |
|
838 TInt CDscDatabase::ConvertErrCode(TInt aErr) const |
|
839 { |
|
840 if (-144<=aErr) |
|
841 { |
|
842 return aErr; |
|
843 } |
|
844 TInt err; |
|
845 switch (aErr) |
|
846 { |
|
847 case KSqlErrPermission: |
|
848 err=KErrPermissionDenied; |
|
849 break; |
|
850 |
|
851 case KSqlErrBusy: |
|
852 case KSqlErrLocked: |
|
853 err=KErrLocked; |
|
854 break; |
|
855 |
|
856 case KSqlErrCorrupt: |
|
857 err=KErrCorrupt; |
|
858 break; |
|
859 |
|
860 case KSqlErrAbort: |
|
861 err=KErrAbort; |
|
862 break; |
|
863 case KSqlErrNotFound: |
|
864 err=KErrNotFound; |
|
865 break; |
|
866 case KSqlErrConstraint: |
|
867 err=KErrAlreadyExists; |
|
868 break; |
|
869 |
|
870 case KSqlErrFull: |
|
871 err=KErrOverflow; |
|
872 break; |
|
873 |
|
874 default: |
|
875 err=KErrGeneral; |
|
876 |
|
877 } |
|
878 return err; |
|
879 } |
|
880 |
|
881 //Get DSC database name |
|
882 void CDscDatabase::GetDatabaseNameL(TDes& aDatabaseName) |
|
883 { |
|
884 RFs fs; |
|
885 CleanupClosePushL(fs); |
|
886 User::LeaveIfError(fs.Connect()); |
|
887 //Retrieve system drive |
|
888 TDriveNumber driveNumber=fs.GetSystemDrive(); |
|
889 |
|
890 TChar driveChar; |
|
891 User::LeaveIfError(RFs::DriveToChar(driveNumber, driveChar)); |
|
892 |
|
893 aDatabaseName.Format(KDatabaseName,&driveChar); |
|
894 CleanupStack::PopAndDestroy(&fs); |
|
895 } |
|
896 //Helper function. Get the next available itemId for the item |
|
897 TInt CDscDatabase::GetItemIdL(TDscPosition aPos, RSqlStatement& aStmt) |
|
898 { |
|
899 TInt itemId=aStmt.ColumnInt(0); |
|
900 |
|
901 if(ELast==aPos ) |
|
902 { |
|
903 if(KMaxTInt32==itemId) |
|
904 { |
|
905 User::Leave(KErrOverflow); |
|
906 } |
|
907 ++itemId; |
|
908 |
|
909 } |
|
910 else if(EFirst==aPos ) |
|
911 { |
|
912 if(KMinTInt32==itemId) |
|
913 { |
|
914 User::Leave(KErrOverflow); |
|
915 } |
|
916 --itemId; |
|
917 } |
|
918 return itemId; |
|
919 } |