messagingfw/msgsrvnstore/server/src/msvsearchsortdbwrapper.cpp
changeset 0 8e480a14352b
child 22 d2c4c66342f3
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // HEADER FILES
       
    15 // 
       
    16 //
       
    17  
       
    18  #include "msvsearchsortdbwrapper.h"
       
    19  #include "MSVSTD.H"
       
    20  #include "msvindexadapter.h"
       
    21  
       
    22  #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
    23  #include "MSVSERV.H"
       
    24  #endif
       
    25  
       
    26  const TInt KMaxQuerySize = 4000;
       
    27  const TInt KMaxInCount = 50;
       
    28  
       
    29  
       
    30 /**
       
    31  * LITERAL DEFINITION
       
    32  */
       
    33 _LIT8(KQuote, "\"");
       
    34 _LIT8(KComma, ", ");
       
    35 _LIT8(KAnd, " AND ");
       
    36 _LIT8(KLike, " LIKE ");
       
    37 _LIT8(KPercent, "%");
       
    38 _LIT8(KUnderScore, "_");
       
    39 _LIT8(KDescription, "description");	
       
    40 _LIT8(KDetails, "details");
       
    41 _LIT8(KDate, "date");
       
    42 _LIT8(KSize, "size");
       
    43 _LIT8(KMtmId, "mtmId");
       
    44 _LIT8(KType,"type");
       
    45 _LIT8(KCloseBrace, ")");
       
    46 _LIT8(KAscending," ASC");
       
    47 _LIT8(KDescending," DESC");
       
    48 _LIT8(KDelimiter,";");
       
    49 _LIT8(KOrderBy," ORDER by ");
       
    50 _LIT8(KBitwiseData,"data & ");
       
    51 _LIT8(KId, "id");
       
    52 _LIT8(KSelect, "SELECT ");
       
    53 #if (!defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
    54 _LIT8(KIdIn, "id IN(");
       
    55 #endif
       
    56 _LIT8(KWhere, " WHERE ");
       
    57 _LIT8(KNull, "NULL");
       
    58 
       
    59 _LIT8(KPrioritySort, "data & 3");
       
    60 _LIT8(KAttachmentSort, "data & 32768");
       
    61 _LIT8(KNewMsgSort, "data & 16");
       
    62 _LIT8(KUnReadSort, "data & 32");
       
    63 
       
    64 
       
    65 _LIT8(KIndexSortInsert, "INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield) ");
       
    66 
       
    67 _LIT8(KGreaterThan, " > ");
       
    68 _LIT8(KLessThan, " < ");
       
    69 _LIT8(KGreaterThanEqualTo," >= ");
       
    70 _LIT8(KLessThanEqualTo," <= ");
       
    71 _LIT8(KNotEqualTo," != ");
       
    72 _LIT8(KEqualTo, " = ");
       
    73 	
       
    74 
       
    75 
       
    76 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
    77 	_LIT8(KFromDb," FROM DB");
       
    78 	_LIT8(KIndexSortSelectRemovable, ".IndexEntry WHERE ");
       
    79 	_LIT8(KIndexSortSelectNoParentRemovable, ".IndexEntry ");
       
    80 	_LIT8(KIdQuerySelect, "SELECT DISTINCT id FROM DB");
       
    81 #else
       
    82 	_LIT8(KIdQuery, "SELECT DISTINCT id ");
       
    83 	_LIT8(KIdQueryNoParent, "SELECT DISTINCT id FROM IndexEntry ");
       
    84 	_LIT8(KIndexSortSelect, " FROM IndexEntry WHERE parentId = ");
       
    85 	_LIT8(KIndexSortSelectNoParent, " FROM IndexEntry ");
       
    86 #endif
       
    87 
       
    88 /**
       
    89  * TSearchSortDbWrapper
       
    90  */
       
    91 
       
    92 
       
    93 
       
    94 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
    95 
       
    96 TSearchSortDbWrapper* TSearchSortDbWrapper::NewL(CMsvServer& aServer)
       
    97 	{
       
    98 	//Create an Search sort db adaption object 
       
    99 	TSearchSortDbWrapper* self = new(ELeave) TSearchSortDbWrapper(aServer);
       
   100 	return self;
       
   101 	}
       
   102 
       
   103 TSearchSortDbWrapper::TSearchSortDbWrapper(CMsvServer& aServer) : iServer(aServer)
       
   104 	{
       
   105 	iDBadapter = iServer.Context().IndexAdapter()->GetDbAdapter();
       
   106 				 
       
   107 	iTotalCount = -1;
       
   108 	iProcessedIndexQueries = 0;
       
   109 	}
       
   110 
       
   111 void TSearchSortDbWrapper::CloseResources()
       
   112 	{
       
   113 	// relese the resources
       
   114 	iMtmIdArray.Close();	
       
   115 	}
       
   116 
       
   117 #else 	// SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB
       
   118 
       
   119 /**
       
   120  NewL()
       
   121 It returns an instance of TSearchSortDbWrapper class. 
       
   122 
       
   123 @param CMsvDBAdapter& aDBadapter: reference to CMsvDBAdapter Class.
       
   124 @return The newly created Msv DBadaption Object.
       
   125 @leave: KErrNone if successful or any of system wide leave codes if not.
       
   126 */
       
   127 TSearchSortDbWrapper* TSearchSortDbWrapper::NewL(CMsvDBAdapter& aDBadapter)
       
   128 	{
       
   129 	//Create an Search sort db adaption object 
       
   130 	TSearchSortDbWrapper* self = new(ELeave) TSearchSortDbWrapper(aDBadapter);
       
   131 	return self;
       
   132 	}
       
   133 
       
   134 /**
       
   135  TSearchSortDbWrapper()
       
   136 Constructor for the TSearchSortDbWrapper class.
       
   137 
       
   138 @param 	None.
       
   139 @return None.
       
   140 */
       
   141 TSearchSortDbWrapper::TSearchSortDbWrapper(CMsvDBAdapter& aDBadapter):iDBadapter(&aDBadapter), iTotalCount(-1), iProcessedIndexQueries(0)
       
   142 	{
       
   143 	}
       
   144 
       
   145 #endif // if (!defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   146 
       
   147 
       
   148 /** 
       
   149   FindL()
       
   150 Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the DB query
       
   151 and gets the resultant TMsvIds for the query so formed.
       
   152 
       
   153 @param CMsvSearchSortCacheEntry& aQuery:	Contains all the SearchSort related information(What to search on, what to search for).
       
   154 @param RArray<TMsvId>& aIdResult: RArray which holds the resultant TMsvIds.
       
   155 @param TBool aSortOnHeader: This specifies whether the sort field is a part of the Header(To, Bcc, Cc) or TMsvEntry(Date, Size, priority).
       
   156 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
   157 */ 
       
   158 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
   159 void TSearchSortDbWrapper::FindL(const CMsvSearchSortCacheEntry& aQuery, RArray<TMsvId>& aIdResult, const TBool aSortOnHeader, TInt aTypeOfQuery, TInt& aStatusOfQuery)
       
   160 #else
       
   161 void TSearchSortDbWrapper::FindL(const CMsvSearchSortCacheEntry& aQuery, RArray<TMsvId>& aIdResult, const TBool aSortOnHeader/*DEFAULT = EFalse*/)
       
   162 #endif
       
   163 	{
       
   164 	RBuf8 queryString;
       
   165 	queryString.CreateL(KMaxQuerySize);
       
   166 	queryString.CleanupClosePushL();
       
   167 	
       
   168 	RArray<TMsvId> folderIdList;
       
   169 	CleanupClosePushL(folderIdList);
       
   170 
       
   171 	TMsvId parentId;
       
   172 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   173 	parentId = UnmaskTMsvId(aQuery.iParentId);
       
   174 #else
       
   175 	parentId = aQuery.iParentId;
       
   176 #endif  
       
   177 	//Append the parentid on which the search/sort is intiated into the folder list
       
   178 	folderIdList.AppendL(parentId);
       
   179 
       
   180 	iSortOnHeader = aSortOnHeader;
       
   181 	
       
   182 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
   183 	iTypeOfQuery = aTypeOfQuery;
       
   184 	iTotalNumMsgPartsOnHeader = 0;
       
   185 	iNumOfMsgParts = 0;
       
   186 	
       
   187 	ParseQueryForHeaderFields(aQuery);
       
   188 #endif	
       
   189 	
       
   190 	for(TInt folderindex = 0; folderindex < folderIdList.Count(); ++folderindex)
       
   191 		{
       
   192 		//If subfolder search is enabled then all the subfolders under the parent and its 
       
   193 		// childrens are searched for a match.
       
   194 		if(aQuery.iSubFolderOption && parentId != KMsvRootIndexEntryIdValue)
       
   195 			{
       
   196 			iDBadapter->GetFolderIdsL(folderIdList[folderindex], folderIdList);	
       
   197 			}
       
   198 	
       
   199 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
   200 		// get MtmIds for corresponding parentId
       
   201 		TRAPD(error, ProcessPreQueryRequestL(folderIdList[folderindex], aStatusOfQuery));
       
   202 		
       
   203 		if(error == KErrArgument)
       
   204 			{
       
   205 			queryString.Delete(0,KMaxQuerySize);
       
   206 			continue;
       
   207 			}
       
   208 #endif
       
   209 		
       
   210 		//Create the SQLquery from the CMsvSearchSortCacheEntry and the parentid specified
       
   211 		CreateQueryL(aQuery, queryString, folderIdList[folderindex]);
       
   212 		
       
   213 		//If the sort is done on a Header specific part(To, Cc, Bcc), sortfield is not stored in DB
       
   214 		//It has to be fetched from client side, hence sending the TMsvIds to client without storing.
       
   215 		
       
   216 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
   217 		if(iStatusOfQuery == KNewQuery)
       
   218 #else
       
   219 		if(iSortOnHeader)
       
   220 #endif				
       
   221 			{
       
   222 			iDBadapter->SearchTMsvIdL(queryString, aIdResult);
       
   223 			}
       
   224 		//If the sort is done on a TMsvEntry specific part(size, date, mtmtype), sortfield is stored in DB
       
   225 		else  // (iStatusOfQuery == KPartialResult || iStatusOfQuery == KFinalResult)
       
   226 			{
       
   227 			iDBadapter->AddEntriesfromIndexTableL(queryString);
       
   228 			}
       
   229 		queryString.Delete(0,KMaxQuerySize);
       
   230 		}
       
   231 
       
   232 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
   233 	if(iStatusOfQuery == KPartialResult || iStatusOfQuery == KFinalResult)
       
   234 #else
       
   235 	if(!iSortOnHeader)
       
   236 #endif
       
   237 		{
       
   238 		//If the sort is done on a TMsvEntry fetch all the TMsvIds matching this query and pass it to client
       
   239 		iDBadapter->GetSearchSortEntriesL(aQuery.iQueryID, aIdResult, aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart));	
       
   240 		}
       
   241 	
       
   242 	iProcessedIndexQueries = 0;
       
   243 	CleanupStack::PopAndDestroy(&folderIdList);  // for folderIdList;
       
   244 	CleanupStack::PopAndDestroy(); // for  queryString;
       
   245 	}
       
   246 
       
   247 
       
   248 /** 
       
   249   UpdateNewIdsL()
       
   250 Depending on the CMsvSearchSortCacheEntry and the TMsvIds passed to this function it constructs the DB query
       
   251 and gets the resultant TMsvIds for the query so formed.
       
   252 
       
   253 @param CMsvSearchSortCacheEntry& aQuery:	Contains all the SearchSort related information(What to search on, what to search for).
       
   254 @param RArray<TMsvId>& aIdFilter: RArray holding the entries to be filtered with
       
   255 @param RArray<TMsvId>& aIdResult: RArray which holds the resultant TMsvIds.
       
   256 @param const TBool aSortOnHeader: This specifies whether the sort field is a part of the Header(To, Bcc, Cc) or TMsvEntry(Date, Size, priority).
       
   257 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
   258 */ 
       
   259 
       
   260 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
   261 void TSearchSortDbWrapper::UpdateNewIdsL(const CMsvSearchSortCacheEntry& aQuery,const RArray<TMsvId>& aIdFilter, RArray<TMsvId>& aIdResult,const TBool aSortOnHeader, TInt aTypeOfQuery, TInt& aStatusOfQuery)
       
   262 #else
       
   263 void TSearchSortDbWrapper::UpdateNewIdsL(const CMsvSearchSortCacheEntry& aQuery,const RArray<TMsvId>& aIdFilter, RArray<TMsvId>& aIdResult,const TBool aSortOnHeader/*DEFAULT = EFalse*/)
       
   264 #endif
       
   265 	{
       
   266 	if(aIdFilter.Count() != 0)
       
   267 		{
       
   268 		TInt idArrayCount = 0;
       
   269 		TInt initQuerySize = 0;
       
   270 		TInt idsAdded = 0;
       
   271 		
       
   272 		RBuf8 queryString;
       
   273 		queryString.CleanupClosePushL();
       
   274 		queryString.Create(KMaxQuerySize);
       
   275 		
       
   276 		//Folderlist for subfolder search
       
   277 		RArray<TMsvId> folderIdList;
       
   278 		TMsvId parentId;
       
   279 	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   280 		parentId = UnmaskTMsvId(aQuery.iParentId);
       
   281 	#else
       
   282 		parentId = aQuery.iParentId;
       
   283 	#endif  
       
   284 		//Append the parentid on which the search/sort is intiated into the folder list
       
   285 		folderIdList.Append(parentId);
       
   286 		
       
   287 		iSortOnHeader = aSortOnHeader;
       
   288 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
   289 		iTypeOfQuery = aTypeOfQuery;
       
   290 		iTotalNumMsgPartsOnHeader = 0;
       
   291 		iNumOfMsgParts = 0;
       
   292 		ParseQueryForHeaderFields(aQuery);
       
   293 #endif
       
   294 		
       
   295 		for(TInt folderindex = 0; folderindex < folderIdList.Count(); ++folderindex)
       
   296 			{
       
   297 			//If subfolder search is enabled then all the subfolders under the parent and its 
       
   298 			// childrens are searched for a match.
       
   299 			if(aQuery.iSubFolderOption && parentId != KMsvRootIndexEntryIdValue)
       
   300 			{
       
   301 			iDBadapter->GetFolderIdsL(folderIdList[folderindex], folderIdList);	
       
   302 			}
       
   303 
       
   304 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
   305 			// get MtmIds for corresponding parentId
       
   306 			ProcessPreQueryRequestL(folderIdList[folderindex], aStatusOfQuery);
       
   307 #endif
       
   308 			//Create the SQLquery from the CMsvSearchSortCacheEntry and the parentid specified
       
   309 			CreateQueryL(aQuery, queryString, folderIdList[folderindex], ETrue);
       
   310 			
       
   311 			//initQuerySize is made one less than entire size to remove the delimiter(;)
       
   312 			initQuerySize = queryString.Size()-1;
       
   313 			
       
   314 			//Reset Query string to Append New ID's
       
   315 			queryString.Delete(initQuerySize,KMaxQuerySize);
       
   316 			
       
   317 			if(iProcessedIndexQueries == 0 && folderIdList[folderindex] == KMsvRootIndexEntryIdValue)
       
   318 				{
       
   319 				queryString.Append(KWhere);
       
   320 				}
       
   321 			else
       
   322 				{
       
   323 				queryString.Append(KAnd);
       
   324 				}
       
   325 				
       
   326 			//initQuerySize
       
   327 			initQuerySize = queryString.Size();
       
   328 			
       
   329 			while(idArrayCount < aIdFilter.Count())
       
   330 				{
       
   331 				//Reset Query string to Append New ID's
       
   332 				queryString.Delete(initQuerySize,KMaxQuerySize);
       
   333 				
       
   334 				//Append Id's into the In statement
       
   335 				DoAppendIdConstraint(aIdFilter, queryString, idArrayCount);
       
   336 				//If the Sort is on Header, need not store the result as it doesnt have the sortfield
       
   337 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
   338 				if(iStatusOfQuery == KNewQuery)
       
   339 #else
       
   340 				if(iSortOnHeader)
       
   341 #endif	
       
   342 					{
       
   343 					iDBadapter->SearchTMsvIdL(queryString, aIdResult);
       
   344 					}
       
   345 				//If the Sort is on index we need to store the result and then send the id's
       
   346 				else
       
   347 					{
       
   348 					idsAdded += iDBadapter->AddEntriesfromIndexTableL(queryString);
       
   349 					}
       
   350 				}
       
   351 			iProcessedIndexQueries = 0;
       
   352 			idArrayCount = 0;
       
   353 			queryString.Delete(0,KMaxQuerySize);
       
   354 			}
       
   355 		
       
   356 		//Get only the updated results for this type of query
       
   357 		// not the previously stored results
       
   358 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
   359 		if(iStatusOfQuery == KNewQuery)
       
   360 #else
       
   361 		if (aQuery.iQueryType == ECombinedQuery && !aQuery.iSortOnHeader)
       
   362 #endif		
       
   363 			{
       
   364 			iDBadapter->GetLastNTMsvIdsfromTableL(aQuery.iQueryID, aIdResult, idsAdded,aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart));
       
   365 			}
       
   366 		
       
   367 		folderIdList.Close();
       
   368 		CleanupStack::PopAndDestroy();
       
   369 		}
       
   370 
       
   371 	//Get the final list of sorted ids from the SearchSortEntry table
       
   372 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   373 	if(iStatusOfQuery == KPartialResult || iStatusOfQuery == KFinalResult)
       
   374 #else
       
   375 	if(!iSortOnHeader)
       
   376 #endif
       
   377 		{
       
   378 		iDBadapter->GetSearchSortEntriesL(aQuery.iQueryID, aIdResult, aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart));	
       
   379 		}
       
   380 	}
       
   381 	
       
   382 	
       
   383 /** 
       
   384   CreateQueryL()
       
   385 Depending on the CMsvSearchSortCacheEntry and the TMsvIds passed to this function it constructs the DB query
       
   386 and gets the resultant TMsvIds for the query so formed.
       
   387 
       
   388 @param CMsvSearchSortCacheEntry&:	Contains all the SearchSort related information(What to search on, what to search for).
       
   389 @param RBuf8&: SQL query created depending on the CMsvSearchSortCacheEntry
       
   390 @param TMsvId& : ParentId on which the the search/sort is performed on
       
   391 @param TBool: This Specifies whether sorting is done on Header or TMsvEntry field
       
   392 @param TBool: This Specifies whether the sort option should be processed or not
       
   393 @leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported
       
   394 		 or any of system wide leave codes or SQL leave codes.
       
   395 @return none.
       
   396 */
       
   397 
       
   398 void TSearchSortDbWrapper::CreateQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, const TMsvId& aParentId, TBool aBypassSort)
       
   399 	{
       
   400 	// If sort field is on Index part, result should be stored on the DB
       
   401 	if(!iSortOnHeader) //it's on TMsvEntry
       
   402 		{
       
   403 		DoCreateInsertSortQueryL(aQuery, aQueryString, aParentId);
       
   404 		}
       
   405 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   406 	// If sort field is on Header part and if Header table/s is availble or partiallly available 
       
   407 	// result should be stored on the DB
       
   408 	else if(iSortOnHeader && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable))
       
   409 		{
       
   410 		DoCreateInsertSortOnHeaderQueryL(aQuery, aQueryString);
       
   411 		}
       
   412 #endif		
       
   413 	else
       
   414 		{
       
   415 		if(aParentId != KMsvRootIndexEntryIdValue)
       
   416 			{
       
   417 		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   418 			aQueryString.Append(KIdQuerySelect);
       
   419 			aQueryString.AppendNum(KCurrentDriveId);
       
   420 			aQueryString.Append(KIndexSortSelectRemovable);
       
   421 		#else
       
   422 			aQueryString.Append(KIdQuery);
       
   423 		#endif
       
   424 			}
       
   425 		else
       
   426 			{
       
   427 		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   428 			aQueryString.Append(KIdQuerySelect);
       
   429 			aQueryString.AppendNum(KCurrentDriveId);
       
   430 			aQueryString.Append(KIndexSortSelectNoParentRemovable);
       
   431 		#else
       
   432 			aQueryString.Append(KIdQueryNoParent);
       
   433 		#endif
       
   434 			} 
       
   435 	
       
   436 	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   437 		UpadeteQueryWithParentIdAndMsgType(aQueryString, KCurrentDriveId, aParentId);
       
   438 	#else
       
   439 		UpadeteQueryWithParentIdAndMsgType(aQueryString, aParentId);
       
   440 	#endif		
       
   441 		
       
   442 		}
       
   443 			
       
   444 	//Checks whether the query has a search part specified, 
       
   445 	//if yes then SQL query is created for the same
       
   446 	if(!aQuery.IsSortQuery())
       
   447 		{
       
   448 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
   449 		if((iTypeOfQuery & EQueryOnHeader) && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable ))
       
   450 			{
       
   451 			DoUpdateSearchQueryForHeaderFieldsL(aQuery, aQueryString, aParentId);
       
   452 			}
       
   453 		
       
   454 		if(iTypeOfQuery & EQueryOnIndexEntry)
       
   455 #endif		
       
   456 			{
       
   457 		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
       
   458 			UpdateQueryWithTMsvEntrySearchFieldsL(aQuery, aQueryString, KCurrentDriveId, aParentId);
       
   459 		#else
       
   460 			UpdateQueryWithTMsvEntrySearchFieldsL(aQuery, aQueryString, aParentId);
       
   461 		#endif
       
   462 			}
       
   463 		}
       
   464 	
       
   465 	//Checks whether the query has a sort part specified
       
   466 	//if yes then SQL query is created for the same
       
   467 	if ((aQuery.IsExplicitSortReq() || aQuery.IsSortQuery()) && !aBypassSort)
       
   468 		{
       
   469 		if(!iSortOnHeader)
       
   470 			{
       
   471 			DoCreateSortQueryL(aQuery, aQueryString);
       
   472 			}
       
   473 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)			
       
   474 		if(iSortOnHeader && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable))
       
   475 			{
       
   476 			UpdateQueryWithSortFieldL(aQuery, aQueryString, KCurrentDriveId);
       
   477 			}
       
   478 #endif			
       
   479 		}
       
   480 	
       
   481 	//Adds the delimiter(;)
       
   482 	aQueryString.Append(KDelimiter);
       
   483 
       
   484 	//Replaces Symbian WildCards(?, *) with SQL Wildcards (_, %)
       
   485 	if(aQuery.IsWildCharacter())
       
   486 		{
       
   487 		ReplaceWildCardCharacters(aQueryString,aQuery);
       
   488 		}
       
   489 	}
       
   490 
       
   491 /** 
       
   492   ReplaceWildCardCharacters()
       
   493 The Function replaces the '?' in the query with '_' and '*' in the string with a '%'.
       
   494 
       
   495 @param TDes8& aString: string on which the replace operation has to be done on.
       
   496 @return none.
       
   497 */
       
   498 void TSearchSortDbWrapper::ReplaceWildCardCharacters(TDes8& aString,const CMsvSearchSortCacheEntry& aQuery)
       
   499 	{
       
   500 	
       
   501 	for(TInt pos=0; pos < aString.Size(); pos++)
       
   502 		{
       
   503 		if(aString[pos] == '?')
       
   504 			{
       
   505 			aString.Replace(pos,1,KUnderScore);
       
   506 			}
       
   507 		else if(aString[pos] == '*')
       
   508 			{
       
   509 			if(!aQuery.IsCaseSensetive())
       
   510 			    aString.Replace(pos,1,KPercent);
       
   511 			}
       
   512 		}
       
   513 	}
       
   514 
       
   515 
       
   516 /** 
       
   517   DoAddRelationalOperatorL()
       
   518 The function Appends the required relational operator to the query string passed 
       
   519 	depending on the enum type specified
       
   520 
       
   521 @param RBuf8& aQuery: string on which the replace operation has to be done on.
       
   522 @param TMsvRelationOp aRelationOp: Relational operator which has to be appended to the string
       
   523 @return none.
       
   524 @leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
       
   525 */
       
   526 void TSearchSortDbWrapper::DoAddRelationalOperatorL(RBuf8& aQuery,TMsvRelationOp aRelationOp)
       
   527 	{
       
   528 	switch(aRelationOp)
       
   529 		{
       
   530 		case EMsvEqual:
       
   531 			{
       
   532 			aQuery.Append(KEqualTo);
       
   533 			break;
       
   534 			}
       
   535 			
       
   536 		case EMsvNotEqual:
       
   537 			{
       
   538 			aQuery.Append(KNotEqualTo);
       
   539 			break;							
       
   540 			}
       
   541 	
       
   542 		case EMsvLessThan:
       
   543 			{
       
   544 			aQuery.Append(KLessThan);
       
   545 			break;
       
   546 			}
       
   547 	
       
   548 		case EMsvGreaterThan:
       
   549 			{
       
   550 			aQuery.Append(KGreaterThan);
       
   551 			break;
       
   552 			}
       
   553 	
       
   554 		case EMsvLessThanOrEqual:
       
   555 			{
       
   556 			aQuery.Append(KLessThanEqualTo);
       
   557 			break;
       
   558 			}
       
   559 	
       
   560 		case EMsvGreaterThanOrEqual:
       
   561 			{
       
   562 			aQuery.Append(KGreaterThanEqualTo);
       
   563 			break;
       
   564 			}
       
   565 	
       
   566 		default:
       
   567 			{
       
   568 			User::Leave(KErrNotSupported);
       
   569 			}
       
   570 		}
       
   571 	}
       
   572 	
       
   573 
       
   574 /** 
       
   575   DoCreateSearchQueryL()
       
   576 Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the SQLDB search query.
       
   577 
       
   578 @param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
       
   579 @param RBuf8& aSearchQuery: The QueryString which will be prepared depending on CMsvSearchSortCacheEntry.
       
   580 @param TMsvId& aParentId: ParentId on which the the search/sort is performed on
       
   581 @return none.
       
   582 @leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
       
   583 */
       
   584 void TSearchSortDbWrapper::DoCreateSearchQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSearchQuery)
       
   585 	{
       
   586 
       
   587 	for(TInt index=0; index<aQuery.iMsgQuery.Count(); index++)
       
   588 		{
       
   589 		switch (aQuery.iMsgQuery[index].iMessagePart)
       
   590 			{
       
   591 			//Header and Body Parts are searched at client side using FindL
       
   592 			case EMsvTo:
       
   593 			case EMsvFrom:
       
   594 			case EMsvCc:
       
   595 			case EMsvBcc:
       
   596 			case EMsvSubject:
       
   597 			case EMsvBody:
       
   598 				{
       
   599 				break;
       
   600 				}
       
   601 			
       
   602 			//Index Entry Parts to be searched
       
   603 			//Search on Description
       
   604 			case EMsvDescription:
       
   605 				{
       
   606 				aSearchQuery.Append(KAnd);
       
   607 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   608 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   609 #endif				
       
   610 				aSearchQuery.Append(KDescription);
       
   611 				
       
   612 				// update query for case sensitive or case insensitive serach
       
   613 				IsCaseSensitiveSearch(aQuery, aSearchQuery, index);
       
   614 				
       
   615 				++iProcessedIndexQueries;
       
   616 				
       
   617 				break;
       
   618 				}
       
   619 			
       
   620 			//Search on Details
       
   621 			case EMsvDetails:
       
   622 				{
       
   623 				aSearchQuery.Append(KAnd);
       
   624 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   625 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   626 #endif				
       
   627 				aSearchQuery.Append(KDetails);
       
   628 				
       
   629 				// update query for case sensitive or case insensitive serach
       
   630 				IsCaseSensitiveSearch(aQuery, aSearchQuery, index);
       
   631 				
       
   632 				++iProcessedIndexQueries;
       
   633 				
       
   634 				break;
       
   635 				}
       
   636 				
       
   637 			//Search on Date
       
   638 			case EMsvDate:  
       
   639 				{
       
   640 				aSearchQuery.Append(KAnd);
       
   641 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   642 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   643 #endif				
       
   644 				TTime time;
       
   645 				User::LeaveIfError(time.Set(aQuery.iMsgQuery[index].iQueryString));
       
   646 				TInt64 date=time.Int64();
       
   647 				
       
   648 				aSearchQuery.Append(KDate);
       
   649 				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   650 				aSearchQuery.AppendNum(date);
       
   651 												
       
   652 				++iProcessedIndexQueries;
       
   653 				
       
   654 				break;
       
   655 				}
       
   656 				
       
   657 			//Search on Size	
       
   658 			case EMsvSize:
       
   659 				{
       
   660 				aSearchQuery.Append(KAnd);
       
   661 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   662 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   663 #endif				
       
   664 				aSearchQuery.Append(KSize);
       
   665 				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   666 				aSearchQuery.Append(aQuery.iMsgQuery[index].iQueryString);
       
   667 				
       
   668 				++iProcessedIndexQueries;
       
   669 				
       
   670 				break;
       
   671 				}
       
   672 				
       
   673 			//Search on Attachment Flag		
       
   674 			case EMsvAttachment:
       
   675 				{
       
   676 				aSearchQuery.Append(KAnd);
       
   677 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   678 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   679 #endif				
       
   680 				aSearchQuery.Append(KBitwiseData);
       
   681 				aSearchQuery.AppendNum(KMsvEntryAttachmentFlag);
       
   682 				//Entries Without attachment
       
   683 				if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("0")))
       
   684 					{
       
   685 					aSearchQuery.Append(KNotEqualTo);
       
   686 					}
       
   687 				//Entries With attachment
       
   688 				else
       
   689 					{
       
   690 					aSearchQuery.Append(KEqualTo);
       
   691 					}
       
   692 				aSearchQuery.AppendNum(KMsvEntryAttachmentFlag);
       
   693 				
       
   694 				++iProcessedIndexQueries;
       
   695 				
       
   696 				break;
       
   697 				}
       
   698 				
       
   699 			//Search on MTM type
       
   700 			case EMsvMtmTypeUID:
       
   701 				{					
       
   702 				aSearchQuery.Append(KAnd);
       
   703 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   704 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   705 #endif				
       
   706 				aSearchQuery.Append(KMtmId);
       
   707 				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   708 				aSearchQuery.Append(aQuery.iMsgQuery[index].iQueryString);
       
   709 				
       
   710 				++iProcessedIndexQueries;
       
   711 				
       
   712 				break;
       
   713 				}
       
   714 		
       
   715 			//Search on High Priority Flag
       
   716 			case EMsvPriority:
       
   717 				{
       
   718 				aSearchQuery.Append(KAnd);
       
   719 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   720 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   721 #endif				
       
   722 				aSearchQuery.Append(KBitwiseData);
       
   723 				
       
   724 				//Search on High Priority Flag
       
   725 				if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("0")))
       
   726 					{
       
   727 					aSearchQuery.AppendNum(KMsvEntryHighPriority);
       
   728 					DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   729 					aSearchQuery.AppendNum(KMsvEntryHighPriority);
       
   730 					}
       
   731 					
       
   732 				//Search on Normal Priority Flag
       
   733 				else if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("1")))
       
   734 					{
       
   735 					aSearchQuery.AppendNum(KMsvEntryMediumPriority);
       
   736 					DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   737 					aSearchQuery.AppendNum(KMsvEntryMediumPriority);
       
   738 					}
       
   739 					
       
   740 					//Search on Low Priority Flag	
       
   741 				else if(!aQuery.iMsgQuery[index].iQueryString.Compare(_L("2")))
       
   742 					{
       
   743 					aSearchQuery.AppendNum(KMsvEntryLowPriority);
       
   744 					DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   745 					aSearchQuery.AppendNum(0);
       
   746 					}
       
   747 				
       
   748 				++iProcessedIndexQueries;
       
   749 				
       
   750 				break;
       
   751 				}
       
   752 
       
   753 			//Search on UnRead Flag
       
   754 			case EMsvUnreadMessages:
       
   755 				{
       
   756 				aSearchQuery.Append(KAnd);
       
   757 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   758 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   759 #endif				
       
   760 				aSearchQuery.Append(KBitwiseData);
       
   761 				aSearchQuery.AppendNum(KMsvEntryUnreadFlag);
       
   762 				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   763 				aSearchQuery.AppendNum(KMsvEntryUnreadFlag);
       
   764 				
       
   765 				++iProcessedIndexQueries;
       
   766 				
       
   767 				break;
       
   768 				}
       
   769 				
       
   770 			//Search on New Message Flag			
       
   771 			case EMsvNew:
       
   772 				{
       
   773 				aSearchQuery.Append(KAnd);
       
   774 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)				
       
   775 				UpdateQueryWithDriveNumAndIndexEntryTable(aSearchQuery, KCurrentDriveId);
       
   776 #endif				
       
   777 				aSearchQuery.Append(KBitwiseData);
       
   778 				aSearchQuery.AppendNum(KMsvEntryNewFlag);
       
   779 				DoAddRelationalOperatorL(aSearchQuery,aQuery.iMsgQuery[index].iRelationOp);
       
   780 				aSearchQuery.AppendNum(KMsvEntryNewFlag);
       
   781 				
       
   782 				++iProcessedIndexQueries;
       
   783 				
       
   784 				break;
       
   785 				}
       
   786 				
       
   787 			default:
       
   788 				{
       
   789 				User::Leave(KErrNotSupported);	
       
   790 				}
       
   791 			}
       
   792 		}
       
   793 	}
       
   794 
       
   795 
       
   796 /** 
       
   797   DoCreateSortQueryL()
       
   798 Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the SQLDB sort query.
       
   799 
       
   800 @param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
       
   801 @param RBuf8& aSortQuery: The QueryString which will be prepared depending on CMsvSearchSortCacheEntry.
       
   802 @return none.
       
   803 @leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
       
   804 */
       
   805 void TSearchSortDbWrapper::DoCreateSortQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSortQuery )
       
   806 	{
       
   807 		
       
   808 	switch (aQuery.iMsgExplicitSortPart)
       
   809 		{
       
   810 			
       
   811 		//Index Entry Parts to be searched
       
   812 		//Sort on Description
       
   813 		case EMsvDescription:
       
   814 			{
       
   815 			aSortQuery.Append(KOrderBy);
       
   816 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   817 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   818 		#endif
       
   819 			aSortQuery.Append(KDescription);
       
   820 			if(aQuery.IsAscendingSort())
       
   821 				aSortQuery.Append(KAscending);
       
   822 			else
       
   823 				aSortQuery.Append(KDescending);
       
   824 			break;
       
   825 			}
       
   826 
       
   827 		//Sort on Details
       
   828 		case EMsvDetails:
       
   829 			{
       
   830 			aSortQuery.Append(KOrderBy);
       
   831 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   832 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   833 		#endif
       
   834 			aSortQuery.Append(KDetails);
       
   835 			if(aQuery.IsAscendingSort())
       
   836 				aSortQuery.Append(KAscending);
       
   837 			else
       
   838 				aSortQuery.Append(KDescending);
       
   839 			break;
       
   840 			}
       
   841 		
       
   842 		//Sort on Date
       
   843 		case EMsvDate:
       
   844 			{
       
   845 			aSortQuery.Append(KOrderBy);
       
   846 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   847 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   848 		#endif			
       
   849 			aSortQuery.Append(KDate);
       
   850 			if(aQuery.IsAscendingSort())
       
   851 				aSortQuery.Append(KAscending);
       
   852 			else
       
   853 				aSortQuery.Append(KDescending);
       
   854 			break;
       
   855 			}
       
   856 		
       
   857 		//Sort on Size
       
   858 		case EMsvSize:
       
   859 			{
       
   860 			aSortQuery.Append(KOrderBy);
       
   861 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   862 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   863 		#endif			
       
   864 			aSortQuery.Append(KSize);
       
   865 			if(aQuery.IsAscendingSort())
       
   866 				aSortQuery.Append(KAscending);
       
   867 			else
       
   868 				aSortQuery.Append(KDescending);
       
   869 			break;
       
   870 			}
       
   871 		
       
   872 		//Sort on MTM type
       
   873 		case EMsvMtmTypeUID:
       
   874 			{
       
   875 			aSortQuery.Append(KOrderBy);
       
   876 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   877 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   878 		#endif			
       
   879 			
       
   880 			aSortQuery.Append(KMtmId);
       
   881 			if(aQuery.IsAscendingSort())
       
   882 				aSortQuery.Append(KAscending);
       
   883 			else
       
   884 				aSortQuery.Append(KDescending);
       
   885 			break;
       
   886 			}
       
   887 			
       
   888 		//Sort on Priority Flag
       
   889 		case EMsvPriority:
       
   890 			{
       
   891 			aSortQuery.Append(KOrderBy);
       
   892 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   893 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   894 		#endif			
       
   895 			
       
   896 			aSortQuery.Append(KPrioritySort);
       
   897 			if(aQuery.IsAscendingSort())
       
   898 				aSortQuery.Append(KAscending);
       
   899 			else
       
   900 				aSortQuery.Append(KDescending);
       
   901 			break;
       
   902 			}
       
   903 		
       
   904 		case EMsvAttachment:
       
   905 			{
       
   906 			aSortQuery.Append(KOrderBy);
       
   907 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   908 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   909 		#endif			
       
   910 			
       
   911 			aSortQuery.Append(KAttachmentSort);
       
   912 			if(aQuery.IsAscendingSort())
       
   913 				aSortQuery.Append(KAscending);
       
   914 			else
       
   915 				aSortQuery.Append(KDescending);
       
   916 			break;
       
   917 			}
       
   918 			
       
   919 		case EMsvNew:
       
   920 			{
       
   921 			aSortQuery.Append(KOrderBy);
       
   922 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   923 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   924 		#endif			
       
   925 			
       
   926 			aSortQuery.Append(KNewMsgSort);
       
   927 			if(aQuery.IsAscendingSort())
       
   928 				aSortQuery.Append(KAscending);
       
   929 			else
       
   930 				aSortQuery.Append(KDescending);
       
   931 			break;
       
   932 			}
       
   933 			
       
   934 		case EMsvUnreadMessages:
       
   935 			{
       
   936 			aSortQuery.Append(KOrderBy);
       
   937 		#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   938 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   939 		#endif			
       
   940 			
       
   941 			aSortQuery.Append(KUnReadSort);
       
   942 			if(aQuery.IsAscendingSort())
       
   943 				aSortQuery.Append(KAscending);
       
   944 			else
       
   945 				aSortQuery.Append(KDescending);
       
   946 			break;
       
   947 			}
       
   948 			
       
   949 		case 0:
       
   950 			break;
       
   951 		
       
   952 		default:
       
   953 			{
       
   954 			User::Leave(KErrNotSupported);	
       
   955 			}
       
   956 		
       
   957 		}
       
   958 	}
       
   959 	
       
   960 /** 
       
   961   DoCreateInsertSortQueryL()
       
   962 Depending on the CMsvSearchSortCacheEntry passed to this function it constructs the SQLDB sort query.
       
   963 
       
   964 @param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
       
   965 @param RBuf8& aSortQuery: The QueryString which will be prepared depending on CMsvSearchSortCacheEntry.
       
   966 @param TMsvId& aParentId: ParentId on which the the search/sort is performed on
       
   967 @return none.
       
   968 @leave: KErrNone if successful, KErrNotSupported if the Search/Sort message passed is not supported.
       
   969 */	
       
   970 
       
   971 void TSearchSortDbWrapper::DoCreateInsertSortQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSortQuery, TMsvId aParentId)
       
   972 	{
       
   973 	aSortQuery.Append(KIndexSortInsert);
       
   974 	
       
   975 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
   976 	if(iMtmIdArray.Count() > 1)
       
   977 		{
       
   978 		// handled in UpdateQueryWithMultipleTablesL()
       
   979 		return;	
       
   980 		}
       
   981 	else
       
   982 #endif		
       
   983 		{
       
   984 		aSortQuery.Append(KSelect);
       
   985 		aSortQuery.AppendNum(aQuery.iQueryID);
       
   986 		aSortQuery.Append(KComma);
       
   987 
       
   988 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   989 		UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   990 #endif		
       
   991 		aSortQuery.Append(KId);
       
   992 		aSortQuery.Append(KComma);
       
   993 		
       
   994 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
       
   995 		if(aQuery.iMsgExplicitSortPart != 0)
       
   996 			{
       
   997 			UpdateQueryWithDriveNumAndIndexEntryTable(aSortQuery, KCurrentDriveId);
       
   998 			}
       
   999 #endif						
       
  1000 		UpdateQueryWithTMsvEntrySortFileldL(aQuery, aSortQuery);
       
  1001 
       
  1002 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)		
       
  1003 		TInt index = 0;
       
  1004 		if( iTypeOfQuery & EQueryOnIndexEntry )
       
  1005 			{
       
  1006 			UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
       
  1007 			
       
  1008 			if(iTypeOfQuery & EQueryOnHeader)
       
  1009 				{
       
  1010 				aSortQuery.Append(KComma);
       
  1011 				UpdateQueryWithHeaderTable(aSortQuery, KCurrentDriveId, iMtmIdArray[index].iUid);	
       
  1012 				}
       
  1013 
       
  1014 			if(aQuery.IsSortQuery())
       
  1015 				{
       
  1016 				aSortQuery.Append(KWhere);
       
  1017 				UpadeteQueryWithParentIdAndMsgType(aSortQuery, KCurrentDriveId, aParentId);	
       
  1018 				}
       
  1019 			}
       
  1020 		else if( (iTypeOfQuery & EQueryOnBody) && (iStatusOfQuery == KPartialResult) )
       
  1021 			{
       
  1022 			UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
       
  1023 			aSortQuery.Append(KWhere);
       
  1024 			UpadeteQueryWithParentIdAndMsgType(aSortQuery, KCurrentDriveId, aParentId);
       
  1025 			}
       
  1026 		else //iTypeOfQuery & EQueryOnHeader
       
  1027 			{
       
  1028 			UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
       
  1029 			aSortQuery.Append(KComma);
       
  1030 			UpdateQueryWithHeaderTable(aSortQuery, KCurrentDriveId, iMtmIdArray[index].iUid);	
       
  1031 			}
       
  1032 #else	
       
  1033 	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1034 		UpadeteQueryWithIndexEntryTable(aSortQuery, KCurrentDriveId);
       
  1035 		aSortQuery.Append(KWhere);
       
  1036 		UpadeteQueryWithParentIdAndMsgType(aSortQuery, KCurrentDriveId, aParentId);
       
  1037 	#else		
       
  1038 		UpadeteQueryWithParentIdAndMsgType(aSortQuery, aParentId);
       
  1039 	#endif
       
  1040 #endif	
       
  1041 		}
       
  1042 	
       
  1043 	}
       
  1044 	
       
  1045 
       
  1046 void TSearchSortDbWrapper::UpdateQueryWithTMsvEntrySortFileldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aSortQuery)
       
  1047 	{
       
  1048 	switch (aQuery.iMsgExplicitSortPart)
       
  1049 		{
       
  1050 		//Index Entry Parts to be searched
       
  1051 		//No Sort
       
  1052 		case 0:
       
  1053 			{
       
  1054 			aSortQuery.Append(KNull);
       
  1055 			break;
       
  1056 			}
       
  1057 		case EMsvDescription:
       
  1058 			{
       
  1059 			aSortQuery.Append(KDescription);
       
  1060 			break;
       
  1061 			}
       
  1062 
       
  1063 		case EMsvDetails:
       
  1064 			{
       
  1065 			aSortQuery.Append(KDetails);
       
  1066 			break;
       
  1067 			}
       
  1068 
       
  1069 		case EMsvDate:  
       
  1070 			{
       
  1071 			aSortQuery.Append(KDate);
       
  1072 			break;
       
  1073 			}
       
  1074 
       
  1075 		case EMsvSize:
       
  1076 			{
       
  1077 			aSortQuery.Append(KSize);
       
  1078 			break;
       
  1079 			}
       
  1080 
       
  1081 		case EMsvMtmTypeUID:
       
  1082 			{
       
  1083 			aSortQuery.Append(KMtmId);
       
  1084 			break;
       
  1085 			}
       
  1086 		
       
  1087 		case EMsvPriority:
       
  1088 			{
       
  1089 			aSortQuery.Append(KPrioritySort);
       
  1090 			break;
       
  1091 			}
       
  1092 			
       
  1093 		case EMsvAttachment:
       
  1094 			{
       
  1095 			aSortQuery.Append(KAttachmentSort);
       
  1096 			break;
       
  1097 			}
       
  1098 		
       
  1099 		case EMsvNew:
       
  1100 			{
       
  1101 			aSortQuery.Append(KNewMsgSort);
       
  1102 			break;
       
  1103 			}
       
  1104 			
       
  1105 		case EMsvUnreadMessages:
       
  1106 			{
       
  1107 			aSortQuery.Append(KUnReadSort);
       
  1108 			break;
       
  1109 			}
       
  1110 
       
  1111 		default:
       
  1112 			{
       
  1113 			User::Leave(KErrNotSupported);	
       
  1114 			}
       
  1115 		}
       
  1116 	}
       
  1117 	
       
  1118 /** 
       
  1119   AddIdtoDBL()
       
  1120 Adds the TMsvId's & sortfield specified in the RArray into the SearchSortEntry table under the query id specified
       
  1121 
       
  1122 @param TInt aQueryId: Query Id under which the entries should be added into the table
       
  1123 @param RArray<TMsvIdWithSortField>& aEntrySelection: TMsvId and sortfield which have to be added into the SearchSortEntry table
       
  1124 @return none.
       
  1125 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
  1126 */
       
  1127 void TSearchSortDbWrapper::AddIdtoDBL(const TInt aQueryId,const RArray<TMsvIdWithSortField>& aEntrySelection)
       
  1128 	{
       
  1129 	for(TInt index = 0; index < aEntrySelection.Count(); ++index)
       
  1130 		{
       
  1131 		iDBadapter->CreateQueryEntryL(aQueryId, aEntrySelection[index]);
       
  1132 		}
       
  1133 	}
       
  1134 
       
  1135 
       
  1136 /** 
       
  1137   GetSortedTMsvIdsfromTableL()
       
  1138 Retrieves all the entries from the SearchSortEntry table under the queryid specified
       
  1139 
       
  1140 @param TInt aQueryId: Query Id under which the entries should be fetched from the table
       
  1141 @param RArray<TMsvId>& aIdSelection: Resultant TMsvIds, retrieved from the SearchSortEntry table
       
  1142 @param TBool aOrder: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
       
  1143 @return none.
       
  1144 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
  1145 */
       
  1146 void TSearchSortDbWrapper::GetSortedTMsvIdsfromTableL(const TInt aQueryId, RArray<TMsvId>& aIdResult, TBool aOrder/*Default = EFalse*/,TMsvMessagePart aMessagePart /*Default = EMsvDate*/ )
       
  1147 	{
       
  1148 	iDBadapter->GetSearchSortEntriesL(aQueryId, aIdResult, aOrder, IsSortAsNumRequired(aMessagePart));	
       
  1149 	}
       
  1150 
       
  1151 /** 
       
  1152   DeleteTMsvIdFromQueryL()
       
  1153 Deletes the TMsvId's under the QueryId specified from the SearchSortEntry table
       
  1154 
       
  1155 @param TInt aQueryId: Query Id under which the entries should be deleted from the table
       
  1156 @param RArray<TMsvId>& aIdSelection: The TMsvId to be deleted 
       
  1157 @return none.
       
  1158 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
  1159 */
       
  1160 void TSearchSortDbWrapper::DeleteTMsvIdFromQueryL(const TInt aQueryId,const RArray<TMsvId>& aIdSelection)
       
  1161 	{
       
  1162 	TMsvId tid;
       
  1163 	for(TInt index = 0; index < aIdSelection.Count(); ++index)
       
  1164 		{
       
  1165 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1166 		tid = UnmaskTMsvId(aIdSelection[index]);
       
  1167 #else
       
  1168 		tid = aIdSelection[index];
       
  1169 #endif
       
  1170 		iDBadapter->DeleteTMsvIdFromQueryL(aQueryId, tid);
       
  1171 		//iDBadapter->DeleteTMsvIdFromQueryL(aQueryId, aIdSelection[index]);
       
  1172 		}
       
  1173 	}
       
  1174 
       
  1175 /** 
       
  1176   DeleteQueryFromTableL()
       
  1177 Deletes all the TMsvIds under the Query Id specified from the SearchSortEntry table
       
  1178 
       
  1179 @param TInt aQueryId: Query Id under which the entries should be deleted from the table
       
  1180 @return none.
       
  1181 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
  1182 */
       
  1183 void TSearchSortDbWrapper::DeleteQueryFromTableL(const TInt aQueryId)
       
  1184 	{
       
  1185 	iDBadapter->DeleteQueryFromTableL(aQueryId);
       
  1186 	}
       
  1187 
       
  1188 
       
  1189 /** 
       
  1190   DeleteQueryFromTableL()
       
  1191 Deletes the TMsvId's under the all QueryId from the SearchSortEntry table
       
  1192 
       
  1193 @param RArray<TMsvId>& aIdSelection: The TMsvId to be deleted 
       
  1194 @return none.
       
  1195 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
  1196 */
       
  1197 void TSearchSortDbWrapper::DeleteTMsvIdFromAllQueriesL(const RArray<TMsvId>& aIdSelection)
       
  1198 	{
       
  1199 	TMsvId tid;
       
  1200 	for(TInt index = 0; index < aIdSelection.Count(); ++index)
       
  1201 		{
       
  1202 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1203 		tid = UnmaskTMsvId(aIdSelection[index]);
       
  1204 #else
       
  1205 		tid = aIdSelection[index];
       
  1206 #endif
       
  1207 		iDBadapter->DeleteTMsvIdFromAllQueriesL(tid);
       
  1208 		//iDBadapter->DeleteTMsvIdFromAllQueriesL(aIdSelection[index]);
       
  1209 		}
       
  1210 	}
       
  1211 	
       
  1212 
       
  1213 /** 
       
  1214   ReturnResultCountInTableL()
       
  1215 Returns the number of TMsvIds stored under the QueryId specified
       
  1216 
       
  1217 @param TInt aQueryId: Query Id under which the entry count should be returned
       
  1218 @return none.
       
  1219 @leave: KErrNone if successful or any of system wide leave codes or SQL leave codes if not.
       
  1220 */
       
  1221 TInt TSearchSortDbWrapper::ReturnResultCountInTableL(const TInt aQueryId)
       
  1222 	{
       
  1223 	return iDBadapter->ReturnIdCountInDBL(aQueryId);
       
  1224 	}
       
  1225 	
       
  1226 /** 
       
  1227   DoAppendIdConstraint()
       
  1228 Appends the TMsvIds passed within the IN() SQL keyword to limit the search/sort capabilty only to these TMsvids.
       
  1229 
       
  1230 @param RArray<TMsvId>& aIdFilter:  RArray holding the entries to be used inside the IN() keyword
       
  1231 @param RBuf8& aSortQuery: This contains the SQL query having the IN() statement with the TMsvIds specified
       
  1232 @param TInt& aIdCount: This contains the index in from which the TMsvIds should be appended from the array,
       
  1233 				This also holds the number of entries appended after the operation is performed.
       
  1234 		
       
  1235 @return none.
       
  1236 */ 
       
  1237 void TSearchSortDbWrapper::DoAppendIdConstraint(const RArray<TMsvId>& aIdFilter, RBuf8& aSortQuery, TInt& aIdCount)
       
  1238 	{
       
  1239 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  1240 	_LIT8(KIndexEntryIdIn, ".IndexEntry.id IN(");
       
  1241 	_LIT8(KDb, 		"DB");
       
  1242 #endif
       
  1243 	
       
  1244 	if(aIdFilter.Count() == 0)
       
  1245 		{
       
  1246 		aSortQuery.Append(KDelimiter);
       
  1247 		}
       
  1248 	else
       
  1249 		{
       
  1250 		
       
  1251 		TInt index=0;
       
  1252 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
  1253 		aSortQuery.Append(KDb);
       
  1254 		aSortQuery.AppendNum(KCurrentDriveId);
       
  1255 		aSortQuery.Append(KIndexEntryIdIn);
       
  1256 #else		
       
  1257 		aSortQuery.Append(KIdIn);
       
  1258 #endif		
       
  1259 		
       
  1260 		for(index=aIdCount; (index < aIdCount+KMaxInCount) && (index < aIdFilter.Count()) ; ++index)
       
  1261 			{
       
  1262 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1263 			aSortQuery.AppendNum(UnmaskTMsvId(aIdFilter[index]));
       
  1264 #else			
       
  1265 			aSortQuery.AppendNum(aIdFilter[index]);
       
  1266 #endif			
       
  1267 			aSortQuery.Append(KComma);
       
  1268 			}
       
  1269 		//Delete the Last KComma
       
  1270 		aSortQuery.Delete(aSortQuery.Size()-2,KMaxQuerySize);
       
  1271 		aSortQuery.Append(KCloseBrace);
       
  1272 		aSortQuery.Append(KDelimiter);
       
  1273 		aIdCount = index;
       
  1274 		}
       
  1275 	}
       
  1276 
       
  1277 
       
  1278 /** 
       
  1279   IsSortAsNumRequired()
       
  1280 Returns whether the Specified message part requires sorting as TEXT or INT
       
  1281 
       
  1282 @param TMessagePart& aMessagePart: Sort Message part
       
  1283 @return TBool returns true if the TMessagePart is INT.
       
  1284 */ 
       
  1285 TBool TSearchSortDbWrapper::IsSortAsNumRequired(const TMsvMessagePart& aMessagePart)
       
  1286 	{
       
  1287 	
       
  1288 	switch(aMessagePart)
       
  1289 		{
       
  1290 		case EMsvDate:  
       
  1291 		case EMsvSize:
       
  1292 		case EMsvMtmTypeUID:
       
  1293 		case EMsvPriority:
       
  1294 			{
       
  1295 			return ETrue;	
       
  1296 			}
       
  1297 
       
  1298 		default:
       
  1299 			{
       
  1300 			return EFalse;	
       
  1301 			}
       
  1302 		}
       
  1303 		
       
  1304 	}
       
  1305 	
       
  1306 /** 
       
  1307   GetIdsInIterator()
       
  1308 This function should be used to retrieve TMsvIds in an iterative way.
       
  1309 The function maintains a counter which hold the last result count sent to the client.
       
  1310 The fuction executes the query from the start and returns the next result every time
       
  1311 
       
  1312 @param TUint32&: The Id of the Search/Sort Query
       
  1313 @param TInt    : The previous count in the result set that was accessed
       
  1314 @param TMsvId& : The result id		
       
  1315 @return void   
       
  1316 */ 
       
  1317 
       
  1318 void TSearchSortDbWrapper::GetIdsInIteratorQueryIdL(const TInt& aQueryId, const TBool aOrder/*Default = ETrue*/, TMsvMessagePart aMessagePart /*Default = EMsvDate*/, const TInt aLimit/*Default = 1*/)
       
  1319 	{
       
  1320 	//Get the total count of results
       
  1321 	iTotalCount=ReturnResultCountInTableL(aQueryId);
       
  1322 	iDBadapter->ReturnIdsInIteratorL(aQueryId, aOrder, IsSortAsNumRequired(aMessagePart), aLimit);
       
  1323 	iLocation = 0;
       
  1324 	}
       
  1325 
       
  1326 
       
  1327 /** 
       
  1328   GetIdsInIteratorNewQueryL()
       
  1329 @param aQuery  : Search/Sort query which has to be processed
       
  1330 @return NONE   
       
  1331 
       
  1332 Initialises iterator for a new query. It executes the query and stores the result in the DB.
       
  1333 Gets  total count of the result and initialises previous count to 0
       
  1334 */ 
       
  1335 
       
  1336 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB) 		
       
  1337 void TSearchSortDbWrapper::GetIdsInIteratorNewQueryL(const CMsvSearchSortCacheEntry& aQuery, TBool aSortOnHeader, TInt aTypeOfQuery, TInt& aReturnResultType,  const TInt aLimit)
       
  1338 #else 		
       
  1339 
       
  1340 void TSearchSortDbWrapper::GetIdsInIteratorNewQueryL(const CMsvSearchSortCacheEntry& aQuery, const TInt aLimit/*Default = 1*/)
       
  1341 #endif
       
  1342 	{
       
  1343 	// Create a new query, Execute that query, Store results
       
  1344 	RArray<TMsvId> iIteratorArray;
       
  1345 	
       
  1346 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
  1347 	FindL(aQuery, iIteratorArray, aSortOnHeader, aTypeOfQuery, aReturnResultType);
       
  1348 #else	
       
  1349 	FindL(aQuery,iIteratorArray,EFalse);
       
  1350 #endif	
       
  1351 	
       
  1352 	// Set total count
       
  1353 	iTotalCount=ReturnResultCountInTableL(aQuery.iQueryID);
       
  1354 	iLocation = 0;
       
  1355 	
       
  1356 	//Init the iterator
       
  1357 	iDBadapter->ReturnIdsInIteratorL(aQuery.iQueryID, aQuery.IsAscendingSort(), IsSortAsNumRequired(aQuery.iMsgExplicitSortPart), aLimit);
       
  1358 	
       
  1359 	//Destroy the Resultant Array
       
  1360 	iIteratorArray.Close();
       
  1361 	}
       
  1362 
       
  1363 /** 
       
  1364 * GetNextIdL()
       
  1365 @param aQueryId  : ID of the Search/Sort query which has to be processed
       
  1366 @param aId       : The next result
       
  1367 @return   KErrEof if the end of the result is reached
       
  1368 
       
  1369 Gets the next ID for a QueryId from the DB
       
  1370 */ 
       
  1371 void TSearchSortDbWrapper::GetNextIdL(TMsvId& aId, TInt& aRemainingCount)
       
  1372 	{
       
  1373 	User::LeaveIfError(iTotalCount);
       
  1374 	
       
  1375 	if(iTotalCount == 0)
       
  1376 		{
       
  1377 		aRemainingCount	= 0;
       
  1378 		aId = 0;
       
  1379 		User::LeaveIfError(iTotalCount = -1);
       
  1380 		}
       
  1381 		
       
  1382 	else if(iTotalCount == iLocation)
       
  1383 		{
       
  1384 		aRemainingCount	= 0;
       
  1385 		aId = 0;
       
  1386 		User::LeaveIfError(iTotalCount = -1);
       
  1387 		}
       
  1388 		
       
  1389 	else
       
  1390 		{
       
  1391 		iLocation = iDBadapter->GetNextL(aId);
       
  1392 		aRemainingCount = iTotalCount - iLocation;
       
  1393 		}
       
  1394 	}
       
  1395 
       
  1396 
       
  1397 /** 
       
  1398   GetDateRelationalOperator()
       
  1399 This function is used to add date field to the query being prepared
       
  1400 @param CMsvSearchSortCacheEntry& aQuery: Search/Sort query which has to be processed
       
  1401 @param TInt aCurrentIndex: The current index of query table
       
  1402 
       
  1403 @return void
       
  1404 */ 
       
  1405 TMsvRelationOp TSearchSortDbWrapper::GetDateRelationalOperator(const CMsvSearchSortCacheEntry& aQuery,TInt aCurrentIndex)
       
  1406 	{
       
  1407 	return(aQuery.iMsgQuery[aCurrentIndex].iRelationOp);
       
  1408 	}
       
  1409 
       
  1410 
       
  1411 /** 
       
  1412 * IsCaseSensitiveSearch()
       
  1413 *
       
  1414 * @param aQuery: Contains SearchSort query information sent by the client
       
  1415 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1416 * @param aIndex: index of query table 
       
  1417 * return NONE
       
  1418 *  
       
  1419 *  Function to update query with case sensitive or case insensitive serach
       
  1420 */ 	
       
  1421 void TSearchSortDbWrapper::IsCaseSensitiveSearch(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TInt aIndex)
       
  1422 	{
       
  1423 	_LIT8(KGlob, " GLOB ");
       
  1424 	_LIT8(KStar, "*");
       
  1425 
       
  1426 	if(aQuery.IsCaseSensetive())
       
  1427 		{
       
  1428 		aQueryString.Append(KGlob);
       
  1429 				
       
  1430 		aQueryString.Append(KQuote);
       
  1431 		aQueryString.Append(KStar);
       
  1432 		aQueryString.Append(aQuery.iMsgQuery[aIndex].iQueryString);
       
  1433 		aQueryString.Append(KStar);
       
  1434 		aQueryString.Append(KQuote);
       
  1435 		}
       
  1436 	else
       
  1437 		{
       
  1438 		aQueryString.Append(KLike);
       
  1439 			
       
  1440 		aQueryString.Append(KQuote);
       
  1441 		aQueryString.Append(KPercent);
       
  1442 		aQueryString.Append(aQuery.iMsgQuery[aIndex].iQueryString);
       
  1443 		aQueryString.Append(KPercent);
       
  1444 		aQueryString.Append(KQuote);	
       
  1445 		}
       
  1446 	}	
       
  1447 
       
  1448 
       
  1449 /** 
       
  1450 * UpdateQueryWithTMsvEntrySearchFieldsL()
       
  1451 *
       
  1452 * @param aQuery: Contains SearchSort query information sent by the client
       
  1453 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1454 * @param aDriveId: update query with Drive number 
       
  1455 * return NONE
       
  1456 *  
       
  1457 *  Update query with TMsvEntry Search field
       
  1458 */ 	
       
  1459 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
       
  1460 void TSearchSortDbWrapper::UpdateQueryWithTMsvEntrySearchFieldsL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId, TMsvId aParentId)
       
  1461 #else
       
  1462 void TSearchSortDbWrapper::UpdateQueryWithTMsvEntrySearchFieldsL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TMsvId aParentId)
       
  1463 #endif
       
  1464 	{
       
  1465 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  1466 	if(iMtmIdArray.Count() > 1)
       
  1467 		{
       
  1468 		if(iTypeOfQuery != EQueryOnHeaderAndBody && iTypeOfQuery != EQueryOnEntryHeaderAndBody)
       
  1469 			{
       
  1470 			UpdateQueryWithMultipleTablesL(aQuery, aQueryString, aDriveId, aParentId);
       
  1471 			}
       
  1472 		}
       
  1473 	else
       
  1474 		{
       
  1475 		if(!iTotalNumMsgPartsOnHeader)
       
  1476 			{
       
  1477 			aQueryString.Append(KWhere);
       
  1478 			UpadeteQueryWithParentIdAndMsgType(aQueryString, aDriveId, aParentId);
       
  1479 			}
       
  1480 #endif
       
  1481 	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1482 		aDriveId = aDriveId;    // to remove compilation warning, need to delete this line while removing macro SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB
       
  1483 	#endif	
       
  1484 		aParentId = aParentId;  // to remove compilation warning, need to delete this line while removing macro SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB
       
  1485 		
       
  1486 
       
  1487 		DoCreateSearchQueryL(aQuery, aQueryString);
       
  1488 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  1489 		}
       
  1490 #endif
       
  1491 	}
       
  1492 
       
  1493 
       
  1494 /** 
       
  1495 * UpadeteQueryWithParentIdAndMsgType()
       
  1496 *
       
  1497 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1498 * @param aDriveId: update query with Drive number 
       
  1499 * return NONE
       
  1500 *  
       
  1501 *  Update query with parentId and type as KUidMsvMessageEntryValue
       
  1502 */ 	
       
  1503 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1504 void TSearchSortDbWrapper::UpadeteQueryWithParentIdAndMsgType(RBuf8& aQueryString, TUint aDriveId, TMsvId aParentId)
       
  1505 #else
       
  1506 void TSearchSortDbWrapper::UpadeteQueryWithParentIdAndMsgType(RBuf8& aQueryString, TMsvId aParentId)
       
  1507 #endif
       
  1508 	{
       
  1509 	#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)	
       
  1510 	_LIT8(KIndexEntry, "IndexEntry");
       
  1511 	_LIT8(KParentId, 	"ParentId");
       
  1512 	_LIT8(KDb, 		"DB");
       
  1513 	_LIT8(KDot, 		".");
       
  1514 	#endif
       
  1515 	
       
  1516 	if(aParentId != KMsvRootIndexEntryIdValue)
       
  1517 		{
       
  1518 		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1519 			// DB(DriveId).IndexEntry.ParentId = ParentId AND DB(DriveId).IndexEntry.type = KUidMsvMessageEntryValue
       
  1520 			aQueryString.Append(KDb);
       
  1521 			aQueryString.AppendNum(aDriveId);
       
  1522 			aQueryString.Append(KDot);
       
  1523 			aQueryString.Append(KIndexEntry);
       
  1524 			aQueryString.Append(KDot);
       
  1525 			aQueryString.Append(KParentId);
       
  1526 			aQueryString.Append(KEqualTo);
       
  1527 			aQueryString.AppendNum(aParentId);
       
  1528 			
       
  1529 			aQueryString.Append(KAnd);
       
  1530 			
       
  1531 			UpdateQueryWithDriveNumAndIndexEntryTable(aQueryString, aDriveId);
       
  1532 			aQueryString.Append(KType);
       
  1533 			aQueryString.Append(KEqualTo);
       
  1534 			aQueryString.AppendNum(KUidMsvMessageEntryValue);
       
  1535 		#else // SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT
       
  1536 			aQueryString.Append(KIndexSortSelect);
       
  1537 			aQueryString.AppendNum(aParentId);
       
  1538 			
       
  1539 			aQueryString.Append(KAnd);
       
  1540 		
       
  1541 			aQueryString.Append(KType);
       
  1542 			aQueryString.Append(KEqualTo);
       
  1543 			aQueryString.AppendNum(KUidMsvMessageEntryValue);
       
  1544 		#endif
       
  1545 		}
       
  1546 	else
       
  1547 		{
       
  1548 		#if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1549 			aQueryString.Append(KType);
       
  1550 			aQueryString.Append(KEqualTo);
       
  1551 			aQueryString.AppendNum(KUidMsvMessageEntryValue);
       
  1552 		#else // SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT
       
  1553 			aQueryString.Append(KIndexSortSelectNoParent);
       
  1554 			aQueryString.Append(KWhere);
       
  1555 			aQueryString.Append(KType);
       
  1556 			aQueryString.Append(KEqualTo);
       
  1557 			aQueryString.AppendNum(KUidMsvMessageEntryValue);
       
  1558 		#endif
       
  1559 		}
       
  1560 	}
       
  1561 
       
  1562 /** 
       
  1563 * UpdateQueryWithHeaderTable()
       
  1564 *
       
  1565 * @param aQuery: Contains SearchSort query information sent by the client
       
  1566 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1567 * return NONE
       
  1568 *  
       
  1569 *  Update query with Header table
       
  1570 */ 
       
  1571 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1572 void TSearchSortDbWrapper::UpdateQueryWithDriveNumAndIndexEntryTable(RBuf8& aQueryString, TUint aDriveId)
       
  1573 	{
       
  1574 	_LIT8(KIndexEntry, "IndexEntry");
       
  1575 	_LIT8(KDb, 		"DB");
       
  1576 	_LIT8(KDot, 		".");
       
  1577 	
       
  1578 	// DB(DriveId).IndexEntry.
       
  1579 	aQueryString.Append(KDb);
       
  1580 	aQueryString.AppendNum(aDriveId);
       
  1581 	aQueryString.Append(KDot);
       
  1582 	aQueryString.Append(KIndexEntry);	
       
  1583 	aQueryString.Append(KDot);
       
  1584 
       
  1585 	}
       
  1586 	
       
  1587 /** 
       
  1588 * UpadeteQueryWithIndexEntryTable()
       
  1589 *
       
  1590 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1591 * @param aDriveId: update query with Drive number 
       
  1592 * return NONE
       
  1593 *  
       
  1594 *  Update the Query with IndexEntrytable 
       
  1595 */
       
  1596 void TSearchSortDbWrapper::UpadeteQueryWithIndexEntryTable(RBuf8& aQueryString, TUint aDriveId)
       
  1597 	{
       
  1598 	_LIT8(KIndexEntry, "IndexEntry");
       
  1599 	_LIT8(KDot, 		".");
       
  1600 	
       
  1601 	// FROM DB(aDriveId).IndexEntry
       
  1602 	aQueryString.Append(KFromDb);
       
  1603 	aQueryString.AppendNum(aDriveId);
       
  1604 	aQueryString.Append(KDot);
       
  1605 	aQueryString.Append(KIndexEntry);
       
  1606 	}
       
  1607 #endif // SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT
       
  1608 
       
  1609 
       
  1610 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
  1611 
       
  1612 /**
       
  1613  * ParseQueryForHeaderFields()
       
  1614  *
       
  1615  * @param aQuery: SearchSort query sent by client
       
  1616  * @return NONE
       
  1617  * 
       
  1618  * Function to parse the SearchSort query header filelds 
       
  1619  * to check wheather it exist it in DB
       
  1620  */
       
  1621 void TSearchSortDbWrapper::ParseQueryForHeaderFields(const CMsvSearchSortCacheEntry& aQuery)
       
  1622 	{
       
  1623 	iHeaderTableStdFields = 0;
       
  1624 	iTotalNumMsgPartsOnHeader = 0;
       
  1625 	
       
  1626 	for(TInt count = 0; count < aQuery.iMsgQuery.Count(); count++)
       
  1627 		{
       
  1628 		ParseCommonHederFilelds(aQuery.iMsgQuery[count].iMessagePart, ETrue);
       
  1629 		}
       
  1630 		
       
  1631 	ParseCommonHederFilelds(aQuery.iMsgExplicitSortPart, EFalse);
       
  1632 	}
       
  1633 
       
  1634 
       
  1635 /**
       
  1636  * ParseCommonHederFilelds()
       
  1637  *
       
  1638  * @param aMessagePart: Message part that availble SearchSort query
       
  1639  * @return NONE
       
  1640  * 
       
  1641  * Function to parse the SearchSort query header filelds 
       
  1642  * to check wheather it exist it in DB
       
  1643  */
       
  1644 void TSearchSortDbWrapper::ParseCommonHederFilelds(TMsvMessagePart aMessagePart, TBool aIsSearhField)
       
  1645 	{
       
  1646 	switch(aMessagePart)
       
  1647 		{
       
  1648 		case EMsvFrom:
       
  1649 			iHeaderTableStdFields |= CMsvHeaderStore::EFrom;
       
  1650 			if(aIsSearhField)
       
  1651 				{
       
  1652 				iTotalNumMsgPartsOnHeader++;
       
  1653 				}
       
  1654 			break;
       
  1655 		
       
  1656 		case EMsvTo:
       
  1657 			iHeaderTableStdFields |= CMsvHeaderStore::ETo;	
       
  1658 			if(aIsSearhField)
       
  1659 				{
       
  1660 				iTotalNumMsgPartsOnHeader++;
       
  1661 				}
       
  1662 			break;
       
  1663 			
       
  1664 		case EMsvCc:  
       
  1665 			iHeaderTableStdFields |= CMsvHeaderStore::ECC;	
       
  1666 			if(aIsSearhField)
       
  1667 				{
       
  1668 				iTotalNumMsgPartsOnHeader++;
       
  1669 				}
       
  1670 			break;
       
  1671 		
       
  1672 		case EMsvBcc:
       
  1673 			iHeaderTableStdFields |= CMsvHeaderStore::EBCC;	
       
  1674 			if(aIsSearhField)
       
  1675 				{
       
  1676 				iTotalNumMsgPartsOnHeader++;
       
  1677 				}
       
  1678 			break;
       
  1679 		
       
  1680 		case EMsvSubject:
       
  1681 			iHeaderTableStdFields |= CMsvHeaderStore::ESubject;	
       
  1682 			if(aIsSearhField)
       
  1683 				{
       
  1684 				iTotalNumMsgPartsOnHeader++;
       
  1685 				}
       
  1686 			break;
       
  1687 		
       
  1688 		default:
       
  1689 			break;
       
  1690 		}
       
  1691 	}
       
  1692 
       
  1693 /**
       
  1694  * ProcessPreQueryRequestL()
       
  1695  *
       
  1696  * @param aQuery: SearchSort query sent by client
       
  1697  * @return Status of the header table
       
  1698  * 
       
  1699  * Function to check wheather header table and correspnding standard column are availble at DB.  
       
  1700  * 
       
  1701  */
       
  1702 void TSearchSortDbWrapper::ProcessPreQueryRequestL(TMsvId aParentId, TInt& aStatusOfQuery) 	
       
  1703 	{
       
  1704 	TBool isOnEntry = EFalse;
       
  1705 	iHeaderTableAtDB = EInvalid;
       
  1706 	iBodyTableAtDB = EInvalid;
       
  1707 	
       
  1708 	switch(iTypeOfQuery)
       
  1709 		{
       
  1710 		case EQueryOnIndexEntry:
       
  1711 			isOnEntry = ETrue;
       
  1712 			break;
       
  1713 		
       
  1714 		case EQueryOnHeader:
       
  1715 		case EQueryOnEntryAndHeader:
       
  1716 			iHeaderTableAtDB = StatusOfHeaderTableL(aParentId);
       
  1717 			break;
       
  1718 
       
  1719 		case EQueryOnBody:
       
  1720 		case EQueryOnEntryAndBody:
       
  1721 			iBodyTableAtDB = ENotAvailable;
       
  1722 			break;
       
  1723 
       
  1724 		case EQueryOnHeaderAndBody:
       
  1725 		case EQueryOnEntryHeaderAndBody:
       
  1726 			iHeaderTableAtDB = StatusOfHeaderTableL(aParentId);
       
  1727 			iBodyTableAtDB = ENotAvailable;
       
  1728 			break;
       
  1729 		}
       
  1730 
       
  1731 	// if sort on header
       
  1732 	if(iSortOnHeader)
       
  1733 		{
       
  1734 		if(iHeaderTableAtDB == EInvalid)
       
  1735 			{
       
  1736 			iHeaderTableAtDB = StatusOfHeaderTableL(aParentId);
       
  1737 			}
       
  1738 		}
       
  1739 		
       
  1740 	// Query on TMsvEntry related fields
       
  1741 	if(isOnEntry && iHeaderTableAtDB == EInvalid && iBodyTableAtDB == EInvalid)
       
  1742 		{
       
  1743 		iStatusOfQuery = KFinalResult;
       
  1744 		}
       
  1745 	// Query on Header related fields	
       
  1746 	else if(iHeaderTableAtDB == EAvailable && iBodyTableAtDB == EInvalid )
       
  1747 		{
       
  1748 		iStatusOfQuery = KFinalResult;
       
  1749 		}
       
  1750 	// Query on Header and Body			
       
  1751 	else if(iHeaderTableAtDB == EAvailable && iBodyTableAtDB == ENotAvailable )
       
  1752 		{
       
  1753 		iStatusOfQuery = KPartialResult;
       
  1754 		}
       
  1755 	// Query on Header related fields (some of the Header the availble at DB and some of availble at file system )		
       
  1756 	else if(iHeaderTableAtDB == EPartiallyAvailable)
       
  1757 		{
       
  1758 		iStatusOfQuery = KPartialResult;
       
  1759 		}
       
  1760 	else if(iBodyTableAtDB == ENotAvailable && iTypeOfQuery == EQueryOnEntryAndBody)
       
  1761 	    {
       
  1762 	    iStatusOfQuery = KPartialResult;
       
  1763 	    }
       
  1764 
       
  1765 	// Header table not availbe in DB
       
  1766 	else if(iHeaderTableAtDB == ENotAvailable || iBodyTableAtDB == ENotAvailable)
       
  1767 		{
       
  1768 		// if search only on body, get all TMsvId from IndexEntry tbale and search at client side
       
  1769 		if(IsSearchQueryOnBody(ETrue))
       
  1770 			{
       
  1771 			iStatusOfQuery = KPartialResult;
       
  1772 			}
       
  1773 		else
       
  1774 			{
       
  1775 			iStatusOfQuery = KNewQuery;	
       
  1776 			}
       
  1777 		}
       
  1778 	else
       
  1779 		{
       
  1780 		User::Leave(KErrArgument);
       
  1781 		}
       
  1782 		
       
  1783 	aStatusOfQuery = iStatusOfQuery;
       
  1784 	}
       
  1785 
       
  1786 
       
  1787 /**
       
  1788  * StatusOfHeaderTableL()
       
  1789  *
       
  1790  * @param aQuery: SearchSort query sent by client
       
  1791  * @return Status of the header table
       
  1792  * 
       
  1793  * Function to check wheather header table and correspnding standard column are availble at DB.  
       
  1794  * 
       
  1795  */
       
  1796 TSearchSortDbWrapper::THeaderBodyTableStatusAtDb TSearchSortDbWrapper::StatusOfHeaderTableL(TMsvId aParentId)
       
  1797 	{
       
  1798  	
       
  1799  	// to get the MtmId 
       
  1800  	QueryToGetMtmIdsL(aParentId, KCurrentDriveId);
       
  1801  	
       
  1802  	THeaderBodyTableStatusAtDb tableStatus = EInvalid;
       
  1803  	
       
  1804  	for(TInt index=0; index < iMtmIdArray.Count(); ++index)
       
  1805 		{
       
  1806 		if(iServer.MessageDBAdapter().CheckHeaderTableAndStdColumnFields(iMtmIdArray[index], iHeaderTableStdFields))
       
  1807 			{
       
  1808 			if(tableStatus == ENotAvailable || tableStatus == EPartiallyAvailable)
       
  1809 				{
       
  1810 				tableStatus = EPartiallyAvailable;
       
  1811 				}
       
  1812 			else
       
  1813 				{
       
  1814 				tableStatus = EAvailable;	
       
  1815 				}
       
  1816 			}
       
  1817 		else
       
  1818 			{
       
  1819 			iMtmIdArray.Remove(index--);
       
  1820 					
       
  1821 			if(tableStatus == EAvailable || tableStatus == EPartiallyAvailable)
       
  1822 				{
       
  1823 				tableStatus = EPartiallyAvailable;
       
  1824 				}
       
  1825 			else
       
  1826 				{
       
  1827 				tableStatus = ENotAvailable;
       
  1828 				}
       
  1829 			}
       
  1830 		}
       
  1831 	return tableStatus;
       
  1832 	}
       
  1833  	
       
  1834 
       
  1835  
       
  1836 /** 
       
  1837 * QueryToGetMtmIdsL()
       
  1838 *
       
  1839 * @param aQuery: SearchSort query information sent by client
       
  1840 * @param aDriveId:  drive number
       
  1841 * @leave: KErrNone if successful or SQL leave codes if not.
       
  1842 *  
       
  1843 *  To get MtmId/s for corresponding query
       
  1844 */ 
       
  1845 void TSearchSortDbWrapper::QueryToGetMtmIdsL(TMsvId aParentId, TUint aDriveId)
       
  1846 	{
       
  1847 	_LIT8(KIdQueryForMtmId, "SELECT DISTINCT mtmId FROM DB");
       
  1848 	_LIT8(KIndexEntryWhereParentId, ".IndexEntry WHERE parentId = ");
       
  1849 	
       
  1850 	RBuf8 queryString;
       
  1851 	queryString.CleanupClosePushL();
       
  1852 	
       
  1853 	queryString.CreateL(KMaxQuerySize);
       
  1854 	
       
  1855 	iMtmIdArray.Reset();
       
  1856 	
       
  1857 	//Query string is: SELECT DISTINCT mtmid FROM DB driveid.IndexEntry WHERE parentid=aQuery.parentId;
       
  1858 	queryString.Append(KIdQueryForMtmId);
       
  1859 	queryString.AppendNum(aDriveId);
       
  1860 	queryString.Append(KIndexEntryWhereParentId);
       
  1861 	queryString.AppendNum(aParentId);
       
  1862 	queryString.Append(KDelimiter);
       
  1863 
       
  1864 	iDBadapter->GetMtmIdsL(queryString, iMtmIdArray);
       
  1865 	
       
  1866 	CleanupStack::PopAndDestroy();  //queryString
       
  1867 	}
       
  1868 	
       
  1869 
       
  1870 /** 
       
  1871 * DoCreateInsertSortOnHeaderQueryL()
       
  1872 *
       
  1873 * @param aQuery: SearchSort query information sent by client
       
  1874 * @param aQueryString:  Querystring to execute on DB
       
  1875 * return NONE
       
  1876 *  
       
  1877 *  Update query with sort information
       
  1878 */ 
       
  1879 void TSearchSortDbWrapper::DoCreateInsertSortOnHeaderQueryL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString)
       
  1880 	{
       
  1881 	_LIT8(KDot, 		".");
       
  1882 
       
  1883 	// INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield) SELECT iQueryID, DB1.IndexEntry.id, DB1.Header_268439594."To" FROM DB1.IndexEntry, DB1.Header_268439594 
       
  1884 	
       
  1885 	UpdateQueryWithSearchSortEntryTable(aQueryString);
       
  1886 	
       
  1887 	// if searching on more than one header table
       
  1888 	if(iMtmIdArray.Count() > 1)
       
  1889 		{
       
  1890 		// handled in UpdateQueryWithMultipleTablesL()
       
  1891 		return;	
       
  1892 		}
       
  1893 	else  // search query on single table
       
  1894 		{
       
  1895 		UpdateQueryToGetQueryIdTMsvId(aQuery, aQueryString, KCurrentDriveId);
       
  1896 		
       
  1897 		TInt index = 0;
       
  1898 		if(iMtmIdArray.Count() == 1 )
       
  1899 			{
       
  1900 			// ,DB(DriveId).Header_268439594."To"
       
  1901 			aQueryString.Append(KComma);
       
  1902 			iHeaderTableForSort = iMtmIdArray[index].iUid;
       
  1903 			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[index].iUid);
       
  1904 			aQueryString.Append(KDot);
       
  1905 			}
       
  1906 		// update sort filed	
       
  1907 		UpdateHeaderFieldL(aQuery, aQueryString);	
       
  1908 		DoUpdateQuery(aQueryString);	
       
  1909 		}
       
  1910 	}
       
  1911 
       
  1912 
       
  1913 /** 
       
  1914 * UpdateQueryWithSearchSortEntryTable()
       
  1915 *
       
  1916 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1917 * return NONE
       
  1918 *  
       
  1919 *  Update Query With SearchSortEntry Table
       
  1920 */ 
       
  1921 void TSearchSortDbWrapper::UpdateQueryWithSearchSortEntryTable(RBuf8& aQueryString)
       
  1922 	{
       
  1923 	// INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield)
       
  1924 	aQueryString.Append(KIndexSortInsert);
       
  1925 	}
       
  1926 
       
  1927 
       
  1928 
       
  1929 /** 
       
  1930 * UpdateQueryToGetQueryIdTMsvId()
       
  1931 *
       
  1932 * @param aQuery: Contains SearchSort query information sent by client
       
  1933 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1934 * return NONE
       
  1935 *  
       
  1936 *  Update Query to get TMsvIds
       
  1937 */ 
       
  1938 void TSearchSortDbWrapper::UpdateQueryToGetQueryIdTMsvId(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
       
  1939 	{
       
  1940 	_LIT8(KIndexEntry, "IndexEntry");
       
  1941 	_LIT8(KDb, 		"DB");
       
  1942 	_LIT8(KDot, 		".");
       
  1943 
       
  1944 	// SELECT iQueryID, IndexEntry.id,
       
  1945 	aQueryString.Append(KSelect);
       
  1946 	aQueryString.AppendNum(aQuery.iQueryID);
       
  1947 	
       
  1948 	// ,DB1.IndexEntry.id
       
  1949 	aQueryString.Append(KComma);
       
  1950 	aQueryString.Append(KDb);
       
  1951 	aQueryString.AppendNum(aDriveId);
       
  1952 	aQueryString.Append(KDot);
       
  1953 	aQueryString.Append(KIndexEntry);
       
  1954 	aQueryString.Append(KDot);
       
  1955 	aQueryString.Append(KId);
       
  1956 	}	
       
  1957 
       
  1958 
       
  1959 /** 
       
  1960 * UpdateQueryWithMultipleTablesL()
       
  1961 *
       
  1962 * @param aQuery: Contains SearchSort query information sent by the client
       
  1963 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  1964 * return NONE
       
  1965 *  
       
  1966 * Function to update the query for more than one Header table and/or multilevel query
       
  1967 *
       
  1968 * Example Query:
       
  1969 *	
       
  1970 * INSERT OR IGNORE INTO SearchSortEntry (Qid, id, sortfield) 
       
  1971 * SELECT 1001, DB1.IndexEntry.id, DB1.Header_268439592."To" FROM DB1.IndexEntry, DB1.Header_268439592 WHERE  ( DB1.IndexEntry.id = DB1.Header_268439592.id AND  
       
  1972 * ( 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" )  )  
       
  1973 * AND DB1.Header_268439592."To" IS NOT NULL  AND DB1.IndexEntry.ParentId = 4101 AND DB1.IndexEntry.type = 268439402 
       
  1974 *
       
  1975 * UNION 
       
  1976 *
       
  1977 * SELECT 1001, DB1.IndexEntry.id, DB1.Header_268439593."To" FROM DB1.IndexEntry, DB1.Header_268439593 WHERE  ( DB1.IndexEntry.id = DB1.Header_268439593.id AND  
       
  1978 * ( 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" )  )  
       
  1979 * AND DB1.Header_268439593."To" IS NOT NULL  AND DB1.IndexEntry.ParentId = 4101 AND DB1.IndexEntry.type = 268439402 
       
  1980 *
       
  1981 * ORDER by "To" ASC;
       
  1982 */ 	
       
  1983 void TSearchSortDbWrapper::UpdateQueryWithMultipleTablesL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId, TMsvId aParentId)
       
  1984 	{
       
  1985 	_LIT8(KUnion, " UNION ");
       
  1986 	_LIT8(KIsNotNull, " IS NOT NULL ");
       
  1987 	_LIT8(KOpenBracket, " ( ");
       
  1988 	_LIT8(KCloseBracket, " ) ");
       
  1989 	_LIT8(KDot, ".");
       
  1990 	
       
  1991 	// for multiple tables
       
  1992 	for(TInt index = 0; index < iMtmIdArray.Count(); ++index)
       
  1993 		{
       
  1994 		// reset for other header table
       
  1995 		iNumOfMsgParts = 0;
       
  1996 		
       
  1997 		// SELECT 1001, IndexEntry.id, 
       
  1998 		UpdateQueryToGetQueryIdTMsvId(aQuery, aQueryString, aDriveId);
       
  1999 		aQueryString.Append(KComma);
       
  2000 		if(iSortOnHeader)
       
  2001 			{
       
  2002 			// Header_268439594."To"
       
  2003 			UpdateQueryWithHeaderTable(aQueryString, aDriveId, iMtmIdArray[index].iUid);
       
  2004 			aQueryString.Append(KDot);
       
  2005 			UpdateHeaderFieldL(aQuery, aQueryString);
       
  2006 			}
       
  2007 		else
       
  2008 			{
       
  2009 			// IndexEntry.size
       
  2010 			if(aQuery.iMsgExplicitSortPart != 0)
       
  2011 				{
       
  2012 				UpdateQueryWithDriveNumAndIndexEntryTable(aQueryString, aDriveId);
       
  2013 				}
       
  2014 			UpdateQueryWithTMsvEntrySortFileldL(aQuery, aQueryString);
       
  2015 			}
       
  2016 	
       
  2017 		// Header_268439594."To"  FROM IndexEntry, Header_268439594			
       
  2018 		UpadeteQueryWithIndexEntryTable(aQueryString, aDriveId);
       
  2019 		aQueryString.Append(KComma);
       
  2020 		UpdateQueryWithHeaderTable(aQueryString, aDriveId, iMtmIdArray[index].iUid);
       
  2021 			
       
  2022 		// WHERE (IndexEntry.id = Header_268439594.id AND Header_268439594."To" LIKE "%test002@10.253.4.75%")
       
  2023 		aQueryString.Append(KWhere);
       
  2024 		aQueryString.Append(KOpenBracket);
       
  2025 		
       
  2026 		// compare TMsvId of IndexEntry table and Header table
       
  2027 		CompareTMsvIds(aQueryString, index);
       
  2028 			
       
  2029 		// if search on header fileld
       
  2030 		if( (iTypeOfQuery & EQueryOnHeader) && !aQuery.IsSortQuery())
       
  2031 			{
       
  2032 			aQueryString.Append(KAnd);
       
  2033 			
       
  2034 			// inner open bracket, if search needs more than one header field
       
  2035 			if(iTotalNumMsgPartsOnHeader > 1)
       
  2036 				{
       
  2037 				aQueryString.Append(KOpenBracket);	
       
  2038 				}
       
  2039 			
       
  2040 			// multilevel query on single header table.
       
  2041 			for(TInt queryCount=0; queryCount < aQuery.iMsgQuery.Count(); ++queryCount)
       
  2042 				{
       
  2043 				DoAddHeaderFields(aQuery, aQueryString, queryCount, index);
       
  2044 				}
       
  2045 				
       
  2046 			// inner close bracket, if search needs more than one header field
       
  2047 			if(iTotalNumMsgPartsOnHeader > 1)
       
  2048 				{
       
  2049 				aQueryString.Append(KCloseBracket);	
       
  2050 				}
       
  2051 
       
  2052 			aQueryString.Append(KCloseBracket);
       
  2053 			}
       
  2054 		else
       
  2055 			{
       
  2056 			aQueryString.Append(KCloseBracket);	
       
  2057 			}
       
  2058 			
       
  2059 		// update Query with search field
       
  2060 		aQueryString.Append(KAnd);
       
  2061 		if(iSortOnHeader)
       
  2062 			{
       
  2063 			UpdateQueryWithHeaderTable(aQueryString, aDriveId, iMtmIdArray[index].iUid);
       
  2064 			aQueryString.Append(KDot);
       
  2065 			UpdateHeaderFieldL(aQuery, aQueryString);
       
  2066 			aQueryString.Append(KIsNotNull);
       
  2067 			aQueryString.Append(KAnd);
       
  2068 			}
       
  2069 					
       
  2070 		// Update Query with ParentId and MsgType
       
  2071 		// IndexEntry.ParentId = 4098 AND IndexEntry.type = 268439402
       
  2072 		UpadeteQueryWithParentIdAndMsgType(aQueryString, aDriveId, aParentId);
       
  2073 				
       
  2074 		if(iTypeOfQuery & EQueryOnIndexEntry)
       
  2075 			{
       
  2076 			DoCreateSearchQueryL(aQuery, aQueryString);
       
  2077 			}
       
  2078 				
       
  2079 		// add UNION
       
  2080 		if((index+1 ) != iMtmIdArray.Count())
       
  2081 			{
       
  2082 			aQueryString.Append(KUnion);	
       
  2083 			}
       
  2084 		} //end of for
       
  2085 	}
       
  2086 
       
  2087 
       
  2088 /** 
       
  2089 * UpdateHeaderFieldL()
       
  2090 *
       
  2091 * @param aQuery: Contains SearchSort query information sent by the client
       
  2092 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2093 * return NONE
       
  2094 *  
       
  2095 *  Update query with Header filed
       
  2096 */ 
       
  2097 void TSearchSortDbWrapper::UpdateHeaderFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString)
       
  2098 	{
       
  2099 	
       
  2100 	_LIT8(KTo, 	 "To");
       
  2101 	_LIT8(KFrom, 	 "From");
       
  2102 	_LIT8(KCc, 	 "Cc");
       
  2103 	_LIT8(KBcc, 	 "Bcc");
       
  2104 	_LIT8(KSubject, "Subject");
       
  2105 	
       
  2106 	// to add header field
       
  2107 	switch (aQuery.iMsgExplicitSortPart)
       
  2108 		{
       
  2109 		//Sort to be done on Header fields
       
  2110 		case EMsvTo:
       
  2111 			aQueryString.Append(KQuote);
       
  2112 			aQueryString.Append(KTo);
       
  2113 			aQueryString.Append(KQuote);
       
  2114 			break;
       
  2115 			
       
  2116 		case EMsvFrom:
       
  2117 			aQueryString.Append(KQuote);
       
  2118 			aQueryString.Append(KFrom);
       
  2119 			aQueryString.Append(KQuote);
       
  2120 			break;
       
  2121 			
       
  2122 		case EMsvCc:  
       
  2123 			aQueryString.Append(KQuote);
       
  2124 			aQueryString.Append(KCc);
       
  2125 			aQueryString.Append(KQuote);
       
  2126 			break;
       
  2127 			
       
  2128 		case EMsvBcc:
       
  2129 			aQueryString.Append(KQuote);
       
  2130 			aQueryString.Append(KBcc);
       
  2131 			aQueryString.Append(KQuote);
       
  2132 			break;
       
  2133 			
       
  2134 		case EMsvSubject:
       
  2135 			aQueryString.Append(KQuote);
       
  2136 			aQueryString.Append(KSubject);
       
  2137 			aQueryString.Append(KQuote);
       
  2138 			break;
       
  2139 			
       
  2140 		case EMsvBody:
       
  2141 		default:
       
  2142 			{
       
  2143 			User::Leave(KErrNotSupported);	
       
  2144 			}
       
  2145 		}
       
  2146 	}	
       
  2147 
       
  2148 /** 
       
  2149 * DoUpdateQuery()
       
  2150 *
       
  2151 * @param aQuery: Contains SearchSort query information sent by the client
       
  2152 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2153 * return NONE
       
  2154 *  
       
  2155 *  Update query with IndexEntry and Header table
       
  2156 */ 
       
  2157 void TSearchSortDbWrapper::DoUpdateQuery(RBuf8& aQueryString)
       
  2158 	{
       
  2159 	
       
  2160 	// FROM DB(aDriveId).IndexEntry, 
       
  2161 	UpadeteQueryWithIndexEntryTable(aQueryString, KCurrentDriveId);
       
  2162 	aQueryString.Append(KComma);
       
  2163 	
       
  2164 	TInt index = 0;
       
  2165 	if( iMtmIdArray.Count() == 1 )
       
  2166 		{
       
  2167 		if(((iTypeOfQuery & EQueryOnHeader) || iSortOnHeader) && (iHeaderTableAtDB == EAvailable || iHeaderTableAtDB == EPartiallyAvailable))
       
  2168 			{
       
  2169 			// ,DB(DriveId).Header_268439594
       
  2170 			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[index].iUid);
       
  2171 			}
       
  2172 		}
       
  2173 	}
       
  2174 
       
  2175 
       
  2176 /** 
       
  2177 * UpdateQueryWithHeaderTable()
       
  2178 *
       
  2179 * @param aQuery: Contains SearchSort query information sent by the client
       
  2180 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2181 * return NONE
       
  2182 *  
       
  2183 *  Update query with Header table
       
  2184 */ 
       
  2185 void TSearchSortDbWrapper::UpdateQueryWithHeaderTable(RBuf8& aQueryString, TUint aDriveId, TInt32 aMtmId)
       
  2186 	{
       
  2187 	_LIT8(KHeader, 	"Header_");
       
  2188 	_LIT8(KDb, 		"DB");
       
  2189 	_LIT8(KDot, 		".");
       
  2190 	
       
  2191 	// DB(DriveId).Header_268439594
       
  2192 	aQueryString.Append(KDb);
       
  2193 	aQueryString.AppendNum(aDriveId);
       
  2194 	aQueryString.Append(KDot);
       
  2195 	aQueryString.Append(KHeader);
       
  2196 	aQueryString.AppendNum(aMtmId);
       
  2197 	}	
       
  2198 
       
  2199 
       
  2200 /** 
       
  2201 * DoUpdateSearchQueryForHeaderFieldsL()
       
  2202 *
       
  2203 * @param aQuery: Contains SearchSort query information sent by the client
       
  2204 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2205 * return NONE
       
  2206 *  
       
  2207 *  Update query with header fields
       
  2208 */ 
       
  2209 void TSearchSortDbWrapper::DoUpdateSearchQueryForHeaderFieldsL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TMsvId aParentId)
       
  2210 	{
       
  2211 	_LIT8(KOpenBracket, " ( ");
       
  2212 	_LIT8(KCloseBracket, " ) ");
       
  2213 	
       
  2214 	
       
  2215 	// if search requies on more than one header table
       
  2216 	if(iMtmIdArray.Count() > 1)
       
  2217 		{
       
  2218 		UpdateQueryWithMultipleTablesL(aQuery, aQueryString, KCurrentDriveId, aParentId);
       
  2219 		return;	
       
  2220 		}
       
  2221 	else
       
  2222 		{
       
  2223 		// multilevel serach with single header table
       
  2224 		TInt index = 0;
       
  2225 		iNumOfMsgParts = 0;
       
  2226 		aQueryString.Append(KWhere);
       
  2227 		
       
  2228 		if( iMtmIdArray.Count() == 1 )
       
  2229 			{
       
  2230 			aQueryString.Append(KOpenBracket);
       
  2231 			
       
  2232 			// compare TMsvId of IndexEntry table and Header table
       
  2233 			CompareTMsvIds(aQueryString, index);
       
  2234 
       
  2235 			aQueryString.Append(KAnd);
       
  2236 			
       
  2237 			// inner open bracket, if search needs more than one header field
       
  2238 			if(iTotalNumMsgPartsOnHeader > 1)
       
  2239 				{
       
  2240 				aQueryString.Append(KOpenBracket);	
       
  2241 				}
       
  2242 			
       
  2243 			// multilevel query on single header table.
       
  2244 			for(TInt queryCount=0; queryCount < aQuery.iMsgQuery.Count(); ++queryCount)
       
  2245 				{
       
  2246 				DoAddHeaderFields(aQuery, aQueryString, queryCount, index);
       
  2247 				}
       
  2248 				
       
  2249 			// inner close bracket, if search needs more than one header field
       
  2250 			if(iTotalNumMsgPartsOnHeader > 1)
       
  2251 				{
       
  2252 				aQueryString.Append(KCloseBracket);	
       
  2253 				}
       
  2254 			
       
  2255 			aQueryString.Append(KCloseBracket);
       
  2256 			}
       
  2257 			
       
  2258 		// update Query with ParentId and MsgType
       
  2259 		aQueryString.Append(KAnd);
       
  2260 		UpadeteQueryWithParentIdAndMsgType(aQueryString, KCurrentDriveId, aParentId);
       
  2261 		}
       
  2262 	}
       
  2263 
       
  2264 
       
  2265 /** 
       
  2266 * UpdateQueryWithSortFieldL()
       
  2267 *
       
  2268 * @param aQuery: Contains SearchSort query information sent by the client
       
  2269 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2270 * return NONE
       
  2271 *  
       
  2272 *  Update query with sort field
       
  2273 */ 
       
  2274 void TSearchSortDbWrapper::UpdateQueryWithSortFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
       
  2275 	{
       
  2276 	if(iMtmIdArray.Count() > 1)
       
  2277 		{
       
  2278 		if(aQuery.IsSortQuery() && iSortOnHeader)
       
  2279 			{
       
  2280 			UpdateQueryWithMultipleTablesL(aQuery, aQueryString, aDriveId, UnmaskTMsvId(aQuery.iParentId));
       
  2281 			}
       
  2282 		DoUpdateSortQueryForHeaderFieldL(aQuery, aQueryString, aDriveId);
       
  2283 		}
       
  2284 	else
       
  2285 		{
       
  2286 		if(aQuery.IsSortQuery() || IsSearchQueryOnBody() )
       
  2287 			{
       
  2288 			aQueryString.Append(KWhere);
       
  2289 			UpadeteQueryWithParentIdAndMsgType(aQueryString, aDriveId, UnmaskTMsvId(aQuery.iParentId));	
       
  2290 			}
       
  2291 		UpdateQueryToRemoveEmptyHeaderFieldL(aQuery, aQueryString, aDriveId);
       
  2292 		DoUpdateSortQueryForHeaderFieldL(aQuery, aQueryString, aDriveId);
       
  2293 		}
       
  2294 	}	
       
  2295 
       
  2296 /** 
       
  2297 * IsSearchQueryOnBody()
       
  2298 *
       
  2299 * @param aIsOnlyBody: to differentiate search only on body of the message
       
  2300 * return NONE
       
  2301 *  
       
  2302 *  To check whether its search only on body of the message
       
  2303 */ 
       
  2304 TBool TSearchSortDbWrapper::IsSearchQueryOnBody(TBool aIsOnlyBody)
       
  2305 	{
       
  2306 	TBool flag = EFalse;
       
  2307 	// is search only on body of the message?
       
  2308 	if(aIsOnlyBody)	
       
  2309 		{
       
  2310 		if( (iTypeOfQuery == EQueryOnBody) && !iSortOnHeader ) 
       
  2311 			{
       
  2312 			flag = ETrue;
       
  2313 			}
       
  2314 		}
       
  2315 	else //is search only on body of the message and sort on header field?
       
  2316 		{
       
  2317 		if( (iTypeOfQuery == EQueryOnBody) && iSortOnHeader )
       
  2318 			{
       
  2319 			flag = ETrue;
       
  2320 			}
       
  2321 		}
       
  2322 	return flag;	
       
  2323 	}
       
  2324 
       
  2325 /** 
       
  2326 * DoUpdateSortQueryForHeaderFieldL()
       
  2327 *
       
  2328 * @param aQuery: Contains SearchSort query information sent by the client
       
  2329 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2330 * return NONE
       
  2331 *  
       
  2332 *  Update query with sort field
       
  2333 */ 
       
  2334 void TSearchSortDbWrapper::DoUpdateSortQueryForHeaderFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
       
  2335 	{
       
  2336 	_LIT8(KTo, 	 "To");
       
  2337 	_LIT8(KFrom, 	 "From");
       
  2338 	_LIT8(KCc, 	 "Cc");
       
  2339 	_LIT8(KBcc, 	 "Bcc");
       
  2340 	_LIT8(KSubject, "Subject");
       
  2341 	
       
  2342 	switch (aQuery.iMsgExplicitSortPart)
       
  2343 		{
       
  2344 		//Sort on EMsvTo
       
  2345 		case EMsvTo:
       
  2346 			{
       
  2347 			aQueryString.Append(KOrderBy);
       
  2348 			
       
  2349 			if(iMtmIdArray.Count() == 1)
       
  2350 				{
       
  2351 				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
       
  2352 				}
       
  2353 			
       
  2354 			aQueryString.Append(KQuote);
       
  2355 			aQueryString.Append(KTo);
       
  2356 			aQueryString.Append(KQuote);
       
  2357 			
       
  2358 			if(aQuery.IsAscendingSort())
       
  2359 				{
       
  2360 				aQueryString.Append(KAscending);
       
  2361 				}
       
  2362 				
       
  2363 			else
       
  2364 				{
       
  2365 				aQueryString.Append(KDescending);
       
  2366 				}
       
  2367 			}
       
  2368 			break;
       
  2369 
       
  2370 		//Sort on EMsvFrom
       
  2371 		case EMsvFrom:
       
  2372 			{
       
  2373 			aQueryString.Append(KOrderBy);
       
  2374 			
       
  2375 			if(iMtmIdArray.Count() == 1)
       
  2376 				{
       
  2377 				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
       
  2378 				}
       
  2379 			
       
  2380 			aQueryString.Append(KQuote);
       
  2381 			aQueryString.Append(KFrom);
       
  2382 			aQueryString.Append(KQuote);
       
  2383 			
       
  2384 			if(aQuery.IsAscendingSort())
       
  2385 				{
       
  2386 				aQueryString.Append(KAscending);
       
  2387 				}
       
  2388 				
       
  2389 			else
       
  2390 				{
       
  2391 				aQueryString.Append(KDescending);
       
  2392 				}
       
  2393 				
       
  2394 			}
       
  2395 			break;
       
  2396 		
       
  2397 		//Sort on EMsvCc
       
  2398 		case EMsvCc:
       
  2399 			{
       
  2400 			aQueryString.Append(KOrderBy);
       
  2401 			
       
  2402 			if(iMtmIdArray.Count() == 1)
       
  2403 				{
       
  2404 				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
       
  2405 				}
       
  2406 			
       
  2407 			aQueryString.Append(KQuote);
       
  2408 			aQueryString.Append(KCc);
       
  2409 			aQueryString.Append(KQuote);
       
  2410 			
       
  2411 			if(aQuery.IsAscendingSort())
       
  2412 				{
       
  2413 				aQueryString.Append(KAscending);
       
  2414 				}
       
  2415 				
       
  2416 			else
       
  2417 				{
       
  2418 				aQueryString.Append(KDescending);
       
  2419 				}
       
  2420 			}
       
  2421 			break;
       
  2422 		
       
  2423 		//Sort on EMsvBcc
       
  2424 		case EMsvBcc:
       
  2425 			{
       
  2426 			aQueryString.Append(KOrderBy);
       
  2427 			
       
  2428 			if(iMtmIdArray.Count() == 1)
       
  2429 				{
       
  2430 				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
       
  2431 				}
       
  2432 			
       
  2433 			aQueryString.Append(KQuote);
       
  2434 			aQueryString.Append(KBcc);
       
  2435 			aQueryString.Append(KQuote);
       
  2436 			
       
  2437 			if(aQuery.IsAscendingSort())
       
  2438 				{
       
  2439 				aQueryString.Append(KAscending);
       
  2440 				}
       
  2441 				
       
  2442 			else
       
  2443 				{
       
  2444 				aQueryString.Append(KDescending);
       
  2445 				}
       
  2446 			}
       
  2447 			break;
       
  2448 		
       
  2449 		//Sort on EMsvSubject
       
  2450 		case EMsvSubject:
       
  2451 			{
       
  2452 			aQueryString.Append(KOrderBy);
       
  2453 			
       
  2454 			if(iMtmIdArray.Count() == 1)
       
  2455 				{
       
  2456 				UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
       
  2457 				}
       
  2458 
       
  2459 			aQueryString.Append(KQuote);
       
  2460 			aQueryString.Append(KSubject);
       
  2461 			aQueryString.Append(KQuote);
       
  2462 			
       
  2463 			if(aQuery.IsAscendingSort())
       
  2464 				{
       
  2465 				aQueryString.Append(KAscending);
       
  2466 				}
       
  2467 			else
       
  2468 				{
       
  2469 				aQueryString.Append(KDescending);
       
  2470 				}
       
  2471 			}
       
  2472 			break;
       
  2473 		
       
  2474 		// No Sort body filed	
       
  2475 		case EMsvBody:
       
  2476 		case 0:
       
  2477 			break;
       
  2478 			
       
  2479 		default:
       
  2480 			{
       
  2481 			User::Leave(KErrNotSupported);	
       
  2482 			}
       
  2483 		}
       
  2484 	}
       
  2485 
       
  2486 
       
  2487 /** 
       
  2488 * UpdateQueryToRemoveEmptyHeaderFieldL()
       
  2489 *
       
  2490 * @param aQuery: Contains SearchSort query information sent by the client
       
  2491 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2492 * return NONE
       
  2493 *  
       
  2494 *  Function to remove the empty header fields from search result
       
  2495 */ 	
       
  2496 void TSearchSortDbWrapper::UpdateQueryToRemoveEmptyHeaderFieldL(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TUint aDriveId)
       
  2497 	{
       
  2498 	_LIT8(KIsNotNull, " IS NOT NULL ");
       
  2499 	
       
  2500 	// if it's sort query on header or 
       
  2501 	// Search on TMsvEntry fields and/or body AND sort on header field
       
  2502 	if( (aQuery.IsSortQuery() && iSortOnHeader) || IsSearchOnEntryAndBody(aQuery) )
       
  2503 		{
       
  2504 		CompareTMsvIds(aQueryString, aDriveId);
       
  2505 		}
       
  2506 	
       
  2507 	aQueryString.Append(KAnd);
       
  2508 	UpdateQueryWithDriveNumAndHeaderTable(aDriveId, aQueryString);
       
  2509 	UpdateHeaderFieldL(aQuery, aQueryString);
       
  2510 	aQueryString.Append(KIsNotNull);
       
  2511 	}
       
  2512 	
       
  2513 
       
  2514 /** 
       
  2515 * IsSearchOnEntryAndBody()
       
  2516 *
       
  2517 * @param aQuery: Contains SearchSort query information sent by the client
       
  2518 * return NONE
       
  2519 *  
       
  2520 *  To check whether its search (search on TMsvEntry fields and/or body) query with sort on header
       
  2521 */ 
       
  2522 TBool TSearchSortDbWrapper::IsSearchOnEntryAndBody(const CMsvSearchSortCacheEntry& aQuery)
       
  2523 	{
       
  2524 	TBool flag = EFalse;
       
  2525 	
       
  2526 	// to check whether its search query with sort on header
       
  2527 	if(!aQuery.IsSortQuery() && iSortOnHeader)
       
  2528 		{
       
  2529 		// to check is search on TMsvEntry fields and/or body
       
  2530 		switch(iTypeOfQuery)
       
  2531 			{
       
  2532 			case EQueryOnIndexEntry:
       
  2533 			case EQueryOnBody:
       
  2534 			case EQueryOnEntryAndBody:
       
  2535 				flag = ETrue;
       
  2536 				break;
       
  2537 		
       
  2538 			default:
       
  2539 				flag = EFalse;
       
  2540 			}
       
  2541 		}
       
  2542 	return flag;
       
  2543 	}
       
  2544 	
       
  2545 
       
  2546 /** 
       
  2547 * CompareTMsvIds()
       
  2548 *
       
  2549 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2550 * @param DriveId: Drive information
       
  2551 * return NONE
       
  2552 *  
       
  2553 *  Function to compare TMsvIds from IndexEntry table and Header table
       
  2554 */ 
       
  2555 void TSearchSortDbWrapper::CompareTMsvIds(RBuf8& aQueryString, TUint aDriveId)
       
  2556 	{
       
  2557 	_LIT8(KHeader, "Header_");
       
  2558 	_LIT8(KIndexEntry, "IndexEntry");
       
  2559 	_LIT8(KOpenBracket, " ( ");
       
  2560 	_LIT8(KCloseBracket, " ) ");
       
  2561 	_LIT8(KDb, "DB");
       
  2562 	_LIT8(KDot, ".");
       
  2563 
       
  2564 	// AND  ( DB(KCurrentDriveId).IndexEntry.id = DB(KCurrentDriveId).Header_268439593.id )
       
  2565 	aQueryString.Append(KAnd);	
       
  2566 	aQueryString.Append(KOpenBracket);
       
  2567 				
       
  2568 	aQueryString.Append(KDb);
       
  2569 	aQueryString.AppendNum(aDriveId);
       
  2570 	aQueryString.Append(KDot);
       
  2571 	aQueryString.Append(KIndexEntry);
       
  2572 	aQueryString.Append(KDot);
       
  2573 	aQueryString.Append(KId);
       
  2574 	aQueryString.Append(KEqualTo);
       
  2575 				
       
  2576 	aQueryString.Append(KDb);
       
  2577 	aQueryString.AppendNum(aDriveId);
       
  2578 	aQueryString.Append(KDot);
       
  2579 	aQueryString.Append(KHeader);
       
  2580 	aQueryString.AppendNum(iHeaderTableForSort);
       
  2581 
       
  2582 	aQueryString.Append(KDot);
       
  2583 	aQueryString.Append(KId);
       
  2584 	
       
  2585 	aQueryString.Append(KCloseBracket);
       
  2586 	}
       
  2587 
       
  2588 
       
  2589 /** 
       
  2590 * UpdateQueryWithDriveNumAndHeaderTable()
       
  2591 *
       
  2592 * @param DriveId: Drive information
       
  2593 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2594 * return NONE
       
  2595 *  
       
  2596 *  Function to update query with header_table
       
  2597 */ 
       
  2598 void TSearchSortDbWrapper::UpdateQueryWithDriveNumAndHeaderTable(TUint aDriveId, RBuf8& aQueryString)
       
  2599 	{
       
  2600 	_LIT8(KHeader, 	"Header_");
       
  2601 	_LIT8(KDb, 		"DB");
       
  2602 	_LIT8(KDot, 		".");
       
  2603 
       
  2604 	// DB(DriveId).Header_mtmid.
       
  2605 	aQueryString.Append(KDb);
       
  2606 	aQueryString.AppendNum(aDriveId);
       
  2607 	aQueryString.Append(KDot);
       
  2608 	aQueryString.Append(KHeader);
       
  2609 	aQueryString.AppendNum(iHeaderTableForSort);
       
  2610 	aQueryString.Append(KDot);	
       
  2611 	}
       
  2612 
       
  2613 /** 
       
  2614 * CompareTMsvIds()
       
  2615 *
       
  2616 * @param aQuery: Contains SearchSort query information sent by the client
       
  2617 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2618 * return NONE
       
  2619 *  
       
  2620 *  Function to compare TMsvIds from IndexEntry table and Header table
       
  2621 */ 
       
  2622 void TSearchSortDbWrapper::CompareTMsvIds(RBuf8& aQueryString, TInt aIndex)
       
  2623 	{
       
  2624 	_LIT8(KHeader, "Header_");
       
  2625 	_LIT8(KIndexEntry, "IndexEntry");
       
  2626 	_LIT8(KDb, "DB");
       
  2627 	_LIT8(KDot, ".");
       
  2628 	
       
  2629 				
       
  2630 	aQueryString.Append(KDb);
       
  2631 	aQueryString.AppendNum(KCurrentDriveId);
       
  2632 	aQueryString.Append(KDot);
       
  2633 	aQueryString.Append(KIndexEntry);
       
  2634 	aQueryString.Append(KDot);
       
  2635 	aQueryString.Append(KId);
       
  2636 	aQueryString.Append(KEqualTo);
       
  2637 				
       
  2638 	aQueryString.Append(KDb);
       
  2639 	aQueryString.AppendNum(KCurrentDriveId);
       
  2640 	aQueryString.Append(KDot);
       
  2641 	
       
  2642 	aQueryString.Append(KHeader);
       
  2643 	aQueryString.AppendNum(iMtmIdArray[aIndex].iUid);
       
  2644 
       
  2645 	aQueryString.Append(KDot);
       
  2646 	aQueryString.Append(KId);
       
  2647 	}
       
  2648 
       
  2649 /** 
       
  2650 * DoAddHeaderFields()
       
  2651 *
       
  2652 * @param aQuery: Contains SearchSort query information sent by the client
       
  2653 * @param aQueryString: QueryString which will be prepared depending on SearchSort Query
       
  2654 * return NONE
       
  2655 *  
       
  2656 *  Function to update query with search fields on header
       
  2657 */ 	
       
  2658 void TSearchSortDbWrapper::DoAddHeaderFields(const CMsvSearchSortCacheEntry& aQuery, RBuf8& aQueryString, TInt aIndex, TInt aMtmIdArrayIndex)
       
  2659 	{
       
  2660 	_LIT8(KTo, 	 "To");
       
  2661 	_LIT8(KFrom, 	 "From");
       
  2662 	_LIT8(KCc, 	 "Cc");
       
  2663 	_LIT8(KBcc, 	 "Bcc");
       
  2664 	_LIT8(KSubject, "Subject");
       
  2665 	_LIT8(KDot, ".");
       
  2666 	_LIT8(KOr, " OR ");
       
  2667 		
       
  2668 	switch (aQuery.iMsgQuery[aIndex].iMessagePart)
       
  2669 		{
       
  2670 		// Header and Body Parts are searched at client side using FindL
       
  2671 		case EMsvTo:
       
  2672 			{
       
  2673 			if(iNumOfMsgParts)
       
  2674 				{
       
  2675 				if(iMtmIdArray.Count() > 1)
       
  2676 					{
       
  2677 					aQueryString.Append(KOr);
       
  2678 					}
       
  2679 				else
       
  2680 					{
       
  2681 					aQueryString.Append(KAnd);
       
  2682 					}
       
  2683 				}
       
  2684 						
       
  2685 			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
       
  2686 			aQueryString.Append(KDot);
       
  2687 			
       
  2688 			aQueryString.Append(KQuote);
       
  2689 			aQueryString.Append(KTo);
       
  2690 			aQueryString.Append(KQuote);
       
  2691 			
       
  2692 			// update query for case sensitive or case insensitive serach
       
  2693 			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
       
  2694 			
       
  2695 			iNumOfMsgParts++;	
       
  2696 			}
       
  2697 			break;
       
  2698 			
       
  2699 		case EMsvFrom:
       
  2700 			{
       
  2701 			if(iNumOfMsgParts)
       
  2702 				{
       
  2703 				if(iMtmIdArray.Count() > 1)
       
  2704 					{
       
  2705 					aQueryString.Append(KOr);
       
  2706 					}
       
  2707 				else
       
  2708 					{
       
  2709 					aQueryString.Append(KAnd);
       
  2710 					}
       
  2711 				}
       
  2712 			
       
  2713 			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
       
  2714 			aQueryString.Append(KDot);
       
  2715 			
       
  2716 			aQueryString.Append(KQuote);
       
  2717 			aQueryString.Append(KFrom);
       
  2718 			aQueryString.Append(KQuote);
       
  2719 			
       
  2720 			// update query for case sensitive or case insensitive serach
       
  2721 			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
       
  2722 			
       
  2723 			iNumOfMsgParts++;	
       
  2724 			}
       
  2725 			break;
       
  2726 
       
  2727 						
       
  2728 		case EMsvCc:
       
  2729 			{
       
  2730 			if(iNumOfMsgParts)
       
  2731 				{
       
  2732 				if(iMtmIdArray.Count() > 1)
       
  2733 					{
       
  2734 					aQueryString.Append(KOr);
       
  2735 					}	
       
  2736 				else
       
  2737 					{
       
  2738 					aQueryString.Append(KAnd);
       
  2739 					}
       
  2740 				}
       
  2741 						
       
  2742 			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
       
  2743 			aQueryString.Append(KDot);
       
  2744 			
       
  2745 			aQueryString.Append(KQuote);
       
  2746 			aQueryString.Append(KCc);
       
  2747 			aQueryString.Append(KQuote);
       
  2748 			
       
  2749 			// update query for case sensitive or case insensitive serach
       
  2750 			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
       
  2751 			
       
  2752 			iNumOfMsgParts++;		
       
  2753 			}
       
  2754 			break;
       
  2755 
       
  2756 		case EMsvBcc:
       
  2757 			{
       
  2758 			if(iNumOfMsgParts)
       
  2759 				{
       
  2760 				if(iMtmIdArray.Count() > 1)
       
  2761 					{
       
  2762 					aQueryString.Append(KOr);
       
  2763 					}
       
  2764 				else
       
  2765 					{
       
  2766 					aQueryString.Append(KAnd);
       
  2767 					}
       
  2768 				}
       
  2769 			
       
  2770 			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
       
  2771 			aQueryString.Append(KDot);
       
  2772 			
       
  2773 			aQueryString.Append(KQuote);
       
  2774 			aQueryString.Append(KBcc);
       
  2775 			aQueryString.Append(KQuote);
       
  2776 			
       
  2777 			// update query for case sensitive or case insensitive serach
       
  2778 			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
       
  2779 			
       
  2780 			iNumOfMsgParts++;		
       
  2781 			}
       
  2782 			break;
       
  2783 						
       
  2784 		case EMsvSubject:
       
  2785 			{
       
  2786 			if(iNumOfMsgParts)
       
  2787 				{
       
  2788 				if(iMtmIdArray.Count() > 1)
       
  2789 					{
       
  2790 					aQueryString.Append(KOr);
       
  2791 					}
       
  2792 				else
       
  2793 					{
       
  2794 					aQueryString.Append(KAnd);
       
  2795 					}
       
  2796 				}
       
  2797 			
       
  2798 			UpdateQueryWithHeaderTable(aQueryString, KCurrentDriveId, iMtmIdArray[aMtmIdArrayIndex].iUid);
       
  2799 			aQueryString.Append(KDot);
       
  2800 
       
  2801 			aQueryString.Append(KQuote);
       
  2802 			aQueryString.Append(KSubject);
       
  2803 			aQueryString.Append(KQuote);
       
  2804 			
       
  2805 			// update query for case sensitive or case insensitive serach
       
  2806 			IsCaseSensitiveSearch(aQuery, aQueryString, aIndex);
       
  2807 						
       
  2808 			iNumOfMsgParts++;		
       
  2809 			}
       
  2810 			break;
       
  2811 		
       
  2812 		default:
       
  2813 			break;
       
  2814 		}
       
  2815 	}
       
  2816 
       
  2817 #endif  // SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB