|
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 <dscitem.h> |
|
17 #include "dscdatabase.h" |
|
18 #include "sysstartpanic.h" |
|
19 |
|
20 /** |
|
21 The maximum length for a database name: 20 characters. |
|
22 @internalComponent |
|
23 @released |
|
24 */ |
|
25 const TInt KMaxDatabaseName=20; |
|
26 |
|
27 _LIT(KDatabaseName, "%c:DBS_DSC.db"); |
|
28 _LIT(KSecureFormat, "secure[2000836D]"); |
|
29 |
|
30 //Table names |
|
31 _LIT(KDscTable, "DSC"); |
|
32 _LIT(KItemTable, "DscItem"); |
|
33 //Column names |
|
34 _LIT(KDscIdCol, "DscId"); |
|
35 _LIT(KDescriptionCol, "Description"); |
|
36 _LIT(KItemIdCol, "ItemId"); |
|
37 _LIT(KFileNameCol, "FileName"); |
|
38 _LIT(KArgListCol, "ArgList"); |
|
39 _LIT(KStartMethodCol, "StartMethod"); |
|
40 _LIT(KTimeoutCol, "Timeout"); |
|
41 _LIT(KNoOfRetriesCol, "NoOfRetries"); |
|
42 _LIT(KMonitorCol, "Monitored"); |
|
43 _LIT(KStartupTypeCol, "StartupType"); |
|
44 _LIT(KViewlessCol, "Viewless"); |
|
45 _LIT(KStartInBackgroundCol, "StartInBackground"); |
|
46 //Index names |
|
47 _LIT(KIdIndex, "DscIndex"); |
|
48 _LIT(KIndex, "Index"); |
|
49 |
|
50 //Max length of respective number when represented as a string |
|
51 const TInt KMaxLengthOfEnum = 5; |
|
52 const TInt KMaxLengthOfTInt = 11; |
|
53 const TInt KMaxLengthOfBoolean = 1; |
|
54 |
|
55 // |
|
56 // SQL Select query definitions |
|
57 // |
|
58 _LIT(KSqlSelectDscItemOnId,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d AND %S=%d"); |
|
59 const TInt KFormatCharCountDscItemOnId=32; //for the %S and %d in the format string |
|
60 const TInt KSqlSelectDscItemOnIdLength = KSqlSelectDscItemOnId().Length() + KDscIdCol().Length() + KItemIdCol().Length() + |
|
61 KFileNameCol().Length() + KArgListCol().Length() + KStartMethodCol().Length() + KTimeoutCol().Length() + |
|
62 KNoOfRetriesCol().Length() + KMonitorCol().Length() + KStartupTypeCol().Length() + KViewlessCol().Length() + |
|
63 KStartInBackgroundCol().Length() + KItemTable().Length() + KDscIdCol().Length() + KMaxLengthOfTInt + |
|
64 KItemIdCol().Length() + KMaxLengthOfTInt - KFormatCharCountDscItemOnId; |
|
65 |
|
66 _LIT(KSqlSelectDscItemOnName,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d AND %S='%S' AND %S ='%S'"); |
|
67 const TInt KFormatCharCountDscItemOnName=36; // the extra characters for the %S, %d in the format string |
|
68 const TInt KSqlSelectDscItemOnNameLength = KSqlSelectDscItemOnName().Length() + KDscIdCol().Length() + KItemIdCol().Length() + |
|
69 KFileNameCol().Length() + KArgListCol().Length() + KStartMethodCol().Length() + KTimeoutCol().Length() + |
|
70 KNoOfRetriesCol().Length() + KMonitorCol().Length() + KStartupTypeCol().Length() + KViewlessCol().Length() + |
|
71 KStartInBackgroundCol().Length() + KItemTable().Length() + KDscIdCol().Length() + KMaxLengthOfTInt + |
|
72 KFileNameCol().Length() + KArgListCol().Length() - KFormatCharCountDscItemOnName; |
|
73 |
|
74 _LIT(KSqlQueryAllItemIds,"SELECT %S FROM %S WHERE %S=%d ORDER BY %S"); |
|
75 const TInt KFormatCharCountQueryAllItemIds = 10; |
|
76 const TInt KSqlQueryAllItemIdsLength = KSqlQueryAllItemIds().Length() + KItemIdCol().Length() + KItemTable().Length() + |
|
77 KDscIdCol().Length() + KMaxLengthOfTInt + KItemIdCol().Length() - KFormatCharCountQueryAllItemIds; |
|
78 |
|
79 _LIT(KSqlSelectDsc,"SELECT %S FROM %S WHERE %S=%d"); |
|
80 const TInt KFormatCharCountSelectDsc = 8; |
|
81 const TInt KSqlSelectDscLength = KSqlSelectDsc().Length() + KDscIdCol().Length() + KDscTable().Length() + |
|
82 KDscIdCol().Length() + KMaxLengthOfTInt - KFormatCharCountSelectDsc; |
|
83 |
|
84 _LIT(KSqlSelectDscDescription,"SELECT %S FROM %S WHERE %S=%d"); |
|
85 const TInt KFormatCharCountSelectDscDescription = 8; |
|
86 const TInt KSqlSelectDscDescriptionLength = KSqlSelectDscDescription().Length() + KDescriptionCol().Length() + KDscTable().Length() + |
|
87 KDscIdCol().Length() + KMaxLengthOfTInt - KFormatCharCountSelectDscDescription; |
|
88 |
|
89 _LIT(KSqlSelectAllItemsInDsc,"SELECT %S, %S, %S, %S, %S, %S, %S, %S, %S, %S, %S FROM %S WHERE %S=%d ORDER BY %S"); |
|
90 const TInt KFormatCharCountSelectAllItemsInDsc = 30; |
|
91 const TInt KSqlSelectAllItemsInDscLength = KSqlSelectAllItemsInDsc().Length() + |
|
92 KDscIdCol().Length() + KItemIdCol().Length() + KFileNameCol().Length() + KArgListCol().Length() + |
|
93 KStartMethodCol().Length() + KTimeoutCol().Length() + KNoOfRetriesCol().Length() + KMonitorCol().Length() + |
|
94 KStartupTypeCol().Length() + KViewlessCol().Length() + KStartInBackgroundCol().Length() + |
|
95 KItemTable().Length() + KDscIdCol().Length() + KMaxLengthOfTInt + KItemIdCol().Length() - KFormatCharCountSelectAllItemsInDsc; |
|
96 |
|
97 // |
|
98 // SQL DML definitions |
|
99 // |
|
100 _LIT(KSqlUpdateUsingName,"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'"); |
|
101 const TInt KFormatCharCountUpdateUsingName = 42; |
|
102 const TInt KSqlUpdateUsingNameLength = KSqlUpdateUsingName().Length() + KItemTable().Length() + |
|
103 KStartMethodCol().Length() + KMaxLengthOfEnum + KTimeoutCol().Length() + KMaxLengthOfTInt + |
|
104 KNoOfRetriesCol().Length() + KMaxLengthOfTInt + KMonitorCol().Length() + KMaxLengthOfBoolean + |
|
105 KStartupTypeCol().Length() + KMaxLengthOfEnum + KViewlessCol().Length() + KMaxLengthOfBoolean + |
|
106 KStartInBackgroundCol().Length() + KMaxLengthOfBoolean + KDscIdCol().Length() + KMaxLengthOfTInt + |
|
107 KFileNameCol().Length() + KArgListCol().Length() - KFormatCharCountUpdateUsingName; |
|
108 |
|
109 _LIT(KSqlUpdateUsingId,"UPDATE %S SET %S=%d,%S=%d, %S=%d,%S=%b,%S=%d,%S=%b, %S=%b WHERE %S=%d AND %S=%d"); |
|
110 const TInt KFormatCharCountUpdateUsingId = 38; |
|
111 const TInt KSqlUpdateUsingIdLength = KSqlUpdateUsingName().Length() + KItemTable().Length() + |
|
112 KStartMethodCol().Length() + KMaxLengthOfEnum + KTimeoutCol().Length() + KMaxLengthOfTInt + |
|
113 KNoOfRetriesCol().Length() + KMaxLengthOfTInt + KMonitorCol().Length() + KMaxLengthOfBoolean + |
|
114 KStartupTypeCol().Length() + KMaxLengthOfEnum + KViewlessCol().Length() + KMaxLengthOfBoolean + |
|
115 KStartInBackgroundCol().Length() + KMaxLengthOfBoolean + KDscIdCol().Length() + KMaxLengthOfTInt + |
|
116 KItemIdCol().Length() + KMaxLengthOfTInt - KFormatCharCountUpdateUsingId; |
|
117 |
|
118 _LIT(KSqlDeleteItemUsingId,"DELETE FROM %S WHERE %S=%d AND %S=%d"); |
|
119 const TInt KFormatCharCountDeleteItemUsingId = 8; |
|
120 const TInt KSqlDeleteItemUsingIdLength = KSqlDeleteItemUsingId().Length() + KItemTable().Length() + KDscIdCol().Length() + |
|
121 KMaxLengthOfTInt + KItemIdCol().Length() + KMaxLengthOfTInt - KFormatCharCountDeleteItemUsingId; |
|
122 |
|
123 _LIT(KSqlDeleteItemUsingName,"DELETE FROM %S WHERE %S=%d AND %S='%S' AND %S= '%S'"); |
|
124 const TInt KFormatCharCountDeleteItemUsingName = 14; |
|
125 const TInt KSqlDeleteItemUsingNameLength = KSqlDeleteItemUsingName().Length() + KItemTable().Length() + KDscIdCol().Length() + |
|
126 KMaxLengthOfTInt + KFileNameCol().Length() + KArgListCol().Length() - KFormatCharCountDeleteItemUsingName; |
|
127 |
|
128 _LIT(KSqlInsertDscItem,"INSERT INTO %S (%S,%S,%S,%S,%S,%S,%S,%S,%S,%S,%S) VALUES (%d,%d,'%S','%S',%d,%d,%d,%b,%d,%b,%b)"); |
|
129 const TInt KFormatCharCountInsertDscItem = 46; |
|
130 const TInt KSqlInsertDscItemLength = KSqlInsertDscItem().Length() + KItemTable().Length() + |
|
131 KDscIdCol().Length() + KItemIdCol().Length() + KFileNameCol().Length() + KArgListCol().Length() + |
|
132 KStartMethodCol().Length() + KTimeoutCol().Length() + KNoOfRetriesCol().Length() + KMonitorCol().Length() + |
|
133 KStartupTypeCol().Length() + KViewlessCol().Length() + KStartInBackgroundCol().Length() + |
|
134 (4*KMaxLengthOfTInt) + (2*KMaxLengthOfEnum) + (3*KMaxLengthOfBoolean) - KFormatCharCountInsertDscItem; |
|
135 |
|
136 _LIT(KSqlInsertDsc,"INSERT INTO %S (%S,%S) VALUES (%d,'%S')"); |
|
137 const TInt KFormatCharCountInsertDsc = 10; |
|
138 const TInt KSqlInsertDscLength = KSqlInsertDsc().Length() + KDscTable().Length() + KDscIdCol().Length() + KDescriptionCol().Length() + |
|
139 KMaxLengthOfTInt - KFormatCharCountInsertDsc; |
|
140 |
|
141 _LIT(KSqlDeleteUsingId,"DELETE FROM %S WHERE %S=%d "); |
|
142 const TInt KFormatCharCountDeleteUsingId = 6; |
|
143 const TInt KMaxTableNameLength = Max(KItemTable().Length(), KDscTable().Length()); |
|
144 const TInt KSqlDeleteUsingIdLength = KSqlDeleteUsingId().Length() + KMaxTableNameLength + KDscIdCol().Length() + KMaxLengthOfTInt - |
|
145 KFormatCharCountDeleteUsingId; |
|
146 |
|
147 // |
|
148 //SQL DDL definitions |
|
149 // |
|
150 _LIT(KSqlCreateItemTable,"CREATE TABLE %S (%S INTEGER NOT NULL, %S INTEGER NOT NULL, %S VARCHAR (%d) NOT NULL, %S VARCHAR(%d), %S TINYINT, %S INTEGER, %S INTEGER, %S BIT, %S TINYINT, %S BIT, %S BIT)"); |
|
151 const TInt KFormatCharCountCreateItemTable = 28; |
|
152 const TInt KSqlCreateItemTableLength = KSqlCreateItemTable().Length() + KItemTable().Length() + KDscIdCol().Length() + |
|
153 KItemIdCol().Length() + KFileNameCol().Length() + KMaxLengthOfTInt + KArgListCol().Length() + KMaxLengthOfTInt + |
|
154 KStartMethodCol().Length() + KTimeoutCol().Length() + KNoOfRetriesCol().Length() + KMonitorCol().Length() + |
|
155 KStartupTypeCol().Length() + KViewlessCol().Length() + KStartInBackgroundCol().Length() - KFormatCharCountCreateItemTable; |
|
156 |
|
157 _LIT(KSqlCreateDscTable,"CREATE TABLE %S (%S INTEGER NOT NULL, %S VARCHAR(%d))"); |
|
158 const TInt KFormatCharCountCreateDscTable = 8; |
|
159 const TInt KSqlCreateDscTableLength = KSqlCreateDscTable().Length() + KDscTable().Length() + KDscIdCol().Length() + |
|
160 KDescriptionCol().Length() + KMaxLengthOfTInt - KFormatCharCountCreateDscTable; |
|
161 |
|
162 _LIT(KSqlCreateDscIndex,"CREATE UNIQUE INDEX %S ON %S (%S)"); |
|
163 const TInt KFormatCharCountCreateDscIndex = 6; |
|
164 const TInt KSqlCreateDscIndexLength = KSqlCreateDscIndex().Length() + KIdIndex().Length() + KDscTable().Length() + KDscIdCol().Length() - |
|
165 KFormatCharCountCreateDscIndex; |
|
166 |
|
167 _LIT(KSqlCreateItemIndex,"CREATE UNIQUE INDEX %S ON %S (%S, %S)"); |
|
168 const TInt KFormatCharCountCreateItemIndex = 8; |
|
169 const TInt KSqlCreateItemIndexLength = KSqlCreateItemIndex().Length() + KIndex().Length() + KItemTable().Length() + KDscIdCol().Length() + |
|
170 KItemIdCol().Length() - KFormatCharCountCreateItemIndex; |
|
171 |
|
172 const TInt KMaxDdlLength = Max(Max(KSqlCreateDscTableLength,KSqlCreateItemTableLength), Max(KSqlCreateDscIndexLength,KSqlCreateItemIndexLength)); |
|
173 // The maximum length for varchar |
|
174 const TInt KDscStoreMaxStringLength = KDbMaxStrLen; |
|
175 |
|
176 |
|
177 /** Help, print out SQL query */ |
|
178 static void DebugPrint(const TDesC& aQuery) |
|
179 { |
|
180 (void)aQuery; |
|
181 #ifdef _DEBUG |
|
182 RDebug::RawPrint(aQuery); |
|
183 #endif |
|
184 } |
|
185 |
|
186 /** |
|
187 Verify aItem. Will leave for following reasons: |
|
188 - if filename is empty |
|
189 - if filename or argList is >KDbMaxStrLen |
|
190 */ |
|
191 static void LeaveIfFileParamsNotValidL(const CDscItem& aItem) |
|
192 { |
|
193 //filename and args in a CDscItem is guaranteed to be trimmed of unnecessary whitespace |
|
194 if( (aItem.FileName().Length() == 0) || |
|
195 (aItem.FileName().Length() > KDbMaxStrLen) || |
|
196 (aItem.Args().Length() > KDbMaxStrLen) ) |
|
197 { |
|
198 User::Leave(KErrArgument); |
|
199 } |
|
200 } |
|
201 |
|
202 CDscDatabase* CDscDatabase::NewL() |
|
203 { |
|
204 CDscDatabase* self = new(ELeave) CDscDatabase(); |
|
205 CleanupStack::PushL(self); |
|
206 self->ConstructL(); |
|
207 CleanupStack::Pop(self); |
|
208 return self; |
|
209 } |
|
210 |
|
211 void CDscDatabase::ConstructL() |
|
212 { |
|
213 //Open database connection |
|
214 User::LeaveIfError(iDbsSession.Connect()); |
|
215 |
|
216 TBuf<KMaxDatabaseName> databaseName; |
|
217 GetDatabaseNameL(databaseName); |
|
218 const TInt error = iDatabase.Open(iDbsSession, databaseName, KSecureFormat); |
|
219 if(KErrNotFound == error) |
|
220 { |
|
221 CreateDatabaseL(databaseName); |
|
222 } |
|
223 else |
|
224 { |
|
225 User::LeaveIfError(error); |
|
226 } |
|
227 } |
|
228 |
|
229 //Default constructor |
|
230 CDscDatabase::CDscDatabase() : iIsEnumOpened(EFalse) |
|
231 { |
|
232 } |
|
233 |
|
234 CDscDatabase::~CDscDatabase() |
|
235 { |
|
236 if(iIsEnumOpened) |
|
237 { |
|
238 Rollback(); |
|
239 } |
|
240 iView.Close(); |
|
241 iDatabase.Close(); |
|
242 iDbsSession.Close(); |
|
243 } |
|
244 |
|
245 //Destroy DSC database |
|
246 TInt CDscDatabase::DeleteDb() |
|
247 { |
|
248 return iDatabase.Destroy(); |
|
249 } |
|
250 |
|
251 void CDscDatabase::CreateDatabaseL(const TDesC& aDatabaseName) |
|
252 { |
|
253 //create it and also open it |
|
254 User::LeaveIfError(iDatabase.Create(iDbsSession, aDatabaseName, KSecureFormat)); |
|
255 |
|
256 //Create tables for DSC database |
|
257 TRAPD(error, CreateTablesL()); |
|
258 if (KErrNone != error) |
|
259 { |
|
260 //Create table fail, destroy the DB, so next time can recreate it |
|
261 DeleteDb(); |
|
262 } |
|
263 |
|
264 User::LeaveIfError(error); |
|
265 } |
|
266 |
|
267 void CDscDatabase::CreateTablesL() |
|
268 { |
|
269 RBuf sqlCmd; |
|
270 CleanupClosePushL(sqlCmd); |
|
271 sqlCmd.CreateL(KMaxDdlLength); |
|
272 |
|
273 //Start a new transaction |
|
274 DatabaseBeginLC(); |
|
275 |
|
276 //Create Table DSC |
|
277 sqlCmd.Format(KSqlCreateDscTable, &KDscTable, &KDscIdCol, &KDescriptionCol, KDbUndefinedLength); |
|
278 DebugPrint(sqlCmd); |
|
279 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
280 |
|
281 //Create unique index for Table DSC |
|
282 sqlCmd.Format(KSqlCreateDscIndex, &KIdIndex, &KDscTable, &KDscIdCol); |
|
283 DebugPrint(sqlCmd); |
|
284 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
285 |
|
286 //Create Table DscItem |
|
287 sqlCmd.Format(KSqlCreateItemTable, &KItemTable, &KDscIdCol, &KItemIdCol, &KFileNameCol, KDbUndefinedLength, &KArgListCol, |
|
288 KDbUndefinedLength, &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, |
|
289 &KViewlessCol, &KStartInBackgroundCol); |
|
290 DebugPrint(sqlCmd); |
|
291 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
292 |
|
293 //Create unique index for Table DscItem |
|
294 sqlCmd.Format(KSqlCreateItemIndex, &KIndex, &KItemTable, &KDscIdCol, &KItemIdCol); |
|
295 DebugPrint(sqlCmd); |
|
296 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
297 |
|
298 DatabaseCommitL(); //CommitL + CleanupStack::Pop() |
|
299 |
|
300 CleanupStack::PopAndDestroy(&sqlCmd); |
|
301 } |
|
302 |
|
303 //Add a DSC with aDscId to DSC DB. if the aDscId exists, leave with KErrAlreadyExists |
|
304 void CDscDatabase::CreateDscL(const TUid& aDscId, const TDesC& aDescription) |
|
305 { |
|
306 //The maximum length of aDescription is KDbMaxStrLen |
|
307 if(aDescription.Length() > KDbMaxStrLen) |
|
308 { |
|
309 User::Leave(KErrArgument); |
|
310 } |
|
311 |
|
312 //If the DSC is opened for enumeration, leave with KErrLocked |
|
313 if (iIsEnumOpened) |
|
314 { |
|
315 User::Leave(KErrLocked); |
|
316 } |
|
317 |
|
318 //Start a new transaction |
|
319 DatabaseBeginLC(); |
|
320 |
|
321 //Insert aDscId in Table DSC. If aDscId exists, will leave with KErrAlreadyExists |
|
322 RBuf sqlCmd; |
|
323 CleanupClosePushL(sqlCmd); |
|
324 sqlCmd.CreateL(KSqlInsertDscLength + aDescription.Length()); |
|
325 |
|
326 sqlCmd.Format(KSqlInsertDsc, &KDscTable, &KDscIdCol, &KDescriptionCol, aDscId, &aDescription); |
|
327 DebugPrint(sqlCmd); |
|
328 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
329 |
|
330 CleanupStack::PopAndDestroy(&sqlCmd); |
|
331 |
|
332 DatabaseCommitL(); //CommitL + CleanupStack::Pop() |
|
333 } |
|
334 |
|
335 //Delete the DSC with aDscId, all items related to aDscId are deleted too. |
|
336 void CDscDatabase::DeleteDscL(const TUid& aDscId) |
|
337 { |
|
338 //If the DSC is opened for enumeration, leave with KErrLocked |
|
339 if (iIsEnumOpened) |
|
340 { |
|
341 User::Leave(KErrLocked); |
|
342 } |
|
343 |
|
344 //Start a new transaction |
|
345 DatabaseBeginLC(); |
|
346 |
|
347 if (!DscExistsL(aDscId)) |
|
348 { |
|
349 // aDscId doesn't exist, leave with KErrNotFound |
|
350 User::Leave(KErrNotFound); |
|
351 } |
|
352 |
|
353 RBuf sqlCmd; |
|
354 CleanupClosePushL(sqlCmd); |
|
355 sqlCmd.CreateL(KSqlDeleteUsingIdLength); |
|
356 |
|
357 //Delete all items related with aDscId first |
|
358 sqlCmd.Format(KSqlDeleteUsingId, &KItemTable, &KDscIdCol, aDscId); |
|
359 DebugPrint(sqlCmd); |
|
360 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
361 |
|
362 //Then delete the row in Table DSC |
|
363 sqlCmd.Format(KSqlDeleteUsingId, &KDscTable, &KDscIdCol, aDscId); |
|
364 DebugPrint(sqlCmd); |
|
365 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
366 |
|
367 CleanupStack::PopAndDestroy(&sqlCmd); |
|
368 |
|
369 DatabaseCommitL(); //CommitL + CleanupStack::Pop() |
|
370 } |
|
371 |
|
372 //Check the existance of a DSC |
|
373 TBool CDscDatabase::DscExistsL(const TUid& aDscId) const |
|
374 { |
|
375 RDbView view; |
|
376 CleanupClosePushL(view); |
|
377 |
|
378 RBuf sqlCmd; |
|
379 CleanupClosePushL(sqlCmd); |
|
380 sqlCmd.CreateL(KSqlSelectDscLength); |
|
381 |
|
382 sqlCmd.Format(KSqlSelectDsc, &KDscIdCol, &KDscTable, &KDscIdCol, aDscId); |
|
383 DebugPrint(sqlCmd); |
|
384 User::LeaveIfError(view.Prepare(iDatabase, sqlCmd)); |
|
385 User::LeaveIfError(view.EvaluateAll()); |
|
386 const TBool dscExists = !view.IsEmptyL(); |
|
387 |
|
388 CleanupStack::PopAndDestroy(&sqlCmd); |
|
389 CleanupStack::PopAndDestroy(&view); |
|
390 |
|
391 return (dscExists); |
|
392 } |
|
393 |
|
394 void CDscDatabase::GetDscDescriptionL(const TUid &aDscId, TDes& aDescription) const |
|
395 { |
|
396 RDbView view; |
|
397 CleanupClosePushL(view); |
|
398 |
|
399 RBuf sqlCmd; |
|
400 CleanupClosePushL(sqlCmd); |
|
401 sqlCmd.CreateL(KSqlSelectDscDescriptionLength); |
|
402 |
|
403 sqlCmd.Format(KSqlSelectDscDescription, &KDescriptionCol, &KDscTable, &KDscIdCol, aDscId); |
|
404 DebugPrint(sqlCmd); |
|
405 User::LeaveIfError(view.Prepare(iDatabase, sqlCmd)); |
|
406 User::LeaveIfError(view.EvaluateAll()); |
|
407 CleanupStack::PopAndDestroy(&sqlCmd); |
|
408 |
|
409 if(view.IsEmptyL()) |
|
410 { |
|
411 User::Leave(KErrNotFound); |
|
412 } |
|
413 |
|
414 view.FirstL(); |
|
415 view.GetL(); |
|
416 |
|
417 //Check the length of aDescription |
|
418 TPtrC description(view.ColDes(1)); |
|
419 if (description.Length() > aDescription.MaxLength()) |
|
420 { |
|
421 User::Leave(KErrOverflow); |
|
422 } |
|
423 |
|
424 aDescription.Zero(); |
|
425 aDescription=description; |
|
426 |
|
427 CleanupStack::PopAndDestroy(&view); |
|
428 } |
|
429 |
|
430 //Check the existance of aItem |
|
431 TBool CDscDatabase::ItemExistsL( const CDscItem& aItem) const |
|
432 { |
|
433 RDbView view; |
|
434 CleanupClosePushL(view); |
|
435 |
|
436 QueryItemL(view, aItem); |
|
437 const TBool itemExists = !view.IsEmptyL(); |
|
438 |
|
439 CleanupStack::PopAndDestroy(&view); |
|
440 return (itemExists); |
|
441 } |
|
442 |
|
443 //Query the aItem from Table DscItem |
|
444 void CDscDatabase::QueryItemL(RDbView& aView, const CDscItem& aItem) const |
|
445 { |
|
446 RBuf sqlCmd; |
|
447 CleanupClosePushL(sqlCmd); |
|
448 |
|
449 if (aItem.ItemId()) |
|
450 { |
|
451 sqlCmd.CreateL(KSqlSelectDscItemOnIdLength); |
|
452 sqlCmd.Format( KSqlSelectDscItemOnId, &KDscIdCol, &KItemIdCol, &KFileNameCol, |
|
453 &KArgListCol,&KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, |
|
454 &KMonitorCol, &KStartupTypeCol, &KViewlessCol, &KStartInBackgroundCol, |
|
455 &KItemTable, &KDscIdCol, aItem.DscId(), &KItemIdCol, aItem.ItemId()); |
|
456 } |
|
457 else |
|
458 { |
|
459 const TPtrC filename = aItem.FileName(); |
|
460 const TPtrC argList = aItem.Args(); //whitespace already trimmed |
|
461 |
|
462 LeaveIfFileParamsNotValidL(aItem); |
|
463 |
|
464 const TInt length = KSqlSelectDscItemOnNameLength + filename.Length() + argList.Length(); |
|
465 sqlCmd.CreateL(length); |
|
466 sqlCmd.Format(KSqlSelectDscItemOnName, &KDscIdCol, &KItemIdCol, &KFileNameCol,&KArgListCol, &KStartMethodCol, |
|
467 &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, &KViewlessCol, &KStartInBackgroundCol, |
|
468 &KItemTable, &KDscIdCol, aItem.DscId(), &KFileNameCol, &filename, &KArgListCol, &argList); |
|
469 } |
|
470 |
|
471 DebugPrint(sqlCmd); |
|
472 |
|
473 User::LeaveIfError(aView.Prepare(iDatabase, sqlCmd)); |
|
474 User::LeaveIfError(aView.EvaluateAll()); //no error for non existing item |
|
475 CleanupStack::PopAndDestroy(&sqlCmd); |
|
476 } |
|
477 |
|
478 |
|
479 //Open a view of items with aDscID for enumeration, need to |
|
480 //call EnumClose() to close the view after enumeration. |
|
481 void CDscDatabase::EnumOpenLC(const TUid& aDscId) |
|
482 { |
|
483 //If the DSC is opened for enumeration, leave with KErrLocked |
|
484 if (iIsEnumOpened) |
|
485 { |
|
486 User::Leave(KErrLocked); |
|
487 } |
|
488 |
|
489 //Start a new transaction to add read-lock on DSC |
|
490 EnumBeginLC(); |
|
491 |
|
492 //Leave with KErrNotFound if aDscId doesn't exist |
|
493 if (!DscExistsL(aDscId)) |
|
494 { |
|
495 User::Leave(KErrNotFound); |
|
496 } |
|
497 |
|
498 iIsEnumOpened = ETrue; |
|
499 |
|
500 //Open a view contains all items in aDscId |
|
501 RBuf sqlCmd; |
|
502 CleanupClosePushL(sqlCmd); |
|
503 sqlCmd.CreateL(KSqlSelectAllItemsInDscLength); |
|
504 |
|
505 sqlCmd.Format(KSqlSelectAllItemsInDsc, &KDscIdCol, &KItemIdCol, &KFileNameCol, &KArgListCol, |
|
506 &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, |
|
507 &KViewlessCol, &KStartInBackgroundCol, &KItemTable, &KDscIdCol, aDscId, &KItemIdCol); |
|
508 DebugPrint(sqlCmd); |
|
509 User::LeaveIfError(iView.Prepare(iDatabase, sqlCmd)); |
|
510 User::LeaveIfError(iView.EvaluateAll()); //no error for non existing item |
|
511 CleanupStack::PopAndDestroy(&sqlCmd); |
|
512 } |
|
513 |
|
514 |
|
515 //Enumerating the view opened by EnumOpenLC(), if there are no item in the DSC |
|
516 //or has reached the end of the list, return NULL |
|
517 CDscItem* CDscDatabase::EnumReadNextL() |
|
518 { |
|
519 if (!iIsEnumOpened) |
|
520 { |
|
521 //EnumOpenLC() has not been called. |
|
522 User::Leave(KErrNotReady); |
|
523 } |
|
524 |
|
525 if (!iView.NextL()) |
|
526 { |
|
527 //reached to the end of the view |
|
528 return NULL; |
|
529 } |
|
530 |
|
531 //Read item from the view |
|
532 CDscItem* item=CDscItem::NewL(); |
|
533 CleanupStack::PushL(item); |
|
534 ReadDscItemL(iView, *item); |
|
535 |
|
536 CleanupStack::Pop(item); |
|
537 return item; |
|
538 } |
|
539 |
|
540 //Read aItem from the view. |
|
541 //Cannot use ReadItemL because we want the read-lock to remain |
|
542 void CDscDatabase::ReadDscItemL(RDbRowSet& rowSet, CDscItem& aItem) const |
|
543 { |
|
544 rowSet.GetL(); |
|
545 |
|
546 aItem.SetDscId(TUid::Uid(rowSet.ColInt(1))); |
|
547 if( 0 == aItem.ItemId() ) |
|
548 { |
|
549 aItem.SetItemId(rowSet.ColInt(2)); |
|
550 } |
|
551 else |
|
552 { |
|
553 __ASSERT_ALWAYS(aItem.ItemId() == rowSet.ColInt(2), PanicNow(KPanicDsc, EIdCannotChange)); |
|
554 } |
|
555 aItem.SetFileParamsL(rowSet.ColDes(3), rowSet.ColDes(4)); |
|
556 aItem.SetStartMethodL(static_cast<TStartMethod> (rowSet.ColInt8(5))); |
|
557 aItem.SetNoOfRetriesL(rowSet.ColInt(7)); |
|
558 aItem.SetTimeoutL(rowSet.ColInt32(6)); |
|
559 aItem.SetMonitored(rowSet.ColInt8(8)); |
|
560 aItem.SetStartupType(static_cast<TStartupType> (rowSet.ColInt8(9))); |
|
561 aItem.SetViewless(rowSet.ColInt8(10)); |
|
562 aItem.SetStartInBackground( rowSet.ColInt8(11)); |
|
563 } |
|
564 |
|
565 //Close the view opened by EnumOpenLC() and rollback the transaction |
|
566 void CDscDatabase::EnumClose() |
|
567 { |
|
568 //To avoid double close |
|
569 if (iIsEnumOpened) |
|
570 { |
|
571 iView.Close(); |
|
572 iIsEnumOpened=EFalse; |
|
573 |
|
574 //Roll back transaction |
|
575 Rollback(); |
|
576 } |
|
577 } |
|
578 |
|
579 //Add aItem to DSC at aPos |
|
580 void CDscDatabase::AddItemL(CDscItem& aItem, TDscPosition aPos) |
|
581 { |
|
582 //Leave if DB is opened for enumeration |
|
583 if (iIsEnumOpened) |
|
584 { |
|
585 User::Leave(KErrLocked); |
|
586 } |
|
587 |
|
588 //verify data integrity, |
|
589 LeaveIfFileParamsNotValidL(aItem); |
|
590 if(aItem.ItemId() != 0) |
|
591 { |
|
592 User::Leave(KErrArgument); |
|
593 } |
|
594 |
|
595 //Start transaction |
|
596 DatabaseBeginLC(); |
|
597 |
|
598 //Leave if aDscId doesn't exist |
|
599 if (!DscExistsL(aItem.DscId())) |
|
600 { |
|
601 User::Leave(KErrNotFound); |
|
602 } |
|
603 |
|
604 //Leave if aItem exists |
|
605 if (ItemExistsL(aItem)) |
|
606 { |
|
607 User::Leave(KErrAlreadyExists); |
|
608 } |
|
609 |
|
610 const TPtrC filename = aItem.FileName(); |
|
611 const TPtrC argList = aItem.Args(); //whitespace already trimmed |
|
612 const TInt itemId = GetNextItemIdL(aPos, aItem.DscId()); |
|
613 |
|
614 RBuf sqlCmd; |
|
615 CleanupClosePushL(sqlCmd); |
|
616 sqlCmd.CreateL(KSqlInsertDscItemLength + filename.Length() + argList.Length()); |
|
617 |
|
618 //insert the item |
|
619 sqlCmd.Format(KSqlInsertDscItem, &KItemTable, &KDscIdCol, &KItemIdCol, &KFileNameCol, &KArgListCol, |
|
620 &KStartMethodCol, &KTimeoutCol, &KNoOfRetriesCol, &KMonitorCol, &KStartupTypeCol, |
|
621 &KViewlessCol, &KStartInBackgroundCol, aItem.DscId(), itemId, &filename, &argList, aItem.StartMethod(), |
|
622 aItem.Timeout(), aItem.NoOfRetries(), aItem.Monitored(), |
|
623 aItem.StartupType(), aItem.Viewless(), aItem.StartInBackground()); |
|
624 |
|
625 DebugPrint(sqlCmd); |
|
626 |
|
627 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
628 CleanupStack::PopAndDestroy(&sqlCmd); |
|
629 DatabaseCommitL(); //CommitL + CleanupStack::Pop() |
|
630 |
|
631 //Now aItem is persistent, set the ItemId so it can be read by the client |
|
632 aItem.SetItemId(itemId); |
|
633 } |
|
634 |
|
635 //Delete aItem from DSC |
|
636 void CDscDatabase::DeleteItemL( const CDscItem& aItem) |
|
637 { |
|
638 //Leave if DB is opened for enumeration |
|
639 if (iIsEnumOpened) |
|
640 { |
|
641 User::Leave(KErrLocked); |
|
642 } |
|
643 |
|
644 DatabaseBeginLC(); |
|
645 |
|
646 //Leave if aItem does not exist |
|
647 if (!ItemExistsL( aItem)) |
|
648 { |
|
649 User::Leave(KErrNotFound); |
|
650 } |
|
651 |
|
652 RBuf sqlCmd; |
|
653 CleanupClosePushL(sqlCmd); |
|
654 |
|
655 if (aItem.ItemId()) |
|
656 { |
|
657 sqlCmd.CreateL(KSqlDeleteItemUsingIdLength); |
|
658 sqlCmd.Format(KSqlDeleteItemUsingId, &KItemTable, &KDscIdCol, aItem.DscId(), &KItemIdCol, aItem.ItemId()); |
|
659 } |
|
660 else |
|
661 { |
|
662 const TPtrC filename = aItem.FileName(); |
|
663 const TPtrC argList = aItem.Args(); //whitespace already trimmed |
|
664 |
|
665 LeaveIfFileParamsNotValidL(aItem); |
|
666 |
|
667 const TInt length = KSqlDeleteItemUsingNameLength + filename.Length() + argList.Length(); |
|
668 sqlCmd.CreateL(length); |
|
669 sqlCmd.Format(KSqlDeleteItemUsingName, &KItemTable, &KDscIdCol, aItem.DscId(), &KFileNameCol, &filename, &KArgListCol, &argList); |
|
670 } |
|
671 |
|
672 DebugPrint(sqlCmd); |
|
673 |
|
674 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
675 CleanupStack::PopAndDestroy(&sqlCmd); |
|
676 DatabaseCommitL(); //CommitL + CleanupStack::Pop() |
|
677 } |
|
678 |
|
679 //Update aItem. |
|
680 void CDscDatabase::UpdateItemL(const CDscItem& aItem) |
|
681 { |
|
682 //Leave if DB is opened for enumeration |
|
683 if (iIsEnumOpened) |
|
684 { |
|
685 User::Leave(KErrLocked); |
|
686 } |
|
687 |
|
688 if(aItem.ItemId() == 0) |
|
689 { |
|
690 LeaveIfFileParamsNotValidL(aItem); |
|
691 } |
|
692 |
|
693 DatabaseBeginLC(); |
|
694 |
|
695 //Leave if aItem does not exist |
|
696 if (!ItemExistsL( aItem)) |
|
697 { |
|
698 User::Leave(KErrNotFound); |
|
699 } |
|
700 |
|
701 RBuf sqlCmd; |
|
702 CleanupClosePushL(sqlCmd); |
|
703 |
|
704 if (aItem.ItemId()) |
|
705 { |
|
706 sqlCmd.CreateL(KSqlUpdateUsingIdLength); |
|
707 sqlCmd.Format(KSqlUpdateUsingId, &KItemTable, &KStartMethodCol, aItem.StartMethod(), &KTimeoutCol, aItem.Timeout(), |
|
708 &KNoOfRetriesCol, aItem.NoOfRetries(), &KMonitorCol, aItem.Monitored(), &KStartupTypeCol, aItem.StartupType(), |
|
709 &KViewlessCol, aItem.Viewless(), &KStartInBackgroundCol, aItem.StartInBackground(), |
|
710 &KDscIdCol, aItem.DscId(), &KItemIdCol, aItem.ItemId()); |
|
711 } |
|
712 else |
|
713 { |
|
714 const TPtrC filename = aItem.FileName(); |
|
715 const TPtrC argList = aItem.Args(); //whitespace already trimmed |
|
716 |
|
717 const TInt length = KSqlUpdateUsingNameLength + filename.Length() + argList.Length(); |
|
718 sqlCmd.CreateL(length); |
|
719 sqlCmd.Format(KSqlUpdateUsingName, &KItemTable, &KStartMethodCol, aItem.StartMethod(), &KTimeoutCol, aItem.Timeout(), |
|
720 &KNoOfRetriesCol, aItem.NoOfRetries(), &KMonitorCol, aItem.Monitored(), &KStartupTypeCol, aItem.StartupType(), |
|
721 &KViewlessCol, aItem.Viewless(), &KStartInBackgroundCol, aItem.StartInBackground(), |
|
722 &KDscIdCol, aItem.DscId(), &KFileNameCol, &filename, &KArgListCol, &argList); |
|
723 } |
|
724 |
|
725 DebugPrint(sqlCmd); |
|
726 |
|
727 User::LeaveIfError(iDatabase.Execute(sqlCmd)); |
|
728 CleanupStack::PopAndDestroy(&sqlCmd); |
|
729 DatabaseCommitL(); //CommitL + CleanupStack::Pop() |
|
730 } |
|
731 |
|
732 //Read aItem from DSC DB either by fileName, argList and dscId, or by itemId and dscId |
|
733 void CDscDatabase::ReadItemL(CDscItem& aItem) |
|
734 { |
|
735 //Leave if DB is opened for enumeration |
|
736 if (iIsEnumOpened) |
|
737 { |
|
738 User::Leave(KErrLocked); |
|
739 } |
|
740 |
|
741 DatabaseBeginLC(); |
|
742 |
|
743 RDbView view; |
|
744 CleanupClosePushL(view); |
|
745 |
|
746 QueryItemL(view, aItem); |
|
747 if(view.CountL()==0) |
|
748 { |
|
749 //aItem does not exist |
|
750 User::Leave(KErrNotFound); |
|
751 } |
|
752 else |
|
753 { |
|
754 view.FirstL(); |
|
755 ReadDscItemL(view, aItem); |
|
756 } |
|
757 |
|
758 CleanupStack::PopAndDestroy(2); //view and CleanupDatabaseRollback |
|
759 } |
|
760 |
|
761 //Rollback transaction |
|
762 void CDscDatabase::Rollback() |
|
763 { |
|
764 iDatabase.Rollback(); |
|
765 if(iDatabase.IsDamaged()) |
|
766 { |
|
767 iDatabase.Recover(); |
|
768 } |
|
769 } |
|
770 |
|
771 //Start a new transaction.Pushes cleanup rollback action to the cleanup stack. |
|
772 void CDscDatabase::DatabaseBeginLC() |
|
773 { |
|
774 User::LeaveIfError(iDatabase.Begin()); |
|
775 CleanupStack::PushL(TCleanupItem(CleanupDatabaseRollback, this)); |
|
776 } |
|
777 |
|
778 //Commit transaction. Pops cleanup rollback action |
|
779 void CDscDatabase::DatabaseCommitL() |
|
780 { |
|
781 User::LeaveIfError(iDatabase.Commit()); |
|
782 // Pop CleanupDatabaseRollback |
|
783 CleanupStack::Pop(); |
|
784 } |
|
785 |
|
786 //Cleanup rollback action for DatabaseBeginLC() |
|
787 void CDscDatabase::CleanupDatabaseRollback(TAny *aDatabase) |
|
788 { |
|
789 ASSERT(aDatabase); |
|
790 CDscDatabase* database = static_cast <CDscDatabase*>(aDatabase); |
|
791 database->Rollback(); |
|
792 } |
|
793 |
|
794 //Start a new transaction for enumeration.Pushes cleanup rollback action to the cleanup stack. |
|
795 void CDscDatabase::EnumBeginLC() |
|
796 { |
|
797 User::LeaveIfError(iDatabase.Begin()); |
|
798 CleanupStack::PushL(TCleanupItem(CleanupEnumRollback, this)); |
|
799 } |
|
800 |
|
801 //Cleanup rollback action for EnumOpenLC() |
|
802 void CDscDatabase::CleanupEnumRollback(TAny *aDatabase) |
|
803 { |
|
804 ASSERT(aDatabase); |
|
805 if(aDatabase) |
|
806 static_cast <CDscDatabase*>(aDatabase)->EnumClose(); |
|
807 } |
|
808 |
|
809 //Get DSC database name |
|
810 void CDscDatabase::GetDatabaseNameL(TDes& aDatabaseName) |
|
811 { |
|
812 RFs fs; |
|
813 CleanupClosePushL(fs); |
|
814 User::LeaveIfError(fs.Connect()); |
|
815 |
|
816 // retrieve system drive |
|
817 TDriveNumber driveNumber = fs.GetSystemDrive(); |
|
818 |
|
819 // convert to char |
|
820 TChar driveChar; |
|
821 User::LeaveIfError(RFs::DriveToChar(driveNumber, driveChar)); |
|
822 |
|
823 aDatabaseName.Format(KDatabaseName, (TUint)driveChar); |
|
824 CleanupStack::PopAndDestroy(&fs); |
|
825 } |
|
826 |
|
827 |
|
828 /** |
|
829 Helper function. Get the next available itemId for the item. |
|
830 Reads all existing ItemIds for the specified DscId, then calculates last+1 |
|
831 or first-1 depending on aPos. Will never return 0 as its reserved to mean |
|
832 not yet persistent. |
|
833 */ |
|
834 TInt CDscDatabase::GetNextItemIdL(TDscPosition aPos, const TUid& aDscId) const |
|
835 { |
|
836 RDbView view; |
|
837 CleanupClosePushL(view); |
|
838 RBuf sqlCmd; |
|
839 CleanupClosePushL(sqlCmd); |
|
840 |
|
841 sqlCmd.CreateL(KSqlQueryAllItemIdsLength); |
|
842 sqlCmd.Format(KSqlQueryAllItemIds, &KItemIdCol, &KItemTable,&KDscIdCol, aDscId, &KItemIdCol ); |
|
843 |
|
844 DebugPrint(sqlCmd); |
|
845 |
|
846 User::LeaveIfError(view.Prepare(iDatabase, sqlCmd)); |
|
847 User::LeaveIfError(view.EvaluateAll()); |
|
848 CleanupStack::PopAndDestroy(&sqlCmd); |
|
849 |
|
850 TInt nextId = 1; //add first item with id=1 and reserve 0 to mean "not yet persistent" |
|
851 if (aPos==ELast && view.LastL()) |
|
852 { |
|
853 //add at ELast: pos =max of itemId+1 |
|
854 view.GetL(); |
|
855 nextId = view.ColInt(1); |
|
856 if(KMaxTInt == nextId) |
|
857 { |
|
858 User::Leave(KErrOverflow); |
|
859 } |
|
860 //increase, make sure to not use 0 as itemid in the database |
|
861 nextId = (-1==nextId) ? (nextId+2) : (nextId+1); |
|
862 } |
|
863 else if (aPos==EFirst && view.FirstL()) |
|
864 { |
|
865 //add at EFirst: pos=min of itemId-1 |
|
866 view.GetL(); |
|
867 nextId = view.ColInt(1); |
|
868 if(KMinTInt == nextId) |
|
869 { |
|
870 User::Leave(KErrUnderflow); |
|
871 } |
|
872 //decrease, but reserve 0 to mean "not yet persistent" |
|
873 nextId = (1==nextId) ? (nextId-2) : (nextId-1); |
|
874 } |
|
875 |
|
876 CleanupStack::PopAndDestroy(&view); |
|
877 return nextId; |
|
878 } |
|
879 |
|
880 TInt CDscDatabase::MaxStringLength() |
|
881 { |
|
882 return KDbMaxStrLen; //defined in d32dbms.h |
|
883 } |
|
884 |