--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/message_store/server/src/ContainerStoreSortingTable.cpp Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1247 @@
+/*
+* Copyright (c) 2006 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: Container store sorting table implementation.
+*
+*/
+
+
+
+#include "ContainerStoreSortingTable.h"
+#include "MsgStoreTypes.h"
+#include "MessageStoreClientServer.h"
+#include "ContainerStoreDefs.h"
+#include "MsgStoreSortResultRowSet.h"
+#include "MsgStoreStringSortResultRowSet.h"
+#include "ContainerStoreUtils.h"
+#include "ContainerStoreEncryption.h"
+#include "MsgStoreInMemorySortRowSet.h"
+
+_LIT( KSelect, "SELECT " );
+_LIT( KDelete, "DELETE " );
+_LIT( KFrom, " FROM " );
+_LIT( KWhere, " WHERE " );
+_LIT( KEquals, " = " );
+_LIT( KOrderBy, " ORDER BY ");
+_LIT( KComma, ", " );
+_LIT( KAsc, " ASC" );
+_LIT( KDesc, " DESC" );
+_LIT( KStar, "* " );
+
+const TUint KQuerryBufSize = 200;
+const TUint KQuerrySizeSmall = 60;
+
+enum TMsgStorePriorityScore
+ {
+ EPriorityScoreLow = -10,
+ EPriorityScoreNormal = 0,
+ EPriorityScoreHigh = 10
+ };
+
+ enum TMsgStoreReadScore
+ {
+ EReadScoreUnread = 0,
+ EReadScoreRead = 1,
+ EReadScoreReadLocal = 2,
+ EReadScoreReadBoth = 3
+ };
+
+ enum TMsgStoreFlagStatusScore
+ {
+ EFlagStatusScoreNone = 0,
+ EFlagStatusScoreFollowUpComplete = 10,
+ EFlagStatusScoreFollowUp = 20
+ };
+
+
+// ==================================
+// CLASS: CContainerStoreSortingTable
+// ==================================
+// ==========================================================================
+// FUNCTION: OpenL
+// ==========================================================================
+CContainerStoreSortingTable* CContainerStoreSortingTable::OpenL( CContainerStoreUtils& aUtils,
+ CContainerStoreEncryption& aEncryption,
+ MSortingTableObserver& aObserver )
+ {
+ CContainerStoreSortingTable* self = new(ELeave) CContainerStoreSortingTable( aUtils, aEncryption, aObserver );
+ CleanupStack::PushL( self );
+ self->OpenTableL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ==========================================================================
+// FUNCTION: CreateL
+// ==========================================================================
+CContainerStoreSortingTable* CContainerStoreSortingTable::CreateL( CContainerStoreUtils& aUtils,
+ CContainerStoreEncryption& aEncryption,
+ MSortingTableObserver& aObserver )
+ {
+ CContainerStoreSortingTable* self = new(ELeave) CContainerStoreSortingTable( aUtils, aEncryption, aObserver );
+ CleanupStack::PushL( self );
+ self->CreateTableL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ==========================================================================
+// FUNCTION: Constructor
+// ==========================================================================
+CContainerStoreSortingTable::CContainerStoreSortingTable( CContainerStoreUtils& aUtils,
+ CContainerStoreEncryption& aEncryption,
+ MSortingTableObserver& aObserver )
+: CContainerStoreTable( aUtils ), iEncryption( aEncryption ), iObserver( aObserver )
+ {
+ __LOG_CONSTRUCT( "msg", "CContainerStoreSortingTable" )
+ __LOG_CLOSE_BETWEEN_WRITES
+ } // end constructor
+
+// ==========================================================================
+// FUNCTION: Destructor
+// ==========================================================================
+CContainerStoreSortingTable::~CContainerStoreSortingTable()
+ {
+ iUtils.CloseTable( iTable );
+ iEncryptedBuffer.Close();
+ __LOG_DESTRUCT
+ } // end destructor
+
+// ==========================================================================
+// FUNCTION: OpenTableL
+// ==========================================================================
+void CContainerStoreSortingTable::OpenTableL()
+ {
+ __LOG_ENTER( "OpenTableL" )
+
+ iUtils.OpenTableL( iTable, KSortingTableName );
+
+ // Get the column numbers for the containers table.
+ CDbColSet* colSet = iTable.ColSetL();
+ CleanupStack::PushL( colSet );
+
+ iMessageIdColNum = colSet->ColNo( KSortingTableMessageIdCol );
+ iFolderIdColNum = colSet->ColNo( KSortingTableFolderIdCol );
+ iMailBoxIdColNum = colSet->ColNo( KSortingTableMailBoxIdCol );
+ iReceivedDateColNum = colSet->ColNo( KSortingTableReceivedDateCol );
+ iReadUnreadColNum = colSet->ColNo( KSortingTableReadUnreadCol );
+ iPriotiryColNum = colSet->ColNo( KSortingTablePriorityCol );
+ iFlagStatusColNum = colSet->ColNo( KSortingTableFlagStatusCol );
+ iSizeColNum = colSet->ColNo( KSortingTableSizeCol );
+ iAttachmentFlagColNum = colSet->ColNo( KSortingTableAttachmentFlagCol );
+ iFromColNum = colSet->ColNo( KSortingTableFromCol );
+ iToColNum = colSet->ColNo( KSortingTableToCol );
+ iSubjectColNum = colSet->ColNo( KSortingTableSubjectCol );
+ iIsEncryptedColNum = colSet->ColNo( KSortingTableIsEncryptedCol );
+
+ CleanupStack::PopAndDestroy( colSet );
+
+ // Set the table's index to the ID index.
+ User::LeaveIfError( iTable.SetIndex( KSortingTableMessageIdIndex ) );
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: CreateTableL
+// ==========================================================================
+void CContainerStoreSortingTable::CreateTableL()
+ {
+ __LOG_ENTER( "CreateTableL" )
+
+ // Create table columns
+ CDbColSet* colSet = CDbColSet::NewLC();
+
+ TDbCol msgIdCol( KSortingTableMessageIdCol, EDbColUint32 );
+ colSet->AddL( msgIdCol );
+
+ TDbCol folderIdCol( KSortingTableFolderIdCol, EDbColUint32 );
+ colSet->AddL( folderIdCol );
+
+ TDbCol mailboxIdCol( KSortingTableMailBoxIdCol, EDbColUint32 );
+ colSet->AddL( mailboxIdCol );
+
+ TDbCol receivedDateCol( KSortingTableReceivedDateCol, EDbColInt64 );
+ colSet->AddL( receivedDateCol );
+
+ TDbCol readUnreadCol( KSortingTableReadUnreadCol, EDbColInt8 );
+ colSet->AddL( readUnreadCol );
+
+ TDbCol priorityCol( KSortingTablePriorityCol, EDbColInt8 );
+ colSet->AddL( priorityCol );
+
+ TDbCol flagStatusCol( KSortingTableFlagStatusCol, EDbColInt8 );
+ colSet->AddL( flagStatusCol );
+
+ TDbCol sizeCol( KSortingTableSizeCol, EDbColUint32 );
+ colSet->AddL( sizeCol );
+
+ TDbCol attCol( KSortingTableAttachmentFlagCol, EDbColInt8 );
+ colSet->AddL( attCol );
+
+ TDbCol fromCol( KSortingTableFromCol, EDbColLongBinary );
+ colSet->AddL( fromCol );
+
+ TDbCol toCol( KSortingTableToCol, EDbColLongBinary );
+ colSet->AddL( toCol );
+
+ TDbCol subjectCol( KSortingTableSubjectCol, EDbColLongBinary );
+ colSet->AddL( subjectCol );
+
+ TDbCol encryptedCol( KSortingTableIsEncryptedCol, EDbColUint8 );
+ colSet->AddL( encryptedCol );
+
+ // Create table.
+ iUtils.CreateTableL( KSortingTableName, *colSet );
+
+ CleanupStack::PopAndDestroy( colSet );
+
+ // Create index for every column except for mailBoxId
+ CreateIndexL( KSortingTableName, KSortingTableMessageIdIndex, KSortingTableMessageIdCol );
+ CreateIndexL( KSortingTableName, KSortingTableFolderIdIndex, KSortingTableFolderIdCol );
+ CreateIndexL( KSortingTableName, KSortingTableMailBoxIdIndex, KSortingTableMailBoxIdCol );
+ CreateIndexL( KSortingTableName, KSortingTableReceivedDateIndex, KSortingTableReceivedDateCol );
+ CreateIndexL( KSortingTableName, KSortingTableReadUnreadIndex, KSortingTableReadUnreadCol, KSortingTableReceivedDateCol );
+ CreateIndexL( KSortingTableName, KSortingTablePriorityIndex, KSortingTablePriorityCol, KSortingTableReceivedDateCol );
+ CreateIndexL( KSortingTableName, KSortingTableFlagStatusIndex, KSortingTableFlagStatusCol, KSortingTableReceivedDateCol );
+ CreateIndexL( KSortingTableName, KSortingTableSizeIndex, KSortingTableSizeCol, KSortingTableReceivedDateCol );
+ CreateIndexL( KSortingTableName, KSortingTableAttachmentFlagIndex, KSortingTableAttachmentFlagCol, KSortingTableReceivedDateCol );
+
+ OpenTableL();
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: AddMessageL
+// ==========================================================================
+void CContainerStoreSortingTable::AddMessageL( TContainerId aMessageId,
+ TContainerId aFolderId,
+ TContainerId aMailboxId,
+ RMsgStoreSortableFields& aSortableFields )
+ {
+ __LOG_ENTER_SUPPRESS( "AddMessageL" )
+
+ __LOG_WRITE8_FORMAT3_DEBUG3( "msgId=%x, folderId=%x, mailBoxId=%x", aMessageId, aFolderId, aMailboxId )
+
+ iTable.LastL();
+
+ InsertRowLC();
+
+ iTable.SetColL( iMessageIdColNum, aMessageId );
+ iTable.SetColL( iFolderIdColNum, aFolderId );
+ iTable.SetColL( iMailBoxIdColNum, aMailboxId );
+ iTable.SetColL( iIsEncryptedColNum, static_cast<TUint8>( iEncryption.IsEncryptionOn() ) );
+
+ //write the rest of the fields
+ WriteFieldsL( aSortableFields );
+
+ PutRowUpdatesL();
+
+ //Notify the observer
+ iObserver.MessageUpdate( aMessageId,
+ aFolderId,
+ EMsgStoreAdd,
+ iFieldsChanged,
+ aSortableFields.iFrom,
+ aSortableFields.iTo,
+ aSortableFields.iSubject,
+ aSortableFields.iReceivedDate );
+ }
+
+// ==========================================================================
+// FUNCTION: DeleteMessageL
+// ==========================================================================
+void CContainerStoreSortingTable::DeleteMessageL( TContainerId aMessageId )
+ {
+ __LOG_ENTER_SUPPRESS( "DeleteMessageL" )
+
+ __LOG_WRITE8_FORMAT1_DEBUG3( "msgId=%x", aMessageId )
+
+ SeekL( aMessageId );
+ iTable.GetL();
+ TContainerId folderId = iTable.ColUint32( iFolderIdColNum );
+
+ iTable.DeleteL();
+
+ //Notify the observer
+ iObserver.MessageUpdate( aMessageId, folderId, EMsgStoreDelete );
+ }
+
+// ==========================================================================
+// FUNCTION: DeleteMessagesByFolderIdL
+// ==========================================================================
+void CContainerStoreSortingTable::DeleteMessagesByFolderIdL( TContainerId aFolderId )
+ {
+ __LOG_ENTER_SUPPRESS( "DeleteMessagesByFolderIdL" )
+ __LOG_WRITE8_FORMAT1_DEBUG3( "aFolderId=%x", aFolderId )
+
+ TBuf<KQuerryBufSize> queryString;
+ queryString.Copy( KDelete );
+ queryString.Append( KFrom );
+ queryString.Append( KSortingTableName );
+ queryString.Append( KWhere );
+ queryString.Append( KSortingTableFolderIdCol );
+ queryString.Append( KEquals );
+ queryString.AppendNum( aFolderId );
+
+ iUtils.Execute( queryString );
+
+ //Notify the observer
+ iObserver.FolderDeleted( aFolderId );
+ }
+
+// ==========================================================================
+// FUNCTION: DeleteMessagesByMailBoxIdL
+// ==========================================================================
+void CContainerStoreSortingTable::DeleteMessagesByMailBoxIdL( TContainerId aMailBoxId )
+ {
+ __LOG_ENTER_SUPPRESS( "DeleteMessagesByMailBoxIdL" )
+ __LOG_WRITE8_FORMAT1_DEBUG3( "aMailBoxId=%x", aMailBoxId )
+
+ TBuf<KQuerryBufSize> queryString;
+ queryString.Copy( KDelete );
+ queryString.Append( KFrom );
+ queryString.Append( KSortingTableName );
+ queryString.Append( KWhere );
+ queryString.Append( KSortingTableMailBoxIdCol );
+ queryString.Append( KEquals );
+ queryString.AppendNum( aMailBoxId );
+
+ iUtils.Execute( queryString );
+
+ //Notify the observer
+ iObserver.MailBoxDeleted( aMailBoxId );
+ }
+
+// ==========================================================================
+// FUNCTION: UpdateMessageL
+// ==========================================================================
+void CContainerStoreSortingTable::UpdateMessageL( TContainerId aMessageId,
+ RMsgStoreSortableFields& aSortableFields )
+ {
+ __LOG_ENTER_SUPPRESS( "UpdateMessageL" )
+
+ __LOG_WRITE8_FORMAT4_DEBUG3( "msgId=%x, flags=%x, ssize=%d csize=%d", aMessageId,
+ aSortableFields.iFlags,
+ aSortableFields.iSizeOnServer,
+ aSortableFields.iSizeOnClient )
+
+ SeekL( aMessageId );
+
+ iTable.GetL();
+ TContainerId folderId = iTable.ColUint32( iFolderIdColNum );
+
+ PrepareRowForUpdateLC();
+
+ WriteFieldsL( aSortableFields, EFalse );
+
+ PutRowUpdatesL();
+
+ if ( iFieldsChanged > 0 )
+ {
+ iObserver.MessageUpdate( aMessageId,
+ folderId,
+ EMsgStoreUpdateProperties,
+ iFieldsChanged,
+ aSortableFields.iFrom,
+ aSortableFields.iTo,
+ aSortableFields.iSubject,
+ aSortableFields.iReceivedDate );
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: UpdateMessageFolderL
+// ==========================================================================
+void CContainerStoreSortingTable::UpdateMessageFolderL( TContainerId aMessageId, TContainerId aNewFolderId )
+ {
+ __LOG_ENTER_SUPPRESS( "UpdateMessageFolderL" )
+
+ __LOG_WRITE8_FORMAT2_DEBUG3( "msgId=%x, aNewFolder=%x", aMessageId, aNewFolderId )
+
+ SeekL( aMessageId );
+ iTable.GetL();
+
+ TContainerId oldFolderId = iTable.ColUint32( iFolderIdColNum );
+
+ if ( oldFolderId != aNewFolderId )
+ {
+
+ PrepareRowForUpdateLC();
+
+ iTable.SetColL( iFolderIdColNum, aNewFolderId );
+
+ PutRowUpdatesL();
+
+ //send a notification for delete from old folder
+ iObserver.MessageUpdate( aMessageId, oldFolderId, EMsgStoreDelete );
+
+ //send a notification for new message to the new folder
+ RBuf from;
+ CleanupClosePushL( from );
+ ReadStringFieldL( iTable, iFromColNum, from );
+
+ RBuf to;
+ CleanupClosePushL( to );
+ ReadStringFieldL( iTable, iToColNum, to );
+
+ RBuf subject;
+ CleanupClosePushL( subject );
+ ReadStringFieldL( iTable, iSubjectColNum, subject );
+
+ TInt64 date = iTable.ColInt64( iReceivedDateColNum );
+
+ iObserver.MessageUpdate( aMessageId, aNewFolderId, EMsgStoreAdd, 0, from, to, subject, date );
+
+ CleanupStack::PopAndDestroy( &subject );
+ CleanupStack::PopAndDestroy( &to );
+ CleanupStack::PopAndDestroy( &from );
+
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: SortL
+// ==========================================================================
+CMsgStoreSortResultRowSet* CContainerStoreSortingTable::SortL( const TMsgStoreSortCriteria& aSortCriteria, TBool aInMemorySort )
+ {
+ __LOG_ENTER_SUPPRESS( "SortL" )
+
+ CMsgStoreSortResultRowSet* result = NULL;
+
+ if ( aSortCriteria.iSortBy == EMsgStoreSortBySender ||
+ aSortCriteria.iSortBy == EMsgStoreSortByRecipient ||
+ aSortCriteria.iSortBy == EMsgStoreSortBySubject )
+ {
+ result = SortByStringFieldL( aSortCriteria );
+ }
+ else if ( aInMemorySort )
+ {
+ result = InMemorySortL( aSortCriteria );
+ }
+ else
+ {
+
+ TBuf<KQuerryBufSize> queryString;
+ queryString.Copy( KSelect );
+ queryString.Append( KStar );
+ queryString.Append( KFrom );
+ queryString.Append( KSortingTableName );
+ queryString.Append( KWhere );
+ queryString.Append( KSortingTableFolderIdCol );
+ queryString.Append( KEquals );
+ queryString.AppendNum( aSortCriteria.iFolderId );
+ queryString.Append( KOrderBy );
+
+ switch( aSortCriteria.iSortBy )
+ {
+ case EMsgStoreSortByReceivedDate:
+ queryString.Append( KSortingTableReceivedDateCol );
+ break;
+
+ case EMsgStoreSortByPriority:
+ queryString.Append( KSortingTablePriorityCol );
+ break;
+
+ case EMsgStoreSortByFlagStatus:
+ queryString.Append( KSortingTableFlagStatusCol );
+ break;
+
+ case EMsgStoreSortByUnRead:
+ queryString.Append( KSortingTableReadUnreadCol );
+ break;
+
+ case EMsgStoreSortBySize:
+ queryString.Append( KSortingTableSizeCol );
+ break;
+
+ case EMsgStoreSortByAttachment:
+ queryString.Append( KSortingTableAttachmentFlagCol );
+ break;
+
+ default:
+ User::Leave( KErrNotSupported );
+ break;
+ }
+
+ //add the sort order
+ AppendSortOrder( queryString, aSortCriteria.iSortOrder );
+
+ //add the secondary sort field if primary is not received date
+ if ( aSortCriteria.iSortBy != EMsgStoreSortByReceivedDate )
+ {
+ queryString.Append( KComma );
+ queryString.Append( KSortingTableReceivedDateCol );
+ AppendSortOrder( queryString, aSortCriteria.iSecondarySortOrder );
+ }
+
+ __LOG_WRITE_FORMAT1_INFO( "query=%S", &queryString );
+
+ result = CMsgStoreSortResultRowSet::NewL( aSortCriteria,
+ iMessageIdColNum,
+ iReceivedDateColNum,
+ iReadUnreadColNum,
+ iPriotiryColNum,
+ iFlagStatusColNum,
+ iSizeColNum,
+ iAttachmentFlagColNum );
+ CleanupStack::PushL( result );
+
+ iUtils.PopulateViewL( result->DbView(), queryString );
+
+ __LOG_WRITE_FORMAT1_INFO( "rowCounts=%d", result->DbView().CountL() );
+
+ CleanupStack::Pop( result );
+ }
+
+ return result;
+ }
+
+
+// ==========================================================================
+// FUNCTION: SortByStringFieldL
+// ==========================================================================
+CMsgStoreStringSortResultRowSet* CContainerStoreSortingTable::SortByStringFieldL( const TMsgStoreSortCriteria& aSortCriteria )
+ {
+ __LOG_ENTER_SUPPRESS( "SortByStringFieldL" )
+
+ CMsgStoreStringSortResultRowSet* result = CMsgStoreStringSortResultRowSet::NewL( aSortCriteria, *this );
+ CleanupStack::PushL( result );
+ TBuf<KQuerryBufSize> queryString;
+ queryString.Copy( KSelect );
+ queryString.Append( KStar );
+ queryString.Append( KFrom );
+ queryString.Append( KSortingTableName );
+ queryString.Append( KWhere );
+ queryString.Append( KSortingTableFolderIdCol );
+ queryString.Append( KEquals );
+ queryString.AppendNum( aSortCriteria.iFolderId );
+
+ iUtils.PopulateViewL( result->DbView(), queryString );
+
+ ReEvaluateStringViewL( *result, aSortCriteria.iSortBy );
+
+ result->SortL();
+
+ CleanupStack::Pop( result );
+
+ return result;
+ }
+
+// ==========================================================================
+// FUNCTION: InMemorySortL
+// ==========================================================================
+CMsgStoreInMemorySortRowSet* CContainerStoreSortingTable::InMemorySortL( const TMsgStoreSortCriteria& aSortCriteria )
+ {
+ __LOG_ENTER_SUPPRESS( "InMemorySortL" )
+
+ CMsgStoreInMemorySortRowSet* result = CMsgStoreInMemorySortRowSet::NewL( aSortCriteria, *this );
+ CleanupStack::PushL( result );
+
+ TBuf<KQuerryBufSize> queryString;
+ queryString.Copy( KSelect );
+ queryString.Append( KStar );
+ queryString.Append( KFrom );
+ queryString.Append( KSortingTableName );
+ queryString.Append( KWhere );
+ queryString.Append( KSortingTableFolderIdCol );
+ queryString.Append( KEquals );
+ queryString.AppendNum( aSortCriteria.iFolderId );
+
+ iUtils.PopulateViewL( result->DbView(), queryString );
+
+ ReEvaluateInMemoryViewL( *result, aSortCriteria.iSortBy );
+
+ result->SortL();
+
+ CleanupStack::Pop( result );
+
+ return result;
+ }
+
+
+// ==========================================================================
+// FUNCTION: ReEvaluateStringViewL
+// ==========================================================================
+void CContainerStoreSortingTable::ReEvaluateStringViewL( CMsgStoreStringSortResultRowSet& aResult, TMsgStoreSortByField aSortBy )
+ {
+ __LOG_ENTER( "ReEvaluateStringViewL" )
+
+ iUtils.SuspendCompactionLC();
+
+ TInt stringColNum = GetColumnNumL( aSortBy );
+
+ RDbView& view = aResult.DbView();
+
+ TBool found = view.FirstL();
+
+ CStringRow* reuseRow = NULL;
+
+ RBuf stringVal;
+ CleanupClosePushL( stringVal );
+
+ while( found )
+ {
+ view.GetL();
+
+ //get the message id, received date, and the desired string
+ TContainerId msgId = view.ColUint32( iMessageIdColNum );
+ TInt64 receivedDate = view.ColInt64( iReceivedDateColNum );
+
+ ReadStringFieldL( view, stringColNum, stringVal );
+
+ //To reduce memory fragmentation, we re-use the row object whenever possible
+ CStringRow* row;
+ if ( reuseRow )
+ {
+ row = reuseRow;
+ row->ResetL( msgId, receivedDate, stringVal );
+ CleanupStack::Pop( reuseRow );
+ }
+ else
+ {
+ row = CStringRow::NewL( msgId, receivedDate, stringVal );
+ }
+
+ reuseRow = aResult.AppendL( row );
+
+ if ( reuseRow )
+ {
+ CleanupStack::PushL( reuseRow );
+ }
+
+ found = view.NextL();
+
+ if ( !found && reuseRow )
+ {
+ //no more rows, delete the reuseRow
+ CleanupStack::PopAndDestroy( reuseRow );
+ }
+
+ } // end while
+
+ CleanupStack::PopAndDestroy( &stringVal );
+
+ iUtils.ResumeCompaction();
+
+ __LOG_EXIT
+ }
+
+// ==========================================================================
+// FUNCTION: ReEvaluateInMemoryViewL
+// ==========================================================================
+void CContainerStoreSortingTable::ReEvaluateInMemoryViewL( CMsgStoreInMemorySortRowSet& aResult, TMsgStoreSortByField aSortBy )
+ {
+ __LOG_ENTER( "ReEvaluateInMemoryViewL" )
+
+ iUtils.SuspendCompactionLC();
+
+ RDbView& view = aResult.DbView();
+ TBool found = view.FirstL();
+
+ while( found )
+ {
+ view.GetL();
+
+ //get the message id, received date, and the desired string
+ TContainerId msgId = view.ColUint32( iMessageIdColNum );
+ TInt64 receivedDate = view.ColInt64( iReceivedDateColNum );
+
+ TInt32 value = GetIntValue( view, aSortBy );
+
+ CIntegerRow* row = new(ELeave) CIntegerRow( msgId, receivedDate, value );
+ CleanupStack::PushL( row );
+
+ aResult.AppendL( row );
+
+ CleanupStack::Pop( row );
+
+ found = view.NextL();
+ } // end while
+
+ iUtils.ResumeCompaction();
+
+ __LOG_EXIT
+ }
+
+
+// ==========================================================================
+// FUNCTION: GetStringRowL
+// ==========================================================================
+CStringRow* CContainerStoreSortingTable::GetStringRowL( RDbView& aView, TContainerId aMessageId, TMsgStoreSortByField aSortBy )
+ {
+
+ TBuf<KQuerrySizeSmall> queryString;
+
+ queryString.Copy( KSortingTableMessageIdCol );
+ queryString.Append( KEquals );
+ queryString.AppendNum( aMessageId );
+
+ User::LeaveIfError( aView.FindL( RDbRowSet::EForwards, queryString ) );
+
+ TInt stringColNum = GetColumnNumL( aSortBy ) ;
+
+ aView.GetL();
+
+ //get the message id, received date, and the desired string
+ TContainerId msgId = aView.ColUint32( iMessageIdColNum );
+ TInt64 receivedDate = aView.ColInt64( iReceivedDateColNum );
+
+ RBuf stringVal;
+ CleanupClosePushL( stringVal );
+
+ ReadStringFieldL( aView, stringColNum, stringVal );
+
+ CStringRow* row = CStringRow::NewL( msgId, receivedDate, stringVal );
+
+ CleanupStack::PopAndDestroy( &stringVal );
+
+ return row;
+ }
+
+// ==========================================================================
+// FUNCTION: GetIntValue
+// ==========================================================================
+TInt32 CContainerStoreSortingTable::GetIntValue( RDbRowSet& aRowSet, TMsgStoreSortByField aSortBy )
+ {
+ TInt32 value = 0;
+ if ( aSortBy != EMsgStoreSortByReceivedDate )
+ {
+ switch( aSortBy )
+ {
+ case EMsgStoreSortByPriority:
+ value = aRowSet.ColInt8( iPriotiryColNum );
+ break;
+
+ case EMsgStoreSortByFlagStatus:
+ value = aRowSet.ColInt8( iFlagStatusColNum );
+ break;
+
+ case EMsgStoreSortByUnRead:
+ value = aRowSet.ColInt8( iReadUnreadColNum );
+ break;
+
+ case EMsgStoreSortBySize:
+ value = static_cast<TInt32>(aRowSet.ColUint32 ( iSizeColNum ));
+ break;
+
+ case EMsgStoreSortByAttachment:
+ value = aRowSet.ColInt8( iAttachmentFlagColNum );
+ break;
+
+ default:
+ break;
+ }
+ }
+ return value;
+ }
+
+// ==========================================================================
+// FUNCTION: GetIntValueL
+// ==========================================================================
+TInt32 CContainerStoreSortingTable::GetIntValueL( TMsgStoreSortByField aSortBy, TContainerId aMessageId )
+ {
+ TBuf<KQuerrySizeSmall> queryString;
+
+ queryString.Copy( KSortingTableMessageIdCol );
+ queryString.Append( KEquals );
+ queryString.AppendNum( aMessageId );
+
+ User::LeaveIfError( iTable.FindL( RDbRowSet::EForwards, queryString ) );
+
+ iTable.GetL();
+
+ return GetIntValue( iTable, aSortBy );
+ }
+
+// ==========================================================================
+// FUNCTION: SeekL
+// ==========================================================================
+void CContainerStoreSortingTable::SeekL( TContainerId aMessageId )
+ {
+ __LOG_ENTER_SUPPRESS("SeekL")
+ if ( !iTable.SeekL( aMessageId ) )
+ {
+ __LOG_WRITE8_FORMAT1_ERROR( "Message id %x not found", aMessageId )
+ User::Leave( KErrNotFound );
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: WriteFieldsL
+// ==========================================================================
+void CContainerStoreSortingTable::WriteFieldsL( RMsgStoreSortableFields& aSortableFields, TBool aIsNew )
+ {
+
+ iFieldsChanged = 0;
+
+ SetFlagIfChangedInt64( aSortableFields.iReceivedDate, iReceivedDateColNum, aIsNew, EMaskReceivedDate );
+ iTable.SetColL( iReceivedDateColNum, aSortableFields.iReceivedDate );
+
+ /******************************
+ * process the read/unread flag
+ *******************************/
+ TUint flags = aSortableFields.iFlags;
+
+ TInt8 readFlag = EReadScoreUnread;
+ if ( (flags & EMsgStoreFlag_Read) && (flags & EMsgStoreFlag_Read_Locally) )
+ {
+ readFlag = EReadScoreReadBoth;
+ }
+ else if ( flags & EMsgStoreFlag_Read )
+ {
+ readFlag = EReadScoreRead;
+ }
+ else if ( flags & EMsgStoreFlag_Read_Locally )
+ {
+ readFlag = EReadScoreReadLocal;
+ }
+
+ SetFlagIfChangedInt8( readFlag, iReadUnreadColNum, aIsNew, EMaskReadUnread );
+
+ //set the new value
+ iTable.SetColL( iReadUnreadColNum, readFlag );
+
+ /******************************
+ * process the priority flag
+ *******************************/
+ TInt8 priority = EPriorityScoreNormal;
+ if ( flags & EMsgStoreFlag_Important )
+ {
+ priority = EPriorityScoreHigh;
+ }
+ else if ( flags & EMsgStoreFlag_Low )
+ {
+ priority = EPriorityScoreLow;
+ }
+ SetFlagIfChangedInt8( priority, iPriotiryColNum, aIsNew, EMaskPriotiry );
+ iTable.SetColL( iPriotiryColNum, priority );
+
+ /******************************
+ * process the follow up flag
+ *******************************/
+ TInt8 flagStatus = EFlagStatusScoreNone;
+ if ( flags & EMsgStoreFlag_FollowUp )
+ {
+ flagStatus = EFlagStatusScoreFollowUp;
+ }
+ else if ( flags & EMsgStoreFlag_FollowUpComplete )
+ {
+ flagStatus = EFlagStatusScoreFollowUpComplete;
+ }
+ SetFlagIfChangedInt8( flagStatus, iFlagStatusColNum, aIsNew, EMaskFlagStatus );
+ iTable.SetColL( iFlagStatusColNum, flagStatus );
+
+ //process the attachment flag
+ TInt8 attachmentFalg = static_cast<TInt8>(flags & EMsgStoreFlag_Attachments);
+ SetFlagIfChangedInt8( attachmentFalg, iAttachmentFlagColNum, aIsNew, EMaskAttachmentFlag );
+ iTable.SetColL( iAttachmentFlagColNum, attachmentFalg );
+
+ //if size on server is available, use it, otherwise, use the size on client
+ TUint size = aSortableFields.iSizeOnServer > 0 ? aSortableFields.iSizeOnServer : aSortableFields.iSizeOnClient;
+ SetFlagIfChangedUint( size, iSizeColNum, aIsNew, EMaskSize );
+ iTable.SetColL( iSizeColNum, size );
+
+ //write the subject
+ WriteStringFieldL( iSubjectColNum, aSortableFields.iSubject, aIsNew, EMaskSubject );
+
+ //write the from
+ WriteStringFieldL( iFromColNum, aSortableFields.iFrom, aIsNew, EMaskFrom );
+
+ //write the to field
+ WriteStringFieldL( iToColNum, aSortableFields.iTo, aIsNew, EMaskTo );
+ }
+
+// ==========================================================================
+// FUNCTION: AppendSortOrder
+// ==========================================================================
+void CContainerStoreSortingTable::AppendSortOrder( TDes& aQuery, TMsgStoreSortOrder aOrder )
+ {
+ if ( aOrder == EMsgStoreSortDescending )
+ {
+ aQuery.Append( KDesc );
+ }
+ else
+ {
+ aQuery.Append( KAsc );
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: WriteStringFieldL
+// ==========================================================================
+void CContainerStoreSortingTable::WriteStringFieldL( TInt aColumnNum,
+ const TDesC& aString,
+ TBool aIsNew,
+ TSortableFieldsMasks aMask )
+ {
+ __LOG_ENTER_SUPPRESS( "WriteStringFieldL" )
+ __LOG_WRITE_FORMAT2_DEBUG3( "col=%d, string=%S", aColumnNum, &aString )
+
+ TBool changed = ETrue;
+
+ if ( !aIsNew )
+ {
+ RBuf curVal;
+ CleanupClosePushL( curVal );
+ ReadStringFieldL( iTable, aColumnNum, curVal );
+ if ( curVal == aString )
+ {
+ changed = EFalse;
+ }
+ CleanupStack::PopAndDestroy( &curVal );
+ }
+
+ if ( changed )
+ {
+ iFieldsChanged |= aMask;
+ }
+
+ if ( aString.Length() == 0 )
+ {
+ iTable.SetColNullL( aColumnNum );
+ }
+ else if ( changed )
+ {
+ WriteStringL( aColumnNum, aString, IsEncrypted( iTable ) );
+ } //end if
+ }
+
+// ==========================================================================
+// FUNCTION: WriteStringL
+// ==========================================================================
+void CContainerStoreSortingTable::WriteStringL( TInt aColumnNum,
+ const TDesC& aString,
+ TBool aIsRowEncrypted )
+ {
+
+ const TUint8* valuePtr8 = reinterpret_cast<const TUint8*>( aString.Ptr() );
+ TPtrC8 string8;
+ string8.Set( valuePtr8, aString.Length() * 2 );
+
+ if ( aIsRowEncrypted && string8.Length() > 0 )
+ {
+ RBuf8 encryptedBuffer;
+ encryptedBuffer.CreateL( string8.Length() + iEncryption.BlockSizeL() );
+ CleanupClosePushL( encryptedBuffer );
+
+ RBuf8 paddedBuffer;
+ paddedBuffer.CreateL( string8.Length() + iEncryption.BlockSizeL() );
+ CleanupClosePushL( paddedBuffer );
+
+ paddedBuffer.Copy( string8 );
+ iEncryption.AddPaddingL( paddedBuffer, iEncryption.BlockSizeL() );
+
+ iEncryption.EncryptL( paddedBuffer, encryptedBuffer );
+
+ CleanupStack::PopAndDestroy( &paddedBuffer );
+
+ iUtils.WriteLongColumnL( iTable, aColumnNum, encryptedBuffer );
+
+ CleanupStack::PopAndDestroy( &encryptedBuffer );
+ }
+ else
+ {
+ iUtils.WriteLongColumnL( iTable, aColumnNum, string8 );
+ }
+
+ }
+
+
+// ==========================================================================
+// FUNCTION: ReadStringFieldL
+// ==========================================================================
+void CContainerStoreSortingTable::ReadStringFieldL( RDbRowSet& aView, TInt aColumnNum, RBuf& aString )
+ {
+ __LOG_ENTER_SUPPRESS( "ReadStringFieldL" )
+
+ aString.SetLength( 0 );
+
+ iUtils.ReadLongColumnL( aView, aColumnNum, iEncryptedBuffer );
+
+ RBuf8 string8;
+ CleanupClosePushL( string8 );
+ string8.Create( iEncryptedBuffer.Length() );
+
+ if( aString.Size() < iEncryptedBuffer.Length() )
+ {
+ aString.ReAllocL( iEncryptedBuffer.Length() );
+ } // end if
+
+ if ( IsEncrypted( aView ) )
+ {
+ if( iEncryptedBuffer.Length() > 0 )
+ {
+ iEncryption.DecryptL( iEncryptedBuffer, string8 );
+ iEncryption.RemovePaddingL( string8 );
+ } // end if
+ }
+ else
+ {
+ string8.Copy( iEncryptedBuffer );
+ }
+
+ const TUint16* valuePtr16 = reinterpret_cast<const TUint16*>( string8.Ptr() );
+ TPtrC16 string16;
+ string16.Set( valuePtr16, string8.Length() / 2 );
+ aString.Copy( string16 );
+
+ CleanupStack::PopAndDestroy( &string8 );
+
+ __LOG_WRITE_FORMAT2_DEBUG3( "col=%d, string=%S", aColumnNum, &aString )
+ }
+
+
+// ==========================================================================
+// FUNCTION: EncryptFirstL
+// ==========================================================================
+TBool CContainerStoreSortingTable::EncryptFirstL( TDbBookmark& aNextRow )
+ {
+ __LOG_ENTER( "EncryptFirstL" )
+
+ TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KSortingTableIsEncryptedCol, EFalse, aNextRow );
+
+ __LOG_EXIT
+
+ return found;
+ }
+
+// ==========================================================================
+// FUNCTION: EncryptNextL
+// ==========================================================================
+TBool CContainerStoreSortingTable::EncryptNextL( TDbBookmark& aNextRow )
+ {
+ __LOG_ENTER( "EncryptNextL" )
+
+ TBool hasMore = EFalse;
+
+ TRAPD( err, iTable.GotoL( aNextRow ) );
+ if ( err == KErrNotFound )
+ {
+ hasMore = EncryptFirstL( aNextRow );
+ }
+ else if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ else
+ {
+ iTable.GetL();
+ if ( !IsEncrypted( iTable ) )
+ {
+ RBuf string;
+ CleanupClosePushL( string );
+
+ PrepareRowForUpdateLC();
+
+ //process the from field
+ ReadStringFieldL( iTable, iFromColNum, string );
+ WriteStringL( iFromColNum, string, ETrue ); //encrypt before write
+
+ //process the to field
+ ReadStringFieldL( iTable, iToColNum, string );
+ WriteStringL( iToColNum, string, ETrue ); //encrypt before write
+
+ //process the subject field
+ ReadStringFieldL( iTable, iSubjectColNum, string );
+ WriteStringL( iSubjectColNum, string, ETrue ); //encrypt before write
+
+ //update the isEncrypted column
+ SetEncryptedL( ETrue );
+
+ PutRowUpdatesL();
+
+ CleanupStack::PopAndDestroy( &string );
+ }
+
+ hasMore = iTable.NextL();
+ if ( hasMore )
+ {
+ __LOG_WRITE_INFO("hasMore is TRUE")
+ aNextRow = iTable.Bookmark();
+ }
+ }
+
+ __LOG_EXIT
+
+ return hasMore;
+ }
+
+// ==========================================================================
+// FUNCTION: DecryptFirstL
+// ==========================================================================
+TBool CContainerStoreSortingTable::DecryptFirstL( TDbBookmark& aNextRow )
+ {
+ __LOG_ENTER( "DecryptFirstL" )
+
+ TBool found = iUtils.FindFirstEncryptedOrUnencryptedL( iTable, KSortingTableIsEncryptedCol, ETrue, aNextRow );
+
+ __LOG_EXIT
+
+ return found;
+ }
+
+// ==========================================================================
+// FUNCTION: DecryptNextL
+// ==========================================================================
+TBool CContainerStoreSortingTable::DecryptNextL( TDbBookmark& aNextRow )
+ {
+ __LOG_ENTER( "DecryptNextL" )
+
+ TBool hasMore = EFalse;
+
+ TRAPD( err, iTable.GotoL( aNextRow ) );
+ if ( err == KErrNotFound )
+ {
+ hasMore = DecryptFirstL( aNextRow );
+ }
+ else if ( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+ else
+ {
+ iTable.GetL();
+ if ( IsEncrypted( iTable ) )
+ {
+ RBuf string;
+ CleanupClosePushL( string );
+
+ PrepareRowForUpdateLC();
+
+ //process the from field
+ ReadStringFieldL( iTable, iFromColNum, string );
+ WriteStringL( iFromColNum, string, EFalse ); //do not encrypt
+
+ //process the to field
+ ReadStringFieldL( iTable, iToColNum, string );
+ WriteStringL( iToColNum, string, EFalse ); //do not encrypt
+
+ //process the subject field
+ ReadStringFieldL( iTable, iSubjectColNum, string );
+ WriteStringL( iSubjectColNum, string, EFalse ); //do not encrypt
+
+ //update the isEncrypted column
+ SetEncryptedL( EFalse );
+
+ PutRowUpdatesL();
+
+ CleanupStack::PopAndDestroy( &string );
+ }
+
+ hasMore = iTable.NextL();
+ if ( hasMore )
+ {
+ __LOG_WRITE_INFO("hasMore is TRUE")
+ aNextRow = iTable.Bookmark();
+ }
+ }
+
+ __LOG_EXIT
+
+ return hasMore;
+ }
+
+// ==========================================================================
+// FUNCTION: SetFlagIfChangedInt8
+// ==========================================================================
+void CContainerStoreSortingTable::SetFlagIfChangedInt8( TInt8 newVal, TInt aColNum, TBool aIsNew, TSortableFieldsMasks aMask )
+ {
+ TInt8 curVal = newVal;
+ if ( !aIsNew )
+ {
+ curVal = iTable.ColInt8( aColNum );
+ }
+
+ if ( aIsNew || curVal != newVal )
+ {
+ iFieldsChanged |= aMask;
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: SetFlagIfChangedUint
+// ==========================================================================
+void CContainerStoreSortingTable::SetFlagIfChangedUint( TUint newVal, TInt aColNum, TBool aIsNew, TSortableFieldsMasks aMask )
+ {
+ TInt8 curVal = newVal;
+ if ( !aIsNew )
+ {
+ curVal = iTable.ColUint32( aColNum );
+ }
+
+ if ( aIsNew || curVal != newVal )
+ {
+ iFieldsChanged |= aMask;
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: SetFlagIfChangedInt64
+// ==========================================================================
+void CContainerStoreSortingTable::SetFlagIfChangedInt64( TInt64 newVal, TInt aColNum, TBool aIsNew, TSortableFieldsMasks aMask )
+ {
+ TInt64 curVal = newVal;
+ if ( !aIsNew )
+ {
+ curVal = iTable.ColInt64( aColNum );
+ }
+
+ if ( aIsNew || curVal != newVal )
+ {
+ iFieldsChanged |= aMask;
+ }
+ }
+
+// ==========================================================================
+// FUNCTION: GetColumnNumL
+// ==========================================================================
+TInt CContainerStoreSortingTable::GetColumnNumL( TMsgStoreSortByField aSortBy )
+ {
+ TInt stringColNum = 0;
+ if ( aSortBy == EMsgStoreSortBySender )
+ {
+ stringColNum = iFromColNum;
+ }
+ else if ( aSortBy == EMsgStoreSortByRecipient )
+ {
+ stringColNum = iToColNum;
+ }
+ else if ( aSortBy == EMsgStoreSortBySubject )
+ {
+ stringColNum = iSubjectColNum;
+ }
+ else
+ {
+ User::Leave(KErrArgument);
+ }
+ return stringColNum;
+ }
+
+// ==========================================================================
+// FUNCTION: IsEncrypted
+// ==========================================================================
+TBool CContainerStoreSortingTable::IsEncrypted( RDbRowSet& aRowSet )
+ {
+ return static_cast<TBool>( aRowSet.ColUint8( iIsEncryptedColNum ) );
+ }
+
+// ==========================================================================
+// FUNCTION: SetEncryptedL
+// ==========================================================================
+void CContainerStoreSortingTable::SetEncryptedL( TBool aIsEncrypted )
+ {
+ iTable.SetColL( iIsEncryptedColNum, static_cast<TUint8>(aIsEncrypted) );
+ }
+