messagingfw/msgsrvnstore/server/src/msvsearchsortdbwrapper.cpp
changeset 0 8e480a14352b
child 22 d2c4c66342f3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgsrvnstore/server/src/msvsearchsortdbwrapper.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,2817 @@
+// Copyright (c) 2008-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:
+// HEADER FILES
+// 
+//
+ 
+ #include "msvsearchsortdbwrapper.h"
+ #include "MSVSTD.H"
+ #include "msvindexadapter.h"
+ 
+ #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+ #include "MSVSERV.H"
+ #endif
+ 
+ const TInt KMaxQuerySize = 4000;
+ const TInt KMaxInCount = 50;
+ 
+ 
+/**
+ * LITERAL DEFINITION
+ */
+_LIT8(KQuote, "\"");
+_LIT8(KComma, ", ");
+_LIT8(KAnd, " AND ");
+_LIT8(KLike, " LIKE ");
+_LIT8(KPercent, "%");
+_LIT8(KUnderScore, "_");
+_LIT8(KDescription, "description");	
+_LIT8(KDetails, "details");
+_LIT8(KDate, "date");
+_LIT8(KSize, "size");
+_LIT8(KMtmId, "mtmId");
+_LIT8(KType,"type");
+_LIT8(KCloseBrace, ")");
+_LIT8(KAscending," ASC");
+_LIT8(KDescending," DESC");
+_LIT8(KDelimiter,";");
+_LIT8(KOrderBy," ORDER by ");
+_LIT8(KBitwiseData,"data & ");
+_LIT8(KId, "id");
+_LIT8(KSelect, "SELECT ");
+#if (!defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+_LIT8(KIdIn, "id IN(");
+#endif
+_LIT8(KWhere, " WHERE ");
+_LIT8(KNull, "NULL");
+
+_LIT8(KPrioritySort, "data & 3");
+_LIT8(KAttachmentSort, "data & 32768");
+_LIT8(KNewMsgSort, "data & 16");
+_LIT8(KUnReadSort, "data & 32");
+
+
+_LIT8(KIndexSortInsert, "INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield) ");
+
+_LIT8(KGreaterThan, " > ");
+_LIT8(KLessThan, " < ");
+_LIT8(KGreaterThanEqualTo," >= ");
+_LIT8(KLessThanEqualTo," <= ");
+_LIT8(KNotEqualTo," != ");
+_LIT8(KEqualTo, " = ");
+	
+
+
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+	_LIT8(KFromDb," FROM DB");
+	_LIT8(KIndexSortSelectRemovable, ".IndexEntry WHERE ");
+	_LIT8(KIndexSortSelectNoParentRemovable, ".IndexEntry ");
+	_LIT8(KIdQuerySelect, "SELECT DISTINCT id FROM DB");
+#else
+	_LIT8(KIdQuery, "SELECT DISTINCT id ");
+	_LIT8(KIdQueryNoParent, "SELECT DISTINCT id FROM IndexEntry ");
+	_LIT8(KIndexSortSelect, " FROM IndexEntry WHERE parentId = ");
+	_LIT8(KIndexSortSelectNoParent, " FROM IndexEntry ");
+#endif
+
+/**
+ * TSearchSortDbWrapper
+ */
+
+
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+
+TSearchSortDbWrapper* TSearchSortDbWrapper::NewL(CMsvServer& aServer)
+	{
+	//Create an Search sort db adaption object 
+	TSearchSortDbWrapper* self = new(ELeave) TSearchSortDbWrapper(aServer);
+	return self;
+	}
+
+TSearchSortDbWrapper::TSearchSortDbWrapper(CMsvServer& aServer) : iServer(aServer)
+	{
+	iDBadapter = iServer.Context().IndexAdapter()->GetDbAdapter();
+				 
+	iTotalCount = -1;
+	iProcessedIndexQueries = 0;
+	}
+
+void TSearchSortDbWrapper::CloseResources()
+	{
+	// relese the resources
+	iMtmIdArray.Close();	
+	}
+
+#else 	// SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB
+
+/**
+ NewL()
+It returns an instance of TSearchSortDbWrapper class. 
+
+@param CMsvDBAdapter& aDBadapter: reference to CMsvDBAdapter Class.
+@return The newly created Msv DBadaption Object.
+@leave: KErrNone if successful or any of system wide leave codes if not.
+*/
+TSearchSortDbWrapper* TSearchSortDbWrapper::NewL(CMsvDBAdapter& aDBadapter)
+	{
+	//Create an Search sort db adaption object 
+	TSearchSortDbWrapper* self = new(ELeave) TSearchSortDbWrapper(aDBadapter);
+	return self;
+	}
+
+/**
+ TSearchSortDbWrapper()
+Constructor for the TSearchSortDbWrapper class.
+
+@param 	None.
+@return None.
+*/
+TSearchSortDbWrapper::TSearchSortDbWrapper(CMsvDBAdapter& aDBadapter):iDBadapter(&aDBadapter), iTotalCount(-1), iProcessedIndexQueries(0)
+	{
+	}
+
+#endif // if (!defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+
+
+/** 
+  FindL()
+Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the DB query
+and gets the resultant TMsvIds for the query so formed.
+
+@param CMsvSearchSortCacheEntry& aQuery:	Contains all the SearchSort related information(What to search on, what to search for).
+@param RArray<TMsvId>& aIdResult: RArray which holds the resultant TMsvIds.
+@param TBool aSortOnHeader: This specifies whether the sort field is a part of the Header(To, Bcc, Cc) or TMsvEntry(Date, Size, priority).
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/ 
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+void TSearchSortDbWrapper::FindL(const CMsvSearchSortCacheEntry& aQuery, RArray<TMsvId>& aIdResult, const TBool aSortOnHeader, TInt aTypeOfQuery, TInt& aStatusOfQuery)
+#else
+void TSearchSortDbWrapper::FindL(const CMsvSearchSortCacheEntry& aQuery, RArray<TMsvId>& aIdResult, const TBool aSortOnHeader/*DEFAULT = EFalse*/)
+#endif
+	{
+	RBuf8 queryString;
+	queryString.CreateL(KMaxQuerySize);
+	queryString.CleanupClosePushL();
+	
+	RArray<TMsvId> folderIdList;
+	CleanupClosePushL(folderIdList);
+
+	TMsvId parentId;
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+	parentId = UnmaskTMsvId(aQuery.iParentId);
+#else
+	parentId = aQuery.iParentId;
+#endif  
+	//Append the parentid on which the search/sort is intiated into the folder list
+	folderIdList.AppendL(parentId);
+
+	iSortOnHeader = aSortOnHeader;
+	
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+	iTypeOfQuery = aTypeOfQuery;
+	iTotalNumMsgPartsOnHeader = 0;
+	iNumOfMsgParts = 0;
+	
+	ParseQueryForHeaderFields(aQuery);
+#endif	
+	
+	for(TInt folderindex = 0; folderindex < folderIdList.Count(); ++folderindex)
+		{
+		//If subfolder search is enabled then all the subfolders under the parent and its 
+		// childrens are searched for a match.
+		if(aQuery.iSubFolderOption && parentId != KMsvRootIndexEntryIdValue)
+			{
+			iDBadapter->GetFolderIdsL(folderIdList[folderindex], folderIdList);	
+			}
+	
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+		// get MtmIds for corresponding parentId
+		TRAPD(error, ProcessPreQueryRequestL(folderIdList[folderindex], aStatusOfQuery));
+		
+		if(error == KErrArgument)
+			{
+			queryString.Delete(0,KMaxQuerySize);
+			continue;
+			}
+#endif
+		
+		//Create the SQLquery from the CMsvSearchSortCacheEntry and the parentid specified
+		CreateQueryL(aQuery, queryString, folderIdList[folderindex]);
+		
+		//If the sort is done on a Header specific part(To, Cc, Bcc), sortfield is not stored in DB
+		//It has to be fetched from client side, hence sending the TMsvIds to client without storing.
+		
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+		if(iStatusOfQuery == KNewQuery)
+#else
+		if(iSortOnHeader)
+#endif				
+			{
+			iDBadapter->SearchTMsvIdL(queryString, aIdResult);
+			}
+		//If the sort is done on a TMsvEntry specific part(size, date, mtmtype), sortfield is stored in DB
+		else  // (iStatusOfQuery == KPartialResult || iStatusOfQuery == KFinalResult)
+			{
+			iDBadapter->AddEntriesfromIndexTableL(queryString);
+			}
+		queryString.Delete(0,KMaxQuerySize);
+		}
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+	if(iStatusOfQuery == KPartialResult || iStatusOfQuery == KFinalResult)
+#else
+	if(!iSortOnHeader)
+#endif
+		{
+		//If the sort is done on a TMsvEntry fetch all the TMsvIds matching this query and pass it to client
+		iDBadapter->GetSearchSortEntriesL(aQuery.iQueryID, aIdResult, aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart));	
+		}
+	
+	iProcessedIndexQueries = 0;
+	CleanupStack::PopAndDestroy(&folderIdList);  // for folderIdList;
+	CleanupStack::PopAndDestroy(); // for  queryString;
+	}
+
+
+/** 
+  UpdateNewIdsL()
+Depending on the CMsvSearchSortCacheEntry and the TMsvIds passed to this function it constructs the DB query
+and gets the resultant TMsvIds for the query so formed.
+
+@param CMsvSearchSortCacheEntry& aQuery:	Contains all the SearchSort related information(What to search on, what to search for).
+@param RArray<TMsvId>& aIdFilter: RArray holding the entries to be filtered with
+@param RArray<TMsvId>& aIdResult: RArray which holds the resultant TMsvIds.
+@param const TBool aSortOnHeader: This specifies whether the sort field is a part of the Header(To, Bcc, Cc) or TMsvEntry(Date, Size, priority).
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/ 
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+void TSearchSortDbWrapper::UpdateNewIdsL(const CMsvSearchSortCacheEntry& aQuery,const RArray<TMsvId>& aIdFilter, RArray<TMsvId>& aIdResult,const TBool aSortOnHeader, TInt aTypeOfQuery, TInt& aStatusOfQuery)
+#else
+void TSearchSortDbWrapper::UpdateNewIdsL(const CMsvSearchSortCacheEntry& aQuery,const RArray<TMsvId>& aIdFilter, RArray<TMsvId>& aIdResult,const TBool aSortOnHeader/*DEFAULT = EFalse*/)
+#endif
+	{
+	if(aIdFilter.Count() != 0)
+		{
+		TInt idArrayCount = 0;
+		TInt initQuerySize = 0;
+		TInt idsAdded = 0;
+		
+		RBuf8 queryString;
+		queryString.CleanupClosePushL();
+		queryString.Create(KMaxQuerySize);
+		
+		//Folderlist for subfolder search
+		RArray<TMsvId> folderIdList;
+		TMsvId parentId;
+	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		parentId = UnmaskTMsvId(aQuery.iParentId);
+	#else
+		parentId = aQuery.iParentId;
+	#endif  
+		//Append the parentid on which the search/sort is intiated into the folder list
+		folderIdList.Append(parentId);
+		
+		iSortOnHeader = aSortOnHeader;
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+		iTypeOfQuery = aTypeOfQuery;
+		iTotalNumMsgPartsOnHeader = 0;
+		iNumOfMsgParts = 0;
+		ParseQueryForHeaderFields(aQuery);
+#endif
+		
+		for(TInt folderindex = 0; folderindex < folderIdList.Count(); ++folderindex)
+			{
+			//If subfolder search is enabled then all the subfolders under the parent and its 
+			// childrens are searched for a match.
+			if(aQuery.iSubFolderOption && parentId != KMsvRootIndexEntryIdValue)
+			{
+			iDBadapter->GetFolderIdsL(folderIdList[folderindex], folderIdList);	
+			}
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+			// get MtmIds for corresponding parentId
+			ProcessPreQueryRequestL(folderIdList[folderindex], aStatusOfQuery);
+#endif
+			//Create the SQLquery from the CMsvSearchSortCacheEntry and the parentid specified
+			CreateQueryL(aQuery, queryString, folderIdList[folderindex], ETrue);
+			
+			//initQuerySize is made one less than entire size to remove the delimiter(;)
+			initQuerySize = queryString.Size()-1;
+			
+			//Reset Query string to Append New ID's
+			queryString.Delete(initQuerySize,KMaxQuerySize);
+			
+			if(iProcessedIndexQueries == 0 && folderIdList[folderindex] == KMsvRootIndexEntryIdValue)
+				{
+				queryString.Append(KWhere);
+				}
+			else
+				{
+				queryString.Append(KAnd);
+				}
+				
+			//initQuerySize
+			initQuerySize = queryString.Size();
+			
+			while(idArrayCount < aIdFilter.Count())
+				{
+				//Reset Query string to Append New ID's
+				queryString.Delete(initQuerySize,KMaxQuerySize);
+				
+				//Append Id's into the In statement
+				DoAppendIdConstraint(aIdFilter, queryString, idArrayCount);
+				//If the Sort is on Header, need not store the result as it doesnt have the sortfield
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+				if(iStatusOfQuery == KNewQuery)
+#else
+				if(iSortOnHeader)
+#endif	
+					{
+					iDBadapter->SearchTMsvIdL(queryString, aIdResult);
+					}
+				//If the Sort is on index we need to store the result and then send the id's
+				else
+					{
+					idsAdded += iDBadapter->AddEntriesfromIndexTableL(queryString);
+					}
+				}
+			iProcessedIndexQueries = 0;
+			idArrayCount = 0;
+			queryString.Delete(0,KMaxQuerySize);
+			}
+		
+		//Get only the updated results for this type of query
+		// not the previously stored results
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+		if(iStatusOfQuery == KNewQuery)
+#else
+		if (aQuery.iQueryType == ECombinedQuery && !aQuery.iSortOnHeader)
+#endif		
+			{
+			iDBadapter->GetLastNTMsvIdsfromTableL(aQuery.iQueryID, aIdResult, idsAdded,aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart));
+			}
+		
+		folderIdList.Close();
+		CleanupStack::PopAndDestroy();
+		}
+
+	//Get the final list of sorted ids from the SearchSortEntry table
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	if(iStatusOfQuery == KPartialResult || iStatusOfQuery == KFinalResult)
+#else
+	if(!iSortOnHeader)
+#endif
+		{
+		iDBadapter->GetSearchSortEntriesL(aQuery.iQueryID, aIdResult, aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart));	
+		}
+	}
+	
+	
+/** 
+  CreateQueryL()
+Depending on the CMsvSearchSortCacheEntry and the TMsvIds passed to this function it constructs the DB query
+and gets the resultant TMsvIds for the query so formed.
+
+@param CMsvSearchSortCacheEntry&:	Contains all the SearchSort related information(What to search on, what to search for).
+@param RBuf8&: SQL query created depending on the CMsvSearchSortCacheEntry
+@param TMsvId& : ParentId on which the the search/sort is performed on
+@param TBool: This Specifies whether sorting is done on Header or TMsvEntry field
+@param TBool: This Specifies whether the sort option should be processed or not
+@leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported
+		 or any of system wide leave codes or SQL leave codes.
+@return none.
+*/
+
+void TSearchSortDbWrapper::CreateQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, const TMsvId& aParentId, TBool aBypassSort)
+	{
+	// If sort field is on Index part, result should be stored on the DB
+	if(!iSortOnHeader) //it's on TMsvEntry
+		{
+		DoCreateInsertSortQueryL(aQuery, aQueryString, aParentId);
+		}
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	// If sort field is on Header part and if Header table/s is availble or partiallly available 
+	// result should be stored on the DB
+	else if(iSortOnHeader && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable))
+		{
+		DoCreateInsertSortOnHeaderQueryL(aQuery, aQueryString);
+		}
+#endif		
+	else
+		{
+		if(aParentId != KMsvRootIndexEntryIdValue)
+			{
+		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			aQueryString.Append(KIdQuerySelect);
+			aQueryString.AppendNum(KCurrentDriveId);
+			aQueryString.Append(KIndexSortSelectRemovable);
+		#else
+			aQueryString.Append(KIdQuery);
+		#endif
+			}
+		else
+			{
+		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			aQueryString.Append(KIdQuerySelect);
+			aQueryString.AppendNum(KCurrentDriveId);
+			aQueryString.Append(KIndexSortSelectNoParentRemovable);
+		#else
+			aQueryString.Append(KIdQueryNoParent);
+		#endif
+			} 
+	
+	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		UpadeteQueryWithParentIdAndMsgType(aQueryString, KCurrentDriveId, aParentId);
+	#else
+		UpadeteQueryWithParentIdAndMsgType(aQueryString, aParentId);
+	#endif		
+		
+		}
+			
+	//Checks whether the query has a search part specified, 
+	//if yes then SQL query is created for the same
+	if(!aQuery.IsSortQuery())
+		{
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+		if((iTypeOfQuery & EQueryOnHeader) && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable ))
+			{
+			DoUpdateSearchQueryForHeaderFieldsL(aQuery, aQueryString, aParentId);
+			}
+		
+		if(iTypeOfQuery & EQueryOnIndexEntry)
+#endif		
+			{
+		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
+			UpdateQueryWithTMsvEntrySearchFieldsL(aQuery, aQueryString, KCurrentDriveId, aParentId);
+		#else
+			UpdateQueryWithTMsvEntrySearchFieldsL(aQuery, aQueryString, aParentId);
+		#endif
+			}
+		}
+	
+	//Checks whether the query has a sort part specified
+	//if yes then SQL query is created for the same
+	if ((aQuery.IsExplicitSortReq() || aQuery.IsSortQuery()) && !aBypassSort)
+		{
+		if(!iSortOnHeader)
+			{
+			DoCreateSortQueryL(aQuery, aQueryString);
+			}
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)			
+		if(iSortOnHeader && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable))
+			{
+			UpdateQueryWithSortFieldL(aQuery, aQueryString, KCurrentDriveId);
+			}
+#endif			
+		}
+	
+	//Adds the delimiter(;)
+	aQueryString.Append(KDelimiter);
+
+	//Replaces Symbian WildCards(?, *) with SQL Wildcards (_, %)
+	if(aQuery.IsWildCharacter())
+		{
+		ReplaceWildCardCharacters(aQueryString,aQuery);
+		}
+	}
+
+/** 
+  ReplaceWildCardCharacters()
+The Function replaces the '?' in the query with '_' and '*' in the string with a '%'.
+
+@param TDes8& aString: string on which the replace operation has to be done on.
+@return none.
+*/
+void TSearchSortDbWrapper::ReplaceWildCardCharacters(TDes8& aString,const CMsvSearchSortCacheEntry& aQuery)
+	{
+	
+	for(TInt pos=0; pos < aString.Size(); pos++)
+		{
+		if(aString[pos] == '?')
+			{
+			aString.Replace(pos,1,KUnderScore);
+			}
+		else if(aString[pos] == '*')
+			{
+			if(!aQuery.IsCaseSensetive())
+			    aString.Replace(pos,1,KPercent);
+			}
+		}
+	}
+
+
+/** 
+  DoAddRelationalOperatorL()
+The function Appends the required relational operator to the query string passed 
+	depending on the enum type specified
+
+@param RBuf8& aQuery: string on which the replace operation has to be done on.
+@param TMsvRelationOp aRelationOp: Relational operator which has to be appended to the string
+@return none.
+@leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
+*/
+void TSearchSortDbWrapper::DoAddRelationalOperatorL(RBuf8& aQuery,TMsvRelationOp aRelationOp)
+	{
+	switch(aRelationOp)
+		{
+		case EMsvEqual:
+			{
+			aQuery.Append(KEqualTo);
+			break;
+			}
+			
+		case EMsvNotEqual:
+			{
+			aQuery.Append(KNotEqualTo);
+			break;							
+			}
+	
+		case EMsvLessThan:
+			{
+			aQuery.Append(KLessThan);
+			break;
+			}
+	
+		case EMsvGreaterThan:
+			{
+			aQuery.Append(KGreaterThan);
+			break;
+			}
+	
+		case EMsvLessThanOrEqual:
+			{
+			aQuery.Append(KLessThanEqualTo);
+			break;
+			}
+	
+		case EMsvGreaterThanOrEqual:
+			{
+			aQuery.Append(KGreaterThanEqualTo);
+			break;
+			}
+	
+		default:
+			{
+			User::Leave(KErrNotSupported);
+			}
+		}
+	}
+	
+
+/** 
+  DoCreateSearchQueryL()
+Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the SQLDB search query.
+
+@param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
+@param RBuf8& aSearchQuery: The QueryString which will be prepared depending on CMsvSearchSortCacheEntry.
+@param TMsvId& aParentId: ParentId on which the the search/sort is performed on
+@return none.
+@leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
+*/
+void TSearchSortDbWrapper::DoCreateSearchQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSearchQuery)
+	{
+
+	for(TInt index=0; index<aQuery.iMsgQuery.Count(); index++)
+		{
+		switch (aQuery.iMsgQuery[index].iMessagePart)
+			{
+			//Header and Body Parts are searched at client side using FindL
+			case EMsvTo:
+			case EMsvFrom:
+			case EMsvCc:
+			case EMsvBcc:
+			case EMsvSubject:
+			case EMsvBody:
+				{
+				break;
+				}
+			
+			//Index Entry Parts to be searched
+			//Search on Description
+			case EMsvDescription:
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KDescription);
+				
+				// update query for case sensitive or case insensitive serach
+				IsCaseSensitiveSearch(aQuery, aSearchQuery, index);
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+			
+			//Search on Details
+			case EMsvDetails:
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KDetails);
+				
+				// update query for case sensitive or case insensitive serach
+				IsCaseSensitiveSearch(aQuery, aSearchQuery, index);
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+				
+			//Search on Date
+			case EMsvDate:  
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				TTime time;
+				User::LeaveIfError(time.Set(aQuery.iMsgQuery[index].iQueryString));
+				TInt64 date=time.Int64();
+				
+				aSearchQuery.Append(KDate);
+				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+				aSearchQuery.AppendNum(date);
+												
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+				
+			//Search on Size	
+			case EMsvSize:
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KSize);
+				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+				aSearchQuery.Append(aQuery.iMsgQuery[index].iQueryString);
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+				
+			//Search on Attachment Flag		
+			case EMsvAttachment:
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KBitwiseData);
+				aSearchQuery.AppendNum(KMsvEntryAttachmentFlag);
+				//Entries Without attachment
+				if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("0")))
+					{
+					aSearchQuery.Append(KNotEqualTo);
+					}
+				//Entries With attachment
+				else
+					{
+					aSearchQuery.Append(KEqualTo);
+					}
+				aSearchQuery.AppendNum(KMsvEntryAttachmentFlag);
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+				
+			//Search on MTM type
+			case EMsvMtmTypeUID:
+				{					
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KMtmId);
+				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+				aSearchQuery.Append(aQuery.iMsgQuery[index].iQueryString);
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+		
+			//Search on High Priority Flag
+			case EMsvPriority:
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KBitwiseData);
+				
+				//Search on High Priority Flag
+				if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("0")))
+					{
+					aSearchQuery.AppendNum(KMsvEntryHighPriority);
+					DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+					aSearchQuery.AppendNum(KMsvEntryHighPriority);
+					}
+					
+				//Search on Normal Priority Flag
+				else if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("1")))
+					{
+					aSearchQuery.AppendNum(KMsvEntryMediumPriority);
+					DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+					aSearchQuery.AppendNum(KMsvEntryMediumPriority);
+					}
+					
+					//Search on Low Priority Flag	
+				else if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("2")))
+					{
+					aSearchQuery.AppendNum(KMsvEntryLowPriority);
+					DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+					aSearchQuery.AppendNum(0);
+					}
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+
+			//Search on UnRead Flag
+			case EMsvUnreadMessages:
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KBitwiseData);
+				aSearchQuery.AppendNum(KMsvEntryUnreadFlag);
+				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+				aSearchQuery.AppendNum(KMsvEntryUnreadFlag);
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+				
+			//Search on New Message Flag			
+			case EMsvNew:
+				{
+				aSearchQuery.Append(KAnd);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
+				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
+#endif				
+				aSearchQuery.Append(KBitwiseData);
+				aSearchQuery.AppendNum(KMsvEntryNewFlag);
+				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
+				aSearchQuery.AppendNum(KMsvEntryNewFlag);
+				
+				++iProcessedIndexQueries;
+				
+				break;
+				}
+				
+			default:
+				{
+				User::Leave(KErrNotSupported);	
+				}
+			}
+		}
+	}
+
+
+/** 
+  DoCreateSortQueryL()
+Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the SQLDB sort query.
+
+@param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
+@param RBuf8& aSortQuery: The QueryString which will be prepared depending on CMsvSearchSortCacheEntry.
+@return none.
+@leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
+*/
+void TSearchSortDbWrapper::DoCreateSortQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSortQuery )
+	{
+		
+	switch (aQuery.iMsgExplicitSortPart)
+		{
+			
+		//Index Entry Parts to be searched
+		//Sort on Description
+		case EMsvDescription:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif
+			aSortQuery.Append(KDescription);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+
+		//Sort on Details
+		case EMsvDetails:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif
+			aSortQuery.Append(KDetails);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+		
+		//Sort on Date
+		case EMsvDate:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif			
+			aSortQuery.Append(KDate);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+		
+		//Sort on Size
+		case EMsvSize:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif			
+			aSortQuery.Append(KSize);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+		
+		//Sort on MTM type
+		case EMsvMtmTypeUID:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif			
+			
+			aSortQuery.Append(KMtmId);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+			
+		//Sort on Priority Flag
+		case EMsvPriority:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif			
+			
+			aSortQuery.Append(KPrioritySort);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+		
+		case EMsvAttachment:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif			
+			
+			aSortQuery.Append(KAttachmentSort);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+			
+		case EMsvNew:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif			
+			
+			aSortQuery.Append(KNewMsgSort);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+			
+		case EMsvUnreadMessages:
+			{
+			aSortQuery.Append(KOrderBy);
+		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+		#endif			
+			
+			aSortQuery.Append(KUnReadSort);
+			if(aQuery.IsAscendingSort())
+				aSortQuery.Append(KAscending);
+			else
+				aSortQuery.Append(KDescending);
+			break;
+			}
+			
+		case 0:
+			break;
+		
+		default:
+			{
+			User::Leave(KErrNotSupported);	
+			}
+		
+		}
+	}
+	
+/** 
+  DoCreateInsertSortQueryL()
+Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the SQLDB sort query.
+
+@param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
+@param RBuf8& aSortQuery: The QueryString which will be prepared depending on CMsvSearchSortCacheEntry.
+@param TMsvId& aParentId: ParentId on which the the search/sort is performed on
+@return none.
+@leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
+*/	
+
+void TSearchSortDbWrapper::DoCreateInsertSortQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSortQuery, TMsvId aParentId)
+	{
+	aSortQuery.Append(KIndexSortInsert);
+	
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+	if(iMtmIdArray.Count() > 1)
+		{
+		// handled in UpdateQueryWithMultipleTablesL()
+		return;	
+		}
+	else
+#endif		
+		{
+		aSortQuery.Append(KSelect);
+		aSortQuery.AppendNum(aQuery.iQueryID);
+		aSortQuery.Append(KComma);
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+		UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+#endif		
+		aSortQuery.Append(KId);
+		aSortQuery.Append(KComma);
+		
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
+		if(aQuery.iMsgExplicitSortPart != 0)
+			{
+			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
+			}
+#endif						
+		UpdateQueryWithTMsvEntrySortFileldL(aQuery, aSortQuery);
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
+		TInt index = 0;
+		if( iTypeOfQuery & EQueryOnIndexEntry )
+			{
+			UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
+			
+			if(iTypeOfQuery & EQueryOnHeader)
+				{
+				aSortQuery.Append(KComma);
+				UpdateQueryWithHeaderTable(aSortQuery, KCurrentDriveId, iMtmIdArray[index].iUid);	
+				}
+
+			if(aQuery.IsSortQuery())
+				{
+				aSortQuery.Append(KWhere);
+				UpadeteQueryWithParentIdAndMsgType(aSortQuery, KCurrentDriveId, aParentId);	
+				}
+			}
+		else if( (iTypeOfQuery & EQueryOnBody) && (iStatusOfQuery == KPartialResult) )
+			{
+			UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
+			aSortQuery.Append(KWhere);
+			UpadeteQueryWithParentIdAndMsgType(aSortQuery, KCurrentDriveId, aParentId);
+			}
+		else //iTypeOfQuery & EQueryOnHeader
+			{
+			UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
+			aSortQuery.Append(KComma);
+			UpdateQueryWithHeaderTable(aSortQuery, KCurrentDriveId, iMtmIdArray[index].iUid);	
+			}
+#else	
+	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
+		aSortQuery.Append(KWhere);
+		UpadeteQueryWithParentIdAndMsgType(aSortQuery, KCurrentDriveId, aParentId);
+	#else		
+		UpadeteQueryWithParentIdAndMsgType(aSortQuery, aParentId);
+	#endif
+#endif	
+		}
+	
+	}
+	
+
+void TSearchSortDbWrapper::UpdateQueryWithTMsvEntrySortFileldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSortQuery)
+	{
+	switch (aQuery.iMsgExplicitSortPart)
+		{
+		//Index Entry Parts to be searched
+		//No Sort
+		case 0:
+			{
+			aSortQuery.Append(KNull);
+			break;
+			}
+		case EMsvDescription:
+			{
+			aSortQuery.Append(KDescription);
+			break;
+			}
+
+		case EMsvDetails:
+			{
+			aSortQuery.Append(KDetails);
+			break;
+			}
+
+		case EMsvDate:  
+			{
+			aSortQuery.Append(KDate);
+			break;
+			}
+
+		case EMsvSize:
+			{
+			aSortQuery.Append(KSize);
+			break;
+			}
+
+		case EMsvMtmTypeUID:
+			{
+			aSortQuery.Append(KMtmId);
+			break;
+			}
+		
+		case EMsvPriority:
+			{
+			aSortQuery.Append(KPrioritySort);
+			break;
+			}
+			
+		case EMsvAttachment:
+			{
+			aSortQuery.Append(KAttachmentSort);
+			break;
+			}
+		
+		case EMsvNew:
+			{
+			aSortQuery.Append(KNewMsgSort);
+			break;
+			}
+			
+		case EMsvUnreadMessages:
+			{
+			aSortQuery.Append(KUnReadSort);
+			break;
+			}
+
+		default:
+			{
+			User::Leave(KErrNotSupported);	
+			}
+		}
+	}
+	
+/** 
+  AddIdtoDBL()
+Adds the TMsvId's & sortfield specified in the RArray into the SearchSortEntry table under the query id specified
+
+@param TInt aQueryId: Query Id under which the entries should be added into the table
+@param RArray<TMsvIdWithSortField>& aEntrySelection: TMsvId and sortfield which have to be added into the SearchSortEntry table
+@return none.
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/
+void TSearchSortDbWrapper::AddIdtoDBL(const TInt aQueryId,const RArray<TMsvIdWithSortField>& aEntrySelection)
+	{
+	for(TInt index = 0; index < aEntrySelection.Count(); ++index)
+		{
+		iDBadapter->CreateQueryEntryL(aQueryId, aEntrySelection[index]);
+		}
+	}
+
+
+/** 
+  GetSortedTMsvIdsfromTableL()
+Retrieves all the entries from the SearchSortEntry table under the queryid specified
+
+@param TInt aQueryId: Query Id under which the entries should be fetched from the table
+@param RArray<TMsvId>& aIdSelection: Resultant TMsvIds, retrieved from the SearchSortEntry table
+@param TBool aOrder: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
+@return none.
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/
+void TSearchSortDbWrapper::GetSortedTMsvIdsfromTableL(const TInt aQueryId, RArray<TMsvId>& aIdResult, TBool aOrder/*Default = EFalse*/,TMsvMessagePart aMessagePart /*Default = EMsvDate*/ )
+	{
+	iDBadapter->GetSearchSortEntriesL(aQueryId, aIdResult, aOrder, IsSortAsNumRequired(aMessagePart));	
+	}
+
+/** 
+  DeleteTMsvIdFromQueryL()
+Deletes the TMsvId's under the QueryId specified from the SearchSortEntry table
+
+@param TInt aQueryId: Query Id under which the entries should be deleted from the table
+@param RArray<TMsvId>& aIdSelection: The TMsvId to be deleted 
+@return none.
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/
+void TSearchSortDbWrapper::DeleteTMsvIdFromQueryL(const TInt aQueryId,const RArray<TMsvId>& aIdSelection)
+	{
+	TMsvId tid;
+	for(TInt index = 0; index < aIdSelection.Count(); ++index)
+		{
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		tid = UnmaskTMsvId(aIdSelection[index]);
+#else
+		tid = aIdSelection[index];
+#endif
+		iDBadapter->DeleteTMsvIdFromQueryL(aQueryId, tid);
+		//iDBadapter->DeleteTMsvIdFromQueryL(aQueryId, aIdSelection[index]);
+		}
+	}
+
+/** 
+  DeleteQueryFromTableL()
+Deletes all the TMsvIds under the Query Id specified from the SearchSortEntry table
+
+@param TInt aQueryId: Query Id under which the entries should be deleted from the table
+@return none.
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/
+void TSearchSortDbWrapper::DeleteQueryFromTableL(const TInt aQueryId)
+	{
+	iDBadapter->DeleteQueryFromTableL(aQueryId);
+	}
+
+
+/** 
+  DeleteQueryFromTableL()
+Deletes the TMsvId's under the all QueryId from the SearchSortEntry table
+
+@param RArray<TMsvId>& aIdSelection: The TMsvId to be deleted 
+@return none.
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/
+void TSearchSortDbWrapper::DeleteTMsvIdFromAllQueriesL(const RArray<TMsvId>& aIdSelection)
+	{
+	TMsvId tid;
+	for(TInt index = 0; index < aIdSelection.Count(); ++index)
+		{
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		tid = UnmaskTMsvId(aIdSelection[index]);
+#else
+		tid = aIdSelection[index];
+#endif
+		iDBadapter->DeleteTMsvIdFromAllQueriesL(tid);
+		//iDBadapter->DeleteTMsvIdFromAllQueriesL(aIdSelection[index]);
+		}
+	}
+	
+
+/** 
+  ReturnResultCountInTableL()
+Returns the number of TMsvIds stored under the QueryId specified
+
+@param TInt aQueryId: Query Id under which the entry count should be returned
+@return none.
+@leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
+*/
+TInt TSearchSortDbWrapper::ReturnResultCountInTableL(const TInt aQueryId)
+	{
+	return iDBadapter->ReturnIdCountInDBL(aQueryId);
+	}
+	
+/** 
+  DoAppendIdConstraint()
+Appends the TMsvIds passed within the IN() SQL keyword to limit the search/sort capabilty only to these TMsvids.
+
+@param RArray<TMsvId>& aIdFilter:  RArray holding the entries to be used inside the IN() keyword
+@param RBuf8& aSortQuery: This contains the SQL query having the IN() statement with the TMsvIds specified
+@param TInt& aIdCount: This contains the index in from which the TMsvIds should be appended from the array,
+				This also holds the number of entries appended after the operation is performed.
+		
+@return none.
+*/ 
+void TSearchSortDbWrapper::DoAppendIdConstraint(const RArray<TMsvId>& aIdFilter, RBuf8& aSortQuery, TInt& aIdCount)
+	{
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	_LIT8(KIndexEntryIdIn, ".IndexEntry.id IN(");
+	_LIT8(KDb, 		"DB");
+#endif
+	
+	if(aIdFilter.Count() == 0)
+		{
+		aSortQuery.Append(KDelimiter);
+		}
+	else
+		{
+		
+		TInt index=0;
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+		aSortQuery.Append(KDb);
+		aSortQuery.AppendNum(KCurrentDriveId);
+		aSortQuery.Append(KIndexEntryIdIn);
+#else		
+		aSortQuery.Append(KIdIn);
+#endif		
+		
+		for(index=aIdCount; (index < aIdCount+KMaxInCount) && (index < aIdFilter.Count()) ; ++index)
+			{
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			aSortQuery.AppendNum(UnmaskTMsvId(aIdFilter[index]));
+#else			
+			aSortQuery.AppendNum(aIdFilter[index]);
+#endif			
+			aSortQuery.Append(KComma);
+			}
+		//Delete the Last KComma
+		aSortQuery.Delete(aSortQuery.Size()-2,KMaxQuerySize);
+		aSortQuery.Append(KCloseBrace);
+		aSortQuery.Append(KDelimiter);
+		aIdCount = index;
+		}
+	}
+
+
+/** 
+  IsSortAsNumRequired()
+Returns whether the Specified message part requires sorting as TEXT or INT
+
+@param TMessagePart& aMessagePart: Sort Message part
+@return TBool returns true if the TMessagePart is INT.
+*/ 
+TBool TSearchSortDbWrapper::IsSortAsNumRequired(const TMsvMessagePart& aMessagePart)
+	{
+	
+	switch(aMessagePart)
+		{
+		case EMsvDate:  
+		case EMsvSize:
+		case EMsvMtmTypeUID:
+		case EMsvPriority:
+			{
+			return ETrue;	
+			}
+
+		default:
+			{
+			return EFalse;	
+			}
+		}
+		
+	}
+	
+/** 
+  GetIdsInIterator()
+This function should be used to retrieve TMsvIds in an iterative way.
+The function maintains a counter which hold the last result count sent to the client.
+The fuction executes the query from the start and returns the next result every time
+
+@param TUint32&: The Id of the Search/Sort Query
+@param TInt    : The previous count in the result set that was accessed
+@param TMsvId& : The result id		
+@return void   
+*/ 
+
+void TSearchSortDbWrapper::GetIdsInIteratorQueryIdL(const TInt& aQueryId, const TBool aOrder/*Default = ETrue*/, TMsvMessagePart aMessagePart /*Default = EMsvDate*/, const TInt aLimit/*Default = 1*/)
+	{
+	//Get the total count of results
+	iTotalCount=ReturnResultCountInTableL(aQueryId);
+	iDBadapter->ReturnIdsInIteratorL(aQueryId, aOrder, IsSortAsNumRequired(aMessagePart), aLimit);
+	iLocation = 0;
+	}
+
+
+/** 
+  GetIdsInIteratorNewQueryL()
+@param aQuery  : Search/Sort query which has to be processed
+@return NONE   
+
+Initialises iterator for a new query. It executes the query and stores the result in the DB.
+Gets  total count of the result and initialises previous count to 0
+*/ 
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB) 		
+void TSearchSortDbWrapper::GetIdsInIteratorNewQueryL(const CMsvSearchSortCacheEntry& aQuery, TBool aSortOnHeader, TInt aTypeOfQuery, TInt& aReturnResultType,  const TInt aLimit)
+#else 		
+
+void TSearchSortDbWrapper::GetIdsInIteratorNewQueryL(const CMsvSearchSortCacheEntry& aQuery, const TInt aLimit/*Default = 1*/)
+#endif
+	{
+	// Create a new query, Execute that query, Store results
+	RArray<TMsvId> iIteratorArray;
+	
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+	FindL(aQuery, iIteratorArray, aSortOnHeader, aTypeOfQuery, aReturnResultType);
+#else	
+	FindL(aQuery,iIteratorArray,EFalse);
+#endif	
+	
+	// Set total count
+	iTotalCount=ReturnResultCountInTableL(aQuery.iQueryID);
+	iLocation = 0;
+	
+	//Init the iterator
+	iDBadapter->ReturnIdsInIteratorL(aQuery.iQueryID, aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart), aLimit);
+	
+	//Destroy the Resultant Array
+	iIteratorArray.Close();
+	}
+
+/** 
+* GetNextIdL()
+@param aQueryId  : ID of the Search/Sort query which has to be processed
+@param aId       : The next result
+@return   KErrEof if the end of the result is reached
+
+Gets the next ID for a QueryId from the DB
+*/ 
+void TSearchSortDbWrapper::GetNextIdL(TMsvId& aId, TInt& aRemainingCount)
+	{
+	User::LeaveIfError(iTotalCount);
+	
+	if(iTotalCount == 0)
+		{
+		aRemainingCount	= 0;
+		aId = 0;
+		User::LeaveIfError(iTotalCount = -1);
+		}
+		
+	else if(iTotalCount == iLocation)
+		{
+		aRemainingCount	= 0;
+		aId = 0;
+		User::LeaveIfError(iTotalCount = -1);
+		}
+		
+	else
+		{
+		iLocation = iDBadapter->GetNextL(aId);
+		aRemainingCount = iTotalCount - iLocation;
+		}
+	}
+
+
+/** 
+  GetDateRelationalOperator()
+This function is used to add date field to the query being prepared
+@param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
+@param TInt aCurrentIndex: The current index of query table
+
+@return void
+*/ 
+TMsvRelationOp TSearchSortDbWrapper::GetDateRelationalOperator(const CMsvSearchSortCacheEntry& aQuery,TInt aCurrentIndex)
+	{
+	return(aQuery.iMsgQuery[aCurrentIndex].iRelationOp);
+	}
+
+
+/** 
+* IsCaseSensitiveSearch()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* @param aIndex: index of query table 
+* return NONE
+*  
+*  Function to update query with case sensitive or case insensitive serach
+*/ 	
+void TSearchSortDbWrapper::IsCaseSensitiveSearch(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TInt aIndex)
+	{
+	_LIT8(KGlob, " GLOB ");
+	_LIT8(KStar, "*");
+
+	if(aQuery.IsCaseSensetive())
+		{
+		aQueryString.Append(KGlob);
+				
+		aQueryString.Append(KQuote);
+		aQueryString.Append(KStar);
+		aQueryString.Append(aQuery.iMsgQuery[aIndex].iQueryString);
+		aQueryString.Append(KStar);
+		aQueryString.Append(KQuote);
+		}
+	else
+		{
+		aQueryString.Append(KLike);
+			
+		aQueryString.Append(KQuote);
+		aQueryString.Append(KPercent);
+		aQueryString.Append(aQuery.iMsgQuery[aIndex].iQueryString);
+		aQueryString.Append(KPercent);
+		aQueryString.Append(KQuote);	
+		}
+	}	
+
+
+/** 
+* UpdateQueryWithTMsvEntrySearchFieldsL()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* @param aDriveId: update query with Drive number 
+* return NONE
+*  
+*  Update query with TMsvEntry Search field
+*/ 	
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
+void TSearchSortDbWrapper::UpdateQueryWithTMsvEntrySearchFieldsL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId, TMsvId aParentId)
+#else
+void TSearchSortDbWrapper::UpdateQueryWithTMsvEntrySearchFieldsL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TMsvId aParentId)
+#endif
+	{
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+	if(iMtmIdArray.Count() > 1)
+		{
+		if(iTypeOfQuery != EQueryOnHeaderAndBody && iTypeOfQuery != EQueryOnEntryHeaderAndBody)
+			{
+			UpdateQueryWithMultipleTablesL(aQuery, aQueryString, aDriveId, aParentId);
+			}
+		}
+	else
+		{
+		if(!iTotalNumMsgPartsOnHeader)
+			{
+			aQueryString.Append(KWhere);
+			UpadeteQueryWithParentIdAndMsgType(aQueryString, aDriveId, aParentId);
+			}
+#endif
+	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+		aDriveId = aDriveId;    // to remove compilation warning, need to delete this line while removing macro SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB
+	#endif	
+		aParentId = aParentId;  // to remove compilation warning, need to delete this line while removing macro SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB
+		
+
+		DoCreateSearchQueryL(aQuery, aQueryString);
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
+		}
+#endif
+	}
+
+
+/** 
+* UpadeteQueryWithParentIdAndMsgType()
+*
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* @param aDriveId: update query with Drive number 
+* return NONE
+*  
+*  Update query with parentId and type as KUidMsvMessageEntryValue
+*/ 	
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+void TSearchSortDbWrapper::UpadeteQueryWithParentIdAndMsgType(RBuf8& aQueryString, TUint aDriveId, TMsvId aParentId)
+#else
+void TSearchSortDbWrapper::UpadeteQueryWithParentIdAndMsgType(RBuf8& aQueryString, TMsvId aParentId)
+#endif
+	{
+	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
+	_LIT8(KIndexEntry, "IndexEntry");
+	_LIT8(KParentId, 	"ParentId");
+	_LIT8(KDb, 		"DB");
+	_LIT8(KDot, 		".");
+	#endif
+	
+	if(aParentId != KMsvRootIndexEntryIdValue)
+		{
+		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			// DB(DriveId).IndexEntry.ParentId = ParentId AND DB(DriveId).IndexEntry.type = KUidMsvMessageEntryValue
+			aQueryString.Append(KDb);
+			aQueryString.AppendNum(aDriveId);
+			aQueryString.Append(KDot);
+			aQueryString.Append(KIndexEntry);
+			aQueryString.Append(KDot);
+			aQueryString.Append(KParentId);
+			aQueryString.Append(KEqualTo);
+			aQueryString.AppendNum(aParentId);
+			
+			aQueryString.Append(KAnd);
+			
+			UpdateQueryWithDriveNumAndIndexEntryTable(aQueryString, aDriveId);
+			aQueryString.Append(KType);
+			aQueryString.Append(KEqualTo);
+			aQueryString.AppendNum(KUidMsvMessageEntryValue);
+		#else // SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT
+			aQueryString.Append(KIndexSortSelect);
+			aQueryString.AppendNum(aParentId);
+			
+			aQueryString.Append(KAnd);
+		
+			aQueryString.Append(KType);
+			aQueryString.Append(KEqualTo);
+			aQueryString.AppendNum(KUidMsvMessageEntryValue);
+		#endif
+		}
+	else
+		{
+		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+			aQueryString.Append(KType);
+			aQueryString.Append(KEqualTo);
+			aQueryString.AppendNum(KUidMsvMessageEntryValue);
+		#else // SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT
+			aQueryString.Append(KIndexSortSelectNoParent);
+			aQueryString.Append(KWhere);
+			aQueryString.Append(KType);
+			aQueryString.Append(KEqualTo);
+			aQueryString.AppendNum(KUidMsvMessageEntryValue);
+		#endif
+		}
+	}
+
+/** 
+* UpdateQueryWithHeaderTable()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update query with Header table
+*/ 
+#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
+void TSearchSortDbWrapper::UpdateQueryWithDriveNumAndIndexEntryTable(RBuf8& aQueryString, TUint aDriveId)
+	{
+	_LIT8(KIndexEntry, "IndexEntry");
+	_LIT8(KDb, 		"DB");
+	_LIT8(KDot, 		".");
+	
+	// DB(DriveId).IndexEntry.
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(aDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KIndexEntry);	
+	aQueryString.Append(KDot);
+
+	}
+	
+/** 
+* UpadeteQueryWithIndexEntryTable()
+*
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* @param aDriveId: update query with Drive number 
+* return NONE
+*  
+*  Update the Query with IndexEntrytable 
+*/
+void TSearchSortDbWrapper::UpadeteQueryWithIndexEntryTable(RBuf8& aQueryString, TUint aDriveId)
+	{
+	_LIT8(KIndexEntry, "IndexEntry");
+	_LIT8(KDot, 		".");
+	
+	// FROM DB(aDriveId).IndexEntry
+	aQueryString.Append(KFromDb);
+	aQueryString.AppendNum(aDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KIndexEntry);
+	}
+#endif // SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT
+
+
+#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
+
+/**
+ * ParseQueryForHeaderFields()
+ *
+ * @param aQuery: SearchSort query sent by client
+ * @return NONE
+ * 
+ * Function to parse the SearchSort query header filelds 
+ * to check wheather it exist it in DB
+ */
+void TSearchSortDbWrapper::ParseQueryForHeaderFields(const CMsvSearchSortCacheEntry& aQuery)
+	{
+	iHeaderTableStdFields = 0;
+	iTotalNumMsgPartsOnHeader = 0;
+	
+	for(TInt count = 0; count < aQuery.iMsgQuery.Count(); count++)
+		{
+		ParseCommonHederFilelds(aQuery.iMsgQuery[count].iMessagePart, ETrue);
+		}
+		
+	ParseCommonHederFilelds(aQuery.iMsgExplicitSortPart, EFalse);
+	}
+
+
+/**
+ * ParseCommonHederFilelds()
+ *
+ * @param aMessagePart: Message part that availble SearchSort query
+ * @return NONE
+ * 
+ * Function to parse the SearchSort query header filelds 
+ * to check wheather it exist it in DB
+ */
+void TSearchSortDbWrapper::ParseCommonHederFilelds(TMsvMessagePart aMessagePart, TBool aIsSearhField)
+	{
+	switch(aMessagePart)
+		{
+		case EMsvFrom:
+			iHeaderTableStdFields |= CMsvHeaderStore::EFrom;
+			if(aIsSearhField)
+				{
+				iTotalNumMsgPartsOnHeader++;
+				}
+			break;
+		
+		case EMsvTo:
+			iHeaderTableStdFields |= CMsvHeaderStore::ETo;	
+			if(aIsSearhField)
+				{
+				iTotalNumMsgPartsOnHeader++;
+				}
+			break;
+			
+		case EMsvCc:  
+			iHeaderTableStdFields |= CMsvHeaderStore::ECC;	
+			if(aIsSearhField)
+				{
+				iTotalNumMsgPartsOnHeader++;
+				}
+			break;
+		
+		case EMsvBcc:
+			iHeaderTableStdFields |= CMsvHeaderStore::EBCC;	
+			if(aIsSearhField)
+				{
+				iTotalNumMsgPartsOnHeader++;
+				}
+			break;
+		
+		case EMsvSubject:
+			iHeaderTableStdFields |= CMsvHeaderStore::ESubject;	
+			if(aIsSearhField)
+				{
+				iTotalNumMsgPartsOnHeader++;
+				}
+			break;
+		
+		default:
+			break;
+		}
+	}
+
+/**
+ * ProcessPreQueryRequestL()
+ *
+ * @param aQuery: SearchSort query sent by client
+ * @return Status of the header table
+ * 
+ * Function to check wheather header table and correspnding standard column are availble at DB.  
+ * 
+ */
+void TSearchSortDbWrapper::ProcessPreQueryRequestL(TMsvId aParentId, TInt& aStatusOfQuery) 	
+	{
+	TBool isOnEntry = EFalse;
+	iHeaderTableAtDB = EInvalid;
+	iBodyTableAtDB = EInvalid;
+	
+	switch(iTypeOfQuery)
+		{
+		case EQueryOnIndexEntry:
+			isOnEntry = ETrue;
+			break;
+		
+		case EQueryOnHeader:
+		case EQueryOnEntryAndHeader:
+			iHeaderTableAtDB = StatusOfHeaderTableL(aParentId);
+			break;
+
+		case EQueryOnBody:
+		case EQueryOnEntryAndBody:
+			iBodyTableAtDB = ENotAvailable;
+			break;
+
+		case EQueryOnHeaderAndBody:
+		case EQueryOnEntryHeaderAndBody:
+			iHeaderTableAtDB = StatusOfHeaderTableL(aParentId);
+			iBodyTableAtDB = ENotAvailable;
+			break;
+		}
+
+	// if sort on header
+	if(iSortOnHeader)
+		{
+		if(iHeaderTableAtDB == EInvalid)
+			{
+			iHeaderTableAtDB = StatusOfHeaderTableL(aParentId);
+			}
+		}
+		
+	// Query on TMsvEntry related fields
+	if(isOnEntry && iHeaderTableAtDB == EInvalid && iBodyTableAtDB == EInvalid)
+		{
+		iStatusOfQuery = KFinalResult;
+		}
+	// Query on Header related fields	
+	else if(iHeaderTableAtDB == EAvailable && iBodyTableAtDB == EInvalid )
+		{
+		iStatusOfQuery = KFinalResult;
+		}
+	// Query on Header and Body			
+	else if(iHeaderTableAtDB == EAvailable && iBodyTableAtDB == ENotAvailable )
+		{
+		iStatusOfQuery = KPartialResult;
+		}
+	// Query on Header related fields (some of the Header the availble at DB and some of availble at file system )		
+	else if(iHeaderTableAtDB == EPartiallyAvailable)
+		{
+		iStatusOfQuery = KPartialResult;
+		}
+	else if(iBodyTableAtDB == ENotAvailable && iTypeOfQuery == EQueryOnEntryAndBody)
+	    {
+	    iStatusOfQuery = KPartialResult;
+	    }
+
+	// Header table not availbe in DB
+	else if(iHeaderTableAtDB == ENotAvailable || iBodyTableAtDB == ENotAvailable)
+		{
+		// if search only on body, get all TMsvId from IndexEntry tbale and search at client side
+		if(IsSearchQueryOnBody(ETrue))
+			{
+			iStatusOfQuery = KPartialResult;
+			}
+		else
+			{
+			iStatusOfQuery = KNewQuery;	
+			}
+		}
+	else
+		{
+		User::Leave(KErrArgument);
+		}
+		
+	aStatusOfQuery = iStatusOfQuery;
+	}
+
+
+/**
+ * StatusOfHeaderTableL()
+ *
+ * @param aQuery: SearchSort query sent by client
+ * @return Status of the header table
+ * 
+ * Function to check wheather header table and correspnding standard column are availble at DB.  
+ * 
+ */
+TSearchSortDbWrapper::THeaderBodyTableStatusAtDb TSearchSortDbWrapper::StatusOfHeaderTableL(TMsvId aParentId)
+	{
+ 	
+ 	// to get the MtmId 
+ 	QueryToGetMtmIdsL(aParentId, KCurrentDriveId);
+ 	
+ 	THeaderBodyTableStatusAtDb tableStatus = EInvalid;
+ 	
+ 	for(TInt index=0; index < iMtmIdArray.Count(); ++index)
+		{
+		if(iServer.MessageDBAdapter().CheckHeaderTableAndStdColumnFields(iMtmIdArray[index], iHeaderTableStdFields))
+			{
+			if(tableStatus == ENotAvailable || tableStatus == EPartiallyAvailable)
+				{
+				tableStatus = EPartiallyAvailable;
+				}
+			else
+				{
+				tableStatus = EAvailable;	
+				}
+			}
+		else
+			{
+			iMtmIdArray.Remove(index--);
+					
+			if(tableStatus == EAvailable || tableStatus == EPartiallyAvailable)
+				{
+				tableStatus = EPartiallyAvailable;
+				}
+			else
+				{
+				tableStatus = ENotAvailable;
+				}
+			}
+		}
+	return tableStatus;
+	}
+ 	
+
+ 
+/** 
+* QueryToGetMtmIdsL()
+*
+* @param aQuery: SearchSort query information sent by client
+* @param aDriveId:  drive number
+* @leave: KErrNone if successful or SQL leave codes if not.
+*  
+*  To get MtmId/s for corresponding query
+*/ 
+void TSearchSortDbWrapper::QueryToGetMtmIdsL(TMsvId aParentId, TUint aDriveId)
+	{
+	_LIT8(KIdQueryForMtmId, "SELECT DISTINCT mtmId FROM DB");
+	_LIT8(KIndexEntryWhereParentId, ".IndexEntry WHERE parentId = ");
+	
+	RBuf8 queryString;
+	queryString.CleanupClosePushL();
+	
+	queryString.CreateL(KMaxQuerySize);
+	
+	iMtmIdArray.Reset();
+	
+	//Query string is: SELECT DISTINCT mtmid FROM DB driveid.IndexEntry WHERE parentid=aQuery.parentId;
+	queryString.Append(KIdQueryForMtmId);
+	queryString.AppendNum(aDriveId);
+	queryString.Append(KIndexEntryWhereParentId);
+	queryString.AppendNum(aParentId);
+	queryString.Append(KDelimiter);
+
+	iDBadapter->GetMtmIdsL(queryString, iMtmIdArray);
+	
+	CleanupStack::PopAndDestroy();  //queryString
+	}
+	
+
+/** 
+* DoCreateInsertSortOnHeaderQueryL()
+*
+* @param aQuery: SearchSort query information sent by client
+* @param aQueryString:  Querystring to execute on DB
+* return NONE
+*  
+*  Update query with sort information
+*/ 
+void TSearchSortDbWrapper::DoCreateInsertSortOnHeaderQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString)
+	{
+	_LIT8(KDot, 		".");
+
+	// INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield) SELECT iQueryID, DB1.IndexEntry.id, DB1.Header_268439594."To" FROM DB1.IndexEntry, DB1.Header_268439594 
+	
+	UpdateQueryWithSearchSortEntryTable(aQueryString);
+	
+	// if searching on more than one header table
+	if(iMtmIdArray.Count() > 1)
+		{
+		// handled in UpdateQueryWithMultipleTablesL()
+		return;	
+		}
+	else  // search query on single table
+		{
+		UpdateQueryToGetQueryIdTMsvId(aQuery, aQueryString, KCurrentDriveId);
+		
+		TInt index = 0;
+		if(iMtmIdArray.Count() == 1 )
+			{
+			// ,DB(DriveId).Header_268439594."To"
+			aQueryString.Append(KComma);
+			iHeaderTableForSort = iMtmIdArray[index].iUid;
+			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[index].iUid);
+			aQueryString.Append(KDot);
+			}
+		// update sort filed	
+		UpdateHeaderFieldL(aQuery, aQueryString);	
+		DoUpdateQuery(aQueryString);	
+		}
+	}
+
+
+/** 
+* UpdateQueryWithSearchSortEntryTable()
+*
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update Query With SearchSortEntry Table
+*/ 
+void TSearchSortDbWrapper::UpdateQueryWithSearchSortEntryTable(RBuf8& aQueryString)
+	{
+	// INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield)
+	aQueryString.Append(KIndexSortInsert);
+	}
+
+
+
+/** 
+* UpdateQueryToGetQueryIdTMsvId()
+*
+* @param aQuery: Contains SearchSort query information sent by client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update Query to get TMsvIds
+*/ 
+void TSearchSortDbWrapper::UpdateQueryToGetQueryIdTMsvId(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
+	{
+	_LIT8(KIndexEntry, "IndexEntry");
+	_LIT8(KDb, 		"DB");
+	_LIT8(KDot, 		".");
+
+	// SELECT iQueryID, IndexEntry.id,
+	aQueryString.Append(KSelect);
+	aQueryString.AppendNum(aQuery.iQueryID);
+	
+	// ,DB1.IndexEntry.id
+	aQueryString.Append(KComma);
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(aDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KIndexEntry);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KId);
+	}	
+
+
+/** 
+* UpdateQueryWithMultipleTablesL()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+* Function to update the query for more than one Header table and/or multilevel query
+*
+* Example Query:
+*	
+* INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield) 
+* SELECT 1001, DB1.IndexEntry.id, DB1.Header_268439592."To" FROM DB1.IndexEntry, DB1.Header_268439592 WHERE  ( DB1.IndexEntry.id = DB1.Header_268439592.id AND  
+* ( DB1.Header_268439592."To" LIKE "test003@10.253.4.75" OR DB1.Header_268439592."Cc" LIKE "test005@10.253.4.75" OR DB1.Header_268439592."From" LIKE "test007@10.253.4.75" )  )  
+* AND DB1.Header_268439592."To" IS NOT NULL  AND DB1.IndexEntry.ParentId = 4101 AND DB1.IndexEntry.type = 268439402 
+*
+* UNION 
+*
+* SELECT 1001, DB1.IndexEntry.id, DB1.Header_268439593."To" FROM DB1.IndexEntry, DB1.Header_268439593 WHERE  ( DB1.IndexEntry.id = DB1.Header_268439593.id AND  
+* ( DB1.Header_268439593."To" LIKE "test003@10.253.4.75" OR DB1.Header_268439593."Cc" LIKE "test005@10.253.4.75" OR DB1.Header_268439593."From" LIKE "test007@10.253.4.75" )  )  
+* AND DB1.Header_268439593."To" IS NOT NULL  AND DB1.IndexEntry.ParentId = 4101 AND DB1.IndexEntry.type = 268439402 
+*
+* ORDER by "To" ASC;
+*/ 	
+void TSearchSortDbWrapper::UpdateQueryWithMultipleTablesL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId, TMsvId aParentId)
+	{
+	_LIT8(KUnion, " UNION ");
+	_LIT8(KIsNotNull, " IS NOT NULL ");
+	_LIT8(KOpenBracket, " ( ");
+	_LIT8(KCloseBracket, " ) ");
+	_LIT8(KDot, ".");
+	
+	// for multiple tables
+	for(TInt index = 0; index < iMtmIdArray.Count(); ++index)
+		{
+		// reset for other header table
+		iNumOfMsgParts = 0;
+		
+		// SELECT 1001, IndexEntry.id, 
+		UpdateQueryToGetQueryIdTMsvId(aQuery, aQueryString, aDriveId);
+		aQueryString.Append(KComma);
+		if(iSortOnHeader)
+			{
+			// Header_268439594."To"
+			UpdateQueryWithHeaderTable(aQueryString, aDriveId, iMtmIdArray[index].iUid);
+			aQueryString.Append(KDot);
+			UpdateHeaderFieldL(aQuery, aQueryString);
+			}
+		else
+			{
+			// IndexEntry.size
+			if(aQuery.iMsgExplicitSortPart != 0)
+				{
+				UpdateQueryWithDriveNumAndIndexEntryTable(aQueryString, aDriveId);
+				}
+			UpdateQueryWithTMsvEntrySortFileldL(aQuery, aQueryString);
+			}
+	
+		// Header_268439594."To"  FROM IndexEntry, Header_268439594			
+		UpadeteQueryWithIndexEntryTable(aQueryString, aDriveId);
+		aQueryString.Append(KComma);
+		UpdateQueryWithHeaderTable(aQueryString, aDriveId, iMtmIdArray[index].iUid);
+			
+		// WHERE (IndexEntry.id = Header_268439594.id AND Header_268439594."To" LIKE "%test002@10.253.4.75%")
+		aQueryString.Append(KWhere);
+		aQueryString.Append(KOpenBracket);
+		
+		// compare TMsvId of IndexEntry table and Header table
+		CompareTMsvIds(aQueryString, index);
+			
+		// if search on header fileld
+		if( (iTypeOfQuery & EQueryOnHeader) && !aQuery.IsSortQuery())
+			{
+			aQueryString.Append(KAnd);
+			
+			// inner open bracket, if search needs more than one header field
+			if(iTotalNumMsgPartsOnHeader > 1)
+				{
+				aQueryString.Append(KOpenBracket);	
+				}
+			
+			// multilevel query on single header table.
+			for(TInt queryCount=0; queryCount < aQuery.iMsgQuery.Count(); ++queryCount)
+				{
+				DoAddHeaderFields(aQuery, aQueryString, queryCount, index);
+				}
+				
+			// inner close bracket, if search needs more than one header field
+			if(iTotalNumMsgPartsOnHeader > 1)
+				{
+				aQueryString.Append(KCloseBracket);	
+				}
+
+			aQueryString.Append(KCloseBracket);
+			}
+		else
+			{
+			aQueryString.Append(KCloseBracket);	
+			}
+			
+		// update Query with search field
+		aQueryString.Append(KAnd);
+		if(iSortOnHeader)
+			{
+			UpdateQueryWithHeaderTable(aQueryString, aDriveId, iMtmIdArray[index].iUid);
+			aQueryString.Append(KDot);
+			UpdateHeaderFieldL(aQuery, aQueryString);
+			aQueryString.Append(KIsNotNull);
+			aQueryString.Append(KAnd);
+			}
+					
+		// Update Query with ParentId and MsgType
+		// IndexEntry.ParentId = 4098 AND IndexEntry.type = 268439402
+		UpadeteQueryWithParentIdAndMsgType(aQueryString, aDriveId, aParentId);
+				
+		if(iTypeOfQuery & EQueryOnIndexEntry)
+			{
+			DoCreateSearchQueryL(aQuery, aQueryString);
+			}
+				
+		// add UNION
+		if((index+1 ) != iMtmIdArray.Count())
+			{
+			aQueryString.Append(KUnion);	
+			}
+		} //end of for
+	}
+
+
+/** 
+* UpdateHeaderFieldL()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update query with Header filed
+*/ 
+void TSearchSortDbWrapper::UpdateHeaderFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString)
+	{
+	
+	_LIT8(KTo, 	 "To");
+	_LIT8(KFrom, 	 "From");
+	_LIT8(KCc, 	 "Cc");
+	_LIT8(KBcc, 	 "Bcc");
+	_LIT8(KSubject, "Subject");
+	
+	// to add header field
+	switch (aQuery.iMsgExplicitSortPart)
+		{
+		//Sort to be done on Header fields
+		case EMsvTo:
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KTo);
+			aQueryString.Append(KQuote);
+			break;
+			
+		case EMsvFrom:
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KFrom);
+			aQueryString.Append(KQuote);
+			break;
+			
+		case EMsvCc:  
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KCc);
+			aQueryString.Append(KQuote);
+			break;
+			
+		case EMsvBcc:
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KBcc);
+			aQueryString.Append(KQuote);
+			break;
+			
+		case EMsvSubject:
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KSubject);
+			aQueryString.Append(KQuote);
+			break;
+			
+		case EMsvBody:
+		default:
+			{
+			User::Leave(KErrNotSupported);	
+			}
+		}
+	}	
+
+/** 
+* DoUpdateQuery()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update query with IndexEntry and Header table
+*/ 
+void TSearchSortDbWrapper::DoUpdateQuery(RBuf8& aQueryString)
+	{
+	
+	// FROM DB(aDriveId).IndexEntry, 
+	UpadeteQueryWithIndexEntryTable(aQueryString, KCurrentDriveId);
+	aQueryString.Append(KComma);
+	
+	TInt index = 0;
+	if( iMtmIdArray.Count() == 1 )
+		{
+		if(((iTypeOfQuery & EQueryOnHeader) || iSortOnHeader) && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable))
+			{
+			// ,DB(DriveId).Header_268439594
+			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[index].iUid);
+			}
+		}
+	}
+
+
+/** 
+* UpdateQueryWithHeaderTable()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update query with Header table
+*/ 
+void TSearchSortDbWrapper::UpdateQueryWithHeaderTable(RBuf8& aQueryString, TUint aDriveId, TInt32 aMtmId)
+	{
+	_LIT8(KHeader, 	"Header_");
+	_LIT8(KDb, 		"DB");
+	_LIT8(KDot, 		".");
+	
+	// DB(DriveId).Header_268439594
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(aDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KHeader);
+	aQueryString.AppendNum(aMtmId);
+	}	
+
+
+/** 
+* DoUpdateSearchQueryForHeaderFieldsL()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update query with header fields
+*/ 
+void TSearchSortDbWrapper::DoUpdateSearchQueryForHeaderFieldsL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TMsvId aParentId)
+	{
+	_LIT8(KOpenBracket, " ( ");
+	_LIT8(KCloseBracket, " ) ");
+	
+	
+	// if search requies on more than one header table
+	if(iMtmIdArray.Count() > 1)
+		{
+		UpdateQueryWithMultipleTablesL(aQuery, aQueryString, KCurrentDriveId, aParentId);
+		return;	
+		}
+	else
+		{
+		// multilevel serach with single header table
+		TInt index = 0;
+		iNumOfMsgParts = 0;
+		aQueryString.Append(KWhere);
+		
+		if( iMtmIdArray.Count() == 1 )
+			{
+			aQueryString.Append(KOpenBracket);
+			
+			// compare TMsvId of IndexEntry table and Header table
+			CompareTMsvIds(aQueryString, index);
+
+			aQueryString.Append(KAnd);
+			
+			// inner open bracket, if search needs more than one header field
+			if(iTotalNumMsgPartsOnHeader > 1)
+				{
+				aQueryString.Append(KOpenBracket);	
+				}
+			
+			// multilevel query on single header table.
+			for(TInt queryCount=0; queryCount < aQuery.iMsgQuery.Count(); ++queryCount)
+				{
+				DoAddHeaderFields(aQuery, aQueryString, queryCount, index);
+				}
+				
+			// inner close bracket, if search needs more than one header field
+			if(iTotalNumMsgPartsOnHeader > 1)
+				{
+				aQueryString.Append(KCloseBracket);	
+				}
+			
+			aQueryString.Append(KCloseBracket);
+			}
+			
+		// update Query with ParentId and MsgType
+		aQueryString.Append(KAnd);
+		UpadeteQueryWithParentIdAndMsgType(aQueryString, KCurrentDriveId, aParentId);
+		}
+	}
+
+
+/** 
+* UpdateQueryWithSortFieldL()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update query with sort field
+*/ 
+void TSearchSortDbWrapper::UpdateQueryWithSortFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
+	{
+	if(iMtmIdArray.Count() > 1)
+		{
+		if(aQuery.IsSortQuery() && iSortOnHeader)
+			{
+			UpdateQueryWithMultipleTablesL(aQuery, aQueryString, aDriveId, UnmaskTMsvId(aQuery.iParentId));
+			}
+		DoUpdateSortQueryForHeaderFieldL(aQuery, aQueryString, aDriveId);
+		}
+	else
+		{
+		if(aQuery.IsSortQuery() || IsSearchQueryOnBody() )
+			{
+			aQueryString.Append(KWhere);
+			UpadeteQueryWithParentIdAndMsgType(aQueryString, aDriveId, UnmaskTMsvId(aQuery.iParentId));	
+			}
+		UpdateQueryToRemoveEmptyHeaderFieldL(aQuery, aQueryString, aDriveId);
+		DoUpdateSortQueryForHeaderFieldL(aQuery, aQueryString, aDriveId);
+		}
+	}	
+
+/** 
+* IsSearchQueryOnBody()
+*
+* @param aIsOnlyBody: to differentiate search only on body of the message
+* return NONE
+*  
+*  To check whether its search only on body of the message
+*/ 
+TBool TSearchSortDbWrapper::IsSearchQueryOnBody(TBool aIsOnlyBody)
+	{
+	TBool flag = EFalse;
+	// is search only on body of the message?
+	if(aIsOnlyBody)	
+		{
+		if( (iTypeOfQuery == EQueryOnBody) && !iSortOnHeader ) 
+			{
+			flag = ETrue;
+			}
+		}
+	else //is search only on body of the message and sort on header field?
+		{
+		if( (iTypeOfQuery == EQueryOnBody) && iSortOnHeader )
+			{
+			flag = ETrue;
+			}
+		}
+	return flag;	
+	}
+
+/** 
+* DoUpdateSortQueryForHeaderFieldL()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Update query with sort field
+*/ 
+void TSearchSortDbWrapper::DoUpdateSortQueryForHeaderFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
+	{
+	_LIT8(KTo, 	 "To");
+	_LIT8(KFrom, 	 "From");
+	_LIT8(KCc, 	 "Cc");
+	_LIT8(KBcc, 	 "Bcc");
+	_LIT8(KSubject, "Subject");
+	
+	switch (aQuery.iMsgExplicitSortPart)
+		{
+		//Sort on EMsvTo
+		case EMsvTo:
+			{
+			aQueryString.Append(KOrderBy);
+			
+			if(iMtmIdArray.Count() == 1)
+				{
+				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
+				}
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KTo);
+			aQueryString.Append(KQuote);
+			
+			if(aQuery.IsAscendingSort())
+				{
+				aQueryString.Append(KAscending);
+				}
+				
+			else
+				{
+				aQueryString.Append(KDescending);
+				}
+			}
+			break;
+
+		//Sort on EMsvFrom
+		case EMsvFrom:
+			{
+			aQueryString.Append(KOrderBy);
+			
+			if(iMtmIdArray.Count() == 1)
+				{
+				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
+				}
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KFrom);
+			aQueryString.Append(KQuote);
+			
+			if(aQuery.IsAscendingSort())
+				{
+				aQueryString.Append(KAscending);
+				}
+				
+			else
+				{
+				aQueryString.Append(KDescending);
+				}
+				
+			}
+			break;
+		
+		//Sort on EMsvCc
+		case EMsvCc:
+			{
+			aQueryString.Append(KOrderBy);
+			
+			if(iMtmIdArray.Count() == 1)
+				{
+				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
+				}
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KCc);
+			aQueryString.Append(KQuote);
+			
+			if(aQuery.IsAscendingSort())
+				{
+				aQueryString.Append(KAscending);
+				}
+				
+			else
+				{
+				aQueryString.Append(KDescending);
+				}
+			}
+			break;
+		
+		//Sort on EMsvBcc
+		case EMsvBcc:
+			{
+			aQueryString.Append(KOrderBy);
+			
+			if(iMtmIdArray.Count() == 1)
+				{
+				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
+				}
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KBcc);
+			aQueryString.Append(KQuote);
+			
+			if(aQuery.IsAscendingSort())
+				{
+				aQueryString.Append(KAscending);
+				}
+				
+			else
+				{
+				aQueryString.Append(KDescending);
+				}
+			}
+			break;
+		
+		//Sort on EMsvSubject
+		case EMsvSubject:
+			{
+			aQueryString.Append(KOrderBy);
+			
+			if(iMtmIdArray.Count() == 1)
+				{
+				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
+				}
+
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KSubject);
+			aQueryString.Append(KQuote);
+			
+			if(aQuery.IsAscendingSort())
+				{
+				aQueryString.Append(KAscending);
+				}
+			else
+				{
+				aQueryString.Append(KDescending);
+				}
+			}
+			break;
+		
+		// No Sort body filed	
+		case EMsvBody:
+		case 0:
+			break;
+			
+		default:
+			{
+			User::Leave(KErrNotSupported);	
+			}
+		}
+	}
+
+
+/** 
+* UpdateQueryToRemoveEmptyHeaderFieldL()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Function to remove the empty header fields from search result
+*/ 	
+void TSearchSortDbWrapper::UpdateQueryToRemoveEmptyHeaderFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
+	{
+	_LIT8(KIsNotNull, " IS NOT NULL ");
+	
+	// if it's sort query on header or 
+	// Search on TMsvEntry fields and/or body AND sort on header field
+	if( (aQuery.IsSortQuery() && iSortOnHeader) || IsSearchOnEntryAndBody(aQuery) )
+		{
+		CompareTMsvIds(aQueryString, aDriveId);
+		}
+	
+	aQueryString.Append(KAnd);
+	UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
+	UpdateHeaderFieldL(aQuery, aQueryString);
+	aQueryString.Append(KIsNotNull);
+	}
+	
+
+/** 
+* IsSearchOnEntryAndBody()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* return NONE
+*  
+*  To check whether its search (search on TMsvEntry fields and/or body) query with sort on header
+*/ 
+TBool TSearchSortDbWrapper::IsSearchOnEntryAndBody(const CMsvSearchSortCacheEntry& aQuery)
+	{
+	TBool flag = EFalse;
+	
+	// to check whether its search query with sort on header
+	if(!aQuery.IsSortQuery() && iSortOnHeader)
+		{
+		// to check is search on TMsvEntry fields and/or body
+		switch(iTypeOfQuery)
+			{
+			case EQueryOnIndexEntry:
+			case EQueryOnBody:
+			case EQueryOnEntryAndBody:
+				flag = ETrue;
+				break;
+		
+			default:
+				flag = EFalse;
+			}
+		}
+	return flag;
+	}
+	
+
+/** 
+* CompareTMsvIds()
+*
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* @param DriveId: Drive information
+* return NONE
+*  
+*  Function to compare TMsvIds from IndexEntry table and Header table
+*/ 
+void TSearchSortDbWrapper::CompareTMsvIds(RBuf8& aQueryString, TUint aDriveId)
+	{
+	_LIT8(KHeader, "Header_");
+	_LIT8(KIndexEntry, "IndexEntry");
+	_LIT8(KOpenBracket, " ( ");
+	_LIT8(KCloseBracket, " ) ");
+	_LIT8(KDb, "DB");
+	_LIT8(KDot, ".");
+
+	// AND  ( DB(KCurrentDriveId).IndexEntry.id = DB(KCurrentDriveId).Header_268439593.id )
+	aQueryString.Append(KAnd);	
+	aQueryString.Append(KOpenBracket);
+				
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(aDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KIndexEntry);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KId);
+	aQueryString.Append(KEqualTo);
+				
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(aDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KHeader);
+	aQueryString.AppendNum(iHeaderTableForSort);
+
+	aQueryString.Append(KDot);
+	aQueryString.Append(KId);
+	
+	aQueryString.Append(KCloseBracket);
+	}
+
+
+/** 
+* UpdateQueryWithDriveNumAndHeaderTable()
+*
+* @param DriveId: Drive information
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Function to update query with header_table
+*/ 
+void TSearchSortDbWrapper::UpdateQueryWithDriveNumAndHeaderTable(TUint aDriveId, RBuf8& aQueryString)
+	{
+	_LIT8(KHeader, 	"Header_");
+	_LIT8(KDb, 		"DB");
+	_LIT8(KDot, 		".");
+
+	// DB(DriveId).Header_mtmid.
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(aDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KHeader);
+	aQueryString.AppendNum(iHeaderTableForSort);
+	aQueryString.Append(KDot);	
+	}
+
+/** 
+* CompareTMsvIds()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Function to compare TMsvIds from IndexEntry table and Header table
+*/ 
+void TSearchSortDbWrapper::CompareTMsvIds(RBuf8& aQueryString, TInt aIndex)
+	{
+	_LIT8(KHeader, "Header_");
+	_LIT8(KIndexEntry, "IndexEntry");
+	_LIT8(KDb, "DB");
+	_LIT8(KDot, ".");
+	
+				
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(KCurrentDriveId);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KIndexEntry);
+	aQueryString.Append(KDot);
+	aQueryString.Append(KId);
+	aQueryString.Append(KEqualTo);
+				
+	aQueryString.Append(KDb);
+	aQueryString.AppendNum(KCurrentDriveId);
+	aQueryString.Append(KDot);
+	
+	aQueryString.Append(KHeader);
+	aQueryString.AppendNum(iMtmIdArray[aIndex].iUid);
+
+	aQueryString.Append(KDot);
+	aQueryString.Append(KId);
+	}
+
+/** 
+* DoAddHeaderFields()
+*
+* @param aQuery: Contains SearchSort query information sent by the client
+* @param aQueryString: QueryString which will be prepared depending on SearchSort Query
+* return NONE
+*  
+*  Function to update query with search fields on header
+*/ 	
+void TSearchSortDbWrapper::DoAddHeaderFields(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TInt aIndex, TInt aMtmIdArrayIndex)
+	{
+	_LIT8(KTo, 	 "To");
+	_LIT8(KFrom, 	 "From");
+	_LIT8(KCc, 	 "Cc");
+	_LIT8(KBcc, 	 "Bcc");
+	_LIT8(KSubject, "Subject");
+	_LIT8(KDot, ".");
+	_LIT8(KOr, " OR ");
+		
+	switch (aQuery.iMsgQuery[aIndex].iMessagePart)
+		{
+		// Header and Body Parts are searched at client side using FindL
+		case EMsvTo:
+			{
+			if(iNumOfMsgParts)
+				{
+				if(iMtmIdArray.Count() > 1)
+					{
+					aQueryString.Append(KOr);
+					}
+				else
+					{
+					aQueryString.Append(KAnd);
+					}
+				}
+						
+			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
+			aQueryString.Append(KDot);
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KTo);
+			aQueryString.Append(KQuote);
+			
+			// update query for case sensitive or case insensitive serach
+			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
+			
+			iNumOfMsgParts++;	
+			}
+			break;
+			
+		case EMsvFrom:
+			{
+			if(iNumOfMsgParts)
+				{
+				if(iMtmIdArray.Count() > 1)
+					{
+					aQueryString.Append(KOr);
+					}
+				else
+					{
+					aQueryString.Append(KAnd);
+					}
+				}
+			
+			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
+			aQueryString.Append(KDot);
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KFrom);
+			aQueryString.Append(KQuote);
+			
+			// update query for case sensitive or case insensitive serach
+			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
+			
+			iNumOfMsgParts++;	
+			}
+			break;
+
+						
+		case EMsvCc:
+			{
+			if(iNumOfMsgParts)
+				{
+				if(iMtmIdArray.Count() > 1)
+					{
+					aQueryString.Append(KOr);
+					}	
+				else
+					{
+					aQueryString.Append(KAnd);
+					}
+				}
+						
+			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
+			aQueryString.Append(KDot);
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KCc);
+			aQueryString.Append(KQuote);
+			
+			// update query for case sensitive or case insensitive serach
+			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
+			
+			iNumOfMsgParts++;		
+			}
+			break;
+
+		case EMsvBcc:
+			{
+			if(iNumOfMsgParts)
+				{
+				if(iMtmIdArray.Count() > 1)
+					{
+					aQueryString.Append(KOr);
+					}
+				else
+					{
+					aQueryString.Append(KAnd);
+					}
+				}
+			
+			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
+			aQueryString.Append(KDot);
+			
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KBcc);
+			aQueryString.Append(KQuote);
+			
+			// update query for case sensitive or case insensitive serach
+			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
+			
+			iNumOfMsgParts++;		
+			}
+			break;
+						
+		case EMsvSubject:
+			{
+			if(iNumOfMsgParts)
+				{
+				if(iMtmIdArray.Count() > 1)
+					{
+					aQueryString.Append(KOr);
+					}
+				else
+					{
+					aQueryString.Append(KAnd);
+					}
+				}
+			
+			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
+			aQueryString.Append(KDot);
+
+			aQueryString.Append(KQuote);
+			aQueryString.Append(KSubject);
+			aQueryString.Append(KQuote);
+			
+			// update query for case sensitive or case insensitive serach
+			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
+						
+			iNumOfMsgParts++;		
+			}
+			break;
+		
+		default:
+			break;
+		}
+	}
+
+#endif  // SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB