diff -r 000000000000 -r c53acadfccc6 metadataengine/server/src/mdssqlobjectmanipulate.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/metadataengine/server/src/mdssqlobjectmanipulate.cpp Mon Jan 18 20:34:07 2010 +0200 @@ -0,0 +1,3283 @@ +/* +* Copyright (c) 2002-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: Add, update and remove items in DB. +* Basic DB manipulation engine. +* +*/ + +#include "mdssqlobjectmanipulate.h" + +#include "mdcitem.h" +#include "mdsdbconnectionpool.h" +#include "mdssqliteconnection.h" +#include "mdsfindsqlclausedef.h" +#include "mdsschema.h" +#include "mdsnamespacedef.h" +#include "mdsobjectdef.h" +#include "mdspropertydef.h" +#include "mdsclausebuffer.h" +#include "mdsobjectlocklist.h" +#include "mdsindexer.h" +#include "mdspreferences.h" +#include "mdslogger.h" +#include "mdcserializationbuffer.h" +#include "mdssqldbmaintenance.h" +#include "mdcresult.h" +#include "mdeinternalerror.h" + +#include "mdsgetimeiao.h" + +#include + +/** logging instance */ +__USES_LOGGER + +const TInt KMaxBuffers = 3; + +_LIT( KMemoryCard, "MC" ); + + +//------------------------------------------------------------------------------------ +// CLASS CMdSSqlObjectManipulate +//------------------------------------------------------------------------------------ + +CMdSIdentifierGenerator* CMdSIdentifierGenerator::NewL( ) + { + CMdSIdentifierGenerator* self = CMdSIdentifierGenerator::NewLC( ); + CleanupStack::Pop( self ); + return self; + } + +CMdSIdentifierGenerator* CMdSIdentifierGenerator::NewLC( ) + { + CMdSIdentifierGenerator* self = new ( ELeave ) CMdSIdentifierGenerator( ); + CleanupStack::PushL( self ); + self->ConstructL( ); + return self; + } + +CMdSIdentifierGenerator::~CMdSIdentifierGenerator() + { + delete iDigest; + } + +void CMdSIdentifierGenerator::ConstructL( ) + { + CMdsGetImeiAO * imeigetter = CMdsGetImeiAO::NewLC(); + iImei = imeigetter->GetIMEI(); + + TTime uTime; + uTime.UniversalTime(); + TInt64 intTime = uTime.Int64(); + TUint32 rand = Math::Rand( intTime ); + + iImei ^= (TInt64)(rand & 0xFF000000) << ( sizeof( TUint32 ) * 8 ); + + CleanupStack::PopAndDestroy(imeigetter); + iLastTime = 0; + + iDigest = CMessageDigestFactory::NewDigestL( CMessageDigest::EMD5 ); + } + +void CMdSIdentifierGenerator::GenerateGuid( TInt64& aGuidHigh, TInt64& aGuidLow ) + { + if (aGuidHigh == 0 && aGuidLow == 0) + { + TTime currTime; + currTime.UniversalTime(); + const TInt64 tickCount = currTime.Int64(); + if (iLastTime < tickCount) + { + iLastTime = tickCount; + } + else + { + ++iLastTime; + } + + //MD5 hash GUID + const TInt64 KXorImei = I64LIT( 0x2C3E773D1A25916E ); + const TInt64 xorImei = iImei ^ KXorImei; + + const TInt KMaxQuidLength = 16; + TBuf8 message; + message.SetLength( KMaxQuidLength ); + Mem::Copy( (TAny*)( message.Ptr() ), &xorImei, sizeof( TInt64 ) ); + Mem::Copy( (TAny*)( message.Ptr() + sizeof( TInt64 ) ), &iLastTime, sizeof( TInt64 ) ); + + TPtrC8 hash = iDigest->Final( message ); + + __ASSERT_DEBUG( hash.Size() >= KMaxQuidLength, User::Panic( _L("CMdSIdentifierGenerator::GenerateGuid"), KErrGeneral ) ); + + Mem::Copy( &aGuidHigh, hash.Ptr(), sizeof( TInt64 ) ); + Mem::Copy( &aGuidLow, hash.Ptr() + sizeof( TInt64 ), sizeof( TInt64 ) ); + //MD5 hash GUID end + } + } + +HBufC* CMdSIdentifierGenerator::GenerateUriL( const CMdsObjectDef& aObjectDef, + const TInt64& aGuidHigh, const TInt64& aGuidLow ) const + { + _LIT( KDot, "." ); + HBufC* uri = HBufC::NewLC( aObjectDef.GetName().Length() + 2 /*two dots*/+ + 2*KMaxUint64ValueLength ); + + TPtr uriPtr( uri->Des() ); + uriPtr.Append( aObjectDef.GetName() ); + uriPtr.Append( KDot ); + uriPtr.AppendNum( aGuidHigh ); + uriPtr.Append( KDot ); + uriPtr.AppendNum( aGuidLow ); + CleanupStack::Pop( uri ); + return uri; + } + + +//----------------------------------------------------------------------------- +// CLASS CMdSSqlObjectManipulate +//----------------------------------------------------------------------------- + +CMdSSqlObjectManipulate* CMdSSqlObjectManipulate::NewL( + const CMdsSchema& aSchema, CMdSObjectLockList& aLockList ) + { + CMdSSqlObjectManipulate* self = CMdSSqlObjectManipulate::NewLC( aSchema, + aLockList ); + CleanupStack::Pop( self ); + return self; + } + +CMdSSqlObjectManipulate* CMdSSqlObjectManipulate::NewLC( + const CMdsSchema& aSchema, CMdSObjectLockList& aLockList ) + { + CMdSSqlObjectManipulate* self = new ( ELeave ) CMdSSqlObjectManipulate( + aSchema, aLockList ); + CleanupStack::PushL( self ); + self->ConstructL( ); + return self; + } + +CMdSSqlObjectManipulate::~CMdSSqlObjectManipulate() + { + // doesn't own namespace definition + iNamespaceDef = NULL; + + const TInt count = iBuffers.Count(); + + for (TInt i = 0; i < count; ++i) + { + delete iBuffers[i].iBuffer; + } + iBuffers.Close(); + + delete iGenerator; + } + +CMdSSqlObjectManipulate::CMdSSqlObjectManipulate( const CMdsSchema& aSchema, + CMdSObjectLockList& aLockList ) + : iSchema( aSchema ), iGenerator(NULL), iLockList( aLockList ) + { + } + +void CMdSSqlObjectManipulate::ConstructL( ) + { + + iGenerator = CMdSIdentifierGenerator::NewL(); + + iNamespaceDef = NULL; + + TLockBuffer lockBuffer; + lockBuffer.iLock = EFalse; + for (TInt i = 0; i < KMaxBuffers; ++i) + { + CMdsClauseBuffer* buffer = CMdsClauseBuffer::NewLC( 1024 ); + lockBuffer.iBuffer = buffer; + iBuffers.AppendL( lockBuffer ); + CleanupStack::Pop(); // buffer + } + + } + +TBool CMdSSqlObjectManipulate::GarbageCollectionL() + { + return DoGarbageCollectionL(); + } + +void CMdSSqlObjectManipulate::SetNamespace( + const CMdsNamespaceDef* aNamespaceDef ) + { + iNamespaceDef = aNamespaceDef; + } + +void CMdSSqlObjectManipulate::AddMemoryCardL(TUint32 aMediaId) + { + TTime currentTime; + currentTime.UniversalTime(); + + TInt modifiedRowCount = MMdsPreferences::UpdateL( KMemoryCard, + MMdsPreferences::EPreferenceExtraSet, aMediaId, + currentTime.Int64() ); + + if( modifiedRowCount <= 0 ) + { + MMdsPreferences::InsertL( KMemoryCard, + MMdsPreferences::EPreferenceBothSet, + aMediaId, currentTime.Int64() ); + } + } + +void CMdSSqlObjectManipulate::GetMemoryCardL(TUint32& aMediaId) + { + TInt rowCount = MMdsPreferences::GetL( KMemoryCard, + MMdsPreferences::EPreferenceValueGet | MMdsPreferences::EPreferenceExtraSortDesc, + aMediaId ); + + // if no rows found leave + if( rowCount <= 0 ) + { + User::Leave( KErrNotFound ); + } + } + +TBool CMdSSqlObjectManipulate::CheckMemoryCardL(TUint32 aMediaId) + { + TInt rowCount = MMdsPreferences::GetL( KMemoryCard, + MMdsPreferences::EPreferenceValueGet | MMdsPreferences::EPreferenceValueSet, + aMediaId ); + + if( rowCount > 0 ) + { + return ETrue; + } + return EFalse; + } + + +void CMdSSqlObjectManipulate::SetMediaL(TUint32 aMediaId, TChar aDrive, + TBool aPresentState) + { + _LIT( KInsertMedia, "INSERT OR REPLACE INTO MdS_Medias VALUES(?,?,?,?);" ); + + RClauseBuffer commonClause( *this, KInsertMedia.iTypeLength ); + CleanupClosePushL( commonClause ); + CMdsClauseBuffer& clauseBuffer = commonClause.BufferL(); + clauseBuffer.BufferL() = KInsertMedia; + + TTime currentTime; + currentTime.UniversalTime(); + const TInt64 currentTime64 = currentTime.Int64(); + + RRowData var; + CleanupClosePushL( var ); + var.ReserveL( 4 ); // reserve space for media ID, drive, present state and time + var.AppendL( TColumn( aMediaId ) ); + var.AppendL( TColumn( (TInt32)aDrive ) ); + var.AppendL( TColumn( aPresentState ) ); + var.AppendL( TColumn( currentTime64 ) ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + connection.ExecuteL( clauseBuffer.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( 2, &commonClause ); // var, commonClauseOne + } + +TBool CMdSSqlObjectManipulate::GetMediaL(TUint32 aMediaId, TChar& aDrive, + TBool& aPresentState) + { + _LIT( KGetMedia, "SELECT Drive, PresentState FROM MdS_Medias WHERE MediaId=?;" ); + + RClauseBuffer commonClause( *this, KGetMedia.iTypeLength ); + CleanupClosePushL( commonClause ); + CMdsClauseBuffer& clauseBuffer = commonClause.BufferL(); + clauseBuffer.BufferL() = KGetMedia; + + RRowData var; + CleanupClosePushL( var ); + var.AppendL( TColumn( aMediaId ) ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + RMdsStatement statement; + CleanupClosePushL( statement ); + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + var.Free(); + var.Reset(); + + TInt32 drive = 0; + + var.ReserveL( 2 ); // reserve space for drive and present state + var.AppendL( TColumn( drive ) ); + var.AppendL( TColumn( aPresentState ) ); + + TBool found = EFalse; + + if( connection.NextRowL( statement, var ) ) + { + var.Column( 0 ).Get( drive ); + var.Column( 1 ).Get( aPresentState ); + + aDrive = drive; + + found = ETrue; + } + + CleanupStack::PopAndDestroy( 3, &commonClause ); // statement, var, commonClauseOne + + return found; + } + +TInt32 CMdSSqlObjectManipulate::GetPresentMediasL(TDes8& aMediaInfoBuffer) + { + _LIT( KGetPresentMedias, "SELECT MediaId, Drive FROM MdS_Medias WHERE PresentState!=?;" ); + + RClauseBuffer commonClause( *this, KGetPresentMedias.iTypeLength ); + CleanupClosePushL( commonClause ); + CMdsClauseBuffer& clauseBuffer = commonClause.BufferL(); + clauseBuffer.BufferL() = KGetPresentMedias; + + const TBool notPresentState = EFalse; + + RRowData var; + CleanupClosePushL( var ); + var.AppendL( TColumn( notPresentState ) ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + RMdsStatement statement; + CleanupClosePushL( statement ); + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + var.Free(); + var.Reset(); + + TUint32 mediaId = 0; + TInt32 drive = 0; + + var.ReserveL( 2 ); // reserve space for drive and present state + var.AppendL( TColumn( mediaId ) ); + var.AppendL( TColumn( drive ) ); + + TInt32 count = 0; + + TInt bufferPosition = 0; + + const TInt lastBufferPosition = aMediaInfoBuffer.MaxSize() - sizeof( TMdEMediaInfo ); + + const TUint8* aMediaInfoBufferPtr = aMediaInfoBuffer.Ptr(); + + while( connection.NextRowL( statement, var ) ) + { + var.Column( 0 ).Get( mediaId ); + var.Column( 1 ).Get( drive ); + + TMdEMediaInfo mediaInfo; + mediaInfo.iMediaId = mediaId; + mediaInfo.iDrive = drive; + + if( bufferPosition > lastBufferPosition ) + { + User::Leave( KErrBadDescriptor ); + } + + TUint8* ptr = (TUint8*)( aMediaInfoBufferPtr + bufferPosition ); + + Mem::Copy( ptr, &mediaInfo, sizeof( TMdEMediaInfo ) ); + + bufferPosition += sizeof( TMdEMediaInfo ); + + ++count; + } + + aMediaInfoBuffer.SetLength( bufferPosition ); + + CleanupStack::PopAndDestroy( 3, &commonClause ); // statement, var, commonClauseOne + + return count; + } + +TItemId CMdSSqlObjectManipulate::SearchNotPresentFileL(TUint32 aMediaId, + TDesC16& aUri, TMdSFileInfo& aFileInfo, + TFilePresentStates& aPlaceHolder, TBool& aNotPresentState) + { + _LIT( KSearchNotPresentFile, "SELECT ObjectId, Flags, LastModifiedDate, Size FROM Object%u WHERE NOT Flags&? AND (Flags&? OR Flags&? OR Flags&? ) AND MediaId=? AND URI=?;" ); + + RClauseBuffer commonClauseOne(*this, KSearchNotPresentFile.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + clauseBuffer.BufferL().Format( KSearchNotPresentFile, KDefaultNamespaceDefId ); + + TItemId objectId = KNoId; + TUint32 flags = 0; + + RRowData var; + CleanupClosePushL( var ); + var.ReserveL( 5 ); + var.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + var.AppendL( TColumn( EMdEObjectFlagNotPresent ) ); // not present flag + var.AppendL( TColumn( EMdEObjectFlagStartUpNotPresent ) ); // start up not present flag + var.AppendL( TColumn( EMdeObjectFlagPending ) ); // pending for composing - needed to complete composing + var.AppendL( TColumn( aMediaId ) ); + var.AppendL( TColumn( aUri ) ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + RMdsStatement statement; + CleanupClosePushL( statement ); + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + TInt64 modifiedTime(0); + TUint32 size(0); + + RRowData result; + CleanupClosePushL( result ); + result.ReserveL( 4 ); + result.AppendL( TColumn( objectId ) ); + result.AppendL( TColumn( flags ) ); + result.AppendL( TColumn( modifiedTime ) ); + result.AppendL( TColumn( size ) ); + + // default values (used if object doesn't exist) + aPlaceHolder = EMdsNotFound; + aNotPresentState = EFalse; + + if( connection.NextRowL( statement, result ) ) + { + result.Column( 0 ).Get( objectId ); + result.Column( 1 ).Get( flags ); + + if ( flags & EMdEObjectFlagPlaceholder ) + { + aPlaceHolder = EMdsPlaceholder; + } + else + { + result.Column( 2 ).Get( modifiedTime ); + result.Column( 3 ).Get( size ); + + // check if file is modified + if ( ( aFileInfo.iModifiedTime == modifiedTime ) && ( aFileInfo.iSize == size ) ) + { + aPlaceHolder = EMdsNormal; + + // If images were pending for composing, composer needs to be notified for the composing to complete + if( (flags & EMdeObjectFlagPending) && (flags & EMdEObjectFlagStartUpNotPresent) ) + { + aNotPresentState = ETrue; + } + } + else + { + aPlaceHolder = EMdsModified; + } + } + + if( flags & EMdEObjectFlagNotPresent ) + { + aNotPresentState = ETrue; + } + } + + CleanupStack::PopAndDestroy( &result ); + CleanupStack::PopAndDestroy( &statement ); + CleanupStack::PopAndDestroy( &var ); + CleanupStack::PopAndDestroy( &commonClauseOne ); + return objectId; + } + +void CMdSSqlObjectManipulate::SetFilesToPresentL(const RArray& aObjectIds) + { + const TInt objectCount = aObjectIds.Count(); + if ( objectCount > 0 ) + { + _LIT( KSetFileToPresent, "UPDATE Object%u SET Flags=Flags&? WHERE (Flags&?)<>0 AND ObjectId IN (?" ); + _LIT( KCommaQuestionmark, ",?"); + _LIT( KBracketSemicolon, ");"); + + RClauseBuffer commonClauseOne(*this, KSetFileToPresent.iTypeLength + KMaxUintValueLength + + ( KCommaQuestionmark.iTypeLength * ( objectCount-1 ) ) + + KBracketSemicolon.iTypeLength ); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + clauseBuffer.BufferL().Format( KSetFileToPresent, KDefaultNamespaceDefId ); + + RRowData var; + CleanupClosePushL( var ); + // reset not present and start up not present flags + var.AppendL( TColumn( ~(EMdEObjectFlagNotPresent | EMdEObjectFlagStartUpNotPresent) ) ); + var.AppendL( TColumn( (EMdEObjectFlagNotPresent | EMdEObjectFlagStartUpNotPresent) ) ); + var.AppendL( TColumn( aObjectIds[0] ) ); + + for ( TInt i = 1; i < objectCount; i++ ) + { + clauseBuffer.AppendL( KCommaQuestionmark ); + var.AppendL( TColumn( aObjectIds[i] ) ); + } + + clauseBuffer.AppendL( KBracketSemicolon ); + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + connection.ExecuteL( clauseBuffer.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( &var ); + CleanupStack::PopAndDestroy( &commonClauseOne ); + } + } + +void CMdSSqlObjectManipulate::SetRelationsToPresentL(TItemId aObjectId, + RArray& aIdArray) + { + _LIT( KSearchNotPresentRelations, "SELECT RelationId FROM Relations%u WHERE NOT Flags&? AND Flags&? AND (LeftObjectId=? OR RightObjectId=?);" ); + _LIT( KSetRelationsToPresent, "UPDATE Relations%u SET Flags=Flags&? WHERE Flags&? AND (LeftObjectId=? OR RightObjectId=?);" ); + + RClauseBuffer commonClauseOne(*this, KSearchNotPresentRelations.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + clauseBuffer.BufferL().Format( KSearchNotPresentRelations, KDefaultNamespaceDefId ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + RRowData var; + CleanupClosePushL( var ); + + var.ReserveL( 4 ); // reserve space for flags and object IDs + var.AppendL( TColumn( EMdERelationFlagDeleted ) ); + var.AppendL( TColumn( EMdERelationFlagNotPresent ) ); + var.AppendL( TColumn( aObjectId ) ); + var.AppendL( TColumn( aObjectId ) ); + + RMdsStatement statement; + CleanupClosePushL( statement ); + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + var.Free(); var.Reset(); + TItemId relationId(0); + var.AppendL( TColumn( relationId ) ); + while( connection.NextRowL( statement, var ) ) + { + var.Column( 0 ).Get( relationId ); + aIdArray.AppendL( relationId ); + } + + clauseBuffer.ReserveSpaceL( KSetRelationsToPresent.iTypeLength + KMaxUintValueLength ); + clauseBuffer.BufferL().Format( KSetRelationsToPresent, KDefaultNamespaceDefId ); + + var.Free(); + var.Reset(); + + var.AppendL( TColumn( ~EMdERelationFlagNotPresent ) ); // reset not present flag + var.AppendL( TColumn( EMdERelationFlagNotPresent ) ); + var.AppendL( TColumn( aObjectId ) ); + var.AppendL( TColumn( aObjectId ) ); + + connection.ExecuteL( clauseBuffer.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // statement, var, clauseBuffer + } + +void CMdSSqlObjectManipulate::SetFilesToNotPresentL(TUint32 aMediaId, TBool aStartUp, + RArray& aObjectIds) + { + + _LIT( KSearchPresentFilesStartUpL, "SELECT ObjectId FROM Object%u WHERE NOT Flags&? AND MediaId=?;" ); + _LIT( KSearchPresentFilesL, "SELECT ObjectId FROM Object%u WHERE NOT Flags&? AND NOT Flags&? AND MediaId=?;" ); + + RClauseBuffer commonClauseOne(*this, ( aStartUp ? KSearchPresentFilesStartUpL.iTypeLength : KSearchPresentFilesL.iTypeLength )+ + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + + if( aStartUp ) + { + clauseBuffer.BufferL().Format( KSearchPresentFilesStartUpL, KDefaultNamespaceDefId ); + } + else + { + clauseBuffer.BufferL().Format( KSearchPresentFilesL, KDefaultNamespaceDefId ); + } + + TItemId objectId = 0; + + RRowData var; + CleanupClosePushL( var ); + + var.ReserveL( 3 ); // reserve space for flags and media ID + var.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + if ( !aStartUp ) + { + var.AppendL( TColumn( EMdEObjectFlagNotPresent ) ); // present flag + } + var.AppendL( TColumn( aMediaId ) ); + + RMdsStatement statement; + CleanupClosePushL( statement ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + var.Free(); + var.Reset(); + + var.AppendL( TColumn( objectId ) ); + while( connection.NextRowL( statement, var ) ) + { + var.Column( 0 ).Get( objectId ); + aObjectIds.AppendL( objectId ); + } + + _LIT( KSetFilesToNotPresent, "UPDATE Object%u SET Flags=Flags|? WHERE MediaId=?;" ); + clauseBuffer.ReserveSpaceL( + KSetFilesToNotPresent.iTypeLength + + KMaxUintValueLength ); // TUint32 max value's lenght is 10 numbers so %u + 8 + clauseBuffer.BufferL().Format( KSetFilesToNotPresent, KDefaultNamespaceDefId ); + + var.Free(); + var.Reset(); + + if( aStartUp ) + { + var.AppendL( TColumn( EMdEObjectFlagStartUpNotPresent ) ); // set not present flag + } + else + { + var.AppendL( TColumn( EMdEObjectFlagNotPresent ) ); // set not present flag + } + var.AppendL( TColumn( aMediaId ) ); + + connection.ExecuteL( clauseBuffer.ConstBufferL(), var ); + + // statement, var, commonClauseOne + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); + } + +void CMdSSqlObjectManipulate::SetRelationsToNotPresentL( + TUint32 aMediaId, RArray& aRelationIds) + { + _LIT( KSearchPresentRelations, "SELECT DISTINCT A.RelationId FROM Relations%u AS A LEFT JOIN object%u AS B On A.LeftObjectId = B.ObjectId OR A.RightObjectId = B.ObjectId WHERE NOT A.Flags&%u AND NOT A.Flags&%u AND B.MediaId=%u" ); + _LIT( KSetRelationsToPresent, "UPDATE Relations%u SET Flags=Flags|? WHERE NOT Flags&? AND RelationId IN (%S);" ); + + // RelationIDs query sql statement + RClauseBuffer commonClauseOne(*this, + KSearchPresentRelations.iTypeLength + + KMaxUintValueLength ); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBufferOne = commonClauseOne.BufferL(); + clauseBufferOne.BufferL().Format( KSearchPresentRelations, + KDefaultNamespaceDefId, + KDefaultNamespaceDefId, + EMdERelationFlagDeleted, + EMdERelationFlagNotPresent, + aMediaId ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RRowData var; + CleanupClosePushL( var ); + + RMdsStatement statement; + CleanupClosePushL( statement ); + + connection.ExecuteQueryL( clauseBufferOne.ConstBufferL(), statement, var ); + + // Get RelationIDs From query result + TItemId relationId(0); + var.AppendL( TColumn( relationId ) ); + while( connection.NextRowL( statement, var ) ) + { + var.Column( 0 ).Get( relationId ); + aRelationIds.AppendL( relationId ); + } + + // Set objects' relations not present by MediaID + RClauseBuffer commonClauseTwo(*this, + KSetRelationsToPresent.iTypeLength + + clauseBufferOne.ConstBufferL().Length() ); + + CleanupClosePushL( commonClauseTwo ); + CMdsClauseBuffer& clauseBufferTwo = commonClauseTwo.BufferL(); + clauseBufferTwo.BufferL().Format( KSetRelationsToPresent, + KDefaultNamespaceDefId, + &clauseBufferOne.ConstBufferL() ); + + var.Free(); + var.Reset(); + var.ReserveL( 2 ); + var.AppendL( TColumn( EMdERelationFlagNotPresent ) ); + var.AppendL( TColumn( EMdERelationFlagNotPresent ) ); + + connection.ExecuteL( clauseBufferTwo.ConstBufferL(), var ); + + // commonClauseTwo, statement, var, commonClauseOne + CleanupStack::PopAndDestroy( 4, &commonClauseOne ); + } + +void CMdSSqlObjectManipulate::RemoveFilesNotPresentL(TUint32 aMediaId, RArray* aObjectIds) + { + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + // collect object IDs from start up not present objects + if( aObjectIds ) + { + _LIT( KSelectFilesStartUpNotPresent, "SELECT ObjectId FROM Object%u WHERE NOT Flags&? AND NOT Flags&? AND Flags&? AND MediaId=?;" ); + + RClauseBuffer commonClauseOne(*this, + KSelectFilesStartUpNotPresent.iTypeLength + KMaxUintValueLength ); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + + clauseBuffer.BufferL().Format( KSelectFilesStartUpNotPresent, KDefaultNamespaceDefId ); + + RRowData var; + CleanupClosePushL( var ); + var.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + var.AppendL( TColumn( EMdEObjectFlagNotPresent ) ); + var.AppendL( TColumn( EMdEObjectFlagStartUpNotPresent ) ); + var.AppendL( TColumn( aMediaId ) ); + + RMdsStatement statement; + CleanupClosePushL( statement ); + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + RRowData result; + CleanupClosePushL( result ); + TItemId objectId( KNoId ); + result.AppendL( TColumn( objectId ) ); + + while( connection.NextRowL( statement, result ) ) + { + result.Column( 0 ).Get( objectId ); + aObjectIds->AppendL( objectId ); + } + + CleanupStack::PopAndDestroy( &result ); + CleanupStack::PopAndDestroy( &statement ); + CleanupStack::PopAndDestroy( &var ); + CleanupStack::PopAndDestroy( &commonClauseOne ); + } + + _LIT( KRemoveFilesNotPresent, "UPDATE Object%u SET Flags=Flags|? WHERE NOT Flags&? AND (Flags&? OR Flags&?) AND MediaId=?;" ); + + RClauseBuffer commonClauseOne(*this, + KRemoveFilesNotPresent.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + clauseBuffer.BufferL().Format( KRemoveFilesNotPresent, KDefaultNamespaceDefId ); + + RRowData var; + CleanupClosePushL( var ); + var.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + var.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + var.AppendL( TColumn( EMdEObjectFlagNotPresent ) ); // not present flag + var.AppendL( TColumn( EMdEObjectFlagStartUpNotPresent ) ); // start up not present flag + var.AppendL( TColumn( aMediaId ) ); + + __LOGQUERY_16( _L("RemoveFilesNotPresentL:"), clauseBuffer.ConstBufferL(), var); + connection.ExecuteL( clauseBuffer.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // var, commonClauseOne + } + +void CMdSSqlObjectManipulate::GetSchemaVersionL( + TInt& aMajorVersion, TInt& aMinorVersion) + { + TInt64 minorVersion; + TInt rowCount = MMdsPreferences::GetL( KMdsSchemaVersionName, + MMdsPreferences::EPreferenceBothGet, + aMajorVersion, &minorVersion ); + + aMinorVersion = minorVersion; + + // if no rows found leave + if( rowCount <= 0 ) + { + User::Leave( KErrNotFound ); + } + } + +void CMdSSqlObjectManipulate::SetObjectToPresentByGuidL( + const TInt64& aGuidHigh, const TInt64& aGuidLow ) + { + // get object ID for later queries + _LIT( KGetObjectIdByGuid, "SELECT ObjectId FROM Object%u WHERE Flags&? AND GuidHigh=? AND GuidLow=?;" ); + + RClauseBuffer commonClauseOne(*this, + KGetObjectIdByGuid.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + clauseBuffer.BufferL().Format( KGetObjectIdByGuid, KDefaultNamespaceDefId ); + + RRowData var; + CleanupClosePushL( var ); + var.ReserveL( 3 ); // for flags and GUID high/low in WHERE + + var.AppendL( TColumn( (TUint32)EMdEObjectFlagNotPresent ) ); + var.AppendL( TColumn( aGuidHigh ) ); + var.AppendL( TColumn( aGuidLow ) ); + + RMdsStatement statement; + CleanupClosePushL( statement ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + __LOGQUERY_16( _L("SetObjectToPresentByGuidL q1:"), clauseBuffer.ConstBufferL(), var); + + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + var.Free(); + var.Reset(); + TItemId objectId = KNoId; + var.AppendL( TColumn( objectId ) ); + + if( connection.NextRowL( statement, var ) ) + { + var.Column( 0 ).Get( objectId ); + + // set object, which object ID is matching, to present state + _LIT( KSetObjectToPresentByGuid, "UPDATE Object%u SET Flags=Flags&? WHERE ObjectId=? AND (Flags&?)<>0;" ); + + RClauseBuffer commonClauseTwo(*this, + KSetObjectToPresentByGuid.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseTwo ); + CMdsClauseBuffer& clauseBuffer2 = commonClauseTwo.BufferL(); + clauseBuffer2.BufferL().Format( KSetObjectToPresentByGuid, + KDefaultNamespaceDefId ); + + var.Free(); + var.Reset(); + var.AppendL( TColumn( (TUint32)~EMdEObjectFlagNotPresent ) ); + var.AppendL( TColumn( objectId ) ); + + var.AppendL( TColumn( (TUint32)EMdEObjectFlagNotPresent ) ); + + __LOGQUERY_16( _L("SetObjectToPresentByGuidL q2:"), + clauseBuffer2.ConstBufferL(), var); + + connection.ExecuteL( clauseBuffer2.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( &commonClauseTwo ); + + // set relations, which left or right object ID is matching, + // to present state + _LIT( KSetRelationToPresentByGuid, "UPDATE Relations%u SET Flags=Flags&? WHERE LeftObjectId=? OR RightObjectId=?;" ); + + RClauseBuffer commonClauseThree(*this, + KSetRelationToPresentByGuid.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseThree ); + CMdsClauseBuffer& clauseBuffer3 = commonClauseThree.BufferL(); + clauseBuffer3.BufferL().Format( KSetRelationToPresentByGuid, + KDefaultNamespaceDefId ); + + var.Free(); + var.Reset(); + var.AppendL( TColumn( (TUint32)~EMdERelationFlagNotPresent ) ); + var.AppendL( TColumn( objectId ) ); + var.AppendL( TColumn( objectId ) ); + + __LOGQUERY_16( _L("SetObjectToPresentByGuidL q3:"), + clauseBuffer3.ConstBufferL(), var); + + connection.ExecuteL( clauseBuffer3.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( &commonClauseThree ); + } + // no any matching object + else + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // statement, var, commonClauseOne + } + +void CMdSSqlObjectManipulate::ChangePathL( + const TDesC& aOldPath, const TDesC& aNewPath, + RArray& aObjectIds) + { + // collect object IDs from object which match to the old path + _LIT( KGetObjectIdByBeginOfUri, "SELECT ObjectId FROM Object%u WHERE NOT Flags&? AND substr(URI, 1, ?) = ?;" ); + + RClauseBuffer commonClauseOne(*this, + KGetObjectIdByBeginOfUri.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBuffer = commonClauseOne.BufferL(); + clauseBuffer.BufferL().Format( KGetObjectIdByBeginOfUri, KDefaultNamespaceDefId ); + + const TUint32 flags = EMdEObjectFlagNotPresent | EMdEObjectFlagRemoved | EMdEObjectFlagGarbage; + + const TInt oldPathLength = aOldPath.Length(); + + RRowData var; + CleanupClosePushL( var ); + var.ReserveL( 3 ); + var.AppendL( TColumn( flags ) ); + var.AppendL( TColumn( oldPathLength ) ); + var.AppendL( TColumn( aOldPath ) ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RMdsStatement statement; + CleanupClosePushL( statement ); + + __LOGQUERY_16( _L("ChangePathL q1:"), clauseBuffer.ConstBufferL(), var); + + connection.ExecuteQueryL( clauseBuffer.ConstBufferL(), statement, var ); + + var.Free(); + var.Reset(); + TItemId objectId( 0 ); + var.AppendL( TColumn( objectId ) ); + + while( connection.NextRowL( statement, var ) ) + { + var.Column( 0 ).Get( objectId ); + aObjectIds.AppendL( objectId ); + } + + // update the new path to objects which match with the old path + _LIT( KChangeOldPathToNewPath, "UPDATE Object%u SET URI=? || substr(URI, ?, length(URI)) WHERE NOT Flags&? AND substr(URI, 1, ?) = ?;" ); + + RClauseBuffer commonClauseTwo(*this, + KChangeOldPathToNewPath.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseTwo ); + CMdsClauseBuffer& clauseBuffer2 = commonClauseTwo.BufferL(); + clauseBuffer2.BufferL().Format( KChangeOldPathToNewPath, KDefaultNamespaceDefId ); + + var.Free(); + var.Reset(); + + var.ReserveL( 5 ); + var.AppendL( TColumn( aNewPath ) ); + var.AppendL( TColumn( oldPathLength + 1 ) ); + var.AppendL( TColumn( flags ) ); + var.AppendL( TColumn( oldPathLength ) ); + var.AppendL( TColumn( aOldPath ) ); + + __LOGQUERY_16( _L("ChangePathL q2:"), clauseBuffer2.ConstBufferL(), var); + + connection.ExecuteL( clauseBuffer2.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( 4, &commonClauseOne ); // commonClauseTwo, statement, var, commonClauseOne + } + +void CMdSSqlObjectManipulate::ChangeMediaIdL() + { + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + TVolumeInfo volumeInfo; + RFs fs; + User::LeaveIfError( fs.Connect() ); + CleanupClosePushL( fs ); + + fs.Volume( volumeInfo, EDriveC ); + CleanupStack::PopAndDestroy( &fs ); + + // update the new media id to objects which match with the old id + _LIT( KChangeOldIdToNewId, "UPDATE Object%u SET MediaId=? WHERE NOT Flags&? AND MediaId = (SELECT Value FROM MdE_Preferences WHERE Key=?);" ); + + RClauseBuffer clauseOne( *this, KChangeOldIdToNewId.iTypeLength + KMaxUintValueLength ); + CleanupClosePushL( clauseOne ); + CMdsClauseBuffer& clauseBuffer = clauseOne.BufferL(); + clauseBuffer.BufferL().Format( KChangeOldIdToNewId, KDefaultNamespaceDefId ); + + const TUint32 flags = EMdEObjectFlagNotPresent | EMdEObjectFlagRemoved | EMdEObjectFlagGarbage; + + RRowData var; + CleanupClosePushL( var ); + + var.ReserveL( 3 ); + var.AppendL( TColumn( (TUint32) volumeInfo.iUniqueID ) ); + var.AppendL( TColumn( flags ) ); + var.AppendL( TColumn( KCMediaIdKey ) ); + + __LOGQUERY_16( _L("ChangeMediaIdL q2:"), clauseBuffer.ConstBufferL(), var); + + connection.ExecuteL( clauseBuffer.ConstBufferL(), var ); + + // update the new media id to objects which match with the old id + _LIT( KUpdateMediaId, "UPDATE MdE_Preferences SET Value=? WHERE Key = ?;" ); + + var.Free(); + var.Reset(); + + TTime currentTime; + currentTime.UniversalTime(); + const TInt64 currentTime64 = currentTime.Int64(); + + var.ReserveL( 2 ); + var.AppendL( TColumn( (TUint32) volumeInfo.iUniqueID ) ); + var.AppendL( TColumn( KCMediaIdKey ) ); + + connection.ExecuteL( KUpdateMediaId, var ); + + CleanupStack::PopAndDestroy( &var ); + CleanupStack::PopAndDestroy( &clauseOne ); + } + +const CMdsPropertyDef& CMdSSqlObjectManipulate::ReadPropertyL( + CMdCSerializationBuffer& aBuffer, const CMdsObjectDef& aObjectDef, + CMdsClauseBuffer& aBaseObjectClause, CMdsClauseBuffer& aObjectClause, + RRowData& aBaseObjectDataRow, RRowData& aObjectDataRow, TUint8& aFlags) + { + const TMdCProperty& property = TMdCProperty::GetFromBufferL( aBuffer ); + const CMdsPropertyDef* propertyDef = aObjectDef.GetPropertyByIdL( + property.iPropertyDefId ); + if ( !propertyDef ) + { +#ifdef _DEBUG + WRITELOG( "Incorrect property" ); +#endif + User::Leave( KErrMdEUnknownPropertyDef ); + } + aFlags = property.iModFlags; + + if (property.iModFlags == EMdEPropertyModNone) + { + return *propertyDef; + } + + const TBool baseObjectProperty = + iBaseObjectDef->GetPropertyByIdL(property.iPropertyDefId) != NULL; + + // if property is not removed add actual value + if( !( property.iModFlags & EMdEPropertyModRemove ) ) + { + switch(propertyDef->GetType()) + { + case EPropertyBool: + { + const TBool boolValue = property.iValue.iInt32; + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( boolValue ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( boolValue ) ); + } + break; + } + case EPropertyInt8: + { + const TInt8 int8Value = property.iValue.iInt32; + if ( !propertyDef->CheckMinMaxValue( (TInt32)int8Value ) ) + { +#ifdef _DEBUG + TInt32 debugValue = int8Value; + WRITELOG2( "Incorrect property[%S] value: %d", + &propertyDef->GetName(), debugValue ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( int8Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( int8Value ) ); + } + break; + } + case EPropertyUint8: + { + const TUint8 uInt8Value = property.iValue.iUint32; + if ( !propertyDef->CheckMinMaxValue( (TInt32)uInt8Value ) ) + { +#ifdef _DEBUG + TInt32 debugValue = uInt8Value; + WRITELOG2( "Incorrect property[%S] value: %d", + &propertyDef->GetName(), debugValue ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( uInt8Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( uInt8Value ) ); + } + break; + } + case EPropertyInt16: + { + const TInt16 int16Value = property.iValue.iInt32; + if ( !propertyDef->CheckMinMaxValue( (TInt32)int16Value ) ) + { +#ifdef _DEBUG + TInt32 debugValue = int16Value; + WRITELOG2( "Incorrect property[%S] value: %d", + &propertyDef->GetName(), debugValue ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( int16Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( int16Value ) ); + } + break; + } + case EPropertyUint16: + { + const TUint16 uInt16Value = property.iValue.iUint32; + if ( !propertyDef->CheckMinMaxValue( (TInt32)uInt16Value ) ) + { +#ifdef _DEBUG + TInt32 debugValue = uInt16Value; + WRITELOG2( "Incorrect property[%S] value: %d", + &propertyDef->GetName(), debugValue ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( uInt16Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( uInt16Value ) ); + } + break; + } + case EPropertyInt32: + { + const TInt32 int32Value = property.iValue.iInt32; + if ( !propertyDef->CheckMinMaxValue( int32Value ) ) + { +#ifdef _DEBUG + WRITELOG2( "Incorrect property[%S] value: %d", + &propertyDef->GetName(), int32Value ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( int32Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( int32Value ) ); + } + break; + } + case EPropertyUint32: + { + const TUint32 uInt32Value = property.iValue.iUint32; + if ( !propertyDef->CheckMinMaxValue( uInt32Value ) ) + { +#ifdef _DEBUG + WRITELOG2( "Incorrect property[%S] value: %u", + &propertyDef->GetName(), uInt32Value ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( uInt32Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( uInt32Value ) ); + } + break; + } + case EPropertyInt64: + { + const TInt64 int64Value = property.iValue.iInt64; + if ( !propertyDef->CheckMinMaxValue( int64Value ) ) + { +#ifdef _DEBUG + WRITELOG2( "Incorrect property[%S] value: %Ld", + &propertyDef->GetName(), int64Value ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( int64Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( int64Value ) ); + } + break; + } + case EPropertyTime: + { + const TInt64 int64Value = property.iValue.iInt64; + if ( !propertyDef->CheckMinMaxValue( int64Value ) ) + { +#ifdef _DEBUG + WRITELOG2( "Incorrect property[%S] value: %Ld", + &propertyDef->GetName(), int64Value ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( int64Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( int64Value ) ); + } + break; + } + case EPropertyReal32: + { + const TReal32 real32Value = property.iValue.iReal; + if ( !propertyDef->CheckMinMaxValue( real32Value ) ) + { +#ifdef _DEBUG + TReal64 debugValue = real32Value; + WRITELOG2( "Incorrect property[%S] value: %.2f", + &propertyDef->GetName(), debugValue ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( real32Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( real32Value ) ); + } + break; + } + case EPropertyReal64: + { + const TReal64 real64Value = property.iValue.iReal; + if ( !propertyDef->CheckMinMaxValue( real64Value ) ) + { +#ifdef _DEBUG + WRITELOG2( "Incorrect property[%S] value: %.2f", + &propertyDef->GetName(), real64Value ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( real64Value ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( real64Value ) ); + } + break; + } + case EPropertyText: + { + aBuffer.PositionL( property.iValue.iPtr.iOffset ); + TPtrC16 textValue( aBuffer.ReceivePtr16L() ); + if ( !propertyDef->CheckMinMaxValue( (TInt32)textValue.Length() ) ) + { +#ifdef _DEBUG + WRITELOG3( "Incorrect property[%S] value: \"%S\", length: %d", + &propertyDef->GetName(), &textValue, + textValue.Length() ); +#endif + User::Leave( KErrMdEPropertyValueNotBetweenAllowedMinMax ); + } + if ( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( textValue ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( textValue ) ); + } + break; + } + default: + User::Leave( KErrMdEUnknownPropertyType ); + } + } + // if property is removed add null value + else + { + TPtrC16 val = TPtr16((TUint16*)0, 0); + if( baseObjectProperty ) + { + aBaseObjectDataRow.AppendL( TColumn( val ) ); + } + else + { + aObjectDataRow.AppendL( TColumn( val ) ); + } + } + + if( baseObjectProperty ) + { + aBaseObjectClause.AppendL( KComma ); + aBaseObjectClause.AppendL( propertyDef->GetName() ); + } + else + { + aObjectClause.AppendL( KComma ); + aObjectClause.AppendL( propertyDef->GetName() ); + } + + return *propertyDef; + } + +TItemId CMdSSqlObjectManipulate::AddObjectL( CMdSSqLiteConnection& aConnection, + CMdCSerializationBuffer& aBuffer, + RMdsStatement& aMdsBaseObjStatement, RMdsStatement& aMdsObjStatement, + const CMdSServerSession* aServerSession ) + { + _LIT( KMdsObjectAddBaseObjectBegin, "INSERT INTO Object%u(ObjectId,ObjectDefId,Flags,MediaId,GuidHigh,GuidLow,URI" ); + _LIT( KMdsObjectAddBaseObjectMiddle, ") VALUES(?,?,?,?,?,?,?" ); + _LIT( KMdsObjectAddObjectBegin, "INSERT INTO %S%u(ObjectId" ); + _LIT( KMdsObjectAddObjectMiddle, ") VALUES(?" ); + _LIT( KMdsObjectAddObjectEnd, ");" ); + + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RRowData baseObjectRow; + CleanupClosePushL( baseObjectRow ); + RRowData objectRow; + CleanupClosePushL( objectRow ); + + const TMdCObject& object = TMdCObject::GetFromBufferL( aBuffer ); + // there must be at least one property (btw. base object have 7 properties) + if (object.iProperties.iPtr.iCount < 1) + { + User::Leave( KErrMdEMandatoryPropertyMissing ); + } + + // objectid + if (object.iId != KNoId) + { + User::Leave( KErrAlreadyExists ); + } + + RSQLIndex sqlIndex; + CleanupClosePushL( sqlIndex ); + const TItemId objectId = sqlIndex.GetId(); + + baseObjectRow.AppendL( TColumn( objectId ) ); + objectRow.AppendL( TColumn( objectId ) ); + + // objectdefid + const CMdsObjectDef* objectDef = iNamespaceDef->GetObjectByIdL( object.iDefId ); + if ( !objectDef ) + { + // objectDef doesn't exist + User::Leave( KErrMdEUnknownObjectDef ); + } + baseObjectRow.AppendL( TColumn( object.iDefId ) ); + + // get BaseObjectDef + iBaseObjectDef = iNamespaceDef->GetObjectByIdL( KBaseObjectDefId ); + + RClauseBuffer commonClauseOne(*this); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseBaseObject = commonClauseOne.BufferL(); + RClauseBuffer commonClauseTwo(*this); + CleanupClosePushL( commonClauseTwo ); + CMdsClauseBuffer& clauseObject = commonClauseTwo.BufferL(); + + const TDesC& objName = objectDef->GetName(); + if(objName != iLastAddedObjName) + { + iLastAddedObjName = objName; + aMdsBaseObjStatement.Close(); + aMdsBaseObjStatement = RMdsStatement(); + aMdsObjStatement.Close(); + aMdsObjStatement = RMdsStatement(); + } + + clauseObject.BufferL().Format( KMdsObjectAddObjectBegin, &objName, iNamespaceDef->GetId() ); + clauseBaseObject.BufferL().Format( KMdsObjectAddBaseObjectBegin, iNamespaceDef->GetId() ); + + TUint32 objectFlags = 0; + if ( !( object.iFlags & ( EMdEObjectFlagModOpen | EMdEObjectFlagAutoLock ) ) ) + { + User::Leave( KErrMdENotLocked ); + } + + if (object.iFlags & EMdEObjectFlagConfidential) + { + objectFlags |= EMdEObjectFlagConfidential; + } + if (object.iFlags & EMdEObjectFlagModFreeText) + { + objectFlags |= EMdEObjectFlagFreetexts; + } + if (object.iFlags & EMdEObjectFlagPlaceholder) + { + objectFlags |= EMdEObjectFlagPlaceholder; + } + if (objectDef->GetFlags() == CMdsObjectDef::EObjectDefFlagsContext) + { + objectFlags |= EMdEObjectFlagContext; + } + baseObjectRow.AppendL( TColumn( objectFlags ) ); + + // mediaId + baseObjectRow.AppendL( TColumn( object.iMediaId ) ); + + TInt64 guidHigh = object.iGuidHigh; + TInt64 guidLow = object.iGuidLow; + + if (guidLow == 0 && guidHigh == 0) + { + iGenerator->GenerateGuid( guidHigh, guidLow ); + } + + baseObjectRow.AppendL( TColumn( guidHigh ) ); + baseObjectRow.AppendL( TColumn( guidLow ) ); + + // uri + HBufC* uriBuf = NULL; + if (object.iUri.iPtr.iCount == 0) + { + uriBuf = iGenerator->GenerateUriL( *objectDef, guidHigh, guidLow ); + } + else + { + aBuffer.PositionL( object.iUri.iPtr.iOffset ); + uriBuf = aBuffer.ReceiveDes16L(); + } + CleanupStack::PushL( uriBuf ); + TPtr16 uri( uriBuf->Des() ); + uri.LowerCase(); + baseObjectRow.AppendL( TColumn( uri ) ); + + const TInt baseObjectRowSizeWithoutProperties = baseObjectRow.Size(); + + TInt mandatoryPropertyCount = objectDef->GetMandatoryPropertyCount(); + + // try to add property + for ( TUint32 i = 0; i < object.iProperties.iPtr.iCount; ++i ) + { + aBuffer.PositionL( object.iProperties.iPtr.iOffset + i * sizeof(TMdCProperty) ); + TUint8 modFlags; + const CMdsPropertyDef& propertyDef = ReadPropertyL( aBuffer, *objectDef, clauseBaseObject, clauseObject, baseObjectRow, objectRow, modFlags ); + if ( modFlags == EMdEPropertyModNone ) + { + continue; + } + + // check if mandatory property is removed + if( propertyDef.GetMandatory() ) + { + if( modFlags & EMdEPropertyModRemove ) + { + User::Leave( KErrMdEMandatoryPropertyMissing ); + } + else + { + --mandatoryPropertyCount; + } + } + } + + if( mandatoryPropertyCount != 0 ) + { + User::Leave( KErrMdEMandatoryPropertyMissing ); + } + + clauseBaseObject.AppendL( KMdsObjectAddBaseObjectMiddle ); + + const TInt baseObjectPropertyCount = baseObjectRow.Size() - + baseObjectRowSizeWithoutProperties; + + for ( TInt i = 0; i < baseObjectPropertyCount; ++i ) + { + clauseBaseObject.AppendL( KComma ); + clauseBaseObject.AppendL( KVariable ); + } + + clauseObject.AppendL( KMdsObjectAddObjectMiddle ); + + // object row property count (object row size without object ID) + const TInt objectPropertyCount = objectRow.Size() - 1; + + for ( TInt i = 0; i < objectPropertyCount; ++i ) + { + clauseObject.AppendL( KComma ); + clauseObject.AppendL( KVariable ); + } + + clauseBaseObject.AppendL( KMdsObjectAddObjectEnd ); + clauseObject.AppendL( KMdsObjectAddObjectEnd ); + + // EVERYTHING IS OK - add object to DB + + TInt queryResult = 0, err; + // add base object properties + __LOGQUERY_16( _L("Add BaseObject to DB:"), clauseBaseObject.ConstBufferL(), baseObjectRow); + TRAP( err, aConnection.ExecuteL( clauseBaseObject.ConstBufferL(), baseObjectRow, &aMdsBaseObjStatement ) ); + if (err == KSqlErrConstraint) + { + __LOG1( ELogQuery, "Adding baseObject constraint error - err:%d", err ); + TRAP_IGNORE( RemoveObjectForceL( uri, KNoId ) ); + __LOGQUERY_16( _L("Add AGAIN BaseObject to DB:"), clauseBaseObject.ConstBufferL(), baseObjectRow); + TRAP( err, aConnection.ExecuteL( clauseBaseObject.ConstBufferL(), baseObjectRow, &aMdsBaseObjStatement ) ); + } + + if (err != KErrNone) + { + __LOG1( ELogQuery, "Adding baseObject failed - err:%d", err ); + User::Leave( KErrGeneral ); + } + + if( !( // skip if object definition is "base object" + // and object is placeholder + (object.iDefId == KBaseObjectDefId) && + (object.iFlags & EMdEObjectFlagPlaceholder) + ) + ) + { + __LOGQUERY_16( _L("Add Object to DB:"), clauseObject.ConstBufferL(), + objectRow); + TRAP( err, queryResult = aConnection.ExecuteL( + clauseObject.ConstBufferL(), objectRow, &aMdsObjStatement ) ); + if (err != KErrNone || queryResult != 1) + { + __LOG2( ELogQuery, "Adding object failed - err:%d, queryResult:%d", err, queryResult ); + TRAP_IGNORE( RemoveObjectForceL( objectId ) ); + User::Leave( err ); + } + } + + CleanupStack::PopAndDestroy( uriBuf ); + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // commonClauseTwo, commonClauseOne + + // add freetext to DB + if ( object.iFreeTexts.iPtr.iCount > 0 ) + { + aBuffer.PositionL( object.iFreeTexts.iPtr.iOffset ); + TRAP( err, AddFreeTextL( aBuffer, object.iFreeTexts.iPtr.iCount, objectId ) ); + if (err != KErrNone) + { + __LOG1( ELogQuery, "Adding object freetext failed - err:%d", err ); + TRAP_IGNORE( RemoveObjectForceL( objectId ) ); + User::Leave( err ); + } + } + + sqlIndex.Commit(); + CleanupStack::PopAndDestroy( &sqlIndex ); + CleanupStack::PopAndDestroy( 2, &baseObjectRow ); // objectRow, baseObjectRow + + if( ( object.iFlags & EMdEObjectFlagAutoLock ) && aServerSession ) + { + iLockList.LockObjectL( *aServerSession, *iNamespaceDef, objectId ); + } + + return objectId; + } + +TUint32 CMdSSqlObjectManipulate::AddFreeTextToDBL( TPtrC16& aWord, TItemId aObjectId, + TInt32 aPosition, TBool aSearch ) + { + _LIT( KMdsFreeTextAdd, "INSERT INTO TextSearch%d(WordId,ObjectId,Position) VALUES(?,?,?)" ); + _LIT( KMdsFreeTextDictAdd, "INSERT INTO TextSearchDictionary%d(Word) VALUES(?)" ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RClauseBuffer commonClauseOne(*this); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& freeTextAdd = commonClauseOne.BufferL(); + RClauseBuffer commonClauseTwo(*this); + CleanupClosePushL( commonClauseTwo ); + CMdsClauseBuffer& freeTextDictAdd = commonClauseTwo.BufferL(); + + freeTextAdd.BufferL().Format( KMdsFreeTextAdd, iNamespaceDef->GetId() ); + freeTextDictAdd.BufferL().Format( KMdsFreeTextDictAdd, iNamespaceDef->GetId() ); + + TItemId freeTextId = KNoId; + RRowData freeTextRow; + CleanupClosePushL( freeTextRow ); + RRowData freeTextRowDict; + CleanupClosePushL( freeTextRowDict ); + + freeTextRow.ReserveL( 3 ); + + freeTextRow.AppendL( TColumn(KNoId) ); + freeTextRow.AppendL( TColumn(aObjectId) ); + freeTextRow.AppendL( TColumn(aPosition) ); + + freeTextId = FindFreeTextInDbL( aWord ); + if ( aSearch && freeTextId ) + { + freeTextRow.Column(0).Set( freeTextId ); + __LOGQUERY_16( _L("Add FreeText index to DB:"), + freeTextAdd.ConstBufferL(), freeTextRow); + connection.ExecuteL( freeTextAdd.ConstBufferL(), freeTextRow ); + } + else + { + freeTextRowDict.AppendL( TColumn( aWord ) ); + __LOGQUERY_16( _L("Add FreeText to DB:"), + freeTextDictAdd.ConstBufferL(), freeTextRowDict); + TRAPD( err, freeTextId = MMdSIndexer::ExecuteAndGetIndexL( + freeTextDictAdd.ConstBufferL(), freeTextRowDict ) ); + if (err != KErrNone || freeTextId == KNoId) + { + __LOG2( ELogQuery, "Adding freetextDict failed - err:%d, freeTextId:%d", + err, freeTextId ); + User::Leave( KErrGeneral ); + } + + freeTextRow.Column(0).Set( freeTextId ); + connection.ExecuteL( freeTextAdd.ConstBufferL(), freeTextRow ); + } + + CleanupStack::PopAndDestroy( 4, &commonClauseOne ); // freeTextRowDict, freeTextRow, commonClauseTwo, commonClauseOne + return freeTextId; + } + +TInt CMdSSqlObjectManipulate::AddFreeTextL( CMdCSerializationBuffer& aBuffer, TInt aFreeTextCount, TItemId aObjectId ) + { + TInt freeTextAdded = 0; + + for ( TUint32 i = 0; i < aFreeTextCount; ++i ) + { + TPtrC16 freeText = aBuffer.ReceivePtr16L(); + AddFreeTextToDBL( freeText, aObjectId, i ); + ++freeTextAdded; + } + return freeTextAdded; + } + +TItemId CMdSSqlObjectManipulate::FindFreeTextInDbL( TPtrC16 aFreeText ) + { + _LIT( KMdsFreeTextSearch, "SELECT WordId FROM TextSearchDictionary%d WHERE Word=? LIMIT 1;" ); + + RClauseBuffer commonClauseOne(*this, KMdsFreeTextSearch.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& freeTextSearchClause = commonClauseOne.BufferL(); + freeTextSearchClause.BufferL().Format( KMdsFreeTextSearch, iNamespaceDef->GetId() ); + + TItemId freeTextId = 0; + RRowData wordRow; + CleanupClosePushL( wordRow ); + RRowData idRow; + CleanupClosePushL( idRow ); + RMdsStatement query; + CleanupClosePushL( query ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + wordRow.AppendL( TColumn( aFreeText ) ); + idRow.AppendL( TColumn( freeTextId ) ); + connection.ExecuteQueryL( freeTextSearchClause.ConstBufferL(), query, wordRow ); + if( connection.NextRowL( query, idRow ) ) + { + idRow.Column( 0 ).Get( freeTextId ); + } + + CleanupStack::PopAndDestroy( 4, &commonClauseOne ); // query, idRow, wordRow, commonClauseOne + return freeTextId; + } + +void CMdSSqlObjectManipulate::RemoveObjectForceL( const TDesC16& aUri, TItemId aObjectId ) + { + _LIT( KMdsRemoveObjectByUri, "DELETE FROM Object%u WHERE Flags&? AND ObjectId!=? AND URI=?;" ); + + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RClauseBuffer commonClauseOne(*this, KMdsRemoveObjectByUri.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& removeObjectClause = commonClauseOne.BufferL(); + + removeObjectClause.BufferL().Format( KMdsRemoveObjectByUri, + iNamespaceDef->GetId() ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + // do remove + RRowData varRemove; + CleanupClosePushL( varRemove ); + varRemove.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + varRemove.AppendL( TColumn( aObjectId ) ); + varRemove.AppendL( TColumn( aUri ) ); + +#ifdef _DEBUG +#ifdef LOG_MASTER_FLAG + TInt queryResult = 0; // For debug + __LOGQUERY_16( _L("Remove FORCE object using URI:"), + removeObjectClause.ConstBufferL(), varRemove); + TRAPD( err, queryResult = connection.ExecuteL( + removeObjectClause.ConstBufferL(), varRemove ) ); + if( err != KErrNone ) + { + __LOG2( ELogQuery, "Remove FORCE object err:%d, queryResult:%d", err, queryResult ); + } +#else + TRAP_IGNORE( connection.ExecuteL( removeObjectClause.ConstBufferL(), varRemove ) ); +#endif // LOG_MASTER_FLAG +#else + TRAP_IGNORE( connection.ExecuteL( removeObjectClause.ConstBufferL(), varRemove ) ); +#endif // _DEBUG + + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // varRemove, commonClauseOne + } + +// USE WITH CAUTION !!! +// THIS FUNCTION REMOVES OBJECT WITHOUT ANY CHECKING +// ONLY FOR INTERNAL USE !!! +void CMdSSqlObjectManipulate::RemoveObjectForceL( TItemId aObjectId ) + { + _LIT( KMdsRemoveObjectById, "DELETE FROM Object%u WHERE ObjectId=?;" ); + + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RClauseBuffer commonClauseOne(*this, KMdsRemoveObjectById.iTypeLength + KMaxUintValueLength ); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& removeObjectClause = commonClauseOne.BufferL(); + + removeObjectClause.BufferL().Format( KMdsRemoveObjectById, iNamespaceDef->GetId() ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + // do remove + RRowData varRemove; + CleanupClosePushL( varRemove ); + varRemove.AppendL( TColumn( aObjectId ) ); + +#ifdef _DEBUG +#ifdef LOG_MASTER_FLAG + TInt queryResult = 0; // For debug + __LOGQUERY_16( _L("Remove object using ID:"), + removeObjectClause.ConstBufferL(), varRemove); + TRAPD( err, queryResult = connection.ExecuteL( + removeObjectClause.ConstBufferL(), varRemove ) ); + if ( err != KErrNone ) + { + __LOG2( ELogQuery, "Remove FORCE Object err:%d, queryResult:%d", err, queryResult ); + } +#else + TRAP_IGNORE( connection.ExecuteL( removeObjectClause.ConstBufferL(), varRemove ) ); +#endif // LOG_MASTER_FLAG +#else + TRAP_IGNORE( connection.ExecuteL( removeObjectClause.ConstBufferL(), varRemove ) ); +#endif // _DEBUG + + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // varRemove, commonClauseOne + } + +CMdCSerializationBuffer* CMdSSqlObjectManipulate::CheckObjectL( TInt aResultBufferSize, + const TDesC& aUri, TDefId aNamespaceDefId ) + { + _LIT( KMdsCheckObjectByUri, "SELECT ObjectId, ObjectDefId, Flags FROM Object%u WHERE URI=?;" ); + + RClauseBuffer commonClauseOne(*this, KMdsCheckObjectByUri.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& checkObjectClause = commonClauseOne.BufferL(); + + checkObjectClause.BufferL().Format( KMdsCheckObjectByUri, aNamespaceDefId ); + + RRowData rowData; + CleanupClosePushL( rowData ); + rowData.AppendL( TColumn( aUri ) ); + + RMdsStatement query; + CleanupClosePushL( query ); + + CMdSSqLiteConnection& db = MMdSDbConnectionPool::GetDefaultDBL(); + + db.ExecuteQueryL( checkObjectClause.ConstBufferL(), query, rowData ); + + rowData.Free(); rowData.Reset(); + rowData.ReserveL( 3 ); // space for SELECTs + + TMdCObject object; + rowData.AppendL( TColumn( object.iId ) ); + rowData.AppendL( TColumn( object.iDefId ) ); + rowData.AppendL( TColumn( object.iFlags ) ); + + CMdCSerializationBuffer* buffer = NULL; + if ( db.NextRowL( query, rowData ) ) + { + rowData.Column(0).Get( object.iId ); + rowData.Column(1).Get( object.iDefId ); + rowData.Column(2).Get( object.iFlags ); + + buffer = CMdCSerializationBuffer::NewLC( aResultBufferSize ); + object.SerializeL( *buffer ); + CleanupStack::Pop( buffer ); + } + else + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // query, rowData, commonClauseOne + + return buffer; + } + +CMdCSerializationBuffer* CMdSSqlObjectManipulate::CheckObjectL( TInt aResultBufferSize, + TItemId aId, TDefId aNamespaceDefId ) + { + _LIT( KMdsCheckObjectById, "SELECT ObjectDefId, Flags FROM Object%u WHERE ObjectId=?;" ); + + RClauseBuffer commonClauseOne(*this, KMdsCheckObjectById.iTypeLength + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& checkObjectClause = commonClauseOne.BufferL(); + + checkObjectClause.BufferL().Format( KMdsCheckObjectById, aNamespaceDefId ); + + RRowData rowData; + CleanupClosePushL( rowData ); + rowData.AppendL( TColumn( aId ) ); + + RMdsStatement query; + CleanupClosePushL( query ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + connection.ExecuteQueryL( checkObjectClause.ConstBufferL(), query, rowData ); + + rowData.Free(); rowData.Reset(); + rowData.ReserveL( 2 ); // space for SELECTs + + TMdCObject object; + object.iId = aId; + rowData.AppendL( TColumn( object.iDefId ) ); + rowData.AppendL( TColumn( object.iFlags ) ); + + CMdCSerializationBuffer* buffer = NULL; + if ( connection.NextRowL( query, rowData ) ) + { + rowData.Column(0).Get( object.iDefId ); + rowData.Column(1).Get( object.iFlags ); + + buffer = CMdCSerializationBuffer::NewLC( aResultBufferSize ); + object.SerializeL( *buffer ); + CleanupStack::Pop( buffer ); + } + else + { + User::Leave( KErrNotFound ); + } + + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // query, rowData, commonClauseOne + + return buffer; + } + +CMdCSerializationBuffer* CMdSSqlObjectManipulate::CheckObjectL( TInt aResultBufferSize, + CMdCSerializationBuffer& aIds, TDefId aNamespaceDefId ) + { + + aIds.PositionL( KNoOffset ); + TUint32 idCount = 0; + aIds.ReceiveL( idCount ); + + // if no IDs, just return 0 objects + if( idCount == 0 ) + { + CMdCSerializationBuffer* buffer = + CMdCSerializationBuffer::NewLC( CMdCSerializationBuffer::KRequiredSizeForTUint32 ); + buffer->InsertL( idCount ); + return buffer; + } + + _LIT( KMdsCheckObjectByIds, "SELECT ObjectId, ObjectDefId, Flags FROM Object%u WHERE ObjectId IN(?" ); + _LIT( KMdsCheckObjectByIdsAppend, ",?" ); + _LIT( KMdsCheckObjectByIdsEnd, ");" ); + + RClauseBuffer commonClauseOne(*this, KMdsCheckObjectByIds.iTypeLength + KMaxUintValueLength + + KMdsCheckObjectByIdsAppend.iTypeLength * (idCount - 1) + + KMdsCheckObjectByIdsEnd.iTypeLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& checkObjectClause = commonClauseOne.BufferL(); + + RRowData rowData; + CleanupClosePushL( rowData ); + + checkObjectClause.BufferL().Format( KMdsCheckObjectByIds, aNamespaceDefId ); + TItemId id; + aIds.ReceiveL( id ); + rowData.AppendL( TColumn( id ) ); + + for( TUint32 i = 1; i < idCount; i++ ) + { + checkObjectClause.BufferL().Append( KMdsCheckObjectByIdsAppend ); + aIds.ReceiveL( id ); + rowData.AppendL( TColumn( id ) ); + } + + checkObjectClause.BufferL().Append( KMdsCheckObjectByIdsEnd ); + + RMdsStatement query; + CleanupClosePushL( query ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + connection.ExecuteQueryL( checkObjectClause.ConstBufferL(), query, rowData ); + + CMdCSerializationBuffer* buffer = CMdCSerializationBuffer::NewLC( aResultBufferSize ); + + // initialize with 0 objects (will be updated later) + TUint32 resultObjectCount = 0; + buffer->InsertL( resultObjectCount ); + + rowData.Free(); + rowData.Reset(); + + rowData.ReserveL( 3 ); // space for SELECT's object + + TMdCObject object; + rowData.AppendL( TColumn( object.iId ) ); + rowData.AppendL( TColumn( object.iDefId ) ); + rowData.AppendL( TColumn( object.iFlags ) ); + + while( connection.NextRowL( query, rowData ) ) + { + rowData.Column(0).Get( object.iId ); + rowData.Column(1).Get( object.iDefId ); + rowData.Column(2).Get( object.iFlags ); + + object.SerializeL( *buffer ); + ++resultObjectCount; + } + + // update object count + buffer->PositionL( KNoOffset ); + buffer->InsertL( resultObjectCount ); + + CleanupStack::Pop( buffer ); + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // query, rowData, commonClauseOne + + return buffer; + } + +static TInt CompareTItemIds( const TItemId& aLeft, const TItemId& aRight ) + { + return aLeft - aRight; + } + +void CMdSSqlObjectManipulate::CollectRemovedItemsL( RArray& aRemoveIds, RArray& aObjectIds, + RArray& aRelationIds, RArray& /*aEventIds*/ ) + { + _LIT( KCollectGetDeleteId, "SELECT O.ObjectId, R.RelationId FROM Object%u AS O LEFT JOIN Relations%u AS R ON O.ObjectId=R.LeftObjectId OR O.ObjectId=R.RightObjectId WHERE NOT O.Flags&? AND ObjectId IN(?" ); + _LIT( KCollectUpdateObjectBegin, "UPDATE Object%u SET Flags=Flags|? WHERE ObjectId IN(?" ); + _LIT( KCollectUpdateRelationsBegin, "UPDATE Relations%u SET Flags=Flags|? WHERE RelationId IN(?" ); + _LIT( KCollectMiddle, ",?" ); + _LIT( KCollectEnd, ");" ); + + const TInt removeIdsCount = aRemoveIds.Count(); + if (removeIdsCount < 1) + { + return; + } + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + RClauseBuffer commonClauseOne(*this, KCollectGetDeleteId().Length() + 2 * KMaxUintValueLength + + (removeIdsCount-1) * KCollectMiddle().Length() + + KCollectEnd().Length()); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& buffer = commonClauseOne.BufferL(); + + // getting removed object id and relation id + RRowData dataRow; + CleanupClosePushL( dataRow ); + dataRow.ReserveL( removeIdsCount ); + dataRow.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + buffer.BufferL().Format( KCollectGetDeleteId, iNamespaceDef->GetId(), iNamespaceDef->GetId() ); + for (TInt i = 0; i < removeIdsCount; ++i) + { + if(i>0) + { + buffer.AppendL( KCollectMiddle ); + } + dataRow.AppendL( TColumn( aRemoveIds[i] ) ); + } + buffer.AppendL( KCollectEnd ); + + RMdsStatement objectQuery; + CleanupClosePushL( objectQuery ); + + __LOGQUERY_16( _L("Find objects to delete:"), buffer.ConstBufferL(), dataRow); + connection.ExecuteQueryL( buffer.ConstBufferL(), objectQuery, dataRow ); + + dataRow.Free(); dataRow.Reset(); + TItemId objectId = KNoId; + TItemId prevId = objectId; + TItemId relationId = KNoId; + dataRow.AppendL( TColumn( objectId ) ); + dataRow.AppendL( TColumn( relationId ) ); + while ( connection.NextRowL( objectQuery, dataRow ) ) + { + dataRow.Column(0).Get( objectId ); + if (objectId != prevId) + { + aObjectIds.AppendL( objectId ); + prevId = objectId; + } + if (!dataRow.Column(1).IsNull()) + { + dataRow.Column(1).Get( relationId ); + aRelationIds.InsertInOrder( relationId, TLinearOrder( CompareTItemIds ) ); + } + else + { + dataRow.Column(1).Set( relationId ); + } + } + + // mark object's as removed + // remove only item that are OK to remove (not removed earlier) + const TInt removeObjectCount = aObjectIds.Count(); + if ( removeObjectCount > 0 ) + { + buffer.ReserveSpaceL( KCollectUpdateObjectBegin().Length() + KMaxUintValueLength + + (removeObjectCount-1) * KCollectMiddle().Length() + + KCollectEnd().Length() ); + + buffer.BufferL().Format( KCollectUpdateObjectBegin, iNamespaceDef->GetId() ); + + dataRow.Free(); + dataRow.Reset(); + dataRow.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + + for (TInt i = 0; i < removeObjectCount; ++i) + { + if(i>0) + { + buffer.AppendL( KCollectMiddle ); + } + dataRow.AppendL( TColumn( aObjectIds[i] ) ); + } + buffer.AppendL( KCollectEnd ); + + __LOGQUERY_16( _L("Remove objects:"), buffer.ConstBufferL(), dataRow); + connection.ExecuteL( buffer.ConstBufferL(), dataRow ); + } + + // mark relations as removed + // remove only item that are OK to remove (not removed earlier) + const TInt removeRelationCount = aRelationIds.Count(); + if ( removeRelationCount > 0 ) + { + buffer.ReserveSpaceL( KCollectUpdateRelationsBegin().Length() + KMaxUintValueLength + + (removeRelationCount-1) * KCollectMiddle().Length() + + KCollectEnd().Length() ); + + buffer.BufferL().Format( KCollectUpdateRelationsBegin, iNamespaceDef->GetId() ); + + dataRow.Free(); dataRow.Reset(); + dataRow.ReserveL( 1 + removeRelationCount ); + dataRow.AppendL( TColumn( EMdERelationFlagDeleted ) ); + + for ( TInt i = 0; i < removeRelationCount; ++i ) + { + if( i > 0 ) + { + buffer.AppendL( KCollectMiddle ); + } + dataRow.AppendL( TColumn( aRelationIds[i] ) ); + } + buffer.AppendL( KCollectEnd ); + + __LOGQUERY_16( _L("Remove relations:"), buffer.ConstBufferL(), dataRow); + connection.ExecuteL( buffer.ConstBufferL(), dataRow ); + } + + + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // objectQuery, dataRow, commonClauseOne + } + +void CMdSSqlObjectManipulate::RemoveObjectsByIdL( + CMdCSerializationBuffer& aBuffer, TInt aCount, RArray& aIdArray, + RArray& aRelationIds, RArray& aEventIds ) + { + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RArray objectIds; + CleanupClosePushL( objectIds ); + + TItemId objectId = KNoId; + + objectIds.ReserveL( aCount ); + for (TUint32 i = 0; i < aCount; ++i) + { + aBuffer.ReceiveL( objectId ); + if ( objectId != KNoId ) + { + if ( iLockList.IsLocked( *iNamespaceDef, objectId ) ) + { + iLockList.UnlockById( *iNamespaceDef, objectId ); + } + + objectIds.AppendL( objectId ); + } + } + + CollectRemovedItemsL( objectIds, aIdArray, aRelationIds, aEventIds ); + + CleanupStack::PopAndDestroy( &objectIds ); + } + +void CMdSSqlObjectManipulate::RemoveObjectsByUriL( + CMdCSerializationBuffer& aBuffer, TInt aCount, RArray& aIdArray, + RArray& aRelationIds, RArray& aEventIds ) + { + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RArray objectIds; + CleanupClosePushL( objectIds ); + + TUint32 flags; + TItemId objectId = KNoId; + objectIds.ReserveL( aCount ); + for (TUint32 i = 0; i < aCount; ++i) + { + TPtrC16 uri = aBuffer.ReceivePtr16L(); + objectId = SearchObjectByUriL( uri, flags ); + if ( objectId != KNoId ) + { + // unlock object, so update is no possible anymore + if ( iLockList.IsLocked( *iNamespaceDef, objectId ) ) + { + iLockList.UnlockById( *iNamespaceDef, objectId ); + } + + objectIds.AppendL( objectId ); + } + } + + CollectRemovedItemsL( objectIds, aIdArray, aRelationIds, aEventIds ); + + CleanupStack::PopAndDestroy( &objectIds ); + } + +TItemId CMdSSqlObjectManipulate::SearchObjectByUriL( const TDesC16& aUri, + TUint32& aFlags ) + { + _LIT( KMdsSearchObjectbyUri, "SELECT ObjectId,Flags FROM Object%u WHERE NOT Flags&? AND NOT Flags&? AND URI=? LIMIT 1;" ); + + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RClauseBuffer commonClauseOne(*this, KMdsSearchObjectbyUri.iTypeLength + KMaxUintValueLength ); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& searchUriClause = commonClauseOne.BufferL(); + + searchUriClause.BufferL().Format( KMdsSearchObjectbyUri, iNamespaceDef->GetId() ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + TItemId objectId = KNoId; + aFlags = 0; + + RRowData varSearch; + CleanupClosePushL( varSearch ); + varSearch.AppendL( TColumn( EMdEObjectFlagNotPresent ) ); + varSearch.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + varSearch.AppendL( TColumn( aUri ) ); + + RMdsStatement getQuery; + CleanupClosePushL( getQuery ); + + __LOGQUERY_16( _L("Search object by URI:"), + searchUriClause.ConstBufferL(), varSearch); + TRAPD( err, connection.ExecuteQueryL( + searchUriClause.ConstBufferL(), getQuery, varSearch ) ); + + varSearch.Free(); + varSearch.Reset(); + varSearch.AppendL( TColumn( objectId ) ); + varSearch.AppendL( TColumn( aFlags ) ); + if ( err == KErrNone && connection.NextRowL( getQuery, varSearch ) ) + { + varSearch.Column(0).Get( objectId ); + varSearch.Column(1).Get( aFlags ); + } + + CleanupStack::PopAndDestroy( 2, &varSearch ); // getQuery, varSearch + CleanupStack::PopAndDestroy( &commonClauseOne ); + return objectId; + } + +TItemId CMdSSqlObjectManipulate::UpdateObjectL( + CMdSSqLiteConnection& aConnection, CMdCSerializationBuffer& aBuffer ) + { + _LIT( KMdsObjectUpdateBaseObjectBegin, "UPDATE Object%u SET " ); + _LIT( KMdsObjectUpdateBaseObjectFlags, "Flags=? " ); + _LIT( KMdsObjectUpdateBaseObjectEnd, ",MediaId=?,GuidHigh=?,GuidLow=?,URI=? "); + _LIT( KMdsObjectUpdateObjectBegin, "UPDATE %S%u SET " ); + _LIT( KMdsObjectUpdateEnd, " WHERE ObjectId=?;" ); + _LIT( KUpdateEqual, "=?" ); + + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + const TMdCObject& object = TMdCObject::GetFromBufferL( aBuffer ); + + // objectid + if (object.iId == KNoId) + { + User::Leave( KErrArgument ); + } + + // object must be locked + if (!iLockList.IsLocked(*iNamespaceDef, object.iId)) + { + User::Leave( KErrMdENotLocked ); + } + + // objectdefid + // objectDef exists ?? + const CMdsObjectDef* objectDef = iNamespaceDef->GetObjectByIdL( + object.iDefId ); + if ( !objectDef ) + { + User::Leave( KErrMdEUnknownObjectDef ); + } + + // get BaseObjectDef + iBaseObjectDef = iNamespaceDef->GetObjectByIdL( KBaseObjectDefId ); + + TUint32 objectFlags = 0; + if (object.iFlags & EMdEObjectFlagConfidential) + { + objectFlags |= EMdEObjectFlagConfidential; + } + if (object.iFlags & EMdEObjectFlagModFreeText) + { + objectFlags |= EMdEObjectFlagFreetexts; + } + if (object.iFlags & EMdEObjectFlagPlaceholder) + { + objectFlags |= EMdEObjectFlagPlaceholder; + } + if (objectDef->GetFlags() == CMdsObjectDef::EObjectDefFlagsContext) + { + objectFlags |= EMdEObjectFlagContext; + } + + if (!(object.iFlags & EMdEObjectFlagModOpen)) + { + User::Leave( KErrMdENotLocked ); + } + + const TBool KUpdateModObject = + object.iFlags & EMdEObjectFlagModObject ? ETrue : EFalse; + const TBool KUpdateModFreeText = + object.iFlags & EMdEObjectFlagModFreeText ? ETrue : EFalse; + const TBool KUpdateModProperty = + object.iFlags & EMdEObjectFlagModProperty ? ETrue : EFalse; + + if ( !( KUpdateModObject || KUpdateModFreeText || KUpdateModProperty ) ) + { + // nothing to change, so unlock object and return + iLockList.UnlockById( *iNamespaceDef, object.iId ); + return object.iId; + } + + RRowData baseObjectRow; + CleanupClosePushL( baseObjectRow ); + RRowData objectRow; + CleanupClosePushL( objectRow ); + + RClauseBuffer commonClauseOne(*this); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& clauseObject = commonClauseOne.BufferL(); + + if (KUpdateModProperty) + { + clauseObject.BufferL().Format( KMdsObjectUpdateObjectBegin, + &objectDef->GetName(), iNamespaceDef->GetId() ); + } + + RClauseBuffer commonClauseTwo(*this); + CleanupClosePushL( commonClauseTwo ); + CMdsClauseBuffer& clauseBaseObject = commonClauseTwo.BufferL(); + if (KUpdateModObject || KUpdateModProperty) + { + clauseBaseObject.BufferL().Format( KMdsObjectUpdateBaseObjectBegin, + iNamespaceDef->GetId() ); + } + + aBuffer.PositionL( object.iUri.iPtr.iOffset ); + HBufC* uriBuf = aBuffer.ReceiveDes16L(); + CleanupStack::PushL( uriBuf ); + TPtr16 uri( uriBuf->Des() ); + uri.LowerCase(); + + // if auto locking, skip extra checks, because only flags can be changed + if( !(object.iFlags & EMdEObjectFlagAutoLock) ) + { + // leave if GUID high and low are 0 + if( object.iGuidHigh == 0 && object.iGuidLow == 0 ) + { + User::Leave( KErrCorrupt ); + } + + // leave if URI is "empty" + if( uri.Length() == 0 ) + { + User::Leave( KErrCorrupt ); + } + } + + TBool KBaseObjectPropertyMod = EFalse; + TBool KObjectPropertyMod = EFalse; + + if (KUpdateModObject) + { + clauseBaseObject.AppendL( KMdsObjectUpdateBaseObjectFlags ); + baseObjectRow.AppendL( TColumn( objectFlags ) ); + + if( !(object.iFlags & EMdEObjectFlagAutoLock) ) + { + clauseBaseObject.AppendL( KMdsObjectUpdateBaseObjectEnd ); + baseObjectRow.AppendL( TColumn( object.iMediaId ) ); + baseObjectRow.AppendL( TColumn( object.iGuidHigh ) ); + baseObjectRow.AppendL( TColumn( object.iGuidLow ) ); + baseObjectRow.AppendL( TColumn( uri ) ); + } + KBaseObjectPropertyMod = ETrue; + } + + // read properties array + if ( KUpdateModProperty ) + { + // try to add property and increase property count + for ( TUint32 i = 0; i < object.iProperties.iPtr.iCount; ++i ) + { + aBuffer.PositionL( object.iProperties.iPtr.iOffset + + i * sizeof(TMdCProperty) ); + TUint8 modFlags; + const CMdsPropertyDef& propertyDef = ReadPropertyL( aBuffer, + *objectDef, clauseBaseObject, clauseObject, baseObjectRow, + objectRow, modFlags ); + // check if property is already in array + if ( modFlags == EMdEPropertyModNone ) + { + continue; + } + + if( ( modFlags & EMdEPropertyModRemove ) && propertyDef.GetMandatory() ) + { + User::Leave( KErrMdEMandatoryPropertyMissing ); + } + + const TDefId propertyId = propertyDef.GetId(); + + if ( iBaseObjectDef->GetPropertyByIdL( propertyId ) ) + { + if (!KBaseObjectPropertyMod) + { + // remove comma before first property + clauseBaseObject.BufferL().Delete( + clauseBaseObject.ConstBufferL().LocateReverse( ',' ), 1 ); + KBaseObjectPropertyMod = ETrue; + } + clauseBaseObject.AppendL( KUpdateEqual ); + } + else + { + if (!KObjectPropertyMod) + { + // remove comma before first property + clauseObject.BufferL().Delete( + clauseObject.ConstBufferL().LocateReverse( ',' ), 1 ); + KObjectPropertyMod = ETrue; + } + clauseObject.AppendL( KUpdateEqual ); + } + } + } + + if (KUpdateModObject || KBaseObjectPropertyMod) + { + clauseBaseObject.AppendL( KMdsObjectUpdateEnd ); + // append confidential and deleted flags + baseObjectRow.AppendL( TColumn( object.iId ) ); + } + + if (KObjectPropertyMod) + { + clauseObject.AppendL( KMdsObjectUpdateEnd ); + // append confidential and deleted flags + objectRow.AppendL( TColumn( object.iId ) ); + } + + TInt queryResult = 0, err; + RMdSTransaction transaction( aConnection ); + CleanupClosePushL( transaction ); + User::LeaveIfError( transaction.Error() ); + + if ( KUpdateModObject || KBaseObjectPropertyMod ) + { + __LOGQUERY_16( _L("Update BaseObject:"), + clauseBaseObject.ConstBufferL(), baseObjectRow); + TRAP( err, queryResult = aConnection.ExecuteL( + clauseBaseObject.ConstBufferL(), baseObjectRow ) ); + + // Try to remove the object which caused the constraint error and try add the object again. + if ( err == KSqlErrConstraint ) + { + __LOG2( ELogQuery, "Update baseObject constraint error - err:%d, queryResult:%d", err, queryResult ); + // The reason of the constraint error is not checked due to performance hit. + TRAP_IGNORE( RemoveObjectForceL( uri, object.iId ) ); + __LOGQUERY_16( _L("Update AGAIN BaseObject:"), + clauseBaseObject.ConstBufferL(), baseObjectRow); + // Fails if the object was not marked as removed. + TRAP( err, queryResult = aConnection.ExecuteL( + clauseBaseObject.ConstBufferL(), baseObjectRow ) ); + } + + if ( err != KErrNone || queryResult != 1 ) + { + __LOG2( ELogQuery, "Update baseObject failed - err:%d, queryResult:%d", err, queryResult ); + User::Leave( KErrGeneral ); + } + } + + if ( KObjectPropertyMod ) + { + __LOGQUERY_16( _L("Update Object:"), clauseObject.ConstBufferL(), + objectRow); + TRAP( err, queryResult = aConnection.ExecuteL( + clauseObject.ConstBufferL(), objectRow ) ); + if (err != KErrNone || queryResult != 1) + { + __LOG2( ELogQuery, "Update Object failed - err:%d, queryResult:%d", err, queryResult ); + User::Leave( KErrGeneral ); + } + } + + if ( KUpdateModFreeText ) + { + if ( object.iFreeTexts.iPtr.iCount > 0 ) + { + aBuffer.PositionL( object.iFreeTexts.iPtr.iOffset ); + UpdateFreeTextL( aBuffer, object.iFreeTexts.iPtr.iCount, object.iId ); + } + } + + transaction.CommitL(); + CleanupStack::PopAndDestroy( &transaction ); + + CleanupStack::PopAndDestroy( uriBuf ); + CleanupStack::PopAndDestroy( &commonClauseTwo ); + CleanupStack::PopAndDestroy( &commonClauseOne ); + + // objectRow, baseObjectRow + CleanupStack::PopAndDestroy( 2, &baseObjectRow ); + + iLockList.UnlockById( *iNamespaceDef, object.iId ); + return object.iId; + } + + +void CMdSSqlObjectManipulate::UpdateFreeTextL( CMdCSerializationBuffer& aBuffer, + TInt aCount, TItemId aObjectId ) + { + _LIT( KMdSUpdateFreeTextDelete, "DELETE FROM TextSearch%u WHERE ObjectId=?;" ); + _LIT( KMdSUpdateFreeTextDictDelete, "DELETE FROM TextSearchDictionary%u WHERE WordId NOT IN(SELECT WordId FROM TextSearch%u);" ); + _LIT( KMdSUpdateFreeTextObjectFlagSet, "UPDATE Object%u SET Flags=Flags|? WHERE ObjectId=?;" ); + _LIT( KMdSUpdateFreeTextObjectFlagReset, "UPDATE Object%u SET Flags=Flags&? WHERE ObjectId=?;" ); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + RClauseBuffer commonClauseOne(*this, KMdSUpdateFreeTextDictDelete.iTypeLength + 2*KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& buffer = commonClauseOne.BufferL(); + RRowData delRow; + CleanupClosePushL( delRow ); + + delRow.AppendL( TColumn( aObjectId ) ); + buffer.BufferL().Format( KMdSUpdateFreeTextDelete, iNamespaceDef->GetId() ); + connection.ExecuteL( buffer.ConstBufferL(), delRow ); + + delRow.Free(); delRow.Reset(); + buffer.BufferL().Format( KMdSUpdateFreeTextDictDelete, iNamespaceDef->GetId(), + iNamespaceDef->GetId() ); + connection.ExecuteL( buffer.ConstBufferL(), delRow ); + + // update object flags + delRow.Free(); delRow.Reset(); + delRow.AppendL( TColumn( EMdEObjectFlagFreetexts ) ); + delRow.AppendL( TColumn( aObjectId ) ); + if ( AddFreeTextL( aBuffer, aCount, aObjectId ) > 0 ) + { + buffer.BufferL().Format( KMdSUpdateFreeTextObjectFlagSet, iNamespaceDef->GetId() ); + } + else + { + buffer.BufferL().Format( KMdSUpdateFreeTextObjectFlagReset, iNamespaceDef->GetId() ); + delRow.Column(0).Set( ~EMdEObjectFlagFreetexts ); + } + connection.ExecuteL( buffer.ConstBufferL(), delRow ); + + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // delRow, commonClauseOne + } + +TItemId CMdSSqlObjectManipulate::AddEventL( CMdSSqLiteConnection& aConnection, + CMdCSerializationBuffer& aBuffer ) + { + _LIT( KAddEvent, "INSERT INTO Event%u(EventId,ObjectId,EventDefId,Timestamp,Source,Participant) VALUES(?,?,?,?,?,?);" ); + + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RClauseBuffer commonClauseOne(*this, KAddEvent().Length() + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& sqlBuf = commonClauseOne.BufferL(); + sqlBuf.BufferL().Format( KAddEvent, iNamespaceDef->GetId() ); + + RRowData var; + CleanupClosePushL( var ); + + const TMdCEvent& event = TMdCEvent::GetFromBufferL( aBuffer ); + + TItemId eventId = event.iId; + if ( eventId != KNoId ) + { + User::Leave( KErrArgument ); + } + + RSQLIndex sqlIndex; + CleanupClosePushL( sqlIndex ); + eventId = sqlIndex.GetId(); + + if ( !iNamespaceDef->GetEventByIdL( event.iDefId ) ) + { + User::Leave( KErrMdEUnknownEventDef ); + } + + if ( event.iObjectId == KNoId ) + { + User::Leave( KErrCorrupt ); + } + + var.AppendL( TColumn( eventId ) ); + var.AppendL( TColumn( event.iObjectId ) ); + var.AppendL( TColumn( event.iDefId ) ); + var.AppendL( TColumn( event.iTime.Int64() ) ); + + TPtrC16 source; + if ( event.iSourceText.iPtr.iCount > 0 ) + { + aBuffer.PositionL( event.iSourceText.iPtr.iOffset ); + source.Set( aBuffer.ReceivePtr16L() ); + } + else + { + source.Set( TPtr16((TUint16*)0, 0) ); + } + var.AppendL( TColumn( source ) ); + + TPtrC16 participant; + if ( event.iParticipantText.iPtr.iCount > 0 ) + { + aBuffer.PositionL( event.iParticipantText.iPtr.iOffset ); + participant.Set( aBuffer.ReceivePtr16L() ); + } + else + { + participant.Set( TPtr16((TUint16*)0, 0) ); + } + var.AppendL( TColumn( participant ) ); + + aConnection.ExecuteL( sqlBuf.ConstBufferL(), var ); + + sqlIndex.Commit(); + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // sqlIndex, var, commonClauseOne + return eventId; + } + +TItemId CMdSSqlObjectManipulate::AddRelationL( + CMdSSqLiteConnection& aConnection, CMdCSerializationBuffer& aBuffer ) + { + _LIT( KAddRelation, "INSERT INTO Relations%u(RelationId,Flags,RelationDefId,LeftObjectId,RightObjectId,Parameter,GuidHigh,GuidLow,LastModifiedDate) VALUES(?,?,?,?,?,?,?,?,?);" ); + + if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RClauseBuffer commonClauseOne(*this, KAddRelation().Length() + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& buffer = commonClauseOne.BufferL(); + buffer.BufferL().Format( KAddRelation, iNamespaceDef->GetId() ); + + RRowData var; + CleanupClosePushL( var ); + + const TMdCRelation& relation = TMdCRelation::GetFromBufferL( aBuffer ); + TItemId relationId = relation.iId; + + if ( relationId != KNoId ) + { + User::Leave( KErrArgument ); + } + + RSQLIndex sqlIndex; + CleanupClosePushL( sqlIndex ); + relationId = sqlIndex.GetId(); + + if ( !iNamespaceDef->GetRelationByIdL( relation.iDefId ) ) + { + User::Leave( KErrMdEUnknownRelationDef ); + } + + if ( relation.iLeftObjectId == KNoId || relation.iRightObjectId == KNoId ) + { + User::Leave( KErrCorrupt ); + } + + TInt64 guidHigh = relation.iGuidHigh; + TInt64 guidLow = relation.iGuidLow; + if ( guidHigh == 0 && guidLow == 0 ) + { + iGenerator->GenerateGuid( guidHigh, guidLow ); + } + + // if last modified date is 0, set it to current universal time + TInt64 lastModifiedDate = relation.iLastModifiedDate.Int64(); + if( lastModifiedDate == 0 ) + { + TTime currentTime; + currentTime.UniversalTime(); + lastModifiedDate = currentTime.Int64(); + } + + var.AppendL( TColumn( relationId ) ); + var.AppendL( TColumn( TUint32(0) ) ); // no flags + var.AppendL( TColumn( relation.iDefId) ); + var.AppendL( TColumn( relation.iLeftObjectId ) ); + var.AppendL( TColumn( relation.iRightObjectId ) ); + var.AppendL( TColumn( relation.iParameter ) ); + var.AppendL( TColumn( guidHigh ) ); + var.AppendL( TColumn( guidLow ) ); + var.AppendL( TColumn( lastModifiedDate ) ); + + aConnection.ExecuteL( buffer.ConstBufferL(), var ); + + sqlIndex.Commit(); + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // sqlIndex, var, commonClauseOne + return relationId; + } + +void CMdSSqlObjectManipulate::RemoveRelationsL( CMdCSerializationBuffer& aBuffer, + TInt aCount, RArray& aIdArray ) + { + _LIT( KRemoveRelation, "UPDATE Relations%u SET Flags=Flags|? WHERE RelationId=? AND NOT Flags&?;" ); + CMdSSqLiteConnection& db = MMdSDbConnectionPool::GetDefaultDBL(); + + RClauseBuffer commonClauseOne(*this, KRemoveRelation().Length() + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& buf = commonClauseOne.BufferL(); + buf.BufferL().Format( KRemoveRelation, iNamespaceDef->GetId() ); + + TInt queryResult = 0; + TItemId relationId = KNoId; + + RRowData varRemove; + CleanupClosePushL( varRemove ); + varRemove.AppendL( TColumn( + EMdERelationFlagDeleted | EMdERelationFlagGarbageDeleted ) ); + varRemove.AppendL( TColumn( relationId ) ); + varRemove.AppendL( TColumn( + EMdERelationFlagDeleted | EMdERelationFlagNotPresent ) ); + + for ( TUint32 i = 0; i < aCount; ++i ) + { + aBuffer.ReceiveL( relationId ); + varRemove.Column( 1 ).Set( relationId ); + TRAPD( err, queryResult = db.ExecuteL( buf.ConstBufferL(), varRemove ) ); + if ( err == KErrNone && queryResult == 1 ) + { + aIdArray.AppendL( relationId ); + } + else + { + aIdArray.AppendL( KNoId ); + } + } + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // varRemove, commonClauseOne + } + +void CMdSSqlObjectManipulate::RemoveEventsL( CMdCSerializationBuffer& aBuffer, + TInt aCount, RArray& aIdArray ) + { + _LIT( KRemoveEvent, "DELETE FROM Event%u WHERE EventId=?;" ); + + CMdSSqLiteConnection& db = MMdSDbConnectionPool::GetDefaultDBL(); + + RClauseBuffer commonClauseOne(*this, KRemoveEvent().Length() + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& buf = commonClauseOne.BufferL(); + buf.BufferL().Format( KRemoveEvent, iNamespaceDef->GetId() ); + + TInt queryResult = 0; + TItemId eventId = KNoId; + + RRowData varRemove; + CleanupClosePushL( varRemove ); + varRemove.AppendL( TColumn( eventId ) ); + + for ( TUint32 i = 0; i < aCount; ++i ) + { + aBuffer.ReceiveL( eventId ); + varRemove.Column( 0 ).Set( eventId ); + TRAPD( err, queryResult = db.ExecuteL( buf.ConstBufferL(), varRemove ) ); + if ( err == KErrNone && queryResult == 1 ) + { + aIdArray.AppendL( eventId ); + } + else + { + aIdArray.AppendL( KNoId ); + } + } + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // varRemove, commonClauseOne + } + +TItemId CMdSSqlObjectManipulate::UpdateRelationsL( + CMdSSqLiteConnection& aConnection, CMdCSerializationBuffer& aBuffer ) + { + _LIT( KUpdateRelation, "UPDATE Relations%u SET RelationDefId=?,LeftObjectId=?,RightObjectId=?,Parameter=?,GuidHigh=?,GuidLow=?,LastModifiedDate=? WHERE NOT Flags&? AND NOT Flags&? AND RelationId=?;" ); + +if ( !iNamespaceDef ) + { + User::Leave( KErrMdEUnknownNamespaceDef ); + } + + RClauseBuffer commonClauseOne(*this, KUpdateRelation().Length() + KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& sqlBuf = commonClauseOne.BufferL(); + sqlBuf.BufferL().Format( KUpdateRelation, iNamespaceDef->GetId() ); + + RRowData var; + CleanupClosePushL( var ); + + const TMdCRelation& relation = TMdCRelation::GetFromBufferL( aBuffer ); + + if ( relation.iId == KNoId ) + { + User::Leave( KErrArgument ); + } + + if ( !iNamespaceDef->GetRelationByIdL( relation.iDefId ) ) + { + User::Leave( KErrMdEUnknownRelationDef ); + } + + // leave if GUID high and low are 0 + if( relation.iGuidHigh == 0 && relation.iGuidLow == 0 ) + { + User::Leave( KErrCorrupt ); + } + + // if last modified date is 0, set it to current universal time + TInt64 lastModifiedDate = relation.iLastModifiedDate.Int64(); + if( lastModifiedDate == 0 ) + { + TTime currentTime; + currentTime.UniversalTime(); + lastModifiedDate = currentTime.Int64(); + } + + var.AppendL( TColumn( relation.iDefId ) ); + var.AppendL( TColumn( relation.iLeftObjectId ) ); + var.AppendL( TColumn( relation.iRightObjectId ) ); + var.AppendL( TColumn( relation.iParameter ) ); + var.AppendL( TColumn( relation.iGuidHigh ) ); + var.AppendL( TColumn( relation.iGuidLow ) ); + var.AppendL( TColumn( lastModifiedDate ) ); + var.AppendL( TColumn( EMdERelationFlagNotPresent ) ); + var.AppendL( TColumn( EMdERelationFlagDeleted ) ); + var.AppendL( TColumn( relation.iId ) ); + + aConnection.ExecuteL( sqlBuf.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( 2, &commonClauseOne ); // var, commonClauseOne + + return relation.iId; + } + +void CMdSSqlObjectManipulate::GetRemovedRelationItemsL( CMdCSerializationBuffer& aBuffer, + const RArray& aRemovedRelations, + const RArray& aAdditionalRemovedRelations ) + { + _LIT( KGetRelationItemsStart, "SELECT RelationId,RelationDefId,LeftObjectId,RightObjectId FROM Relations%u WHERE Flags&? AND RelationId IN(?" ); + _LIT( KGetRelationItemsMiddle, ",?" ); + _LIT( KGetRelationItemsEnd, ");" ); + + const TInt relationsCount = aRemovedRelations.Count() + aAdditionalRemovedRelations.Count(); + + TMdCItems relationItems; + + relationItems.iNamespaceDefId = iNamespaceDef->GetId(); + relationItems.iRelations.iPtr.iCount = 0; // will be updated later + relationItems.iRelations.iPtr.iOffset = sizeof( TMdCItems ); + + if ( relationsCount == 0 ) + { + relationItems.SerializeL( aBuffer ); + + return; + } + + RClauseBuffer commonClauseOne(*this, KGetRelationItemsStart().Length() + KMaxUintValueLength + + KGetRelationItemsMiddle().Length() * relationsCount + + KGetRelationItemsEnd().Length() ); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& sqlBuffer = commonClauseOne.BufferL(); + sqlBuffer.BufferL().Format( KGetRelationItemsStart, iNamespaceDef->GetId() ); + + RRowData var; + CleanupClosePushL( var ); + var.ReserveL( 1 + relationsCount ); + var.AppendL( EMdERelationFlagDeleted ); + + const TInt removedRelationsCount = aRemovedRelations.Count(); + for (TInt i = 0; i < removedRelationsCount-1; ++i) + { + sqlBuffer.AppendL( KGetRelationItemsMiddle ); + var.AppendL( aRemovedRelations[i] ); + } + if ( removedRelationsCount ) + { + var.AppendL( aRemovedRelations[removedRelationsCount-1] ); + } + + const TInt additionalRemovedRelationsCount = aAdditionalRemovedRelations.Count(); + for (TInt i = 0; i < additionalRemovedRelationsCount-1; ++i) + { + sqlBuffer.AppendL( KGetRelationItemsMiddle ); + var.AppendL( aAdditionalRemovedRelations[i] ); + } + if ( removedRelationsCount == 0 /*&& additionalRemovedRelationsCount*/ ) + { + // cannot be empty + var.AppendL( aAdditionalRemovedRelations[additionalRemovedRelationsCount-1] ); + } + + sqlBuffer.AppendL( KGetRelationItemsEnd ); + + RMdsStatement getQuery; + CleanupClosePushL( getQuery ); + + __LOGQUERY_16( _L("CMdSSqlObjectManipulate::GetRemovedRelationItemsL:"), + sqlBuffer.ConstBufferL(), var); + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + + connection.ExecuteQueryL( sqlBuffer.ConstBufferL(), getQuery, var ); + + var.Free(); + var.Reset(); + + var.ReserveL( 4 ); + + TMdCRelation relation; + var.AppendL( relation.iId ); + var.AppendL( relation.iDefId ); + var.AppendL( relation.iLeftObjectId ); + var.AppendL( relation.iRightObjectId ); + + TUint32 resultCount = 0; + + // move position after items + aBuffer.PositionL( relationItems.iRelations.iPtr.iOffset ); + + while( connection.NextRowL( getQuery, var ) ) + { + ++resultCount; + + var.Column( 0 ).Get( relation.iId ); + var.Column( 1 ).Get( relation.iDefId ); + var.Column( 2 ).Get( relation.iLeftObjectId ); + var.Column( 3 ).Get( relation.iRightObjectId ); + + relation.SerializeL( aBuffer ); + } + + // update relation count + relationItems.iRelations.iPtr.iCount = resultCount; + + // move position to begin of buffer and serialize items + aBuffer.PositionL( KNoOffset ); + relationItems.SerializeL( aBuffer ); + + CleanupStack::PopAndDestroy( 3, &commonClauseOne ); // getQuery, var, commonClauseOne + } + +void CMdSSqlObjectManipulate::SetPendingL(const RArray& aObjectIds, + TBool aReset) + { + _LIT( KUpdatePending, "UPDATE Object%u SET Flags=Flags%c? WHERE ObjectId IN(?" ); + _LIT( KUpdatePendingMiddle, ",?" ); + _LIT( KUpdatePendingEnd, ");" ); + + CMdSSqLiteConnection& db = MMdSDbConnectionPool::GetDefaultDBL(); + + const TInt objectIdsCount = aObjectIds.Count(); + + RClauseBuffer commonClause(*this, KUpdatePending().Length() + KMaxUintValueLength + + KUpdatePendingMiddle().Length() * (objectIdsCount - 1) + + KUpdatePendingEnd().Length() ); + CleanupClosePushL( commonClause ); + CMdsClauseBuffer& buf = commonClause.BufferL(); + + const TChar KSetUpdateFlag = '|'; + const TChar KResetUpdateFlag = '&'; + + TChar flagUpdate = KSetUpdateFlag; // set flag + TUint32 objectFlag = EMdeObjectFlagPending; + + if( aReset ) + { + flagUpdate = KResetUpdateFlag; // reset flag + objectFlag = ~objectFlag; // not pending flag + } + + buf.BufferL().Format( KUpdatePending, KDefaultNamespaceDefId, (TUint)flagUpdate ); + + RRowData var; + CleanupClosePushL( var ); + + var.ReserveL( 1 + objectIdsCount ); + + var.AppendL( TColumn( objectFlag ) ); + + var.AppendL( aObjectIds[0] ); + for (TInt i = 1; i < objectIdsCount; ++i) + { + buf.AppendL( KUpdatePendingMiddle ); + var.AppendL( aObjectIds[i] ); + } + buf.AppendL( KUpdatePendingEnd ); + + db.ExecuteL( buf.ConstBufferL(), var ); + + CleanupStack::PopAndDestroy( 2, &commonClause ); // var, commonClause + } + +TInt CMdSSqlObjectManipulate::GetPendingCountL(TDefId aObjectDefId) + { + _LIT( KGetPendingCount, "SELECT count(*) FROM Object%u WHERE Flags&? AND NOT Flags&?" ); + _LIT( KGetPendingCountObjectDefId, " AND ObjectDefId=?" ); + _LIT( KGetPendingCountEnd, ";" ); + + CMdSSqLiteConnection& db = MMdSDbConnectionPool::GetDefaultDBL(); + + TInt bufferSize = KGetPendingCount().Length() + KMaxUintValueLength + + KGetPendingCountEnd().Length(); + + if( aObjectDefId != KNoDefId ) + { + bufferSize += KGetPendingCountObjectDefId().Length(); + } + + RClauseBuffer commonClause( *this, bufferSize ); + CleanupClosePushL( commonClause ); + CMdsClauseBuffer& buf = commonClause.BufferL(); + buf.BufferL().Format( KGetPendingCount, KDefaultNamespaceDefId ); + + TInt varReservation = 2; + + if( aObjectDefId != KNoDefId ) + { + buf.AppendL( KGetPendingCountObjectDefId ); + ++varReservation; + } + + buf.AppendL( KGetPendingCountEnd ); + + RRowData var; + CleanupClosePushL( var ); + + var.ReserveL( varReservation ); + + var.AppendL( TColumn( EMdeObjectFlagPending ) ); + var.AppendL( TColumn( EMdEObjectFlagNotPresent | EMdEObjectFlagRemoved | + EMdEObjectFlagPlaceholder | EMdEObjectFlagStartUpNotPresent ) ); + + if( aObjectDefId != KNoDefId ) + { + var.AppendL( TColumn( aObjectDefId ) ); + } + + RMdsStatement getQuery; + CleanupClosePushL( getQuery ); + + db.ExecuteQueryL( buf.ConstBufferL(), getQuery, var ); + + var.Free(); + var.Reset(); + + TUint32 count = 0; + + var.AppendL( TColumn( count ) ); + + if ( db.NextRowL( getQuery, var ) ) + { + var.Column(0).Get( count ); + } + + CleanupStack::PopAndDestroy( 2, &var ); // getQuery, varSearch + CleanupStack::PopAndDestroy( &commonClause ); + + return count; + } + +TInt CMdSSqlObjectManipulate::GetPendingL(TDefId aObjectDefId, + TInt aBufferSize, RArray& aObjectIds) + { + _LIT( KGetPending, "SELECT ObjectId FROM Object%u WHERE Flags&? AND NOT Flags&?" ); + _LIT( KGetPendingObjectDefId, " AND ObjectDefId=?" ); + _LIT( KGetPendingEnd, " LIMIT ?;" ); + + CMdSSqLiteConnection& db = MMdSDbConnectionPool::GetDefaultDBL(); + + TInt bufferSize = KGetPending().Length() + KMaxUintValueLength + + KGetPendingEnd().Length(); + + if( aObjectDefId != KNoDefId ) + { + bufferSize += KGetPendingObjectDefId().Length(); + } + + RClauseBuffer commonClause( *this, bufferSize ); + CleanupClosePushL( commonClause ); + CMdsClauseBuffer& buf = commonClause.BufferL(); + buf.BufferL().Format( KGetPending, KDefaultNamespaceDefId ); + + TInt varReservation = 3; + + if( aObjectDefId != KNoDefId ) + { + buf.AppendL( KGetPendingObjectDefId ); + ++varReservation; + } + + buf.AppendL( KGetPendingEnd ); + + RRowData var; + CleanupClosePushL( var ); + + var.ReserveL( varReservation ); + + var.AppendL( TColumn( EMdeObjectFlagPending ) ); + var.AppendL( TColumn( EMdEObjectFlagNotPresent | EMdEObjectFlagRemoved | + EMdEObjectFlagPlaceholder | EMdEObjectFlagStartUpNotPresent ) ); + + if( aObjectDefId != KNoDefId ) + { + var.AppendL( TColumn( aObjectDefId ) ); + } + + // get as much as possible to buffer and check if there is more than that + var.AppendL( TColumn( aBufferSize + 1 ) ); + + RMdsStatement getQuery; + CleanupClosePushL( getQuery ); + + db.ExecuteQueryL( buf.ConstBufferL(), getQuery, var ); + + var.Free(); + var.Reset(); + + TItemId objectId = 0; + + var.AppendL( TColumn( objectId ) ); + + TInt extraRows = 0; + + while( db.NextRowL( getQuery, var ) ) + { + var.Column(0).Get( objectId ); + + if( aObjectIds.Count() < aBufferSize ) + { + aObjectIds.Append( objectId ); + } + else + { + extraRows = 1; + break; + } + } + + CleanupStack::PopAndDestroy( 2, &var ); // getQuery, varSearch + CleanupStack::PopAndDestroy( &commonClause ); + + return extraRows; + } + +TBool CMdSSqlObjectManipulate::DoGarbageCollectionL() + { + _LIT( KDeleteObject, "DELETE FROM Object%u WHERE Flags&?;" ); + _LIT( KUpdateDeleteObject, "UPDATE Object%u SET Flags=Flags|? WHERE Flags&?;" ); + _LIT( KDeleteRelations, "DELETE FROM Relations%u WHERE Flags&?;" ); + _LIT( KUpdateDeleteRelations, "UPDATE Relations%u SET Flags=Flags|? WHERE Flags&?;" ); + _LIT( KUpdateDeleteContextObjects, "UPDATE Object%u SET Flags=Flags|? WHERE ObjectId IN ( SELECT ObjectId FROM Object%u AS O WHERE Flags&? AND UsageCount=0 AND ( SELECT count(*) FROM Relations%u WHERE NOT Flags&? AND ( LeftObjectId = O.ObjectId OR RightObjectId = O.ObjectId ) )= 0 );" ); + _LIT( KDeleteWordFromTextSearchDict, "DELETE FROM TextSearchDictionary%u WHERE NOT EXISTS(SELECT WordId FROM TextSearch%u WHERE WordId = TextSearchDictionary%u.WordId);"); + + + RClauseBuffer commonClauseOne(*this, KUpdateDeleteContextObjects().Length() + 3 * KMaxUintValueLength); + CleanupClosePushL( commonClauseOne ); + CMdsClauseBuffer& buffer = commonClauseOne.BufferL(); + + RRowData rowDataDel; + CleanupClosePushL( rowDataDel ); + rowDataDel.AppendL( TColumn( EMdEObjectFlagGarbage ) ); + + RRowData rowDataUpd; + CleanupClosePushL( rowDataUpd ); + rowDataUpd.AppendL( TColumn( EMdEObjectFlagGarbage ) ); + rowDataUpd.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + + RRowData rowDataDelRel; + CleanupClosePushL( rowDataDelRel ); + rowDataDelRel.AppendL( TColumn( EMdERelationFlagGarbageDeleted ) ); + + RRowData rowDataUpdRel; + CleanupClosePushL( rowDataUpdRel ); + rowDataUpdRel.AppendL( TColumn( EMdERelationFlagGarbageDeleted ) ); + rowDataUpdRel.AppendL( TColumn( EMdERelationFlagDeleted ) ); + + RRowData rowDataDelContext; + CleanupClosePushL( rowDataDelContext ); + rowDataDelContext.AppendL( TColumn( EMdEObjectFlagRemoved ) ); + rowDataDelContext.AppendL( TColumn( EMdEObjectFlagContext ) ); + rowDataDelContext.AppendL( TColumn( EMdERelationFlagDeleted ) ); + + RRowData emptyRow; + CleanupClosePushL( emptyRow ); + + const RPointerArray& namespaceDefs = + iSchema.NamespaceDefs(); + + CMdSSqLiteConnection& connection = MMdSDbConnectionPool::GetDefaultDBL(); + TInt deleteObjectResult; + TInt updateResult = 0; + + const TInt count = namespaceDefs.Count(); + + for( TInt i = 0; i < count; ++i ) + { + const TDefId nmspId = namespaceDefs[i]->GetId(); + + // deleting objects + buffer.BufferL().Format( KDeleteObject, nmspId ); + User::LeaveIfError( deleteObjectResult = connection.ExecuteL( + buffer.ConstBufferL(), rowDataDel ) ); + + buffer.BufferL().Format( KUpdateDeleteObject, nmspId ); + User::LeaveIfError( updateResult += connection.ExecuteL( + buffer.ConstBufferL(), rowDataUpd ) ); + + // deleting relations + buffer.BufferL().Format( KDeleteRelations, nmspId ); + User::LeaveIfError( connection.ExecuteL( + buffer.ConstBufferL(), rowDataDelRel ) ); + + buffer.BufferL().Format( KUpdateDeleteRelations, nmspId ); + User::LeaveIfError( updateResult += connection.ExecuteL( + buffer.ConstBufferL(), rowDataUpdRel ) ); + + // deleting context objects + buffer.BufferL().Format( KUpdateDeleteContextObjects, nmspId, nmspId, nmspId ); + User::LeaveIfError( updateResult += connection.ExecuteL( + buffer.ConstBufferL(), rowDataDelContext ) ); + + // deleting words from text search dictionary + if ( deleteObjectResult > 0 ) + { + buffer.BufferL().Format( KDeleteWordFromTextSearchDict, nmspId, nmspId, + nmspId ); + User::LeaveIfError( connection.ExecuteL( + buffer.ConstBufferL(), emptyRow ) ); + } + } + + // empryRow, rowDataDelContext, rowDataUpdRel, rowDataDelRel, rowDataUpd, + // rowDataDel, commonClauseOne + CleanupStack::PopAndDestroy( 7, &commonClauseOne ); + + return updateResult != 0; + } + +CMdSSqlObjectManipulate::RClauseBuffer::RClauseBuffer( CMdSSqlObjectManipulate& aSOM, TInt aSize ) + : iBuffers( aSOM.iBuffers ), iBuffer( NULL ), iNr( -1 ), iSize( aSize ) + { + // search for available buffer + // or create new one + for (TInt i = 0; i < iBuffers.Count(); ++i) + { + if (!iBuffers[i].iLock) + { + iBuffers[i].iLock = ETrue; + iBuffer = iBuffers[i].iBuffer; + iNr = i; + TRAP_IGNORE( iBuffer->ReserveSpaceL(aSize) ); + TRAP_IGNORE( iBuffer->BufferL().Zero() ); + return; + } + } + } + +CMdsClauseBuffer& CMdSSqlObjectManipulate::RClauseBuffer::BufferL() + { + if ( iNr < 0 && !iBuffer ) + { + iBuffer = CMdsClauseBuffer::NewL( iSize ); + } + return *iBuffer; + } + +void CMdSSqlObjectManipulate::RClauseBuffer::Close() + { + if ( iNr < 0 ) + { + __ASSERT_DEBUG( iBuffer, _L("RClauseBuffer::Close()") ); + if ( iBuffer ) + { + delete iBuffer; + iBuffer = NULL; + } + } + else + { + iBuffers[iNr].iLock = EFalse; + iBuffer = NULL; + } + }