messagingfw/msgsrvnstore/server/src/msvdbadapter.cpp
changeset 22 bde600d88860
child 35 f8ad95794a08
child 40 320ec5cd0227
equal deleted inserted replaced
21:08008ce8a6df 22:bde600d88860
       
     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 	CleanupStack::PushL(cacheEntry);
       
  1243 	aEntry->Entry().iId = aId;
       
  1244 	
       
  1245 	LoadEntryFromStatementL(getStmt, EGetEntry, aVisibleParentEntryId, *aEntry);
       
  1246 	
       
  1247 	//We do not return non-standard visible folders from a non-current drive's database.
       
  1248 	if(driveId != KCurrentDriveId 		&&
       
  1249 	   aEntry->Entry().Visible() 		&&
       
  1250 	   !IsStandardId(aEntry->GetId()) 	&&
       
  1251 	   KUidMsvFolderEntryValue == aEntry->Entry().iType.iUid
       
  1252 	  )
       
  1253 		{
       
  1254 		CMsvEntryFreePool::Instance()->ReleaseEntry(aEntry);
       
  1255 		User::Leave(KErrNotFound);
       
  1256 		}
       
  1257 	
       
  1258 	// Unmask iId's of standard Ids.
       
  1259 	if(IsStandardId(aEntry->GetId()))
       
  1260 		{
       
  1261 		aEntry->Entry().SetId(UnmaskTMsvId(aEntry->GetId()));
       
  1262 		}
       
  1263 	
       
  1264 	// Mask iParentId if it is a non-standard id.
       
  1265 	if(!IsStandardId(aEntry->Entry().iParentId))
       
  1266 		{
       
  1267 		aEntry->Entry().iParentId = MaskTMsvId(driveId, aEntry->Entry().iParentId);
       
  1268 		}
       
  1269 	
       
  1270 	// Mask visible folder if it is a non-standard id.
       
  1271 	if(!IsStandardId(aVisibleParentEntryId))
       
  1272 		{
       
  1273 		aVisibleParentEntryId = MaskTMsvId(driveId, aVisibleParentEntryId);
       
  1274 		}
       
  1275 	
       
  1276 	// Mask iServiceId if it is a non-standard id.
       
  1277 	if(!IsStandardId(aEntry->Entry().iServiceId))
       
  1278 		{
       
  1279 		aEntry->Entry().iServiceId = MaskTMsvId(driveId, aEntry->Entry().iServiceId);
       
  1280 		}
       
  1281 	
       
  1282 	// Mask iRelatedId if it is a non-standard id.
       
  1283 	if(!IsStandardId(aEntry->Entry().iRelatedId))
       
  1284 		{
       
  1285 		aEntry->Entry().iRelatedId = MaskTMsvId(driveId, aEntry->Entry().iRelatedId);
       
  1286 		}
       
  1287 
       
  1288 	CleanupStack::Pop(cacheEntry);
       
  1289 	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
       
  1290 	}
       
  1291 
       
  1292 
       
  1293 
       
  1294 
       
  1295 /**
       
  1296  * GetChildrenL()
       
  1297  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  1298  * @param RPointerArray<TMsvEntry>&: List of child entries to be filled.
       
  1299  * @return None.
       
  1300  *
       
  1301  * Fetch child entries from the database for a given parent Id.
       
  1302  * This does not check if the parent entry already exist. The 
       
  1303  * entries will be added in ascending order of their TMsvId.
       
  1304  */
       
  1305 void CMsvDBAdapter::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  1306 	{
       
  1307 	_LIT8(KGetChildEntriesQuery1, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
       
  1308 							"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
  1309 							"reserved, visibleParent, description, details FROM DB");
       
  1310 	_LIT8(KGetChildEntriesQuery2, ".IndexEntry WHERE parentId = ");
       
  1311 	_LIT8(KGetChildEntriesQuery3, " order by id ASC;");
       
  1312 	
       
  1313 	//Get the driveId and unmask the TMsvId supplied.
       
  1314 	TInt driveId = GetDriveId(aParentId);
       
  1315 	aParentId = UnmaskTMsvId(aParentId);
       
  1316 	
       
  1317 	//Construct the query for the particular drive.
       
  1318 	RBuf8 queryBuf;
       
  1319 	CleanupClosePushL(queryBuf);
       
  1320 	queryBuf.CreateL(350);	
       
  1321 	queryBuf.Append(KGetChildEntriesQuery1);
       
  1322 	queryBuf.AppendNum(driveId);
       
  1323 	queryBuf.Append(KGetChildEntriesQuery2);
       
  1324 	queryBuf.AppendNum(aParentId);
       
  1325 	queryBuf.Append(KGetChildEntriesQuery3);
       
  1326 	
       
  1327 	//Prepare a statement for the query.
       
  1328 	RSqlStatement getStmt;
       
  1329 	CleanupClosePushL(getStmt);
       
  1330 	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
       
  1331 	
       
  1332 	while(KSqlAtRow == getStmt.Next())
       
  1333 		{
       
  1334 		// Do not return non-standard visible folders from non-current drive.
       
  1335 			// If it is a non-current drive...
       
  1336 		if( (driveId != KCurrentDriveId) 										     	  &&
       
  1337 			// If it is a folder entry.
       
  1338 		    (KUidMsvFolderEntryValue == ColumnInt(getStmt, iTypeIndex[EGetChildEntries])) &&
       
  1339 		    // If it is a visible folder.
       
  1340 			(IsVisibleFolder(ColumnInt(getStmt, iDataIndex[EGetChildEntries])))		      &&
       
  1341 			// If it is a non-standard folder.
       
  1342 			(!IsStandardId(ColumnInt(getStmt, iIdIndex[EGetChildEntries])))
       
  1343 		  )		  		
       
  1344 			{
       
  1345 			continue;
       
  1346 			}
       
  1347 			
       
  1348 		TMsvId aVisibleParentEntryId;
       
  1349 		CMsvCacheEntry *cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  1350 		CleanupStack::PushL(cacheEntry);
       
  1351 		if(!IsStandardId(aParentId))
       
  1352 			{
       
  1353 			aParentId = MaskTMsvId(driveId, aParentId);
       
  1354 			}
       
  1355 		cacheEntry->Entry().iParentId = aParentId;
       
  1356 		LoadEntryFromStatementL(getStmt, EGetChildEntries, aVisibleParentEntryId, *cacheEntry);
       
  1357 		
       
  1358 		//Add the drive mask to the TMsvId.
       
  1359 		if(!IsStandardId(cacheEntry->GetId()))
       
  1360 			{
       
  1361 			cacheEntry->Entry().iId = MaskTMsvId(driveId, cacheEntry->Entry().iId);
       
  1362 			}
       
  1363 		
       
  1364 		// Mask iServiceId if it is a non-standard id.
       
  1365 		if(!IsStandardId(cacheEntry->Entry().iServiceId))
       
  1366 			{
       
  1367 			cacheEntry->Entry().iServiceId = MaskTMsvId(driveId, cacheEntry->Entry().iServiceId);
       
  1368 			}
       
  1369 		
       
  1370 		// Mask iRelatedId if it is a non-standard id.
       
  1371 		if(!IsStandardId(cacheEntry->Entry().iRelatedId))
       
  1372 			{
       
  1373 			cacheEntry->Entry().iRelatedId = MaskTMsvId(driveId, cacheEntry->Entry().iRelatedId);
       
  1374 			}
       
  1375 	
       
  1376 		//Add the child entry to the array given
       
  1377 		aChildArray.AppendL(cacheEntry);
       
  1378 		CleanupStack::Pop(cacheEntry);
       
  1379 		}
       
  1380 	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
       
  1381 	}
       
  1382 
       
  1383 
       
  1384 
       
  1385 
       
  1386 /**
       
  1387  * GetChildrenIdL()
       
  1388  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  1389  * @param CMsvEntrySelection&: List of child entry Id's.
       
  1390  * @return None.
       
  1391  *
       
  1392  * Fetch child entry Id's from the database for a given parent Id.
       
  1393  * This does not check if the parent entry already exist. The 
       
  1394  * entries will be added in ascending order of their TMsvId.
       
  1395  */
       
  1396 void CMsvDBAdapter::GetChildrenIdL(TMsvId aParentId, CMsvEntrySelection& aChildArray)
       
  1397 	{
       
  1398 	_LIT8(KGetChildIdsQuery1, "SELECT id, type, data FROM DB");
       
  1399 	_LIT8(KGetChildIdsQuery2, ".IndexEntry WHERE parentId = ");
       
  1400 	_LIT8(KGetChildIdsQuery3, " order by id ASC;");
       
  1401 	
       
  1402 	//Get the driveId and unmask the TMsvId supplied.
       
  1403 	TInt driveId = GetDriveId(aParentId);
       
  1404 	aParentId = UnmaskTMsvId(aParentId);
       
  1405 	
       
  1406 	//Construct the query for the particular drive.
       
  1407 	RBuf8 queryBuf;
       
  1408 	CleanupClosePushL(queryBuf);
       
  1409 	queryBuf.CreateL(100);	
       
  1410 	queryBuf.Append(KGetChildIdsQuery1);
       
  1411 	queryBuf.AppendNum(driveId);
       
  1412 	queryBuf.Append(KGetChildIdsQuery2);
       
  1413 	queryBuf.AppendNum(aParentId);
       
  1414 	queryBuf.Append(KGetChildIdsQuery3);
       
  1415 	
       
  1416 	//Prepare a statement for the query.
       
  1417 	RSqlStatement getStmt;
       
  1418 	CleanupClosePushL(getStmt);
       
  1419 	User::LeaveIfError(getStmt.Prepare(iDatabase, queryBuf));
       
  1420 	
       
  1421 	while(KSqlAtRow == getStmt.Next())
       
  1422 		{
       
  1423 		// Do not return non-standard visible folders from non-current drive.
       
  1424 			// If it is a non-current drive...
       
  1425 		if( (driveId != KCurrentDriveId) 					 				     	  &&
       
  1426 			// If it is a folder entry.
       
  1427 		    (KUidMsvFolderEntryValue == ColumnInt(getStmt, iTypeIndex[EGetChildIds])) &&
       
  1428 		    // If it is a visible folder.
       
  1429 			(IsVisibleFolder(ColumnInt(getStmt, iDataIndex[EGetChildIds])))		      &&
       
  1430 			// If it is a non-standard folder.
       
  1431 			(!IsStandardId(ColumnInt(getStmt, iIdIndex[EGetChildIds])))
       
  1432 		  )		  		
       
  1433 			{
       
  1434 			continue;
       
  1435 			}
       
  1436 		
       
  1437 		TMsvId id = ColumnInt(getStmt, iIdIndex[EGetChildIds]);
       
  1438 		if(!IsStandardId(id))
       
  1439 			{
       
  1440 			id = MaskTMsvId(driveId, id);
       
  1441 			}
       
  1442 		//Add the child Id to the array given
       
  1443 		aChildArray.AppendL(id);
       
  1444 		}
       
  1445 	
       
  1446 	CleanupStack::PopAndDestroy(2); //getStmt, queryBuf
       
  1447 	}
       
  1448 
       
  1449 
       
  1450 
       
  1451 
       
  1452 /**
       
  1453  * GetChildrenL()
       
  1454 * @param const TDesC&: Partial query string. (Where clause condition).
       
  1455  *               The query string should start with 'AND' and should 
       
  1456  *               end with a semicolon. Examples are:
       
  1457  *               "AND ID BETWEEN 100 and 200 ORDER BY ID ASC;"
       
  1458  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  1459  * @param RPointerArray<TMsvEntry>&: List of child entries to be filled.
       
  1460  * @return None.
       
  1461  *
       
  1462  * Fetch child entries from the database for a given parent Id.
       
  1463  * This does not check if the parent entry already exist. The 
       
  1464  * entries will be added in ascending order of their TMsvId.
       
  1465  */
       
  1466 void CMsvDBAdapter::GetChildrenL(const TDesC8& aQueryStr, TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  1467 	{
       
  1468 	_LIT8(KQueryString1, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
       
  1469 			"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
  1470 			"reserved, visibleParent, description, details FROM DB");
       
  1471 	_LIT8(KQueryString2, ".IndexEntry WHERE parentId = ");
       
  1472 
       
  1473 	//Get the driveId and unmask the TMsvId supplied.
       
  1474 	TInt driveId = GetDriveId(aParentId);
       
  1475 	aParentId = UnmaskTMsvId(aParentId);
       
  1476 	
       
  1477 	//Construct a query for the particular drive.
       
  1478 	TInt len = KQueryString1().Length() + KQueryString2().Length() + aQueryStr.Length();
       
  1479 	len += 30;
       
  1480 	RBuf8 queryBuf;
       
  1481 	CleanupClosePushL(queryBuf);
       
  1482 	queryBuf.CreateL(len);	
       
  1483 	queryBuf.Append(KQueryString1);
       
  1484 	queryBuf.AppendNum(driveId);
       
  1485 	queryBuf.Append(KQueryString2);
       
  1486 	queryBuf.AppendNum(aParentId);
       
  1487 	queryBuf.Append(aQueryStr);
       
  1488 	
       
  1489 	//Prepare a statement for the query.
       
  1490 	RSqlStatement condGetChildrenStmnt;
       
  1491 	CleanupClosePushL(condGetChildrenStmnt);
       
  1492 	
       
  1493 	User::LeaveIfError(condGetChildrenStmnt.Prepare(iDatabase, queryBuf));
       
  1494 	TInt index = 0;
       
  1495 
       
  1496 	while(KSqlAtRow == condGetChildrenStmnt.Next())
       
  1497 		{
       
  1498 		TInt type = ColumnInt(condGetChildrenStmnt, 3);
       
  1499 		TInt32 data = ColumnInt(condGetChildrenStmnt, 5);
       
  1500 
       
  1501 		// Do not return non-standard visible folders from non-current drive.
       
  1502 			// If it is a non-current drive...
       
  1503 		if( (driveId != KCurrentDriveId) 	  &&
       
  1504 			// If it is a folder entry.
       
  1505 		    (KUidMsvFolderEntryValue == type) &&
       
  1506 		    // If it is a visible folder.
       
  1507 			(IsVisibleFolder(data))		      &&
       
  1508 			// If it is a non-standard folder.
       
  1509 			(!IsStandardId(ColumnInt(condGetChildrenStmnt, 0)))
       
  1510 		  )
       
  1511 		  	{
       
  1512 			continue;
       
  1513 			}
       
  1514 		
       
  1515 		CMsvCacheEntry* cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  1516 		CleanupStack::PushL(cacheEntry);
       
  1517 		if(!IsStandardId(aParentId))
       
  1518 			{
       
  1519 			aParentId = MaskTMsvId(driveId, aParentId);
       
  1520 			}
       
  1521 		cacheEntry->Entry().iParentId = aParentId;
       
  1522 
       
  1523 		index = 0;
       
  1524 		TMsvId id = ColumnInt(condGetChildrenStmnt, index);
       
  1525 		if(IsStandardId(id))
       
  1526 			{
       
  1527 			cacheEntry->Entry().iId = id;
       
  1528 			}
       
  1529 		else
       
  1530 			{
       
  1531 			cacheEntry->Entry().iId = MaskTMsvId(driveId, id);
       
  1532 			}		
       
  1533 		cacheEntry->Entry().iServiceId = ColumnInt(condGetChildrenStmnt, ++index);
       
  1534 		cacheEntry->Entry().iMtm.iUid = ColumnInt(condGetChildrenStmnt, ++index);
       
  1535 		cacheEntry->Entry().iType.iUid = type;
       
  1536 		cacheEntry->Entry().iDate = ColumnInt64(condGetChildrenStmnt, ++index);
       
  1537 		cacheEntry->Entry().iData = data;
       
  1538 		cacheEntry->Entry().iSize = ColumnInt(condGetChildrenStmnt, ++index);
       
  1539 		cacheEntry->Entry().iError = ColumnInt(condGetChildrenStmnt, ++index);
       
  1540 		cacheEntry->Entry().iMtmData1 = ColumnInt(condGetChildrenStmnt, ++index);
       
  1541 		cacheEntry->Entry().iMtmData2 = ColumnInt(condGetChildrenStmnt, ++index);
       
  1542 		cacheEntry->Entry().iMtmData3 = ColumnInt(condGetChildrenStmnt, ++index);
       
  1543 		cacheEntry->Entry().iRelatedId = ColumnInt(condGetChildrenStmnt, ++index);
       
  1544 		cacheEntry->Entry().iBioType = ColumnInt(condGetChildrenStmnt, ++index);
       
  1545 		cacheEntry->Entry().iPcSyncCount = ColumnInt(condGetChildrenStmnt, ++index);
       
  1546 		cacheEntry->Entry().iReserved = ColumnInt(condGetChildrenStmnt, ++index);
       
  1547 		TMsvId aVisibleParentEntryId = ColumnInt(condGetChildrenStmnt, ++index);
       
  1548 		
       
  1549 		cacheEntry->iDescriptionBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  1550 		cacheEntry->Entry().iDescription.Set(*cacheEntry->iDescriptionBuffer);
       
  1551 		
       
  1552 		cacheEntry->iDetailsBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  1553 		cacheEntry->Entry().iDetails.Set(*cacheEntry->iDetailsBuffer);
       
  1554 		
       
  1555 		
       
  1556 		// Mask iServiceId if it is a non-standard id.
       
  1557 		if(!IsStandardId(cacheEntry->Entry().iServiceId))
       
  1558 			{
       
  1559 			cacheEntry->Entry().iServiceId = MaskTMsvId(driveId, cacheEntry->Entry().iServiceId);
       
  1560 			}
       
  1561 		
       
  1562 		// Mask iRelatedId if it is a non-standard id.
       
  1563 		if(!IsStandardId(cacheEntry->Entry().iRelatedId))
       
  1564 			{
       
  1565 			cacheEntry->Entry().iRelatedId = MaskTMsvId(driveId, cacheEntry->Entry().iRelatedId);
       
  1566 			}
       
  1567 		
       
  1568 		//Add the child entry to the array given
       
  1569 		aChildArray.AppendL(cacheEntry);
       
  1570 		CleanupStack::Pop(cacheEntry);
       
  1571 		}
       
  1572 	CleanupStack::PopAndDestroy(2);		// condGetChildrenStmnt,queryBuf
       
  1573 	}
       
  1574 
       
  1575 
       
  1576 
       
  1577 
       
  1578 /**
       
  1579  * EntryExistsL()
       
  1580  * @param TMsvId: Entry Id to check.
       
  1581  * @return TBool: ETrue if the entry exists, otherwise EFalse.
       
  1582  *
       
  1583  * Checks if an entry with the specified TMsvId exists in the database.
       
  1584  */
       
  1585 TBool CMsvDBAdapter::EntryExistsL(TMsvId aId)
       
  1586 	{
       
  1587 	_LIT8(KEntryExistsQuery1, "SELECT id FROM DB");
       
  1588 	_LIT8(KEntryExistsQuery2, ".IndexEntry WHERE id = ");
       
  1589 		
       
  1590 	//Get the driveId and unmask the TMsvId supplied.
       
  1591 	TInt driveId = GetDriveId(aId);
       
  1592 	aId = UnmaskTMsvId(aId);
       
  1593 	
       
  1594 	//Construct a query for the particular drive.
       
  1595 	RBuf8 queryBuf;
       
  1596 	CleanupClosePushL(queryBuf);
       
  1597 	TInt len = KEntryExistsQuery1().Length() + 10 + KEntryExistsQuery2().Length(); //10 = space for TMsvId
       
  1598 	queryBuf.CreateL(len);	
       
  1599 	queryBuf.Append(KEntryExistsQuery1);
       
  1600 	queryBuf.AppendNum(driveId);
       
  1601 	queryBuf.Append(KEntryExistsQuery2);
       
  1602 	queryBuf.AppendNum(aId);
       
  1603 	queryBuf.Append(KDelimiter);
       
  1604 	
       
  1605 	TSqlScalarFullSelectQuery query(iDatabase);
       
  1606 	TMsvId id = NULL;
       
  1607 	TRAPD(err, id = query.SelectIntL(queryBuf));
       
  1608 	
       
  1609 	CleanupStack::PopAndDestroy(); //queryBuf
       
  1610 	if(err!= KErrNone && err!= KErrNotFound)
       
  1611 		{
       
  1612 		User::Leave(err);
       
  1613 		}
       
  1614 	if(id)
       
  1615 		{
       
  1616 		return ETrue;
       
  1617 		}
       
  1618 	else
       
  1619 		{
       
  1620 		return EFalse;
       
  1621 		}
       
  1622 	}
       
  1623 
       
  1624 
       
  1625 
       
  1626 	
       
  1627 /**
       
  1628  * GetInPreparationIdL()
       
  1629  * @param CMsvEntrySelection&: List of the TMsvEntries 
       
  1630  * 		                       whose KMsvEntryInPreparationFlag is set.
       
  1631  * @return None.
       
  1632  *
       
  1633  * Gets the TMsvId's of all the entries whose KMsvEntryInPreparationFlag
       
  1634  * is set in the database.
       
  1635  */
       
  1636 void CMsvDBAdapter::GetInPreparationIdL(CMsvEntrySelection& aSelection, TUint aDriveId /* DEFAULT = 0 */)
       
  1637 	{
       
  1638 	if(aDriveId)
       
  1639 		{
       
  1640 		DoGetInPreparationIdL(aSelection, aDriveId);
       
  1641 		}
       
  1642 	else
       
  1643 		{
       
  1644 		//Iterate through all the dives that might have a database.
       
  1645 		for(TInt driveId = 1; driveId < KMaxNumberOfDrives; ++driveId)
       
  1646 			{
       
  1647 			DoGetInPreparationIdL(aSelection, driveId);		
       
  1648 			}
       
  1649 		}	
       
  1650 	}
       
  1651 
       
  1652 
       
  1653 
       
  1654 
       
  1655 void CMsvDBAdapter::DoGetInPreparationIdL(CMsvEntrySelection& aSelection, TUint aDriveId)
       
  1656 	{
       
  1657 	_LIT8(KGetInPreparationIdQuery1, "SELECT id, data FROM DB");
       
  1658 	_LIT8(KGetInPreparationIdQuery2, ".IndexEntry;");
       
  1659 	
       
  1660 	TInt paramIdColumn = 0;
       
  1661 	TInt paramDataColumn = 1;
       
  1662 			
       
  1663 	//Check if the drive has the database present.
       
  1664 	//The iDatabasePresent array will have a value for only those driveIds which
       
  1665 	//have been added through AttachDBL().
       
  1666 	if((*iDatabasePresent)[aDriveId])
       
  1667 		{
       
  1668 		RBuf8 queryBuf;
       
  1669 		CleanupClosePushL(queryBuf);
       
  1670 		queryBuf.CreateL(40);		
       
  1671 		queryBuf.Append(KGetInPreparationIdQuery1);
       
  1672 		queryBuf.AppendNum(aDriveId);
       
  1673 		queryBuf.Append(KGetInPreparationIdQuery2);
       
  1674 		
       
  1675 		RSqlStatement statement;
       
  1676 		CleanupClosePushL(statement);
       
  1677 		User::LeaveIfError(statement.Prepare(iDatabase, queryBuf));
       
  1678 		
       
  1679 		TMsvId id;
       
  1680 		TInt32 data;
       
  1681 		while (KSqlAtRow == statement.Next())
       
  1682 			{
       
  1683 			data = ColumnInt(statement, paramDataColumn);
       
  1684 			if( data & TMsvEntry::KMsvEntryInPreparationFlag )
       
  1685 				{
       
  1686 				id = ColumnInt(statement, paramIdColumn);
       
  1687 				if(!IsStandardId(id))
       
  1688 					{
       
  1689 					id = MaskTMsvId(aDriveId, id);
       
  1690 					}
       
  1691 				aSelection.AppendL(id);
       
  1692 				}
       
  1693 			}
       
  1694 		CleanupStack::PopAndDestroy(2); //statement, queryBuf
       
  1695 		}
       
  1696 	}
       
  1697 
       
  1698 	
       
  1699 	
       
  1700 
       
  1701 /**
       
  1702  * GetVisibleFlagL()
       
  1703  * @param TMsvId: the Id of the entry whose flag is to be checked.
       
  1704  * @return TBool: ETrue if the entry is visible, EFalse otherwise.
       
  1705  *
       
  1706  * Returns the status of the visible flag of an entry in the DB.
       
  1707  */
       
  1708 TBool CMsvDBAdapter::GetVisibleFlagL(TMsvId aEntryId)
       
  1709 	{
       
  1710 	_LIT8(KGetVisibleFlagQuery1, "SELECT data FROM DB");
       
  1711 	_LIT8(KGetVisibleFlagQuery2, ".IndexEntry WHERE id = ");
       
  1712 	
       
  1713 	//Get the driveId and unmask the TMsvId supplied.
       
  1714 	TInt driveId = GetDriveId(aEntryId);
       
  1715 	aEntryId = UnmaskTMsvId(aEntryId);
       
  1716 	
       
  1717 	RBuf8 queryBuf;
       
  1718 	CleanupClosePushL(queryBuf);
       
  1719 	queryBuf.CreateL(60);	
       
  1720 	queryBuf.Append(KGetVisibleFlagQuery1);
       
  1721 	queryBuf.AppendNum(driveId);
       
  1722 	queryBuf.Append(KGetVisibleFlagQuery2);
       
  1723 	queryBuf.AppendNum(aEntryId);
       
  1724 	queryBuf.Append(KDelimiter);
       
  1725 	
       
  1726 	TSqlScalarFullSelectQuery query(iDatabase);
       
  1727 	TInt32 data = query.SelectIntL(queryBuf);
       
  1728 	CleanupStack::PopAndDestroy();		// queryBuf
       
  1729 	if(data & TMsvEntry::KMsvEntryInvisibleFlag )
       
  1730 		{
       
  1731 		return EFalse;
       
  1732 		}
       
  1733 	else
       
  1734 		{
       
  1735 		return ETrue;
       
  1736 		}
       
  1737 	}
       
  1738 
       
  1739 
       
  1740 
       
  1741 
       
  1742 /**
       
  1743  * UpdateVisibleFolderL()
       
  1744  * @param CMsvEntrySelection*: List of entries whose visible parent is
       
  1745  *							   to be updated.
       
  1746  * @param TMsvId: The new visible folder Id.
       
  1747  * @return None.
       
  1748  *
       
  1749  * Updates the visible parent of the entries passed through the selection.
       
  1750  */
       
  1751  void CMsvDBAdapter::UpdateVisibleFolderL(CMsvEntrySelection* aEntryList, TMsvId aNewVisibleFolderId)
       
  1752  	{
       
  1753  	_LIT8(KUpdateVisibleFolderQuery1,	"UPDATE DB");
       
  1754  	_LIT8(KUpdateVisibleFolderQuery2, ".IndexEntry SET visibleParent = ");
       
  1755 	_LIT8(KUpdateVisibleFolderQuery3,	" WHERE id IN ( ");
       
  1756 	_LIT8(KEndDelimiter, ");");
       
  1757 	
       
  1758 	TInt count = aEntryList->Count();
       
  1759 	if(0 == count)
       
  1760 		{
       
  1761 		return;
       
  1762 		}
       
  1763 	
       
  1764 	//Get the driveId and unmask the TMsvId supplied.
       
  1765 	aNewVisibleFolderId = UnmaskTMsvId(aNewVisibleFolderId);
       
  1766 	CMsvEntrySelection* list = aEntryList->CopyL();
       
  1767 	CleanupStack::PushL(list);
       
  1768 	
       
  1769 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  1770 	TInt maxEntries = 50; //for testing
       
  1771 #else
       
  1772 	TInt maxEntries = 100;
       
  1773 #endif
       
  1774 	
       
  1775 	BeginTransactionL();
       
  1776 	for(TInt index1 = 0; index1<count; ++index1)
       
  1777 		{
       
  1778 		TInt driveId = GetDriveId(list->At(index1));
       
  1779 		
       
  1780 		RBuf8 queryBuf;
       
  1781 		CleanupClosePushL(queryBuf);
       
  1782 		queryBuf.CreateL(50 + ((10+2)*maxEntries));		
       
  1783 		queryBuf.Append(KUpdateVisibleFolderQuery1);
       
  1784 		queryBuf.AppendNum(driveId);
       
  1785 		queryBuf.Append(KUpdateVisibleFolderQuery2);
       
  1786 		queryBuf.AppendNum(aNewVisibleFolderId);
       
  1787 		queryBuf.Append(KUpdateVisibleFolderQuery3);
       
  1788 		queryBuf.AppendNum(UnmaskTMsvId(list->At(index1)));
       
  1789 		TInt num = 1;
       
  1790 		for(TInt index2 = index1 + 1; index2<count && num<maxEntries; ++index2)
       
  1791 			{
       
  1792 			if(driveId == GetDriveId(list->At(index2)))
       
  1793 				{
       
  1794 				queryBuf.Append(KComma);
       
  1795 				queryBuf.AppendNum(UnmaskTMsvId(list->At(index2)));
       
  1796 				++num;
       
  1797 				list->Delete(index2);
       
  1798 				--index2;
       
  1799 				--count;
       
  1800 				}
       
  1801 			}
       
  1802 		list->Delete(index1);
       
  1803 		--index1;
       
  1804 		--count;
       
  1805 		queryBuf.Append(KEndDelimiter);
       
  1806 		TInt err = iDatabase.Exec(queryBuf);
       
  1807 		CleanupStack::PopAndDestroy(); //queryBuf
       
  1808 		if(err < 0)
       
  1809 			{
       
  1810 			User::Leave(err);
       
  1811 			}
       
  1812 		}
       
  1813 	
       
  1814 	CommitTransactionL();
       
  1815 	CleanupStack::PopAndDestroy(); //list
       
  1816 	}
       
  1817 
       
  1818 
       
  1819 
       
  1820 
       
  1821 /**
       
  1822  * UpdateOwnerStatusL()
       
  1823  *
       
  1824  * @param TMsvId: the Id of an entry which has had a child added
       
  1825  *				   under it and needs its owner flag updated.
       
  1826  * @param const TMsvEntry&: the parent entry.
       
  1827  * @param TBool: ETrue if the owner flag should be set, EFalse if otherwise.
       
  1828  * @return None.
       
  1829  *
       
  1830  * The function updates the owner flag of an entry which has had a
       
  1831  * child added or deleted under it.
       
  1832  */
       
  1833 void CMsvDBAdapter::UpdateOwnerStatusL(TMsvId aId, const TMsvEntry& aParent, TBool aSet)
       
  1834 	{
       
  1835 	_LIT8(KUpdateOwnershipQuery1,	"UPDATE DB");
       
  1836 	_LIT8(KUpdateOwnershipQuery2, ".IndexEntry SET data = ");
       
  1837 	_LIT8(KUpdateOwnershipQuery3,	" WHERE id = ");
       
  1838 	
       
  1839 	// Owner flag has already been set. Return to caller.
       
  1840 	if(aParent.Owner() && aSet)
       
  1841 		{
       
  1842 		return;
       
  1843 		}
       
  1844 	// Otherwise update the owner flag for the entry in the DB.
       
  1845 	else
       
  1846 		{
       
  1847 		//Get the driveId and unmask the TMsvId supplied.
       
  1848 		TInt driveId = GetDriveId(aId);
       
  1849 		TMsvId parentId = UnmaskTMsvId(aId);
       
  1850 		
       
  1851 		TInt32 data;
       
  1852 		if(aSet)
       
  1853 			{
       
  1854 			data = aParent.iData | TMsvEntry::KMsvEntryOwnerFlag;
       
  1855 			}
       
  1856 		else
       
  1857 			{
       
  1858 			data = aParent.iData & ~(TMsvEntry::KMsvEntryOwnerFlag);
       
  1859 			}
       
  1860 		TInt len = KUpdateOwnershipQuery1().Length() + KUpdateOwnershipQuery2().Length();
       
  1861 		len += KUpdateOwnershipQuery3().Length() + 100; //data and TMsvId.
       
  1862 		RBuf8 queryBuf;
       
  1863 		CleanupClosePushL(queryBuf);
       
  1864 		queryBuf.CreateL(len);		
       
  1865 		queryBuf.Append(KUpdateOwnershipQuery1);
       
  1866 		queryBuf.AppendNum(driveId);
       
  1867 		queryBuf.Append(KUpdateOwnershipQuery2);
       
  1868 		queryBuf.AppendNum(data);
       
  1869 		queryBuf.Append(KUpdateOwnershipQuery3);
       
  1870 		queryBuf.AppendNum(parentId);
       
  1871 		queryBuf.Append(KDelimiter);
       
  1872 		TInt err = iDatabase.Exec(queryBuf);
       
  1873 		if(err < 0)
       
  1874 			{
       
  1875 			User::Leave(err);
       
  1876 			}
       
  1877 		CleanupStack::PopAndDestroy(); //queryBuf
       
  1878 		}
       
  1879 	}
       
  1880 
       
  1881 
       
  1882 
       
  1883 
       
  1884 #else		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  1885 
       
  1886 
       
  1887 
       
  1888 
       
  1889 /**
       
  1890  * NewL()
       
  1891  * @param TFileName: DB File Name.
       
  1892  * @return The newly created database adapter object.
       
  1893  *
       
  1894  * The function creates a new secure database in syslib private folder.
       
  1895  * It takes database name as input arg and returns instance of 
       
  1896  * DB adpater class.
       
  1897  */
       
  1898 CMsvDBAdapter* CMsvDBAdapter::NewL(const TFileName& aDbFileName)
       
  1899 	{
       
  1900 	//Create an messaging DB adaptor object.
       
  1901 	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
       
  1902 	CleanupStack::PushL(self);
       
  1903 	
       
  1904 	// Create the database.
       
  1905 	TBool isDBCreated = EFalse;
       
  1906 	TRAPD(err, self->ConstructNewL(aDbFileName, isDBCreated));
       
  1907 	if( KErrNone != err )
       
  1908 		{
       
  1909 		if( isDBCreated )
       
  1910 			{
       
  1911 			DeleteDB(aDbFileName);
       
  1912 			}
       
  1913 		User::Leave(err);
       
  1914 		}
       
  1915 
       
  1916 	CleanupStack::Pop(self);
       
  1917 	return self;
       
  1918 	}
       
  1919 
       
  1920 
       
  1921 
       
  1922 
       
  1923 /**
       
  1924  * OpenL()
       
  1925  * @param TFileName: DB File Name.
       
  1926  * @return The newly created database adapter object.
       
  1927  *
       
  1928  * The function opens an already existing database. The database file
       
  1929  * is searched in syslib private folder. It takes database name as 
       
  1930  * input arg and returns instance of DB adpater class. The function
       
  1931  * leaves if the DB file is not found or if the file is corrupted.
       
  1932  */
       
  1933 CMsvDBAdapter* CMsvDBAdapter::OpenL(const TFileName& aDbFileName)
       
  1934 	{
       
  1935 	//Create an messaging DB adaptor object 
       
  1936 	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
       
  1937 	CleanupStack::PushL(self);
       
  1938 	
       
  1939 	// Open the database.
       
  1940 	self->ConstructOpenL(aDbFileName);
       
  1941 	
       
  1942 	CleanupStack::Pop(self);
       
  1943 	return self;
       
  1944 	}
       
  1945 
       
  1946 
       
  1947 
       
  1948 
       
  1949 /**
       
  1950  * DeleteDB()
       
  1951  * @param TFileName: DB File Name.
       
  1952  * @return error.
       
  1953  *
       
  1954  * This is a static function, hence can be called without creating
       
  1955  * an instance of this class. The function deletes the database
       
  1956  * file as mentioned in the input argument. The database file is
       
  1957  * searched in syslib private folder. 
       
  1958  */
       
  1959 TInt CMsvDBAdapter::DeleteDB(const TFileName& aDbFileName)
       
  1960 	{
       
  1961 	return RSqlDatabase::Delete(aDbFileName);
       
  1962 	}
       
  1963 
       
  1964 
       
  1965 
       
  1966 
       
  1967 /**
       
  1968  * ConstructOpenL()
       
  1969  * @param TFileName: DB File Name.
       
  1970  * 
       
  1971  * This functions is called by OpenL() to open an existing database.
       
  1972  * The function leaves if there is an error while opening the DB with
       
  1973  * the leave code same as error code. It takes DB filename as input 
       
  1974  * argument. The database file is searched in syslib private folder. 
       
  1975  */
       
  1976 void CMsvDBAdapter::ConstructOpenL(const TFileName& aDbFileName)
       
  1977 	{
       
  1978 	// >>> Pass configuration parameter, while opening the DB.
       
  1979 	User::LeaveIfError(iDatabase.Open(aDbFileName));
       
  1980 	ClearDBContentsL();
       
  1981 	ConstructSortTableL();
       
  1982 	
       
  1983 	//Initialize the database adapter class
       
  1984 	InitializeL();
       
  1985 
       
  1986 	//Initialize the Search Sort database adapter class
       
  1987 	InitializeSortTableL();
       
  1988 	}
       
  1989 
       
  1990 
       
  1991 
       
  1992 
       
  1993 /**
       
  1994  * ConstructNewL()
       
  1995  * @param TFileName: DB File Name.
       
  1996  * 
       
  1997  * This functions is called by NewL() to create a new database.
       
  1998  * The function leaves if there is an error while creating the DB with
       
  1999  * the leave code same as error code. It takes DB filename as input 
       
  2000  * argument. The database file is created in syslib private folder. 
       
  2001  * It then create standard tables as well as indexes in the database.
       
  2002  */
       
  2003 void CMsvDBAdapter::ConstructNewL(const TFileName& aDbFileName, TBool& aIsDBCreated)
       
  2004 	{
       
  2005 	HBufC8* heapBuf = KEncodingText().AllocLC();
       
  2006 
       
  2007 	//Create the database.
       
  2008 #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  2009 	User::LeaveIfError(iDatabase.Create(aDbFileName, heapBuf));
       
  2010 #else	
       
  2011 	// Using SID based security policy.
       
  2012 	TSecureId sid(SERVER_UID);
       
  2013 	const TSecurityPolicy KDefaultPolicy(sid);
       
  2014 	
       
  2015 	//Create security policy
       
  2016 	RSqlSecurityPolicy securityPolicy;
       
  2017 	CleanupClosePushL(securityPolicy);	
       
  2018 		
       
  2019 	User::LeaveIfError(securityPolicy.Create(KDefaultPolicy));
       
  2020 	User::LeaveIfError(iDatabase.Create(aDbFileName, securityPolicy, heapBuf));
       
  2021 	
       
  2022 	// Destroy securityPolicy.
       
  2023 	CleanupStack::PopAndDestroy();		
       
  2024 #endif		// #if (defined SYMBIAN_MESSAGESTORE_UNIT_TESTCODE)
       
  2025 
       
  2026 	// Destroy heapBuf
       
  2027 	CleanupStack::PopAndDestroy();
       
  2028 	aIsDBCreated = ETrue;
       
  2029 
       
  2030 	//Create tables for the database
       
  2031 	TInt err = iDatabase.Exec(KCreateIndexEntryTableQuery);
       
  2032 	if(err < 0)
       
  2033 		{
       
  2034 		User::Leave(err);
       
  2035 		}
       
  2036 	else if(!err)
       
  2037 		{
       
  2038 		User::Leave(KErrGeneral);
       
  2039 		}
       
  2040 		
       
  2041 	//Create index on indexEnty table.
       
  2042 	//Index is created on parentId.
       
  2043 	err = iDatabase.Exec(KCreateIndexQuery);
       
  2044 	if(err < 0)
       
  2045 		{
       
  2046 		User::Leave(err);
       
  2047 		}
       
  2048 	else if(!err)
       
  2049 		{
       
  2050 		User::Leave(KErrGeneral);
       
  2051 		}
       
  2052 	
       
  2053 	//Create the version table to store the message store version.
       
  2054 	err = iDatabase.Exec(KCreateVersionTableQuery);
       
  2055 	if(err < 0)
       
  2056 		{
       
  2057 		User::Leave(err);
       
  2058 		}
       
  2059 	else if(!err)
       
  2060 		{
       
  2061 		User::Leave(KErrGeneral);
       
  2062 		}
       
  2063 	//Insert the version number into the above table.
       
  2064 	_LIT8(KInsertVersionNumberQuery, " INSERT INTO VersionTable Values ( " );
       
  2065 	_LIT8(KDelimiter, " );");
       
  2066 	RBuf8 versionQuery;
       
  2067 	CleanupClosePushL(versionQuery);
       
  2068 	versionQuery.CreateL(50); //a small value is more than enough for the above query.	
       
  2069 	versionQuery.Append(KInsertVersionNumberQuery);
       
  2070 	versionQuery.AppendNum(KCurrentDatabaseVersion);
       
  2071 	versionQuery.Append(KDelimiter);
       
  2072 	err = iDatabase.Exec(versionQuery);
       
  2073 	if(err < 0)
       
  2074 		{
       
  2075 		User::Leave(err);
       
  2076 		}
       
  2077 	else if(!err)
       
  2078 		{
       
  2079 		User::Leave(KErrGeneral);
       
  2080 		}
       
  2081 	CleanupStack::PopAndDestroy(); //versionQuery
       
  2082 
       
  2083 	ConstructSortTableL();
       
  2084 	
       
  2085 	//Initialize the database adapter class
       
  2086 	InitializeL();
       
  2087 
       
  2088 	//Initialize the Search Sort database adapter class
       
  2089 	InitializeSortTableL();
       
  2090 	}
       
  2091 
       
  2092 
       
  2093 
       
  2094 
       
  2095 /**
       
  2096  * GetVisibleFolderIdL()
       
  2097  * @param TMsvId: Parent Id.
       
  2098  * @return Most immediate visible folder id of any child entry 
       
  2099  *         present under passed parent id.
       
  2100  *
       
  2101  * This functions returns the most immediate parent visible folder id.
       
  2102  * There are two types of folders. A visible folder is one which is 
       
  2103  * visible to the external user, but there are internal non-visible folders
       
  2104  * created under each email message to organize the content of the email.
       
  2105  * Parent entry of an entry is either root or a folder. A folder can be 
       
  2106  * service folder (like LocalServices), userdefined folder/standard folder
       
  2107  * like Inbox or a non-visible folder (created under an email message).
       
  2108  * 
       
  2109  * For a given parent Id, the function returns the most immediate visible
       
  2110  * parent folder. The rules are as follows:
       
  2111  * 1. If the parent entry is root or children of root, then the visibleFolder 
       
  2112  * will be root itself. This is because service folders are considered 
       
  2113  * invisible, since they are not seen by user. 
       
  2114  * 2. If the parent entry itself is a visible folder then child's visibleFolder
       
  2115  * id should be its parent id.
       
  2116  * 3. If the parent entry is a non-visible folder then child's visibleFolder
       
  2117  * id is same as its parent's visibleFolder id.
       
  2118  */
       
  2119 void CMsvDBAdapter::GetVisibleFolderIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
       
  2120 	{
       
  2121 	// If the entry is either a root entry (parent=KErrNotFound) or 
       
  2122 	// child of root entry its visibleFolderId will be root entry itself.
       
  2123 	if((KErrNotFound == aParentId) || (KMsvRootIndexEntryId == aParentId))
       
  2124 		{
       
  2125 		aVisibleFolderId = KMsvRootIndexEntryId;
       
  2126 		}
       
  2127 	else
       
  2128 		{
       
  2129 		// Get the visible flag of parent entry.
       
  2130 		
       
  2131 		// If parent entry is visible, then immediateVisibleFolder of child
       
  2132 		// should be parent Id. And if it is invisible then child's immediateVisibleFolder 
       
  2133 		// should be same as parent's immediateVisibleFolder.
       
  2134 		
       
  2135 		//Bind the msv id
       
  2136 		BindIntL(iStatement[EGetVisibleId], iIdIndex[EGetVisibleId], aParentId);
       
  2137 
       
  2138 		// If parent entry does not exists leave with KErrNotFound.
       
  2139 		if (KSqlAtRow != iStatement[EGetVisibleId].Next())
       
  2140 			{
       
  2141 			iStatement[EGetVisibleId].Reset();
       
  2142 			User::Leave(KErrNotFound);
       
  2143 			}
       
  2144 
       
  2145 		TInt32 data = ColumnInt(iStatement[EGetVisibleId], iDataIndex[EGetVisibleId]);
       
  2146 		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
       
  2147 			{
       
  2148 			// If visible folder flag is not set for parent entry.
       
  2149 			aVisibleFolderId = ColumnInt(iStatement[EGetVisibleId], iVisibleParent[EGetVisibleId]);
       
  2150 			}
       
  2151 		else
       
  2152 			{
       
  2153 			// If parent entry is visible
       
  2154 			aVisibleFolderId = aParentId;
       
  2155 			}
       
  2156 		//Reset the RSqlStatement
       
  2157 		User::LeaveIfError(iStatement[EGetVisibleId].Reset());
       
  2158 		}
       
  2159 	}
       
  2160 
       
  2161 
       
  2162 
       
  2163 
       
  2164 /**
       
  2165  * CreateEntryL()
       
  2166  * @param const TMsvEntry&: DB File Name.
       
  2167  * @return TMsvId: Immediate visible parent folder of the entry
       
  2168  *
       
  2169  * The function creates a new entry in the database. It gets the immediate
       
  2170  * visible folder id of the entry before inserting them into the database.
       
  2171  * No consisitency check is performed on the passed entry. The function may
       
  2172  * leave if query execution fails.
       
  2173  */
       
  2174 void CMsvDBAdapter::CreateEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
       
  2175 	{
       
  2176 	//Bind the entry data
       
  2177 	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], aNewEntry.iId);
       
  2178 	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], aNewEntry.iParentId);
       
  2179 	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
       
  2180 	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
       
  2181 	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
       
  2182 	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], aNewEntry.iRelatedId);
       
  2183 	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
       
  2184 	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
       
  2185 	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
       
  2186 	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
       
  2187 	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
       
  2188 	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
       
  2189 	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
       
  2190 	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
       
  2191 	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], aNewEntry.iServiceId);
       
  2192 	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
       
  2193 	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], aImmediateVisibleFolder);
       
  2194 	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
       
  2195 	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
       
  2196 	//Execute the prepared SQL statement.
       
  2197 	
       
  2198 	TInt err = iStatement[ECreateEntry].Exec();
       
  2199 	if(err < 0)
       
  2200 		{
       
  2201 		iStatement[ECreateEntry].Reset();
       
  2202 		User::Leave(err);
       
  2203 		}
       
  2204 	else if(!err)
       
  2205 		{
       
  2206 		iStatement[ECreateEntry].Reset();
       
  2207 		User::Leave(KErrGeneral);
       
  2208 		}
       
  2209 	
       
  2210 	//Reset the RSqlStatement
       
  2211 	User::LeaveIfError(iStatement[ECreateEntry].Reset());	
       
  2212 	}
       
  2213 
       
  2214 
       
  2215 
       
  2216 
       
  2217 /**
       
  2218  * UpdateEntryL()
       
  2219  * @param const TMsvEntry&: Entry to be updated.
       
  2220  * @param TBool: ETrue if the parent of the entry has been changed,
       
  2221  *				 EFalse if otherwise.
       
  2222  * @param TMsvId&: the visible folder Id of the updated entry.
       
  2223  *				   If aParentChanged is ETrue then aImmediateVisibleFolder
       
  2224  *                 is an output parameter, and input parameter if otherwise.
       
  2225  * @return None.
       
  2226  *
       
  2227  * The function updates an entry in the database. It gets the immediate
       
  2228  * visible folder id of the entry before inserting them into the database.
       
  2229  * No consisitency check is performed on the passed entry. The function may
       
  2230  * leave if query execution fails.
       
  2231  */
       
  2232 void CMsvDBAdapter::UpdateEntryL(const TMsvEntry& aEntry, const TMsvId aImmediateVisibleFolder, const TBool aIsParentIdUpdated/*DEFAULT=ETrue*/)
       
  2233 	{
       
  2234 	iStatementType updateStmt;
       
  2235 	//Bind the entry data
       
  2236 	if(aIsParentIdUpdated)
       
  2237 		{
       
  2238 		updateStmt = EUpdateEntry;
       
  2239 		BindIntL(iStatement[updateStmt], iParentIdIndex[updateStmt], aEntry.iParentId);
       
  2240 		BindIntL(iStatement[updateStmt], iVisibleParent[updateStmt], aImmediateVisibleFolder);
       
  2241 		}
       
  2242 	else
       
  2243 		{
       
  2244 		updateStmt = EUpdateEntryNoParent;
       
  2245 		}
       
  2246 	BindIntL(iStatement[updateStmt], iIdIndex[updateStmt], aEntry.iId);
       
  2247 	BindIntL(iStatement[updateStmt], iDataIndex[updateStmt], aEntry.iData);
       
  2248 	BindIntL(iStatement[updateStmt], iPcSyncCountIndex[updateStmt], aEntry.iPcSyncCount);
       
  2249 	BindIntL(iStatement[updateStmt], iReservedIndex[updateStmt], aEntry.iReserved);
       
  2250 	BindIntL(iStatement[updateStmt], iRelatedIdIndex[updateStmt], aEntry.iRelatedId);
       
  2251 	BindIntL(iStatement[updateStmt], iTypeIndex[updateStmt], aEntry.iType.iUid);
       
  2252 	BindInt64L(iStatement[updateStmt], iDateIndex[updateStmt], aEntry.iDate.Int64());
       
  2253 	BindIntL(iStatement[updateStmt], iSizeIndex[updateStmt], aEntry.iSize);
       
  2254 	BindIntL(iStatement[updateStmt], iErrorIndex[updateStmt], aEntry.iError);
       
  2255 	BindIntL(iStatement[updateStmt], iBiotypeIndex[updateStmt], aEntry.iBioType);
       
  2256 	BindIntL(iStatement[updateStmt], iMtmData1Index[updateStmt], aEntry.iMtmData1);
       
  2257 	BindIntL(iStatement[updateStmt], iMtmData2Index[updateStmt], aEntry.iMtmData2);
       
  2258 	BindIntL(iStatement[updateStmt], iMtmData3Index[updateStmt], aEntry.iMtmData3);
       
  2259 	BindIntL(iStatement[updateStmt], iServiceIdIndex[updateStmt], aEntry.iServiceId);
       
  2260 	BindIntL(iStatement[updateStmt], iMtmIdIndex[updateStmt], aEntry.iMtm.iUid);
       
  2261 	BindTextL(iStatement[updateStmt], iDescriptionIndex[updateStmt],aEntry.iDescription);
       
  2262 	BindTextL(iStatement[updateStmt], iDetailsIndex[updateStmt],aEntry.iDetails);
       
  2263 
       
  2264 	//Execute the prepared SQL statement.
       
  2265 	TInt err = iStatement[updateStmt].Exec();
       
  2266 	if(err < 0)
       
  2267 		{
       
  2268 		iStatement[updateStmt].Reset();
       
  2269 		User::Leave(err);
       
  2270 		}
       
  2271 	else if(!err)
       
  2272 		{
       
  2273 		iStatement[updateStmt].Reset();
       
  2274 		User::Leave(KErrNotFound);
       
  2275 		}
       
  2276 
       
  2277 	//Reset the RSqlStatement
       
  2278 	User::LeaveIfError(iStatement[updateStmt].Reset());
       
  2279 	}
       
  2280 
       
  2281 
       
  2282 
       
  2283 
       
  2284 /**
       
  2285  * DeleteEntryL()
       
  2286  * @param TMsvId: Entry Id to be deleted.
       
  2287  *
       
  2288  * The function deletes an entry with the passed Id. The function
       
  2289  * may leave due to database error while execution. The function
       
  2290  * does not leave if the entry does not exist.
       
  2291  *
       
  2292  * **WARNING** The function does NOT ensure that if a parent entry
       
  2293  * is deleted all its child entries are also deleted.
       
  2294  */
       
  2295 void CMsvDBAdapter::DeleteEntryL(TMsvId aEntryId)
       
  2296 	{
       
  2297 	_LIT8(KDeleteEntryQuery, "DELETE FROM IndexEntry WHERE id = ");
       
  2298 	_LIT8(KSemiColon, ";");
       
  2299 	
       
  2300 	RBuf8 queryBuf;
       
  2301 	CleanupClosePushL(queryBuf);
       
  2302 	queryBuf.CreateL(KDeleteEntryQuery().Length() + 20);
       
  2303 	queryBuf.Append(KDeleteEntryQuery);
       
  2304 	queryBuf.AppendNum(aEntryId);
       
  2305 	queryBuf.Append(KSemiColon);
       
  2306 	
       
  2307 	TInt err = iDatabase.Exec(queryBuf);
       
  2308 	if(err < 0)
       
  2309 		{		
       
  2310 		User::Leave(err);
       
  2311 		}
       
  2312 	else if(!err)
       
  2313 		{
       
  2314 		User::Leave(KErrNotFound);			
       
  2315 		}
       
  2316 	CleanupStack::PopAndDestroy();		// queryBuf
       
  2317 	}
       
  2318 
       
  2319 
       
  2320 
       
  2321 
       
  2322 /**
       
  2323  * DeleteEntryL()
       
  2324  * @param CMsvEntrySelection: Entry Id list to be deleted.
       
  2325  *
       
  2326  * The function deletes all entries mentioned in the passed Id list.
       
  2327  * The function may leave due to database error while execution or
       
  2328  * if an entry does not exist.
       
  2329  *
       
  2330  * **WARNING** The function does NOT ensure that if a parent entry
       
  2331  * is deleted all its child entries are also deleted.
       
  2332  */
       
  2333 void CMsvDBAdapter::DeleteEntryL(const CMsvEntrySelection& aEntryIdList)
       
  2334 	{
       
  2335 	TInt count;
       
  2336 	if( 0 == (count = aEntryIdList.Count()) )
       
  2337 		{
       
  2338 		return;
       
  2339 		}
       
  2340 
       
  2341 	_LIT(KQuery, "DELETE FROM IndexEntry WHERE id IN (");
       
  2342 	_LIT(KComma, ", ");
       
  2343 	_LIT(KEndDelimeter, ");");
       
  2344 	
       
  2345 	RBuf8 buf;
       
  2346 	CleanupClosePushL(buf);
       
  2347 	TInt index = 0;
       
  2348 	//Delete maximum 100 entries at a time so as to not overflow IPC buffer
       
  2349 	TInt maxEntries = 100;
       
  2350 	TInt iterRequired = count/maxEntries;
       
  2351 	if(count%maxEntries)
       
  2352 		{
       
  2353 		iterRequired++;
       
  2354 		}
       
  2355 	if(iterRequired) 
       
  2356 		{
       
  2357 		maxEntries = count/iterRequired;
       
  2358 		}
       
  2359 	for(TInt iter = 0; iter < iterRequired; ++iter)
       
  2360 		{
       
  2361 		if(iter && iter+1 == iterRequired)
       
  2362 			{
       
  2363 			maxEntries = count - index;
       
  2364 			}		
       
  2365 		buf.CreateL( 40 + ((7 + 2) * maxEntries) + 2); //KQuery + (TMsvId+KComma)*100 + KEndDelimiter		
       
  2366 		buf.Append(KQuery);
       
  2367 		TBool firstId = ETrue;
       
  2368 		TInt num = 0;
       
  2369 		while(num < maxEntries)
       
  2370 			{
       
  2371 			if(!firstId)
       
  2372 				{
       
  2373 				buf.Append(KComma);
       
  2374 				}
       
  2375 			firstId = EFalse;
       
  2376 			buf.AppendNum(aEntryIdList.At(index));
       
  2377 			++index;
       
  2378 			++num;
       
  2379 			}
       
  2380 		buf.Append(KEndDelimeter);
       
  2381 		User::LeaveIfError(iDatabase.Exec(buf));		
       
  2382 		buf.Close();
       
  2383 		}
       
  2384 	CleanupStack::PopAndDestroy(); //buf
       
  2385 	}
       
  2386 
       
  2387 
       
  2388 
       
  2389 
       
  2390 /**
       
  2391  * GetEntryL()
       
  2392  * @param TMsvId: Id of the entry to be fetched.
       
  2393  * @return TMsvId: Value of VisibleParent column.
       
  2394  * @return TMsvEntry*: The newly fetched entry.
       
  2395  *
       
  2396  * Fetch an entry from the database. Memory to aEntry
       
  2397  * should not already be assigned.
       
  2398  */
       
  2399 void CMsvDBAdapter::GetEntryL(TMsvId aId, CMsvCacheEntry*& aEntry, TMsvId& aVisibleParentEntryId)
       
  2400 	{
       
  2401 	//Bind the msv id of the entry to be retrieved
       
  2402 	BindIntL(iStatement[EGetEntry], iIdIndex[EGetEntry], aId);
       
  2403 
       
  2404 	if (KSqlAtRow != iStatement[EGetEntry].Next())
       
  2405 		{
       
  2406 		iStatement[EGetEntry].Reset();
       
  2407 		User::Leave(KErrNotFound);
       
  2408 		}
       
  2409 
       
  2410 	//Get the entry from the statement
       
  2411 	aEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  2412 	CleanupStack::PushL(aEntry);
       
  2413 	aEntry->Entry().iId = aId;
       
  2414 	LoadEntryFromStatementL(iStatement[EGetEntry], EGetEntry, aVisibleParentEntryId, *aEntry);
       
  2415 	CleanupStack::Pop(aEntry);
       
  2416 	//Reset the RSqlStatement
       
  2417 	User::LeaveIfError(iStatement[EGetEntry].Reset());
       
  2418 	}
       
  2419 
       
  2420 
       
  2421 
       
  2422 
       
  2423 /**
       
  2424  * GetChildrenL()
       
  2425  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  2426  * @return RPointerArray<TMsvEntry>&: List of child entries.
       
  2427  *
       
  2428  * Fetch child entries from the database for a given parent Id.
       
  2429  * This does not check if the parent entry already exist. The 
       
  2430  * entries will be added in ascending order of their TMsvId.
       
  2431  */
       
  2432 void CMsvDBAdapter::GetChildrenL(TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  2433 	{
       
  2434 	//Bind the msv id of the entry whose children have to be retrieved
       
  2435 	BindIntL(iStatement[EGetChildEntries], iParentIdIndex[EGetChildEntries], aParentId);
       
  2436 
       
  2437 	while(KSqlAtRow == iStatement[EGetChildEntries].Next())
       
  2438 		{
       
  2439 		TMsvId aVisibleParentEntryId;
       
  2440 		CMsvCacheEntry *cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  2441 		CleanupStack::PushL(cacheEntry);
       
  2442 		cacheEntry->Entry().iParentId = aParentId;
       
  2443 		LoadEntryFromStatementL(iStatement[EGetChildEntries], EGetChildEntries, aVisibleParentEntryId, *cacheEntry);
       
  2444 		//Add the child entry to the array given
       
  2445 		aChildArray.AppendL(cacheEntry);
       
  2446 		CleanupStack::Pop(cacheEntry);
       
  2447 		}
       
  2448 
       
  2449 	//Reset the RSqlStatement
       
  2450 	User::LeaveIfError(iStatement[EGetChildEntries].Reset());
       
  2451 	}
       
  2452 
       
  2453 
       
  2454 
       
  2455 
       
  2456 /**
       
  2457  * GetChildrenIdL()
       
  2458  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  2459  * @return RPointerArray<TMsvEntry>&: List of child entries.
       
  2460  *
       
  2461  * Fetch child entries from the database for a given parent Id.
       
  2462  * This does not check if the parent entry already exist. The 
       
  2463  * entries will be added in ascending order of their TMsvId.
       
  2464  */
       
  2465 void CMsvDBAdapter::GetChildrenIdL(TMsvId aParentId, CMsvEntrySelection& aChildArray)
       
  2466 	{
       
  2467 	//Bind the msv id of the entry whose children have to be retrieved
       
  2468 	BindIntL(iStatement[EGetChildIds], iParentIdIndex[EGetChildIds], aParentId);
       
  2469 
       
  2470 	while(KSqlAtRow == iStatement[EGetChildIds].Next())
       
  2471 		{
       
  2472 		TMsvId id = ColumnInt(iStatement[EGetChildIds], iIdIndex[EGetChildIds]);
       
  2473 		//Add the child Id to the array given
       
  2474 		aChildArray.AppendL(id);
       
  2475 		}
       
  2476 
       
  2477 	//Reset the RSqlStatement	
       
  2478 	User::LeaveIfError(iStatement[EGetChildIds].Reset());
       
  2479 	}
       
  2480 
       
  2481 
       
  2482 
       
  2483 
       
  2484 /**
       
  2485  * GetChildrenL()
       
  2486  * @param TDesc: Partial query string. (Where clause condition).
       
  2487  *               The query string should start with 'AND' and should 
       
  2488  *               end with a semicolon. Examples are:
       
  2489  *               "AND ID BETWEEN 100 and 200 ORDER BY ID ASC;"
       
  2490  * @param TMsvId: Parent Id of the child entries to be fetched.
       
  2491  * @return RPointerArray<TMsvEntry>&: List of child entries.
       
  2492  *
       
  2493  * Fetch child entries from the database for a given parent Id.
       
  2494  * This does not check if the parent entry already exist. The 
       
  2495  * entries will be added in ascending order of their TMsvId.
       
  2496  */
       
  2497 void CMsvDBAdapter::GetChildrenL(const TDesC8& aQueryStr, TMsvId aParentId, RPointerArray<CMsvCacheEntry>& aChildArray)
       
  2498 	{
       
  2499 	_LIT8(KQueryString, "SELECT id, serviceId, mtmId, type, date, data, size, error, "
       
  2500 			"mtmData1, mtmData2, mtmData3, relatedId, bioType, pcSyncCount, "
       
  2501 			"reserved, visibleParent, description, details FROM IndexEntry "
       
  2502 			"WHERE parentId = :parentId ");
       
  2503 
       
  2504 	RSqlStatement condGetChildrenStmnt;
       
  2505 	CleanupClosePushL(condGetChildrenStmnt);
       
  2506 	TInt len = KQueryString().Length() + aQueryStr.Length();
       
  2507 	RBuf8 queryBuf;
       
  2508 	CleanupClosePushL(queryBuf);
       
  2509 	queryBuf.CreateL(len);	
       
  2510 	queryBuf.Append(KQueryString);
       
  2511 	queryBuf.Append(aQueryStr);
       
  2512 		
       
  2513 	User::LeaveIfError(condGetChildrenStmnt.Prepare(iDatabase, queryBuf));
       
  2514 	TInt index = 0;
       
  2515 
       
  2516 	//Bind the msv id of the entry whose children have to be retrieved
       
  2517 	BindIntL(condGetChildrenStmnt, index, aParentId);
       
  2518 
       
  2519 	while(KSqlAtRow == condGetChildrenStmnt.Next())
       
  2520 		{
       
  2521 		CMsvCacheEntry* cacheEntry = CMsvEntryFreePool::Instance()->EntryL();
       
  2522 		CleanupStack::PushL(cacheEntry);
       
  2523 		cacheEntry->Entry().iParentId = aParentId;
       
  2524 
       
  2525 		index = 0;
       
  2526 		cacheEntry->Entry().iId = ColumnInt(condGetChildrenStmnt, index);
       
  2527 		cacheEntry->Entry().iServiceId = ColumnInt(condGetChildrenStmnt, ++index);
       
  2528 		cacheEntry->Entry().iMtm.iUid = ColumnInt(condGetChildrenStmnt, ++index);
       
  2529 		cacheEntry->Entry().iType.iUid = ColumnInt(condGetChildrenStmnt, ++index);
       
  2530 		cacheEntry->Entry().iDate = ColumnInt64(condGetChildrenStmnt, ++index);
       
  2531 		cacheEntry->Entry().iData = ColumnInt(condGetChildrenStmnt, ++index);
       
  2532 		cacheEntry->Entry().iSize = ColumnInt(condGetChildrenStmnt, ++index);
       
  2533 		cacheEntry->Entry().iError = ColumnInt(condGetChildrenStmnt, ++index);
       
  2534 		cacheEntry->Entry().iMtmData1 = ColumnInt(condGetChildrenStmnt, ++index);
       
  2535 		cacheEntry->Entry().iMtmData2 = ColumnInt(condGetChildrenStmnt, ++index);
       
  2536 		cacheEntry->Entry().iMtmData3 = ColumnInt(condGetChildrenStmnt, ++index);
       
  2537 		cacheEntry->Entry().iRelatedId = ColumnInt(condGetChildrenStmnt, ++index);
       
  2538 		cacheEntry->Entry().iBioType = ColumnInt(condGetChildrenStmnt, ++index);
       
  2539 		cacheEntry->Entry().iPcSyncCount = ColumnInt(condGetChildrenStmnt, ++index);
       
  2540 		cacheEntry->Entry().iReserved = ColumnInt(condGetChildrenStmnt, ++index);
       
  2541 		TMsvId aVisibleParentEntryId = ColumnInt(condGetChildrenStmnt, ++index);
       
  2542 		cacheEntry->iDescriptionBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  2543 		cacheEntry->Entry().iDescription.Set(*cacheEntry->iDescriptionBuffer);
       
  2544 		
       
  2545 		cacheEntry->iDetailsBuffer = ColumnTextL(condGetChildrenStmnt, ++index); 	
       
  2546 		cacheEntry->Entry().iDetails.Set(*cacheEntry->iDetailsBuffer);
       
  2547 		
       
  2548 		//Add the child entry to the array given
       
  2549 		aChildArray.AppendL(cacheEntry);
       
  2550 		CleanupStack::Pop(cacheEntry);
       
  2551 		}
       
  2552 	CleanupStack::PopAndDestroy(2);		// condGetChildrenStmnt,queryBuf
       
  2553 	}
       
  2554 
       
  2555 
       
  2556 
       
  2557 
       
  2558 /**
       
  2559  * EntryExistsL()
       
  2560  * @param TMsvId: Entry Id to check.
       
  2561  * @return TBool: ETrue if the entry exists, otherwise EFalse.
       
  2562  */
       
  2563 TBool CMsvDBAdapter::EntryExistsL(TMsvId aId)
       
  2564 	{	
       
  2565 	_LIT8(KEntryExistsQuery, "SELECT id FROM IndexEntry WHERE id = ");
       
  2566 	_LIT8(KEndDelimeter, ";");
       
  2567 	
       
  2568 	RBuf8 queryBuf;
       
  2569 	CleanupClosePushL(queryBuf);
       
  2570 	TInt len = KEntryExistsQuery().Length() + 10 + KEndDelimeter().Length(); //10 = space for TMsvId
       
  2571 	queryBuf.CreateL(len);
       
  2572 	queryBuf.Append(KEntryExistsQuery);
       
  2573 	queryBuf.AppendNum(aId);
       
  2574 	queryBuf.Append(KEndDelimeter);
       
  2575 	TSqlScalarFullSelectQuery query(iDatabase);
       
  2576 	TMsvId id = NULL;
       
  2577 	TRAPD(err, id = query.SelectIntL(queryBuf));
       
  2578 	CleanupStack::PopAndDestroy();		// queryBuf
       
  2579 	if(err!= KErrNone && err!= KErrNotFound)
       
  2580 		{
       
  2581 		User::Leave(err);
       
  2582 		}
       
  2583 	if(id)
       
  2584 		{
       
  2585 		return ETrue;
       
  2586 		}
       
  2587 	else
       
  2588 		{
       
  2589 		return EFalse;
       
  2590 		}
       
  2591 	}
       
  2592 	
       
  2593 	
       
  2594 	
       
  2595 	
       
  2596 /**
       
  2597  * GetMaxTMsvIdL()
       
  2598  * @param TMsvId&: Out parameter for maximum TMsvId in the database.
       
  2599  * @return None.
       
  2600  * 
       
  2601  * If there are no entries in the database (DB is empty),
       
  2602  * the aMaxTMsvId is set to NULL.
       
  2603  */
       
  2604 void CMsvDBAdapter::GetMaxTMsvIdL(TMsvId& aMaxTMsvId)
       
  2605 	{
       
  2606 	_LIT8(KQuery, "SELECT MAX(id) FROM IndexEntry;");
       
  2607 	RBuf8 queryBuf;
       
  2608 	CleanupClosePushL(queryBuf);
       
  2609 	queryBuf.CreateL(35);
       
  2610 	queryBuf.Append(KQuery);
       
  2611 
       
  2612 	//Create a select query
       
  2613     TSqlScalarFullSelectQuery query(iDatabase);
       
  2614 
       
  2615 	//Get the column data
       
  2616     aMaxTMsvId = query.SelectIntL(queryBuf);
       
  2617     CleanupStack::PopAndDestroy();
       
  2618 	}
       
  2619 
       
  2620 
       
  2621 
       
  2622 
       
  2623 /**
       
  2624  * GetInPreparationIdL()
       
  2625  * @param aSelection CMsvEntrySelection of the TMsvEntries 
       
  2626  * 					 whose KMsvEntryInPreparationFlag is set
       
  2627  * @return void
       
  2628  */
       
  2629 void CMsvDBAdapter::GetInPreparationIdL(CMsvEntrySelection& aSelection)
       
  2630 	{
       
  2631 	RSqlStatement statement;	
       
  2632 	User::LeaveIfError(statement.Prepare(iDatabase, KGetInPreparationIdQuery));
       
  2633 	
       
  2634 	TInt paramIdColumn = GetColumnIndexL(statement, KMsgColumnId());
       
  2635 	TInt paramDataColumn = GetColumnIndexL(statement, KMsgColumnData());
       
  2636 	
       
  2637 	TMsvId Id;
       
  2638 	TInt32 data;
       
  2639 	while (KSqlAtRow == statement.Next())
       
  2640 		{
       
  2641 		data = ColumnInt(statement, paramDataColumn);
       
  2642 		if( data & TMsvEntry::KMsvEntryInPreparationFlag )
       
  2643 			{
       
  2644 			Id = ColumnInt(statement, paramIdColumn);
       
  2645 			aSelection.AppendL(Id);
       
  2646 			}
       
  2647 		}	
       
  2648 	statement.Close();
       
  2649 	}
       
  2650 
       
  2651 
       
  2652 
       
  2653 
       
  2654 /**
       
  2655  * GetVisibleFlagL()
       
  2656  *@param TMsvId : the Id of the entry whose flag is to be checked.
       
  2657  *@return TBool : ETrue if the entry is visible, EFalse otherwise.
       
  2658  *
       
  2659  * Returns the status of the visible flag of an entry in the DB.
       
  2660  */
       
  2661 TBool CMsvDBAdapter::GetVisibleFlagL(TMsvId entryId)
       
  2662 	{
       
  2663 	_LIT8(KGetVisibleFlagQuery, "SELECT data FROM IndexEntry "
       
  2664 								"WHERE id = ");
       
  2665 	_LIT8(KEndDelimeter, ";");
       
  2666 	RBuf8 queryBuf;
       
  2667 	CleanupClosePushL(queryBuf);
       
  2668 	queryBuf.CreateL(60);	
       
  2669 	queryBuf.Append(KGetVisibleFlagQuery);
       
  2670 	queryBuf.AppendNum(entryId);
       
  2671 	queryBuf.Append(KEndDelimeter);
       
  2672 	TSqlScalarFullSelectQuery query(iDatabase);
       
  2673 	TInt32 data = 0;
       
  2674 	TRAPD(err, data = query.SelectIntL(queryBuf));
       
  2675 	CleanupStack::PopAndDestroy(); //queryBuf
       
  2676 	if(err!= KErrNone && err!= KErrNotFound)
       
  2677 		{
       
  2678 		User::Leave(err);
       
  2679 		}
       
  2680 	if(data & TMsvEntry::KMsvEntryInvisibleFlag )
       
  2681 		{
       
  2682 		return EFalse;
       
  2683 		}
       
  2684 	else
       
  2685 		{
       
  2686 		return ETrue;
       
  2687 		}
       
  2688 	}
       
  2689 
       
  2690 
       
  2691 
       
  2692 
       
  2693 /**
       
  2694  * UpdateVisibleFolderL()
       
  2695  * @param RBuf8 : the ID's of the entries of whose visible parent is to 
       
  2696  *				  be updated.
       
  2697  * @return None.
       
  2698  *
       
  2699  * Updates the visible parent of the entries passed through the RBuf* idList.
       
  2700  */
       
  2701  void CMsvDBAdapter::UpdateVisibleFolderL(CMsvEntrySelection* entryList, TMsvId newVisibleFolderId)
       
  2702  	{
       
  2703  	_LIT8(KUpdateVisibleFolderQuery1,	"UPDATE IndexEntry SET "
       
  2704 										"visibleParent = ");
       
  2705 	_LIT8(KUpdateVisibleFolderQuery2,	" WHERE id IN ( ");
       
  2706 	_LIT8(KComma, ", ");
       
  2707 	_LIT8(KDelimiter, ");");
       
  2708 	
       
  2709 	BeginTransactionL();
       
  2710 						
       
  2711 	TInt count = entryList->Count();
       
  2712 	TInt arrIndex = 0;
       
  2713 	while(arrIndex < count)
       
  2714 		{
       
  2715 		TInt len = KUpdateVisibleFolderQuery1().Length() + KUpdateVisibleFolderQuery2().Length(); 
       
  2716 		TInt temp;
       
  2717 		//Update 50 entries or lesser at a time.
       
  2718 		
       
  2719 		TInt totalEntries = count - arrIndex;
       
  2720 		
       
  2721 		if(totalEntries < 50)
       
  2722 			{
       
  2723 			len += totalEntries*12 + 15; //number of entries*length of a TMsvId + length of visibleParent id
       
  2724 			temp = totalEntries;
       
  2725 			}
       
  2726 		else
       
  2727 			{
       
  2728 			len += 50*12 + 15; //number of entries*length of a TMsvId + length of visibleParent id
       
  2729 			temp = 50;
       
  2730 			}
       
  2731 		RBuf8 queryBuf;
       
  2732 		CleanupClosePushL(queryBuf);
       
  2733 		queryBuf.CreateL(len);
       
  2734 		queryBuf.Append(KUpdateVisibleFolderQuery1);
       
  2735 		queryBuf.AppendNum(newVisibleFolderId);
       
  2736 		queryBuf.Append(KUpdateVisibleFolderQuery2);
       
  2737 		TInt index = arrIndex;
       
  2738 		for(; index < arrIndex + temp; ++index)
       
  2739 			{
       
  2740 			queryBuf.AppendNum(entryList->At(index));
       
  2741 			if(index != arrIndex + temp - 1)
       
  2742 				{
       
  2743 				queryBuf.Append(KComma);
       
  2744 				}
       
  2745 			}
       
  2746 		queryBuf.Append(KDelimiter);
       
  2747 		arrIndex += temp;	
       
  2748 		TInt err = iDatabase.Exec(queryBuf);
       
  2749 		CleanupStack::PopAndDestroy();	// queryBuf
       
  2750 		if(err < 0)
       
  2751 			{			
       
  2752 			RollbackTransactionL();
       
  2753 			User::Leave(err);
       
  2754 			}
       
  2755 		else if(!err) //no entries updated
       
  2756 			{
       
  2757 			RollbackTransactionL();
       
  2758 			User::Leave(KErrNotFound);
       
  2759 			}
       
  2760 		}
       
  2761 	CommitTransactionL();
       
  2762 	}
       
  2763 
       
  2764 
       
  2765 
       
  2766 
       
  2767 /**
       
  2768  * UpdateOwnerStatusL()
       
  2769  *
       
  2770  * @param TMsvId : the Id of an entry which has had a child added
       
  2771  *				   under it and needs its owner flag updated.
       
  2772  * @return None.
       
  2773  *
       
  2774  * The function updates the owner flag of an entry which has had a
       
  2775  * child added under it.
       
  2776  */
       
  2777 void CMsvDBAdapter::UpdateOwnerStatusL(TMsvId aId, const TMsvEntry& aParent, TBool aSet)
       
  2778 	{
       
  2779 	_LIT8(KUpdateOwnershipQuery1,	"UPDATE IndexEntry SET "
       
  2780 										" data = ");
       
  2781 	_LIT8(KUpdateOwnershipQuery2,	" WHERE id = ");
       
  2782 	_LIT8(KDelimiter, ";");
       
  2783 	
       
  2784 	// Owner flag has already been set. Return to caller.
       
  2785 	if(aParent.Owner() && aSet)
       
  2786 		{
       
  2787 		return;
       
  2788 		}
       
  2789 	// Otherwise update the owner flag for the entry in the DB.
       
  2790 	else
       
  2791 		{
       
  2792 		TInt32 data;
       
  2793 		if(aSet)
       
  2794 			{
       
  2795 			data = aParent.iData | TMsvEntry::KMsvEntryOwnerFlag;
       
  2796 			}
       
  2797 		else
       
  2798 			{
       
  2799 			data = aParent.iData & ~(TMsvEntry::KMsvEntryOwnerFlag);
       
  2800 			}
       
  2801 		TInt len = KUpdateOwnershipQuery1().Length() + KUpdateOwnershipQuery2().Length();
       
  2802 		len += 100; //data and TMsvId.
       
  2803 		RBuf8 queryBuf;
       
  2804 		CleanupClosePushL(queryBuf);
       
  2805 		queryBuf.CreateL(len);		
       
  2806 		queryBuf.Append(KUpdateOwnershipQuery1);
       
  2807 		queryBuf.AppendNum(data);
       
  2808 		queryBuf.Append(KUpdateOwnershipQuery2);
       
  2809 		queryBuf.AppendNum(aId);
       
  2810 		queryBuf.Append(KDelimiter);
       
  2811 		TInt err = iDatabase.Exec(queryBuf);
       
  2812 		if(err < 0)
       
  2813 			{
       
  2814 			User::Leave(err);
       
  2815 			}
       
  2816 		CleanupStack::PopAndDestroy(); //queryBuf
       
  2817 		}
       
  2818 	}
       
  2819 
       
  2820 
       
  2821 
       
  2822 #endif		// #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2823 
       
  2824 
       
  2825 
       
  2826 
       
  2827 /**
       
  2828  * InitializeL()
       
  2829  *
       
  2830  * This functions prepares (compiles) frequetly used SQL queries,
       
  2831  * and create indexes on the variable arguments. When the query
       
  2832  * needs to be executed, we just have to bind the variables with
       
  2833  * the values and execute them. This increases the performance of
       
  2834  * query execution.
       
  2835  */
       
  2836 void CMsvDBAdapter::InitializeL()
       
  2837 	{
       
  2838 	//Prepare the frequently used SQL statements
       
  2839 	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, KCreateEntryQuery));
       
  2840 	User::LeaveIfError(iStatement[EUpdateEntry].Prepare(iDatabase, KUpdateEntryQuery));
       
  2841 	User::LeaveIfError(iStatement[EUpdateEntryNoParent].Prepare(iDatabase, KUpdateEntryNoParentQuery));
       
  2842 	User::LeaveIfError(iStatement[EGetEntry].Prepare(iDatabase, KGetEntryQuery));
       
  2843 	User::LeaveIfError(iStatement[EGetChildEntries].Prepare(iDatabase, KGetChildEntriesQuery));
       
  2844 	User::LeaveIfError(iStatement[EGetVisibleId].Prepare(iDatabase, KGetVisibleIdQuery));
       
  2845 	User::LeaveIfError(iStatement[EEntryExists].Prepare(iDatabase, KGetEntryExistsQuery));
       
  2846 	User::LeaveIfError(iStatement[EGetChildIds].Prepare(iDatabase, KGetChildIdsQuery));
       
  2847 
       
  2848 	//Get the indices - This maps the parameter name to its offset
       
  2849 	//in the SQL statement templates.
       
  2850 	for(TInt index = ECreateEntry; index < EIndexSentinel; ++index)
       
  2851 		{
       
  2852 		switch(index)
       
  2853 			{
       
  2854 			case ECreateEntry:			// KCreateEntryQuery
       
  2855 			case EUpdateEntry:			// KUpdateEntryQuery
       
  2856 				//For creating and updating entries
       
  2857 				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
       
  2858 				iVisibleParent[index] = GetParamIndexL(iStatement[index], KMsgParamVisibleParent());
       
  2859 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());				
       
  2860 				iServiceIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamServiceId());
       
  2861 				iMtmIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamMtmId());
       
  2862 				iTypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamType());
       
  2863 				iDateIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDate());
       
  2864 				iDataIndex[index] = GetParamIndexL(iStatement[index], KMsgParamData());
       
  2865 				iSizeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamSize());
       
  2866 				iErrorIndex[index] = GetParamIndexL(iStatement[index], KMsgParamError());
       
  2867 				iMtmData1Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData1());
       
  2868 				iMtmData2Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData2());
       
  2869 				iMtmData3Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData3());
       
  2870 				iRelatedIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamRelatedId());
       
  2871 				iBiotypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamBiotype());
       
  2872 				iPcSyncCountIndex[index] = GetParamIndexL(iStatement[index], KMsgParamPcSyncCount());
       
  2873 				iReservedIndex[index] = GetParamIndexL(iStatement[index], KMsgParamReserved());
       
  2874 				iDescriptionIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDescriptionTxt());
       
  2875 				iDetailsIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDetailsTxt());
       
  2876 				break;
       
  2877 			case EUpdateEntryNoParent:
       
  2878 				iVisibleParent[index] = GetParamIndexL(iStatement[index], KMsgParamVisibleParent());
       
  2879 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());				
       
  2880 				iServiceIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamServiceId());
       
  2881 				iMtmIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamMtmId());
       
  2882 				iTypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamType());
       
  2883 				iDateIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDate());
       
  2884 				iDataIndex[index] = GetParamIndexL(iStatement[index], KMsgParamData());
       
  2885 				iSizeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamSize());
       
  2886 				iErrorIndex[index] = GetParamIndexL(iStatement[index], KMsgParamError());
       
  2887 				iMtmData1Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData1());
       
  2888 				iMtmData2Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData2());
       
  2889 				iMtmData3Index[index] = GetParamIndexL(iStatement[index], KMsgParamMtmData3());
       
  2890 				iRelatedIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamRelatedId());
       
  2891 				iBiotypeIndex[index] = GetParamIndexL(iStatement[index], KMsgParamBiotype());
       
  2892 				iPcSyncCountIndex[index] = GetParamIndexL(iStatement[index], KMsgParamPcSyncCount());
       
  2893 				iReservedIndex[index] = GetParamIndexL(iStatement[index], KMsgParamReserved());
       
  2894 				iDescriptionIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDescriptionTxt());
       
  2895 				iDetailsIndex[index] = GetParamIndexL(iStatement[index], KMsgParamDetailsTxt());
       
  2896 				break;
       
  2897 			case EGetEntry:				// KGetEntryQuery
       
  2898 				//Read an entry from DB
       
  2899 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
       
  2900 				iParentIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnParentId());
       
  2901 				iServiceIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnServiceId());
       
  2902 				iMtmIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmId());
       
  2903 				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
       
  2904 				iDateIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDate());
       
  2905 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
       
  2906 				iSizeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnSize());
       
  2907 				iErrorIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnError());
       
  2908 				iMtmData1Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData1());
       
  2909 				iMtmData2Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData2());
       
  2910 				iMtmData3Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData3());
       
  2911 				iRelatedIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnRelatedId());
       
  2912 				iBiotypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnBiotype());
       
  2913 				iPcSyncCountIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnPcSyncCount());
       
  2914 				iReservedIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnReserved());
       
  2915 				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
       
  2916 				iDescriptionIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDescriptionTxt());
       
  2917 				iDetailsIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDetailsTxt());
       
  2918 				break;
       
  2919 			case EGetChildEntries:		// KGetChildEntriesQuery
       
  2920 				//Read child entries for a given parent Id.
       
  2921 				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
       
  2922 				iIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnId());
       
  2923 				iServiceIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnServiceId());
       
  2924 				iMtmIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmId());
       
  2925 				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
       
  2926 				iDateIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDate());
       
  2927 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
       
  2928 				iSizeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnSize());
       
  2929 				iErrorIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnError());
       
  2930 				iMtmData1Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData1());
       
  2931 				iMtmData2Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData2());
       
  2932 				iMtmData3Index[index] = GetColumnIndexL(iStatement[index], KMsgColumnMtmData3());
       
  2933 				iRelatedIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnRelatedId());
       
  2934 				iBiotypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnBiotype());
       
  2935 				iPcSyncCountIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnPcSyncCount());
       
  2936 				iReservedIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnReserved());
       
  2937 				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
       
  2938 				iDescriptionIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDescriptionTxt());
       
  2939 				iDetailsIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnDetailsTxt());
       
  2940 				break;
       
  2941 			case EGetVisibleId:			// KGetVisibleIdQuery
       
  2942 				//For getting visible Id related information
       
  2943 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
       
  2944 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());	
       
  2945 				iVisibleParent[index] = GetColumnIndexL(iStatement[index], KMsgColumnVisibleParent());
       
  2946 				break;
       
  2947 			case EEntryExists:			// KGetEntryExistsQuery
       
  2948 				//To check if an entry exists in DB.
       
  2949 				iIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamId());
       
  2950 				iParentIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnParentId());
       
  2951 				break;
       
  2952 			case EGetChildIds:			// KGetChildIdsQuery
       
  2953 				//To check if an entry exists in DB.
       
  2954 				iParentIdIndex[index] = GetParamIndexL(iStatement[index], KMsgParamParentId());
       
  2955 				iIdIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnId());
       
  2956 
       
  2957 #if (defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  2958 				iTypeIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnType());
       
  2959 				iDataIndex[index] = GetColumnIndexL(iStatement[index], KMsgColumnData());
       
  2960 #endif
       
  2961 				break;
       
  2962 			default:
       
  2963 				break;
       
  2964 			}
       
  2965 		}
       
  2966 	}
       
  2967 
       
  2968 
       
  2969 
       
  2970 
       
  2971 /**
       
  2972  * BeginTransactionL()
       
  2973  * 
       
  2974  * Starts a new DB transaction.
       
  2975  */
       
  2976 void CMsvDBAdapter::BeginTransactionL()
       
  2977 	{
       
  2978 	if(!isTransactionOpen)
       
  2979 		{
       
  2980 		_LIT8(KBeginTransaction, "BEGIN;");
       
  2981 		User::LeaveIfError(iDatabase.Exec(KBeginTransaction));
       
  2982 		isTransactionOpen = ETrue;
       
  2983 		}
       
  2984 	}
       
  2985 
       
  2986 
       
  2987 
       
  2988 
       
  2989 /**
       
  2990  * CommitTransactionL()
       
  2991  * 
       
  2992  * Commits an already opened transaction.
       
  2993  */
       
  2994 void CMsvDBAdapter::CommitTransactionL()
       
  2995 	{
       
  2996 	if(isTransactionOpen)
       
  2997 		{
       
  2998 		_LIT8(KCommitTransaction,	 "COMMIT;");
       
  2999 		isTransactionOpen = EFalse;
       
  3000 		User::LeaveIfError(iDatabase.Exec(KCommitTransaction));		
       
  3001 		}
       
  3002 	}
       
  3003 
       
  3004 
       
  3005 /**
       
  3006  * RollbackTransactionL()
       
  3007  * 
       
  3008  * Rollback an already opened transaction.
       
  3009  */
       
  3010 void CMsvDBAdapter::RollbackTransactionL()
       
  3011 	{
       
  3012 	if(isTransactionOpen)
       
  3013 		{
       
  3014 		_LIT8(KRollbackTransaction,	 "ROLLBACK;");
       
  3015 		isTransactionOpen = EFalse;
       
  3016 		User::LeaveIfError(iDatabase.Exec(KRollbackTransaction));		
       
  3017 		}
       
  3018 	}
       
  3019 
       
  3020 
       
  3021 
       
  3022 
       
  3023 
       
  3024 /**
       
  3025  * LoadEntryFromStatementL()
       
  3026  * @param RSqlStatement&: a reference to the RSqlStatement to work against.
       
  3027  * @param TInt: Index of the SQL statement.
       
  3028  * @param TMsvId&: Out parameter for value of VisibleParent column.
       
  3029  * @param CMsvCacheEntry&: The newly fetched entry to be filled.
       
  3030  * @return None.
       
  3031  *
       
  3032  * Creates a CMsvCacheEntry from the executed RSqlStatement.
       
  3033  */
       
  3034 void CMsvDBAdapter::LoadEntryFromStatementL(RSqlStatement& aStmt, TInt aIndex, TMsvId& aVisibleParentEntryId, CMsvCacheEntry& aEntry)
       
  3035 	{
       
  3036 	if(EGetEntry != aIndex)
       
  3037 		{
       
  3038 		aEntry.Entry().iId = ColumnInt(aStmt, iIdIndex[aIndex]);
       
  3039 		}
       
  3040 	if(EGetChildEntries != aIndex)
       
  3041 		{
       
  3042 		aEntry.Entry().iParentId = ColumnInt(aStmt, iParentIdIndex[aIndex]);
       
  3043 		}
       
  3044 	
       
  3045 	aEntry.Entry().iData = ColumnInt(aStmt, iDataIndex[aIndex]);
       
  3046 	aEntry.Entry().iPcSyncCount = ColumnInt(aStmt, iPcSyncCountIndex[aIndex]);
       
  3047 	aEntry.Entry().iReserved = ColumnInt(aStmt, iReservedIndex[aIndex]);
       
  3048 	aEntry.Entry().iRelatedId = ColumnInt(aStmt, iRelatedIdIndex[aIndex]);
       
  3049 	aEntry.Entry().iType.iUid = ColumnInt(aStmt, iTypeIndex[aIndex]);
       
  3050 	aEntry.Entry().iDate = ColumnInt64(aStmt, iDateIndex[aIndex]);
       
  3051 	aEntry.Entry().iSize = ColumnInt(aStmt, iSizeIndex[aIndex]);
       
  3052 	aEntry.Entry().iError = ColumnInt(aStmt, iErrorIndex[aIndex]);
       
  3053 	aEntry.Entry().iBioType = ColumnInt(aStmt, iBiotypeIndex[aIndex]);
       
  3054 	aEntry.Entry().iMtmData1 = ColumnInt(aStmt, iMtmData1Index[aIndex]);
       
  3055 	aEntry.Entry().iMtmData2 = ColumnInt(aStmt, iMtmData2Index[aIndex]);
       
  3056 	aEntry.Entry().iMtmData3 = ColumnInt(aStmt, iMtmData3Index[aIndex]);
       
  3057 	aEntry.Entry().iServiceId = ColumnInt(aStmt, iServiceIdIndex[aIndex]);
       
  3058 	aEntry.Entry().iMtm.iUid = ColumnInt(aStmt, iMtmIdIndex[aIndex]);
       
  3059 	aEntry.iDescriptionBuffer = ColumnTextL(aStmt, iDescriptionIndex[aIndex]);
       
  3060 	aEntry.Entry().iDescription.Set(*aEntry.iDescriptionBuffer);
       
  3061 	aEntry.iDetailsBuffer = ColumnTextL(aStmt, iDetailsIndex[aIndex]);
       
  3062 	aEntry.Entry().iDetails.Set(*aEntry.iDetailsBuffer);
       
  3063 	
       
  3064 	//Get the visible parent id
       
  3065 	aVisibleParentEntryId = ColumnInt(aStmt, iVisibleParent[aIndex]);
       
  3066 	}
       
  3067 
       
  3068 
       
  3069 
       
  3070 
       
  3071 /**
       
  3072  * GetNextSiblingL()
       
  3073  *
       
  3074  * @param TMsvId: TMsvId of the entry whose sibling id is to be found.
       
  3075  * @param TMsvId: TMsvId of the parent entry of aId.
       
  3076  * @param TMsvId&: TMsvId of the sibling of aId, this is an o/p parameter.
       
  3077  * @return TBool
       
  3078  *
       
  3079  * Gets the id of the sibling of aId.
       
  3080  */
       
  3081 TBool CMsvDBAdapter::GetNextSiblingL(TMsvId aId,TMsvId aParentId,TMsvId& aNextSiblingId)
       
  3082 	{
       
  3083 	TBool foundSibling=EFalse;
       
  3084 	//get all the children for this parent
       
  3085 	CMsvEntrySelection* children=new(ELeave)CMsvEntrySelection;
       
  3086 	CleanupStack::PushL(children);
       
  3087 	GetChildrenIdL(aParentId,*children);
       
  3088 	TInt childCount=children->Count();
       
  3089 	
       
  3090 	for(TInt i=0;i<childCount;++i)
       
  3091 		{
       
  3092 		if(children->At(i)==aId && i<childCount-1)
       
  3093 			{
       
  3094 			aNextSiblingId=children->At(i+1);
       
  3095 			foundSibling=ETrue;
       
  3096 			break;
       
  3097 			}
       
  3098 		}
       
  3099 	CleanupStack::PopAndDestroy(children);
       
  3100 	return foundSibling;
       
  3101 	}
       
  3102 
       
  3103 
       
  3104 
       
  3105 /**
       
  3106  * GetFirstChildIdL()
       
  3107  *
       
  3108  * @param TMsvId: TMsvId of the parent entry of aId.
       
  3109  * @param TMsvId: TMsvId of the child of aParentId, this is an o/p parameter.
       
  3110  * @return TBool.
       
  3111  *
       
  3112  * Gets the id of first child of aParentId.
       
  3113  */
       
  3114 TBool CMsvDBAdapter::GetFirstChildIdL(TMsvId aParentId,TMsvId& aFirstChild)
       
  3115 	{
       
  3116 	TBool foundChild=EFalse;
       
  3117 	//get all the children for this parent
       
  3118 	CMsvEntrySelection* children=new(ELeave)CMsvEntrySelection;
       
  3119 	CleanupStack::PushL(children);
       
  3120 	GetChildrenIdL(aParentId,*children);
       
  3121 	TInt childCount=children->Count();
       
  3122 	
       
  3123 	if(childCount>0)
       
  3124 		{
       
  3125 		aFirstChild=children->At(0);
       
  3126 		foundChild=ETrue;
       
  3127 		}
       
  3128 	CleanupStack::PopAndDestroy(children);
       
  3129 	return foundChild;
       
  3130 	}
       
  3131 
       
  3132 
       
  3133 /**
       
  3134  * ConstructSortTableL()
       
  3135  * @param none.
       
  3136  * #return none.
       
  3137  * 
       
  3138  * This functions is called to create a new table,
       
  3139  * which stores the information for the search/sort
       
  3140  * operations performed.
       
  3141  */ 
       
  3142 void CMsvDBAdapter::ConstructSortTableL()
       
  3143 	{
       
  3144 		
       
  3145 	//Create Search Sort Cache table. This stores the results of
       
  3146 	// search sort result	
       
  3147 	TInt err = iDatabase.Exec(KCreateSearchSortEntryTableQuery);
       
  3148 	if(err < 0)
       
  3149 		{
       
  3150 		User::Leave(err);
       
  3151 		}
       
  3152 #if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3153 	if(err == 0)
       
  3154 		{
       
  3155 		ClearDBContentsL();
       
  3156 		}
       
  3157 #endif
       
  3158 	
       
  3159 	//Create Unique index's on indexEnty table.
       
  3160 	//Unique Index is created on all columns to defer duplicates.
       
  3161 	err = iDatabase.Exec(KCreateSearchSortQuery);
       
  3162 	if(err < 0)
       
  3163 		{
       
  3164 		User::Leave(err);
       
  3165 		}
       
  3166 	}
       
  3167 
       
  3168 
       
  3169 
       
  3170 
       
  3171 /**
       
  3172  * InitializeSortTableL()
       
  3173  * @param none.
       
  3174  * #return none.
       
  3175  * 
       
  3176  * This functions prepares (compiles) frequetly used SQL queries,
       
  3177  * and create indexes on the variable arguments. When the query
       
  3178  * needs to be executed, we just have to bind the variables with
       
  3179  * the values and execute them. This increases the performance of
       
  3180  * query execution.
       
  3181  */
       
  3182 void CMsvDBAdapter::InitializeSortTableL()
       
  3183 	{						 
       
  3184 	//Prepare the frequently used SQL statements
       
  3185 	User::LeaveIfError(iQueryStatement[EQueryCreateEntry].Prepare(iDatabase, KCreateQueryEntry));
       
  3186 	User::LeaveIfError(iQueryStatement[EQueryGetEntryAsc].Prepare(iDatabase, KGetEntryAsc));
       
  3187 	User::LeaveIfError(iQueryStatement[EQueryGetEntryDesc].Prepare(iDatabase, KGetEntryDesc));
       
  3188 	User::LeaveIfError(iQueryStatement[EQueryGetEntryNumAsc].Prepare(iDatabase, KGetEntryNumAsc));
       
  3189 	User::LeaveIfError(iQueryStatement[EQueryGetEntryNumDesc].Prepare(iDatabase, KGetEntryNumDesc));
       
  3190 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsAsc].Prepare(iDatabase, KGetLastNIdsAsc));
       
  3191 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsDesc].Prepare(iDatabase, KGetLastNIdsDesc));
       
  3192 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsNumAsc].Prepare(iDatabase, KGetLastNIdsNumAsc));
       
  3193 	User::LeaveIfError(iQueryStatement[EQueryGetLastNIdsNumDesc].Prepare(iDatabase, KGetLastNIdsNumDesc));
       
  3194 	User::LeaveIfError(iQueryStatement[EGetFolderIds].Prepare(iDatabase, KGetFolderIds));
       
  3195 	User::LeaveIfError(iQueryStatement[EQueryCount].Prepare(iDatabase, KGetQueryCount));
       
  3196 	User::LeaveIfError(iQueryStatement[EQueryIteratorNumAsc].Prepare(iDatabase, KGetIterResultCastAsc));
       
  3197 	User::LeaveIfError(iQueryStatement[EQueryIteratorNumDesc].Prepare(iDatabase, KGetIterResultCastDesc));
       
  3198 	User::LeaveIfError(iQueryStatement[EQueryIteratorAsc].Prepare(iDatabase, KGetIterResultAsc));
       
  3199 	User::LeaveIfError(iQueryStatement[EQueryIteratorDesc].Prepare(iDatabase, KGetIterResultDesc));
       
  3200 
       
  3201 	//Get the indices - This maps the parameter name to its offset
       
  3202 	//in the SQL statement templates.
       
  3203 	for(TInt index = EQueryCreateEntry; index < EQuerySentinel; ++index)
       
  3204 		{
       
  3205 		switch(index)
       
  3206 			{							 
       
  3207 			case EQueryCreateEntry:
       
  3208 				{
       
  3209 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3210 				iIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryTMsvId());
       
  3211 				iSortfieldQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQuerySortfield());
       
  3212 				break;
       
  3213 				}
       
  3214 
       
  3215 			case EQueryGetEntryAsc:
       
  3216 				{
       
  3217 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3218 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3219 				break;
       
  3220 				}
       
  3221 
       
  3222 			case EQueryGetEntryDesc:
       
  3223 				{
       
  3224 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3225 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3226 				break;
       
  3227 				}
       
  3228 				
       
  3229 			case EQueryGetEntryNumAsc:
       
  3230 				{
       
  3231 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3232 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3233 				break;
       
  3234 				}
       
  3235 
       
  3236 			case EQueryGetEntryNumDesc:
       
  3237 				{
       
  3238 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3239 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3240 				break;
       
  3241 				}
       
  3242 				
       
  3243 			case EQueryGetLastNIdsAsc:
       
  3244 				{
       
  3245 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3246 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3247 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3248 				break;
       
  3249 				}
       
  3250 				
       
  3251 			case EQueryGetLastNIdsDesc:
       
  3252 				{
       
  3253 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3254 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3255 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());
       
  3256 				break;
       
  3257 				}
       
  3258 		
       
  3259 			case EQueryGetLastNIdsNumAsc:
       
  3260 				{
       
  3261 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3262 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3263 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());	
       
  3264 				break;
       
  3265 				}
       
  3266 			
       
  3267 			case EQueryGetLastNIdsNumDesc:
       
  3268 				{
       
  3269 				iRowIdIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryRowId());
       
  3270 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3271 				iIdQueryIndex[index] = GetColumnIndexL(iQueryStatement[index], KQueryColumnTMsvId());	
       
  3272 				break;
       
  3273 				}
       
  3274 				
       
  3275 			case EGetFolderIds:
       
  3276 				{
       
  3277 				iParentIdfield = GetParamIndexL(iQueryStatement[index], KMsgParamParentId());
       
  3278 				iTMsvidfield = GetParamIndexL(iQueryStatement[index], KMsgParamType());
       
  3279 				break;
       
  3280 				}
       
  3281 					
       
  3282 			case EQueryCount:
       
  3283 				{
       
  3284 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3285 				break;
       
  3286 				}
       
  3287 			
       
  3288 			case EQueryIteratorNumAsc:
       
  3289 				{
       
  3290 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3291 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3292 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3293 				break;
       
  3294 				}
       
  3295 			
       
  3296 			case EQueryIteratorNumDesc:
       
  3297 				{
       
  3298 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3299 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3300 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3301 				break;
       
  3302 				}
       
  3303 			
       
  3304 			case EQueryIteratorAsc:
       
  3305 				{
       
  3306 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3307 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3308 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3309 				break;
       
  3310 				}
       
  3311 			
       
  3312 			case EQueryIteratorDesc:
       
  3313 				{
       
  3314 				iQIdQueryIndex[index] = GetParamIndexL(iQueryStatement[index], KQueryQId());
       
  3315 				iIterOffset[index] =GetParamIndexL(iQueryStatement[index], KOffset());
       
  3316 				iIterLimit[index] =GetParamIndexL(iQueryStatement[index], KLimit());
       
  3317 				break;
       
  3318 				}
       
  3319 
       
  3320 			default:
       
  3321 				break;
       
  3322 			}
       
  3323 		}
       
  3324 	}
       
  3325 
       
  3326 
       
  3327 
       
  3328 	
       
  3329 /**
       
  3330  * CreateQueryEntryL()
       
  3331  * @param TInt&: The Id of the Search/Sort Query
       
  3332  * @param TMsvIdWithSortField&: Fields to be added under the query id specified
       
  3333  * @return none.
       
  3334  *
       
  3335  * This Function adds the Entries into the DB under the Queryid specified
       
  3336  */
       
  3337 void CMsvDBAdapter::CreateQueryEntryL(const TInt& aQueryId,const TMsvIdWithSortField& aEntry)
       
  3338 	{
       
  3339 	//Bind the entry data
       
  3340 	BindIntL(iQueryStatement[EQueryCreateEntry], iQIdQueryIndex[EQueryCreateEntry], aQueryId);
       
  3341 	
       
  3342 	#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3343 		BindIntL(iQueryStatement[EQueryCreateEntry], iIdQueryIndex[EQueryCreateEntry], UnmaskTMsvId(aEntry.iMessageId));
       
  3344 	#else
       
  3345 		BindIntL(iQueryStatement[EQueryCreateEntry], iIdQueryIndex[EQueryCreateEntry], aEntry.iMessageId);
       
  3346 	#endif		
       
  3347 	
       
  3348 	
       
  3349 	BindTextL(iQueryStatement[EQueryCreateEntry], iSortfieldQueryIndex[EQueryCreateEntry], aEntry.iContentMessagePart);
       
  3350 		
       
  3351 	TInt err = iQueryStatement[EQueryCreateEntry].Exec();
       
  3352 	if(err < 0)
       
  3353 		{
       
  3354 		iQueryStatement[EQueryCreateEntry].Reset();
       
  3355 		User::Leave(err);
       
  3356 		}
       
  3357 	
       
  3358 	//Reset the RSqlStatement
       
  3359 	User::LeaveIfError(iQueryStatement[EQueryCreateEntry].Reset());
       
  3360 	}
       
  3361 	
       
  3362 
       
  3363 
       
  3364 
       
  3365 /**
       
  3366  * GetSortedEntriesL()
       
  3367  * @param TInt&: The Id of the Search/Sort Query
       
  3368  * @param RArray<TMsvIdWithSortField>&: this array will be filled with the resultant ids
       
  3369  * #param TBool: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
       
  3370  * @return none.
       
  3371  *
       
  3372  * This Function retrieves all the ids under the specified Query Id
       
  3373  */
       
  3374 void CMsvDBAdapter::GetSearchSortEntriesL(const TInt& aQueryId, RArray<TMsvId>& aEntrySelection, const TBool aOrder/*Default = EFalse*/,const TBool aSortAsInt/*Default = EFalse*/)
       
  3375 	{
       
  3376 	TInt sortOrder;
       
  3377 	TMsvId entryId;
       
  3378 	
       
  3379 	if(aSortAsInt)
       
  3380 		{
       
  3381 		if(aOrder)
       
  3382 			{
       
  3383 			sortOrder = EQueryGetEntryNumAsc;
       
  3384 			}
       
  3385 		else
       
  3386 			{
       
  3387 			sortOrder = EQueryGetEntryNumDesc;
       
  3388 			}
       
  3389 		}
       
  3390 	else
       
  3391 		{
       
  3392 		if(aOrder)
       
  3393 			{
       
  3394 			sortOrder = EQueryGetEntryAsc;
       
  3395 			}
       
  3396 		else
       
  3397 			{
       
  3398 			sortOrder = EQueryGetEntryDesc;
       
  3399 			}
       
  3400 		}
       
  3401 	
       
  3402 	//Bind the msv id of the entry to be retrieved
       
  3403 	BindIntL(iQueryStatement[sortOrder], iQIdQueryIndex[sortOrder], aQueryId);
       
  3404 
       
  3405 	while(KSqlAtRow == iQueryStatement[sortOrder].Next())
       
  3406 		{
       
  3407 		entryId = ColumnInt(iQueryStatement[sortOrder], iIdQueryIndex[sortOrder]);
       
  3408 		
       
  3409 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3410 			entryId = MaskTMsvId(KCurrentDriveId,entryId);
       
  3411 		#endif
       
  3412 		
       
  3413 		aEntrySelection.AppendL(entryId);
       
  3414 		}
       
  3415 
       
  3416 	//Reset the RSqlStatement
       
  3417 	User::LeaveIfError(iQueryStatement[sortOrder].Reset());
       
  3418 	}
       
  3419 
       
  3420 
       
  3421 
       
  3422 
       
  3423 /**
       
  3424  * GetLastNTMsvIdsfromTableL()
       
  3425  * @param TInt&: The Id of the Search/Sort Query
       
  3426  * @param RArray<TMsvIdWithSortField>&: this array will be filled with the resultant ids
       
  3427  * @param TInt aLastCount: The Number of entries from the last rowid to be fetched from
       
  3428  * @param TBool: Order of the Sort operation, default value is EFalse which performs sort in Ascending order
       
  3429  * @return none.
       
  3430  *
       
  3431  * This Function retrieves the last N ids under the specified Query Id
       
  3432  */
       
  3433 void CMsvDBAdapter::GetLastNTMsvIdsfromTableL(const TInt& aQueryId, RArray<TMsvId>& aEntrySelection, TInt aLastCount, const TBool aOrder/*Default = ETrue*/,const TBool aSortAsInt/*Default = EFalse*/)
       
  3434 	{
       
  3435 	TInt sortOrder;
       
  3436 	TMsvId entryId;
       
  3437 
       
  3438 	if(aSortAsInt)
       
  3439 		{
       
  3440 		if(aOrder)
       
  3441 			{
       
  3442 			sortOrder = EQueryGetLastNIdsAsc;
       
  3443 			}
       
  3444 		else
       
  3445 			{
       
  3446 			sortOrder = EQueryGetLastNIdsDesc;
       
  3447 			}
       
  3448 		}
       
  3449 	else
       
  3450 		{
       
  3451 		if(aOrder)
       
  3452 			{
       
  3453 			sortOrder = EQueryGetLastNIdsNumAsc;
       
  3454 			}
       
  3455 		else
       
  3456 			{
       
  3457 			sortOrder = EQueryGetLastNIdsNumDesc;
       
  3458 			}
       
  3459 		}
       
  3460 	
       
  3461 	//Bind the count value
       
  3462 	BindIntL(iQueryStatement[sortOrder], iRowIdIndex[sortOrder], aLastCount);
       
  3463 	
       
  3464 	//Bind the msv id of the entry to be retrieved
       
  3465 	BindIntL(iQueryStatement[sortOrder], iQIdQueryIndex[sortOrder], aQueryId);
       
  3466 
       
  3467 	while(KSqlAtRow == iQueryStatement[sortOrder].Next())
       
  3468 		{
       
  3469 		entryId = ColumnInt(iQueryStatement[sortOrder], iIdQueryIndex[sortOrder]);
       
  3470 		
       
  3471 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3472 			entryId = MaskTMsvId(KCurrentDriveId, entryId);
       
  3473 		#endif
       
  3474 		
       
  3475 		aEntrySelection.AppendL(entryId);
       
  3476 		}
       
  3477 
       
  3478 	//Reset the RSqlStatement
       
  3479 	User::LeaveIfError(iQueryStatement[sortOrder].Reset());
       
  3480 	}
       
  3481 
       
  3482 
       
  3483 
       
  3484 
       
  3485 /**
       
  3486  * DeleteTMsvIdFromAllQueriesL()
       
  3487  * @param TMsvId&: The id to be deleted
       
  3488  * @return none.
       
  3489  *
       
  3490  * This Function delete a id under all Queryid's
       
  3491  */
       
  3492 void CMsvDBAdapter::DeleteTMsvIdFromAllQueriesL(const TMsvId& aId)
       
  3493 	{	
       
  3494 	RBuf8 queryBuf;
       
  3495 	CleanupClosePushL(queryBuf);
       
  3496 	queryBuf.CreateL(KDeleteId().Length() + 20);
       
  3497 	queryBuf.Append(KDeleteId);
       
  3498 	queryBuf.AppendNum(aId);
       
  3499 	queryBuf.Append(KSemiColon);
       
  3500 	
       
  3501 	TInt err = iDatabase.Exec(queryBuf);
       
  3502 	CleanupStack::PopAndDestroy();		// queryBuf
       
  3503 	if(err < 0)
       
  3504 		{		
       
  3505 		User::Leave(err);
       
  3506 		}
       
  3507 	}
       
  3508 
       
  3509 
       
  3510 
       
  3511 
       
  3512 /**
       
  3513  * DeleteQueryFromTableL()
       
  3514  * @param TInt&: The Id of the Search/Sort Query
       
  3515  * @return none.
       
  3516  *
       
  3517  * This Function deletes a particular Query from DB
       
  3518  */
       
  3519 void CMsvDBAdapter::DeleteQueryFromTableL(const TInt& aQueryId)
       
  3520 	{
       
  3521 	RBuf8 queryBuf;
       
  3522 	CleanupClosePushL(queryBuf);
       
  3523 	queryBuf.CreateL(KDeleteQueryId().Length() + 20);
       
  3524 	queryBuf.Append(KDeleteQueryId);
       
  3525 	queryBuf.AppendNum(aQueryId);
       
  3526 	queryBuf.Append(KSemiColon);
       
  3527 	
       
  3528 	TInt err = iDatabase.Exec(queryBuf);
       
  3529 	CleanupStack::PopAndDestroy();		// queryBuf
       
  3530 	if(err < 0)
       
  3531 		{		
       
  3532 		User::Leave(err);
       
  3533 		}
       
  3534 	}
       
  3535 
       
  3536 
       
  3537 
       
  3538 
       
  3539 /**
       
  3540  * DeleteTMsvIdFromQueryL()
       
  3541  * @param TInt&: The Id of the Search/Sort Query
       
  3542  * @param TMsvId&: The TMsvId of the entry to be deleted 
       
  3543  * @return none.
       
  3544  *
       
  3545  * This Function deletes a particular id under the specified QueryId
       
  3546  */
       
  3547 void CMsvDBAdapter::DeleteTMsvIdFromQueryL(const TInt& aQueryId,const TMsvId& aId)
       
  3548 	{
       
  3549 	RBuf8 queryBuf;
       
  3550 	CleanupClosePushL(queryBuf);
       
  3551 	queryBuf.CreateL(KDeleteQueryId().Length()+KAndId().Length() + 20);
       
  3552 	queryBuf.Append(KDeleteQueryId);
       
  3553 	queryBuf.AppendNum(aQueryId);
       
  3554 	queryBuf.Append(KAndId);
       
  3555 	queryBuf.AppendNum(aId);
       
  3556 	queryBuf.Append(KSemiColon);
       
  3557 	
       
  3558 	TInt err = iDatabase.Exec(queryBuf);
       
  3559 	CleanupStack::PopAndDestroy();		// queryBuf
       
  3560 	if(err < 0)
       
  3561 		{		
       
  3562 		User::Leave(err);
       
  3563 		}
       
  3564 	}
       
  3565 
       
  3566 
       
  3567 
       
  3568 
       
  3569 /**
       
  3570  * AddEntriesfromIndexTableL()
       
  3571  * @param TDesC8&: The Query to fill the SearchSortTable with the IndexEntry
       
  3572  * @return number of entries successfully added.
       
  3573  *
       
  3574  * This Function fills the SearchSortTable with the query specified on the IndexEntryTable
       
  3575  */
       
  3576 TInt CMsvDBAdapter::AddEntriesfromIndexTableL(const TDesC8& aQuery)
       
  3577 	{
       
  3578 	TInt err = iDatabase.Exec(aQuery);
       
  3579 	
       
  3580 	TPtrC errMsg = iDatabase.LastErrorMessage();
       
  3581 	
       
  3582 	if(err < 0)
       
  3583 		{
       
  3584 		User::Leave(err);
       
  3585 		}
       
  3586 
       
  3587 	return err;
       
  3588 	}
       
  3589 
       
  3590 
       
  3591 
       
  3592 
       
  3593 /**
       
  3594  * ReturnIdCountInDBL()
       
  3595  * @param TInt&: The Id of the Search/Sort Query
       
  3596  * @return TInt: The number of entries stored under the QueryId specified
       
  3597  *
       
  3598  * This Function returns the number of id's stored under the specified QueryId
       
  3599  */
       
  3600 TInt CMsvDBAdapter::ReturnIdCountInDBL(const TInt& aQueryId)
       
  3601 	{
       
  3602 	TInt count=0;
       
  3603 	//Bind the msv id of the entry to be retrieved
       
  3604 	BindIntL(iQueryStatement[EQueryCount], iQIdQueryIndex[EQueryCount], aQueryId);
       
  3605 
       
  3606 	while(KSqlAtRow == iQueryStatement[EQueryCount].Next())
       
  3607 		{
       
  3608 		count = ColumnInt(iQueryStatement[EQueryCount], iIdQueryIndex[EQueryCount]);
       
  3609 		}
       
  3610 
       
  3611 	//Reset the RSqlStatement
       
  3612 	User::LeaveIfError(iQueryStatement[EQueryCount].Reset());
       
  3613 	return count;
       
  3614 	}
       
  3615 
       
  3616 
       
  3617 
       
  3618 
       
  3619 /**
       
  3620  * SearchTMsvIdL()
       
  3621  * @param aQuery        An object representing the the search sort query.
       
  3622  * @param aIdSelection  RArray holding the resultant TMsvId list. 
       
  3623  * 
       
  3624  * This function should be used to retrieve TMsvId list of result set.					 
       
  3625  * Queries the table holding TMsvEntry and retrieves id list of matched results.
       
  3626  */
       
  3627 void CMsvDBAdapter::SearchTMsvIdL(const TDesC8& aQuery, RArray<TMsvId>& aIdSelection)
       
  3628 	{
       
  3629 	RSqlStatement queryStmt;
       
  3630 	CleanupClosePushL(queryStmt);
       
  3631 	User::LeaveIfError(queryStmt.Prepare(iDatabase, aQuery));
       
  3632 	
       
  3633 	TInt idColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
       
  3634 	while(KSqlAtRow == queryStmt.Next())
       
  3635 		{
       
  3636 		
       
  3637 		TMsvId id = ColumnInt(queryStmt, idColumnIndex);
       
  3638 		
       
  3639 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3640 			id = MaskTMsvId(KCurrentDriveId, id);
       
  3641 		#endif
       
  3642 		
       
  3643 		aIdSelection.AppendL(id);
       
  3644 		}
       
  3645 
       
  3646 	CleanupStack::PopAndDestroy();
       
  3647 	}
       
  3648 
       
  3649 
       
  3650 
       
  3651 
       
  3652 /**
       
  3653  * GetFolderIdsL()
       
  3654  * @param aParentId      Parent Id of the folder.
       
  3655  * @param aFolderIdList  RArray holding the resultant TMsvId list. 
       
  3656  * 
       
  3657  * This function returns the id's of all the KUidMsvMessageEntry type under the parent.
       
  3658  */
       
  3659 void CMsvDBAdapter::GetFolderIdsL(const TMsvId aParentId, RArray<TMsvId>& aFolderIdList)
       
  3660 	{
       
  3661 	TMsvId entryId;
       
  3662 	TUid folderType = KUidMsvFolderEntry;
       
  3663 	
       
  3664 	#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3665 		{
       
  3666 		_LIT8(KGetFolderIds, "SELECT id FROM DB");
       
  3667 		_LIT8(KGetFolderQuery,".IndexEntry WHERE parentId = ");
       
  3668 	
       
  3669 		_LIT8(KTypeLike," AND type = ");
       
  3670 
       
  3671 		RBuf8 folderIdQuery;
       
  3672 		CleanupClosePushL(folderIdQuery);
       
  3673 		folderIdQuery.CreateL(500);		
       
  3674 		folderIdQuery.Append(KGetFolderIds);
       
  3675 		folderIdQuery.AppendNum(KCurrentDriveId);
       
  3676 		folderIdQuery.Append(KGetFolderQuery);
       
  3677 		folderIdQuery.AppendNum(aParentId);
       
  3678 		folderIdQuery.Append(KTypeLike);
       
  3679 		folderIdQuery.AppendNum(folderType.iUid);
       
  3680 		folderIdQuery.Append(KSemiColon);
       
  3681 	
       
  3682 		RSqlStatement folderquerystatement;
       
  3683 	
       
  3684 		User::LeaveIfError(folderquerystatement.Prepare(iDatabase, folderIdQuery));
       
  3685 	
       
  3686 		while(KSqlAtRow == folderquerystatement.Next())
       
  3687 			{
       
  3688 			entryId = ColumnInt(folderquerystatement, 0);
       
  3689 			aFolderIdList.AppendL(entryId);
       
  3690 			}
       
  3691 		folderquerystatement.Close();
       
  3692 		CleanupStack::PopAndDestroy();  //folderIdQuery
       
  3693 		}
       
  3694 	#else
       
  3695 		{
       
  3696 		//Bind the msv id of the entry to be retrieved
       
  3697 		BindIntL(iQueryStatement[EGetFolderIds], iParentIdfield, aParentId);
       
  3698 		BindIntL(iQueryStatement[EGetFolderIds], iTMsvidfield, folderType.iUid);
       
  3699 		
       
  3700 		while(KSqlAtRow == iQueryStatement[EGetFolderIds].Next())
       
  3701 			{
       
  3702 			entryId = ColumnInt(iQueryStatement[EGetFolderIds], iParentIdfield);
       
  3703 			aFolderIdList.AppendL(entryId);
       
  3704 			}
       
  3705 		//Reset the RSqlStatement
       
  3706 		User::LeaveIfError(iQueryStatement[EGetFolderIds].Reset());
       
  3707 		}
       
  3708 	#endif
       
  3709 	}
       
  3710 
       
  3711 
       
  3712 
       
  3713 
       
  3714 /**
       
  3715  * ClearDBContentsL()
       
  3716  * @param none.
       
  3717  * @param none.
       
  3718  * 
       
  3719  * This function clears the DB contents.
       
  3720  */
       
  3721 void CMsvDBAdapter::ClearDBContentsL()
       
  3722 	{
       
  3723 #if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3724 	RSqlDatabase temp;
       
  3725 	CleanupClosePushL(temp);
       
  3726 	//Get the system drive.
       
  3727 	TInt systemDrive = (TInt)RFs::GetSystemDrive();
       
  3728 	
       
  3729 	RBuf dbFile;
       
  3730 	CleanupClosePushL(dbFile);
       
  3731 	dbFile.CreateL(50);	
       
  3732 	dbFile.Append(TDriveUnit(systemDrive).Name());
       
  3733 	dbFile.Append(KMainDummyDBName);
       
  3734 	
       
  3735 	TRAPD(err, temp.OpenL(dbFile));
       
  3736 	if(err == KErrNone)
       
  3737 		{
       
  3738 		err = temp.Exec(KClearTableContents);
       
  3739 		if(err < 0)
       
  3740 			{
       
  3741 			User::Leave(err);
       
  3742 			}
       
  3743 		}
       
  3744 	temp.Close();
       
  3745 	CleanupStack::PopAndDestroy(2); //temp, dbFile
       
  3746 #else
       
  3747 	TInt err = iDatabase.Exec(KDeleteTable);
       
  3748 	if(err < 0)
       
  3749 		{
       
  3750 		User::Leave(err);
       
  3751 		}
       
  3752 #endif	
       
  3753 	
       
  3754 	}
       
  3755 
       
  3756 
       
  3757 
       
  3758 
       
  3759 /**
       
  3760  * ReturnIdsInIteratorL()
       
  3761  * @param aQueryId      Query ID of the query to be executed.
       
  3762  * @param prevCount     The previous value returned to the caller. 
       
  3763  * @param aId           If successfull, than this contains the result.
       
  3764  
       
  3765  * This function returns the TMsvId's for each unique Query ID.
       
  3766    Upon called for the first time, it binds the query id to the statement and returns 
       
  3767    next result in each subsequent execution. If the statement fails for some reason, than it returns the 
       
  3768    error code.	
       
  3769  */
       
  3770 void CMsvDBAdapter::ReturnIdsInIteratorL(const TInt& aQueryId, const TBool aOrder/*Default = ETrue*/,const TBool aSortAsInt/*Default = EFalse*/,const TInt aLimit/*Default = 1*/)
       
  3771 	{
       
  3772 	if(aSortAsInt)
       
  3773 		{
       
  3774 		if(aOrder)
       
  3775 			{
       
  3776 			iIterQuery = EQueryIteratorNumAsc;
       
  3777 			}
       
  3778 		else
       
  3779 			{
       
  3780 			iIterQuery = EQueryIteratorNumDesc;
       
  3781 			}
       
  3782 		}
       
  3783 	else
       
  3784 		{
       
  3785 		if(aOrder)
       
  3786 			{
       
  3787 			iIterQuery = EQueryIteratorAsc;
       
  3788 			}
       
  3789 		else
       
  3790 			{
       
  3791 			iIterQuery = EQueryIteratorDesc;
       
  3792 			}
       
  3793 		}
       
  3794 		
       
  3795 	iOffsetValue = 0;
       
  3796 	iQueryId = aQueryId;
       
  3797 	iLimit = aLimit;
       
  3798 	
       
  3799 	iIdColumnIndex = GetColumnIndexL(iQueryStatement[iIterQuery], KMsgColumnId());	
       
  3800 	}
       
  3801 
       
  3802 /**
       
  3803  * GetNextL()
       
  3804  * @param aId           If successfull, than this contains the result.
       
  3805  
       
  3806  * This function returns the next TMsvId's from the Iterator	
       
  3807  */	
       
  3808 TInt CMsvDBAdapter::GetNextL(TMsvId& aId)
       
  3809 	{
       
  3810 	BindIntL(iQueryStatement[iIterQuery], iQIdQueryIndex[iIterQuery], iQueryId);
       
  3811 	BindIntL(iQueryStatement[iIterQuery], iIterLimit[iIterQuery], iLimit);
       
  3812 	BindIntL(iQueryStatement[iIterQuery], iIterOffset[iIterQuery], iOffsetValue);
       
  3813 	
       
  3814 	while(iQueryStatement[iIterQuery].Next() == KSqlAtRow)
       
  3815 		{
       
  3816 		aId = ColumnInt(iQueryStatement[iIterQuery],iIdColumnIndex);
       
  3817 		
       
  3818 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3819 			aId = MaskTMsvId(KCurrentDriveId, aId);
       
  3820 		#endif
       
  3821 			
       
  3822 		++iOffsetValue;
       
  3823 		}
       
  3824 	
       
  3825 	User::LeaveIfError(iQueryStatement[iIterQuery].Reset());
       
  3826 	return iOffsetValue;
       
  3827 	}
       
  3828 	
       
  3829 
       
  3830 /**
       
  3831  * GetPrevL()
       
  3832  * @param aId           If successfull, than this contains the result.
       
  3833  
       
  3834  * This function returns the previous TMsvId's from the Iterator	
       
  3835  */
       
  3836 TInt CMsvDBAdapter::GetPrevL(TMsvId& aId)
       
  3837 	{
       
  3838 	BindIntL(iQueryStatement[iIterQuery], iQIdQueryIndex[iIterQuery], iQueryId);
       
  3839 	BindIntL(iQueryStatement[iIterQuery], iIterLimit[iIterQuery], iLimit);
       
  3840 	BindIntL(iQueryStatement[iIterQuery], iIterOffset[iIterQuery], iOffsetValue);
       
  3841 	
       
  3842 	while(iQueryStatement[iIterQuery].Next() == KSqlAtRow)
       
  3843 		{
       
  3844 		aId = ColumnInt(iQueryStatement[iIterQuery],iIdColumnIndex);
       
  3845 		#if(defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3846 			aId = MaskTMsvId(KCurrentDriveId, aId);
       
  3847 		#endif
       
  3848 		
       
  3849 		--iOffsetValue;
       
  3850 		}
       
  3851 	
       
  3852 	User::LeaveIfError(iQueryStatement[iIterQuery].Reset());
       
  3853 	return iOffsetValue;
       
  3854 	}
       
  3855 
       
  3856 
       
  3857 
       
  3858 
       
  3859 
       
  3860 #if (!defined SYMBIAN_MSGS_ENHANCED_REMOVABLE_MEDIA_SUPPORT)
       
  3861 /**
       
  3862  * ValidateDatabaseL()
       
  3863  * 
       
  3864  * @param TFileName& The database filename to be checked.
       
  3865  * @return None.
       
  3866  *
       
  3867  * Checks the database version to see if it is supported.
       
  3868  * Supported version is KCurrentDatabaseVersion (1) only.
       
  3869  */
       
  3870 void CMsvDBAdapter::ValidateDatabaseL(const TFileName& aDbFile)
       
  3871 	{
       
  3872 	_LIT8(KSelectVersionQuery, "SELECT version FROM VersionTable;");
       
  3873 	
       
  3874 	//Use a temporary local database connection to open the file for now.
       
  3875 	RSqlDatabase temp;
       
  3876 	CleanupClosePushL(temp);
       
  3877 	temp.OpenL(aDbFile);	
       
  3878 	TSqlScalarFullSelectQuery query(temp);
       
  3879 
       
  3880 	TInt version = 0;
       
  3881 	version = query.SelectIntL(KSelectVersionQuery);
       
  3882 	if(KCurrentDatabaseVersion != version)
       
  3883 		{
       
  3884 		User::Leave(KErrNotSupported);
       
  3885 		}
       
  3886 	CleanupStack::PopAndDestroy();  // temp
       
  3887 	}
       
  3888 #endif
       
  3889 
       
  3890 
       
  3891 
       
  3892 #if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  3893 /** 
       
  3894 * GetMtmIdsL()
       
  3895 *
       
  3896 * @param aMtmIdTable: aMtmIdTable will be updated with MtmIds
       
  3897 * @param aQuery: QueryString which is prepared depending on SearchSort Query
       
  3898 * return NONE
       
  3899 *  
       
  3900 *  Function to get MtmId/s for given parent id.
       
  3901 */ 
       
  3902 void CMsvDBAdapter::GetMtmIdsL(const TDesC8& aQuery, RArray<TUid>& aMtmIdArray)
       
  3903 	{
       
  3904 	RSqlStatement queryStmt;
       
  3905 	CleanupClosePushL(queryStmt);
       
  3906 	User::LeaveIfError(queryStmt.Prepare(iDatabase, aQuery));
       
  3907 	
       
  3908 	TInt mtmIdColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnMtmId());
       
  3909 	
       
  3910 	TUid tempMtmId ;
       
  3911 	TInt32 mtmId = KErrNotFound;
       
  3912 	
       
  3913 	while(KSqlAtRow == queryStmt.Next())
       
  3914 		{
       
  3915 		mtmId = ColumnInt(queryStmt, mtmIdColumnIndex);
       
  3916 		
       
  3917 		tempMtmId.iUid = mtmId;
       
  3918 		aMtmIdArray.AppendL(tempMtmId);
       
  3919 		}
       
  3920 	
       
  3921 	CleanupStack::PopAndDestroy();
       
  3922 	}
       
  3923 
       
  3924 
       
  3925 
       
  3926 /***************************** Converter************************/
       
  3927 
       
  3928 /**
       
  3929 OpenL()
       
  3930 Opens a database and returns a handle to it.
       
  3931 
       
  3932 @param aDbFileName: DB name.
       
  3933 @retun :CMsvDBAdapter object.
       
  3934 */	
       
  3935 CMsvDBAdapter* CMsvDBAdapter::OpenL(const TFileName& aDbFileName)
       
  3936 	{
       
  3937 	//Create an messaging DB adaptor object 
       
  3938 	CMsvDBAdapter* self = new(ELeave) CMsvDBAdapter();
       
  3939 	CleanupStack::PushL(self);
       
  3940 	
       
  3941 	// Open the database.
       
  3942 	self->ConstructOpenDBL(aDbFileName);
       
  3943 	
       
  3944 	CleanupStack::Pop(self);
       
  3945 	return self;
       
  3946 	}
       
  3947 	
       
  3948 /**
       
  3949 ConstructOpenDBL()
       
  3950 
       
  3951 @param aDbFileName: DB name.
       
  3952 @retun None
       
  3953 */
       
  3954 void CMsvDBAdapter::ConstructOpenDBL(const TFileName& aDbFileName)
       
  3955 	{
       
  3956 	User::LeaveIfError(iDatabase.Open(aDbFileName));
       
  3957 	iDatabasePresent = new(ELeave)RArray<TBool>(KMaxNumberOfDrives);
       
  3958 	for(TInt index = 0; index < KMaxNumberOfDrives; ++index)
       
  3959 		{
       
  3960 		iDatabasePresent->Append(EFalse);
       
  3961 		}
       
  3962 	}
       
  3963 
       
  3964 	
       
  3965 /**
       
  3966  * InitializeL()
       
  3967  *
       
  3968  * This functions prepares (compiles) frequetly used SQL queries,
       
  3969  * and create indexes on the variable arguments. When the query
       
  3970  * needs to be executed, we just have to bind the variables with
       
  3971  * the values and execute them. This increases the performance of
       
  3972  * query execution.
       
  3973  */
       
  3974 void CMsvDBAdapter::InitializeLConverterStatementL()
       
  3975 	{
       
  3976 	//Prepare the frequently used SQL statements
       
  3977 	User::LeaveIfError(iStatement[ECreateEntry].Prepare(iDatabase, KCreateEntryQuery));
       
  3978 	
       
  3979 	//For creating and updating entries
       
  3980 	iParentIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamParentId());
       
  3981 	iVisibleParent[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamVisibleParent());
       
  3982 	iIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamId());				
       
  3983 	iServiceIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamServiceId());
       
  3984 	iMtmIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmId());
       
  3985 	iTypeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamType());
       
  3986 	iDateIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDate());
       
  3987 	iDataIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamData());
       
  3988 	iSizeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamSize());
       
  3989 	iErrorIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamError());
       
  3990 	iMtmData1Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData1());
       
  3991 	iMtmData2Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData2());
       
  3992 	iMtmData3Index[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamMtmData3());
       
  3993 	iRelatedIdIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamRelatedId());
       
  3994 	iBiotypeIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamBiotype());
       
  3995 	iPcSyncCountIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamPcSyncCount());
       
  3996 	iReservedIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamReserved());
       
  3997 	iDescriptionIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDescriptionTxt());
       
  3998 	iDetailsIndex[ECreateEntry] = GetParamIndexL(iStatement[ECreateEntry], KMsgParamDetailsTxt());
       
  3999 	}
       
  4000 
       
  4001 
       
  4002 /**
       
  4003 CreateIndexEntryL()
       
  4004 Inserts an entry in IndexEntry table.  
       
  4005 
       
  4006 @param aNewEntry: TMsvEntry.
       
  4007 @param aImmediateVisibleFolder: Visible Parent.
       
  4008 @retun None
       
  4009 */
       
  4010 void CMsvDBAdapter::CreateIndexEntryL(const TMsvEntry& aNewEntry, const TMsvId aImmediateVisibleFolder)
       
  4011 	{
       
  4012 	//Bind the entry data
       
  4013 	BindIntL(iStatement[ECreateEntry], iIdIndex[ECreateEntry], aNewEntry.iId);
       
  4014 	BindIntL(iStatement[ECreateEntry], iParentIdIndex[ECreateEntry], aNewEntry.iParentId);
       
  4015 	BindIntL(iStatement[ECreateEntry], iDataIndex[ECreateEntry], aNewEntry.iData);
       
  4016 	BindIntL(iStatement[ECreateEntry], iPcSyncCountIndex[ECreateEntry], aNewEntry.iPcSyncCount);
       
  4017 	BindIntL(iStatement[ECreateEntry], iReservedIndex[ECreateEntry], aNewEntry.iReserved);
       
  4018 	BindIntL(iStatement[ECreateEntry], iRelatedIdIndex[ECreateEntry], aNewEntry.iRelatedId);
       
  4019 	BindIntL(iStatement[ECreateEntry], iTypeIndex[ECreateEntry], aNewEntry.iType.iUid);
       
  4020 	BindInt64L(iStatement[ECreateEntry], iDateIndex[ECreateEntry], aNewEntry.iDate.Int64());
       
  4021 	BindIntL(iStatement[ECreateEntry], iSizeIndex[ECreateEntry], aNewEntry.iSize);
       
  4022 	BindIntL(iStatement[ECreateEntry], iErrorIndex[ECreateEntry], aNewEntry.iError);
       
  4023 	BindIntL(iStatement[ECreateEntry], iBiotypeIndex[ECreateEntry], aNewEntry.iBioType);
       
  4024 	BindIntL(iStatement[ECreateEntry], iMtmData1Index[ECreateEntry], aNewEntry.iMtmData1);
       
  4025 	BindIntL(iStatement[ECreateEntry], iMtmData2Index[ECreateEntry], aNewEntry.iMtmData2);
       
  4026 	BindIntL(iStatement[ECreateEntry], iMtmData3Index[ECreateEntry], aNewEntry.iMtmData3);
       
  4027 	BindIntL(iStatement[ECreateEntry], iServiceIdIndex[ECreateEntry], aNewEntry.iServiceId);
       
  4028 	BindIntL(iStatement[ECreateEntry], iMtmIdIndex[ECreateEntry], aNewEntry.iMtm.iUid);
       
  4029 	BindIntL(iStatement[ECreateEntry], iVisibleParent[ECreateEntry], aImmediateVisibleFolder);
       
  4030 	BindTextL(iStatement[ECreateEntry],iDescriptionIndex[ECreateEntry],aNewEntry.iDescription);
       
  4031 	BindTextL(iStatement[ECreateEntry],iDetailsIndex[ECreateEntry],aNewEntry.iDetails);
       
  4032 	//Execute the prepared SQL statement.
       
  4033 	
       
  4034 	TInt err = iStatement[ECreateEntry].Exec();
       
  4035 	if(err < 0)
       
  4036 		{
       
  4037 		iStatement[ECreateEntry].Reset();
       
  4038 		User::Leave(err);
       
  4039 		}
       
  4040 	else if(!err)
       
  4041 		{
       
  4042 		iStatement[ECreateEntry].Reset();
       
  4043 		User::Leave(KErrGeneral);
       
  4044 		}
       
  4045 	
       
  4046 	//Reset the RSqlStatement
       
  4047 	User::LeaveIfError(iStatement[ECreateEntry].Reset());	
       
  4048 	}
       
  4049 
       
  4050 
       
  4051 /**
       
  4052 ChangeVersionL()
       
  4053 Changes message store version of messaging database.
       
  4054 
       
  4055 @param aVersion: version
       
  4056 @retun None
       
  4057 */	
       
  4058 void CMsvDBAdapter::ChangeVersionL(TInt aVersion)
       
  4059 	{
       
  4060 	_LIT(KUpdateVersionQuery, "UPDATE VersionTable SET version = "); 
       
  4061 		
       
  4062 	RBuf buf;
       
  4063 	CleanupClosePushL(buf);
       
  4064 	buf.CreateL(100);
       
  4065 	buf.Append(KUpdateVersionQuery);
       
  4066 	buf.AppendNum(aVersion);
       
  4067 	buf.Append(KDelimiter);
       
  4068 	
       
  4069 	TInt err = iDatabase.Exec(buf);
       
  4070 	if(err < 0)
       
  4071 		{
       
  4072 		User::Leave(err);
       
  4073 		}
       
  4074 	CleanupStack::PopAndDestroy(); //buf
       
  4075 	}
       
  4076 
       
  4077 	
       
  4078 /**************************** Conversion Status Table API's **************************/
       
  4079 /**
       
  4080 CreateConversionStatusTableL()
       
  4081 Creates conversion status table.
       
  4082 
       
  4083 @param None: 
       
  4084 @retun None
       
  4085 */
       
  4086 void CMsvDBAdapter::CreateConversionStatusTableL()
       
  4087 	{
       
  4088 	TInt err = iDatabase.Exec(KCreateConversionStatusTableQuery);
       
  4089 	if(err < 0)
       
  4090 		{
       
  4091 		User::Leave(KErrGeneral);
       
  4092 		}
       
  4093 	}
       
  4094 
       
  4095 /**
       
  4096 RemoveConversionStatusTableL()
       
  4097 Removes conversion status table.
       
  4098 
       
  4099 @param None: 
       
  4100 @retun None
       
  4101 */	
       
  4102 void CMsvDBAdapter::RemoveConversionStatusTableL()
       
  4103 	{
       
  4104 	TInt err = iDatabase.Exec(KRemoveConversionStatusTable);
       
  4105 	if(err < 0)
       
  4106 		{
       
  4107 		User::Leave(err);
       
  4108 		}
       
  4109 	}
       
  4110 
       
  4111 /**
       
  4112 GetConversionStatusL()
       
  4113 Fetches conversion resume state from the conversion status table.
       
  4114 
       
  4115 @param aConversionResumeStatus: Conversion sresume status entry.
       
  4116 @retun None
       
  4117 */	
       
  4118 void CMsvDBAdapter::GetConversionStatusL(TConversionResumeStatus& aConversionResumeStatus)
       
  4119 	{
       
  4120 	// We shld not get more than one mtm results for this query
       
  4121 	_LIT16(KGetConversionStatusQuery, "SELECT * FROM ConversionStatus WHERE remainingCount != 0;"); 
       
  4122 	
       
  4123 	RSqlStatement statement;
       
  4124 	CleanupClosePushL(statement);
       
  4125 	TInt index =0;
       
  4126 	
       
  4127 	User::LeaveIfError(statement.Prepare(iDatabase, KGetConversionStatusQuery));
       
  4128 		
       
  4129 	while(KSqlAtRow ==  statement.Next())
       
  4130 		{
       
  4131 		aConversionResumeStatus.lastId = ColumnInt(statement, index);
       
  4132 		aConversionResumeStatus.serviceId = ColumnInt(statement, ++index);
       
  4133 		aConversionResumeStatus.sourceVersion = ColumnInt(statement, ++index);
       
  4134 		aConversionResumeStatus.targetVersion = ColumnInt(statement, ++index);
       
  4135 		aConversionResumeStatus.mtmId.iUid = ColumnInt(statement, ++index);
       
  4136 		aConversionResumeStatus.remainingCount = ColumnInt(statement, ++index);
       
  4137 		index =0;
       
  4138 		}
       
  4139 	CleanupStack::PopAndDestroy(); //statement
       
  4140 	}
       
  4141 
       
  4142 /**
       
  4143 AddConversionStatusEntryL()
       
  4144 Inserts a conversion status entry in the conversion status table.
       
  4145 
       
  4146 @param aConversionResumeStatus: Conversion sresume status entry.
       
  4147 @retun None
       
  4148 */	
       
  4149 void CMsvDBAdapter::AddConversionStatusEntryL(TConversionResumeStatus& aConversionResumeStatus)
       
  4150 	{
       
  4151 	_LIT8(KAddConversionStatusEntryQuery, "INSERT INTO ConversionStatus VALUES ("
       
  4152 							 ":lastId, :serviceId, :sourceVersion, :targetVersion, :mtmId, :remainingCount);"
       
  4153 		 ); //
       
  4154 			 
       
  4155 	RSqlStatement statement;
       
  4156 	CleanupClosePushL(statement);
       
  4157 	TInt index =0;
       
  4158 	
       
  4159 	User::LeaveIfError(statement.Prepare(iDatabase,KAddConversionStatusEntryQuery));
       
  4160 	BindIntL(statement, index++, aConversionResumeStatus.lastId);
       
  4161 	BindIntL(statement, index++, aConversionResumeStatus.serviceId);
       
  4162 	BindIntL(statement, index++, aConversionResumeStatus.sourceVersion);
       
  4163 	BindIntL(statement, index++, aConversionResumeStatus.targetVersion);
       
  4164 	BindIntL(statement, index++, aConversionResumeStatus.mtmId.iUid);
       
  4165 	BindIntL(statement, index++, aConversionResumeStatus.remainingCount);
       
  4166 	
       
  4167 	TInt err = statement.Exec();
       
  4168 	
       
  4169 	CleanupStack::PopAndDestroy(); //statement
       
  4170 
       
  4171 	if(err < 0)
       
  4172 		{
       
  4173 		User::Leave(err);
       
  4174 		}
       
  4175 	else if(!err )
       
  4176 		{
       
  4177 		User::Leave(KErrGeneral);
       
  4178 		}
       
  4179 	}
       
  4180 
       
  4181 /**
       
  4182 UpdateConversionStatusEntryL()
       
  4183 Updates a conversion status entry in the conversion status table.
       
  4184 
       
  4185 @param aConversionResumeStatus:Conversion sresume status entry.
       
  4186 @retun None
       
  4187 */	
       
  4188 void CMsvDBAdapter::UpdateConversionStatusEntryL(TConversionResumeStatus& aConversionResumeStatus)	
       
  4189 	{
       
  4190 	_LIT(KUpdateConversionStatusQuery1,	"UPDATE ConversionStatus SET remainingCount = "); //
       
  4191 	_LIT(KUpdateConversionStatusQuery2,	" WHERE mtmId = "); //
       
  4192 	_LIT(KUpdateConversionStatusQuery3,	" AND serviceId = "); //
       
  4193 	 
       
  4194 	RBuf buf;
       
  4195 	CleanupClosePushL(buf);
       
  4196 	buf.CreateL(100);
       
  4197 	buf.Append(KUpdateConversionStatusQuery1);
       
  4198 	buf.AppendNum(aConversionResumeStatus.remainingCount);
       
  4199 	buf.Append(KUpdateConversionStatusQuery2);
       
  4200 	buf.AppendNum(aConversionResumeStatus.mtmId.iUid);
       
  4201 	buf.Append(KUpdateConversionStatusQuery3);
       
  4202 	buf.AppendNum(aConversionResumeStatus.serviceId);
       
  4203 	buf.Append(KDelimiter); 
       
  4204 	 
       
  4205 	TInt err = iDatabase.Exec(buf);
       
  4206 	CleanupStack::PopAndDestroy(); //buf
       
  4207 	
       
  4208 	if(err < 0)
       
  4209 		{
       
  4210 		User::Leave(err);
       
  4211 		}
       
  4212 	else if(!err )
       
  4213 		{
       
  4214 		User::Leave(KErrGeneral);
       
  4215 		}
       
  4216 	}
       
  4217 
       
  4218 /**
       
  4219 RemoveConversionStatusEntriesL()
       
  4220 Removes all conversion status entries in the conversion status table.
       
  4221 
       
  4222 @param None: 
       
  4223 @retun None
       
  4224 */		
       
  4225 void CMsvDBAdapter::RemoveConversionStatusEntriesL()	
       
  4226 	{
       
  4227  	_LIT(KRemoveConversionStatusEntry,	"DELETE FROM ConversionStatus;");
       
  4228 	
       
  4229 	RSqlStatement statement;
       
  4230 	CleanupClosePushL(statement);
       
  4231 	User::LeaveIfError(statement.Prepare(iDatabase, KRemoveConversionStatusEntry));
       
  4232 	TInt err = statement.Exec();
       
  4233 	
       
  4234 	CleanupStack::PopAndDestroy(); // statement
       
  4235 	
       
  4236 	if(err < 0)
       
  4237 		{
       
  4238 		User::Leave(err);
       
  4239 		}
       
  4240 	else if(err != KErrNone)
       
  4241 		{
       
  4242 		User::Leave(KErrGeneral);
       
  4243 		}
       
  4244 	}
       
  4245 
       
  4246 /**
       
  4247 GetRemainingServiceIdsL()
       
  4248 Fetches all service ids for which the conversion is not complete from the conversion status table.
       
  4249 
       
  4250 @param aIdArray:Array of TMsvId.
       
  4251 @retun None
       
  4252 */	
       
  4253 void CMsvDBAdapter::GetRemainingServiceIdsL(RArray<TMsvId>& aIdArray)
       
  4254 	{
       
  4255 	_LIT(KGetToResumeServiceIds, "SELECT serviceId FROM ConversionStatus WHERE remainingCount != 0;"); 	
       
  4256 	
       
  4257 	RSqlStatement queryStmt;
       
  4258 	CleanupClosePushL(queryStmt);
       
  4259 	User::LeaveIfError(queryStmt.Prepare(iDatabase, KGetToResumeServiceIds));
       
  4260 	
       
  4261 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnServiceId());
       
  4262 	
       
  4263 	while(KSqlAtRow == queryStmt.Next())
       
  4264 		{
       
  4265 		TMsvId serviceId = ColumnInt(queryStmt, serviceColumnIndex);
       
  4266 		aIdArray.AppendL(serviceId);
       
  4267 		}
       
  4268 	CleanupStack::PopAndDestroy(); // stmt
       
  4269 	}
       
  4270 
       
  4271 /**
       
  4272 GetAllMessageIdsL()
       
  4273 Gets all message ids for a service id. If the conversion is resumed than retrives the message ids
       
  4274 after the last id that was converted. 
       
  4275 
       
  4276 @param aServiceId: service id.
       
  4277 @param aIdArray: Array of TMsvId.
       
  4278 @param lastId: last id that was converted and commited in the database.
       
  4279 @retun None
       
  4280 */	
       
  4281 void CMsvDBAdapter::GetAllMessageIdsL(TMsvId aServiceId, RArray<TMsvId>& aIdArray,TInt32 aMtm,TMsvId lastId)
       
  4282 	{
       
  4283 	_LIT16(KSelectMessageId, "Select id FROM IndexEntry WHERE type = ");
       
  4284 	_LIT16(KMessageMtmId," AND mtmId = ");
       
  4285 	_LIT16(KSelectServiceId," AND serviceId = ");
       
  4286 	_LIT16(KMessageId, " AND id > ");
       
  4287 	_LIT16(KOrderByString, " order by id ASC");
       
  4288 	
       
  4289 	RBuf buf;
       
  4290 	CleanupClosePushL(buf);
       
  4291 	buf.CreateL(200);
       
  4292 	buf.Append(KSelectMessageId);
       
  4293 	buf.AppendNum(KUidMsvMessageEntryValue);
       
  4294 	buf.Append(KMessageMtmId);
       
  4295 	buf.AppendNum(aMtm);
       
  4296 	buf.Append(KSelectServiceId);
       
  4297 	buf.AppendNum(aServiceId);
       
  4298 	buf.Append(KMessageId);
       
  4299 	buf.AppendNum(lastId);
       
  4300 	buf.Append(KOrderByString);
       
  4301 	buf.Append(KDelimiter);
       
  4302 	
       
  4303 	RSqlStatement Idquerystatement;
       
  4304 	CleanupClosePushL(Idquerystatement);
       
  4305 	User::LeaveIfError(Idquerystatement.Prepare(iDatabase, buf));
       
  4306 	
       
  4307 	TInt Idindex = GetColumnIndexL(Idquerystatement, KMsgColumnId());
       
  4308 	
       
  4309 	while(KSqlAtRow == Idquerystatement.Next())
       
  4310 		{
       
  4311 		aIdArray.Append(ColumnInt(Idquerystatement, Idindex));
       
  4312 		}
       
  4313 		
       
  4314 	CleanupStack::PopAndDestroy(2);  //buf,Idquerystatement
       
  4315 	}
       
  4316 
       
  4317 /**
       
  4318 GetAllMimeIdsL()
       
  4319 Gets all attachment ids for a message.
       
  4320 
       
  4321 @param aId: id
       
  4322 @param aIdArray: Array of TMsvId.
       
  4323 @retun None
       
  4324 */
       
  4325 void CMsvDBAdapter::GetAllMimeIdsL(TMsvId aId, RArray<TMsvId>& aIdArray)
       
  4326 	{
       
  4327 	_LIT(KGetChild, "Select id, type FROM IndexEntry WHERE parentId = ");
       
  4328 	
       
  4329 	const TInt32 KUidMsvEmailTextEntryValue = 0x100038F1;
       
  4330 	const TInt32 KUidMsvEmailHtmlEntryValue = 0x100057C0; // 268457920
       
  4331 	const TInt32 KUidMsvEmailRtfEntryValue = 0x1028368F; // 271070863
       
  4332 
       
  4333 	RBuf buf;
       
  4334 	CleanupClosePushL(buf);
       
  4335 	buf.CreateL(100);
       
  4336 	buf.Append(KGetChild);
       
  4337 	buf.AppendNum(aId);
       
  4338 	buf.Append(KDelimiter);
       
  4339 	
       
  4340 	RSqlStatement stmt;
       
  4341 	CleanupClosePushL(stmt);
       
  4342 	User::LeaveIfError(stmt.Prepare(iDatabase, buf));
       
  4343 	
       
  4344 	TInt idIndex = 0;
       
  4345 	TInt typeIndex = 1;
       
  4346 		
       
  4347 	// For every child..
       
  4348 	while(KSqlAtRow == stmt.Next())
       
  4349 		{
       
  4350 		// Get the type
       
  4351 		TMsvId childId = ColumnInt(stmt, idIndex);
       
  4352 		TInt32 type = ColumnInt(stmt, typeIndex);
       
  4353 		
       
  4354 		// Append TMsvId's which may have MIME header
       
  4355 		if( type == KUidMsvAttachmentEntryValue ||
       
  4356 			type == KUidMsvEmailTextEntryValue ||
       
  4357 			type == KUidMsvEmailHtmlEntryValue ||
       
  4358 			type == KUidMsvEmailRtfEntryValue
       
  4359 			)
       
  4360 			{
       
  4361 			aIdArray.Append(childId);
       
  4362 			}
       
  4363 		// Recursion for alternate folders
       
  4364 		else if(type == KUidMsvFolderEntryValue)
       
  4365 			{
       
  4366 			aIdArray.Append(childId);
       
  4367 			// also get the childs for these messages
       
  4368 			GetAllMimeIdsL(childId, aIdArray);
       
  4369 			}
       
  4370 		}
       
  4371 		
       
  4372 	CleanupStack::PopAndDestroy(2); // stmt, buf
       
  4373 	}
       
  4374 
       
  4375 /**
       
  4376 GetMessageCountL()
       
  4377 Gets the count of messages under a service id.
       
  4378 
       
  4379 @param aServiceId: service id
       
  4380 */
       
  4381 TInt CMsvDBAdapter::GetMessageCountL(TMsvId aServiceId)
       
  4382 	{
       
  4383 	_LIT(KSelectMessageId, "Select count(*) FROM IndexEntry WHERE type = ");
       
  4384 	_LIT(KServiceId," AND serviceId = ");
       
  4385 	RBuf buf;
       
  4386 	CleanupClosePushL(buf);
       
  4387 	buf.CreateL(100);
       
  4388 	buf.Append(KSelectMessageId);
       
  4389 	buf.AppendNum(KUidMsvMessageEntryValue);
       
  4390 	buf.Append(KServiceId);
       
  4391 	buf.AppendNum(aServiceId);
       
  4392 	buf.Append(KDelimiter);
       
  4393 	
       
  4394 	TSqlScalarFullSelectQuery query(iDatabase);
       
  4395 	TInt msgcount = 0;
       
  4396 	msgcount = query.SelectIntL(buf);
       
  4397 	
       
  4398 	CleanupStack::PopAndDestroy();  //buf
       
  4399 	return msgcount;
       
  4400 	}
       
  4401 
       
  4402 /**
       
  4403 GetOwningServiceL()
       
  4404 Gets the ids owning service.
       
  4405 
       
  4406 @param aId: id
       
  4407 @param aOwningId: owning service id reference variable.
       
  4408 @retun None
       
  4409 */
       
  4410 void CMsvDBAdapter::GetOwningServiceL(TMsvId aId, TMsvId& aOwningId)
       
  4411 	{
       
  4412 	_LIT(KSelectServiceId, "Select parentId,type FROM IndexEntry WHERE id = ");
       
  4413 	
       
  4414 	TBool found = EFalse;
       
  4415 	TMsvId entryid = aId;
       
  4416 	TMsvId parentId = 0;
       
  4417 	TMsvId typeId = 0;
       
  4418 	
       
  4419 	while (!found)
       
  4420 		{
       
  4421 		RBuf buf;
       
  4422 		CleanupClosePushL(buf);
       
  4423 		buf.CreateL(100);
       
  4424 		buf.Append(KSelectServiceId);
       
  4425 		buf.AppendNum(entryid);
       
  4426 		buf.Append(KDelimiter);
       
  4427 		
       
  4428 		RSqlStatement parentIdquerystatement;
       
  4429 		CleanupClosePushL(parentIdquerystatement);
       
  4430 		User::LeaveIfError(parentIdquerystatement.Prepare(iDatabase, buf));
       
  4431 		
       
  4432 		TInt parentIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnParentId());
       
  4433 		TInt typeIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnType());
       
  4434 	
       
  4435 		while(KSqlAtRow == parentIdquerystatement.Next())
       
  4436 			{
       
  4437 			parentId  = ColumnInt(parentIdquerystatement, parentIdindex);
       
  4438 			typeId = ColumnInt(parentIdquerystatement, typeIdindex);
       
  4439 			}
       
  4440 		
       
  4441 		CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
       
  4442 			
       
  4443 		if (typeId == KUidMsvServiceEntryValue)
       
  4444 			{
       
  4445 			found = ETrue;
       
  4446 			}
       
  4447 		else
       
  4448 			{
       
  4449 			entryid = parentId;
       
  4450 			}
       
  4451 		}
       
  4452 	aOwningId = entryid;
       
  4453 	}
       
  4454 	
       
  4455 /**
       
  4456 GetAllServiceIDsForMtmL()
       
  4457 Gets all service ids for the specified mtm.
       
  4458 
       
  4459 @param aMtm: mtm id.
       
  4460 @param aIdArray&: Array of TMsvId.
       
  4461 @retun None
       
  4462 */
       
  4463 void CMsvDBAdapter::GetAllServiceIDsForMtmL(TInt32 aMtm, RArray<TMsvId>& aIdArray)
       
  4464 	{
       
  4465 	// if sms, than dont get smtp id else, get the smtp id also
       
  4466 	_LIT16(KSelectServiceIds, "Select distinct serviceId FROM IndexEntry where type = ");
       
  4467 	_LIT16(KMtmIdQuery," AND mtmId = ");
       
  4468 
       
  4469 	RBuf buf;
       
  4470 	CleanupClosePushL(buf);
       
  4471 	buf.CreateL(200);
       
  4472 	buf.Append(KSelectServiceIds);
       
  4473 	buf.AppendNum(KUidMsvServiceEntryValue);
       
  4474 	buf.Append(KMtmIdQuery);
       
  4475 	buf.AppendNum(aMtm);
       
  4476 	buf.Append(KDelimiter);
       
  4477 	
       
  4478 	RSqlStatement queryStmt;
       
  4479 	CleanupClosePushL(queryStmt);
       
  4480 	User::LeaveIfError(queryStmt.Prepare(iDatabase, buf));
       
  4481 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnServiceId());
       
  4482 	
       
  4483 	while(KSqlAtRow == queryStmt.Next())
       
  4484 		{
       
  4485 		TMsvId serviceId = ColumnInt(queryStmt, serviceColumnIndex);
       
  4486 		aIdArray.AppendL(serviceId);
       
  4487 		}
       
  4488 	CleanupStack::PopAndDestroy(2); //buf, stmt
       
  4489 	
       
  4490 	// lets also get all messages in the root with this service id
       
  4491 	if(aMtm == 268439592 ) //0x1000102C sms
       
  4492 		{
       
  4493 		aIdArray.AppendL(KMsvGlobalOutBoxIndexEntryIdValue);	
       
  4494 		aIdArray.AppendL(KMsvDraftEntryIdValue);
       
  4495 		aIdArray.AppendL(KMsvSentEntryIdValue);	
       
  4496 		}
       
  4497 	}
       
  4498 
       
  4499 /**
       
  4500 GetAllIndexEntryTableIdsL()
       
  4501 Gets all ids present in index entry table.
       
  4502 
       
  4503 @param aIdArray: Array of TMsvId.
       
  4504 @retun None
       
  4505 */
       
  4506 void CMsvDBAdapter::GetAllIndexEntryTableIdsL(RArray<TMsvId>& aIdArray)	
       
  4507 	{
       
  4508 	_LIT(KSelectAllIds, "Select * FROM IndexEntry;");
       
  4509 	
       
  4510 	RSqlStatement queryStmt;
       
  4511 	CleanupClosePushL(queryStmt);
       
  4512 	User::LeaveIfError(queryStmt.Prepare(iDatabase, KSelectAllIds));
       
  4513 	
       
  4514 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
       
  4515 	
       
  4516 	while(KSqlAtRow == queryStmt.Next())
       
  4517 		{
       
  4518 		TMsvId Id = ColumnInt(queryStmt, serviceColumnIndex);
       
  4519 		aIdArray.AppendL(Id);
       
  4520 		}
       
  4521 	CleanupStack::PopAndDestroy(); //queryStmt
       
  4522 	}
       
  4523 
       
  4524 /**
       
  4525 GetVisibleParentL()
       
  4526 Gets the visible parent of the specified id.
       
  4527 
       
  4528 @param aId: id
       
  4529 @param aVisibleParentId: visible parent id.
       
  4530 @retun None
       
  4531 */
       
  4532  
       
  4533 void CMsvDBAdapter::GetVisibleParentL(TMsvId aId, TMsvId& aVisibleParentId)
       
  4534 	{
       
  4535 	_LIT(KSelectServiceId, "Select parentId,type FROM IndexEntry WHERE id = ");
       
  4536 	
       
  4537 	TMsvId entryid = aId;
       
  4538 	TMsvId parentId = 0;
       
  4539 		
       
  4540 	RBuf buf;
       
  4541 	CleanupClosePushL(buf);
       
  4542 	buf.CreateL(100);
       
  4543 	buf.Append(KSelectServiceId);
       
  4544 	buf.AppendNum(entryid);
       
  4545 	buf.Append(KDelimiter);
       
  4546 	
       
  4547 	RSqlStatement parentIdquerystatement;
       
  4548 	CleanupClosePushL(parentIdquerystatement);
       
  4549 	
       
  4550 	User::LeaveIfError(parentIdquerystatement.Prepare(iDatabase, buf));
       
  4551 		
       
  4552 	TInt parentIdindex = GetColumnIndexL(parentIdquerystatement, KMsgColumnParentId());
       
  4553 		
       
  4554 	while(KSqlAtRow == parentIdquerystatement.Next())
       
  4555 		{
       
  4556 		parentId  = ColumnInt(parentIdquerystatement, parentIdindex);
       
  4557 		}
       
  4558 	
       
  4559 	CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
       
  4560 	
       
  4561 	GetVisibleParentIdL(parentId,aVisibleParentId);
       
  4562 	}
       
  4563 
       
  4564 /**
       
  4565 GetVisibleParentIdL()
       
  4566 This functions returns the most immediate parent visible folder id.
       
  4567 There are two types of folders. A visible folder is one which is 
       
  4568 visible to the external user, but there are internal non-visible folders
       
  4569 created under each email message to organize the content of the email.
       
  4570 Parent entry of an entry is either root or a folder. A folder can be 
       
  4571 service folder (like LocalServices), userdefined folder/standard folder
       
  4572 like Inbox or a non-visible folder (created under an email message).
       
  4573 
       
  4574 For a given parent Id, the function returns the most immediate visible
       
  4575 parent folder. The rules are as follows:
       
  4576 1. If the parent entry is root or children of root, then the visibleFolder 
       
  4577 will be root itself. This is because service folders are considered 
       
  4578 invisible, since they are not seen by user. 
       
  4579 2. If the parent entry itself is a visible folder then child's visibleFolder
       
  4580 id should be its parent id.
       
  4581 3. If the parent entry is a non-visible folder then child's visibleFolder
       
  4582 id is same as its parent's visibleFolder id.
       
  4583 
       
  4584 @param TMsvId: Parent Id.
       
  4585 @return Most immediate visible folder id of any child entry present under passed parent id.
       
  4586 */
       
  4587 void CMsvDBAdapter::GetVisibleParentIdL(TMsvId aParentId, TMsvId& aVisibleFolderId)
       
  4588 	{
       
  4589 	// If the entry is either a root entry (parent=KErrNotFound) or 
       
  4590 	// child of root entry its visibleFolderId will be root entry itself.
       
  4591 	if((KErrNotFound == aParentId) || (KMsvRootIndexEntryId == aParentId))
       
  4592 		{
       
  4593 		aVisibleFolderId = KMsvRootIndexEntryId;
       
  4594 		}
       
  4595 	else
       
  4596 		{
       
  4597 		// Get the visible flag of parent entry.
       
  4598 		
       
  4599 		// If parent entry is visible, then immediateVisibleFolder of child
       
  4600 		// should be parent Id. And if it is invisible then child's immediateVisibleFolder 
       
  4601 		// should be same as parent's immediateVisibleFolder.
       
  4602 		
       
  4603 		//Bind the msv id
       
  4604 		BindIntL(iStatement[EGetVisibleId], iIdIndex[EGetVisibleId], aParentId);
       
  4605 
       
  4606 		// If parent entry does not exists leave with KErrNotFound.
       
  4607 		if (KSqlAtRow != iStatement[EGetVisibleId].Next())
       
  4608 			{
       
  4609 			iStatement[EGetVisibleId].Reset();
       
  4610 			User::Leave(KErrNotFound);
       
  4611 			}
       
  4612 
       
  4613 		TInt32 data = ColumnInt(iStatement[EGetVisibleId], iDataIndex[EGetVisibleId]);
       
  4614 		if( data & TMsvEntry::KMsvVisibleFolderNodeFlag)
       
  4615 			{
       
  4616 			// If visible folder flag is not set for parent entry.
       
  4617 			aVisibleFolderId = ColumnInt(iStatement[EGetVisibleId], iVisibleParent[EGetVisibleId]);
       
  4618 			}
       
  4619 		else
       
  4620 			{
       
  4621 			// If parent entry is visible
       
  4622 			aVisibleFolderId = aParentId;
       
  4623 			}
       
  4624 		//Reset the RSqlStatement
       
  4625 		User::LeaveIfError(iStatement[EGetVisibleId].Reset());
       
  4626 		}
       
  4627 	}
       
  4628 
       
  4629 /**
       
  4630 UpdateVisibleFolderIdL()
       
  4631 Updates visible parent and any other new changes in TMsvEntry structure post PREQ 1189. 
       
  4632 
       
  4633 @param aId: id. 
       
  4634 @param visibleId: visible parent id.
       
  4635 @retun None
       
  4636 */	
       
  4637 void CMsvDBAdapter::UpdateVisibleFolderIdL(TMsvId aId,TMsvId visibleId)
       
  4638 	{
       
  4639 	_LIT(KUpdateVisibleParentQuery,"UPDATE IndexEntry SET visibleParent = ");
       
  4640 	_LIT(KWhere, " WHERE ");
       
  4641 	_LIT(KUpdateVisibleParentQuery1, "id = ");
       
  4642 	 	
       
  4643 	RBuf buf;
       
  4644 	CleanupClosePushL(buf);
       
  4645 	buf.CreateL(100);
       
  4646 	buf.Append(KUpdateVisibleParentQuery);
       
  4647 	buf.AppendNum(visibleId);
       
  4648 	buf.Append(KWhere);
       
  4649 	buf.Append(KUpdateVisibleParentQuery1);
       
  4650 	buf.AppendNum(aId);
       
  4651 	buf.Append(KDelimiter);
       
  4652 	
       
  4653 	RSqlStatement queryStmt;
       
  4654 	CleanupClosePushL(queryStmt);
       
  4655 	User::LeaveIfError(queryStmt.Prepare(iDatabase, buf));
       
  4656 	
       
  4657 	TInt err = queryStmt.Exec();
       
  4658 	
       
  4659 	CleanupStack::PopAndDestroy(2); //stmt
       
  4660 	
       
  4661 	if(err < 0)
       
  4662 		{
       
  4663 		User::Leave(err);
       
  4664 		}
       
  4665 	else if(!err)
       
  4666 		{
       
  4667 		User::Leave(KErrGeneral);
       
  4668 		}
       
  4669 	}
       
  4670 
       
  4671 TBool CMsvDBAdapter::GetParentVisibleFlagL(TMsvId parentId)
       
  4672 	{
       
  4673 	_LIT(KSelectServiceId, "Select data FROM IndexEntry WHERE id = ");
       
  4674 	
       
  4675 	TInt data = KErrNotFound;		
       
  4676 	RBuf buf;
       
  4677 	CleanupClosePushL(buf);
       
  4678 	buf.CreateL(100);
       
  4679 	buf.Append(KSelectServiceId);
       
  4680 	buf.AppendNum(parentId);
       
  4681 	buf.Append(KDelimiter);
       
  4682 	
       
  4683 	RSqlStatement parentDataQuerystatement;
       
  4684 	CleanupClosePushL(parentDataQuerystatement);
       
  4685 	
       
  4686 	User::LeaveIfError(parentDataQuerystatement.Prepare(iDatabase, buf));
       
  4687 		
       
  4688 	TInt parentIdindex = GetColumnIndexL(parentDataQuerystatement, KMsgColumnData());
       
  4689 		
       
  4690 	while(KSqlAtRow == parentDataQuerystatement.Next())
       
  4691 		{
       
  4692 		data  = ColumnInt(parentDataQuerystatement, parentIdindex);
       
  4693 		}
       
  4694 	CleanupStack::PopAndDestroy(2);  //buf,parentIdquerystatement
       
  4695 	
       
  4696 	return !(data & TMsvEntry::KMsvVisibleFolderNodeFlag);
       
  4697 			
       
  4698 	}
       
  4699 	
       
  4700 /**
       
  4701 GetAllIndexEntryTableIdsL()
       
  4702 Gets all ids present in index entry table.
       
  4703 
       
  4704 @param aIdArray: Array of TMsvId.
       
  4705 @retun None
       
  4706 */
       
  4707 void CMsvDBAdapter::GetRemainingIdsL(RArray<TMsvId>& aIdArray)	
       
  4708 	{
       
  4709 	_LIT(KSelectAllIds, "Select id FROM IndexEntry where visibleParent = -99;");
       
  4710 	
       
  4711 	RSqlStatement queryStmt;
       
  4712 	CleanupClosePushL(queryStmt);
       
  4713 	User::LeaveIfError(queryStmt.Prepare(iDatabase, KSelectAllIds));
       
  4714 	
       
  4715 	TInt serviceColumnIndex = GetColumnIndexL(queryStmt, KMsgColumnId());
       
  4716 	
       
  4717 	while(KSqlAtRow == queryStmt.Next())
       
  4718 		{
       
  4719 		TMsvId Id = ColumnInt(queryStmt, serviceColumnIndex);
       
  4720 		aIdArray.AppendL(Id);
       
  4721 		}
       
  4722 	CleanupStack::PopAndDestroy(); //queryStmt
       
  4723 	}
       
  4724 
       
  4725 /**
       
  4726 DeleteTable()
       
  4727 Deletes the header table identified by the UID
       
  4728 
       
  4729 @param aMtmId: MTM id.
       
  4730 @retun None
       
  4731 */
       
  4732 void CMsvDBAdapter::DeleteTableL(TUid aMtmId)	
       
  4733 	{
       
  4734 	_LIT16(KDropTableQuery, "DROP table if exists Header_");
       
  4735 	
       
  4736 	RBuf16 buf;
       
  4737 	CleanupClosePushL(buf);
       
  4738 	buf.CreateL(100);
       
  4739 	buf.Append(KDropTableQuery);
       
  4740 	buf.AppendNum(aMtmId.iUid);
       
  4741 	buf.Append(KDelimiter);
       
  4742 	
       
  4743 	TInt err = iDatabase.Exec(buf);
       
  4744 
       
  4745 	CleanupStack::PopAndDestroy(); //buf
       
  4746 	}
       
  4747  
       
  4748  /**
       
  4749 DeleteTable()
       
  4750 Deletes the header table identified by the UID
       
  4751 
       
  4752 @param None
       
  4753 @retun None
       
  4754 */
       
  4755 void CMsvDBAdapter::DeleteSearchSortTable()	
       
  4756 	{
       
  4757 	_LIT16(KDropSearchSortTableQuery, "DROP table if exists SearchSortEntry;");
       
  4758 	
       
  4759 	TInt err = iDatabase.Exec(KDropSearchSortTableQuery);
       
  4760 	}
       
  4761  
       
  4762  
       
  4763 #endif //#if (defined SYMBIAN_MESSAGESTORE_HEADER_BODY_USING_SQLDB)
       
  4764 
       
  4765 
       
  4766