messagingfw/msgsrvnstore/server/src/msvdbadapter.cpp
changeset 0 8e480a14352b
child 6 fe71b07a6401
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2007-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 
       
    19 /**
       
    20  * HEADER FILES
       
    21  */
       
    22 #include <barsc.h>
       
    23 #include <bautils.h>
       
    24 
       
    25 #include "msvdbadapter.h"
       
    26 #include "msventryfreepool.h"
       
    27 #include "msvsearchsortdbwrapper.h"
       
    28 
       
    29 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    30 #include "msvsearchsortconstants.h"
       
    31 #endif
       
    32 
       
    33 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
    34 	#include "cmessageconvertermanager.h"
       
    35 #endif
       
    36 
       
    37 /**
       
    38  * CONSTANT DEFINITION
       
    39  */
       
    40 #define SERVER_UID 0x1000484B
       
    41 #define KMsvNumStdFolder 7
       
    42 
       
    43 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
    44 	#include "msvindexadapter.h"
       
    45 	
       
    46 	//Main (dummy) DB name.
       
    47 	#if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
    48 		_LIT(KMainDummyDBName, "\\messaging_master.db");
       
    49 		_LIT(KMessagingDBName, "\\messaging.db");
       
    50 	#else
       
    51 		_LIT(KMainDummyDBName, "[1000484b]messaging_master.db");
       
    52 		_LIT(KMessagingDBName, "[1000484b]messaging.db");
       
    53 	#endif
       
    54 
       
    55 	_LIT(KLogicalName, "DB");
       
    56 	_LIT(KComma, ", ");
       
    57 	_LIT(KDelimiter, " ;");
       
    58 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
    59 
       
    60 
       
    61 /**
       
    62  * LITERAL DEFINITION
       
    63  */
       
    64 //Data definition queries
       
    65 _LIT8(KEncodingText, "encoding=UTF-8");
       
    66 _LIT8(KCreateIndexEntryTableQuery,	"CREATE TABLE IF NOT EXISTS IndexEntry ("
       
    67 								"id INTEGER PRIMARY KEY,"
       
    68 						  		"parentId INT,"
       
    69 								"serviceId INT,"
       
    70 								"mtmId INT,"
       
    71 								"type INT,"
       
    72 								"date INT64,"
       
    73 								"data INT,"
       
    74 								"size INT,"
       
    75 								"error INT,"
       
    76 								"mtmData1 INT,"
       
    77 								"mtmData2 INT,"
       
    78 								"mtmData3 INT,"
       
    79 								"relatedId INT,"
       
    80 								"bioType INT,"
       
    81 								"pcSyncCount INT,"
       
    82 								"reserved INT,"
       
    83 								"visibleParent INT,"
       
    84 								"description TEXT,"
       
    85 						  		"details TEXT" ");"
       
    86 	  );
       
    87 	  
       
    88 _LIT8(KCreateIndexQuery, "CREATE INDEX IF NOT EXISTS INDEX_PARENT ON IndexEntry(parentId);");
       
    89 _LIT8(KCreateVersionTableQuery, "CREATE TABLE IF NOT EXISTS VersionTable ( "
       
    90 									"version INTEGER PRIMARY KEY );"
       
    91 		);
       
    92 	
       
    93 //Common database queries
       
    94 _LIT8(KGetEntryExistsQuery, "SELECT parentId FROM IndexEntry WHERE id = :id;"); //
       
    95 _LIT8(KGetVisibleIdQuery, "SELECT data, visibleParent FROM IndexEntry WHERE id = :id;"); //
       
    96 _LIT8(KGetEntryQuery, "SELECT parentId, serviceId, mtmId, type, date, data, size, error, "
       
    97 						"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
    98 						"reserved, visibleParent, description, details FROM IndexEntry WHERE id = :id;"); //
       
    99 _LIT8(KGetChildEntriesQuery, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
       
   100 							"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
   101 							"reserved, visibleParent, description, details FROM IndexEntry "
       
   102 							"WHERE parentId = :parentId order by id ASC;"); //
       
   103 		
       
   104 //Data manipulation queries
       
   105 _LIT8(KCreateEntryQuery,	 "INSERT INTO IndexEntry VALUES ("
       
   106 							 ":id, :parentId, :serviceId, :mtmId, :type, :date, :data, :size, :error,"
       
   107 							 ":mtmData1, :mtmData2, :mtmData3, :relatedId, :bioType, :pcSyncCount,"
       
   108 							 ":reserved, :visibleParent, :description, :details);"
       
   109 	 ); //
       
   110 _LIT8(KUpdateEntryQuery,	"UPDATE IndexEntry SET "
       
   111 							"parentId = :parentId, serviceId = :serviceId, mtmId = :mtmId, type = :type, date = :date,"
       
   112 							"data = :data, size = :size, error = :error, mtmData1 = :mtmData1, mtmData2 = :mtmData2,"
       
   113 							"mtmData3 = :mtmData3, relatedId = :relatedId, bioType = :bioType, pcSyncCount = :pcSyncCount,"
       
   114 							"reserved = :reserved, visibleParent = :visibleParent, description = :description,"
       
   115 							"details = :details WHERE id = :id;"
       
   116 	 ); //
       
   117 _LIT8(KUpdateEntryNoParentQuery,	"UPDATE IndexEntry SET "
       
   118 							"serviceId = :serviceId, mtmId = :mtmId, type = :type, date = :date,"
       
   119 							"data = :data, size = :size, error = :error, mtmData1 = :mtmData1, mtmData2 = :mtmData2,"
       
   120 							"mtmData3 = :mtmData3, relatedId = :relatedId, bioType = :bioType, pcSyncCount = :pcSyncCount,"
       
   121 							"reserved = :reserved, visibleParent = :visibleParent, description = :description,"
       
   122 							"details = :details WHERE id = :id;"
       
   123 	 ); //
       
   124 
       
   125 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   126 _LIT8(KCreateConversionStatusTableQuery, 	"CREATE TABLE IF NOT EXISTS ConversionStatus ("
       
   127 								"lastId INT,"
       
   128 						  		"serviceId INTEGER PRIMARY KEY,"
       
   129 								"sourceVersion INT,"
       
   130 								"targetVersion INT,"
       
   131 								"mtmId INT,"
       
   132 								"remainingCount INT );"
       
   133 	 );	
       
   134 
       
   135 _LIT8(KRemoveConversionStatusTable,  "DROP TABLE IF EXISTS ConversionStatus;");					
       
   136 
       
   137 
       
   138 
       
   139 #endif
       
   140 	 
       
   141 	 
       
   142 //Literals for parameter indexes
       
   143 _LIT(KMsgParamId, ":id");
       
   144 _LIT(KMsgParamParentId, ":parentId");
       
   145 _LIT(KMsgParamServiceId, ":serviceId");
       
   146 _LIT(KMsgParamMtmId, ":mtmId");
       
   147 _LIT(KMsgParamType, ":type");
       
   148 _LIT(KMsgParamDate, ":date");
       
   149 _LIT(KMsgParamData, ":data");
       
   150 _LIT(KMsgParamSize, ":size");
       
   151 _LIT(KMsgParamError, ":error");
       
   152 _LIT(KMsgParamMtmData1, ":mtmData1");
       
   153 _LIT(KMsgParamMtmData2, ":mtmData2");
       
   154 _LIT(KMsgParamMtmData3, ":mtmData3");
       
   155 _LIT(KMsgParamRelatedId, ":relatedId");
       
   156 _LIT(KMsgParamBiotype, ":bioType");
       
   157 _LIT(KMsgParamPcSyncCount, ":pcSyncCount");
       
   158 _LIT(KMsgParamReserved, ":reserved");
       
   159 _LIT(KMsgParamVisibleParent, ":visibleParent");
       
   160 _LIT(KMsgParamDescriptionTxt, ":description");
       
   161 _LIT(KMsgParamDetailsTxt, ":details");
       
   162 
       
   163 //Literals for column indexes
       
   164 _LIT(KMsgColumnId, "id");
       
   165 _LIT(KMsgColumnParentId, "parentId");
       
   166 _LIT(KMsgColumnServiceId, "serviceId");
       
   167 _LIT(KMsgColumnMtmId, "mtmId");
       
   168 _LIT(KMsgColumnType, "type");
       
   169 _LIT(KMsgColumnDate, "date");
       
   170 _LIT(KMsgColumnData, "data");
       
   171 _LIT(KMsgColumnSize, "size");
       
   172 _LIT(KMsgColumnError, "error");
       
   173 _LIT(KMsgColumnMtmData1, "mtmData1");
       
   174 _LIT(KMsgColumnMtmData2, "mtmData2");
       
   175 _LIT(KMsgColumnMtmData3, "mtmData3");
       
   176 _LIT(KMsgColumnRelatedId, "relatedId");
       
   177 _LIT(KMsgColumnBiotype, "bioType");
       
   178 _LIT(KMsgColumnPcSyncCount, "pcSyncCount");
       
   179 _LIT(KMsgColumnReserved, "reserved");
       
   180 _LIT(KMsgColumnVisibleParent, "visibleParent");
       
   181 _LIT(KMsgColumnDescriptionTxt, "description");
       
   182 _LIT(KMsgColumnDetailsTxt, "details");
       
   183 
       
   184 
       
   185 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   186 	_LIT8(KGetChildIdsQuery, "SELECT id, type, data FROM IndexEntry WHERE parentId = :parentId order by id ASC;"); //
       
   187 	_LIT8(KClearTableContents, "DELETE FROM SearchSortEntry;");
       
   188 #else
       
   189 	_LIT8(KDeleteTable,  "DROP TABLE IF EXISTS SearchSortEntry;");
       
   190 	_LIT8(KGetChildIdsQuery, "SELECT id FROM IndexEntry WHERE parentId = :parentId order by id ASC;"); //
       
   191 	_LIT8(KGetInPreparationIdQuery, "SELECT id, data FROM IndexEntry;");
       
   192 #endif
       
   193 
       
   194 
       
   195 
       
   196 // Changes for PREQ 1667.
       
   197 //Data definition queries for SearchSort-Table
       
   198 _LIT8(KCreateSearchSortEntryTableQuery,	"CREATE TABLE IF NOT EXISTS SearchSortEntry ("
       
   199 						"Qid INT,"
       
   200 				  		"id INT,"
       
   201 						"sortfield TEXT" ");"
       
   202 );
       
   203 
       
   204 _LIT8(KCreateSearchSortQuery, "CREATE UNIQUE INDEX IF NOT EXISTS SearchSortEntry_UNIQUE ON SearchSortEntry (Qid, id,sortfield);");
       
   205 
       
   206 //Common database queries
       
   207 _LIT8(KGetEntryAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by sortfield ASC;");
       
   208 _LIT8(KGetEntryDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by sortfield DESC;");
       
   209 _LIT8(KGetEntryNumAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by CAST(sortfield AS INT) ASC;");
       
   210 _LIT8(KGetEntryNumDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE Qid = :Qid ORDER by CAST(sortfield AS INT) DESC;");
       
   211 
       
   212 _LIT8(KGetLastNIdsAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by sortfield ASC;");
       
   213 _LIT8(KGetLastNIdsDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by sortfield DESC;");
       
   214 _LIT8(KGetLastNIdsNumAsc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by CAST(sortfield AS INT) ASC;");
       
   215 _LIT8(KGetLastNIdsNumDesc, "SELECT DISTINCT id FROM SearchSortEntry WHERE ROWID > (LAST_INSERT_ROWID() - :RowId) AND Qid = :Qid ORDER by CAST(sortfield AS INT) DESC;");
       
   216 
       
   217 _LIT8(KGetQueryCount, "SELECT COUNT(DISTINCT id) FROM SearchSortEntry WHERE Qid = :Qid");
       
   218 
       
   219 _LIT8(KGetFolderIds, "SELECT id FROM IndexEntry WHERE parentId = :parentId AND type LIKE :type");
       
   220 
       
   221 _LIT8(KGetIterResultCastAsc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by CAST(sortfield AS INT) ASC LIMIT :lim OFFSET :off ");
       
   222 _LIT8(KGetIterResultCastDesc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by CAST(sortfield AS INT) DESC LIMIT :lim OFFSET :off ");
       
   223 _LIT8(KGetIterResultAsc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by sortfield ASC LIMIT :lim OFFSET :off ");
       
   224 _LIT8(KGetIterResultDesc, "SELECT id FROM SearchSortEntry WHERE Qid = :qid ORDER by sortfield ASC LIMIT :lim OFFSET :off ");
       
   225 
       
   226 //Data manipulation queries
       
   227 _LIT8(KDeleteId, 	 "DELETE FROM SearchSortEntry WHERE id = ");
       
   228 _LIT8(KCreateQueryEntry,	 "INSERT OR IGNORE INTO SearchSortEntry VALUES ("
       
   229 							 ":Qid, :id, :sortfield);");
       
   230 
       
   231 _LIT8(KDeleteQueryId, 	 "DELETE FROM SearchSortEntry WHERE Qid = ");
       
   232 _LIT8(KAndId, " AND id = ");
       
   233 _LIT8(KSemiColon, ";");
       
   234 
       
   235 //Literals for parameter indexes
       
   236 _LIT(KQueryQId, ":Qid");
       
   237 _LIT(KQueryTMsvId, ":id");
       
   238 _LIT(KQuerySortfield, ":sortfield");
       
   239 _LIT(KQueryRowId, ":RowId");
       
   240 _LIT(KOffset, ":off");
       
   241 _LIT(KLimit, ":lim");
       
   242 
       
   243 //Literals for column indexes
       
   244 _LIT(KQueryColumnTMsvId, "id");
       
   245 
       
   246 
       
   247 
       
   248 /**
       
   249  * MEMBER FUNCTIONS OF CMsvDBAdapter
       
   250  */
       
   251 
       
   252 
       
   253 
       
   254 /**
       
   255  * CMsvDBAdapter()
       
   256  * The default Constructor. 
       
   257  */
       
   258 CMsvDBAdapter::CMsvDBAdapter():isTransactionOpen(EFalse)
       
   259 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   260 		,iDbPtrInitialized(EFalse)
       
   261 #endif
       
   262 	{
       
   263 	}
       
   264 
       
   265 
       
   266 
       
   267 
       
   268 /**
       
   269  * ~CMsvDBAdapter()
       
   270  * The default Destructor. 
       
   271  */
       
   272 CMsvDBAdapter::~CMsvDBAdapter()
       
   273 	{
       
   274 	//Close all RSqlStatement object.
       
   275 	for(TInt index = ECreateEntry; index < EIndexSentinel; index++)
       
   276 		{
       
   277 		iStatement[index].Close();
       
   278 		}
       
   279 
       
   280 	for(TInt index = EQueryCreateEntry; index < EQuerySentinel; index++)
       
   281 		{
       
   282 		iQueryStatement[index].Close();
       
   283 		}
       
   284 		
       
   285 	iDatabase.Close();
       
   286 	
       
   287 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   288 	if(iDatabasePresent)
       
   289 		{
       
   290 		iDatabasePresent->Close();
       
   291 		delete iDatabasePresent;
       
   292 		}
       
   293 #endif
       
   294 	}
       
   295 
       
   296 
       
   297 
       
   298 
       
   299 // Code added in PREQ 557.
       
   300 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
   301 
       
   302 /**
       
   303  * NewL()
       
   304  * @param None.
       
   305  * @return None.
       
   306  * 
       
   307  * Allocates and constructs a new DBAdapter object, calls ConstructL 
       
   308  * to create the dummy database and returns a handle to the DBAdapter.
       
   309  */
       
   310 CMsvDBAdapter* CMsvDBAdapter::NewL()
       
   311 	{
       
   312 	//Create the DBAdapter object.
       
   313 	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
       
   314 	CleanupStack::PushL(self);
       
   315 	
       
   316 	// Create the database.
       
   317 	self->ConstructL();
       
   318 	
       
   319 	CleanupStack::Pop(self);
       
   320 	return self;
       
   321 	
       
   322 	}
       
   323 
       
   324 
       
   325 
       
   326 
       
   327 /**
       
   328  * ConstructL()
       
   329  * @param None.
       
   330  * @return None.
       
   331  * 
       
   332  * Checks if there is the main (dummy) DB in the system drive
       
   333  * and creates one if it is not present. Other databases will
       
   334  * be attached to this DB which will not get deleted during
       
   335  * the operation of the message server.
       
   336  */
       
   337 void CMsvDBAdapter::ConstructL()
       
   338 	{
       
   339 	//Get the system drive.
       
   340 	TInt systemDrive = (TInt)RFs::GetSystemDrive();
       
   341 	
       
   342 	RBuf dbFile;
       
   343 	CleanupClosePushL(dbFile);
       
   344 	dbFile.CreateL(50);	
       
   345 	dbFile.Append(TDriveUnit(systemDrive).Name());
       
   346 	dbFile.Append(KMainDummyDBName);
       
   347 	
       
   348 	//Check if the main DB exists. If not, then create it.
       
   349 	// > KErrNotFound, KErrPathNotFound - DB doesn't exist.
       
   350 	// > KErrNone, KErrInUse - DB exists.
       
   351 	TRAPD(err, iDatabase.OpenL(dbFile));
       
   352 	if(KErrNone != err)
       
   353 		{
       
   354 		
       
   355 		// Leave in unfavorable condition.
       
   356 		if(KErrNoMemory == err ||
       
   357 		   KErrNotReady == err ||
       
   358 		   KErrInUse    == err
       
   359 		  )
       
   360 			{
       
   361 			User::Leave(err);
       
   362 			}
       
   363 
       
   364 		HBufC8* heapBuf = KEncodingText().AllocLC();
       
   365 		
       
   366 		if(KSqlErrCorrupt == err || KSqlErrNotDb == err)
       
   367 			{
       
   368 			RSqlDatabase::Delete(dbFile);
       
   369 			}
       
   370 		
       
   371 		//Create the dummy DB.		
       
   372 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   373 		// Create the non-secure database.
       
   374 		User::LeaveIfError(iDatabase.Create(dbFile, heapBuf));
       
   375 #else
       
   376 		// Using SID based security policy.
       
   377 		TSecureId sid(SERVER_UID);
       
   378 		const TSecurityPolicy KDefaultPolicy(sid);
       
   379 	
       
   380 		//Create security policy
       
   381 		RSqlSecurityPolicy securityPolicy;
       
   382 		CleanupClosePushL(securityPolicy);	
       
   383 		
       
   384 		User::LeaveIfError(securityPolicy.Create(KDefaultPolicy));
       
   385 		User::LeaveIfError(iDatabase.Create(dbFile, securityPolicy, heapBuf));
       
   386 		CleanupStack::PopAndDestroy(); //securityPolicy
       
   387 #endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   388 
       
   389 		CleanupStack::PopAndDestroy(); //heapBuf
       
   390 		}
       
   391 	CleanupStack::PopAndDestroy(); //dbFile
       
   392 			
       
   393 	//Construct the data structure to store maximum TMsvIds in
       
   394 	//a given driveId.
       
   395 	iDatabasePresent = new(ELeave)RArray<TBool>(KMaxNumberOfDrives);
       
   396 	//Initialisation.
       
   397 	for(TInt index = 0; index < KMaxNumberOfDrives; ++index)
       
   398 		{
       
   399 		iDatabasePresent->Append(EFalse);
       
   400 		}
       
   401 	
       
   402 	}
       
   403 	
       
   404 
       
   405 
       
   406 
       
   407 /**
       
   408  * AttachDBL()
       
   409  * @param TDriveUnit The drive information of the drive to be checked.
       
   410  * @param TUint The driveId of the drive (0-7).
       
   411  * @param TMsvId& An output parameter that gives the maximum TMsvId of an 
       
   412  *				  entry in the messaging database of that drive.
       
   413  * 
       
   414  * Attaches a database on the specified drive to the main (dummy) 
       
   415  * database on the system drive so that appropriate queries 
       
   416  * access entries in that database too. The function calls MaxTMsvIdL()
       
   417  * to query the particular database to get the maximum TMsvId of an entry 
       
   418  * stored in it. This TMsvId is maintained in a data structure which has 
       
   419  * the driveId as the index.
       
   420  *
       
   421  * The database is detached by using its logical name which can
       
   422  * be obtained from the driveId.
       
   423  * (E.g.: logical name of a database on driveId 3 is 'DB3'. A query on the
       
   424  * IndexEntry in this database should address the table as DB3.IndexEntry.)
       
   425  */
       
   426 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)	
       
   427 void CMsvDBAdapter::AttachDBL(TDriveUnit aDriveUnit, TUint aDriveId, TMsvId& aMaxId, CMsvMessageDBAdapter* iMessageDBAdapter/*default= NULL*/)
       
   428 #else
       
   429 void CMsvDBAdapter::AttachDBL(TDriveUnit aDriveUnit, TUint aDriveId, TMsvId& aMaxId)
       
   430 #endif
       
   431 	{
       
   432 	//Construct the logical name of the database to be attached from 
       
   433 	//the driveId.
       
   434 	RBuf logicalName;
       
   435 	CleanupClosePushL(logicalName);
       
   436 	logicalName.CreateL(5);	
       
   437 	logicalName.Append(KLogicalName);
       
   438 	logicalName.AppendNum(aDriveId);
       
   439 		
       
   440 	//Construct the DB filename appending messaging DB name to the drive name.
       
   441 	RBuf dbFile;
       
   442 	CleanupClosePushL(dbFile);
       
   443 	dbFile.CreateL(50);	
       
   444 	dbFile.Append(aDriveUnit.Name());
       
   445 	dbFile.Append(KMessagingDBName);
       
   446 	
       
   447 	//Attach the database to the connection.
       
   448 	User::LeaveIfError(iDatabase.Attach(dbFile, logicalName));
       
   449 	
       
   450 	//Find the parameter and column indexes just once.
       
   451 	if((KErrNotFound == iDatabasePresent->Find(ETrue)) && (!iDbPtrInitialized))
       
   452 		{
       
   453 		InitializeL();
       
   454 		iDbPtrInitialized = ETrue;
       
   455 		}
       
   456 		
       
   457 	//Find the maximum TMsvId in the database and store it.
       
   458 	aMaxId = MaxTMsvIdL(aDriveId);
       
   459 	(*iDatabasePresent)[aDriveId] = ETrue;
       
   460 	
       
   461 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
   462 	if(iMessageDBAdapter)
       
   463 		{
       
   464 		iMessageDBAdapter->UpdateMetadataStructureL(aDriveId);		
       
   465 		}	
       
   466 #endif
       
   467 
       
   468 	CleanupStack::PopAndDestroy(2); //logicalName, dbFile	
       
   469 	}
       
   470 
       
   471 	
       
   472 
       
   473 	
       
   474 /**
       
   475  * DetachDBL()
       
   476  * @param TUint The driveId (0-7) of the drive from which the database
       
   477  * 				is to be detached.
       
   478  * @return None.
       
   479  *
       
   480  * Detaches a database on the drive specified by the driveId from
       
   481  * the main database connection. This is done when:
       
   482  * a. The disk is removed from the drive.
       
   483  * b. The drive is removed from the preferred drive list.
       
   484  *
       
   485  * The database is detached by using its logical name which can
       
   486  * be obtained from the driveId.
       
   487  * (E.g.: logical name of a database on driveId 3 is 'DB3'.)
       
   488  */
       
   489 void CMsvDBAdapter::DetachDBL(TUint aDriveId)
       
   490 	{
       
   491 	//Construct the logical name.
       
   492 	RBuf logicalName;
       
   493 	CleanupClosePushL(logicalName);
       
   494 	logicalName.CreateL(5);	
       
   495 	logicalName.Append(KLogicalName);
       
   496 	logicalName.AppendNum(aDriveId);
       
   497 	
       
   498 	User::LeaveIfError(iDatabase.Detach(logicalName));
       
   499 	
       
   500 	CleanupStack::PopAndDestroy(); //logicalName
       
   501 	
       
   502 	(*iDatabasePresent)[aDriveId] = EFalse;
       
   503 	
       
   504 	}
       
   505 
       
   506 
       
   507 
       
   508 
       
   509 /**
       
   510  * CreateDBL()
       
   511  * @param TDriveNumber The drive number of the drive on which a 
       
   512  *						a new messaging database is to be created.
       
   513  * @return None.
       
   514  *
       
   515  * Creates the messaging database on the drive specified by the TDriveNumber
       
   516  * using a temporary local database connection.
       
   517  * Also creates the IndexEntry table and an index on the parentId field in it,
       
   518  * and then the Root entry in the database.
       
   519  * Also creates a version table, which is a database with just one column
       
   520  * and row which stores the current database version for message store
       
   521  * versioning.
       
   522  */
       
   523 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   524 void CMsvDBAdapter::CreateDBL(TDriveNumber aDriveNumber, TBool aCreateVersionTable /*Default=ETrue*/, TBool aInvalid /*Default=EFalse*/)
       
   525 #else
       
   526 void CMsvDBAdapter::CreateDBL(TDriveNumber aDriveNumber)
       
   527 #endif
       
   528 	{
       
   529 	//Construct the database filename.
       
   530 	TParse parse;
       
   531 	TPtrC drive = TDriveUnit(aDriveNumber).Name();
       
   532 	parse.Set(KMessagingDBName, &drive, NULL);
       
   533 	TFileName dbFileName = parse.FullName();
       
   534 	
       
   535 	RSqlDatabase tempDB; //A temporary local database connection.
       
   536 	CleanupClosePushL(tempDB);
       
   537 
       
   538 	HBufC8* heapBuf = KEncodingText().AllocLC();
       
   539 
       
   540 	//Create the database.
       
   541 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   542 	User::LeaveIfError(tempDB.Create(dbFileName, heapBuf));
       
   543 #else	
       
   544 	// Using SID based security policy.
       
   545 	TSecureId sid(SERVER_UID);
       
   546 	const TSecurityPolicy KDefaultPolicy(sid);
       
   547 	
       
   548 	//Create security policy
       
   549 	RSqlSecurityPolicy securityPolicy;
       
   550 	CleanupClosePushL(securityPolicy);	
       
   551 		
       
   552 	User::LeaveIfError(securityPolicy.Create(KDefaultPolicy));
       
   553 	User::LeaveIfError(tempDB.Create(dbFileName, securityPolicy, heapBuf));
       
   554 	
       
   555 	CleanupStack::PopAndDestroy(); //securityPolicy
       
   556 #endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   557 
       
   558 	CleanupStack::PopAndDestroy(); //heapBuf
       
   559 	
       
   560 	//Create tables for the database
       
   561 	TInt err = tempDB.Exec(KCreateIndexEntryTableQuery);
       
   562 	if(err < 0)
       
   563 		{
       
   564 		User::Leave(err);
       
   565 		}
       
   566 	else if(!err)
       
   567 		{
       
   568 		User::Leave(KErrGeneral);
       
   569 		}
       
   570 		
       
   571 	//Create index on indexEnty table.
       
   572 	//Index is created on parentId.
       
   573 	err = tempDB.Exec(KCreateIndexQuery);
       
   574 	if(err < 0)
       
   575 		{
       
   576 		User::Leave(err);
       
   577 		}
       
   578 	else if(!err)
       
   579 		{
       
   580 		User::Leave(KErrGeneral);
       
   581 		}
       
   582 	
       
   583 	// Create root entry in DB.
       
   584 	CreateRootEntryL(tempDB);	
       
   585 
       
   586 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   587 	if(aCreateVersionTable)
       
   588 		{
       
   589 #endif
       
   590 	//Create the version table to store the message store version.
       
   591 	err = tempDB.Exec(KCreateVersionTableQuery);
       
   592 	if(err < 0)
       
   593 		{
       
   594 		User::Leave(err);
       
   595 		}
       
   596 	else if(!err)
       
   597 		{
       
   598 		User::Leave(KErrGeneral);
       
   599 		}
       
   600 	//Insert the version number into the above table.
       
   601 	_LIT(KInsertVersionNumberQuery, " INSERT INTO VersionTable Values ( " );
       
   602 	RBuf8 versionQuery;
       
   603 	CleanupClosePushL(versionQuery);
       
   604 	versionQuery.CreateL(50);
       
   605 	versionQuery.Append(KInsertVersionNumberQuery);
       
   606 
       
   607 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
   608 	if(aInvalid) //create an invalid database wrt version for testing
       
   609 		versionQuery.AppendNum(999);
       
   610 	else
       
   611 		versionQuery.AppendNum(KCurrentDatabaseVersion);	
       
   612 #else
       
   613 	versionQuery.AppendNum(KCurrentDatabaseVersion);	
       
   614 #endif
       
   615 
       
   616 	versionQuery.Append(_L(");"));
       
   617 	err = tempDB.Exec(versionQuery);
       
   618 	if(err < 0)
       
   619 		{
       
   620 		User::Leave(err);
       
   621 		}
       
   622 	else if(!err)
       
   623 		{
       
   624 		User::Leave(KErrGeneral);
       
   625 		}
       
   626 
       
   627 	CleanupStack::PopAndDestroy();	//versionQuery
       
   628 		
       
   629 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)		
       
   630 		}
       
   631 #endif
       
   632 	
       
   633 	CleanupStack::PopAndDestroy(); // tempDB
       
   634 	}
       
   635  
       
   636  
       
   637 
       
   638 /**
       
   639  * CreateRootEntryL()
       
   640  *
       
   641  * Creates root entry in the DB.
       
   642  */
       
   643 void CMsvDBAdapter::CreateRootEntryL(RSqlDatabase& tempDB)
       
   644 	{
       
   645 	_LIT(KCreateRootEntryQuery, "INSERT INTO IndexEntry VALUES (");
       
   646 	_LIT(KComma, ", ");
       
   647 	_LIT(KDelimiter, " );");
       
   648 	
       
   649 	TMsvEntry rootEntry;
       
   650 	rootEntry.iType = KUidMsvRootEntry;
       
   651 	rootEntry.iMtm = KUidMsvRootEntry;
       
   652 	rootEntry.iDate.UniversalTime();
       
   653 	rootEntry.SetId(KMsvRootIndexEntryId);
       
   654 	rootEntry.SetParent(KErrNotFound);
       
   655 	rootEntry.SetOwner(ETrue);
       
   656 	rootEntry.iSize = 0;
       
   657 	
       
   658 	RBuf queryBuf;
       
   659 	CleanupClosePushL(queryBuf);
       
   660 	queryBuf.CreateL(300);	
       
   661 	queryBuf.Append(KCreateRootEntryQuery);
       
   662 	queryBuf.AppendNum(rootEntry.iId);
       
   663 	queryBuf.Append(KComma);
       
   664 	queryBuf.AppendNum(rootEntry.Parent());
       
   665 	queryBuf.Append(KComma);
       
   666 	queryBuf.AppendNum(rootEntry.iServiceId);
       
   667 	queryBuf.Append(KComma);
       
   668 	queryBuf.AppendNum(rootEntry.iMtm.iUid);
       
   669 	queryBuf.Append(KComma);
       
   670 	queryBuf.AppendNum(rootEntry.iType.iUid);
       
   671 	queryBuf.Append(KComma);
       
   672 	queryBuf.AppendNum(rootEntry.iDate.Int64());
       
   673 	queryBuf.Append(KComma);
       
   674 	queryBuf.AppendNum(rootEntry.iData);
       
   675 	queryBuf.Append(KComma);
       
   676 	queryBuf.AppendNum(rootEntry.iSize);
       
   677 	queryBuf.Append(KComma);
       
   678 	queryBuf.AppendNum(rootEntry.iError);
       
   679 	queryBuf.Append(KComma);
       
   680 	queryBuf.AppendNum(rootEntry.iMtmData1);
       
   681 	queryBuf.Append(KComma);
       
   682 	queryBuf.AppendNum(rootEntry.iMtmData2);
       
   683 	queryBuf.Append(KComma);
       
   684 	queryBuf.AppendNum(rootEntry.iMtmData3);
       
   685 	queryBuf.Append(KComma);
       
   686 	queryBuf.AppendNum(rootEntry.iRelatedId);
       
   687 	queryBuf.Append(KComma);
       
   688 	queryBuf.AppendNum(rootEntry.iBioType);
       
   689 	queryBuf.Append(KComma);
       
   690 	queryBuf.AppendNum(rootEntry.iPcSyncCount);
       
   691 	queryBuf.Append(KComma);
       
   692 	queryBuf.AppendNum(rootEntry.iReserved);
       
   693 	queryBuf.Append(KComma);
       
   694 	queryBuf.AppendNum(KMsvRootIndexEntryId);
       
   695 	queryBuf.Append(KComma);
       
   696 	queryBuf.Append(_L("\"\""));
       
   697 	queryBuf.Append(KComma);
       
   698 	queryBuf.Append(_L("\"\""));
       
   699 	queryBuf.Append(KDelimiter);
       
   700 	
       
   701 	TInt err = tempDB.Exec(queryBuf);
       
   702 	if(err < 0)
       
   703 		{
       
   704 		User::Leave(err);
       
   705 		}
       
   706 	else if(!err)
       
   707 		{
       
   708 		User::Leave(KErrGeneral);
       
   709 		}
       
   710 	CleanupStack::PopAndDestroy(); //queryBuf	
       
   711 	}
       
   712 	
       
   713 	
       
   714 	
       
   715 
       
   716 /**
       
   717  * MaxTMsvIdL()
       
   718  * @param TDriveNumber The drive number of the drive to be queried.
       
   719  * @return None.
       
   720  *
       
   721  * Queries the specified drive's database for the maximum TMsvId
       
   722  * of an entry stored in it.
       
   723  */
       
   724 TMsvId CMsvDBAdapter::MaxTMsvIdL(TUint aDriveId)
       
   725 	{	 
       
   726 	_LIT(KMaxTMsvIdQuery1, "SELECT MAX(id) FROM DB");
       
   727 	_LIT(KMaxTMsvIdQuery2, ".IndexEntry;");
       
   728 	
       
   729 	RBuf queryBuf;
       
   730 	CleanupClosePushL(queryBuf);
       
   731 	queryBuf.CreateL(50);	
       
   732 	
       
   733 	queryBuf.Append(KMaxTMsvIdQuery1);
       
   734 	queryBuf.AppendNum(aDriveId);
       
   735 	queryBuf.Append(KMaxTMsvIdQuery2);
       
   736 	
       
   737 	//Create a select query
       
   738     TSqlScalarFullSelectQuery query(iDatabase);
       
   739 
       
   740 	//Get the column data
       
   741     TMsvId maxTMsvId = query.SelectIntL(queryBuf);
       
   742     
       
   743     CleanupStack::PopAndDestroy(); //queryBuf
       
   744     
       
   745     if(KMsvRootIndexEntryId != maxTMsvId)
       
   746     	maxTMsvId = MaskTMsvId(aDriveId, maxTMsvId);
       
   747     return maxTMsvId;
       
   748 	}
       
   749 
       
   750 
       
   751 
       
   752 
       
   753 /**
       
   754  * ValidateDatabaseL()
       
   755  * @param TDriveNumber The drive number of the drive to be checked.
       
   756  * @return None.
       
   757  *
       
   758  * Validates a database by checking if:
       
   759  * a. The database file is in the appropriate location.
       
   760  * b. The database is readable and not corrupt.
       
   761  * c. The database is of latest supported version.
       
   762  * d. All standard folders (as specified in the messaging resource file)
       
   763  *    exist in the database.
       
   764  */
       
   765 void CMsvDBAdapter::ValidateDatabaseL(TDriveNumber aDriveNumber)
       
   766 	{
       
   767 	//Check (a) and (b).
       
   768 	TParse parse;
       
   769 	TPtrC drive(TDriveUnit(aDriveNumber).Name());
       
   770 	parse.Set(KMessagingDBName, &drive, NULL);
       
   771 	TFileName dbFile = parse.FullName();
       
   772 	
       
   773 	RSqlDatabase tempDB;
       
   774 	CleanupClosePushL(tempDB);
       
   775 	tempDB.OpenL(dbFile);
       
   776 		
       
   777 	//Check (d) with the connection still open.
       
   778 	//Entries to be checked are Root, Local, Inbox, Outbox, Drafts,
       
   779 	//Sent and Deleted.
       
   780 	_LIT(KStandardEntryExistsQuery1, "SELECT count(*) FROM IndexEntry WHERE id <= ");
       
   781 	RBuf queryBuf;	
       
   782 	CleanupClosePushL(queryBuf);
       
   783 	queryBuf.CreateL(150);
       
   784 	queryBuf.Append(KStandardEntryExistsQuery1);
       
   785 	queryBuf.AppendNum(KMsvDeletedEntryFolderEntryId);
       
   786 	queryBuf.Append(KDelimiter);
       
   787 	
       
   788 	TSqlScalarFullSelectQuery query(tempDB);
       
   789 	TInt folders = 0;
       
   790 	folders = query.SelectIntL(queryBuf);
       
   791 	
       
   792 	//The database is invalid if the number of folders returned
       
   793 	//from the above query is not 7.
       
   794 	if(folders != KMsvNumStdFolder) //Number of standard folders + root. To be put in a macro or const
       
   795 		{
       
   796 		User::Leave(KSqlErrCorrupt); 
       
   797 		}
       
   798 	CleanupStack::PopAndDestroy(); //queryBuf	
       
   799 	
       
   800 	//(a), (b) and (d) are fine. Check (c).
       
   801 	//Check the version number against the expected version number.
       
   802 	//PREQ557 version - 1; Post-557 version - 2.
       
   803 	_LIT(KSelectVersionQuery, "SELECT version FROM VersionTable;");
       
   804 	TInt version = 0;
       
   805 	
       
   806 	version = query.SelectIntL(KSelectVersionQuery);
       
   807 	if(version != KCurrentDatabaseVersion)
       
   808 		{
       
   809 		User::Leave(KErrNotSupported);
       
   810 		}
       
   811 	
       
   812 	CleanupStack::PopAndDestroy();  // tempDB
       
   813 	}
       
   814 
       
   815 
       
   816 
       
   817 
       
   818 /**
       
   819  * GetVisibleFolderIdL()
       
   820  * @param TMsvId: Parent Id.
       
   821  * @param TMsvId&: Out parameter for most immediate visible folder id of
       
   822  *				   any child entry present under passed parent id.
       
   823  * @return None. 
       
   824  *
       
   825  * This functions returns the most immediate parent visible folder id.
       
   826  * There are two types of folders. A visible folder is one which is 
       
   827  * visible to the external user, but there are internal non-visible folders
       
   828  * created under each email message to organize the content of the email.
       
   829  * Parent entry of an entry is either root or a folder. A folder can be 
       
   830  * service folder (like LocalServices), user-defined folder/standard folder
       
   831  * like Inbox or a non-visible folder (created under an email message).
       
   832  * 
       
   833  * For a given parent Id, the function returns the most immediate visible
       
   834  * parent folder. The rules are as follows:
       
   835  * 1. If the parent entry is root or children of root, then the visibleFolder 
       
   836  * will be root itself. This is because service folders are considered 
       
   837  * invisible, since they are not seen by user. 
       
   838  * 2. If the parent entry itself is a visible folder then child's visibleFolder
       
   839  * id should be its parent id.
       
   840  * 3. If the parent entry is a non-visible folder then child's visibleFolder
       
   841  * id is same as its parent's visibleFolder id.
       
   842  */
       
   843 void CMsvDBAdapter::GetVisibleFolderIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
       
   844 	{
       
   845 	// If the entry is either a root entry (parent=KErrNotFound) or 
       
   846 	// child of root entry its visibleFolderId will be root entry itself.
       
   847 	if(KErrNotFound == aParentId)
       
   848 		{
       
   849 		aVisibleFolderId = KMsvRootIndexEntryId;
       
   850 		return;		
       
   851 		}
       
   852 
       
   853 	//Get the driveId and unmask the TMsvId supplied.
       
   854 	TInt driveId = GetDriveId(aParentId);
       
   855 	aParentId = UnmaskTMsvId(aParentId);
       
   856 
       
   857 	if(KMsvRootIndexEntryId == aParentId)
       
   858 		{
       
   859 		aVisibleFolderId = KMsvRootIndexEntryId;
       
   860 		}
       
   861 	else
       
   862 		{
       
   863 		//Construct a query for the particular drive.
       
   864 		_LIT8(KGetVisibleIdQuery1, "SELECT data, visibleParent FROM DB");
       
   865 		_LIT8(KGetVisibleIdQuery2, ".IndexEntry WHERE id = ");
       
   866 		
       
   867 		RBuf8 queryBuf;
       
   868 		CleanupClosePushL(queryBuf);
       
   869 		queryBuf.CreateL(70);		
       
   870 		queryBuf.Append(KGetVisibleIdQuery1);
       
   871 		queryBuf.AppendNum(driveId);
       
   872 		queryBuf.Append(KGetVisibleIdQuery2);
       
   873 		queryBuf.AppendNum(aParentId);
       
   874 		queryBuf.Append(KDelimiter);
       
   875 		
       
   876 		RSqlStatement visQuery;
       
   877 		CleanupClosePushL(visQuery);
       
   878 		User::LeaveIfError(visQuery.Prepare(iDatabase, queryBuf));
       
   879 		TInt dataParam = GetColumnIndexL(visQuery, KMsgColumnData());
       
   880 		TInt visParam = GetColumnIndexL(visQuery, KMsgColumnVisibleParent());
       
   881 		
       
   882 		if (KSqlAtRow != visQuery.Next())
       
   883 			{
       
   884 			User::Leave(KErrNotFound);
       
   885 			}
       
   886 		
       
   887 		TInt32 data = ColumnInt(visQuery, dataParam);
       
   888 		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
       
   889 			{
       
   890 			// If visible folder flag is not set for parent entry.
       
   891 			aVisibleFolderId = ColumnInt(visQuery, visParam);
       
   892 			if(!IsStandardId(aVisibleFolderId))
       
   893 				{
       
   894 				aVisibleFolderId = MaskTMsvId(driveId, aVisibleFolderId);
       
   895 				}
       
   896 			}
       
   897 		else
       
   898 			{
       
   899 			// If parent entry is visible
       
   900 			if(IsStandardId(aParentId))
       
   901 				{
       
   902 				aVisibleFolderId = aParentId;				
       
   903 				}
       
   904 			else
       
   905 				{
       
   906 				aVisibleFolderId = MaskTMsvId(driveId, aParentId);
       
   907 				}
       
   908 			}		
       
   909 		CleanupStack::PopAndDestroy(2); //visQuery, queryBuf
       
   910 		}
       
   911 	}
       
   912 
       
   913 
       
   914 
       
   915 
       
   916 /**
       
   917  * CreateEntryL()
       
   918  * @param const TMsvEntry&: The entry to be created.
       
   919  * @param const TMsvId: Immediate visible parent folder of the entry
       
   920  * @return None.
       
   921  *
       
   922  * The function creates a new entry in the database.
       
   923  * No consisitency check is performed on the passed entry. The function may
       
   924  * leave if query execution fails.
       
   925  */
       
   926 void CMsvDBAdapter::CreateEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
       
   927 	{
       
   928 	_LIT8(KCreateEntryQuery1,	 "INSERT INTO DB");
       
   929 	_LIT8(KCreateEntryQuery2, ".IndexEntry VALUES ("
       
   930 							  ":id, :parentId, :serviceId, :mtmId, :type, :date, :data, :size, :error,"
       
   931 							  ":mtmData1, :mtmData2, :mtmData3, :relatedId, :bioType, :pcSyncCount,"
       
   932 							  ":reserved, :visibleParent, :description, :details);"
       
   933 		 );
       
   934 
       
   935 	//Get the driveId and unmask the TMsvId supplied.
       
   936 	TInt driveId = GetDriveId(aNewEntry.iId);
       
   937 	TMsvId id = UnmaskTMsvId(aNewEntry.iId);
       
   938 	TMsvId parentId = UnmaskTMsvId(aNewEntry.iParentId);
       
   939 	TMsvId visFolder = UnmaskTMsvId(aImmediateVisibleFolder);
       
   940 	TMsvId serviceId = UnmaskTMsvId(aNewEntry.iServiceId);
       
   941 	TMsvId relatedId = UnmaskTMsvId(aNewEntry.iRelatedId);
       
   942 	
       
   943 	//Construct a query for the particular drive.
       
   944 	RBuf8 queryBuf;
       
   945 	CleanupClosePushL(queryBuf);
       
   946 	queryBuf.CreateL(350);
       
   947 	queryBuf.Append(KCreateEntryQuery1);
       
   948 	queryBuf.AppendNum(driveId);
       
   949 	queryBuf.Append(KCreateEntryQuery2);
       
   950 	iStatement[ECreateEntry].Close(); //closing any statement prepared previously
       
   951 	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, queryBuf));
       
   952 	
       
   953 	//Bind the entry data
       
   954 	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], id);
       
   955 	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], parentId);
       
   956 	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
       
   957 	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
       
   958 	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
       
   959 	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], relatedId);
       
   960 	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
       
   961 	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
       
   962 	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
       
   963 	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
       
   964 	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
       
   965 	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
       
   966 	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
       
   967 	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
       
   968 	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], serviceId);
       
   969 	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
       
   970 	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], visFolder);
       
   971 	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
       
   972 	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
       
   973 	
       
   974 	TInt err = iStatement[ECreateEntry].Exec();
       
   975 	if(err < 0)
       
   976 		{
       
   977 		User::Leave(err);
       
   978 		}
       
   979 	else if(!err)
       
   980 		{
       
   981 		User::Leave(KErrGeneral);
       
   982 		}
       
   983 	iStatement[ECreateEntry].Close();
       
   984 	CleanupStack::PopAndDestroy();
       
   985 	}
       
   986 
       
   987 
       
   988 
       
   989 
       
   990 /**
       
   991  * UpdateEntryL()
       
   992  * @param const TMsvEntry&: Entry to be updated.
       
   993  * @param const TMsvId: the visible folder Id of the updated entry.
       
   994  * @param TBool: ETrue if the parent of the entry has been changed,
       
   995  *				 EFalse if otherwise.
       
   996  * @return None.
       
   997  *
       
   998  * The function updates an entry in the database.
       
   999  * No consisitency check is performed on the passed entry. The function may
       
  1000  * leave if query execution fails.
       
  1001  */
       
  1002 void CMsvDBAdapter::UpdateEntryL(const TMsvEntry& aEntry, const TMsvId aImmediateVisibleFolder, TBool aIsParentIdUpdated/*DEFAULT=ETrue*/)
       
  1003 	{
       
  1004 	_LIT8(KUpdateEntryQuery1,	"UPDATE DB");
       
  1005 	_LIT8(KUpdateEntryQuery2, ".IndexEntry SET ");
       
  1006 	_LIT8(KUpdateEntryQueryWithParent,	"parentId = :parentId, ");
       
  1007 	_LIT8(KUpdateEntryQueryWithoutParent,	"serviceId = :serviceId, mtmId = :mtmId, type = :type, date = :date,"
       
  1008 							"data = :data, size = :size, error = :error, mtmData1 = :mtmData1, mtmData2 = :mtmData2,"
       
  1009 							"mtmData3 = :mtmData3, relatedId = :relatedId, bioType = :bioType, pcSyncCount = :pcSyncCount,"
       
  1010 							"reserved = :reserved, visibleParent = :visibleParent, description = :description,"
       
  1011 							"details = :details WHERE id = :id;"
       
  1012 		 );
       
  1013 	
       
  1014 	//Get the driveId and unmask the TMsvId supplied.
       
  1015 	TInt driveId = GetDriveId(aEntry.iId);
       
  1016 	TMsvId id = UnmaskTMsvId(aEntry.iId);
       
  1017 	TMsvId parentId = UnmaskTMsvId(aEntry.iParentId);
       
  1018 	TMsvId serviceId = UnmaskTMsvId(aEntry.iServiceId);
       
  1019 	TMsvId relatedId = UnmaskTMsvId(aEntry.iRelatedId);
       
  1020 	TMsvId visFolder = UnmaskTMsvId(aImmediateVisibleFolder);
       
  1021 	
       
  1022 	//Form the query for the particular drive.
       
  1023 	RBuf8 queryBuf;
       
  1024 	CleanupClosePushL(queryBuf);
       
  1025 	queryBuf.CreateL(500);	
       
  1026 	queryBuf.Append(KUpdateEntryQuery1);
       
  1027 	queryBuf.AppendNum(driveId);
       
  1028 	queryBuf.Append(KUpdateEntryQuery2);
       
  1029 
       
  1030 	iStatementType updateStmt;
       
  1031 	TInt err = KErrNone;
       
  1032 	//Bind the entry data
       
  1033 	if(aIsParentIdUpdated)
       
  1034 		{
       
  1035 		updateStmt = EUpdateEntry;
       
  1036 		queryBuf.Append(KUpdateEntryQueryWithParent);
       
  1037 		queryBuf.Append(KUpdateEntryQueryWithoutParent);
       
  1038 		iStatement[updateStmt].Close(); //closing any statement prepared previously
       
  1039 		User::LeaveIfError(iStatement[updateStmt].Prepare(iDatabase, queryBuf));
       
  1040 		BindIntL(iStatement[updateStmt], iParentIdIndex[updateStmt], parentId);
       
  1041 		}
       
  1042 	else
       
  1043 		{
       
  1044 		updateStmt = EUpdateEntryNoParent;
       
  1045 		iStatement[updateStmt].Close(); //closing any statement prepared previously
       
  1046 		queryBuf.Append(KUpdateEntryQueryWithoutParent);
       
  1047 		User::LeaveIfError(iStatement[updateStmt].Prepare(iDatabase, queryBuf));
       
  1048 		}
       
  1049 	BindIntL(iStatement[updateStmt], iVisibleParent[updateStmt], visFolder);
       
  1050 	BindIntL(iStatement[updateStmt], iIdIndex[updateStmt], id);
       
  1051 	BindIntL(iStatement[updateStmt], iDataIndex[updateStmt], aEntry.iData);
       
  1052 	BindIntL(iStatement[updateStmt], iPcSyncCountIndex[updateStmt], aEntry.iPcSyncCount);
       
  1053 	BindIntL(iStatement[updateStmt], iReservedIndex[updateStmt], aEntry.iReserved);
       
  1054 	BindIntL(iStatement[updateStmt], iRelatedIdIndex[updateStmt], relatedId);
       
  1055 	BindIntL(iStatement[updateStmt], iTypeIndex[updateStmt], aEntry.iType.iUid);
       
  1056 	BindInt64L(iStatement[updateStmt], iDateIndex[updateStmt], aEntry.iDate.Int64());
       
  1057 	BindIntL(iStatement[updateStmt], iSizeIndex[updateStmt], aEntry.iSize);
       
  1058 	BindIntL(iStatement[updateStmt], iErrorIndex[updateStmt], aEntry.iError);
       
  1059 	BindIntL(iStatement[updateStmt], iBiotypeIndex[updateStmt], aEntry.iBioType);
       
  1060 	BindIntL(iStatement[updateStmt], iMtmData1Index[updateStmt], aEntry.iMtmData1);
       
  1061 	BindIntL(iStatement[updateStmt], iMtmData2Index[updateStmt], aEntry.iMtmData2);
       
  1062 	BindIntL(iStatement[updateStmt], iMtmData3Index[updateStmt], aEntry.iMtmData3);
       
  1063 	BindIntL(iStatement[updateStmt], iServiceIdIndex[updateStmt], serviceId);
       
  1064 	BindIntL(iStatement[updateStmt], iMtmIdIndex[updateStmt], aEntry.iMtm.iUid);
       
  1065 	BindTextL(iStatement[updateStmt], iDescriptionIndex[updateStmt],aEntry.iDescription);
       
  1066 	BindTextL(iStatement[updateStmt], iDetailsIndex[updateStmt],aEntry.iDetails);
       
  1067 
       
  1068 	//Execute the prepared SQL statement.
       
  1069 	err = iStatement[updateStmt].Exec();
       
  1070 	if(err < 0)
       
  1071 		{
       
  1072 		User::Leave(err);
       
  1073 		}
       
  1074 	iStatement[updateStmt].Close();
       
  1075 	CleanupStack::PopAndDestroy(); //queryBuf
       
  1076 	}
       
  1077 
       
  1078 
       
  1079 
       
  1080 
       
  1081 /**
       
  1082  * DeleteEntryL()
       
  1083  * @param TMsvId: Entry Id to be deleted.
       
  1084  *
       
  1085  * The function deletes an entry with the passed Id. The function
       
  1086  * may leave due to database error while execution. The function
       
  1087  * does not leave if the entry does not exist.
       
  1088  *
       
  1089  * **WARNING** The function does NOT ensure that if a parent entry
       
  1090  * is deleted all its child entries are also deleted.
       
  1091  */
       
  1092 void CMsvDBAdapter::DeleteEntryL(TMsvId aEntryId)
       
  1093 	{
       
  1094 	_LIT8(KDeleteEntryQuery1, "DELETE FROM DB");
       
  1095 	_LIT8(KDeleteEntryQuery2, ".IndexEntry WHERE id = ");
       
  1096 		
       
  1097 	//Get the driveId and unmask the TMsvId supplied.
       
  1098 	TInt driveId = GetDriveId(aEntryId);
       
  1099 	aEntryId = UnmaskTMsvId(aEntryId);
       
  1100 	
       
  1101 	RBuf8 queryBuf;
       
  1102 	CleanupClosePushL(queryBuf);
       
  1103 	queryBuf.CreateL(100);	
       
  1104 	queryBuf.Append(KDeleteEntryQuery1);
       
  1105 	queryBuf.AppendNum(driveId);
       
  1106 	queryBuf.Append(KDeleteEntryQuery2);
       
  1107 	queryBuf.AppendNum(aEntryId);
       
  1108 	queryBuf.Append(KDelimiter);
       
  1109 	
       
  1110 	TInt err = iDatabase.Exec(queryBuf);
       
  1111 	CleanupStack::PopAndDestroy();
       
  1112 	if(err < 0)
       
  1113 		{		
       
  1114 		User::Leave(err);
       
  1115 		}
       
  1116 	else if(!err)
       
  1117 		{
       
  1118 		User::Leave(KErrNotFound);			
       
  1119 		}	
       
  1120 	}
       
  1121 
       
  1122 
       
  1123 
       
  1124 
       
  1125 /**
       
  1126  * DeleteEntryL()
       
  1127  * @param const CMsvEntrySelection&: Entry Id list to be deleted.
       
  1128  * @return None.
       
  1129  * 
       
  1130  * The function deletes all entries mentioned in the passed Id list.
       
  1131  * The function may leave due to database error while execution or
       
  1132  * if an entry does not exist.
       
  1133  *
       
  1134  * **WARNING** The function does NOT ensure that if a parent entry
       
  1135  * is deleted all its child entries are also deleted.
       
  1136  */
       
  1137 void CMsvDBAdapter::DeleteEntryL(const CMsvEntrySelection& aEntryIdList)
       
  1138 	{	
       
  1139 	TInt count;
       
  1140 	if( 0 == (count = aEntryIdList.Count()) )
       
  1141 		{
       
  1142 		return;
       
  1143 		}
       
  1144 
       
  1145 	_LIT(KQuery1, "DELETE FROM DB");
       
  1146 	_LIT(KQuery2, ".IndexEntry WHERE id IN (");
       
  1147 	_LIT(KEndDelimiter, ");");
       
  1148 	
       
  1149 	//Delete maximum 100 entries at a time so as to not overflow IPC buffer
       
  1150 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  1151 	TInt maxEntries = 50; //for testing
       
  1152 #else
       
  1153 	TInt maxEntries = 100;
       
  1154 #endif
       
  1155 
       
  1156 	CMsvEntrySelection* entryList = aEntryIdList.CopyL(); //separate copy of the list to work on
       
  1157 	CleanupStack::PushL(entryList);
       
  1158 	
       
  1159 	for(TInt index1 = 0; index1<count; ++index1)
       
  1160 		{
       
  1161 		TInt driveId = GetDriveId(entryList->At(index1));
       
  1162 		TInt numDeleted = 1;
       
  1163 		RBuf8 queryBuf;
       
  1164 		CleanupClosePushL(queryBuf);
       
  1165 		queryBuf.CreateL(70 + ((10+2)*maxEntries));		
       
  1166 		queryBuf.Append(KQuery1);
       
  1167 		queryBuf.AppendNum(driveId);
       
  1168 		queryBuf.Append(KQuery2);
       
  1169 		queryBuf.AppendNum(UnmaskTMsvId(entryList->At(index1)));
       
  1170 		for(TInt index2 = index1 + 1; index2<count && numDeleted<maxEntries; ++index2)
       
  1171 			{
       
  1172 			if(driveId == GetDriveId(entryList->At(index2)))
       
  1173 				{
       
  1174 				queryBuf.Append(KComma);
       
  1175 				queryBuf.AppendNum(UnmaskTMsvId(entryList->At(index2)));
       
  1176 				++numDeleted;
       
  1177 				entryList->Delete(index2);
       
  1178 				--index2;
       
  1179 				--count;
       
  1180 				}
       
  1181 			}
       
  1182 		entryList->Delete(index1);
       
  1183 		--index1;
       
  1184 		--count;
       
  1185 		queryBuf.Append(KEndDelimiter);
       
  1186 		TInt err = iDatabase.Exec(queryBuf);
       
  1187 		CleanupStack::PopAndDestroy(); //queryBuf
       
  1188 		if(err < 0)
       
  1189 			{
       
  1190 			User::Leave(err);
       
  1191 			}
       
  1192 		}
       
  1193 	CleanupStack::PopAndDestroy(); //entryList
       
  1194 	}
       
  1195 
       
  1196 
       
  1197 
       
  1198 
       
  1199 /**
       
  1200  * GetEntryL()
       
  1201  * @param TMsvId: Id of the entry to be fetched.
       
  1202  * @param CMsvCacheEntry*&: The newly fetched entry.
       
  1203  * @param TMsvId&: Out parameter for value of VisibleParent column.
       
  1204  * @return None.
       
  1205  *
       
  1206  * Fetch an entry from the database. Memory to aEntry
       
  1207  * should not already be assigned.
       
  1208  */
       
  1209 void CMsvDBAdapter::GetEntryL(TMsvId aId, CMsvCacheEntry*& aEntry, TMsvId& aVisibleParentEntryId)
       
  1210 	{
       
  1211 	_LIT8(KGetEntryQuery1, "SELECT parentId, serviceId, mtmId, type, date, data, size, error, "
       
  1212 						"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
  1213 						"reserved, visibleParent, description, details FROM DB");
       
  1214 	_LIT8(KGetEntryQuery2, ".IndexEntry WHERE id = ");
       
  1215 
       
  1216 	//Get the driveId and unmask the TMsvId supplied.
       
  1217 	TInt driveId = GetDriveId(aId);
       
  1218 	
       
  1219 	//Construct a query for the particular drive.
       
  1220 	RBuf8 queryBuf;
       
  1221 	CleanupClosePushL(queryBuf);
       
  1222 	TInt len = KGetEntryQuery1().Length() + KGetEntryQuery2().Length() + 15;
       
  1223 	queryBuf.CreateL(len);	
       
  1224 	queryBuf.Append(KGetEntryQuery1);
       
  1225 	queryBuf.AppendNum(driveId);
       
  1226 	queryBuf.Append(KGetEntryQuery2);
       
  1227 	queryBuf.AppendNum(UnmaskTMsvId(aId));
       
  1228 	queryBuf.Append(KDelimiter);
       
  1229 	
       
  1230 	//Prepare a statement for the query.
       
  1231 	RSqlStatement getStmt;
       
  1232 	CleanupClosePushL(getStmt);
       
  1233 	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
       
  1234 		
       
  1235 	if(KSqlAtRow != getStmt.Next())
       
  1236 		{
       
  1237 		User::Leave(KErrNotFound);
       
  1238 		}
       
  1239 
       
  1240 	//Get the entry from the statement
       
  1241 	aEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  1242 	aEntry->Entry().iId = aId;
       
  1243 	
       
  1244 	LoadEntryFromStatementL(getStmt, EGetEntry, aVisibleParentEntryId, *aEntry);
       
  1245 	
       
  1246 	//We do not return non-standard visible folders from a non-current drive's database.
       
  1247 	if(driveId != KCurrentDriveId 		&&
       
  1248 	   aEntry->Entry().Visible() 		&&
       
  1249 	   !IsStandardId(aEntry->GetId()) 	&&
       
  1250 	   KUidMsvFolderEntryValue == aEntry->Entry().iType.iUid
       
  1251 	  )
       
  1252 		{
       
  1253 		CMsvEntryFreePool::Instance()->ReleaseEntry(aEntry);
       
  1254 		User::Leave(KErrNotFound);
       
  1255 		}
       
  1256 	
       
  1257 	// Unmask iId's of standard Ids.
       
  1258 	if(IsStandardId(aEntry->GetId()))
       
  1259 		{
       
  1260 		aEntry->Entry().SetId(UnmaskTMsvId(aEntry->GetId()));
       
  1261 		}
       
  1262 	
       
  1263 	// Mask iParentId if it is a non-standard id.
       
  1264 	if(!IsStandardId(aEntry->Entry().iParentId))
       
  1265 		{
       
  1266 		aEntry->Entry().iParentId = MaskTMsvId(driveId, aEntry->Entry().iParentId);
       
  1267 		}
       
  1268 	
       
  1269 	// Mask visible folder if it is a non-standard id.
       
  1270 	if(!IsStandardId(aVisibleParentEntryId))
       
  1271 		{
       
  1272 		aVisibleParentEntryId = MaskTMsvId(driveId, aVisibleParentEntryId);
       
  1273 		}
       
  1274 	
       
  1275 	// Mask iServiceId if it is a non-standard id.
       
  1276 	if(!IsStandardId(aEntry->Entry().iServiceId))
       
  1277 		{
       
  1278 		aEntry->Entry().iServiceId = MaskTMsvId(driveId, aEntry->Entry().iServiceId);
       
  1279 		}
       
  1280 	
       
  1281 	// Mask iRelatedId if it is a non-standard id.
       
  1282 	if(!IsStandardId(aEntry->Entry().iRelatedId))
       
  1283 		{
       
  1284 		aEntry->Entry().iRelatedId = MaskTMsvId(driveId, aEntry->Entry().iRelatedId);
       
  1285 		}
       
  1286 	
       
  1287 	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
       
  1288 	}
       
  1289 
       
  1290 
       
  1291 
       
  1292 
       
  1293 /**
       
  1294  * GetChildrenL()
       
  1295  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  1296  * @param RPointerArray<TMsvEntry>&: List of child entries to be filled.
       
  1297  * @return None.
       
  1298  *
       
  1299  * Fetch child entries from the database for a given parent Id.
       
  1300  * This does not check if the parent entry already exist. The 
       
  1301  * entries will be added in ascending order of their TMsvId.
       
  1302  */
       
  1303 void CMsvDBAdapter::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  1304 	{
       
  1305 	_LIT8(KGetChildEntriesQuery1, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
       
  1306 							"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
  1307 							"reserved, visibleParent, description, details FROM DB");
       
  1308 	_LIT8(KGetChildEntriesQuery2, ".IndexEntry WHERE parentId = ");
       
  1309 	_LIT8(KGetChildEntriesQuery3, " order by id ASC;");
       
  1310 	
       
  1311 	//Get the driveId and unmask the TMsvId supplied.
       
  1312 	TInt driveId = GetDriveId(aParentId);
       
  1313 	aParentId = UnmaskTMsvId(aParentId);
       
  1314 	
       
  1315 	//Construct the query for the particular drive.
       
  1316 	RBuf8 queryBuf;
       
  1317 	CleanupClosePushL(queryBuf);
       
  1318 	queryBuf.CreateL(350);	
       
  1319 	queryBuf.Append(KGetChildEntriesQuery1);
       
  1320 	queryBuf.AppendNum(driveId);
       
  1321 	queryBuf.Append(KGetChildEntriesQuery2);
       
  1322 	queryBuf.AppendNum(aParentId);
       
  1323 	queryBuf.Append(KGetChildEntriesQuery3);
       
  1324 	
       
  1325 	//Prepare a statement for the query.
       
  1326 	RSqlStatement getStmt;
       
  1327 	CleanupClosePushL(getStmt);
       
  1328 	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
       
  1329 	
       
  1330 	while(KSqlAtRow == getStmt.Next())
       
  1331 		{
       
  1332 		// Do not return non-standard visible folders from non-current drive.
       
  1333 			// If it is a non-current drive...
       
  1334 		if( (driveId != KCurrentDriveId) 										     	  &&
       
  1335 			// If it is a folder entry.
       
  1336 		    (KUidMsvFolderEntryValue == ColumnInt(getStmt, iTypeIndex[EGetChildEntries])) &&
       
  1337 		    // If it is a visible folder.
       
  1338 			(IsVisibleFolder(ColumnInt(getStmt, iDataIndex[EGetChildEntries])))		      &&
       
  1339 			// If it is a non-standard folder.
       
  1340 			(!IsStandardId(ColumnInt(getStmt, iIdIndex[EGetChildEntries])))
       
  1341 		  )		  		
       
  1342 			{
       
  1343 			continue;
       
  1344 			}
       
  1345 			
       
  1346 		TMsvId aVisibleParentEntryId;
       
  1347 		CMsvCacheEntry *cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  1348 		if(!IsStandardId(aParentId))
       
  1349 			{
       
  1350 			aParentId = MaskTMsvId(driveId, aParentId);
       
  1351 			}
       
  1352 		cacheEntry->Entry().iParentId = aParentId;
       
  1353 		LoadEntryFromStatementL(getStmt, EGetChildEntries, aVisibleParentEntryId, *cacheEntry);
       
  1354 		
       
  1355 		//Add the drive mask to the TMsvId.
       
  1356 		if(!IsStandardId(cacheEntry->GetId()))
       
  1357 			{
       
  1358 			cacheEntry->Entry().iId = MaskTMsvId(driveId, cacheEntry->Entry().iId);
       
  1359 			}
       
  1360 		
       
  1361 		// Mask iServiceId if it is a non-standard id.
       
  1362 		if(!IsStandardId(cacheEntry->Entry().iServiceId))
       
  1363 			{
       
  1364 			cacheEntry->Entry().iServiceId = MaskTMsvId(driveId, cacheEntry->Entry().iServiceId);
       
  1365 			}
       
  1366 		
       
  1367 		// Mask iRelatedId if it is a non-standard id.
       
  1368 		if(!IsStandardId(cacheEntry->Entry().iRelatedId))
       
  1369 			{
       
  1370 			cacheEntry->Entry().iRelatedId = MaskTMsvId(driveId, cacheEntry->Entry().iRelatedId);
       
  1371 			}
       
  1372 	
       
  1373 		//Add the child entry to the array given
       
  1374 		aChildArray.AppendL(cacheEntry);
       
  1375 		}
       
  1376 	
       
  1377 	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
       
  1378 	}
       
  1379 
       
  1380 
       
  1381 
       
  1382 
       
  1383 /**
       
  1384  * GetChildrenIdL()
       
  1385  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  1386  * @param CMsvEntrySelection&: List of child entry Id's.
       
  1387  * @return None.
       
  1388  *
       
  1389  * Fetch child entry Id's from the database for a given parent Id.
       
  1390  * This does not check if the parent entry already exist. The 
       
  1391  * entries will be added in ascending order of their TMsvId.
       
  1392  */
       
  1393 void CMsvDBAdapter::GetChildrenIdL(TMsvId aParentId, CMsvEntrySelection& aChildArray)
       
  1394 	{
       
  1395 	_LIT8(KGetChildIdsQuery1, "SELECT id, type, data FROM DB");
       
  1396 	_LIT8(KGetChildIdsQuery2, ".IndexEntry WHERE parentId = ");
       
  1397 	_LIT8(KGetChildIdsQuery3, " order by id ASC;");
       
  1398 	
       
  1399 	//Get the driveId and unmask the TMsvId supplied.
       
  1400 	TInt driveId = GetDriveId(aParentId);
       
  1401 	aParentId = UnmaskTMsvId(aParentId);
       
  1402 	
       
  1403 	//Construct the query for the particular drive.
       
  1404 	RBuf8 queryBuf;
       
  1405 	CleanupClosePushL(queryBuf);
       
  1406 	queryBuf.CreateL(100);	
       
  1407 	queryBuf.Append(KGetChildIdsQuery1);
       
  1408 	queryBuf.AppendNum(driveId);
       
  1409 	queryBuf.Append(KGetChildIdsQuery2);
       
  1410 	queryBuf.AppendNum(aParentId);
       
  1411 	queryBuf.Append(KGetChildIdsQuery3);
       
  1412 	
       
  1413 	//Prepare a statement for the query.
       
  1414 	RSqlStatement getStmt;
       
  1415 	CleanupClosePushL(getStmt);
       
  1416 	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
       
  1417 	
       
  1418 	while(KSqlAtRow == getStmt.Next())
       
  1419 		{
       
  1420 		// Do not return non-standard visible folders from non-current drive.
       
  1421 			// If it is a non-current drive...
       
  1422 		if( (driveId != KCurrentDriveId) 					 				     	  &&
       
  1423 			// If it is a folder entry.
       
  1424 		    (KUidMsvFolderEntryValue == ColumnInt(getStmt, iTypeIndex[EGetChildIds])) &&
       
  1425 		    // If it is a visible folder.
       
  1426 			(IsVisibleFolder(ColumnInt(getStmt, iDataIndex[EGetChildIds])))		      &&
       
  1427 			// If it is a non-standard folder.
       
  1428 			(!IsStandardId(ColumnInt(getStmt, iIdIndex[EGetChildIds])))
       
  1429 		  )		  		
       
  1430 			{
       
  1431 			continue;
       
  1432 			}
       
  1433 		
       
  1434 		TMsvId id = ColumnInt(getStmt, iIdIndex[EGetChildIds]);
       
  1435 		if(!IsStandardId(id))
       
  1436 			{
       
  1437 			id = MaskTMsvId(driveId, id);
       
  1438 			}
       
  1439 		//Add the child Id to the array given
       
  1440 		aChildArray.AppendL(id);
       
  1441 		}
       
  1442 	
       
  1443 	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
       
  1444 	}
       
  1445 
       
  1446 
       
  1447 
       
  1448 
       
  1449 /**
       
  1450  * GetChildrenL()
       
  1451 * @param const TDesC&: Partial query string. (Where clause condition).
       
  1452  *               The query string should start with 'AND' and should 
       
  1453  *               end with a semicolon. Examples are:
       
  1454  *               "AND ID BETWEEN 100 and 200 ORDER BY ID ASC;"
       
  1455  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  1456  * @param RPointerArray<TMsvEntry>&: List of child entries to be filled.
       
  1457  * @return None.
       
  1458  *
       
  1459  * Fetch child entries from the database for a given parent Id.
       
  1460  * This does not check if the parent entry already exist. The 
       
  1461  * entries will be added in ascending order of their TMsvId.
       
  1462  */
       
  1463 void CMsvDBAdapter::GetChildrenL(const TDesC8& aQueryStr, TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  1464 	{
       
  1465 	_LIT8(KQueryString1, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
       
  1466 			"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
  1467 			"reserved, visibleParent, description, details FROM DB");
       
  1468 	_LIT8(KQueryString2, ".IndexEntry WHERE parentId = ");
       
  1469 
       
  1470 	//Get the driveId and unmask the TMsvId supplied.
       
  1471 	TInt driveId = GetDriveId(aParentId);
       
  1472 	aParentId = UnmaskTMsvId(aParentId);
       
  1473 	
       
  1474 	//Construct a query for the particular drive.
       
  1475 	TInt len = KQueryString1().Length() + KQueryString2().Length() + aQueryStr.Length();
       
  1476 	len += 30;
       
  1477 	RBuf8 queryBuf;
       
  1478 	CleanupClosePushL(queryBuf);
       
  1479 	queryBuf.CreateL(len);	
       
  1480 	queryBuf.Append(KQueryString1);
       
  1481 	queryBuf.AppendNum(driveId);
       
  1482 	queryBuf.Append(KQueryString2);
       
  1483 	queryBuf.AppendNum(aParentId);
       
  1484 	queryBuf.Append(aQueryStr);
       
  1485 	
       
  1486 	//Prepare a statement for the query.
       
  1487 	RSqlStatement condGetChildrenStmnt;
       
  1488 	CleanupClosePushL(condGetChildrenStmnt);
       
  1489 	
       
  1490 	User::LeaveIfError(condGetChildrenStmnt.Prepare(iDatabase, queryBuf));
       
  1491 	TInt index = 0;
       
  1492 
       
  1493 	while(KSqlAtRow == condGetChildrenStmnt.Next())
       
  1494 		{
       
  1495 		TInt type = ColumnInt(condGetChildrenStmnt, 3);
       
  1496 		TInt32 data = ColumnInt(condGetChildrenStmnt, 5);
       
  1497 
       
  1498 		// Do not return non-standard visible folders from non-current drive.
       
  1499 			// If it is a non-current drive...
       
  1500 		if( (driveId != KCurrentDriveId) 	  &&
       
  1501 			// If it is a folder entry.
       
  1502 		    (KUidMsvFolderEntryValue == type) &&
       
  1503 		    // If it is a visible folder.
       
  1504 			(IsVisibleFolder(data))		      &&
       
  1505 			// If it is a non-standard folder.
       
  1506 			(!IsStandardId(ColumnInt(condGetChildrenStmnt, 0)))
       
  1507 		  )
       
  1508 		  	{
       
  1509 			continue;
       
  1510 			}
       
  1511 		
       
  1512 		CMsvCacheEntry* cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  1513 		if(!IsStandardId(aParentId))
       
  1514 			{
       
  1515 			aParentId = MaskTMsvId(driveId, aParentId);
       
  1516 			}
       
  1517 		cacheEntry->Entry().iParentId = aParentId;
       
  1518 
       
  1519 		index = 0;
       
  1520 		TMsvId id = ColumnInt(condGetChildrenStmnt, index);
       
  1521 		if(IsStandardId(id))
       
  1522 			{
       
  1523 			cacheEntry->Entry().iId = id;
       
  1524 			}
       
  1525 		else
       
  1526 			{
       
  1527 			cacheEntry->Entry().iId = MaskTMsvId(driveId, id);
       
  1528 			}		
       
  1529 		cacheEntry->Entry().iServiceId = ColumnInt(condGetChildrenStmnt, ++index);
       
  1530 		cacheEntry->Entry().iMtm.iUid = ColumnInt(condGetChildrenStmnt, ++index);
       
  1531 		cacheEntry->Entry().iType.iUid = type;
       
  1532 		cacheEntry->Entry().iDate = ColumnInt64(condGetChildrenStmnt, ++index);
       
  1533 		cacheEntry->Entry().iData = data;
       
  1534 		cacheEntry->Entry().iSize = ColumnInt(condGetChildrenStmnt, ++index);
       
  1535 		cacheEntry->Entry().iError = ColumnInt(condGetChildrenStmnt, ++index);
       
  1536 		cacheEntry->Entry().iMtmData1 = ColumnInt(condGetChildrenStmnt, ++index);
       
  1537 		cacheEntry->Entry().iMtmData2 = ColumnInt(condGetChildrenStmnt, ++index);
       
  1538 		cacheEntry->Entry().iMtmData3 = ColumnInt(condGetChildrenStmnt, ++index);
       
  1539 		cacheEntry->Entry().iRelatedId = ColumnInt(condGetChildrenStmnt, ++index);
       
  1540 		cacheEntry->Entry().iBioType = ColumnInt(condGetChildrenStmnt, ++index);
       
  1541 		cacheEntry->Entry().iPcSyncCount = ColumnInt(condGetChildrenStmnt, ++index);
       
  1542 		cacheEntry->Entry().iReserved = ColumnInt(condGetChildrenStmnt, ++index);
       
  1543 		TMsvId aVisibleParentEntryId = ColumnInt(condGetChildrenStmnt, ++index);
       
  1544 		
       
  1545 		cacheEntry->iDescriptionBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  1546 		cacheEntry->Entry().iDescription.Set(*cacheEntry->iDescriptionBuffer);
       
  1547 		
       
  1548 		cacheEntry->iDetailsBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  1549 		cacheEntry->Entry().iDetails.Set(*cacheEntry->iDetailsBuffer);
       
  1550 		
       
  1551 		
       
  1552 		// Mask iServiceId if it is a non-standard id.
       
  1553 		if(!IsStandardId(cacheEntry->Entry().iServiceId))
       
  1554 			{
       
  1555 			cacheEntry->Entry().iServiceId = MaskTMsvId(driveId, cacheEntry->Entry().iServiceId);
       
  1556 			}
       
  1557 		
       
  1558 		// Mask iRelatedId if it is a non-standard id.
       
  1559 		if(!IsStandardId(cacheEntry->Entry().iRelatedId))
       
  1560 			{
       
  1561 			cacheEntry->Entry().iRelatedId = MaskTMsvId(driveId, cacheEntry->Entry().iRelatedId);
       
  1562 			}
       
  1563 		
       
  1564 		//Add the child entry to the array given
       
  1565 		aChildArray.AppendL(cacheEntry);
       
  1566 		}
       
  1567 	CleanupStack::PopAndDestroy(2);		// condGetChildrenStmnt,queryBuf
       
  1568 	}
       
  1569 
       
  1570 
       
  1571 
       
  1572 
       
  1573 /**
       
  1574  * EntryExistsL()
       
  1575  * @param TMsvId: Entry Id to check.
       
  1576  * @return TBool: ETrue if the entry exists, otherwise EFalse.
       
  1577  *
       
  1578  * Checks if an entry with the specified TMsvId exists in the database.
       
  1579  */
       
  1580 TBool CMsvDBAdapter::EntryExistsL(TMsvId aId)
       
  1581 	{
       
  1582 	_LIT8(KEntryExistsQuery1, "SELECT id FROM DB");
       
  1583 	_LIT8(KEntryExistsQuery2, ".IndexEntry WHERE id = ");
       
  1584 		
       
  1585 	//Get the driveId and unmask the TMsvId supplied.
       
  1586 	TInt driveId = GetDriveId(aId);
       
  1587 	aId = UnmaskTMsvId(aId);
       
  1588 	
       
  1589 	//Construct a query for the particular drive.
       
  1590 	RBuf8 queryBuf;
       
  1591 	CleanupClosePushL(queryBuf);
       
  1592 	TInt len = KEntryExistsQuery1().Length() + 10 + KEntryExistsQuery2().Length(); //10 = space for TMsvId
       
  1593 	queryBuf.CreateL(len);	
       
  1594 	queryBuf.Append(KEntryExistsQuery1);
       
  1595 	queryBuf.AppendNum(driveId);
       
  1596 	queryBuf.Append(KEntryExistsQuery2);
       
  1597 	queryBuf.AppendNum(aId);
       
  1598 	queryBuf.Append(KDelimiter);
       
  1599 	
       
  1600 	TSqlScalarFullSelectQuery query(iDatabase);
       
  1601 	TMsvId id = NULL;
       
  1602 	TRAPD(err, id = query.SelectIntL(queryBuf));
       
  1603 	
       
  1604 	CleanupStack::PopAndDestroy(); //queryBuf
       
  1605 	if(err!= KErrNone && err!= KErrNotFound)
       
  1606 		{
       
  1607 		User::Leave(err);
       
  1608 		}
       
  1609 	if(id)
       
  1610 		{
       
  1611 		return ETrue;
       
  1612 		}
       
  1613 	else
       
  1614 		{
       
  1615 		return EFalse;
       
  1616 		}
       
  1617 	}
       
  1618 
       
  1619 
       
  1620 
       
  1621 	
       
  1622 /**
       
  1623  * GetInPreparationIdL()
       
  1624  * @param CMsvEntrySelection&: List of the TMsvEntries 
       
  1625  * 		                       whose KMsvEntryInPreparationFlag is set.
       
  1626  * @return None.
       
  1627  *
       
  1628  * Gets the TMsvId's of all the entries whose KMsvEntryInPreparationFlag
       
  1629  * is set in the database.
       
  1630  */
       
  1631 void CMsvDBAdapter::GetInPreparationIdL(CMsvEntrySelection& aSelection, TUint aDriveId /* DEFAULT = 0 */)
       
  1632 	{
       
  1633 	if(aDriveId)
       
  1634 		{
       
  1635 		DoGetInPreparationIdL(aSelection, aDriveId);
       
  1636 		}
       
  1637 	else
       
  1638 		{
       
  1639 		//Iterate through all the dives that might have a database.
       
  1640 		for(TInt driveId = 1; driveId < KMaxNumberOfDrives; ++driveId)
       
  1641 			{
       
  1642 			DoGetInPreparationIdL(aSelection, driveId);		
       
  1643 			}
       
  1644 		}	
       
  1645 	}
       
  1646 
       
  1647 
       
  1648 
       
  1649 
       
  1650 void CMsvDBAdapter::DoGetInPreparationIdL(CMsvEntrySelection& aSelection, TUint aDriveId)
       
  1651 	{
       
  1652 	_LIT8(KGetInPreparationIdQuery1, "SELECT id, data FROM DB");
       
  1653 	_LIT8(KGetInPreparationIdQuery2, ".IndexEntry;");
       
  1654 	
       
  1655 	TInt paramIdColumn = 0;
       
  1656 	TInt paramDataColumn = 1;
       
  1657 			
       
  1658 	//Check if the drive has the database present.
       
  1659 	//The iDatabasePresent array will have a value for only those driveIds which
       
  1660 	//have been added through AttachDBL().
       
  1661 	if((*iDatabasePresent)[aDriveId])
       
  1662 		{
       
  1663 		RBuf8 queryBuf;
       
  1664 		CleanupClosePushL(queryBuf);
       
  1665 		queryBuf.CreateL(40);		
       
  1666 		queryBuf.Append(KGetInPreparationIdQuery1);
       
  1667 		queryBuf.AppendNum(aDriveId);
       
  1668 		queryBuf.Append(KGetInPreparationIdQuery2);
       
  1669 		
       
  1670 		RSqlStatement statement;
       
  1671 		CleanupClosePushL(statement);
       
  1672 		User::LeaveIfError(statement.Prepare(iDatabase, queryBuf));
       
  1673 		
       
  1674 		TMsvId id;
       
  1675 		TInt32 data;
       
  1676 		while (KSqlAtRow == statement.Next())
       
  1677 			{
       
  1678 			data = ColumnInt(statement, paramDataColumn);
       
  1679 			if( data & TMsvEntry::KMsvEntryInPreparationFlag )
       
  1680 				{
       
  1681 				id = ColumnInt(statement, paramIdColumn);
       
  1682 				if(!IsStandardId(id))
       
  1683 					{
       
  1684 					id = MaskTMsvId(aDriveId, id);
       
  1685 					}
       
  1686 				aSelection.AppendL(id);
       
  1687 				}
       
  1688 			}
       
  1689 		CleanupStack::PopAndDestroy(2); //statement, queryBuf
       
  1690 		}
       
  1691 	}
       
  1692 
       
  1693 	
       
  1694 	
       
  1695 
       
  1696 /**
       
  1697  * GetVisibleFlagL()
       
  1698  * @param TMsvId: the Id of the entry whose flag is to be checked.
       
  1699  * @return TBool: ETrue if the entry is visible, EFalse otherwise.
       
  1700  *
       
  1701  * Returns the status of the visible flag of an entry in the DB.
       
  1702  */
       
  1703 TBool CMsvDBAdapter::GetVisibleFlagL(TMsvId aEntryId)
       
  1704 	{
       
  1705 	_LIT8(KGetVisibleFlagQuery1, "SELECT data FROM DB");
       
  1706 	_LIT8(KGetVisibleFlagQuery2, ".IndexEntry WHERE id = ");
       
  1707 	
       
  1708 	//Get the driveId and unmask the TMsvId supplied.
       
  1709 	TInt driveId = GetDriveId(aEntryId);
       
  1710 	aEntryId = UnmaskTMsvId(aEntryId);
       
  1711 	
       
  1712 	RBuf8 queryBuf;
       
  1713 	CleanupClosePushL(queryBuf);
       
  1714 	queryBuf.CreateL(60);	
       
  1715 	queryBuf.Append(KGetVisibleFlagQuery1);
       
  1716 	queryBuf.AppendNum(driveId);
       
  1717 	queryBuf.Append(KGetVisibleFlagQuery2);
       
  1718 	queryBuf.AppendNum(aEntryId);
       
  1719 	queryBuf.Append(KDelimiter);
       
  1720 	
       
  1721 	TSqlScalarFullSelectQuery query(iDatabase);
       
  1722 	TInt32 data = query.SelectIntL(queryBuf);
       
  1723 	CleanupStack::PopAndDestroy();		// queryBuf
       
  1724 	if(data & TMsvEntry::KMsvEntryInvisibleFlag )
       
  1725 		{
       
  1726 		return EFalse;
       
  1727 		}
       
  1728 	else
       
  1729 		{
       
  1730 		return ETrue;
       
  1731 		}
       
  1732 	}
       
  1733 
       
  1734 
       
  1735 
       
  1736 
       
  1737 /**
       
  1738  * UpdateVisibleFolderL()
       
  1739  * @param CMsvEntrySelection*: List of entries whose visible parent is
       
  1740  *							   to be updated.
       
  1741  * @param TMsvId: The new visible folder Id.
       
  1742  * @return None.
       
  1743  *
       
  1744  * Updates the visible parent of the entries passed through the selection.
       
  1745  */
       
  1746  void CMsvDBAdapter::UpdateVisibleFolderL(CMsvEntrySelection* aEntryList, TMsvId aNewVisibleFolderId)
       
  1747  	{
       
  1748  	_LIT8(KUpdateVisibleFolderQuery1,	"UPDATE DB");
       
  1749  	_LIT8(KUpdateVisibleFolderQuery2, ".IndexEntry SET visibleParent = ");
       
  1750 	_LIT8(KUpdateVisibleFolderQuery3,	" WHERE id IN ( ");
       
  1751 	_LIT8(KEndDelimiter, ");");
       
  1752 	
       
  1753 	TInt count = aEntryList->Count();
       
  1754 	if(0 == count)
       
  1755 		{
       
  1756 		return;
       
  1757 		}
       
  1758 	
       
  1759 	//Get the driveId and unmask the TMsvId supplied.
       
  1760 	aNewVisibleFolderId = UnmaskTMsvId(aNewVisibleFolderId);
       
  1761 	CMsvEntrySelection* list = aEntryList->CopyL();
       
  1762 	CleanupStack::PushL(list);
       
  1763 	
       
  1764 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  1765 	TInt maxEntries = 50; //for testing
       
  1766 #else
       
  1767 	TInt maxEntries = 100;
       
  1768 #endif
       
  1769 	
       
  1770 	BeginTransactionL();
       
  1771 	for(TInt index1 = 0; index1<count; ++index1)
       
  1772 		{
       
  1773 		TInt driveId = GetDriveId(list->At(index1));
       
  1774 		
       
  1775 		RBuf8 queryBuf;
       
  1776 		CleanupClosePushL(queryBuf);
       
  1777 		queryBuf.CreateL(50 + ((10+2)*maxEntries));		
       
  1778 		queryBuf.Append(KUpdateVisibleFolderQuery1);
       
  1779 		queryBuf.AppendNum(driveId);
       
  1780 		queryBuf.Append(KUpdateVisibleFolderQuery2);
       
  1781 		queryBuf.AppendNum(aNewVisibleFolderId);
       
  1782 		queryBuf.Append(KUpdateVisibleFolderQuery3);
       
  1783 		queryBuf.AppendNum(UnmaskTMsvId(list->At(index1)));
       
  1784 		TInt num = 1;
       
  1785 		for(TInt index2 = index1 + 1; index2<count && num<maxEntries; ++index2)
       
  1786 			{
       
  1787 			if(driveId == GetDriveId(list->At(index2)))
       
  1788 				{
       
  1789 				queryBuf.Append(KComma);
       
  1790 				queryBuf.AppendNum(UnmaskTMsvId(list->At(index2)));
       
  1791 				++num;
       
  1792 				list->Delete(index2);
       
  1793 				--index2;
       
  1794 				--count;
       
  1795 				}
       
  1796 			}
       
  1797 		list->Delete(index1);
       
  1798 		--index1;
       
  1799 		--count;
       
  1800 		queryBuf.Append(KEndDelimiter);
       
  1801 		TInt err = iDatabase.Exec(queryBuf);
       
  1802 		CleanupStack::PopAndDestroy(); //queryBuf
       
  1803 		if(err < 0)
       
  1804 			{
       
  1805 			User::Leave(err);
       
  1806 			}
       
  1807 		}
       
  1808 	
       
  1809 	CommitTransactionL();
       
  1810 	CleanupStack::PopAndDestroy(); //list
       
  1811 	}
       
  1812 
       
  1813 
       
  1814 
       
  1815 
       
  1816 /**
       
  1817  * UpdateOwnerStatusL()
       
  1818  *
       
  1819  * @param TMsvId: the Id of an entry which has had a child added
       
  1820  *				   under it and needs its owner flag updated.
       
  1821  * @param const TMsvEntry&: the parent entry.
       
  1822  * @param TBool: ETrue if the owner flag should be set, EFalse if otherwise.
       
  1823  * @return None.
       
  1824  *
       
  1825  * The function updates the owner flag of an entry which has had a
       
  1826  * child added or deleted under it.
       
  1827  */
       
  1828 void CMsvDBAdapter::UpdateOwnerStatusL(TMsvId aId, const TMsvEntry& aParent, TBool aSet)
       
  1829 	{
       
  1830 	_LIT8(KUpdateOwnershipQuery1,	"UPDATE DB");
       
  1831 	_LIT8(KUpdateOwnershipQuery2, ".IndexEntry SET data = ");
       
  1832 	_LIT8(KUpdateOwnershipQuery3,	" WHERE id = ");
       
  1833 	
       
  1834 	// Owner flag has already been set. Return to caller.
       
  1835 	if(aParent.Owner() && aSet)
       
  1836 		{
       
  1837 		return;
       
  1838 		}
       
  1839 	// Otherwise update the owner flag for the entry in the DB.
       
  1840 	else
       
  1841 		{
       
  1842 		//Get the driveId and unmask the TMsvId supplied.
       
  1843 		TInt driveId = GetDriveId(aId);
       
  1844 		TMsvId parentId = UnmaskTMsvId(aId);
       
  1845 		
       
  1846 		TInt32 data;
       
  1847 		if(aSet)
       
  1848 			{
       
  1849 			data = aParent.iData | TMsvEntry::KMsvEntryOwnerFlag;
       
  1850 			}
       
  1851 		else
       
  1852 			{
       
  1853 			data = aParent.iData & ~(TMsvEntry::KMsvEntryOwnerFlag);
       
  1854 			}
       
  1855 		TInt len = KUpdateOwnershipQuery1().Length() + KUpdateOwnershipQuery2().Length();
       
  1856 		len += KUpdateOwnershipQuery3().Length() + 100; //data and TMsvId.
       
  1857 		RBuf8 queryBuf;
       
  1858 		CleanupClosePushL(queryBuf);
       
  1859 		queryBuf.CreateL(len);		
       
  1860 		queryBuf.Append(KUpdateOwnershipQuery1);
       
  1861 		queryBuf.AppendNum(driveId);
       
  1862 		queryBuf.Append(KUpdateOwnershipQuery2);
       
  1863 		queryBuf.AppendNum(data);
       
  1864 		queryBuf.Append(KUpdateOwnershipQuery3);
       
  1865 		queryBuf.AppendNum(parentId);
       
  1866 		queryBuf.Append(KDelimiter);
       
  1867 		TInt err = iDatabase.Exec(queryBuf);
       
  1868 		if(err < 0)
       
  1869 			{
       
  1870 			User::Leave(err);
       
  1871 			}
       
  1872 		CleanupStack::PopAndDestroy(); //queryBuf
       
  1873 		}
       
  1874 	}
       
  1875 
       
  1876 
       
  1877 
       
  1878 
       
  1879 #else		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1880 
       
  1881 
       
  1882 
       
  1883 
       
  1884 /**
       
  1885  * NewL()
       
  1886  * @param TFileName: DB File Name.
       
  1887  * @return The newly created database adapter object.
       
  1888  *
       
  1889  * The function creates a new secure database in syslib private folder.
       
  1890  * It takes database name as input arg and returns instance of 
       
  1891  * DB adpater class.
       
  1892  */
       
  1893 CMsvDBAdapter* CMsvDBAdapter::NewL(const TFileName& aDbFileName)
       
  1894 	{
       
  1895 	//Create an messaging DB adaptor object.
       
  1896 	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
       
  1897 	CleanupStack::PushL(self);
       
  1898 	
       
  1899 	// Create the database.
       
  1900 	TBool isDBCreated = EFalse;
       
  1901 	TRAPD(err, self->ConstructNewL(aDbFileName, isDBCreated));
       
  1902 	if( KErrNone != err )
       
  1903 		{
       
  1904 		if( isDBCreated )
       
  1905 			{
       
  1906 			DeleteDB(aDbFileName);
       
  1907 			}
       
  1908 		User::Leave(err);
       
  1909 		}
       
  1910 
       
  1911 	CleanupStack::Pop(self);
       
  1912 	return self;
       
  1913 	}
       
  1914 
       
  1915 
       
  1916 
       
  1917 
       
  1918 /**
       
  1919  * OpenL()
       
  1920  * @param TFileName: DB File Name.
       
  1921  * @return The newly created database adapter object.
       
  1922  *
       
  1923  * The function opens an already existing database. The database file
       
  1924  * is searched in syslib private folder. It takes database name as 
       
  1925  * input arg and returns instance of DB adpater class. The function
       
  1926  * leaves if the DB file is not found or if the file is corrupted.
       
  1927  */
       
  1928 CMsvDBAdapter* CMsvDBAdapter::OpenL(const TFileName& aDbFileName)
       
  1929 	{
       
  1930 	//Create an messaging DB adaptor object 
       
  1931 	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
       
  1932 	CleanupStack::PushL(self);
       
  1933 	
       
  1934 	// Open the database.
       
  1935 	self->ConstructOpenL(aDbFileName);
       
  1936 	
       
  1937 	CleanupStack::Pop(self);
       
  1938 	return self;
       
  1939 	}
       
  1940 
       
  1941 
       
  1942 
       
  1943 
       
  1944 /**
       
  1945  * DeleteDB()
       
  1946  * @param TFileName: DB File Name.
       
  1947  * @return error.
       
  1948  *
       
  1949  * This is a static function, hence can be called without creating
       
  1950  * an instance of this class. The function deletes the database
       
  1951  * file as mentioned in the input argument. The database file is
       
  1952  * searched in syslib private folder. 
       
  1953  */
       
  1954 TInt CMsvDBAdapter::DeleteDB(const TFileName& aDbFileName)
       
  1955 	{
       
  1956 	return RSqlDatabase::Delete(aDbFileName);
       
  1957 	}
       
  1958 
       
  1959 
       
  1960 
       
  1961 
       
  1962 /**
       
  1963  * ConstructOpenL()
       
  1964  * @param TFileName: DB File Name.
       
  1965  * 
       
  1966  * This functions is called by OpenL() to open an existing database.
       
  1967  * The function leaves if there is an error while opening the DB with
       
  1968  * the leave code same as error code. It takes DB filename as input 
       
  1969  * argument. The database file is searched in syslib private folder. 
       
  1970  */
       
  1971 void CMsvDBAdapter::ConstructOpenL(const TFileName& aDbFileName)
       
  1972 	{
       
  1973 	// >>> Pass configuration parameter, while opening the DB.
       
  1974 	User::LeaveIfError(iDatabase.Open(aDbFileName));
       
  1975 	ClearDBContentsL();
       
  1976 	ConstructSortTableL();
       
  1977 	
       
  1978 	//Initialize the database adapter class
       
  1979 	InitializeL();
       
  1980 
       
  1981 	//Initialize the Search Sort database adapter class
       
  1982 	InitializeSortTableL();
       
  1983 	}
       
  1984 
       
  1985 
       
  1986 
       
  1987 
       
  1988 /**
       
  1989  * ConstructNewL()
       
  1990  * @param TFileName: DB File Name.
       
  1991  * 
       
  1992  * This functions is called by NewL() to create a new database.
       
  1993  * The function leaves if there is an error while creating the DB with
       
  1994  * the leave code same as error code. It takes DB filename as input 
       
  1995  * argument. The database file is created in syslib private folder. 
       
  1996  * It then create standard tables as well as indexes in the database.
       
  1997  */
       
  1998 void CMsvDBAdapter::ConstructNewL(const TFileName& aDbFileName, TBool& aIsDBCreated)
       
  1999 	{
       
  2000 	HBufC8* heapBuf = KEncodingText().AllocLC();
       
  2001 
       
  2002 	//Create the database.
       
  2003 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  2004 	User::LeaveIfError(iDatabase.Create(aDbFileName, heapBuf));
       
  2005 #else	
       
  2006 	// Using SID based security policy.
       
  2007 	TSecureId sid(SERVER_UID);
       
  2008 	const TSecurityPolicy KDefaultPolicy(sid);
       
  2009 	
       
  2010 	//Create security policy
       
  2011 	RSqlSecurityPolicy securityPolicy;
       
  2012 	CleanupClosePushL(securityPolicy);	
       
  2013 		
       
  2014 	User::LeaveIfError(securityPolicy.Create(KDefaultPolicy));
       
  2015 	User::LeaveIfError(iDatabase.Create(aDbFileName, securityPolicy, heapBuf));
       
  2016 	
       
  2017 	// Destroy securityPolicy.
       
  2018 	CleanupStack::PopAndDestroy();		
       
  2019 #endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  2020 
       
  2021 	// Destroy heapBuf
       
  2022 	CleanupStack::PopAndDestroy();
       
  2023 	aIsDBCreated = ETrue;
       
  2024 
       
  2025 	//Create tables for the database
       
  2026 	TInt err = iDatabase.Exec(KCreateIndexEntryTableQuery);
       
  2027 	if(err < 0)
       
  2028 		{
       
  2029 		User::Leave(err);
       
  2030 		}
       
  2031 	else if(!err)
       
  2032 		{
       
  2033 		User::Leave(KErrGeneral);
       
  2034 		}
       
  2035 		
       
  2036 	//Create index on indexEnty table.
       
  2037 	//Index is created on parentId.
       
  2038 	err = iDatabase.Exec(KCreateIndexQuery);
       
  2039 	if(err < 0)
       
  2040 		{
       
  2041 		User::Leave(err);
       
  2042 		}
       
  2043 	else if(!err)
       
  2044 		{
       
  2045 		User::Leave(KErrGeneral);
       
  2046 		}
       
  2047 	
       
  2048 	//Create the version table to store the message store version.
       
  2049 	err = iDatabase.Exec(KCreateVersionTableQuery);
       
  2050 	if(err < 0)
       
  2051 		{
       
  2052 		User::Leave(err);
       
  2053 		}
       
  2054 	else if(!err)
       
  2055 		{
       
  2056 		User::Leave(KErrGeneral);
       
  2057 		}
       
  2058 	//Insert the version number into the above table.
       
  2059 	_LIT8(KInsertVersionNumberQuery, " INSERT INTO VersionTable Values ( " );
       
  2060 	_LIT8(KDelimiter, " );");
       
  2061 	RBuf8 versionQuery;
       
  2062 	CleanupClosePushL(versionQuery);
       
  2063 	versionQuery.CreateL(50); //a small value is more than enough for the above query.	
       
  2064 	versionQuery.Append(KInsertVersionNumberQuery);
       
  2065 	versionQuery.AppendNum(KCurrentDatabaseVersion);
       
  2066 	versionQuery.Append(KDelimiter);
       
  2067 	err = iDatabase.Exec(versionQuery);
       
  2068 	if(err < 0)
       
  2069 		{
       
  2070 		User::Leave(err);
       
  2071 		}
       
  2072 	else if(!err)
       
  2073 		{
       
  2074 		User::Leave(KErrGeneral);
       
  2075 		}
       
  2076 	CleanupStack::PopAndDestroy(); //versionQuery
       
  2077 
       
  2078 	ConstructSortTableL();
       
  2079 	
       
  2080 	//Initialize the database adapter class
       
  2081 	InitializeL();
       
  2082 
       
  2083 	//Initialize the Search Sort database adapter class
       
  2084 	InitializeSortTableL();
       
  2085 	}
       
  2086 
       
  2087 
       
  2088 
       
  2089 
       
  2090 /**
       
  2091  * GetVisibleFolderIdL()
       
  2092  * @param TMsvId: Parent Id.
       
  2093  * @return Most immediate visible folder id of any child entry 
       
  2094  *         present under passed parent id.
       
  2095  *
       
  2096  * This functions returns the most immediate parent visible folder id.
       
  2097  * There are two types of folders. A visible folder is one which is 
       
  2098  * visible to the external user, but there are internal non-visible folders
       
  2099  * created under each email message to organize the content of the email.
       
  2100  * Parent entry of an entry is either root or a folder. A folder can be 
       
  2101  * service folder (like LocalServices), userdefined folder/standard folder
       
  2102  * like Inbox or a non-visible folder (created under an email message).
       
  2103  * 
       
  2104  * For a given parent Id, the function returns the most immediate visible
       
  2105  * parent folder. The rules are as follows:
       
  2106  * 1. If the parent entry is root or children of root, then the visibleFolder 
       
  2107  * will be root itself. This is because service folders are considered 
       
  2108  * invisible, since they are not seen by user. 
       
  2109  * 2. If the parent entry itself is a visible folder then child's visibleFolder
       
  2110  * id should be its parent id.
       
  2111  * 3. If the parent entry is a non-visible folder then child's visibleFolder
       
  2112  * id is same as its parent's visibleFolder id.
       
  2113  */
       
  2114 void CMsvDBAdapter::GetVisibleFolderIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
       
  2115 	{
       
  2116 	// If the entry is either a root entry (parent=KErrNotFound) or 
       
  2117 	// child of root entry its visibleFolderId will be root entry itself.
       
  2118 	if((KErrNotFound == aParentId) || (KMsvRootIndexEntryId == aParentId))
       
  2119 		{
       
  2120 		aVisibleFolderId = KMsvRootIndexEntryId;
       
  2121 		}
       
  2122 	else
       
  2123 		{
       
  2124 		// Get the visible flag of parent entry.
       
  2125 		
       
  2126 		// If parent entry is visible, then immediateVisibleFolder of child
       
  2127 		// should be parent Id. And if it is invisible then child's immediateVisibleFolder 
       
  2128 		// should be same as parent's immediateVisibleFolder.
       
  2129 		
       
  2130 		//Bind the msv id
       
  2131 		BindIntL(iStatement[EGetVisibleId], iIdIndex[EGetVisibleId], aParentId);
       
  2132 
       
  2133 		// If parent entry does not exists leave with KErrNotFound.
       
  2134 		if (KSqlAtRow != iStatement[EGetVisibleId].Next())
       
  2135 			{
       
  2136 			iStatement[EGetVisibleId].Reset();
       
  2137 			User::Leave(KErrNotFound);
       
  2138 			}
       
  2139 
       
  2140 		TInt32 data = ColumnInt(iStatement[EGetVisibleId], iDataIndex[EGetVisibleId]);
       
  2141 		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
       
  2142 			{
       
  2143 			// If visible folder flag is not set for parent entry.
       
  2144 			aVisibleFolderId = ColumnInt(iStatement[EGetVisibleId], iVisibleParent[EGetVisibleId]);
       
  2145 			}
       
  2146 		else
       
  2147 			{
       
  2148 			// If parent entry is visible
       
  2149 			aVisibleFolderId = aParentId;
       
  2150 			}
       
  2151 		//Reset the RSqlStatement
       
  2152 		User::LeaveIfError(iStatement[EGetVisibleId].Reset());
       
  2153 		}
       
  2154 	}
       
  2155 
       
  2156 
       
  2157 
       
  2158 
       
  2159 /**
       
  2160  * CreateEntryL()
       
  2161  * @param const TMsvEntry&: DB File Name.
       
  2162  * @return TMsvId: Immediate visible parent folder of the entry
       
  2163  *
       
  2164  * The function creates a new entry in the database. It gets the immediate
       
  2165  * visible folder id of the entry before inserting them into the database.
       
  2166  * No consisitency check is performed on the passed entry. The function may
       
  2167  * leave if query execution fails.
       
  2168  */
       
  2169 void CMsvDBAdapter::CreateEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
       
  2170 	{
       
  2171 	//Bind the entry data
       
  2172 	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], aNewEntry.iId);
       
  2173 	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], aNewEntry.iParentId);
       
  2174 	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
       
  2175 	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
       
  2176 	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
       
  2177 	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], aNewEntry.iRelatedId);
       
  2178 	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
       
  2179 	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
       
  2180 	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
       
  2181 	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
       
  2182 	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
       
  2183 	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
       
  2184 	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
       
  2185 	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
       
  2186 	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], aNewEntry.iServiceId);
       
  2187 	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
       
  2188 	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], aImmediateVisibleFolder);
       
  2189 	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
       
  2190 	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
       
  2191 	//Execute the prepared SQL statement.
       
  2192 	
       
  2193 	TInt err = iStatement[ECreateEntry].Exec();
       
  2194 	if(err < 0)
       
  2195 		{
       
  2196 		iStatement[ECreateEntry].Reset();
       
  2197 		User::Leave(err);
       
  2198 		}
       
  2199 	else if(!err)
       
  2200 		{
       
  2201 		iStatement[ECreateEntry].Reset();
       
  2202 		User::Leave(KErrGeneral);
       
  2203 		}
       
  2204 	
       
  2205 	//Reset the RSqlStatement
       
  2206 	User::LeaveIfError(iStatement[ECreateEntry].Reset());	
       
  2207 	}
       
  2208 
       
  2209 
       
  2210 
       
  2211 
       
  2212 /**
       
  2213  * UpdateEntryL()
       
  2214  * @param const TMsvEntry&: Entry to be updated.
       
  2215  * @param TBool: ETrue if the parent of the entry has been changed,
       
  2216  *				 EFalse if otherwise.
       
  2217  * @param TMsvId&: the visible folder Id of the updated entry.
       
  2218  *				   If aParentChanged is ETrue then aImmediateVisibleFolder
       
  2219  *                 is an output parameter, and input parameter if otherwise.
       
  2220  * @return None.
       
  2221  *
       
  2222  * The function updates an entry in the database. It gets the immediate
       
  2223  * visible folder id of the entry before inserting them into the database.
       
  2224  * No consisitency check is performed on the passed entry. The function may
       
  2225  * leave if query execution fails.
       
  2226  */
       
  2227 void CMsvDBAdapter::UpdateEntryL(const TMsvEntry& aEntry, const TMsvId aImmediateVisibleFolder, const TBool aIsParentIdUpdated/*DEFAULT=ETrue*/)
       
  2228 	{
       
  2229 	iStatementType updateStmt;
       
  2230 	//Bind the entry data
       
  2231 	if(aIsParentIdUpdated)
       
  2232 		{
       
  2233 		updateStmt = EUpdateEntry;
       
  2234 		BindIntL(iStatement[updateStmt], iParentIdIndex[updateStmt], aEntry.iParentId);
       
  2235 		BindIntL(iStatement[updateStmt], iVisibleParent[updateStmt], aImmediateVisibleFolder);
       
  2236 		}
       
  2237 	else
       
  2238 		{
       
  2239 		updateStmt = EUpdateEntryNoParent;
       
  2240 		}
       
  2241 	BindIntL(iStatement[updateStmt], iIdIndex[updateStmt], aEntry.iId);
       
  2242 	BindIntL(iStatement[updateStmt], iDataIndex[updateStmt], aEntry.iData);
       
  2243 	BindIntL(iStatement[updateStmt], iPcSyncCountIndex[updateStmt], aEntry.iPcSyncCount);
       
  2244 	BindIntL(iStatement[updateStmt], iReservedIndex[updateStmt], aEntry.iReserved);
       
  2245 	BindIntL(iStatement[updateStmt], iRelatedIdIndex[updateStmt], aEntry.iRelatedId);
       
  2246 	BindIntL(iStatement[updateStmt], iTypeIndex[updateStmt], aEntry.iType.iUid);
       
  2247 	BindInt64L(iStatement[updateStmt], iDateIndex[updateStmt], aEntry.iDate.Int64());
       
  2248 	BindIntL(iStatement[updateStmt], iSizeIndex[updateStmt], aEntry.iSize);
       
  2249 	BindIntL(iStatement[updateStmt], iErrorIndex[updateStmt], aEntry.iError);
       
  2250 	BindIntL(iStatement[updateStmt], iBiotypeIndex[updateStmt], aEntry.iBioType);
       
  2251 	BindIntL(iStatement[updateStmt], iMtmData1Index[updateStmt], aEntry.iMtmData1);
       
  2252 	BindIntL(iStatement[updateStmt], iMtmData2Index[updateStmt], aEntry.iMtmData2);
       
  2253 	BindIntL(iStatement[updateStmt], iMtmData3Index[updateStmt], aEntry.iMtmData3);
       
  2254 	BindIntL(iStatement[updateStmt], iServiceIdIndex[updateStmt], aEntry.iServiceId);
       
  2255 	BindIntL(iStatement[updateStmt], iMtmIdIndex[updateStmt], aEntry.iMtm.iUid);
       
  2256 	BindTextL(iStatement[updateStmt], iDescriptionIndex[updateStmt],aEntry.iDescription);
       
  2257 	BindTextL(iStatement[updateStmt], iDetailsIndex[updateStmt],aEntry.iDetails);
       
  2258 
       
  2259 	//Execute the prepared SQL statement.
       
  2260 	TInt err = iStatement[updateStmt].Exec();
       
  2261 	if(err < 0)
       
  2262 		{
       
  2263 		iStatement[updateStmt].Reset();
       
  2264 		User::Leave(err);
       
  2265 		}
       
  2266 	else if(!err)
       
  2267 		{
       
  2268 		iStatement[updateStmt].Reset();
       
  2269 		User::Leave(KErrNotFound);
       
  2270 		}
       
  2271 
       
  2272 	//Reset the RSqlStatement
       
  2273 	User::LeaveIfError(iStatement[updateStmt].Reset());
       
  2274 	}
       
  2275 
       
  2276 
       
  2277 
       
  2278 
       
  2279 /**
       
  2280  * DeleteEntryL()
       
  2281  * @param TMsvId: Entry Id to be deleted.
       
  2282  *
       
  2283  * The function deletes an entry with the passed Id. The function
       
  2284  * may leave due to database error while execution. The function
       
  2285  * does not leave if the entry does not exist.
       
  2286  *
       
  2287  * **WARNING** The function does NOT ensure that if a parent entry
       
  2288  * is deleted all its child entries are also deleted.
       
  2289  */
       
  2290 void CMsvDBAdapter::DeleteEntryL(TMsvId aEntryId)
       
  2291 	{
       
  2292 	_LIT8(KDeleteEntryQuery, "DELETE FROM IndexEntry WHERE id = ");
       
  2293 	_LIT8(KSemiColon, ";");
       
  2294 	
       
  2295 	RBuf8 queryBuf;
       
  2296 	CleanupClosePushL(queryBuf);
       
  2297 	queryBuf.CreateL(KDeleteEntryQuery().Length() + 20);
       
  2298 	queryBuf.Append(KDeleteEntryQuery);
       
  2299 	queryBuf.AppendNum(aEntryId);
       
  2300 	queryBuf.Append(KSemiColon);
       
  2301 	
       
  2302 	TInt err = iDatabase.Exec(queryBuf);
       
  2303 	if(err < 0)
       
  2304 		{		
       
  2305 		User::Leave(err);
       
  2306 		}
       
  2307 	else if(!err)
       
  2308 		{
       
  2309 		User::Leave(KErrNotFound);			
       
  2310 		}
       
  2311 	CleanupStack::PopAndDestroy();		// queryBuf
       
  2312 	}
       
  2313 
       
  2314 
       
  2315 
       
  2316 
       
  2317 /**
       
  2318  * DeleteEntryL()
       
  2319  * @param CMsvEntrySelection: Entry Id list to be deleted.
       
  2320  *
       
  2321  * The function deletes all entries mentioned in the passed Id list.
       
  2322  * The function may leave due to database error while execution or
       
  2323  * if an entry does not exist.
       
  2324  *
       
  2325  * **WARNING** The function does NOT ensure that if a parent entry
       
  2326  * is deleted all its child entries are also deleted.
       
  2327  */
       
  2328 void CMsvDBAdapter::DeleteEntryL(const CMsvEntrySelection& aEntryIdList)
       
  2329 	{
       
  2330 	TInt count;
       
  2331 	if( 0 == (count = aEntryIdList.Count()) )
       
  2332 		{
       
  2333 		return;
       
  2334 		}
       
  2335 
       
  2336 	_LIT(KQuery, "DELETE FROM IndexEntry WHERE id IN (");
       
  2337 	_LIT(KComma, ", ");
       
  2338 	_LIT(KEndDelimeter, ");");
       
  2339 	
       
  2340 	RBuf8 buf;
       
  2341 	CleanupClosePushL(buf);
       
  2342 	TInt index = 0;
       
  2343 	//Delete maximum 100 entries at a time so as to not overflow IPC buffer
       
  2344 	TInt maxEntries = 100;
       
  2345 	TInt iterRequired = count/maxEntries;
       
  2346 	if(count%maxEntries)
       
  2347 		{
       
  2348 		iterRequired++;
       
  2349 		}
       
  2350 	if(iterRequired) 
       
  2351 		{
       
  2352 		maxEntries = count/iterRequired;
       
  2353 		}
       
  2354 	for(TInt iter = 0; iter < iterRequired; ++iter)
       
  2355 		{
       
  2356 		if(iter && iter+1 == iterRequired)
       
  2357 			{
       
  2358 			maxEntries = count - index;
       
  2359 			}		
       
  2360 		buf.CreateL( 40 + ((7 + 2) * maxEntries) + 2); //KQuery + (TMsvId+KComma)*100 + KEndDelimiter		
       
  2361 		buf.Append(KQuery);
       
  2362 		TBool firstId = ETrue;
       
  2363 		TInt num = 0;
       
  2364 		while(num < maxEntries)
       
  2365 			{
       
  2366 			if(!firstId)
       
  2367 				{
       
  2368 				buf.Append(KComma);
       
  2369 				}
       
  2370 			firstId = EFalse;
       
  2371 			buf.AppendNum(aEntryIdList.At(index));
       
  2372 			++index;
       
  2373 			++num;
       
  2374 			}
       
  2375 		buf.Append(KEndDelimeter);
       
  2376 		User::LeaveIfError(iDatabase.Exec(buf));		
       
  2377 		buf.Close();
       
  2378 		}
       
  2379 	CleanupStack::PopAndDestroy(); //buf
       
  2380 	}
       
  2381 
       
  2382 
       
  2383 
       
  2384 
       
  2385 /**
       
  2386  * GetEntryL()
       
  2387  * @param TMsvId: Id of the entry to be fetched.
       
  2388  * @return TMsvId: Value of VisibleParent column.
       
  2389  * @return TMsvEntry*: The newly fetched entry.
       
  2390  *
       
  2391  * Fetch an entry from the database. Memory to aEntry
       
  2392  * should not already be assigned.
       
  2393  */
       
  2394 void CMsvDBAdapter::GetEntryL(TMsvId aId, CMsvCacheEntry*& aEntry, TMsvId& aVisibleParentEntryId)
       
  2395 	{
       
  2396 	//Bind the msv id of the entry to be retrieved
       
  2397 	BindIntL(iStatement[EGetEntry], iIdIndex[EGetEntry], aId);
       
  2398 
       
  2399 	if (KSqlAtRow != iStatement[EGetEntry].Next())
       
  2400 		{
       
  2401 		iStatement[EGetEntry].Reset();
       
  2402 		User::Leave(KErrNotFound);
       
  2403 		}
       
  2404 
       
  2405 	//Get the entry from the statement
       
  2406 	aEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  2407 	aEntry->Entry().iId = aId;
       
  2408 	LoadEntryFromStatementL(iStatement[EGetEntry], EGetEntry, aVisibleParentEntryId, *aEntry);
       
  2409 
       
  2410 	//Reset the RSqlStatement
       
  2411 	User::LeaveIfError(iStatement[EGetEntry].Reset());
       
  2412 	}
       
  2413 
       
  2414 
       
  2415 
       
  2416 
       
  2417 /**
       
  2418  * GetChildrenL()
       
  2419  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  2420  * @return RPointerArray<TMsvEntry>&: List of child entries.
       
  2421  *
       
  2422  * Fetch child entries from the database for a given parent Id.
       
  2423  * This does not check if the parent entry already exist. The 
       
  2424  * entries will be added in ascending order of their TMsvId.
       
  2425  */
       
  2426 void CMsvDBAdapter::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  2427 	{
       
  2428 	//Bind the msv id of the entry whose children have to be retrieved
       
  2429 	BindIntL(iStatement[EGetChildEntries], iParentIdIndex[EGetChildEntries], aParentId);
       
  2430 
       
  2431 	while(KSqlAtRow == iStatement[EGetChildEntries].Next())
       
  2432 		{
       
  2433 		TMsvId aVisibleParentEntryId;
       
  2434 		CMsvCacheEntry *cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  2435 		cacheEntry->Entry().iParentId = aParentId;
       
  2436 		LoadEntryFromStatementL(iStatement[EGetChildEntries], EGetChildEntries, aVisibleParentEntryId, *cacheEntry);
       
  2437 		//Add the child entry to the array given
       
  2438 		aChildArray.AppendL(cacheEntry);
       
  2439 		}
       
  2440 
       
  2441 	//Reset the RSqlStatement
       
  2442 	User::LeaveIfError(iStatement[EGetChildEntries].Reset());
       
  2443 	}
       
  2444 
       
  2445 
       
  2446 
       
  2447 
       
  2448 /**
       
  2449  * GetChildrenIdL()
       
  2450  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  2451  * @return RPointerArray<TMsvEntry>&: List of child entries.
       
  2452  *
       
  2453  * Fetch child entries from the database for a given parent Id.
       
  2454  * This does not check if the parent entry already exist. The 
       
  2455  * entries will be added in ascending order of their TMsvId.
       
  2456  */
       
  2457 void CMsvDBAdapter::GetChildrenIdL(TMsvId aParentId, CMsvEntrySelection& aChildArray)
       
  2458 	{
       
  2459 	//Bind the msv id of the entry whose children have to be retrieved
       
  2460 	BindIntL(iStatement[EGetChildIds], iParentIdIndex[EGetChildIds], aParentId);
       
  2461 
       
  2462 	while(KSqlAtRow == iStatement[EGetChildIds].Next())
       
  2463 		{
       
  2464 		TMsvId id = ColumnInt(iStatement[EGetChildIds], iIdIndex[EGetChildIds]);
       
  2465 		//Add the child Id to the array given
       
  2466 		aChildArray.AppendL(id);
       
  2467 		}
       
  2468 
       
  2469 	//Reset the RSqlStatement	
       
  2470 	User::LeaveIfError(iStatement[EGetChildIds].Reset());
       
  2471 	}
       
  2472 
       
  2473 
       
  2474 
       
  2475 
       
  2476 /**
       
  2477  * GetChildrenL()
       
  2478  * @param TDesc: Partial query string. (Where clause condition).
       
  2479  *               The query string should start with 'AND' and should 
       
  2480  *               end with a semicolon. Examples are:
       
  2481  *               "AND ID BETWEEN 100 and 200 ORDER BY ID ASC;"
       
  2482  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  2483  * @return RPointerArray<TMsvEntry>&: List of child entries.
       
  2484  *
       
  2485  * Fetch child entries from the database for a given parent Id.
       
  2486  * This does not check if the parent entry already exist. The 
       
  2487  * entries will be added in ascending order of their TMsvId.
       
  2488  */
       
  2489 void CMsvDBAdapter::GetChildrenL(const TDesC8& aQueryStr, TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  2490 	{
       
  2491 	_LIT8(KQueryString, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
       
  2492 			"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
  2493 			"reserved, visibleParent, description, details FROM IndexEntry "
       
  2494 			"WHERE parentId = :parentId ");
       
  2495 
       
  2496 	RSqlStatement condGetChildrenStmnt;
       
  2497 	CleanupClosePushL(condGetChildrenStmnt);
       
  2498 	TInt len = KQueryString().Length() + aQueryStr.Length();
       
  2499 	RBuf8 queryBuf;
       
  2500 	CleanupClosePushL(queryBuf);
       
  2501 	queryBuf.CreateL(len);	
       
  2502 	queryBuf.Append(KQueryString);
       
  2503 	queryBuf.Append(aQueryStr);
       
  2504 		
       
  2505 	User::LeaveIfError(condGetChildrenStmnt.Prepare(iDatabase, queryBuf));
       
  2506 	TInt index = 0;
       
  2507 
       
  2508 	//Bind the msv id of the entry whose children have to be retrieved
       
  2509 	BindIntL(condGetChildrenStmnt, index, aParentId);
       
  2510 
       
  2511 	while(KSqlAtRow == condGetChildrenStmnt.Next())
       
  2512 		{
       
  2513 		CMsvCacheEntry* cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  2514 		cacheEntry->Entry().iParentId = aParentId;
       
  2515 
       
  2516 		index = 0;
       
  2517 		cacheEntry->Entry().iId = ColumnInt(condGetChildrenStmnt, index);
       
  2518 		cacheEntry->Entry().iServiceId = ColumnInt(condGetChildrenStmnt, ++index);
       
  2519 		cacheEntry->Entry().iMtm.iUid = ColumnInt(condGetChildrenStmnt, ++index);
       
  2520 		cacheEntry->Entry().iType.iUid = ColumnInt(condGetChildrenStmnt, ++index);
       
  2521 		cacheEntry->Entry().iDate = ColumnInt64(condGetChildrenStmnt, ++index);
       
  2522 		cacheEntry->Entry().iData = ColumnInt(condGetChildrenStmnt, ++index);
       
  2523 		cacheEntry->Entry().iSize = ColumnInt(condGetChildrenStmnt, ++index);
       
  2524 		cacheEntry->Entry().iError = ColumnInt(condGetChildrenStmnt, ++index);
       
  2525 		cacheEntry->Entry().iMtmData1 = ColumnInt(condGetChildrenStmnt, ++index);
       
  2526 		cacheEntry->Entry().iMtmData2 = ColumnInt(condGetChildrenStmnt, ++index);
       
  2527 		cacheEntry->Entry().iMtmData3 = ColumnInt(condGetChildrenStmnt, ++index);
       
  2528 		cacheEntry->Entry().iRelatedId = ColumnInt(condGetChildrenStmnt, ++index);
       
  2529 		cacheEntry->Entry().iBioType = ColumnInt(condGetChildrenStmnt, ++index);
       
  2530 		cacheEntry->Entry().iPcSyncCount = ColumnInt(condGetChildrenStmnt, ++index);
       
  2531 		cacheEntry->Entry().iReserved = ColumnInt(condGetChildrenStmnt, ++index);
       
  2532 		TMsvId aVisibleParentEntryId = ColumnInt(condGetChildrenStmnt, ++index);
       
  2533 		cacheEntry->iDescriptionBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  2534 		cacheEntry->Entry().iDescription.Set(*cacheEntry->iDescriptionBuffer);
       
  2535 		
       
  2536 		cacheEntry->iDetailsBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  2537 		cacheEntry->Entry().iDetails.Set(*cacheEntry->iDetailsBuffer);
       
  2538 		
       
  2539 		//Add the child entry to the array given
       
  2540 		aChildArray.AppendL(cacheEntry);
       
  2541 		}
       
  2542 	CleanupStack::PopAndDestroy(2);		// condGetChildrenStmnt,queryBuf
       
  2543 	}
       
  2544 
       
  2545 
       
  2546 
       
  2547 
       
  2548 /**
       
  2549  * EntryExistsL()
       
  2550  * @param TMsvId: Entry Id to check.
       
  2551  * @return TBool: ETrue if the entry exists, otherwise EFalse.
       
  2552  */
       
  2553 TBool CMsvDBAdapter::EntryExistsL(TMsvId aId)
       
  2554 	{	
       
  2555 	_LIT8(KEntryExistsQuery, "SELECT id FROM IndexEntry WHERE id = ");
       
  2556 	_LIT8(KEndDelimeter, ";");
       
  2557 	
       
  2558 	RBuf8 queryBuf;
       
  2559 	CleanupClosePushL(queryBuf);
       
  2560 	TInt len = KEntryExistsQuery().Length() + 10 + KEndDelimeter().Length(); //10 = space for TMsvId
       
  2561 	queryBuf.CreateL(len);
       
  2562 	queryBuf.Append(KEntryExistsQuery);
       
  2563 	queryBuf.AppendNum(aId);
       
  2564 	queryBuf.Append(KEndDelimeter);
       
  2565 	TSqlScalarFullSelectQuery query(iDatabase);
       
  2566 	TMsvId id = NULL;
       
  2567 	TRAPD(err, id = query.SelectIntL(queryBuf));
       
  2568 	CleanupStack::PopAndDestroy();		// queryBuf
       
  2569 	if(err!= KErrNone && err!= KErrNotFound)
       
  2570 		{
       
  2571 		User::Leave(err);
       
  2572 		}
       
  2573 	if(id)
       
  2574 		{
       
  2575 		return ETrue;
       
  2576 		}
       
  2577 	else
       
  2578 		{
       
  2579 		return EFalse;
       
  2580 		}
       
  2581 	}
       
  2582 	
       
  2583 	
       
  2584 	
       
  2585 	
       
  2586 /**
       
  2587  * GetMaxTMsvIdL()
       
  2588  * @param TMsvId&: Out parameter for maximum TMsvId in the database.
       
  2589  * @return None.
       
  2590  * 
       
  2591  * If there are no entries in the database (DB is empty),
       
  2592  * the aMaxTMsvId is set to NULL.
       
  2593  */
       
  2594 void CMsvDBAdapter::GetMaxTMsvIdL(TMsvId& aMaxTMsvId)
       
  2595 	{
       
  2596 	_LIT8(KQuery, "SELECT MAX(id) FROM IndexEntry;");
       
  2597 	RBuf8 queryBuf;
       
  2598 	CleanupClosePushL(queryBuf);
       
  2599 	queryBuf.CreateL(35);
       
  2600 	queryBuf.Append(KQuery);
       
  2601 
       
  2602 	//Create a select query
       
  2603     TSqlScalarFullSelectQuery query(iDatabase);
       
  2604 
       
  2605 	//Get the column data
       
  2606     aMaxTMsvId = query.SelectIntL(queryBuf);
       
  2607     CleanupStack::PopAndDestroy();
       
  2608 	}
       
  2609 
       
  2610 
       
  2611 
       
  2612 
       
  2613 /**
       
  2614  * GetInPreparationIdL()
       
  2615  * @param aSelection CMsvEntrySelection of the TMsvEntries 
       
  2616  * 					 whose KMsvEntryInPreparationFlag is set
       
  2617  * @return void
       
  2618  */
       
  2619 void CMsvDBAdapter::GetInPreparationIdL(CMsvEntrySelection& aSelection)
       
  2620 	{
       
  2621 	RSqlStatement statement;	
       
  2622 	User::LeaveIfError(statement.Prepare(iDatabase, KGetInPreparationIdQuery));
       
  2623 	
       
  2624 	TInt paramIdColumn = GetColumnIndexL(statement, KMsgColumnId());
       
  2625 	TInt paramDataColumn = GetColumnIndexL(statement, KMsgColumnData());
       
  2626 	
       
  2627 	TMsvId Id;
       
  2628 	TInt32 data;
       
  2629 	while (KSqlAtRow == statement.Next())
       
  2630 		{
       
  2631 		data = ColumnInt(statement, paramDataColumn);
       
  2632 		if( data & TMsvEntry::KMsvEntryInPreparationFlag )
       
  2633 			{
       
  2634 			Id = ColumnInt(statement, paramIdColumn);
       
  2635 			aSelection.AppendL(Id);
       
  2636 			}
       
  2637 		}	
       
  2638 	statement.Close();
       
  2639 	}
       
  2640 
       
  2641 
       
  2642 
       
  2643 
       
  2644 /**
       
  2645  * GetVisibleFlagL()
       
  2646  *@param TMsvId : the Id of the entry whose flag is to be checked.
       
  2647  *@return TBool : ETrue if the entry is visible, EFalse otherwise.
       
  2648  *
       
  2649  * Returns the status of the visible flag of an entry in the DB.
       
  2650  */
       
  2651 TBool CMsvDBAdapter::GetVisibleFlagL(TMsvId entryId)
       
  2652 	{
       
  2653 	_LIT8(KGetVisibleFlagQuery, "SELECT data FROM IndexEntry "
       
  2654 								"WHERE id = ");
       
  2655 	_LIT8(KEndDelimeter, ";");
       
  2656 	RBuf8 queryBuf;
       
  2657 	CleanupClosePushL(queryBuf);
       
  2658 	queryBuf.CreateL(60);	
       
  2659 	queryBuf.Append(KGetVisibleFlagQuery);
       
  2660 	queryBuf.AppendNum(entryId);
       
  2661 	queryBuf.Append(KEndDelimeter);
       
  2662 	TSqlScalarFullSelectQuery query(iDatabase);
       
  2663 	TInt32 data = 0;
       
  2664 	TRAPD(err, data = query.SelectIntL(queryBuf));
       
  2665 	CleanupStack::PopAndDestroy(); //queryBuf
       
  2666 	if(err!= KErrNone && err!= KErrNotFound)
       
  2667 		{
       
  2668 		User::Leave(err);
       
  2669 		}
       
  2670 	if(data & TMsvEntry::KMsvEntryInvisibleFlag )
       
  2671 		{
       
  2672 		return EFalse;
       
  2673 		}
       
  2674 	else
       
  2675 		{
       
  2676 		return ETrue;
       
  2677 		}
       
  2678 	}
       
  2679 
       
  2680 
       
  2681 
       
  2682 
       
  2683 /**
       
  2684  * UpdateVisibleFolderL()
       
  2685  * @param RBuf8 : the ID's of the entries of whose visible parent is to 
       
  2686  *				  be updated.
       
  2687  * @return None.
       
  2688  *
       
  2689  * Updates the visible parent of the entries passed through the RBuf* idList.
       
  2690  */
       
  2691  void CMsvDBAdapter::UpdateVisibleFolderL(CMsvEntrySelection* entryList, TMsvId newVisibleFolderId)
       
  2692  	{
       
  2693  	_LIT8(KUpdateVisibleFolderQuery1,	"UPDATE IndexEntry SET "
       
  2694 										"visibleParent = ");
       
  2695 	_LIT8(KUpdateVisibleFolderQuery2,	" WHERE id IN ( ");
       
  2696 	_LIT8(KComma, ", ");
       
  2697 	_LIT8(KDelimiter, ");");
       
  2698 	
       
  2699 	BeginTransactionL();
       
  2700 						
       
  2701 	TInt count = entryList->Count();
       
  2702 	TInt arrIndex = 0;
       
  2703 	while(arrIndex < count)
       
  2704 		{
       
  2705 		TInt len = KUpdateVisibleFolderQuery1().Length() + KUpdateVisibleFolderQuery2().Length(); 
       
  2706 		TInt temp;
       
  2707 		//Update 50 entries or lesser at a time.
       
  2708 		
       
  2709 		TInt totalEntries = count - arrIndex;
       
  2710 		
       
  2711 		if(totalEntries < 50)
       
  2712 			{
       
  2713 			len += totalEntries*12 + 15; //number of entries*length of a TMsvId + length of visibleParent id
       
  2714 			temp = totalEntries;
       
  2715 			}
       
  2716 		else
       
  2717 			{
       
  2718 			len += 50*12 + 15; //number of entries*length of a TMsvId + length of visibleParent id
       
  2719 			temp = 50;
       
  2720 			}
       
  2721 		RBuf8 queryBuf;
       
  2722 		CleanupClosePushL(queryBuf);
       
  2723 		queryBuf.CreateL(len);
       
  2724 		queryBuf.Append(KUpdateVisibleFolderQuery1);
       
  2725 		queryBuf.AppendNum(newVisibleFolderId);
       
  2726 		queryBuf.Append(KUpdateVisibleFolderQuery2);
       
  2727 		TInt index = arrIndex;
       
  2728 		for(; index < arrIndex + temp; ++index)
       
  2729 			{
       
  2730 			queryBuf.AppendNum(entryList->At(index));
       
  2731 			if(index != arrIndex + temp - 1)
       
  2732 				{
       
  2733 				queryBuf.Append(KComma);
       
  2734 				}
       
  2735 			}
       
  2736 		queryBuf.Append(KDelimiter);
       
  2737 		arrIndex += temp;	
       
  2738 		TInt err = iDatabase.Exec(queryBuf);
       
  2739 		CleanupStack::PopAndDestroy();	// queryBuf
       
  2740 		if(err < 0)
       
  2741 			{			
       
  2742 			RollbackTransactionL();
       
  2743 			User::Leave(err);
       
  2744 			}
       
  2745 		else if(!err) //no entries updated
       
  2746 			{
       
  2747 			RollbackTransactionL();
       
  2748 			User::Leave(KErrNotFound);
       
  2749 			}
       
  2750 		}
       
  2751 	CommitTransactionL();
       
  2752 	}
       
  2753 
       
  2754 
       
  2755 
       
  2756 
       
  2757 /**
       
  2758  * UpdateOwnerStatusL()
       
  2759  *
       
  2760  * @param TMsvId : the Id of an entry which has had a child added
       
  2761  *				   under it and needs its owner flag updated.
       
  2762  * @return None.
       
  2763  *
       
  2764  * The function updates the owner flag of an entry which has had a
       
  2765  * child added under it.
       
  2766  */
       
  2767 void CMsvDBAdapter::UpdateOwnerStatusL(TMsvId aId, const TMsvEntry& aParent, TBool aSet)
       
  2768 	{
       
  2769 	_LIT8(KUpdateOwnershipQuery1,	"UPDATE IndexEntry SET "
       
  2770 										" data = ");
       
  2771 	_LIT8(KUpdateOwnershipQuery2,	" WHERE id = ");
       
  2772 	_LIT8(KDelimiter, ";");
       
  2773 	
       
  2774 	// Owner flag has already been set. Return to caller.
       
  2775 	if(aParent.Owner() && aSet)
       
  2776 		{
       
  2777 		return;
       
  2778 		}
       
  2779 	// Otherwise update the owner flag for the entry in the DB.
       
  2780 	else
       
  2781 		{
       
  2782 		TInt32 data;
       
  2783 		if(aSet)
       
  2784 			{
       
  2785 			data = aParent.iData | TMsvEntry::KMsvEntryOwnerFlag;
       
  2786 			}
       
  2787 		else
       
  2788 			{
       
  2789 			data = aParent.iData & ~(TMsvEntry::KMsvEntryOwnerFlag);
       
  2790 			}
       
  2791 		TInt len = KUpdateOwnershipQuery1().Length() + KUpdateOwnershipQuery2().Length();
       
  2792 		len += 100; //data and TMsvId.
       
  2793 		RBuf8 queryBuf;
       
  2794 		CleanupClosePushL(queryBuf);
       
  2795 		queryBuf.CreateL(len);		
       
  2796 		queryBuf.Append(KUpdateOwnershipQuery1);
       
  2797 		queryBuf.AppendNum(data);
       
  2798 		queryBuf.Append(KUpdateOwnershipQuery2);
       
  2799 		queryBuf.AppendNum(aId);
       
  2800 		queryBuf.Append(KDelimiter);
       
  2801 		TInt err = iDatabase.Exec(queryBuf);
       
  2802 		if(err < 0)
       
  2803 			{
       
  2804 			User::Leave(err);
       
  2805 			}
       
  2806 		CleanupStack::PopAndDestroy(); //queryBuf
       
  2807 		}
       
  2808 	}
       
  2809 
       
  2810 
       
  2811 
       
  2812 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2813 
       
  2814 
       
  2815 
       
  2816 
       
  2817 /**
       
  2818  * InitializeL()
       
  2819  *
       
  2820  * This functions prepares (compiles) frequetly used SQL queries,
       
  2821  * and create indexes on the variable arguments. When the query
       
  2822  * needs to be executed, we just have to bind the variables with
       
  2823  * the values and execute them. This increases the performance of
       
  2824  * query execution.
       
  2825  */
       
  2826 void CMsvDBAdapter::InitializeL()
       
  2827 	{
       
  2828 	//Prepare the frequently used SQL statements
       
  2829 	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, KCreateEntryQuery));
       
  2830 	User::LeaveIfError(iStatement[EUpdateEntry].Prepare(iDatabase, KUpdateEntryQuery));
       
  2831 	User::LeaveIfError(iStatement[EUpdateEntryNoParent].Prepare(iDatabase, KUpdateEntryNoParentQuery));
       
  2832 	User::LeaveIfError(iStatement[EGetEntry].Prepare(iDatabase, KGetEntryQuery));
       
  2833 	User::LeaveIfError(iStatement[EGetChildEntries].Prepare(iDatabase, KGetChildEntriesQuery));
       
  2834 	User::LeaveIfError(iStatement[EGetVisibleId].Prepare(iDatabase, KGetVisibleIdQuery));
       
  2835 	User::LeaveIfError(iStatement[EEntryExists].Prepare(iDatabase, KGetEntryExistsQuery));
       
  2836 	User::LeaveIfError(iStatement[EGetChildIds].Prepare(iDatabase, KGetChildIdsQuery));
       
  2837 
       
  2838 	//Get the indices - This maps the parameter name to its offset
       
  2839 	//in the SQL statement templates.
       
  2840 	for(TInt index = ECreateEntry; index < EIndexSentinel; ++index)
       
  2841 		{
       
  2842 		switch(index)
       
  2843 			{
       
  2844 			case ECreateEntry:			// KCreateEntryQuery
       
  2845 			case EUpdateEntry:			// KUpdateEntryQuery
       
  2846 				//For creating and updating entries
       
  2847 				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
       
  2848 				iVisibleParent[index] = GetParamIndexL(iStatement[index], KMsgParamVisibleParent());
       
  2849 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());				
       
  2850 				iServiceIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamServiceId());
       
  2851 				iMtmIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamMtmId());
       
  2852 				iTypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamType());
       
  2853 				iDateIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDate());
       
  2854 				iDataIndex[index] = GetParamIndexL(iStatement[index], KMsgParamData());
       
  2855 				iSizeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamSize());
       
  2856 				iErrorIndex[index] = GetParamIndexL(iStatement[index], KMsgParamError());
       
  2857 				iMtmData1Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData1());
       
  2858 				iMtmData2Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData2());
       
  2859 				iMtmData3Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData3());
       
  2860 				iRelatedIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamRelatedId());
       
  2861 				iBiotypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamBiotype());
       
  2862 				iPcSyncCountIndex[index] = GetParamIndexL(iStatement[index], KMsgParamPcSyncCount());
       
  2863 				iReservedIndex[index] = GetParamIndexL(iStatement[index], KMsgParamReserved());
       
  2864 				iDescriptionIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDescriptionTxt());
       
  2865 				iDetailsIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDetailsTxt());
       
  2866 				break;
       
  2867 			case EUpdateEntryNoParent:
       
  2868 				iVisibleParent[index] = GetParamIndexL(iStatement[index], KMsgParamVisibleParent());
       
  2869 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());				
       
  2870 				iServiceIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamServiceId());
       
  2871 				iMtmIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamMtmId());
       
  2872 				iTypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamType());
       
  2873 				iDateIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDate());
       
  2874 				iDataIndex[index] = GetParamIndexL(iStatement[index], KMsgParamData());
       
  2875 				iSizeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamSize());
       
  2876 				iErrorIndex[index] = GetParamIndexL(iStatement[index], KMsgParamError());
       
  2877 				iMtmData1Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData1());
       
  2878 				iMtmData2Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData2());
       
  2879 				iMtmData3Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData3());
       
  2880 				iRelatedIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamRelatedId());
       
  2881 				iBiotypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamBiotype());
       
  2882 				iPcSyncCountIndex[index] = GetParamIndexL(iStatement[index], KMsgParamPcSyncCount());
       
  2883 				iReservedIndex[index] = GetParamIndexL(iStatement[index], KMsgParamReserved());
       
  2884 				iDescriptionIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDescriptionTxt());
       
  2885 				iDetailsIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDetailsTxt());
       
  2886 				break;
       
  2887 			case EGetEntry:				// KGetEntryQuery
       
  2888 				//Read an entry from DB
       
  2889 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
       
  2890 				iParentIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnParentId());
       
  2891 				iServiceIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnServiceId());
       
  2892 				iMtmIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmId());
       
  2893 				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
       
  2894 				iDateIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDate());
       
  2895 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
       
  2896 				iSizeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnSize());
       
  2897 				iErrorIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnError());
       
  2898 				iMtmData1Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData1());
       
  2899 				iMtmData2Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData2());
       
  2900 				iMtmData3Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData3());
       
  2901 				iRelatedIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnRelatedId());
       
  2902 				iBiotypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnBiotype());
       
  2903 				iPcSyncCountIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnPcSyncCount());
       
  2904 				iReservedIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnReserved());
       
  2905 				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
       
  2906 				iDescriptionIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDescriptionTxt());
       
  2907 				iDetailsIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDetailsTxt());
       
  2908 				break;
       
  2909 			case EGetChildEntries:		// KGetChildEntriesQuery
       
  2910 				//Read child entries for a given parent Id.
       
  2911 				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
       
  2912 				iIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnId());
       
  2913 				iServiceIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnServiceId());
       
  2914 				iMtmIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmId());
       
  2915 				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
       
  2916 				iDateIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDate());
       
  2917 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
       
  2918 				iSizeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnSize());
       
  2919 				iErrorIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnError());
       
  2920 				iMtmData1Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData1());
       
  2921 				iMtmData2Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData2());
       
  2922 				iMtmData3Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData3());
       
  2923 				iRelatedIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnRelatedId());
       
  2924 				iBiotypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnBiotype());
       
  2925 				iPcSyncCountIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnPcSyncCount());
       
  2926 				iReservedIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnReserved());
       
  2927 				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
       
  2928 				iDescriptionIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDescriptionTxt());
       
  2929 				iDetailsIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDetailsTxt());
       
  2930 				break;
       
  2931 			case EGetVisibleId:			// KGetVisibleIdQuery
       
  2932 				//For getting visible Id related information
       
  2933 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
       
  2934 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());	
       
  2935 				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
       
  2936 				break;
       
  2937 			case EEntryExists:			// KGetEntryExistsQuery
       
  2938 				//To check if an entry exists in DB.
       
  2939 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
       
  2940 				iParentIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnParentId());
       
  2941 				break;
       
  2942 			case EGetChildIds:			// KGetChildIdsQuery
       
  2943 				//To check if an entry exists in DB.
       
  2944 				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
       
  2945 				iIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnId());
       
  2946 
       
  2947 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2948 				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
       
  2949 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
       
  2950 #endif
       
  2951 				break;
       
  2952 			default:
       
  2953 				break;
       
  2954 			}
       
  2955 		}
       
  2956 	}
       
  2957 
       
  2958 
       
  2959 
       
  2960 
       
  2961 /**
       
  2962  * BeginTransactionL()
       
  2963  * 
       
  2964  * Starts a new DB transaction.
       
  2965  */
       
  2966 void CMsvDBAdapter::BeginTransactionL()
       
  2967 	{
       
  2968 	if(!isTransactionOpen)
       
  2969 		{
       
  2970 		_LIT8(KBeginTransaction, "BEGIN;");
       
  2971 		User::LeaveIfError(iDatabase.Exec(KBeginTransaction));
       
  2972 		isTransactionOpen = ETrue;
       
  2973 		}
       
  2974 	}
       
  2975 
       
  2976 
       
  2977 
       
  2978 
       
  2979 /**
       
  2980  * CommitTransactionL()
       
  2981  * 
       
  2982  * Commits an already opened transaction.
       
  2983  */
       
  2984 void CMsvDBAdapter::CommitTransactionL()
       
  2985 	{
       
  2986 	if(isTransactionOpen)
       
  2987 		{
       
  2988 		_LIT8(KCommitTransaction,	 "COMMIT;");
       
  2989 		isTransactionOpen = EFalse;
       
  2990 		User::LeaveIfError(iDatabase.Exec(KCommitTransaction));		
       
  2991 		}
       
  2992 	}
       
  2993 
       
  2994 
       
  2995 /**
       
  2996  * RollbackTransactionL()
       
  2997  * 
       
  2998  * Rollback an already opened transaction.
       
  2999  */
       
  3000 void CMsvDBAdapter::RollbackTransactionL()
       
  3001 	{
       
  3002 	if(isTransactionOpen)
       
  3003 		{
       
  3004 		_LIT8(KRollbackTransaction,	 "ROLLBACK;");
       
  3005 		isTransactionOpen = EFalse;
       
  3006 		User::LeaveIfError(iDatabase.Exec(KRollbackTransaction));		
       
  3007 		}
       
  3008 	}
       
  3009 
       
  3010 
       
  3011 
       
  3012 
       
  3013 
       
  3014 /**
       
  3015  * LoadEntryFromStatementL()
       
  3016  * @param RSqlStatement&: a reference to the RSqlStatement to work against.
       
  3017  * @param TInt: Index of the SQL statement.
       
  3018  * @param TMsvId&: Out parameter for value of VisibleParent column.
       
  3019  * @param CMsvCacheEntry&: The newly fetched entry to be filled.
       
  3020  * @return None.
       
  3021  *
       
  3022  * Creates a CMsvCacheEntry from the executed RSqlStatement.
       
  3023  */
       
  3024 void CMsvDBAdapter::LoadEntryFromStatementL(RSqlStatement& aStmt, TInt aIndex, TMsvId& aVisibleParentEntryId, CMsvCacheEntry& aEntry)
       
  3025 	{
       
  3026 	if(EGetEntry != aIndex)
       
  3027 		{
       
  3028 		aEntry.Entry().iId = ColumnInt(aStmt, iIdIndex[aIndex]);
       
  3029 		}
       
  3030 	if(EGetChildEntries != aIndex)
       
  3031 		{
       
  3032 		aEntry.Entry().iParentId = ColumnInt(aStmt, iParentIdIndex[aIndex]);
       
  3033 		}
       
  3034 	
       
  3035 	aEntry.Entry().iData = ColumnInt(aStmt, iDataIndex[aIndex]);
       
  3036 	aEntry.Entry().iPcSyncCount = ColumnInt(aStmt, iPcSyncCountIndex[aIndex]);
       
  3037 	aEntry.Entry().iReserved = ColumnInt(aStmt, iReservedIndex[aIndex]);
       
  3038 	aEntry.Entry().iRelatedId = ColumnInt(aStmt, iRelatedIdIndex[aIndex]);
       
  3039 	aEntry.Entry().iType.iUid = ColumnInt(aStmt, iTypeIndex[aIndex]);
       
  3040 	aEntry.Entry().iDate = ColumnInt64(aStmt, iDateIndex[aIndex]);
       
  3041 	aEntry.Entry().iSize = ColumnInt(aStmt, iSizeIndex[aIndex]);
       
  3042 	aEntry.Entry().iError = ColumnInt(aStmt, iErrorIndex[aIndex]);
       
  3043 	aEntry.Entry().iBioType = ColumnInt(aStmt, iBiotypeIndex[aIndex]);
       
  3044 	aEntry.Entry().iMtmData1 = ColumnInt(aStmt, iMtmData1Index[aIndex]);
       
  3045 	aEntry.Entry().iMtmData2 = ColumnInt(aStmt, iMtmData2Index[aIndex]);
       
  3046 	aEntry.Entry().iMtmData3 = ColumnInt(aStmt, iMtmData3Index[aIndex]);
       
  3047 	aEntry.Entry().iServiceId = ColumnInt(aStmt, iServiceIdIndex[aIndex]);
       
  3048 	aEntry.Entry().iMtm.iUid = ColumnInt(aStmt, iMtmIdIndex[aIndex]);
       
  3049 	aEntry.iDescriptionBuffer = ColumnTextL(aStmt, iDescriptionIndex[aIndex]);
       
  3050 	aEntry.Entry().iDescription.Set(*aEntry.iDescriptionBuffer);
       
  3051 	aEntry.iDetailsBuffer = ColumnTextL(aStmt, iDetailsIndex[aIndex]);
       
  3052 	aEntry.Entry().iDetails.Set(*aEntry.iDetailsBuffer);
       
  3053 	
       
  3054 	//Get the visible parent id
       
  3055 	aVisibleParentEntryId = ColumnInt(aStmt, iVisibleParent[aIndex]);
       
  3056 	}
       
  3057 
       
  3058 
       
  3059 
       
  3060 
       
  3061 /**
       
  3062  * GetNextSiblingL()
       
  3063  *
       
  3064  * @param TMsvId: TMsvId of the entry whose sibling id is to be found.
       
  3065  * @param TMsvId: TMsvId of the parent entry of aId.
       
  3066  * @param TMsvId&: TMsvId of the sibling of aId, this is an o/p parameter.
       
  3067  * @return TBool
       
  3068  *
       
  3069  * Gets the id of the sibling of aId.
       
  3070  */
       
  3071 TBool CMsvDBAdapter::GetNextSiblingL(TMsvId aId,TMsvId aParentId,TMsvId& aNextSiblingId)
       
  3072 	{
       
  3073 	TBool foundSibling=EFalse;
       
  3074 	//get all the children for this parent
       
  3075 	CMsvEntrySelection* children=new(ELeave)CMsvEntrySelection;
       
  3076 	CleanupStack::PushL(children);
       
  3077 	GetChildrenIdL(aParentId,*children);
       
  3078 	TInt childCount=children->Count();
       
  3079 	
       
  3080 	for(TInt i=0;i<childCount;++i)
       
  3081 		{
       
  3082 		if(children->At(i)==aId && i<childCount-1)
       
  3083 			{
       
  3084 			aNextSiblingId=children->At(i+1);
       
  3085 			foundSibling=ETrue;
       
  3086 			break;
       
  3087 			}
       
  3088 		}
       
  3089 	CleanupStack::PopAndDestroy(children);
       
  3090 	return foundSibling;
       
  3091 	}
       
  3092 
       
  3093 
       
  3094 
       
  3095 /**
       
  3096  * GetFirstChildIdL()
       
  3097  *
       
  3098  * @param TMsvId: TMsvId of the parent entry of aId.
       
  3099  * @param TMsvId: TMsvId of the child of aParentId, this is an o/p parameter.
       
  3100  * @return TBool.
       
  3101  *
       
  3102  * Gets the id of first child of aParentId.
       
  3103  */
       
  3104 TBool CMsvDBAdapter::GetFirstChildIdL(TMsvId aParentId,TMsvId& aFirstChild)
       
  3105 	{
       
  3106 	TBool foundChild=EFalse;
       
  3107 	//get all the children for this parent
       
  3108 	CMsvEntrySelection* children=new(ELeave)CMsvEntrySelection;
       
  3109 	CleanupStack::PushL(children);
       
  3110 	GetChildrenIdL(aParentId,*children);
       
  3111 	TInt childCount=children->Count();
       
  3112 	
       
  3113 	if(childCount>0)
       
  3114 		{
       
  3115 		aFirstChild=children->At(0);
       
  3116 		foundChild=ETrue;
       
  3117 		}
       
  3118 	CleanupStack::PopAndDestroy(children);
       
  3119 	return foundChild;
       
  3120 	}
       
  3121 
       
  3122 
       
  3123 /**
       
  3124  * ConstructSortTableL()
       
  3125  * @param none.
       
  3126  * #return none.
       
  3127  * 
       
  3128  * This functions is called to create a new table,
       
  3129  * which stores the information for the search/sort
       
  3130  * operations performed.
       
  3131  */ 
       
  3132 void CMsvDBAdapter::ConstructSortTableL()
       
  3133 	{
       
  3134 		
       
  3135 	//Create Search Sort Cache table. This stores the results of
       
  3136 	// search sort result	
       
  3137 	TInt err = iDatabase.Exec(KCreateSearchSortEntryTableQuery);
       
  3138 	if(err < 0)
       
  3139 		{
       
  3140 		User::Leave(err);
       
  3141 		}
       
  3142 #if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3143 	if(err == 0)
       
  3144 		{
       
  3145 		ClearDBContentsL();
       
  3146 		}
       
  3147 #endif
       
  3148 	
       
  3149 	//Create Unique index's on indexEnty table.
       
  3150 	//Unique Index is created on all columns to defer duplicates.
       
  3151 	err = iDatabase.Exec(KCreateSearchSortQuery);
       
  3152 	if(err < 0)
       
  3153 		{
       
  3154 		User::Leave(err);
       
  3155 		}
       
  3156 	}
       
  3157 
       
  3158 
       
  3159 
       
  3160 
       
  3161 /**
       
  3162  * InitializeSortTableL()
       
  3163  * @param none.
       
  3164  * #return none.
       
  3165  * 
       
  3166  * This functions prepares (compiles) frequetly used SQL queries,
       
  3167  * and create indexes on the variable arguments. When the query
       
  3168  * needs to be executed, we just have to bind the variables with
       
  3169  * the values and execute them. This increases the performance of
       
  3170  * query execution.
       
  3171  */
       
  3172 void CMsvDBAdapter::InitializeSortTableL()
       
  3173 	{						 
       
  3174 	//Prepare the frequently used SQL statements
       
  3175 	User::LeaveIfError(iQueryStatement[EQueryCreateEntry].Prepare(iDatabase, KCreateQueryEntry));
       
  3176 	User::LeaveIfError(iQueryStatement[EQueryGetEntryAsc].Prepare(iDatabase, KGetEntryAsc));
       
  3177 	User::LeaveIfError(iQueryStatement[EQueryGetEntryDesc].Prepare(iDatabase, KGetEntryDesc));
       
  3178 	User::LeaveIfError(iQueryStatement[EQueryGetEntryNumAsc].Prepare(iDatabase, KGetEntryNumAsc));
       
  3179 	User::LeaveIfError(iQueryStatement[EQueryGetEntryNumDesc].Prepare(iDatabase, KGetEntryNumDesc));
       
  3180 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsAsc].Prepare(iDatabase, KGetLastNIdsAsc));
       
  3181 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsDesc].Prepare(iDatabase, KGetLastNIdsDesc));
       
  3182 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsNumAsc].Prepare(iDatabase, KGetLastNIdsNumAsc));
       
  3183 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsNumDesc].Prepare(iDatabase, KGetLastNIdsNumDesc));
       
  3184 	User::LeaveIfError(iQueryStatement[EGetFolderIds].Prepare(iDatabase, KGetFolderIds));
       
  3185 	User::LeaveIfError(iQueryStatement[EQueryCount].Prepare(iDatabase, KGetQueryCount));
       
  3186 	User::LeaveIfError(iQueryStatement[EQueryIteratorNumAsc].Prepare(iDatabase, KGetIterResultCastAsc));
       
  3187 	User::LeaveIfError(iQueryStatement[EQueryIteratorNumDesc].Prepare(iDatabase, KGetIterResultCastDesc));
       
  3188 	User::LeaveIfError(iQueryStatement[EQueryIteratorAsc].Prepare(iDatabase, KGetIterResultAsc));
       
  3189 	User::LeaveIfError(iQueryStatement[EQueryIteratorDesc].Prepare(iDatabase, KGetIterResultDesc));
       
  3190 
       
  3191 	//Get the indices - This maps the parameter name to its offset
       
  3192 	//in the SQL statement templates.
       
  3193 	for(TInt index = EQueryCreateEntry; index < EQuerySentinel; ++index)
       
  3194 		{
       
  3195 		switch(index)
       
  3196 			{							 
       
  3197 			case EQueryCreateEntry:
       
  3198 				{
       
  3199 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3200 				iIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryTMsvId());
       
  3201 				iSortfieldQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQuerySortfield());
       
  3202 				break;
       
  3203 				}
       
  3204 
       
  3205 			case EQueryGetEntryAsc:
       
  3206 				{
       
  3207 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3208 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3209 				break;
       
  3210 				}
       
  3211 
       
  3212 			case EQueryGetEntryDesc:
       
  3213 				{
       
  3214 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3215 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3216 				break;
       
  3217 				}
       
  3218 				
       
  3219 			case EQueryGetEntryNumAsc:
       
  3220 				{
       
  3221 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3222 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3223 				break;
       
  3224 				}
       
  3225 
       
  3226 			case EQueryGetEntryNumDesc:
       
  3227 				{
       
  3228 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3229 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3230 				break;
       
  3231 				}
       
  3232 				
       
  3233 			case EQueryGetLastNIdsAsc:
       
  3234 				{
       
  3235 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3236 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3237 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3238 				break;
       
  3239 				}
       
  3240 				
       
  3241 			case EQueryGetLastNIdsDesc:
       
  3242 				{
       
  3243 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3244 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3245 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3246 				break;
       
  3247 				}
       
  3248 		
       
  3249 			case EQueryGetLastNIdsNumAsc:
       
  3250 				{
       
  3251 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3252 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3253 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());	
       
  3254 				break;
       
  3255 				}
       
  3256 			
       
  3257 			case EQueryGetLastNIdsNumDesc:
       
  3258 				{
       
  3259 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3260 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3261 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());	
       
  3262 				break;
       
  3263 				}
       
  3264 				
       
  3265 			case EGetFolderIds:
       
  3266 				{
       
  3267 				iParentIdfield = GetParamIndexL(iQueryStatement[index], KMsgParamParentId());
       
  3268 				iTMsvidfield = GetParamIndexL(iQueryStatement[index], KMsgParamType());
       
  3269 				break;
       
  3270 				}
       
  3271 					
       
  3272 			case EQueryCount:
       
  3273 				{
       
  3274 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3275 				break;
       
  3276 				}
       
  3277 			
       
  3278 			case EQueryIteratorNumAsc:
       
  3279 				{
       
  3280 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3281 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3282 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3283 				break;
       
  3284 				}
       
  3285 			
       
  3286 			case EQueryIteratorNumDesc:
       
  3287 				{
       
  3288 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3289 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3290 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3291 				break;
       
  3292 				}
       
  3293 			
       
  3294 			case EQueryIteratorAsc:
       
  3295 				{
       
  3296 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3297 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3298 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3299 				break;
       
  3300 				}
       
  3301 			
       
  3302 			case EQueryIteratorDesc:
       
  3303 				{
       
  3304 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3305 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3306 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3307 				break;
       
  3308 				}
       
  3309 
       
  3310 			default:
       
  3311 				break;
       
  3312 			}
       
  3313 		}
       
  3314 	}
       
  3315 
       
  3316 
       
  3317 
       
  3318 	
       
  3319 /**
       
  3320  * CreateQueryEntryL()
       
  3321  * @param TInt&: The Id of the Search/Sort Query
       
  3322  * @param TMsvIdWithSortField&: Fields to be added under the query id specified
       
  3323  * @return none.
       
  3324  *
       
  3325  * This Function adds the Entries into the DB under the Queryid specified
       
  3326  */
       
  3327 void CMsvDBAdapter::CreateQueryEntryL(const TInt& aQueryId,const TMsvIdWithSortField& aEntry)
       
  3328 	{
       
  3329 	//Bind the entry data
       
  3330 	BindIntL(iQueryStatement[EQueryCreateEntry], iQIdQueryIndex[EQueryCreateEntry], aQueryId);
       
  3331 	
       
  3332 	#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3333 		BindIntL(iQueryStatement[EQueryCreateEntry], iIdQueryIndex[EQueryCreateEntry], UnmaskTMsvId(aEntry.iMessageId));
       
  3334 	#else
       
  3335 		BindIntL(iQueryStatement[EQueryCreateEntry], iIdQueryIndex[EQueryCreateEntry], aEntry.iMessageId);
       
  3336 	#endif		
       
  3337 	
       
  3338 	
       
  3339 	BindTextL(iQueryStatement[EQueryCreateEntry], iSortfieldQueryIndex[EQueryCreateEntry], aEntry.iContentMessagePart);
       
  3340 		
       
  3341 	TInt err = iQueryStatement[EQueryCreateEntry].Exec();
       
  3342 	if(err < 0)
       
  3343 		{
       
  3344 		iQueryStatement[EQueryCreateEntry].Reset();
       
  3345 		User::Leave(err);
       
  3346 		}
       
  3347 	
       
  3348 	//Reset the RSqlStatement
       
  3349 	User::LeaveIfError(iQueryStatement[EQueryCreateEntry].Reset());
       
  3350 	}
       
  3351 	
       
  3352 
       
  3353 
       
  3354 
       
  3355 /**
       
  3356  * GetSortedEntriesL()
       
  3357  * @param TInt&: The Id of the Search/Sort Query
       
  3358  * @param RArray<TMsvIdWithSortField>&: this array will be filled with the resultant ids
       
  3359  * #param TBool: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
       
  3360  * @return none.
       
  3361  *
       
  3362  * This Function retrieves all the ids under the specified Query Id
       
  3363  */
       
  3364 void CMsvDBAdapter::GetSearchSortEntriesL(const TInt& aQueryId, RArray<TMsvId>& aEntrySelection, const TBool aOrder/*Default = EFalse*/,const TBool aSortAsInt/*Default = EFalse*/)
       
  3365 	{
       
  3366 	TInt sortOrder;
       
  3367 	TMsvId entryId;
       
  3368 	
       
  3369 	if(aSortAsInt)
       
  3370 		{
       
  3371 		if(aOrder)
       
  3372 			{
       
  3373 			sortOrder = EQueryGetEntryNumAsc;
       
  3374 			}
       
  3375 		else
       
  3376 			{
       
  3377 			sortOrder = EQueryGetEntryNumDesc;
       
  3378 			}
       
  3379 		}
       
  3380 	else
       
  3381 		{
       
  3382 		if(aOrder)
       
  3383 			{
       
  3384 			sortOrder = EQueryGetEntryAsc;
       
  3385 			}
       
  3386 		else
       
  3387 			{
       
  3388 			sortOrder = EQueryGetEntryDesc;
       
  3389 			}
       
  3390 		}
       
  3391 	
       
  3392 	//Bind the msv id of the entry to be retrieved
       
  3393 	BindIntL(iQueryStatement[sortOrder], iQIdQueryIndex[sortOrder], aQueryId);
       
  3394 
       
  3395 	while(KSqlAtRow == iQueryStatement[sortOrder].Next())
       
  3396 		{
       
  3397 		entryId = ColumnInt(iQueryStatement[sortOrder], iIdQueryIndex[sortOrder]);
       
  3398 		
       
  3399 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3400 			entryId = MaskTMsvId(KCurrentDriveId,entryId);
       
  3401 		#endif
       
  3402 		
       
  3403 		aEntrySelection.AppendL(entryId);
       
  3404 		}
       
  3405 
       
  3406 	//Reset the RSqlStatement
       
  3407 	User::LeaveIfError(iQueryStatement[sortOrder].Reset());
       
  3408 	}
       
  3409 
       
  3410 
       
  3411 
       
  3412 
       
  3413 /**
       
  3414  * GetLastNTMsvIdsfromTableL()
       
  3415  * @param TInt&: The Id of the Search/Sort Query
       
  3416  * @param RArray<TMsvIdWithSortField>&: this array will be filled with the resultant ids
       
  3417  * @param TInt aLastCount: The Number of entries from the last rowid to be fetched from
       
  3418  * @param TBool: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
       
  3419  * @return none.
       
  3420  *
       
  3421  * This Function retrieves the last N ids under the specified Query Id
       
  3422  */
       
  3423 void CMsvDBAdapter::GetLastNTMsvIdsfromTableL(const TInt& aQueryId, RArray<TMsvId>& aEntrySelection, TInt aLastCount, const TBool aOrder/*Default = ETrue*/,const TBool aSortAsInt/*Default = EFalse*/)
       
  3424 	{
       
  3425 	TInt sortOrder;
       
  3426 	TMsvId entryId;
       
  3427 
       
  3428 	if(aSortAsInt)
       
  3429 		{
       
  3430 		if(aOrder)
       
  3431 			{
       
  3432 			sortOrder = EQueryGetLastNIdsAsc;
       
  3433 			}
       
  3434 		else
       
  3435 			{
       
  3436 			sortOrder = EQueryGetLastNIdsDesc;
       
  3437 			}
       
  3438 		}
       
  3439 	else
       
  3440 		{
       
  3441 		if(aOrder)
       
  3442 			{
       
  3443 			sortOrder = EQueryGetLastNIdsNumAsc;
       
  3444 			}
       
  3445 		else
       
  3446 			{
       
  3447 			sortOrder = EQueryGetLastNIdsNumDesc;
       
  3448 			}
       
  3449 		}
       
  3450 	
       
  3451 	//Bind the count value
       
  3452 	BindIntL(iQueryStatement[sortOrder], iRowIdIndex[sortOrder], aLastCount);
       
  3453 	
       
  3454 	//Bind the msv id of the entry to be retrieved
       
  3455 	BindIntL(iQueryStatement[sortOrder], iQIdQueryIndex[sortOrder], aQueryId);
       
  3456 
       
  3457 	while(KSqlAtRow == iQueryStatement[sortOrder].Next())
       
  3458 		{
       
  3459 		entryId = ColumnInt(iQueryStatement[sortOrder], iIdQueryIndex[sortOrder]);
       
  3460 		
       
  3461 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3462 			entryId = MaskTMsvId(KCurrentDriveId, entryId);
       
  3463 		#endif
       
  3464 		
       
  3465 		aEntrySelection.AppendL(entryId);
       
  3466 		}
       
  3467 
       
  3468 	//Reset the RSqlStatement
       
  3469 	User::LeaveIfError(iQueryStatement[sortOrder].Reset());
       
  3470 	}
       
  3471 
       
  3472 
       
  3473 
       
  3474 
       
  3475 /**
       
  3476  * DeleteTMsvIdFromAllQueriesL()
       
  3477  * @param TMsvId&: The id to be deleted
       
  3478  * @return none.
       
  3479  *
       
  3480  * This Function delete a id under all Queryid's
       
  3481  */
       
  3482 void CMsvDBAdapter::DeleteTMsvIdFromAllQueriesL(const TMsvId& aId)
       
  3483 	{	
       
  3484 	RBuf8 queryBuf;
       
  3485 	CleanupClosePushL(queryBuf);
       
  3486 	queryBuf.CreateL(KDeleteId().Length() + 20);
       
  3487 	queryBuf.Append(KDeleteId);
       
  3488 	queryBuf.AppendNum(aId);
       
  3489 	queryBuf.Append(KSemiColon);
       
  3490 	
       
  3491 	TInt err = iDatabase.Exec(queryBuf);
       
  3492 	CleanupStack::PopAndDestroy();		// queryBuf
       
  3493 	if(err < 0)
       
  3494 		{		
       
  3495 		User::Leave(err);
       
  3496 		}
       
  3497 	}
       
  3498 
       
  3499 
       
  3500 
       
  3501 
       
  3502 /**
       
  3503  * DeleteQueryFromTableL()
       
  3504  * @param TInt&: The Id of the Search/Sort Query
       
  3505  * @return none.
       
  3506  *
       
  3507  * This Function deletes a particular Query from DB
       
  3508  */
       
  3509 void CMsvDBAdapter::DeleteQueryFromTableL(const TInt& aQueryId)
       
  3510 	{
       
  3511 	RBuf8 queryBuf;
       
  3512 	CleanupClosePushL(queryBuf);
       
  3513 	queryBuf.CreateL(KDeleteQueryId().Length() + 20);
       
  3514 	queryBuf.Append(KDeleteQueryId);
       
  3515 	queryBuf.AppendNum(aQueryId);
       
  3516 	queryBuf.Append(KSemiColon);
       
  3517 	
       
  3518 	TInt err = iDatabase.Exec(queryBuf);
       
  3519 	CleanupStack::PopAndDestroy();		// queryBuf
       
  3520 	if(err < 0)
       
  3521 		{		
       
  3522 		User::Leave(err);
       
  3523 		}
       
  3524 	}
       
  3525 
       
  3526 
       
  3527 
       
  3528 
       
  3529 /**
       
  3530  * DeleteTMsvIdFromQueryL()
       
  3531  * @param TInt&: The Id of the Search/Sort Query
       
  3532  * @param TMsvId&: The TMsvId of the entry to be deleted 
       
  3533  * @return none.
       
  3534  *
       
  3535  * This Function deletes a particular id under the specified QueryId
       
  3536  */
       
  3537 void CMsvDBAdapter::DeleteTMsvIdFromQueryL(const TInt& aQueryId,const TMsvId& aId)
       
  3538 	{
       
  3539 	RBuf8 queryBuf;
       
  3540 	CleanupClosePushL(queryBuf);
       
  3541 	queryBuf.CreateL(KDeleteQueryId().Length()+KAndId().Length() + 20);
       
  3542 	queryBuf.Append(KDeleteQueryId);
       
  3543 	queryBuf.AppendNum(aQueryId);
       
  3544 	queryBuf.Append(KAndId);
       
  3545 	queryBuf.AppendNum(aId);
       
  3546 	queryBuf.Append(KSemiColon);
       
  3547 	
       
  3548 	TInt err = iDatabase.Exec(queryBuf);
       
  3549 	CleanupStack::PopAndDestroy();		// queryBuf
       
  3550 	if(err < 0)
       
  3551 		{		
       
  3552 		User::Leave(err);
       
  3553 		}
       
  3554 	}
       
  3555 
       
  3556 
       
  3557 
       
  3558 
       
  3559 /**
       
  3560  * AddEntriesfromIndexTableL()
       
  3561  * @param TDesC8&: The Query to fill the SearchSortTable with the IndexEntry
       
  3562  * @return number of entries successfully added.
       
  3563  *
       
  3564  * This Function fills the SearchSortTable with the query specified on the IndexEntryTable
       
  3565  */
       
  3566 TInt CMsvDBAdapter::AddEntriesfromIndexTableL(const TDesC8& aQuery)
       
  3567 	{
       
  3568 	TInt err = iDatabase.Exec(aQuery);
       
  3569 	
       
  3570 	TPtrC errMsg = iDatabase.LastErrorMessage();
       
  3571 	
       
  3572 	if(err < 0)
       
  3573 		{
       
  3574 		User::Leave(err);
       
  3575 		}
       
  3576 
       
  3577 	return err;
       
  3578 	}
       
  3579 
       
  3580 
       
  3581 
       
  3582 
       
  3583 /**
       
  3584  * ReturnIdCountInDBL()
       
  3585  * @param TInt&: The Id of the Search/Sort Query
       
  3586  * @return TInt: The number of entries stored under the QueryId specified
       
  3587  *
       
  3588  * This Function returns the number of id's stored under the specified QueryId
       
  3589  */
       
  3590 TInt CMsvDBAdapter::ReturnIdCountInDBL(const TInt& aQueryId)
       
  3591 	{
       
  3592 	TInt count=0;
       
  3593 	//Bind the msv id of the entry to be retrieved
       
  3594 	BindIntL(iQueryStatement[EQueryCount], iQIdQueryIndex[EQueryCount], aQueryId);
       
  3595 
       
  3596 	while(KSqlAtRow == iQueryStatement[EQueryCount].Next())
       
  3597 		{
       
  3598 		count = ColumnInt(iQueryStatement[EQueryCount], iIdQueryIndex[EQueryCount]);
       
  3599 		}
       
  3600 
       
  3601 	//Reset the RSqlStatement
       
  3602 	User::LeaveIfError(iQueryStatement[EQueryCount].Reset());
       
  3603 	return count;
       
  3604 	}
       
  3605 
       
  3606 
       
  3607 
       
  3608 
       
  3609 /**
       
  3610  * SearchTMsvIdL()
       
  3611  * @param aQuery        An object representing the the search sort query.
       
  3612  * @param aIdSelection  RArray holding the resultant TMsvId list. 
       
  3613  * 
       
  3614  * This function should be used to retrieve TMsvId list of result set.					 
       
  3615  * Queries the table holding TMsvEntry and retrieves id list of matched results.
       
  3616  */
       
  3617 void CMsvDBAdapter::SearchTMsvIdL(const TDesC8& aQuery, RArray<TMsvId>& aIdSelection)
       
  3618 	{
       
  3619 	RSqlStatement queryStmt;
       
  3620 	CleanupClosePushL(queryStmt);
       
  3621 	User::LeaveIfError(queryStmt.Prepare(iDatabase, aQuery));
       
  3622 	
       
  3623 	TInt idColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
       
  3624 	while(KSqlAtRow == queryStmt.Next())
       
  3625 		{
       
  3626 		
       
  3627 		TMsvId id = ColumnInt(queryStmt, idColumnIndex);
       
  3628 		
       
  3629 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3630 			id = MaskTMsvId(KCurrentDriveId, id);
       
  3631 		#endif
       
  3632 		
       
  3633 		aIdSelection.AppendL(id);
       
  3634 		}
       
  3635 
       
  3636 	CleanupStack::PopAndDestroy();
       
  3637 	}
       
  3638 
       
  3639 
       
  3640 
       
  3641 
       
  3642 /**
       
  3643  * GetFolderIdsL()
       
  3644  * @param aParentId      Parent Id of the folder.
       
  3645  * @param aFolderIdList  RArray holding the resultant TMsvId list. 
       
  3646  * 
       
  3647  * This function returns the id's of all the KUidMsvMessageEntry type under the parent.
       
  3648  */
       
  3649 void CMsvDBAdapter::GetFolderIdsL(const TMsvId aParentId, RArray<TMsvId>& aFolderIdList)
       
  3650 	{
       
  3651 	TMsvId entryId;
       
  3652 	TUid folderType = KUidMsvFolderEntry;
       
  3653 	
       
  3654 	#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3655 		{
       
  3656 		_LIT8(KGetFolderIds, "SELECT id FROM DB");
       
  3657 		_LIT8(KGetFolderQuery,".IndexEntry WHERE parentId = ");
       
  3658 	
       
  3659 		_LIT8(KTypeLike," AND type = ");
       
  3660 
       
  3661 		RBuf8 folderIdQuery;
       
  3662 		CleanupClosePushL(folderIdQuery);
       
  3663 		folderIdQuery.CreateL(500);		
       
  3664 		folderIdQuery.Append(KGetFolderIds);
       
  3665 		folderIdQuery.AppendNum(KCurrentDriveId);
       
  3666 		folderIdQuery.Append(KGetFolderQuery);
       
  3667 		folderIdQuery.AppendNum(aParentId);
       
  3668 		folderIdQuery.Append(KTypeLike);
       
  3669 		folderIdQuery.AppendNum(folderType.iUid);
       
  3670 		folderIdQuery.Append(KSemiColon);
       
  3671 	
       
  3672 		RSqlStatement folderquerystatement;
       
  3673 	
       
  3674 		User::LeaveIfError(folderquerystatement.Prepare(iDatabase, folderIdQuery));
       
  3675 	
       
  3676 		while(KSqlAtRow == folderquerystatement.Next())
       
  3677 			{
       
  3678 			entryId = ColumnInt(folderquerystatement, 0);
       
  3679 			aFolderIdList.AppendL(entryId);
       
  3680 			}
       
  3681 		folderquerystatement.Close();
       
  3682 		CleanupStack::PopAndDestroy();  //folderIdQuery
       
  3683 		}
       
  3684 	#else
       
  3685 		{
       
  3686 		//Bind the msv id of the entry to be retrieved
       
  3687 		BindIntL(iQueryStatement[EGetFolderIds], iParentIdfield, aParentId);
       
  3688 		BindIntL(iQueryStatement[EGetFolderIds], iTMsvidfield, folderType.iUid);
       
  3689 		
       
  3690 		while(KSqlAtRow == iQueryStatement[EGetFolderIds].Next())
       
  3691 			{
       
  3692 			entryId = ColumnInt(iQueryStatement[EGetFolderIds], iParentIdfield);
       
  3693 			aFolderIdList.AppendL(entryId);
       
  3694 			}
       
  3695 		//Reset the RSqlStatement
       
  3696 		User::LeaveIfError(iQueryStatement[EGetFolderIds].Reset());
       
  3697 		}
       
  3698 	#endif
       
  3699 	}
       
  3700 
       
  3701 
       
  3702 
       
  3703 
       
  3704 /**
       
  3705  * ClearDBContentsL()
       
  3706  * @param none.
       
  3707  * @param none.
       
  3708  * 
       
  3709  * This function clears the DB contents.
       
  3710  */
       
  3711 void CMsvDBAdapter::ClearDBContentsL()
       
  3712 	{
       
  3713 #if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3714 	RSqlDatabase temp;
       
  3715 	CleanupClosePushL(temp);
       
  3716 	//Get the system drive.
       
  3717 	TInt systemDrive = (TInt)RFs::GetSystemDrive();
       
  3718 	
       
  3719 	RBuf dbFile;
       
  3720 	CleanupClosePushL(dbFile);
       
  3721 	dbFile.CreateL(50);	
       
  3722 	dbFile.Append(TDriveUnit(systemDrive).Name());
       
  3723 	dbFile.Append(KMainDummyDBName);
       
  3724 	
       
  3725 	TRAPD(err, temp.OpenL(dbFile));
       
  3726 	if(err == KErrNone)
       
  3727 		{
       
  3728 		err = temp.Exec(KClearTableContents);
       
  3729 		if(err < 0)
       
  3730 			{
       
  3731 			User::Leave(err);
       
  3732 			}
       
  3733 		}
       
  3734 	temp.Close();
       
  3735 	CleanupStack::PopAndDestroy(2); //temp, dbFile
       
  3736 #else
       
  3737 	TInt err = iDatabase.Exec(KDeleteTable);
       
  3738 	if(err < 0)
       
  3739 		{
       
  3740 		User::Leave(err);
       
  3741 		}
       
  3742 #endif	
       
  3743 	
       
  3744 	}
       
  3745 
       
  3746 
       
  3747 
       
  3748 
       
  3749 /**
       
  3750  * ReturnIdsInIteratorL()
       
  3751  * @param aQueryId      Query ID of the query to be executed.
       
  3752  * @param prevCount     The previous value returned to the caller. 
       
  3753  * @param aId           If successfull, than this contains the result.
       
  3754  
       
  3755  * This function returns the TMsvId's for each unique Query ID.
       
  3756    Upon called for the first time, it binds the query id to the statement and returns 
       
  3757    next result in each subsequent execution. If the statement fails for some reason, than it returns the 
       
  3758    error code.	
       
  3759  */
       
  3760 void CMsvDBAdapter::ReturnIdsInIteratorL(const TInt& aQueryId, const TBool aOrder/*Default = ETrue*/,const TBool aSortAsInt/*Default = EFalse*/,const TInt aLimit/*Default = 1*/)
       
  3761 	{
       
  3762 	if(aSortAsInt)
       
  3763 		{
       
  3764 		if(aOrder)
       
  3765 			{
       
  3766 			iIterQuery = EQueryIteratorNumAsc;
       
  3767 			}
       
  3768 		else
       
  3769 			{
       
  3770 			iIterQuery = EQueryIteratorNumDesc;
       
  3771 			}
       
  3772 		}
       
  3773 	else
       
  3774 		{
       
  3775 		if(aOrder)
       
  3776 			{
       
  3777 			iIterQuery = EQueryIteratorAsc;
       
  3778 			}
       
  3779 		else
       
  3780 			{
       
  3781 			iIterQuery = EQueryIteratorDesc;
       
  3782 			}
       
  3783 		}
       
  3784 		
       
  3785 	iOffsetValue = 0;
       
  3786 	iQueryId = aQueryId;
       
  3787 	iLimit = aLimit;
       
  3788 	
       
  3789 	iIdColumnIndex = GetColumnIndexL(iQueryStatement[iIterQuery], KMsgColumnId());	
       
  3790 	}
       
  3791 
       
  3792 /**
       
  3793  * GetNextL()
       
  3794  * @param aId           If successfull, than this contains the result.
       
  3795  
       
  3796  * This function returns the next TMsvId's from the Iterator	
       
  3797  */	
       
  3798 TInt CMsvDBAdapter::GetNextL(TMsvId& aId)
       
  3799 	{
       
  3800 	BindIntL(iQueryStatement[iIterQuery], iQIdQueryIndex[iIterQuery], iQueryId);
       
  3801 	BindIntL(iQueryStatement[iIterQuery], iIterLimit[iIterQuery], iLimit);
       
  3802 	BindIntL(iQueryStatement[iIterQuery], iIterOffset[iIterQuery], iOffsetValue);
       
  3803 	
       
  3804 	while(iQueryStatement[iIterQuery].Next() == KSqlAtRow)
       
  3805 		{
       
  3806 		aId = ColumnInt(iQueryStatement[iIterQuery],iIdColumnIndex);
       
  3807 		
       
  3808 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3809 			aId = MaskTMsvId(KCurrentDriveId, aId);
       
  3810 		#endif
       
  3811 			
       
  3812 		++iOffsetValue;
       
  3813 		}
       
  3814 	
       
  3815 	User::LeaveIfError(iQueryStatement[iIterQuery].Reset());
       
  3816 	return iOffsetValue;
       
  3817 	}
       
  3818 	
       
  3819 
       
  3820 /**
       
  3821  * GetPrevL()
       
  3822  * @param aId           If successfull, than this contains the result.
       
  3823  
       
  3824  * This function returns the previous TMsvId's from the Iterator	
       
  3825  */
       
  3826 TInt CMsvDBAdapter::GetPrevL(TMsvId& aId)
       
  3827 	{
       
  3828 	BindIntL(iQueryStatement[iIterQuery], iQIdQueryIndex[iIterQuery], iQueryId);
       
  3829 	BindIntL(iQueryStatement[iIterQuery], iIterLimit[iIterQuery], iLimit);
       
  3830 	BindIntL(iQueryStatement[iIterQuery], iIterOffset[iIterQuery], iOffsetValue);
       
  3831 	
       
  3832 	while(iQueryStatement[iIterQuery].Next() == KSqlAtRow)
       
  3833 		{
       
  3834 		aId = ColumnInt(iQueryStatement[iIterQuery],iIdColumnIndex);
       
  3835 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3836 			aId = MaskTMsvId(KCurrentDriveId, aId);
       
  3837 		#endif
       
  3838 		
       
  3839 		--iOffsetValue;
       
  3840 		}
       
  3841 	
       
  3842 	User::LeaveIfError(iQueryStatement[iIterQuery].Reset());
       
  3843 	return iOffsetValue;
       
  3844 	}
       
  3845 
       
  3846 
       
  3847 
       
  3848 
       
  3849 
       
  3850 #if (!defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3851 /**
       
  3852  * ValidateDatabaseL()
       
  3853  * 
       
  3854  * @param TFileName& The database filename to be checked.
       
  3855  * @return None.
       
  3856  *
       
  3857  * Checks the database version to see if it is supported.
       
  3858  * Supported version is KCurrentDatabaseVersion (1) only.
       
  3859  */
       
  3860 void CMsvDBAdapter::ValidateDatabaseL(const TFileName& aDbFile)
       
  3861 	{
       
  3862 	_LIT8(KSelectVersionQuery, "SELECT version FROM VersionTable;");
       
  3863 	
       
  3864 	//Use a temporary local database connection to open the file for now.
       
  3865 	RSqlDatabase temp;
       
  3866 	CleanupClosePushL(temp);
       
  3867 	temp.OpenL(aDbFile);	
       
  3868 	TSqlScalarFullSelectQuery query(temp);
       
  3869 
       
  3870 	TInt version = 0;
       
  3871 	version = query.SelectIntL(KSelectVersionQuery);
       
  3872 	if(KCurrentDatabaseVersion != version)
       
  3873 		{
       
  3874 		User::Leave(KErrNotSupported);
       
  3875 		}
       
  3876 	CleanupStack::PopAndDestroy();  // temp
       
  3877 	}
       
  3878 #endif
       
  3879 
       
  3880 
       
  3881 
       
  3882 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  3883 /** 
       
  3884 * GetMtmIdsL()
       
  3885 *
       
  3886 * @param aMtmIdTable: aMtmIdTable will be updated with MtmIds
       
  3887 * @param aQuery: QueryString which is prepared depending on SearchSort Query
       
  3888 * return NONE
       
  3889 *  
       
  3890 *  Function to get MtmId/s for given parent id.
       
  3891 */ 
       
  3892 void CMsvDBAdapter::GetMtmIdsL(const TDesC8& aQuery, RArray<TUid>& aMtmIdArray)
       
  3893 	{
       
  3894 	RSqlStatement queryStmt;
       
  3895 	CleanupClosePushL(queryStmt);
       
  3896 	User::LeaveIfError(queryStmt.Prepare(iDatabase, aQuery));
       
  3897 	
       
  3898 	TInt mtmIdColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnMtmId());
       
  3899 	
       
  3900 	TUid tempMtmId ;
       
  3901 	TInt32 mtmId = KErrNotFound;
       
  3902 	
       
  3903 	while(KSqlAtRow == queryStmt.Next())
       
  3904 		{
       
  3905 		mtmId = ColumnInt(queryStmt, mtmIdColumnIndex);
       
  3906 		
       
  3907 		tempMtmId.iUid = mtmId;
       
  3908 		aMtmIdArray.AppendL(tempMtmId);
       
  3909 		}
       
  3910 	
       
  3911 	CleanupStack::PopAndDestroy();
       
  3912 	}
       
  3913 
       
  3914 
       
  3915 
       
  3916 /***************************** Converter************************/
       
  3917 
       
  3918 /**
       
  3919 OpenL()
       
  3920 Opens a database and returns a handle to it.
       
  3921 
       
  3922 @param aDbFileName: DB name.
       
  3923 @retun :CMsvDBAdapter object.
       
  3924 */	
       
  3925 CMsvDBAdapter* CMsvDBAdapter::OpenL(const TFileName& aDbFileName)
       
  3926 	{
       
  3927 	//Create an messaging DB adaptor object 
       
  3928 	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
       
  3929 	CleanupStack::PushL(self);
       
  3930 	
       
  3931 	// Open the database.
       
  3932 	self->ConstructOpenDBL(aDbFileName);
       
  3933 	
       
  3934 	CleanupStack::Pop(self);
       
  3935 	return self;
       
  3936 	}
       
  3937 	
       
  3938 /**
       
  3939 ConstructOpenDBL()
       
  3940 
       
  3941 @param aDbFileName: DB name.
       
  3942 @retun None
       
  3943 */
       
  3944 void CMsvDBAdapter::ConstructOpenDBL(const TFileName& aDbFileName)
       
  3945 	{
       
  3946 	User::LeaveIfError(iDatabase.Open(aDbFileName));
       
  3947 	iDatabasePresent = new(ELeave)RArray<TBool>(KMaxNumberOfDrives);
       
  3948 	for(TInt index = 0; index < KMaxNumberOfDrives; ++index)
       
  3949 		{
       
  3950 		iDatabasePresent->Append(EFalse);
       
  3951 		}
       
  3952 	}
       
  3953 
       
  3954 	
       
  3955 /**
       
  3956  * InitializeL()
       
  3957  *
       
  3958  * This functions prepares (compiles) frequetly used SQL queries,
       
  3959  * and create indexes on the variable arguments. When the query
       
  3960  * needs to be executed, we just have to bind the variables with
       
  3961  * the values and execute them. This increases the performance of
       
  3962  * query execution.
       
  3963  */
       
  3964 void CMsvDBAdapter::InitializeLConverterStatementL()
       
  3965 	{
       
  3966 	//Prepare the frequently used SQL statements
       
  3967 	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, KCreateEntryQuery));
       
  3968 	
       
  3969 	//For creating and updating entries
       
  3970 	iParentIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamParentId());
       
  3971 	iVisibleParent[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamVisibleParent());
       
  3972 	iIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamId());				
       
  3973 	iServiceIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamServiceId());
       
  3974 	iMtmIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmId());
       
  3975 	iTypeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamType());
       
  3976 	iDateIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDate());
       
  3977 	iDataIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamData());
       
  3978 	iSizeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamSize());
       
  3979 	iErrorIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamError());
       
  3980 	iMtmData1Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData1());
       
  3981 	iMtmData2Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData2());
       
  3982 	iMtmData3Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData3());
       
  3983 	iRelatedIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamRelatedId());
       
  3984 	iBiotypeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamBiotype());
       
  3985 	iPcSyncCountIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamPcSyncCount());
       
  3986 	iReservedIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamReserved());
       
  3987 	iDescriptionIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDescriptionTxt());
       
  3988 	iDetailsIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDetailsTxt());
       
  3989 	}
       
  3990 
       
  3991 
       
  3992 /**
       
  3993 CreateIndexEntryL()
       
  3994 Inserts an entry in IndexEntry table.  
       
  3995 
       
  3996 @param aNewEntry: TMsvEntry.
       
  3997 @param aImmediateVisibleFolder: Visible Parent.
       
  3998 @retun None
       
  3999 */
       
  4000 void CMsvDBAdapter::CreateIndexEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
       
  4001 	{
       
  4002 	//Bind the entry data
       
  4003 	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], aNewEntry.iId);
       
  4004 	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], aNewEntry.iParentId);
       
  4005 	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
       
  4006 	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
       
  4007 	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
       
  4008 	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], aNewEntry.iRelatedId);
       
  4009 	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
       
  4010 	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
       
  4011 	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
       
  4012 	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
       
  4013 	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
       
  4014 	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
       
  4015 	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
       
  4016 	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
       
  4017 	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], aNewEntry.iServiceId);
       
  4018 	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
       
  4019 	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], aImmediateVisibleFolder);
       
  4020 	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
       
  4021 	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
       
  4022 	//Execute the prepared SQL statement.
       
  4023 	
       
  4024 	TInt err = iStatement[ECreateEntry].Exec();
       
  4025 	if(err < 0)
       
  4026 		{
       
  4027 		iStatement[ECreateEntry].Reset();
       
  4028 		User::Leave(err);
       
  4029 		}
       
  4030 	else if(!err)
       
  4031 		{
       
  4032 		iStatement[ECreateEntry].Reset();
       
  4033 		User::Leave(KErrGeneral);
       
  4034 		}
       
  4035 	
       
  4036 	//Reset the RSqlStatement
       
  4037 	User::LeaveIfError(iStatement[ECreateEntry].Reset());	
       
  4038 	}
       
  4039 
       
  4040 
       
  4041 /**
       
  4042 ChangeVersionL()
       
  4043 Changes message store version of messaging database.
       
  4044 
       
  4045 @param aVersion: version
       
  4046 @retun None
       
  4047 */	
       
  4048 void CMsvDBAdapter::ChangeVersionL(TInt aVersion)
       
  4049 	{
       
  4050 	_LIT(KUpdateVersionQuery, "UPDATE VersionTable SET version = "); 
       
  4051 		
       
  4052 	RBuf buf;
       
  4053 	CleanupClosePushL(buf);
       
  4054 	buf.CreateL(100);
       
  4055 	buf.Append(KUpdateVersionQuery);
       
  4056 	buf.AppendNum(aVersion);
       
  4057 	buf.Append(KDelimiter);
       
  4058 	
       
  4059 	TInt err = iDatabase.Exec(buf);
       
  4060 	if(err < 0)
       
  4061 		{
       
  4062 		User::Leave(err);
       
  4063 		}
       
  4064 	CleanupStack::PopAndDestroy(); //buf
       
  4065 	}
       
  4066 
       
  4067 	
       
  4068 /**************************** Conversion Status Table API's **************************/
       
  4069 /**
       
  4070 CreateConversionStatusTableL()
       
  4071 Creates conversion status table.
       
  4072 
       
  4073 @param None: 
       
  4074 @retun None
       
  4075 */
       
  4076 void CMsvDBAdapter::CreateConversionStatusTableL()
       
  4077 	{
       
  4078 	TInt err = iDatabase.Exec(KCreateConversionStatusTableQuery);
       
  4079 	if(err < 0)
       
  4080 		{
       
  4081 		User::Leave(KErrGeneral);
       
  4082 		}
       
  4083 	}
       
  4084 
       
  4085 /**
       
  4086 RemoveConversionStatusTableL()
       
  4087 Removes conversion status table.
       
  4088 
       
  4089 @param None: 
       
  4090 @retun None
       
  4091 */	
       
  4092 void CMsvDBAdapter::RemoveConversionStatusTableL()
       
  4093 	{
       
  4094 	TInt err = iDatabase.Exec(KRemoveConversionStatusTable);
       
  4095 	if(err < 0)
       
  4096 		{
       
  4097 		User::Leave(err);
       
  4098 		}
       
  4099 	}
       
  4100 
       
  4101 /**
       
  4102 GetConversionStatusL()
       
  4103 Fetches conversion resume state from the conversion status table.
       
  4104 
       
  4105 @param aConversionResumeStatus: Conversion sresume status entry.
       
  4106 @retun None
       
  4107 */	
       
  4108 void CMsvDBAdapter::GetConversionStatusL(TConversionResumeStatus& aConversionResumeStatus)
       
  4109 	{
       
  4110 	// We shld not get more than one mtm results for this query
       
  4111 	_LIT16(KGetConversionStatusQuery, "SELECT * FROM ConversionStatus WHERE remainingCount != 0;"); 
       
  4112 	
       
  4113 	RSqlStatement statement;
       
  4114 	CleanupClosePushL(statement);
       
  4115 	TInt index =0;
       
  4116 	
       
  4117 	User::LeaveIfError(statement.Prepare(iDatabase, KGetConversionStatusQuery));
       
  4118 		
       
  4119 	while(KSqlAtRow ==  statement.Next())
       
  4120 		{
       
  4121 		aConversionResumeStatus.lastId = ColumnInt(statement, index);
       
  4122 		aConversionResumeStatus.serviceId = ColumnInt(statement, ++index);
       
  4123 		aConversionResumeStatus.sourceVersion = ColumnInt(statement, ++index);
       
  4124 		aConversionResumeStatus.targetVersion = ColumnInt(statement, ++index);
       
  4125 		aConversionResumeStatus.mtmId.iUid = ColumnInt(statement, ++index);
       
  4126 		aConversionResumeStatus.remainingCount = ColumnInt(statement, ++index);
       
  4127 		index =0;
       
  4128 		}
       
  4129 	CleanupStack::PopAndDestroy(); //statement
       
  4130 	}
       
  4131 
       
  4132 /**
       
  4133 AddConversionStatusEntryL()
       
  4134 Inserts a conversion status entry in the conversion status table.
       
  4135 
       
  4136 @param aConversionResumeStatus: Conversion sresume status entry.
       
  4137 @retun None
       
  4138 */	
       
  4139 void CMsvDBAdapter::AddConversionStatusEntryL(TConversionResumeStatus& aConversionResumeStatus)
       
  4140 	{
       
  4141 	_LIT8(KAddConversionStatusEntryQuery, "INSERT INTO ConversionStatus VALUES ("
       
  4142 							 ":lastId, :serviceId, :sourceVersion, :targetVersion, :mtmId, :remainingCount);"
       
  4143 		 ); //
       
  4144 			 
       
  4145 	RSqlStatement statement;
       
  4146 	CleanupClosePushL(statement);
       
  4147 	TInt index =0;
       
  4148 	
       
  4149 	User::LeaveIfError(statement.Prepare(iDatabase,KAddConversionStatusEntryQuery));
       
  4150 	BindIntL(statement, index++, aConversionResumeStatus.lastId);
       
  4151 	BindIntL(statement, index++, aConversionResumeStatus.serviceId);
       
  4152 	BindIntL(statement, index++, aConversionResumeStatus.sourceVersion);
       
  4153 	BindIntL(statement, index++, aConversionResumeStatus.targetVersion);
       
  4154 	BindIntL(statement, index++, aConversionResumeStatus.mtmId.iUid);
       
  4155 	BindIntL(statement, index++, aConversionResumeStatus.remainingCount);
       
  4156 	
       
  4157 	TInt err = statement.Exec();
       
  4158 	
       
  4159 	CleanupStack::PopAndDestroy(); //statement
       
  4160 
       
  4161 	if(err < 0)
       
  4162 		{
       
  4163 		User::Leave(err);
       
  4164 		}
       
  4165 	else if(!err )
       
  4166 		{
       
  4167 		User::Leave(KErrGeneral);
       
  4168 		}
       
  4169 	}
       
  4170 
       
  4171 /**
       
  4172 UpdateConversionStatusEntryL()
       
  4173 Updates a conversion status entry in the conversion status table.
       
  4174 
       
  4175 @param aConversionResumeStatus:Conversion sresume status entry.
       
  4176 @retun None
       
  4177 */	
       
  4178 void CMsvDBAdapter::UpdateConversionStatusEntryL(TConversionResumeStatus& aConversionResumeStatus)	
       
  4179 	{
       
  4180 	_LIT(KUpdateConversionStatusQuery1,	"UPDATE ConversionStatus SET remainingCount = "); //
       
  4181 	_LIT(KUpdateConversionStatusQuery2,	" WHERE mtmId = "); //
       
  4182 	_LIT(KUpdateConversionStatusQuery3,	" AND serviceId = "); //
       
  4183 	 
       
  4184 	RBuf buf;
       
  4185 	CleanupClosePushL(buf);
       
  4186 	buf.CreateL(100);
       
  4187 	buf.Append(KUpdateConversionStatusQuery1);
       
  4188 	buf.AppendNum(aConversionResumeStatus.remainingCount);
       
  4189 	buf.Append(KUpdateConversionStatusQuery2);
       
  4190 	buf.AppendNum(aConversionResumeStatus.mtmId.iUid);
       
  4191 	buf.Append(KUpdateConversionStatusQuery3);
       
  4192 	buf.AppendNum(aConversionResumeStatus.serviceId);
       
  4193 	buf.Append(KDelimiter); 
       
  4194 	 
       
  4195 	TInt err = iDatabase.Exec(buf);
       
  4196 	CleanupStack::PopAndDestroy(); //buf
       
  4197 	
       
  4198 	if(err < 0)
       
  4199 		{
       
  4200 		User::Leave(err);
       
  4201 		}
       
  4202 	else if(!err )
       
  4203 		{
       
  4204 		User::Leave(KErrGeneral);
       
  4205 		}
       
  4206 	}
       
  4207 
       
  4208 /**
       
  4209 RemoveConversionStatusEntriesL()
       
  4210 Removes all conversion status entries in the conversion status table.
       
  4211 
       
  4212 @param None: 
       
  4213 @retun None
       
  4214 */		
       
  4215 void CMsvDBAdapter::RemoveConversionStatusEntriesL()	
       
  4216 	{
       
  4217  	_LIT(KRemoveConversionStatusEntry,	"DELETE FROM ConversionStatus;");
       
  4218 	
       
  4219 	RSqlStatement statement;
       
  4220 	CleanupClosePushL(statement);
       
  4221 	User::LeaveIfError(statement.Prepare(iDatabase, KRemoveConversionStatusEntry));
       
  4222 	TInt err = statement.Exec();
       
  4223 	
       
  4224 	CleanupStack::PopAndDestroy(); // statement
       
  4225 	
       
  4226 	if(err < 0)
       
  4227 		{
       
  4228 		User::Leave(err);
       
  4229 		}
       
  4230 	else if(err != KErrNone)
       
  4231 		{
       
  4232 		User::Leave(KErrGeneral);
       
  4233 		}
       
  4234 	}
       
  4235 
       
  4236 /**
       
  4237 GetRemainingServiceIdsL()
       
  4238 Fetches all service ids for which the conversion is not complete from the conversion status table.
       
  4239 
       
  4240 @param aIdArray:Array of TMsvId.
       
  4241 @retun None
       
  4242 */	
       
  4243 void CMsvDBAdapter::GetRemainingServiceIdsL(RArray<TMsvId>& aIdArray)
       
  4244 	{
       
  4245 	_LIT(KGetToResumeServiceIds, "SELECT serviceId FROM ConversionStatus WHERE remainingCount != 0;"); 	
       
  4246 	
       
  4247 	RSqlStatement queryStmt;
       
  4248 	CleanupClosePushL(queryStmt);
       
  4249 	User::LeaveIfError(queryStmt.Prepare(iDatabase, KGetToResumeServiceIds));
       
  4250 	
       
  4251 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnServiceId());
       
  4252 	
       
  4253 	while(KSqlAtRow == queryStmt.Next())
       
  4254 		{
       
  4255 		TMsvId serviceId = ColumnInt(queryStmt, serviceColumnIndex);
       
  4256 		aIdArray.AppendL(serviceId);
       
  4257 		}
       
  4258 	CleanupStack::PopAndDestroy(); // stmt
       
  4259 	}
       
  4260 
       
  4261 /**
       
  4262 GetAllMessageIdsL()
       
  4263 Gets all message ids for a service id. If the conversion is resumed than retrives the message ids
       
  4264 after the last id that was converted. 
       
  4265 
       
  4266 @param aServiceId: service id.
       
  4267 @param aIdArray: Array of TMsvId.
       
  4268 @param lastId: last id that was converted and commited in the database.
       
  4269 @retun None
       
  4270 */	
       
  4271 void CMsvDBAdapter::GetAllMessageIdsL(TMsvId aServiceId, RArray<TMsvId>& aIdArray,TInt32 aMtm,TMsvId lastId)
       
  4272 	{
       
  4273 	_LIT16(KSelectMessageId, "Select id FROM IndexEntry WHERE type = ");
       
  4274 	_LIT16(KMessageMtmId," AND mtmId = ");
       
  4275 	_LIT16(KSelectServiceId," AND serviceId = ");
       
  4276 	_LIT16(KMessageId, " AND id > ");
       
  4277 	_LIT16(KOrderByString, " order by id ASC");
       
  4278 	
       
  4279 	RBuf buf;
       
  4280 	CleanupClosePushL(buf);
       
  4281 	buf.CreateL(200);
       
  4282 	buf.Append(KSelectMessageId);
       
  4283 	buf.AppendNum(KUidMsvMessageEntryValue);
       
  4284 	buf.Append(KMessageMtmId);
       
  4285 	buf.AppendNum(aMtm);
       
  4286 	buf.Append(KSelectServiceId);
       
  4287 	buf.AppendNum(aServiceId);
       
  4288 	buf.Append(KMessageId);
       
  4289 	buf.AppendNum(lastId);
       
  4290 	buf.Append(KOrderByString);
       
  4291 	buf.Append(KDelimiter);
       
  4292 	
       
  4293 	RSqlStatement Idquerystatement;
       
  4294 	CleanupClosePushL(Idquerystatement);
       
  4295 	User::LeaveIfError(Idquerystatement.Prepare(iDatabase, buf));
       
  4296 	
       
  4297 	TInt Idindex = GetColumnIndexL(Idquerystatement, KMsgColumnId());
       
  4298 	
       
  4299 	while(KSqlAtRow == Idquerystatement.Next())
       
  4300 		{
       
  4301 		aIdArray.Append(ColumnInt(Idquerystatement, Idindex));
       
  4302 		}
       
  4303 		
       
  4304 	CleanupStack::PopAndDestroy(2);  //buf,Idquerystatement
       
  4305 	}
       
  4306 
       
  4307 /**
       
  4308 GetAllMimeIdsL()
       
  4309 Gets all attachment ids for a message.
       
  4310 
       
  4311 @param aId: id
       
  4312 @param aIdArray: Array of TMsvId.
       
  4313 @retun None
       
  4314 */
       
  4315 void CMsvDBAdapter::GetAllMimeIdsL(TMsvId aId, RArray<TMsvId>& aIdArray)
       
  4316 	{
       
  4317 	_LIT(KGetChild, "Select id, type FROM IndexEntry WHERE parentId = ");
       
  4318 	
       
  4319 	const TInt32 KUidMsvEmailTextEntryValue = 0x100038F1;
       
  4320 	const TInt32 KUidMsvEmailHtmlEntryValue = 0x100057C0; // 268457920
       
  4321 	const TInt32 KUidMsvEmailRtfEntryValue = 0x1028368F; // 271070863
       
  4322 
       
  4323 	RBuf buf;
       
  4324 	CleanupClosePushL(buf);
       
  4325 	buf.CreateL(100);
       
  4326 	buf.Append(KGetChild);
       
  4327 	buf.AppendNum(aId);
       
  4328 	buf.Append(KDelimiter);
       
  4329 	
       
  4330 	RSqlStatement stmt;
       
  4331 	CleanupClosePushL(stmt);
       
  4332 	User::LeaveIfError(stmt.Prepare(iDatabase, buf));
       
  4333 	
       
  4334 	TInt idIndex = 0;
       
  4335 	TInt typeIndex = 1;
       
  4336 		
       
  4337 	// For every child..
       
  4338 	while(KSqlAtRow == stmt.Next())
       
  4339 		{
       
  4340 		// Get the type
       
  4341 		TMsvId childId = ColumnInt(stmt, idIndex);
       
  4342 		TInt32 type = ColumnInt(stmt, typeIndex);
       
  4343 		
       
  4344 		// Append TMsvId's which may have MIME header
       
  4345 		if( type == KUidMsvAttachmentEntryValue ||
       
  4346 			type == KUidMsvEmailTextEntryValue ||
       
  4347 			type == KUidMsvEmailHtmlEntryValue ||
       
  4348 			type == KUidMsvEmailRtfEntryValue
       
  4349 			)
       
  4350 			{
       
  4351 			aIdArray.Append(childId);
       
  4352 			}
       
  4353 		// Recursion for alternate folders
       
  4354 		else if(type == KUidMsvFolderEntryValue)
       
  4355 			{
       
  4356 			aIdArray.Append(childId);
       
  4357 			// also get the childs for these messages
       
  4358 			GetAllMimeIdsL(childId, aIdArray);
       
  4359 			}
       
  4360 		}
       
  4361 		
       
  4362 	CleanupStack::PopAndDestroy(2); // stmt, buf
       
  4363 	}
       
  4364 
       
  4365 /**
       
  4366 GetMessageCountL()
       
  4367 Gets the count of messages under a service id.
       
  4368 
       
  4369 @param aServiceId: service id
       
  4370 */
       
  4371 TInt CMsvDBAdapter::GetMessageCountL(TMsvId aServiceId)
       
  4372 	{
       
  4373 	_LIT(KSelectMessageId, "Select count(*) FROM IndexEntry WHERE type = ");
       
  4374 	_LIT(KServiceId," AND serviceId = ");
       
  4375 	RBuf buf;
       
  4376 	CleanupClosePushL(buf);
       
  4377 	buf.CreateL(100);
       
  4378 	buf.Append(KSelectMessageId);
       
  4379 	buf.AppendNum(KUidMsvMessageEntryValue);
       
  4380 	buf.Append(KServiceId);
       
  4381 	buf.AppendNum(aServiceId);
       
  4382 	buf.Append(KDelimiter);
       
  4383 	
       
  4384 	TSqlScalarFullSelectQuery query(iDatabase);
       
  4385 	TInt msgcount = 0;
       
  4386 	msgcount = query.SelectIntL(buf);
       
  4387 	
       
  4388 	CleanupStack::PopAndDestroy();  //buf
       
  4389 	return msgcount;
       
  4390 	}
       
  4391 
       
  4392 /**
       
  4393 GetOwningServiceL()
       
  4394 Gets the ids owning service.
       
  4395 
       
  4396 @param aId: id
       
  4397 @param aOwningId: owning service id reference variable.
       
  4398 @retun None
       
  4399 */
       
  4400 void CMsvDBAdapter::GetOwningServiceL(TMsvId aId, TMsvId& aOwningId)
       
  4401 	{
       
  4402 	_LIT(KSelectServiceId, "Select parentId,type FROM IndexEntry WHERE id = ");
       
  4403 	
       
  4404 	TBool found = EFalse;
       
  4405 	TMsvId entryid = aId;
       
  4406 	TMsvId parentId = 0;
       
  4407 	TMsvId typeId = 0;
       
  4408 	
       
  4409 	while (!found)
       
  4410 		{
       
  4411 		RBuf buf;
       
  4412 		CleanupClosePushL(buf);
       
  4413 		buf.CreateL(100);
       
  4414 		buf.Append(KSelectServiceId);
       
  4415 		buf.AppendNum(entryid);
       
  4416 		buf.Append(KDelimiter);
       
  4417 		
       
  4418 		RSqlStatement parentIdquerystatement;
       
  4419 		CleanupClosePushL(parentIdquerystatement);
       
  4420 		User::LeaveIfError(parentIdquerystatement.Prepare(iDatabase, buf));
       
  4421 		
       
  4422 		TInt parentIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnParentId());
       
  4423 		TInt typeIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnType());
       
  4424 	
       
  4425 		while(KSqlAtRow == parentIdquerystatement.Next())
       
  4426 			{
       
  4427 			parentId  = ColumnInt(parentIdquerystatement, parentIdindex);
       
  4428 			typeId = ColumnInt(parentIdquerystatement, typeIdindex);
       
  4429 			}
       
  4430 		
       
  4431 		CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
       
  4432 			
       
  4433 		if (typeId == KUidMsvServiceEntryValue)
       
  4434 			{
       
  4435 			found = ETrue;
       
  4436 			}
       
  4437 		else
       
  4438 			{
       
  4439 			entryid = parentId;
       
  4440 			}
       
  4441 		}
       
  4442 	aOwningId = entryid;
       
  4443 	}
       
  4444 	
       
  4445 /**
       
  4446 GetAllServiceIDsForMtmL()
       
  4447 Gets all service ids for the specified mtm.
       
  4448 
       
  4449 @param aMtm: mtm id.
       
  4450 @param aIdArray&: Array of TMsvId.
       
  4451 @retun None
       
  4452 */
       
  4453 void CMsvDBAdapter::GetAllServiceIDsForMtmL(TInt32 aMtm, RArray<TMsvId>& aIdArray)
       
  4454 	{
       
  4455 	// if sms, than dont get smtp id else, get the smtp id also
       
  4456 	_LIT16(KSelectServiceIds, "Select distinct serviceId FROM IndexEntry where type = ");
       
  4457 	_LIT16(KMtmIdQuery," AND mtmId = ");
       
  4458 
       
  4459 	RBuf buf;
       
  4460 	CleanupClosePushL(buf);
       
  4461 	buf.CreateL(200);
       
  4462 	buf.Append(KSelectServiceIds);
       
  4463 	buf.AppendNum(KUidMsvServiceEntryValue);
       
  4464 	buf.Append(KMtmIdQuery);
       
  4465 	buf.AppendNum(aMtm);
       
  4466 	buf.Append(KDelimiter);
       
  4467 	
       
  4468 	RSqlStatement queryStmt;
       
  4469 	CleanupClosePushL(queryStmt);
       
  4470 	User::LeaveIfError(queryStmt.Prepare(iDatabase, buf));
       
  4471 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnServiceId());
       
  4472 	
       
  4473 	while(KSqlAtRow == queryStmt.Next())
       
  4474 		{
       
  4475 		TMsvId serviceId = ColumnInt(queryStmt, serviceColumnIndex);
       
  4476 		aIdArray.AppendL(serviceId);
       
  4477 		}
       
  4478 	CleanupStack::PopAndDestroy(2); //buf, stmt
       
  4479 	
       
  4480 	// lets also get all messages in the root with this service id
       
  4481 	if(aMtm == 268439592 ) //0x1000102C sms
       
  4482 		{
       
  4483 		aIdArray.AppendL(KMsvGlobalOutBoxIndexEntryIdValue);	
       
  4484 		aIdArray.AppendL(KMsvDraftEntryIdValue);
       
  4485 		aIdArray.AppendL(KMsvSentEntryIdValue);	
       
  4486 		}
       
  4487 	}
       
  4488 
       
  4489 /**
       
  4490 GetAllIndexEntryTableIdsL()
       
  4491 Gets all ids present in index entry table.
       
  4492 
       
  4493 @param aIdArray: Array of TMsvId.
       
  4494 @retun None
       
  4495 */
       
  4496 void CMsvDBAdapter::GetAllIndexEntryTableIdsL(RArray<TMsvId>& aIdArray)	
       
  4497 	{
       
  4498 	_LIT(KSelectAllIds, "Select * FROM IndexEntry;");
       
  4499 	
       
  4500 	RSqlStatement queryStmt;
       
  4501 	CleanupClosePushL(queryStmt);
       
  4502 	User::LeaveIfError(queryStmt.Prepare(iDatabase, KSelectAllIds));
       
  4503 	
       
  4504 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
       
  4505 	
       
  4506 	while(KSqlAtRow == queryStmt.Next())
       
  4507 		{
       
  4508 		TMsvId Id = ColumnInt(queryStmt, serviceColumnIndex);
       
  4509 		aIdArray.AppendL(Id);
       
  4510 		}
       
  4511 	CleanupStack::PopAndDestroy(); //queryStmt
       
  4512 	}
       
  4513 
       
  4514 /**
       
  4515 GetVisibleParentL()
       
  4516 Gets the visible parent of the specified id.
       
  4517 
       
  4518 @param aId: id
       
  4519 @param aVisibleParentId: visible parent id.
       
  4520 @retun None
       
  4521 */
       
  4522  
       
  4523 void CMsvDBAdapter::GetVisibleParentL(TMsvId aId, TMsvId& aVisibleParentId)
       
  4524 	{
       
  4525 	_LIT(KSelectServiceId, "Select parentId,type FROM IndexEntry WHERE id = ");
       
  4526 	
       
  4527 	TMsvId entryid = aId;
       
  4528 	TMsvId parentId = 0;
       
  4529 		
       
  4530 	RBuf buf;
       
  4531 	CleanupClosePushL(buf);
       
  4532 	buf.CreateL(100);
       
  4533 	buf.Append(KSelectServiceId);
       
  4534 	buf.AppendNum(entryid);
       
  4535 	buf.Append(KDelimiter);
       
  4536 	
       
  4537 	RSqlStatement parentIdquerystatement;
       
  4538 	CleanupClosePushL(parentIdquerystatement);
       
  4539 	
       
  4540 	User::LeaveIfError(parentIdquerystatement.Prepare(iDatabase, buf));
       
  4541 		
       
  4542 	TInt parentIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnParentId());
       
  4543 		
       
  4544 	while(KSqlAtRow == parentIdquerystatement.Next())
       
  4545 		{
       
  4546 		parentId  = ColumnInt(parentIdquerystatement, parentIdindex);
       
  4547 		}
       
  4548 	
       
  4549 	CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
       
  4550 	
       
  4551 	GetVisibleParentIdL(parentId,aVisibleParentId);
       
  4552 	}
       
  4553 
       
  4554 /**
       
  4555 GetVisibleParentIdL()
       
  4556 This functions returns the most immediate parent visible folder id.
       
  4557 There are two types of folders. A visible folder is one which is 
       
  4558 visible to the external user, but there are internal non-visible folders
       
  4559 created under each email message to organize the content of the email.
       
  4560 Parent entry of an entry is either root or a folder. A folder can be 
       
  4561 service folder (like LocalServices), userdefined folder/standard folder
       
  4562 like Inbox or a non-visible folder (created under an email message).
       
  4563 
       
  4564 For a given parent Id, the function returns the most immediate visible
       
  4565 parent folder. The rules are as follows:
       
  4566 1. If the parent entry is root or children of root, then the visibleFolder 
       
  4567 will be root itself. This is because service folders are considered 
       
  4568 invisible, since they are not seen by user. 
       
  4569 2. If the parent entry itself is a visible folder then child's visibleFolder
       
  4570 id should be its parent id.
       
  4571 3. If the parent entry is a non-visible folder then child's visibleFolder
       
  4572 id is same as its parent's visibleFolder id.
       
  4573 
       
  4574 @param TMsvId: Parent Id.
       
  4575 @return Most immediate visible folder id of any child entry present under passed parent id.
       
  4576 */
       
  4577 void CMsvDBAdapter::GetVisibleParentIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
       
  4578 	{
       
  4579 	// If the entry is either a root entry (parent=KErrNotFound) or 
       
  4580 	// child of root entry its visibleFolderId will be root entry itself.
       
  4581 	if((KErrNotFound == aParentId) || (KMsvRootIndexEntryId == aParentId))
       
  4582 		{
       
  4583 		aVisibleFolderId = KMsvRootIndexEntryId;
       
  4584 		}
       
  4585 	else
       
  4586 		{
       
  4587 		// Get the visible flag of parent entry.
       
  4588 		
       
  4589 		// If parent entry is visible, then immediateVisibleFolder of child
       
  4590 		// should be parent Id. And if it is invisible then child's immediateVisibleFolder 
       
  4591 		// should be same as parent's immediateVisibleFolder.
       
  4592 		
       
  4593 		//Bind the msv id
       
  4594 		BindIntL(iStatement[EGetVisibleId], iIdIndex[EGetVisibleId], aParentId);
       
  4595 
       
  4596 		// If parent entry does not exists leave with KErrNotFound.
       
  4597 		if (KSqlAtRow != iStatement[EGetVisibleId].Next())
       
  4598 			{
       
  4599 			iStatement[EGetVisibleId].Reset();
       
  4600 			User::Leave(KErrNotFound);
       
  4601 			}
       
  4602 
       
  4603 		TInt32 data = ColumnInt(iStatement[EGetVisibleId], iDataIndex[EGetVisibleId]);
       
  4604 		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
       
  4605 			{
       
  4606 			// If visible folder flag is not set for parent entry.
       
  4607 			aVisibleFolderId = ColumnInt(iStatement[EGetVisibleId], iVisibleParent[EGetVisibleId]);
       
  4608 			}
       
  4609 		else
       
  4610 			{
       
  4611 			// If parent entry is visible
       
  4612 			aVisibleFolderId = aParentId;
       
  4613 			}
       
  4614 		//Reset the RSqlStatement
       
  4615 		User::LeaveIfError(iStatement[EGetVisibleId].Reset());
       
  4616 		}
       
  4617 	}
       
  4618 
       
  4619 /**
       
  4620 UpdateVisibleFolderIdL()
       
  4621 Updates visible parent and any other new changes in TMsvEntry structure post PREQ 1189. 
       
  4622 
       
  4623 @param aId: id. 
       
  4624 @param visibleId: visible parent id.
       
  4625 @retun None
       
  4626 */	
       
  4627 void CMsvDBAdapter::UpdateVisibleFolderIdL(TMsvId aId,TMsvId visibleId)
       
  4628 	{
       
  4629 	_LIT(KUpdateVisibleParentQuery,"UPDATE IndexEntry SET visibleParent = ");
       
  4630 	_LIT(KWhere, " WHERE ");
       
  4631 	_LIT(KUpdateVisibleParentQuery1, "id = ");
       
  4632 	 	
       
  4633 	RBuf buf;
       
  4634 	CleanupClosePushL(buf);
       
  4635 	buf.CreateL(100);
       
  4636 	buf.Append(KUpdateVisibleParentQuery);
       
  4637 	buf.AppendNum(visibleId);
       
  4638 	buf.Append(KWhere);
       
  4639 	buf.Append(KUpdateVisibleParentQuery1);
       
  4640 	buf.AppendNum(aId);
       
  4641 	buf.Append(KDelimiter);
       
  4642 	
       
  4643 	RSqlStatement queryStmt;
       
  4644 	CleanupClosePushL(queryStmt);
       
  4645 	User::LeaveIfError(queryStmt.Prepare(iDatabase, buf));
       
  4646 	
       
  4647 	TInt err = queryStmt.Exec();
       
  4648 	
       
  4649 	CleanupStack::PopAndDestroy(2); //stmt
       
  4650 	
       
  4651 	if(err < 0)
       
  4652 		{
       
  4653 		User::Leave(err);
       
  4654 		}
       
  4655 	else if(!err)
       
  4656 		{
       
  4657 		User::Leave(KErrGeneral);
       
  4658 		}
       
  4659 	}
       
  4660 
       
  4661 TBool CMsvDBAdapter::GetParentVisibleFlagL(TMsvId parentId)
       
  4662 	{
       
  4663 	_LIT(KSelectServiceId, "Select data FROM IndexEntry WHERE id = ");
       
  4664 	
       
  4665 	TInt data = KErrNotFound;		
       
  4666 	RBuf buf;
       
  4667 	CleanupClosePushL(buf);
       
  4668 	buf.CreateL(100);
       
  4669 	buf.Append(KSelectServiceId);
       
  4670 	buf.AppendNum(parentId);
       
  4671 	buf.Append(KDelimiter);
       
  4672 	
       
  4673 	RSqlStatement parentDataQuerystatement;
       
  4674 	CleanupClosePushL(parentDataQuerystatement);
       
  4675 	
       
  4676 	User::LeaveIfError(parentDataQuerystatement.Prepare(iDatabase, buf));
       
  4677 		
       
  4678 	TInt parentIdindex = GetColumnIndexL(parentDataQuerystatement, KMsgColumnData());
       
  4679 		
       
  4680 	while(KSqlAtRow == parentDataQuerystatement.Next())
       
  4681 		{
       
  4682 		data  = ColumnInt(parentDataQuerystatement, parentIdindex);
       
  4683 		}
       
  4684 	CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
       
  4685 	
       
  4686 	return !(data & TMsvEntry::KMsvVisibleFolderNodeFlag);
       
  4687 			
       
  4688 	}
       
  4689 	
       
  4690 /**
       
  4691 GetAllIndexEntryTableIdsL()
       
  4692 Gets all ids present in index entry table.
       
  4693 
       
  4694 @param aIdArray: Array of TMsvId.
       
  4695 @retun None
       
  4696 */
       
  4697 void CMsvDBAdapter::GetRemainingIdsL(RArray<TMsvId>& aIdArray)	
       
  4698 	{
       
  4699 	_LIT(KSelectAllIds, "Select id FROM IndexEntry where visibleParent = -99;");
       
  4700 	
       
  4701 	RSqlStatement queryStmt;
       
  4702 	CleanupClosePushL(queryStmt);
       
  4703 	User::LeaveIfError(queryStmt.Prepare(iDatabase, KSelectAllIds));
       
  4704 	
       
  4705 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
       
  4706 	
       
  4707 	while(KSqlAtRow == queryStmt.Next())
       
  4708 		{
       
  4709 		TMsvId Id = ColumnInt(queryStmt, serviceColumnIndex);
       
  4710 		aIdArray.AppendL(Id);
       
  4711 		}
       
  4712 	CleanupStack::PopAndDestroy(); //queryStmt
       
  4713 	}
       
  4714 
       
  4715 /**
       
  4716 DeleteTable()
       
  4717 Deletes the header table identified by the UID
       
  4718 
       
  4719 @param aMtmId: MTM id.
       
  4720 @retun None
       
  4721 */
       
  4722 void CMsvDBAdapter::DeleteTableL(TUid aMtmId)	
       
  4723 	{
       
  4724 	_LIT16(KDropTableQuery, "DROP table if exists Header_");
       
  4725 	
       
  4726 	RBuf16 buf;
       
  4727 	CleanupClosePushL(buf);
       
  4728 	buf.CreateL(100);
       
  4729 	buf.Append(KDropTableQuery);
       
  4730 	buf.AppendNum(aMtmId.iUid);
       
  4731 	buf.Append(KDelimiter);
       
  4732 	
       
  4733 	TInt err = iDatabase.Exec(buf);
       
  4734 
       
  4735 	CleanupStack::PopAndDestroy(); //buf
       
  4736 	}
       
  4737  
       
  4738  /**
       
  4739 DeleteTable()
       
  4740 Deletes the header table identified by the UID
       
  4741 
       
  4742 @param None
       
  4743 @retun None
       
  4744 */
       
  4745 void CMsvDBAdapter::DeleteSearchSortTable()	
       
  4746 	{
       
  4747 	_LIT16(KDropSearchSortTableQuery, "DROP table if exists SearchSortEntry;");
       
  4748 	
       
  4749 	TInt err = iDatabase.Exec(KDropSearchSortTableQuery);
       
  4750 	}
       
  4751  
       
  4752  
       
  4753 #endif //#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  4754 
       
  4755 
       
  4756