|
1 /* |
|
2 * Copyright (c) 2009 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: Class to hold description about schema |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <badesca.h> |
|
19 #include "mdsschema.h" |
|
20 |
|
21 #include "mdcdef.h" |
|
22 #include "mdsnamespacedef.h" |
|
23 #include "mdsobjectdef.h" |
|
24 #include "mdsclausebuffer.h" |
|
25 #include "mdsfindsqlclausedef.h" |
|
26 #include "mdspropertydef.h" |
|
27 #include "mdsdbconnectionpool.h" |
|
28 #include "mdssqliteconnection.h" |
|
29 #include "mdcserializationbuffer.h" |
|
30 #include <mdeconstants.h> |
|
31 |
|
32 |
|
33 /** |
|
34 * NewLC |
|
35 */ |
|
36 CMdsSchema* CMdsSchema::NewLC( ) |
|
37 { |
|
38 CMdsSchema* ret = new( ELeave ) CMdsSchema( ); |
|
39 CleanupStack::PushL( ret ); |
|
40 ret->ConstructL( ); |
|
41 return ret; |
|
42 } |
|
43 |
|
44 /** |
|
45 * NewL |
|
46 */ |
|
47 CMdsSchema* CMdsSchema::NewL( ) |
|
48 { |
|
49 CMdsSchema* ret = CMdsSchema::NewLC( ); |
|
50 CleanupStack::Pop( ret ); |
|
51 return ret; |
|
52 } |
|
53 |
|
54 /** |
|
55 * ConstructL |
|
56 */ |
|
57 void CMdsSchema::ConstructL( ) |
|
58 { |
|
59 } |
|
60 |
|
61 /** |
|
62 * Constructor |
|
63 */ |
|
64 CMdsSchema::CMdsSchema() : iBaseObject( NULL ), |
|
65 iSerialized( EFalse ), iSchemaHandle( 0 ) |
|
66 { |
|
67 } |
|
68 |
|
69 /** |
|
70 * Destructor |
|
71 */ |
|
72 CMdsSchema::~CMdsSchema() |
|
73 { |
|
74 iNamespaceDefs.ResetAndDestroy(); |
|
75 iNamespaceDefs.Close(); |
|
76 |
|
77 iSerializedSchema.Close(); |
|
78 iProperties.Close(); |
|
79 |
|
80 delete iBaseObject; |
|
81 } |
|
82 |
|
83 void CMdsSchema::Reset() |
|
84 { |
|
85 // deleting namespaces |
|
86 iNamespaceDefs.ResetAndDestroy(); |
|
87 } |
|
88 |
|
89 void CMdsSchema::AddDefaultObjectL() |
|
90 { |
|
91 |
|
92 iBaseObject = CMdsObjectDef::NewL( MdeConstants::Object::KBaseObject, NULL ); |
|
93 iBaseObject->SetId(KBaseObjectDefId); |
|
94 |
|
95 // name, type, min, max, read-only, mandatory, indexed |
|
96 iBaseObject->AddPropertyL( MdeConstants::Object::KOriginProperty, EPropertyUint8, TInt32(0), TInt32(KMaxTUint8), EFalse, EFalse, EFalse ); |
|
97 iBaseObject->AddPropertyL( MdeConstants::Object::KSizeProperty, EPropertyUint32, TUint32(0), KMaxTUint32, EFalse, EFalse, EFalse ); |
|
98 iBaseObject->AddPropertyL( MdeConstants::Object::KTimeOffsetProperty, EPropertyInt16, TInt32(KMinTInt16), TInt32(KMaxTInt16), ETrue, EFalse, EFalse ); |
|
99 iBaseObject->AddPropertyL( MdeConstants::Object::KCreationDateProperty, EPropertyTime, KMinTInt64, KMaxTInt64, EFalse, ETrue, EFalse ); |
|
100 iBaseObject->AddPropertyL( MdeConstants::Object::KLastModifiedDateProperty, EPropertyTime, KMinTInt64, KMaxTInt64, EFalse, ETrue, EFalse ); |
|
101 iBaseObject->AddPropertyL( MdeConstants::Object::KItemTypeProperty, EPropertyText, TInt32(0), TInt32(255), EFalse, EFalse, EFalse ); |
|
102 iBaseObject->AddPropertyL( MdeConstants::Object::KTitleProperty, EPropertyText, TInt32(0), TInt32(255), EFalse, EFalse, EFalse ); |
|
103 |
|
104 TInt propcount = iBaseObject->GetPropertiesCount(); |
|
105 iBaseObject->iCol2Prop.Reset(); |
|
106 |
|
107 for (TInt i = 0 ; i < propcount; i++) |
|
108 { |
|
109 CMdsPropertyDef* propertyDef = iBaseObject->GetProperty(i); |
|
110 propertyDef->SetId(i+1); |
|
111 CMdsObjectDef::TMdsColumnOrder col = |
|
112 { i + KBaseObjectBasicValueColumnOffset, *propertyDef }; |
|
113 iBaseObject->iCol2Prop.AppendL( col ); |
|
114 if( propertyDef->GetMandatory() ) |
|
115 { |
|
116 ++iBaseObject->iMandatoryPropertyCount; |
|
117 } |
|
118 } |
|
119 } |
|
120 |
|
121 void CMdsSchema::AddDefaultNamespaceL() |
|
122 { |
|
123 NamespaceAddL( KMdEDefaultNameSpace, EFalse, KNokiaVendorId, KDefaultNamespaceDefId ); |
|
124 } |
|
125 |
|
126 CMdsNamespaceDef* CMdsSchema::NamespaceAddL( const TDesC& aName, const TBool aReadOnly, TInt32 aVendorId, TDefId aNamespaceDefId ) |
|
127 { |
|
128 CMdsNamespaceDef* newNamespace = CMdsNamespaceDef::NewLC( aNamespaceDefId, aName, aReadOnly, aVendorId ); |
|
129 newNamespace->SetBaseObject( iBaseObject ); |
|
130 iNamespaceDefs.AppendL( newNamespace ); |
|
131 CleanupStack::Pop( newNamespace ); |
|
132 return newNamespace; |
|
133 } |
|
134 |
|
135 CMdsNamespaceDef* CMdsSchema::GetNamespace( const TDesC& aName ) |
|
136 { |
|
137 const TInt count = iNamespaceDefs.Count(); |
|
138 |
|
139 for( TInt i = 0; i < count; ++i ) |
|
140 { |
|
141 if ( iNamespaceDefs[i]->GetName().Compare( aName ) == 0 ) |
|
142 { |
|
143 return iNamespaceDefs[i]; |
|
144 } |
|
145 } |
|
146 return NULL; |
|
147 } |
|
148 |
|
149 const CMdsNamespaceDef* CMdsSchema::GetNamespaceByIdL( TDefId aId ) |
|
150 { |
|
151 const TInt namespaceCount = iNamespaceDefs.Count(); |
|
152 for ( TInt i = 0; i < namespaceCount; ++i ) |
|
153 { |
|
154 if( iNamespaceDefs[i]->GetId() == aId ) |
|
155 { |
|
156 return iNamespaceDefs[i]; |
|
157 } |
|
158 } |
|
159 return NULL; |
|
160 } |
|
161 |
|
162 TInt CMdsSchema::NamespaceDefsCount() const |
|
163 { |
|
164 return iNamespaceDefs.Count(); |
|
165 } |
|
166 |
|
167 const RPointerArray<CMdsNamespaceDef>& CMdsSchema::NamespaceDefs() const |
|
168 { |
|
169 return iNamespaceDefs; |
|
170 } |
|
171 |
|
172 void CMdsSchema::AddObjectToSqlClauseL( CMdsObjectDef* aObject, CMdsClauseBuffer* aClause, |
|
173 const TBool& aAddText ) |
|
174 { |
|
175 if ( !aObject->iParent ) |
|
176 { |
|
177 return; |
|
178 } |
|
179 AddObjectToSqlClauseL( (CMdsObjectDef*)aObject->iParent, aClause, aAddText); |
|
180 |
|
181 const TInt objectPropertyCount = aObject->iPropertyDefs.Count(); |
|
182 for ( TInt i = 0; i < objectPropertyCount; ++i ) |
|
183 { |
|
184 CMdsPropertyDef* propertyDef = aObject->iPropertyDefs[i]; |
|
185 // to set up text columns as a last one |
|
186 if ( propertyDef->GetType() == EPropertyText && aAddText == EFalse ) |
|
187 { |
|
188 continue; |
|
189 } |
|
190 if ( propertyDef->GetType() != EPropertyText && aAddText ) |
|
191 { |
|
192 continue; |
|
193 } |
|
194 // end |
|
195 |
|
196 // make object table definition |
|
197 aClause->AppendL( propertyDef->GetName() ); |
|
198 aClause->AppendL( KSpace ); |
|
199 aClause->AppendL( propertyDef->GetSqlTypeName() ); |
|
200 aClause->AppendL( KComma ); |
|
201 } |
|
202 } |
|
203 |
|
204 void CMdsSchema::CreateObjectTablesL() |
|
205 { |
|
206 _LIT( KBaseObjectDefinition, "CREATE TABLE IF NOT EXISTS %S%u(ObjectId INTEGER PRIMARY KEY AUTOINCREMENT,ObjectDefId INTEGER NOT NULL,Flags INTEGER,MediaId LARGEINT,UsageCount LARGEINT DEFAULT 0,GuidHigh LARGEINT,GuidLow LARGEINT,URI TEXT NOT NULL COLLATE NOCASE,Origin INTEGER,Size LARGEINT,TimeOffset INTEGER,CreationDate LARGEINT,LastModifiedDate LARGEINT,ItemType TEXT,Title TEXT,UNIQUE(GuidHigh,GuidLow),UNIQUE(MediaId,URI));" ); |
|
207 _LIT( KCreateRelationsTable, "CREATE TABLE IF NOT EXISTS Relations%u(RelationId INTEGER PRIMARY KEY AUTOINCREMENT,Flags INTEGER,RelationDefId INTEGER NOT NULL,LeftObjectId INTEGER NOT NULL,RightObjectId INTEGER NOT NULL,Parameter INTEGER,GuidHigh LARGEINT,GuidLow LARGEINT,LastModifiedDate LARGEINT);" ); |
|
208 _LIT( KCreateEventsTable, "CREATE TABLE IF NOT EXISTS Event%u(EventId INTEGER PRIMARY KEY AUTOINCREMENT,ObjectId INTEGER NOT NULL, EventDefId INTEGER NOT NULL, Timestamp INTEGER NOT NULL, Source TEXT, Participant TEXT);" ); |
|
209 _LIT( KCreateTxtSrchTable, "CREATE TABLE IF NOT EXISTS TextSearch%u(WordId INTEGER NOT NULL,ObjectId INTEGER NOT NULL,Position INTEGER);" ); |
|
210 _LIT( KCreateTxtSrchDicTable, "CREATE TABLE IF NOT EXISTS TextSearchDictionary%u(WordId INTEGER PRIMARY KEY,Word TEXT NOT NULL);" ); |
|
211 |
|
212 _LIT( KMdsSqlClauseObjTableBeg, "CREATE TABLE IF NOT EXISTS %S%u(ObjectId INTEGER NOT NULL," ); |
|
213 _LIT( KMdsSqlClauseObjTableEnd, " UNIQUE(ObjectId));" ); |
|
214 |
|
215 // Triggers |
|
216 _LIT( KMdsTriggerEvent, "CREATE TRIGGER DeleteEvent%u BEFORE DELETE ON Object%u BEGIN DELETE FROM Event%u WHERE ObjectId=OLD.ObjectId; END;" ); |
|
217 _LIT( KMdsTriggerRelation, "CREATE TRIGGER DeleteRelations%u BEFORE DELETE ON Object%u BEGIN DELETE FROM Relations%u WHERE LeftObjectId=OLD.ObjectId OR RightObjectId=OLD.ObjectId; END;" ); |
|
218 _LIT( KMdsTriggerTextSearch, "CREATE TRIGGER DeleteTextSearch%u BEFORE DELETE ON Object%u BEGIN DELETE FROM TextSearch%u WHERE ObjectId=OLD.ObjectId; END;" ); |
|
219 |
|
220 // UsageCount relation triggers |
|
221 _LIT( KMdsTriggerInsertRelation, "CREATE TRIGGER InsertRelations%u INSERT ON Relations%u BEGIN UPDATE Object%u SET UsageCount = UsageCount + 1 WHERE ObjectId=NEW.LeftObjectId OR ObjectId=NEW.RightObjectId; END;" ); |
|
222 _LIT( KMdsTriggerUpdateRelation, "CREATE TRIGGER UpdateRelations%u UPDATE OF LeftObjectId, RightObjectId ON Relations%u WHEN OLD.Flags=NEW.Flags BEGIN UPDATE Object%u SET UsageCount = UsageCount - 1 WHERE ObjectId=OLD.LeftObjectId OR ObjectId=OLD.RightObjectId; UPDATE Object1 SET UsageCount = UsageCount + 1 WHERE ObjectId=NEW.LeftObjectId OR ObjectId=NEW.RightObjectId; END;" ); |
|
223 _LIT( KMdsTriggerUpdateNotRemovedRelation, "CREATE TRIGGER UpdateNotRemovedRelations%u UPDATE OF Flags ON Relations%u WHEN OLD.Flags!=NEW.Flags AND NOT NEW.Flags&%u BEGIN UPDATE Object%u SET UsageCount = UsageCount + 1 WHERE ObjectId=NEW.LeftObjectId OR ObjectId=NEW.RightObjectId; END;" ); |
|
224 _LIT( KMdsTriggerUpdateRemovedRelation, "CREATE TRIGGER UpdateRemovedRelations%u UPDATE OF Flags ON Relations%u WHEN OLD.Flags!=NEW.Flags AND NEW.Flags&%u AND NOT OLD.Flags&%u BEGIN UPDATE Object%u SET UsageCount = UsageCount - 1 WHERE ObjectId=OLD.LeftObjectId OR ObjectId=OLD.RightObjectId; END;" ); |
|
225 |
|
226 // Relation indexes |
|
227 _LIT( KMdsIndexRelationLeftObjectId, "CREATE INDEX RelationsLeftObjectIdIndex%u ON Relations%u(LeftObjectId);" ); |
|
228 _LIT( KMdsIndexRelationRightObjectId, "CREATE INDEX RelationsRightObjectIdIndex%u ON Relations%u(RightObjectId);" ); |
|
229 |
|
230 // freetext indexes |
|
231 _LIT( KMdsIndexFreetextWordId, "CREATE INDEX FreetextWordIdIndex%u ON TextSearch%u(WordId);" ); |
|
232 _LIT( KMdsIndexFreetextObjectId, "CREATE INDEX FreetextObjectIdIndex%u ON TextSearch%u(ObjectId);" ); |
|
233 |
|
234 // ObjectTypeDefinition index |
|
235 _LIT( KMdsIndexObjectDefId, "CREATE INDEX ObjectDefIndex%u ON Object%u(ObjectDefId);" ); |
|
236 |
|
237 // create tables |
|
238 CMdsClauseBuffer* clause = CMdsClauseBuffer::NewLC( 1024 ); |
|
239 clause->ReserveSpaceL( KBaseObjectDefinition.iTypeLength + 30 ); // maxIntNumberDecimal.Length = 10 |
|
240 CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); |
|
241 RRowData emptyRowData; |
|
242 CleanupClosePushL( emptyRowData ); |
|
243 |
|
244 // for triggers |
|
245 CMdsClauseBuffer* clauseTrigger = CMdsClauseBuffer::NewLC( 1024 ); |
|
246 |
|
247 const TInt namespaceDefCount = iNamespaceDefs.Count(); |
|
248 |
|
249 // add objectdef[number] to DB |
|
250 for( TInt i = 0; i < namespaceDefCount; ++i ) |
|
251 { |
|
252 CMdsNamespaceDef* namespaceDef = iNamespaceDefs[i]; |
|
253 const TDefId namespaceDefId = namespaceDef->GetId(); |
|
254 |
|
255 if (!namespaceDef->GetTableStoredInDB()) |
|
256 { |
|
257 // add base objectdef[number] |
|
258 clause->BufferL().Format( KBaseObjectDefinition, &MdeConstants::Object::KBaseObject, namespaceDefId ); |
|
259 TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) ); |
|
260 |
|
261 // add relations[number] |
|
262 clause->BufferL().Format( KCreateRelationsTable, namespaceDefId ); |
|
263 TRAPD( errRel, connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) ); |
|
264 if( errRel == KErrNone ) |
|
265 { |
|
266 clauseTrigger->ReserveSpaceL( KMdsTriggerRelation().Size() + ( KMaxUintValueLength * 3 ) ); |
|
267 clauseTrigger->BufferL().Format( KMdsTriggerRelation, namespaceDefId, namespaceDefId, namespaceDefId ); |
|
268 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
269 } |
|
270 |
|
271 // add event[number] |
|
272 clause->BufferL().Format( KCreateEventsTable, namespaceDefId ); |
|
273 TRAPD( errEve, connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) ); |
|
274 if( errEve == KErrNone ) |
|
275 { |
|
276 clauseTrigger->ReserveSpaceL( KMdsTriggerEvent().Size() + ( KMaxUintValueLength * 3 ) ); |
|
277 clauseTrigger->BufferL().Format( KMdsTriggerEvent, namespaceDefId, namespaceDefId, namespaceDefId ); |
|
278 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
279 } |
|
280 |
|
281 // add textsearch[number] |
|
282 clause->BufferL().Format( KCreateTxtSrchTable, namespaceDefId ); |
|
283 TRAPD( errTS, connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) ); |
|
284 if( errTS == KErrNone ) |
|
285 { |
|
286 clauseTrigger->ReserveSpaceL( KMdsTriggerTextSearch().Size() + ( KMaxUintValueLength * 3 ) ); |
|
287 clauseTrigger->BufferL().Format( KMdsTriggerTextSearch, namespaceDefId, namespaceDefId, namespaceDefId ); |
|
288 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
289 |
|
290 // add KMdsIndexFreetextWordId[number] |
|
291 clauseTrigger->ReserveSpaceL( KMdsIndexFreetextWordId().Size() + ( KMaxUintValueLength * 2 ) ); |
|
292 clauseTrigger->BufferL().Format( KMdsIndexFreetextWordId, namespaceDefId, namespaceDefId ); |
|
293 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
294 |
|
295 // add KMdsIndexFreetextObjectId[number] |
|
296 clauseTrigger->ReserveSpaceL( KMdsIndexFreetextObjectId().Size() + ( KMaxUintValueLength * 2 ) ); |
|
297 clauseTrigger->BufferL().Format( KMdsIndexFreetextObjectId, namespaceDefId, namespaceDefId ); |
|
298 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
299 } |
|
300 |
|
301 // add textsearchdictionary[number] |
|
302 clause->BufferL().Format( KCreateTxtSrchDicTable, namespaceDefId ); |
|
303 TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) ); |
|
304 |
|
305 // add insertrelations[number] |
|
306 clauseTrigger->ReserveSpaceL( KMdsTriggerInsertRelation().Size() + ( KMaxUintValueLength * 3 ) ); |
|
307 clauseTrigger->BufferL().Format( KMdsTriggerInsertRelation, namespaceDefId, namespaceDefId, namespaceDefId ); |
|
308 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
309 |
|
310 // add updaterelations[number] |
|
311 clauseTrigger->ReserveSpaceL( KMdsTriggerUpdateRelation().Size() + ( KMaxUintValueLength * 3 ) ); |
|
312 clauseTrigger->BufferL().Format( KMdsTriggerUpdateRelation, namespaceDefId, namespaceDefId, namespaceDefId ); |
|
313 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
314 |
|
315 // add updatenotremovedrelations[number] |
|
316 clauseTrigger->ReserveSpaceL( KMdsTriggerUpdateNotRemovedRelation().Size() + ( KMaxUintValueLength * 4 ) ); |
|
317 clauseTrigger->BufferL().Format( KMdsTriggerUpdateNotRemovedRelation, namespaceDefId, namespaceDefId, |
|
318 EMdERelationFlagNotPresent | EMdERelationFlagDeleted, namespaceDefId ); |
|
319 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
320 |
|
321 // add updateremovedrelations[number] |
|
322 clauseTrigger->ReserveSpaceL( KMdsTriggerUpdateRemovedRelation().Size() + ( KMaxUintValueLength * 5 ) ); |
|
323 clauseTrigger->BufferL().Format( KMdsTriggerUpdateRemovedRelation, namespaceDefId, namespaceDefId, EMdERelationFlagNotPresent | EMdERelationFlagDeleted, EMdERelationFlagNotPresent | EMdERelationFlagDeleted, namespaceDefId ); |
|
324 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
325 |
|
326 // add relationleftobjectidindex[number] |
|
327 clauseTrigger->ReserveSpaceL( KMdsIndexRelationLeftObjectId().Size() + ( KMaxUintValueLength * 2 ) ); |
|
328 clauseTrigger->BufferL().Format( KMdsIndexRelationLeftObjectId, namespaceDefId, namespaceDefId ); |
|
329 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
330 |
|
331 // add relationrightobjectidindex[number] |
|
332 clauseTrigger->ReserveSpaceL( KMdsIndexRelationRightObjectId().Size() + ( KMaxUintValueLength * 2 ) ); |
|
333 clauseTrigger->BufferL().Format( KMdsIndexRelationRightObjectId, namespaceDefId, namespaceDefId ); |
|
334 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
335 |
|
336 // add objectdefidindex[number] |
|
337 clauseTrigger->ReserveSpaceL( KMdsIndexObjectDefId().Size() + ( KMaxUintValueLength * 2 ) ); |
|
338 clauseTrigger->BufferL().Format( KMdsIndexObjectDefId, namespaceDefId, namespaceDefId ); |
|
339 connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData ); |
|
340 |
|
341 namespaceDef->SetTableStoredInDB(); |
|
342 } |
|
343 |
|
344 const TInt objectDefCount = namespaceDef->iObjectDefs.Count(); |
|
345 |
|
346 for ( TInt j = 0; j < objectDefCount; ++j ) |
|
347 { |
|
348 CMdsObjectDef* objectDef = namespaceDef->iObjectDefs[j]; |
|
349 |
|
350 if (!objectDef->GetTableStoredInDB()) |
|
351 { |
|
352 clause->BufferL().Format( KMdsSqlClauseObjTableBeg, &objectDef->GetName(), namespaceDef->GetId() ); |
|
353 |
|
354 // add no text properties |
|
355 AddObjectToSqlClauseL( objectDef, clause, EFalse ); |
|
356 // add text properties at end |
|
357 AddObjectToSqlClauseL( objectDef, clause, ETrue ); |
|
358 |
|
359 clause->AppendL( KMdsSqlClauseObjTableEnd ); |
|
360 TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) ); |
|
361 |
|
362 objectDef->SetTableStoredInDB(); |
|
363 } |
|
364 |
|
365 const TInt objectPropertyCount = objectDef->iPropertyDefs.Count(); |
|
366 for ( TInt k = 0; k < objectPropertyCount; ++k ) |
|
367 { |
|
368 CMdsPropertyDef* propertyDef = objectDef->iPropertyDefs[k]; |
|
369 |
|
370 if ( propertyDef->GetIndexed() ) |
|
371 { |
|
372 iProperties.AppendL( TPropertyInfo( objectDef->GetName(), |
|
373 propertyDef->GetName(), namespaceDef->GetId() ) ); |
|
374 } |
|
375 } |
|
376 } |
|
377 iProperties.AppendL( TPropertyInfo( MdeConstants::Object::KBaseObject, MdeConstants::Object::KItemTypeProperty, namespaceDef->GetId() ) ); |
|
378 } |
|
379 |
|
380 CleanupStack::PopAndDestroy( 3, clause ); // clauseTrigger, emptyRowData, clause |
|
381 } |
|
382 |
|
383 void CMdsSchema::CreatePropertyIndexL( const TDesC& aPropertyName, const TDesC& aTableName, |
|
384 TDefId aNamespaceId ) |
|
385 { |
|
386 _LIT( KMdsPropertyIndexCreate, "CREATE INDEX %S%SIndex%u ON %S%u(%S);" ); |
|
387 |
|
388 const TUint clauseLength = KMdsPropertyIndexCreate.iTypeLength + aTableName.Length() * 2 + |
|
389 + aPropertyName.Length() * 2 + KMaxUintValueLength * 2; |
|
390 CMdsClauseBuffer* clause = CMdsClauseBuffer::NewLC( clauseLength ); |
|
391 CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); |
|
392 RRowData emptyRowData; |
|
393 CleanupClosePushL( emptyRowData ); |
|
394 clause->BufferL().Format( KMdsPropertyIndexCreate, &aTableName, &aPropertyName, aNamespaceId, |
|
395 &aTableName, aNamespaceId, &aPropertyName ); |
|
396 TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) ); |
|
397 CleanupStack::PopAndDestroy( 2, clause ); // emptyRowData, clause |
|
398 } |
|
399 |
|
400 void CMdsSchema::StoreToDBL() |
|
401 { |
|
402 CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); |
|
403 RMdSTransaction transaction( connection ); |
|
404 CleanupClosePushL( transaction ); |
|
405 User::LeaveIfError( transaction.Error() ); |
|
406 |
|
407 StoreNamespacesAndBaseObjectL(); |
|
408 CreateObjectTablesL(); |
|
409 StoreSchemaToDBL(); |
|
410 CreateCol2PropTableL(); |
|
411 |
|
412 transaction.CommitL(); |
|
413 CleanupStack::PopAndDestroy( &transaction ); |
|
414 |
|
415 TUint propertyCount = iProperties.Count(); |
|
416 for ( TUint i = 0; i < propertyCount; ++i ) |
|
417 { |
|
418 TPropertyInfo& propertyInfo = iProperties[i]; |
|
419 CreatePropertyIndexL( propertyInfo.iPropertyName, propertyInfo.iTableName, |
|
420 propertyInfo.iNamespaceId ); |
|
421 } |
|
422 iProperties.Reset(); |
|
423 } |
|
424 |
|
425 void CMdsSchema::AddCol2PropObjectL( CMdsObjectDef* aObject, CMdsObjectDef* aChildObject, |
|
426 TUint32& aPropertyColumnCounter, TBool aText ) |
|
427 { |
|
428 _LIT( KMdsSqlClauseAddCol2Prop, "INSERT INTO Col2Prop(ObjectDefId,PropertyDefId,ColumnId) Values(?,?,?);" ); |
|
429 CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); |
|
430 if ( !aChildObject->iParent ) |
|
431 { |
|
432 if (aText) |
|
433 { |
|
434 return; |
|
435 } |
|
436 RRowData rowData; |
|
437 CleanupClosePushL( rowData ); |
|
438 const TInt childObjectPropertyCount = aChildObject->iPropertyDefs.Count(); |
|
439 for ( TInt i = 0; i < childObjectPropertyCount; ++i ) |
|
440 { |
|
441 CMdsPropertyDef* propertyDef = aChildObject->iPropertyDefs[i]; |
|
442 CMdsObjectDef::TMdsColumnOrder col = { aChildObject->iCol2Prop[i].iColumnId, *propertyDef }; |
|
443 aObject->iCol2Prop.AppendL( col ); |
|
444 |
|
445 if( propertyDef->GetMandatory() ) |
|
446 { |
|
447 ++aObject->iMandatoryPropertyCount; |
|
448 } |
|
449 |
|
450 ++aPropertyColumnCounter; |
|
451 rowData.Reset(); |
|
452 rowData.AppendL( TColumn( aObject->GetId() ) ); |
|
453 rowData.AppendL( TColumn( propertyDef->GetId() ) ); |
|
454 rowData.AppendL( TColumn( col.iColumnId ) ); |
|
455 connection.ExecuteL( KMdsSqlClauseAddCol2Prop, rowData ); |
|
456 } |
|
457 CleanupStack::PopAndDestroy( &rowData ); |
|
458 return; |
|
459 } |
|
460 |
|
461 AddCol2PropObjectL( aObject, (CMdsObjectDef*)aChildObject->iParent, aPropertyColumnCounter, aText ); |
|
462 |
|
463 // if parent is baseobject |
|
464 if ( !aText && !aChildObject->iParent->iParent ) |
|
465 { |
|
466 ++aPropertyColumnCounter; |
|
467 } |
|
468 |
|
469 RRowData rowData; |
|
470 CleanupClosePushL( rowData ); |
|
471 |
|
472 const TInt childObjectPropertyCount = aChildObject->iPropertyDefs.Count(); |
|
473 for ( TInt i = 0; i < childObjectPropertyCount; ++i ) |
|
474 { |
|
475 CMdsPropertyDef* propertyDef = aChildObject->iPropertyDefs[i]; |
|
476 CMdsObjectDef::TMdsColumnOrder col = { 0, *propertyDef }; |
|
477 if ( aText && propertyDef->GetType() != EPropertyText || |
|
478 !aText && propertyDef->GetType() == EPropertyText ) |
|
479 { |
|
480 continue; |
|
481 } |
|
482 |
|
483 col.iColumnId = aPropertyColumnCounter++; |
|
484 |
|
485 aObject->iCol2Prop.AppendL( col ); |
|
486 |
|
487 if( propertyDef->GetMandatory() ) |
|
488 { |
|
489 ++aObject->iMandatoryPropertyCount; |
|
490 } |
|
491 |
|
492 rowData.Reset(); |
|
493 rowData.AppendL( TColumn( aObject->GetId() ) ); |
|
494 rowData.AppendL( TColumn( propertyDef->GetId() ) ); |
|
495 rowData.AppendL( TColumn( col.iColumnId ) ); |
|
496 connection.ExecuteL( KMdsSqlClauseAddCol2Prop, rowData ); |
|
497 } |
|
498 |
|
499 CleanupStack::PopAndDestroy( &rowData ); |
|
500 } |
|
501 |
|
502 void CMdsSchema::CreateCol2PropTableL() |
|
503 { |
|
504 _LIT( KMdsSqlClauseCol2Prop, "CREATE TABLE IF NOT EXISTS Col2Prop(ObjectDefId INTEGER NOT NULL,PropertyDefId INTEGER NOT NULL,ColumnId INTEGER NOT NULL);" ); |
|
505 |
|
506 RRowData emptyRowData; |
|
507 CleanupClosePushL( emptyRowData ); |
|
508 |
|
509 CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); |
|
510 // create binding column <--> property table |
|
511 connection.ExecuteL( KMdsSqlClauseCol2Prop, emptyRowData ); |
|
512 TUint32 propertyColumnCounter; |
|
513 |
|
514 const TInt count = iNamespaceDefs.Count(); |
|
515 |
|
516 for( TInt i = 0; i < count; ++i ) |
|
517 { |
|
518 CMdsNamespaceDef* namespaceDef = iNamespaceDefs[i]; |
|
519 const TInt namespaceObjectCount = namespaceDef->iObjectDefs.Count(); |
|
520 for ( TInt j = 0; j < namespaceObjectCount; ++j ) |
|
521 { |
|
522 CMdsObjectDef* objectDef = namespaceDef->iObjectDefs[j]; |
|
523 if (!objectDef->GetC2PStoredInDB()) |
|
524 { |
|
525 propertyColumnCounter = KBaseObjectBasicValueColumnOffset; |
|
526 |
|
527 objectDef->iCol2Prop.Reset(); |
|
528 objectDef->iMandatoryPropertyCount = 0; |
|
529 |
|
530 AddCol2PropObjectL( objectDef, objectDef, propertyColumnCounter, EFalse ); |
|
531 AddCol2PropObjectL( objectDef, objectDef, propertyColumnCounter, ETrue ); |
|
532 objectDef->SetC2PStoredInDB(); |
|
533 } |
|
534 } |
|
535 } |
|
536 CleanupStack::PopAndDestroy( &emptyRowData ); |
|
537 } |
|
538 |
|
539 void CMdsSchema::StoreNamespacesAndBaseObjectL() |
|
540 { |
|
541 _LIT( KMdsSqlClauseNamespaceDef, "CREATE TABLE IF NOT EXISTS NamespaceDef(NamespaceDefId INTEGER PRIMARY KEY,ReadOnly INTEGER,VendorId INTEGER,Name TEXT);" ); |
|
542 _LIT( KMdsSqlClauseObjectDef, "CREATE TABLE IF NOT EXISTS ObjectDef(ObjectDefId INTEGER PRIMARY KEY,NamespaceDefId INTEGER NOT NULL,ParentDefId INTEGER NOT NULL,Flags INTEGER,Name TEXT);" ); |
|
543 _LIT( KMdsSqlClausePropertyDef, "CREATE TABLE IF NOT EXISTS PropertyDef(PropertyDefId INTEGER PRIMARY KEY,ObjectDefId INTEGER NOT NULL,Flags INTEGER,Type INTEGER,MinValue NUMERIC,MaxValue NUMERIC,Name TEXT);" ); |
|
544 _LIT( KMdsSqlClauseRelationDef, "CREATE TABLE IF NOT EXISTS RelationDef(RelationDefId INTEGER PRIMARY KEY,NamespaceDefId INTEGER NOT NULL,Name TEXT);" ); |
|
545 _LIT( KMdsSqlClauseEventDef, "CREATE TABLE IF NOT EXISTS EventDef(EventDefId INTEGER PRIMARY KEY,NamespaceDefId INTEGER NOT NULL,Priority INTEGER,Name TEXT);" ); |
|
546 |
|
547 RRowData emptyRowData; |
|
548 CleanupClosePushL( emptyRowData ); |
|
549 |
|
550 // create tables |
|
551 const TUint KNumClauses = 5; |
|
552 |
|
553 CDesCArrayFlat* descarray = new (ELeave) CDesCArrayFlat(KNumClauses); |
|
554 CleanupStack::PushL(descarray); |
|
555 descarray->AppendL(KMdsSqlClauseNamespaceDef); |
|
556 descarray->AppendL(KMdsSqlClauseObjectDef); |
|
557 descarray->AppendL(KMdsSqlClausePropertyDef); |
|
558 descarray->AppendL(KMdsSqlClauseRelationDef); |
|
559 descarray->AppendL(KMdsSqlClauseEventDef); |
|
560 |
|
561 CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); |
|
562 |
|
563 TInt error; |
|
564 for (TUint i = 0; i < KNumClauses; i++) |
|
565 { |
|
566 TRAP( error,connection.ExecuteL( (*descarray)[i], emptyRowData ) ); |
|
567 if ( error != KErrNone && error != KSqlErrGeneral ) |
|
568 { |
|
569 User::Leave( error ); |
|
570 } |
|
571 } |
|
572 descarray->Reset(); |
|
573 CleanupStack::PopAndDestroy( descarray ); |
|
574 |
|
575 const TInt count = iNamespaceDefs.Count(); |
|
576 |
|
577 // add only namespaceDef to DB |
|
578 for( TInt i = 0; i < count; ++i ) |
|
579 { |
|
580 iNamespaceDefs[i]->StoreToDBL( ETrue ); |
|
581 } |
|
582 |
|
583 CleanupStack::PopAndDestroy( &emptyRowData ); |
|
584 } |
|
585 |
|
586 void CMdsSchema::StoreSchemaToDBL() |
|
587 { |
|
588 _LIT( KMdsSqlClauseDeleteBoFromOd, "DELETE FROM ObjectDef WHERE ObjectDefId=?;" ); |
|
589 _LIT( KMdsSqlClauseDeleteBoFromPd, "DELETE FROM PropertyDef WHERE ObjectDefId=?;" ); |
|
590 |
|
591 iBaseObject->StoreToDBL( KNoDefId ); |
|
592 |
|
593 const TInt count = iNamespaceDefs.Count(); |
|
594 |
|
595 // add namespaceDef to DB |
|
596 for( TInt i = 0; i < count; ++i ) |
|
597 { |
|
598 iNamespaceDefs[i]->StoreToDBL(); |
|
599 } |
|
600 |
|
601 RRowData removeBo; |
|
602 CleanupClosePushL( removeBo ); |
|
603 removeBo.AppendL( TColumn( KBaseObjectDefId ) ); |
|
604 |
|
605 CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); |
|
606 TRAPD( err, connection.ExecuteL( KMdsSqlClauseDeleteBoFromOd, removeBo ) ); |
|
607 TRAP ( err, connection.ExecuteL( KMdsSqlClauseDeleteBoFromPd, removeBo ) ); |
|
608 |
|
609 CleanupStack::PopAndDestroy( &removeBo ); |
|
610 } |
|
611 |
|
612 void CMdsSchema::MergeElementsL( CMdsSchema& aSchema, const TBool& aDryRun ) |
|
613 { |
|
614 const TInt count = aSchema.iNamespaceDefs.Count(); |
|
615 |
|
616 for ( TInt i = 0; i < count; ++i ) |
|
617 { |
|
618 CMdsNamespaceDef* lNamespace = NULL; |
|
619 CMdsNamespaceDef* rNamespace = aSchema.iNamespaceDefs[i]; |
|
620 // reseting after namespace read from file |
|
621 rNamespace->UnsetFirstRead(); |
|
622 // search for namespace |
|
623 lNamespace = GetNamespace( rNamespace->GetName() ); |
|
624 if ( !lNamespace ) |
|
625 { |
|
626 if ( !aDryRun ) |
|
627 { |
|
628 // just add pointer to new schema and remove it from old one |
|
629 iNamespaceDefs.AppendL( rNamespace ); |
|
630 aSchema.iNamespaceDefs[i] = NULL; |
|
631 rNamespace->SetAllNotStoredInDB(); |
|
632 } |
|
633 } |
|
634 else |
|
635 { |
|
636 // copy appropriate elements |
|
637 if ( lNamespace->GetVendorId() == rNamespace->GetVendorId() && !lNamespace->GetReadOnly() ) |
|
638 { |
|
639 lNamespace->MergeObjectsL( rNamespace, aDryRun ); |
|
640 lNamespace->MergeEventsL( rNamespace, aDryRun ); |
|
641 lNamespace->MergeRelationsL( rNamespace, aDryRun ); |
|
642 } |
|
643 else |
|
644 { |
|
645 User::Leave( KErrAccessDenied ); |
|
646 } |
|
647 } |
|
648 } |
|
649 } |
|
650 |
|
651 void CMdsSchema::MergeNamespacesL( CMdsSchema& aSchema ) |
|
652 { |
|
653 if ( iNamespaceDefs.Count() == 0 ) |
|
654 {// speed optimization |
|
655 Reset(); |
|
656 |
|
657 const TInt count = aSchema.iNamespaceDefs.Count(); |
|
658 |
|
659 for ( TInt i = 0; i < count; ++i ) |
|
660 { |
|
661 // reseting after namespace read from file |
|
662 aSchema.iNamespaceDefs[i]->UnsetFirstRead(); |
|
663 iNamespaceDefs.AppendL( aSchema.iNamespaceDefs[i] ); |
|
664 aSchema.iNamespaceDefs[i] = NULL; |
|
665 } |
|
666 aSchema.Reset(); |
|
667 } |
|
668 else |
|
669 { |
|
670 MergeElementsL( aSchema, ETrue ); |
|
671 MergeElementsL( aSchema, EFalse ); |
|
672 } |
|
673 } |
|
674 |
|
675 void CMdsSchema::SerializeToSharedMemoryL() |
|
676 { |
|
677 const TInt namespaceCount = iNamespaceDefs.Count(); |
|
678 |
|
679 // namespace count, namespace offsets |
|
680 TUint32 bufferSize = sizeof(TMdCSchema) + namespaceCount * sizeof(TMdCNamespaceDef); |
|
681 |
|
682 for ( TInt i = 0; i < namespaceCount; ++i ) |
|
683 { |
|
684 bufferSize += iNamespaceDefs[i]->RequiredBufferSize(); |
|
685 } |
|
686 |
|
687 // create shared memory chunk |
|
688 iSerialized = EFalse; |
|
689 iSerializedSchema.Close(); |
|
690 ++iSchemaHandle; |
|
691 HBufC* name = HBufC::NewLC( KSchemaChunkName.iTypeLength + KMaxUintValueLength ); |
|
692 *name = KSchemaChunkName; |
|
693 name->Des().AppendNum( iSchemaHandle ); |
|
694 |
|
695 TInt error = KErrNone; |
|
696 while( (error = iSerializedSchema.CreateGlobal( *name, bufferSize, bufferSize )) == KErrAlreadyExists ) |
|
697 { |
|
698 ++iSchemaHandle; |
|
699 *name = KSchemaChunkName; |
|
700 name->Des().AppendNum( iSchemaHandle ); |
|
701 } |
|
702 User::LeaveIfError( error ); |
|
703 |
|
704 CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( iSerializedSchema.Base(), bufferSize ); |
|
705 |
|
706 TMdCSchema schema; |
|
707 schema.iNamespaceDefs.iPtr.iCount = namespaceCount; |
|
708 schema.iNamespaceDefs.iPtr.iOffset = sizeof(schema); |
|
709 schema.SerializeL( *buffer ); |
|
710 |
|
711 TMdCOffset freeSpace = schema.iNamespaceDefs.iPtr.iOffset + namespaceCount * sizeof(TMdCNamespaceDef); |
|
712 for ( TInt i = 0; i < namespaceCount; ++i ) |
|
713 { |
|
714 buffer->PositionL( schema.iNamespaceDefs.iPtr.iOffset + i * sizeof(TMdCNamespaceDef) ); |
|
715 |
|
716 // write namespace |
|
717 freeSpace = iNamespaceDefs[i]->SerializeL( *buffer, freeSpace ); |
|
718 } |
|
719 |
|
720 CleanupStack::PopAndDestroy( buffer ); |
|
721 CleanupStack::PopAndDestroy( name ); |
|
722 iSerialized = ETrue; |
|
723 } |
|
724 |
|
725 TInt CMdsSchema::SharedMemoryHandleL() |
|
726 { |
|
727 if ( !iSerialized ) |
|
728 { |
|
729 User::Leave( KErrNotReady ); |
|
730 } |
|
731 return iSchemaHandle; |
|
732 } |
|
733 |