--- /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 <e32math.h>
+
+/** 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<KMaxQuidLength> 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<TItemId>& 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<TItemId>& 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<TItemId>& 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<TItemId>& 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<TItemId>* 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<TItemId>& 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<TItemId>& aRemoveIds, RArray<TItemId>& aObjectIds,
+ RArray<TItemId>& aRelationIds, RArray<TItemId>& /*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<TItemId>( 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<TItemId>& aIdArray,
+ RArray<TItemId>& aRelationIds, RArray<TItemId>& aEventIds )
+ {
+ if ( !iNamespaceDef )
+ {
+ User::Leave( KErrMdEUnknownNamespaceDef );
+ }
+
+ RArray<TItemId> 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<TItemId>& aIdArray,
+ RArray<TItemId>& aRelationIds, RArray<TItemId>& aEventIds )
+ {
+ if ( !iNamespaceDef )
+ {
+ User::Leave( KErrMdEUnknownNamespaceDef );
+ }
+
+ RArray<TItemId> 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<TItemId>& 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<TItemId>& 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<TItemId>& aRemovedRelations,
+ const RArray<TItemId>& 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<TItemId>& 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<TItemId>& 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<CMdsNamespaceDef>& 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;
+ }
+ }