--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/metadataengine/server/src/mdsschema.cpp Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,733 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Class to hold description about schema
+*
+*/
+
+#include <badesca.h>
+#include "mdsschema.h"
+
+#include "mdcdef.h"
+#include "mdsnamespacedef.h"
+#include "mdsobjectdef.h"
+#include "mdsclausebuffer.h"
+#include "mdsfindsqlclausedef.h"
+#include "mdspropertydef.h"
+#include "mdsdbconnectionpool.h"
+#include "mdssqliteconnection.h"
+#include "mdcserializationbuffer.h"
+#include <mdeconstants.h>
+
+
+/**
+ * NewLC
+ */
+CMdsSchema* CMdsSchema::NewLC( )
+ {
+ CMdsSchema* ret = new( ELeave ) CMdsSchema( );
+ CleanupStack::PushL( ret );
+ ret->ConstructL( );
+ return ret;
+ }
+
+/**
+ * NewL
+ */
+CMdsSchema* CMdsSchema::NewL( )
+ {
+ CMdsSchema* ret = CMdsSchema::NewLC( );
+ CleanupStack::Pop( ret );
+ return ret;
+ }
+
+/**
+ * ConstructL
+ */
+void CMdsSchema::ConstructL( )
+ {
+ }
+
+/**
+ * Constructor
+ */
+CMdsSchema::CMdsSchema() : iBaseObject( NULL ),
+ iSerialized( EFalse ), iSchemaHandle( 0 )
+ {
+ }
+
+/**
+ * Destructor
+ */
+CMdsSchema::~CMdsSchema()
+ {
+ iNamespaceDefs.ResetAndDestroy();
+ iNamespaceDefs.Close();
+
+ iSerializedSchema.Close();
+ iProperties.Close();
+
+ delete iBaseObject;
+ }
+
+void CMdsSchema::Reset()
+ {
+ // deleting namespaces
+ iNamespaceDefs.ResetAndDestroy();
+ }
+
+void CMdsSchema::AddDefaultObjectL()
+ {
+
+ iBaseObject = CMdsObjectDef::NewL( MdeConstants::Object::KBaseObject, NULL );
+ iBaseObject->SetId(KBaseObjectDefId);
+
+ // name, type, min, max, read-only, mandatory, indexed
+ iBaseObject->AddPropertyL( MdeConstants::Object::KOriginProperty, EPropertyUint8, TInt32(0), TInt32(KMaxTUint8), EFalse, EFalse, EFalse );
+ iBaseObject->AddPropertyL( MdeConstants::Object::KSizeProperty, EPropertyUint32, TUint32(0), KMaxTUint32, EFalse, EFalse, EFalse );
+ iBaseObject->AddPropertyL( MdeConstants::Object::KTimeOffsetProperty, EPropertyInt16, TInt32(KMinTInt16), TInt32(KMaxTInt16), ETrue, EFalse, EFalse );
+ iBaseObject->AddPropertyL( MdeConstants::Object::KCreationDateProperty, EPropertyTime, KMinTInt64, KMaxTInt64, EFalse, ETrue, EFalse );
+ iBaseObject->AddPropertyL( MdeConstants::Object::KLastModifiedDateProperty, EPropertyTime, KMinTInt64, KMaxTInt64, EFalse, ETrue, EFalse );
+ iBaseObject->AddPropertyL( MdeConstants::Object::KItemTypeProperty, EPropertyText, TInt32(0), TInt32(255), EFalse, EFalse, EFalse );
+ iBaseObject->AddPropertyL( MdeConstants::Object::KTitleProperty, EPropertyText, TInt32(0), TInt32(255), EFalse, EFalse, EFalse );
+
+ TInt propcount = iBaseObject->GetPropertiesCount();
+ iBaseObject->iCol2Prop.Reset();
+
+ for (TInt i = 0 ; i < propcount; i++)
+ {
+ CMdsPropertyDef* propertyDef = iBaseObject->GetProperty(i);
+ propertyDef->SetId(i+1);
+ CMdsObjectDef::TMdsColumnOrder col =
+ { i + KBaseObjectBasicValueColumnOffset, *propertyDef };
+ iBaseObject->iCol2Prop.AppendL( col );
+ if( propertyDef->GetMandatory() )
+ {
+ ++iBaseObject->iMandatoryPropertyCount;
+ }
+ }
+ }
+
+void CMdsSchema::AddDefaultNamespaceL()
+ {
+ NamespaceAddL( KMdEDefaultNameSpace, EFalse, KNokiaVendorId, KDefaultNamespaceDefId );
+ }
+
+CMdsNamespaceDef* CMdsSchema::NamespaceAddL( const TDesC& aName, const TBool aReadOnly, TInt32 aVendorId, TDefId aNamespaceDefId )
+ {
+ CMdsNamespaceDef* newNamespace = CMdsNamespaceDef::NewLC( aNamespaceDefId, aName, aReadOnly, aVendorId );
+ newNamespace->SetBaseObject( iBaseObject );
+ iNamespaceDefs.AppendL( newNamespace );
+ CleanupStack::Pop( newNamespace );
+ return newNamespace;
+ }
+
+CMdsNamespaceDef* CMdsSchema::GetNamespace( const TDesC& aName )
+ {
+ const TInt count = iNamespaceDefs.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ if ( iNamespaceDefs[i]->GetName().Compare( aName ) == 0 )
+ {
+ return iNamespaceDefs[i];
+ }
+ }
+ return NULL;
+ }
+
+const CMdsNamespaceDef* CMdsSchema::GetNamespaceByIdL( TDefId aId )
+ {
+ const TInt namespaceCount = iNamespaceDefs.Count();
+ for ( TInt i = 0; i < namespaceCount; ++i )
+ {
+ if( iNamespaceDefs[i]->GetId() == aId )
+ {
+ return iNamespaceDefs[i];
+ }
+ }
+ return NULL;
+ }
+
+TInt CMdsSchema::NamespaceDefsCount() const
+ {
+ return iNamespaceDefs.Count();
+ }
+
+const RPointerArray<CMdsNamespaceDef>& CMdsSchema::NamespaceDefs() const
+ {
+ return iNamespaceDefs;
+ }
+
+void CMdsSchema::AddObjectToSqlClauseL( CMdsObjectDef* aObject, CMdsClauseBuffer* aClause,
+ const TBool& aAddText )
+ {
+ if ( !aObject->iParent )
+ {
+ return;
+ }
+ AddObjectToSqlClauseL( (CMdsObjectDef*)aObject->iParent, aClause, aAddText);
+
+ const TInt objectPropertyCount = aObject->iPropertyDefs.Count();
+ for ( TInt i = 0; i < objectPropertyCount; ++i )
+ {
+ CMdsPropertyDef* propertyDef = aObject->iPropertyDefs[i];
+ // to set up text columns as a last one
+ if ( propertyDef->GetType() == EPropertyText && aAddText == EFalse )
+ {
+ continue;
+ }
+ if ( propertyDef->GetType() != EPropertyText && aAddText )
+ {
+ continue;
+ }
+ // end
+
+ // make object table definition
+ aClause->AppendL( propertyDef->GetName() );
+ aClause->AppendL( KSpace );
+ aClause->AppendL( propertyDef->GetSqlTypeName() );
+ aClause->AppendL( KComma );
+ }
+ }
+
+void CMdsSchema::CreateObjectTablesL()
+ {
+ _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));" );
+ _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);" );
+ _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);" );
+ _LIT( KCreateTxtSrchTable, "CREATE TABLE IF NOT EXISTS TextSearch%u(WordId INTEGER NOT NULL,ObjectId INTEGER NOT NULL,Position INTEGER);" );
+ _LIT( KCreateTxtSrchDicTable, "CREATE TABLE IF NOT EXISTS TextSearchDictionary%u(WordId INTEGER PRIMARY KEY,Word TEXT NOT NULL);" );
+
+ _LIT( KMdsSqlClauseObjTableBeg, "CREATE TABLE IF NOT EXISTS %S%u(ObjectId INTEGER NOT NULL," );
+ _LIT( KMdsSqlClauseObjTableEnd, " UNIQUE(ObjectId));" );
+
+ // Triggers
+ _LIT( KMdsTriggerEvent, "CREATE TRIGGER DeleteEvent%u BEFORE DELETE ON Object%u BEGIN DELETE FROM Event%u WHERE ObjectId=OLD.ObjectId; END;" );
+ _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;" );
+ _LIT( KMdsTriggerTextSearch, "CREATE TRIGGER DeleteTextSearch%u BEFORE DELETE ON Object%u BEGIN DELETE FROM TextSearch%u WHERE ObjectId=OLD.ObjectId; END;" );
+
+ // UsageCount relation triggers
+ _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;" );
+ _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;" );
+ _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;" );
+ _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;" );
+
+ // Relation indexes
+ _LIT( KMdsIndexRelationLeftObjectId, "CREATE INDEX RelationsLeftObjectIdIndex%u ON Relations%u(LeftObjectId);" );
+ _LIT( KMdsIndexRelationRightObjectId, "CREATE INDEX RelationsRightObjectIdIndex%u ON Relations%u(RightObjectId);" );
+
+ // freetext indexes
+ _LIT( KMdsIndexFreetextWordId, "CREATE INDEX FreetextWordIdIndex%u ON TextSearch%u(WordId);" );
+ _LIT( KMdsIndexFreetextObjectId, "CREATE INDEX FreetextObjectIdIndex%u ON TextSearch%u(ObjectId);" );
+
+ // ObjectTypeDefinition index
+ _LIT( KMdsIndexObjectDefId, "CREATE INDEX ObjectDefIndex%u ON Object%u(ObjectDefId);" );
+
+ // create tables
+ CMdsClauseBuffer* clause = CMdsClauseBuffer::NewLC( 1024 );
+ clause->ReserveSpaceL( KBaseObjectDefinition.iTypeLength + 30 ); // maxIntNumberDecimal.Length = 10
+ CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+ RRowData emptyRowData;
+ CleanupClosePushL( emptyRowData );
+
+ // for triggers
+ CMdsClauseBuffer* clauseTrigger = CMdsClauseBuffer::NewLC( 1024 );
+
+ const TInt namespaceDefCount = iNamespaceDefs.Count();
+
+ // add objectdef[number] to DB
+ for( TInt i = 0; i < namespaceDefCount; ++i )
+ {
+ CMdsNamespaceDef* namespaceDef = iNamespaceDefs[i];
+ const TDefId namespaceDefId = namespaceDef->GetId();
+
+ if (!namespaceDef->GetTableStoredInDB())
+ {
+ // add base objectdef[number]
+ clause->BufferL().Format( KBaseObjectDefinition, &MdeConstants::Object::KBaseObject, namespaceDefId );
+ TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) );
+
+ // add relations[number]
+ clause->BufferL().Format( KCreateRelationsTable, namespaceDefId );
+ TRAPD( errRel, connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) );
+ if( errRel == KErrNone )
+ {
+ clauseTrigger->ReserveSpaceL( KMdsTriggerRelation().Size() + ( KMaxUintValueLength * 3 ) );
+ clauseTrigger->BufferL().Format( KMdsTriggerRelation, namespaceDefId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+ }
+
+ // add event[number]
+ clause->BufferL().Format( KCreateEventsTable, namespaceDefId );
+ TRAPD( errEve, connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) );
+ if( errEve == KErrNone )
+ {
+ clauseTrigger->ReserveSpaceL( KMdsTriggerEvent().Size() + ( KMaxUintValueLength * 3 ) );
+ clauseTrigger->BufferL().Format( KMdsTriggerEvent, namespaceDefId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+ }
+
+ // add textsearch[number]
+ clause->BufferL().Format( KCreateTxtSrchTable, namespaceDefId );
+ TRAPD( errTS, connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) );
+ if( errTS == KErrNone )
+ {
+ clauseTrigger->ReserveSpaceL( KMdsTriggerTextSearch().Size() + ( KMaxUintValueLength * 3 ) );
+ clauseTrigger->BufferL().Format( KMdsTriggerTextSearch, namespaceDefId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add KMdsIndexFreetextWordId[number]
+ clauseTrigger->ReserveSpaceL( KMdsIndexFreetextWordId().Size() + ( KMaxUintValueLength * 2 ) );
+ clauseTrigger->BufferL().Format( KMdsIndexFreetextWordId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add KMdsIndexFreetextObjectId[number]
+ clauseTrigger->ReserveSpaceL( KMdsIndexFreetextObjectId().Size() + ( KMaxUintValueLength * 2 ) );
+ clauseTrigger->BufferL().Format( KMdsIndexFreetextObjectId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+ }
+
+ // add textsearchdictionary[number]
+ clause->BufferL().Format( KCreateTxtSrchDicTable, namespaceDefId );
+ TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) );
+
+ // add insertrelations[number]
+ clauseTrigger->ReserveSpaceL( KMdsTriggerInsertRelation().Size() + ( KMaxUintValueLength * 3 ) );
+ clauseTrigger->BufferL().Format( KMdsTriggerInsertRelation, namespaceDefId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add updaterelations[number]
+ clauseTrigger->ReserveSpaceL( KMdsTriggerUpdateRelation().Size() + ( KMaxUintValueLength * 3 ) );
+ clauseTrigger->BufferL().Format( KMdsTriggerUpdateRelation, namespaceDefId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add updatenotremovedrelations[number]
+ clauseTrigger->ReserveSpaceL( KMdsTriggerUpdateNotRemovedRelation().Size() + ( KMaxUintValueLength * 4 ) );
+ clauseTrigger->BufferL().Format( KMdsTriggerUpdateNotRemovedRelation, namespaceDefId, namespaceDefId,
+ EMdERelationFlagNotPresent | EMdERelationFlagDeleted, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add updateremovedrelations[number]
+ clauseTrigger->ReserveSpaceL( KMdsTriggerUpdateRemovedRelation().Size() + ( KMaxUintValueLength * 5 ) );
+ clauseTrigger->BufferL().Format( KMdsTriggerUpdateRemovedRelation, namespaceDefId, namespaceDefId, EMdERelationFlagNotPresent | EMdERelationFlagDeleted, EMdERelationFlagNotPresent | EMdERelationFlagDeleted, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add relationleftobjectidindex[number]
+ clauseTrigger->ReserveSpaceL( KMdsIndexRelationLeftObjectId().Size() + ( KMaxUintValueLength * 2 ) );
+ clauseTrigger->BufferL().Format( KMdsIndexRelationLeftObjectId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add relationrightobjectidindex[number]
+ clauseTrigger->ReserveSpaceL( KMdsIndexRelationRightObjectId().Size() + ( KMaxUintValueLength * 2 ) );
+ clauseTrigger->BufferL().Format( KMdsIndexRelationRightObjectId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ // add objectdefidindex[number]
+ clauseTrigger->ReserveSpaceL( KMdsIndexObjectDefId().Size() + ( KMaxUintValueLength * 2 ) );
+ clauseTrigger->BufferL().Format( KMdsIndexObjectDefId, namespaceDefId, namespaceDefId );
+ connection.ExecuteL( clauseTrigger->ConstBufferL(), emptyRowData );
+
+ namespaceDef->SetTableStoredInDB();
+ }
+
+ const TInt objectDefCount = namespaceDef->iObjectDefs.Count();
+
+ for ( TInt j = 0; j < objectDefCount; ++j )
+ {
+ CMdsObjectDef* objectDef = namespaceDef->iObjectDefs[j];
+
+ if (!objectDef->GetTableStoredInDB())
+ {
+ clause->BufferL().Format( KMdsSqlClauseObjTableBeg, &objectDef->GetName(), namespaceDef->GetId() );
+
+ // add no text properties
+ AddObjectToSqlClauseL( objectDef, clause, EFalse );
+ // add text properties at end
+ AddObjectToSqlClauseL( objectDef, clause, ETrue );
+
+ clause->AppendL( KMdsSqlClauseObjTableEnd );
+ TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) );
+
+ objectDef->SetTableStoredInDB();
+ }
+
+ const TInt objectPropertyCount = objectDef->iPropertyDefs.Count();
+ for ( TInt k = 0; k < objectPropertyCount; ++k )
+ {
+ CMdsPropertyDef* propertyDef = objectDef->iPropertyDefs[k];
+
+ if ( propertyDef->GetIndexed() )
+ {
+ iProperties.AppendL( TPropertyInfo( objectDef->GetName(),
+ propertyDef->GetName(), namespaceDef->GetId() ) );
+ }
+ }
+ }
+ iProperties.AppendL( TPropertyInfo( MdeConstants::Object::KBaseObject, MdeConstants::Object::KItemTypeProperty, namespaceDef->GetId() ) );
+ }
+
+ CleanupStack::PopAndDestroy( 3, clause ); // clauseTrigger, emptyRowData, clause
+ }
+
+void CMdsSchema::CreatePropertyIndexL( const TDesC& aPropertyName, const TDesC& aTableName,
+ TDefId aNamespaceId )
+ {
+ _LIT( KMdsPropertyIndexCreate, "CREATE INDEX %S%SIndex%u ON %S%u(%S);" );
+
+ const TUint clauseLength = KMdsPropertyIndexCreate.iTypeLength + aTableName.Length() * 2 +
+ + aPropertyName.Length() * 2 + KMaxUintValueLength * 2;
+ CMdsClauseBuffer* clause = CMdsClauseBuffer::NewLC( clauseLength );
+ CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+ RRowData emptyRowData;
+ CleanupClosePushL( emptyRowData );
+ clause->BufferL().Format( KMdsPropertyIndexCreate, &aTableName, &aPropertyName, aNamespaceId,
+ &aTableName, aNamespaceId, &aPropertyName );
+ TRAP_IGNORE( connection.ExecuteL( clause->ConstBufferL(), emptyRowData ) );
+ CleanupStack::PopAndDestroy( 2, clause ); // emptyRowData, clause
+ }
+
+void CMdsSchema::StoreToDBL()
+ {
+ CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+ RMdSTransaction transaction( connection );
+ CleanupClosePushL( transaction );
+ User::LeaveIfError( transaction.Error() );
+
+ StoreNamespacesAndBaseObjectL();
+ CreateObjectTablesL();
+ StoreSchemaToDBL();
+ CreateCol2PropTableL();
+
+ transaction.CommitL();
+ CleanupStack::PopAndDestroy( &transaction );
+
+ TUint propertyCount = iProperties.Count();
+ for ( TUint i = 0; i < propertyCount; ++i )
+ {
+ TPropertyInfo& propertyInfo = iProperties[i];
+ CreatePropertyIndexL( propertyInfo.iPropertyName, propertyInfo.iTableName,
+ propertyInfo.iNamespaceId );
+ }
+ iProperties.Reset();
+ }
+
+void CMdsSchema::AddCol2PropObjectL( CMdsObjectDef* aObject, CMdsObjectDef* aChildObject,
+ TUint32& aPropertyColumnCounter, TBool aText )
+ {
+ _LIT( KMdsSqlClauseAddCol2Prop, "INSERT INTO Col2Prop(ObjectDefId,PropertyDefId,ColumnId) Values(?,?,?);" );
+ CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+ if ( !aChildObject->iParent )
+ {
+ if (aText)
+ {
+ return;
+ }
+ RRowData rowData;
+ CleanupClosePushL( rowData );
+ const TInt childObjectPropertyCount = aChildObject->iPropertyDefs.Count();
+ for ( TInt i = 0; i < childObjectPropertyCount; ++i )
+ {
+ CMdsPropertyDef* propertyDef = aChildObject->iPropertyDefs[i];
+ CMdsObjectDef::TMdsColumnOrder col = { aChildObject->iCol2Prop[i].iColumnId, *propertyDef };
+ aObject->iCol2Prop.AppendL( col );
+
+ if( propertyDef->GetMandatory() )
+ {
+ ++aObject->iMandatoryPropertyCount;
+ }
+
+ ++aPropertyColumnCounter;
+ rowData.Reset();
+ rowData.AppendL( TColumn( aObject->GetId() ) );
+ rowData.AppendL( TColumn( propertyDef->GetId() ) );
+ rowData.AppendL( TColumn( col.iColumnId ) );
+ connection.ExecuteL( KMdsSqlClauseAddCol2Prop, rowData );
+ }
+ CleanupStack::PopAndDestroy( &rowData );
+ return;
+ }
+
+ AddCol2PropObjectL( aObject, (CMdsObjectDef*)aChildObject->iParent, aPropertyColumnCounter, aText );
+
+ // if parent is baseobject
+ if ( !aText && !aChildObject->iParent->iParent )
+ {
+ ++aPropertyColumnCounter;
+ }
+
+ RRowData rowData;
+ CleanupClosePushL( rowData );
+
+ const TInt childObjectPropertyCount = aChildObject->iPropertyDefs.Count();
+ for ( TInt i = 0; i < childObjectPropertyCount; ++i )
+ {
+ CMdsPropertyDef* propertyDef = aChildObject->iPropertyDefs[i];
+ CMdsObjectDef::TMdsColumnOrder col = { 0, *propertyDef };
+ if ( aText && propertyDef->GetType() != EPropertyText ||
+ !aText && propertyDef->GetType() == EPropertyText )
+ {
+ continue;
+ }
+
+ col.iColumnId = aPropertyColumnCounter++;
+
+ aObject->iCol2Prop.AppendL( col );
+
+ if( propertyDef->GetMandatory() )
+ {
+ ++aObject->iMandatoryPropertyCount;
+ }
+
+ rowData.Reset();
+ rowData.AppendL( TColumn( aObject->GetId() ) );
+ rowData.AppendL( TColumn( propertyDef->GetId() ) );
+ rowData.AppendL( TColumn( col.iColumnId ) );
+ connection.ExecuteL( KMdsSqlClauseAddCol2Prop, rowData );
+ }
+
+ CleanupStack::PopAndDestroy( &rowData );
+ }
+
+void CMdsSchema::CreateCol2PropTableL()
+ {
+ _LIT( KMdsSqlClauseCol2Prop, "CREATE TABLE IF NOT EXISTS Col2Prop(ObjectDefId INTEGER NOT NULL,PropertyDefId INTEGER NOT NULL,ColumnId INTEGER NOT NULL);" );
+
+ RRowData emptyRowData;
+ CleanupClosePushL( emptyRowData );
+
+ CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+ // create binding column <--> property table
+ connection.ExecuteL( KMdsSqlClauseCol2Prop, emptyRowData );
+ TUint32 propertyColumnCounter;
+
+ const TInt count = iNamespaceDefs.Count();
+
+ for( TInt i = 0; i < count; ++i )
+ {
+ CMdsNamespaceDef* namespaceDef = iNamespaceDefs[i];
+ const TInt namespaceObjectCount = namespaceDef->iObjectDefs.Count();
+ for ( TInt j = 0; j < namespaceObjectCount; ++j )
+ {
+ CMdsObjectDef* objectDef = namespaceDef->iObjectDefs[j];
+ if (!objectDef->GetC2PStoredInDB())
+ {
+ propertyColumnCounter = KBaseObjectBasicValueColumnOffset;
+
+ objectDef->iCol2Prop.Reset();
+ objectDef->iMandatoryPropertyCount = 0;
+
+ AddCol2PropObjectL( objectDef, objectDef, propertyColumnCounter, EFalse );
+ AddCol2PropObjectL( objectDef, objectDef, propertyColumnCounter, ETrue );
+ objectDef->SetC2PStoredInDB();
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy( &emptyRowData );
+ }
+
+void CMdsSchema::StoreNamespacesAndBaseObjectL()
+ {
+ _LIT( KMdsSqlClauseNamespaceDef, "CREATE TABLE IF NOT EXISTS NamespaceDef(NamespaceDefId INTEGER PRIMARY KEY,ReadOnly INTEGER,VendorId INTEGER,Name TEXT);" );
+ _LIT( KMdsSqlClauseObjectDef, "CREATE TABLE IF NOT EXISTS ObjectDef(ObjectDefId INTEGER PRIMARY KEY,NamespaceDefId INTEGER NOT NULL,ParentDefId INTEGER NOT NULL,Flags INTEGER,Name TEXT);" );
+ _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);" );
+ _LIT( KMdsSqlClauseRelationDef, "CREATE TABLE IF NOT EXISTS RelationDef(RelationDefId INTEGER PRIMARY KEY,NamespaceDefId INTEGER NOT NULL,Name TEXT);" );
+ _LIT( KMdsSqlClauseEventDef, "CREATE TABLE IF NOT EXISTS EventDef(EventDefId INTEGER PRIMARY KEY,NamespaceDefId INTEGER NOT NULL,Priority INTEGER,Name TEXT);" );
+
+ RRowData emptyRowData;
+ CleanupClosePushL( emptyRowData );
+
+ // create tables
+ const TUint KNumClauses = 5;
+
+ CDesCArrayFlat* descarray = new (ELeave) CDesCArrayFlat(KNumClauses);
+ CleanupStack::PushL(descarray);
+ descarray->AppendL(KMdsSqlClauseNamespaceDef);
+ descarray->AppendL(KMdsSqlClauseObjectDef);
+ descarray->AppendL(KMdsSqlClausePropertyDef);
+ descarray->AppendL(KMdsSqlClauseRelationDef);
+ descarray->AppendL(KMdsSqlClauseEventDef);
+
+ CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+
+ TInt error;
+ for (TUint i = 0; i < KNumClauses; i++)
+ {
+ TRAP( error,connection.ExecuteL( (*descarray)[i], emptyRowData ) );
+ if ( error != KErrNone && error != KSqlErrGeneral )
+ {
+ User::Leave( error );
+ }
+ }
+ descarray->Reset();
+ CleanupStack::PopAndDestroy( descarray );
+
+ const TInt count = iNamespaceDefs.Count();
+
+ // add only namespaceDef to DB
+ for( TInt i = 0; i < count; ++i )
+ {
+ iNamespaceDefs[i]->StoreToDBL( ETrue );
+ }
+
+ CleanupStack::PopAndDestroy( &emptyRowData );
+ }
+
+void CMdsSchema::StoreSchemaToDBL()
+ {
+ _LIT( KMdsSqlClauseDeleteBoFromOd, "DELETE FROM ObjectDef WHERE ObjectDefId=?;" );
+ _LIT( KMdsSqlClauseDeleteBoFromPd, "DELETE FROM PropertyDef WHERE ObjectDefId=?;" );
+
+ iBaseObject->StoreToDBL( KNoDefId );
+
+ const TInt count = iNamespaceDefs.Count();
+
+ // add namespaceDef to DB
+ for( TInt i = 0; i < count; ++i )
+ {
+ iNamespaceDefs[i]->StoreToDBL();
+ }
+
+ RRowData removeBo;
+ CleanupClosePushL( removeBo );
+ removeBo.AppendL( TColumn( KBaseObjectDefId ) );
+
+ CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL();
+ TRAPD( err, connection.ExecuteL( KMdsSqlClauseDeleteBoFromOd, removeBo ) );
+ TRAP ( err, connection.ExecuteL( KMdsSqlClauseDeleteBoFromPd, removeBo ) );
+
+ CleanupStack::PopAndDestroy( &removeBo );
+ }
+
+void CMdsSchema::MergeElementsL( CMdsSchema& aSchema, const TBool& aDryRun )
+ {
+ const TInt count = aSchema.iNamespaceDefs.Count();
+
+ for ( TInt i = 0; i < count; ++i )
+ {
+ CMdsNamespaceDef* lNamespace = NULL;
+ CMdsNamespaceDef* rNamespace = aSchema.iNamespaceDefs[i];
+ // reseting after namespace read from file
+ rNamespace->UnsetFirstRead();
+ // search for namespace
+ lNamespace = GetNamespace( rNamespace->GetName() );
+ if ( !lNamespace )
+ {
+ if ( !aDryRun )
+ {
+ // just add pointer to new schema and remove it from old one
+ iNamespaceDefs.AppendL( rNamespace );
+ aSchema.iNamespaceDefs[i] = NULL;
+ rNamespace->SetAllNotStoredInDB();
+ }
+ }
+ else
+ {
+ // copy appropriate elements
+ if ( lNamespace->GetVendorId() == rNamespace->GetVendorId() && !lNamespace->GetReadOnly() )
+ {
+ lNamespace->MergeObjectsL( rNamespace, aDryRun );
+ lNamespace->MergeEventsL( rNamespace, aDryRun );
+ lNamespace->MergeRelationsL( rNamespace, aDryRun );
+ }
+ else
+ {
+ User::Leave( KErrAccessDenied );
+ }
+ }
+ }
+ }
+
+void CMdsSchema::MergeNamespacesL( CMdsSchema& aSchema )
+ {
+ if ( iNamespaceDefs.Count() == 0 )
+ {// speed optimization
+ Reset();
+
+ const TInt count = aSchema.iNamespaceDefs.Count();
+
+ for ( TInt i = 0; i < count; ++i )
+ {
+ // reseting after namespace read from file
+ aSchema.iNamespaceDefs[i]->UnsetFirstRead();
+ iNamespaceDefs.AppendL( aSchema.iNamespaceDefs[i] );
+ aSchema.iNamespaceDefs[i] = NULL;
+ }
+ aSchema.Reset();
+ }
+ else
+ {
+ MergeElementsL( aSchema, ETrue );
+ MergeElementsL( aSchema, EFalse );
+ }
+ }
+
+void CMdsSchema::SerializeToSharedMemoryL()
+ {
+ const TInt namespaceCount = iNamespaceDefs.Count();
+
+ // namespace count, namespace offsets
+ TUint32 bufferSize = sizeof(TMdCSchema) + namespaceCount * sizeof(TMdCNamespaceDef);
+
+ for ( TInt i = 0; i < namespaceCount; ++i )
+ {
+ bufferSize += iNamespaceDefs[i]->RequiredBufferSize();
+ }
+
+ // create shared memory chunk
+ iSerialized = EFalse;
+ iSerializedSchema.Close();
+ ++iSchemaHandle;
+ HBufC* name = HBufC::NewLC( KSchemaChunkName.iTypeLength + KMaxUintValueLength );
+ *name = KSchemaChunkName;
+ name->Des().AppendNum( iSchemaHandle );
+
+ TInt error = KErrNone;
+ while( (error = iSerializedSchema.CreateGlobal( *name, bufferSize, bufferSize )) == KErrAlreadyExists )
+ {
+ ++iSchemaHandle;
+ *name = KSchemaChunkName;
+ name->Des().AppendNum( iSchemaHandle );
+ }
+ User::LeaveIfError( error );
+
+ CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( iSerializedSchema.Base(), bufferSize );
+
+ TMdCSchema schema;
+ schema.iNamespaceDefs.iPtr.iCount = namespaceCount;
+ schema.iNamespaceDefs.iPtr.iOffset = sizeof(schema);
+ schema.SerializeL( *buffer );
+
+ TMdCOffset freeSpace = schema.iNamespaceDefs.iPtr.iOffset + namespaceCount * sizeof(TMdCNamespaceDef);
+ for ( TInt i = 0; i < namespaceCount; ++i )
+ {
+ buffer->PositionL( schema.iNamespaceDefs.iPtr.iOffset + i * sizeof(TMdCNamespaceDef) );
+
+ // write namespace
+ freeSpace = iNamespaceDefs[i]->SerializeL( *buffer, freeSpace );
+ }
+
+ CleanupStack::PopAndDestroy( buffer );
+ CleanupStack::PopAndDestroy( name );
+ iSerialized = ETrue;
+ }
+
+TInt CMdsSchema::SharedMemoryHandleL()
+ {
+ if ( !iSerialized )
+ {
+ User::Leave( KErrNotReady );
+ }
+ return iSchemaHandle;
+ }
+